Commit 49f59499 authored by Jun Lei's avatar Jun Lei Committed by Alex Deucher

drm/amd/display: add new pixel rate programming

[why]
New dividers in DCCG need to be programmed depending
on encoder/stream type since pixels per clock in
OTG/DIO is different

DIO also needs additional programming depending on
pixels per clock
Signed-off-by: default avatarJun Lei <Jun.Lei@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
Signed-off-by: default avatarRodrigo Siqueira <Rodrigo.Siqueira@amd.com>
parent 452e9214
...@@ -576,6 +576,7 @@ struct dcn10_stream_enc_registers { ...@@ -576,6 +576,7 @@ struct dcn10_stream_enc_registers {
type DP_SEC_GSP11_LINE_NUM type DP_SEC_GSP11_LINE_NUM
#define SE_REG_FIELD_LIST_DCN3_2(type) \ #define SE_REG_FIELD_LIST_DCN3_2(type) \
type DIG_FIFO_OUTPUT_PIXEL_MODE;\
type DIG_SYMCLK_FE_ON;\ type DIG_SYMCLK_FE_ON;\
type DIG_FIFO_READ_START_LEVEL;\ type DIG_FIFO_READ_START_LEVEL;\
type DIG_FIFO_ENABLE;\ type DIG_FIFO_ENABLE;\
......
...@@ -661,7 +661,17 @@ enum dc_status dcn20_enable_stream_timing( ...@@ -661,7 +661,17 @@ enum dc_status dcn20_enable_stream_timing(
struct mpc_dwb_flow_control flow_control; struct mpc_dwb_flow_control flow_control;
struct mpc *mpc = dc->res_pool->mpc; struct mpc *mpc = dc->res_pool->mpc;
bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing)); bool rate_control_2x_pclk = (interlace || optc2_is_two_pixels_per_containter(&stream->timing));
unsigned int k1_div = PIXEL_RATE_DIV_NA;
unsigned int k2_div = PIXEL_RATE_DIV_NA;
if (hws->funcs.calculate_dccg_k1_k2_values && dc->res_pool->dccg->funcs->set_pixel_rate_div) {
hws->funcs.calculate_dccg_k1_k2_values(pipe_ctx, &k1_div, &k2_div);
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
k1_div, k2_div);
}
/* by upper caller loop, pipe0 is parent pipe and be called first. /* by upper caller loop, pipe0 is parent pipe and be called first.
* back end is set up by for pipe0. Other children pipe share back end * back end is set up by for pipe0. Other children pipe share back end
* with pipe 0. No program is needed. * with pipe 0. No program is needed.
...@@ -2485,6 +2495,10 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx) ...@@ -2485,6 +2495,10 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
tg->funcs->set_early_control(tg, early_control); tg->funcs->set_early_control(tg, early_control);
if (pipe_ctx->stream_res.stream_enc->funcs->set_input_mode)
pipe_ctx->stream_res.stream_enc->funcs->set_input_mode(pipe_ctx->stream_res.stream_enc,
timing->pixel_encoding == PIXEL_ENCODING_YCBCR420 ? 2 : 1);
/* enable audio only within mode set */ /* enable audio only within mode set */
if (pipe_ctx->stream_res.audio != NULL) { if (pipe_ctx->stream_res.audio != NULL) {
if (is_dp_128b_132b_signal(pipe_ctx)) if (is_dp_128b_132b_signal(pipe_ctx))
......
...@@ -272,6 +272,7 @@ static const struct dccg_funcs dccg32_funcs = { ...@@ -272,6 +272,7 @@ static const struct dccg_funcs dccg32_funcs = {
.set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto, .set_audio_dtbclk_dto = dccg31_set_audio_dtbclk_dto,
.otg_add_pixel = dccg32_otg_add_pixel, .otg_add_pixel = dccg32_otg_add_pixel,
.otg_drop_pixel = dccg32_otg_drop_pixel, .otg_drop_pixel = dccg32_otg_drop_pixel,
.set_pixel_rate_div = dccg32_set_pixel_rate_div,
}; };
struct dccg *dccg32_create( struct dccg *dccg32_create(
......
...@@ -240,7 +240,8 @@ ...@@ -240,7 +240,8 @@
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_READ_START_LEVEL, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_ENABLE, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\ SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh) SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_RESET_DONE, mask_sh),\
SE_SF(DIG0_DIG_FIFO_CTRL0, DIG_FIFO_OUTPUT_PIXEL_MODE, mask_sh)
#if defined(CONFIG_DRM_AMD_DC_HDCP) #if defined(CONFIG_DRM_AMD_DC_HDCP)
#define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\ #define SE_COMMON_MASK_SH_LIST_DCN32(mask_sh)\
......
...@@ -47,6 +47,7 @@ ...@@ -47,6 +47,7 @@
#include "clk_mgr.h" #include "clk_mgr.h"
#include "dsc.h" #include "dsc.h"
#include "dcn20/dcn20_optc.h" #include "dcn20/dcn20_optc.h"
#include "dc_link_dp.h"
#define DC_LOGGER_INIT(logger) #define DC_LOGGER_INIT(logger)
...@@ -836,20 +837,44 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable) ...@@ -836,20 +837,44 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
} }
} }
/*
* Given any pipe_ctx, return the total ODM combine factor, and optionally return
* the OPPids which are used
* */
static unsigned int get_odm_config(struct pipe_ctx *pipe_ctx, unsigned int *opp_instances)
{
unsigned int opp_count = 1;
struct pipe_ctx *odm_pipe;
/* First get to the top pipe */
for (odm_pipe = pipe_ctx; odm_pipe->prev_odm_pipe; odm_pipe = odm_pipe->prev_odm_pipe)
;
/* First pipe is always used */
if (opp_instances)
opp_instances[0] = odm_pipe->stream_res.opp->inst;
/* Find and count odm pipes, if any */
for (odm_pipe = odm_pipe->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
if (opp_instances)
opp_instances[opp_count] = odm_pipe->stream_res.opp->inst;
opp_count++;
}
return opp_count;
}
void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx) void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx)
{ {
struct pipe_ctx *odm_pipe; struct pipe_ctx *odm_pipe;
int opp_cnt = 1; int opp_cnt = 0;
int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst }; int opp_inst[MAX_PIPES] = {0};
bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing)); bool rate_control_2x_pclk = (pipe_ctx->stream->timing.flags.INTERLACE || optc2_is_two_pixels_per_containter(&pipe_ctx->stream->timing));
struct mpc_dwb_flow_control flow_control; struct mpc_dwb_flow_control flow_control;
struct mpc *mpc = dc->res_pool->mpc; struct mpc *mpc = dc->res_pool->mpc;
int i; int i;
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) { opp_cnt = get_odm_config(pipe_ctx, opp_inst);
opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
opp_cnt++;
}
if (opp_cnt > 1) if (opp_cnt > 1)
pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg->funcs->set_odm_combine(
...@@ -892,3 +917,38 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * ...@@ -892,3 +917,38 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC); update_dsc_on_stream(pipe_ctx, pipe_ctx->stream->timing.flags.DSC);
} }
unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div)
{
struct dc_stream_state *stream = pipe_ctx->stream;
unsigned int odm_combine_factor = 0;
odm_combine_factor = get_odm_config(pipe_ctx, NULL);
if (is_dp_128b_132b_signal(pipe_ctx)) {
*k2_div = PIXEL_RATE_DIV_BY_1;
} else if (dc_is_hdmi_tmds_signal(pipe_ctx->stream->signal) || dc_is_dvi_signal(pipe_ctx->stream->signal)) {
*k1_div = PIXEL_RATE_DIV_BY_1;
if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420)
*k2_div = PIXEL_RATE_DIV_BY_2;
else
*k2_div = PIXEL_RATE_DIV_BY_4;
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR420) {
*k1_div = PIXEL_RATE_DIV_BY_1;
*k2_div = PIXEL_RATE_DIV_BY_2;
} else if (stream->timing.pixel_encoding == PIXEL_ENCODING_YCBCR422) {
*k1_div = PIXEL_RATE_DIV_BY_2;
*k2_div = PIXEL_RATE_DIV_BY_2;
} else {
if (odm_combine_factor == 1)
*k2_div = PIXEL_RATE_DIV_BY_4;
else if (odm_combine_factor == 2)
*k2_div = PIXEL_RATE_DIV_BY_2;
}
}
if ((*k1_div == PIXEL_RATE_DIV_NA) && (*k2_div == PIXEL_RATE_DIV_NA))
ASSERT(false);
return odm_combine_factor;
}
...@@ -61,4 +61,6 @@ void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context); ...@@ -61,4 +61,6 @@ void dcn32_subvp_update_force_pstate(struct dc *dc, struct dc_state *context);
void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx); void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *pipe_ctx);
unsigned int dcn32_calculate_dccg_k1_k2_values(struct pipe_ctx *pipe_ctx, unsigned int *k1_div, unsigned int *k2_div);
#endif /* __DC_HWSS_DCN32_H__ */ #endif /* __DC_HWSS_DCN32_H__ */
...@@ -141,6 +141,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = { ...@@ -141,6 +141,7 @@ static const struct hwseq_private_funcs dcn32_private_funcs = {
.program_mall_pipe_config = dcn32_program_mall_pipe_config, .program_mall_pipe_config = dcn32_program_mall_pipe_config,
.subvp_update_force_pstate = dcn32_subvp_update_force_pstate, .subvp_update_force_pstate = dcn32_subvp_update_force_pstate,
.update_mall_sel = dcn32_update_mall_sel, .update_mall_sel = dcn32_update_mall_sel,
.calculate_dccg_k1_k2_values = dcn32_calculate_dccg_k1_k2_values,
}; };
void dcn32_hw_sequencer_init_functions(struct dc *dc) void dcn32_hw_sequencer_init_functions(struct dc *dc)
......
...@@ -59,7 +59,8 @@ enum dentist_dispclk_change_mode { ...@@ -59,7 +59,8 @@ enum dentist_dispclk_change_mode {
enum pixel_rate_div { enum pixel_rate_div {
PIXEL_RATE_DIV_BY_1 = 0, PIXEL_RATE_DIV_BY_1 = 0,
PIXEL_RATE_DIV_BY_2 = 1, PIXEL_RATE_DIV_BY_2 = 1,
PIXEL_RATE_DIV_BY_4 = 3 PIXEL_RATE_DIV_BY_4 = 3,
PIXEL_RATE_DIV_NA = 0xF
}; };
struct dccg { struct dccg {
......
...@@ -247,6 +247,9 @@ struct stream_encoder_funcs { ...@@ -247,6 +247,9 @@ struct stream_encoder_funcs {
uint32_t (*get_fifo_cal_average_level)( uint32_t (*get_fifo_cal_average_level)(
struct stream_encoder *enc); struct stream_encoder *enc);
void (*set_input_mode)(
struct stream_encoder *enc, unsigned int pix_per_container);
}; };
struct hpo_dp_stream_encoder_state { struct hpo_dp_stream_encoder_state {
......
...@@ -149,6 +149,9 @@ struct hwseq_private_funcs { ...@@ -149,6 +149,9 @@ struct hwseq_private_funcs {
void (*program_mall_pipe_config)(struct dc *dc, struct dc_state *context); void (*program_mall_pipe_config)(struct dc *dc, struct dc_state *context);
void (*subvp_update_force_pstate)(struct dc *dc, struct dc_state *context); void (*subvp_update_force_pstate)(struct dc *dc, struct dc_state *context);
void (*update_mall_sel)(struct dc *dc, struct dc_state *context); void (*update_mall_sel)(struct dc *dc, struct dc_state *context);
unsigned int (*calculate_dccg_k1_k2_values)(struct pipe_ctx *pipe_ctx,
unsigned int *k1_div,
unsigned int *k2_div);
#endif #endif
}; };
......
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