aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorZhao Yakui <yakui.zhao@intel.com>2009-11-19 22:24:16 -0500
committerEric Anholt <eric@anholt.net>2009-11-25 15:46:41 -0500
commit18f9ed12f8c977e25d65a16af8e8d73f72417ba1 (patch)
tree2e840183946aacd6bf310cbf083825d137d199b9
parentc8e0f93a381d1d76135e567f13a4418fce66fd95 (diff)
drm/i915: Enable LVDS downclock feature through EDID.
If more than one mode with the same resolution defined in EDID has different refresh rate, it is thought that the downclock is found for LVDS. We will program the different FPx0/1 register so that we can select dynamically between the low and high frequency. On the g4x platform we will use the CxSR feature to switch the different refresh rate if the LVDS downclock feature is supported. Signed-off-by: Zhao Yakui <yakui.zhao@intel.com> Reviewed-by: Jesse Barnes <jbarnes@virtuousgeek.org> Signed-off-by: Eric Anholt <eric@anholt.net>
-rw-r--r--drivers/gpu/drm/i915/i915_drv.h2
-rw-r--r--drivers/gpu/drm/i915/intel_display.c17
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c56
3 files changed, 72 insertions, 3 deletions
diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h
index 835625ba7c9c..dcc061cdc9a5 100644
--- a/drivers/gpu/drm/i915/i915_drv.h
+++ b/drivers/gpu/drm/i915/i915_drv.h
@@ -539,6 +539,8 @@ typedef struct drm_i915_private {
539 /* Reclocking support */ 539 /* Reclocking support */
540 bool render_reclock_avail; 540 bool render_reclock_avail;
541 bool lvds_downclock_avail; 541 bool lvds_downclock_avail;
542 /* indicates the reduced downclock for LVDS*/
543 int lvds_downclock;
542 struct work_struct idle_work; 544 struct work_struct idle_work;
543 struct timer_list idle_timer; 545 struct timer_list idle_timer;
544 bool busy; 546 bool busy;
diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c
index 33113c7d4e49..a65838ed24b9 100644
--- a/drivers/gpu/drm/i915/intel_display.c
+++ b/drivers/gpu/drm/i915/intel_display.c
@@ -2869,14 +2869,25 @@ static int intel_crtc_mode_set(struct drm_crtc *crtc,
2869 return -EINVAL; 2869 return -EINVAL;
2870 } 2870 }
2871 2871
2872 if (limit->find_reduced_pll && dev_priv->lvds_downclock_avail) { 2872 if (is_lvds && limit->find_reduced_pll &&
2873 dev_priv->lvds_downclock_avail) {
2873 memcpy(&reduced_clock, &clock, sizeof(intel_clock_t)); 2874 memcpy(&reduced_clock, &clock, sizeof(intel_clock_t));
2874 has_reduced_clock = limit->find_reduced_pll(limit, crtc, 2875 has_reduced_clock = limit->find_reduced_pll(limit, crtc,
2875 (adjusted_mode->clock*3/4), 2876 dev_priv->lvds_downclock,
2876 refclk, 2877 refclk,
2877 &reduced_clock); 2878 &reduced_clock);
2879 if (has_reduced_clock && (clock.p != reduced_clock.p)) {
2880 /*
2881 * If the different P is found, it means that we can't
2882 * switch the display clock by using the FP0/FP1.
2883 * In such case we will disable the LVDS downclock
2884 * feature.
2885 */
2886 DRM_DEBUG_KMS("Different P is found for "
2887 "LVDS clock/downclock\n");
2888 has_reduced_clock = 0;
2889 }
2878 } 2890 }
2879
2880 /* SDVO TV has fixed PLL values depend on its clock range, 2891 /* SDVO TV has fixed PLL values depend on its clock range,
2881 this mirrors vbios setting. */ 2892 this mirrors vbios setting. */
2882 if (is_sdvo && is_tv) { 2893 if (is_sdvo && is_tv) {
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index b1e3af792cf9..95011dfe1758 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -914,6 +914,61 @@ static int intel_lid_present(void)
914#endif 914#endif
915 915
916/** 916/**
917 * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
918 * @dev: drm device
919 * @connector: LVDS connector
920 *
921 * Find the reduced downclock for LVDS in EDID.
922 */
923static void intel_find_lvds_downclock(struct drm_device *dev,
924 struct drm_connector *connector)
925{
926 struct drm_i915_private *dev_priv = dev->dev_private;
927 struct drm_display_mode *scan, *panel_fixed_mode;
928 int temp_downclock;
929
930 panel_fixed_mode = dev_priv->panel_fixed_mode;
931 temp_downclock = panel_fixed_mode->clock;
932
933 mutex_lock(&dev->mode_config.mutex);
934 list_for_each_entry(scan, &connector->probed_modes, head) {
935 /*
936 * If one mode has the same resolution with the fixed_panel
937 * mode while they have the different refresh rate, it means
938 * that the reduced downclock is found for the LVDS. In such
939 * case we can set the different FPx0/1 to dynamically select
940 * between low and high frequency.
941 */
942 if (scan->hdisplay == panel_fixed_mode->hdisplay &&
943 scan->hsync_start == panel_fixed_mode->hsync_start &&
944 scan->hsync_end == panel_fixed_mode->hsync_end &&
945 scan->htotal == panel_fixed_mode->htotal &&
946 scan->vdisplay == panel_fixed_mode->vdisplay &&
947 scan->vsync_start == panel_fixed_mode->vsync_start &&
948 scan->vsync_end == panel_fixed_mode->vsync_end &&
949 scan->vtotal == panel_fixed_mode->vtotal) {
950 if (scan->clock < temp_downclock) {
951 /*
952 * The downclock is already found. But we
953 * expect to find the lower downclock.
954 */
955 temp_downclock = scan->clock;
956 }
957 }
958 }
959 mutex_unlock(&dev->mode_config.mutex);
960 if (temp_downclock < panel_fixed_mode->clock) {
961 /* We found the downclock for LVDS. */
962 dev_priv->lvds_downclock_avail = 1;
963 dev_priv->lvds_downclock = temp_downclock;
964 DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
965 "Normal clock %dKhz, downclock %dKhz\n",
966 panel_fixed_mode->clock, temp_downclock);
967 }
968 return;
969}
970
971/**
917 * intel_lvds_init - setup LVDS connectors on this device 972 * intel_lvds_init - setup LVDS connectors on this device
918 * @dev: drm device 973 * @dev: drm device
919 * 974 *
@@ -1023,6 +1078,7 @@ void intel_lvds_init(struct drm_device *dev)
1023 dev_priv->panel_fixed_mode = 1078 dev_priv->panel_fixed_mode =
1024 drm_mode_duplicate(dev, scan); 1079 drm_mode_duplicate(dev, scan);
1025 mutex_unlock(&dev->mode_config.mutex); 1080 mutex_unlock(&dev->mode_config.mutex);
1081 intel_find_lvds_downclock(dev, connector);
1026 goto out; 1082 goto out;
1027 } 1083 }
1028 mutex_unlock(&dev->mode_config.mutex); 1084 mutex_unlock(&dev->mode_config.mutex);