drm/amd/display: add optc get crc support for timings with ODM/DSC
authorWenjing Liu <wenjing.liu@amd.com>
Tue, 31 Mar 2020 16:32:53 +0000 (12:32 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Wed, 22 Apr 2020 22:11:47 +0000 (18:11 -0400)
[why]
Optc needs to know if timing is enabled with ODM or DSC before computing
crc.  Otherwise value computed will be inaccurate. Before this change,
the CRC computed without ODM is not equal to the CRC computed with ODM
for the same timing. This is unexpected as we are driving the same
timing despite of the underlaying hardware setup to achieve it. This is
caused by missing hardware programming sequence to support it.

[how]
Add the new programming sequence based on hardware guide.

Signed-off-by: Wenjing Liu <wenjing.liu@amd.com>
Reviewed-by: Nikola Cornij <Nikola.Cornij@amd.com>
Acked-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/core/dc.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_optc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_optc.h
drivers/gpu/drm/amd/display/dc/inc/hw/timing_generator.h

index 9bde05547b30d06290bb86f3c3cdb39ff068a031..d5ecf20312550148226db63ca726f1cfdf2b9e05 100644 (file)
@@ -350,7 +350,7 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
 
        for (i = 0; i < MAX_PIPES; i++) {
                pipe = &dc->current_state->res_ctx.pipe_ctx[i];
-               if (pipe->stream == stream)
+               if (pipe->stream == stream && !pipe->top_pipe && !pipe->prev_odm_pipe)
                        break;
        }
        /* Stream not found */
@@ -367,6 +367,9 @@ bool dc_stream_configure_crc(struct dc *dc, struct dc_stream_state *stream,
        param.windowb_x_end = pipe->stream->timing.h_addressable;
        param.windowb_y_end = pipe->stream->timing.v_addressable;
 
+       param.dsc_mode = pipe->stream->timing.flags.DSC ? 1:0;
+       param.odm_mode = pipe->next_odm_pipe ? 1:0;
+
        /* Default to the union of both windows */
        param.selection = UNION_WINDOW_A_B;
        param.continuous_mode = continuous;
index 9a459a8fe8a055802b3ff7ab550a619938c5eefa..8d1e52fb0393918ff2fd39dc0993484d43c38a02 100644 (file)
@@ -158,6 +158,7 @@ struct dcn_optc_registers {
        uint32_t OTG_GSL_WINDOW_Y;
        uint32_t OTG_VUPDATE_KEEPOUT;
        uint32_t OTG_CRC_CNTL;
+       uint32_t OTG_CRC_CNTL2;
        uint32_t OTG_CRC0_DATA_RG;
        uint32_t OTG_CRC0_DATA_B;
        uint32_t OTG_CRC0_WINDOWA_X_CONTROL;
@@ -475,7 +476,11 @@ struct dcn_optc_registers {
        type OPTC_DSC_SLICE_WIDTH;\
        type OPTC_SEGMENT_WIDTH;\
        type OPTC_DWB0_SOURCE_SELECT;\
-       type OPTC_DWB1_SOURCE_SELECT;
+       type OPTC_DWB1_SOURCE_SELECT;\
+       type OTG_CRC_DSC_MODE;\
+       type OTG_CRC_DATA_STREAM_COMBINE_MODE;\
+       type OTG_CRC_DATA_STREAM_SPLIT_MODE;\
+       type OTG_CRC_DATA_FORMAT;
 
 
 
index d875b0c38fded4928c81e2173ba3b425f5e54963..8c16967fe01807c96eacb37576690a1070a1a2c6 100644 (file)
@@ -409,6 +409,18 @@ void optc2_program_manual_trigger(struct timing_generator *optc)
                        OTG_TRIGA_MANUAL_TRIG, 1);
 }
 
+bool optc2_configure_crc(struct timing_generator *optc,
+                         const struct crc_params *params)
+{
+       struct optc *optc1 = DCN10TG_FROM_TG(optc);
+
+       REG_SET_2(OTG_CRC_CNTL2, 0,
+                       OTG_CRC_DSC_MODE, params->dsc_mode,
+                       OTG_CRC_DATA_STREAM_COMBINE_MODE, params->odm_mode);
+
+       return optc1_configure_crc(optc, params);
+}
+
 static struct timing_generator_funcs dcn20_tg_funcs = {
                .validate_timing = optc1_validate_timing,
                .program_timing = optc1_program_timing,
@@ -452,7 +464,7 @@ static struct timing_generator_funcs dcn20_tg_funcs = {
                .clear_optc_underflow = optc1_clear_optc_underflow,
                .setup_global_swap_lock = NULL,
                .get_crc = optc1_get_crc,
-               .configure_crc = optc1_configure_crc,
+               .configure_crc = optc2_configure_crc,
                .set_dsc_config = optc2_set_dsc_config,
                .set_dwb_source = optc2_set_dwb_source,
                .set_odm_bypass = optc2_set_odm_bypass,
index 239cc40ae474be3765e7bbd54c9766a52b2f9712..e0a0a8a8e2c606214f72fc32cc6e8c2ec6bfc625 100644 (file)
@@ -36,6 +36,7 @@
        SRI(OTG_GSL_WINDOW_Y, OTG, inst),\
        SRI(OTG_VUPDATE_KEEPOUT, OTG, inst),\
        SRI(OTG_DSC_START_POSITION, OTG, inst),\
+       SRI(OTG_CRC_CNTL2, OTG, inst),\
        SRI(OPTC_DATA_FORMAT_CONTROL, ODM, inst),\
        SRI(OPTC_BYTES_PER_PIXEL, ODM, inst),\
        SRI(OPTC_WIDTH_CONTROL, ODM, inst),\
        SF(OTG0_OTG_GSL_CONTROL, OTG_MASTER_UPDATE_LOCK_GSL_EN, mask_sh), \
        SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_X, mask_sh), \
        SF(OTG0_OTG_DSC_START_POSITION, OTG_DSC_START_POSITION_LINE_NUM, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DSC_MODE, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_COMBINE_MODE, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_STREAM_SPLIT_MODE, mask_sh),\
+       SF(OTG0_OTG_CRC_CNTL2, OTG_CRC_DATA_FORMAT, mask_sh),\
        SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG0_SRC_SEL, mask_sh),\
        SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_SEG1_SRC_SEL, mask_sh),\
        SF(ODM0_OPTC_DATA_SOURCE_SELECT, OPTC_NUM_OF_INPUT_SEGMENT, mask_sh),\
@@ -109,4 +114,6 @@ void optc2_lock_doublebuffer_enable(struct timing_generator *optc);
 void optc2_setup_manual_trigger(struct timing_generator *optc);
 void optc2_program_manual_trigger(struct timing_generator *optc);
 bool optc2_is_two_pixels_per_containter(const struct dc_crtc_timing *timing);
+bool optc2_configure_crc(struct timing_generator *optc,
+                         const struct crc_params *params);
 #endif /* __DC_OPTC_DCN20_H__ */
index e5e7d94026fc6b7ed0c796ff508d7f601cbbcd32..f803191e3134ad5db9ffc2282b7934c0156a77fe 100644 (file)
@@ -117,6 +117,9 @@ struct crc_params {
 
        enum crc_selection selection;
 
+       uint8_t dsc_mode;
+       uint8_t odm_mode;
+
        bool continuous_mode;
        bool enable;
 };