diff options
-rw-r--r-- | drivers/gpu/drm/i915/intel_drv.h | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 69 | ||||
-rw-r--r-- | drivers/gpu/drm/i915/intel_panel.c | 57 |
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 | ||
156 | struct intel_panel { | 156 | struct 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); | |||
823 | void intel_panel_destroy_backlight(struct drm_connector *connector); | 824 | void intel_panel_destroy_backlight(struct drm_connector *connector); |
824 | void intel_panel_init_backlight_funcs(struct drm_device *dev); | 825 | void intel_panel_init_backlight_funcs(struct drm_device *dev); |
825 | enum drm_connector_status intel_panel_detect(struct drm_device *dev); | 826 | enum drm_connector_status intel_panel_detect(struct drm_device *dev); |
826 | 827 | extern 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 */ |
829 | void intel_init_clock_gating(struct drm_device *dev); | 833 | void 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 | */ | ||
765 | static 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 | */ | ||
1116 | struct drm_display_mode * | ||
1117 | intel_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 */ |
1108 | void intel_panel_init_backlight_funcs(struct drm_device *dev) | 1161 | void 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 | } |