drm/amd/display: Fix double buffering in dcn2 ICSC
authorNoah Abradjian <noah.abradjian@amd.com>
Fri, 13 Dec 2019 14:31:20 +0000 (09:31 -0500)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 16 Jan 2020 19:13:16 +0000 (14:13 -0500)
[Why]
When rapidly adjusting video brightness, screen tearing was observed.
This was due to overwritten values in ICSC registers. In dcn10, this issue had been
fixed by implementing double buffering via alternating ICSC modes.
However, the second register set used in dcn1 doesn't exist in dcn2.

[How]
Create new program_input_csc for dcn20.
Use ICSC_B registers instead of COMA registers as second set.

Signed-off-by: Noah Abradjian <noah.abradjian@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Harry Wentland <harry.wentland@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/dcn10/dcn10_dpp_cm.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_dpp_cm.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.c
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_mpc.h
drivers/gpu/drm/amd/display/dc/dcn20/dcn20_resource.c
drivers/gpu/drm/amd/display/dc/dcn21/dcn21_resource.c
drivers/gpu/drm/amd/display/dc/inc/hw/dpp.h

index 935c892622a06be6169956851729f0c89e48d931..4d3f7d5e1473afa1f61b379729f6528eb5702c64 100644 (file)
@@ -88,26 +88,6 @@ enum dscl_mode_sel {
        DSCL_MODE_DSCL_BYPASS = 6
 };
 
-static const struct dpp_input_csc_matrix dpp_input_csc_matrix[] = {
-       {COLOR_SPACE_SRGB,
-               {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-       {COLOR_SPACE_SRGB_LIMITED,
-               {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
-       {COLOR_SPACE_YCBCR601,
-               {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
-                                               0, 0x2000, 0x38b4, 0xe3a6} },
-       {COLOR_SPACE_YCBCR601_LIMITED,
-               {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
-                                               0, 0x2568, 0x40de, 0xdd3a} },
-       {COLOR_SPACE_YCBCR709,
-               {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
-                                               0x2000, 0x3b61, 0xe24f} },
-
-       {COLOR_SPACE_YCBCR709_LIMITED,
-               {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
-                                               0x2568, 0x43ee, 0xdbb2} }
-};
-
 static void program_gamut_remap(
                struct dcn10_dpp *dpp,
                const uint16_t *regval,
index 4d7e45892f087ac81db26a2aaff99de449201b99..bbdab5000a7ccc178e1f8b3cd2be05e4bcabe216 100644 (file)
@@ -104,7 +104,7 @@ static void dpp2_cnv_setup (
        uint32_t pixel_format = 0;
        uint32_t alpha_en = 1;
        enum dc_color_space color_space = COLOR_SPACE_SRGB;
-       enum dcn10_input_csc_select select = INPUT_CSC_SELECT_BYPASS;
+       enum dcn20_input_csc_select select = DCN2_ICSC_SELECT_BYPASS;
        bool force_disable_cursor = false;
        struct out_csc_color_matrix tbl_entry;
        uint32_t is_2bit = 0;
@@ -145,25 +145,25 @@ static void dpp2_cnv_setup (
                force_disable_cursor = false;
                pixel_format = 65;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                break;
        case SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb:
                force_disable_cursor = true;
                pixel_format = 64;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                break;
        case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCbCr:
                force_disable_cursor = true;
                pixel_format = 67;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                break;
        case SURFACE_PIXEL_FORMAT_VIDEO_420_10bpc_YCrCb:
                force_disable_cursor = true;
                pixel_format = 66;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                break;
        case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
                pixel_format = 22;
@@ -177,7 +177,7 @@ static void dpp2_cnv_setup (
        case SURFACE_PIXEL_FORMAT_VIDEO_AYCrCb8888:
                pixel_format = 12;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                break;
        case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FIX:
                pixel_format = 112;
@@ -188,13 +188,13 @@ static void dpp2_cnv_setup (
        case SURFACE_PIXEL_FORMAT_VIDEO_ACrYCb2101010:
                pixel_format = 114;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                is_2bit = 1;
                break;
        case SURFACE_PIXEL_FORMAT_VIDEO_CrYCbA1010102:
                pixel_format = 115;
                color_space = COLOR_SPACE_YCBCR709;
-               select = INPUT_CSC_SELECT_ICSC;
+               select = DCN2_ICSC_SELECT_ICSC_A;
                is_2bit = 1;
                break;
        case SURFACE_PIXEL_FORMAT_GRPH_RGB111110_FLOAT:
@@ -227,13 +227,13 @@ static void dpp2_cnv_setup (
                tbl_entry.color_space = input_color_space;
 
                if (color_space >= COLOR_SPACE_YCBCR601)
-                       select = INPUT_CSC_SELECT_ICSC;
+                       select = DCN2_ICSC_SELECT_ICSC_A;
                else
-                       select = INPUT_CSC_SELECT_BYPASS;
+                       select = DCN2_ICSC_SELECT_BYPASS;
 
-               dpp1_program_input_csc(dpp_base, color_space, select, &tbl_entry);
+               dpp2_program_input_csc(dpp_base, color_space, select, &tbl_entry);
        } else
-       dpp1_program_input_csc(dpp_base, color_space, select, NULL);
+       dpp2_program_input_csc(dpp_base, color_space, select, NULL);
 
        if (force_disable_cursor) {
                REG_UPDATE(CURSOR_CONTROL,
index 5b03b737b1d6104f2e95ea6e9780f6e940ce77dc..d9ce60b6aa6efef3e8f1bcfff1eaae9afb76cb18 100644 (file)
        SRI(CM_SHAPER_RAMA_REGION_32_33, CM, id), \
        SRI(CM_SHAPER_LUT_INDEX, CM, id)
 
+#define TF_REG_LIST_DCN20_COMMON_APPEND(id) \
+       SRI(CM_ICSC_B_C11_C12, CM, id), \
+       SRI(CM_ICSC_B_C33_C34, CM, id)
+
 #define TF_REG_LIST_DCN20(id) \
        TF_REG_LIST_DCN(id), \
        TF_REG_LIST_DCN20_COMMON(id), \
        TF_SF(DSCL0_OBUF_MEM_PWR_CTRL, OBUF_MEM_PWR_FORCE, mask_sh),\
        TF_SF(DSCL0_DSCL_MEM_PWR_CTRL, LUT_MEM_PWR_FORCE, mask_sh)
 
+/* DPP CM debug status register:
+ *
+ *             Status index including current ICSC, Gamut Remap Mode is 9
+ *                     ICSC Mode: [5..4]
+ */
+#define CM_TEST_DEBUG_DATA_STATUS_IDX 9
+#define CM_TEST_DEBUG_DATA_ICSC_MODE_SH 4
+#define CM_TEST_DEBUG_DATA_ICSC_MODE_MASK 0x3
 
 #define TF_REG_FIELD_LIST_DCN2_0(type) \
        TF_REG_FIELD_LIST(type) \
@@ -630,11 +642,16 @@ struct dcn2_dpp_mask {
        uint32_t COLOR_KEYER_RED; \
        uint32_t COLOR_KEYER_GREEN; \
        uint32_t COLOR_KEYER_BLUE; \
-       uint32_t OBUF_MEM_PWR_CTRL;\
+       uint32_t OBUF_MEM_PWR_CTRL; \
        uint32_t DSCL_MEM_PWR_CTRL
 
+#define DPP_DCN2_REG_VARIABLE_LIST_CM_APPEND \
+       uint32_t CM_ICSC_B_C11_C12; \
+       uint32_t CM_ICSC_B_C33_C34
+
 struct dcn2_dpp_registers {
        DPP_DCN2_REG_VARIABLE_LIST;
+       DPP_DCN2_REG_VARIABLE_LIST_CM_APPEND;
 };
 
 struct dcn20_dpp {
@@ -656,6 +673,12 @@ struct dcn20_dpp {
        struct pwl_params pwl_data;
 };
 
+enum dcn20_input_csc_select {
+       DCN2_ICSC_SELECT_BYPASS = 0,
+       DCN2_ICSC_SELECT_ICSC_A = 1,
+       DCN2_ICSC_SELECT_ICSC_B = 2
+};
+
 void dpp20_read_state(struct dpp *dpp_base,
                struct dcn_dpp_state *s);
 
@@ -667,6 +690,12 @@ void dpp2_set_degamma(
                struct dpp *dpp_base,
                enum ipp_degamma_mode mode);
 
+void dpp2_program_input_csc(
+               struct dpp *dpp_base,
+               enum dc_color_space color_space,
+               enum dcn20_input_csc_select input_select,
+               const struct out_csc_color_matrix *tbl_entry);
+
 bool dpp20_program_blnd_lut(
        struct dpp *dpp_base, const struct pwl_params *params);
 
index 05a3e7f97ef05eb78ae3e6244f86b0a8344e6851..423f3daa177f25bbd76d58cccb1658f9da58f199 100644 (file)
@@ -36,6 +36,9 @@
 #define REG(reg)\
        dpp->tf_regs->reg
 
+#define IND_REG(index) \
+       (index)
+
 #define CTX \
        dpp->base.ctx
 
@@ -44,9 +47,6 @@
        dpp->tf_shift->field_name, dpp->tf_mask->field_name
 
 
-
-
-
 static void dpp2_enable_cm_block(
                struct dpp *dpp_base)
 {
@@ -158,6 +158,83 @@ void dpp2_set_degamma(
        }
 }
 
+void dpp2_program_input_csc(
+               struct dpp *dpp_base,
+               enum dc_color_space color_space,
+               enum dcn20_input_csc_select input_select,
+               const struct out_csc_color_matrix *tbl_entry)
+{
+       struct dcn20_dpp *dpp = TO_DCN20_DPP(dpp_base);
+       int i;
+       int arr_size = sizeof(dpp_input_csc_matrix)/sizeof(struct dpp_input_csc_matrix);
+       const uint16_t *regval = NULL;
+       uint32_t cur_select = 0;
+       enum dcn20_input_csc_select select;
+       struct color_matrices_reg icsc_regs;
+
+       if (input_select == DCN2_ICSC_SELECT_BYPASS) {
+               REG_SET(CM_ICSC_CONTROL, 0, CM_ICSC_MODE, 0);
+               return;
+       }
+
+       if (tbl_entry == NULL) {
+               for (i = 0; i < arr_size; i++)
+                       if (dpp_input_csc_matrix[i].color_space == color_space) {
+                               regval = dpp_input_csc_matrix[i].regval;
+                               break;
+                       }
+
+               if (regval == NULL) {
+                       BREAK_TO_DEBUGGER();
+                       return;
+               }
+       } else {
+               regval = tbl_entry->regval;
+       }
+
+       /* determine which CSC coefficients (A or B) we are using
+        * currently.  select the alternate set to double buffer
+        * the CSC update so CSC is updated on frame boundary
+        */
+       cur_select = IX_REG_READ(CM_TEST_DEBUG_INDEX, CM_TEST_DEBUG_DATA,
+                                       CM_TEST_DEBUG_DATA_STATUS_IDX);
+
+       /* IX_REG_READ reads whole reg, so isolate part we want [5..4] */
+       cur_select = (cur_select >> CM_TEST_DEBUG_DATA_ICSC_MODE_SH)
+                                       & CM_TEST_DEBUG_DATA_ICSC_MODE_MASK;
+
+       /* value stored in dbg reg will be 1 greater than mode we want */
+       if (cur_select - 1 != DCN2_ICSC_SELECT_ICSC_A)
+               select = DCN2_ICSC_SELECT_ICSC_A;
+       else
+               select = DCN2_ICSC_SELECT_ICSC_B;
+
+       icsc_regs.shifts.csc_c11 = dpp->tf_shift->CM_ICSC_C11;
+       icsc_regs.masks.csc_c11  = dpp->tf_mask->CM_ICSC_C11;
+       icsc_regs.shifts.csc_c12 = dpp->tf_shift->CM_ICSC_C12;
+       icsc_regs.masks.csc_c12 = dpp->tf_mask->CM_ICSC_C12;
+
+       if (select == DCN2_ICSC_SELECT_ICSC_A) {
+
+               icsc_regs.csc_c11_c12 = REG(CM_ICSC_C11_C12);
+               icsc_regs.csc_c33_c34 = REG(CM_ICSC_C33_C34);
+
+       } else {
+
+               icsc_regs.csc_c11_c12 = REG(CM_ICSC_B_C11_C12);
+               icsc_regs.csc_c33_c34 = REG(CM_ICSC_B_C33_C34);
+
+       }
+
+       cm_helper_program_color_matrices(
+                       dpp->base.ctx,
+                       regval,
+                       &icsc_regs);
+
+       REG_SET(CM_ICSC_CONTROL, 0,
+                               CM_ICSC_MODE, select);
+}
+
 static void dpp20_power_on_blnd_lut(
        struct dpp *dpp_base,
        bool power_on)
index c38f7fdb43a8ccb59cabeceacc0d652847d733af..ce95e7db48142d0d8d34025befa6658603fad9db 100644 (file)
@@ -154,7 +154,10 @@ void mpc2_set_output_csc(
         * the CSC update so CSC is updated on frame boundary
         */
        cur_mode = IX_REG_READ(MPC_OCSC_TEST_DEBUG_INDEX, MPC_OCSC_TEST_DEBUG_DATA,
-                                               MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_IDX);
+                                               MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX);
+
+       /* Isolate part of reg data we want [1..0] */
+       cur_mode = cur_mode & MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_MASK;
 
        if (cur_mode != MPC_OUTPUT_CSC_COEF_A)
                ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
@@ -211,7 +214,10 @@ void mpc2_set_ocsc_default(
         * the CSC update so CSC is updated on frame boundary
         */
        cur_mode = IX_REG_READ(MPC_OCSC_TEST_DEBUG_INDEX, MPC_OCSC_TEST_DEBUG_DATA,
-                                               MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_IDX);
+                                               MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX);
+
+       /* Isolate part of reg data we want [1..0] */
+       cur_mode = cur_mode & MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_MASK;
 
        if (cur_mode != MPC_OUTPUT_CSC_COEF_A)
                ocsc_mode = MPC_OUTPUT_CSC_COEF_A;
index 8c77e78e2df53952624f998c73ecb856481ff847..950e6f9cd23e2d8154abd2af1192bf73bd9d1999 100644 (file)
 /*
  *     DCN2 MPC_OCSC debug status register:
  *
- *             Field describing current OCSC Mode has index 1 [1..0]
+ *             Status index including current OCSC Mode is 1
+ *                     OCSC Mode: [1..0]
  */
-#define MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_IDX 1
+#define MPC_OCSC_TEST_DEBUG_DATA_STATUS_IDX 1
+#define MPC_OCSC_TEST_DEBUG_DATA_OCSC_MODE_MASK 0x3
 
 #define MPC_REG_FIELD_LIST_DCN2_0(type) \
        MPC_REG_FIELD_LIST(type)\
index 9233144ae74ee574598e2cd7bfa9563c970c4149..2ef6d0e2b0ed006637525701789d2c8aab5eda90 100644 (file)
@@ -638,6 +638,7 @@ static const struct dce110_aux_registers aux_engine_regs[] = {
 #define tf_regs(id)\
 [id] = {\
        TF_REG_LIST_DCN20(id),\
+       TF_REG_LIST_DCN20_COMMON_APPEND(id),\
 }
 
 static const struct dcn2_dpp_registers tf_regs[] = {
index 5a6e7ac5f7854befaaa744c2cf3d6d765736da35..81e087e85721befb1f41c29612bf361ca491757f 100644 (file)
@@ -609,6 +609,7 @@ static const struct dce110_aux_registers aux_engine_regs[] = {
 #define tf_regs(id)\
 [id] = {\
        TF_REG_LIST_DCN20(id),\
+       TF_REG_LIST_DCN20_COMMON_APPEND(id),\
 }
 
 static const struct dcn2_dpp_registers tf_regs[] = {
@@ -619,11 +620,13 @@ static const struct dcn2_dpp_registers tf_regs[] = {
 };
 
 static const struct dcn2_dpp_shift tf_shift = {
-               TF_REG_LIST_SH_MASK_DCN20(__SHIFT)
+               TF_REG_LIST_SH_MASK_DCN20(__SHIFT),
+               TF_DEBUG_REG_LIST_SH_DCN10
 };
 
 static const struct dcn2_dpp_mask tf_mask = {
-               TF_REG_LIST_SH_MASK_DCN20(_MASK)
+               TF_REG_LIST_SH_MASK_DCN20(_MASK),
+               TF_DEBUG_REG_LIST_MASK_DCN10
 };
 
 #define stream_enc_regs(id)\
index 125e42dbd3c581727b3221c3cf4fa89b8be36725..45ef390ae052cf26d4234a4ec41915e45de7e20b 100644 (file)
@@ -47,6 +47,26 @@ struct dpp_input_csc_matrix {
        uint16_t regval[12];
 };
 
+static const struct dpp_input_csc_matrix dpp_input_csc_matrix[] = {
+       {COLOR_SPACE_SRGB,
+               {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+       {COLOR_SPACE_SRGB_LIMITED,
+               {0x2000, 0, 0, 0, 0, 0x2000, 0, 0, 0, 0, 0x2000, 0} },
+       {COLOR_SPACE_YCBCR601,
+               {0x2cdd, 0x2000, 0, 0xe991, 0xe926, 0x2000, 0xf4fd, 0x10ef,
+                                               0, 0x2000, 0x38b4, 0xe3a6} },
+       {COLOR_SPACE_YCBCR601_LIMITED,
+               {0x3353, 0x2568, 0, 0xe400, 0xe5dc, 0x2568, 0xf367, 0x1108,
+                                               0, 0x2568, 0x40de, 0xdd3a} },
+       {COLOR_SPACE_YCBCR709,
+               {0x3265, 0x2000, 0, 0xe6ce, 0xf105, 0x2000, 0xfa01, 0xa7d, 0,
+                                               0x2000, 0x3b61, 0xe24f} },
+
+       {COLOR_SPACE_YCBCR709_LIMITED,
+               {0x39a6, 0x2568, 0, 0xe0d6, 0xeedd, 0x2568, 0xf925, 0x9a8, 0,
+                                               0x2568, 0x43ee, 0xdbb2} }
+};
+
 struct dpp_grph_csc_adjustment {
        struct fixed31_32 temperature_matrix[CSC_TEMPERATURE_MATRIX_SIZE];
        enum graphics_gamut_adjust_type gamut_adjust_type;