diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_lvds.c')
| -rw-r--r-- | drivers/gpu/drm/i915/intel_lvds.c | 115 |
1 files changed, 46 insertions, 69 deletions
diff --git a/drivers/gpu/drm/i915/intel_lvds.c b/drivers/gpu/drm/i915/intel_lvds.c index 0a2e60059fb3..6ec39a86ed06 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 | /** |
| @@ -455,7 +445,8 @@ static void intel_lvds_mode_set(struct drm_encoder *encoder, | |||
| 455 | * connected and closed means disconnected. We also send hotplug events as | 445 | * connected and closed means disconnected. We also send hotplug events as |
| 456 | * needed, using lid status notification from the input layer. | 446 | * needed, using lid status notification from the input layer. |
| 457 | */ | 447 | */ |
| 458 | static enum drm_connector_status intel_lvds_detect(struct drm_connector *connector) | 448 | static enum drm_connector_status |
| 449 | intel_lvds_detect(struct drm_connector *connector, bool force) | ||
| 459 | { | 450 | { |
| 460 | struct drm_device *dev = connector->dev; | 451 | struct drm_device *dev = connector->dev; |
| 461 | enum drm_connector_status status = connector_status_connected; | 452 | enum drm_connector_status status = connector_status_connected; |
| @@ -550,7 +541,9 @@ static int intel_lid_notify(struct notifier_block *nb, unsigned long val, | |||
| 550 | * the LID nofication event. | 541 | * the LID nofication event. |
| 551 | */ | 542 | */ |
| 552 | if (connector) | 543 | if (connector) |
| 553 | connector->status = connector->funcs->detect(connector); | 544 | connector->status = connector->funcs->detect(connector, |
| 545 | false); | ||
| 546 | |||
| 554 | /* Don't force modeset on machines where it causes a GPU lockup */ | 547 | /* Don't force modeset on machines where it causes a GPU lockup */ |
| 555 | if (dmi_check_system(intel_no_modeset_on_lid)) | 548 | if (dmi_check_system(intel_no_modeset_on_lid)) |
| 556 | return NOTIFY_OK; | 549 | return NOTIFY_OK; |
| @@ -600,18 +593,17 @@ static int intel_lvds_set_property(struct drm_connector *connector, | |||
| 600 | connector->encoder) { | 593 | connector->encoder) { |
| 601 | struct drm_crtc *crtc = connector->encoder->crtc; | 594 | struct drm_crtc *crtc = connector->encoder->crtc; |
| 602 | struct drm_encoder *encoder = connector->encoder; | 595 | struct drm_encoder *encoder = connector->encoder; |
| 603 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 596 | struct intel_lvds *intel_lvds = enc_to_intel_lvds(encoder); |
| 604 | struct intel_lvds_priv *lvds_priv = intel_encoder->dev_priv; | ||
| 605 | 597 | ||
| 606 | if (value == DRM_MODE_SCALE_NONE) { | 598 | if (value == DRM_MODE_SCALE_NONE) { |
| 607 | DRM_DEBUG_KMS("no scaling not supported\n"); | 599 | DRM_DEBUG_KMS("no scaling not supported\n"); |
| 608 | return 0; | 600 | return 0; |
| 609 | } | 601 | } |
| 610 | if (lvds_priv->fitting_mode == value) { | 602 | if (intel_lvds->fitting_mode == value) { |
| 611 | /* the LVDS scaling property is not changed */ | 603 | /* the LVDS scaling property is not changed */ |
| 612 | return 0; | 604 | return 0; |
| 613 | } | 605 | } |
| 614 | lvds_priv->fitting_mode = value; | 606 | intel_lvds->fitting_mode = value; |
| 615 | if (crtc && crtc->enabled) { | 607 | if (crtc && crtc->enabled) { |
| 616 | /* | 608 | /* |
| 617 | * If the CRTC is enabled, the display will be changed | 609 | * If the CRTC is enabled, the display will be changed |
| @@ -647,19 +639,8 @@ static const struct drm_connector_funcs intel_lvds_connector_funcs = { | |||
| 647 | .destroy = intel_lvds_destroy, | 639 | .destroy = intel_lvds_destroy, |
| 648 | }; | 640 | }; |
| 649 | 641 | ||
| 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 = { | 642 | static const struct drm_encoder_funcs intel_lvds_enc_funcs = { |
| 662 | .destroy = intel_lvds_enc_destroy, | 643 | .destroy = intel_encoder_destroy, |
| 663 | }; | 644 | }; |
| 664 | 645 | ||
| 665 | static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) | 646 | static int __init intel_no_lvds_dmi_callback(const struct dmi_system_id *id) |
| @@ -843,13 +824,13 @@ static int lvds_is_present_in_vbt(struct drm_device *dev) | |||
| 843 | void intel_lvds_init(struct drm_device *dev) | 824 | void intel_lvds_init(struct drm_device *dev) |
| 844 | { | 825 | { |
| 845 | struct drm_i915_private *dev_priv = dev->dev_private; | 826 | struct drm_i915_private *dev_priv = dev->dev_private; |
| 827 | struct intel_lvds *intel_lvds; | ||
| 846 | struct intel_encoder *intel_encoder; | 828 | struct intel_encoder *intel_encoder; |
| 847 | struct intel_connector *intel_connector; | 829 | struct intel_connector *intel_connector; |
| 848 | struct drm_connector *connector; | 830 | struct drm_connector *connector; |
| 849 | struct drm_encoder *encoder; | 831 | struct drm_encoder *encoder; |
| 850 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ | 832 | struct drm_display_mode *scan; /* *modes, *bios_mode; */ |
| 851 | struct drm_crtc *crtc; | 833 | struct drm_crtc *crtc; |
| 852 | struct intel_lvds_priv *lvds_priv; | ||
| 853 | u32 lvds; | 834 | u32 lvds; |
| 854 | int pipe, gpio = GPIOC; | 835 | int pipe, gpio = GPIOC; |
| 855 | 836 | ||
| @@ -872,20 +853,20 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 872 | gpio = PCH_GPIOC; | 853 | gpio = PCH_GPIOC; |
| 873 | } | 854 | } |
| 874 | 855 | ||
| 875 | intel_encoder = kzalloc(sizeof(struct intel_encoder) + | 856 | intel_lvds = kzalloc(sizeof(struct intel_lvds), GFP_KERNEL); |
| 876 | sizeof(struct intel_lvds_priv), GFP_KERNEL); | 857 | if (!intel_lvds) { |
| 877 | if (!intel_encoder) { | ||
| 878 | return; | 858 | return; |
| 879 | } | 859 | } |
| 880 | 860 | ||
| 881 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 861 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
| 882 | if (!intel_connector) { | 862 | if (!intel_connector) { |
| 883 | kfree(intel_encoder); | 863 | kfree(intel_lvds); |
| 884 | return; | 864 | return; |
| 885 | } | 865 | } |
| 886 | 866 | ||
| 887 | connector = &intel_connector->base; | 867 | intel_encoder = &intel_lvds->base; |
| 888 | encoder = &intel_encoder->enc; | 868 | encoder = &intel_encoder->enc; |
| 869 | connector = &intel_connector->base; | ||
| 889 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, | 870 | drm_connector_init(dev, &intel_connector->base, &intel_lvds_connector_funcs, |
| 890 | DRM_MODE_CONNECTOR_LVDS); | 871 | DRM_MODE_CONNECTOR_LVDS); |
| 891 | 872 | ||
| @@ -897,16 +878,12 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 897 | 878 | ||
| 898 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); | 879 | intel_encoder->clone_mask = (1 << INTEL_LVDS_CLONE_BIT); |
| 899 | intel_encoder->crtc_mask = (1 << 1); | 880 | intel_encoder->crtc_mask = (1 << 1); |
| 900 | if (IS_I965G(dev)) | ||
| 901 | intel_encoder->crtc_mask |= (1 << 0); | ||
| 902 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); | 881 | drm_encoder_helper_add(encoder, &intel_lvds_helper_funcs); |
| 903 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); | 882 | drm_connector_helper_add(connector, &intel_lvds_connector_helper_funcs); |
| 904 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; | 883 | connector->display_info.subpixel_order = SubPixelHorizontalRGB; |
| 905 | connector->interlace_allowed = false; | 884 | connector->interlace_allowed = false; |
| 906 | connector->doublescan_allowed = false; | 885 | connector->doublescan_allowed = false; |
| 907 | 886 | ||
| 908 | lvds_priv = (struct intel_lvds_priv *)(intel_encoder + 1); | ||
| 909 | intel_encoder->dev_priv = lvds_priv; | ||
| 910 | /* create the scaling mode property */ | 887 | /* create the scaling mode property */ |
| 911 | drm_mode_create_scaling_mode_property(dev); | 888 | drm_mode_create_scaling_mode_property(dev); |
| 912 | /* | 889 | /* |
| @@ -916,7 +893,7 @@ void intel_lvds_init(struct drm_device *dev) | |||
| 916 | drm_connector_attach_property(&intel_connector->base, | 893 | drm_connector_attach_property(&intel_connector->base, |
| 917 | dev->mode_config.scaling_mode_property, | 894 | dev->mode_config.scaling_mode_property, |
| 918 | DRM_MODE_SCALE_ASPECT); | 895 | DRM_MODE_SCALE_ASPECT); |
| 919 | lvds_priv->fitting_mode = DRM_MODE_SCALE_ASPECT; | 896 | intel_lvds->fitting_mode = DRM_MODE_SCALE_ASPECT; |
| 920 | /* | 897 | /* |
| 921 | * LVDS discovery: | 898 | * LVDS discovery: |
| 922 | * 1) check for EDID on DDC | 899 | * 1) check for EDID on DDC |
| @@ -1024,6 +1001,6 @@ failed: | |||
| 1024 | intel_i2c_destroy(intel_encoder->ddc_bus); | 1001 | intel_i2c_destroy(intel_encoder->ddc_bus); |
| 1025 | drm_connector_cleanup(connector); | 1002 | drm_connector_cleanup(connector); |
| 1026 | drm_encoder_cleanup(encoder); | 1003 | drm_encoder_cleanup(encoder); |
| 1027 | kfree(intel_encoder); | 1004 | kfree(intel_lvds); |
| 1028 | kfree(intel_connector); | 1005 | kfree(intel_connector); |
| 1029 | } | 1006 | } |
