drm/radeon: add radeon_atom_get_clock_dividers helper
Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Jerome Glisse <jglisse@redhat.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
73afc70d11
commit
7062ab67d4
|
@ -206,6 +206,11 @@ void radeon_pm_suspend(struct radeon_device *rdev);
|
|||
void radeon_pm_resume(struct radeon_device *rdev);
|
||||
void radeon_combios_get_power_modes(struct radeon_device *rdev);
|
||||
void radeon_atombios_get_power_modes(struct radeon_device *rdev);
|
||||
int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
|
||||
u8 clock_type,
|
||||
u32 clock,
|
||||
bool strobe_mode,
|
||||
struct atom_clock_dividers *dividers);
|
||||
void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type);
|
||||
void rs690_pm_info(struct radeon_device *rdev);
|
||||
extern int rv6xx_get_temp(struct radeon_device *rdev);
|
||||
|
|
|
@ -2654,6 +2654,113 @@ void radeon_atombios_get_power_modes(struct radeon_device *rdev)
|
|||
rdev->pm.current_vddc = 0;
|
||||
}
|
||||
|
||||
union get_clock_dividers {
|
||||
struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS v1;
|
||||
struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V2 v2;
|
||||
struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V3 v3;
|
||||
struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 v4;
|
||||
struct _COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V5 v5;
|
||||
};
|
||||
|
||||
int radeon_atom_get_clock_dividers(struct radeon_device *rdev,
|
||||
u8 clock_type,
|
||||
u32 clock,
|
||||
bool strobe_mode,
|
||||
struct atom_clock_dividers *dividers)
|
||||
{
|
||||
union get_clock_dividers args;
|
||||
int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL);
|
||||
u8 frev, crev;
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
memset(dividers, 0, sizeof(struct atom_clock_dividers));
|
||||
|
||||
if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev))
|
||||
return -EINVAL;
|
||||
|
||||
switch (crev) {
|
||||
case 1:
|
||||
/* r4xx, r5xx */
|
||||
args.v1.ucAction = clock_type;
|
||||
args.v1.ulClock = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
dividers->post_div = args.v1.ucPostDiv;
|
||||
dividers->fb_div = args.v1.ucFbDiv;
|
||||
dividers->enable_post_div = true;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
/* r6xx, r7xx, evergreen, ni */
|
||||
if (rdev->family <= CHIP_RV770) {
|
||||
args.v2.ucAction = clock_type;
|
||||
args.v2.ulClock = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
dividers->post_div = args.v2.ucPostDiv;
|
||||
dividers->fb_div = le16_to_cpu(args.v2.usFbDiv);
|
||||
dividers->ref_div = args.v2.ucAction;
|
||||
if (rdev->family == CHIP_RV770) {
|
||||
dividers->enable_post_div = (le32_to_cpu(args.v2.ulClock) & (1 << 24)) ?
|
||||
true : false;
|
||||
dividers->vco_mode = (le32_to_cpu(args.v2.ulClock) & (1 << 25)) ? 1 : 0;
|
||||
} else
|
||||
dividers->enable_post_div = (dividers->fb_div & 1) ? true : false;
|
||||
} else {
|
||||
if (clock_type == COMPUTE_ENGINE_PLL_PARAM) {
|
||||
args.v3.ulClock.ulComputeClockFlag = clock_type;
|
||||
args.v3.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
dividers->post_div = args.v3.ucPostDiv;
|
||||
dividers->enable_post_div = (args.v3.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
|
||||
dividers->enable_dithen = (args.v3.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
|
||||
dividers->fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDiv);
|
||||
dividers->frac_fb_div = le16_to_cpu(args.v3.ulFbDiv.usFbDivFrac);
|
||||
dividers->ref_div = args.v3.ucRefDiv;
|
||||
dividers->vco_mode = (args.v3.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
|
||||
} else {
|
||||
args.v5.ulClock.ulComputeClockFlag = clock_type;
|
||||
args.v5.ulClock.ulClockFreq = cpu_to_le32(clock); /* 10 khz */
|
||||
if (strobe_mode)
|
||||
args.v5.ucInputFlag = ATOM_PLL_INPUT_FLAG_PLL_STROBE_MODE_EN;
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
dividers->post_div = args.v5.ucPostDiv;
|
||||
dividers->enable_post_div = (args.v5.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_PLL_POST_DIV_EN) ? true : false;
|
||||
dividers->enable_dithen = (args.v5.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_FRACTION_DISABLE) ? false : true;
|
||||
dividers->whole_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDiv);
|
||||
dividers->frac_fb_div = le16_to_cpu(args.v5.ulFbDiv.usFbDivFrac);
|
||||
dividers->ref_div = args.v5.ucRefDiv;
|
||||
dividers->vco_mode = (args.v5.ucCntlFlag &
|
||||
ATOM_PLL_CNTL_FLAG_MPLL_VCO_MODE) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 4:
|
||||
/* fusion */
|
||||
args.v4.ulClock = cpu_to_le32(clock); /* 10 khz */
|
||||
|
||||
atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args);
|
||||
|
||||
dividers->post_div = args.v4.ucPostDiv;
|
||||
dividers->real_clock = le32_to_cpu(args.v4.ulClock);
|
||||
break;
|
||||
default:
|
||||
return -EINVAL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable)
|
||||
{
|
||||
DYNAMIC_CLOCK_GATING_PS_ALLOCATION args;
|
||||
|
|
|
@ -492,6 +492,29 @@ struct radeon_framebuffer {
|
|||
#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
|
||||
((em) == ATOM_ENCODER_MODE_DP_MST))
|
||||
|
||||
struct atom_clock_dividers {
|
||||
u32 post_div;
|
||||
union {
|
||||
struct {
|
||||
#ifdef __BIG_ENDIAN
|
||||
u32 reserved : 6;
|
||||
u32 whole_fb_div : 12;
|
||||
u32 frac_fb_div : 14;
|
||||
#else
|
||||
u32 frac_fb_div : 14;
|
||||
u32 whole_fb_div : 12;
|
||||
u32 reserved : 6;
|
||||
#endif
|
||||
};
|
||||
u32 fb_div;
|
||||
};
|
||||
u32 ref_div;
|
||||
bool enable_post_div;
|
||||
bool enable_dithen;
|
||||
u32 vco_mode;
|
||||
u32 real_clock;
|
||||
};
|
||||
|
||||
extern enum radeon_tv_std
|
||||
radeon_combios_get_tv_info(struct radeon_device *rdev);
|
||||
extern enum radeon_tv_std
|
||||
|
|
Loading…
Reference in New Issue