drm/amd/display: Avoid unnecessary pixel rate divider programming
authorTaimur Hassan <Syed.Hassan@amd.com>
Tue, 13 Sep 2022 22:35:20 +0000 (18:35 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Thu, 29 Sep 2022 13:41:45 +0000 (09:41 -0400)
[Why]
Programming pixel rate divider when FIFO is enabled can cause FIFO error.

[How]
Skip divider programming when divider values are the same to prevent FIFO
error.

Reviewed-by: Alvin Lee <alvin.lee2@amd.com>
Acked-by: Jasdeep Dhillon <jdhillon@amd.com>
Signed-off-by: Taimur Hassan <Syed.Hassan@amd.com>
Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dcn32/dcn32_dccg.c

index 26eb04ea472c0fd66f07d69d6643431e9b151413..e4daed44ef5f9038c81f31c5da5d0263e2acb060 100644 (file)
 #define DC_LOGGER \
        dccg->ctx->logger
 
+static void dccg32_get_pixel_rate_div(
+               struct dccg *dccg,
+               uint32_t otg_inst,
+               enum pixel_rate_div *k1,
+               enum pixel_rate_div *k2)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+       uint32_t val_k1 = PIXEL_RATE_DIV_NA, val_k2 = PIXEL_RATE_DIV_NA;
+
+       *k1 = PIXEL_RATE_DIV_NA;
+       *k2 = PIXEL_RATE_DIV_NA;
+
+       switch (otg_inst) {
+       case 0:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG0_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG0_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 1:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG1_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG1_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 2:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG2_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG2_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       case 3:
+               REG_GET_2(OTG_PIXEL_RATE_DIV,
+                       OTG3_PIXEL_RATE_DIVK1, &val_k1,
+                       OTG3_PIXEL_RATE_DIVK2, &val_k2);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+
+       *k1 = (enum pixel_rate_div)val_k1;
+       *k2 = (enum pixel_rate_div)val_k2;
+}
+
 static void dccg32_set_pixel_rate_div(
                struct dccg *dccg,
                uint32_t otg_inst,
@@ -50,6 +92,17 @@ static void dccg32_set_pixel_rate_div(
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
 
+       enum pixel_rate_div cur_k1 = PIXEL_RATE_DIV_NA, cur_k2 = PIXEL_RATE_DIV_NA;
+
+       // Don't program 0xF into the register field. Not valid since
+       // K1 / K2 field is only 1 / 2 bits wide
+       if (k1 == PIXEL_RATE_DIV_NA || k2 == PIXEL_RATE_DIV_NA)
+               return;
+
+       dccg32_get_pixel_rate_div(dccg, otg_inst, &cur_k1, &cur_k2);
+       if (k1 == cur_k1 && k2 == cur_k2)
+               return;
+
        switch (otg_inst) {
        case 0:
                REG_UPDATE_2(OTG_PIXEL_RATE_DIV,