]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
drm/amd/display: Add source select helper functions
authorHansen Dsouza <hansen.dsouza@amd.com>
Thu, 11 Jul 2024 14:58:51 +0000 (10:58 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Tue, 23 Jul 2024 21:36:21 +0000 (17:36 -0400)
[why & how]
Add source select helpers based on DCCG spec

Reviewed-by: Daniel Miess <daniel.miess@amd.com>
Signed-off-by: Hansen Dsouza <hansen.dsouza@amd.com>
Signed-off-by: Aurabindo Pillai <aurabindo.pillai@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dccg/dcn35/dcn35_dccg.c

index 76f069f703effa8418f992ccbd3b9598c3d242b8..b698b773338ab01fd0f4c35843c7339ac1488947 100644 (file)
@@ -418,6 +418,320 @@ static void dccg35_set_smclk32_se_rcg(
        }
 }
 
+static void dccg35_set_dsc_clk_src_new(struct dccg *dccg, int inst, enum dsc_clk_source src)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       /* DSCCLK#_EN=0 switches to refclock from functional clock */
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK0_EN, src);
+               break;
+       case 1:
+               REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK1_EN, src);
+               break;
+       case 2:
+               REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK2_EN, src);
+               break;
+       case 3:
+               REG_UPDATE(DSCCLK_DTO_CTRL, DSCCLK3_EN, src);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static void dccg35_set_symclk32_se_src_new(
+       struct dccg *dccg,
+       int inst,
+       enum symclk32_se_clk_source src
+       )
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(SYMCLK32_SE_CNTL,
+                                        SYMCLK32_SE0_SRC_SEL, (src == SYMCLK32_SE_REFCLK) ? 0 : src,
+                                        SYMCLK32_SE0_EN,  (src == SYMCLK32_SE_REFCLK) ? 0 : 1);
+               break;
+       case 1:
+               REG_UPDATE_2(SYMCLK32_SE_CNTL,
+                                        SYMCLK32_SE1_SRC_SEL, (src == SYMCLK32_SE_REFCLK) ? 0 : src,
+                                        SYMCLK32_SE1_EN, (src == SYMCLK32_SE_REFCLK) ? 0 : 1);
+               break;
+       case 2:
+               REG_UPDATE_2(SYMCLK32_SE_CNTL,
+                                        SYMCLK32_SE2_SRC_SEL, (src == SYMCLK32_SE_REFCLK) ? 0 : src,
+                                        SYMCLK32_SE2_EN, (src == SYMCLK32_SE_REFCLK) ? 0 : 1);
+               break;
+       case 3:
+               REG_UPDATE_2(SYMCLK32_SE_CNTL,
+                                        SYMCLK32_SE3_SRC_SEL, (src == SYMCLK32_SE_REFCLK) ? 0 : src,
+                                        SYMCLK32_SE3_EN, (src == SYMCLK32_SE_REFCLK) ? 0 : 1);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static int
+dccg35_is_symclk32_se_src_functional_le_new(struct dccg *dccg, int symclk_32_se_inst, int symclk_32_le_inst)
+{
+       uint32_t en;
+       uint32_t src_sel;
+
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       REG_GET_2(SYMCLK32_SE_CNTL, SYMCLK32_SE3_SRC_SEL, &src_sel, SYMCLK32_SE3_EN, &en);
+
+       if (en == 1 && src_sel == symclk_32_le_inst)
+               return 1;
+
+       return 0;
+}
+
+
+static void dccg35_set_symclk32_le_src_new(
+       struct dccg *dccg,
+       int inst,
+       enum symclk32_le_clk_source src)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(SYMCLK32_LE_CNTL,
+                                        SYMCLK32_LE0_SRC_SEL, (src == SYMCLK32_LE_REFCLK) ? 0 : src,
+                                        SYMCLK32_LE0_EN, (src == SYMCLK32_LE_REFCLK) ? 0 : 1);
+               break;
+       case 1:
+               REG_UPDATE_2(SYMCLK32_LE_CNTL,
+                                        SYMCLK32_LE1_SRC_SEL, (src == SYMCLK32_LE_REFCLK) ? 0 : src,
+                                        SYMCLK32_LE1_EN, (src == SYMCLK32_LE_REFCLK) ? 0 : 1);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static void dcn35_set_dppclk_src_new(struct dccg *dccg,
+                                int inst, enum dppclk_clock_source src)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE(DPPCLK_CTRL, DPPCLK0_EN, src);
+               break;
+       case 1:
+               REG_UPDATE(DPPCLK_CTRL, DPPCLK1_EN, src);
+               break;
+       case 2:
+               REG_UPDATE(DPPCLK_CTRL, DPPCLK2_EN, src);
+               break;
+       case 3:
+               REG_UPDATE(DPPCLK_CTRL, DPPCLK3_EN, src);
+               break;
+       default:
+       BREAK_TO_DEBUGGER();
+               break;
+       }
+}
+
+static void dccg35_set_dtbclk_p_src_new(
+       struct dccg *dccg,
+       enum dtbclk_source src,
+       int inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       /* If DTBCLK_P#_EN is 0 refclock is selected as functional clock
+        * If DTBCLK_P#_EN is 1 functional clock is selected as DTBCLK_P#_SRC_SEL
+        */
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(DTBCLK_P_CNTL,
+                                        DTBCLK_P0_SRC_SEL, (src == DTBCLK_REFCLK) ? 0 : src,
+                                        DTBCLK_P0_EN, (src == DTBCLK_REFCLK) ? 0 : 1);
+               break;
+       case 1:
+               REG_UPDATE_2(DTBCLK_P_CNTL,
+                                        DTBCLK_P1_SRC_SEL, (src == DTBCLK_REFCLK) ? 0 : src,
+                                        DTBCLK_P1_EN, (src == DTBCLK_REFCLK) ? 0 : 1);
+               break;
+       case 2:
+               REG_UPDATE_2(DTBCLK_P_CNTL,
+                                        DTBCLK_P2_SRC_SEL, (src == DTBCLK_REFCLK) ? 0 : src,
+                                        DTBCLK_P2_EN, (src == DTBCLK_REFCLK) ? 0 : 1);
+               break;
+       case 3:
+               REG_UPDATE_2(DTBCLK_P_CNTL,
+                                        DTBCLK_P3_SRC_SEL, (src == DTBCLK_REFCLK) ? 0 : src,
+                                        DTBCLK_P3_EN, (src == DTBCLK_REFCLK) ? 0 : 1);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static void dccg35_set_dpstreamclk_src_new(
+       struct dccg *dccg,
+       enum dp_stream_clk_source src,
+       int inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK0_EN,
+                                        (src == DP_STREAM_REFCLK) ? 0 : 1,
+                                        DPSTREAMCLK0_SRC_SEL,
+                                        (src == DP_STREAM_REFCLK) ? 0 : src);
+               break;
+       case 1:
+               REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK1_EN,
+                                        (src == DP_STREAM_REFCLK) ? 0 : 1,
+                                        DPSTREAMCLK1_SRC_SEL,
+                                        (src == DP_STREAM_REFCLK) ? 0 : src);
+
+               break;
+       case 2:
+               REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK2_EN,
+                                        (src == DP_STREAM_REFCLK) ? 0 : 1,
+                                        DPSTREAMCLK2_SRC_SEL,
+                                        (src == DP_STREAM_REFCLK) ? 0 : src);
+
+               break;
+       case 3:
+               REG_UPDATE_2(DPSTREAMCLK_CNTL, DPSTREAMCLK3_EN,
+                                        (src == DP_STREAM_REFCLK) ? 0 : 1,
+                                        DPSTREAMCLK3_SRC_SEL,
+                                        (src == DP_STREAM_REFCLK) ? 0 : src);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static void dccg35_set_physymclk_src_new(
+       struct dccg *dccg,
+       enum physymclk_source src,
+       int inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(PHYASYMCLK_CLOCK_CNTL, PHYASYMCLK_EN,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : 1,
+                                        PHYASYMCLK_SRC_SEL,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : src);
+               break;
+       case 1:
+               REG_UPDATE_2(PHYBSYMCLK_CLOCK_CNTL, PHYBSYMCLK_EN,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : 1,
+                                        PHYBSYMCLK_SRC_SEL,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : src);
+               break;
+       case 2:
+               REG_UPDATE_2(PHYCSYMCLK_CLOCK_CNTL, PHYCSYMCLK_EN,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : 1,
+                                        PHYCSYMCLK_SRC_SEL,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : src);
+               break;
+       case 3:
+               REG_UPDATE_2(PHYDSYMCLK_CLOCK_CNTL, PHYDSYMCLK_EN,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : 1,
+                                        PHYDSYMCLK_SRC_SEL,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : src);
+               break;
+       case 4:
+               REG_UPDATE_2(PHYESYMCLK_CLOCK_CNTL, PHYESYMCLK_EN,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : 1,
+                                        PHYESYMCLK_SRC_SEL,
+                                        (src == PHYSYMCLK_REFCLK) ? 0 : src);
+               break;
+       default:
+               BREAK_TO_DEBUGGER();
+               return;
+       }
+}
+
+static int dccg35_is_symclk_fe_src_functional_be(struct dccg *dccg,
+                                                                                                int symclk_fe_inst,
+                                                                                                int symclk_be_inst)
+{
+
+       uint32_t en = 0;
+       uint32_t src_sel = 0;
+
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (symclk_fe_inst) {
+       case 0:
+               REG_GET_2(SYMCLKA_CLOCK_ENABLE, SYMCLKA_FE_SRC_SEL, &src_sel, SYMCLKA_FE_EN, &en);
+               break;
+       case 1:
+               REG_GET_2(SYMCLKB_CLOCK_ENABLE, SYMCLKB_FE_SRC_SEL, &src_sel, SYMCLKB_FE_EN, &en);
+               break;
+       case 2:
+               REG_GET_2(SYMCLKC_CLOCK_ENABLE, SYMCLKC_FE_SRC_SEL, &src_sel, SYMCLKC_FE_EN, &en);
+               break;
+       case 3:
+               REG_GET_2(SYMCLKD_CLOCK_ENABLE, SYMCLKD_FE_SRC_SEL, &src_sel, SYMCLKD_FE_EN, &en);
+               break;
+       case 4:
+               REG_GET_2(SYMCLKE_CLOCK_ENABLE, SYMCLKE_FE_SRC_SEL, &src_sel, SYMCLKE_FE_EN, &en);
+               break;
+       }
+
+       if (en == 1 && src_sel == symclk_be_inst)
+               return 1;
+
+       return 0;
+}
+
+static void dccg35_set_symclk_fe_src_new(struct dccg *dccg, enum physymclk_fe_source src, int inst)
+{
+       struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
+
+       switch (inst) {
+       case 0:
+               REG_UPDATE_2(SYMCLKA_CLOCK_ENABLE,
+                                        SYMCLKA_FE_EN, (src == PHYSYMCLK_FE_REFCLK) ? 0 : 1,
+                                        SYMCLKA_FE_SRC_SEL, (src == PHYSYMCLK_FE_REFCLK) ? 0 : src);
+               break;
+       case 1:
+               REG_UPDATE_2(SYMCLKB_CLOCK_ENABLE,
+                                        SYMCLKB_FE_EN, (src == PHYSYMCLK_FE_REFCLK) ? 0 : 1,
+                                        SYMCLKB_FE_SRC_SEL, (src == PHYSYMCLK_FE_REFCLK) ? 0 : src);
+               break;
+       case 2:
+               REG_UPDATE_2(SYMCLKC_CLOCK_ENABLE,
+                                        SYMCLKC_FE_EN, (src == PHYSYMCLK_FE_REFCLK) ? 0 : 1,
+                                        SYMCLKC_FE_SRC_SEL, (src == PHYSYMCLK_FE_REFCLK) ? 0 : src);
+               break;
+       case 3:
+               REG_UPDATE_2(SYMCLKD_CLOCK_ENABLE,
+                                        SYMCLKD_FE_EN, (src == PHYSYMCLK_FE_REFCLK) ? 0 : 1,
+                                        SYMCLKD_FE_SRC_SEL, (src == PHYSYMCLK_FE_REFCLK) ? 0 : src);
+               break;
+       case 4:
+               REG_UPDATE_2(SYMCLKE_CLOCK_ENABLE,
+                                        SYMCLKE_FE_EN, (src == PHYSYMCLK_FE_REFCLK) ? 0 : 1,
+                                        SYMCLKE_FE_SRC_SEL, (src == PHYSYMCLK_FE_REFCLK) ? 0 : src);
+               break;
+       }
+}
+
 static void dccg35_trigger_dio_fifo_resync(struct dccg *dccg)
 {
        struct dcn_dccg *dccg_dcn = TO_DCN_DCCG(dccg);
@@ -1429,6 +1743,16 @@ struct dccg *dccg35_create(
        (void)&dccg35_set_dppclk_rcg;
        (void)&dccg35_set_dpstreamclk_rcg;
        (void)&dccg35_set_smclk32_se_rcg;
+       (void)&dccg35_set_dsc_clk_src_new;
+       (void)&dccg35_set_symclk32_se_src_new;
+       (void)&dccg35_is_symclk32_se_src_functional_le_new;
+       (void)&dccg35_set_symclk32_le_src_new;
+       (void)&dcn35_set_dppclk_src_new;
+       (void)&dccg35_set_dtbclk_p_src_new;
+       (void)&dccg35_set_dpstreamclk_src_new;
+       (void)&dccg35_set_physymclk_src_new;
+       (void)&dccg35_is_symclk_fe_src_functional_be;
+       (void)&dccg35_set_symclk_fe_src_new;
 
        base = &dccg_dcn->base;
        base->ctx = ctx;