diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 106 |
1 files changed, 41 insertions, 65 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0a2e60059fb..b819c108114 100644 --- a/drivers/gpu/drm/i915/intel_lvds.c +++ b/drivers/gpu/drm/i915/intel_lvds.c | |||
@@ -41,12 +41,18 @@ | |||
41 | #include <linux/acpi.h> | 41 | #include <linux/acpi.h> |
42 | 42 | ||
43 | /* Private structure for the integrated LVDS support */ | 43 | /* Private structure for the integrated LVDS support */ |
44 | struct intel_lvds_priv { | 44 | struct intel_lvds { |
45 | struct intel_encoder base; | ||
45 | int fitting_mode; | 46 | int fitting_mode; |
46 | u32 pfit_control; | 47 | u32 pfit_control; |
47 | u32 pfit_pgm_ratios; | 48 | u32 pfit_pgm_ratios; |
48 | }; | 49 | }; |
49 | 50 | ||
51 | static struct intel_lvds *enc_to_intel_lvds(struct drm_encoder *encoder) | ||
52 | { | ||
53 | return container_of(enc_to_intel_encoder(encoder), struct intel_lvds, base); | ||
54 | } | ||
55 | |||
50 | /** | 56 | /** |
51 | * Sets the backlight level. | 57 | * Sets the backlight level. |
52 | * | 58 | * |
@@ -90,7 +96,7 @@ static u32 intel_lvds_get_max_backlight(struct drm_device *dev) | |||
90 | static void intel_lvds_set_power(struct drm_device *dev, bool on) | 96 | static void intel_lvds_set_power(struct drm_device *dev, bool on) |
91 | { | 97 | { |
92 | struct drm_i915_private *dev_priv = dev->dev_private; | 98 | struct drm_i915_private *dev_priv = dev->dev_private; |
93 | u32 pp_status, ctl_reg, status_reg, lvds_reg; | 99 | u32 ctl_reg, status_reg, lvds_reg; |
94 | 100 | ||
95 | if (HAS_PCH_SPLIT(dev)) { | 101 | if (HAS_PCH_SPLIT(dev)) { |
96 | ctl_reg = PCH_PP_CONTROL; | 102 | ctl_reg = PCH_PP_CONTROL; |
@@ -108,9 +114,8 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on) | |||
108 | 114 | ||
109 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | | 115 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) | |
110 | POWER_TARGET_ON); | 116 | POWER_TARGET_ON); |
111 | do { | 117 | if (wait_for(I915_READ(status_reg) & PP_ON, 1000, 0)) |
112 | pp_status = I915_READ(status_reg); | 118 | DRM_ERROR("timed out waiting to enable LVDS pipe"); |
113 | } while ((pp_status & PP_ON) == 0); | ||
114 | 119 | ||
115 | intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); | 120 | intel_lvds_set_backlight(dev, dev_priv->backlight_duty_cycle); |
116 | } else { | 121 | } else { |
@@ -118,9 +123,8 @@ static void intel_lvds_set_power(struct drm_device *dev, bool on) | |||
118 | 123 | ||
119 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & | 124 | I915_WRITE(ctl_reg, I915_READ(ctl_reg) & |
120 | ~POWER_TARGET_ON); | 125 | ~POWER_TARGET_ON); |
121 | do { | 126 | if (wait_for((I915_READ(status_reg) & PP_ON) == 0, 1000, 0)) |
122 | pp_status = I915_READ(status_reg); | 127 | DRM_ERROR("timed out waiting for LVDS pipe to turn off"); |
123 | } while (pp_status & PP_ON); | ||
124 | 128 | ||
125 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); | 129 | I915_WRITE(lvds_reg, I915_READ(lvds_reg) & ~LVDS_PORT_EN); |
126 | POSTING_READ(lvds_reg); | 130 | POSTING_READ(lvds_reg); |
@@ -219,9 +223,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
219 | struct drm_device *dev = encoder->dev; | 223 | struct drm_device *dev = encoder->dev; |
220 | struct drm_i915_private *dev_priv = dev->dev_private; | 224 | struct drm_i915_private *dev_priv = dev->dev_private; |
221 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); | 225 | struct intel_crtc *intel_crtc = to_intel_crtc(encoder->crtc); |
226 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); | ||
222 | struct drm_encoder *tmp_encoder; | 227 | struct drm_encoder *tmp_encoder; |
223 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
224 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; | ||
225 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; | 228 | u32 pfit_control = 0, pfit_pgm_ratios = 0, border = 0; |
226 | 229 | ||
227 | /* Should never happen!! */ | 230 | /* Should never happen!! */ |
@@ -241,26 +244,20 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
241 | /* If we don't have a panel mode, there is nothing we can do */ | 244 | /* If we don't have a panel mode, there is nothing we can do */ |
242 | if (dev_priv->panel_fixed_mode == NULL) | 245 | if (dev_priv->panel_fixed_mode == NULL) |
243 | return true; | 246 | return true; |
247 | |||
244 | /* | 248 | /* |
245 | * We have timings from the BIOS for the panel, put them in | 249 | * We have timings from the BIOS for the panel, put them in |
246 | * to the adjusted mode. The CRTC will be set up for this mode, | 250 | * to the adjusted mode. The CRTC will be set up for this mode, |
247 | * with the panel scaling set up to source from the H/VDisplay | 251 | * with the panel scaling set up to source from the H/VDisplay |
248 | * of the original mode. | 252 | * of the original mode. |
249 | */ | 253 | */ |
250 | adjusted_mode->hdisplay = dev_priv->panel_fixed_mode->hdisplay; | 254 | intel_fixed_panel_mode(dev_priv->panel_fixed_mode, adjusted_mode); |
251 | adjusted_mode->hsync_start = | 255 | |
252 | dev_priv->panel_fixed_mode->hsync_start; | 256 | if (HAS_PCH_SPLIT(dev)) { |
253 | adjusted_mode->hsync_end = | 257 | intel_pch_panel_fitting(dev, intel_lvds->fitting_mode, |
254 | dev_priv->panel_fixed_mode->hsync_end; | 258 | mode, adjusted_mode); |
255 | adjusted_mode->htotal = dev_priv->panel_fixed_mode->htotal; | 259 | return true; |
256 | adjusted_mode->vdisplay = dev_priv->panel_fixed_mode->vdisplay; | 260 | } |
257 | adjusted_mode->vsync_start = | ||
258 | dev_priv->panel_fixed_mode->vsync_start; | ||
259 | adjusted_mode->vsync_end = | ||
260 | dev_priv->panel_fixed_mode->vsync_end; | ||
261 | adjusted_mode->vtotal = dev_priv->panel_fixed_mode->vtotal; | ||
262 | adjusted_mode->clock = dev_priv->panel_fixed_mode->clock; | ||
263 | drm_mode_set_crtcinfo(adjusted_mode, CRTC_INTERLACE_HALVE_V); | ||
264 | 261 | ||
265 | /* Make sure pre-965s set dither correctly */ | 262 | /* Make sure pre-965s set dither correctly */ |
266 | if (!IS_I965G(dev)) { | 263 | if (!IS_I965G(dev)) { |
@@ -273,10 +270,6 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
273 | adjusted_mode->vdisplay == mode->vdisplay) | 270 | adjusted_mode->vdisplay == mode->vdisplay) |
274 | goto out; | 271 | goto out; |
275 | 272 | ||
276 | /* full screen scale for now */ | ||
277 | if (HAS_PCH_SPLIT(dev)) | ||
278 | goto out; | ||
279 | |||
280 | /* 965+ wants fuzzy fitting */ | 273 | /* 965+ wants fuzzy fitting */ |
281 | if (IS_I965G(dev)) | 274 | if (IS_I965G(dev)) |
282 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | | 275 | pfit_control |= ((intel_crtc->pipe << PFIT_PIPE_SHIFT) | |
@@ -288,12 +281,10 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
288 | * to register description and PRM. | 281 | * to register description and PRM. |
289 | * Change the value here to see the borders for debugging | 282 | * Change the value here to see the borders for debugging |
290 | */ | 283 | */ |
291 | if (!HAS_PCH_SPLIT(dev)) { | 284 | I915_WRITE(BCLRPAT_A, 0); |
292 | I915_WRITE(BCLRPAT_A, 0); | 285 | I915_WRITE(BCLRPAT_B, 0); |
293 | I915_WRITE(BCLRPAT_B, 0); | ||
294 | } | ||
295 | 286 | ||
296 | switch (lvds_priv->fitting_mode) { | 287 | switch (intel_lvds->fitting_mode) { |
297 | case DRM_MODE_SCALE_CENTER: | 288 | case DRM_MODE_SCALE_CENTER: |
298 | /* | 289 | /* |
299 | * For centered modes, we have to calculate border widths & | 290 | * For centered modes, we have to calculate border widths & |
@@ -378,8 +369,8 @@ static bool intel_lvds_mode_fixup(struct drm_encoder *encoder, | |||
378 | } | 369 | } |
379 | 370 | ||
380 | out: | 371 | out: |
381 | lvds_priv->pfit_control = pfit_control; | 372 | intel_lvds->pfit_control = pfit_control; |
382 | lvds_priv->pfit_pgm_ratios = pfit_pgm_ratios; | 373 | intel_lvds->pfit_pgm_ratios = pfit_pgm_ratios; |
383 | dev_priv->lvds_border_bits = border; | 374 | dev_priv->lvds_border_bits = border; |
384 | 375 | ||
385 | /* | 376 | /* |
@@ -427,8 +418,7 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
427 | { | 418 | { |
428 | struct drm_device *dev = encoder->dev; | 419 | struct drm_device *dev = encoder->dev; |
429 | struct drm_i915_private *dev_priv = dev->dev_private; | 420 | struct drm_i915_private *dev_priv = dev->dev_private; |
430 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 421 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); |
431 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; | ||
432 | 422 | ||
433 | /* | 423 | /* |
434 | * The LVDS pin pair will already have been turned on in the | 424 | * The LVDS pin pair will already have been turned on in the |
@@ -444,8 +434,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
444 | * screen. Should be enabled before the pipe is enabled, according to | 434 | * screen. Should be enabled before the pipe is enabled, according to |
445 | * register description and PRM. | 435 | * register description and PRM. |
446 | */ | 436 | */ |
447 | I915_WRITE(PFIT_PGM_RATIOS, lvds_priv->pfit_pgm_ratios); | 437 | I915_WRITE(PFIT_PGM_RATIOS, intel_lvds->pfit_pgm_ratios); |
448 | I915_WRITE(PFIT_CONTROL, lvds_priv->pfit_control); | 438 | I915_WRITE(PFIT_CONTROL, intel_lvds->pfit_control); |
449 | } | 439 | } |
450 | 440 | ||
451 | /** | 441 | /** |
@@ -600,18 +590,17 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
600 | connector->encoder) { | 590 | connector->encoder) { |
601 | struct drm_crtc *crtc = connector->encoder->crtc; | 591 | struct drm_crtc *crtc = connector->encoder->crtc; |
602 | struct drm_encoder *encoder = connector->encoder; | 592 | struct drm_encoder *encoder = connector->encoder; |
603 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 593 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); |
604 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; | ||
605 | 594 | ||
606 | if (value == DRM_MODE_SCALE_NONE) { | 595 | if (value == DRM_MODE_SCALE_NONE) { |
607 | DRM_DEBUG_KMS("no scaling not supported\n"); | 596 | DRM_DEBUG_KMS("no scaling not supported\n"); |
608 | return 0; | 597 | return 0; |
609 | } | 598 | } |
610 | if (lvds_priv->fitting_mode == value) { | 599 | if (intel_lvds->fitting_mode == value) { |
611 | /* the LVDS scaling property is not changed */ | 600 | /* the LVDS scaling property is not changed */ |
612 | return 0; | 601 | return 0; |
613 | } | 602 | } |
614 | lvds_priv->fitting_mode = value; | 603 | intel_lvds->fitting_mode = value; |
615 | if (crtc && crtc->enabled) { | 604 | if (crtc && crtc->enabled) { |
616 | /* | 605 | /* |
617 | * If the CRTC is enabled, the display will be changed | 606 | * If the CRTC is enabled, the display will be changed |
@@ -647,19 +636,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { | |||
647 | .destroy = intel_lvds_destroy, | 636 | .destroy = intel_lvds_destroy, |
648 | }; | 637 | }; |
649 | 638 | ||
650 | |||
651 | static void intel_lvds_enc_destroy(struct drm_encoder *encoder) | ||
652 | { | ||
653 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
654 | |||
655 | if (intel_encoder->ddc_bus) | ||
656 | intel_i2c_destroy(intel_encoder->ddc_bus); | ||
657 | drm_encoder_cleanup(encoder); | ||
658 | kfree(intel_encoder); | ||
659 | } | ||
660 | |||
661 | static const struct drm_encoder_funcs intel_lvds_enc_funcs = { | 639 | static const struct drm_encoder_funcs intel_lvds_enc_funcs = { |
662 | .destroy = intel_lvds_enc_destroy, | 640 | .destroy = intel_encoder_destroy, |
663 | }; | 641 | }; |
664 | 642 | ||
665 | static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) | 643 | static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) |
@@ -843,13 +821,13 @@ static int lvds_is_present_in_vbt(struct drm_device *dev) | |||
843 | void intel_lvds_init(struct drm_device *dev) | 821 | void intel_lvds_init(struct drm_device *dev) |
844 | { | 822 | { |
845 | struct drm_i915_private *dev_priv = dev->dev_private; | 823 | struct drm_i915_private *dev_priv = dev->dev_private; |
824 | struct intel_lvds *intel_lvds; | ||
846 | struct intel_encoder *intel_encoder; | 825 | struct intel_encoder *intel_encoder; |
847 | struct intel_connector *intel_connector; | 826 | struct intel_connector *intel_connector; |
848 | struct drm_connector *connector; | 827 | struct drm_connector *connector; |
849 | struct drm_encoder *encoder; | 828 | struct drm_encoder *encoder; |
850 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 829 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
851 | struct drm_crtc *crtc; | 830 | struct drm_crtc *crtc; |
852 | struct intel_lvds_priv *lvds_priv; | ||
853 | u32 lvds; | 831 | u32 lvds; |
854 | int pipe, gpio = GPIOC; | 832 | int pipe, gpio = GPIOC; |
855 | 833 | ||
@@ -872,20 +850,20 @@ void intel_lvds_init(struct drm_device *dev) | |||
872 | gpio = PCH_GPIOC; | 850 | gpio = PCH_GPIOC; |
873 | } | 851 | } |
874 | 852 | ||
875 | intel_encoder = kzalloc(sizeof(struct intel_encoder) + | 853 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); |
876 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | 854 | if (!intel_lvds) { |
877 | if (!intel_encoder) { | ||
878 | return; | 855 | return; |
879 | } | 856 | } |
880 | 857 | ||
881 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 858 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
882 | if (!intel_connector) { | 859 | if (!intel_connector) { |
883 | kfree(intel_encoder); | 860 | kfree(intel_lvds); |
884 | return; | 861 | return; |
885 | } | 862 | } |
886 | 863 | ||
887 | connector = &intel_connector->base; | 864 | intel_encoder = &intel_lvds->base; |
888 | encoder = &intel_encoder->enc; | 865 | encoder = &intel_encoder->enc; |
866 | connector = &intel_connector->base; | ||
889 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, | 867 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, |
890 | DRM_MODE_CONNECTOR_LVDS); | 868 | DRM_MODE_CONNECTOR_LVDS); |
891 | 869 | ||
@@ -905,8 +883,6 @@ void intel_lvds_init(struct drm_device *dev) | |||
905 | connector->interlace_allowed = false; | 883 | connector->interlace_allowed = false; |
906 | connector->doublescan_allowed = false; | 884 | connector->doublescan_allowed = false; |
907 | 885 | ||
908 | lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1); | ||
909 | intel_encoder->dev_priv = lvds_priv; | ||
910 | /* create the scaling mode property */ | 886 | /* create the scaling mode property */ |
911 | drm_mode_create_scaling_mode_property(dev); | 887 | drm_mode_create_scaling_mode_property(dev); |
912 | /* | 888 | /* |
@@ -916,7 +892,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
916 | drm_connector_attach_property(&intel_connector->base, | 892 | drm_connector_attach_property(&intel_connector->base, |
917 | dev->mode_config.scaling_mode_property, | 893 | dev->mode_config.scaling_mode_property, |
918 | DRM_MODE_SCALE_ASPECT); | 894 | DRM_MODE_SCALE_ASPECT); |
919 | lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT; | 895 | intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT; |
920 | /* | 896 | /* |
921 | * LVDS discovery: | 897 | * LVDS discovery: |
922 | * 1) check for EDID on DDC | 898 | * 1) check for EDID on DDC |
@@ -1024,6 +1000,6 @@ failed: | |||
1024 | intel_i2c_destroy(intel_encoder->ddc_bus); | 1000 | intel_i2c_destroy(intel_encoder->ddc_bus); |
1025 | drm_connector_cleanup(connector); | 1001 | drm_connector_cleanup(connector); |
1026 | drm_encoder_cleanup(encoder); | 1002 | drm_encoder_cleanup(encoder); |
1027 | kfree(intel_encoder); | 1003 | kfree(intel_lvds); |
1028 | kfree(intel_connector); | 1004 | kfree(intel_connector); |
1029 | } | 1005 | } |