diff options
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.c | 169 |
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) |
