aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/i915/intel_drv.h6
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c69
-rw-r--r--drivers/gpu/drm/i915/intel_panel.c57
3 files changed, 78 insertions, 54 deletions
diff --git a/drivers/gpu/drm/i915/intel_drv.h b/drivers/gpu/drm/i915/intel_drv.h
index 5dea38967523..9f8b46574956 100644
--- a/drivers/gpu/drm/i915/intel_drv.h
+++ b/drivers/gpu/drm/i915/intel_drv.h
@@ -155,6 +155,7 @@ struct intel_encoder {
155 155
156struct intel_panel { 156struct intel_panel {
157 struct drm_display_mode *fixed_mode; 157 struct drm_display_mode *fixed_mode;
158 struct drm_display_mode *downclock_mode;
158 int fitting_mode; 159 int fitting_mode;
159 160
160 /* backlight */ 161 /* backlight */
@@ -823,7 +824,10 @@ void intel_panel_disable_backlight(struct intel_connector *connector);
823void intel_panel_destroy_backlight(struct drm_connector *connector); 824void intel_panel_destroy_backlight(struct drm_connector *connector);
824void intel_panel_init_backlight_funcs(struct drm_device *dev); 825void intel_panel_init_backlight_funcs(struct drm_device *dev);
825enum drm_connector_status intel_panel_detect(struct drm_device *dev); 826enum drm_connector_status intel_panel_detect(struct drm_device *dev);
826 827extern struct drm_display_mode *intel_find_panel_downclock(
828 struct drm_device *dev,
829 struct drm_display_mode *fixed_mode,
830 struct drm_connector *connector);
827 831
828/* intel_pm.c */ 832/* intel_pm.c */
829void intel_init_clock_gating(struct drm_device *dev); 833void intel_init_clock_gating(struct drm_device *dev);
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index 4c8553ea82f7..8bcb93a2a9f6 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -755,57 +755,6 @@ static const struct dmi_system_id intel_no_lvds[] = {
755 { } /* terminating entry */ 755 { } /* terminating entry */
756}; 756};
757 757
758/**
759 * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID
760 * @dev: drm device
761 * @connector: LVDS connector
762 *
763 * Find the reduced downclock for LVDS in EDID.
764 */
765static void intel_find_lvds_downclock(struct drm_device *dev,
766 struct drm_display_mode *fixed_mode,
767 struct drm_connector *connector)
768{
769 struct drm_i915_private *dev_priv = dev->dev_private;
770 struct drm_display_mode *scan;
771 int temp_downclock;
772
773 temp_downclock = fixed_mode->clock;
774 list_for_each_entry(scan, &connector->probed_modes, head) {
775 /*
776 * If one mode has the same resolution with the fixed_panel
777 * mode while they have the different refresh rate, it means
778 * that the reduced downclock is found for the LVDS. In such
779 * case we can set the different FPx0/1 to dynamically select
780 * between low and high frequency.
781 */
782 if (scan->hdisplay == fixed_mode->hdisplay &&
783 scan->hsync_start == fixed_mode->hsync_start &&
784 scan->hsync_end == fixed_mode->hsync_end &&
785 scan->htotal == fixed_mode->htotal &&
786 scan->vdisplay == fixed_mode->vdisplay &&
787 scan->vsync_start == fixed_mode->vsync_start &&
788 scan->vsync_end == fixed_mode->vsync_end &&
789 scan->vtotal == fixed_mode->vtotal) {
790 if (scan->clock < temp_downclock) {
791 /*
792 * The downclock is already found. But we
793 * expect to find the lower downclock.
794 */
795 temp_downclock = scan->clock;
796 }
797 }
798 }
799 if (temp_downclock < fixed_mode->clock && i915_lvds_downclock) {
800 /* We found the downclock for LVDS. */
801 dev_priv->lvds_downclock_avail = 1;
802 dev_priv->lvds_downclock = temp_downclock;
803 DRM_DEBUG_KMS("LVDS downclock is found in EDID. "
804 "Normal clock %dKhz, downclock %dKhz\n",
805 fixed_mode->clock, temp_downclock);
806 }
807}
808
809/* 758/*
810 * Enumerate the child dev array parsed from VBT to check whether 759 * Enumerate the child dev array parsed from VBT to check whether
811 * the LVDS is present. 760 * the LVDS is present.
@@ -1083,8 +1032,22 @@ void intel_lvds_init(struct drm_device *dev)
1083 1032
1084 fixed_mode = drm_mode_duplicate(dev, scan); 1033 fixed_mode = drm_mode_duplicate(dev, scan);
1085 if (fixed_mode) { 1034 if (fixed_mode) {
1086 intel_find_lvds_downclock(dev, fixed_mode, 1035 intel_connector->panel.downclock_mode =
1087 connector); 1036 intel_find_panel_downclock(dev,
1037 fixed_mode, connector);
1038 if (intel_connector->panel.downclock_mode !=
1039 NULL && i915_lvds_downclock) {
1040 /* We found the downclock for LVDS. */
1041 dev_priv->lvds_downclock_avail = true;
1042 dev_priv->lvds_downclock =
1043 intel_connector->panel.
1044 downclock_mode->clock;
1045 DRM_DEBUG_KMS("LVDS downclock is found"
1046 " in EDID. Normal clock %dKhz, "
1047 "downclock %dKhz\n",
1048 fixed_mode->clock,
1049 dev_priv->lvds_downclock);
1050 }
1088 goto out; 1051 goto out;
1089 } 1052 }
1090 } 1053 }
diff --git a/drivers/gpu/drm/i915/intel_panel.c b/drivers/gpu/drm/i915/intel_panel.c
index e480cf41c536..b0f6e6cc4354 100644
--- a/drivers/gpu/drm/i915/intel_panel.c
+++ b/drivers/gpu/drm/i915/intel_panel.c
@@ -1104,6 +1104,59 @@ void intel_panel_destroy_backlight(struct drm_connector *connector)
1104 intel_backlight_device_unregister(intel_connector); 1104 intel_backlight_device_unregister(intel_connector);
1105} 1105}
1106 1106
1107/**
1108 * intel_find_panel_downclock - find the reduced downclock for LVDS in EDID
1109 * @dev: drm device
1110 * @fixed_mode : panel native mode
1111 * @connector: LVDS/eDP connector
1112 *
1113 * Return downclock_avail
1114 * Find the reduced downclock for LVDS/eDP in EDID.
1115 */
1116struct drm_display_mode *
1117intel_find_panel_downclock(struct drm_device *dev,
1118 struct drm_display_mode *fixed_mode,
1119 struct drm_connector *connector)
1120{
1121 struct drm_display_mode *scan, *tmp_mode;
1122 int temp_downclock;
1123
1124 temp_downclock = fixed_mode->clock;
1125 tmp_mode = NULL;
1126
1127 list_for_each_entry(scan, &connector->probed_modes, head) {
1128 /*
1129 * If one mode has the same resolution with the fixed_panel
1130 * mode while they have the different refresh rate, it means
1131 * that the reduced downclock is found. In such
1132 * case we can set the different FPx0/1 to dynamically select
1133 * between low and high frequency.
1134 */
1135 if (scan->hdisplay == fixed_mode->hdisplay &&
1136 scan->hsync_start == fixed_mode->hsync_start &&
1137 scan->hsync_end == fixed_mode->hsync_end &&
1138 scan->htotal == fixed_mode->htotal &&
1139 scan->vdisplay == fixed_mode->vdisplay &&
1140 scan->vsync_start == fixed_mode->vsync_start &&
1141 scan->vsync_end == fixed_mode->vsync_end &&
1142 scan->vtotal == fixed_mode->vtotal) {
1143 if (scan->clock < temp_downclock) {
1144 /*
1145 * The downclock is already found. But we
1146 * expect to find the lower downclock.
1147 */
1148 temp_downclock = scan->clock;
1149 tmp_mode = scan;
1150 }
1151 }
1152 }
1153
1154 if (temp_downclock < fixed_mode->clock)
1155 return drm_mode_duplicate(dev, tmp_mode);
1156 else
1157 return NULL;
1158}
1159
1107/* Set up chip specific backlight functions */ 1160/* Set up chip specific backlight functions */
1108void intel_panel_init_backlight_funcs(struct drm_device *dev) 1161void intel_panel_init_backlight_funcs(struct drm_device *dev)
1109{ 1162{
@@ -1157,4 +1210,8 @@ void intel_panel_fini(struct intel_panel *panel)
1157 1210
1158 if (panel->fixed_mode) 1211 if (panel->fixed_mode)
1159 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode); 1212 drm_mode_destroy(intel_connector->base.dev, panel->fixed_mode);
1213
1214 if (panel->downclock_mode)
1215 drm_mode_destroy(intel_connector->base.dev,
1216 panel->downclock_mode);
1160} 1217}