diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 111 |
1 files changed, 27 insertions, 84 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index b66806a37d37..6a1accd83aec 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -139,75 +139,6 @@ static void intel_lvds_dpms(struct drm_encoder *encoder, int mode) | |||
139 | /* XXX: We never power down the LVDS pairs. */ | 139 | /* XXX: We never power down the LVDS pairs. */ |
140 | } | 140 | } |
141 | 141 | ||
142 | static void intel_lvds_save(struct drm_connector *connector) | ||
143 | { | ||
144 | struct drm_device *dev = connector->dev; | ||
145 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
146 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | ||
147 | u32 pwm_ctl_reg; | ||
148 | |||
149 | if (HAS_PCH_SPLIT(dev)) { | ||
150 | pp_on_reg = PCH_PP_ON_DELAYS; | ||
151 | pp_off_reg = PCH_PP_OFF_DELAYS; | ||
152 | pp_ctl_reg = PCH_PP_CONTROL; | ||
153 | pp_div_reg = PCH_PP_DIVISOR; | ||
154 | pwm_ctl_reg = BLC_PWM_CPU_CTL; | ||
155 | } else { | ||
156 | pp_on_reg = PP_ON_DELAYS; | ||
157 | pp_off_reg = PP_OFF_DELAYS; | ||
158 | pp_ctl_reg = PP_CONTROL; | ||
159 | pp_div_reg = PP_DIVISOR; | ||
160 | pwm_ctl_reg = BLC_PWM_CTL; | ||
161 | } | ||
162 | |||
163 | dev_priv->savePP_ON = I915_READ(pp_on_reg); | ||
164 | dev_priv->savePP_OFF = I915_READ(pp_off_reg); | ||
165 | dev_priv->savePP_CONTROL = I915_READ(pp_ctl_reg); | ||
166 | dev_priv->savePP_DIVISOR = I915_READ(pp_div_reg); | ||
167 | dev_priv->saveBLC_PWM_CTL = I915_READ(pwm_ctl_reg); | ||
168 | dev_priv->backlight_duty_cycle = (dev_priv->saveBLC_PWM_CTL & | ||
169 | BACKLIGHT_DUTY_CYCLE_MASK); | ||
170 | |||
171 | /* | ||
172 | * If the light is off at server startup, just make it full brightness | ||
173 | */ | ||
174 | if (dev_priv->backlight_duty_cycle == 0) | ||
175 | dev_priv->backlight_duty_cycle = | ||
176 | intel_lvds_get_max_backlight(dev); | ||
177 | } | ||
178 | |||
179 | static void intel_lvds_restore(struct drm_connector *connector) | ||
180 | { | ||
181 | struct drm_device *dev = connector->dev; | ||
182 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
183 | u32 pp_on_reg, pp_off_reg, pp_ctl_reg, pp_div_reg; | ||
184 | u32 pwm_ctl_reg; | ||
185 | |||
186 | if (HAS_PCH_SPLIT(dev)) { | ||
187 | pp_on_reg = PCH_PP_ON_DELAYS; | ||
188 | pp_off_reg = PCH_PP_OFF_DELAYS; | ||
189 | pp_ctl_reg = PCH_PP_CONTROL; | ||
190 | pp_div_reg = PCH_PP_DIVISOR; | ||
191 | pwm_ctl_reg = BLC_PWM_CPU_CTL; | ||
192 | } else { | ||
193 | pp_on_reg = PP_ON_DELAYS; | ||
194 | pp_off_reg = PP_OFF_DELAYS; | ||
195 | pp_ctl_reg = PP_CONTROL; | ||
196 | pp_div_reg = PP_DIVISOR; | ||
197 | pwm_ctl_reg = BLC_PWM_CTL; | ||
198 | } | ||
199 | |||
200 | I915_WRITE(pwm_ctl_reg, dev_priv->saveBLC_PWM_CTL); | ||
201 | I915_WRITE(pp_on_reg, dev_priv->savePP_ON); | ||
202 | I915_WRITE(pp_off_reg, dev_priv->savePP_OFF); | ||
203 | I915_WRITE(pp_div_reg, dev_priv->savePP_DIVISOR); | ||
204 | I915_WRITE(pp_ctl_reg, dev_priv->savePP_CONTROL); | ||
205 | if (dev_priv->savePP_CONTROL & POWER_TARGET_ON) | ||
206 | intel_lvds_set_power(dev, true); | ||
207 | else | ||
208 | intel_lvds_set_power(dev, false); | ||
209 | } | ||
210 | |||
211 | static int intel_lvds_mode_valid(struct drm_connector *connector, | 142 | static int intel_lvds_mode_valid(struct drm_connector *connector, |
212 | struct drm_display_mode *mode) | 143 | struct drm_display_mode *mode) |
213 | { | 144 | { |
@@ -635,12 +566,13 @@ static enum drm_connector_status intel_lvds_detect(struct drm_connector *connect | |||
635 | static int intel_lvds_get_modes(struct drm_connector *connector) | 566 | static int intel_lvds_get_modes(struct drm_connector *connector) |
636 | { | 567 | { |
637 | struct drm_device *dev = connector->dev; | 568 | struct drm_device *dev = connector->dev; |
638 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | 569 | struct drm_encoder *encoder = intel_attached_encoder(connector); |
570 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
639 | struct drm_i915_private *dev_priv = dev->dev_private; | 571 | struct drm_i915_private *dev_priv = dev->dev_private; |
640 | int ret = 0; | 572 | int ret = 0; |
641 | 573 | ||
642 | if (dev_priv->lvds_edid_good) { | 574 | if (dev_priv->lvds_edid_good) { |
643 | ret = intel_ddc_get_modes(intel_encoder); | 575 | ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); |
644 | 576 | ||
645 | if (ret) | 577 | if (ret) |
646 | return ret; | 578 | return ret; |
@@ -717,11 +649,8 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
717 | static void intel_lvds_destroy(struct drm_connector *connector) | 649 | static void intel_lvds_destroy(struct drm_connector *connector) |
718 | { | 650 | { |
719 | struct drm_device *dev = connector->dev; | 651 | struct drm_device *dev = connector->dev; |
720 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); | ||
721 | struct drm_i915_private *dev_priv = dev->dev_private; | 652 | struct drm_i915_private *dev_priv = dev->dev_private; |
722 | 653 | ||
723 | if (intel_encoder->ddc_bus) | ||
724 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
725 | if (dev_priv->lid_notifier.notifier_call) | 654 | if (dev_priv->lid_notifier.notifier_call) |
726 | acpi_lid_notifier_unregister(&dev_priv->lid_notifier); | 655 | acpi_lid_notifier_unregister(&dev_priv->lid_notifier); |
727 | drm_sysfs_connector_remove(connector); | 656 | drm_sysfs_connector_remove(connector); |
@@ -734,13 +663,14 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
734 | uint64_t value) | 663 | uint64_t value) |
735 | { | 664 | { |
736 | struct drm_device *dev = connector->dev; | 665 | struct drm_device *dev = connector->dev; |
737 | struct intel_encoder *intel_encoder = | ||
738 | to_intel_encoder(connector); | ||
739 | 666 | ||
740 | if (property == dev->mode_config.scaling_mode_property && | 667 | if (property == dev->mode_config.scaling_mode_property && |
741 | connector->encoder) { | 668 | connector->encoder) { |
742 | struct drm_crtc *crtc = connector->encoder->crtc; | 669 | struct drm_crtc *crtc = connector->encoder->crtc; |
670 | struct drm_encoder *encoder = connector->encoder; | ||
671 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
743 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; | 672 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; |
673 | |||
744 | if (value == DRM_MODE_SCALE_NONE) { | 674 | if (value == DRM_MODE_SCALE_NONE) { |
745 | DRM_DEBUG_KMS("no scaling not supported\n"); | 675 | DRM_DEBUG_KMS("no scaling not supported\n"); |
746 | return 0; | 676 | return 0; |
@@ -774,13 +704,11 @@ static const struct drm_encoder_helper_funcs intel_lvds_helper_funcs = { | |||
774 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { | 704 | static const struct drm_connector_helper_funcs intel_lvds_connector_helper_funcs = { |
775 | .get_modes = intel_lvds_get_modes, | 705 | .get_modes = intel_lvds_get_modes, |
776 | .mode_valid = intel_lvds_mode_valid, | 706 | .mode_valid = intel_lvds_mode_valid, |
777 | .best_encoder = intel_best_encoder, | 707 | .best_encoder = intel_attached_encoder, |
778 | }; | 708 | }; |
779 | 709 | ||
780 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { | 710 | static const struct drm_connector_funcs intel_lvds_connector_funcs = { |
781 | .dpms = drm_helper_connector_dpms, | 711 | .dpms = drm_helper_connector_dpms, |
782 | .save = intel_lvds_save, | ||
783 | .restore = intel_lvds_restore, | ||
784 | .detect = intel_lvds_detect, | 712 | .detect = intel_lvds_detect, |
785 | .fill_modes = drm_helper_probe_single_connector_modes, | 713 | .fill_modes = drm_helper_probe_single_connector_modes, |
786 | .set_property = intel_lvds_set_property, | 714 | .set_property = intel_lvds_set_property, |
@@ -790,7 +718,12 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { | |||
790 | 718 | ||
791 | static void intel_lvds_enc_destroy(struct drm_encoder *encoder) | 719 | static void intel_lvds_enc_destroy(struct drm_encoder *encoder) |
792 | { | 720 | { |
721 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
722 | |||
723 | if (intel_encoder->ddc_bus) | ||
724 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
793 | drm_encoder_cleanup(encoder); | 725 | drm_encoder_cleanup(encoder); |
726 | kfree(intel_encoder); | ||
794 | } | 727 | } |
795 | 728 | ||
796 | static const struct drm_encoder_funcs intel_lvds_enc_funcs = { | 729 | static const struct drm_encoder_funcs intel_lvds_enc_funcs = { |
@@ -979,6 +912,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
979 | { | 912 | { |
980 | struct drm_i915_private *dev_priv = dev->dev_private; | 913 | struct drm_i915_private *dev_priv = dev->dev_private; |
981 | struct intel_encoder *intel_encoder; | 914 | struct intel_encoder *intel_encoder; |
915 | struct intel_connector *intel_connector; | ||
982 | struct drm_connector *connector; | 916 | struct drm_connector *connector; |
983 | struct drm_encoder *encoder; | 917 | struct drm_encoder *encoder; |
984 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 918 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
@@ -1012,19 +946,27 @@ void intel_lvds_init(struct drm_device *dev) | |||
1012 | return; | 946 | return; |
1013 | } | 947 | } |
1014 | 948 | ||
1015 | connector = &intel_encoder->base; | 949 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
950 | if (!intel_connector) { | ||
951 | kfree(intel_encoder); | ||
952 | return; | ||
953 | } | ||
954 | |||
955 | connector = &intel_connector->base; | ||
1016 | encoder = &intel_encoder->enc; | 956 | encoder = &intel_encoder->enc; |
1017 | drm_connector_init(dev, &intel_encoder->base, &intel_lvds_connector_funcs, | 957 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, |
1018 | DRM_MODE_CONNECTOR_LVDS); | 958 | DRM_MODE_CONNECTOR_LVDS); |
1019 | 959 | ||
1020 | drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs, | 960 | drm_encoder_init(dev, &intel_encoder->enc, &intel_lvds_enc_funcs, |
1021 | DRM_MODE_ENCODER_LVDS); | 961 | DRM_MODE_ENCODER_LVDS); |
1022 | 962 | ||
1023 | drm_mode_connector_attach_encoder(&intel_encoder->base, &intel_encoder->enc); | 963 | drm_mode_connector_attach_encoder(&intel_connector->base, &intel_encoder->enc); |
1024 | intel_encoder->type = INTEL_OUTPUT_LVDS; | 964 | intel_encoder->type = INTEL_OUTPUT_LVDS; |
1025 | 965 | ||
1026 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 966 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
1027 | intel_encoder->crtc_mask = (1 << 1); | 967 | intel_encoder->crtc_mask = (1 << 1); |
968 | if (IS_I965G(dev)) | ||
969 | intel_encoder->crtc_mask |= (1 << 0); | ||
1028 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); | 970 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); |
1029 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); | 971 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
1030 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 972 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
@@ -1039,7 +981,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
1039 | * the initial panel fitting mode will be FULL_SCREEN. | 981 | * the initial panel fitting mode will be FULL_SCREEN. |
1040 | */ | 982 | */ |
1041 | 983 | ||
1042 | drm_connector_attach_property(&intel_encoder->base, | 984 | drm_connector_attach_property(&intel_connector->base, |
1043 | dev->mode_config.scaling_mode_property, | 985 | dev->mode_config.scaling_mode_property, |
1044 | DRM_MODE_SCALE_FULLSCREEN); | 986 | DRM_MODE_SCALE_FULLSCREEN); |
1045 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; | 987 | lvds_priv->fitting_mode = DRM_MODE_SCALE_FULLSCREEN; |
@@ -1067,7 +1009,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
1067 | */ | 1009 | */ |
1068 | dev_priv->lvds_edid_good = true; | 1010 | dev_priv->lvds_edid_good = true; |
1069 | 1011 | ||
1070 | if (!intel_ddc_get_modes(intel_encoder)) | 1012 | if (!intel_ddc_get_modes(connector, intel_encoder->ddc_bus)) |
1071 | dev_priv->lvds_edid_good = false; | 1013 | dev_priv->lvds_edid_good = false; |
1072 | 1014 | ||
1073 | list_for_each_entry(scan, &connector->probed_modes, head) { | 1015 | list_for_each_entry(scan, &connector->probed_modes, head) { |
@@ -1151,4 +1093,5 @@ failed: | |||
1151 | drm_connector_cleanup(connector); | 1093 | drm_connector_cleanup(connector); |
1152 | drm_encoder_cleanup(encoder); | 1094 | drm_encoder_cleanup(encoder); |
1153 | kfree(intel_encoder); | 1095 | kfree(intel_encoder); |
1096 | kfree(intel_connector); | ||
1154 | } | 1097 | } |