static int dce_clocks_get_dp_ref_freq(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); int dprefclk_wdivider; int dprefclk_src_sel; int dp_ref_clk_khz = 600000; int target_div = INVALID_DIVIDER; /* ASSERT DP Reference Clock source is from DFS*/ REG_GET(DPREFCLK_CNTL, DPREFCLK_SRC_SEL, &dprefclk_src_sel); ASSERT(dprefclk_src_sel == 0); /* Read the mmDENTIST_DISPCLK_CNTL to get the currently * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ REG_GET(DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER, &dprefclk_wdivider); /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ target_div = dce_divider_range_get_divider( clk_dce->divider_ranges, DIVIDER_RANGE_MAX, dprefclk_wdivider); if (target_div != INVALID_DIVIDER) { /* Calculate the current DFS clock, in kHz.*/ dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR * clk_dce->dentist_vco_freq_khz) / target_div; } /* SW will adjust DP REF Clock average value for all purposes * (DP DTO / DP Audio DTO and DP GTC) if clock is spread for all cases: -if SS enabled on DP Ref clock and HW de-spreading enabled with SW calculations for DS_INCR/DS_MODULO (this is planned to be default case) -if SS enabled on DP Ref clock and HW de-spreading enabled with HW calculations (not planned to be used, but average clock should still be valid) -if SS enabled on DP Ref clock and HW de-spreading disabled (should not be case with CIK) then SW should program all rates generated according to average value (case as with previous ASICs) */ if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( dal_fixed32_32_from_fraction( clk_dce->dprefclk_ss_percentage, clk_dce->dprefclk_ss_divider), 200); struct fixed32_32 adj_dp_ref_clk_khz; ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, ss_percentage); adj_dp_ref_clk_khz = dal_fixed32_32_mul_int( ss_percentage, dp_ref_clk_khz); dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); } return dp_ref_clk_khz; }
/* TODO: This is DCN DPREFCLK: it could be program by DENTIST by VBIOS * or CLK0_CLK11 by SMU. For DCE120, it is wlays 600Mhz. Will re-visit * clock implementation */ static int dce_clocks_get_dp_ref_freq_wrkaround(struct display_clock *clk) { struct dce_disp_clk *clk_dce = TO_DCE_CLOCKS(clk); int dp_ref_clk_khz = 600000; if (clk_dce->ss_on_dprefclk && clk_dce->dprefclk_ss_divider != 0) { struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( dal_fixed32_32_from_fraction( clk_dce->dprefclk_ss_percentage, clk_dce->dprefclk_ss_divider), 200); struct fixed32_32 adj_dp_ref_clk_khz; ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, ss_percentage); adj_dp_ref_clk_khz = dal_fixed32_32_mul_int( ss_percentage, dp_ref_clk_khz); dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); } return dp_ref_clk_khz; }
static uint32_t get_dp_ref_clk_frequency(struct display_clock *dc) { uint32_t dispclk_cntl_value; uint32_t dp_ref_clk_cntl_value; uint32_t dp_ref_clk_cntl_src_sel_value; uint32_t dp_ref_clk_khz = 600000; uint32_t target_div = INVALID_DIVIDER; struct display_clock_dce110 *disp_clk = FROM_DISPLAY_CLOCK(dc); /* ASSERT DP Reference Clock source is from DFS*/ dp_ref_clk_cntl_value = dm_read_reg(dc->ctx, mmDPREFCLK_CNTL); dp_ref_clk_cntl_src_sel_value = get_reg_field_value( dp_ref_clk_cntl_value, DPREFCLK_CNTL, DPREFCLK_SRC_SEL); ASSERT(dp_ref_clk_cntl_src_sel_value == 0); /* Read the mmDENTIST_DISPCLK_CNTL to get the currently * programmed DID DENTIST_DPREFCLK_WDIVIDER*/ dispclk_cntl_value = dm_read_reg(dc->ctx, mmDENTIST_DISPCLK_CNTL); /* Convert DENTIST_DPREFCLK_WDIVIDERto actual divider*/ target_div = dal_divider_range_get_divider( divider_ranges, DIVIDER_RANGE_MAX, get_reg_field_value(dispclk_cntl_value, DENTIST_DISPCLK_CNTL, DENTIST_DPREFCLK_WDIVIDER)); if (target_div != INVALID_DIVIDER) { /* Calculate the current DFS clock, in kHz.*/ dp_ref_clk_khz = (DIVIDER_RANGE_SCALE_FACTOR * disp_clk->dentist_vco_freq_khz) / target_div; } /* SW will adjust DP REF Clock average value for all purposes * (DP DTO / DP Audio DTO and DP GTC) if clock is spread for all cases: -if SS enabled on DP Ref clock and HW de-spreading enabled with SW calculations for DS_INCR/DS_MODULO (this is planned to be default case) -if SS enabled on DP Ref clock and HW de-spreading enabled with HW calculations (not planned to be used, but average clock should still be valid) -if SS enabled on DP Ref clock and HW de-spreading disabled (should not be case with CIK) then SW should program all rates generated according to average value (case as with previous ASICs) */ if ((disp_clk->ss_on_gpu_pll) && (disp_clk->gpu_pll_ss_divider != 0)) { struct fixed32_32 ss_percentage = dal_fixed32_32_div_int( dal_fixed32_32_from_fraction( disp_clk->gpu_pll_ss_percentage, disp_clk->gpu_pll_ss_divider), 200); struct fixed32_32 adj_dp_ref_clk_khz; ss_percentage = dal_fixed32_32_sub(dal_fixed32_32_one, ss_percentage); adj_dp_ref_clk_khz = dal_fixed32_32_mul_int( ss_percentage, dp_ref_clk_khz); dp_ref_clk_khz = dal_fixed32_32_floor(adj_dp_ref_clk_khz); } return dp_ref_clk_khz; }