Commit 4eaeca33 authored by Alex Deucher's avatar Alex Deucher Committed by Dave Airlie

drm/radeon/kms: clean up atombios pll code

- split pll adjust into a separate function
- use a union for SetPixelClock params
Signed-off-by: default avatarAlex Deucher <alexdeucher@gmail.com>
Signed-off-by: default avatarDave Airlie <airlied@redhat.com>
parent fc10332b
...@@ -409,30 +409,22 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) ...@@ -409,30 +409,22 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable)
} }
} }
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) union adjust_pixel_clock {
ADJUST_DISPLAY_PLL_PS_ALLOCATION v1;
};
static u32 atombios_adjust_pll(struct drm_crtc *crtc,
struct drm_display_mode *mode,
struct radeon_pll *pll)
{ {
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev; struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private; struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *encoder = NULL; struct drm_encoder *encoder = NULL;
struct radeon_encoder *radeon_encoder = NULL; struct radeon_encoder *radeon_encoder = NULL;
uint8_t frev, crev; u32 adjusted_clock = mode->clock;
int index;
SET_PIXEL_CLOCK_PS_ALLOCATION args;
PIXEL_CLOCK_PARAMETERS *spc1_ptr;
PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr;
PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr;
uint32_t pll_clock = mode->clock;
uint32_t adjusted_clock;
uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
struct radeon_pll *pll;
if (radeon_crtc->crtc_id == 0)
pll = &rdev->clock.p1pll;
else
pll = &rdev->clock.p2pll;
memset(&args, 0, sizeof(args)); /* reset the pll flags */
pll->flags = 0;
if (ASIC_IS_AVIVO(rdev)) { if (ASIC_IS_AVIVO(rdev)) {
if ((rdev->family == CHIP_RS600) || if ((rdev->family == CHIP_RS600) ||
...@@ -457,15 +449,17 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -457,15 +449,17 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) { if (encoder->crtc == crtc) {
if (!ASIC_IS_AVIVO(rdev)) { radeon_encoder = to_radeon_encoder(encoder);
if (encoder->encoder_type != if (ASIC_IS_AVIVO(rdev)) {
DRM_MODE_ENCODER_DAC) /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */
if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)
adjusted_clock = mode->clock * 2;
} else {
if (encoder->encoder_type != DRM_MODE_ENCODER_DAC)
pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; pll->flags |= RADEON_PLL_NO_ODD_POST_DIV;
if (encoder->encoder_type == if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS)
DRM_MODE_ENCODER_LVDS)
pll->flags |= RADEON_PLL_USE_REF_DIV; pll->flags |= RADEON_PLL_USE_REF_DIV;
} }
radeon_encoder = to_radeon_encoder(encoder);
break; break;
} }
} }
...@@ -475,28 +469,88 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -475,28 +469,88 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
* special hw requirements. * special hw requirements.
*/ */
if (ASIC_IS_DCE3(rdev)) { if (ASIC_IS_DCE3(rdev)) {
ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args; union adjust_pixel_clock args;
struct radeon_encoder_atom_dig *dig;
if (!encoder) u8 frev, crev;
return; int index;
memset(&adjust_pll_args, 0, sizeof(adjust_pll_args)); if (!radeon_encoder->enc_priv)
adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10); return adjusted_clock;
adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id; dig = radeon_encoder->enc_priv;
adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder);
index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll);
atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev,
&crev);
memset(&args, 0, sizeof(args));
switch (frev) {
case 1:
switch (crev) {
case 1:
case 2:
args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
args.v1.ucTransmitterID = radeon_encoder->encoder_id;
args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder);
atom_execute_table(rdev->mode_info.atom_context, atom_execute_table(rdev->mode_info.atom_context,
index, (uint32_t *)&adjust_pll_args); index, (uint32_t *)&args);
adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10; adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10;
} else { break;
/* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ default:
if (ASIC_IS_AVIVO(rdev) && DRM_ERROR("Unknown table version %d %d\n", frev, crev);
(radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) return adjusted_clock;
adjusted_clock = mode->clock * 2; }
else break;
adjusted_clock = mode->clock; default:
DRM_ERROR("Unknown table version %d %d\n", frev, crev);
return adjusted_clock;
}
} }
return adjusted_clock;
}
union set_pixel_clock {
SET_PIXEL_CLOCK_PS_ALLOCATION base;
PIXEL_CLOCK_PARAMETERS v1;
PIXEL_CLOCK_PARAMETERS_V2 v2;
PIXEL_CLOCK_PARAMETERS_V3 v3;
};
void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
{
struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc);
struct drm_device *dev = crtc->dev;
struct radeon_device *rdev = dev->dev_private;
struct drm_encoder *encoder = NULL;
struct radeon_encoder *radeon_encoder = NULL;
u8 frev, crev;
int index;
union set_pixel_clock args;
u32 pll_clock = mode->clock;
u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0;
struct radeon_pll *pll;
u32 adjusted_clock;
memset(&args, 0, sizeof(args));
list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
if (encoder->crtc == crtc) {
radeon_encoder = to_radeon_encoder(encoder);
break;
}
}
if (!radeon_encoder)
return;
if (radeon_crtc->crtc_id == 0)
pll = &rdev->clock.p1pll;
else
pll = &rdev->clock.p2pll;
/* adjust pixel clock as needed */
adjusted_clock = atombios_adjust_pll(crtc, mode, pll);
if (ASIC_IS_AVIVO(rdev)) { if (ASIC_IS_AVIVO(rdev)) {
if (radeon_new_pll) if (radeon_new_pll)
...@@ -519,45 +573,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -519,45 +573,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
case 1: case 1:
switch (crev) { switch (crev) {
case 1: case 1:
spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; args.v1.usPixelClock = cpu_to_le16(mode->clock / 10);
spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); args.v1.usRefDiv = cpu_to_le16(ref_div);
spc1_ptr->usRefDiv = cpu_to_le16(ref_div); args.v1.usFbDiv = cpu_to_le16(fb_div);
spc1_ptr->usFbDiv = cpu_to_le16(fb_div); args.v1.ucFracFbDiv = frac_fb_div;
spc1_ptr->ucFracFbDiv = frac_fb_div; args.v1.ucPostDiv = post_div;
spc1_ptr->ucPostDiv = post_div; args.v1.ucPpll =
spc1_ptr->ucPpll =
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
spc1_ptr->ucCRTC = radeon_crtc->crtc_id; args.v1.ucCRTC = radeon_crtc->crtc_id;
spc1_ptr->ucRefDivSrc = 1; args.v1.ucRefDivSrc = 1;
break; break;
case 2: case 2:
spc2_ptr = args.v2.usPixelClock = cpu_to_le16(mode->clock / 10);
(PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; args.v2.usRefDiv = cpu_to_le16(ref_div);
spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); args.v2.usFbDiv = cpu_to_le16(fb_div);
spc2_ptr->usRefDiv = cpu_to_le16(ref_div); args.v2.ucFracFbDiv = frac_fb_div;
spc2_ptr->usFbDiv = cpu_to_le16(fb_div); args.v2.ucPostDiv = post_div;
spc2_ptr->ucFracFbDiv = frac_fb_div; args.v2.ucPpll =
spc2_ptr->ucPostDiv = post_div;
spc2_ptr->ucPpll =
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
spc2_ptr->ucCRTC = radeon_crtc->crtc_id; args.v2.ucCRTC = radeon_crtc->crtc_id;
spc2_ptr->ucRefDivSrc = 1; args.v2.ucRefDivSrc = 1;
break; break;
case 3: case 3:
if (!encoder) args.v3.usPixelClock = cpu_to_le16(mode->clock / 10);
return; args.v3.usRefDiv = cpu_to_le16(ref_div);
spc3_ptr = args.v3.usFbDiv = cpu_to_le16(fb_div);
(PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; args.v3.ucFracFbDiv = frac_fb_div;
spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); args.v3.ucPostDiv = post_div;
spc3_ptr->usRefDiv = cpu_to_le16(ref_div); args.v3.ucPpll =
spc3_ptr->usFbDiv = cpu_to_le16(fb_div);
spc3_ptr->ucFracFbDiv = frac_fb_div;
spc3_ptr->ucPostDiv = post_div;
spc3_ptr->ucPpll =
radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1;
spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2);
spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; args.v3.ucTransmitterId = radeon_encoder->encoder_id;
spc3_ptr->ucEncoderMode = args.v3.ucEncoderMode =
atombios_get_encoder_mode(encoder); atombios_get_encoder_mode(encoder);
break; break;
default: default:
...@@ -570,7 +617,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) ...@@ -570,7 +617,6 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode)
return; return;
} }
printk("executing set pll\n");
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
} }
......
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