diff options
20 files changed, 140 insertions, 106 deletions
diff --git a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c index fd03d7129ffa..fd624b1fee25 100644 --- a/drivers/gpu/drm/amd/display/dc/core/dc_resource.c +++ b/drivers/gpu/drm/amd/display/dc/core/dc_resource.c @@ -2110,12 +2110,19 @@ struct rect resource_get_odm_slice_src_rect(struct pipe_ctx *pipe_ctx) struct rect odm_slice_dst; struct rect odm_slice_src; struct pipe_ctx *opp_head = resource_get_opp_head(pipe_ctx); + struct output_pixel_processor *opp = opp_head->stream_res.opp; uint32_t left_edge_extra_pixel_count; odm_slice_dst = resource_get_odm_slice_dst_rect(opp_head); odm_slice_src = odm_slice_dst; - left_edge_extra_pixel_count = 0; + if (opp->funcs->opp_get_left_edge_extra_pixel_count) + left_edge_extra_pixel_count = + opp->funcs->opp_get_left_edge_extra_pixel_count( + opp, pipe_ctx->stream->timing.pixel_encoding, + resource_is_pipe_type(opp_head, OTG_MASTER)); + else + left_edge_extra_pixel_count = 0; odm_slice_src.x -= left_edge_extra_pixel_count; odm_slice_src.width += left_edge_extra_pixel_count; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c index fbf1b6370eb2..f5fe0cac7cb0 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.c @@ -23,6 +23,7 @@ * */ +#include "core_types.h" #include "dm_services.h" #include "dcn20_opp.h" #include "reg_helper.h" @@ -350,19 +351,32 @@ bool opp2_dpg_is_pending(struct output_pixel_processor *opp) return (dpg_en == 1 && double_buffer_pending == 1); } -void opp2_program_left_edge_extra_pixel ( +void opp2_program_left_edge_extra_pixel( struct output_pixel_processor *opp, - bool count) + enum dc_pixel_encoding pixel_encoding, + bool is_primary) { struct dcn20_opp *oppn20 = TO_DCN20_OPP(opp); + uint32_t count = opp2_get_left_edge_extra_pixel_count(opp, pixel_encoding, is_primary); - /* Specifies the number of extra left edge pixels that are supplied to + /* + * Specifies the number of extra left edge pixels that are supplied to * the 422 horizontal chroma sub-sample filter. - * Note that when left edge pixel is not "0", fmt pixel encoding can be in either 420 or 422 mode - * */ + */ REG_UPDATE(FMT_422_CONTROL, FMT_LEFT_EDGE_EXTRA_PIXEL_COUNT, count); } +uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp, + enum dc_pixel_encoding pixel_encoding, bool is_primary) +{ + if ((pixel_encoding == PIXEL_ENCODING_YCBCR422 || pixel_encoding == PIXEL_ENCODING_YCBCR420) && + !opp->ctx->dc->debug.force_chroma_subsampling_1tap && + !is_primary) + return 1; + else + return 0; +} + /*****************************************/ /* Constructor, Destructor */ /*****************************************/ @@ -380,6 +394,7 @@ static struct opp_funcs dcn20_opp_funcs = { .opp_dpg_set_blank_color = opp2_dpg_set_blank_color, .opp_destroy = opp1_destroy, .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel, + .opp_get_left_edge_extra_pixel_count = opp2_get_left_edge_extra_pixel_count, }; void dcn20_opp_construct(struct dcn20_opp *oppn20, diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h index 8f186abd558d..34936e6c49f3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_opp.h @@ -167,6 +167,8 @@ void opp2_dpg_set_blank_color( void opp2_program_left_edge_extra_pixel ( struct output_pixel_processor *opp, - bool count); + enum dc_pixel_encoding pixel_encoding, bool is_primary); +uint32_t opp2_get_left_edge_extra_pixel_count(struct output_pixel_processor *opp, + enum dc_pixel_encoding pixel_encoding, bool is_primary); #endif diff --git a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c index 6a71ba3dfc63..e83367a9b6b3 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c +++ b/drivers/gpu/drm/amd/display/dc/dcn201/dcn201_opp.c @@ -54,6 +54,7 @@ static struct opp_funcs dcn201_opp_funcs = { .opp_dpg_set_blank_color = opp2_dpg_set_blank_color, .opp_destroy = opp1_destroy, .opp_program_left_edge_extra_pixel = opp2_program_left_edge_extra_pixel, + .opp_get_left_edge_extra_pixel_count = opp2_get_left_edge_extra_pixel_count, }; void dcn201_opp_construct(struct dcn201_opp *oppn201, 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 5623a48cf3fd..d085c9ff9d38 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 @@ -820,9 +820,8 @@ 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; @@ -832,6 +831,9 @@ enum dc_status dcn20_enable_stream_timing( bool rate_control_2x_pclk = (interlace || is_two_pixels_per_container); unsigned int k1_div = PIXEL_RATE_DIV_NA; unsigned int k2_div = PIXEL_RATE_DIV_NA; + int odm_slice_width; + int last_odm_slice_width; + struct pipe_ctx *opp_heads[MAX_PIPES]; 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); @@ -850,16 +852,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[opp_cnt] = 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. @@ -927,14 +930,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); @@ -1175,6 +1179,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; @@ -1185,7 +1191,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); @@ -1203,12 +1209,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; - bool is_two_pixels_per_container = - pipe_ctx->stream_res.tg->funcs->is_two_pixels_per_container(&stream->timing); + struct rect odm_slice_src; if (stream->link->test_pattern_enabled) return; @@ -1216,13 +1217,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; - if ((odm_slice_width % 2) && is_two_pixels_per_container) - odm_slice_width++; - last_odm_slice_width = h_active - odm_slice_width * (odm_cnt - 1); - if (blank) { dc->hwss.set_abm_immediate_disable(pipe_ctx); @@ -1237,28 +1231,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) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c index 0b12a69e2df0..1d853241ca32 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn314/dcn314_hwseq.c @@ -160,6 +160,8 @@ void dcn314_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; + 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); opp_cnt = get_odm_config(pipe_ctx, opp_inst); @@ -167,7 +169,7 @@ void dcn314_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); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c index df0fceb11ae1..7aaef3709baa 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn32/dcn32_hwseq.c @@ -1078,6 +1078,8 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; + 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); opp_cnt = get_odm_config(pipe_ctx, opp_inst); @@ -1085,7 +1087,7 @@ void dcn32_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); @@ -1094,6 +1096,10 @@ void dcn32_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * odm_pipe->stream_res.opp->funcs->opp_pipe_clock_control( odm_pipe->stream_res.opp, true); + odm_pipe->stream_res.opp->funcs->opp_program_left_edge_extra_pixel( + odm_pipe->stream_res.opp, + pipe_ctx->stream->timing.pixel_encoding, + resource_is_pipe_type(odm_pipe, OTG_MASTER)); } if (pipe_ctx->stream_res.dsc) { diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c index bddcd23a2727..6d40e93b5497 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn35/dcn35_hwseq.c @@ -451,6 +451,8 @@ void dcn35_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx * struct pipe_ctx *odm_pipe; int opp_cnt = 0; int opp_inst[MAX_PIPES] = {0}; + 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); opp_cnt = get_odm_config(pipe_ctx, opp_inst); @@ -458,7 +460,7 @@ void dcn35_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); diff --git a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c index 5b87186598e6..c01cf2a2f786 100644 --- a/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/hwss/dcn401/dcn401_hwseq.c @@ -744,20 +744,20 @@ static void enable_stream_timing_calc( unsigned int *tmds_div, int *opp_inst, int *opp_cnt, + struct pipe_ctx *opp_heads[MAX_PIPES], bool *manual_mode, struct drr_params *params, unsigned int *event_triggers) { struct dc_stream_state *stream = pipe_ctx->stream; - struct pipe_ctx *odm_pipe; + int i; if (dc_is_tmds_signal(stream->signal) || dc_is_virtual_signal(stream->signal)) dcn401_calculate_dccg_tmds_div_value(pipe_ctx, tmds_div); - 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; if (dc_is_tmds_signal(stream->signal)) { stream->link->phy_state.symclk_ref_cnts.otg = 1; @@ -786,18 +786,21 @@ enum dc_status dcn401_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}; + struct pipe_ctx *opp_heads[MAX_PIPES]; bool manual_mode; unsigned int tmds_div = PIXEL_RATE_DIV_NA; unsigned int unused_div = PIXEL_RATE_DIV_NA; + int odm_slice_width; + int last_odm_slice_width; + int i; if (!resource_is_pipe_type(pipe_ctx, OTG_MASTER)) return DC_OK; enable_stream_timing_calc(pipe_ctx, context, dc, &tmds_div, opp_inst, - &opp_cnt, &manual_mode, ¶ms, &event_triggers); + &opp_cnt, opp_heads, &manual_mode, ¶ms, &event_triggers); if (dc->res_pool->dccg->funcs->set_pixel_rate_div) { dc->res_pool->dccg->funcs->set_pixel_rate_div( @@ -807,11 +810,14 @@ enum dc_status dcn401_enable_stream_timing( /* TODO check if timing_changed, disable stream if timing changed */ - if (opp_cnt > 1) + if (opp_cnt > 1) { + 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); 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); + } /* HW program guide assume display already disable * by unplug sequence. OTG assume stop. @@ -840,10 +846,15 @@ enum dc_status dcn401_enable_stream_timing( pipe_ctx->stream->signal, true); - 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); + 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)); + } pipe_ctx->stream_res.opp->funcs->opp_pipe_clock_control( pipe_ctx->stream_res.opp, @@ -1593,6 +1604,8 @@ void dcn401_update_odm(struct dc *dc, struct dc_state *context, struct pipe_ctx *opp_heads[MAX_PIPES]; int opp_inst[MAX_PIPES] = {0}; int opp_head_count; + int odm_slice_width = resource_get_odm_slice_dst_width(otg_master, false); + int last_odm_slice_width = resource_get_odm_slice_dst_width(otg_master, true); int i; opp_head_count = resource_get_opp_heads_for_otg_master( @@ -1604,16 +1617,21 @@ void dcn401_update_odm(struct dc *dc, struct dc_state *context, otg_master->stream_res.tg->funcs->set_odm_combine( otg_master->stream_res.tg, opp_inst, opp_head_count, - &otg_master->stream->timing); + odm_slice_width, last_odm_slice_width); else otg_master->stream_res.tg->funcs->set_odm_bypass( otg_master->stream_res.tg, &otg_master->stream->timing); - for (i = 0; i < opp_head_count; i++) + for (i = 0; i < opp_head_count; i++) { opp_heads[i]->stream_res.opp->funcs->opp_pipe_clock_control( opp_heads[i]->stream_res.opp, true); + opp_heads[i]->stream_res.opp->funcs->opp_program_left_edge_extra_pixel( + opp_heads[i]->stream_res.opp, + opp_heads[i]->stream->timing.pixel_encoding, + resource_is_pipe_type(opp_heads[i], OTG_MASTER)); + } update_dsc_for_odm_change(dc, context, otg_master); diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h index d89c92370d5b..127fb1a51654 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/opp.h @@ -346,8 +346,13 @@ struct opp_funcs { void (*opp_program_left_edge_extra_pixel)( struct output_pixel_processor *opp, - bool count); + enum dc_pixel_encoding pixel_encoding, + bool is_primary); + uint32_t (*opp_get_left_edge_extra_pixel_count)( + struct output_pixel_processor *opp, + enum dc_pixel_encoding pixel_encoding, + bool is_primary); }; #endif diff --git a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h index a347425c1da2..cd4826f329c1 100644 --- a/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h +++ b/drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h @@ -313,7 +313,7 @@ struct timing_generator_funcs { * OPP(s) and turn on/off ODM memory. */ void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing); + int segment_width, int last_segment_width); void (*get_odm_combine_segments)(struct timing_generator *tg, int *odm_segments); void (*set_h_timing_div_manual_mode)(struct timing_generator *optc, bool manual_mode); void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c index 314a0cee08ae..43417cff2c9b 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.c @@ -179,11 +179,9 @@ void optc2_set_odm_bypass(struct timing_generator *optc, } void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; uint32_t memory_mask; ASSERT(opp_cnt == 2); @@ -213,7 +211,7 @@ void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c OPTC_SEG1_SRC_SEL, opp_id[1]); REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1); optc1->opp_count = opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h index 1f8bc7fce9fc..364034b19028 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn20/dcn20_optc.h @@ -105,7 +105,7 @@ void optc2_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing); + int segment_width, int last_segment_width); void optc2_get_optc_source(struct timing_generator *optc, uint32_t *num_of_src_opp, diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c index c805fd2a48a1..abcd03d78668 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.c @@ -216,11 +216,9 @@ void optc3_set_odm_bypass(struct timing_generator *optc, } void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; uint32_t memory_mask = 0; /* TODO: In pseudocode but does not affect maximus, delete comment if we dont need on asic @@ -267,7 +265,7 @@ void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_c } REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); optc1->opp_count = opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h index d3a056c12b0d..bda974d432ea 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn30/dcn30_optc.h @@ -352,7 +352,7 @@ void optc3_set_timing_db_mode(struct timing_generator *optc, bool enable); void optc3_set_odm_bypass(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); void optc3_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing); + int segment_width, int last_segment_width); void optc3_wait_drr_doublebuffer_pending_clear(struct timing_generator *optc); void optc3_tg_init(struct timing_generator *optc); void optc3_set_vtotal_min_max(struct timing_generator *optc, int vtotal_min, int vtotal_max); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c index 84d2ba31e2ca..de83761edce8 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn31/dcn31_optc.c @@ -41,13 +41,11 @@ optc1->tg_shift->field_name, optc1->tg_mask->field_name static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); - int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) - / opp_cnt; uint32_t memory_mask = 0; - int mem_count_per_opp = (mpcc_hactive + 2559) / 2560; + int mem_count_per_opp = (segment_width + 2559) / 2560; /* Assume less than 6 pipes */ if (opp_cnt == 4) { @@ -85,7 +83,7 @@ static void optc31_set_odm_combine(struct timing_generator *optc, int *opp_id, i } REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); optc1->opp_count = opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c index 9022fb2ffca4..633d62addd4d 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn314/dcn314_optc.c @@ -48,12 +48,11 @@ */ static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; + int h_active = segment_width * opp_cnt; /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ int odm_mem_count = (h_active + 2047) / 2048; @@ -96,7 +95,7 @@ static void optc314_set_odm_combine(struct timing_generator *optc, int *opp_id, } REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c index c18d580279a8..6c837409df42 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn32/dcn32_optc.c @@ -43,12 +43,11 @@ optc1->tg_shift->field_name, optc1->tg_mask->field_name static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; + int h_active = segment_width * opp_cnt; /* Each memory instance is 2048x(32x2) bits to support half line of 4096 */ int odm_mem_count = (h_active + 2047) / 2048; @@ -91,7 +90,7 @@ static void optc32_set_odm_combine(struct timing_generator *optc, int *opp_id, i } REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c index cf8da22492dc..7c9faa507ec2 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn35/dcn35_optc.c @@ -55,12 +55,11 @@ * Return: void. */ static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, - struct dc_crtc_timing *timing) + int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t memory_mask = 0; - int h_active = timing->h_addressable + timing->h_border_left + timing->h_border_right; - int mpcc_hactive = h_active / opp_cnt; + int h_active = segment_width * opp_cnt; /* Each memory instance is 2048x(314x2) bits to support half line of 4096 */ int odm_mem_count = (h_active + 2047) / 2048; @@ -103,7 +102,7 @@ static void optc35_set_odm_combine(struct timing_generator *optc, int *opp_id, i } REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, mpcc_hactive); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, opp_cnt - 1); optc1->opp_count = opp_cnt; diff --git a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c index 099658bcd77f..8ab788b6e6c1 100644 --- a/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c +++ b/drivers/gpu/drm/amd/display/dc/optc/dcn401/dcn401_optc.c @@ -102,22 +102,12 @@ static uint32_t decide_odm_mem_bit_map(int *opp_id, int opp_cnt, int h_active) } static void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id, - int opp_cnt, struct dc_crtc_timing *timing) + int opp_cnt, int segment_width, int last_segment_width) { struct optc *optc1 = DCN10TG_FROM_TG(optc); - uint32_t h_active = timing->h_addressable + - timing->h_border_left + timing->h_border_right; + uint32_t h_active = segment_width * (opp_cnt - 1) + last_segment_width; uint32_t odm_mem_bit_map = decide_odm_mem_bit_map( opp_id, opp_cnt, h_active); - uint32_t odm_segment_width; - uint32_t odm_segment_width_last; - bool is_two_pixels_per_container = optc->funcs->is_two_pixels_per_container(timing); - - odm_segment_width = h_active / opp_cnt; - if ((odm_segment_width % 2) && is_two_pixels_per_container) - odm_segment_width++; - odm_segment_width_last = - h_active - odm_segment_width * (opp_cnt - 1); REG_SET(OPTC_MEMORY_CONFIG, 0, OPTC_MEM_SEL, odm_mem_bit_map); @@ -129,7 +119,7 @@ static void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id, OPTC_SEG0_SRC_SEL, opp_id[0], OPTC_SEG1_SRC_SEL, opp_id[1]); REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, odm_segment_width); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, H_TIMING_DIV_BY2); @@ -141,10 +131,10 @@ static void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id, OPTC_SEG1_SRC_SEL, opp_id[1], OPTC_SEG2_SRC_SEL, opp_id[2]); REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, odm_segment_width); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OPTC_WIDTH_CONTROL2, OPTC_SEGMENT_WIDTH_LAST, - odm_segment_width_last); + last_segment_width); /* In ODM combine 3:1 mode ODM packs 4 pixels per data transfer * so OTG_H_TIMING_DIV_MODE should be configured to * H_TIMING_DIV_BY4 even though ODM combines 3 OPP inputs, it @@ -161,7 +151,7 @@ static void optc401_set_odm_combine(struct timing_generator *optc, int *opp_id, OPTC_SEG2_SRC_SEL, opp_id[2], OPTC_SEG3_SRC_SEL, opp_id[3]); REG_UPDATE(OPTC_WIDTH_CONTROL, - OPTC_SEGMENT_WIDTH, odm_segment_width); + OPTC_SEGMENT_WIDTH, segment_width); REG_UPDATE(OTG_H_TIMING_CNTL, OTG_H_TIMING_DIV_MODE, H_TIMING_DIV_BY4); break; |