Skip to content

Commit

Permalink
drm/amd/display: add support for DTO genarated dscclk
Browse files Browse the repository at this point in the history
[ Upstream commit 08a32ad ]

Current implementation will choose to use refclk as dscclk. This is not
recommended by hardware team as refclk is a fixed value which could
cause unnecessary power consumption or it could be not enough for large
DSC timings. So we are adding new interfaces so we could switch to use
dynamically generated DSCCLK by DTO. So DSCCLK is programmable based on
current pixel clock and dispclk.

Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Reviewed-by: Chaitanya Dhere <chaitanya.dhere@amd.com>
Acked-by: Rodrigo Siqueira <rodrigo.siqueira@amd.com>
Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
Signed-off-by: Sasha Levin <sashal@kernel.org>
  • Loading branch information
Wenjing Liu authored and gregkh committed Feb 5, 2024
1 parent 89824a0 commit 17ba4ac
Show file tree
Hide file tree
Showing 3 changed files with 55 additions and 1 deletion.
25 changes: 25 additions & 0 deletions drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c
Expand Up @@ -995,9 +995,22 @@ static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
{
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
struct dccg *dccg = dc->res_pool->dccg;
/* It has been found that when DSCCLK is lower than 16Mhz, we will get DCN
* register access hung. When DSCCLk is based on refclk, DSCCLk is always a
* fixed value higher than 16Mhz so the issue doesn't occur. When DSCCLK is
* generated by DTO, DSCCLK would be based on 1/3 dispclk. For small timings
* with DSC such as 480p60Hz, the dispclk could be low enough to trigger
* this problem. We are implementing a workaround here to keep using dscclk
* based on fixed value refclk when timing is smaller than 3x16Mhz (i.e
* 48Mhz) pixel clock to avoid hitting this problem.
*/
bool should_use_dto_dscclk = (dccg->funcs->set_dto_dscclk != NULL) &&
stream->timing.pix_clk_100hz > 480000;

ASSERT(dsc);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
Expand All @@ -1020,12 +1033,16 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)

dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;

ASSERT(odm_dsc);
odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
dsc_cfg.pic_width *= opp_cnt;
Expand All @@ -1045,9 +1062,13 @@ static void update_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
OPTC_DSC_DISABLED, 0, 0);

/* disable DSC block */
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, pipe_ctx->stream_res.dsc->inst);
dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
ASSERT(odm_pipe->stream_res.dsc);
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);
odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
}
}
Expand Down Expand Up @@ -1130,6 +1151,10 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
if (!pipe_ctx->next_odm_pipe && current_pipe_ctx->next_odm_pipe &&
current_pipe_ctx->next_odm_pipe->stream_res.dsc) {
struct display_stream_compressor *dsc = current_pipe_ctx->next_odm_pipe->stream_res.dsc;
struct dccg *dccg = dc->res_pool->dccg;

if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, dsc->inst);
/* disconnect DSC block from stream */
dsc->funcs->dsc_disconnect(dsc);
}
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/amd/display/dc/inc/hw/dccg.h
Expand Up @@ -201,6 +201,10 @@ struct dccg_funcs {
struct dccg *dccg,
enum streamclk_source src,
uint32_t otg_inst);
void (*set_dto_dscclk)(
struct dccg *dccg,
uint32_t dsc_inst);
void (*set_ref_dscclk)(struct dccg *dccg, uint32_t dsc_inst);
};

#endif //__DAL_DCCG_H__
27 changes: 26 additions & 1 deletion drivers/gpu/drm/amd/display/dc/link/link_dpms.c
Expand Up @@ -776,10 +776,26 @@ static bool dp_set_dsc_on_rx(struct pipe_ctx *pipe_ctx, bool enable)
*/
void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
{
/* TODO: Move this to HWSS as this is hardware programming sequence not a
* link layer sequence
*/
struct display_stream_compressor *dsc = pipe_ctx->stream_res.dsc;
struct dc *dc = pipe_ctx->stream->ctx->dc;
struct dc_stream_state *stream = pipe_ctx->stream;
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
struct dccg *dccg = dc->res_pool->dccg;
/* It has been found that when DSCCLK is lower than 16Mhz, we will get DCN
* register access hung. When DSCCLk is based on refclk, DSCCLk is always a
* fixed value higher than 16Mhz so the issue doesn't occur. When DSCCLK is
* generated by DTO, DSCCLK would be based on 1/3 dispclk. For small timings
* with DSC such as 480p60Hz, the dispclk could be low enough to trigger
* this problem. We are implementing a workaround here to keep using dscclk
* based on fixed value refclk when timing is smaller than 3x16Mhz (i.e
* 48Mhz) pixel clock to avoid hitting this problem.
*/
bool should_use_dto_dscclk = (dccg->funcs->set_dto_dscclk != NULL) &&
stream->timing.pix_clk_100hz > 480000;
DC_LOGGER_INIT(dsc->ctx->logger);

for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
Expand All @@ -802,11 +818,15 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)

dsc->funcs->dsc_set_config(dsc, &dsc_cfg, &dsc_optc_cfg);
dsc->funcs->dsc_enable(dsc, pipe_ctx->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, dsc->inst);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
struct display_stream_compressor *odm_dsc = odm_pipe->stream_res.dsc;

odm_dsc->funcs->dsc_set_config(odm_dsc, &dsc_cfg, &dsc_optc_cfg);
odm_dsc->funcs->dsc_enable(odm_dsc, odm_pipe->stream_res.opp->inst);
if (should_use_dto_dscclk)
dccg->funcs->set_dto_dscclk(dccg, odm_dsc->inst);
}
dsc_cfg.dc_dsc_cfg.num_slices_h *= opp_cnt;
dsc_cfg.pic_width *= opp_cnt;
Expand Down Expand Up @@ -856,9 +876,14 @@ void link_set_dsc_on_stream(struct pipe_ctx *pipe_ctx, bool enable)
}

/* disable DSC block */
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, pipe_ctx->stream_res.dsc->inst);
pipe_ctx->stream_res.dsc->funcs->dsc_disable(pipe_ctx->stream_res.dsc);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
if (dccg->funcs->set_ref_dscclk)
dccg->funcs->set_ref_dscclk(dccg, odm_pipe->stream_res.dsc->inst);
odm_pipe->stream_res.dsc->funcs->dsc_disable(odm_pipe->stream_res.dsc);
}
}
}

Expand Down

0 comments on commit 17ba4ac

Please sign in to comment.