diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/gpu/drm/i915/intel_crt.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff) |
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/gpu/drm/i915/intel_crt.c')
-rw-r--r-- | drivers/gpu/drm/i915/intel_crt.c | 124 |
1 files changed, 51 insertions, 73 deletions
diff --git a/drivers/gpu/drm/i915/intel_crt.c b/drivers/gpu/drm/i915/intel_crt.c index e5051446c48e..759c2ef72eff 100644 --- a/drivers/gpu/drm/i915/intel_crt.c +++ b/drivers/gpu/drm/i915/intel_crt.c | |||
@@ -25,6 +25,7 @@ | |||
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <linux/i2c.h> | 27 | #include <linux/i2c.h> |
28 | #include <linux/slab.h> | ||
28 | #include "drmP.h" | 29 | #include "drmP.h" |
29 | #include "drm.h" | 30 | #include "drm.h" |
30 | #include "drm_crtc.h" | 31 | #include "drm_crtc.h" |
@@ -39,7 +40,7 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
39 | struct drm_i915_private *dev_priv = dev->dev_private; | 40 | struct drm_i915_private *dev_priv = dev->dev_private; |
40 | u32 temp, reg; | 41 | u32 temp, reg; |
41 | 42 | ||
42 | if (IS_IGDNG(dev)) | 43 | if (HAS_PCH_SPLIT(dev)) |
43 | reg = PCH_ADPA; | 44 | reg = PCH_ADPA; |
44 | else | 45 | else |
45 | reg = ADPA; | 46 | reg = ADPA; |
@@ -64,34 +65,6 @@ static void intel_crt_dpms(struct drm_encoder *encoder, int mode) | |||
64 | } | 65 | } |
65 | 66 | ||
66 | I915_WRITE(reg, temp); | 67 | I915_WRITE(reg, temp); |
67 | |||
68 | if (IS_IGD(dev)) { | ||
69 | if (mode == DRM_MODE_DPMS_OFF) { | ||
70 | /* turn off DAC */ | ||
71 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
72 | temp &= ~CRT_EOS_INT_EN; | ||
73 | I915_WRITE(PORT_HOTPLUG_EN, temp); | ||
74 | |||
75 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
76 | if (temp & CRT_EOS_INT_STATUS) | ||
77 | I915_WRITE(PORT_HOTPLUG_STAT, | ||
78 | CRT_EOS_INT_STATUS); | ||
79 | } else { | ||
80 | /* turn on DAC. EOS interrupt must be enabled after DAC | ||
81 | * is enabled, so it sounds not good to enable it in | ||
82 | * i915_driver_irq_postinstall() | ||
83 | * wait 12.5ms after DAC is enabled | ||
84 | */ | ||
85 | msleep(13); | ||
86 | temp = I915_READ(PORT_HOTPLUG_STAT); | ||
87 | if (temp & CRT_EOS_INT_STATUS) | ||
88 | I915_WRITE(PORT_HOTPLUG_STAT, | ||
89 | CRT_EOS_INT_STATUS); | ||
90 | temp = I915_READ(PORT_HOTPLUG_EN); | ||
91 | temp |= CRT_EOS_INT_EN; | ||
92 | I915_WRITE(PORT_HOTPLUG_EN, temp); | ||
93 | } | ||
94 | } | ||
95 | } | 68 | } |
96 | 69 | ||
97 | static int intel_crt_mode_valid(struct drm_connector *connector, | 70 | static int intel_crt_mode_valid(struct drm_connector *connector, |
@@ -141,7 +114,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
141 | else | 114 | else |
142 | dpll_md_reg = DPLL_B_MD; | 115 | dpll_md_reg = DPLL_B_MD; |
143 | 116 | ||
144 | if (IS_IGDNG(dev)) | 117 | if (HAS_PCH_SPLIT(dev)) |
145 | adpa_reg = PCH_ADPA; | 118 | adpa_reg = PCH_ADPA; |
146 | else | 119 | else |
147 | adpa_reg = ADPA; | 120 | adpa_reg = ADPA; |
@@ -150,7 +123,7 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
150 | * Disable separate mode multiplier used when cloning SDVO to CRT | 123 | * Disable separate mode multiplier used when cloning SDVO to CRT |
151 | * XXX this needs to be adjusted when we really are cloning | 124 | * XXX this needs to be adjusted when we really are cloning |
152 | */ | 125 | */ |
153 | if (IS_I965G(dev) && !IS_IGDNG(dev)) { | 126 | if (IS_I965G(dev) && !HAS_PCH_SPLIT(dev)) { |
154 | dpll_md = I915_READ(dpll_md_reg); | 127 | dpll_md = I915_READ(dpll_md_reg); |
155 | I915_WRITE(dpll_md_reg, | 128 | I915_WRITE(dpll_md_reg, |
156 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); | 129 | dpll_md & ~DPLL_MD_UDI_MULTIPLIER_MASK); |
@@ -164,18 +137,18 @@ static void intel_crt_mode_set(struct drm_encoder *encoder, | |||
164 | 137 | ||
165 | if (intel_crtc->pipe == 0) { | 138 | if (intel_crtc->pipe == 0) { |
166 | adpa |= ADPA_PIPE_A_SELECT; | 139 | adpa |= ADPA_PIPE_A_SELECT; |
167 | if (!IS_IGDNG(dev)) | 140 | if (!HAS_PCH_SPLIT(dev)) |
168 | I915_WRITE(BCLRPAT_A, 0); | 141 | I915_WRITE(BCLRPAT_A, 0); |
169 | } else { | 142 | } else { |
170 | adpa |= ADPA_PIPE_B_SELECT; | 143 | adpa |= ADPA_PIPE_B_SELECT; |
171 | if (!IS_IGDNG(dev)) | 144 | if (!HAS_PCH_SPLIT(dev)) |
172 | I915_WRITE(BCLRPAT_B, 0); | 145 | I915_WRITE(BCLRPAT_B, 0); |
173 | } | 146 | } |
174 | 147 | ||
175 | I915_WRITE(adpa_reg, adpa); | 148 | I915_WRITE(adpa_reg, adpa); |
176 | } | 149 | } |
177 | 150 | ||
178 | static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) | 151 | static bool intel_ironlake_crt_detect_hotplug(struct drm_connector *connector) |
179 | { | 152 | { |
180 | struct drm_device *dev = connector->dev; | 153 | struct drm_device *dev = connector->dev; |
181 | struct drm_i915_private *dev_priv = dev->dev_private; | 154 | struct drm_i915_private *dev_priv = dev->dev_private; |
@@ -185,6 +158,9 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) | |||
185 | adpa = I915_READ(PCH_ADPA); | 158 | adpa = I915_READ(PCH_ADPA); |
186 | 159 | ||
187 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; | 160 | adpa &= ~ADPA_CRT_HOTPLUG_MASK; |
161 | /* disable HPD first */ | ||
162 | I915_WRITE(PCH_ADPA, adpa); | ||
163 | (void)I915_READ(PCH_ADPA); | ||
188 | 164 | ||
189 | adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | | 165 | adpa |= (ADPA_CRT_HOTPLUG_PERIOD_128 | |
190 | ADPA_CRT_HOTPLUG_WARMUP_10MS | | 166 | ADPA_CRT_HOTPLUG_WARMUP_10MS | |
@@ -194,7 +170,7 @@ static bool intel_igdng_crt_detect_hotplug(struct drm_connector *connector) | |||
194 | ADPA_CRT_HOTPLUG_ENABLE | | 170 | ADPA_CRT_HOTPLUG_ENABLE | |
195 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); | 171 | ADPA_CRT_HOTPLUG_FORCE_TRIGGER); |
196 | 172 | ||
197 | DRM_DEBUG("pch crt adpa 0x%x", adpa); | 173 | DRM_DEBUG_KMS("pch crt adpa 0x%x", adpa); |
198 | I915_WRITE(PCH_ADPA, adpa); | 174 | I915_WRITE(PCH_ADPA, adpa); |
199 | 175 | ||
200 | while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0) | 176 | while ((I915_READ(PCH_ADPA) & ADPA_CRT_HOTPLUG_FORCE_TRIGGER) != 0) |
@@ -227,8 +203,8 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
227 | u32 hotplug_en; | 203 | u32 hotplug_en; |
228 | int i, tries = 0; | 204 | int i, tries = 0; |
229 | 205 | ||
230 | if (IS_IGDNG(dev)) | 206 | if (HAS_PCH_SPLIT(dev)) |
231 | return intel_igdng_crt_detect_hotplug(connector); | 207 | return intel_ironlake_crt_detect_hotplug(connector); |
232 | 208 | ||
233 | /* | 209 | /* |
234 | * On 4 series desktop, CRT detect sequence need to be done twice | 210 | * On 4 series desktop, CRT detect sequence need to be done twice |
@@ -271,19 +247,19 @@ static bool intel_crt_detect_hotplug(struct drm_connector *connector) | |||
271 | 247 | ||
272 | static bool intel_crt_detect_ddc(struct drm_connector *connector) | 248 | static bool intel_crt_detect_ddc(struct drm_connector *connector) |
273 | { | 249 | { |
274 | struct intel_output *intel_output = to_intel_output(connector); | 250 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
275 | 251 | ||
276 | /* CRT should always be at 0, but check anyway */ | 252 | /* CRT should always be at 0, but check anyway */ |
277 | if (intel_output->type != INTEL_OUTPUT_ANALOG) | 253 | if (intel_encoder->type != INTEL_OUTPUT_ANALOG) |
278 | return false; | 254 | return false; |
279 | 255 | ||
280 | return intel_ddc_probe(intel_output); | 256 | return intel_ddc_probe(intel_encoder); |
281 | } | 257 | } |
282 | 258 | ||
283 | static enum drm_connector_status | 259 | static enum drm_connector_status |
284 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_output *intel_output) | 260 | intel_crt_load_detect(struct drm_crtc *crtc, struct intel_encoder *intel_encoder) |
285 | { | 261 | { |
286 | struct drm_encoder *encoder = &intel_output->enc; | 262 | struct drm_encoder *encoder = &intel_encoder->enc; |
287 | struct drm_device *dev = encoder->dev; | 263 | struct drm_device *dev = encoder->dev; |
288 | struct drm_i915_private *dev_priv = dev->dev_private; | 264 | struct drm_i915_private *dev_priv = dev->dev_private; |
289 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); | 265 | struct intel_crtc *intel_crtc = to_intel_crtc(crtc); |
@@ -411,8 +387,8 @@ intel_crt_load_detect(struct drm_crtc *crtc, struct intel_output *intel_output) | |||
411 | static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) | 387 | static enum drm_connector_status intel_crt_detect(struct drm_connector *connector) |
412 | { | 388 | { |
413 | struct drm_device *dev = connector->dev; | 389 | struct drm_device *dev = connector->dev; |
414 | struct intel_output *intel_output = to_intel_output(connector); | 390 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
415 | struct drm_encoder *encoder = &intel_output->enc; | 391 | struct drm_encoder *encoder = &intel_encoder->enc; |
416 | struct drm_crtc *crtc; | 392 | struct drm_crtc *crtc; |
417 | int dpms_mode; | 393 | int dpms_mode; |
418 | enum drm_connector_status status; | 394 | enum drm_connector_status status; |
@@ -429,13 +405,13 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto | |||
429 | 405 | ||
430 | /* for pre-945g platforms use load detect */ | 406 | /* for pre-945g platforms use load detect */ |
431 | if (encoder->crtc && encoder->crtc->enabled) { | 407 | if (encoder->crtc && encoder->crtc->enabled) { |
432 | status = intel_crt_load_detect(encoder->crtc, intel_output); | 408 | status = intel_crt_load_detect(encoder->crtc, intel_encoder); |
433 | } else { | 409 | } else { |
434 | crtc = intel_get_load_detect_pipe(intel_output, | 410 | crtc = intel_get_load_detect_pipe(intel_encoder, |
435 | NULL, &dpms_mode); | 411 | NULL, &dpms_mode); |
436 | if (crtc) { | 412 | if (crtc) { |
437 | status = intel_crt_load_detect(crtc, intel_output); | 413 | status = intel_crt_load_detect(crtc, intel_encoder); |
438 | intel_release_load_detect_pipe(intel_output, dpms_mode); | 414 | intel_release_load_detect_pipe(intel_encoder, dpms_mode); |
439 | } else | 415 | } else |
440 | status = connector_status_unknown; | 416 | status = connector_status_unknown; |
441 | } | 417 | } |
@@ -445,9 +421,9 @@ static enum drm_connector_status intel_crt_detect(struct drm_connector *connecto | |||
445 | 421 | ||
446 | static void intel_crt_destroy(struct drm_connector *connector) | 422 | static void intel_crt_destroy(struct drm_connector *connector) |
447 | { | 423 | { |
448 | struct intel_output *intel_output = to_intel_output(connector); | 424 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
449 | 425 | ||
450 | intel_i2c_destroy(intel_output->ddc_bus); | 426 | intel_i2c_destroy(intel_encoder->ddc_bus); |
451 | drm_sysfs_connector_remove(connector); | 427 | drm_sysfs_connector_remove(connector); |
452 | drm_connector_cleanup(connector); | 428 | drm_connector_cleanup(connector); |
453 | kfree(connector); | 429 | kfree(connector); |
@@ -456,28 +432,28 @@ static void intel_crt_destroy(struct drm_connector *connector) | |||
456 | static int intel_crt_get_modes(struct drm_connector *connector) | 432 | static int intel_crt_get_modes(struct drm_connector *connector) |
457 | { | 433 | { |
458 | int ret; | 434 | int ret; |
459 | struct intel_output *intel_output = to_intel_output(connector); | 435 | struct intel_encoder *intel_encoder = to_intel_encoder(connector); |
460 | struct i2c_adapter *ddcbus; | 436 | struct i2c_adapter *ddcbus; |
461 | struct drm_device *dev = connector->dev; | 437 | struct drm_device *dev = connector->dev; |
462 | 438 | ||
463 | 439 | ||
464 | ret = intel_ddc_get_modes(intel_output); | 440 | ret = intel_ddc_get_modes(intel_encoder); |
465 | if (ret || !IS_G4X(dev)) | 441 | if (ret || !IS_G4X(dev)) |
466 | goto end; | 442 | goto end; |
467 | 443 | ||
468 | ddcbus = intel_output->ddc_bus; | 444 | ddcbus = intel_encoder->ddc_bus; |
469 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ | 445 | /* Try to probe digital port for output in DVI-I -> VGA mode. */ |
470 | intel_output->ddc_bus = | 446 | intel_encoder->ddc_bus = |
471 | intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); | 447 | intel_i2c_create(connector->dev, GPIOD, "CRTDDC_D"); |
472 | 448 | ||
473 | if (!intel_output->ddc_bus) { | 449 | if (!intel_encoder->ddc_bus) { |
474 | intel_output->ddc_bus = ddcbus; | 450 | intel_encoder->ddc_bus = ddcbus; |
475 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, | 451 | dev_printk(KERN_ERR, &connector->dev->pdev->dev, |
476 | "DDC bus registration failed for CRTDDC_D.\n"); | 452 | "DDC bus registration failed for CRTDDC_D.\n"); |
477 | goto end; | 453 | goto end; |
478 | } | 454 | } |
479 | /* Try to get modes by GPIOD port */ | 455 | /* Try to get modes by GPIOD port */ |
480 | ret = intel_ddc_get_modes(intel_output); | 456 | ret = intel_ddc_get_modes(intel_encoder); |
481 | intel_i2c_destroy(ddcbus); | 457 | intel_i2c_destroy(ddcbus); |
482 | 458 | ||
483 | end: | 459 | end: |
@@ -530,50 +506,52 @@ static const struct drm_encoder_funcs intel_crt_enc_funcs = { | |||
530 | void intel_crt_init(struct drm_device *dev) | 506 | void intel_crt_init(struct drm_device *dev) |
531 | { | 507 | { |
532 | struct drm_connector *connector; | 508 | struct drm_connector *connector; |
533 | struct intel_output *intel_output; | 509 | struct intel_encoder *intel_encoder; |
534 | struct drm_i915_private *dev_priv = dev->dev_private; | 510 | struct drm_i915_private *dev_priv = dev->dev_private; |
535 | u32 i2c_reg; | 511 | u32 i2c_reg; |
536 | 512 | ||
537 | intel_output = kzalloc(sizeof(struct intel_output), GFP_KERNEL); | 513 | intel_encoder = kzalloc(sizeof(struct intel_encoder), GFP_KERNEL); |
538 | if (!intel_output) | 514 | if (!intel_encoder) |
539 | return; | 515 | return; |
540 | 516 | ||
541 | connector = &intel_output->base; | 517 | connector = &intel_encoder->base; |
542 | drm_connector_init(dev, &intel_output->base, | 518 | drm_connector_init(dev, &intel_encoder->base, |
543 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); | 519 | &intel_crt_connector_funcs, DRM_MODE_CONNECTOR_VGA); |
544 | 520 | ||
545 | drm_encoder_init(dev, &intel_output->enc, &intel_crt_enc_funcs, | 521 | drm_encoder_init(dev, &intel_encoder->enc, &intel_crt_enc_funcs, |
546 | DRM_MODE_ENCODER_DAC); | 522 | DRM_MODE_ENCODER_DAC); |
547 | 523 | ||
548 | drm_mode_connector_attach_encoder(&intel_output->base, | 524 | drm_mode_connector_attach_encoder(&intel_encoder->base, |
549 | &intel_output->enc); | 525 | &intel_encoder->enc); |
550 | 526 | ||
551 | /* Set up the DDC bus. */ | 527 | /* Set up the DDC bus. */ |
552 | if (IS_IGDNG(dev)) | 528 | if (HAS_PCH_SPLIT(dev)) |
553 | i2c_reg = PCH_GPIOA; | 529 | i2c_reg = PCH_GPIOA; |
554 | else { | 530 | else { |
555 | i2c_reg = GPIOA; | 531 | i2c_reg = GPIOA; |
556 | /* Use VBT information for CRT DDC if available */ | 532 | /* Use VBT information for CRT DDC if available */ |
557 | if (dev_priv->crt_ddc_bus != -1) | 533 | if (dev_priv->crt_ddc_bus != 0) |
558 | i2c_reg = dev_priv->crt_ddc_bus; | 534 | i2c_reg = dev_priv->crt_ddc_bus; |
559 | } | 535 | } |
560 | intel_output->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); | 536 | intel_encoder->ddc_bus = intel_i2c_create(dev, i2c_reg, "CRTDDC_A"); |
561 | if (!intel_output->ddc_bus) { | 537 | if (!intel_encoder->ddc_bus) { |
562 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " | 538 | dev_printk(KERN_ERR, &dev->pdev->dev, "DDC bus registration " |
563 | "failed.\n"); | 539 | "failed.\n"); |
564 | return; | 540 | return; |
565 | } | 541 | } |
566 | 542 | ||
567 | intel_output->type = INTEL_OUTPUT_ANALOG; | 543 | intel_encoder->type = INTEL_OUTPUT_ANALOG; |
568 | intel_output->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | | 544 | intel_encoder->clone_mask = (1 << INTEL_SDVO_NON_TV_CLONE_BIT) | |
569 | (1 << INTEL_ANALOG_CLONE_BIT) | | 545 | (1 << INTEL_ANALOG_CLONE_BIT) | |
570 | (1 << INTEL_SDVO_LVDS_CLONE_BIT); | 546 | (1 << INTEL_SDVO_LVDS_CLONE_BIT); |
571 | intel_output->crtc_mask = (1 << 0) | (1 << 1); | 547 | intel_encoder->crtc_mask = (1 << 0) | (1 << 1); |
572 | connector->interlace_allowed = 0; | 548 | connector->interlace_allowed = 0; |
573 | connector->doublescan_allowed = 0; | 549 | connector->doublescan_allowed = 0; |
574 | 550 | ||
575 | drm_encoder_helper_add(&intel_output->enc, &intel_crt_helper_funcs); | 551 | drm_encoder_helper_add(&intel_encoder->enc, &intel_crt_helper_funcs); |
576 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); | 552 | drm_connector_helper_add(connector, &intel_crt_connector_helper_funcs); |
577 | 553 | ||
578 | drm_sysfs_connector_add(connector); | 554 | drm_sysfs_connector_add(connector); |
555 | |||
556 | dev_priv->hotplug_supported_mask |= CRT_HOTPLUG_INT_STATUS; | ||
579 | } | 557 | } |