mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
drm/amd/display: Update get_pixel_clk_frequency() for DCN4x DCCG DP DTO
[Why & How] DCN4x ASICs have different DCCG logic for programming DP DTO. The current get_pixel_clk_frequency_100hz() function does not account for this. Rename the function to "get_dp_dto_frequency" to more accurately reflect its intended behaviour. Create a new function that correctly calculates the target pixel rate for DCN4.x DCCG design and use it. Reviewed-by: Leo Chen <leo.chen@amd.com> Signed-off-by: Ovidiu Bunea <ovidiu.bunea@amd.com> Signed-off-by: Ray Wu <ray.wu@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
470d1ae31d
commit
6f6483dbfa
|
|
@ -1487,7 +1487,7 @@ static void disable_vbios_mode_if_required(
|
|||
}
|
||||
}
|
||||
|
||||
dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source,
|
||||
tg_inst, &pix_clk_100hz);
|
||||
|
||||
|
|
@ -2004,7 +2004,7 @@ bool dc_validate_boot_timing(const struct dc *dc,
|
|||
uint32_t numOdmPipes = 1;
|
||||
uint32_t id_src[4] = {0};
|
||||
|
||||
dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source,
|
||||
tg_inst, &pix_clk_100hz);
|
||||
|
||||
|
|
|
|||
|
|
@ -1188,15 +1188,16 @@ static bool dce110_clock_source_power_down(
|
|||
return bp_result == BP_RESULT_OK;
|
||||
}
|
||||
|
||||
static bool get_pixel_clk_frequency_100hz(
|
||||
static bool get_dp_dto_frequency_100hz(
|
||||
const struct clock_source *clock_source,
|
||||
unsigned int inst,
|
||||
unsigned int *pixel_clk_khz)
|
||||
unsigned int *pixel_clk_100hz)
|
||||
{
|
||||
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
|
||||
unsigned int clock_hz = 0;
|
||||
unsigned int modulo_hz = 0;
|
||||
unsigned int dp_dto_ref_khz = clock_source->ctx->dc->clk_mgr->dprefclk_khz;
|
||||
unsigned long long temp = 0;
|
||||
|
||||
if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
|
||||
clock_hz = REG_READ(PHASE[inst]);
|
||||
|
|
@ -1207,17 +1208,18 @@ static bool get_pixel_clk_frequency_100hz(
|
|||
* not be programmed equal to DPREFCLK
|
||||
*/
|
||||
modulo_hz = REG_READ(MODULO[inst]);
|
||||
if (modulo_hz)
|
||||
*pixel_clk_khz = (unsigned int)div_u64((uint64_t)clock_hz *
|
||||
dp_dto_ref_khz * 10, modulo_hz);
|
||||
else
|
||||
*pixel_clk_khz = 0;
|
||||
if (modulo_hz) {
|
||||
temp = div_u64((uint64_t)clock_hz * dp_dto_ref_khz * 10, modulo_hz);
|
||||
ASSERT(temp / 100 <= 0xFFFFFFFFUL);
|
||||
*pixel_clk_100hz = (unsigned int)(temp / 100);
|
||||
} else
|
||||
*pixel_clk_100hz = 0;
|
||||
} else {
|
||||
/* NOTE: There is agreement with VBIOS here that MODULO is
|
||||
* programmed equal to DPREFCLK, in which case PHASE will be
|
||||
* equivalent to pixel clock.
|
||||
*/
|
||||
*pixel_clk_khz = clock_hz / 100;
|
||||
*pixel_clk_100hz = clock_hz / 100;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
@ -1225,6 +1227,61 @@ static bool get_pixel_clk_frequency_100hz(
|
|||
return false;
|
||||
}
|
||||
|
||||
static bool dcn401_get_dp_dto_frequency_100hz(const struct clock_source *clock_source, unsigned int inst,
|
||||
unsigned int *pixel_clk_100hz)
|
||||
{
|
||||
struct dce110_clk_src *clk_src = TO_DCE110_CLK_SRC(clock_source);
|
||||
unsigned int phase_hz = 0;
|
||||
unsigned int modulo_hz = 0;
|
||||
unsigned int dp_dto_integer = 0;
|
||||
unsigned long long temp = 0;
|
||||
|
||||
if (clock_source->id == CLOCK_SOURCE_ID_DP_DTO) {
|
||||
phase_hz = REG_READ(PHASE[inst]);
|
||||
modulo_hz = REG_READ(MODULO[inst]);
|
||||
|
||||
switch (inst) {
|
||||
case 0:
|
||||
REG_GET(OTG_PIXEL_RATE_DIV, DPDTO0_INT, &dp_dto_integer);
|
||||
break;
|
||||
case 1:
|
||||
REG_GET(OTG_PIXEL_RATE_DIV, DPDTO1_INT, &dp_dto_integer);
|
||||
break;
|
||||
case 2:
|
||||
REG_GET(OTG_PIXEL_RATE_DIV, DPDTO2_INT, &dp_dto_integer);
|
||||
break;
|
||||
case 3:
|
||||
REG_GET(OTG_PIXEL_RATE_DIV, DPDTO3_INT, &dp_dto_integer);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
|
||||
/* On DCN4x, the DCCG DPDTO is directly programmed with the required pixel clock as per the following formula:
|
||||
* - DPDTO INTEGER = INT(4:4:4 pixel rate / DTBCLK_P rate)
|
||||
* - DPDTO PHASE = 4:4:4 pixel rate – DPDTO INTEGER * DTBCLK_P rate
|
||||
* - DPDTO MODULO = DTBCLK_P rate
|
||||
* - target pix_clk_hz = (DPDTO INTEGER * DPDTO MODULO + DPDTO PHASE)
|
||||
*/
|
||||
|
||||
dp_dto_integer += 1; // integer=0 represents 1x multiplier, etc.
|
||||
temp = (unsigned long long)dp_dto_integer * modulo_hz + phase_hz;
|
||||
|
||||
if (temp / 100 > 0xFFFFFFFFUL) {
|
||||
/* pixel rate 100hz should never be this high, if it is, throw an assert and return 0 */
|
||||
BREAK_TO_DEBUGGER();
|
||||
*pixel_clk_100hz = 0;
|
||||
} else {
|
||||
*pixel_clk_100hz = (unsigned int)(temp / 100);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
|
||||
const struct pixel_rate_range_table_entry video_optimized_pixel_rates[] = {
|
||||
// /1.001 rates
|
||||
|
|
@ -1318,7 +1375,7 @@ static const struct clock_source_funcs dcn20_clk_src_funcs = {
|
|||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dcn20_program_pix_clk,
|
||||
.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz,
|
||||
.get_dp_dto_frequency_100hz = get_dp_dto_frequency_100hz,
|
||||
.override_dp_pix_clk = dcn20_override_dp_pix_clk
|
||||
};
|
||||
|
||||
|
|
@ -1405,21 +1462,21 @@ static const struct clock_source_funcs dcn3_clk_src_funcs = {
|
|||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dcn3_program_pix_clk,
|
||||
.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
|
||||
.get_dp_dto_frequency_100hz = get_dp_dto_frequency_100hz
|
||||
};
|
||||
|
||||
static const struct clock_source_funcs dcn31_clk_src_funcs = {
|
||||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dcn31_program_pix_clk,
|
||||
.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
|
||||
.get_dp_dto_frequency_100hz = get_dp_dto_frequency_100hz
|
||||
};
|
||||
|
||||
static const struct clock_source_funcs dcn401_clk_src_funcs = {
|
||||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dcn401_program_pix_clk,
|
||||
.get_pix_clk_dividers = dcn3_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
|
||||
.get_dp_dto_frequency_100hz = dcn401_get_dp_dto_frequency_100hz
|
||||
};
|
||||
|
||||
/*****************************************/
|
||||
|
|
@ -1430,13 +1487,13 @@ static const struct clock_source_funcs dce112_clk_src_funcs = {
|
|||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dce112_program_pix_clk,
|
||||
.get_pix_clk_dividers = dce112_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
|
||||
.get_dp_dto_frequency_100hz = get_dp_dto_frequency_100hz
|
||||
};
|
||||
static const struct clock_source_funcs dce110_clk_src_funcs = {
|
||||
.cs_power_down = dce110_clock_source_power_down,
|
||||
.program_pix_clk = dce110_program_pix_clk,
|
||||
.get_pix_clk_dividers = dce110_get_pix_clk_dividers,
|
||||
.get_pixel_clk_frequency_100hz = get_pixel_clk_frequency_100hz
|
||||
.get_dp_dto_frequency_100hz = get_dp_dto_frequency_100hz
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -202,7 +202,11 @@
|
|||
type PLL_REF_DIV; \
|
||||
type DP_DTO0_PHASE; \
|
||||
type DP_DTO0_MODULO; \
|
||||
type DP_DTO0_ENABLE;
|
||||
type DP_DTO0_ENABLE; \
|
||||
type DPDTO0_INT; \
|
||||
type DPDTO1_INT; \
|
||||
type DPDTO2_INT; \
|
||||
type DPDTO3_INT;
|
||||
|
||||
#define CS_REG_FIELD_LIST_DCN32(type) \
|
||||
type PIPE0_DTO_SRC_SEL;
|
||||
|
|
@ -221,6 +225,7 @@ struct dce110_clk_src_regs {
|
|||
uint32_t RESYNC_CNTL;
|
||||
uint32_t PIXCLK_RESYNC_CNTL;
|
||||
uint32_t PLL_CNTL;
|
||||
uint32_t OTG_PIXEL_RATE_DIV;
|
||||
|
||||
/* below are for DTO.
|
||||
* todo: should probably use different struct to not waste space
|
||||
|
|
|
|||
|
|
@ -2423,7 +2423,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
|
|||
grouped_pipes[i]->stream_res.tg->funcs->get_hw_timing(
|
||||
grouped_pipes[i]->stream_res.tg,
|
||||
&hw_crtc_timing[i]);
|
||||
dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source,
|
||||
grouped_pipes[i]->stream_res.tg->inst,
|
||||
&pclk);
|
||||
|
|
@ -2462,7 +2462,7 @@ static int dcn10_align_pixel_clocks(struct dc *dc, int group_size,
|
|||
dc->res_pool->dp_clock_source,
|
||||
grouped_pipes[i]->stream_res.tg->inst,
|
||||
(unsigned int)phase[i], (unsigned int)modulo[i]);
|
||||
dc->res_pool->dp_clock_source->funcs->get_pixel_clk_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source->funcs->get_dp_dto_frequency_100hz(
|
||||
dc->res_pool->dp_clock_source,
|
||||
grouped_pipes[i]->stream_res.tg->inst, &pclk);
|
||||
grouped_pipes[i]->stream->timing.pix_clk_100hz =
|
||||
|
|
|
|||
|
|
@ -170,10 +170,10 @@ struct clock_source_funcs {
|
|||
struct clock_source *,
|
||||
struct pixel_clk_params *,
|
||||
struct pll_settings *);
|
||||
bool (*get_pixel_clk_frequency_100hz)(
|
||||
bool (*get_dp_dto_frequency_100hz)(
|
||||
const struct clock_source *clock_source,
|
||||
unsigned int inst,
|
||||
unsigned int *pixel_clk_khz);
|
||||
unsigned int *pixel_clk_100hz);
|
||||
bool (*override_dp_pix_clk)(
|
||||
struct clock_source *clock_source,
|
||||
unsigned int inst,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user