aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/i915/intel_crt.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-04 02:29:23 -0400
commit612a9aab56a93533e76e3ad91642db7033e03b69 (patch)
tree8402096973f67af941f9392f7da06cca03e0b58a /drivers/gpu/drm/i915/intel_crt.c
parent3a494318b14b1bc0f59d2d6ce84c505c74d82d2a (diff)
parent268d28371cd326be4dfcd7eba5917bf4b9d30c8f (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm merge (part 1) from Dave Airlie: "So first of all my tree and uapi stuff has a conflict mess, its my fault as the nouveau stuff didn't hit -next as were trying to rebase regressions out of it before we merged. Highlights: - SH mobile modesetting driver and associated helpers - some DRM core documentation - i915 modesetting rework, haswell hdmi, haswell and vlv fixes, write combined pte writing, ilk rc6 support, - nouveau: major driver rework into a hw core driver, makes features like SLI a lot saner to implement, - psb: add eDP/DP support for Cedarview - radeon: 2 layer page tables, async VM pte updates, better PLL selection for > 2 screens, better ACPI interactions The rest is general grab bag of fixes. So why part 1? well I have the exynos pull req which came in a bit late but was waiting for me to do something they shouldn't have and it looks fairly safe, and David Howells has some more header cleanups he'd like me to pull, that seem like a good idea, but I'd like to get this merge out of the way so -next dosen't get blocked." Tons of conflicts mostly due to silly include line changes, but mostly mindless. A few other small semantic conflicts too, noted from Dave's pre-merged branch. * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (447 commits) drm/nv98/crypt: fix fuc build with latest envyas drm/nouveau/devinit: fixup various issues with subdev ctor/init ordering drm/nv41/vm: fix and enable use of "real" pciegart drm/nv44/vm: fix and enable use of "real" pciegart drm/nv04/dmaobj: fixup vm target handling in preparation for nv4x pcie drm/nouveau: store supported dma mask in vmmgr drm/nvc0/ibus: initial implementation of subdev drm/nouveau/therm: add support for fan-control modes drm/nouveau/hwmon: rename pwm0* to pmw1* to follow hwmon's rules drm/nouveau/therm: calculate the pwm divisor on nv50+ drm/nouveau/fan: rewrite the fan tachometer driver to get more precision, faster drm/nouveau/therm: move thermal-related functions to the therm subdev drm/nouveau/bios: parse the pwm divisor from the perf table drm/nouveau/therm: use the EXTDEV table to detect i2c monitoring devices drm/nouveau/therm: rework thermal table parsing drm/nouveau/gpio: expose the PWM/TOGGLE parameter found in the gpio vbios table drm/nouveau: fix pm initialization order drm/nouveau/bios: check that fixed tvdac gpio data is valid before using it drm/nouveau: log channel debug/error messages from client object rather than drm client drm/nouveau: have drm debugging macros build on top of core macros ...
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r--drivers/gpu/drm/i915/intel_crt.c165
1 files changed, 112 insertions, 53 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c
index c8f1c0db446d..893f30164b7e 100644
--- a/drivers/gpu/drm/i915/intel_crt.c
+++ b/drivers/gpu/drm/i915/intel_crt.c
@@ -46,6 +46,7 @@
46struct intel_crt { 46struct intel_crt {
47 struct intel_encoder base; 47 struct intel_encoder base;
48 bool force_hotplug_required; 48 bool force_hotplug_required;
49 u32 adpa_reg;
49}; 50};
50 51
51static struct intel_crt *intel_attached_crt(struct drm_connector *connector) 52static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
@@ -54,42 +55,68 @@ static struct intel_crt *intel_attached_crt(struct drm_connector *connector)
54 struct intel_crt, base); 55 struct intel_crt, base);
55} 56}
56 57
57static void pch_crt_dpms(struct drm_encoder *encoder, int mode) 58static struct intel_crt *intel_encoder_to_crt(struct intel_encoder *encoder)
58{ 59{
59 struct drm_device *dev = encoder->dev; 60 return container_of(encoder, struct intel_crt, base);
61}
62
63static bool intel_crt_get_hw_state(struct intel_encoder *encoder,
64 enum pipe *pipe)
65{
66 struct drm_device *dev = encoder->base.dev;
60 struct drm_i915_private *dev_priv = dev->dev_private; 67 struct drm_i915_private *dev_priv = dev->dev_private;
68 struct intel_crt *crt = intel_encoder_to_crt(encoder);
69 u32 tmp;
70
71 tmp = I915_READ(crt->adpa_reg);
72
73 if (!(tmp & ADPA_DAC_ENABLE))
74 return false;
75
76 if (HAS_PCH_CPT(dev))
77 *pipe = PORT_TO_PIPE_CPT(tmp);
78 else
79 *pipe = PORT_TO_PIPE(tmp);
80
81 return true;
82}
83
84static void intel_disable_crt(struct intel_encoder *encoder)
85{
86 struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
87 struct intel_crt *crt = intel_encoder_to_crt(encoder);
61 u32 temp; 88 u32 temp;
62 89
63 temp = I915_READ(PCH_ADPA); 90 temp = I915_READ(crt->adpa_reg);
91 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
64 temp &= ~ADPA_DAC_ENABLE; 92 temp &= ~ADPA_DAC_ENABLE;
93 I915_WRITE(crt->adpa_reg, temp);
94}
65 95
66 switch (mode) { 96static void intel_enable_crt(struct intel_encoder *encoder)
67 case DRM_MODE_DPMS_ON: 97{
68 temp |= ADPA_DAC_ENABLE; 98 struct drm_i915_private *dev_priv = encoder->base.dev->dev_private;
69 break; 99 struct intel_crt *crt = intel_encoder_to_crt(encoder);
70 case DRM_MODE_DPMS_STANDBY: 100 u32 temp;
71 case DRM_MODE_DPMS_SUSPEND:
72 case DRM_MODE_DPMS_OFF:
73 /* Just leave port enable cleared */
74 break;
75 }
76 101
77 I915_WRITE(PCH_ADPA, temp); 102 temp = I915_READ(crt->adpa_reg);
103 temp |= ADPA_DAC_ENABLE;
104 I915_WRITE(crt->adpa_reg, temp);
78} 105}
79 106
80static void gmch_crt_dpms(struct drm_encoder *encoder, int mode) 107/* Note: The caller is required to filter out dpms modes not supported by the
108 * platform. */
109static void intel_crt_set_dpms(struct intel_encoder *encoder, int mode)
81{ 110{
82 struct drm_device *dev = encoder->dev; 111 struct drm_device *dev = encoder->base.dev;
83 struct drm_i915_private *dev_priv = dev->dev_private; 112 struct drm_i915_private *dev_priv = dev->dev_private;
113 struct intel_crt *crt = intel_encoder_to_crt(encoder);
84 u32 temp; 114 u32 temp;
85 115
86 temp = I915_READ(ADPA); 116 temp = I915_READ(crt->adpa_reg);
87 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE); 117 temp &= ~(ADPA_HSYNC_CNTL_DISABLE | ADPA_VSYNC_CNTL_DISABLE);
88 temp &= ~ADPA_DAC_ENABLE; 118 temp &= ~ADPA_DAC_ENABLE;
89 119
90 if (IS_VALLEYVIEW(dev) && mode != DRM_MODE_DPMS_ON)
91 mode = DRM_MODE_DPMS_OFF;
92
93 switch (mode) { 120 switch (mode) {
94 case DRM_MODE_DPMS_ON: 121 case DRM_MODE_DPMS_ON:
95 temp |= ADPA_DAC_ENABLE; 122 temp |= ADPA_DAC_ENABLE;
@@ -105,7 +132,51 @@ static void gmch_crt_dpms(struct drm_encoder *encoder, int mode)
105 break; 132 break;
106 } 133 }
107 134
108 I915_WRITE(ADPA, temp); 135 I915_WRITE(crt->adpa_reg, temp);
136}
137
138static void intel_crt_dpms(struct drm_connector *connector, int mode)
139{
140 struct drm_device *dev = connector->dev;
141 struct intel_encoder *encoder = intel_attached_encoder(connector);
142 struct drm_crtc *crtc;
143 int old_dpms;
144
145 /* PCH platforms and VLV only support on/off. */
146 if (INTEL_INFO(dev)->gen < 5 && mode != DRM_MODE_DPMS_ON)
147 mode = DRM_MODE_DPMS_OFF;
148
149 if (mode == connector->dpms)
150 return;
151
152 old_dpms = connector->dpms;
153 connector->dpms = mode;
154
155 /* Only need to change hw state when actually enabled */
156 crtc = encoder->base.crtc;
157 if (!crtc) {
158 encoder->connectors_active = false;
159 return;
160 }
161
162 /* We need the pipe to run for anything but OFF. */
163 if (mode == DRM_MODE_DPMS_OFF)
164 encoder->connectors_active = false;
165 else
166 encoder->connectors_active = true;
167
168 if (mode < old_dpms) {
169 /* From off to on, enable the pipe first. */
170 intel_crtc_update_dpms(crtc);
171
172 intel_crt_set_dpms(encoder, mode);
173 } else {
174 intel_crt_set_dpms(encoder, mode);
175
176 intel_crtc_update_dpms(crtc);
177 }
178
179 intel_modeset_check_state(connector->dev);
109} 180}
110 181
111static int intel_crt_mode_valid(struct drm_connector *connector, 182static int intel_crt_mode_valid(struct drm_connector *connector,
@@ -144,19 +215,15 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
144 215
145 struct drm_device *dev = encoder->dev; 216 struct drm_device *dev = encoder->dev;
146 struct drm_crtc *crtc = encoder->crtc; 217 struct drm_crtc *crtc = encoder->crtc;
218 struct intel_crt *crt =
219 intel_encoder_to_crt(to_intel_encoder(encoder));
147 struct intel_crtc *intel_crtc = to_intel_crtc(crtc); 220 struct intel_crtc *intel_crtc = to_intel_crtc(crtc);
148 struct drm_i915_private *dev_priv = dev->dev_private; 221 struct drm_i915_private *dev_priv = dev->dev_private;
149 int dpll_md_reg; 222 int dpll_md_reg;
150 u32 adpa, dpll_md; 223 u32 adpa, dpll_md;
151 u32 adpa_reg;
152 224
153 dpll_md_reg = DPLL_MD(intel_crtc->pipe); 225 dpll_md_reg = DPLL_MD(intel_crtc->pipe);
154 226
155 if (HAS_PCH_SPLIT(dev))
156 adpa_reg = PCH_ADPA;
157 else
158 adpa_reg = ADPA;
159
160 /* 227 /*
161 * Disable separate mode multiplier used when cloning SDVO to CRT 228 * Disable separate mode multiplier used when cloning SDVO to CRT
162 * XXX this needs to be adjusted when we really are cloning 229 * XXX this needs to be adjusted when we really are cloning
@@ -184,7 +251,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder,
184 if (!HAS_PCH_SPLIT(dev)) 251 if (!HAS_PCH_SPLIT(dev))
185 I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); 252 I915_WRITE(BCLRPAT(intel_crtc->pipe), 0);
186 253
187 I915_WRITE(adpa_reg, adpa); 254 I915_WRITE(crt->adpa_reg, adpa);
188} 255}
189 256
190static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) 257static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector)
@@ -544,14 +611,12 @@ intel_crt_detect(struct drm_connector *connector, bool force)
544 return connector->status; 611 return connector->status;
545 612
546 /* for pre-945g platforms use load detect */ 613 /* for pre-945g platforms use load detect */
547 if (intel_get_load_detect_pipe(&crt->base, connector, NULL, 614 if (intel_get_load_detect_pipe(connector, NULL, &tmp)) {
548 &tmp)) {
549 if (intel_crt_detect_ddc(connector)) 615 if (intel_crt_detect_ddc(connector))
550 status = connector_status_connected; 616 status = connector_status_connected;
551 else 617 else
552 status = intel_crt_load_detect(crt); 618 status = intel_crt_load_detect(crt);
553 intel_release_load_detect_pipe(&crt->base, connector, 619 intel_release_load_detect_pipe(connector, &tmp);
554 &tmp);
555 } else 620 } else
556 status = connector_status_unknown; 621 status = connector_status_unknown;
557 622
@@ -602,25 +667,15 @@ static void intel_crt_reset(struct drm_connector *connector)
602 * Routines for controlling stuff on the analog port 667 * Routines for controlling stuff on the analog port
603 */ 668 */
604 669
605static const struct drm_encoder_helper_funcs pch_encoder_funcs = { 670static const struct drm_encoder_helper_funcs crt_encoder_funcs = {
606 .mode_fixup = intel_crt_mode_fixup, 671 .mode_fixup = intel_crt_mode_fixup,
607 .prepare = intel_encoder_prepare,
608 .commit = intel_encoder_commit,
609 .mode_set = intel_crt_mode_set, 672 .mode_set = intel_crt_mode_set,
610 .dpms = pch_crt_dpms, 673 .disable = intel_encoder_noop,
611};
612
613static const struct drm_encoder_helper_funcs gmch_encoder_funcs = {
614 .mode_fixup = intel_crt_mode_fixup,
615 .prepare = intel_encoder_prepare,
616 .commit = intel_encoder_commit,
617 .mode_set = intel_crt_mode_set,
618 .dpms = gmch_crt_dpms,
619}; 674};
620 675
621static const struct drm_connector_funcs intel_crt_connector_funcs = { 676static const struct drm_connector_funcs intel_crt_connector_funcs = {
622 .reset = intel_crt_reset, 677 .reset = intel_crt_reset,
623 .dpms = drm_helper_connector_dpms, 678 .dpms = intel_crt_dpms,
624 .detect = intel_crt_detect, 679 .detect = intel_crt_detect,
625 .fill_modes = drm_helper_probe_single_connector_modes, 680 .fill_modes = drm_helper_probe_single_connector_modes,
626 .destroy = intel_crt_destroy, 681 .destroy = intel_crt_destroy,
@@ -661,7 +716,6 @@ void intel_crt_init(struct drm_device *dev)
661 struct intel_crt *crt; 716 struct intel_crt *crt;
662 struct intel_connector *intel_connector; 717 struct intel_connector *intel_connector;
663 struct drm_i915_private *dev_priv = dev->dev_private; 718 struct drm_i915_private *dev_priv = dev->dev_private;
664 const struct drm_encoder_helper_funcs *encoder_helper_funcs;
665 719
666 /* Skip machines without VGA that falsely report hotplug events */ 720 /* Skip machines without VGA that falsely report hotplug events */
667 if (dmi_check_system(intel_no_crt)) 721 if (dmi_check_system(intel_no_crt))
@@ -687,13 +741,11 @@ void intel_crt_init(struct drm_device *dev)
687 intel_connector_attach_encoder(intel_connector, &crt->base); 741 intel_connector_attach_encoder(intel_connector, &crt->base);
688 742
689 crt->base.type = INTEL_OUTPUT_ANALOG; 743 crt->base.type = INTEL_OUTPUT_ANALOG;
690 crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT | 744 crt->base.cloneable = true;
691 1 << INTEL_ANALOG_CLONE_BIT |
692 1 << INTEL_SDVO_LVDS_CLONE_BIT);
693 if (IS_HASWELL(dev)) 745 if (IS_HASWELL(dev))
694 crt->base.crtc_mask = (1 << 0); 746 crt->base.crtc_mask = (1 << 0);
695 else 747 else
696 crt->base.crtc_mask = (1 << 0) | (1 << 1); 748 crt->base.crtc_mask = (1 << 0) | (1 << 1) | (1 << 2);
697 749
698 if (IS_GEN2(dev)) 750 if (IS_GEN2(dev))
699 connector->interlace_allowed = 0; 751 connector->interlace_allowed = 0;
@@ -702,11 +754,18 @@ void intel_crt_init(struct drm_device *dev)
702 connector->doublescan_allowed = 0; 754 connector->doublescan_allowed = 0;
703 755
704 if (HAS_PCH_SPLIT(dev)) 756 if (HAS_PCH_SPLIT(dev))
705 encoder_helper_funcs = &pch_encoder_funcs; 757 crt->adpa_reg = PCH_ADPA;
758 else if (IS_VALLEYVIEW(dev))
759 crt->adpa_reg = VLV_ADPA;
706 else 760 else
707 encoder_helper_funcs = &gmch_encoder_funcs; 761 crt->adpa_reg = ADPA;
762
763 crt->base.disable = intel_disable_crt;
764 crt->base.enable = intel_enable_crt;
765 crt->base.get_hw_state = intel_crt_get_hw_state;
766 intel_connector->get_hw_state = intel_connector_get_hw_state;
708 767
709 drm_encoder_helper_add(&crt->base.base, encoder_helper_funcs); 768 drm_encoder_helper_add(&crt->base.base, &crt_encoder_funcs);
710 drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); 769 drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs);
711 770
712 drm_sysfs_connector_add(connector); 771 drm_sysfs_connector_add(connector);