diff options
author | Alex Deucher <alexander.deucher@amd.com> | 2013-02-13 16:38:25 -0500 |
---|---|---|
committer | Alex Deucher <alexander.deucher@amd.com> | 2013-06-27 19:16:23 -0400 |
commit | eaa778aff0f19c35e9380c2bc5513b5b60ce01a6 (patch) | |
tree | 153c9da3bd059419edabbef11a1e0e508efe939b | |
parent | e37e6a0e4fc68cfa9c54410170577de385231de0 (diff) |
drm/radeon/atom: add helper to calcuate mpll params
There's a new table for calculating the memory pll
parameters on SI. Required for SI DPM support.
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
-rw-r--r-- | drivers/gpu/drm/radeon/radeon.h | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_atombios.c | 51 | ||||
-rw-r--r-- | drivers/gpu/drm/radeon/radeon_mode.h | 24 |
3 files changed, 79 insertions, 0 deletions
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index f57e36d6fb4a..1fb1d3faed0a 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -219,6 +219,10 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev, u32 clock, bool strobe_mode, struct atom_clock_dividers *dividers); +int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev, + u32 clock, + bool strobe_mode, + struct atom_mpll_param *mpll_param); void radeon_atom_set_voltage(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type); int radeon_atom_get_voltage_gpio_settings(struct radeon_device *rdev, u16 voltage_level, u8 voltage_type, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 612d9bc1ccb0..45a6f5d155df 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -2833,6 +2833,57 @@ int radeon_atom_get_clock_dividers(struct radeon_device *rdev, return 0; } +int radeon_atom_get_memory_pll_dividers(struct radeon_device *rdev, + u32 clock, + bool strobe_mode, + struct atom_mpll_param *mpll_param) +{ + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 args; + int index = GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam); + u8 frev, crev; + + memset(&args, 0, sizeof(args)); + memset(mpll_param, 0, sizeof(struct atom_mpll_param)); + + if (!atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, &crev)) + return -EINVAL; + + switch (frev) { + case 2: + switch (crev) { + case 1: + /* SI */ + args.ulClock = cpu_to_le32(clock); /* 10 khz */ + args.ucInputFlag = 0; + if (strobe_mode) + args.ucInputFlag |= MPLL_INPUT_FLAG_STROBE_MODE_EN; + + atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); + + mpll_param->clkfrac = le16_to_cpu(args.ulFbDiv.usFbDivFrac); + mpll_param->clkf = le16_to_cpu(args.ulFbDiv.usFbDiv); + mpll_param->post_div = args.ucPostDiv; + mpll_param->dll_speed = args.ucDllSpeed; + mpll_param->bwcntl = args.ucBWCntl; + mpll_param->vco_mode = + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_VCO_MODE_MASK) ? 1 : 0; + mpll_param->yclk_sel = + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0; + mpll_param->qdr = + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0; + mpll_param->half_rate = + (args.ucPllCntlFlag & MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0; + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + return 0; +} + void radeon_atom_set_clock_gating(struct radeon_device *rdev, int enable) { DYNAMIC_CLOCK_GATING_PS_ALLOCATION args; diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 02bf4a755f34..e5ea915993d9 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -519,6 +519,30 @@ struct atom_clock_dividers { u32 flags; }; +struct atom_mpll_param { + union { + struct { +#ifdef __BIG_ENDIAN + u32 reserved : 8; + u32 clkfrac : 12; + u32 clkf : 12; +#else + u32 clkf : 12; + u32 clkfrac : 12; + u32 reserved : 8; +#endif + }; + u32 fb_div; + }; + u32 post_div; + u32 bwcntl; + u32 dll_speed; + u32 vco_mode; + u32 yclk_sel; + u32 qdr; + u32 half_rate; +}; + #define MEM_TYPE_GDDR5 0x50 #define MEM_TYPE_GDDR4 0x40 #define MEM_TYPE_GDDR3 0x30 |