From 2b162fd3024997b97c95290b0a8ed08d914f115d Mon Sep 17 00:00:00 2001 From: Dmytro Laktyushkin Date: Fri, 19 Jul 2019 11:43:39 -0400 Subject: [PATCH] drm/amd/display: update optc odm interface for more than 2 opps Current optc odm interface only accepts 2 opps, we need to expand this to allow 4 to 1 odm combine. Signed-off-by: Dmytro Laktyushkin Reviewed-by: Charlene Liu Acked-by: Leo Li Signed-off-by: Alex Deucher --- .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.c | 3 +-- .../gpu/drm/amd/display/dc/dcn10/dcn10_optc.h | 2 +- .../drm/amd/display/dc/dcn20/dcn20_hwseq.c | 22 +++++++++++-------- .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.c | 20 +++++++++-------- .../gpu/drm/amd/display/dc/dcn20/dcn20_optc.h | 4 ++-- .../amd/display/dc/inc/hw/timing_generator.h | 6 ++--- 6 files changed, 31 insertions(+), 26 deletions(-) diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c index a546c2bc9129..b631786a4a34 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.c @@ -287,7 +287,7 @@ void optc1_program_timing( h_div_2 = optc1_is_two_pixels_per_containter(&patched_crtc_timing); REG_UPDATE(OTG_H_TIMING_CNTL, - OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->comb_opp_id != 0xf); + OTG_H_TIMING_DIV_BY2, h_div_2 || optc1->opp_count == 2); } @@ -1513,7 +1513,6 @@ void dcn10_timing_generator_init(struct optc *optc1) optc1->min_v_blank_interlace = 5; optc1->min_h_sync_width = 8; optc1->min_v_sync_width = 1; - optc1->comb_opp_id = 0xf; } #ifdef CONFIG_DRM_AMD_DC_DSC_SUPPORT diff --git a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h index 66c08d05da0e..82d91ab54ba5 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h @@ -494,7 +494,7 @@ struct optc { const struct dcn_optc_shift *tg_shift; const struct dcn_optc_mask *tg_mask; - int comb_opp_id; + int opp_count; uint32_t max_h_total; uint32_t max_v_total; diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c index c3635f5cd990..5904d4d329df 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_hwseq.c @@ -545,12 +545,14 @@ enum dc_status dcn20_enable_stream_timing( /* TODO check if timing_changed, disable stream if timing changed */ - if (odm_pipe) + if (odm_pipe) { + int opp_inst[2] = { pipe_ctx->stream_res.opp->inst, odm_pipe->stream_res.opp->inst }; + pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg, - odm_pipe->stream_res.opp->inst, - pipe_ctx->stream->timing.h_addressable/2, - pipe_ctx->stream->timing.pixel_encoding); + opp_inst, 2, + &pipe_ctx->stream->timing); + } /* HW program guide assume display already disable * by unplug sequence. OTG assume stop. */ @@ -822,13 +824,15 @@ static void dcn20_update_odm(struct dc *dc, struct dc_state *context, struct pip { struct pipe_ctx *combine_pipe = dc_res_get_odm_bottom_pipe(pipe_ctx); - if (combine_pipe) + if (combine_pipe) { + int opp_inst[2] = { pipe_ctx->stream_res.opp->inst, + combine_pipe->stream_res.opp->inst }; + pipe_ctx->stream_res.tg->funcs->set_odm_combine( pipe_ctx->stream_res.tg, - combine_pipe->stream_res.opp->inst, - pipe_ctx->plane_res.scl_data.h_active, - pipe_ctx->stream->timing.pixel_encoding); - else + opp_inst, 2, + &pipe_ctx->stream->timing); + } 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/dcn20/dcn20_optc.c b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c index 6dede495d0fd..aedf9de1c947 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c @@ -224,7 +224,6 @@ void optc2_set_odm_bypass(struct timing_generator *optc, struct optc *optc1 = DCN10TG_FROM_TG(optc); uint32_t h_div_2 = 0; - optc1->comb_opp_id = 0xf; REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, OPTC_NUM_OF_INPUT_SEGMENT, 0, OPTC_SEG0_SRC_SEL, optc->inst, @@ -236,13 +235,16 @@ void optc2_set_odm_bypass(struct timing_generator *optc, OTG_H_TIMING_DIV_BY2, h_div_2); REG_SET(OPTC_MEMORY_CONFIG, 0, OPTC_MEM_SEL, 0); + optc1->opp_count = 1; } -void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id, - int mpcc_hactive, enum dc_pixel_encoding pixel_encoding) +void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing) { struct optc *optc1 = DCN10TG_FROM_TG(optc); /* 2 pieces of memory required for up to 5120 displays, 4 for up to 8192 */ + int mpcc_hactive = (timing->h_addressable + timing->h_border_left + timing->h_border_right) + / opp_cnt; int memory_mask = mpcc_hactive <= 2560 ? 0x3 : 0xf; uint32_t data_fmt = 0; @@ -257,23 +259,24 @@ void optc2_set_odm_combine(struct timing_generator *optc, int combine_opp_id, REG_SET(OPTC_MEMORY_CONFIG, 0, OPTC_MEM_SEL, memory_mask << (optc->inst * 4)); - if (pixel_encoding == PIXEL_ENCODING_YCBCR422) + if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR422) data_fmt = 1; - else if (pixel_encoding == PIXEL_ENCODING_YCBCR420) + else if (timing->pixel_encoding == PIXEL_ENCODING_YCBCR420) data_fmt = 2; REG_UPDATE(OPTC_DATA_FORMAT_CONTROL, OPTC_DATA_FORMAT, data_fmt); + ASSERT(opp_cnt == 2); REG_SET_3(OPTC_DATA_SOURCE_SELECT, 0, OPTC_NUM_OF_INPUT_SEGMENT, 1, - OPTC_SEG0_SRC_SEL, optc->inst, - OPTC_SEG1_SRC_SEL, combine_opp_id); + OPTC_SEG0_SRC_SEL, opp_id[0], + OPTC_SEG1_SRC_SEL, opp_id[1]); REG_UPDATE(OPTC_WIDTH_CONTROL, OPTC_SEGMENT_WIDTH, mpcc_hactive); REG_SET(OTG_H_TIMING_CNTL, 0, OTG_H_TIMING_DIV_BY2, 1); - optc1->comb_opp_id = combine_opp_id; + optc1->opp_count = opp_cnt; } void optc2_get_optc_source(struct timing_generator *optc, @@ -538,6 +541,5 @@ void dcn20_timing_generator_init(struct optc *optc1) optc1->min_v_blank_interlace = 5; optc1->min_h_sync_width = 4;// Minimum HSYNC = 8 pixels asked By HW in the first place for no actual reason. Oculus Rift S will not light up with 8 as it's hsyncWidth is 6. Changing it to 4 to fix that issue. optc1->min_v_sync_width = 1; - optc1->comb_opp_id = 0xf; } diff --git a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h index ebf07c582da2..47cb4de1564c 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h +++ b/drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h @@ -96,8 +96,8 @@ void optc2_set_dsc_config(struct timing_generator *optc, 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 combine_opp_id, - int mpcc_hactive, enum dc_pixel_encoding pixel_encoding); +void optc2_set_odm_combine(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing); void optc2_get_optc_source(struct timing_generator *optc, uint32_t *num_of_src_opp, 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 5e93bc0e8ff9..1f83cb7c7dd4 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 @@ -267,9 +267,9 @@ struct timing_generator_funcs { uint32_t dsc_bytes_per_pixel, uint32_t dsc_slice_width); #endif - void (*set_odm_bypass)(struct timing_generator *tg, const struct dc_crtc_timing *dc_crtc_timing); - void (*set_odm_combine)(struct timing_generator *tg, int combine_opp_id, - int mpcc_hactive, enum dc_pixel_encoding pixel_encoding); + void (*set_odm_bypass)(struct timing_generator *optc, const struct dc_crtc_timing *dc_crtc_timing); + void (*set_odm_combine)(struct timing_generator *optc, int *opp_id, int opp_cnt, + struct dc_crtc_timing *timing); void (*set_gsl)(struct timing_generator *optc, const struct gsl_params *params); void (*set_gsl_source_select)(struct timing_generator *optc, int group_idx, -- 2.30.2