Commit f71d9ebd authored by Alex Deucher's avatar Alex Deucher

drm/radeon: fix pll setup for hdmi deep color (v7)

Need to adjust the pll up for deep color modes.
Additionally, the atom bpc defines were wrong in certain
cases.

v2: set the adjusted clock to the pll clock for hdmi deep
color.  This fixes display and audio issues with deep color
as reported by Andy Furniss <adf.lists@gmail.com>

v3: set crtc_clock as well

v4: setcrtcinfo on the adjusted mode

v5: just use the adjusted clock for setting the pll

v6: only use the adjusted clock for hdmi

v7: only DCE5 and DCE6 and bpc > 8
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 79766915
...@@ -559,6 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -559,6 +559,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
u32 adjusted_clock = mode->clock; u32 adjusted_clock = mode->clock;
int encoder_mode = atombios_get_encoder_mode(encoder); int encoder_mode = atombios_get_encoder_mode(encoder);
u32 dp_clock = mode->clock; u32 dp_clock = mode->clock;
u32 clock = mode->clock;
int bpc = radeon_crtc->bpc; int bpc = radeon_crtc->bpc;
bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock); bool is_duallink = radeon_dig_monitor_is_duallink(encoder, mode->clock);
...@@ -634,6 +635,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -634,6 +635,24 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV; radeon_crtc->pll_flags |= RADEON_PLL_USE_REF_DIV;
} }
/* adjust pll for deep color modes */
if (encoder_mode == ATOM_ENCODER_MODE_HDMI) {
switch (bpc) {
case 8:
default:
break;
case 10:
clock = (clock * 5) / 4;
break;
case 12:
clock = (clock * 3) / 2;
break;
case 16:
clock = clock * 2;
break;
}
}
/* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock /* DCE3+ has an AdjustDisplayPll that will adjust the pixel clock
* accordingly based on the encoder/transmitter to work around * accordingly based on the encoder/transmitter to work around
* special hw requirements. * special hw requirements.
...@@ -655,7 +674,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -655,7 +674,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
switch (crev) { switch (crev) {
case 1: case 1:
case 2: case 2:
args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); args.v1.usPixelClock = cpu_to_le16(clock / 10);
args.v1.ucTransmitterID = radeon_encoder->encoder_id; args.v1.ucTransmitterID = radeon_encoder->encoder_id;
args.v1.ucEncodeMode = encoder_mode; args.v1.ucEncodeMode = encoder_mode;
if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage) if (radeon_crtc->ss_enabled && radeon_crtc->ss.percentage)
...@@ -667,7 +686,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -667,7 +686,7 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
break; break;
case 3: case 3:
args.v3.sInput.usPixelClock = cpu_to_le16(mode->clock / 10); args.v3.sInput.usPixelClock = cpu_to_le16(clock / 10);
args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id; args.v3.sInput.ucTransmitterID = radeon_encoder->encoder_id;
args.v3.sInput.ucEncodeMode = encoder_mode; args.v3.sInput.ucEncodeMode = encoder_mode;
args.v3.sInput.ucDispPllConfig = 0; args.v3.sInput.ucDispPllConfig = 0;
...@@ -681,10 +700,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc, ...@@ -681,10 +700,6 @@ static u32 atombios_adjust_pll(struct drm_crtc *crtc,
args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10); args.v3.sInput.usPixelClock = cpu_to_le16(dp_clock / 10);
} else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) { } else if (radeon_encoder->devices & (ATOM_DEVICE_DFP_SUPPORT)) {
struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv; struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
if (encoder_mode == ATOM_ENCODER_MODE_HDMI)
/* deep color support */
args.v3.sInput.usPixelClock =
cpu_to_le16((mode->clock * bpc / 8) / 10);
if (dig->coherent_mode) if (dig->coherent_mode)
args.v3.sInput.ucDispPllConfig |= args.v3.sInput.ucDispPllConfig |=
DISPPLL_CONFIG_COHERENT_MODE; DISPPLL_CONFIG_COHERENT_MODE;
...@@ -871,6 +886,11 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, ...@@ -871,6 +886,11 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP; args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_24BPP;
break; break;
case 10: case 10:
/* yes this is correct, the atom define is wrong */
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_32BPP;
break;
case 12:
/* yes this is correct, the atom define is wrong */
args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP; args.v5.ucMiscInfo |= PIXEL_CLOCK_V5_MISC_HDMI_30BPP;
break; break;
} }
...@@ -895,10 +915,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc, ...@@ -895,10 +915,10 @@ static void atombios_crtc_program_pll(struct drm_crtc *crtc,
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP; args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_24BPP;
break; break;
case 10: case 10:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP; args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_30BPP_V6;
break; break;
case 12: case 12:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP; args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_36BPP_V6;
break; break;
case 16: case 16:
args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP; args.v6.ucMiscInfo |= PIXEL_CLOCK_V6_MISC_HDMI_48BPP;
...@@ -1025,10 +1045,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -1025,10 +1045,17 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
struct radeon_encoder *radeon_encoder = struct radeon_encoder *radeon_encoder =
to_radeon_encoder(radeon_crtc->encoder); to_radeon_encoder(radeon_crtc->encoder);
u32 pll_clock = mode->clock; u32 pll_clock = mode->clock;
u32 clock = mode->clock;
u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
struct radeon_pll *pll; struct radeon_pll *pll;
int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder); int encoder_mode = atombios_get_encoder_mode(radeon_crtc->encoder);
/* pass the actual clock to atombios_crtc_program_pll for DCE5,6 for HDMI */
if (ASIC_IS_DCE5(rdev) && !ASIC_IS_DCE8(rdev) &&
(encoder_mode == ATOM_ENCODER_MODE_HDMI) &&
(radeon_crtc->bpc > 8))
clock = radeon_crtc->adjusted_clock;
switch (radeon_crtc->pll_id) { switch (radeon_crtc->pll_id) {
case ATOM_PPLL1: case ATOM_PPLL1:
pll = &rdev->clock.p1pll; pll = &rdev->clock.p1pll;
...@@ -1063,7 +1090,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode ...@@ -1063,7 +1090,7 @@ static void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode
radeon_crtc->crtc_id, &radeon_crtc->ss); radeon_crtc->crtc_id, &radeon_crtc->ss);
atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id, atombios_crtc_program_pll(crtc, radeon_crtc->crtc_id, radeon_crtc->pll_id,
encoder_mode, radeon_encoder->encoder_id, mode->clock, encoder_mode, radeon_encoder->encoder_id, clock,
ref_div, fb_div, frac_fb_div, post_div, ref_div, fb_div, frac_fb_div, post_div,
radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss); radeon_crtc->bpc, radeon_crtc->ss_enabled, &radeon_crtc->ss);
......
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