aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/radeon/r600_hdmi.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 22:40:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2013-05-02 22:40:34 -0400
commit20a2078ce7705a6e0722ef5184336eb8657a58d8 (patch)
tree5b927c96516380aa0ecd68d8a609f7cd72120ad5 /drivers/gpu/drm/radeon/r600_hdmi.c
parent0279b3c0ada1d78882f24acf94ac4595bd657a89 (diff)
parent307b9c022720f9de90d58e51743e01e9a42aec59 (diff)
Merge branch 'drm-next' of git://people.freedesktop.org/~airlied/linux
Pull drm updates from Dave Airlie: "This is the main drm pull request for 3.10. Wierd bits: - OMAP drm changes required OMAP dss changes, in drivers/video, so I took them in here. - one more fbcon fix for font handover - VT switch avoidance in pm code - scatterlist helpers for gpu drivers - have acks from akpm Highlights: - qxl kms driver - driver for the spice qxl virtual GPU Nouveau: - fermi/kepler VRAM compression - GK110/nvf0 modesetting support. Tegra: - host1x core merged with 2D engine support i915: - vt switchless resume - more valleyview support - vblank fixes - modesetting pipe config rework radeon: - UVD engine support - SI chip tiling support - GPU registers initialisation from golden values. exynos: - device tree changes - fimc block support Otherwise: - bunches of fixes all over the place." * 'drm-next' of git://people.freedesktop.org/~airlied/linux: (513 commits) qxl: update to new idr interfaces. drm/nouveau: fix build with nv50->nvc0 drm/radeon: fix handling of v6 power tables drm/radeon: clarify family checks in pm table parsing drm/radeon: consolidate UVD clock programming drm/radeon: fix UPLL_REF_DIV_MASK definition radeon: add bo tracking debugfs drm/radeon: add new richland pci ids drm/radeon: add some new SI PCI ids drm/radeon: fix scratch reg handling for UVD fence drm/radeon: allocate SA bo in the requested domain drm/radeon: fix possible segfault when parsing pm tables drm/radeon: fix endian bugs in atom_allocate_fb_scratch() OMAPDSS: TFP410: return EPROBE_DEFER if the i2c adapter not found OMAPDSS: VENC: Add error handling for venc_probe_pdata OMAPDSS: HDMI: Add error handling for hdmi_probe_pdata OMAPDSS: RFBI: Add error handling for rfbi_probe_pdata OMAPDSS: DSI: Add error handling for dsi_probe_pdata OMAPDSS: SDI: Add error handling for sdi_probe_pdata OMAPDSS: DPI: Add error handling for dpi_probe_pdata ...
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_hdmi.c')
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c150
1 files changed, 71 insertions, 79 deletions
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c
index 21ecc0e12dc4..47f180a79352 100644
--- a/drivers/gpu/drm/radeon/r600_hdmi.c
+++ b/drivers/gpu/drm/radeon/r600_hdmi.c
@@ -226,6 +226,39 @@ static void r600_hdmi_audio_workaround(struct drm_encoder *encoder)
226 value, ~HDMI0_AUDIO_TEST_EN); 226 value, ~HDMI0_AUDIO_TEST_EN);
227} 227}
228 228
229void r600_audio_set_dto(struct drm_encoder *encoder, u32 clock)
230{
231 struct drm_device *dev = encoder->dev;
232 struct radeon_device *rdev = dev->dev_private;
233 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
234 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
235 u32 base_rate = 48000;
236
237 if (!dig || !dig->afmt)
238 return;
239
240 /* there are two DTOs selected by DCCG_AUDIO_DTO_SELECT.
241 * doesn't matter which one you use. Just use the first one.
242 */
243 /* XXX: properly calculate this */
244 /* XXX two dtos; generally use dto0 for hdmi */
245 /* Express [24MHz / target pixel clock] as an exact rational
246 * number (coefficient of two integer numbers. DCCG_AUDIO_DTOx_PHASE
247 * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator
248 */
249 if (ASIC_IS_DCE3(rdev)) {
250 /* according to the reg specs, this should DCE3.2 only, but in
251 * practice it seems to cover DCE3.0 as well.
252 */
253 WREG32(DCCG_AUDIO_DTO0_PHASE, base_rate * 50);
254 WREG32(DCCG_AUDIO_DTO0_MODULE, clock * 100);
255 WREG32(DCCG_AUDIO_DTO_SELECT, 0); /* select DTO0 */
256 } else {
257 /* according to the reg specs, this should be DCE2.0 and DCE3.0 */
258 WREG32(AUDIO_DTO, AUDIO_DTO_PHASE(base_rate * 50) |
259 AUDIO_DTO_MODULE(clock * 100));
260 }
261}
229 262
230/* 263/*
231 * update the info frames with the data from the current display mode 264 * update the info frames with the data from the current display mode
@@ -246,7 +279,7 @@ void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mod
246 return; 279 return;
247 offset = dig->afmt->offset; 280 offset = dig->afmt->offset;
248 281
249 r600_audio_set_clock(encoder, mode->clock); 282 r600_audio_set_dto(encoder, mode->clock);
250 283
251 WREG32(HDMI0_VBI_PACKET_CONTROL + offset, 284 WREG32(HDMI0_VBI_PACKET_CONTROL + offset,
252 HDMI0_NULL_SEND); /* send null packets when required */ 285 HDMI0_NULL_SEND); /* send null packets when required */
@@ -415,114 +448,73 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder)
415/* 448/*
416 * enable the HDMI engine 449 * enable the HDMI engine
417 */ 450 */
418void r600_hdmi_enable(struct drm_encoder *encoder) 451void r600_hdmi_enable(struct drm_encoder *encoder, bool enable)
419{ 452{
420 struct drm_device *dev = encoder->dev; 453 struct drm_device *dev = encoder->dev;
421 struct radeon_device *rdev = dev->dev_private; 454 struct radeon_device *rdev = dev->dev_private;
422 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); 455 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
423 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; 456 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
424 uint32_t offset; 457 u32 hdmi = HDMI0_ERROR_ACK;
425 u32 hdmi;
426
427 if (ASIC_IS_DCE6(rdev))
428 return;
429 458
430 /* Silent, r600_hdmi_enable will raise WARN for us */ 459 /* Silent, r600_hdmi_enable will raise WARN for us */
431 if (dig->afmt->enabled) 460 if (enable && dig->afmt->enabled)
461 return;
462 if (!enable && !dig->afmt->enabled)
432 return; 463 return;
433 offset = dig->afmt->offset;
434 464
435 /* Older chipsets require setting HDMI and routing manually */ 465 /* Older chipsets require setting HDMI and routing manually */
436 if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { 466 if (!ASIC_IS_DCE3(rdev)) {
437 hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE; 467 if (enable)
468 hdmi |= HDMI0_ENABLE;
438 switch (radeon_encoder->encoder_id) { 469 switch (radeon_encoder->encoder_id) {
439 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: 470 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
440 WREG32_P(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN, 471 if (enable) {
441 ~AVIVO_TMDSA_CNTL_HDMI_EN); 472 WREG32_OR(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN);
442 hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA); 473 hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA);
474 } else {
475 WREG32_AND(AVIVO_TMDSA_CNTL, ~AVIVO_TMDSA_CNTL_HDMI_EN);
476 }
443 break; 477 break;
444 case ENCODER_OBJECT_ID_INTERNAL_LVTM1: 478 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
445 WREG32_P(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN, 479 if (enable) {
446 ~AVIVO_LVTMA_CNTL_HDMI_EN); 480 WREG32_OR(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN);
447 hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA); 481 hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA);
482 } else {
483 WREG32_AND(AVIVO_LVTMA_CNTL, ~AVIVO_LVTMA_CNTL_HDMI_EN);
484 }
448 break; 485 break;
449 case ENCODER_OBJECT_ID_INTERNAL_DDI: 486 case ENCODER_OBJECT_ID_INTERNAL_DDI:
450 WREG32_P(DDIA_CNTL, DDIA_HDMI_EN, ~DDIA_HDMI_EN); 487 if (enable) {
451 hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA); 488 WREG32_OR(DDIA_CNTL, DDIA_HDMI_EN);
489 hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA);
490 } else {
491 WREG32_AND(DDIA_CNTL, ~DDIA_HDMI_EN);
492 }
452 break; 493 break;
453 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: 494 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
454 hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA); 495 if (enable)
496 hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA);
455 break; 497 break;
456 default: 498 default:
457 dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", 499 dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
458 radeon_encoder->encoder_id); 500 radeon_encoder->encoder_id);
459 break; 501 break;
460 } 502 }
461 WREG32(HDMI0_CONTROL + offset, hdmi); 503 WREG32(HDMI0_CONTROL + dig->afmt->offset, hdmi);
462 } 504 }
463 505
464 if (rdev->irq.installed) { 506 if (rdev->irq.installed) {
465 /* if irq is available use it */ 507 /* if irq is available use it */
466 radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); 508 /* XXX: shouldn't need this on any asics. Double check DCE2/3 */
509 if (enable)
510 radeon_irq_kms_enable_afmt(rdev, dig->afmt->id);
511 else
512 radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
467 } 513 }
468 514
469 dig->afmt->enabled = true; 515 dig->afmt->enabled = enable;
470 516
471 DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", 517 DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n",
472 offset, radeon_encoder->encoder_id); 518 enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id);
473} 519}
474 520
475/*
476 * disable the HDMI engine
477 */
478void r600_hdmi_disable(struct drm_encoder *encoder)
479{
480 struct drm_device *dev = encoder->dev;
481 struct radeon_device *rdev = dev->dev_private;
482 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
483 struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
484 uint32_t offset;
485
486 if (ASIC_IS_DCE6(rdev))
487 return;
488
489 /* Called for ATOM_ENCODER_MODE_HDMI only */
490 if (!dig || !dig->afmt) {
491 return;
492 }
493 if (!dig->afmt->enabled)
494 return;
495 offset = dig->afmt->offset;
496
497 DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
498 offset, radeon_encoder->encoder_id);
499
500 /* disable irq */
501 radeon_irq_kms_disable_afmt(rdev, dig->afmt->id);
502
503 /* Older chipsets not handled by AtomBIOS */
504 if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
505 switch (radeon_encoder->encoder_id) {
506 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
507 WREG32_P(AVIVO_TMDSA_CNTL, 0,
508 ~AVIVO_TMDSA_CNTL_HDMI_EN);
509 break;
510 case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
511 WREG32_P(AVIVO_LVTMA_CNTL, 0,
512 ~AVIVO_LVTMA_CNTL_HDMI_EN);
513 break;
514 case ENCODER_OBJECT_ID_INTERNAL_DDI:
515 WREG32_P(DDIA_CNTL, 0, ~DDIA_HDMI_EN);
516 break;
517 case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1:
518 break;
519 default:
520 dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n",
521 radeon_encoder->encoder_id);
522 break;
523 }
524 WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK);
525 }
526
527 dig->afmt->enabled = false;
528}