diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-04-18 11:32:16 -0400 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-04-23 18:03:53 -0400 |
commit | a973bea11c91bf8283cc13eb17d3ef7086f679d6 (patch) | |
tree | 8f406b2083834344788d539c0b8c9498c64da544 /drivers/gpu/drm/radeon/r600_hdmi.c | |
parent | b1f6f47e3e33c4a74534f1301aca241ffabbb3a0 (diff) |
drm/radeon: switch audio handling to use callbacks
Register audio callbacks for asic where we support
audio. Cleans up the code and makes it easier to
add support for newer asics.
Reviewed-by: Christian König <christian.koenig@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Diffstat (limited to 'drivers/gpu/drm/radeon/r600_hdmi.c')
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 109 |
1 files changed, 35 insertions, 74 deletions
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 62721bfabe77..2e15888d8307 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -439,112 +439,73 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder) | |||
439 | /* | 439 | /* |
440 | * enable the HDMI engine | 440 | * enable the HDMI engine |
441 | */ | 441 | */ |
442 | void r600_hdmi_enable(struct drm_encoder *encoder) | 442 | void r600_hdmi_enable(struct drm_encoder *encoder, bool enable) |
443 | { | 443 | { |
444 | struct drm_device *dev = encoder->dev; | 444 | struct drm_device *dev = encoder->dev; |
445 | struct radeon_device *rdev = dev->dev_private; | 445 | struct radeon_device *rdev = dev->dev_private; |
446 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 446 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
447 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | 447 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; |
448 | uint32_t offset; | 448 | u32 hdmi = HDMI0_ERROR_ACK; |
449 | u32 hdmi; | ||
450 | |||
451 | if (ASIC_IS_DCE6(rdev)) | ||
452 | return; | ||
453 | 449 | ||
454 | /* Silent, r600_hdmi_enable will raise WARN for us */ | 450 | /* Silent, r600_hdmi_enable will raise WARN for us */ |
455 | if (dig->afmt->enabled) | 451 | if (enable && dig->afmt->enabled) |
452 | return; | ||
453 | if (!enable && !dig->afmt->enabled) | ||
456 | return; | 454 | return; |
457 | offset = dig->afmt->offset; | ||
458 | 455 | ||
459 | /* Older chipsets require setting HDMI and routing manually */ | 456 | /* Older chipsets require setting HDMI and routing manually */ |
460 | if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) { | 457 | if (!ASIC_IS_DCE3(rdev)) { |
461 | hdmi = HDMI0_ERROR_ACK | HDMI0_ENABLE; | 458 | if (enable) |
459 | hdmi |= HDMI0_ENABLE; | ||
462 | switch (radeon_encoder->encoder_id) { | 460 | switch (radeon_encoder->encoder_id) { |
463 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | 461 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: |
464 | WREG32_OR(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN); | 462 | if (enable) { |
465 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA); | 463 | WREG32_OR(AVIVO_TMDSA_CNTL, AVIVO_TMDSA_CNTL_HDMI_EN); |
464 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_TMDSA); | ||
465 | } else { | ||
466 | WREG32_AND(AVIVO_TMDSA_CNTL, ~AVIVO_TMDSA_CNTL_HDMI_EN); | ||
467 | } | ||
466 | break; | 468 | break; |
467 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | 469 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: |
468 | WREG32_OR(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN); | 470 | if (enable) { |
469 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA); | 471 | WREG32_OR(AVIVO_LVTMA_CNTL, AVIVO_LVTMA_CNTL_HDMI_EN); |
472 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_LVTMA); | ||
473 | } else { | ||
474 | WREG32_AND(AVIVO_LVTMA_CNTL, ~AVIVO_LVTMA_CNTL_HDMI_EN); | ||
475 | } | ||
470 | break; | 476 | break; |
471 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | 477 | case ENCODER_OBJECT_ID_INTERNAL_DDI: |
472 | WREG32_OR(DDIA_CNTL, DDIA_HDMI_EN); | 478 | if (enable) { |
473 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA); | 479 | WREG32_OR(DDIA_CNTL, DDIA_HDMI_EN); |
480 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_DDIA); | ||
481 | } else { | ||
482 | WREG32_AND(DDIA_CNTL, ~DDIA_HDMI_EN); | ||
483 | } | ||
474 | break; | 484 | break; |
475 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | 485 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: |
476 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA); | 486 | if (enable) |
487 | hdmi |= HDMI0_STREAM(HDMI0_STREAM_DVOA); | ||
477 | break; | 488 | break; |
478 | default: | 489 | default: |
479 | dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", | 490 | dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", |
480 | radeon_encoder->encoder_id); | 491 | radeon_encoder->encoder_id); |
481 | break; | 492 | break; |
482 | } | 493 | } |
483 | WREG32(HDMI0_CONTROL + offset, hdmi); | 494 | WREG32(HDMI0_CONTROL + dig->afmt->offset, hdmi); |
484 | } | 495 | } |
485 | 496 | ||
486 | if (rdev->irq.installed) { | 497 | if (rdev->irq.installed) { |
487 | /* if irq is available use it */ | 498 | /* if irq is available use it */ |
488 | /* XXX: shouldn't need this on any asics. Double check DCE2/3 */ | 499 | /* XXX: shouldn't need this on any asics. Double check DCE2/3 */ |
489 | if (!ASIC_IS_DCE4(rdev)) | 500 | if (enable) |
490 | radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); | 501 | radeon_irq_kms_enable_afmt(rdev, dig->afmt->id); |
502 | else | ||
503 | radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); | ||
491 | } | 504 | } |
492 | 505 | ||
493 | dig->afmt->enabled = true; | 506 | dig->afmt->enabled = enable; |
494 | 507 | ||
495 | DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", | 508 | DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
496 | offset, radeon_encoder->encoder_id); | 509 | enable ? "En" : "Dis", dig->afmt->offset, radeon_encoder->encoder_id); |
497 | } | 510 | } |
498 | 511 | ||
499 | /* | ||
500 | * disable the HDMI engine | ||
501 | */ | ||
502 | void r600_hdmi_disable(struct drm_encoder *encoder) | ||
503 | { | ||
504 | struct drm_device *dev = encoder->dev; | ||
505 | struct radeon_device *rdev = dev->dev_private; | ||
506 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | ||
507 | struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; | ||
508 | uint32_t offset; | ||
509 | |||
510 | if (ASIC_IS_DCE6(rdev)) | ||
511 | return; | ||
512 | |||
513 | /* Called for ATOM_ENCODER_MODE_HDMI only */ | ||
514 | if (!dig || !dig->afmt) { | ||
515 | return; | ||
516 | } | ||
517 | if (!dig->afmt->enabled) | ||
518 | return; | ||
519 | offset = dig->afmt->offset; | ||
520 | |||
521 | DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", | ||
522 | offset, radeon_encoder->encoder_id); | ||
523 | |||
524 | /* disable irq */ | ||
525 | radeon_irq_kms_disable_afmt(rdev, dig->afmt->id); | ||
526 | |||
527 | /* Older chipsets not handled by AtomBIOS */ | ||
528 | if (ASIC_IS_DCE2(rdev) && !ASIC_IS_DCE3(rdev)) { | ||
529 | switch (radeon_encoder->encoder_id) { | ||
530 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
531 | WREG32_AND(AVIVO_TMDSA_CNTL, ~AVIVO_TMDSA_CNTL_HDMI_EN); | ||
532 | break; | ||
533 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
534 | WREG32_AND(AVIVO_LVTMA_CNTL, ~AVIVO_LVTMA_CNTL_HDMI_EN); | ||
535 | break; | ||
536 | case ENCODER_OBJECT_ID_INTERNAL_DDI: | ||
537 | WREG32_AND(DDIA_CNTL, ~DDIA_HDMI_EN); | ||
538 | break; | ||
539 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1: | ||
540 | break; | ||
541 | default: | ||
542 | dev_err(rdev->dev, "Invalid encoder for HDMI: 0x%X\n", | ||
543 | radeon_encoder->encoder_id); | ||
544 | break; | ||
545 | } | ||
546 | WREG32(HDMI0_CONTROL + offset, HDMI0_ERROR_ACK); | ||
547 | } | ||
548 | |||
549 | dig->afmt->enabled = false; | ||
550 | } | ||