diff options
author | Jesse Barnes <jbarnes@virtuousgeek.org> | 2012-04-17 18:06:33 -0400 |
---|---|---|
committer | Daniel Vetter <daniel.vetter@ffwll.ch> | 2012-04-18 04:34:49 -0400 |
commit | df0323c42ac35f81b49e25fe04e8e52b9c6f6467 (patch) | |
tree | ad651d75626df4bdbd3ddbefa540a4e5649d5b0d | |
parent | 446f254566ea8911c9e19c7bc8a162fc0e53cf31 (diff) |
drm/i915: IBX+ doesn't have separate vsync/hsync controls on the VGA DAC
When the PCH split occurred, hw dropped support for separate hsync and
vsync disable in the VGA DAC. So add a PCH specific DPMS function that
just uses the port enable bit for controlling DPMS states.
Before this fix, when anything other than a full DPMS off occurred,
the VGA port would be left enabled and scanning out while all the other
heads would turn off as expected.
v2: duplicate encoder helper vtable into pch and gmch versions (Daniel)
Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=48491
Reviewed-by: Chris Wilson <chris@chris-wilson.co.uk>
Signed-off-by: Jesse Barnes <jbarnes@virtuousgeek.org>
[danvet: s/intel_crt_dpms/gmch_crt_dpms as suggested by Chris.]
Signed-off-by: Daniel Vetter <daniel.vetter@ffwll.ch>
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 54 |
1 files changed, 43 insertions, 11 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 70b0f1abf149..0976137ab79a 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -55,18 +55,36 @@ static struct intel_crt *intel_attached_crt(struct drm_connector *connector) | |||
55 | struct intel_crt, base); | 55 | struct intel_crt, base); |
56 | } | 56 | } |
57 | 57 | ||
58 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | 58 | static void pch_crt_dpms(struct drm_encoder *encoder, int mode) |
59 | { | 59 | { |
60 | struct drm_device *dev = encoder->dev; | 60 | struct drm_device *dev = encoder->dev; |
61 | struct drm_i915_private *dev_priv = dev->dev_private; | 61 | struct drm_i915_private *dev_priv = dev->dev_private; |
62 | u32 temp, reg; | 62 | u32 temp; |
63 | 63 | ||
64 | if (HAS_PCH_SPLIT(dev)) | 64 | temp = I915_READ(PCH_ADPA); |
65 | reg = PCH_ADPA; | 65 | temp &= ~ADPA_DAC_ENABLE; |
66 | else | 66 | |
67 | reg = ADPA; | 67 | switch (mode) { |
68 | case DRM_MODE_DPMS_ON: | ||
69 | temp |= ADPA_DAC_ENABLE; | ||
70 | break; | ||
71 | case DRM_MODE_DPMS_STANDBY: | ||
72 | case DRM_MODE_DPMS_SUSPEND: | ||
73 | case DRM_MODE_DPMS_OFF: | ||
74 | /* Just leave port enable cleared */ | ||
75 | break; | ||
76 | } | ||
77 | |||
78 | I915_WRITE(PCH_ADPA, temp); | ||
79 | } | ||
68 | 80 | ||
69 | temp = I915_READ(reg); | 81 | static void gmch_crt_dpms(struct drm_encoder *encoder, int mode) |
82 | { | ||
83 | struct drm_device *dev = encoder->dev; | ||
84 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
85 | u32 temp; | ||
86 | |||
87 | temp = I915_READ(ADPA); | ||
70 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); | 88 | temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); |
71 | temp &= ~ADPA_DAC_ENABLE; | 89 | temp &= ~ADPA_DAC_ENABLE; |
72 | 90 | ||
@@ -85,7 +103,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
85 | break; | 103 | break; |
86 | } | 104 | } |
87 | 105 | ||
88 | I915_WRITE(reg, temp); | 106 | I915_WRITE(ADPA, temp); |
89 | } | 107 | } |
90 | 108 | ||
91 | static int intel_crt_mode_valid(struct drm_connector *connector, | 109 | static int intel_crt_mode_valid(struct drm_connector *connector, |
@@ -516,12 +534,20 @@ static void intel_crt_reset(struct drm_connector *connector) | |||
516 | * Routines for controlling stuff on the analog port | 534 | * Routines for controlling stuff on the analog port |
517 | */ | 535 | */ |
518 | 536 | ||
519 | static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = { | 537 | static const struct drm_encoder_helper_funcs pch_encoder_funcs = { |
520 | .dpms = intel_crt_dpms, | 538 | .mode_fixup = intel_crt_mode_fixup, |
539 | .prepare = intel_encoder_prepare, | ||
540 | .commit = intel_encoder_commit, | ||
541 | .mode_set = intel_crt_mode_set, | ||
542 | .dpms = pch_crt_dpms, | ||
543 | }; | ||
544 | |||
545 | static const struct drm_encoder_helper_funcs gmch_encoder_funcs = { | ||
521 | .mode_fixup = intel_crt_mode_fixup, | 546 | .mode_fixup = intel_crt_mode_fixup, |
522 | .prepare = intel_encoder_prepare, | 547 | .prepare = intel_encoder_prepare, |
523 | .commit = intel_encoder_commit, | 548 | .commit = intel_encoder_commit, |
524 | .mode_set = intel_crt_mode_set, | 549 | .mode_set = intel_crt_mode_set, |
550 | .dpms = gmch_crt_dpms, | ||
525 | }; | 551 | }; |
526 | 552 | ||
527 | static const struct drm_connector_funcs intel_crt_connector_funcs = { | 553 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
@@ -567,6 +593,7 @@ void intel_crt_init(struct drm_device *dev) | |||
567 | struct intel_crt *crt; | 593 | struct intel_crt *crt; |
568 | struct intel_connector *intel_connector; | 594 | struct intel_connector *intel_connector; |
569 | struct drm_i915_private *dev_priv = dev->dev_private; | 595 | struct drm_i915_private *dev_priv = dev->dev_private; |
596 | const struct drm_encoder_helper_funcs *encoder_helper_funcs; | ||
570 | 597 | ||
571 | /* Skip machines without VGA that falsely report hotplug events */ | 598 | /* Skip machines without VGA that falsely report hotplug events */ |
572 | if (dmi_check_system(intel_no_crt)) | 599 | if (dmi_check_system(intel_no_crt)) |
@@ -602,7 +629,12 @@ void intel_crt_init(struct drm_device *dev) | |||
602 | connector->interlace_allowed = 1; | 629 | connector->interlace_allowed = 1; |
603 | connector->doublescan_allowed = 0; | 630 | connector->doublescan_allowed = 0; |
604 | 631 | ||
605 | drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs); | 632 | if (HAS_PCH_SPLIT(dev)) |
633 | encoder_helper_funcs = &pch_encoder_funcs; | ||
634 | else | ||
635 | encoder_helper_funcs = &gmch_encoder_funcs; | ||
636 | |||
637 | drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs); | ||
606 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 638 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
607 | 639 | ||
608 | drm_sysfs_connector_add(connector); | 640 | drm_sysfs_connector_add(connector); |