Commit cfe4645e authored by Dmytro Laktyushkin's avatar Dmytro Laktyushkin Committed by Alex Deucher

drm/amd/display: fix dcn pipe reset sequence

This change fixes dcn10 front end reset sequence. Previously we
would reset front end during flip which led to issues
in certain MPO and 4k/5k scenarios. We would also never properly
power gate our front end.
Signed-off-by: default avatarDmytro Laktyushkin <Dmytro.Laktyushkin@amd.com>
Reviewed-by: default avatarCharlene Liu <Charlene.Liu@amd.com>
Acked-by: default avatarHarry Wentland <Harry.Wentland@amd.com>
Signed-off-by: default avatarAlex Deucher <alexander.deucher@amd.com>
parent 7f524a0d
...@@ -2380,7 +2380,7 @@ static void amdgpu_dm_do_flip( ...@@ -2380,7 +2380,7 @@ static void amdgpu_dm_do_flip(
surface_updates->flip_addr = &addr; surface_updates->flip_addr = &addr;
dc_update_surfaces_for_stream(adev->dm.dc, surface_updates, 1, acrtc->stream); dc_update_surfaces_and_stream(adev->dm.dc, surface_updates, 1, acrtc->stream, NULL);
DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n", DRM_DEBUG_DRIVER("%s Flipping to hi: 0x%x, low: 0x%x \n",
__func__, __func__,
......
...@@ -511,12 +511,14 @@ static void split_stream_across_pipes( ...@@ -511,12 +511,14 @@ static void split_stream_across_pipes(
struct pipe_ctx *primary_pipe, struct pipe_ctx *primary_pipe,
struct pipe_ctx *secondary_pipe) struct pipe_ctx *secondary_pipe)
{ {
int pipe_idx = secondary_pipe->pipe_idx;
if (!primary_pipe->surface) if (!primary_pipe->surface)
return; return;
secondary_pipe->stream = primary_pipe->stream; *secondary_pipe = *primary_pipe;
secondary_pipe->tg = primary_pipe->tg;
secondary_pipe->pipe_idx = pipe_idx;
secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx]; secondary_pipe->mpcc = pool->mpcc[secondary_pipe->pipe_idx];
secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx]; secondary_pipe->mi = pool->mis[secondary_pipe->pipe_idx];
secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx]; secondary_pipe->ipp = pool->ipps[secondary_pipe->pipe_idx];
...@@ -528,8 +530,6 @@ static void split_stream_across_pipes( ...@@ -528,8 +530,6 @@ static void split_stream_across_pipes(
} }
primary_pipe->bottom_pipe = secondary_pipe; primary_pipe->bottom_pipe = secondary_pipe;
secondary_pipe->top_pipe = primary_pipe; secondary_pipe->top_pipe = primary_pipe;
secondary_pipe->surface = primary_pipe->surface;
secondary_pipe->pipe_dlg_param = primary_pipe->pipe_dlg_param;
resource_build_scaling_params(primary_pipe); resource_build_scaling_params(primary_pipe);
resource_build_scaling_params(secondary_pipe); resource_build_scaling_params(secondary_pipe);
...@@ -1011,10 +1011,13 @@ bool dcn_validate_bandwidth( ...@@ -1011,10 +1011,13 @@ bool dcn_validate_bandwidth(
dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe); dcn_bw_calc_rq_dlg_ttu(dc, v, hsplit_pipe);
} else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) { } else if (hsplit_pipe && hsplit_pipe->surface == pipe->surface) {
/* merge previously split pipe */ /* merge previously split pipe */
if (pipe->bottom_pipe->bottom_pipe) pipe->bottom_pipe = hsplit_pipe->bottom_pipe;
pipe->bottom_pipe->bottom_pipe->top_pipe = pipe; if (hsplit_pipe->bottom_pipe)
memset(pipe->bottom_pipe, 0, sizeof(*pipe->bottom_pipe)); hsplit_pipe->bottom_pipe->top_pipe = pipe;
pipe->bottom_pipe = pipe->bottom_pipe->bottom_pipe; hsplit_pipe->surface = NULL;
hsplit_pipe->stream = NULL;
hsplit_pipe->top_pipe = NULL;
hsplit_pipe->bottom_pipe = NULL;
resource_build_scaling_params(pipe); resource_build_scaling_params(pipe);
} }
/* for now important to do this after pipe split for building e2e params */ /* for now important to do this after pipe split for building e2e params */
......
...@@ -963,11 +963,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc) ...@@ -963,11 +963,8 @@ bool dc_post_update_surfaces_to_stream(struct dc *dc)
for (i = 0; i < core_dc->res_pool->pipe_count; i++) for (i = 0; i < core_dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].stream == NULL if (context->res_ctx.pipe_ctx[i].stream == NULL
|| context->res_ctx.pipe_ctx[i].surface == NULL) { || context->res_ctx.pipe_ctx[i].surface == NULL)
context->res_ctx.pipe_ctx[i].pipe_idx = i; core_dc->hwss.power_down_front_end(core_dc, i);
core_dc->hwss.power_down_front_end(
core_dc, &context->res_ctx.pipe_ctx[i]);
}
/* 3rd param should be true, temp w/a for RV*/ /* 3rd param should be true, temp w/a for RV*/
#if defined(CONFIG_DRM_AMD_DC_DCN1_0) #if defined(CONFIG_DRM_AMD_DC_DCN1_0)
...@@ -989,7 +986,6 @@ bool dc_commit_surfaces_to_stream( ...@@ -989,7 +986,6 @@ bool dc_commit_surfaces_to_stream(
struct dc_plane_info plane_info[MAX_SURFACES]; struct dc_plane_info plane_info[MAX_SURFACES];
struct dc_scaling_info scaling_info[MAX_SURFACES]; struct dc_scaling_info scaling_info[MAX_SURFACES];
int i; int i;
bool ret;
struct dc_stream_update *stream_update = struct dc_stream_update *stream_update =
dm_alloc(sizeof(struct dc_stream_update)); dm_alloc(sizeof(struct dc_stream_update));
...@@ -1038,10 +1034,10 @@ bool dc_commit_surfaces_to_stream( ...@@ -1038,10 +1034,10 @@ bool dc_commit_surfaces_to_stream(
new_surface_count, new_surface_count,
dc_stream, stream_update); dc_stream, stream_update);
ret = dc_post_update_surfaces_to_stream(dc); dc_post_update_surfaces_to_stream(dc);
dm_free(stream_update); dm_free(stream_update);
return ret; return true;
} }
static bool is_surface_in_context( static bool is_surface_in_context(
...@@ -1217,14 +1213,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream( ...@@ -1217,14 +1213,6 @@ enum surface_update_type dc_check_update_surfaces_for_stream(
return overall_type; return overall_type;
} }
void dc_update_surfaces_for_stream(struct dc *dc,
struct dc_surface_update *surface_updates, int surface_count,
const struct dc_stream *dc_stream)
{
dc_update_surfaces_and_stream(dc, surface_updates, surface_count,
dc_stream, NULL);
}
enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL; enum surface_update_type update_surface_trace_level = UPDATE_TYPE_FULL;
void dc_update_surfaces_and_stream(struct dc *dc, void dc_update_surfaces_and_stream(struct dc *dc,
...@@ -1401,7 +1389,7 @@ void dc_update_surfaces_and_stream(struct dc *dc, ...@@ -1401,7 +1389,7 @@ void dc_update_surfaces_and_stream(struct dc *dc,
} }
} }
if (!surface_count) /* reset */ if (surface_count == 0)
core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context); core_dc->hwss.apply_ctx_for_surface(core_dc, NULL, context);
/* Lock pipes for provided surfaces, or all active if full update*/ /* Lock pipes for provided surfaces, or all active if full update*/
......
...@@ -1096,6 +1096,10 @@ bool resource_attach_surfaces_to_context( ...@@ -1096,6 +1096,10 @@ bool resource_attach_surfaces_to_context(
free_pipe->surface = surface; free_pipe->surface = surface;
if (tail_pipe) { if (tail_pipe) {
free_pipe->tg = tail_pipe->tg;
free_pipe->stream_enc = tail_pipe->stream_enc;
free_pipe->audio = tail_pipe->audio;
free_pipe->clock_source = tail_pipe->clock_source;
free_pipe->top_pipe = tail_pipe; free_pipe->top_pipe = tail_pipe;
tail_pipe->bottom_pipe = free_pipe; tail_pipe->bottom_pipe = free_pipe;
} }
...@@ -2300,6 +2304,9 @@ bool pipe_need_reprogram( ...@@ -2300,6 +2304,9 @@ bool pipe_need_reprogram(
struct pipe_ctx *pipe_ctx_old, struct pipe_ctx *pipe_ctx_old,
struct pipe_ctx *pipe_ctx) struct pipe_ctx *pipe_ctx)
{ {
if (!pipe_ctx_old->stream)
return false;
if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink) if (pipe_ctx_old->stream->sink != pipe_ctx->stream->sink)
return true; return true;
......
...@@ -415,9 +415,6 @@ bool dc_commit_surfaces_to_stream( ...@@ -415,9 +415,6 @@ bool dc_commit_surfaces_to_stream(
bool dc_post_update_surfaces_to_stream( bool dc_post_update_surfaces_to_stream(
struct dc *dc); struct dc *dc);
void dc_update_surfaces_for_stream(struct dc *dc, struct dc_surface_update *updates,
int surface_count, const struct dc_stream *stream);
/* Surface update type is used by dc_update_surfaces_and_stream /* Surface update type is used by dc_update_surfaces_and_stream
* The update type is determined at the very beginning of the function based * The update type is determined at the very beginning of the function based
* on parameters passed in and decides how much programming (or updating) is * on parameters passed in and decides how much programming (or updating) is
......
...@@ -1185,8 +1185,7 @@ static void disable_vga_and_power_gate_all_controllers( ...@@ -1185,8 +1185,7 @@ static void disable_vga_and_power_gate_all_controllers(
enable_display_pipe_clock_gating(ctx, enable_display_pipe_clock_gating(ctx,
true); true);
dc->hwss.power_down_front_end( dc->hwss.power_down_front_end(dc, i);
dc, &dc->current_context->res_ctx.pipe_ctx[i]);
} }
} }
...@@ -1340,7 +1339,7 @@ static void reset_single_pipe_hw_ctx( ...@@ -1340,7 +1339,7 @@ static void reset_single_pipe_hw_ctx(
resource_unreference_clock_source(&context->res_ctx, dc->res_pool, resource_unreference_clock_source(&context->res_ctx, dc->res_pool,
&pipe_ctx->clock_source); &pipe_ctx->clock_source);
dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx); dc->hwss.power_down_front_end((struct core_dc *)dc, pipe_ctx->pipe_idx);
pipe_ctx->stream = NULL; pipe_ctx->stream = NULL;
} }
...@@ -2538,17 +2537,17 @@ static void dce110_apply_ctx_for_surface( ...@@ -2538,17 +2537,17 @@ static void dce110_apply_ctx_for_surface(
} }
} }
static void dce110_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe) static void dce110_power_down_fe(struct core_dc *dc, int fe_idx)
{ {
/* Do not power down fe when stream is active on dce*/ /* Do not power down fe when stream is active on dce*/
if (pipe->stream) if (dc->current_context->res_ctx.pipe_ctx[fe_idx].stream)
return; return;
dc->hwss.enable_display_power_gating( dc->hwss.enable_display_power_gating(
dc, pipe->pipe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE); dc, fe_idx, dc->ctx->dc_bios, PIPE_GATING_CONTROL_ENABLE);
if (pipe->xfm)
pipe->xfm->funcs->transform_reset(pipe->xfm); dc->res_pool->transforms[fe_idx]->funcs->transform_reset(
memset(&pipe->scl_data, 0, sizeof(struct scaler_data)); dc->res_pool->transforms[fe_idx]);
} }
static const struct hw_sequencer_funcs dce110_funcs = { static const struct hw_sequencer_funcs dce110_funcs = {
......
...@@ -116,18 +116,6 @@ static const struct dcn10_hwseq_reg_offsets reg_offsets[] = { ...@@ -116,18 +116,6 @@ static const struct dcn10_hwseq_reg_offsets reg_offsets[] = {
HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val) HWSEQ_REG_SET_N(reg, 1, FD(reg##__##field), val)
/* TODO should be moved to OTG */ /* TODO should be moved to OTG */
static void lock_otg_master_update(
struct dc_context *ctx,
uint8_t inst)
{
uint32_t inst_offset = reg_offsets[inst].otg;
HWSEQ_REG_UPDATE(OTG0_OTG_GLOBAL_CONTROL0,
OTG_MASTER_UPDATE_LOCK_SEL, inst);
HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
OTG_MASTER_UPDATE_LOCK, 1);
}
static bool unlock_master_tg_and_wait( static bool unlock_master_tg_and_wait(
struct dc_context *ctx, struct dc_context *ctx,
...@@ -148,19 +136,6 @@ static bool unlock_master_tg_and_wait( ...@@ -148,19 +136,6 @@ static bool unlock_master_tg_and_wait(
return true; return true;
} }
/* TODO: should be moved to OTG ? */
static void unlock_otg_master(
struct dc_context *ctx,
uint8_t inst)
{
uint32_t inst_offset = reg_offsets[inst].otg;
/* unlock master locker */
HWSEQ_REG_UPDATE(OTG0_OTG_MASTER_UPDATE_LOCK,
OTG_MASTER_UPDATE_LOCK, 0);
}
static void wait_no_outstanding_request( static void wait_no_outstanding_request(
struct dc_context *ctx, struct dc_context *ctx,
uint8_t plane_id) uint8_t plane_id)
...@@ -489,8 +464,7 @@ static void hubp_pg_control( ...@@ -489,8 +464,7 @@ static void hubp_pg_control(
static void power_on_plane( static void power_on_plane(
struct dc_context *ctx, struct dc_context *ctx,
uint8_t plane_id, int plane_id)
uint8_t inst)
{ {
uint32_t inst_offset = 0; uint32_t inst_offset = 0;
...@@ -500,6 +474,8 @@ static void power_on_plane( ...@@ -500,6 +474,8 @@ static void power_on_plane(
hubp_pg_control(ctx, plane_id, true); hubp_pg_control(ctx, plane_id, true);
HWSEQ_REG_SET(DC_IP_REQUEST_CNTL, HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
IP_REQUEST_EN, 0); IP_REQUEST_EN, 0);
dm_logger_write(ctx->logger, LOG_DC,
"Un-gated front end for pipe %d\n", plane_id);
} }
/* fully check bios enabledisplaypowergating table. dal only need dce init /* fully check bios enabledisplaypowergating table. dal only need dce init
...@@ -596,13 +572,13 @@ static void init_hw(struct core_dc *dc) ...@@ -596,13 +572,13 @@ static void init_hw(struct core_dc *dc)
dc->res_pool->mpcc[i]; dc->res_pool->mpcc[i];
struct mpcc_cfg mpcc_cfg; struct mpcc_cfg mpcc_cfg;
lock_otg_master_update(dc->ctx, tg->inst); tg->funcs->lock(tg);
mpcc_cfg.opp_id = 0xf; mpcc_cfg.opp_id = 0xf;
mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf;
mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf;
mpcc_cfg.top_of_tree = true; mpcc_cfg.top_of_tree = true;
mpcc->funcs->set(mpcc, &mpcc_cfg); mpcc->funcs->set(mpcc, &mpcc_cfg);
unlock_otg_master(dc->ctx, tg->inst); tg->funcs->unlock(tg);
tg->funcs->disable_vga(tg); tg->funcs->disable_vga(tg);
/* Blank controller using driver code instead of /* Blank controller using driver code instead of
...@@ -822,56 +798,85 @@ static void reset_back_end_for_pipe( ...@@ -822,56 +798,85 @@ static void reset_back_end_for_pipe(
return; return;
pipe_ctx->stream = NULL; pipe_ctx->stream = NULL;
dm_logger_write(dc->ctx->logger, LOG_DC,
"Reset back end for pipe %d, tg:%d\n",
pipe_ctx->pipe_idx, pipe_ctx->tg->inst);
} }
static void reset_front_end_for_pipe( static void reset_front_end(
struct core_dc *dc, struct core_dc *dc,
struct pipe_ctx *pipe_ctx, int fe_idx)
struct validate_context *context)
{ {
struct mpcc_cfg mpcc_cfg; struct mpcc_cfg mpcc_cfg;
struct mem_input *mi = dc->res_pool->mis[fe_idx];
struct transform *xfm = dc->res_pool->transforms[fe_idx];
struct mpcc *mpcc = dc->res_pool->mpcc[fe_idx];
struct timing_generator *tg = dc->res_pool->timing_generators[mpcc->opp_id];
if (!pipe_ctx->surface) /*Already reset*/
if (mpcc->opp_id == 0xf)
return; return;
pipe_ctx->mi->funcs->dcc_control(pipe_ctx->mi, false, false); mi->funcs->dcc_control(mi, false, false);
tg->funcs->lock(tg);
lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst);
mpcc_cfg.opp_id = 0xf; mpcc_cfg.opp_id = 0xf;
mpcc_cfg.top_dpp_id = 0xf; mpcc_cfg.top_dpp_id = 0xf;
mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf;
mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; mpcc_cfg.top_of_tree = tg->inst == mpcc->inst;
pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); mpcc->funcs->set(mpcc, &mpcc_cfg);
pipe_ctx->top_pipe = NULL;
pipe_ctx->bottom_pipe = NULL;
unlock_master_tg_and_wait(dc->ctx, pipe_ctx->tg->inst); unlock_master_tg_and_wait(dc->ctx, tg->inst);
mpcc->funcs->wait_for_idle(mpcc);
mi->funcs->set_blank(mi, true);
wait_no_outstanding_request(dc->ctx, fe_idx);
disable_clocks(dc->ctx, fe_idx);
pipe_ctx->mi->funcs->set_blank(pipe_ctx->mi, true); xfm->funcs->transform_reset(xfm);
wait_no_outstanding_request(dc->ctx, pipe_ctx->pipe_idx); dm_logger_write(dc->ctx->logger, LOG_DC,
"Reset front end %d\n",
fe_idx);
}
disable_clocks(dc->ctx, pipe_ctx->pipe_idx); static void dcn10_power_down_fe(struct core_dc *dc, int fe_idx)
{
struct dc_context *ctx = dc->ctx;
uint32_t inst_offset = 0;
pipe_ctx->xfm->funcs->transform_reset(pipe_ctx->xfm); reset_front_end(dc, fe_idx);
HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
IP_REQUEST_EN, 1);
dpp_pg_control(ctx, fe_idx, false);
hubp_pg_control(ctx, fe_idx, false);
HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
IP_REQUEST_EN, 0);
dm_logger_write(dc->ctx->logger, LOG_DC, dm_logger_write(dc->ctx->logger, LOG_DC,
"Reset front end for pipe %d\n", "Power gated front end %d\n", fe_idx);
pipe_ctx->pipe_idx);
pipe_ctx->surface = NULL;
} }
static void reset_hw_ctx(struct core_dc *dc, static void reset_hw_ctx_wrap(
struct validate_context *context, struct core_dc *dc,
void (*reset)(struct core_dc *dc, struct validate_context *context)
struct pipe_ctx *pipe_ctx,
struct validate_context *context))
{ {
int i; int i;
/* Reset Front End*/
for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
struct pipe_ctx *pipe_ctx_old =
&dc->current_context->res_ctx.pipe_ctx[i];
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
/*if (!pipe_ctx_old->stream)
continue;*/
if (!pipe_ctx->stream || !pipe_ctx->surface)
dcn10_power_down_fe(dc, i);
else if (pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
reset_front_end(dc, i);
}
/* Reset Back End*/
for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) { for (i = dc->res_pool->pipe_count - 1; i >= 0 ; i--) {
struct pipe_ctx *pipe_ctx_old = struct pipe_ctx *pipe_ctx_old =
&dc->current_context->res_ctx.pipe_ctx[i]; &dc->current_context->res_ctx.pipe_ctx[i];
...@@ -882,23 +887,13 @@ static void reset_hw_ctx(struct core_dc *dc, ...@@ -882,23 +887,13 @@ static void reset_hw_ctx(struct core_dc *dc,
if (!pipe_ctx->stream || if (!pipe_ctx->stream ||
pipe_need_reprogram(pipe_ctx_old, pipe_ctx)) pipe_need_reprogram(pipe_ctx_old, pipe_ctx))
reset(dc, pipe_ctx_old, dc->current_context); reset_back_end_for_pipe(dc, pipe_ctx_old, dc->current_context);
} }
} }
static void reset_hw_ctx_wrap(
struct core_dc *dc,
struct validate_context *context)
{
/* Reset Front End*/
reset_hw_ctx(dc, context, reset_front_end_for_pipe);
/* Reset Back End*/
reset_hw_ctx(dc, context, reset_back_end_for_pipe);
}
static bool patch_address_for_sbs_tb_stereo(
static bool patch_address_for_sbs_tb_stereo(struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx, PHYSICAL_ADDRESS_LOC *addr)
PHYSICAL_ADDRESS_LOC *addr)
{ {
struct core_surface *surface = pipe_ctx->surface; struct core_surface *surface = pipe_ctx->surface;
bool sec_split = pipe_ctx->top_pipe && bool sec_split = pipe_ctx->top_pipe &&
...@@ -936,8 +931,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct ...@@ -936,8 +931,7 @@ static void update_plane_addr(const struct core_dc *dc, struct pipe_ctx *pipe_ct
} }
static bool dcn10_set_input_transfer_func( static bool dcn10_set_input_transfer_func(
struct pipe_ctx *pipe_ctx, struct pipe_ctx *pipe_ctx, const struct core_surface *surface)
const struct core_surface *surface)
{ {
struct input_pixel_processor *ipp = pipe_ctx->ipp; struct input_pixel_processor *ipp = pipe_ctx->ipp;
const struct core_transfer_func *tf = NULL; const struct core_transfer_func *tf = NULL;
...@@ -1333,8 +1327,6 @@ static void dcn10_pipe_control_lock( ...@@ -1333,8 +1327,6 @@ static void dcn10_pipe_control_lock(
struct pipe_ctx *pipe, struct pipe_ctx *pipe,
bool lock) bool lock)
{ {
struct dce_hwseq *hws = hws = dc->hwseq;
/* use TG master update lock to lock everything on the TG /* use TG master update lock to lock everything on the TG
* therefore only top pipe need to lock * therefore only top pipe need to lock
*/ */
...@@ -1342,9 +1334,9 @@ static void dcn10_pipe_control_lock( ...@@ -1342,9 +1334,9 @@ static void dcn10_pipe_control_lock(
return; return;
if (lock) if (lock)
dcn10_lock(pipe->tg); pipe->tg->funcs->lock(pipe->tg);
else else
dcn10_unlock(pipe->tg); pipe->tg->funcs->unlock(pipe->tg);
} }
static bool wait_for_reset_trigger_to_occur( static bool wait_for_reset_trigger_to_occur(
...@@ -1543,7 +1535,7 @@ static void dcn10_power_on_fe( ...@@ -1543,7 +1535,7 @@ static void dcn10_power_on_fe(
struct dc_surface *dc_surface = &pipe_ctx->surface->public; struct dc_surface *dc_surface = &pipe_ctx->surface->public;
power_on_plane(dc->ctx, power_on_plane(dc->ctx,
pipe_ctx->pipe_idx, pipe_ctx->tg->inst); pipe_ctx->pipe_idx);
/* enable DCFCLK current DCHUB */ /* enable DCFCLK current DCHUB */
enable_dcfclk(dc->ctx, enable_dcfclk(dc->ctx,
...@@ -1694,7 +1686,6 @@ static void update_dchubp_dpp( ...@@ -1694,7 +1686,6 @@ static void update_dchubp_dpp(
struct default_adjustment ocsc = {0}; struct default_adjustment ocsc = {0};
struct tg_color black_color = {0}; struct tg_color black_color = {0};
struct mpcc_cfg mpcc_cfg; struct mpcc_cfg mpcc_cfg;
struct pipe_ctx *top_pipe;
bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe; bool per_pixel_alpha = surface->public.per_pixel_alpha && pipe_ctx->bottom_pipe;
/* TODO: proper fix once fpga works */ /* TODO: proper fix once fpga works */
...@@ -1734,14 +1725,13 @@ static void update_dchubp_dpp( ...@@ -1734,14 +1725,13 @@ static void update_dchubp_dpp(
IPP_OUTPUT_FORMAT_12_BIT_FIX); IPP_OUTPUT_FORMAT_12_BIT_FIX);
pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha; pipe_ctx->scl_data.lb_params.alpha_en = per_pixel_alpha;
for (top_pipe = pipe_ctx; top_pipe != NULL; top_pipe = top_pipe->top_pipe)
mpcc_cfg.opp_id = top_pipe->opp->inst;
mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx; mpcc_cfg.top_dpp_id = pipe_ctx->pipe_idx;
if (pipe_ctx->bottom_pipe) if (pipe_ctx->bottom_pipe)
mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst; mpcc_cfg.bot_mpcc_id = pipe_ctx->bottom_pipe->mpcc->inst;
else else
mpcc_cfg.bot_mpcc_id = 0xf; mpcc_cfg.bot_mpcc_id = 0xf;
mpcc_cfg.top_of_tree = !pipe_ctx->top_pipe; mpcc_cfg.opp_id = pipe_ctx->tg->inst;
mpcc_cfg.top_of_tree = pipe_ctx->pipe_idx == pipe_ctx->tg->inst;
mpcc_cfg.per_pixel_alpha = per_pixel_alpha; mpcc_cfg.per_pixel_alpha = per_pixel_alpha;
/* DCN1.0 has output CM before MPC which seems to screw with /* DCN1.0 has output CM before MPC which seems to screw with
* pre-multiplied alpha. * pre-multiplied alpha.
...@@ -1749,8 +1739,6 @@ static void update_dchubp_dpp( ...@@ -1749,8 +1739,6 @@ static void update_dchubp_dpp(
mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace( mpcc_cfg.pre_multiplied_alpha = is_rgb_cspace(
pipe_ctx->stream->public.output_color_space) pipe_ctx->stream->public.output_color_space)
&& per_pixel_alpha; && per_pixel_alpha;
if (!dc->current_context->res_ctx.pipe_ctx[pipe_ctx->pipe_idx].surface)
pipe_ctx->mpcc->funcs->wait_for_idle(pipe_ctx->mpcc);
pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg); pipe_ctx->mpcc->funcs->set(pipe_ctx->mpcc, &mpcc_cfg);
color_space_to_black_color( color_space_to_black_color(
...@@ -1796,7 +1784,7 @@ static void program_all_pipe_in_tree( ...@@ -1796,7 +1784,7 @@ static void program_all_pipe_in_tree(
/* watermark is for all pipes */ /* watermark is for all pipes */
pipe_ctx->mi->funcs->program_watermarks( pipe_ctx->mi->funcs->program_watermarks(
pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz); pipe_ctx->mi, &context->bw.dcn.watermarks, ref_clk_mhz);
lock_otg_master_update(dc->ctx, pipe_ctx->tg->inst); pipe_ctx->tg->funcs->lock(pipe_ctx->tg);
pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset; pipe_ctx->tg->dlg_otg_param.vready_offset = pipe_ctx->pipe_dlg_param.vready_offset;
pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start; pipe_ctx->tg->dlg_otg_param.vstartup_start = pipe_ctx->pipe_dlg_param.vstartup_start;
...@@ -1852,13 +1840,41 @@ static void dcn10_apply_ctx_for_surface( ...@@ -1852,13 +1840,41 @@ static void dcn10_apply_ctx_for_surface(
{ {
int i; int i;
/* reset unused mpcc */
/*for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe_ctx =
&dc->current_context->res_ctx.pipe_ctx[i];
if ((!pipe_ctx->surface && old_pipe_ctx->surface)
|| (!pipe_ctx->stream && old_pipe_ctx->stream)) {
struct mpcc_cfg mpcc_cfg;
mpcc_cfg.opp_id = 0xf;
mpcc_cfg.top_dpp_id = 0xf;
mpcc_cfg.bot_mpcc_id = 0xf;
mpcc_cfg.top_of_tree = !old_pipe_ctx->top_pipe;
old_pipe_ctx->mpcc->funcs->set(old_pipe_ctx->mpcc, &mpcc_cfg);
old_pipe_ctx->top_pipe = NULL;
old_pipe_ctx->bottom_pipe = NULL;
old_pipe_ctx->surface = NULL;
dm_logger_write(dc->ctx->logger, LOG_DC,
"Reset mpcc for pipe %d\n",
old_pipe_ctx->pipe_idx);
}
}*/
if (!surface)
return;
for (i = 0; i < dc->res_pool->pipe_count; i++) { for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i]; struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (!pipe_ctx->surface || pipe_ctx->surface != surface) if (pipe_ctx->surface != surface)
continue; continue;
/* looking for top pipe to program */ /* looking for top pipe to program */
if (!pipe_ctx->top_pipe) if (!pipe_ctx->top_pipe)
program_all_pipe_in_tree(dc, pipe_ctx, context); program_all_pipe_in_tree(dc, pipe_ctx, context);
...@@ -1910,27 +1926,6 @@ static void dcn10_apply_ctx_for_surface( ...@@ -1910,27 +1926,6 @@ static void dcn10_apply_ctx_for_surface(
context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns, context->bw.dcn.watermarks.d.cstate_pstate.pstate_change_ns,
context->bw.dcn.watermarks.d.pte_meta_urgent_ns context->bw.dcn.watermarks.d.pte_meta_urgent_ns
); );
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
if (!pipe_ctx->surface || pipe_ctx->top_pipe)
continue;
/* unlock master update lock */
unlock_otg_master(dc->ctx, pipe_ctx->tg->inst);
}
/* reset unused pipe */
for (i = 0; i < dc->res_pool->pipe_count; i++) {
struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
struct pipe_ctx *old_pipe_ctx =
&dc->current_context->res_ctx.pipe_ctx[i];
if ((!pipe_ctx->surface && old_pipe_ctx->surface)
|| (!pipe_ctx->stream && old_pipe_ctx->stream))
reset_front_end_for_pipe(dc, old_pipe_ctx, dc->current_context);
}
} }
static void dcn10_set_bandwidth( static void dcn10_set_bandwidth(
...@@ -1992,23 +1987,6 @@ static void dcn10_set_bandwidth( ...@@ -1992,23 +1987,6 @@ static void dcn10_set_bandwidth(
dcn10_pplib_apply_display_requirements(dc, context); dcn10_pplib_apply_display_requirements(dc, context);
} }
static void dcn10_power_down_fe(struct core_dc *dc, struct pipe_ctx *pipe)
{
struct dc_context *ctx = dc->ctx;
uint32_t inst_offset = 0;
HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
IP_REQUEST_EN, 1);
dpp_pg_control(ctx, pipe->pipe_idx, false);
hubp_pg_control(ctx, pipe->pipe_idx, false);
HWSEQ_REG_SET(DC_IP_REQUEST_CNTL,
IP_REQUEST_EN, 0);
if (pipe->xfm)
pipe->xfm->funcs->transform_reset(pipe->xfm);
memset(&pipe->scl_data, 0, sizeof(pipe->scl_data));
}
static void set_drr(struct pipe_ctx **pipe_ctx, static void set_drr(struct pipe_ctx **pipe_ctx,
int num_pipes, int vmin, int vmax) int num_pipes, int vmin, int vmax)
{ {
......
...@@ -65,17 +65,17 @@ void dcn10_mpcc_set_bg_color( ...@@ -65,17 +65,17 @@ void dcn10_mpcc_set_bg_color(
static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id) static void set_output_mux(struct dcn10_mpcc *mpcc10, int opp_id, int mpcc_id)
{ {
ASSERT(mpcc10->opp_id == 0xf || opp_id == mpcc10->opp_id); ASSERT(mpcc10->base.opp_id == 0xf || opp_id == mpcc10->base.opp_id);
mpcc10->opp_id = opp_id; mpcc10->base.opp_id = opp_id;
REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1); REG_UPDATE(OPP_PIPE_CONTROL[opp_id], OPP_PIPE_CLOCK_EN, 1);
REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id); REG_SET(MUX[opp_id], 0, MPC_OUT_MUX, mpcc_id);
} }
static void reset_output_mux(struct dcn10_mpcc *mpcc10) static void reset_output_mux(struct dcn10_mpcc *mpcc10)
{ {
REG_SET(MUX[mpcc10->opp_id], 0, MPC_OUT_MUX, 0xf); REG_SET(MUX[mpcc10->base.opp_id], 0, MPC_OUT_MUX, 0xf);
REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->opp_id], OPP_PIPE_CLOCK_EN, 0); REG_UPDATE(OPP_PIPE_CONTROL[mpcc10->base.opp_id], OPP_PIPE_CLOCK_EN, 0);
mpcc10->opp_id = 0xf; mpcc10->base.opp_id = 0xf;
} }
static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg)
...@@ -104,16 +104,17 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg) ...@@ -104,16 +104,17 @@ static void dcn10_mpcc_set(struct mpcc *mpcc, struct mpcc_cfg *cfg)
if (cfg->top_of_tree) { if (cfg->top_of_tree) {
if (cfg->opp_id != 0xf) if (cfg->opp_id != 0xf)
set_output_mux(mpcc10, cfg->opp_id, mpcc->inst); set_output_mux(mpcc10, cfg->opp_id, mpcc->inst);
else else if (mpcc->opp_id != 0xf)
reset_output_mux(mpcc10); reset_output_mux(mpcc10);
} }
mpcc10->base.opp_id = cfg->opp_id;
} }
static void dcn10_mpcc_wait_idle(struct mpcc *mpcc) static void dcn10_mpcc_wait_idle(struct mpcc *mpcc)
{ {
struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc); struct dcn10_mpcc *mpcc10 = TO_DCN10_MPCC(mpcc);
REG_WAIT(MPCC_STATUS, MPCC_IDLE, 1, 1000, 1000); REG_WAIT(MPCC_STATUS, MPCC_BUSY, 0, 1000, 1000);
} }
...@@ -139,5 +140,5 @@ void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, ...@@ -139,5 +140,5 @@ void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10,
mpcc10->mpcc_shift = mpcc_shift; mpcc10->mpcc_shift = mpcc_shift;
mpcc10->mpcc_mask = mpcc_mask; mpcc10->mpcc_mask = mpcc_mask;
mpcc10->opp_id = inst; mpcc10->base.opp_id = inst;
} }
...@@ -68,6 +68,7 @@ struct dcn_mpcc_registers { ...@@ -68,6 +68,7 @@ struct dcn_mpcc_registers {
SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_ALPHA_MULTIPLIED_MODE, mask_sh),\
SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\ SF(MPCC0_MPCC_CONTROL, MPCC_BLND_ACTIVE_OVERLAP_ONLY, mask_sh),\
SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\ SF(MPCC0_MPCC_STATUS, MPCC_IDLE, mask_sh),\
SF(MPCC0_MPCC_STATUS, MPCC_BUSY, mask_sh),\
SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\ SF(MPCC0_MPCC_OPP_ID, MPCC_OPP_ID, mask_sh),\
SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\ SF(MPCC0_MPCC_BG_G_Y, MPCC_BG_G_Y, mask_sh),\
SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\ SF(MPCC0_MPCC_BG_R_CR, MPCC_BG_R_CR, mask_sh),\
...@@ -83,6 +84,7 @@ struct dcn_mpcc_registers { ...@@ -83,6 +84,7 @@ struct dcn_mpcc_registers {
type MPCC_ALPHA_MULTIPLIED_MODE;\ type MPCC_ALPHA_MULTIPLIED_MODE;\
type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\ type MPCC_BLND_ACTIVE_OVERLAP_ONLY;\
type MPCC_IDLE;\ type MPCC_IDLE;\
type MPCC_BUSY;\
type MPCC_OPP_ID;\ type MPCC_OPP_ID;\
type MPCC_BG_G_Y;\ type MPCC_BG_G_Y;\
type MPCC_BG_R_CR;\ type MPCC_BG_R_CR;\
...@@ -103,8 +105,6 @@ struct dcn10_mpcc { ...@@ -103,8 +105,6 @@ struct dcn10_mpcc {
const struct dcn_mpcc_registers *mpcc_regs; const struct dcn_mpcc_registers *mpcc_regs;
const struct dcn_mpcc_shift *mpcc_shift; const struct dcn_mpcc_shift *mpcc_shift;
const struct dcn_mpcc_mask *mpcc_mask; const struct dcn_mpcc_mask *mpcc_mask;
int opp_id;
}; };
void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10, void dcn10_mpcc_construct(struct dcn10_mpcc *mpcc10,
......
...@@ -575,6 +575,8 @@ void dcn10_lock(struct timing_generator *tg) ...@@ -575,6 +575,8 @@ void dcn10_lock(struct timing_generator *tg)
{ {
struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg); struct dcn10_timing_generator *tgn10 = DCN10TG_FROM_TG(tg);
REG_SET(OTG_GLOBAL_CONTROL0, 0,
OTG_MASTER_UPDATE_LOCK_SEL, tg->inst);
REG_SET(OTG_MASTER_UPDATE_LOCK, 0, REG_SET(OTG_MASTER_UPDATE_LOCK, 0,
OTG_MASTER_UPDATE_LOCK, 1); OTG_MASTER_UPDATE_LOCK, 1);
} }
...@@ -587,9 +589,9 @@ void dcn10_unlock(struct timing_generator *tg) ...@@ -587,9 +589,9 @@ void dcn10_unlock(struct timing_generator *tg)
OTG_MASTER_UPDATE_LOCK, 0); OTG_MASTER_UPDATE_LOCK, 0);
/* why are we waiting here? */ /* why are we waiting here? */
REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL, /*REG_WAIT(OTG_DOUBLE_BUFFER_CONTROL,
OTG_UPDATE_PENDING, 0, OTG_UPDATE_PENDING, 0,
20000, 200000); 20000, 200000);*/
} }
static void dcn10_get_position(struct timing_generator *tg, static void dcn10_get_position(struct timing_generator *tg,
......
...@@ -37,6 +37,7 @@ ...@@ -37,6 +37,7 @@
SRI(OTG_VREADY_PARAM, OTG, inst),\ SRI(OTG_VREADY_PARAM, OTG, inst),\
SRI(OTG_BLANK_CONTROL, OTG, inst),\ SRI(OTG_BLANK_CONTROL, OTG, inst),\
SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\ SRI(OTG_MASTER_UPDATE_LOCK, OTG, inst),\
SRI(OTG_GLOBAL_CONTROL0, OTG, inst),\
SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\ SRI(OTG_DOUBLE_BUFFER_CONTROL, OTG, inst),\
SRI(OTG_H_TOTAL, OTG, inst),\ SRI(OTG_H_TOTAL, OTG, inst),\
SRI(OTG_H_BLANK_START_END, OTG, inst),\ SRI(OTG_H_BLANK_START_END, OTG, inst),\
...@@ -83,6 +84,7 @@ struct dcn_tg_registers { ...@@ -83,6 +84,7 @@ struct dcn_tg_registers {
uint32_t OTG_VREADY_PARAM; uint32_t OTG_VREADY_PARAM;
uint32_t OTG_BLANK_CONTROL; uint32_t OTG_BLANK_CONTROL;
uint32_t OTG_MASTER_UPDATE_LOCK; uint32_t OTG_MASTER_UPDATE_LOCK;
uint32_t OTG_GLOBAL_CONTROL0;
uint32_t OTG_DOUBLE_BUFFER_CONTROL; uint32_t OTG_DOUBLE_BUFFER_CONTROL;
uint32_t OTG_H_TOTAL; uint32_t OTG_H_TOTAL;
uint32_t OTG_H_BLANK_START_END; uint32_t OTG_H_BLANK_START_END;
...@@ -134,6 +136,7 @@ struct dcn_tg_registers { ...@@ -134,6 +136,7 @@ struct dcn_tg_registers {
SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_BLANK_DE_MODE, mask_sh),\
SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\ SF(OTG0_OTG_BLANK_CONTROL, OTG_CURRENT_BLANK_STATE, mask_sh),\
SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\ SF(OTG0_OTG_MASTER_UPDATE_LOCK, OTG_MASTER_UPDATE_LOCK, mask_sh),\
SF(OTG0_OTG_GLOBAL_CONTROL0, OTG_MASTER_UPDATE_LOCK_SEL, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_UPDATE_PENDING, mask_sh),\
SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\ SF(OTG0_OTG_DOUBLE_BUFFER_CONTROL, OTG_BLANK_DATA_DOUBLE_BUFFER_EN, mask_sh),\
SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\ SF(OTG0_OTG_H_TOTAL, OTG_H_TOTAL, mask_sh),\
...@@ -224,6 +227,7 @@ struct dcn_tg_registers { ...@@ -224,6 +227,7 @@ struct dcn_tg_registers {
type OTG_CURRENT_BLANK_STATE;\ type OTG_CURRENT_BLANK_STATE;\
type OTG_MASTER_UPDATE_LOCK;\ type OTG_MASTER_UPDATE_LOCK;\
type OTG_UPDATE_PENDING;\ type OTG_UPDATE_PENDING;\
type OTG_MASTER_UPDATE_LOCK_SEL;\
type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\ type OTG_BLANK_DATA_DOUBLE_BUFFER_EN;\
type OTG_H_TOTAL;\ type OTG_H_TOTAL;\
type OTG_H_BLANK_START;\ type OTG_H_BLANK_START;\
......
...@@ -40,6 +40,7 @@ struct mpcc { ...@@ -40,6 +40,7 @@ struct mpcc {
const struct mpcc_funcs *funcs; const struct mpcc_funcs *funcs;
struct dc_context *ctx; struct dc_context *ctx;
int inst; int inst;
int opp_id;
}; };
struct mpcc_funcs { struct mpcc_funcs {
......
...@@ -105,7 +105,7 @@ struct hw_sequencer_funcs { ...@@ -105,7 +105,7 @@ struct hw_sequencer_funcs {
struct dc_bios *dcb, struct dc_bios *dcb,
enum pipe_gating_control power_gating); enum pipe_gating_control power_gating);
void (*power_down_front_end)(struct core_dc *dc, struct pipe_ctx *pipe); void (*power_down_front_end)(struct core_dc *dc, int fe_idx);
void (*power_on_front_end)(struct core_dc *dc, void (*power_on_front_end)(struct core_dc *dc,
struct pipe_ctx *pipe, struct pipe_ctx *pipe,
......
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