drm/amd/display: Set dispclk and dprefclock directly
authorEric Yang <Eric.Yang2@amd.com>
Wed, 3 Apr 2019 19:40:05 +0000 (15:40 -0400)
committerAlex Deucher <alexander.deucher@amd.com>
Fri, 24 May 2019 17:20:49 +0000 (12:20 -0500)
[Why]
To simply logic for setting DCN specific clocks, we will send
SMU message directly through the VBIOS message box.

[How]
Add new structure in pp_smu to hold functions to set clocks
through vbios message box

Signed-off-by: Eric Yang <Eric.Yang2@amd.com>
Reviewed-by: Tony Cheng <Tony.Cheng@amd.com>
Acked-by: Bhawanpreet Lakha <Bhawanpreet.Lakha@amd.com>
Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
drivers/gpu/drm/amd/display/dc/dc_helper.c
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dce/dce_clk_mgr.h
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_clk_mgr.c
drivers/gpu/drm/amd/display/dc/dcn10/dcn10_resource.c
drivers/gpu/drm/amd/display/dc/dm_pp_smu.h
drivers/gpu/drm/amd/display/dc/inc/hw/clk_mgr.h
drivers/gpu/drm/amd/display/include/dal_asic_id.h

index 5e6c5ef..2d0acf1 100644 (file)
@@ -297,7 +297,7 @@ void generic_reg_wait(const struct dc_context *ctx,
        int i;
 
        /* something is terribly wrong if time out is > 200ms. (5Hz) */
-       ASSERT(delay_between_poll_us * time_out_num_tries <= 200000);
+       ASSERT(delay_between_poll_us * time_out_num_tries <= 3000000);
 
        for (i = 0; i <= time_out_num_tries; i++) {
                if (i) {
index 9636863..365c108 100644 (file)
@@ -782,22 +782,22 @@ static void dce12_update_clocks(struct clk_mgr *clk_mgr,
        dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
 }
 
-static const struct clk_mgr_funcs dce120_funcs = {
+static struct clk_mgr_funcs dce120_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = dce12_update_clocks
 };
 
-static const struct clk_mgr_funcs dce112_funcs = {
+static struct clk_mgr_funcs dce112_funcs = {
        .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
        .update_clocks = dce112_update_clocks
 };
 
-static const struct clk_mgr_funcs dce110_funcs = {
+static struct clk_mgr_funcs dce110_funcs = {
        .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
        .update_clocks = dce11_update_clocks,
 };
 
-static const struct clk_mgr_funcs dce_funcs = {
+static struct clk_mgr_funcs dce_funcs = {
        .get_dp_ref_clk_frequency = dce_get_dp_ref_freq_khz,
        .update_clocks = dce_update_clocks
 };
index c8f8c44..36942ab 100644 (file)
 #define CLK_COMMON_REG_LIST_DCN_BASE() \
        SR(DENTIST_DISPCLK_CNTL)
 
+#define VBIOS_SMU_MSG_BOX_REG_LIST_RV() \
+       .MP1_SMN_C2PMSG_91 = mmMP1_SMN_C2PMSG_91, \
+       .MP1_SMN_C2PMSG_83 = mmMP1_SMN_C2PMSG_83, \
+       .MP1_SMN_C2PMSG_67 = mmMP1_SMN_C2PMSG_67
+
 #define CLK_SF(reg_name, field_name, post_fix)\
        .field_name = reg_name ## __ ## field_name ## post_fix
 
        CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_WDIVIDER, mask_sh),\
        CLK_SF(DENTIST_DISPCLK_CNTL, DENTIST_DISPCLK_CHG_DONE, mask_sh)
 
+#define CLK_MASK_SH_LIST_RV1(mask_sh) \
+       CLK_COMMON_MASK_SH_LIST_DCN_COMMON_BASE(mask_sh),\
+       CLK_SF(MP1_SMN_C2PMSG_67, CONTENT, mask_sh),\
+       CLK_SF(MP1_SMN_C2PMSG_83, CONTENT, mask_sh),\
+       CLK_SF(MP1_SMN_C2PMSG_91, CONTENT, mask_sh),
+
+
 #define CLK_REG_FIELD_LIST(type) \
        type DPREFCLK_SRC_SEL; \
        type DENTIST_DPREFCLK_WDIVIDER; \
        type DENTIST_DISPCLK_WDIVIDER; \
        type DENTIST_DISPCLK_CHG_DONE;
 
+#define VBIOS_SMU_REG_FIELD_LIST(type) \
+       type CONTENT;
+
 struct clk_mgr_shift {
        CLK_REG_FIELD_LIST(uint8_t)
+       VBIOS_SMU_REG_FIELD_LIST(uint32_t)
 };
 
 struct clk_mgr_mask {
        CLK_REG_FIELD_LIST(uint32_t)
+       VBIOS_SMU_REG_FIELD_LIST(uint32_t)
 };
 
 struct clk_mgr_registers {
        uint32_t DPREFCLK_CNTL;
        uint32_t DENTIST_DISPCLK_CNTL;
+
+       uint32_t MP1_SMN_C2PMSG_67;
+       uint32_t MP1_SMN_C2PMSG_83;
+       uint32_t MP1_SMN_C2PMSG_91;
 };
 
 struct state_dependent_clocks {
index 2b2de1d..9f2ffce 100644 (file)
@@ -27,6 +27,7 @@
 
 #include "reg_helper.h"
 #include "core_types.h"
+#include "dal_asic_id.h"
 
 #define TO_DCE_CLK_MGR(clocks)\
        container_of(clocks, struct dce_clk_mgr, base)
@@ -91,13 +92,18 @@ static int dcn1_determine_dppclk_threshold(struct clk_mgr *clk_mgr, struct dc_cl
 
 static void dcn1_ramp_up_dispclk_with_dpp(struct clk_mgr *clk_mgr, struct dc_clocks *new_clocks)
 {
+       int i;
        struct dc *dc = clk_mgr->ctx->dc;
        int dispclk_to_dpp_threshold = dcn1_determine_dppclk_threshold(clk_mgr, new_clocks);
        bool request_dpp_div = new_clocks->dispclk_khz > new_clocks->dppclk_khz;
-       int i;
 
        /* set disp clk to dpp clk threshold */
-       dce112_set_clock(clk_mgr, dispclk_to_dpp_threshold);
+
+       if (clk_mgr->funcs->set_dispclk && clk_mgr->funcs->set_dprefclk) {
+               clk_mgr->funcs->set_dispclk(clk_mgr, dispclk_to_dpp_threshold);
+               clk_mgr->funcs->set_dprefclk(clk_mgr);
+       } else
+               dce112_set_clock(clk_mgr, dispclk_to_dpp_threshold);
 
        /* update request dpp clk division option */
        for (i = 0; i < dc->res_pool->pipe_count; i++) {
@@ -113,8 +119,13 @@ static void dcn1_ramp_up_dispclk_with_dpp(struct clk_mgr *clk_mgr, struct dc_clo
        }
 
        /* If target clk not same as dppclk threshold, set to target clock */
-       if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz)
-               dce112_set_clock(clk_mgr, new_clocks->dispclk_khz);
+       if (dispclk_to_dpp_threshold != new_clocks->dispclk_khz) {
+               if (clk_mgr->funcs->set_dispclk && clk_mgr->funcs->set_dprefclk) {
+                       clk_mgr->funcs->set_dispclk(clk_mgr, new_clocks->dispclk_khz);
+                       clk_mgr->funcs->set_dprefclk(clk_mgr);
+               } else
+                       dce112_set_clock(clk_mgr, dispclk_to_dpp_threshold);
+       }
 
        clk_mgr->clks.dispclk_khz = new_clocks->dispclk_khz;
        clk_mgr->clks.dppclk_khz = new_clocks->dppclk_khz;
@@ -242,7 +253,62 @@ static void dcn1_update_clocks(struct clk_mgr *clk_mgr,
                }
        }
 }
-static const struct clk_mgr_funcs dcn1_funcs = {
+
+#define VBIOSSMC_MSG_SetDispclkFreq           0x4
+#define VBIOSSMC_MSG_SetDprefclkFreq          0x5
+
+int dcn10_set_dispclk(struct clk_mgr *clk_mgr_base, int requested_dispclk_khz)
+{
+       int actual_dispclk_set_khz = -1;
+       struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr_base);
+
+       /* First clear response register */
+       //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_91, 0);
+       REG_WRITE(MP1_SMN_C2PMSG_91, 0);
+
+       /* Set the parameter register for the SMU message, unit is Mhz */
+       //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000);
+       REG_WRITE(MP1_SMN_C2PMSG_83, requested_dispclk_khz / 1000);
+
+       /* Trigger the message transaction by writing the message ID */
+       //dm_write_reg(ctx, mmMP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq);
+       REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDispclkFreq);
+
+       REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000);
+
+       /* Actual dispclk set is returned in the parameter register */
+       actual_dispclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000;
+
+       return actual_dispclk_set_khz;
+
+}
+
+int dcn10_set_dprefclk(struct clk_mgr *clk_mgr_base)
+{
+       int actual_dprefclk_set_khz = -1;
+       struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr_base);
+
+       REG_WRITE(MP1_SMN_C2PMSG_91, 0);
+
+       /* Set the parameter register for the SMU message */
+       REG_WRITE(MP1_SMN_C2PMSG_83, clk_mgr_dce->dprefclk_khz / 1000);
+
+       /* Trigger the message transaction by writing the message ID */
+       REG_WRITE(MP1_SMN_C2PMSG_67, VBIOSSMC_MSG_SetDprefclkFreq);
+
+       /* Wait for SMU response */
+       REG_WAIT(MP1_SMN_C2PMSG_91, CONTENT, 1, 10, 200000);
+
+       actual_dprefclk_set_khz = REG_READ(MP1_SMN_C2PMSG_83) * 1000;
+
+       return actual_dprefclk_set_khz;
+}
+
+int (*set_dispclk)(struct pp_smu *pp_smu, int dispclk);
+
+int (*set_dprefclk)(struct pp_smu *pp_smu);
+
+static struct clk_mgr_funcs dcn1_funcs = {
        .get_dp_ref_clk_frequency = dce12_get_dp_ref_freq_khz,
        .update_clocks = dcn1_update_clocks
 };
@@ -266,8 +332,8 @@ struct clk_mgr *dcn1_clk_mgr_create(struct dc_context *ctx)
        clk_mgr_dce->dprefclk_ss_percentage = 0;
        clk_mgr_dce->dprefclk_ss_divider = 1000;
        clk_mgr_dce->ss_on_dprefclk = false;
-
        clk_mgr_dce->dprefclk_khz = 600000;
+
        if (bp->integrated_info)
                clk_mgr_dce->dentist_vco_freq_khz = bp->integrated_info->dentist_vco_freq;
        if (clk_mgr_dce->dentist_vco_freq_khz == 0) {
index 7eccb54..ddb020a 100644 (file)
@@ -29,7 +29,6 @@
 #include "resource.h"
 #include "include/irq_service_interface.h"
 #include "dcn10_resource.h"
-
 #include "dcn10_ipp.h"
 #include "dcn10_mpc.h"
 #include "irq/dcn10/irq_service_dcn10.h"
@@ -445,7 +444,6 @@ static const struct bios_registers bios_regs = {
        HUBP_REG_LIST_DCN10(id)\
 }
 
-
 static const struct dcn_mi_registers hubp_regs[] = {
        hubp_regs(0),
        hubp_regs(1),
@@ -461,7 +459,6 @@ static const struct dcn_mi_mask hubp_mask = {
                HUBP_MASK_SH_LIST_DCN10(_MASK)
 };
 
-
 static const struct dcn_hubbub_registers hubbub_reg = {
                HUBBUB_REG_LIST_DCN10(0)
 };
@@ -494,6 +491,27 @@ static const struct dce110_clk_src_mask cs_mask = {
                CS_COMMON_MASK_SH_LIST_DCN1_0(_MASK)
 };
 
+
+#define mmMP1_SMN_C2PMSG_91            0x1629B
+#define mmMP1_SMN_C2PMSG_83            0x16293
+#define mmMP1_SMN_C2PMSG_67            0x16283
+
+#define MP1_SMN_C2PMSG_91__CONTENT_MASK                    0xffffffffL
+#define MP1_SMN_C2PMSG_83__CONTENT_MASK                    0xffffffffL
+#define MP1_SMN_C2PMSG_67__CONTENT_MASK                    0xffffffffL
+#define        MP1_SMN_C2PMSG_91__CONTENT__SHIFT                  0x00000000
+#define        MP1_SMN_C2PMSG_83__CONTENT__SHIFT                  0x00000000
+#define        MP1_SMN_C2PMSG_67__CONTENT__SHIFT                  0x00000000
+
+
+static const struct clk_mgr_shift clk_mgr_shift = {
+               CLK_MASK_SH_LIST_RV1(__SHIFT)
+};
+
+static const struct clk_mgr_mask clk_mgr_mask = {
+               CLK_MASK_SH_LIST_RV1(_MASK)
+};
+
 static const struct resource_caps res_cap = {
                .num_timing_generator = 4,
                .num_opp = 4,
@@ -1343,12 +1361,6 @@ static bool construct(
                        goto fail;
                }
        }
-       pool->base.clk_mgr = dcn1_clk_mgr_create(ctx);
-       if (pool->base.clk_mgr == NULL) {
-               dm_error("DC: failed to create display clock!\n");
-               BREAK_TO_DEBUGGER();
-               goto fail;
-       }
 
        pool->base.dmcu = dcn10_dmcu_create(ctx,
                        &dmcu_regs,
@@ -1410,6 +1422,13 @@ static bool construct(
 
        pool->base.pp_smu = dcn10_pp_smu_create(ctx);
 
+       pool->base.clk_mgr = dcn1_clk_mgr_create(ctx);
+       if (pool->base.clk_mgr == NULL) {
+               dm_error("DC: failed to create display clock!\n");
+               BREAK_TO_DEBUGGER();
+               goto fail;
+       }
+
        if (!dc->debug.disable_pplib_clock_request)
                dcn_bw_update_from_pplib(dc);
        dcn_bw_sync_calcs_and_dml(dc);
index 4fc4208..9f7ebf6 100644 (file)
@@ -80,6 +80,7 @@ struct pp_smu_funcs_rv {
        /* PPSMC_MSG_SetDisplayCount
         * 0 triggers S0i2 optimization
         */
+
        void (*set_display_count)(struct pp_smu *pp, int count);
 
        /* reader and writer WM's are sent together as part of one table*/
@@ -115,7 +116,6 @@ struct pp_smu_funcs_rv {
 
        /* PME w/a */
        void (*set_pme_wa_enable)(struct pp_smu *pp);
-
 };
 
 struct pp_smu_funcs {
index 31bd6d5..f3fd3f8 100644 (file)
@@ -31,7 +31,7 @@
 
 struct clk_mgr {
        struct dc_context *ctx;
-       const struct clk_mgr_funcs *funcs;
+       struct clk_mgr_funcs *funcs;
 
        struct dc_clocks clks;
 };
@@ -44,6 +44,12 @@ struct clk_mgr_funcs {
        int (*get_dp_ref_clk_frequency)(struct clk_mgr *clk_mgr);
 
        void (*init_clocks)(struct clk_mgr *clk_mgr);
+
+       /* Returns actual clk that's set */
+       int (*set_dispclk)(struct clk_mgr *clk_mgr, int requested_dispclk_khz);
+       int (*set_dprefclk)(struct clk_mgr *clk_mgr);
 };
 
+
+
 #endif /* __DAL_CLK_MGR_H__ */
index 34d6fdc..1a9b750 100644 (file)
 #define INTERNAL_REV_RAVEN_A0             0x00    /* First spin of Raven */
 #define RAVEN_A0 0x01
 #define RAVEN_B0 0x21
-#define PICASSO_A0 0x41
 #if defined(CONFIG_DRM_AMD_DC_DCN1_01)
 /* DCN1_01 */
+#define PICASSO_A0 0x41
 #define RAVEN2_A0 0x81
 #endif
+#define RAVEN1_F0 0xF0
 #define RAVEN_UNKNOWN 0xFF
 
 #if defined(CONFIG_DRM_AMD_DC_DCN1_01)