Skip to content

Commit

Permalink
drm/radeon/kms: clean assigning HDMI blocks to encoders
Browse files Browse the repository at this point in the history
We almost always used first HDMI block for first encoder and second for sencod.
Exception was KLDSCP_LVTMA. Analyzing code picking DIG encoder shows the same
behaviour. It shows HDMI block are related to DIGs, which relation we now use.

Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
  • Loading branch information
Rafał Miłecki authored and Dave Airlie committed Mar 15, 2010
1 parent 808032e commit 2cd6218
Show file tree
Hide file tree
Showing 4 changed files with 62 additions and 72 deletions.
7 changes: 6 additions & 1 deletion drivers/gpu/drm/radeon/r600_audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
int base_rate = 48000;

switch (radeon_encoder->encoder_id) {
Expand All @@ -245,7 +246,7 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
return;
}

switch (r600_audio_tmds_index(encoder)) {
switch (dig->dig_encoder) {
case 0:
WREG32(R600_AUDIO_PLL1_MUL, base_rate*50);
WREG32(R600_AUDIO_PLL1_DIV, clock*100);
Expand All @@ -257,6 +258,10 @@ void r600_audio_set_clock(struct drm_encoder *encoder, int clock)
WREG32(R600_AUDIO_PLL2_DIV, clock*100);
WREG32(R600_AUDIO_CLK_SRCSEL, 1);
break;
default:
dev_err(rdev->dev, "Unsupported DIG on encoder 0x%02X\n",
radeon_encoder->encoder_id);
return;
}
}

Expand Down
114 changes: 49 additions & 65 deletions drivers/gpu/drm/radeon/r600_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -417,90 +417,74 @@ void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
WREG32_P(offset+R600_HDMI_CNTL, 0x04000000, ~0x04000000);
}

/*
* enable/disable the HDMI engine
*/
void r600_hdmi_enable(struct drm_encoder *encoder, int enable)
static void r600_hdmi_assign_block(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
uint32_t offset = to_radeon_encoder(encoder)->hdmi_offset;
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;

if (!offset)
if (!dig) {
dev_err(rdev->dev, "Enabling HDMI on non-dig encoder\n");
return;
}

DRM_DEBUG("%s HDMI interface @ 0x%04X\n", enable ? "Enabling" : "Disabling", offset);

/* some version of atombios ignore the enable HDMI flag
* so enabling/disabling HDMI was moved here for TMDS1+2 */
switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
WREG32_P(AVIVO_TMDSA_CNTL, enable ? 0x4 : 0x0, ~0x4);
WREG32(offset+R600_HDMI_ENABLE, enable ? 0x101 : 0x0);
break;

case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
WREG32_P(AVIVO_LVTMA_CNTL, enable ? 0x4 : 0x0, ~0x4);
WREG32(offset+R600_HDMI_ENABLE, enable ? 0x105 : 0x0);
break;

case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
/* This part is doubtfull in my opinion */
WREG32(offset+R600_HDMI_ENABLE, enable ? 0x110 : 0x0);
break;

default:
DRM_ERROR("unknown HDMI output type\n");
break;
if (ASIC_IS_DCE4(rdev)) {
/* TODO */
} else if (ASIC_IS_DCE3(rdev)) {
radeon_encoder->hdmi_offset = dig->dig_encoder ?
R600_HDMI_BLOCK3 : R600_HDMI_BLOCK1;
if (ASIC_IS_DCE32(rdev))
radeon_encoder->hdmi_config_offset = dig->dig_encoder ?
R600_HDMI_CONFIG2 : R600_HDMI_CONFIG1;
}
}

/*
* determin at which register offset the HDMI encoder is
* enable the HDMI engine
*/
void r600_hdmi_init(struct drm_encoder *encoder)
void r600_hdmi_enable(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);

switch (radeon_encoder->encoder_id) {
case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1;
break;

case ENCODER_OBJECT_ID_INTERNAL_LVTM1:
switch (r600_audio_tmds_index(encoder)) {
case 0:
radeon_encoder->hdmi_offset = R600_HDMI_BLOCK1;
break;
case 1:
radeon_encoder->hdmi_offset = R600_HDMI_BLOCK2;
break;
default:
radeon_encoder->hdmi_offset = 0;
break;
if (!radeon_encoder->hdmi_offset) {
r600_hdmi_assign_block(encoder);
if (!radeon_encoder->hdmi_offset) {
dev_warn(rdev->dev, "Could not find HDMI block for "
"0x%x encoder\n", radeon_encoder->encoder_id);
return;
}
case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
radeon_encoder->hdmi_offset = R600_HDMI_BLOCK2;
break;
}

case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
radeon_encoder->hdmi_offset = R600_HDMI_BLOCK3;
break;
if (ASIC_IS_DCE32(rdev) && !ASIC_IS_DCE4(rdev))
WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0x1, ~0x1);

DRM_DEBUG("Enabling HDMI interface @ 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
}

default:
radeon_encoder->hdmi_offset = 0;
break;
/*
* disable the HDMI engine
*/
void r600_hdmi_disable(struct drm_encoder *encoder)
{
struct drm_device *dev = encoder->dev;
struct radeon_device *rdev = dev->dev_private;
struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);

if (!radeon_encoder->hdmi_offset) {
dev_err(rdev->dev, "Disabling not enabled HDMI\n");
return;
}

DRM_DEBUG("using HDMI engine at offset 0x%04X for encoder 0x%x\n",
radeon_encoder->hdmi_offset, radeon_encoder->encoder_id);
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))
WREG32_P(radeon_encoder->hdmi_config_offset + 0x4, 0, ~0x1);

/* TODO: make this configureable */
radeon_encoder->hdmi_audio_workaround = 0;
radeon_encoder->hdmi_offset = 0;
radeon_encoder->hdmi_config_offset = 0;
}
3 changes: 2 additions & 1 deletion drivers/gpu/drm/radeon/radeon.h
Original file line number Diff line number Diff line change
Expand Up @@ -1322,7 +1322,8 @@ extern int r600_audio_tmds_index(struct drm_encoder *encoder);
extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock);
extern void r600_audio_fini(struct radeon_device *rdev);
extern void r600_hdmi_init(struct drm_encoder *encoder);
extern void r600_hdmi_enable(struct drm_encoder *encoder, int enable);
extern void r600_hdmi_enable(struct drm_encoder *encoder);
extern void r600_hdmi_disable(struct drm_encoder *encoder);
extern void r600_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode *mode);
extern int r600_hdmi_buffer_status_changed(struct drm_encoder *encoder);
extern void r600_hdmi_update_audio_settings(struct drm_encoder *encoder,
Expand Down
10 changes: 5 additions & 5 deletions drivers/gpu/drm/radeon/radeon_encoders.c
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,6 @@ atombios_digital_setup(struct drm_encoder *encoder, int action)
}

atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
r600_hdmi_enable(encoder, hdmi_detected);
}

int
Expand Down Expand Up @@ -1389,9 +1388,10 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
}
atombios_apply_encoder_quirks(encoder, adjusted_mode);

/* XXX */
if (!ASIC_IS_DCE4(rdev))
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
r600_hdmi_enable(encoder);
r600_hdmi_setmode(encoder, adjusted_mode);
}
}

static bool
Expand Down Expand Up @@ -1514,6 +1514,8 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);

if (radeon_encoder_is_digital(encoder)) {
if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI)
r600_hdmi_disable(encoder);
dig = radeon_encoder->enc_priv;
dig->dig_encoder = -1;
}
Expand Down Expand Up @@ -1664,6 +1666,4 @@ radeon_add_atom_encoder(struct drm_device *dev, uint32_t encoder_id, uint32_t su
drm_encoder_helper_add(encoder, &radeon_atom_dig_helper_funcs);
break;
}

r600_hdmi_init(encoder);
}

0 comments on commit 2cd6218

Please sign in to comment.