Commit 5715f67c authored by Rafał Miłecki's avatar Rafał Miłecki Committed by Dave Airlie

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: default avatarRafał Miłecki <zajec5@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent 2cd6218c
......@@ -417,6 +417,39 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
}
static int r600_hdmi_find_free_block(struct drm_device *dev)
{
struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *encoder;
struct radeon_encoder *radeon_encoder;
bool free_blocks[3] = { true, true, true };
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
radeon_encoder = to_radeon_encoder(encoder);
switch (radeon_encoder->hdmi_offset) {
case R600_HDMI_BLOCK1:
free_blocks[0] = false;
break;
case R600_HDMI_BLOCK2:
free_blocks[1] = false;
break;
case R600_HDMI_BLOCK3:
free_blocks[2] = false;
break;
}
}
if (rdev->family == CHIP_RS600 || rdev->family == CHIP_RS690) {
return free_blocks[0] ? R600_HDMI_BLOCK1 : 0;
} else if (rdev->family >= CHIP_R600) {
if (free_blocks[0])
return R600_HDMI_BLOCK1;
else if (free_blocks[1])
return R600_HDMI_BLOCK2;
}
return 0;
}
static void r600_hdmi_assign_block(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
......@@ -437,6 +470,8 @@ static void r600_hdmi_assign_block(struct drm_encoder *encoder)
if (ASIC_IS_DCE32(rdev))
radeon_encoder->hdmi_config_offset = dig->dig_encoder ?
R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1;
} else if (rdev->family >= CHIP_R600) {
radeon_encoder->hdmi_offset = r600_hdmi_find_free_block(dev);
}
}
......@@ -458,8 +493,24 @@ void r600_hdmi_enable(struct drm_encoder *encoder)
}
}
if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev))
if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);
} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
int offset = radeon_encoder->hdmi_offset;
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
WREG32_P(AVIVO_TMDSA_CNTL, 0x4, ~0x4);
WREG32(offset + R600_HDMI_ENABLE, 0x101);
break;
case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
WREG32_P(AVIVO_LVTMA_CNTL, 0x4, ~0x4);
WREG32(offset + R600_HDMI_ENABLE, 0x105);
break;
default:
dev_err(rdev->dev, "Unknown HDMI output type\n");
break;
}
}
DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
......@@ -482,8 +533,24 @@ void r600_hdmi_disable(struct drm_encoder *encoder)
DRM_DEBUG("Disabling HDMI interface @ 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev))
if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev)) {
WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);
} else if (rdev->family >= CHIP_R600 && !ASIC_IS_DCE3(rdev)) {
int offset = radeon_encoder->hdmi_offset;
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
WREG32_P(AVIVO_TMDSA_CNTL, 0, ~0x4);
WREG32(offset + R600_HDMI_ENABLE, 0);
break;
case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
WREG32_P(AVIVO_LVTMA_CNTL, 0, ~0x4);
WREG32(offset + R600_HDMI_ENABLE, 0);
break;
default:
dev_err(rdev->dev, "Unknown HDMI output type\n");
break;
}
}
radeon_encoder->hdmi_offset = 0;
radeon_encoder->hdmi_config_offset = 0;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment