diff options
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 307 |
1 files changed, 168 insertions, 139 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index 197d4f32585a..0979d8877880 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -30,10 +30,30 @@ | |||
30 | #include "drm.h" | 30 | #include "drm.h" |
31 | #include "drm_crtc.h" | 31 | #include "drm_crtc.h" |
32 | #include "drm_crtc_helper.h" | 32 | #include "drm_crtc_helper.h" |
33 | #include "drm_edid.h" | ||
33 | #include "intel_drv.h" | 34 | #include "intel_drv.h" |
34 | #include "i915_drm.h" | 35 | #include "i915_drm.h" |
35 | #include "i915_drv.h" | 36 | #include "i915_drv.h" |
36 | 37 | ||
38 | /* Here's the desired hotplug mode */ | ||
39 | #define ADPA_HOTPLUG_BITS (ADPA_CRT_HOTPLUG_PERIOD_128 | \ | ||
40 | ADPA_CRT_HOTPLUG_WARMUP_10MS | \ | ||
41 | ADPA_CRT_HOTPLUG_SAMPLE_4S | \ | ||
42 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | \ | ||
43 | ADPA_CRT_HOTPLUG_VOLREF_325MV | \ | ||
44 | ADPA_CRT_HOTPLUG_ENABLE) | ||
45 | |||
46 | struct intel_crt { | ||
47 | struct intel_encoder base; | ||
48 | bool force_hotplug_required; | ||
49 | }; | ||
50 | |||
51 | static struct intel_crt *intel_attached_crt(struct drm_connector *connector) | ||
52 | { | ||
53 | return container_of(intel_attached_encoder(connector), | ||
54 | struct intel_crt, base); | ||
55 | } | ||
56 | |||
37 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | 57 | static void intel_crt_dpms(struct drm_encoder *encoder, int mode) |
38 | { | 58 | { |
39 | struct drm_device *dev = encoder->dev; | 59 | struct drm_device *dev = encoder->dev; |
@@ -79,7 +99,7 @@ static int intel_crt_mode_valid(struct drm_connector *connector, | |||
79 | if (mode->clock < 25000) | 99 | if (mode->clock < 25000) |
80 | return MODE_CLOCK_LOW; | 100 | return MODE_CLOCK_LOW; |
81 | 101 | ||
82 | if (!IS_I9XX(dev)) | 102 | if (IS_GEN2(dev)) |
83 | max_clock = 350000; | 103 | max_clock = 350000; |
84 | else | 104 | else |
85 | max_clock = 400000; | 105 | max_clock = 400000; |
@@ -109,10 +129,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
109 | u32 adpa, dpll_md; | 129 | u32 adpa, dpll_md; |
110 | u32 adpa_reg; | 130 | u32 adpa_reg; |
111 | 131 | ||
112 | if (intel_crtc->pipe == 0) | 132 | dpll_md_reg = DPLL_MD(intel_crtc->pipe); |
113 | dpll_md_reg = DPLL_A_MD; | ||
114 | else | ||
115 | dpll_md_reg = DPLL_B_MD; | ||
116 | 133 | ||
117 | if (HAS_PCH_SPLIT(dev)) | 134 | if (HAS_PCH_SPLIT(dev)) |
118 | adpa_reg = PCH_ADPA; | 135 | adpa_reg = PCH_ADPA; |
@@ -123,13 +140,13 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
123 | * Disable separate mode multiplier used when cloning SDVO to CRT | 140 | * Disable separate mode multiplier used when cloning SDVO to CRT |
124 | * XXX this needs to be adjusted when we really are cloning | 141 | * XXX this needs to be adjusted when we really are cloning |
125 | */ | 142 | */ |
126 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { | 143 | if (INTEL_INFO(dev)->gen >= 4 && !HAS_PCH_SPLIT(dev)) { |
127 | dpll_md = I915_READ(dpll_md_reg); | 144 | dpll_md = I915_READ(dpll_md_reg); |
128 | I915_WRITE(dpll_md_reg, | 145 | I915_WRITE(dpll_md_reg, |
129 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); | 146 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); |
130 | } | 147 | } |
131 | 148 | ||
132 | adpa = 0; | 149 | adpa = ADPA_HOTPLUG_BITS; |
133 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) | 150 | if (adjusted_mode->flags & DRM_MODE_FLAG_PHSYNC) |
134 | adpa |= ADPA_HSYNC_ACTIVE_HIGH; | 151 | adpa |= ADPA_HSYNC_ACTIVE_HIGH; |
135 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) | 152 | if (adjusted_mode->flags & DRM_MODE_FLAG_PVSYNC) |
@@ -140,69 +157,60 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
140 | adpa |= PORT_TRANS_A_SEL_CPT; | 157 | adpa |= PORT_TRANS_A_SEL_CPT; |
141 | else | 158 | else |
142 | adpa |= ADPA_PIPE_A_SELECT; | 159 | adpa |= ADPA_PIPE_A_SELECT; |
143 | if (!HAS_PCH_SPLIT(dev)) | ||
144 | I915_WRITE(BCLRPAT_A, 0); | ||
145 | } else { | 160 | } else { |
146 | if (HAS_PCH_CPT(dev)) | 161 | if (HAS_PCH_CPT(dev)) |
147 | adpa |= PORT_TRANS_B_SEL_CPT; | 162 | adpa |= PORT_TRANS_B_SEL_CPT; |
148 | else | 163 | else |
149 | adpa |= ADPA_PIPE_B_SELECT; | 164 | adpa |= ADPA_PIPE_B_SELECT; |
150 | if (!HAS_PCH_SPLIT(dev)) | ||
151 | I915_WRITE(BCLRPAT_B, 0); | ||
152 | } | 165 | } |
153 | 166 | ||
167 | if (!HAS_PCH_SPLIT(dev)) | ||
168 | I915_WRITE(BCLRPAT(intel_crtc->pipe), 0); | ||
169 | |||
154 | I915_WRITE(adpa_reg, adpa); | 170 | I915_WRITE(adpa_reg, adpa); |
155 | } | 171 | } |
156 | 172 | ||
157 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) | 173 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) |
158 | { | 174 | { |
159 | struct drm_device *dev = connector->dev; | 175 | struct drm_device *dev = connector->dev; |
176 | struct intel_crt *crt = intel_attached_crt(connector); | ||
160 | struct drm_i915_private *dev_priv = dev->dev_private; | 177 | struct drm_i915_private *dev_priv = dev->dev_private; |
161 | u32 adpa, temp; | 178 | u32 adpa; |
162 | bool ret; | 179 | bool ret; |
163 | bool turn_off_dac = false; | ||
164 | 180 | ||
165 | temp = adpa = I915_READ(PCH_ADPA); | 181 | /* The first time through, trigger an explicit detection cycle */ |
182 | if (crt->force_hotplug_required) { | ||
183 | bool turn_off_dac = HAS_PCH_SPLIT(dev); | ||
184 | u32 save_adpa; | ||
166 | 185 | ||
167 | if (HAS_PCH_SPLIT(dev)) | 186 | crt->force_hotplug_required = 0; |
168 | turn_off_dac = true; | 187 | |
169 | 188 | save_adpa = adpa = I915_READ(PCH_ADPA); | |
170 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | 189 | DRM_DEBUG_KMS("trigger hotplug detect cycle: adpa=0x%x\n", adpa); |
171 | if (turn_off_dac) | 190 | |
172 | adpa &= ~ADPA_DAC_ENABLE; | 191 | adpa |= ADPA_CRT_HOTPLUG_FORCE_TRIGGER; |
173 | 192 | if (turn_off_dac) | |
174 | /* disable HPD first */ | 193 | adpa &= ~ADPA_DAC_ENABLE; |
175 | I915_WRITE(PCH_ADPA, adpa); | 194 | |
176 | (void)I915_READ(PCH_ADPA); | 195 | I915_WRITE(PCH_ADPA, adpa); |
177 | 196 | ||
178 | adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | | 197 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, |
179 | ADPA_CRT_HOTPLUG_WARMUP_10MS | | 198 | 1000)) |
180 | ADPA_CRT_HOTPLUG_SAMPLE_4S | | 199 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); |
181 | ADPA_CRT_HOTPLUG_VOLTAGE_50 | /* default */ | 200 | |
182 | ADPA_CRT_HOTPLUG_VOLREF_325MV | | 201 | if (turn_off_dac) { |
183 | ADPA_CRT_HOTPLUG_ENABLE | | 202 | I915_WRITE(PCH_ADPA, save_adpa); |
184 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); | 203 | POSTING_READ(PCH_ADPA); |
185 | 204 | } | |
186 | DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); | ||
187 | I915_WRITE(PCH_ADPA, adpa); | ||
188 | |||
189 | if (wait_for((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) == 0, | ||
190 | 1000, 1)) | ||
191 | DRM_DEBUG_KMS("timed out waiting for FORCE_TRIGGER"); | ||
192 | |||
193 | if (turn_off_dac) { | ||
194 | I915_WRITE(PCH_ADPA, temp); | ||
195 | (void)I915_READ(PCH_ADPA); | ||
196 | } | 205 | } |
197 | 206 | ||
198 | /* Check the status to see if both blue and green are on now */ | 207 | /* Check the status to see if both blue and green are on now */ |
199 | adpa = I915_READ(PCH_ADPA); | 208 | adpa = I915_READ(PCH_ADPA); |
200 | adpa &= ADPA_CRT_HOTPLUG_MONITOR_MASK; | 209 | if ((adpa & ADPA_CRT_HOTPLUG_MONITOR_MASK) != 0) |
201 | if ((adpa == ADPA_CRT_HOTPLUG_MONITOR_COLOR) || | ||
202 | (adpa == ADPA_CRT_HOTPLUG_MONITOR_MONO)) | ||
203 | ret = true; | 210 | ret = true; |
204 | else | 211 | else |
205 | ret = false; | 212 | ret = false; |
213 | DRM_DEBUG_KMS("ironlake hotplug adpa=0x%x, result %d\n", adpa, ret); | ||
206 | 214 | ||
207 | return ret; | 215 | return ret; |
208 | } | 216 | } |
@@ -244,7 +252,7 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
244 | /* wait for FORCE_DETECT to go off */ | 252 | /* wait for FORCE_DETECT to go off */ |
245 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & | 253 | if (wait_for((I915_READ(PORT_HOTPLUG_EN) & |
246 | CRT_HOTPLUG_FORCE_DETECT) == 0, | 254 | CRT_HOTPLUG_FORCE_DETECT) == 0, |
247 | 1000, 1)) | 255 | 1000)) |
248 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); | 256 | DRM_DEBUG_KMS("timed out waiting for FORCE_DETECT to go off"); |
249 | } | 257 | } |
250 | 258 | ||
@@ -261,25 +269,51 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
261 | return ret; | 269 | return ret; |
262 | } | 270 | } |
263 | 271 | ||
264 | static bool intel_crt_detect_ddc(struct drm_encoder *encoder) | 272 | static bool intel_crt_detect_ddc(struct drm_connector *connector) |
265 | { | 273 | { |
266 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | 274 | struct intel_crt *crt = intel_attached_crt(connector); |
275 | struct drm_i915_private *dev_priv = crt->base.base.dev->dev_private; | ||
267 | 276 | ||
268 | /* CRT should always be at 0, but check anyway */ | 277 | /* CRT should always be at 0, but check anyway */ |
269 | if (intel_encoder->type != INTEL_OUTPUT_ANALOG) | 278 | if (crt->base.type != INTEL_OUTPUT_ANALOG) |
270 | return false; | 279 | return false; |
271 | 280 | ||
272 | return intel_ddc_probe(intel_encoder); | 281 | if (intel_ddc_probe(&crt->base, dev_priv->crt_ddc_pin)) { |
282 | struct edid *edid; | ||
283 | bool is_digital = false; | ||
284 | |||
285 | edid = drm_get_edid(connector, | ||
286 | &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); | ||
287 | /* | ||
288 | * This may be a DVI-I connector with a shared DDC | ||
289 | * link between analog and digital outputs, so we | ||
290 | * have to check the EDID input spec of the attached device. | ||
291 | * | ||
292 | * On the other hand, what should we do if it is a broken EDID? | ||
293 | */ | ||
294 | if (edid != NULL) { | ||
295 | is_digital = edid->input & DRM_EDID_INPUT_DIGITAL; | ||
296 | connector->display_info.raw_edid = NULL; | ||
297 | kfree(edid); | ||
298 | } | ||
299 | |||
300 | if (!is_digital) { | ||
301 | DRM_DEBUG_KMS("CRT detected via DDC:0x50 [EDID]\n"); | ||
302 | return true; | ||
303 | } else { | ||
304 | DRM_DEBUG_KMS("CRT not detected via DDC:0x50 [EDID reports a digital panel]\n"); | ||
305 | } | ||
306 | } | ||
307 | |||
308 | return false; | ||
273 | } | 309 | } |
274 | 310 | ||
275 | static enum drm_connector_status | 311 | static enum drm_connector_status |
276 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) | 312 | intel_crt_load_detect(struct intel_crt *crt) |
277 | { | 313 | { |
278 | struct drm_encoder *encoder = &intel_encoder->enc; | 314 | struct drm_device *dev = crt->base.base.dev; |
279 | struct drm_device *dev = encoder->dev; | ||
280 | struct drm_i915_private *dev_priv = dev->dev_private; | 315 | struct drm_i915_private *dev_priv = dev->dev_private; |
281 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 316 | uint32_t pipe = to_intel_crtc(crt->base.base.crtc)->pipe; |
282 | uint32_t pipe = intel_crtc->pipe; | ||
283 | uint32_t save_bclrpat; | 317 | uint32_t save_bclrpat; |
284 | uint32_t save_vtotal; | 318 | uint32_t save_vtotal; |
285 | uint32_t vtotal, vactive; | 319 | uint32_t vtotal, vactive; |
@@ -295,21 +329,14 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
295 | uint8_t st00; | 329 | uint8_t st00; |
296 | enum drm_connector_status status; | 330 | enum drm_connector_status status; |
297 | 331 | ||
298 | if (pipe == 0) { | 332 | DRM_DEBUG_KMS("starting load-detect on CRT\n"); |
299 | bclrpat_reg = BCLRPAT_A; | 333 | |
300 | vtotal_reg = VTOTAL_A; | 334 | bclrpat_reg = BCLRPAT(pipe); |
301 | vblank_reg = VBLANK_A; | 335 | vtotal_reg = VTOTAL(pipe); |
302 | vsync_reg = VSYNC_A; | 336 | vblank_reg = VBLANK(pipe); |
303 | pipeconf_reg = PIPEACONF; | 337 | vsync_reg = VSYNC(pipe); |
304 | pipe_dsl_reg = PIPEADSL; | 338 | pipeconf_reg = PIPECONF(pipe); |
305 | } else { | 339 | pipe_dsl_reg = PIPEDSL(pipe); |
306 | bclrpat_reg = BCLRPAT_B; | ||
307 | vtotal_reg = VTOTAL_B; | ||
308 | vblank_reg = VBLANK_B; | ||
309 | vsync_reg = VSYNC_B; | ||
310 | pipeconf_reg = PIPEBCONF; | ||
311 | pipe_dsl_reg = PIPEBDSL; | ||
312 | } | ||
313 | 340 | ||
314 | save_bclrpat = I915_READ(bclrpat_reg); | 341 | save_bclrpat = I915_READ(bclrpat_reg); |
315 | save_vtotal = I915_READ(vtotal_reg); | 342 | save_vtotal = I915_READ(vtotal_reg); |
@@ -324,9 +351,10 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder | |||
324 | /* Set the border color to purple. */ | 351 | /* Set the border color to purple. */ |
325 | I915_WRITE(bclrpat_reg, 0x500050); | 352 | I915_WRITE(bclrpat_reg, 0x500050); |
326 | 353 | ||
327 | if (IS_I9XX(dev)) { | 354 | if (!IS_GEN2(dev)) { |
328 | uint32_t pipeconf = I915_READ(pipeconf_reg); | 355 | uint32_t pipeconf = I915_READ(pipeconf_reg); |
329 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); | 356 | I915_WRITE(pipeconf_reg, pipeconf | PIPECONF_FORCE_BORDER); |
357 | POSTING_READ(pipeconf_reg); | ||
330 | /* Wait for next Vblank to substitue | 358 | /* Wait for next Vblank to substitue |
331 | * border color for Color info */ | 359 | * border color for Color info */ |
332 | intel_wait_for_vblank(dev, pipe); | 360 | intel_wait_for_vblank(dev, pipe); |
@@ -404,35 +432,41 @@ static enum drm_connector_status | |||
404 | intel_crt_detect(struct drm_connector *connector, bool force) | 432 | intel_crt_detect(struct drm_connector *connector, bool force) |
405 | { | 433 | { |
406 | struct drm_device *dev = connector->dev; | 434 | struct drm_device *dev = connector->dev; |
407 | struct drm_encoder *encoder = intel_attached_encoder(connector); | 435 | struct intel_crt *crt = intel_attached_crt(connector); |
408 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
409 | struct drm_crtc *crtc; | 436 | struct drm_crtc *crtc; |
410 | int dpms_mode; | ||
411 | enum drm_connector_status status; | 437 | enum drm_connector_status status; |
412 | 438 | ||
413 | if (IS_I9XX(dev) && !IS_I915G(dev) && !IS_I915GM(dev)) { | 439 | if (I915_HAS_HOTPLUG(dev)) { |
414 | if (intel_crt_detect_hotplug(connector)) | 440 | if (intel_crt_detect_hotplug(connector)) { |
441 | DRM_DEBUG_KMS("CRT detected via hotplug\n"); | ||
415 | return connector_status_connected; | 442 | return connector_status_connected; |
416 | else | 443 | } else { |
444 | DRM_DEBUG_KMS("CRT not detected via hotplug\n"); | ||
417 | return connector_status_disconnected; | 445 | return connector_status_disconnected; |
446 | } | ||
418 | } | 447 | } |
419 | 448 | ||
420 | if (intel_crt_detect_ddc(encoder)) | 449 | if (intel_crt_detect_ddc(connector)) |
421 | return connector_status_connected; | 450 | return connector_status_connected; |
422 | 451 | ||
423 | if (!force) | 452 | if (!force) |
424 | return connector->status; | 453 | return connector->status; |
425 | 454 | ||
426 | /* for pre-945g platforms use load detect */ | 455 | /* for pre-945g platforms use load detect */ |
427 | if (encoder->crtc && encoder->crtc->enabled) { | 456 | crtc = crt->base.base.crtc; |
428 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); | 457 | if (crtc && crtc->enabled) { |
458 | status = intel_crt_load_detect(crt); | ||
429 | } else { | 459 | } else { |
430 | crtc = intel_get_load_detect_pipe(intel_encoder, connector, | 460 | struct intel_load_detect_pipe tmp; |
431 | NULL, &dpms_mode); | 461 | |
432 | if (crtc) { | 462 | if (intel_get_load_detect_pipe(&crt->base, connector, NULL, |
433 | status = intel_crt_load_detect(crtc, intel_encoder); | 463 | &tmp)) { |
434 | intel_release_load_detect_pipe(intel_encoder, | 464 | if (intel_crt_detect_ddc(connector)) |
435 | connector, dpms_mode); | 465 | status = connector_status_connected; |
466 | else | ||
467 | status = intel_crt_load_detect(crt); | ||
468 | intel_release_load_detect_pipe(&crt->base, connector, | ||
469 | &tmp); | ||
436 | } else | 470 | } else |
437 | status = connector_status_unknown; | 471 | status = connector_status_unknown; |
438 | } | 472 | } |
@@ -449,32 +483,18 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
449 | 483 | ||
450 | static int intel_crt_get_modes(struct drm_connector *connector) | 484 | static int intel_crt_get_modes(struct drm_connector *connector) |
451 | { | 485 | { |
452 | int ret; | ||
453 | struct drm_encoder *encoder = intel_attached_encoder(connector); | ||
454 | struct intel_encoder *intel_encoder = enc_to_intel_encoder(encoder); | ||
455 | struct i2c_adapter *ddc_bus; | ||
456 | struct drm_device *dev = connector->dev; | 486 | struct drm_device *dev = connector->dev; |
487 | struct drm_i915_private *dev_priv = dev->dev_private; | ||
488 | int ret; | ||
457 | 489 | ||
458 | 490 | ret = intel_ddc_get_modes(connector, | |
459 | ret = intel_ddc_get_modes(connector, intel_encoder->ddc_bus); | 491 | &dev_priv->gmbus[dev_priv->crt_ddc_pin].adapter); |
460 | if (ret || !IS_G4X(dev)) | 492 | if (ret || !IS_G4X(dev)) |
461 | goto end; | 493 | return ret; |
462 | 494 | ||
463 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | 495 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
464 | ddc_bus = intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); | 496 | return intel_ddc_get_modes(connector, |
465 | 497 | &dev_priv->gmbus[GMBUS_PORT_DPB].adapter); | |
466 | if (!ddc_bus) { | ||
467 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, | ||
468 | "DDC bus registration failed for CRTDDC_D.\n"); | ||
469 | goto end; | ||
470 | } | ||
471 | /* Try to get modes by GPIOD port */ | ||
472 | ret = intel_ddc_get_modes(connector, ddc_bus); | ||
473 | intel_i2c_destroy(ddc_bus); | ||
474 | |||
475 | end: | ||
476 | return ret; | ||
477 | |||
478 | } | 498 | } |
479 | 499 | ||
480 | static int intel_crt_set_property(struct drm_connector *connector, | 500 | static int intel_crt_set_property(struct drm_connector *connector, |
@@ -484,6 +504,15 @@ static int intel_crt_set_property(struct drm_connector *connector, | |||
484 | return 0; | 504 | return 0; |
485 | } | 505 | } |
486 | 506 | ||
507 | static void intel_crt_reset(struct drm_connector *connector) | ||
508 | { | ||
509 | struct drm_device *dev = connector->dev; | ||
510 | struct intel_crt *crt = intel_attached_crt(connector); | ||
511 | |||
512 | if (HAS_PCH_SPLIT(dev)) | ||
513 | crt->force_hotplug_required = 1; | ||
514 | } | ||
515 | |||
487 | /* | 516 | /* |
488 | * Routines for controlling stuff on the analog port | 517 | * Routines for controlling stuff on the analog port |
489 | */ | 518 | */ |
@@ -497,6 +526,7 @@ static const struct drm_encoder_helper_funcs intel_crt_helper_funcs = { | |||
497 | }; | 526 | }; |
498 | 527 | ||
499 | static const struct drm_connector_funcs intel_crt_connector_funcs = { | 528 | static const struct drm_connector_funcs intel_crt_connector_funcs = { |
529 | .reset = intel_crt_reset, | ||
500 | .dpms = drm_helper_connector_dpms, | 530 | .dpms = drm_helper_connector_dpms, |
501 | .detect = intel_crt_detect, | 531 | .detect = intel_crt_detect, |
502 | .fill_modes = drm_helper_probe_single_connector_modes, | 532 | .fill_modes = drm_helper_probe_single_connector_modes, |
@@ -507,7 +537,7 @@ static const struct drm_connector_funcs intel_crt_connector_funcs = { | |||
507 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { | 537 | static const struct drm_connector_helper_funcs intel_crt_connector_helper_funcs = { |
508 | .mode_valid = intel_crt_mode_valid, | 538 | .mode_valid = intel_crt_mode_valid, |
509 | .get_modes = intel_crt_get_modes, | 539 | .get_modes = intel_crt_get_modes, |
510 | .best_encoder = intel_attached_encoder, | 540 | .best_encoder = intel_best_encoder, |
511 | }; | 541 | }; |
512 | 542 | ||
513 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { | 543 | static const struct drm_encoder_funcs intel_crt_enc_funcs = { |
@@ -517,18 +547,17 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { | |||
517 | void intel_crt_init(struct drm_device *dev) | 547 | void intel_crt_init(struct drm_device *dev) |
518 | { | 548 | { |
519 | struct drm_connector *connector; | 549 | struct drm_connector *connector; |
520 | struct intel_encoder *intel_encoder; | 550 | struct intel_crt *crt; |
521 | struct intel_connector *intel_connector; | 551 | struct intel_connector *intel_connector; |
522 | struct drm_i915_private *dev_priv = dev->dev_private; | 552 | struct drm_i915_private *dev_priv = dev->dev_private; |
523 | u32 i2c_reg; | ||
524 | 553 | ||
525 | intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); | 554 | crt = kzalloc(sizeof(struct intel_crt), GFP_KERNEL); |
526 | if (!intel_encoder) | 555 | if (!crt) |
527 | return; | 556 | return; |
528 | 557 | ||
529 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); | 558 | intel_connector = kzalloc(sizeof(struct intel_connector), GFP_KERNEL); |
530 | if (!intel_connector) { | 559 | if (!intel_connector) { |
531 | kfree(intel_encoder); | 560 | kfree(crt); |
532 | return; | 561 | return; |
533 | } | 562 | } |
534 | 563 | ||
@@ -536,37 +565,20 @@ void intel_crt_init(struct drm_device *dev) | |||
536 | drm_connector_init(dev, &intel_connector->base, | 565 | drm_connector_init(dev, &intel_connector->base, |
537 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 566 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
538 | 567 | ||
539 | drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs, | 568 | drm_encoder_init(dev, &crt->base.base, &intel_crt_enc_funcs, |
540 | DRM_MODE_ENCODER_DAC); | 569 | DRM_MODE_ENCODER_DAC); |
541 | 570 | ||
542 | drm_mode_connector_attach_encoder(&intel_connector->base, | 571 | intel_connector_attach_encoder(intel_connector, &crt->base); |
543 | &intel_encoder->enc); | ||
544 | 572 | ||
545 | /* Set up the DDC bus. */ | 573 | crt->base.type = INTEL_OUTPUT_ANALOG; |
546 | if (HAS_PCH_SPLIT(dev)) | 574 | crt->base.clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT | |
547 | i2c_reg = PCH_GPIOA; | 575 | 1 << INTEL_ANALOG_CLONE_BIT | |
548 | else { | 576 | 1 << INTEL_SDVO_LVDS_CLONE_BIT); |
549 | i2c_reg = GPIOA; | 577 | crt->base.crtc_mask = (1 << 0) | (1 << 1); |
550 | /* Use VBT information for CRT DDC if available */ | ||
551 | if (dev_priv->crt_ddc_bus != 0) | ||
552 | i2c_reg = dev_priv->crt_ddc_bus; | ||
553 | } | ||
554 | intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); | ||
555 | if (!intel_encoder->ddc_bus) { | ||
556 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | ||
557 | "failed.\n"); | ||
558 | return; | ||
559 | } | ||
560 | |||
561 | intel_encoder->type = INTEL_OUTPUT_ANALOG; | ||
562 | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | ||
563 | (1 << INTEL_ANALOG_CLONE_BIT) | | ||
564 | (1 << INTEL_SDVO_LVDS_CLONE_BIT); | ||
565 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); | ||
566 | connector->interlace_allowed = 1; | 578 | connector->interlace_allowed = 1; |
567 | connector->doublescan_allowed = 0; | 579 | connector->doublescan_allowed = 0; |
568 | 580 | ||
569 | drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs); | 581 | drm_encoder_helper_add(&crt->base.base, &intel_crt_helper_funcs); |
570 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 582 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
571 | 583 | ||
572 | drm_sysfs_connector_add(connector); | 584 | drm_sysfs_connector_add(connector); |
@@ -576,5 +588,22 @@ void intel_crt_init(struct drm_device *dev) | |||
576 | else | 588 | else |
577 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; | 589 | connector->polled = DRM_CONNECTOR_POLL_CONNECT; |
578 | 590 | ||
591 | /* | ||
592 | * Configure the automatic hotplug detection stuff | ||
593 | */ | ||
594 | crt->force_hotplug_required = 0; | ||
595 | if (HAS_PCH_SPLIT(dev)) { | ||
596 | u32 adpa; | ||
597 | |||
598 | adpa = I915_READ(PCH_ADPA); | ||
599 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | ||
600 | adpa |= ADPA_HOTPLUG_BITS; | ||
601 | I915_WRITE(PCH_ADPA, adpa); | ||
602 | POSTING_READ(PCH_ADPA); | ||
603 | |||
604 | DRM_DEBUG_KMS("pch crt adpa set to 0x%x\n", adpa); | ||
605 | crt->force_hotplug_required = 1; | ||
606 | } | ||
607 | |||
579 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; | 608 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; |
580 | } | 609 | } |