diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/i915/intel_lvds.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 291 |
1 files changed, 174 insertions, 117 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 05598ae10c4b..b66806a37d37 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <acpi/button.h> | 30 | #include <acpi/button.h> |
31 | #include <linux/dmi.h> | 31 | #include <linux/dmi.h> |
32 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
33 | #include <linux/slab.h> | ||
33 | #include "drmP.h" | 34 | #include "drmP.h" |
34 | #include "drm.h" | 35 | #include "drm.h" |
35 | #include "drm_crtc.h" | 36 | #include "drm_crtc.h" |
@@ -56,7 +57,7 @@ static void intel_lvds_set_backlight(struct drm_device *dev, int level) | |||
56 | struct drm_i915_private *dev_priv = dev->dev_private; | 57 | struct drm_i915_private *dev_priv = dev->dev_private; |
57 | u32 blc_pwm_ctl, reg; | 58 | u32 blc_pwm_ctl, reg; |
58 | 59 | ||
59 | if (IS_IGDNG(dev)) | 60 | if (HAS_PCH_SPLIT(dev)) |
60 | reg = BLC_PWM_CPU_CTL; | 61 | reg = BLC_PWM_CPU_CTL; |
61 | else | 62 | else |
62 | reg = BLC_PWM_CTL; | 63 | reg = BLC_PWM_CTL; |
@@ -74,7 +75,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | |||
74 | struct drm_i915_private *dev_priv = dev->dev_private; | 75 | struct drm_i915_private *dev_priv = dev->dev_private; |
75 | u32 reg; | 76 | u32 reg; |
76 | 77 | ||
77 | if (IS_IGDNG(dev)) | 78 | if (HAS_PCH_SPLIT(dev)) |
78 | reg = BLC_PWM_PCH_CTL2; | 79 | reg = BLC_PWM_PCH_CTL2; |
79 | else | 80 | else |
80 | reg = BLC_PWM_CTL; | 81 | reg = BLC_PWM_CTL; |
@@ -89,17 +90,22 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | |||
89 | static void intel_lvds_set_power(struct drm_device *dev, bool on) | 90 | static void intel_lvds_set_power(struct drm_device *dev, bool on) |
90 | { | 91 | { |
91 | struct drm_i915_private *dev_priv = dev->dev_private; | 92 | struct drm_i915_private *dev_priv = dev->dev_private; |
92 | u32 pp_status, ctl_reg, status_reg; | 93 | u32 pp_status, ctl_reg, status_reg, lvds_reg; |
93 | 94 | ||
94 | if (IS_IGDNG(dev)) { | 95 | if (HAS_PCH_SPLIT(dev)) { |
95 | ctl_reg = PCH_PP_CONTROL; | 96 | ctl_reg = PCH_PP_CONTROL; |
96 | status_reg = PCH_PP_STATUS; | 97 | status_reg = PCH_PP_STATUS; |
98 | lvds_reg = PCH_LVDS; | ||
97 | } else { | 99 | } else { |
98 | ctl_reg = PP_CONTROL; | 100 | ctl_reg = PP_CONTROL; |
99 | status_reg = PP_STATUS; | 101 | status_reg = PP_STATUS; |
102 | lvds_reg = LVDS; | ||
100 | } | 103 | } |
101 | 104 | ||
102 | if (on) { | 105 | if (on) { |
106 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) | LVDS_PORT_EN); | ||
107 | POSTING_READ(lvds_reg); | ||
108 | |||
103 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | | 109 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | |
104 | POWER_TARGET_ON); | 110 | POWER_TARGET_ON); |
105 | do { | 111 | do { |
@@ -115,6 +121,9 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on) | |||
115 | do { | 121 | do { |
116 | pp_status = I915_READ(status_reg); | 122 | pp_status = I915_READ(status_reg); |
117 | } while (pp_status & PP_ON); | 123 | } while (pp_status & PP_ON); |
124 | |||
125 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); | ||
126 | POSTING_READ(lvds_reg); | ||
118 | } | 127 | } |
119 | } | 128 | } |
120 | 129 | ||
@@ -137,7 +146,7 @@ static void intel_lvds_save(struct drm_connector *connector) | |||
137 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | 146 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; |
138 | u32 pwm_ctl_reg; | 147 | u32 pwm_ctl_reg; |
139 | 148 | ||
140 | if (IS_IGDNG(dev)) { | 149 | if (HAS_PCH_SPLIT(dev)) { |
141 | pp_on_reg = PCH_PP_ON_DELAYS; | 150 | pp_on_reg = PCH_PP_ON_DELAYS; |
142 | pp_off_reg = PCH_PP_OFF_DELAYS; | 151 | pp_off_reg = PCH_PP_OFF_DELAYS; |
143 | pp_ctl_reg = PCH_PP_CONTROL; | 152 | pp_ctl_reg = PCH_PP_CONTROL; |
@@ -174,7 +183,7 @@ static void intel_lvds_restore(struct drm_connector *connector) | |||
174 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | 183 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; |
175 | u32 pwm_ctl_reg; | 184 | u32 pwm_ctl_reg; |
176 | 185 | ||
177 | if (IS_IGDNG(dev)) { | 186 | if (HAS_PCH_SPLIT(dev)) { |
178 | pp_on_reg = PCH_PP_ON_DELAYS; | 187 | pp_on_reg = PCH_PP_ON_DELAYS; |
179 | pp_off_reg = PCH_PP_OFF_DELAYS; | 188 | pp_off_reg = PCH_PP_OFF_DELAYS; |
180 | pp_ctl_reg = PCH_PP_CONTROL; | 189 | pp_ctl_reg = PCH_PP_CONTROL; |
@@ -230,8 +239,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
230 | struct drm_i915_private *dev_priv = dev->dev_private; | 239 | struct drm_i915_private *dev_priv = dev->dev_private; |
231 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 240 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
232 | struct drm_encoder *tmp_encoder; | 241 | struct drm_encoder *tmp_encoder; |
233 | struct intel_output *intel_output = enc_to_intel_output(encoder); | 242 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
234 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | 243 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; |
235 | u32 pfit_control = 0, pfit_pgm_ratios = 0; | 244 | u32 pfit_control = 0, pfit_pgm_ratios = 0; |
236 | int left_border = 0, right_border = 0, top_border = 0; | 245 | int left_border = 0, right_border = 0, top_border = 0; |
237 | int bottom_border = 0; | 246 | int bottom_border = 0; |
@@ -297,7 +306,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
297 | } | 306 | } |
298 | 307 | ||
299 | /* full screen scale for now */ | 308 | /* full screen scale for now */ |
300 | if (IS_IGDNG(dev)) | 309 | if (HAS_PCH_SPLIT(dev)) |
301 | goto out; | 310 | goto out; |
302 | 311 | ||
303 | /* 965+ wants fuzzy fitting */ | 312 | /* 965+ wants fuzzy fitting */ |
@@ -327,7 +336,7 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
327 | * to register description and PRM. | 336 | * to register description and PRM. |
328 | * Change the value here to see the borders for debugging | 337 | * Change the value here to see the borders for debugging |
329 | */ | 338 | */ |
330 | if (!IS_IGDNG(dev)) { | 339 | if (!HAS_PCH_SPLIT(dev)) { |
331 | I915_WRITE(BCLRPAT_A, 0); | 340 | I915_WRITE(BCLRPAT_A, 0); |
332 | I915_WRITE(BCLRPAT_B, 0); | 341 | I915_WRITE(BCLRPAT_B, 0); |
333 | } | 342 | } |
@@ -548,7 +557,7 @@ static void intel_lvds_prepare(struct drm_encoder *encoder) | |||
548 | struct drm_i915_private *dev_priv = dev->dev_private; | 557 | struct drm_i915_private *dev_priv = dev->dev_private; |
549 | u32 reg; | 558 | u32 reg; |
550 | 559 | ||
551 | if (IS_IGDNG(dev)) | 560 | if (HAS_PCH_SPLIT(dev)) |
552 | reg = BLC_PWM_CPU_CTL; | 561 | reg = BLC_PWM_CPU_CTL; |
553 | else | 562 | else |
554 | reg = BLC_PWM_CTL; | 563 | reg = BLC_PWM_CTL; |
@@ -578,8 +587,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
578 | { | 587 | { |
579 | struct drm_device *dev = encoder->dev; | 588 | struct drm_device *dev = encoder->dev; |
580 | struct drm_i915_private *dev_priv = dev->dev_private; | 589 | struct drm_i915_private *dev_priv = dev->dev_private; |
581 | struct intel_output *intel_output = enc_to_intel_output(encoder); | 590 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); |
582 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | 591 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; |
583 | 592 | ||
584 | /* | 593 | /* |
585 | * The LVDS pin pair will already have been turned on in the | 594 | * The LVDS pin pair will already have been turned on in the |
@@ -587,7 +596,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
587 | * settings. | 596 | * settings. |
588 | */ | 597 | */ |
589 | 598 | ||
590 | if (IS_IGDNG(dev)) | 599 | if (HAS_PCH_SPLIT(dev)) |
591 | return; | 600 | return; |
592 | 601 | ||
593 | /* | 602 | /* |
@@ -599,18 +608,6 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
599 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); | 608 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); |
600 | } | 609 | } |
601 | 610 | ||
602 | /* Some lid devices report incorrect lid status, assume they're connected */ | ||
603 | static const struct dmi_system_id bad_lid_status[] = { | ||
604 | { | ||
605 | .ident = "Aspire One", | ||
606 | .matches = { | ||
607 | DMI_MATCH(DMI_SYS_VENDOR, "Acer"), | ||
608 | DMI_MATCH(DMI_PRODUCT_NAME, "Aspire one"), | ||
609 | }, | ||
610 | }, | ||
611 | { } | ||
612 | }; | ||
613 | |||
614 | /** | 611 | /** |
615 | * Detect the LVDS connection. | 612 | * Detect the LVDS connection. |
616 | * | 613 | * |
@@ -620,10 +617,14 @@ static const struct dmi_system_id bad_lid_status[] = { | |||
620 | */ | 617 | */ |
621 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) | 618 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) |
622 | { | 619 | { |
620 | struct drm_device *dev = connector->dev; | ||
623 | enum drm_connector_status status = connector_status_connected; | 621 | enum drm_connector_status status = connector_status_connected; |
624 | 622 | ||
625 | if (!acpi_lid_open() && !dmi_check_system(bad_lid_status)) | 623 | /* ACPI lid methods were generally unreliable in this generation, so |
626 | status = connector_status_disconnected; | 624 | * don't even bother. |
625 | */ | ||
626 | if (IS_GEN2(dev) || IS_GEN3(dev)) | ||
627 | return connector_status_connected; | ||
627 | 628 | ||
628 | return status; | 629 | return status; |
629 | } | 630 | } |
@@ -634,14 +635,16 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect | |||
634 | static int intel_lvds_get_modes(struct drm_connector *connector) | 635 | static int intel_lvds_get_modes(struct drm_connector *connector) |
635 | { | 636 | { |
636 | struct drm_device *dev = connector->dev; | 637 | struct drm_device *dev = connector->dev; |
637 | struct intel_output *intel_output = to_intel_output(connector); | 638 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
638 | struct drm_i915_private *dev_priv = dev->dev_private; | 639 | struct drm_i915_private *dev_priv = dev->dev_private; |
639 | int ret = 0; | 640 | int ret = 0; |
640 | 641 | ||
641 | ret = intel_ddc_get_modes(intel_output); | 642 | if (dev_priv->lvds_edid_good) { |
643 | ret = intel_ddc_get_modes(intel_encoder); | ||
642 | 644 | ||
643 | if (ret) | 645 | if (ret) |
644 | return ret; | 646 | return ret; |
647 | } | ||
645 | 648 | ||
646 | /* Didn't get an EDID, so | 649 | /* Didn't get an EDID, so |
647 | * Set wide sync ranges so we get all modes | 650 | * Set wide sync ranges so we get all modes |
@@ -679,7 +682,14 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
679 | struct drm_i915_private *dev_priv = | 682 | struct drm_i915_private *dev_priv = |
680 | container_of(nb, struct drm_i915_private, lid_notifier); | 683 | container_of(nb, struct drm_i915_private, lid_notifier); |
681 | struct drm_device *dev = dev_priv->dev; | 684 | struct drm_device *dev = dev_priv->dev; |
685 | struct drm_connector *connector = dev_priv->int_lvds_connector; | ||
682 | 686 | ||
687 | /* | ||
688 | * check and update the status of LVDS connector after receiving | ||
689 | * the LID nofication event. | ||
690 | */ | ||
691 | if (connector) | ||
692 | connector->status = connector->funcs->detect(connector); | ||
683 | if (!acpi_lid_open()) { | 693 | if (!acpi_lid_open()) { |
684 | dev_priv->modeset_on_lid = 1; | 694 | dev_priv->modeset_on_lid = 1; |
685 | return NOTIFY_OK; | 695 | return NOTIFY_OK; |
@@ -707,11 +717,11 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
707 | static void intel_lvds_destroy(struct drm_connector *connector) | 717 | static void intel_lvds_destroy(struct drm_connector *connector) |
708 | { | 718 | { |
709 | struct drm_device *dev = connector->dev; | 719 | struct drm_device *dev = connector->dev; |
710 | struct intel_output *intel_output = to_intel_output(connector); | 720 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
711 | struct drm_i915_private *dev_priv = dev->dev_private; | 721 | struct drm_i915_private *dev_priv = dev->dev_private; |
712 | 722 | ||
713 | if (intel_output->ddc_bus) | 723 | if (intel_encoder->ddc_bus) |
714 | intel_i2c_destroy(intel_output->ddc_bus); | 724 | intel_i2c_destroy(intel_encoder->ddc_bus); |
715 | if (dev_priv->lid_notifier.notifier_call) | 725 | if (dev_priv->lid_notifier.notifier_call) |
716 | acpi_lid_notifier_unregister(&dev_priv->lid_notifier); | 726 | acpi_lid_notifier_unregister(&dev_priv->lid_notifier); |
717 | drm_sysfs_connector_remove(connector); | 727 | drm_sysfs_connector_remove(connector); |
@@ -724,13 +734,13 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
724 | uint64_t value) | 734 | uint64_t value) |
725 | { | 735 | { |
726 | struct drm_device *dev = connector->dev; | 736 | struct drm_device *dev = connector->dev; |
727 | struct intel_output *intel_output = | 737 | struct intel_encoder *intel_encoder = |
728 | to_intel_output(connector); | 738 | to_intel_encoder(connector); |
729 | 739 | ||
730 | if (property == dev->mode_config.scaling_mode_property && | 740 | if (property == dev->mode_config.scaling_mode_property && |
731 | connector->encoder) { | 741 | connector->encoder) { |
732 | struct drm_crtc *crtc = connector->encoder->crtc; | 742 | struct drm_crtc *crtc = connector->encoder->crtc; |
733 | struct intel_lvds_priv *lvds_priv = intel_output->dev_priv; | 743 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; |
734 | if (value == DRM_MODE_SCALE_NONE) { | 744 | if (value == DRM_MODE_SCALE_NONE) { |
735 | DRM_DEBUG_KMS("no scaling not supported\n"); | 745 | DRM_DEBUG_KMS("no scaling not supported\n"); |
736 | return 0; | 746 | return 0; |
@@ -850,68 +860,113 @@ static const struct dmi_system_id intel_no_lvds[] = { | |||
850 | DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"), | 860 | DMI_MATCH(DMI_PRODUCT_VERSION, "AO00001JW"), |
851 | }, | 861 | }, |
852 | }, | 862 | }, |
863 | { | ||
864 | .callback = intel_no_lvds_dmi_callback, | ||
865 | .ident = "Clientron U800", | ||
866 | .matches = { | ||
867 | DMI_MATCH(DMI_SYS_VENDOR, "Clientron"), | ||
868 | DMI_MATCH(DMI_PRODUCT_NAME, "U800"), | ||
869 | }, | ||
870 | }, | ||
853 | 871 | ||
854 | { } /* terminating entry */ | 872 | { } /* terminating entry */ |
855 | }; | 873 | }; |
856 | 874 | ||
857 | #ifdef CONFIG_ACPI | 875 | /** |
858 | /* | 876 | * intel_find_lvds_downclock - find the reduced downclock for LVDS in EDID |
859 | * check_lid_device -- check whether @handle is an ACPI LID device. | 877 | * @dev: drm device |
860 | * @handle: ACPI device handle | 878 | * @connector: LVDS connector |
861 | * @level : depth in the ACPI namespace tree | 879 | * |
862 | * @context: the number of LID device when we find the device | 880 | * Find the reduced downclock for LVDS in EDID. |
863 | * @rv: a return value to fill if desired (Not use) | ||
864 | */ | 881 | */ |
865 | static acpi_status | 882 | static void intel_find_lvds_downclock(struct drm_device *dev, |
866 | check_lid_device(acpi_handle handle, u32 level, void *context, | 883 | struct drm_connector *connector) |
867 | void **return_value) | ||
868 | { | 884 | { |
869 | struct acpi_device *acpi_dev; | 885 | struct drm_i915_private *dev_priv = dev->dev_private; |
870 | int *lid_present = context; | 886 | struct drm_display_mode *scan, *panel_fixed_mode; |
871 | 887 | int temp_downclock; | |
872 | acpi_dev = NULL; | ||
873 | /* Get the acpi device for device handle */ | ||
874 | if (acpi_bus_get_device(handle, &acpi_dev) || !acpi_dev) { | ||
875 | /* If there is no ACPI device for handle, return */ | ||
876 | return AE_OK; | ||
877 | } | ||
878 | 888 | ||
879 | if (!strncmp(acpi_device_hid(acpi_dev), "PNP0C0D", 7)) | 889 | panel_fixed_mode = dev_priv->panel_fixed_mode; |
880 | *lid_present = 1; | 890 | temp_downclock = panel_fixed_mode->clock; |
881 | 891 | ||
882 | return AE_OK; | 892 | mutex_lock(&dev->mode_config.mutex); |
893 | list_for_each_entry(scan, &connector->probed_modes, head) { | ||
894 | /* | ||
895 | * If one mode has the same resolution with the fixed_panel | ||
896 | * mode while they have the different refresh rate, it means | ||
897 | * that the reduced downclock is found for the LVDS. In such | ||
898 | * case we can set the different FPx0/1 to dynamically select | ||
899 | * between low and high frequency. | ||
900 | */ | ||
901 | if (scan->hdisplay == panel_fixed_mode->hdisplay && | ||
902 | scan->hsync_start == panel_fixed_mode->hsync_start && | ||
903 | scan->hsync_end == panel_fixed_mode->hsync_end && | ||
904 | scan->htotal == panel_fixed_mode->htotal && | ||
905 | scan->vdisplay == panel_fixed_mode->vdisplay && | ||
906 | scan->vsync_start == panel_fixed_mode->vsync_start && | ||
907 | scan->vsync_end == panel_fixed_mode->vsync_end && | ||
908 | scan->vtotal == panel_fixed_mode->vtotal) { | ||
909 | if (scan->clock < temp_downclock) { | ||
910 | /* | ||
911 | * The downclock is already found. But we | ||
912 | * expect to find the lower downclock. | ||
913 | */ | ||
914 | temp_downclock = scan->clock; | ||
915 | } | ||
916 | } | ||
917 | } | ||
918 | mutex_unlock(&dev->mode_config.mutex); | ||
919 | if (temp_downclock < panel_fixed_mode->clock && | ||
920 | i915_lvds_downclock) { | ||
921 | /* We found the downclock for LVDS. */ | ||
922 | dev_priv->lvds_downclock_avail = 1; | ||
923 | dev_priv->lvds_downclock = temp_downclock; | ||
924 | DRM_DEBUG_KMS("LVDS downclock is found in EDID. " | ||
925 | "Normal clock %dKhz, downclock %dKhz\n", | ||
926 | panel_fixed_mode->clock, temp_downclock); | ||
927 | } | ||
928 | return; | ||
883 | } | 929 | } |
884 | 930 | ||
885 | /** | 931 | /* |
886 | * check whether there exists the ACPI LID device by enumerating the ACPI | 932 | * Enumerate the child dev array parsed from VBT to check whether |
887 | * device tree. | 933 | * the LVDS is present. |
934 | * If it is present, return 1. | ||
935 | * If it is not present, return false. | ||
936 | * If no child dev is parsed from VBT, it assumes that the LVDS is present. | ||
937 | * Note: The addin_offset should also be checked for LVDS panel. | ||
938 | * Only when it is non-zero, it is assumed that it is present. | ||
888 | */ | 939 | */ |
889 | static int intel_lid_present(void) | 940 | static int lvds_is_present_in_vbt(struct drm_device *dev) |
890 | { | 941 | { |
891 | int lid_present = 0; | 942 | struct drm_i915_private *dev_priv = dev->dev_private; |
943 | struct child_device_config *p_child; | ||
944 | int i, ret; | ||
892 | 945 | ||
893 | if (acpi_disabled) { | 946 | if (!dev_priv->child_dev_num) |
894 | /* If ACPI is disabled, there is no ACPI device tree to | ||
895 | * check, so assume the LID device would have been present. | ||
896 | */ | ||
897 | return 1; | 947 | return 1; |
898 | } | ||
899 | 948 | ||
900 | acpi_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, | 949 | ret = 0; |
901 | ACPI_UINT32_MAX, | 950 | for (i = 0; i < dev_priv->child_dev_num; i++) { |
902 | check_lid_device, &lid_present, NULL); | 951 | p_child = dev_priv->child_dev + i; |
952 | /* | ||
953 | * If the device type is not LFP, continue. | ||
954 | * If the device type is 0x22, it is also regarded as LFP. | ||
955 | */ | ||
956 | if (p_child->device_type != DEVICE_TYPE_INT_LFP && | ||
957 | p_child->device_type != DEVICE_TYPE_LFP) | ||
958 | continue; | ||
903 | 959 | ||
904 | return lid_present; | 960 | /* The addin_offset should be checked. Only when it is |
905 | } | 961 | * non-zero, it is regarded as present. |
906 | #else | 962 | */ |
907 | static int intel_lid_present(void) | 963 | if (p_child->addin_offset) { |
908 | { | 964 | ret = 1; |
909 | /* In the absence of ACPI built in, assume that the LID device would | 965 | break; |
910 | * have been present. | 966 | } |
911 | */ | 967 | } |
912 | return 1; | 968 | return ret; |
913 | } | 969 | } |
914 | #endif | ||
915 | 970 | ||
916 | /** | 971 | /** |
917 | * intel_lvds_init - setup LVDS connectors on this device | 972 | * intel_lvds_init - setup LVDS connectors on this device |
@@ -923,7 +978,7 @@ static int intel_lid_present(void) | |||
923 | void intel_lvds_init(struct drm_device *dev) | 978 | void intel_lvds_init(struct drm_device *dev) |
924 | { | 979 | { |
925 | struct drm_i915_private *dev_priv = dev->dev_private; | 980 | struct drm_i915_private *dev_priv = dev->dev_private; |
926 | struct intel_output *intel_output; | 981 | struct intel_encoder *intel_encoder; |
927 | struct drm_connector *connector; | 982 | struct drm_connector *connector; |
928 | struct drm_encoder *encoder; | 983 | struct drm_encoder *encoder; |
929 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 984 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
@@ -936,60 +991,55 @@ void intel_lvds_init(struct drm_device *dev) | |||
936 | if (dmi_check_system(intel_no_lvds)) | 991 | if (dmi_check_system(intel_no_lvds)) |
937 | return; | 992 | return; |
938 | 993 | ||
939 | /* Assume that any device without an ACPI LID device also doesn't | 994 | if (!lvds_is_present_in_vbt(dev)) { |
940 | * have an integrated LVDS. We would be better off parsing the BIOS | 995 | DRM_DEBUG_KMS("LVDS is not present in VBT\n"); |
941 | * to get a reliable indicator, but that code isn't written yet. | ||
942 | * | ||
943 | * In the case of all-in-one desktops using LVDS that we've seen, | ||
944 | * they're using SDVO LVDS. | ||
945 | */ | ||
946 | if (!intel_lid_present()) | ||
947 | return; | 996 | return; |
997 | } | ||
948 | 998 | ||
949 | if (IS_IGDNG(dev)) { | 999 | if (HAS_PCH_SPLIT(dev)) { |
950 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) | 1000 | if ((I915_READ(PCH_LVDS) & LVDS_DETECTED) == 0) |
951 | return; | 1001 | return; |
952 | if (dev_priv->edp_support) { | 1002 | if (dev_priv->edp_support) { |
953 | DRM_DEBUG("disable LVDS for eDP support\n"); | 1003 | DRM_DEBUG_KMS("disable LVDS for eDP support\n"); |
954 | return; | 1004 | return; |
955 | } | 1005 | } |
956 | gpio = PCH_GPIOC; | 1006 | gpio = PCH_GPIOC; |
957 | } | 1007 | } |
958 | 1008 | ||
959 | intel_output = kzalloc(sizeof(struct intel_output) + | 1009 | intel_encoder = kzalloc(sizeof(struct intel_encoder) + |
960 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | 1010 | sizeof(struct intel_lvds_priv), GFP_KERNEL); |
961 | if (!intel_output) { | 1011 | if (!intel_encoder) { |
962 | return; | 1012 | return; |
963 | } | 1013 | } |
964 | 1014 | ||
965 | connector = &intel_output->base; | 1015 | connector = &intel_encoder->base; |
966 | encoder = &intel_output->enc; | 1016 | encoder = &intel_encoder->enc; |
967 | drm_connector_init(dev, &intel_output->base, &intel_lvds_connector_funcs, | 1017 | drm_connector_init(dev, &intel_encoder->base, &intel_lvds_connector_funcs, |
968 | DRM_MODE_CONNECTOR_LVDS); | 1018 | DRM_MODE_CONNECTOR_LVDS); |
969 | 1019 | ||
970 | drm_encoder_init(dev, &intel_output->enc, &intel_lvds_enc_funcs, | 1020 | drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs, |
971 | DRM_MODE_ENCODER_LVDS); | 1021 | DRM_MODE_ENCODER_LVDS); |
972 | 1022 | ||
973 | drm_mode_connector_attach_encoder(&intel_output->base, &intel_output->enc); | 1023 | drm_mode_connector_attach_encoder(&intel_encoder->base, &intel_encoder->enc); |
974 | intel_output->type = INTEL_OUTPUT_LVDS; | 1024 | intel_encoder->type = INTEL_OUTPUT_LVDS; |
975 | 1025 | ||
976 | intel_output->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 1026 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
977 | intel_output->crtc_mask = (1 << 1); | 1027 | intel_encoder->crtc_mask = (1 << 1); |
978 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); | 1028 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); |
979 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); | 1029 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
980 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 1030 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
981 | connector->interlace_allowed = false; | 1031 | connector->interlace_allowed = false; |
982 | connector->doublescan_allowed = false; | 1032 | connector->doublescan_allowed = false; |
983 | 1033 | ||
984 | lvds_priv = (struct intel_lvds_priv *)(intel_output + 1); | 1034 | lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1); |
985 | intel_output->dev_priv = lvds_priv; | 1035 | intel_encoder->dev_priv = lvds_priv; |
986 | /* create the scaling mode property */ | 1036 | /* create the scaling mode property */ |
987 | drm_mode_create_scaling_mode_property(dev); | 1037 | drm_mode_create_scaling_mode_property(dev); |
988 | /* | 1038 | /* |
989 | * the initial panel fitting mode will be FULL_SCREEN. | 1039 | * the initial panel fitting mode will be FULL_SCREEN. |
990 | */ | 1040 | */ |
991 | 1041 | ||
992 | drm_connector_attach_property(&intel_output->base, | 1042 | drm_connector_attach_property(&intel_encoder->base, |
993 | dev->mode_config.scaling_mode_property, | 1043 | dev->mode_config.scaling_mode_property, |
994 | DRM_MODE_SCALE_FULLSCREEN); | 1044 | DRM_MODE_SCALE_FULLSCREEN); |
995 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; | 1045 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; |
@@ -1004,8 +1054,8 @@ void intel_lvds_init(struct drm_device *dev) | |||
1004 | */ | 1054 | */ |
1005 | 1055 | ||
1006 | /* Set up the DDC bus. */ | 1056 | /* Set up the DDC bus. */ |
1007 | intel_output->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); | 1057 | intel_encoder->ddc_bus = intel_i2c_create(dev, gpio, "LVDSDDC_C"); |
1008 | if (!intel_output->ddc_bus) { | 1058 | if (!intel_encoder->ddc_bus) { |
1009 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | 1059 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " |
1010 | "failed.\n"); | 1060 | "failed.\n"); |
1011 | goto failed; | 1061 | goto failed; |
@@ -1015,7 +1065,10 @@ void intel_lvds_init(struct drm_device *dev) | |||
1015 | * Attempt to get the fixed panel mode from DDC. Assume that the | 1065 | * Attempt to get the fixed panel mode from DDC. Assume that the |
1016 | * preferred mode is the right one. | 1066 | * preferred mode is the right one. |
1017 | */ | 1067 | */ |
1018 | intel_ddc_get_modes(intel_output); | 1068 | dev_priv->lvds_edid_good = true; |
1069 | |||
1070 | if (!intel_ddc_get_modes(intel_encoder)) | ||
1071 | dev_priv->lvds_edid_good = false; | ||
1019 | 1072 | ||
1020 | list_for_each_entry(scan, &connector->probed_modes, head) { | 1073 | list_for_each_entry(scan, &connector->probed_modes, head) { |
1021 | mutex_lock(&dev->mode_config.mutex); | 1074 | mutex_lock(&dev->mode_config.mutex); |
@@ -1023,6 +1076,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
1023 | dev_priv->panel_fixed_mode = | 1076 | dev_priv->panel_fixed_mode = |
1024 | drm_mode_duplicate(dev, scan); | 1077 | drm_mode_duplicate(dev, scan); |
1025 | mutex_unlock(&dev->mode_config.mutex); | 1078 | mutex_unlock(&dev->mode_config.mutex); |
1079 | intel_find_lvds_downclock(dev, connector); | ||
1026 | goto out; | 1080 | goto out; |
1027 | } | 1081 | } |
1028 | mutex_unlock(&dev->mode_config.mutex); | 1082 | mutex_unlock(&dev->mode_config.mutex); |
@@ -1047,8 +1101,8 @@ void intel_lvds_init(struct drm_device *dev) | |||
1047 | * correct mode. | 1101 | * correct mode. |
1048 | */ | 1102 | */ |
1049 | 1103 | ||
1050 | /* IGDNG: FIXME if still fail, not try pipe mode now */ | 1104 | /* Ironlake: FIXME if still fail, not try pipe mode now */ |
1051 | if (IS_IGDNG(dev)) | 1105 | if (HAS_PCH_SPLIT(dev)) |
1052 | goto failed; | 1106 | goto failed; |
1053 | 1107 | ||
1054 | lvds = I915_READ(LVDS); | 1108 | lvds = I915_READ(LVDS); |
@@ -1069,7 +1123,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
1069 | goto failed; | 1123 | goto failed; |
1070 | 1124 | ||
1071 | out: | 1125 | out: |
1072 | if (IS_IGDNG(dev)) { | 1126 | if (HAS_PCH_SPLIT(dev)) { |
1073 | u32 pwm; | 1127 | u32 pwm; |
1074 | /* make sure PWM is enabled */ | 1128 | /* make sure PWM is enabled */ |
1075 | pwm = I915_READ(BLC_PWM_CPU_CTL2); | 1129 | pwm = I915_READ(BLC_PWM_CPU_CTL2); |
@@ -1082,16 +1136,19 @@ out: | |||
1082 | } | 1136 | } |
1083 | dev_priv->lid_notifier.notifier_call = intel_lid_notify; | 1137 | dev_priv->lid_notifier.notifier_call = intel_lid_notify; |
1084 | if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { | 1138 | if (acpi_lid_notifier_register(&dev_priv->lid_notifier)) { |
1085 | DRM_DEBUG("lid notifier registration failed\n"); | 1139 | DRM_DEBUG_KMS("lid notifier registration failed\n"); |
1086 | dev_priv->lid_notifier.notifier_call = NULL; | 1140 | dev_priv->lid_notifier.notifier_call = NULL; |
1087 | } | 1141 | } |
1142 | /* keep the LVDS connector */ | ||
1143 | dev_priv->int_lvds_connector = connector; | ||
1088 | drm_sysfs_connector_add(connector); | 1144 | drm_sysfs_connector_add(connector); |
1089 | return; | 1145 | return; |
1090 | 1146 | ||
1091 | failed: | 1147 | failed: |
1092 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); | 1148 | DRM_DEBUG_KMS("No LVDS modes found, disabling.\n"); |
1093 | if (intel_output->ddc_bus) | 1149 | if (intel_encoder->ddc_bus) |
1094 | intel_i2c_destroy(intel_output->ddc_bus); | 1150 | intel_i2c_destroy(intel_encoder->ddc_bus); |
1095 | drm_connector_cleanup(connector); | 1151 | drm_connector_cleanup(connector); |
1096 | kfree(intel_output); | 1152 | drm_encoder_cleanup(encoder); |
1153 | kfree(intel_encoder); | ||
1097 | } | 1154 | } |