[MIPI,SEQ,PARSING,v1,3/9] drm/i915: Using the approprite vbt size if vbt is not in mailbox4 of opregion

Submitted by Deepak M on July 28, 2015, 10:01 a.m.

Details

Message ID 1438077670-12953-4-git-send-email-m.deepak@intel.com
State New
Headers show

Not browsing as part of any series.

Commit Message

Deepak M July 28, 2015, 10:01 a.m.
Currently the field in bdb header which indicates the VBT size
is of 2 bytes, but there are some cases where VBT size exceeds
64KB in which case this field may not contain the correct VBT size.
So its better to get the VBT size from the mailbox3 if
VBT is not present in the mailbox4 of opregion.

Signed-off-by: Deepak M <m.deepak@intel.com>
---
 drivers/gpu/drm/i915/i915_drv.h       |    5 ++++
 drivers/gpu/drm/i915/intel_bios.c     |   43 +++++++++++++++++++--------------
 drivers/gpu/drm/i915/intel_opregion.c |    7 ++++--
 3 files changed, 35 insertions(+), 20 deletions(-)

Patch hide | download patch | download mbox

diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 1dbd957..b38f52ee 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -1740,6 +1740,11 @@  struct drm_i915_private {
 	u32 pm_rps_events;
 	u32 pipestat_irq_mask[I915_MAX_PIPES];
 
+	bool vbt_in_mailbox4;
+
+	/* value is true when VBT is present in mailbox4 */
+	u32 vbt_size;
+
 	struct i915_hotplug hotplug;
 	struct i915_fbc fbc;
 	struct i915_drrs drrs;
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index 1b9164e..5e0ff22 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -37,17 +37,22 @@ 
 static int panel_type;
 
 static const void *
-find_section(const void *_bdb, int section_id)
+find_section(struct drm_i915_private *dev_priv,
+		const void *_bdb, int section_id)
 {
 	const struct bdb_header *bdb = _bdb;
 	const u8 *base = _bdb;
 	int index = 0;
-	u16 total, current_size;
+	u32 total, current_size;
 	u8 current_id;
 
 	/* skip to first section */
 	index += bdb->header_size;
-	total = bdb->bdb_size;
+
+	if (dev_priv->vbt_in_mailbox4)
+		total = bdb->bdb_size;
+	else
+		total = dev_priv->vbt_size;
 
 	/* walk the sections looking for section_id */
 	while (index + 3 < total) {
@@ -179,7 +184,7 @@  parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 	struct drm_display_mode *panel_fixed_mode;
 	int drrs_mode;
 
-	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
+	lvds_options = find_section(dev_priv, bdb, BDB_LVDS_OPTIONS);
 	if (!lvds_options)
 		return;
 
@@ -211,11 +216,12 @@  parse_lfp_panel_data(struct drm_i915_private *dev_priv,
 		break;
 	}
 
-	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
+	lvds_lfp_data = find_section(dev_priv, bdb, BDB_LVDS_LFP_DATA);
 	if (!lvds_lfp_data)
 		return;
 
-	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
+	lvds_lfp_data_ptrs = find_section(dev_priv, bdb,
+					BDB_LVDS_LFP_DATA_PTRS);
 	if (!lvds_lfp_data_ptrs)
 		return;
 
@@ -257,7 +263,7 @@  parse_lfp_backlight(struct drm_i915_private *dev_priv,
 	const struct bdb_lfp_backlight_data *backlight_data;
 	const struct bdb_lfp_backlight_data_entry *entry;
 
-	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
+	backlight_data = find_section(dev_priv, bdb, BDB_LVDS_BACKLIGHT);
 	if (!backlight_data)
 		return;
 
@@ -305,14 +311,15 @@  parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
 	if (index == -1) {
 		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
 
-		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
+		sdvo_lvds_options = find_section(dev_priv, bdb,
+						BDB_SDVO_LVDS_OPTIONS);
 		if (!sdvo_lvds_options)
 			return;
 
 		index = sdvo_lvds_options->panel_type;
 	}
 
-	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
+	dvo_timing = find_section(dev_priv, bdb, BDB_SDVO_PANEL_DTDS);
 	if (!dvo_timing)
 		return;
 
@@ -349,7 +356,7 @@  parse_general_features(struct drm_i915_private *dev_priv,
 	struct drm_device *dev = dev_priv->dev;
 	const struct bdb_general_features *general;
 
-	general = find_section(bdb, BDB_GENERAL_FEATURES);
+	general = find_section(dev_priv, bdb, BDB_GENERAL_FEATURES);
 	if (general) {
 		dev_priv->vbt.int_tv_support = general->int_tv_support;
 		dev_priv->vbt.int_crt_support = general->int_crt_support;
@@ -374,7 +381,7 @@  parse_general_definitions(struct drm_i915_private *dev_priv,
 {
 	const struct bdb_general_definitions *general;
 
-	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	general = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
 	if (general) {
 		u16 block_size = get_blocksize(general);
 		if (block_size >= sizeof(*general)) {
@@ -405,7 +412,7 @@  parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
 	int i, child_device_num, count;
 	u16	block_size;
 
-	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	p_defs = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
 	if (!p_defs) {
 		DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
 		return;
@@ -491,7 +498,7 @@  parse_driver_features(struct drm_i915_private *dev_priv,
 {
 	const struct bdb_driver_features *driver;
 
-	driver = find_section(bdb, BDB_DRIVER_FEATURES);
+	driver = find_section(dev_priv, bdb, BDB_DRIVER_FEATURES);
 	if (!driver)
 		return;
 
@@ -519,7 +526,7 @@  parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 	const struct edp_power_seq *edp_pps;
 	const struct edp_link_params *edp_link_params;
 
-	edp = find_section(bdb, BDB_EDP);
+	edp = find_section(dev_priv, bdb, BDB_EDP);
 	if (!edp) {
 		if (dev_priv->vbt.edp_support)
 			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
@@ -630,7 +637,7 @@  parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 	const struct bdb_psr *psr;
 	const struct psr_table *psr_table;
 
-	psr = find_section(bdb, BDB_PSR);
+	psr = find_section(dev_priv, bdb, BDB_PSR);
 	if (!psr) {
 		DRM_DEBUG_KMS("No PSR BDB found.\n");
 		return;
@@ -768,7 +775,7 @@  parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 	/* Parse #52 for panel index used from panel_type already
 	 * parsed
 	 */
-	start = find_section(bdb, BDB_MIPI_CONFIG);
+	start = find_section(dev_priv, bdb, BDB_MIPI_CONFIG);
 	if (!start) {
 		DRM_DEBUG_KMS("No MIPI config BDB found");
 		return;
@@ -799,7 +806,7 @@  parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
 	dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
 
 	/* Check if we have sequence block as well */
-	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
+	sequence = find_section(dev_priv, bdb, BDB_MIPI_SEQUENCE);
 	if (!sequence) {
 		DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n");
 		return;
@@ -1023,7 +1030,7 @@  parse_device_mapping(struct drm_i915_private *dev_priv,
 	int i, child_device_num, count;
 	u16	block_size;
 
-	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
+	p_defs = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
 	if (!p_defs) {
 		DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
 		return;
diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
index 1372e39..1f76715 100644
--- a/drivers/gpu/drm/i915/intel_opregion.c
+++ b/drivers/gpu/drm/i915/intel_opregion.c
@@ -896,11 +896,14 @@  int intel_opregion_setup(struct drm_device *dev)
 	opregion->header = base;
 	opregion->asle = base + OPREGION_ASLE_OFFSET;
 
+	dev_priv->vbt_in_mailbox4 = true;
 	if (opregion->header->opregion_ver >= 2) {
-		if (opregion->asle->rvda)
+		if (opregion->asle->rvda) {
 			vbt_base = acpi_os_ioremap(opregion->asle->rvda,
 						opregion->asle->rvds);
-		else
+			dev_priv->vbt_in_mailbox4 = false;
+			dev_priv->vbt_size = opregion->asle->rvds;
+		} else
 			vbt_base = acpi_os_ioremap(asls + OPREGION_VBT_OFFSET,
 					OPREGION_SIZE - OPREGION_VBT_OFFSET);
 	} else

Comments

On Tue, 28 Jul 2015, Deepak M <m.deepak@intel.com> wrote:
> Currently the field in bdb header which indicates the VBT size
> is of 2 bytes, but there are some cases where VBT size exceeds
> 64KB in which case this field may not contain the correct VBT size.
> So its better to get the VBT size from the mailbox3 if
> VBT is not present in the mailbox4 of opregion.
>
> Signed-off-by: Deepak M <m.deepak@intel.com>
> ---
>  drivers/gpu/drm/i915/i915_drv.h       |    5 ++++
>  drivers/gpu/drm/i915/intel_bios.c     |   43 +++++++++++++++++++--------------
>  drivers/gpu/drm/i915/intel_opregion.c |    7 ++++--
>  3 files changed, 35 insertions(+), 20 deletions(-)
>
> diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
> index 1dbd957..b38f52ee 100644
> --- a/drivers/gpu/drm/i915/i915_drv.h
> +++ b/drivers/gpu/drm/i915/i915_drv.h
> @@ -1740,6 +1740,11 @@ struct drm_i915_private {
>  	u32 pm_rps_events;
>  	u32 pipestat_irq_mask[I915_MAX_PIPES];
>  
> +	bool vbt_in_mailbox4;
> +
> +	/* value is true when VBT is present in mailbox4 */
> +	u32 vbt_size;
> +

There's already struct intel_opregion opregion field in dev_priv where
this belongs instead of cluttering the top level.

You should only add vbt size in the struct, and make sure it's valid for
all scenarios, mailbox 4 or not, and always check against that. Having
size fields with separate validity fields will drive people insane.

>  	struct i915_hotplug hotplug;
>  	struct i915_fbc fbc;
>  	struct i915_drrs drrs;
> diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
> index 1b9164e..5e0ff22 100644
> --- a/drivers/gpu/drm/i915/intel_bios.c
> +++ b/drivers/gpu/drm/i915/intel_bios.c
> @@ -37,17 +37,22 @@
>  static int panel_type;
>  
>  static const void *
> -find_section(const void *_bdb, int section_id)
> +find_section(struct drm_i915_private *dev_priv,
> +		const void *_bdb, int section_id)
>  {
>  	const struct bdb_header *bdb = _bdb;
>  	const u8 *base = _bdb;
>  	int index = 0;
> -	u16 total, current_size;
> +	u32 total, current_size;
>  	u8 current_id;
>  
>  	/* skip to first section */
>  	index += bdb->header_size;
> -	total = bdb->bdb_size;
> +
> +	if (dev_priv->vbt_in_mailbox4)
> +		total = bdb->bdb_size;
> +	else
> +		total = dev_priv->vbt_size;
>  
>  	/* walk the sections looking for section_id */
>  	while (index + 3 < total) {
> @@ -179,7 +184,7 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
>  	struct drm_display_mode *panel_fixed_mode;
>  	int drrs_mode;
>  
> -	lvds_options = find_section(bdb, BDB_LVDS_OPTIONS);
> +	lvds_options = find_section(dev_priv, bdb, BDB_LVDS_OPTIONS);
>  	if (!lvds_options)
>  		return;
>  
> @@ -211,11 +216,12 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
>  		break;
>  	}
>  
> -	lvds_lfp_data = find_section(bdb, BDB_LVDS_LFP_DATA);
> +	lvds_lfp_data = find_section(dev_priv, bdb, BDB_LVDS_LFP_DATA);
>  	if (!lvds_lfp_data)
>  		return;
>  
> -	lvds_lfp_data_ptrs = find_section(bdb, BDB_LVDS_LFP_DATA_PTRS);
> +	lvds_lfp_data_ptrs = find_section(dev_priv, bdb,
> +					BDB_LVDS_LFP_DATA_PTRS);
>  	if (!lvds_lfp_data_ptrs)
>  		return;
>  
> @@ -257,7 +263,7 @@ parse_lfp_backlight(struct drm_i915_private *dev_priv,
>  	const struct bdb_lfp_backlight_data *backlight_data;
>  	const struct bdb_lfp_backlight_data_entry *entry;
>  
> -	backlight_data = find_section(bdb, BDB_LVDS_BACKLIGHT);
> +	backlight_data = find_section(dev_priv, bdb, BDB_LVDS_BACKLIGHT);
>  	if (!backlight_data)
>  		return;
>  
> @@ -305,14 +311,15 @@ parse_sdvo_panel_data(struct drm_i915_private *dev_priv,
>  	if (index == -1) {
>  		const struct bdb_sdvo_lvds_options *sdvo_lvds_options;
>  
> -		sdvo_lvds_options = find_section(bdb, BDB_SDVO_LVDS_OPTIONS);
> +		sdvo_lvds_options = find_section(dev_priv, bdb,
> +						BDB_SDVO_LVDS_OPTIONS);
>  		if (!sdvo_lvds_options)
>  			return;
>  
>  		index = sdvo_lvds_options->panel_type;
>  	}
>  
> -	dvo_timing = find_section(bdb, BDB_SDVO_PANEL_DTDS);
> +	dvo_timing = find_section(dev_priv, bdb, BDB_SDVO_PANEL_DTDS);
>  	if (!dvo_timing)
>  		return;
>  
> @@ -349,7 +356,7 @@ parse_general_features(struct drm_i915_private *dev_priv,
>  	struct drm_device *dev = dev_priv->dev;
>  	const struct bdb_general_features *general;
>  
> -	general = find_section(bdb, BDB_GENERAL_FEATURES);
> +	general = find_section(dev_priv, bdb, BDB_GENERAL_FEATURES);
>  	if (general) {
>  		dev_priv->vbt.int_tv_support = general->int_tv_support;
>  		dev_priv->vbt.int_crt_support = general->int_crt_support;
> @@ -374,7 +381,7 @@ parse_general_definitions(struct drm_i915_private *dev_priv,
>  {
>  	const struct bdb_general_definitions *general;
>  
> -	general = find_section(bdb, BDB_GENERAL_DEFINITIONS);
> +	general = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
>  	if (general) {
>  		u16 block_size = get_blocksize(general);
>  		if (block_size >= sizeof(*general)) {
> @@ -405,7 +412,7 @@ parse_sdvo_device_mapping(struct drm_i915_private *dev_priv,
>  	int i, child_device_num, count;
>  	u16	block_size;
>  
> -	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
> +	p_defs = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
>  	if (!p_defs) {
>  		DRM_DEBUG_KMS("No general definition block is found, unable to construct sdvo mapping.\n");
>  		return;
> @@ -491,7 +498,7 @@ parse_driver_features(struct drm_i915_private *dev_priv,
>  {
>  	const struct bdb_driver_features *driver;
>  
> -	driver = find_section(bdb, BDB_DRIVER_FEATURES);
> +	driver = find_section(dev_priv, bdb, BDB_DRIVER_FEATURES);
>  	if (!driver)
>  		return;
>  
> @@ -519,7 +526,7 @@ parse_edp(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  	const struct edp_power_seq *edp_pps;
>  	const struct edp_link_params *edp_link_params;
>  
> -	edp = find_section(bdb, BDB_EDP);
> +	edp = find_section(dev_priv, bdb, BDB_EDP);
>  	if (!edp) {
>  		if (dev_priv->vbt.edp_support)
>  			DRM_DEBUG_KMS("No eDP BDB found but eDP panel supported.\n");
> @@ -630,7 +637,7 @@ parse_psr(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  	const struct bdb_psr *psr;
>  	const struct psr_table *psr_table;
>  
> -	psr = find_section(bdb, BDB_PSR);
> +	psr = find_section(dev_priv, bdb, BDB_PSR);
>  	if (!psr) {
>  		DRM_DEBUG_KMS("No PSR BDB found.\n");
>  		return;
> @@ -768,7 +775,7 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  	/* Parse #52 for panel index used from panel_type already
>  	 * parsed
>  	 */
> -	start = find_section(bdb, BDB_MIPI_CONFIG);
> +	start = find_section(dev_priv, bdb, BDB_MIPI_CONFIG);
>  	if (!start) {
>  		DRM_DEBUG_KMS("No MIPI config BDB found");
>  		return;
> @@ -799,7 +806,7 @@ parse_mipi(struct drm_i915_private *dev_priv, const struct bdb_header *bdb)
>  	dev_priv->vbt.dsi.panel_id = MIPI_DSI_GENERIC_PANEL_ID;
>  
>  	/* Check if we have sequence block as well */
> -	sequence = find_section(bdb, BDB_MIPI_SEQUENCE);
> +	sequence = find_section(dev_priv, bdb, BDB_MIPI_SEQUENCE);
>  	if (!sequence) {
>  		DRM_DEBUG_KMS("No MIPI Sequence found, parsing complete\n");
>  		return;
> @@ -1023,7 +1030,7 @@ parse_device_mapping(struct drm_i915_private *dev_priv,
>  	int i, child_device_num, count;
>  	u16	block_size;
>  
> -	p_defs = find_section(bdb, BDB_GENERAL_DEFINITIONS);
> +	p_defs = find_section(dev_priv, bdb, BDB_GENERAL_DEFINITIONS);
>  	if (!p_defs) {
>  		DRM_DEBUG_KMS("No general definition block is found, no devices defined.\n");
>  		return;
> diff --git a/drivers/gpu/drm/i915/intel_opregion.c b/drivers/gpu/drm/i915/intel_opregion.c
> index 1372e39..1f76715 100644
> --- a/drivers/gpu/drm/i915/intel_opregion.c
> +++ b/drivers/gpu/drm/i915/intel_opregion.c
> @@ -896,11 +896,14 @@ int intel_opregion_setup(struct drm_device *dev)
>  	opregion->header = base;
>  	opregion->asle = base + OPREGION_ASLE_OFFSET;
>  
> +	dev_priv->vbt_in_mailbox4 = true;
>  	if (opregion->header->opregion_ver >= 2) {
> -		if (opregion->asle->rvda)
> +		if (opregion->asle->rvda) {
>  			vbt_base = acpi_os_ioremap(opregion->asle->rvda,
>  						opregion->asle->rvds);
> -		else
> +			dev_priv->vbt_in_mailbox4 = false;
> +			dev_priv->vbt_size = opregion->asle->rvds;
> +		} else
>  			vbt_base = acpi_os_ioremap(asls + OPREGION_VBT_OFFSET,
>  					OPREGION_SIZE - OPREGION_VBT_OFFSET);
>  	} else
> -- 
> 1.7.9.5
>
> _______________________________________________
> Intel-gfx mailing list
> Intel-gfx@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/intel-gfx