Rev 5354 | Rev 6660 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 5354 | Rev 6084 | ||
---|---|---|---|
Line 26... | Line 26... | ||
26 | 26 | ||
27 | #include |
27 | #include |
28 | #include |
28 | #include |
29 | #include |
29 | #include |
- | 30 | #include |
|
30 | #include |
31 | #include |
31 | #include |
32 | #include |
32 | #include |
33 | #include |
33 | #include |
34 | #include |
34 | #include "intel_drv.h" |
35 | #include "intel_drv.h" |
Line 108... | Line 109... | ||
108 | 109 | ||
109 | return flags; |
110 | return flags; |
Line 110... | Line 111... | ||
110 | } |
111 | } |
111 | 112 | ||
112 | static void intel_crt_get_config(struct intel_encoder *encoder, |
113 | static void intel_crt_get_config(struct intel_encoder *encoder, |
113 | struct intel_crtc_config *pipe_config) |
114 | struct intel_crtc_state *pipe_config) |
114 | { |
115 | { |
Line 115... | Line 116... | ||
115 | struct drm_device *dev = encoder->base.dev; |
116 | struct drm_device *dev = encoder->base.dev; |
Line 116... | Line 117... | ||
116 | int dotclock; |
117 | int dotclock; |
Line 117... | Line 118... | ||
117 | 118 | ||
118 | pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); |
119 | pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
Line 119... | Line 120... | ||
119 | 120 | ||
120 | dotclock = pipe_config->port_clock; |
121 | dotclock = pipe_config->port_clock; |
Line 121... | Line 122... | ||
121 | 122 | ||
122 | if (HAS_PCH_SPLIT(dev)) |
123 | if (HAS_PCH_SPLIT(dev)) |
123 | ironlake_check_encoder_dotclock(pipe_config, dotclock); |
124 | ironlake_check_encoder_dotclock(pipe_config, dotclock); |
124 | 125 | ||
Line 125... | Line 126... | ||
125 | pipe_config->adjusted_mode.crtc_clock = dotclock; |
126 | pipe_config->base.adjusted_mode.crtc_clock = dotclock; |
126 | } |
127 | } |
127 | 128 | ||
128 | static void hsw_crt_get_config(struct intel_encoder *encoder, |
129 | static void hsw_crt_get_config(struct intel_encoder *encoder, |
129 | struct intel_crtc_config *pipe_config) |
130 | struct intel_crtc_state *pipe_config) |
130 | { |
- | |
131 | intel_ddi_get_config(encoder, pipe_config); |
- | |
132 | - | ||
133 | pipe_config->adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | |
- | |
134 | DRM_MODE_FLAG_NHSYNC | |
- | |
135 | DRM_MODE_FLAG_PVSYNC | |
- | |
136 | DRM_MODE_FLAG_NVSYNC); |
- | |
137 | pipe_config->adjusted_mode.flags |= intel_crt_get_flags(encoder); |
- | |
138 | } |
- | |
139 | - | ||
140 | static void hsw_crt_pre_enable(struct intel_encoder *encoder) |
- | |
141 | { |
- | |
142 | struct drm_device *dev = encoder->base.dev; |
131 | { |
Line 143... | Line 132... | ||
143 | struct drm_i915_private *dev_priv = dev->dev_private; |
132 | intel_ddi_get_config(encoder, pipe_config); |
144 | 133 | ||
145 | WARN(I915_READ(SPLL_CTL) & SPLL_PLL_ENABLE, "SPLL already enabled\n"); |
134 | pipe_config->base.adjusted_mode.flags &= ~(DRM_MODE_FLAG_PHSYNC | |
146 | I915_WRITE(SPLL_CTL, |
135 | DRM_MODE_FLAG_NHSYNC | |
147 | SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC); |
136 | DRM_MODE_FLAG_PVSYNC | |
148 | POSTING_READ(SPLL_CTL); |
137 | DRM_MODE_FLAG_NVSYNC); |
149 | udelay(20); |
138 | pipe_config->base.adjusted_mode.flags |= intel_crt_get_flags(encoder); |
150 | } |
139 | } |
151 | 140 | ||
152 | /* Note: The caller is required to filter out dpms modes not supported by the |
141 | /* Note: The caller is required to filter out dpms modes not supported by the |
Line 153... | Line 142... | ||
153 | * platform. */ |
142 | * platform. */ |
154 | static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) |
143 | static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode) |
155 | { |
144 | { |
Line 204... | Line 193... | ||
204 | static void intel_disable_crt(struct intel_encoder *encoder) |
193 | static void intel_disable_crt(struct intel_encoder *encoder) |
205 | { |
194 | { |
206 | intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF); |
195 | intel_crt_set_dpms(encoder, DRM_MODE_DPMS_OFF); |
207 | } |
196 | } |
Line 208... | Line -... | ||
208 | - | ||
209 | 197 | ||
210 | static void hsw_crt_post_disable(struct intel_encoder *encoder) |
198 | static void pch_disable_crt(struct intel_encoder *encoder) |
211 | { |
- | |
212 | struct drm_device *dev = encoder->base.dev; |
- | |
213 | struct drm_i915_private *dev_priv = dev->dev_private; |
199 | { |
Line 214... | Line 200... | ||
214 | uint32_t val; |
200 | } |
- | 201 | ||
215 | 202 | static void pch_post_disable_crt(struct intel_encoder *encoder) |
|
216 | DRM_DEBUG_KMS("Disabling SPLL\n"); |
- | |
217 | val = I915_READ(SPLL_CTL); |
- | |
218 | WARN_ON(!(val & SPLL_PLL_ENABLE)); |
- | |
219 | I915_WRITE(SPLL_CTL, val & ~SPLL_PLL_ENABLE); |
203 | { |
Line 220... | Line 204... | ||
220 | POSTING_READ(SPLL_CTL); |
204 | intel_disable_crt(encoder); |
221 | } |
205 | } |
222 | 206 | ||
Line 223... | Line 207... | ||
223 | static void intel_enable_crt(struct intel_encoder *encoder) |
207 | static void intel_enable_crt(struct intel_encoder *encoder) |
224 | { |
208 | { |
Line 225... | Line -... | ||
225 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
- | |
226 | - | ||
227 | intel_crt_set_dpms(encoder, crt->connector->base.dpms); |
- | |
228 | } |
- | |
229 | - | ||
230 | /* Special dpms function to support cloning between dvo/sdvo/crt. */ |
- | |
231 | static void intel_crt_dpms(struct drm_connector *connector, int mode) |
- | |
232 | { |
- | |
233 | struct drm_device *dev = connector->dev; |
- | |
234 | struct intel_encoder *encoder = intel_attached_encoder(connector); |
- | |
235 | struct drm_crtc *crtc; |
- | |
236 | int old_dpms; |
- | |
237 | - | ||
238 | /* PCH platforms and VLV only support on/off. */ |
- | |
239 | if (INTEL_INFO(dev)->gen >= 5 && mode != DRM_MODE_DPMS_ON) |
- | |
240 | mode = DRM_MODE_DPMS_OFF; |
- | |
241 | - | ||
242 | if (mode == connector->dpms) |
- | |
243 | return; |
- | |
244 | - | ||
245 | old_dpms = connector->dpms; |
- | |
246 | connector->dpms = mode; |
- | |
247 | - | ||
248 | /* Only need to change hw state when actually enabled */ |
- | |
249 | crtc = encoder->base.crtc; |
- | |
250 | if (!crtc) { |
- | |
251 | encoder->connectors_active = false; |
- | |
252 | return; |
- | |
253 | } |
- | |
254 | - | ||
255 | /* We need the pipe to run for anything but OFF. */ |
- | |
256 | if (mode == DRM_MODE_DPMS_OFF) |
- | |
257 | encoder->connectors_active = false; |
- | |
258 | else |
- | |
259 | encoder->connectors_active = true; |
- | |
260 | - | ||
261 | /* We call connector dpms manually below in case pipe dpms doesn't |
- | |
262 | * change due to cloning. */ |
- | |
263 | if (mode < old_dpms) { |
- | |
264 | /* From off to on, enable the pipe first. */ |
- | |
265 | intel_crtc_update_dpms(crtc); |
- | |
266 | - | ||
267 | intel_crt_set_dpms(encoder, mode); |
- | |
268 | } else { |
- | |
269 | intel_crt_set_dpms(encoder, mode); |
- | |
270 | - | ||
271 | intel_crtc_update_dpms(crtc); |
- | |
272 | } |
209 | struct intel_crt *crt = intel_encoder_to_crt(encoder); |
273 | 210 | ||
274 | intel_modeset_check_state(connector->dev); |
211 | intel_crt_set_dpms(encoder, crt->connector->base.dpms); |
275 | } |
212 | } |
276 | 213 | ||
Line 301... | Line 238... | ||
301 | 238 | ||
302 | return MODE_OK; |
239 | return MODE_OK; |
Line 303... | Line 240... | ||
303 | } |
240 | } |
304 | 241 | ||
305 | static bool intel_crt_compute_config(struct intel_encoder *encoder, |
242 | static bool intel_crt_compute_config(struct intel_encoder *encoder, |
306 | struct intel_crtc_config *pipe_config) |
243 | struct intel_crtc_state *pipe_config) |
Line 307... | Line 244... | ||
307 | { |
244 | { |
308 | struct drm_device *dev = encoder->base.dev; |
245 | struct drm_device *dev = encoder->base.dev; |
Line 316... | Line 253... | ||
316 | 253 | ||
317 | /* FDI must always be 2.7 GHz */ |
254 | /* FDI must always be 2.7 GHz */ |
318 | if (HAS_DDI(dev)) { |
255 | if (HAS_DDI(dev)) { |
319 | pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
256 | pipe_config->ddi_pll_sel = PORT_CLK_SEL_SPLL; |
- | 257 | pipe_config->port_clock = 135000 * 2; |
|
- | 258 | ||
- | 259 | pipe_config->dpll_hw_state.wrpll = 0; |
|
- | 260 | pipe_config->dpll_hw_state.spll = |
|
320 | pipe_config->port_clock = 135000 * 2; |
261 | SPLL_PLL_ENABLE | SPLL_PLL_FREQ_1350MHz | SPLL_PLL_SSC; |
Line 321... | Line 262... | ||
321 | } |
262 | } |
322 | 263 | ||
Line 412... | Line 353... | ||
412 | */ |
353 | */ |
413 | static bool intel_crt_detect_hotplug(struct drm_connector *connector) |
354 | static bool intel_crt_detect_hotplug(struct drm_connector *connector) |
414 | { |
355 | { |
415 | struct drm_device *dev = connector->dev; |
356 | struct drm_device *dev = connector->dev; |
416 | struct drm_i915_private *dev_priv = dev->dev_private; |
357 | struct drm_i915_private *dev_priv = dev->dev_private; |
417 | u32 hotplug_en, orig, stat; |
358 | u32 stat; |
418 | bool ret = false; |
359 | bool ret = false; |
419 | int i, tries = 0; |
360 | int i, tries = 0; |
Line 420... | Line 361... | ||
420 | 361 | ||
421 | if (HAS_PCH_SPLIT(dev)) |
362 | if (HAS_PCH_SPLIT(dev)) |
Line 431... | Line 372... | ||
431 | 372 | ||
432 | if (IS_G4X(dev) && !IS_GM45(dev)) |
373 | if (IS_G4X(dev) && !IS_GM45(dev)) |
433 | tries = 2; |
374 | tries = 2; |
434 | else |
375 | else |
435 | tries = 1; |
- | |
436 | hotplug_en = orig = I915_READ(PORT_HOTPLUG_EN); |
- | |
Line 437... | Line 376... | ||
437 | hotplug_en |= CRT_HOTPLUG_FORCE_DETECT; |
376 | tries = 1; |
438 | 377 | ||
- | 378 | for (i = 0; i < tries ; i++) { |
|
- | 379 | /* turn on the FORCE_DETECT */ |
|
439 | for (i = 0; i < tries ; i++) { |
380 | i915_hotplug_interrupt_update(dev_priv, |
440 | /* turn on the FORCE_DETECT */ |
381 | CRT_HOTPLUG_FORCE_DETECT, |
441 | I915_WRITE(PORT_HOTPLUG_EN, hotplug_en); |
382 | CRT_HOTPLUG_FORCE_DETECT); |
442 | /* wait for FORCE_DETECT to go off */ |
383 | /* wait for FORCE_DETECT to go off */ |
443 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & |
384 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & |
444 | CRT_HOTPLUG_FORCE_DETECT) == 0, |
385 | CRT_HOTPLUG_FORCE_DETECT) == 0, |
Line 451... | Line 392... | ||
451 | ret = true; |
392 | ret = true; |
Line 452... | Line 393... | ||
452 | 393 | ||
453 | /* clear the interrupt we just generated, if any */ |
394 | /* clear the interrupt we just generated, if any */ |
Line 454... | Line -... | ||
454 | I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); |
- | |
455 | 395 | I915_WRITE(PORT_HOTPLUG_STAT, CRT_HOTPLUG_INT_STATUS); |
|
Line 456... | Line 396... | ||
456 | /* and put the bits back */ |
396 | |
457 | I915_WRITE(PORT_HOTPLUG_EN, orig); |
397 | i915_hotplug_interrupt_update(dev_priv, CRT_HOTPLUG_FORCE_DETECT, 0); |
Line 458... | Line 398... | ||
458 | 398 | ||
Line 687... | Line 627... | ||
687 | 627 | ||
688 | /* Load detection is broken on HPD capable machines. Whoever wants a |
628 | /* Load detection is broken on HPD capable machines. Whoever wants a |
689 | * broken monitor (without edid) to work behind a broken kvm (that fails |
629 | * broken monitor (without edid) to work behind a broken kvm (that fails |
690 | * to have the right resistors for HP detection) needs to fix this up. |
630 | * to have the right resistors for HP detection) needs to fix this up. |
691 | * For now just bail out. */ |
631 | * For now just bail out. */ |
692 | if (I915_HAS_HOTPLUG(dev)) { |
632 | if (I915_HAS_HOTPLUG(dev) && !i915.load_detect_test) { |
693 | status = connector_status_disconnected; |
633 | status = connector_status_disconnected; |
694 | goto out; |
634 | goto out; |
Line 695... | Line 635... | ||
695 | } |
635 | } |
Line 703... | Line 643... | ||
703 | 643 | ||
704 | /* for pre-945g platforms use load detect */ |
644 | /* for pre-945g platforms use load detect */ |
705 | if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { |
645 | if (intel_get_load_detect_pipe(connector, NULL, &tmp, &ctx)) { |
706 | if (intel_crt_detect_ddc(connector)) |
646 | if (intel_crt_detect_ddc(connector)) |
707 | status = connector_status_connected; |
647 | status = connector_status_connected; |
708 | else |
648 | else if (INTEL_INFO(dev)->gen < 4) |
- | 649 | status = intel_crt_load_detect(crt); |
|
- | 650 | else |
|
709 | status = intel_crt_load_detect(crt); |
651 | status = connector_status_unknown; |
710 | intel_release_load_detect_pipe(connector, &tmp); |
652 | intel_release_load_detect_pipe(connector, &tmp, &ctx); |
711 | } else |
653 | } else |
Line 712... | Line 654... | ||
712 | status = connector_status_unknown; |
654 | status = connector_status_unknown; |
713 | 655 | ||
Line 742... | Line 684... | ||
742 | ret = intel_crt_ddc_get_modes(connector, i2c); |
684 | ret = intel_crt_ddc_get_modes(connector, i2c); |
743 | if (ret || !IS_G4X(dev)) |
685 | if (ret || !IS_G4X(dev)) |
744 | goto out; |
686 | goto out; |
Line 745... | Line 687... | ||
745 | 687 | ||
746 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
688 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
747 | i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PORT_DPB); |
689 | i2c = intel_gmbus_get_adapter(dev_priv, GMBUS_PIN_DPB); |
Line 748... | Line 690... | ||
748 | ret = intel_crt_ddc_get_modes(connector, i2c); |
690 | ret = intel_crt_ddc_get_modes(connector, i2c); |
749 | 691 | ||
Line 785... | Line 727... | ||
785 | * Routines for controlling stuff on the analog port |
727 | * Routines for controlling stuff on the analog port |
786 | */ |
728 | */ |
Line 787... | Line 729... | ||
787 | 729 | ||
788 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
730 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
789 | .reset = intel_crt_reset, |
731 | .reset = intel_crt_reset, |
790 | .dpms = intel_crt_dpms, |
732 | .dpms = drm_atomic_helper_connector_dpms, |
791 | .detect = intel_crt_detect, |
733 | .detect = intel_crt_detect, |
792 | .fill_modes = drm_helper_probe_single_connector_modes, |
734 | .fill_modes = drm_helper_probe_single_connector_modes, |
793 | .destroy = intel_crt_destroy, |
735 | .destroy = intel_crt_destroy, |
- | 736 | .set_property = intel_crt_set_property, |
|
- | 737 | .atomic_destroy_state = drm_atomic_helper_connector_destroy_state, |
|
- | 738 | .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, |
|
794 | .set_property = intel_crt_set_property, |
739 | .atomic_get_property = intel_connector_atomic_get_property, |
Line 795... | Line 740... | ||
795 | }; |
740 | }; |
796 | 741 | ||
797 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
742 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
Line 843... | Line 788... | ||
843 | 788 | ||
844 | crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); |
789 | crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); |
845 | if (!crt) |
790 | if (!crt) |
Line 846... | Line 791... | ||
846 | return; |
791 | return; |
847 | 792 | ||
848 | intel_connector = kzalloc(sizeof(*intel_connector), GFP_KERNEL); |
793 | intel_connector = intel_connector_alloc(); |
849 | if (!intel_connector) { |
794 | if (!intel_connector) { |
850 | kfree(crt); |
795 | kfree(crt); |
Line 880... | Line 825... | ||
880 | crt->adpa_reg = VLV_ADPA; |
825 | crt->adpa_reg = VLV_ADPA; |
881 | else |
826 | else |
882 | crt->adpa_reg = ADPA; |
827 | crt->adpa_reg = ADPA; |
Line 883... | Line 828... | ||
883 | 828 | ||
- | 829 | crt->base.compute_config = intel_crt_compute_config; |
|
- | 830 | if (HAS_PCH_SPLIT(dev) && !HAS_DDI(dev)) { |
|
- | 831 | crt->base.disable = pch_disable_crt; |
|
- | 832 | crt->base.post_disable = pch_post_disable_crt; |
|
884 | crt->base.compute_config = intel_crt_compute_config; |
833 | } else { |
- | 834 | crt->base.disable = intel_disable_crt; |
|
885 | crt->base.disable = intel_disable_crt; |
835 | } |
886 | crt->base.enable = intel_enable_crt; |
836 | crt->base.enable = intel_enable_crt; |
887 | if (I915_HAS_HOTPLUG(dev)) |
837 | if (I915_HAS_HOTPLUG(dev)) |
888 | crt->base.hpd_pin = HPD_CRT; |
838 | crt->base.hpd_pin = HPD_CRT; |
889 | if (HAS_DDI(dev)) { |
839 | if (HAS_DDI(dev)) { |
890 | crt->base.get_config = hsw_crt_get_config; |
840 | crt->base.get_config = hsw_crt_get_config; |
891 | crt->base.get_hw_state = intel_ddi_get_hw_state; |
- | |
892 | crt->base.pre_enable = hsw_crt_pre_enable; |
- | |
893 | crt->base.post_disable = hsw_crt_post_disable; |
841 | crt->base.get_hw_state = intel_ddi_get_hw_state; |
894 | } else { |
842 | } else { |
895 | crt->base.get_config = intel_crt_get_config; |
843 | crt->base.get_config = intel_crt_get_config; |
896 | crt->base.get_hw_state = intel_crt_get_hw_state; |
844 | crt->base.get_hw_state = intel_crt_get_hw_state; |
897 | } |
845 | } |
Line 917... | Line 865... | ||
917 | */ |
865 | */ |
918 | if (HAS_PCH_LPT(dev)) { |
866 | if (HAS_PCH_LPT(dev)) { |
919 | u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | |
867 | u32 fdi_config = FDI_RX_POLARITY_REVERSED_LPT | |
920 | FDI_RX_LINK_REVERSAL_OVERRIDE; |
868 | FDI_RX_LINK_REVERSAL_OVERRIDE; |
Line 921... | Line 869... | ||
921 | 869 | ||
922 | dev_priv->fdi_rx_config = I915_READ(_FDI_RXA_CTL) & fdi_config; |
870 | dev_priv->fdi_rx_config = I915_READ(FDI_RX_CTL(PIPE_A)) & fdi_config; |
Line 923... | Line 871... | ||
923 | } |
871 | } |
924 | 872 |