aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c')
-rw-r--r--drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c169
1 files changed, 112 insertions, 57 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
index 7d833fa6dd77..0d58c9d439c6 100644
--- a/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
+++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn20/dcn20_hwseq.c
@@ -204,7 +204,7 @@ static int find_free_gsl_group(const struct dc *dc)
* gsl_0 <=> pipe_ctx->stream_res.gsl_group == 1
* Using a magic value like -1 would require tracking all inits/resets
*/
- void dcn20_setup_gsl_group_as_lock(
+void dcn20_setup_gsl_group_as_lock(
const struct dc *dc,
struct pipe_ctx *pipe_ctx,
bool enable)
@@ -758,9 +758,9 @@ void dcn20_disable_pixel_data(struct dc *dc, struct pipe_ctx *pipe_ctx, bool bla
}
static int calc_mpc_flow_ctrl_cnt(const struct dc_stream_state *stream,
- int opp_cnt)
+ int opp_cnt, bool is_two_pixels_per_container)
{
- bool hblank_halved = optc2_is_two_pixels_per_containter(&stream->timing);
+ bool hblank_halved = is_two_pixels_per_container;
int flow_ctrl_cnt;
if (opp_cnt >= 2)
@@ -820,25 +820,26 @@ enum dc_status dcn20_enable_stream_timing(
struct dc_stream_state *stream = pipe_ctx->stream;
struct drr_params params = {0};
unsigned int event_triggers = 0;
- struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
- int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
+ int opp_inst[MAX_PIPES] = {0};
bool interlace = stream->timing.flags.INTERLACE;
int i;
struct mpc_dwb_flow_control flow_control;
struct mpc *mpc = dc->res_pool->mpc;
- 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);
-
+ bool is_two_pixels_per_container =
+ pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
+ bool rate_control_2x_pclk = (interlace || is_two_pixels_per_container);
+ int odm_slice_width;
+ int last_odm_slice_width;
+ struct pipe_ctx *opp_heads[MAX_PIPES];
+
+ if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
- k1_div, k2_div);
- }
+ pipe_ctx->pixel_rate_divider.div_factor1,
+ pipe_ctx->pixel_rate_divider.div_factor2);
+
/* 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
* with pipe 0. No program is needed.
@@ -848,16 +849,17 @@ enum dc_status dcn20_enable_stream_timing(
/* TODO check if timing_changed, disable stream if timing changed */
- for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
- opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
- opp_cnt++;
- }
+ opp_cnt = resource_get_opp_heads_for_otg_master(pipe_ctx, &context->res_ctx, opp_heads);
+ for (i = 0; i < opp_cnt; i++)
+ opp_inst[i] = opp_heads[i]->stream_res.opp->inst;
+ odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false);
+ last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
if (opp_cnt > 1)
pipe_ctx->stream_res.tg->funcs->set_odm_combine(
pipe_ctx->stream_res.tg,
- opp_inst, opp_cnt,
- &pipe_ctx->stream->timing);
+ opp_inst, opp_cnt, odm_slice_width,
+ last_odm_slice_width);
/* HW program guide assume display already disable
* by unplug sequence. OTG assume stop.
@@ -913,7 +915,8 @@ enum dc_status dcn20_enable_stream_timing(
rate_control_2x_pclk = rate_control_2x_pclk || opp_cnt > 1;
flow_control.flow_ctrl_mode = 0;
flow_control.flow_ctrl_cnt0 = 0x80;
- flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt);
+ flow_control.flow_ctrl_cnt1 = calc_mpc_flow_ctrl_cnt(stream, opp_cnt,
+ is_two_pixels_per_container);
if (mpc->funcs->set_out_rate_control) {
for (i = 0; i < opp_cnt; ++i) {
mpc->funcs->set_out_rate_control(
@@ -924,14 +927,15 @@ enum dc_status dcn20_enable_stream_timing(
}
}
- for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
- odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control(
- odm_pipe->stream_res.opp,
+ for (i = 0; i < opp_cnt; i++) {
+ opp_heads[i]->stream_res.opp->funcs->opp_pipe_clock_control(
+ opp_heads[i]->stream_res.opp,
true);
-
- pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control(
- pipe_ctx->stream_res.opp,
- true);
+ opp_heads[i]->stream_res.opp->funcs->opp_program_left_edge_extra_pixel(
+ opp_heads[i]->stream_res.opp,
+ stream->timing.pixel_encoding,
+ resource_is_pipe_type(opp_heads[i], OTG_MASTER));
+ }
hws->funcs.blank_pixel_data(dc, pipe_ctx, true);
@@ -1172,6 +1176,8 @@ void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
struct pipe_ctx *odm_pipe;
int opp_cnt = 1;
int opp_inst[MAX_PIPES] = { pipe_ctx->stream_res.opp->inst };
+ int odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, false);
+ int last_odm_slice_width = resource_get_odm_slice_dst_width(pipe_ctx, true);
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
opp_inst[opp_cnt] = odm_pipe->stream_res.opp->inst;
@@ -1182,7 +1188,7 @@ void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *
pipe_ctx->stream_res.tg->funcs->set_odm_combine(
pipe_ctx->stream_res.tg,
opp_inst, opp_cnt,
- &pipe_ctx->stream->timing);
+ odm_slice_width, last_odm_slice_width);
else
pipe_ctx->stream_res.tg->funcs->set_odm_bypass(
pipe_ctx->stream_res.tg, &pipe_ctx->stream->timing);
@@ -1200,10 +1206,7 @@ void dcn20_blank_pixel_data(
enum controller_dp_test_pattern test_pattern = CONTROLLER_DP_TEST_PATTERN_SOLID_COLOR;
enum controller_dp_color_space test_pattern_color_space = CONTROLLER_DP_COLOR_SPACE_UDEFINED;
struct pipe_ctx *odm_pipe;
- int odm_cnt = 1;
- int h_active = stream->timing.h_addressable + stream->timing.h_border_left + stream->timing.h_border_right;
- int v_active = stream->timing.v_addressable + stream->timing.v_border_bottom + stream->timing.v_border_top;
- int odm_slice_width, last_odm_slice_width, offset = 0;
+ struct rect odm_slice_src;
if (stream->link->test_pattern_enabled)
return;
@@ -1211,11 +1214,6 @@ void dcn20_blank_pixel_data(
/* get opp dpg blank color */
color_space_to_black_color(dc, color_space, &black_color);
- for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe)
- odm_cnt++;
- odm_slice_width = h_active / odm_cnt;
- last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1);
-
if (blank) {
dc->hwss.set_abm_immediate_disable(pipe_ctx);
@@ -1230,28 +1228,29 @@ void dcn20_blank_pixel_data(
odm_pipe = pipe_ctx;
while (odm_pipe->next_odm_pipe) {
+ odm_slice_src = resource_get_odm_slice_src_rect(odm_pipe);
dc->hwss.set_disp_pattern_generator(dc,
odm_pipe,
test_pattern,
test_pattern_color_space,
stream->timing.display_color_depth,
&black_color,
- odm_slice_width,
- v_active,
- offset);
- offset += odm_slice_width;
+ odm_slice_src.width,
+ odm_slice_src.height,
+ odm_slice_src.x);
odm_pipe = odm_pipe->next_odm_pipe;
}
+ odm_slice_src = resource_get_odm_slice_src_rect(odm_pipe);
dc->hwss.set_disp_pattern_generator(dc,
odm_pipe,
test_pattern,
test_pattern_color_space,
stream->timing.display_color_depth,
&black_color,
- last_odm_slice_width,
- v_active,
- offset);
+ odm_slice_src.width,
+ odm_slice_src.height,
+ odm_slice_src.x);
if (!blank)
if (stream_res->abm) {
@@ -1709,6 +1708,11 @@ static void dcn20_update_dchubp_dpp(
plane_state->color_space,
NULL);
+ if (dpp->funcs->set_cursor_matrix) {
+ dpp->funcs->set_cursor_matrix(dpp,
+ plane_state->color_space,
+ plane_state->cursor_csc_color_matrix);
+ }
if (dpp->funcs->dpp_program_bias_and_scale) {
//TODO :for CNVC set scale and bias registers if necessary
build_prescale_params(&bns_params, plane_state);
@@ -1754,8 +1758,8 @@ static void dcn20_update_dchubp_dpp(
if ((pipe_ctx->update_flags.bits.enable || pipe_ctx->update_flags.bits.opp_changed ||
pipe_ctx->update_flags.bits.scaler || viewport_changed == true) &&
pipe_ctx->stream->cursor_attributes.address.quad_part != 0) {
- dc->hwss.set_cursor_position(pipe_ctx);
dc->hwss.set_cursor_attribute(pipe_ctx);
+ dc->hwss.set_cursor_position(pipe_ctx);
if (dc->hwss.set_cursor_sdr_white_level)
dc->hwss.set_cursor_sdr_white_level(pipe_ctx);
@@ -1908,6 +1912,10 @@ static void dcn20_program_pipe(
if (dc->res_pool->hubbub->funcs->program_det_size)
dc->res_pool->hubbub->funcs->program_det_size(
dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->det_buffer_size_kb);
+
+ if (dc->res_pool->hubbub->funcs->program_det_segments)
+ dc->res_pool->hubbub->funcs->program_det_segments(
+ dc->res_pool->hubbub, pipe_ctx->plane_res.hubp->inst, pipe_ctx->hubp_regs.det_size);
}
if (pipe_ctx->update_flags.raw || pipe_ctx->plane_state->update_flags.raw || pipe_ctx->stream->update_flags.raw)
@@ -1917,6 +1925,11 @@ static void dcn20_program_pipe(
|| pipe_ctx->plane_state->update_flags.bits.hdr_mult)
hws->funcs.set_hdr_multiplier(pipe_ctx);
+ if (hws->funcs.populate_mcm_luts) {
+ hws->funcs.populate_mcm_luts(dc, pipe_ctx, pipe_ctx->plane_state->mcm_luts,
+ pipe_ctx->plane_state->lut_bank_a);
+ pipe_ctx->plane_state->lut_bank_a = !pipe_ctx->plane_state->lut_bank_a;
+ }
if (pipe_ctx->update_flags.bits.enable ||
pipe_ctx->plane_state->update_flags.bits.in_transfer_func_change ||
pipe_ctx->plane_state->update_flags.bits.gamma_change ||
@@ -2073,6 +2086,8 @@ void dcn20_program_front_end_for_ctx(
(context->res_ctx.pipe_ctx[i].plane_state && dc_state_get_pipe_subvp_type(context, &context->res_ctx.pipe_ctx[i]) == SUBVP_PHANTOM))) {
if (hubbub->funcs->program_det_size)
hubbub->funcs->program_det_size(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
+ if (dc->res_pool->hubbub->funcs->program_det_segments)
+ dc->res_pool->hubbub->funcs->program_det_segments(hubbub, dc->current_state->res_ctx.pipe_ctx[i].plane_res.hubp->inst, 0);
}
hws->funcs.plane_atomic_disconnect(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
DC_LOG_DC("Reset mpcc for pipe %d\n", dc->current_state->res_ctx.pipe_ctx[i].pipe_idx);
@@ -2135,6 +2150,43 @@ void dcn20_program_front_end_for_ctx(
}
}
+/* post_unlock_reset_opp - the function wait for corresponding double
+ * buffered pending status clear and reset opp head pipe's none double buffered
+ * registers to their initial state.
+ */
+static void post_unlock_reset_opp(struct dc *dc,
+ struct pipe_ctx *opp_head)
+{
+ struct display_stream_compressor *dsc = opp_head->stream_res.dsc;
+ struct dccg *dccg = dc->res_pool->dccg;
+
+ /*
+ * wait for all DPP pipes in current mpc blending tree completes double
+ * buffered disconnection before resetting OPP
+ */
+ dc->hwss.wait_for_mpcc_disconnect(dc, dc->res_pool, opp_head);
+
+ if (dsc) {
+ bool is_dsc_ungated = false;
+
+ if (dc->hwseq->funcs.dsc_pg_status)
+ is_dsc_ungated = dc->hwseq->funcs.dsc_pg_status(dc->hwseq, dsc->inst);
+
+ if (is_dsc_ungated) {
+ /*
+ * seamless update specific where we will postpone non
+ * double buffered DSCCLK disable logic in post unlock
+ * sequence after DSC is disconnected from OPP but not
+ * yet power gated.
+ */
+ dsc->funcs->dsc_wait_disconnect_pending_clear(dsc);
+ if (dccg->funcs->set_ref_dscclk)
+ dccg->funcs->set_ref_dscclk(dccg, dsc->inst);
+ dsc->funcs->dsc_disable(dsc);
+ }
+ }
+}
+
void dcn20_post_unlock_program_front_end(
struct dc *dc,
struct dc_state *context)
@@ -2145,6 +2197,12 @@ void dcn20_post_unlock_program_front_end(
struct dce_hwseq *hwseq = dc->hwseq;
for (i = 0; i < dc->res_pool->pipe_count; i++)
+ if (resource_is_pipe_type(&dc->current_state->res_ctx.pipe_ctx[i], OPP_HEAD) &&
+ !resource_is_pipe_type(&context->res_ctx.pipe_ctx[i], OPP_HEAD))
+ post_unlock_reset_opp(dc,
+ &dc->current_state->res_ctx.pipe_ctx[i]);
+
+ for (i = 0; i < dc->res_pool->pipe_count; i++)
if (context->res_ctx.pipe_ctx[i].update_flags.bits.disable)
dc->hwss.disable_plane(dc, dc->current_state, &dc->current_state->res_ctx.pipe_ctx[i]);
@@ -2620,8 +2678,11 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
struct dc_link *link = stream->link;
struct dce_hwseq *hws = link->dc->hwseq;
struct pipe_ctx *odm_pipe;
+ bool is_two_pixels_per_container =
+ pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing);
params.opp_cnt = 1;
+
for (odm_pipe = pipe_ctx->next_odm_pipe; odm_pipe; odm_pipe = odm_pipe->next_odm_pipe) {
params.opp_cnt++;
}
@@ -2636,7 +2697,7 @@ void dcn20_unblank_stream(struct pipe_ctx *pipe_ctx,
pipe_ctx->stream_res.hpo_dp_stream_enc,
pipe_ctx->stream_res.tg->inst);
} else if (dc_is_dp_signal(pipe_ctx->stream->signal)) {
- if (optc2_is_two_pixels_per_containter(&stream->timing) || params.opp_cnt > 1)
+ if (is_two_pixels_per_container || params.opp_cnt > 1)
params.timing.pix_clk_100hz /= 2;
pipe_ctx->stream_res.stream_enc->funcs->dp_set_odm_combine(
pipe_ctx->stream_res.stream_enc, params.opp_cnt > 1);
@@ -2877,9 +2938,7 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
struct dccg *dccg = dc->res_pool->dccg;
enum phyd32clk_clock_source phyd32clk;
int dp_hpo_inst;
- struct dce_hwseq *hws = dc->hwseq;
- unsigned int k1_div = PIXEL_RATE_DIV_NA;
- unsigned int k2_div = PIXEL_RATE_DIV_NA;
+
struct link_encoder *link_enc = link_enc_cfg_get_link_enc(pipe_ctx->stream->link);
struct stream_encoder *stream_enc = pipe_ctx->stream_res.stream_enc;
@@ -2900,14 +2959,13 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
dccg->funcs->enable_symclk_se(dccg, stream_enc->stream_enc_inst,
link_enc->transmitter - TRANSMITTER_UNIPHY_A);
}
- 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);
+ if (dc->res_pool->dccg->funcs->set_pixel_rate_div)
dc->res_pool->dccg->funcs->set_pixel_rate_div(
dc->res_pool->dccg,
pipe_ctx->stream_res.tg->inst,
- k1_div, k2_div);
- }
+ pipe_ctx->pixel_rate_divider.div_factor1,
+ pipe_ctx->pixel_rate_divider.div_factor2);
link_hwss->setup_stream_encoder(pipe_ctx);
@@ -2934,9 +2992,6 @@ void dcn20_enable_stream(struct pipe_ctx *pipe_ctx)
early_control = lane_count;
tg->funcs->set_early_control(tg, early_control);
-
- if (dc->hwseq->funcs.set_pixels_per_cycle)
- dc->hwseq->funcs.set_pixels_per_cycle(pipe_ctx);
}
void dcn20_program_dmdata_engine(struct pipe_ctx *pipe_ctx)