summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-11-20 11:24:17 +0800
committerEric Anholt <eric@anholt.net>2009-11-25 13:02:33 -0800
commitd1fcea6a529d22212b324f26cd660c85b289a026 (patch)
tree4b17d2172a1d05f4049386b9528c5d7c4bdc19cd
parent18f9ed12f8c977e25d65a16af8e8d73f72417ba1 (diff)
downloadkernel-crypto-d1fcea6a529d22212b324f26cd660c85b289a026.tar.gz
kernel-crypto-d1fcea6a529d22212b324f26cd660c85b289a026.tar.xz
kernel-crypto-d1fcea6a529d22212b324f26cd660c85b289a026.zip
drm/i915: Check whether the LVDS downclock is found in VBT
Enumerate the LVDS panel timing info entry list in VBT to check whether the LVDS downclock is found. If found, the downclock is also used to switch dynamically between low and high frequency for LVDS. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Acked-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/intel_bios.c42
1 files changed, 42 insertions, 0 deletions
diff --git a/drivers/gpu/drm/i915/intel_bios.c b/drivers/gpu/drm/i915/intel_bios.c
index cbd911837b0..10806cd5e4d 100644
--- a/drivers/gpu/drm/i915/intel_bios.c
+++ b/drivers/gpu/drm/i915/intel_bios.c
@@ -114,6 +114,8 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
struct lvds_dvo_timing *dvo_timing;
struct drm_display_mode *panel_fixed_mode;
int lfp_data_size, dvo_timing_offset;
+ int i, temp_downclock;
+ struct drm_display_mode *temp_mode;
/* Defaults if we can't find VBT info */
dev_priv->lvds_dither = 0;
@@ -162,6 +164,46 @@ parse_lfp_panel_data(struct drm_i915_private *dev_priv,
DRM_DEBUG_KMS("Found panel mode in BIOS VBT tables:\n");
drm_mode_debug_printmodeline(panel_fixed_mode);
+ temp_mode = kzalloc(sizeof(*temp_mode), GFP_KERNEL);
+ temp_downclock = panel_fixed_mode->clock;
+ /*
+ * enumerate the LVDS panel timing info entry in VBT to check whether
+ * the LVDS downclock is found.
+ */
+ for (i = 0; i < 16; i++) {
+ entry = (struct bdb_lvds_lfp_data_entry *)
+ ((uint8_t *)lvds_lfp_data->data + (lfp_data_size * i));
+ dvo_timing = (struct lvds_dvo_timing *)
+ ((unsigned char *)entry + dvo_timing_offset);
+
+ fill_detail_timing_data(temp_mode, dvo_timing);
+
+ if (temp_mode->hdisplay == panel_fixed_mode->hdisplay &&
+ temp_mode->hsync_start == panel_fixed_mode->hsync_start &&
+ temp_mode->hsync_end == panel_fixed_mode->hsync_end &&
+ temp_mode->htotal == panel_fixed_mode->htotal &&
+ temp_mode->vdisplay == panel_fixed_mode->vdisplay &&
+ temp_mode->vsync_start == panel_fixed_mode->vsync_start &&
+ temp_mode->vsync_end == panel_fixed_mode->vsync_end &&
+ temp_mode->vtotal == panel_fixed_mode->vtotal &&
+ temp_mode->clock < temp_downclock) {
+ /*
+ * downclock is already found. But we expect
+ * to find the lower downclock.
+ */
+ temp_downclock = temp_mode->clock;
+ }
+ /* clear it to zero */
+ memset(temp_mode, 0, sizeof(*temp_mode));
+ }
+ kfree(temp_mode);
+ if (temp_downclock < panel_fixed_mode->clock) {
+ dev_priv->lvds_downclock_avail = 1;
+ dev_priv->lvds_downclock = temp_downclock;
+ DRM_DEBUG_KMS("LVDS downclock is found in VBT. ",
+ "Normal Clock %dKHz, downclock %dKHz\n",
+ temp_downclock, panel_fixed_mode->clock);
+ }
return;
}