aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_lvds.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
-rw-r--r--drivers/gpu/drm/i915/intel_lvds.c140
1 files changed, 118 insertions, 22 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c
index eb365021bb5a..3118ce274e67 100644
--- a/drivers/gpu/drm/i915/intel_lvds.c
+++ b/drivers/gpu/drm/i915/intel_lvds.c
@@ -56,7 +56,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level)
56 struct drm_i915_private *dev_priv = dev->dev_private; 56 struct drm_i915_private *dev_priv = dev->dev_private;
57 u32 blc_pwm_ctl, reg; 57 u32 blc_pwm_ctl, reg;
58 58
59 if (IS_IGDNG(dev)) 59 if (IS_IRONLAKE(dev))
60 reg = BLC_PWM_CPU_CTL; 60 reg = BLC_PWM_CPU_CTL;
61 else 61 else
62 reg = BLC_PWM_CTL; 62 reg = BLC_PWM_CTL;
@@ -74,7 +74,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev)
74 struct drm_i915_private *dev_priv = dev->dev_private; 74 struct drm_i915_private *dev_priv = dev->dev_private;
75 u32 reg; 75 u32 reg;
76 76
77 if (IS_IGDNG(dev)) 77 if (IS_IRONLAKE(dev))
78 reg = BLC_PWM_PCH_CTL2; 78 reg = BLC_PWM_PCH_CTL2;
79 else 79 else
80 reg = BLC_PWM_CTL; 80 reg = BLC_PWM_CTL;
@@ -91,7 +91,7 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on)
91 struct drm_i915_private *dev_priv = dev->dev_private; 91 struct drm_i915_private *dev_priv = dev->dev_private;
92 u32 pp_status, ctl_reg, status_reg; 92 u32 pp_status, ctl_reg, status_reg;
93 93
94 if (IS_IGDNG(dev)) { 94 if (IS_IRONLAKE(dev)) {
95 ctl_reg = PCH_PP_CONTROL; 95 ctl_reg = PCH_PP_CONTROL;
96 status_reg = PCH_PP_STATUS; 96 status_reg = PCH_PP_STATUS;
97 } else { 97 } else {
@@ -137,7 +137,7 @@ static void intel_lvds_save(struct drm_connector *connector)
137 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; 137 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
138 u32 pwm_ctl_reg; 138 u32 pwm_ctl_reg;
139 139
140 if (IS_IGDNG(dev)) { 140 if (IS_IRONLAKE(dev)) {
141 pp_on_reg = PCH_PP_ON_DELAYS; 141 pp_on_reg = PCH_PP_ON_DELAYS;
142 pp_off_reg = PCH_PP_OFF_DELAYS; 142 pp_off_reg = PCH_PP_OFF_DELAYS;
143 pp_ctl_reg = PCH_PP_CONTROL; 143 pp_ctl_reg = PCH_PP_CONTROL;
@@ -174,7 +174,7 @@ static void intel_lvds_restore(struct drm_connector *connector)
174 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; 174 u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg;
175 u32 pwm_ctl_reg; 175 u32 pwm_ctl_reg;
176 176
177 if (IS_IGDNG(dev)) { 177 if (IS_IRONLAKE(dev)) {
178 pp_on_reg = PCH_PP_ON_DELAYS; 178 pp_on_reg = PCH_PP_ON_DELAYS;
179 pp_off_reg = PCH_PP_OFF_DELAYS; 179 pp_off_reg = PCH_PP_OFF_DELAYS;
180 pp_ctl_reg = PCH_PP_CONTROL; 180 pp_ctl_reg = PCH_PP_CONTROL;
@@ -297,7 +297,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
297 } 297 }
298 298
299 /* full screen scale for now */ 299 /* full screen scale for now */
300 if (IS_IGDNG(dev)) 300 if (IS_IRONLAKE(dev))
301 goto out; 301 goto out;
302 302
303 /* 965+ wants fuzzy fitting */ 303 /* 965+ wants fuzzy fitting */
@@ -327,7 +327,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder,
327 * to register description and PRM. 327 * to register description and PRM.
328 * Change the value here to see the borders for debugging 328 * Change the value here to see the borders for debugging
329 */ 329 */
330 if (!IS_IGDNG(dev)) { 330 if (!IS_IRONLAKE(dev)) {
331 I915_WRITE(BCLRPAT_A, 0); 331 I915_WRITE(BCLRPAT_A, 0);
332 I915_WRITE(BCLRPAT_B, 0); 332 I915_WRITE(BCLRPAT_B, 0);
333 } 333 }
@@ -548,7 +548,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder)
548 struct drm_i915_private *dev_priv = dev->dev_private; 548 struct drm_i915_private *dev_priv = dev->dev_private;
549 u32 reg; 549 u32 reg;
550 550
551 if (IS_IGDNG(dev)) 551 if (IS_IRONLAKE(dev))
552 reg = BLC_PWM_CPU_CTL; 552 reg = BLC_PWM_CPU_CTL;
553 else 553 else
554 reg = BLC_PWM_CTL; 554 reg = BLC_PWM_CTL;
@@ -587,7 +587,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder,
587 * settings. 587 * settings.
588 */ 588 */
589 589
590 if (IS_IGDNG(dev)) 590 if (IS_IRONLAKE(dev))
591 return; 591 return;
592 592
593 /* 593 /*
@@ -914,6 +914,101 @@ 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/*
972 * Enumerate the child dev array parsed from VBT to check whether
973 * the LVDS is present.
974 * If it is present, return 1.
975 * If it is not present, return false.
976 * If no child dev is parsed from VBT, it assumes that the LVDS is present.
977 * Note: The addin_offset should also be checked for LVDS panel.
978 * Only when it is non-zero, it is assumed that it is present.
979 */
980static int lvds_is_present_in_vbt(struct drm_device *dev)
981{
982 struct drm_i915_private *dev_priv = dev->dev_private;
983 struct child_device_config *p_child;
984 int i, ret;
985
986 if (!dev_priv->child_dev_num)
987 return 1;
988
989 ret = 0;
990 for (i = 0; i < dev_priv->child_dev_num; i++) {
991 p_child = dev_priv->child_dev + i;
992 /*
993 * If the device type is not LFP, continue.
994 * If the device type is 0x22, it is also regarded as LFP.
995 */
996 if (p_child->device_type != DEVICE_TYPE_INT_LFP &&
997 p_child->device_type != DEVICE_TYPE_LFP)
998 continue;
999
1000 /* The addin_offset should be checked. Only when it is
1001 * non-zero, it is regarded as present.
1002 */
1003 if (p_child->addin_offset) {
1004 ret = 1;
1005 break;
1006 }
1007 }
1008 return ret;
1009}
1010
1011/**
917 * intel_lvds_init - setup LVDS connectors on this device 1012 * intel_lvds_init - setup LVDS connectors on this device
918 * @dev: drm device 1013 * @dev: drm device
919 * 1014 *
@@ -936,21 +1031,20 @@ void intel_lvds_init(struct drm_device *dev)
936 if (dmi_check_system(intel_no_lvds)) 1031 if (dmi_check_system(intel_no_lvds))
937 return; 1032 return;
938 1033
939 /* Assume that any device without an ACPI LID device also doesn't 1034 /*
940 * have an integrated LVDS. We would be better off parsing the BIOS 1035 * Assume LVDS is present if there's an ACPI lid device or if the
941 * to get a reliable indicator, but that code isn't written yet. 1036 * device is present in the VBT.
942 *
943 * In the case of all-in-one desktops using LVDS that we've seen,
944 * they're using SDVO LVDS.
945 */ 1037 */
946 if (!intel_lid_present()) 1038 if (!lvds_is_present_in_vbt(dev) && !intel_lid_present()) {
1039 DRM_DEBUG_KMS("LVDS is not present in VBT and no lid detected\n");
947 return; 1040 return;
1041 }
948 1042
949 if (IS_IGDNG(dev)) { 1043 if (IS_IRONLAKE(dev)) {
950 if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) 1044 if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0)
951 return; 1045 return;
952 if (dev_priv->edp_support) { 1046 if (dev_priv->edp_support) {
953 DRM_DEBUG("disable LVDS for eDP support\n"); 1047 DRM_DEBUG_KMS("disable LVDS for eDP support\n");
954 return; 1048 return;
955 } 1049 }
956 gpio = PCH_GPIOC; 1050 gpio = PCH_GPIOC;
@@ -1023,6 +1117,7 @@ void intel_lvds_init(struct drm_device *dev)
1023 dev_priv->panel_fixed_mode = 1117 dev_priv->panel_fixed_mode =
1024 drm_mode_duplicate(dev, scan); 1118 drm_mode_duplicate(dev, scan);
1025 mutex_unlock(&dev->mode_config.mutex); 1119 mutex_unlock(&dev->mode_config.mutex);
1120 intel_find_lvds_downclock(dev, connector);
1026 goto out; 1121 goto out;
1027 } 1122 }
1028 mutex_unlock(&dev->mode_config.mutex); 1123 mutex_unlock(&dev->mode_config.mutex);
@@ -1047,8 +1142,8 @@ void intel_lvds_init(struct drm_device *dev)
1047 * correct mode. 1142 * correct mode.
1048 */ 1143 */
1049 1144
1050 /* IGDNG: FIXME if still fail, not try pipe mode now */ 1145 /* Ironlake: FIXME if still fail, not try pipe mode now */
1051 if (IS_IGDNG(dev)) 1146 if (IS_IRONLAKE(dev))
1052 goto failed; 1147 goto failed;
1053 1148
1054 lvds = I915_READ(LVDS); 1149 lvds = I915_READ(LVDS);
@@ -1069,7 +1164,7 @@ void intel_lvds_init(struct drm_device *dev)
1069 goto failed; 1164 goto failed;
1070 1165
1071out: 1166out:
1072 if (IS_IGDNG(dev)) { 1167 if (IS_IRONLAKE(dev)) {
1073 u32 pwm; 1168 u32 pwm;
1074 /* make sure PWM is enabled */ 1169 /* make sure PWM is enabled */
1075 pwm = I915_READ(BLC_PWM_CPU_CTL2); 1170 pwm = I915_READ(BLC_PWM_CPU_CTL2);
@@ -1082,7 +1177,7 @@ out:
1082 } 1177 }
1083 dev_priv->lid_notifier.notifier_call = intel_lid_notify; 1178 dev_priv->lid_notifier.notifier_call = intel_lid_notify;
1084 if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { 1179 if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) {
1085 DRM_DEBUG("lid notifier registration failed\n"); 1180 DRM_DEBUG_KMS("lid notifier registration failed\n");
1086 dev_priv->lid_notifier.notifier_call = NULL; 1181 dev_priv->lid_notifier.notifier_call = NULL;
1087 } 1182 }
1088 drm_sysfs_connector_add(connector); 1183 drm_sysfs_connector_add(connector);
@@ -1093,5 +1188,6 @@ failed:
1093 if (intel_output->ddc_bus) 1188 if (intel_output->ddc_bus)
1094 intel_i2c_destroy(intel_output->ddc_bus); 1189 intel_i2c_destroy(intel_output->ddc_bus);
1095 drm_connector_cleanup(connector); 1190 drm_connector_cleanup(connector);
1191 drm_encoder_cleanup(encoder);
1096 kfree(intel_output); 1192 kfree(intel_output);
1097} 1193}