aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRafał Miłecki <zajec5@gmail.com>2010-03-06 08:03:35 -0500
committerDave Airlie <airlied@redhat.com>2010-03-14 20:04:47 -0400
commit5715f67cecee3617c7a6ff84ee44da46d525559e (patch)
treebdcb730a149151434fc9a9b1c827447747595dce
parent2cd6218cb8043ef4360b561e726cd081f8a380cc (diff)
drm/radeon/kms: add HDMI code for pre-DCE3 R6xx GPUs
Older GPUs are little different, HDMI blocks are not hard-wired, but routable. We should just find some free HDMI block and route it to choosen encoder. In case of RS6x0 there is only one HDMI block, we don't enable HDMI on RS6x00 yet however. Signed-off-by: Rafał Miłecki <zajec5@gmail.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
-rw-r--r--drivers/gpu/drm/radeon/r600_hdmi.c71
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 5275a81b1df..8fbfc73170f 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
420static 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
420static void r600_hdmi_assign_block(struct drm_encoder *encoder) 453static 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;