diff options
-rw-r--r-- | drivers/gpu/drm/radeon/r600_hdmi.c | 71 |
1 files changed, 69 insertions, 2 deletions
diff --git a/drivers/gpu/drm/radeon/r600_hdmi.c b/drivers/gpu/drm/radeon/r600_hdmi.c index 5275a81b1df3..8fbfc73170fc 100644 --- a/drivers/gpu/drm/radeon/r600_hdmi.c +++ b/drivers/gpu/drm/radeon/r600_hdmi.c | |||
@@ -417,6 +417,39 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder, | |||
417 | WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); | 417 | WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000); |
418 | } | 418 | } |
419 | 419 | ||
420 | static int r600_hdmi_find_free_block(struct drm_device *dev) | ||
421 | { | ||
422 | struct radeon_device *rdev = dev->dev_private; | ||
423 | struct drm_encoder *encoder; | ||
424 | struct radeon_encoder *radeon_encoder; | ||
425 | bool free_blocks[3] = { true, true, true }; | ||
426 | |||
427 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
428 | radeon_encoder = to_radeon_encoder(encoder); | ||
429 | switch (radeon_encoder->hdmi_offset) { | ||
430 | case R600_HDMI_BLOCK1: | ||
431 | free_blocks[0] = false; | ||
432 | break; | ||
433 | case R600_HDMI_BLOCK2: | ||
434 | free_blocks[1] = false; | ||
435 | break; | ||
436 | case R600_HDMI_BLOCK3: | ||
437 | free_blocks[2] = false; | ||
438 | break; | ||
439 | } | ||
440 | } | ||
441 | |||
442 | if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690) { | ||
443 | return free_blocks[0] ? R600_HDMI_BLOCK1 : 0; | ||
444 | } else if (rdev->family >= CHIP_R600) { | ||
445 | if (free_blocks[0]) | ||
446 | return R600_HDMI_BLOCK1; | ||
447 | else if (free_blocks[1]) | ||
448 | return R600_HDMI_BLOCK2; | ||
449 | } | ||
450 | return 0; | ||
451 | } | ||
452 | |||
420 | static void r600_hdmi_assign_block(struct drm_encoder *encoder) | 453 | static void r600_hdmi_assign_block(struct drm_encoder *encoder) |
421 | { | 454 | { |
422 | struct drm_device *dev = encoder->dev; | 455 | struct drm_device *dev = encoder->dev; |
@@ -437,6 +470,8 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder) | |||
437 | if (ASIC_IS_DCE32(rdev)) | 470 | if (ASIC_IS_DCE32(rdev)) |
438 | radeon_encoder->hdmi_config_offset = dig->dig_encoder ? | 471 | radeon_encoder->hdmi_config_offset = dig->dig_encoder ? |
439 | R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1; | 472 | R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1; |
473 | } else if (rdev->family >= CHIP_R600) { | ||
474 | radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev); | ||
440 | } | 475 | } |
441 | } | 476 | } |
442 | 477 | ||
@@ -458,8 +493,24 @@ void r600_hdmi_enable(struct drm_encoder *encoder) | |||
458 | } | 493 | } |
459 | } | 494 | } |
460 | 495 | ||
461 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) | 496 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { |
462 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); | 497 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1); |
498 | } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | ||
499 | int offset = radeon_encoder->hdmi_offset; | ||
500 | switch (radeon_encoder->encoder_id) { | ||
501 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
502 | WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4); | ||
503 | WREG32(offset + R600_HDMI_ENABLE, 0x101); | ||
504 | break; | ||
505 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
506 | WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4); | ||
507 | WREG32(offset + R600_HDMI_ENABLE, 0x105); | ||
508 | break; | ||
509 | default: | ||
510 | dev_err(rdev->dev, "Unknown HDMI output type\n"); | ||
511 | break; | ||
512 | } | ||
513 | } | ||
463 | 514 | ||
464 | DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", | 515 | DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
465 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); | 516 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); |
@@ -482,8 +533,24 @@ void r600_hdmi_disable(struct drm_encoder *encoder) | |||
482 | DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", | 533 | DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
483 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); | 534 | radeon_encoder->hdmi_offset, radeon_encoder->encoder_id); |
484 | 535 | ||
485 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) | 536 | if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) { |
486 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); | 537 | WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1); |
538 | } else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) { | ||
539 | int offset = radeon_encoder->hdmi_offset; | ||
540 | switch (radeon_encoder->encoder_id) { | ||
541 | case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1: | ||
542 | WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4); | ||
543 | WREG32(offset + R600_HDMI_ENABLE, 0); | ||
544 | break; | ||
545 | case ENCODER_OBJECT_ID_INTERNAL_LVTM1: | ||
546 | WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4); | ||
547 | WREG32(offset + R600_HDMI_ENABLE, 0); | ||
548 | break; | ||
549 | default: | ||
550 | dev_err(rdev->dev, "Unknown HDMI output type\n"); | ||
551 | break; | ||
552 | } | ||
553 | } | ||
487 | 554 | ||
488 | radeon_encoder->hdmi_offset = 0; | 555 | radeon_encoder->hdmi_offset = 0; |
489 | radeon_encoder->hdmi_config_offset = 0; | 556 | radeon_encoder->hdmi_config_offset = 0; |