mirror of
https://github.com/torvalds/linux.git
synced 2026-05-26 16:12:59 +02:00
drm/amd/display: Add 3DLUT DMA broadcast support
[WHY&HOW] A single HUBP can be used to fetch 3DLUT and broadcast to a single HUBP. Add logic to select the top pipe for a given plane and use it's HUBP as the broadcast source for multiple MPC's. Reviewed-by: Ilya Bakoulin <ilya.bakoulin@amd.com> Signed-off-by: Dillon Varone <Dillon.Varone@amd.com> Signed-off-by: Chuanyu Tseng <chuanyu.tseng@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
60e8ffaf96
commit
7d59465de3
|
|
@ -4617,7 +4617,7 @@ static void commit_planes_for_stream(struct dc *dc,
|
||||||
srf_updates[i].cm->flags.bits.lut3d_enable &&
|
srf_updates[i].cm->flags.bits.lut3d_enable &&
|
||||||
srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
|
srf_updates[i].cm->flags.bits.lut3d_dma_enable &&
|
||||||
dc->hwss.trigger_3dlut_dma_load)
|
dc->hwss.trigger_3dlut_dma_load)
|
||||||
dc->hwss.trigger_3dlut_dma_load(dc, pipe_ctx);
|
dc->hwss.trigger_3dlut_dma_load(pipe_ctx);
|
||||||
|
|
||||||
/*program triple buffer after lock based on flip type*/
|
/*program triple buffer after lock based on flip type*/
|
||||||
if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
|
if (dc->hwss.program_triplebuffer != NULL && dc->debug.enable_tri_buf) {
|
||||||
|
|
|
||||||
|
|
@ -369,12 +369,14 @@ void dcn401_init_hw(struct dc *dc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void dcn401_trigger_3dlut_dma_load(struct dc *dc, struct pipe_ctx *pipe_ctx)
|
void dcn401_trigger_3dlut_dma_load(struct pipe_ctx *pipe_ctx)
|
||||||
{
|
{
|
||||||
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
const struct pipe_ctx *primary_dpp_pipe_ctx = resource_get_primary_dpp_pipe(pipe_ctx);
|
||||||
|
struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
|
||||||
|
primary_dpp_pipe_ctx->plane_res.hubp : NULL;
|
||||||
|
|
||||||
if (hubp->funcs->hubp_enable_3dlut_fl) {
|
if (primary_hubp && primary_hubp->funcs->hubp_enable_3dlut_fl) {
|
||||||
hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
|
primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -382,8 +384,11 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
|
||||||
const struct dc_plane_state *plane_state)
|
const struct dc_plane_state *plane_state)
|
||||||
{
|
{
|
||||||
struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
|
struct dc *dc = pipe_ctx->plane_res.hubp->ctx->dc;
|
||||||
|
const struct pipe_ctx *primary_dpp_pipe_ctx = resource_get_primary_dpp_pipe(pipe_ctx);
|
||||||
struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
|
struct dpp *dpp_base = pipe_ctx->plane_res.dpp;
|
||||||
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
struct hubp *hubp = pipe_ctx->plane_res.hubp;
|
||||||
|
struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
|
||||||
|
primary_dpp_pipe_ctx->plane_res.hubp : NULL;
|
||||||
const struct dc_plane_cm *cm = &plane_state->cm;
|
const struct dc_plane_cm *cm = &plane_state->cm;
|
||||||
int mpcc_id = hubp->inst;
|
int mpcc_id = hubp->inst;
|
||||||
struct mpc *mpc = dc->res_pool->mpc;
|
struct mpc *mpc = dc->res_pool->mpc;
|
||||||
|
|
@ -481,25 +486,41 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
|
||||||
mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, 12, mpcc_id);
|
mpc->funcs->program_lut_read_write_control(mpc, MCM_LUT_3DLUT, lut_bank_a, 12, mpcc_id);
|
||||||
|
|
||||||
if (mpc->funcs->update_3dlut_fast_load_select)
|
if (mpc->funcs->update_3dlut_fast_load_select)
|
||||||
mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, hubp->inst);
|
mpc->funcs->update_3dlut_fast_load_select(mpc, mpcc_id, primary_hubp->inst);
|
||||||
|
|
||||||
/* HUBP */
|
/* HUBP */
|
||||||
if (hubp->funcs->hubp_program_3dlut_fl_config)
|
if (primary_hubp->inst == hubp->inst) {
|
||||||
hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
|
/* only program if this is the primary dpp pipe for the given plane */
|
||||||
|
if (hubp->funcs->hubp_program_3dlut_fl_config)
|
||||||
|
hubp->funcs->hubp_program_3dlut_fl_config(hubp, &cm->lut3d_dma);
|
||||||
|
|
||||||
if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
|
if (hubp->funcs->hubp_program_3dlut_fl_crossbar)
|
||||||
hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format);
|
hubp->funcs->hubp_program_3dlut_fl_crossbar(hubp, cm->lut3d_dma.format);
|
||||||
|
|
||||||
if (hubp->funcs->hubp_program_3dlut_fl_addr)
|
if (hubp->funcs->hubp_program_3dlut_fl_addr)
|
||||||
hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
|
hubp->funcs->hubp_program_3dlut_fl_addr(hubp, &cm->lut3d_dma.addr);
|
||||||
|
|
||||||
if (hubp->funcs->hubp_enable_3dlut_fl) {
|
if (hubp->funcs->hubp_enable_3dlut_fl) {
|
||||||
hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
|
hubp->funcs->hubp_enable_3dlut_fl(hubp, true);
|
||||||
|
} else {
|
||||||
|
/* GPU memory only supports fast load path */
|
||||||
|
BREAK_TO_DEBUGGER();
|
||||||
|
lut_enable = false;
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
/* GPU memory only supports fast load path */
|
/* re-trigger priamry HUBP to load 3DLUT */
|
||||||
BREAK_TO_DEBUGGER();
|
if (primary_hubp->funcs->hubp_enable_3dlut_fl) {
|
||||||
lut_enable = false;
|
primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
|
||||||
result = false;
|
}
|
||||||
|
|
||||||
|
/* clear FL setup on this pipe's HUBP */
|
||||||
|
memset(&lut3d_dma, 0, sizeof(lut3d_dma));
|
||||||
|
if (hubp->funcs->hubp_program_3dlut_fl_config)
|
||||||
|
hubp->funcs->hubp_program_3dlut_fl_config(hubp, &lut3d_dma);
|
||||||
|
|
||||||
|
if (hubp->funcs->hubp_enable_3dlut_fl)
|
||||||
|
hubp->funcs->hubp_enable_3dlut_fl(hubp, false);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
/* Legacy (Host) Load Mode */
|
/* Legacy (Host) Load Mode */
|
||||||
|
|
@ -1809,42 +1830,41 @@ void dcn401_perform_3dlut_wa_unlock(struct pipe_ctx *pipe_ctx)
|
||||||
* This is meant to work around a known HW issue where VREADY will cancel the pending 3DLUT_ENABLE signal regardless
|
* This is meant to work around a known HW issue where VREADY will cancel the pending 3DLUT_ENABLE signal regardless
|
||||||
* of whether OTG lock is currently being held or not.
|
* of whether OTG lock is currently being held or not.
|
||||||
*/
|
*/
|
||||||
struct pipe_ctx *wa_pipes[MAX_PIPES] = { NULL };
|
const struct pipe_ctx *otg_master_pipe_ctx = resource_get_otg_master(pipe_ctx);
|
||||||
struct pipe_ctx *odm_pipe, *mpc_pipe;
|
struct timing_generator *tg = otg_master_pipe_ctx ?
|
||||||
int i, wa_pipe_ct = 0;
|
otg_master_pipe_ctx->stream_res.tg : NULL;
|
||||||
|
const struct pipe_ctx *primary_dpp_pipe_ctx = resource_is_pipe_type(pipe_ctx, DPP_PIPE) ?
|
||||||
|
resource_get_primary_dpp_pipe(pipe_ctx) : pipe_ctx;
|
||||||
|
struct hubp *primary_hubp = primary_dpp_pipe_ctx ?
|
||||||
|
primary_dpp_pipe_ctx->plane_res.hubp : NULL;
|
||||||
|
|
||||||
for (odm_pipe = pipe_ctx; odm_pipe != NULL; odm_pipe = odm_pipe->next_odm_pipe) {
|
if (!otg_master_pipe_ctx && !tg) {
|
||||||
for (mpc_pipe = odm_pipe; mpc_pipe != NULL; mpc_pipe = mpc_pipe->bottom_pipe) {
|
return;
|
||||||
if (mpc_pipe->plane_state &&
|
|
||||||
mpc_pipe->plane_state->cm.flags.bits.lut3d_enable &&
|
|
||||||
mpc_pipe->plane_state->cm.flags.bits.lut3d_dma_enable) {
|
|
||||||
wa_pipes[wa_pipe_ct++] = mpc_pipe;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (wa_pipe_ct > 0) {
|
if (primary_dpp_pipe_ctx &&
|
||||||
if (pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout)
|
primary_dpp_pipe_ctx->plane_state &&
|
||||||
pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout(pipe_ctx->stream_res.tg, true);
|
primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_enable &&
|
||||||
|
primary_dpp_pipe_ctx->plane_state->cm.flags.bits.lut3d_dma_enable) {
|
||||||
|
if (tg->funcs->set_vupdate_keepout)
|
||||||
|
tg->funcs->set_vupdate_keepout(tg, true);
|
||||||
|
|
||||||
for (i = 0; i < wa_pipe_ct; ++i) {
|
if (primary_hubp->funcs->hubp_enable_3dlut_fl) {
|
||||||
if (wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl)
|
primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
|
||||||
wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl(wa_pipes[i]->plane_res.hubp, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
|
tg->funcs->unlock(tg);
|
||||||
if (pipe_ctx->stream_res.tg->funcs->wait_update_lock_status)
|
if (tg->funcs->wait_update_lock_status)
|
||||||
pipe_ctx->stream_res.tg->funcs->wait_update_lock_status(pipe_ctx->stream_res.tg, false);
|
tg->funcs->wait_update_lock_status(tg, false);
|
||||||
|
|
||||||
for (i = 0; i < wa_pipe_ct; ++i) {
|
if (primary_hubp->funcs->hubp_enable_3dlut_fl) {
|
||||||
if (wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl)
|
primary_hubp->funcs->hubp_enable_3dlut_fl(primary_hubp, true);
|
||||||
wa_pipes[i]->plane_res.hubp->funcs->hubp_enable_3dlut_fl(wa_pipes[i]->plane_res.hubp, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout)
|
if (tg->funcs->set_vupdate_keepout)
|
||||||
pipe_ctx->stream_res.tg->funcs->set_vupdate_keepout(pipe_ctx->stream_res.tg, false);
|
tg->funcs->set_vupdate_keepout(tg, false);
|
||||||
} else {
|
} else {
|
||||||
pipe_ctx->stream_res.tg->funcs->unlock(pipe_ctx->stream_res.tg);
|
tg->funcs->unlock(tg);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -41,8 +41,7 @@ bool dcn401_set_mcm_luts(struct pipe_ctx *pipe_ctx,
|
||||||
bool dcn401_set_output_transfer_func(struct dc *dc,
|
bool dcn401_set_output_transfer_func(struct dc *dc,
|
||||||
struct pipe_ctx *pipe_ctx,
|
struct pipe_ctx *pipe_ctx,
|
||||||
const struct dc_stream_state *stream);
|
const struct dc_stream_state *stream);
|
||||||
void dcn401_trigger_3dlut_dma_load(struct dc *dc,
|
void dcn401_trigger_3dlut_dma_load(struct pipe_ctx *pipe_ctx);
|
||||||
struct pipe_ctx *pipe_ctx);
|
|
||||||
void dcn401_calculate_dccg_tmds_div_value(struct pipe_ctx *pipe_ctx,
|
void dcn401_calculate_dccg_tmds_div_value(struct pipe_ctx *pipe_ctx,
|
||||||
unsigned int *tmds_div);
|
unsigned int *tmds_div);
|
||||||
enum dc_status dcn401_enable_stream_timing(
|
enum dc_status dcn401_enable_stream_timing(
|
||||||
|
|
|
||||||
|
|
@ -1120,7 +1120,7 @@ struct hw_sequencer_funcs {
|
||||||
void (*program_output_csc)(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
void (*program_output_csc)(struct dc *dc, struct pipe_ctx *pipe_ctx,
|
||||||
enum dc_color_space colorspace,
|
enum dc_color_space colorspace,
|
||||||
uint16_t *matrix, int opp_id);
|
uint16_t *matrix, int opp_id);
|
||||||
void (*trigger_3dlut_dma_load)(struct dc *dc, struct pipe_ctx *pipe_ctx);
|
void (*trigger_3dlut_dma_load)(struct pipe_ctx *pipe_ctx);
|
||||||
|
|
||||||
/* VM Related */
|
/* VM Related */
|
||||||
int (*init_sys_ctx)(struct dce_hwseq *hws,
|
int (*init_sys_ctx)(struct dce_hwseq *hws,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user