Commit cdaa052b authored by Zhao Yakui's avatar Zhao Yakui Committed by Eric Anholt

drm/I915: Fix offset to DVO timings in LVDS data

Now the DVO timing in LVDS data entry is obtained by using the
following step:
    a. get the entry size for every LVDS panel data
    b. Get the LVDS fp entry for the preferred panel type
    c. get the DVO timing by using entry->dvo_timing

In our driver the entry->dvo_timing is related with the size of
lvds_fp_timing. For example: the size is 46.

But it seems that the size of lvds_fp_timing varies on the differnt
platform. In such case we will get the incorrect DVO timing entry
because of the incorrect DVO offset in LVDS panel data entry.
This also removes a hack on new IGDNG to get proper DVO timing.

Calculate the DVO timing offset in LVDS data entry to get the DVO timing
    a. get the DVO timing offset in the LVDS fp data entry by using the
pointer definition in LVDS data ptr
    b. get the LVDS data entry
    c. get the DVO timing by adding the DVO timing offset to data entry

https://bugs.freedesktop.org/show_bug.cgi?id=22787Signed-off-by: default avatarZhao Yakui <yakui.zhao@intel.com>
Tested-by: default avatarZhenyu Wang <zhenyuw@linux.intel.com>
Acked-by: default avatarJesse Barnes <jbarnes@virtuousgeek.org>
Signed-off-by: default avatarEric Anholt <eric@anholt.net>
parent 2ded9e27
...@@ -97,14 +97,13 @@ static void ...@@ -97,14 +97,13 @@ static void
parse_lfp_panel_data(struct drm_i915_private *dev_priv, parse_lfp_panel_data(struct drm_i915_private *dev_priv,
struct bdb_header *bdb) struct bdb_header *bdb)
{ {
struct drm_device *dev = dev_priv->dev;
struct bdb_lvds_options *lvds_options; struct bdb_lvds_options *lvds_options;
struct bdb_lvds_lfp_data *lvds_lfp_data; struct bdb_lvds_lfp_data *lvds_lfp_data;
struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs; struct bdb_lvds_lfp_data_ptrs *lvds_lfp_data_ptrs;
struct bdb_lvds_lfp_data_entry *entry; struct bdb_lvds_lfp_data_entry *entry;
struct lvds_dvo_timing *dvo_timing; struct lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode; struct drm_display_mode *panel_fixed_mode;
int lfp_data_size; int lfp_data_size, dvo_timing_offset;
/* Defaults if we can't find VBT info */ /* Defaults if we can't find VBT info */
dev_priv->lvds_dither = 0; dev_priv->lvds_dither = 0;
...@@ -133,14 +132,16 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv, ...@@ -133,14 +132,16 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
entry = (struct bdb_lvds_lfp_data_entry *) entry = (struct bdb_lvds_lfp_data_entry *)
((uint8_t *)lvds_lfp_data->data + (lfp_data_size * ((uint8_t *)lvds_lfp_data->data + (lfp_data_size *
lvds_options->panel_type)); lvds_options->panel_type));
dvo_timing_offset = lvds_lfp_data_ptrs->ptr[0].dvo_timing_offset -
lvds_lfp_data_ptrs->ptr[0].fp_timing_offset;
/* On IGDNG mobile, LVDS data block removes panel fitting registers. /*
So dec 2 dword from dvo_timing offset */ * the size of fp_timing varies on the different platform.
if (IS_IGDNG(dev)) * So calculate the DVO timing relative offset in LVDS data
* entry to get the DVO timing entry
*/
dvo_timing = (struct lvds_dvo_timing *) dvo_timing = (struct lvds_dvo_timing *)
((u8 *)&entry->dvo_timing - 8); ((unsigned char *)entry + dvo_timing_offset);
else
dvo_timing = &entry->dvo_timing;
panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL); panel_fixed_mode = kzalloc(sizeof(*panel_fixed_mode), GFP_KERNEL);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment