diff options
Diffstat (limited to 'drivers/gpu/drm/radeon/evergreen_hdmi.c')
| -rw-r--r-- | drivers/gpu/drm/radeon/evergreen_hdmi.c | 74 |
1 files changed, 60 insertions, 14 deletions
diff --git a/drivers/gpu/drm/radeon/evergreen_hdmi.c b/drivers/gpu/drm/radeon/evergreen_hdmi.c index 0c6d5cef4cf..1ec0e6e83f9 100644 --- a/drivers/gpu/drm/radeon/evergreen_hdmi.c +++ b/drivers/gpu/drm/radeon/evergreen_hdmi.c @@ -293,10 +293,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode 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; + struct drm_connector *connector = radeon_get_connector_for_encoder(encoder); u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_AVI_INFOFRAME_SIZE]; struct hdmi_avi_infoframe frame; uint32_t offset; ssize_t err; + uint32_t val; + int bpc = 8; if (!dig || !dig->afmt) return; @@ -306,6 +309,21 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode return; offset = dig->afmt->offset; + /* hdmi deep color mode general control packets setup, if bpc > 8 */ + if (encoder->crtc) { + struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc); + bpc = radeon_crtc->bpc; + } + + /* disable audio prior to setting up hw */ + if (ASIC_IS_DCE6(rdev)) { + dig->afmt->pin = dce6_audio_get_pin(rdev); + dce6_audio_enable(rdev, dig->afmt->pin, false); + } else { + dig->afmt->pin = r600_audio_get_pin(rdev); + r600_audio_enable(rdev, dig->afmt->pin, false); + } + evergreen_audio_set_dto(encoder, mode->clock); WREG32(HDMI_VBI_PACKET_CONTROL + offset, @@ -313,6 +331,35 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode WREG32(AFMT_AUDIO_CRC_CONTROL + offset, 0x1000); + val = RREG32(HDMI_CONTROL + offset); + val &= ~HDMI_DEEP_COLOR_ENABLE; + val &= ~HDMI_DEEP_COLOR_DEPTH_MASK; + + switch (bpc) { + case 0: + case 6: + case 8: + case 16: + default: + DRM_DEBUG("%s: Disabling hdmi deep color for %d bpc.\n", + connector->name, bpc); + break; + case 10: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_30BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 30 for 10 bpc.\n", + connector->name); + break; + case 12: + val |= HDMI_DEEP_COLOR_ENABLE; + val |= HDMI_DEEP_COLOR_DEPTH(HDMI_36BIT_DEEP_COLOR); + DRM_DEBUG("%s: Enabling hdmi deep color 36 for 12 bpc.\n", + connector->name); + break; + } + + WREG32(HDMI_CONTROL + offset, val); + WREG32(HDMI_VBI_PACKET_CONTROL + offset, HDMI_NULL_SEND | /* send null packets when required */ HDMI_GC_SEND | /* send general control packets */ @@ -339,9 +386,13 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode /* fglrx clears sth in AFMT_AUDIO_PACKET_CONTROL2 here */ - WREG32(HDMI_ACR_PACKET_CONTROL + offset, - HDMI_ACR_SOURCE | /* select SW CTS value */ - HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + if (bpc > 8) + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ + else + WREG32(HDMI_ACR_PACKET_CONTROL + offset, + HDMI_ACR_SOURCE | /* select SW CTS value */ + HDMI_ACR_AUTO_SEND); /* allow hw to sent ACR packets when required */ evergreen_hdmi_update_ACR(encoder, mode->clock); @@ -409,12 +460,16 @@ void evergreen_hdmi_setmode(struct drm_encoder *encoder, struct drm_display_mode WREG32(AFMT_RAMP_CONTROL1 + offset, 0x007FFFFF); WREG32(AFMT_RAMP_CONTROL2 + offset, 0x00000001); WREG32(AFMT_RAMP_CONTROL3 + offset, 0x00000001); + + /* enable audio after to setting up hw */ + if (ASIC_IS_DCE6(rdev)) + dce6_audio_enable(rdev, dig->afmt->pin, true); + else + r600_audio_enable(rdev, dig->afmt->pin, true); } void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) { - 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; @@ -427,15 +482,6 @@ void evergreen_hdmi_enable(struct drm_encoder *encoder, bool enable) if (!enable && !dig->afmt->enabled) return; - if (enable) { - if (ASIC_IS_DCE6(rdev)) - dig->afmt->pin = dce6_audio_get_pin(rdev); - else - dig->afmt->pin = r600_audio_get_pin(rdev); - } else { - dig->afmt->pin = NULL; - } - dig->afmt->enabled = enable; DRM_DEBUG("%sabling HDMI interface @ 0x%04X for encoder 0x%x\n", |
