2 * Copyright 2012-15 Advanced Micro Devices, Inc.
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 * OTHER DEALINGS IN THE SOFTWARE.
26 #include "dm_services.h"
30 #include "core_types.h"
32 #include "include/grph_object_id.h"
33 #include "include/logger_interface.h"
35 #include "dce_clock_source.h"
38 #include "reg_helper.h"
46 #define DC_LOGGER_INIT()
49 #define FN(reg_name, field_name) \
50 clk_src->cs_shift->field_name, clk_src->cs_mask->field_name
52 #define FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM 6
53 #define CALC_PLL_CLK_SRC_ERR_TOLERANCE 1
54 #define MAX_PLL_CALC_ERROR 0xFFFFFFFF
56 #define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
58 static const struct spread_spectrum_data
*get_ss_data_entry(
59 struct dce110_clk_src
*clk_src
,
60 enum signal_type signal
,
66 struct spread_spectrum_data
*ss_parm
= NULL
;
67 struct spread_spectrum_data
*ret
= NULL
;
70 case SIGNAL_TYPE_DVI_SINGLE_LINK
:
71 case SIGNAL_TYPE_DVI_DUAL_LINK
:
72 ss_parm
= clk_src
->dvi_ss_params
;
73 entrys_num
= clk_src
->dvi_ss_params_cnt
;
76 case SIGNAL_TYPE_HDMI_TYPE_A
:
77 ss_parm
= clk_src
->hdmi_ss_params
;
78 entrys_num
= clk_src
->hdmi_ss_params_cnt
;
81 case SIGNAL_TYPE_LVDS
:
82 ss_parm
= clk_src
->lvds_ss_params
;
83 entrys_num
= clk_src
->lvds_ss_params_cnt
;
86 case SIGNAL_TYPE_DISPLAY_PORT
:
87 case SIGNAL_TYPE_DISPLAY_PORT_MST
:
89 case SIGNAL_TYPE_VIRTUAL
:
90 ss_parm
= clk_src
->dp_ss_params
;
91 entrys_num
= clk_src
->dp_ss_params_cnt
;
103 for (i
= 0; i
< entrys_num
; ++i
, ++ss_parm
) {
104 if (ss_parm
->freq_range_khz
>= pix_clk_khz
) {
114 * calculate_fb_and_fractional_fb_divider - Calculates feedback and fractional
115 * feedback dividers values
117 * @calc_pll_cs: Pointer to clock source information
118 * @target_pix_clk_100hz: Desired frequency in 100 Hz
119 * @ref_divider: Reference divider (already known)
120 * @post_divider: Post Divider (already known)
121 * @feedback_divider_param: Pointer where to store
122 * calculated feedback divider value
123 * @fract_feedback_divider_param: Pointer where to store
124 * calculated fract feedback divider value
127 * It fills the locations pointed by feedback_divider_param
128 * and fract_feedback_divider_param
129 * It returns - true if feedback divider not 0
130 * - false should never happen)
132 static bool calculate_fb_and_fractional_fb_divider(
133 struct calc_pll_clock_source
*calc_pll_cs
,
134 uint32_t target_pix_clk_100hz
,
135 uint32_t ref_divider
,
136 uint32_t post_divider
,
137 uint32_t *feedback_divider_param
,
138 uint32_t *fract_feedback_divider_param
)
140 uint64_t feedback_divider
;
143 (uint64_t)target_pix_clk_100hz
* ref_divider
* post_divider
;
144 feedback_divider
*= 10;
145 /* additional factor, since we divide by 10 afterwards */
146 feedback_divider
*= (uint64_t)(calc_pll_cs
->fract_fb_divider_factor
);
147 feedback_divider
= div_u64(feedback_divider
, calc_pll_cs
->ref_freq_khz
* 10ull);
149 /*Round to the number of precision
150 * The following code replace the old code (ullfeedbackDivider + 5)/10
151 * for example if the difference between the number
152 * of fractional feedback decimal point and the fractional FB Divider precision
153 * is 2 then the equation becomes (ullfeedbackDivider + 5*100) / (10*100))*/
155 feedback_divider
+= 5ULL *
156 calc_pll_cs
->fract_fb_divider_precision_factor
;
158 div_u64(feedback_divider
,
159 calc_pll_cs
->fract_fb_divider_precision_factor
* 10);
160 feedback_divider
*= (uint64_t)
161 (calc_pll_cs
->fract_fb_divider_precision_factor
);
163 *feedback_divider_param
=
166 calc_pll_cs
->fract_fb_divider_factor
,
167 fract_feedback_divider_param
);
169 if (*feedback_divider_param
!= 0)
175 * calc_fb_divider_checking_tolerance - Calculates Feedback and
176 * Fractional Feedback divider values
177 * for passed Reference and Post divider,
178 * checking for tolerance.
179 * @calc_pll_cs: Pointer to clock source information
180 * @pll_settings: Pointer to PLL settings
181 * @ref_divider: Reference divider (already known)
182 * @post_divider: Post Divider (already known)
183 * @tolerance: Tolerance for Calculated Pixel Clock to be within
186 * It fills the PLLSettings structure with PLL Dividers values
187 * if calculated values are within required tolerance
188 * It returns - true if error is within tolerance
189 * - false if error is not within tolerance
191 static bool calc_fb_divider_checking_tolerance(
192 struct calc_pll_clock_source
*calc_pll_cs
,
193 struct pll_settings
*pll_settings
,
194 uint32_t ref_divider
,
195 uint32_t post_divider
,
198 uint32_t feedback_divider
;
199 uint32_t fract_feedback_divider
;
200 uint32_t actual_calculated_clock_100hz
;
202 uint64_t actual_calc_clk_100hz
;
204 calculate_fb_and_fractional_fb_divider(
206 pll_settings
->adjusted_pix_clk_100hz
,
210 &fract_feedback_divider
);
212 /*Actual calculated value*/
213 actual_calc_clk_100hz
= (uint64_t)feedback_divider
*
214 calc_pll_cs
->fract_fb_divider_factor
+
215 fract_feedback_divider
;
216 actual_calc_clk_100hz
*= calc_pll_cs
->ref_freq_khz
* 10;
217 actual_calc_clk_100hz
=
218 div_u64(actual_calc_clk_100hz
,
219 ref_divider
* post_divider
*
220 calc_pll_cs
->fract_fb_divider_factor
);
222 actual_calculated_clock_100hz
= (uint32_t)(actual_calc_clk_100hz
);
224 abs_err
= (actual_calculated_clock_100hz
>
225 pll_settings
->adjusted_pix_clk_100hz
)
226 ? actual_calculated_clock_100hz
-
227 pll_settings
->adjusted_pix_clk_100hz
228 : pll_settings
->adjusted_pix_clk_100hz
-
229 actual_calculated_clock_100hz
;
231 if (abs_err
<= tolerance
) {
232 /*found good values*/
233 pll_settings
->reference_freq
= calc_pll_cs
->ref_freq_khz
;
234 pll_settings
->reference_divider
= ref_divider
;
235 pll_settings
->feedback_divider
= feedback_divider
;
236 pll_settings
->fract_feedback_divider
= fract_feedback_divider
;
237 pll_settings
->pix_clk_post_divider
= post_divider
;
238 pll_settings
->calculated_pix_clk_100hz
=
239 actual_calculated_clock_100hz
;
240 pll_settings
->vco_freq
=
241 div_u64((u64
)actual_calculated_clock_100hz
* post_divider
, 10);
247 static bool calc_pll_dividers_in_range(
248 struct calc_pll_clock_source
*calc_pll_cs
,
249 struct pll_settings
*pll_settings
,
250 uint32_t min_ref_divider
,
251 uint32_t max_ref_divider
,
252 uint32_t min_post_divider
,
253 uint32_t max_post_divider
,
254 uint32_t err_tolerance
)
256 uint32_t ref_divider
;
257 uint32_t post_divider
;
260 /* This is err_tolerance / 10000 = 0.0025 - acceptable error of 0.25%
261 * This is errorTolerance / 10000 = 0.0001 - acceptable error of 0.01%*/
262 tolerance
= (pll_settings
->adjusted_pix_clk_100hz
* err_tolerance
) /
264 if (tolerance
< CALC_PLL_CLK_SRC_ERR_TOLERANCE
)
265 tolerance
= CALC_PLL_CLK_SRC_ERR_TOLERANCE
;
268 post_divider
= max_post_divider
;
269 post_divider
>= min_post_divider
;
272 ref_divider
= min_ref_divider
;
273 ref_divider
<= max_ref_divider
;
275 if (calc_fb_divider_checking_tolerance(
289 static uint32_t calculate_pixel_clock_pll_dividers(
290 struct calc_pll_clock_source
*calc_pll_cs
,
291 struct pll_settings
*pll_settings
)
293 uint32_t err_tolerance
;
294 uint32_t min_post_divider
;
295 uint32_t max_post_divider
;
296 uint32_t min_ref_divider
;
297 uint32_t max_ref_divider
;
299 if (pll_settings
->adjusted_pix_clk_100hz
== 0) {
301 "%s Bad requested pixel clock", __func__
);
302 return MAX_PLL_CALC_ERROR
;
305 /* 1) Find Post divider ranges */
306 if (pll_settings
->pix_clk_post_divider
) {
307 min_post_divider
= pll_settings
->pix_clk_post_divider
;
308 max_post_divider
= pll_settings
->pix_clk_post_divider
;
310 min_post_divider
= calc_pll_cs
->min_pix_clock_pll_post_divider
;
311 if (min_post_divider
* pll_settings
->adjusted_pix_clk_100hz
<
312 calc_pll_cs
->min_vco_khz
* 10) {
313 min_post_divider
= calc_pll_cs
->min_vco_khz
* 10 /
314 pll_settings
->adjusted_pix_clk_100hz
;
315 if ((min_post_divider
*
316 pll_settings
->adjusted_pix_clk_100hz
) <
317 calc_pll_cs
->min_vco_khz
* 10)
321 max_post_divider
= calc_pll_cs
->max_pix_clock_pll_post_divider
;
322 if (max_post_divider
* pll_settings
->adjusted_pix_clk_100hz
323 > calc_pll_cs
->max_vco_khz
* 10)
324 max_post_divider
= calc_pll_cs
->max_vco_khz
* 10 /
325 pll_settings
->adjusted_pix_clk_100hz
;
328 /* 2) Find Reference divider ranges
329 * When SS is enabled, or for Display Port even without SS,
330 * pll_settings->referenceDivider is not zero.
331 * So calculate PPLL FB and fractional FB divider
332 * using the passed reference divider*/
334 if (pll_settings
->reference_divider
) {
335 min_ref_divider
= pll_settings
->reference_divider
;
336 max_ref_divider
= pll_settings
->reference_divider
;
338 min_ref_divider
= ((calc_pll_cs
->ref_freq_khz
339 / calc_pll_cs
->max_pll_input_freq_khz
)
340 > calc_pll_cs
->min_pll_ref_divider
)
341 ? calc_pll_cs
->ref_freq_khz
342 / calc_pll_cs
->max_pll_input_freq_khz
343 : calc_pll_cs
->min_pll_ref_divider
;
345 max_ref_divider
= ((calc_pll_cs
->ref_freq_khz
346 / calc_pll_cs
->min_pll_input_freq_khz
)
347 < calc_pll_cs
->max_pll_ref_divider
)
348 ? calc_pll_cs
->ref_freq_khz
/
349 calc_pll_cs
->min_pll_input_freq_khz
350 : calc_pll_cs
->max_pll_ref_divider
;
353 /* If some parameters are invalid we could have scenario when "min">"max"
354 * which produced endless loop later.
355 * We should investigate why we get the wrong parameters.
356 * But to follow the similar logic when "adjustedPixelClock" is set to be 0
357 * it is better to return here than cause system hang/watchdog timeout later.
358 * ## SVS Wed 15 Jul 2009 */
360 if (min_post_divider
> max_post_divider
) {
362 "%s Post divider range is invalid", __func__
);
363 return MAX_PLL_CALC_ERROR
;
366 if (min_ref_divider
> max_ref_divider
) {
368 "%s Reference divider range is invalid", __func__
);
369 return MAX_PLL_CALC_ERROR
;
372 /* 3) Try to find PLL dividers given ranges
373 * starting with minimal error tolerance.
374 * Increase error tolerance until PLL dividers found*/
375 err_tolerance
= MAX_PLL_CALC_ERROR
;
377 while (!calc_pll_dividers_in_range(
385 err_tolerance
+= (err_tolerance
> 10)
386 ? (err_tolerance
/ 10)
389 return err_tolerance
;
392 static bool pll_adjust_pix_clk(
393 struct dce110_clk_src
*clk_src
,
394 struct pixel_clk_params
*pix_clk_params
,
395 struct pll_settings
*pll_settings
)
397 uint32_t actual_pix_clk_100hz
= 0;
398 uint32_t requested_clk_100hz
= 0;
399 struct bp_adjust_pixel_clock_parameters bp_adjust_pixel_clock_params
= {
401 enum bp_result bp_result
;
402 switch (pix_clk_params
->signal_type
) {
403 case SIGNAL_TYPE_HDMI_TYPE_A
: {
404 requested_clk_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
405 if (pix_clk_params
->pixel_encoding
!= PIXEL_ENCODING_YCBCR422
) {
406 switch (pix_clk_params
->color_depth
) {
407 case COLOR_DEPTH_101010
:
408 requested_clk_100hz
= (requested_clk_100hz
* 5) >> 2;
410 case COLOR_DEPTH_121212
:
411 requested_clk_100hz
= (requested_clk_100hz
* 6) >> 2;
413 case COLOR_DEPTH_161616
:
414 requested_clk_100hz
= requested_clk_100hz
* 2;
420 actual_pix_clk_100hz
= requested_clk_100hz
;
424 case SIGNAL_TYPE_DISPLAY_PORT
:
425 case SIGNAL_TYPE_DISPLAY_PORT_MST
:
426 case SIGNAL_TYPE_EDP
:
427 requested_clk_100hz
= pix_clk_params
->requested_sym_clk
* 10;
428 actual_pix_clk_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
432 requested_clk_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
433 actual_pix_clk_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
437 bp_adjust_pixel_clock_params
.pixel_clock
= requested_clk_100hz
/ 10;
438 bp_adjust_pixel_clock_params
.
439 encoder_object_id
= pix_clk_params
->encoder_object_id
;
440 bp_adjust_pixel_clock_params
.signal_type
= pix_clk_params
->signal_type
;
441 bp_adjust_pixel_clock_params
.
442 ss_enable
= pix_clk_params
->flags
.ENABLE_SS
;
443 bp_result
= clk_src
->bios
->funcs
->adjust_pixel_clock(
444 clk_src
->bios
, &bp_adjust_pixel_clock_params
);
445 if (bp_result
== BP_RESULT_OK
) {
446 pll_settings
->actual_pix_clk_100hz
= actual_pix_clk_100hz
;
447 pll_settings
->adjusted_pix_clk_100hz
=
448 bp_adjust_pixel_clock_params
.adjusted_pixel_clock
* 10;
449 pll_settings
->reference_divider
=
450 bp_adjust_pixel_clock_params
.reference_divider
;
451 pll_settings
->pix_clk_post_divider
=
452 bp_adjust_pixel_clock_params
.pixel_clock_post_divider
;
461 * Calculate PLL Dividers for given Clock Value.
462 * First will call VBIOS Adjust Exec table to check if requested Pixel clock
463 * will be Adjusted based on usage.
464 * Then it will calculate PLL Dividers for this Adjusted clock using preferred
465 * method (Maximum VCO frequency).
468 * Calculation error in units of 0.01%
471 static uint32_t dce110_get_pix_clk_dividers_helper (
472 struct dce110_clk_src
*clk_src
,
473 struct pll_settings
*pll_settings
,
474 struct pixel_clk_params
*pix_clk_params
)
477 uint32_t pll_calc_error
= MAX_PLL_CALC_ERROR
;
479 /* Check if reference clock is external (not pcie/xtalin)
481 * 00 - PCIE_REFCLK, 01 - XTALIN, 02 - GENERICA, 03 - GENERICB
482 * 04 - HSYNCA, 05 - GENLK_CLK, 06 - PCIE_REFCLK, 07 - DVOCLK0 */
483 REG_GET(PLL_CNTL
, PLL_REF_DIV_SRC
, &field
);
484 pll_settings
->use_external_clk
= (field
> 1);
486 /* VBIOS by default enables DP SS (spread on IDCLK) for DCE 8.0 always
487 * (we do not care any more from SI for some older DP Sink which
488 * does not report SS support, no known issues) */
489 if ((pix_clk_params
->flags
.ENABLE_SS
) ||
490 (dc_is_dp_signal(pix_clk_params
->signal_type
))) {
492 const struct spread_spectrum_data
*ss_data
= get_ss_data_entry(
494 pix_clk_params
->signal_type
,
495 pll_settings
->adjusted_pix_clk_100hz
/ 10);
498 pll_settings
->ss_percentage
= ss_data
->percentage
;
501 /* Check VBIOS AdjustPixelClock Exec table */
502 if (!pll_adjust_pix_clk(clk_src
, pix_clk_params
, pll_settings
)) {
503 /* Should never happen, ASSERT and fill up values to be able
506 "%s: Failed to adjust pixel clock!!", __func__
);
507 pll_settings
->actual_pix_clk_100hz
=
508 pix_clk_params
->requested_pix_clk_100hz
;
509 pll_settings
->adjusted_pix_clk_100hz
=
510 pix_clk_params
->requested_pix_clk_100hz
;
512 if (dc_is_dp_signal(pix_clk_params
->signal_type
))
513 pll_settings
->adjusted_pix_clk_100hz
= 1000000;
516 /* Calculate Dividers */
517 if (pix_clk_params
->signal_type
== SIGNAL_TYPE_HDMI_TYPE_A
)
518 /*Calculate Dividers by HDMI object, no SS case or SS case */
520 calculate_pixel_clock_pll_dividers(
521 &clk_src
->calc_pll_hdmi
,
524 /*Calculate Dividers by default object, no SS case or SS case */
526 calculate_pixel_clock_pll_dividers(
530 return pll_calc_error
;
533 static void dce112_get_pix_clk_dividers_helper (
534 struct dce110_clk_src
*clk_src
,
535 struct pll_settings
*pll_settings
,
536 struct pixel_clk_params
*pix_clk_params
)
538 uint32_t actual_pixel_clock_100hz
;
540 actual_pixel_clock_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
541 /* Calculate Dividers */
542 if (pix_clk_params
->signal_type
== SIGNAL_TYPE_HDMI_TYPE_A
) {
543 switch (pix_clk_params
->color_depth
) {
544 case COLOR_DEPTH_101010
:
545 actual_pixel_clock_100hz
= (actual_pixel_clock_100hz
* 5) >> 2;
546 actual_pixel_clock_100hz
-= actual_pixel_clock_100hz
% 10;
548 case COLOR_DEPTH_121212
:
549 actual_pixel_clock_100hz
= (actual_pixel_clock_100hz
* 6) >> 2;
550 actual_pixel_clock_100hz
-= actual_pixel_clock_100hz
% 10;
552 case COLOR_DEPTH_161616
:
553 actual_pixel_clock_100hz
= actual_pixel_clock_100hz
* 2;
559 pll_settings
->actual_pix_clk_100hz
= actual_pixel_clock_100hz
;
560 pll_settings
->adjusted_pix_clk_100hz
= actual_pixel_clock_100hz
;
561 pll_settings
->calculated_pix_clk_100hz
= pix_clk_params
->requested_pix_clk_100hz
;
564 static uint32_t dce110_get_pix_clk_dividers(
565 struct clock_source
*cs
,
566 struct pixel_clk_params
*pix_clk_params
,
567 struct pll_settings
*pll_settings
)
569 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(cs
);
570 uint32_t pll_calc_error
= MAX_PLL_CALC_ERROR
;
573 if (pix_clk_params
== NULL
|| pll_settings
== NULL
574 || pix_clk_params
->requested_pix_clk_100hz
== 0) {
576 "%s: Invalid parameters!!\n", __func__
);
577 return pll_calc_error
;
580 memset(pll_settings
, 0, sizeof(*pll_settings
));
582 if (cs
->id
== CLOCK_SOURCE_ID_DP_DTO
||
583 cs
->id
== CLOCK_SOURCE_ID_EXTERNAL
) {
584 pll_settings
->adjusted_pix_clk_100hz
= clk_src
->ext_clk_khz
* 10;
585 pll_settings
->calculated_pix_clk_100hz
= clk_src
->ext_clk_khz
* 10;
586 pll_settings
->actual_pix_clk_100hz
=
587 pix_clk_params
->requested_pix_clk_100hz
;
591 pll_calc_error
= dce110_get_pix_clk_dividers_helper(clk_src
,
592 pll_settings
, pix_clk_params
);
594 return pll_calc_error
;
597 static uint32_t dce112_get_pix_clk_dividers(
598 struct clock_source
*cs
,
599 struct pixel_clk_params
*pix_clk_params
,
600 struct pll_settings
*pll_settings
)
602 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(cs
);
605 if (pix_clk_params
== NULL
|| pll_settings
== NULL
606 || pix_clk_params
->requested_pix_clk_100hz
== 0) {
608 "%s: Invalid parameters!!\n", __func__
);
612 memset(pll_settings
, 0, sizeof(*pll_settings
));
614 if (cs
->id
== CLOCK_SOURCE_ID_DP_DTO
||
615 cs
->id
== CLOCK_SOURCE_ID_EXTERNAL
) {
616 pll_settings
->adjusted_pix_clk_100hz
= clk_src
->ext_clk_khz
* 10;
617 pll_settings
->calculated_pix_clk_100hz
= clk_src
->ext_clk_khz
* 10;
618 pll_settings
->actual_pix_clk_100hz
=
619 pix_clk_params
->requested_pix_clk_100hz
;
623 dce112_get_pix_clk_dividers_helper(clk_src
,
624 pll_settings
, pix_clk_params
);
629 static bool disable_spread_spectrum(struct dce110_clk_src
*clk_src
)
631 enum bp_result result
;
632 struct bp_spread_spectrum_parameters bp_ss_params
= {0};
634 bp_ss_params
.pll_id
= clk_src
->base
.id
;
636 /*Call ASICControl to process ATOMBIOS Exec table*/
637 result
= clk_src
->bios
->funcs
->enable_spread_spectrum_on_ppll(
642 return result
== BP_RESULT_OK
;
645 static bool calculate_ss(
646 const struct pll_settings
*pll_settings
,
647 const struct spread_spectrum_data
*ss_data
,
648 struct delta_sigma_data
*ds_data
)
650 struct fixed31_32 fb_div
;
651 struct fixed31_32 ss_amount
;
652 struct fixed31_32 ss_nslip_amount
;
653 struct fixed31_32 ss_ds_frac_amount
;
654 struct fixed31_32 ss_step_size
;
655 struct fixed31_32 modulation_time
;
661 if (ss_data
->percentage
== 0)
663 if (pll_settings
== NULL
)
666 memset(ds_data
, 0, sizeof(struct delta_sigma_data
));
668 /* compute SS_AMOUNT_FBDIV & SS_AMOUNT_NFRAC_SLIP & SS_AMOUNT_DSFRAC*/
669 /* 6 decimal point support in fractional feedback divider */
670 fb_div
= dc_fixpt_from_fraction(
671 pll_settings
->fract_feedback_divider
, 1000000);
672 fb_div
= dc_fixpt_add_int(fb_div
, pll_settings
->feedback_divider
);
674 ds_data
->ds_frac_amount
= 0;
675 /*spreadSpectrumPercentage is in the unit of .01%,
676 * so have to divided by 100 * 100*/
677 ss_amount
= dc_fixpt_mul(
678 fb_div
, dc_fixpt_from_fraction(ss_data
->percentage
,
679 100 * ss_data
->percentage_divider
));
680 ds_data
->feedback_amount
= dc_fixpt_floor(ss_amount
);
682 ss_nslip_amount
= dc_fixpt_sub(ss_amount
,
683 dc_fixpt_from_int(ds_data
->feedback_amount
));
684 ss_nslip_amount
= dc_fixpt_mul_int(ss_nslip_amount
, 10);
685 ds_data
->nfrac_amount
= dc_fixpt_floor(ss_nslip_amount
);
687 ss_ds_frac_amount
= dc_fixpt_sub(ss_nslip_amount
,
688 dc_fixpt_from_int(ds_data
->nfrac_amount
));
689 ss_ds_frac_amount
= dc_fixpt_mul_int(ss_ds_frac_amount
, 65536);
690 ds_data
->ds_frac_amount
= dc_fixpt_floor(ss_ds_frac_amount
);
692 /* compute SS_STEP_SIZE_DSFRAC */
693 modulation_time
= dc_fixpt_from_fraction(
694 pll_settings
->reference_freq
* 1000,
695 pll_settings
->reference_divider
* ss_data
->modulation_freq_hz
);
697 if (ss_data
->flags
.CENTER_SPREAD
)
698 modulation_time
= dc_fixpt_div_int(modulation_time
, 4);
700 modulation_time
= dc_fixpt_div_int(modulation_time
, 2);
702 ss_step_size
= dc_fixpt_div(ss_amount
, modulation_time
);
703 /* SS_STEP_SIZE_DSFRAC_DEC = Int(SS_STEP_SIZE * 2 ^ 16 * 10)*/
704 ss_step_size
= dc_fixpt_mul_int(ss_step_size
, 65536 * 10);
705 ds_data
->ds_frac_size
= dc_fixpt_floor(ss_step_size
);
710 static bool enable_spread_spectrum(
711 struct dce110_clk_src
*clk_src
,
712 enum signal_type signal
, struct pll_settings
*pll_settings
)
714 struct bp_spread_spectrum_parameters bp_params
= {0};
715 struct delta_sigma_data d_s_data
;
716 const struct spread_spectrum_data
*ss_data
= NULL
;
718 ss_data
= get_ss_data_entry(
721 pll_settings
->calculated_pix_clk_100hz
/ 10);
723 /* Pixel clock PLL has been programmed to generate desired pixel clock,
724 * now enable SS on pixel clock */
725 /* TODO is it OK to return true not doing anything ??*/
726 if (ss_data
!= NULL
&& pll_settings
->ss_percentage
!= 0) {
727 if (calculate_ss(pll_settings
, ss_data
, &d_s_data
)) {
728 bp_params
.ds
.feedback_amount
=
729 d_s_data
.feedback_amount
;
730 bp_params
.ds
.nfrac_amount
=
731 d_s_data
.nfrac_amount
;
732 bp_params
.ds
.ds_frac_size
= d_s_data
.ds_frac_size
;
733 bp_params
.ds_frac_amount
=
734 d_s_data
.ds_frac_amount
;
735 bp_params
.flags
.DS_TYPE
= 1;
736 bp_params
.pll_id
= clk_src
->base
.id
;
737 bp_params
.percentage
= ss_data
->percentage
;
738 if (ss_data
->flags
.CENTER_SPREAD
)
739 bp_params
.flags
.CENTER_SPREAD
= 1;
740 if (ss_data
->flags
.EXTERNAL_SS
)
741 bp_params
.flags
.EXTERNAL_SS
= 1;
744 clk_src
->bios
->funcs
->
745 enable_spread_spectrum_on_ppll(
756 static void dce110_program_pixel_clk_resync(
757 struct dce110_clk_src
*clk_src
,
758 enum signal_type signal_type
,
759 enum dc_color_depth colordepth
)
761 REG_UPDATE(RESYNC_CNTL
,
762 DCCG_DEEP_COLOR_CNTL1
, 0);
764 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1)
765 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)
766 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2)
767 48 bit mode: TMDS clock = 2 x pixel clock (2:1)
769 if (signal_type
!= SIGNAL_TYPE_HDMI_TYPE_A
)
772 switch (colordepth
) {
773 case COLOR_DEPTH_888
:
774 REG_UPDATE(RESYNC_CNTL
,
775 DCCG_DEEP_COLOR_CNTL1
, 0);
777 case COLOR_DEPTH_101010
:
778 REG_UPDATE(RESYNC_CNTL
,
779 DCCG_DEEP_COLOR_CNTL1
, 1);
781 case COLOR_DEPTH_121212
:
782 REG_UPDATE(RESYNC_CNTL
,
783 DCCG_DEEP_COLOR_CNTL1
, 2);
785 case COLOR_DEPTH_161616
:
786 REG_UPDATE(RESYNC_CNTL
,
787 DCCG_DEEP_COLOR_CNTL1
, 3);
794 static void dce112_program_pixel_clk_resync(
795 struct dce110_clk_src
*clk_src
,
796 enum signal_type signal_type
,
797 enum dc_color_depth colordepth
,
798 bool enable_ycbcr420
)
800 uint32_t deep_color_cntl
= 0;
801 uint32_t double_rate_enable
= 0;
804 24 bit mode: TMDS clock = 1.0 x pixel clock (1:1)
805 30 bit mode: TMDS clock = 1.25 x pixel clock (5:4)
806 36 bit mode: TMDS clock = 1.5 x pixel clock (3:2)
807 48 bit mode: TMDS clock = 2 x pixel clock (2:1)
809 if (signal_type
== SIGNAL_TYPE_HDMI_TYPE_A
) {
810 double_rate_enable
= enable_ycbcr420
? 1 : 0;
812 switch (colordepth
) {
813 case COLOR_DEPTH_888
:
816 case COLOR_DEPTH_101010
:
819 case COLOR_DEPTH_121212
:
822 case COLOR_DEPTH_161616
:
830 if (clk_src
->cs_mask
->PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE
)
831 REG_UPDATE_2(PIXCLK_RESYNC_CNTL
,
832 PHYPLLA_DCCG_DEEP_COLOR_CNTL
, deep_color_cntl
,
833 PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE
, double_rate_enable
);
835 REG_UPDATE(PIXCLK_RESYNC_CNTL
,
836 PHYPLLA_DCCG_DEEP_COLOR_CNTL
, deep_color_cntl
);
840 static bool dce110_program_pix_clk(
841 struct clock_source
*clock_source
,
842 struct pixel_clk_params
*pix_clk_params
,
843 enum dp_link_encoding encoding
,
844 struct pll_settings
*pll_settings
)
846 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
847 struct bp_pixel_clock_parameters bp_pc_params
= {0};
850 * ATOMBIOS will enable by default SS on PLL for DP,
851 * do not disable it here
853 if (clock_source
->id
!= CLOCK_SOURCE_ID_EXTERNAL
&&
854 !dc_is_dp_signal(pix_clk_params
->signal_type
) &&
855 clock_source
->ctx
->dce_version
<= DCE_VERSION_11_0
)
856 disable_spread_spectrum(clk_src
);
858 /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
859 bp_pc_params
.controller_id
= pix_clk_params
->controller_id
;
860 bp_pc_params
.pll_id
= clock_source
->id
;
861 bp_pc_params
.target_pixel_clock_100hz
= pll_settings
->actual_pix_clk_100hz
;
862 bp_pc_params
.encoder_object_id
= pix_clk_params
->encoder_object_id
;
863 bp_pc_params
.signal_type
= pix_clk_params
->signal_type
;
865 bp_pc_params
.reference_divider
= pll_settings
->reference_divider
;
866 bp_pc_params
.feedback_divider
= pll_settings
->feedback_divider
;
867 bp_pc_params
.fractional_feedback_divider
=
868 pll_settings
->fract_feedback_divider
;
869 bp_pc_params
.pixel_clock_post_divider
=
870 pll_settings
->pix_clk_post_divider
;
871 bp_pc_params
.flags
.SET_EXTERNAL_REF_DIV_SRC
=
872 pll_settings
->use_external_clk
;
874 switch (pix_clk_params
->color_depth
) {
875 case COLOR_DEPTH_101010
:
876 bp_pc_params
.color_depth
= TRANSMITTER_COLOR_DEPTH_30
;
878 case COLOR_DEPTH_121212
:
879 bp_pc_params
.color_depth
= TRANSMITTER_COLOR_DEPTH_36
;
881 case COLOR_DEPTH_161616
:
882 bp_pc_params
.color_depth
= TRANSMITTER_COLOR_DEPTH_48
;
888 if (clk_src
->bios
->funcs
->set_pixel_clock(
889 clk_src
->bios
, &bp_pc_params
) != BP_RESULT_OK
)
892 * ATOMBIOS will enable by default SS for DP on PLL ( DP ID clock),
893 * based on HW display PLL team, SS control settings should be programmed
894 * during PLL Reset, but they do not have effect
895 * until SS_EN is asserted.*/
896 if (clock_source
->id
!= CLOCK_SOURCE_ID_EXTERNAL
897 && !dc_is_dp_signal(pix_clk_params
->signal_type
)) {
899 if (pix_clk_params
->flags
.ENABLE_SS
)
900 if (!enable_spread_spectrum(clk_src
,
901 pix_clk_params
->signal_type
,
905 /* Resync deep color DTO */
906 dce110_program_pixel_clk_resync(clk_src
,
907 pix_clk_params
->signal_type
,
908 pix_clk_params
->color_depth
);
914 static bool dce112_program_pix_clk(
915 struct clock_source
*clock_source
,
916 struct pixel_clk_params
*pix_clk_params
,
917 enum dp_link_encoding encoding
,
918 struct pll_settings
*pll_settings
)
920 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
921 struct bp_pixel_clock_parameters bp_pc_params
= {0};
923 if (IS_FPGA_MAXIMUS_DC(clock_source
->ctx
->dce_environment
)) {
924 unsigned int inst
= pix_clk_params
->controller_id
- CONTROLLER_ID_D0
;
925 unsigned dp_dto_ref_100hz
= 7000000;
926 unsigned clock_100hz
= pll_settings
->actual_pix_clk_100hz
;
928 /* Set DTO values: phase = target clock, modulo = reference clock */
929 REG_WRITE(PHASE
[inst
], clock_100hz
);
930 REG_WRITE(MODULO
[inst
], dp_dto_ref_100hz
);
933 if (clk_src
->cs_mask
->PIPE0_DTO_SRC_SEL
)
934 REG_UPDATE_2(PIXEL_RATE_CNTL
[inst
],
936 PIPE0_DTO_SRC_SEL
, 1);
938 REG_UPDATE(PIXEL_RATE_CNTL
[inst
],
943 * ATOMBIOS will enable by default SS on PLL for DP,
944 * do not disable it here
946 if (clock_source
->id
!= CLOCK_SOURCE_ID_EXTERNAL
&&
947 !dc_is_dp_signal(pix_clk_params
->signal_type
) &&
948 clock_source
->ctx
->dce_version
<= DCE_VERSION_11_0
)
949 disable_spread_spectrum(clk_src
);
951 /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
952 bp_pc_params
.controller_id
= pix_clk_params
->controller_id
;
953 bp_pc_params
.pll_id
= clock_source
->id
;
954 bp_pc_params
.target_pixel_clock_100hz
= pll_settings
->actual_pix_clk_100hz
;
955 bp_pc_params
.encoder_object_id
= pix_clk_params
->encoder_object_id
;
956 bp_pc_params
.signal_type
= pix_clk_params
->signal_type
;
958 if (clock_source
->id
!= CLOCK_SOURCE_ID_DP_DTO
) {
959 bp_pc_params
.flags
.SET_GENLOCK_REF_DIV_SRC
=
960 pll_settings
->use_external_clk
;
961 bp_pc_params
.flags
.SET_XTALIN_REF_SRC
=
962 !pll_settings
->use_external_clk
;
963 if (pix_clk_params
->flags
.SUPPORT_YCBCR420
) {
964 bp_pc_params
.flags
.SUPPORT_YUV_420
= 1;
967 if (clk_src
->bios
->funcs
->set_pixel_clock(
968 clk_src
->bios
, &bp_pc_params
) != BP_RESULT_OK
)
970 /* Resync deep color DTO */
971 if (clock_source
->id
!= CLOCK_SOURCE_ID_DP_DTO
)
972 dce112_program_pixel_clk_resync(clk_src
,
973 pix_clk_params
->signal_type
,
974 pix_clk_params
->color_depth
,
975 pix_clk_params
->flags
.SUPPORT_YCBCR420
);
980 static bool dcn31_program_pix_clk(
981 struct clock_source
*clock_source
,
982 struct pixel_clk_params
*pix_clk_params
,
983 enum dp_link_encoding encoding
,
984 struct pll_settings
*pll_settings
)
986 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
987 unsigned int inst
= pix_clk_params
->controller_id
- CONTROLLER_ID_D0
;
988 unsigned int dp_dto_ref_khz
= clock_source
->ctx
->dc
->clk_mgr
->dprefclk_khz
;
989 const struct pixel_rate_range_table_entry
*e
=
990 look_up_in_video_optimized_rate_tlb(pix_clk_params
->requested_pix_clk_100hz
/ 10);
991 struct bp_pixel_clock_parameters bp_pc_params
= {0};
992 enum transmitter_color_depth bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_24
;
993 // For these signal types Driver to program DP_DTO without calling VBIOS Command table
994 if (dc_is_dp_signal(pix_clk_params
->signal_type
) || dc_is_virtual_signal(pix_clk_params
->signal_type
)) {
996 /* Set DTO values: phase = target clock, modulo = reference clock*/
997 REG_WRITE(PHASE
[inst
], e
->target_pixel_rate_khz
* e
->mult_factor
);
998 REG_WRITE(MODULO
[inst
], dp_dto_ref_khz
* e
->div_factor
);
1000 /* Set DTO values: phase = target clock, modulo = reference clock*/
1001 REG_WRITE(PHASE
[inst
], pll_settings
->actual_pix_clk_100hz
* 100);
1002 REG_WRITE(MODULO
[inst
], dp_dto_ref_khz
* 1000);
1005 if (clk_src
->cs_mask
->PIPE0_DTO_SRC_SEL
)
1006 if (encoding
== DP_128b_132b_ENCODING
)
1007 REG_UPDATE_2(PIXEL_RATE_CNTL
[inst
],
1009 PIPE0_DTO_SRC_SEL
, 2);
1011 REG_UPDATE_2(PIXEL_RATE_CNTL
[inst
],
1013 PIPE0_DTO_SRC_SEL
, 1);
1015 REG_UPDATE(PIXEL_RATE_CNTL
[inst
],
1018 if (IS_FPGA_MAXIMUS_DC(clock_source
->ctx
->dce_environment
)) {
1019 unsigned int inst
= pix_clk_params
->controller_id
- CONTROLLER_ID_D0
;
1020 unsigned dp_dto_ref_100hz
= 7000000;
1021 unsigned clock_100hz
= pll_settings
->actual_pix_clk_100hz
;
1023 /* Set DTO values: phase = target clock, modulo = reference clock */
1024 REG_WRITE(PHASE
[inst
], clock_100hz
);
1025 REG_WRITE(MODULO
[inst
], dp_dto_ref_100hz
);
1028 if (clk_src
->cs_mask
->PIPE0_DTO_SRC_SEL
)
1029 REG_UPDATE_2(PIXEL_RATE_CNTL
[inst
],
1031 PIPE0_DTO_SRC_SEL
, 1);
1033 REG_UPDATE(PIXEL_RATE_CNTL
[inst
],
1038 if (clk_src
->cs_mask
->PIPE0_DTO_SRC_SEL
)
1039 REG_UPDATE(PIXEL_RATE_CNTL
[inst
],
1040 PIPE0_DTO_SRC_SEL
, 0);
1042 /*ATOMBIOS expects pixel rate adjusted by deep color ratio)*/
1043 bp_pc_params
.controller_id
= pix_clk_params
->controller_id
;
1044 bp_pc_params
.pll_id
= clock_source
->id
;
1045 bp_pc_params
.target_pixel_clock_100hz
= pll_settings
->actual_pix_clk_100hz
;
1046 bp_pc_params
.encoder_object_id
= pix_clk_params
->encoder_object_id
;
1047 bp_pc_params
.signal_type
= pix_clk_params
->signal_type
;
1049 // Make sure we send the correct color depth to DMUB for HDMI
1050 if (pix_clk_params
->signal_type
== SIGNAL_TYPE_HDMI_TYPE_A
) {
1051 switch (pix_clk_params
->color_depth
) {
1052 case COLOR_DEPTH_888
:
1053 bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_24
;
1055 case COLOR_DEPTH_101010
:
1056 bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_30
;
1058 case COLOR_DEPTH_121212
:
1059 bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_36
;
1061 case COLOR_DEPTH_161616
:
1062 bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_48
;
1065 bp_pc_colour_depth
= TRANSMITTER_COLOR_DEPTH_24
;
1068 bp_pc_params
.color_depth
= bp_pc_colour_depth
;
1071 if (clock_source
->id
!= CLOCK_SOURCE_ID_DP_DTO
) {
1072 bp_pc_params
.flags
.SET_GENLOCK_REF_DIV_SRC
=
1073 pll_settings
->use_external_clk
;
1074 bp_pc_params
.flags
.SET_XTALIN_REF_SRC
=
1075 !pll_settings
->use_external_clk
;
1076 if (pix_clk_params
->flags
.SUPPORT_YCBCR420
) {
1077 bp_pc_params
.flags
.SUPPORT_YUV_420
= 1;
1080 if (clk_src
->bios
->funcs
->set_pixel_clock(
1081 clk_src
->bios
, &bp_pc_params
) != BP_RESULT_OK
)
1083 /* Resync deep color DTO */
1084 if (clock_source
->id
!= CLOCK_SOURCE_ID_DP_DTO
)
1085 dce112_program_pixel_clk_resync(clk_src
,
1086 pix_clk_params
->signal_type
,
1087 pix_clk_params
->color_depth
,
1088 pix_clk_params
->flags
.SUPPORT_YCBCR420
);
1094 static bool dce110_clock_source_power_down(
1095 struct clock_source
*clk_src
)
1097 struct dce110_clk_src
*dce110_clk_src
= TO_DCE110_CLK_SRC(clk_src
);
1098 enum bp_result bp_result
;
1099 struct bp_pixel_clock_parameters bp_pixel_clock_params
= {0};
1101 if (clk_src
->dp_clk_src
)
1104 /* If Pixel Clock is 0 it means Power Down Pll*/
1105 bp_pixel_clock_params
.controller_id
= CONTROLLER_ID_UNDEFINED
;
1106 bp_pixel_clock_params
.pll_id
= clk_src
->id
;
1107 bp_pixel_clock_params
.flags
.FORCE_PROGRAMMING_OF_PLL
= 1;
1109 /*Call ASICControl to process ATOMBIOS Exec table*/
1110 bp_result
= dce110_clk_src
->bios
->funcs
->set_pixel_clock(
1111 dce110_clk_src
->bios
,
1112 &bp_pixel_clock_params
);
1114 return bp_result
== BP_RESULT_OK
;
1117 static bool get_pixel_clk_frequency_100hz(
1118 const struct clock_source
*clock_source
,
1120 unsigned int *pixel_clk_khz
)
1122 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
1123 unsigned int clock_hz
= 0;
1124 unsigned int modulo_hz
= 0;
1126 if (clock_source
->id
== CLOCK_SOURCE_ID_DP_DTO
) {
1127 clock_hz
= REG_READ(PHASE
[inst
]);
1129 if (clock_source
->ctx
->dc
->hwss
.enable_vblanks_synchronization
&&
1130 clock_source
->ctx
->dc
->config
.vblank_alignment_max_frame_time_diff
> 0) {
1131 /* NOTE: In case VBLANK syncronization is enabled, MODULO may
1132 * not be programmed equal to DPREFCLK
1134 modulo_hz
= REG_READ(MODULO
[inst
]);
1136 *pixel_clk_khz
= div_u64((uint64_t)clock_hz
*
1137 clock_source
->ctx
->dc
->clk_mgr
->dprefclk_khz
*10,
1142 /* NOTE: There is agreement with VBIOS here that MODULO is
1143 * programmed equal to DPREFCLK, in which case PHASE will be
1144 * equivalent to pixel clock.
1146 *pixel_clk_khz
= clock_hz
/ 100;
1154 /* this table is use to find *1.001 and /1.001 pixel rates from non-precise pixel rate */
1155 const struct pixel_rate_range_table_entry video_optimized_pixel_rates
[] = {
1157 {25170, 25180, 25200, 1000, 1001}, //25.2MHz -> 25.17
1158 {59340, 59350, 59400, 1000, 1001}, //59.4Mhz -> 59.340
1159 {74170, 74180, 74250, 1000, 1001}, //74.25Mhz -> 74.1758
1160 {125870, 125880, 126000, 1000, 1001}, //126Mhz -> 125.87
1161 {148350, 148360, 148500, 1000, 1001}, //148.5Mhz -> 148.3516
1162 {167830, 167840, 168000, 1000, 1001}, //168Mhz -> 167.83
1163 {222520, 222530, 222750, 1000, 1001}, //222.75Mhz -> 222.527
1164 {257140, 257150, 257400, 1000, 1001}, //257.4Mhz -> 257.1429
1165 {296700, 296710, 297000, 1000, 1001}, //297Mhz -> 296.7033
1166 {342850, 342860, 343200, 1000, 1001}, //343.2Mhz -> 342.857
1167 {395600, 395610, 396000, 1000, 1001}, //396Mhz -> 395.6
1168 {409090, 409100, 409500, 1000, 1001}, //409.5Mhz -> 409.091
1169 {445050, 445060, 445500, 1000, 1001}, //445.5Mhz -> 445.055
1170 {467530, 467540, 468000, 1000, 1001}, //468Mhz -> 467.5325
1171 {519230, 519240, 519750, 1000, 1001}, //519.75Mhz -> 519.231
1172 {525970, 525980, 526500, 1000, 1001}, //526.5Mhz -> 525.974
1173 {545450, 545460, 546000, 1000, 1001}, //546Mhz -> 545.455
1174 {593400, 593410, 594000, 1000, 1001}, //594Mhz -> 593.4066
1175 {623370, 623380, 624000, 1000, 1001}, //624Mhz -> 623.377
1176 {692300, 692310, 693000, 1000, 1001}, //693Mhz -> 692.308
1177 {701290, 701300, 702000, 1000, 1001}, //702Mhz -> 701.2987
1178 {791200, 791210, 792000, 1000, 1001}, //792Mhz -> 791.209
1179 {890100, 890110, 891000, 1000, 1001}, //891Mhz -> 890.1099
1180 {1186810, 1186820, 1188000, 1000, 1001},//1188Mhz -> 1186.8131
1183 {27020, 27030, 27000, 1001, 1000}, //27Mhz
1184 {54050, 54060, 54000, 1001, 1000}, //54Mhz
1185 {108100, 108110, 108000, 1001, 1000},//108Mhz
1188 const struct pixel_rate_range_table_entry
*look_up_in_video_optimized_rate_tlb(
1189 unsigned int pixel_rate_khz
)
1193 for (i
= 0; i
< NUM_ELEMENTS(video_optimized_pixel_rates
); i
++) {
1194 const struct pixel_rate_range_table_entry
*e
= &video_optimized_pixel_rates
[i
];
1196 if (e
->range_min_khz
<= pixel_rate_khz
&& pixel_rate_khz
<= e
->range_max_khz
) {
1204 static bool dcn20_program_pix_clk(
1205 struct clock_source
*clock_source
,
1206 struct pixel_clk_params
*pix_clk_params
,
1207 enum dp_link_encoding encoding
,
1208 struct pll_settings
*pll_settings
)
1210 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
1211 unsigned int inst
= pix_clk_params
->controller_id
- CONTROLLER_ID_D0
;
1213 dce112_program_pix_clk(clock_source
, pix_clk_params
, encoding
, pll_settings
);
1215 if (clock_source
->ctx
->dc
->hwss
.enable_vblanks_synchronization
&&
1216 clock_source
->ctx
->dc
->config
.vblank_alignment_max_frame_time_diff
> 0) {
1217 /* NOTE: In case VBLANK syncronization is enabled,
1218 * we need to set modulo to default DPREFCLK first
1219 * dce112_program_pix_clk does not set default DPREFCLK
1221 REG_WRITE(MODULO
[inst
],
1222 clock_source
->ctx
->dc
->clk_mgr
->dprefclk_khz
*1000);
1227 static bool dcn20_override_dp_pix_clk(
1228 struct clock_source
*clock_source
,
1230 unsigned int pixel_clk
,
1231 unsigned int ref_clk
)
1233 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
1235 REG_UPDATE(PIXEL_RATE_CNTL
[inst
], DP_DTO0_ENABLE
, 0);
1236 REG_WRITE(PHASE
[inst
], pixel_clk
);
1237 REG_WRITE(MODULO
[inst
], ref_clk
);
1238 REG_UPDATE(PIXEL_RATE_CNTL
[inst
], DP_DTO0_ENABLE
, 1);
1242 static const struct clock_source_funcs dcn20_clk_src_funcs
= {
1243 .cs_power_down
= dce110_clock_source_power_down
,
1244 .program_pix_clk
= dcn20_program_pix_clk
,
1245 .get_pix_clk_dividers
= dce112_get_pix_clk_dividers
,
1246 .get_pixel_clk_frequency_100hz
= get_pixel_clk_frequency_100hz
,
1247 .override_dp_pix_clk
= dcn20_override_dp_pix_clk
1250 static bool dcn3_program_pix_clk(
1251 struct clock_source
*clock_source
,
1252 struct pixel_clk_params
*pix_clk_params
,
1253 enum dp_link_encoding encoding
,
1254 struct pll_settings
*pll_settings
)
1256 struct dce110_clk_src
*clk_src
= TO_DCE110_CLK_SRC(clock_source
);
1257 unsigned int inst
= pix_clk_params
->controller_id
- CONTROLLER_ID_D0
;
1258 unsigned int dp_dto_ref_khz
= clock_source
->ctx
->dc
->clk_mgr
->dprefclk_khz
;
1259 const struct pixel_rate_range_table_entry
*e
=
1260 look_up_in_video_optimized_rate_tlb(pix_clk_params
->requested_pix_clk_100hz
/ 10);
1262 // For these signal types Driver to program DP_DTO without calling VBIOS Command table
1263 if (dc_is_dp_signal(pix_clk_params
->signal_type
)) {
1265 /* Set DTO values: phase = target clock, modulo = reference clock*/
1266 REG_WRITE(PHASE
[inst
], e
->target_pixel_rate_khz
* e
->mult_factor
);
1267 REG_WRITE(MODULO
[inst
], dp_dto_ref_khz
* e
->div_factor
);
1269 /* Set DTO values: phase = target clock, modulo = reference clock*/
1270 REG_WRITE(PHASE
[inst
], pll_settings
->actual_pix_clk_100hz
* 100);
1271 REG_WRITE(MODULO
[inst
], dp_dto_ref_khz
* 1000);
1274 if (clk_src
->cs_mask
->PIPE0_DTO_SRC_SEL
)
1275 REG_UPDATE_2(PIXEL_RATE_CNTL
[inst
],
1277 PIPE0_DTO_SRC_SEL
, 1);
1279 REG_UPDATE(PIXEL_RATE_CNTL
[inst
],
1282 // For other signal types(HDMI_TYPE_A, DVI) Driver still to call VBIOS Command table
1283 dce112_program_pix_clk(clock_source
, pix_clk_params
, encoding
, pll_settings
);
1288 static uint32_t dcn3_get_pix_clk_dividers(
1289 struct clock_source
*cs
,
1290 struct pixel_clk_params
*pix_clk_params
,
1291 struct pll_settings
*pll_settings
)
1293 unsigned long long actual_pix_clk_100Hz
= pix_clk_params
? pix_clk_params
->requested_pix_clk_100hz
: 0;
1297 if (pix_clk_params
== NULL
|| pll_settings
== NULL
1298 || pix_clk_params
->requested_pix_clk_100hz
== 0) {
1300 "%s: Invalid parameters!!\n", __func__
);
1304 memset(pll_settings
, 0, sizeof(*pll_settings
));
1305 /* Adjust for HDMI Type A deep color */
1306 if (pix_clk_params
->signal_type
== SIGNAL_TYPE_HDMI_TYPE_A
) {
1307 switch (pix_clk_params
->color_depth
) {
1308 case COLOR_DEPTH_101010
:
1309 actual_pix_clk_100Hz
= (actual_pix_clk_100Hz
* 5) >> 2;
1311 case COLOR_DEPTH_121212
:
1312 actual_pix_clk_100Hz
= (actual_pix_clk_100Hz
* 6) >> 2;
1314 case COLOR_DEPTH_161616
:
1315 actual_pix_clk_100Hz
= actual_pix_clk_100Hz
* 2;
1321 pll_settings
->actual_pix_clk_100hz
= (unsigned int) actual_pix_clk_100Hz
;
1322 pll_settings
->adjusted_pix_clk_100hz
= (unsigned int) actual_pix_clk_100Hz
;
1323 pll_settings
->calculated_pix_clk_100hz
= (unsigned int) actual_pix_clk_100Hz
;
1328 static const struct clock_source_funcs dcn3_clk_src_funcs
= {
1329 .cs_power_down
= dce110_clock_source_power_down
,
1330 .program_pix_clk
= dcn3_program_pix_clk
,
1331 .get_pix_clk_dividers
= dcn3_get_pix_clk_dividers
,
1332 .get_pixel_clk_frequency_100hz
= get_pixel_clk_frequency_100hz
1335 static const struct clock_source_funcs dcn31_clk_src_funcs
= {
1336 .cs_power_down
= dce110_clock_source_power_down
,
1337 .program_pix_clk
= dcn31_program_pix_clk
,
1338 .get_pix_clk_dividers
= dcn3_get_pix_clk_dividers
,
1339 .get_pixel_clk_frequency_100hz
= get_pixel_clk_frequency_100hz
1342 /*****************************************/
1344 /*****************************************/
1346 static const struct clock_source_funcs dce112_clk_src_funcs
= {
1347 .cs_power_down
= dce110_clock_source_power_down
,
1348 .program_pix_clk
= dce112_program_pix_clk
,
1349 .get_pix_clk_dividers
= dce112_get_pix_clk_dividers
,
1350 .get_pixel_clk_frequency_100hz
= get_pixel_clk_frequency_100hz
1352 static const struct clock_source_funcs dce110_clk_src_funcs
= {
1353 .cs_power_down
= dce110_clock_source_power_down
,
1354 .program_pix_clk
= dce110_program_pix_clk
,
1355 .get_pix_clk_dividers
= dce110_get_pix_clk_dividers
,
1356 .get_pixel_clk_frequency_100hz
= get_pixel_clk_frequency_100hz
1360 static void get_ss_info_from_atombios(
1361 struct dce110_clk_src
*clk_src
,
1362 enum as_signal_type as_signal
,
1363 struct spread_spectrum_data
*spread_spectrum_data
[],
1364 uint32_t *ss_entries_num
)
1366 enum bp_result bp_result
= BP_RESULT_FAILURE
;
1367 struct spread_spectrum_info
*ss_info
;
1368 struct spread_spectrum_data
*ss_data
;
1369 struct spread_spectrum_info
*ss_info_cur
;
1370 struct spread_spectrum_data
*ss_data_cur
;
1373 if (ss_entries_num
== NULL
) {
1375 "Invalid entry !!!\n");
1378 if (spread_spectrum_data
== NULL
) {
1380 "Invalid array pointer!!!\n");
1384 spread_spectrum_data
[0] = NULL
;
1385 *ss_entries_num
= 0;
1387 *ss_entries_num
= clk_src
->bios
->funcs
->get_ss_entry_number(
1391 if (*ss_entries_num
== 0)
1394 ss_info
= kcalloc(*ss_entries_num
,
1395 sizeof(struct spread_spectrum_info
),
1397 ss_info_cur
= ss_info
;
1398 if (ss_info
== NULL
)
1401 ss_data
= kcalloc(*ss_entries_num
,
1402 sizeof(struct spread_spectrum_data
),
1404 if (ss_data
== NULL
)
1407 for (i
= 0, ss_info_cur
= ss_info
;
1408 i
< (*ss_entries_num
);
1409 ++i
, ++ss_info_cur
) {
1411 bp_result
= clk_src
->bios
->funcs
->get_spread_spectrum_info(
1417 if (bp_result
!= BP_RESULT_OK
)
1421 for (i
= 0, ss_info_cur
= ss_info
, ss_data_cur
= ss_data
;
1422 i
< (*ss_entries_num
);
1423 ++i
, ++ss_info_cur
, ++ss_data_cur
) {
1425 if (ss_info_cur
->type
.STEP_AND_DELAY_INFO
!= false) {
1427 "Invalid ATOMBIOS SS Table!!!\n");
1431 /* for HDMI check SS percentage,
1432 * if it is > 6 (0.06%), the ATOMBIOS table info is invalid*/
1433 if (as_signal
== AS_SIGNAL_TYPE_HDMI
1434 && ss_info_cur
->spread_spectrum_percentage
> 6){
1435 /* invalid input, do nothing */
1437 "Invalid SS percentage ");
1439 "for HDMI in ATOMBIOS info Table!!!\n");
1442 if (ss_info_cur
->spread_percentage_divider
== 1000) {
1443 /* Keep previous precision from ATOMBIOS for these
1444 * in case new precision set by ATOMBIOS for these
1445 * (otherwise all code in DCE specific classes
1446 * for all previous ASICs would need
1447 * to be updated for SS calculations,
1448 * Audio SS compensation and DP DTO SS compensation
1449 * which assumes fixed SS percentage Divider = 100)*/
1450 ss_info_cur
->spread_spectrum_percentage
/= 10;
1451 ss_info_cur
->spread_percentage_divider
= 100;
1454 ss_data_cur
->freq_range_khz
= ss_info_cur
->target_clock_range
;
1455 ss_data_cur
->percentage
=
1456 ss_info_cur
->spread_spectrum_percentage
;
1457 ss_data_cur
->percentage_divider
=
1458 ss_info_cur
->spread_percentage_divider
;
1459 ss_data_cur
->modulation_freq_hz
=
1460 ss_info_cur
->spread_spectrum_range
;
1462 if (ss_info_cur
->type
.CENTER_MODE
)
1463 ss_data_cur
->flags
.CENTER_SPREAD
= 1;
1465 if (ss_info_cur
->type
.EXTERNAL
)
1466 ss_data_cur
->flags
.EXTERNAL_SS
= 1;
1470 *spread_spectrum_data
= ss_data
;
1476 *ss_entries_num
= 0;
1481 static void ss_info_from_atombios_create(
1482 struct dce110_clk_src
*clk_src
)
1484 get_ss_info_from_atombios(
1486 AS_SIGNAL_TYPE_DISPLAY_PORT
,
1487 &clk_src
->dp_ss_params
,
1488 &clk_src
->dp_ss_params_cnt
);
1489 get_ss_info_from_atombios(
1491 AS_SIGNAL_TYPE_HDMI
,
1492 &clk_src
->hdmi_ss_params
,
1493 &clk_src
->hdmi_ss_params_cnt
);
1494 get_ss_info_from_atombios(
1497 &clk_src
->dvi_ss_params
,
1498 &clk_src
->dvi_ss_params_cnt
);
1499 get_ss_info_from_atombios(
1501 AS_SIGNAL_TYPE_LVDS
,
1502 &clk_src
->lvds_ss_params
,
1503 &clk_src
->lvds_ss_params_cnt
);
1506 static bool calc_pll_max_vco_construct(
1507 struct calc_pll_clock_source
*calc_pll_cs
,
1508 struct calc_pll_clock_source_init_data
*init_data
)
1511 struct dc_firmware_info
*fw_info
;
1512 if (calc_pll_cs
== NULL
||
1513 init_data
== NULL
||
1514 init_data
->bp
== NULL
)
1517 if (!init_data
->bp
->fw_info_valid
)
1520 fw_info
= &init_data
->bp
->fw_info
;
1521 calc_pll_cs
->ctx
= init_data
->ctx
;
1522 calc_pll_cs
->ref_freq_khz
= fw_info
->pll_info
.crystal_frequency
;
1523 calc_pll_cs
->min_vco_khz
=
1524 fw_info
->pll_info
.min_output_pxl_clk_pll_frequency
;
1525 calc_pll_cs
->max_vco_khz
=
1526 fw_info
->pll_info
.max_output_pxl_clk_pll_frequency
;
1528 if (init_data
->max_override_input_pxl_clk_pll_freq_khz
!= 0)
1529 calc_pll_cs
->max_pll_input_freq_khz
=
1530 init_data
->max_override_input_pxl_clk_pll_freq_khz
;
1532 calc_pll_cs
->max_pll_input_freq_khz
=
1533 fw_info
->pll_info
.max_input_pxl_clk_pll_frequency
;
1535 if (init_data
->min_override_input_pxl_clk_pll_freq_khz
!= 0)
1536 calc_pll_cs
->min_pll_input_freq_khz
=
1537 init_data
->min_override_input_pxl_clk_pll_freq_khz
;
1539 calc_pll_cs
->min_pll_input_freq_khz
=
1540 fw_info
->pll_info
.min_input_pxl_clk_pll_frequency
;
1542 calc_pll_cs
->min_pix_clock_pll_post_divider
=
1543 init_data
->min_pix_clk_pll_post_divider
;
1544 calc_pll_cs
->max_pix_clock_pll_post_divider
=
1545 init_data
->max_pix_clk_pll_post_divider
;
1546 calc_pll_cs
->min_pll_ref_divider
=
1547 init_data
->min_pll_ref_divider
;
1548 calc_pll_cs
->max_pll_ref_divider
=
1549 init_data
->max_pll_ref_divider
;
1551 if (init_data
->num_fract_fb_divider_decimal_point
== 0 ||
1552 init_data
->num_fract_fb_divider_decimal_point_precision
>
1553 init_data
->num_fract_fb_divider_decimal_point
) {
1555 "The dec point num or precision is incorrect!");
1558 if (init_data
->num_fract_fb_divider_decimal_point_precision
== 0) {
1560 "Incorrect fract feedback divider precision num!");
1564 calc_pll_cs
->fract_fb_divider_decimal_points_num
=
1565 init_data
->num_fract_fb_divider_decimal_point
;
1566 calc_pll_cs
->fract_fb_divider_precision
=
1567 init_data
->num_fract_fb_divider_decimal_point_precision
;
1568 calc_pll_cs
->fract_fb_divider_factor
= 1;
1569 for (i
= 0; i
< calc_pll_cs
->fract_fb_divider_decimal_points_num
; ++i
)
1570 calc_pll_cs
->fract_fb_divider_factor
*= 10;
1572 calc_pll_cs
->fract_fb_divider_precision_factor
= 1;
1575 i
< (calc_pll_cs
->fract_fb_divider_decimal_points_num
-
1576 calc_pll_cs
->fract_fb_divider_precision
);
1578 calc_pll_cs
->fract_fb_divider_precision_factor
*= 10;
1583 bool dce110_clk_src_construct(
1584 struct dce110_clk_src
*clk_src
,
1585 struct dc_context
*ctx
,
1586 struct dc_bios
*bios
,
1587 enum clock_source_id id
,
1588 const struct dce110_clk_src_regs
*regs
,
1589 const struct dce110_clk_src_shift
*cs_shift
,
1590 const struct dce110_clk_src_mask
*cs_mask
)
1592 struct calc_pll_clock_source_init_data calc_pll_cs_init_data_hdmi
;
1593 struct calc_pll_clock_source_init_data calc_pll_cs_init_data
;
1595 clk_src
->base
.ctx
= ctx
;
1596 clk_src
->bios
= bios
;
1597 clk_src
->base
.id
= id
;
1598 clk_src
->base
.funcs
= &dce110_clk_src_funcs
;
1600 clk_src
->regs
= regs
;
1601 clk_src
->cs_shift
= cs_shift
;
1602 clk_src
->cs_mask
= cs_mask
;
1604 if (!clk_src
->bios
->fw_info_valid
) {
1605 ASSERT_CRITICAL(false);
1606 goto unexpected_failure
;
1609 clk_src
->ext_clk_khz
= clk_src
->bios
->fw_info
.external_clock_source_frequency_for_dp
;
1611 /* structure normally used with PLL ranges from ATOMBIOS; DS on by default */
1612 calc_pll_cs_init_data
.bp
= bios
;
1613 calc_pll_cs_init_data
.min_pix_clk_pll_post_divider
= 1;
1614 calc_pll_cs_init_data
.max_pix_clk_pll_post_divider
=
1615 clk_src
->cs_mask
->PLL_POST_DIV_PIXCLK
;
1616 calc_pll_cs_init_data
.min_pll_ref_divider
= 1;
1617 calc_pll_cs_init_data
.max_pll_ref_divider
= clk_src
->cs_mask
->PLL_REF_DIV
;
1618 /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
1619 calc_pll_cs_init_data
.min_override_input_pxl_clk_pll_freq_khz
= 0;
1620 /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
1621 calc_pll_cs_init_data
.max_override_input_pxl_clk_pll_freq_khz
= 0;
1622 /*numberOfFractFBDividerDecimalPoints*/
1623 calc_pll_cs_init_data
.num_fract_fb_divider_decimal_point
=
1624 FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM
;
1625 /*number of decimal point to round off for fractional feedback divider value*/
1626 calc_pll_cs_init_data
.num_fract_fb_divider_decimal_point_precision
=
1627 FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM
;
1628 calc_pll_cs_init_data
.ctx
= ctx
;
1630 /*structure for HDMI, no SS or SS% <= 0.06% for 27 MHz Ref clock */
1631 calc_pll_cs_init_data_hdmi
.bp
= bios
;
1632 calc_pll_cs_init_data_hdmi
.min_pix_clk_pll_post_divider
= 1;
1633 calc_pll_cs_init_data_hdmi
.max_pix_clk_pll_post_divider
=
1634 clk_src
->cs_mask
->PLL_POST_DIV_PIXCLK
;
1635 calc_pll_cs_init_data_hdmi
.min_pll_ref_divider
= 1;
1636 calc_pll_cs_init_data_hdmi
.max_pll_ref_divider
= clk_src
->cs_mask
->PLL_REF_DIV
;
1637 /* when 0 use minInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
1638 calc_pll_cs_init_data_hdmi
.min_override_input_pxl_clk_pll_freq_khz
= 13500;
1639 /* when 0 use maxInputPxlClkPLLFrequencyInKHz from firmwareInfo*/
1640 calc_pll_cs_init_data_hdmi
.max_override_input_pxl_clk_pll_freq_khz
= 27000;
1641 /*numberOfFractFBDividerDecimalPoints*/
1642 calc_pll_cs_init_data_hdmi
.num_fract_fb_divider_decimal_point
=
1643 FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM
;
1644 /*number of decimal point to round off for fractional feedback divider value*/
1645 calc_pll_cs_init_data_hdmi
.num_fract_fb_divider_decimal_point_precision
=
1646 FRACT_FB_DIVIDER_DEC_POINTS_MAX_NUM
;
1647 calc_pll_cs_init_data_hdmi
.ctx
= ctx
;
1649 clk_src
->ref_freq_khz
= clk_src
->bios
->fw_info
.pll_info
.crystal_frequency
;
1651 if (clk_src
->base
.id
== CLOCK_SOURCE_ID_EXTERNAL
)
1654 /* PLL only from here on */
1655 ss_info_from_atombios_create(clk_src
);
1657 if (!calc_pll_max_vco_construct(
1659 &calc_pll_cs_init_data
)) {
1660 ASSERT_CRITICAL(false);
1661 goto unexpected_failure
;
1665 calc_pll_cs_init_data_hdmi
.
1666 min_override_input_pxl_clk_pll_freq_khz
= clk_src
->ref_freq_khz
/2;
1667 calc_pll_cs_init_data_hdmi
.
1668 max_override_input_pxl_clk_pll_freq_khz
= clk_src
->ref_freq_khz
;
1671 if (!calc_pll_max_vco_construct(
1672 &clk_src
->calc_pll_hdmi
, &calc_pll_cs_init_data_hdmi
)) {
1673 ASSERT_CRITICAL(false);
1674 goto unexpected_failure
;
1683 bool dce112_clk_src_construct(
1684 struct dce110_clk_src
*clk_src
,
1685 struct dc_context
*ctx
,
1686 struct dc_bios
*bios
,
1687 enum clock_source_id id
,
1688 const struct dce110_clk_src_regs
*regs
,
1689 const struct dce110_clk_src_shift
*cs_shift
,
1690 const struct dce110_clk_src_mask
*cs_mask
)
1692 clk_src
->base
.ctx
= ctx
;
1693 clk_src
->bios
= bios
;
1694 clk_src
->base
.id
= id
;
1695 clk_src
->base
.funcs
= &dce112_clk_src_funcs
;
1697 clk_src
->regs
= regs
;
1698 clk_src
->cs_shift
= cs_shift
;
1699 clk_src
->cs_mask
= cs_mask
;
1701 if (!clk_src
->bios
->fw_info_valid
) {
1702 ASSERT_CRITICAL(false);
1706 clk_src
->ext_clk_khz
= clk_src
->bios
->fw_info
.external_clock_source_frequency_for_dp
;
1711 bool dcn20_clk_src_construct(
1712 struct dce110_clk_src
*clk_src
,
1713 struct dc_context
*ctx
,
1714 struct dc_bios
*bios
,
1715 enum clock_source_id id
,
1716 const struct dce110_clk_src_regs
*regs
,
1717 const struct dce110_clk_src_shift
*cs_shift
,
1718 const struct dce110_clk_src_mask
*cs_mask
)
1720 bool ret
= dce112_clk_src_construct(clk_src
, ctx
, bios
, id
, regs
, cs_shift
, cs_mask
);
1722 clk_src
->base
.funcs
= &dcn20_clk_src_funcs
;
1727 bool dcn3_clk_src_construct(
1728 struct dce110_clk_src
*clk_src
,
1729 struct dc_context
*ctx
,
1730 struct dc_bios
*bios
,
1731 enum clock_source_id id
,
1732 const struct dce110_clk_src_regs
*regs
,
1733 const struct dce110_clk_src_shift
*cs_shift
,
1734 const struct dce110_clk_src_mask
*cs_mask
)
1736 bool ret
= dce112_clk_src_construct(clk_src
, ctx
, bios
, id
, regs
, cs_shift
, cs_mask
);
1738 clk_src
->base
.funcs
= &dcn3_clk_src_funcs
;
1743 bool dcn31_clk_src_construct(
1744 struct dce110_clk_src
*clk_src
,
1745 struct dc_context
*ctx
,
1746 struct dc_bios
*bios
,
1747 enum clock_source_id id
,
1748 const struct dce110_clk_src_regs
*regs
,
1749 const struct dce110_clk_src_shift
*cs_shift
,
1750 const struct dce110_clk_src_mask
*cs_mask
)
1752 bool ret
= dce112_clk_src_construct(clk_src
, ctx
, bios
, id
, regs
, cs_shift
, cs_mask
);
1754 clk_src
->base
.funcs
= &dcn31_clk_src_funcs
;
1759 bool dcn301_clk_src_construct(
1760 struct dce110_clk_src
*clk_src
,
1761 struct dc_context
*ctx
,
1762 struct dc_bios
*bios
,
1763 enum clock_source_id id
,
1764 const struct dce110_clk_src_regs
*regs
,
1765 const struct dce110_clk_src_shift
*cs_shift
,
1766 const struct dce110_clk_src_mask
*cs_mask
)
1768 bool ret
= dce112_clk_src_construct(clk_src
, ctx
, bios
, id
, regs
, cs_shift
, cs_mask
);
1770 clk_src
->base
.funcs
= &dcn3_clk_src_funcs
;