17ff89ca2SVille Syrjälä /*
27ff89ca2SVille Syrjälä * Copyright © 2006-2017 Intel Corporation
37ff89ca2SVille Syrjälä *
47ff89ca2SVille Syrjälä * Permission is hereby granted, free of charge, to any person obtaining a
57ff89ca2SVille Syrjälä * copy of this software and associated documentation files (the "Software"),
67ff89ca2SVille Syrjälä * to deal in the Software without restriction, including without limitation
77ff89ca2SVille Syrjälä * the rights to use, copy, modify, merge, publish, distribute, sublicense,
87ff89ca2SVille Syrjälä * and/or sell copies of the Software, and to permit persons to whom the
97ff89ca2SVille Syrjälä * Software is furnished to do so, subject to the following conditions:
107ff89ca2SVille Syrjälä *
117ff89ca2SVille Syrjälä * The above copyright notice and this permission notice (including the next
127ff89ca2SVille Syrjälä * paragraph) shall be included in all copies or substantial portions of the
137ff89ca2SVille Syrjälä * Software.
147ff89ca2SVille Syrjälä *
157ff89ca2SVille Syrjälä * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
167ff89ca2SVille Syrjälä * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
177ff89ca2SVille Syrjälä * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
187ff89ca2SVille Syrjälä * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
197ff89ca2SVille Syrjälä * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
207ff89ca2SVille Syrjälä * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
217ff89ca2SVille Syrjälä * DEALINGS IN THE SOFTWARE.
227ff89ca2SVille Syrjälä */
237ff89ca2SVille Syrjälä
24ae19ba91SJani Nikula #include <linux/debugfs.h>
25cd191546SStanislav Lisovskiy #include <linux/time.h>
26cac91e67SStanislav Lisovskiy
27ce9b1466SImre Deak #include <drm/drm_fixed.h>
28ce9b1466SImre Deak
291cd377f3SJani Nikula #include "soc/intel_dram.h"
30ce9b1466SImre Deak
31f3b603deSVille Syrjälä #include "hsw_ips.h"
32399f7b67SJani Nikula #include "i915_drv.h"
33801543b2SJani Nikula #include "i915_reg.h"
34fe4709a8SVille Syrjälä #include "intel_atomic.h"
35754d6275SJani Nikula #include "intel_audio.h"
36112a87c4SKai Vehmanen #include "intel_bw.h"
37cac91e67SStanislav Lisovskiy #include "intel_cdclk.h"
38e7674ef6SJani Nikula #include "intel_crtc.h"
39fd2b94a5SJani Nikula #include "intel_de.h"
407785ae0bSVille Syrjälä #include "intel_display_regs.h"
411d455f8dSJani Nikula #include "intel_display_types.h"
42e30e6c7bSMatt Roper #include "intel_mchbar_regs.h"
437e470f10SJani Nikula #include "intel_pci_config.h"
444dd4375bSJani Nikula #include "intel_pcode.h"
4517c1a4b7SVille Syrjälä #include "intel_plane.h"
468290bceeSStanislav Lisovskiy #include "intel_psr.h"
479161e311SGustavo Sousa #include "intel_vdsc.h"
48c834a080SGustavo Sousa #include "skl_watermark.h"
4995601c60SVille Syrjälä #include "skl_watermark_regs.h"
501eecf31eSJani Nikula #include "vlv_dsi.h"
517ff89ca2SVille Syrjälä #include "vlv_sideband.h"
527ff89ca2SVille Syrjälä
537ff89ca2SVille Syrjälä /**
547ff89ca2SVille Syrjälä * DOC: CDCLK / RAWCLK
557ff89ca2SVille Syrjälä *
567ff89ca2SVille Syrjälä * The display engine uses several different clocks to do its work. There
577ff89ca2SVille Syrjälä * are two main clocks involved that aren't directly related to the actual
587ff89ca2SVille Syrjälä * pixel clock or any symbol/bit clock of the actual output port. These
597ff89ca2SVille Syrjälä * are the core display clock (CDCLK) and RAWCLK.
607ff89ca2SVille Syrjälä *
617ff89ca2SVille Syrjälä * CDCLK clocks most of the display pipe logic, and thus its frequency
627ff89ca2SVille Syrjälä * must be high enough to support the rate at which pixels are flowing
637ff89ca2SVille Syrjälä * through the pipes. Downscaling must also be accounted as that increases
647ff89ca2SVille Syrjälä * the effective pixel rate.
657ff89ca2SVille Syrjälä *
667ff89ca2SVille Syrjälä * On several platforms the CDCLK frequency can be changed dynamically
677ff89ca2SVille Syrjälä * to minimize power consumption for a given display configuration.
687ff89ca2SVille Syrjälä * Typically changes to the CDCLK frequency require all the display pipes
697ff89ca2SVille Syrjälä * to be shut down while the frequency is being changed.
707ff89ca2SVille Syrjälä *
717ff89ca2SVille Syrjälä * On SKL+ the DMC will toggle the CDCLK off/on during DC5/6 entry/exit.
727ff89ca2SVille Syrjälä * DMC will not change the active CDCLK frequency however, so that part
737ff89ca2SVille Syrjälä * will still be performed by the driver directly.
74f6e4fe15SGustavo Sousa *
75f6e4fe15SGustavo Sousa * There are multiple components involved in the generation of the CDCLK
76f6e4fe15SGustavo Sousa * frequency:
77f6e4fe15SGustavo Sousa *
78f6e4fe15SGustavo Sousa * - We have the CDCLK PLL, which generates an output clock based on a
79f6e4fe15SGustavo Sousa * reference clock and a ratio parameter.
80f6e4fe15SGustavo Sousa * - The CD2X Divider, which divides the output of the PLL based on a
81f6e4fe15SGustavo Sousa * divisor selected from a set of pre-defined choices.
82f6e4fe15SGustavo Sousa * - The CD2X Squasher, which further divides the output based on a
83f6e4fe15SGustavo Sousa * waveform represented as a sequence of bits where each zero
84f6e4fe15SGustavo Sousa * "squashes out" a clock cycle.
85f6e4fe15SGustavo Sousa * - And, finally, a fixed divider that divides the output frequency by 2.
86f6e4fe15SGustavo Sousa *
87f6e4fe15SGustavo Sousa * As such, the resulting CDCLK frequency can be calculated with the
88f6e4fe15SGustavo Sousa * following formula:
89f6e4fe15SGustavo Sousa *
90f6e4fe15SGustavo Sousa * cdclk = vco / cd2x_div / (sq_len / sq_div) / 2
91f6e4fe15SGustavo Sousa *
92f6e4fe15SGustavo Sousa * , where vco is the frequency generated by the PLL; cd2x_div
93f6e4fe15SGustavo Sousa * represents the CD2X Divider; sq_len and sq_div are the bit length
94f6e4fe15SGustavo Sousa * and the number of high bits for the CD2X Squasher waveform, respectively;
95f6e4fe15SGustavo Sousa * and 2 represents the fixed divider.
96f6e4fe15SGustavo Sousa *
97f6e4fe15SGustavo Sousa * Note that some older platforms do not contain the CD2X Divider
98f6e4fe15SGustavo Sousa * and/or CD2X Squasher, in which case we can ignore their respective
99f6e4fe15SGustavo Sousa * factors in the formula above.
10079e2ea2eSVille Syrjälä *
10179e2ea2eSVille Syrjälä * Several methods exist to change the CDCLK frequency, which ones are
1020be4e0a5SRodrigo Vivi * supported depends on the platform:
10379e2ea2eSVille Syrjälä *
10479e2ea2eSVille Syrjälä * - Full PLL disable + re-enable with new VCO frequency. Pipes must be inactive.
10579e2ea2eSVille Syrjälä * - CD2X divider update. Single pipe can be active as the divider update
10679e2ea2eSVille Syrjälä * can be synchronized with the pipe's start of vblank.
10779e2ea2eSVille Syrjälä * - Crawl the PLL smoothly to the new VCO frequency. Pipes can be active.
10879e2ea2eSVille Syrjälä * - Squash waveform update. Pipes can be active.
10979e2ea2eSVille Syrjälä * - Crawl and squash can also be done back to back. Pipes can be active.
1107ff89ca2SVille Syrjälä *
1117ff89ca2SVille Syrjälä * RAWCLK is a fixed frequency clock, often used by various auxiliary
1127ff89ca2SVille Syrjälä * blocks such as AUX CH or backlight PWM. Hence the only thing we
1137ff89ca2SVille Syrjälä * really need to know about RAWCLK is its frequency so that various
1147ff89ca2SVille Syrjälä * dividers can be programmed correctly.
1157ff89ca2SVille Syrjälä */
116a908db6dSJani Nikula
117d34927acSVille Syrjälä struct intel_cdclk_state {
118a908db6dSJani Nikula struct intel_global_state base;
119d34927acSVille Syrjälä
120a908db6dSJani Nikula /*
121a908db6dSJani Nikula * Logical configuration of cdclk (used for all scaling,
1224fab6b8bSVille Syrjälä * watermark, etc. calculations and checks). This is
123a908db6dSJani Nikula * computed as if all enabled crtcs were active.
124a908db6dSJani Nikula */
125a908db6dSJani Nikula struct intel_cdclk_config logical;
126d34927acSVille Syrjälä
12744892ffaSDave Airlie /*
12844892ffaSDave Airlie * Actual configuration of cdclk, can be different from the
129d34927acSVille Syrjälä * logical configuration only when all crtc's are DPMS off.
13044892ffaSDave Airlie */
13144892ffaSDave Airlie struct intel_cdclk_config actual;
132d34927acSVille Syrjälä
13344892ffaSDave Airlie /* minimum acceptable cdclk to satisfy bandwidth requirements */
13444892ffaSDave Airlie int bw_min_cdclk;
13544892ffaSDave Airlie /* minimum acceptable cdclk for each pipe */
136d34927acSVille Syrjälä int min_cdclk[I915_MAX_PIPES];
13744892ffaSDave Airlie /* minimum acceptable voltage level for each pipe */
13844892ffaSDave Airlie u8 min_voltage_level[I915_MAX_PIPES];
1394fab6b8bSVille Syrjälä
14044892ffaSDave Airlie /* pipe to which cd2x update is synchronized */
141d34927acSVille Syrjälä enum pipe pipe;
1424fab6b8bSVille Syrjälä
143d34927acSVille Syrjälä /* forced minimum cdclk for glk+ audio w/a */
14444892ffaSDave Airlie int force_min_cdclk;
14544892ffaSDave Airlie
146d34927acSVille Syrjälä /* bitmask of active pipes */
14744892ffaSDave Airlie u8 active_pipes;
14844892ffaSDave Airlie
149d34927acSVille Syrjälä /* update cdclk with pipes disabled */
15044892ffaSDave Airlie bool disable_pipes;
15144892ffaSDave Airlie };
152d34927acSVille Syrjälä
1530bb94e03SVille Syrjälä struct intel_cdclk_funcs {
1547ff89ca2SVille Syrjälä void (*get_cdclk)(struct intel_display *display,
1550bb94e03SVille Syrjälä struct intel_cdclk_config *cdclk_config);
1567ff89ca2SVille Syrjälä void (*set_cdclk)(struct intel_display *display,
1577ff89ca2SVille Syrjälä const struct intel_cdclk_config *cdclk_config,
158d34927acSVille Syrjälä enum pipe pipe);
1590bb94e03SVille Syrjälä int (*modeset_calc_cdclk)(struct intel_atomic_state *state);
1607ff89ca2SVille Syrjälä u8 (*calc_voltage_level)(int cdclk);
1610bb94e03SVille Syrjälä };
1627ff89ca2SVille Syrjälä
intel_cdclk_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)1637ff89ca2SVille Syrjälä void intel_cdclk_get_cdclk(struct intel_display *display,
164d34927acSVille Syrjälä struct intel_cdclk_config *cdclk_config)
1650bb94e03SVille Syrjälä {
1667ff89ca2SVille Syrjälä display->funcs.cdclk->get_cdclk(display, cdclk_config);
1670bb94e03SVille Syrjälä }
1687ff89ca2SVille Syrjälä
intel_cdclk_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)1697ff89ca2SVille Syrjälä static void intel_cdclk_set_cdclk(struct intel_display *display,
170d34927acSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
1710bb94e03SVille Syrjälä enum pipe pipe)
1727ff89ca2SVille Syrjälä {
1730bb94e03SVille Syrjälä display->funcs.cdclk->set_cdclk(display, cdclk_config, pipe);
1747ff89ca2SVille Syrjälä }
1757ff89ca2SVille Syrjälä
intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state * state)176d34927acSVille Syrjälä static int intel_cdclk_modeset_calc_cdclk(struct intel_atomic_state *state)
1770bb94e03SVille Syrjälä {
1787ff89ca2SVille Syrjälä struct intel_display *display = to_intel_display(state);
1790bb94e03SVille Syrjälä
1807ff89ca2SVille Syrjälä return display->funcs.cdclk->modeset_calc_cdclk(state);
1817ff89ca2SVille Syrjälä }
182d34927acSVille Syrjälä
intel_cdclk_calc_voltage_level(struct intel_display * display,int cdclk)1830bb94e03SVille Syrjälä static u8 intel_cdclk_calc_voltage_level(struct intel_display *display,
1847ff89ca2SVille Syrjälä int cdclk)
1850bb94e03SVille Syrjälä {
1867ff89ca2SVille Syrjälä return display->funcs.cdclk->calc_voltage_level(cdclk);
1877ff89ca2SVille Syrjälä }
188d34927acSVille Syrjälä
fixed_133mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)1890bb94e03SVille Syrjälä static void fixed_133mhz_get_cdclk(struct intel_display *display,
1907ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
191d34927acSVille Syrjälä {
1927ff89ca2SVille Syrjälä cdclk_config->cdclk = 133333;
1937ff89ca2SVille Syrjälä }
1947ff89ca2SVille Syrjälä
fixed_200mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)1957ff89ca2SVille Syrjälä static void fixed_200mhz_get_cdclk(struct intel_display *display,
1967ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
1977ff89ca2SVille Syrjälä {
1987ff89ca2SVille Syrjälä cdclk_config->cdclk = 200000;
19949cd97a3SVille Syrjälä }
2000bb94e03SVille Syrjälä
fixed_266mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)20149cd97a3SVille Syrjälä static void fixed_266mhz_get_cdclk(struct intel_display *display,
20249cd97a3SVille Syrjälä struct intel_cdclk_config *cdclk_config)
2037ff89ca2SVille Syrjälä {
2047ff89ca2SVille Syrjälä cdclk_config->cdclk = 266667;
2057ff89ca2SVille Syrjälä }
2067ff89ca2SVille Syrjälä
fixed_333mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2077ff89ca2SVille Syrjälä static void fixed_333mhz_get_cdclk(struct intel_display *display,
2087ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
2097ff89ca2SVille Syrjälä {
2107ff89ca2SVille Syrjälä cdclk_config->cdclk = 333333;
2117ff89ca2SVille Syrjälä }
2127ff89ca2SVille Syrjälä
fixed_400mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2137ff89ca2SVille Syrjälä static void fixed_400mhz_get_cdclk(struct intel_display *display,
2140bb94e03SVille Syrjälä struct intel_cdclk_config *cdclk_config)
21549cd97a3SVille Syrjälä {
2167ff89ca2SVille Syrjälä cdclk_config->cdclk = 400000;
2170bb94e03SVille Syrjälä }
21849cd97a3SVille Syrjälä
fixed_450mhz_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2197ff89ca2SVille Syrjälä static void fixed_450mhz_get_cdclk(struct intel_display *display,
2200bb94e03SVille Syrjälä struct intel_cdclk_config *cdclk_config)
22149cd97a3SVille Syrjälä {
2227ff89ca2SVille Syrjälä cdclk_config->cdclk = 450000;
2237ff89ca2SVille Syrjälä }
2247ff89ca2SVille Syrjälä
i85x_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2250bb94e03SVille Syrjälä static void i85x_get_cdclk(struct intel_display *display,
22649cd97a3SVille Syrjälä struct intel_cdclk_config *cdclk_config)
22749cd97a3SVille Syrjälä {
2287ff89ca2SVille Syrjälä struct pci_dev *pdev = to_pci_dev(display->drm->dev);
2297ff89ca2SVille Syrjälä u16 hpllcc = 0;
230d34927acSVille Syrjälä
2310bb94e03SVille Syrjälä /*
2327ff89ca2SVille Syrjälä * 852GM/852GMV only supports 133 MHz and the HPLLCC
233d34927acSVille Syrjälä * encoding is different :(
2347ff89ca2SVille Syrjälä * FIXME is this the right way to detect 852GM/852GMV?
2357ff89ca2SVille Syrjälä */
2367ff89ca2SVille Syrjälä if (pdev->revision == 0x1) {
2377ff89ca2SVille Syrjälä cdclk_config->cdclk = 133333;
23849cd97a3SVille Syrjälä return;
2390bb94e03SVille Syrjälä }
24049cd97a3SVille Syrjälä
24149cd97a3SVille Syrjälä pci_bus_read_config_word(pdev->bus,
2427ff89ca2SVille Syrjälä PCI_DEVFN(0, 3), HPLLCC, &hpllcc);
2437ff89ca2SVille Syrjälä
2447ff89ca2SVille Syrjälä /* Assume that the hardware is in the high speed state. This
2450bb94e03SVille Syrjälä * should be the default.
24649cd97a3SVille Syrjälä */
2477ff89ca2SVille Syrjälä switch (hpllcc & GC_CLOCK_CONTROL_MASK) {
2487ff89ca2SVille Syrjälä case GC_CLOCK_133_200:
2490bb94e03SVille Syrjälä case GC_CLOCK_133_200_2:
25049cd97a3SVille Syrjälä case GC_CLOCK_100_200:
2517ff89ca2SVille Syrjälä cdclk_config->cdclk = 200000;
2527ff89ca2SVille Syrjälä break;
2537ff89ca2SVille Syrjälä case GC_CLOCK_166_250:
254d34927acSVille Syrjälä cdclk_config->cdclk = 250000;
2550bb94e03SVille Syrjälä break;
2567ff89ca2SVille Syrjälä case GC_CLOCK_100_133:
257d34927acSVille Syrjälä cdclk_config->cdclk = 133333;
2587ff89ca2SVille Syrjälä break;
2597ff89ca2SVille Syrjälä case GC_CLOCK_133_266:
2607ff89ca2SVille Syrjälä case GC_CLOCK_133_266_2:
2617ff89ca2SVille Syrjälä case GC_CLOCK_166_266:
26249cd97a3SVille Syrjälä cdclk_config->cdclk = 266667;
2630bb94e03SVille Syrjälä break;
26449cd97a3SVille Syrjälä }
26549cd97a3SVille Syrjälä }
2667ff89ca2SVille Syrjälä
i915gm_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2677ff89ca2SVille Syrjälä static void i915gm_get_cdclk(struct intel_display *display,
2687ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
2690bb94e03SVille Syrjälä {
27049cd97a3SVille Syrjälä struct pci_dev *pdev = to_pci_dev(display->drm->dev);
2717ff89ca2SVille Syrjälä u16 gcfgc = 0;
2727ff89ca2SVille Syrjälä
2730bb94e03SVille Syrjälä pci_read_config_word(pdev, GCFGC, &gcfgc);
27449cd97a3SVille Syrjälä
2757ff89ca2SVille Syrjälä if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
2767ff89ca2SVille Syrjälä cdclk_config->cdclk = 133333;
2777ff89ca2SVille Syrjälä return;
278d34927acSVille Syrjälä }
2797ff89ca2SVille Syrjälä
2807ff89ca2SVille Syrjälä switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
2817ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_333_320_MHZ:
2827ff89ca2SVille Syrjälä cdclk_config->cdclk = 333333;
2837ff89ca2SVille Syrjälä break;
2847ff89ca2SVille Syrjälä default:
2857ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_190_200_MHZ:
2867ff89ca2SVille Syrjälä cdclk_config->cdclk = 190000;
2877ff89ca2SVille Syrjälä break;
2887ff89ca2SVille Syrjälä }
2897ff89ca2SVille Syrjälä }
2907ff89ca2SVille Syrjälä
i945gm_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)2917ff89ca2SVille Syrjälä static void i945gm_get_cdclk(struct intel_display *display,
2927ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
2937ff89ca2SVille Syrjälä {
2947ff89ca2SVille Syrjälä struct pci_dev *pdev = to_pci_dev(display->drm->dev);
2957ff89ca2SVille Syrjälä u16 gcfgc = 0;
2967ff89ca2SVille Syrjälä
2977ff89ca2SVille Syrjälä pci_read_config_word(pdev, GCFGC, &gcfgc);
2987ff89ca2SVille Syrjälä
2997ff89ca2SVille Syrjälä if (gcfgc & GC_LOW_FREQUENCY_ENABLE) {
3007ff89ca2SVille Syrjälä cdclk_config->cdclk = 133333;
3017ff89ca2SVille Syrjälä return;
3027ff89ca2SVille Syrjälä }
3037ff89ca2SVille Syrjälä
3047ff89ca2SVille Syrjälä switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
3057ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_333_320_MHZ:
3067ff89ca2SVille Syrjälä cdclk_config->cdclk = 320000;
3077ff89ca2SVille Syrjälä break;
3087ff89ca2SVille Syrjälä default:
3097ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_190_200_MHZ:
3107ff89ca2SVille Syrjälä cdclk_config->cdclk = 200000;
3117ff89ca2SVille Syrjälä break;
3127ff89ca2SVille Syrjälä }
3137ff89ca2SVille Syrjälä }
3147ff89ca2SVille Syrjälä
intel_hpll_vco(struct intel_display * display)3157ff89ca2SVille Syrjälä static unsigned int intel_hpll_vco(struct intel_display *display)
3167ff89ca2SVille Syrjälä {
3177ff89ca2SVille Syrjälä static const unsigned int blb_vco[8] = {
3187ff89ca2SVille Syrjälä [0] = 3200000,
319cbe974fbSJani Nikula [1] = 4000000,
3207ff89ca2SVille Syrjälä [2] = 5333333,
3217ff89ca2SVille Syrjälä [3] = 4800000,
322f0453266SJani Nikula [4] = 6400000,
3237ff89ca2SVille Syrjälä };
324f0453266SJani Nikula static const unsigned int pnv_vco[8] = {
3257ff89ca2SVille Syrjälä [0] = 3200000,
326f0453266SJani Nikula [1] = 4000000,
3277ff89ca2SVille Syrjälä [2] = 5333333,
328f0453266SJani Nikula [3] = 4800000,
3297ff89ca2SVille Syrjälä [4] = 2666667,
330f0453266SJani Nikula };
3317ff89ca2SVille Syrjälä static const unsigned int cl_vco[8] = {
3327ff89ca2SVille Syrjälä [0] = 3200000,
3337ff89ca2SVille Syrjälä [1] = 4000000,
3347ff89ca2SVille Syrjälä [2] = 5333333,
335f0453266SJani Nikula [3] = 6400000,
336f0453266SJani Nikula [4] = 3333333,
3377ff89ca2SVille Syrjälä [5] = 3566667,
3387ff89ca2SVille Syrjälä [6] = 4266667,
3397ff89ca2SVille Syrjälä };
340d34927acSVille Syrjälä static const unsigned int elk_vco[8] = {
34123194610SWambui Karuga [0] = 3200000,
3427ff89ca2SVille Syrjälä [1] = 4000000,
343d34927acSVille Syrjälä [2] = 5333333,
3447ff89ca2SVille Syrjälä [3] = 4800000,
3457ff89ca2SVille Syrjälä };
3467ff89ca2SVille Syrjälä static const unsigned int ctg_vco[8] = {
3477ff89ca2SVille Syrjälä [0] = 3200000,
348d34927acSVille Syrjälä [1] = 4000000,
3490bb94e03SVille Syrjälä [2] = 5333333,
3507ff89ca2SVille Syrjälä [3] = 6400000,
351d34927acSVille Syrjälä [4] = 2666667,
352cbe974fbSJani Nikula [5] = 4266667,
353cbe974fbSJani Nikula };
354cbe974fbSJani Nikula const unsigned int *vco_table;
355cbe974fbSJani Nikula unsigned int vco;
356cbe974fbSJani Nikula u8 tmp = 0;
35749cd97a3SVille Syrjälä
358cbe974fbSJani Nikula /* FIXME other chipsets? */
3597ff89ca2SVille Syrjälä if (display->platform.gm45)
360d34927acSVille Syrjälä vco_table = ctg_vco;
36149cd97a3SVille Syrjälä else if (display->platform.g45)
3627ff89ca2SVille Syrjälä vco_table = elk_vco;
3637ff89ca2SVille Syrjälä else if (display->platform.i965gm)
3647ff89ca2SVille Syrjälä vco_table = cl_vco;
3657ff89ca2SVille Syrjälä else if (display->platform.pineview)
3667ff89ca2SVille Syrjälä vco_table = pnv_vco;
3677ff89ca2SVille Syrjälä else if (display->platform.g33)
3687ff89ca2SVille Syrjälä vco_table = blb_vco;
3690bb94e03SVille Syrjälä else
3707ff89ca2SVille Syrjälä return 0;
3717ff89ca2SVille Syrjälä
3727ff89ca2SVille Syrjälä tmp = intel_de_read(display, display->platform.pineview ||
3737ff89ca2SVille Syrjälä display->platform.mobile ? HPLLVCO_MOBILE : HPLLVCO);
3747ff89ca2SVille Syrjälä
3757ff89ca2SVille Syrjälä vco = vco_table[tmp & 0x7];
3767ff89ca2SVille Syrjälä if (vco == 0)
3777ff89ca2SVille Syrjälä drm_err(display->drm, "Bad HPLL VCO (HPLLVCO=0x%02x)\n",
3787ff89ca2SVille Syrjälä tmp);
3797ff89ca2SVille Syrjälä else
3807ff89ca2SVille Syrjälä drm_dbg_kms(display->drm, "HPLL VCO %u kHz\n", vco);
3817ff89ca2SVille Syrjälä
3827ff89ca2SVille Syrjälä return vco;
3837ff89ca2SVille Syrjälä }
3847ff89ca2SVille Syrjälä
g33_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)3857ff89ca2SVille Syrjälä static void g33_get_cdclk(struct intel_display *display,
3860bb94e03SVille Syrjälä struct intel_cdclk_config *cdclk_config)
38749cd97a3SVille Syrjälä {
38849cd97a3SVille Syrjälä struct pci_dev *pdev = to_pci_dev(display->drm->dev);
3897ff89ca2SVille Syrjälä static const u8 div_3200[] = { 12, 10, 8, 7, 5, 16 };
3907ff89ca2SVille Syrjälä static const u8 div_4000[] = { 14, 12, 10, 8, 6, 20 };
391d34927acSVille Syrjälä static const u8 div_4800[] = { 20, 14, 12, 10, 8, 24 };
39223194610SWambui Karuga static const u8 div_5333[] = { 20, 16, 12, 12, 8, 28 };
3930bb94e03SVille Syrjälä const u8 *div_table;
3940bb94e03SVille Syrjälä unsigned int cdclk_sel;
3957ff89ca2SVille Syrjälä u16 tmp = 0;
3967ff89ca2SVille Syrjälä
397d34927acSVille Syrjälä cdclk_config->vco = intel_hpll_vco(display);
3980bb94e03SVille Syrjälä
3997ff89ca2SVille Syrjälä pci_read_config_word(pdev, GCFGC, &tmp);
400d34927acSVille Syrjälä
4017ff89ca2SVille Syrjälä cdclk_sel = (tmp >> 4) & 0x7;
4027ff89ca2SVille Syrjälä
4037ff89ca2SVille Syrjälä if (cdclk_sel >= ARRAY_SIZE(div_3200))
4047ff89ca2SVille Syrjälä goto fail;
4057ff89ca2SVille Syrjälä
4067ff89ca2SVille Syrjälä switch (cdclk_config->vco) {
4070bb94e03SVille Syrjälä case 3200000:
40849cd97a3SVille Syrjälä div_table = div_3200;
4097ff89ca2SVille Syrjälä break;
4100bb94e03SVille Syrjälä case 4000000:
41149cd97a3SVille Syrjälä div_table = div_4000;
4127ff89ca2SVille Syrjälä break;
4130bb94e03SVille Syrjälä case 4800000:
41449cd97a3SVille Syrjälä div_table = div_4800;
4157ff89ca2SVille Syrjälä break;
4160bb94e03SVille Syrjälä case 5333333:
41749cd97a3SVille Syrjälä div_table = div_5333;
4187ff89ca2SVille Syrjälä break;
419d34927acSVille Syrjälä default:
42023194610SWambui Karuga goto fail;
421df561f66SGustavo A. R. Silva }
4227ff89ca2SVille Syrjälä
4230bb94e03SVille Syrjälä cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco,
42449cd97a3SVille Syrjälä div_table[cdclk_sel]);
4257ff89ca2SVille Syrjälä return;
4260bb94e03SVille Syrjälä
42749cd97a3SVille Syrjälä fail:
4287ff89ca2SVille Syrjälä drm_err(display->drm,
4297ff89ca2SVille Syrjälä "Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%08x\n",
4307ff89ca2SVille Syrjälä cdclk_config->vco, tmp);
431d34927acSVille Syrjälä cdclk_config->cdclk = 190476;
4320bb94e03SVille Syrjälä }
4337ff89ca2SVille Syrjälä
pnv_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)434d34927acSVille Syrjälä static void pnv_get_cdclk(struct intel_display *display,
435cbe974fbSJani Nikula struct intel_cdclk_config *cdclk_config)
436cbe974fbSJani Nikula {
437cbe974fbSJani Nikula struct pci_dev *pdev = to_pci_dev(display->drm->dev);
438cbe974fbSJani Nikula u16 gcfgc = 0;
43949cd97a3SVille Syrjälä
440cbe974fbSJani Nikula pci_read_config_word(pdev, GCFGC, &gcfgc);
4417ff89ca2SVille Syrjälä
442d34927acSVille Syrjälä switch (gcfgc & GC_DISPLAY_CLOCK_MASK) {
44349cd97a3SVille Syrjälä case GC_DISPLAY_CLOCK_267_MHZ_PNV:
4447ff89ca2SVille Syrjälä cdclk_config->cdclk = 266667;
4457ff89ca2SVille Syrjälä break;
4467ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_333_MHZ_PNV:
4477ff89ca2SVille Syrjälä cdclk_config->cdclk = 333333;
4487ff89ca2SVille Syrjälä break;
4497ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_444_MHZ_PNV:
4507ff89ca2SVille Syrjälä cdclk_config->cdclk = 444444;
4510bb94e03SVille Syrjälä break;
4527ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_200_MHZ_PNV:
4537ff89ca2SVille Syrjälä cdclk_config->cdclk = 200000;
4547ff89ca2SVille Syrjälä break;
4557ff89ca2SVille Syrjälä default:
4567ff89ca2SVille Syrjälä drm_err(display->drm,
4577ff89ca2SVille Syrjälä "Unknown pnv display core clock 0x%04x\n", gcfgc);
4587ff89ca2SVille Syrjälä fallthrough;
4597ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_133_MHZ_PNV:
4607ff89ca2SVille Syrjälä cdclk_config->cdclk = 133333;
4617ff89ca2SVille Syrjälä break;
4627ff89ca2SVille Syrjälä case GC_DISPLAY_CLOCK_167_MHZ_PNV:
4637ff89ca2SVille Syrjälä cdclk_config->cdclk = 166667;
4647ff89ca2SVille Syrjälä break;
4650bb94e03SVille Syrjälä }
46649cd97a3SVille Syrjälä }
46749cd97a3SVille Syrjälä
i965gm_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)4687ff89ca2SVille Syrjälä static void i965gm_get_cdclk(struct intel_display *display,
4697ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
470d34927acSVille Syrjälä {
47123194610SWambui Karuga struct pci_dev *pdev = to_pci_dev(display->drm->dev);
4720bb94e03SVille Syrjälä static const u8 div_3200[] = { 16, 10, 8 };
4730bb94e03SVille Syrjälä static const u8 div_4000[] = { 20, 12, 10 };
4747ff89ca2SVille Syrjälä static const u8 div_5333[] = { 24, 16, 14 };
4757ff89ca2SVille Syrjälä const u8 *div_table;
476d34927acSVille Syrjälä unsigned int cdclk_sel;
4770bb94e03SVille Syrjälä u16 tmp = 0;
4787ff89ca2SVille Syrjälä
479d34927acSVille Syrjälä cdclk_config->vco = intel_hpll_vco(display);
48049cd97a3SVille Syrjälä
481cbe974fbSJani Nikula pci_read_config_word(pdev, GCFGC, &tmp);
4827ff89ca2SVille Syrjälä
483d34927acSVille Syrjälä cdclk_sel = ((tmp >> 8) & 0x1f) - 1;
48449cd97a3SVille Syrjälä
4857ff89ca2SVille Syrjälä if (cdclk_sel >= ARRAY_SIZE(div_3200))
4867ff89ca2SVille Syrjälä goto fail;
4877ff89ca2SVille Syrjälä
4887ff89ca2SVille Syrjälä switch (cdclk_config->vco) {
4890bb94e03SVille Syrjälä case 3200000:
4907ff89ca2SVille Syrjälä div_table = div_3200;
4917ff89ca2SVille Syrjälä break;
4927ff89ca2SVille Syrjälä case 4000000:
4930bb94e03SVille Syrjälä div_table = div_4000;
49449cd97a3SVille Syrjälä break;
4957ff89ca2SVille Syrjälä case 5333333:
4960bb94e03SVille Syrjälä div_table = div_5333;
49749cd97a3SVille Syrjälä break;
4987ff89ca2SVille Syrjälä default:
499d34927acSVille Syrjälä goto fail;
50023194610SWambui Karuga }
5010bb94e03SVille Syrjälä
5020bb94e03SVille Syrjälä cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco,
50349cd97a3SVille Syrjälä div_table[cdclk_sel]);
5047ff89ca2SVille Syrjälä return;
5057ff89ca2SVille Syrjälä
5067ff89ca2SVille Syrjälä fail:
507d34927acSVille Syrjälä drm_err(display->drm,
5080bb94e03SVille Syrjälä "Unable to determine CDCLK. HPLL VCO=%u kHz, CFGC=0x%04x\n",
5097ff89ca2SVille Syrjälä cdclk_config->vco, tmp);
510d34927acSVille Syrjälä cdclk_config->cdclk = 200000;
511cbe974fbSJani Nikula }
5127ff89ca2SVille Syrjälä
gm45_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)5137ff89ca2SVille Syrjälä static void gm45_get_cdclk(struct intel_display *display,
5140bb94e03SVille Syrjälä struct intel_cdclk_config *cdclk_config)
515d34927acSVille Syrjälä {
5160bb94e03SVille Syrjälä struct pci_dev *pdev = to_pci_dev(display->drm->dev);
5177ff89ca2SVille Syrjälä unsigned int cdclk_sel;
5180bb94e03SVille Syrjälä u16 tmp = 0;
519f0453266SJani Nikula
5200bb94e03SVille Syrjälä cdclk_config->vco = intel_hpll_vco(display);
5217ff89ca2SVille Syrjälä
5220bb94e03SVille Syrjälä pci_read_config_word(pdev, GCFGC, &tmp);
5237ff89ca2SVille Syrjälä
5247ff89ca2SVille Syrjälä cdclk_sel = (tmp >> 12) & 0x1;
525d34927acSVille Syrjälä
5267ff89ca2SVille Syrjälä switch (cdclk_config->vco) {
527d34927acSVille Syrjälä case 2666667:
5287ff89ca2SVille Syrjälä case 4000000:
5297ff89ca2SVille Syrjälä case 5333333:
5307ff89ca2SVille Syrjälä cdclk_config->cdclk = cdclk_sel ? 333333 : 222222;
5317ff89ca2SVille Syrjälä break;
5327ff89ca2SVille Syrjälä case 3200000:
5337ff89ca2SVille Syrjälä cdclk_config->cdclk = cdclk_sel ? 320000 : 228571;
5347ff89ca2SVille Syrjälä break;
5357ff89ca2SVille Syrjälä default:
536f0453266SJani Nikula drm_err(display->drm,
5377ff89ca2SVille Syrjälä "Unable to determine CDCLK. HPLL VCO=%u, CFGC=0x%04x\n",
538d305e061SVille Syrjälä cdclk_config->vco, tmp);
5397ff89ca2SVille Syrjälä cdclk_config->cdclk = 222222;
540d305e061SVille Syrjälä break;
5417ff89ca2SVille Syrjälä }
5427ff89ca2SVille Syrjälä }
5437ff89ca2SVille Syrjälä
hsw_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)5447ff89ca2SVille Syrjälä static void hsw_get_cdclk(struct intel_display *display,
5457ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
546d34927acSVille Syrjälä {
547999c5766SVille Syrjälä u32 lcpll = intel_de_read(display, LCPLL_CTL);
548d34927acSVille Syrjälä u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
549d34927acSVille Syrjälä
550f0453266SJani Nikula if (lcpll & LCPLL_CD_SOURCE_FCLK)
551999c5766SVille Syrjälä cdclk_config->cdclk = 800000;
552999c5766SVille Syrjälä else if (intel_de_read(display, FUSE_STRAP) & HSW_CDCLK_LIMIT)
553999c5766SVille Syrjälä cdclk_config->cdclk = 450000;
554999c5766SVille Syrjälä else if (freq == LCPLL_CLK_FREQ_450)
555999c5766SVille Syrjälä cdclk_config->cdclk = 450000;
556999c5766SVille Syrjälä else if (display->platform.haswell_ult)
557999c5766SVille Syrjälä cdclk_config->cdclk = 337500;
558999c5766SVille Syrjälä else
559999c5766SVille Syrjälä cdclk_config->cdclk = 540000;
560999c5766SVille Syrjälä }
561999c5766SVille Syrjälä
vlv_calc_cdclk(struct intel_display * display,int min_cdclk)562999c5766SVille Syrjälä static int vlv_calc_cdclk(struct intel_display *display, int min_cdclk)
563999c5766SVille Syrjälä {
564999c5766SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(display->drm);
565999c5766SVille Syrjälä int freq_320 = (dev_priv->hpll_freq << 1) % 320000 != 0 ?
566999c5766SVille Syrjälä 333333 : 320000;
567d34927acSVille Syrjälä
5680bb94e03SVille Syrjälä /*
5697ff89ca2SVille Syrjälä * We seem to get an unstable or solid color picture at 200MHz.
570d34927acSVille Syrjälä * Not sure what's wrong. For now use 200MHz only when all pipes
571999c5766SVille Syrjälä * are off.
572999c5766SVille Syrjälä */
573337fa6e0SChris Wilson if (display->platform.valleyview && min_cdclk > freq_320)
574337fa6e0SChris Wilson return 400000;
575337fa6e0SChris Wilson else if (min_cdclk > 266667)
5760bb94e03SVille Syrjälä return freq_320;
5770bb94e03SVille Syrjälä else if (min_cdclk > 0)
57849cd97a3SVille Syrjälä return 266667;
5790bb94e03SVille Syrjälä else
580999c5766SVille Syrjälä return 200000;
581c11b813fSVille Syrjälä }
582337fa6e0SChris Wilson
vlv_calc_voltage_level(struct intel_display * display,int cdclk)583337fa6e0SChris Wilson static u8 vlv_calc_voltage_level(struct intel_display *display, int cdclk)
584337fa6e0SChris Wilson {
585999c5766SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(display->drm);
586f0453266SJani Nikula
5870bb94e03SVille Syrjälä if (display->platform.valleyview) {
588999c5766SVille Syrjälä if (cdclk >= 320000) /* jump to highest voltage for 400MHz too */
589999c5766SVille Syrjälä return 2;
5900bb94e03SVille Syrjälä else if (cdclk >= 266667)
591999c5766SVille Syrjälä return 1;
5927ff89ca2SVille Syrjälä else
5937ff89ca2SVille Syrjälä return 0;
594d34927acSVille Syrjälä } else {
5957ff89ca2SVille Syrjälä /*
596d34927acSVille Syrjälä * Specs are full of misinformation, but testing on actual
5977ff89ca2SVille Syrjälä * hardware has shown that we just need to write the desired
5987ff89ca2SVille Syrjälä * CCK divider into the Punit register.
599f0453266SJani Nikula */
6007ff89ca2SVille Syrjälä return DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1, cdclk) - 1;
6017ff89ca2SVille Syrjälä }
6027ff89ca2SVille Syrjälä }
6037ff89ca2SVille Syrjälä
vlv_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)604d34927acSVille Syrjälä static void vlv_get_cdclk(struct intel_display *display,
6057ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
606f0453266SJani Nikula {
6077ff89ca2SVille Syrjälä u32 val;
6087ff89ca2SVille Syrjälä
6097ff89ca2SVille Syrjälä vlv_iosf_sb_get(display->drm, BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
6107ff89ca2SVille Syrjälä
6117ff89ca2SVille Syrjälä cdclk_config->vco = vlv_get_hpll_vco(display->drm);
6127ff89ca2SVille Syrjälä cdclk_config->cdclk = vlv_get_cck_clock(display->drm, "cdclk",
6137ff89ca2SVille Syrjälä CCK_DISPLAY_CLOCK_CONTROL,
6147ff89ca2SVille Syrjälä cdclk_config->vco);
6157ff89ca2SVille Syrjälä
6167ff89ca2SVille Syrjälä val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
6177ff89ca2SVille Syrjälä
618d34927acSVille Syrjälä vlv_iosf_sb_put(display->drm,
6193e9f55dfSJani Nikula BIT(VLV_IOSF_SB_CCK) | BIT(VLV_IOSF_SB_PUNIT));
6207ff89ca2SVille Syrjälä
621d34927acSVille Syrjälä if (display->platform.valleyview)
6223e9f55dfSJani Nikula cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK) >>
6237ff89ca2SVille Syrjälä DSPFREQGUAR_SHIFT;
6247ff89ca2SVille Syrjälä else
6257ff89ca2SVille Syrjälä cdclk_config->voltage_level = (val & DSPFREQGUAR_MASK_CHV) >>
6267ff89ca2SVille Syrjälä DSPFREQGUAR_SHIFT_CHV;
6277ff89ca2SVille Syrjälä }
628d34927acSVille Syrjälä
vlv_program_pfi_credits(struct intel_display * display)629d34927acSVille Syrjälä static void vlv_program_pfi_credits(struct intel_display *display)
6307ff89ca2SVille Syrjälä {
6317ff89ca2SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(display->drm);
632d34927acSVille Syrjälä unsigned int credits, default_credits;
6330bb94e03SVille Syrjälä
63459f9e9caSVille Syrjälä if (display->platform.cherryview)
6357ff89ca2SVille Syrjälä default_credits = PFI_CREDIT(12);
636d34927acSVille Syrjälä else
6370bb94e03SVille Syrjälä default_credits = PFI_CREDIT(8);
6380bb94e03SVille Syrjälä
6390e6e0be4SChris Wilson if (display->cdclk.hw.cdclk >= dev_priv->czclk_freq) {
6407ff89ca2SVille Syrjälä /* CHV suggested value is 31 or 63 */
6410c9f353fSVille Syrjälä if (display->platform.cherryview)
6420c9f353fSVille Syrjälä credits = PFI_CREDIT_63;
6430c9f353fSVille Syrjälä else
6440c9f353fSVille Syrjälä credits = PFI_CREDIT(15);
6450c9f353fSVille Syrjälä } else {
6460c9f353fSVille Syrjälä credits = default_credits;
6470c9f353fSVille Syrjälä }
6480c9f353fSVille Syrjälä
6490c9f353fSVille Syrjälä /*
6500c9f353fSVille Syrjälä * WA - write default credits before re-programming
6510c9f353fSVille Syrjälä * FIXME: should we also set the resend bit here?
6520c9f353fSVille Syrjälä */
653886015a0SGabriel Krisman Bertazi intel_de_write(display, GCI_CONTROL,
654886015a0SGabriel Krisman Bertazi VGA_FAST_MODE_DISABLE | default_credits);
655886015a0SGabriel Krisman Bertazi
65613ce6092SVille Syrjälä intel_de_write(display, GCI_CONTROL,
657886015a0SGabriel Krisman Bertazi VGA_FAST_MODE_DISABLE | credits | PFI_CREDIT_RESEND);
658886015a0SGabriel Krisman Bertazi
6595dcfda5cSVille Syrjälä /*
660886015a0SGabriel Krisman Bertazi * FIXME is this guaranteed to clear
661337fa6e0SChris Wilson * immediately or should we poll for it?
662337fa6e0SChris Wilson */
663337fa6e0SChris Wilson drm_WARN_ON(display->drm,
664337fa6e0SChris Wilson intel_de_read(display, GCI_CONTROL) & PFI_CREDIT_RESEND);
665337fa6e0SChris Wilson }
666c11b813fSVille Syrjälä
vlv_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)6677ff89ca2SVille Syrjälä static void vlv_set_cdclk(struct intel_display *display,
6687ff89ca2SVille Syrjälä const struct intel_cdclk_config *cdclk_config,
669c11b813fSVille Syrjälä enum pipe pipe)
670c11b813fSVille Syrjälä {
6717ff89ca2SVille Syrjälä struct drm_i915_private *dev_priv = to_i915(display->drm);
6727ff89ca2SVille Syrjälä int cdclk = cdclk_config->cdclk;
673d34927acSVille Syrjälä u32 val, cmd = cdclk_config->voltage_level;
67423194610SWambui Karuga intel_wakeref_t wakeref;
6757ff89ca2SVille Syrjälä
6767ff89ca2SVille Syrjälä switch (cdclk) {
6777ff89ca2SVille Syrjälä case 400000:
6787ff89ca2SVille Syrjälä case 333333:
6797ff89ca2SVille Syrjälä case 320000:
6807ff89ca2SVille Syrjälä case 266667:
6817ff89ca2SVille Syrjälä case 200000:
6827ff89ca2SVille Syrjälä break;
6837ff89ca2SVille Syrjälä default:
6847ff89ca2SVille Syrjälä MISSING_CASE(cdclk);
6857ff89ca2SVille Syrjälä return;
6867ff89ca2SVille Syrjälä }
6877ff89ca2SVille Syrjälä
6887ff89ca2SVille Syrjälä /* There are cases where we can end up here with power domains
6897ff89ca2SVille Syrjälä * off and a CDCLK frequency other than the minimum, like when
6907ff89ca2SVille Syrjälä * issuing a modeset without actually changing any display after
6917ff89ca2SVille Syrjälä * a system suspend. So grab the display core domain, which covers
692d34927acSVille Syrjälä * the HW blocks needed for the following programming.
69323194610SWambui Karuga */
6947ff89ca2SVille Syrjälä wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
6957ff89ca2SVille Syrjälä
6967ff89ca2SVille Syrjälä vlv_iosf_sb_get(display->drm,
6977ff89ca2SVille Syrjälä BIT(VLV_IOSF_SB_CCK) |
6987ff89ca2SVille Syrjälä BIT(VLV_IOSF_SB_BUNIT) |
6997ff89ca2SVille Syrjälä BIT(VLV_IOSF_SB_PUNIT));
7007ff89ca2SVille Syrjälä
7017ff89ca2SVille Syrjälä val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
7027ff89ca2SVille Syrjälä val &= ~DSPFREQGUAR_MASK;
7037ff89ca2SVille Syrjälä val |= (cmd << DSPFREQGUAR_SHIFT);
7047ff89ca2SVille Syrjälä vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
7057ff89ca2SVille Syrjälä if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) &
7067ff89ca2SVille Syrjälä DSPFREQSTAT_MASK) == (cmd << DSPFREQSTAT_SHIFT),
7077ff89ca2SVille Syrjälä 50)) {
7087ff89ca2SVille Syrjälä drm_err(display->drm,
7097ff89ca2SVille Syrjälä "timed out waiting for CDclk change\n");
710221c7862SChris Wilson }
711337fa6e0SChris Wilson
712337fa6e0SChris Wilson if (cdclk == 400000) {
713337fa6e0SChris Wilson u32 divider;
7147ff89ca2SVille Syrjälä
715d34927acSVille Syrjälä divider = DIV_ROUND_CLOSEST(dev_priv->hpll_freq << 1,
7161a5301a5SVille Syrjälä cdclk) - 1;
717d34927acSVille Syrjälä
718886015a0SGabriel Krisman Bertazi /* adjust cdclk divider */
7195dcfda5cSVille Syrjälä val = vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL);
7207ff89ca2SVille Syrjälä val &= ~CCK_FREQUENCY_VALUES;
7217ff89ca2SVille Syrjälä val |= divider;
722d34927acSVille Syrjälä vlv_cck_write(display->drm, CCK_DISPLAY_CLOCK_CONTROL, val);
7230bb94e03SVille Syrjälä
72459f9e9caSVille Syrjälä if (wait_for((vlv_cck_read(display->drm, CCK_DISPLAY_CLOCK_CONTROL) &
7257ff89ca2SVille Syrjälä CCK_FREQUENCY_STATUS) == (divider << CCK_FREQUENCY_STATUS_SHIFT),
726d34927acSVille Syrjälä 50))
7270bb94e03SVille Syrjälä drm_err(display->drm,
7280bb94e03SVille Syrjälä "timed out waiting for CDclk change\n");
7290e6e0be4SChris Wilson }
7307ff89ca2SVille Syrjälä
7317ff89ca2SVille Syrjälä /* adjust self-refresh exit latency value */
7327ff89ca2SVille Syrjälä val = vlv_bunit_read(display->drm, BUNIT_REG_BISOC);
7337ff89ca2SVille Syrjälä val &= ~0x7f;
7347ff89ca2SVille Syrjälä
7357ff89ca2SVille Syrjälä /*
7367ff89ca2SVille Syrjälä * For high bandwidth configs, we set a higher latency in the bunit
7377ff89ca2SVille Syrjälä * so that the core display fetch happens in time to avoid underruns.
7387ff89ca2SVille Syrjälä */
7397ff89ca2SVille Syrjälä if (cdclk == 400000)
7407ff89ca2SVille Syrjälä val |= 4500 / 250; /* 4.5 usec */
7417ff89ca2SVille Syrjälä else
742886015a0SGabriel Krisman Bertazi val |= 3000 / 250; /* 3.0 usec */
743886015a0SGabriel Krisman Bertazi vlv_bunit_write(display->drm, BUNIT_REG_BISOC, val);
744886015a0SGabriel Krisman Bertazi
74513ce6092SVille Syrjälä vlv_iosf_sb_put(display->drm,
746886015a0SGabriel Krisman Bertazi BIT(VLV_IOSF_SB_CCK) |
747886015a0SGabriel Krisman Bertazi BIT(VLV_IOSF_SB_BUNIT) |
7485dcfda5cSVille Syrjälä BIT(VLV_IOSF_SB_PUNIT));
749886015a0SGabriel Krisman Bertazi
750337fa6e0SChris Wilson intel_update_cdclk(display);
751c11b813fSVille Syrjälä
7527ff89ca2SVille Syrjälä vlv_program_pfi_credits(display);
7537ff89ca2SVille Syrjälä
754c11b813fSVille Syrjälä intel_display_power_put(display, POWER_DOMAIN_DISPLAY_CORE, wakeref);
755c11b813fSVille Syrjälä }
7567ff89ca2SVille Syrjälä
chv_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)7577ff89ca2SVille Syrjälä static void chv_set_cdclk(struct intel_display *display,
758d34927acSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
75923194610SWambui Karuga enum pipe pipe)
7607ff89ca2SVille Syrjälä {
761337fa6e0SChris Wilson int cdclk = cdclk_config->cdclk;
762337fa6e0SChris Wilson u32 val, cmd = cdclk_config->voltage_level;
7637ff89ca2SVille Syrjälä intel_wakeref_t wakeref;
764d34927acSVille Syrjälä
7651a5301a5SVille Syrjälä switch (cdclk) {
766d34927acSVille Syrjälä case 333333:
767886015a0SGabriel Krisman Bertazi case 320000:
7685dcfda5cSVille Syrjälä case 266667:
7697ff89ca2SVille Syrjälä case 200000:
7707ff89ca2SVille Syrjälä break;
771d305e061SVille Syrjälä default:
7727ff89ca2SVille Syrjälä MISSING_CASE(cdclk);
773d305e061SVille Syrjälä return;
7747ff89ca2SVille Syrjälä }
775d305e061SVille Syrjälä
7767ff89ca2SVille Syrjälä /* There are cases where we can end up here with power domains
777d305e061SVille Syrjälä * off and a CDCLK frequency other than the minimum, like when
7787ff89ca2SVille Syrjälä * issuing a modeset without actually changing any display after
7797ff89ca2SVille Syrjälä * a system suspend. So grab the display core domain, which covers
7807ff89ca2SVille Syrjälä * the HW blocks needed for the following programming.
7817ff89ca2SVille Syrjälä */
7827ff89ca2SVille Syrjälä wakeref = intel_display_power_get(display, POWER_DOMAIN_DISPLAY_CORE);
783d7ffaeefSVille Syrjälä
784d7ffaeefSVille Syrjälä vlv_punit_get(display->drm);
785d7ffaeefSVille Syrjälä val = vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM);
786d7ffaeefSVille Syrjälä val &= ~DSPFREQGUAR_MASK_CHV;
787d7ffaeefSVille Syrjälä val |= (cmd << DSPFREQGUAR_SHIFT_CHV);
788d7ffaeefSVille Syrjälä vlv_punit_write(display->drm, PUNIT_REG_DSPSSPM, val);
789d7ffaeefSVille Syrjälä if (wait_for((vlv_punit_read(display->drm, PUNIT_REG_DSPSSPM) &
790d7ffaeefSVille Syrjälä DSPFREQSTAT_MASK_CHV) == (cmd << DSPFREQSTAT_SHIFT_CHV),
791d7ffaeefSVille Syrjälä 50)) {
792d7ffaeefSVille Syrjälä drm_err(display->drm,
793d7ffaeefSVille Syrjälä "timed out waiting for CDclk change\n");
794d7ffaeefSVille Syrjälä }
795d7ffaeefSVille Syrjälä
796d7ffaeefSVille Syrjälä vlv_punit_put(display->drm);
797d7ffaeefSVille Syrjälä
798d34927acSVille Syrjälä intel_update_cdclk(display);
7990bb94e03SVille Syrjälä
8007ff89ca2SVille Syrjälä vlv_program_pfi_credits(display);
801d34927acSVille Syrjälä
802cbe974fbSJani Nikula intel_display_power_put(display, POWER_DOMAIN_DISPLAY_CORE, wakeref);
8037ff89ca2SVille Syrjälä }
8047ff89ca2SVille Syrjälä
bdw_calc_cdclk(int min_cdclk)8050bb94e03SVille Syrjälä static int bdw_calc_cdclk(int min_cdclk)
806d34927acSVille Syrjälä {
8070bb94e03SVille Syrjälä if (min_cdclk > 540000)
8087ff89ca2SVille Syrjälä return 675000;
8090bb94e03SVille Syrjälä else if (min_cdclk > 450000)
8107ff89ca2SVille Syrjälä return 540000;
8110bb94e03SVille Syrjälä else if (min_cdclk > 337500)
8127ff89ca2SVille Syrjälä return 450000;
8130bb94e03SVille Syrjälä else
8147ff89ca2SVille Syrjälä return 337500;
8150bb94e03SVille Syrjälä }
816d7ffaeefSVille Syrjälä
bdw_calc_voltage_level(int cdclk)817d7ffaeefSVille Syrjälä static u8 bdw_calc_voltage_level(int cdclk)
818d7ffaeefSVille Syrjälä {
819d7ffaeefSVille Syrjälä switch (cdclk) {
820d7ffaeefSVille Syrjälä default:
8210bb94e03SVille Syrjälä case 337500:
8220bb94e03SVille Syrjälä return 2;
8237ff89ca2SVille Syrjälä case 450000:
8247ff89ca2SVille Syrjälä return 0;
825b41df85aSVille Syrjälä case 540000:
826b41df85aSVille Syrjälä return 1;
827b41df85aSVille Syrjälä case 675000:
828b41df85aSVille Syrjälä return 3;
829b41df85aSVille Syrjälä }
830b41df85aSVille Syrjälä }
831b41df85aSVille Syrjälä
bdw_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)832b41df85aSVille Syrjälä static void bdw_get_cdclk(struct intel_display *display,
833b41df85aSVille Syrjälä struct intel_cdclk_config *cdclk_config)
834b41df85aSVille Syrjälä {
835b41df85aSVille Syrjälä u32 lcpll = intel_de_read(display, LCPLL_CTL);
836b41df85aSVille Syrjälä u32 freq = lcpll & LCPLL_CLK_FREQ_MASK;
837b41df85aSVille Syrjälä
838b41df85aSVille Syrjälä if (lcpll & LCPLL_CD_SOURCE_FCLK)
839b41df85aSVille Syrjälä cdclk_config->cdclk = 800000;
840b41df85aSVille Syrjälä else if (intel_de_read(display, FUSE_STRAP) & HSW_CDCLK_LIMIT)
841b41df85aSVille Syrjälä cdclk_config->cdclk = 450000;
842d34927acSVille Syrjälä else if (freq == LCPLL_CLK_FREQ_450)
8430bb94e03SVille Syrjälä cdclk_config->cdclk = 450000;
84459f9e9caSVille Syrjälä else if (freq == LCPLL_CLK_FREQ_54O_BDW)
8457ff89ca2SVille Syrjälä cdclk_config->cdclk = 540000;
846d34927acSVille Syrjälä else if (freq == LCPLL_CLK_FREQ_337_5_BDW)
8470bb94e03SVille Syrjälä cdclk_config->cdclk = 337500;
8487ff89ca2SVille Syrjälä else
8497ff89ca2SVille Syrjälä cdclk_config->cdclk = 675000;
850d34927acSVille Syrjälä
851d34927acSVille Syrjälä /*
8527ff89ca2SVille Syrjälä * Can't read this out :( Let's assume it's
8537ff89ca2SVille Syrjälä * at least what the CDCLK frequency requires.
8547ff89ca2SVille Syrjälä */
8557ff89ca2SVille Syrjälä cdclk_config->voltage_level =
8567ff89ca2SVille Syrjälä bdw_calc_voltage_level(cdclk_config->cdclk);
8577ff89ca2SVille Syrjälä }
8587ff89ca2SVille Syrjälä
bdw_cdclk_freq_sel(int cdclk)859ee421bb4SAshutosh Dixit static u32 bdw_cdclk_freq_sel(int cdclk)
8607ff89ca2SVille Syrjälä {
861d34927acSVille Syrjälä switch (cdclk) {
86223194610SWambui Karuga default:
8637ff89ca2SVille Syrjälä MISSING_CASE(cdclk);
8647ff89ca2SVille Syrjälä fallthrough;
8657ff89ca2SVille Syrjälä case 337500:
866d34927acSVille Syrjälä return LCPLL_CLK_FREQ_337_5_BDW;
867fb12fbb1SVille Syrjälä case 450000:
8687ff89ca2SVille Syrjälä return LCPLL_CLK_FREQ_450;
8693164888aSMarta Lofstedt case 540000:
8703164888aSMarta Lofstedt return LCPLL_CLK_FREQ_54O_BDW;
8713164888aSMarta Lofstedt case 675000:
8723164888aSMarta Lofstedt return LCPLL_CLK_FREQ_675_BDW;
873d34927acSVille Syrjälä }
8743164888aSMarta Lofstedt }
875d34927acSVille Syrjälä
bdw_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)8767ff89ca2SVille Syrjälä static void bdw_set_cdclk(struct intel_display *display,
877d34927acSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
878fb12fbb1SVille Syrjälä enum pipe pipe)
8797ff89ca2SVille Syrjälä {
880d34927acSVille Syrjälä int cdclk = cdclk_config->cdclk;
881fb12fbb1SVille Syrjälä int ret;
8827ff89ca2SVille Syrjälä
883d34927acSVille Syrjälä if (drm_WARN(display->drm,
8847ff89ca2SVille Syrjälä (intel_de_read(display, LCPLL_CTL) &
885d34927acSVille Syrjälä (LCPLL_PLL_DISABLE | LCPLL_PLL_LOCK |
8867ff89ca2SVille Syrjälä LCPLL_CD_CLOCK_DISABLE | LCPLL_ROOT_CD_CLOCK_DISABLE |
887ee421bb4SAshutosh Dixit LCPLL_CD2X_CLOCK_DISABLE | LCPLL_POWER_DOWN_ALLOW |
8880bb94e03SVille Syrjälä LCPLL_CD_SOURCE_FCLK)) != LCPLL_PLL_LOCK,
8897ff89ca2SVille Syrjälä "trying to change cdclk frequency with cdclk not enabled\n"))
890d34927acSVille Syrjälä return;
8913e9f55dfSJani Nikula
8927ff89ca2SVille Syrjälä ret = intel_pcode_write(display->drm, BDW_PCODE_DISPLAY_FREQ_CHANGE_REQ, 0x0);
893d34927acSVille Syrjälä if (ret) {
8947ff89ca2SVille Syrjälä drm_err(display->drm,
8957ff89ca2SVille Syrjälä "failed to inform pcode about cdclk change\n");
896d305e061SVille Syrjälä return;
8977ff89ca2SVille Syrjälä }
8987ff89ca2SVille Syrjälä
899d305e061SVille Syrjälä intel_de_rmw(display, LCPLL_CTL,
9007ff89ca2SVille Syrjälä 0, LCPLL_CD_SOURCE_FCLK);
901d305e061SVille Syrjälä
9027ff89ca2SVille Syrjälä /*
903d305e061SVille Syrjälä * According to the spec, it should be enough to poll for this 1 us.
9047ff89ca2SVille Syrjälä * However, extensive testing shows that this can take longer.
9057ff89ca2SVille Syrjälä */
9067ff89ca2SVille Syrjälä if (wait_for_us(intel_de_read(display, LCPLL_CTL) &
9077ff89ca2SVille Syrjälä LCPLL_CD_SOURCE_FCLK_DONE, 100))
908d305e061SVille Syrjälä drm_err(display->drm, "Switching to FCLK failed\n");
9097ff89ca2SVille Syrjälä
910d305e061SVille Syrjälä intel_de_rmw(display, LCPLL_CTL,
9117ff89ca2SVille Syrjälä LCPLL_CLK_FREQ_MASK, bdw_cdclk_freq_sel(cdclk));
912d305e061SVille Syrjälä
9137ff89ca2SVille Syrjälä intel_de_rmw(display, LCPLL_CTL,
9147ff89ca2SVille Syrjälä LCPLL_CD_SOURCE_FCLK, 0);
9157ff89ca2SVille Syrjälä
9167ff89ca2SVille Syrjälä if (wait_for_us((intel_de_read(display, LCPLL_CTL) &
9177ff89ca2SVille Syrjälä LCPLL_CD_SOURCE_FCLK_DONE) == 0, 1))
9187ff89ca2SVille Syrjälä drm_err(display->drm, "Switching back to LCPLL failed\n");
9192aa97491SVille Syrjälä
9202aa97491SVille Syrjälä intel_pcode_write(display->drm, HSW_PCODE_DE_WRITE_FREQ_REQ,
921522d47cfSLucas De Marchi cdclk_config->voltage_level);
9222aa97491SVille Syrjälä
923522d47cfSLucas De Marchi intel_de_write(display, CDCLK_FREQ,
924522d47cfSLucas De Marchi DIV_ROUND_CLOSEST(cdclk, 1000) - 1);
925522d47cfSLucas De Marchi
926522d47cfSLucas De Marchi intel_update_cdclk(display);
927522d47cfSLucas De Marchi }
928522d47cfSLucas De Marchi
skl_calc_cdclk(int min_cdclk,int vco)9292aa97491SVille Syrjälä static int skl_calc_cdclk(int min_cdclk, int vco)
9302aa97491SVille Syrjälä {
931d34927acSVille Syrjälä if (vco == 8640000) {
9320bb94e03SVille Syrjälä if (min_cdclk > 540000)
9337ff89ca2SVille Syrjälä return 617143;
9347ff89ca2SVille Syrjälä else if (min_cdclk > 432000)
9357ff89ca2SVille Syrjälä return 540000;
9360bb94e03SVille Syrjälä else if (min_cdclk > 308571)
9370bb94e03SVille Syrjälä return 432000;
9387ff89ca2SVille Syrjälä else
939d34927acSVille Syrjälä return 308571;
9407ff89ca2SVille Syrjälä } else {
9417ff89ca2SVille Syrjälä if (min_cdclk > 540000)
9427ff89ca2SVille Syrjälä return 675000;
943d34927acSVille Syrjälä else if (min_cdclk > 450000)
9447ff89ca2SVille Syrjälä return 540000;
9457ff89ca2SVille Syrjälä else if (min_cdclk > 337500)
946d34927acSVille Syrjälä return 450000;
9477ff89ca2SVille Syrjälä else
948d34927acSVille Syrjälä return 337500;
949aff35110SPankaj Bharadiya }
9507ff89ca2SVille Syrjälä }
9517ff89ca2SVille Syrjälä
skl_calc_voltage_level(int cdclk)9527ff89ca2SVille Syrjälä static u8 skl_calc_voltage_level(int cdclk)
9537ff89ca2SVille Syrjälä {
9547ff89ca2SVille Syrjälä if (cdclk > 540000)
9557ff89ca2SVille Syrjälä return 3;
9567ff89ca2SVille Syrjälä else if (cdclk > 450000)
9577ff89ca2SVille Syrjälä return 2;
9587ff89ca2SVille Syrjälä else if (cdclk > 337500)
9597ff89ca2SVille Syrjälä return 1;
9600bb94e03SVille Syrjälä else
9617ff89ca2SVille Syrjälä return 0;
9627ff89ca2SVille Syrjälä }
9637ff89ca2SVille Syrjälä
skl_dpll0_update(struct intel_display * display,struct intel_cdclk_config * cdclk_config)9640bb94e03SVille Syrjälä static void skl_dpll0_update(struct intel_display *display,
9657ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
9667ff89ca2SVille Syrjälä {
9677ff89ca2SVille Syrjälä u32 val;
9687ff89ca2SVille Syrjälä
9697ff89ca2SVille Syrjälä cdclk_config->ref = 24000;
9707ff89ca2SVille Syrjälä cdclk_config->vco = 0;
9717ff89ca2SVille Syrjälä
972d34927acSVille Syrjälä val = intel_de_read(display, LCPLL1_CTL);
9730bb94e03SVille Syrjälä if ((val & LCPLL_PLL_ENABLE) == 0)
9747ff89ca2SVille Syrjälä return;
9757ff89ca2SVille Syrjälä
9767ff89ca2SVille Syrjälä if (drm_WARN_ON(display->drm, (val & LCPLL_PLL_LOCK) == 0))
977d34927acSVille Syrjälä return;
9787ff89ca2SVille Syrjälä
9790bb94e03SVille Syrjälä val = intel_de_read(display, DPLL_CTRL1);
98049cd97a3SVille Syrjälä
9810bb94e03SVille Syrjälä if (drm_WARN_ON(display->drm,
9822aa97491SVille Syrjälä (val & (DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
9837ff89ca2SVille Syrjälä DPLL_CTRL1_SSC(SKL_DPLL0) |
984d34927acSVille Syrjälä DPLL_CTRL1_OVERRIDE(SKL_DPLL0))) !=
9857ff89ca2SVille Syrjälä DPLL_CTRL1_OVERRIDE(SKL_DPLL0)))
9860bb94e03SVille Syrjälä return;
9877ff89ca2SVille Syrjälä
9887ff89ca2SVille Syrjälä switch (val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0)) {
9890bb94e03SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0):
99049cd97a3SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1350, SKL_DPLL0):
9917ff89ca2SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1620, SKL_DPLL0):
9920bb94e03SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2700, SKL_DPLL0):
99349cd97a3SVille Syrjälä cdclk_config->vco = 8100000;
9947ff89ca2SVille Syrjälä break;
9950bb94e03SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0):
99649cd97a3SVille Syrjälä case DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_2160, SKL_DPLL0):
9977ff89ca2SVille Syrjälä cdclk_config->vco = 8640000;
9980bb94e03SVille Syrjälä break;
99949cd97a3SVille Syrjälä default:
10007ff89ca2SVille Syrjälä MISSING_CASE(val & DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0));
10017ff89ca2SVille Syrjälä break;
100249cd97a3SVille Syrjälä }
10037ff89ca2SVille Syrjälä }
10047ff89ca2SVille Syrjälä
skl_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)10057ff89ca2SVille Syrjälä static void skl_get_cdclk(struct intel_display *display,
10067ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
10070bb94e03SVille Syrjälä {
100849cd97a3SVille Syrjälä u32 cdctl;
10097ff89ca2SVille Syrjälä
10100bb94e03SVille Syrjälä skl_dpll0_update(display, cdclk_config);
101149cd97a3SVille Syrjälä
10127ff89ca2SVille Syrjälä cdclk_config->cdclk = cdclk_config->bypass = cdclk_config->ref;
10130bb94e03SVille Syrjälä
101449cd97a3SVille Syrjälä if (cdclk_config->vco == 0)
10157ff89ca2SVille Syrjälä goto out;
10160bb94e03SVille Syrjälä
101749cd97a3SVille Syrjälä cdctl = intel_de_read(display, CDCLK_CTL);
10187ff89ca2SVille Syrjälä
10197ff89ca2SVille Syrjälä if (cdclk_config->vco == 8640000) {
102049cd97a3SVille Syrjälä switch (cdctl & CDCLK_FREQ_SEL_MASK) {
10217ff89ca2SVille Syrjälä case CDCLK_FREQ_450_432:
10227ff89ca2SVille Syrjälä cdclk_config->cdclk = 432000;
10232aa97491SVille Syrjälä break;
10242aa97491SVille Syrjälä case CDCLK_FREQ_337_308:
10252aa97491SVille Syrjälä cdclk_config->cdclk = 308571;
10262aa97491SVille Syrjälä break;
10272aa97491SVille Syrjälä case CDCLK_FREQ_540:
10282aa97491SVille Syrjälä cdclk_config->cdclk = 540000;
10290bb94e03SVille Syrjälä break;
10300bb94e03SVille Syrjälä case CDCLK_FREQ_675_617:
10317ff89ca2SVille Syrjälä cdclk_config->cdclk = 617143;
10327ff89ca2SVille Syrjälä break;
10337ff89ca2SVille Syrjälä default:
10347ff89ca2SVille Syrjälä MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
10357ff89ca2SVille Syrjälä break;
10367ff89ca2SVille Syrjälä }
10377ff89ca2SVille Syrjälä } else {
10387ff89ca2SVille Syrjälä switch (cdctl & CDCLK_FREQ_SEL_MASK) {
1039d34927acSVille Syrjälä case CDCLK_FREQ_450_432:
10407ff89ca2SVille Syrjälä cdclk_config->cdclk = 450000;
1041d34927acSVille Syrjälä break;
10427ff89ca2SVille Syrjälä case CDCLK_FREQ_337_308:
1043d34927acSVille Syrjälä cdclk_config->cdclk = 337500;
10447ff89ca2SVille Syrjälä break;
10457ff89ca2SVille Syrjälä case CDCLK_FREQ_540:
1046d34927acSVille Syrjälä cdclk_config->cdclk = 540000;
10477ff89ca2SVille Syrjälä break;
10487ff89ca2SVille Syrjälä case CDCLK_FREQ_675_617:
1049d34927acSVille Syrjälä cdclk_config->cdclk = 675000;
10507ff89ca2SVille Syrjälä break;
1051d34927acSVille Syrjälä default:
10527ff89ca2SVille Syrjälä MISSING_CASE(cdctl & CDCLK_FREQ_SEL_MASK);
10537ff89ca2SVille Syrjälä break;
10547ff89ca2SVille Syrjälä }
10557ff89ca2SVille Syrjälä }
10567ff89ca2SVille Syrjälä
10577ff89ca2SVille Syrjälä out:
10587ff89ca2SVille Syrjälä /*
10597ff89ca2SVille Syrjälä * Can't read this out :( Let's assume it's
10607ff89ca2SVille Syrjälä * at least what the CDCLK frequency requires.
10617ff89ca2SVille Syrjälä */
1062b41df85aSVille Syrjälä cdclk_config->voltage_level =
1063b41df85aSVille Syrjälä skl_calc_voltage_level(cdclk_config->cdclk);
1064b41df85aSVille Syrjälä }
1065b41df85aSVille Syrjälä
1066b41df85aSVille Syrjälä /* convert from kHz to .1 fixpoint MHz with -1MHz offset */
skl_cdclk_decimal(int cdclk)1067b41df85aSVille Syrjälä static int skl_cdclk_decimal(int cdclk)
1068d34927acSVille Syrjälä {
1069b41df85aSVille Syrjälä return DIV_ROUND_CLOSEST(cdclk - 1000, 500);
1070d34927acSVille Syrjälä }
10713b71a9b6SVille Syrjälä
skl_set_preferred_cdclk_vco(struct intel_display * display,int vco)10723b71a9b6SVille Syrjälä static void skl_set_preferred_cdclk_vco(struct intel_display *display, int vco)
10733b71a9b6SVille Syrjälä {
10743b71a9b6SVille Syrjälä bool changed = display->cdclk.skl_preferred_vco_freq != vco;
1075d34927acSVille Syrjälä
1076d34927acSVille Syrjälä display->cdclk.skl_preferred_vco_freq = vco;
10777ff89ca2SVille Syrjälä
1078d34927acSVille Syrjälä if (changed)
10793b71a9b6SVille Syrjälä intel_update_max_cdclk(display);
10807ff89ca2SVille Syrjälä }
1081d34927acSVille Syrjälä
skl_dpll0_link_rate(struct intel_display * display,int vco)1082d34927acSVille Syrjälä static u32 skl_dpll0_link_rate(struct intel_display *display, int vco)
10837ff89ca2SVille Syrjälä {
1084d34927acSVille Syrjälä drm_WARN_ON(display->drm, vco != 8100000 && vco != 8640000);
10857ff89ca2SVille Syrjälä
10867ff89ca2SVille Syrjälä /*
1087d34927acSVille Syrjälä * We always enable DPLL0 with the lowest link rate possible, but still
10887ff89ca2SVille Syrjälä * taking into account the VCO required to operate the eDP panel at the
10897ff89ca2SVille Syrjälä * desired frequency. The usual DP link rates operate with a VCO of
1090d34927acSVille Syrjälä * 8100 while the eDP 1.4 alternate link rates need a VCO of 8640.
10917ff89ca2SVille Syrjälä * The modeset code is responsible for the selection of the exact link
1092d34927acSVille Syrjälä * rate later on, with the constraint of choosing a frequency that
10933b71a9b6SVille Syrjälä * works with vco.
10943b71a9b6SVille Syrjälä */
1095d34927acSVille Syrjälä if (vco == 8640000)
1096d34927acSVille Syrjälä return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_1080, SKL_DPLL0);
10977ff89ca2SVille Syrjälä else
1098d34927acSVille Syrjälä return DPLL_CTRL1_LINK_RATE(DPLL_CTRL1_LINK_RATE_810, SKL_DPLL0);
10997ff89ca2SVille Syrjälä }
11007ff89ca2SVille Syrjälä
skl_dpll0_enable(struct intel_display * display,int vco)1101d34927acSVille Syrjälä static void skl_dpll0_enable(struct intel_display *display, int vco)
1102b41df85aSVille Syrjälä {
1103b41df85aSVille Syrjälä intel_de_rmw(display, DPLL_CTRL1,
1104b41df85aSVille Syrjälä DPLL_CTRL1_HDMI_MODE(SKL_DPLL0) |
1105b41df85aSVille Syrjälä DPLL_CTRL1_SSC(SKL_DPLL0) |
1106d34927acSVille Syrjälä DPLL_CTRL1_LINK_RATE_MASK(SKL_DPLL0),
1107d34927acSVille Syrjälä DPLL_CTRL1_OVERRIDE(SKL_DPLL0) |
1108d34927acSVille Syrjälä skl_dpll0_link_rate(display, vco));
1109b41df85aSVille Syrjälä intel_de_posting_read(display, DPLL_CTRL1);
1110b41df85aSVille Syrjälä
1111b41df85aSVille Syrjälä intel_de_rmw(display, LCPLL1_CTL,
1112b41df85aSVille Syrjälä 0, LCPLL_PLL_ENABLE);
1113b41df85aSVille Syrjälä
1114b41df85aSVille Syrjälä if (intel_de_wait_for_set(display, LCPLL1_CTL, LCPLL_PLL_LOCK, 5))
1115b41df85aSVille Syrjälä drm_err(display->drm, "DPLL0 not locked\n");
1116b41df85aSVille Syrjälä
1117b41df85aSVille Syrjälä display->cdclk.hw.vco = vco;
1118b41df85aSVille Syrjälä
1119b41df85aSVille Syrjälä /* We'll want to keep using the current vco from now on. */
1120b41df85aSVille Syrjälä skl_set_preferred_cdclk_vco(display, vco);
1121b41df85aSVille Syrjälä }
1122b41df85aSVille Syrjälä
skl_dpll0_disable(struct intel_display * display)1123b41df85aSVille Syrjälä static void skl_dpll0_disable(struct intel_display *display)
1124d34927acSVille Syrjälä {
11250bb94e03SVille Syrjälä intel_de_rmw(display, LCPLL1_CTL,
112659f9e9caSVille Syrjälä LCPLL_PLL_ENABLE, 0);
11277ff89ca2SVille Syrjälä
1128d34927acSVille Syrjälä if (intel_de_wait_for_clear(display, LCPLL1_CTL, LCPLL_PLL_LOCK, 1))
11290bb94e03SVille Syrjälä drm_err(display->drm, "Couldn't disable DPLL0\n");
11300bb94e03SVille Syrjälä
113153421c2fSLucas De Marchi display->cdclk.hw.vco = 0;
11327ff89ca2SVille Syrjälä }
11337ff89ca2SVille Syrjälä
skl_cdclk_freq_sel(struct intel_display * display,int cdclk,int vco)1134602a9de5SImre Deak static u32 skl_cdclk_freq_sel(struct intel_display *display,
1135602a9de5SImre Deak int cdclk, int vco)
1136602a9de5SImre Deak {
1137602a9de5SImre Deak switch (cdclk) {
1138602a9de5SImre Deak default:
1139602a9de5SImre Deak drm_WARN_ON(display->drm,
1140602a9de5SImre Deak cdclk != display->cdclk.hw.bypass);
1141602a9de5SImre Deak drm_WARN_ON(display->drm, vco != 0);
1142d34927acSVille Syrjälä fallthrough;
1143f0453266SJani Nikula case 308571:
1144602a9de5SImre Deak case 337500:
1145ee421bb4SAshutosh Dixit return CDCLK_FREQ_337_308;
11467ff89ca2SVille Syrjälä case 450000:
11477ff89ca2SVille Syrjälä case 432000:
11487ff89ca2SVille Syrjälä return CDCLK_FREQ_450_432;
11497ff89ca2SVille Syrjälä case 540000:
1150d34927acSVille Syrjälä return CDCLK_FREQ_540;
115123194610SWambui Karuga case 617143:
11527ff89ca2SVille Syrjälä case 675000:
11537ff89ca2SVille Syrjälä return CDCLK_FREQ_675_617;
11547ff89ca2SVille Syrjälä }
1155d34927acSVille Syrjälä }
11567ff89ca2SVille Syrjälä
skl_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)1157d34927acSVille Syrjälä static void skl_set_cdclk(struct intel_display *display,
1158d34927acSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
1159d34927acSVille Syrjälä enum pipe pipe)
11607ff89ca2SVille Syrjälä {
1161d34927acSVille Syrjälä int cdclk = cdclk_config->cdclk;
116253421c2fSLucas De Marchi int vco = cdclk_config->vco;
1163d34927acSVille Syrjälä u32 freq_select, cdclk_ctl;
116453421c2fSLucas De Marchi int ret;
116553421c2fSLucas De Marchi
116653421c2fSLucas De Marchi /*
1167d34927acSVille Syrjälä * Based on WA#1183 CDCLK rates 308 and 617MHz CDCLK rates are
116853421c2fSLucas De Marchi * unsupported on SKL. In theory this should never happen since only
116953421c2fSLucas De Marchi * the eDP1.4 2.16 and 4.32Gbps rates require it, but eDP1.4 is not
117053421c2fSLucas De Marchi * supported on SKL either, see the above WA. WARN whenever trying to
117153421c2fSLucas De Marchi * use the corresponding VCO freq as that always leads to using the
1172d34927acSVille Syrjälä * minimum 308MHz CDCLK.
1173d34927acSVille Syrjälä */
117453421c2fSLucas De Marchi drm_WARN_ON_ONCE(display->drm,
1175d34927acSVille Syrjälä display->platform.skylake && vco == 8640000);
1176d34927acSVille Syrjälä
11777ff89ca2SVille Syrjälä ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
117853421c2fSLucas De Marchi SKL_CDCLK_PREPARE_FOR_CHANGE,
117953421c2fSLucas De Marchi SKL_CDCLK_READY_FOR_CHANGE,
1180d34927acSVille Syrjälä SKL_CDCLK_READY_FOR_CHANGE, 3);
118153421c2fSLucas De Marchi if (ret) {
118253421c2fSLucas De Marchi drm_err(display->drm,
1183d34927acSVille Syrjälä "Failed to inform PCU about cdclk change (%d)\n", ret);
118453421c2fSLucas De Marchi return;
118553421c2fSLucas De Marchi }
118653421c2fSLucas De Marchi
1187d34927acSVille Syrjälä freq_select = skl_cdclk_freq_sel(display, cdclk, vco);
1188d34927acSVille Syrjälä
11897ff89ca2SVille Syrjälä if (display->cdclk.hw.vco != 0 &&
11907ff89ca2SVille Syrjälä display->cdclk.hw.vco != vco)
1191ee421bb4SAshutosh Dixit skl_dpll0_disable(display);
11920bb94e03SVille Syrjälä
11937ff89ca2SVille Syrjälä cdclk_ctl = intel_de_read(display, CDCLK_CTL);
1194d34927acSVille Syrjälä
11957ff89ca2SVille Syrjälä if (display->cdclk.hw.vco != vco) {
11967ff89ca2SVille Syrjälä /* Wa Display #1183: skl,kbl,cfl */
1197d34927acSVille Syrjälä cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
11987ff89ca2SVille Syrjälä cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
1199cbe974fbSJani Nikula intel_de_write(display, CDCLK_CTL, cdclk_ctl);
12007ff89ca2SVille Syrjälä }
12017ff89ca2SVille Syrjälä
12027ff89ca2SVille Syrjälä /* Wa Display #1183: skl,kbl,cfl */
12037ff89ca2SVille Syrjälä cdclk_ctl |= CDCLK_DIVMUX_CD_OVERRIDE;
12047ff89ca2SVille Syrjälä intel_de_write(display, CDCLK_CTL, cdclk_ctl);
12057ff89ca2SVille Syrjälä intel_de_posting_read(display, CDCLK_CTL);
1206d34927acSVille Syrjälä
12077ff89ca2SVille Syrjälä if (display->cdclk.hw.vco != vco)
12087ff89ca2SVille Syrjälä skl_dpll0_enable(display, vco);
1209d34927acSVille Syrjälä
1210d34927acSVille Syrjälä /* Wa Display #1183: skl,kbl,cfl */
1211cfddadc9SVille Syrjälä cdclk_ctl &= ~(CDCLK_FREQ_SEL_MASK | CDCLK_FREQ_DECIMAL_MASK);
12127ff89ca2SVille Syrjälä intel_de_write(display, CDCLK_CTL, cdclk_ctl);
1213d34927acSVille Syrjälä
1214d34927acSVille Syrjälä cdclk_ctl |= freq_select | skl_cdclk_decimal(cdclk);
12157ff89ca2SVille Syrjälä intel_de_write(display, CDCLK_CTL, cdclk_ctl);
12167ff89ca2SVille Syrjälä
12177ff89ca2SVille Syrjälä /* Wa Display #1183: skl,kbl,cfl */
12187ff89ca2SVille Syrjälä cdclk_ctl &= ~CDCLK_DIVMUX_CD_OVERRIDE;
12197ff89ca2SVille Syrjälä intel_de_write(display, CDCLK_CTL, cdclk_ctl);
12207ff89ca2SVille Syrjälä intel_de_posting_read(display, CDCLK_CTL);
12217ff89ca2SVille Syrjälä
12227ff89ca2SVille Syrjälä /* inform PCU of the change */
1223d34927acSVille Syrjälä intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
12247ff89ca2SVille Syrjälä cdclk_config->voltage_level);
1225d34927acSVille Syrjälä
12267ff89ca2SVille Syrjälä intel_update_cdclk(display);
12277ff89ca2SVille Syrjälä }
12287ff89ca2SVille Syrjälä
skl_sanitize_cdclk(struct intel_display * display)12297ff89ca2SVille Syrjälä static void skl_sanitize_cdclk(struct intel_display *display)
12307ff89ca2SVille Syrjälä {
1231d34927acSVille Syrjälä u32 cdctl, expected;
12327ff89ca2SVille Syrjälä
12337ff89ca2SVille Syrjälä /*
1234d34927acSVille Syrjälä * check if the pre-os initialized the display
12357ff89ca2SVille Syrjälä * There is SWF18 scratchpad register defined which is set by the
1236d34927acSVille Syrjälä * pre-os which can be used by the OS drivers to check the status
12377ff89ca2SVille Syrjälä */
12387ff89ca2SVille Syrjälä if ((intel_de_read(display, SWF_ILK(0x18)) & 0x00FFFFFF) == 0)
1239d34927acSVille Syrjälä goto sanitize;
12407ff89ca2SVille Syrjälä
12410bb94e03SVille Syrjälä intel_update_cdclk(display);
12427ff89ca2SVille Syrjälä intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
1243d34927acSVille Syrjälä
12447ff89ca2SVille Syrjälä /* Is PLL enabled and locked ? */
1245d34927acSVille Syrjälä if (display->cdclk.hw.vco == 0 ||
1246d34927acSVille Syrjälä display->cdclk.hw.cdclk == display->cdclk.hw.bypass)
12477ff89ca2SVille Syrjälä goto sanitize;
12487ff89ca2SVille Syrjälä
12497ff89ca2SVille Syrjälä /* DPLL okay; verify the cdclock
12507ff89ca2SVille Syrjälä *
1251d34927acSVille Syrjälä * Noticed in some instances that the freq selection is correct but
1252d34927acSVille Syrjälä * decimal part is programmed wrong from BIOS where pre-os does not
1253d34927acSVille Syrjälä * enable display. Verify the same as well.
12547ff89ca2SVille Syrjälä */
12557ff89ca2SVille Syrjälä cdctl = intel_de_read(display, CDCLK_CTL);
12567ff89ca2SVille Syrjälä expected = (cdctl & CDCLK_FREQ_SEL_MASK) |
1257d34927acSVille Syrjälä skl_cdclk_decimal(display->cdclk.hw.cdclk);
12587ff89ca2SVille Syrjälä if (cdctl == expected)
1259d34927acSVille Syrjälä /* All well; nothing to sanitize */
12600bb94e03SVille Syrjälä return;
12610bb94e03SVille Syrjälä
12620bb94e03SVille Syrjälä sanitize:
12630bb94e03SVille Syrjälä drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
126483c5fda7SVille Syrjälä
1265d34927acSVille Syrjälä /* force cdclk programming */
12667ff89ca2SVille Syrjälä display->cdclk.hw.cdclk = 0;
12677ff89ca2SVille Syrjälä /* force full PLL disable + enable */
1268d34927acSVille Syrjälä display->cdclk.hw.vco = ~0;
12697ff89ca2SVille Syrjälä }
1270d34927acSVille Syrjälä
skl_cdclk_init_hw(struct intel_display * display)127183c5fda7SVille Syrjälä static void skl_cdclk_init_hw(struct intel_display *display)
12720bb94e03SVille Syrjälä {
12730bb94e03SVille Syrjälä struct intel_cdclk_config cdclk_config;
12740bb94e03SVille Syrjälä
127583c5fda7SVille Syrjälä skl_sanitize_cdclk(display);
1276d34927acSVille Syrjälä
12777ff89ca2SVille Syrjälä if (display->cdclk.hw.cdclk != 0 &&
12787ff89ca2SVille Syrjälä display->cdclk.hw.vco != 0) {
12792bebea57SJani Nikula /*
12802bebea57SJani Nikula * Use the current vco as our initial
12812bebea57SJani Nikula * guess as to what the preferred vco is.
12822bebea57SJani Nikula */
12832bebea57SJani Nikula if (display->cdclk.skl_preferred_vco_freq == 0)
12842bebea57SJani Nikula skl_set_preferred_cdclk_vco(display,
12852bebea57SJani Nikula display->cdclk.hw.vco);
1286736da811SMatt Roper return;
128789d6708dSGustavo Sousa }
128889d6708dSGustavo Sousa
128989d6708dSGustavo Sousa cdclk_config = display->cdclk.hw;
129089d6708dSGustavo Sousa
129189d6708dSGustavo Sousa cdclk_config.vco = display->cdclk.skl_preferred_vco_freq;
1292736da811SMatt Roper if (cdclk_config.vco == 0)
1293736da811SMatt Roper cdclk_config.vco = 8100000;
1294736da811SMatt Roper cdclk_config.cdclk = skl_calc_cdclk(0, cdclk_config.vco);
1295736da811SMatt Roper cdclk_config.voltage_level = skl_calc_voltage_level(cdclk_config.cdclk);
129689d6708dSGustavo Sousa
129789d6708dSGustavo Sousa skl_set_cdclk(display, &cdclk_config, INVALID_PIPE);
129889d6708dSGustavo Sousa }
1299736da811SMatt Roper
skl_cdclk_uninit_hw(struct intel_display * display)1300736da811SMatt Roper static void skl_cdclk_uninit_hw(struct intel_display *display)
1301736da811SMatt Roper {
1302736da811SMatt Roper struct intel_cdclk_config cdclk_config = display->cdclk.hw;
130389d6708dSGustavo Sousa
130489d6708dSGustavo Sousa cdclk_config.cdclk = cdclk_config.bypass;
130589d6708dSGustavo Sousa cdclk_config.vco = 0;
130689d6708dSGustavo Sousa cdclk_config.voltage_level = skl_calc_voltage_level(cdclk_config.cdclk);
130789d6708dSGustavo Sousa
130889d6708dSGustavo Sousa skl_set_cdclk(display, &cdclk_config, INVALID_PIPE);
1309736da811SMatt Roper }
131089d6708dSGustavo Sousa
131189d6708dSGustavo Sousa struct intel_cdclk_vals {
131289d6708dSGustavo Sousa u32 cdclk;
131389d6708dSGustavo Sousa u16 refclk;
131489d6708dSGustavo Sousa u16 waveform;
131589d6708dSGustavo Sousa u8 ratio;
1316736da811SMatt Roper };
131789d6708dSGustavo Sousa
131889d6708dSGustavo Sousa static const struct intel_cdclk_vals bxt_cdclk_table[] = {
131989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 144000, .ratio = 60 },
132089d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 288000, .ratio = 60 },
132189d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 384000, .ratio = 60 },
132289d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 576000, .ratio = 60 },
1323736da811SMatt Roper { .refclk = 19200, .cdclk = 624000, .ratio = 65 },
1324736da811SMatt Roper {}
1325736da811SMatt Roper };
1326693260cfSMatt Roper
132789d6708dSGustavo Sousa static const struct intel_cdclk_vals glk_cdclk_table[] = {
132889d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 79200, .ratio = 33 },
132989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 158400, .ratio = 33 },
133089d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 316800, .ratio = 33 },
133189d6708dSGustavo Sousa {}
133289d6708dSGustavo Sousa };
1333693260cfSMatt Roper
133489d6708dSGustavo Sousa static const struct intel_cdclk_vals icl_cdclk_table[] = {
133589d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 172800, .ratio = 18 },
133689d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
133789d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
133889d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 326400, .ratio = 68 },
133989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
1340693260cfSMatt Roper { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
134189d6708dSGustavo Sousa
134289d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 180000, .ratio = 15 },
134389d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
134489d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
134589d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 324000, .ratio = 54 },
134689d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
1347693260cfSMatt Roper { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
1348693260cfSMatt Roper
1349693260cfSMatt Roper { .refclk = 38400, .cdclk = 172800, .ratio = 9 },
13502680bea7SJosé Roberto de Souza { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
135189d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
135289d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 326400, .ratio = 34 },
135389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
13542680bea7SJosé Roberto de Souza { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
135589d6708dSGustavo Sousa {}
135689d6708dSGustavo Sousa };
135789d6708dSGustavo Sousa
13582680bea7SJosé Roberto de Souza static const struct intel_cdclk_vals rkl_cdclk_table[] = {
135989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 172800, .ratio = 36 },
136089d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 192000, .ratio = 40 },
136189d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 307200, .ratio = 64 },
13622680bea7SJosé Roberto de Souza { .refclk = 19200, .cdclk = 326400, .ratio = 136 },
13632680bea7SJosé Roberto de Souza { .refclk = 19200, .cdclk = 556800, .ratio = 116 },
13642680bea7SJosé Roberto de Souza { .refclk = 19200, .cdclk = 652800, .ratio = 136 },
1365626426ffSAnusha Srivatsa
136689d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 180000, .ratio = 30 },
136789d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 192000, .ratio = 32 },
136889d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 312000, .ratio = 52 },
136989d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 324000, .ratio = 108 },
137089d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 552000, .ratio = 92 },
1371626426ffSAnusha Srivatsa { .refclk = 24000, .cdclk = 648000, .ratio = 108 },
137289d6708dSGustavo Sousa
137389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 172800, .ratio = 18 },
137489d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 192000, .ratio = 20 },
137589d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 307200, .ratio = 32 },
137689d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 326400, .ratio = 68 },
1377626426ffSAnusha Srivatsa { .refclk = 38400, .cdclk = 556800, .ratio = 58 },
137889d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 652800, .ratio = 68 },
137989d6708dSGustavo Sousa {}
138089d6708dSGustavo Sousa };
138189d6708dSGustavo Sousa
138289d6708dSGustavo Sousa static const struct intel_cdclk_vals adlp_a_step_cdclk_table[] = {
1383626426ffSAnusha Srivatsa { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
1384626426ffSAnusha Srivatsa { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
1385626426ffSAnusha Srivatsa { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
138606f1b06dSChaitanya Kumar Borah
138789d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
138889d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
138989d6708dSGustavo Sousa { .refclk = 24400, .cdclk = 648000, .ratio = 54 },
139089d6708dSGustavo Sousa
139189d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
139289d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
139306f1b06dSChaitanya Kumar Borah { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
139489d6708dSGustavo Sousa {}
139589d6708dSGustavo Sousa };
139689d6708dSGustavo Sousa
139789d6708dSGustavo Sousa static const struct intel_cdclk_vals adlp_cdclk_table[] = {
139889d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 172800, .ratio = 27 },
139989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
140006f1b06dSChaitanya Kumar Borah { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
140189d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
140289d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
140389d6708dSGustavo Sousa
140489d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 176000, .ratio = 22 },
140589d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
140689d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
140706f1b06dSChaitanya Kumar Borah { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
140806f1b06dSChaitanya Kumar Borah { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
140906f1b06dSChaitanya Kumar Borah
14101f3e84c4SMatt Roper { .refclk = 38400, .cdclk = 179200, .ratio = 14 },
141189d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
141289d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
141389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
141489d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
141589d6708dSGustavo Sousa {}
141689d6708dSGustavo Sousa };
141789d6708dSGustavo Sousa
141889d6708dSGustavo Sousa static const struct intel_cdclk_vals rplu_cdclk_table[] = {
141989d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 172800, .ratio = 27 },
142089d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 192000, .ratio = 20 },
142189d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 307200, .ratio = 32 },
142289d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 480000, .ratio = 50 },
142389d6708dSGustavo Sousa { .refclk = 19200, .cdclk = 556800, .ratio = 58 },
14241f3e84c4SMatt Roper { .refclk = 19200, .cdclk = 652800, .ratio = 68 },
14251f3e84c4SMatt Roper
14261f3e84c4SMatt Roper { .refclk = 24000, .cdclk = 176000, .ratio = 22 },
142786c0ef72SAnusha Srivatsa { .refclk = 24000, .cdclk = 192000, .ratio = 16 },
142889d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 312000, .ratio = 26 },
142989d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 480000, .ratio = 40 },
143089d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 552000, .ratio = 46 },
143189d6708dSGustavo Sousa { .refclk = 24000, .cdclk = 648000, .ratio = 54 },
143289d6708dSGustavo Sousa
143389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 179200, .ratio = 14 },
143486c0ef72SAnusha Srivatsa { .refclk = 38400, .cdclk = 192000, .ratio = 10 },
143586c0ef72SAnusha Srivatsa { .refclk = 38400, .cdclk = 307200, .ratio = 16 },
143686c0ef72SAnusha Srivatsa { .refclk = 38400, .cdclk = 480000, .ratio = 25 },
1437dfdfc609SGustavo Sousa { .refclk = 38400, .cdclk = 556800, .ratio = 29 },
143889d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 652800, .ratio = 34 },
143989d6708dSGustavo Sousa {}
144089d6708dSGustavo Sousa };
144189d6708dSGustavo Sousa
144289d6708dSGustavo Sousa static const struct intel_cdclk_vals dg2_cdclk_table[] = {
144389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 163200, .ratio = 34, .waveform = 0x8888 },
144489d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 204000, .ratio = 34, .waveform = 0x9248 },
144589d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 244800, .ratio = 34, .waveform = 0xa4a4 },
144689d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 285600, .ratio = 34, .waveform = 0xa54a },
144789d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 326400, .ratio = 34, .waveform = 0xaaaa },
144889d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 367200, .ratio = 34, .waveform = 0xad5a },
144989d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 408000, .ratio = 34, .waveform = 0xb6b6 },
145089d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 448800, .ratio = 34, .waveform = 0xdbb6 },
145189d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 489600, .ratio = 34, .waveform = 0xeeee },
145289d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 530400, .ratio = 34, .waveform = 0xf7de },
145389d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 571200, .ratio = 34, .waveform = 0xfefe },
145489d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 612000, .ratio = 34, .waveform = 0xfffe },
145589d6708dSGustavo Sousa { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
145689d6708dSGustavo Sousa {}
145789d6708dSGustavo Sousa };
145889d6708dSGustavo Sousa
1459394b4b7dSStanislav Lisovskiy static const struct intel_cdclk_vals mtl_cdclk_table[] = {
1460394b4b7dSStanislav Lisovskiy { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
1461394b4b7dSStanislav Lisovskiy { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
1462080b76d8SClint Taylor { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0x0000 },
1463080b76d8SClint Taylor { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0x0000 },
1464080b76d8SClint Taylor { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0x0000 },
1465080b76d8SClint Taylor { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0x0000 },
1466080b76d8SClint Taylor {}
1467080b76d8SClint Taylor };
1468080b76d8SClint Taylor
1469080b76d8SClint Taylor static const struct intel_cdclk_vals xe2lpd_cdclk_table[] = {
1470b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 153600, .ratio = 16, .waveform = 0xaaaa },
1471b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
1472b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
1473b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 211200, .ratio = 16, .waveform = 0xdbb6 },
1474b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 230400, .ratio = 16, .waveform = 0xeeee },
1475b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 249600, .ratio = 16, .waveform = 0xf7de },
1476b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 268800, .ratio = 16, .waveform = 0xfefe },
1477b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 288000, .ratio = 16, .waveform = 0xfffe },
1478b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0xffff },
1479b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 330000, .ratio = 25, .waveform = 0xdbb6 },
1480b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 360000, .ratio = 25, .waveform = 0xeeee },
1481b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 390000, .ratio = 25, .waveform = 0xf7de },
1482b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 420000, .ratio = 25, .waveform = 0xfefe },
1483b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 450000, .ratio = 25, .waveform = 0xfffe },
1484b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0xffff },
1485b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 487200, .ratio = 29, .waveform = 0xfefe },
1486b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 522000, .ratio = 29, .waveform = 0xfffe },
1487b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0xffff },
1488b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 571200, .ratio = 34, .waveform = 0xfefe },
1489b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 612000, .ratio = 34, .waveform = 0xfffe },
1490b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
1491b0ad56ceSRadhakrishna Sripada {}
1492b0ad56ceSRadhakrishna Sripada };
1493b0ad56ceSRadhakrishna Sripada
1494b0ad56ceSRadhakrishna Sripada /*
1495b0ad56ceSRadhakrishna Sripada * Xe2_HPD always uses the minimal cdclk table from Wa_15015413771
1496b0ad56ceSRadhakrishna Sripada */
1497b0ad56ceSRadhakrishna Sripada static const struct intel_cdclk_vals xe2hpd_cdclk_table[] = {
1498b0ad56ceSRadhakrishna Sripada { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
1499b0ad56ceSRadhakrishna Sripada {}
1500b0ad56ceSRadhakrishna Sripada };
1501b0ad56ceSRadhakrishna Sripada
1502b0ad56ceSRadhakrishna Sripada static const struct intel_cdclk_vals xe3lpd_cdclk_table[] = {
150326aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 153600, .ratio = 16, .waveform = 0xaaaa },
150426aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 172800, .ratio = 16, .waveform = 0xad5a },
150526aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 192000, .ratio = 16, .waveform = 0xb6b6 },
150626aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 211200, .ratio = 16, .waveform = 0xdbb6 },
150726aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 230400, .ratio = 16, .waveform = 0xeeee },
150826aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 249600, .ratio = 16, .waveform = 0xf7de },
150926aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 268800, .ratio = 16, .waveform = 0xfefe },
151026aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 288000, .ratio = 16, .waveform = 0xfffe },
151126aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 307200, .ratio = 16, .waveform = 0xffff },
151226aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 326400, .ratio = 17, .waveform = 0xffff },
151326aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 345600, .ratio = 18, .waveform = 0xffff },
151426aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 364800, .ratio = 19, .waveform = 0xffff },
151526aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 384000, .ratio = 20, .waveform = 0xffff },
151626aba0d1SVille Syrjälä { .refclk = 38400, .cdclk = 403200, .ratio = 21, .waveform = 0xffff },
1517d34927acSVille Syrjälä { .refclk = 38400, .cdclk = 422400, .ratio = 22, .waveform = 0xffff },
15187ff89ca2SVille Syrjälä { .refclk = 38400, .cdclk = 441600, .ratio = 23, .waveform = 0xffff },
1519d34927acSVille Syrjälä { .refclk = 38400, .cdclk = 460800, .ratio = 24, .waveform = 0xffff },
1520736da811SMatt Roper { .refclk = 38400, .cdclk = 480000, .ratio = 25, .waveform = 0xffff },
1521736da811SMatt Roper { .refclk = 38400, .cdclk = 499200, .ratio = 26, .waveform = 0xffff },
1522736da811SMatt Roper { .refclk = 38400, .cdclk = 518400, .ratio = 27, .waveform = 0xffff },
1523d34927acSVille Syrjälä { .refclk = 38400, .cdclk = 537600, .ratio = 28, .waveform = 0xffff },
1524736da811SMatt Roper { .refclk = 38400, .cdclk = 556800, .ratio = 29, .waveform = 0xffff },
1525736da811SMatt Roper { .refclk = 38400, .cdclk = 576000, .ratio = 30, .waveform = 0xffff },
1526736da811SMatt Roper { .refclk = 38400, .cdclk = 595200, .ratio = 31, .waveform = 0xffff },
1527d34927acSVille Syrjälä { .refclk = 38400, .cdclk = 614400, .ratio = 32, .waveform = 0xffff },
1528aff35110SPankaj Bharadiya { .refclk = 38400, .cdclk = 633600, .ratio = 33, .waveform = 0xffff },
1529d34927acSVille Syrjälä { .refclk = 38400, .cdclk = 652800, .ratio = 34, .waveform = 0xffff },
1530736da811SMatt Roper { .refclk = 38400, .cdclk = 672000, .ratio = 35, .waveform = 0xffff },
15317ff89ca2SVille Syrjälä { .refclk = 38400, .cdclk = 691200, .ratio = 36, .waveform = 0xffff },
15327ff89ca2SVille Syrjälä {}
1533d34927acSVille Syrjälä };
15347ff89ca2SVille Syrjälä
1535d34927acSVille Syrjälä static const int cdclk_squash_len = 16;
1536736da811SMatt Roper
cdclk_squash_divider(u16 waveform)1537736da811SMatt Roper static int cdclk_squash_divider(u16 waveform)
1538d34927acSVille Syrjälä {
1539736da811SMatt Roper return hweight16(waveform ?: 0xffff);
1540736da811SMatt Roper }
1541736da811SMatt Roper
cdclk_divider(int cdclk,int vco,u16 waveform)1542d34927acSVille Syrjälä static int cdclk_divider(int cdclk, int vco, u16 waveform)
1543736da811SMatt Roper {
1544d34927acSVille Syrjälä /* 2 * cd2x divider */
1545736da811SMatt Roper return DIV_ROUND_CLOSEST(vco * cdclk_squash_divider(waveform),
1546d34927acSVille Syrjälä cdclk * cdclk_squash_len);
1547d34927acSVille Syrjälä }
1548736da811SMatt Roper
bxt_calc_cdclk(struct intel_display * display,int min_cdclk)15497ff89ca2SVille Syrjälä static int bxt_calc_cdclk(struct intel_display *display, int min_cdclk)
15507ff89ca2SVille Syrjälä {
15512123f442SVille Syrjälä const struct intel_cdclk_vals *table = display->cdclk.table;
15522123f442SVille Syrjälä int i;
15532123f442SVille Syrjälä
15542123f442SVille Syrjälä for (i = 0; table[i].refclk; i++)
15552123f442SVille Syrjälä if (table[i].refclk == display->cdclk.hw.ref &&
1556f23fe4d7SVille Syrjälä table[i].cdclk >= min_cdclk)
1557f23fe4d7SVille Syrjälä return table[i].cdclk;
1558f23fe4d7SVille Syrjälä
1559f23fe4d7SVille Syrjälä drm_WARN(display->drm, 1,
1560f23fe4d7SVille Syrjälä "Cannot satisfy minimum cdclk %d with refclk %u\n",
1561f23fe4d7SVille Syrjälä min_cdclk, display->cdclk.hw.ref);
1562f23fe4d7SVille Syrjälä return 0;
1563f23fe4d7SVille Syrjälä }
1564f23fe4d7SVille Syrjälä
bxt_calc_cdclk_pll_vco(struct intel_display * display,int cdclk)1565f23fe4d7SVille Syrjälä static int bxt_calc_cdclk_pll_vco(struct intel_display *display, int cdclk)
1566f23fe4d7SVille Syrjälä {
1567f23fe4d7SVille Syrjälä const struct intel_cdclk_vals *table = display->cdclk.table;
1568f23fe4d7SVille Syrjälä int i;
1569f23fe4d7SVille Syrjälä
157071dc367eSMatt Roper if (cdclk == display->cdclk.hw.bypass)
157171dc367eSMatt Roper return 0;
1572f23fe4d7SVille Syrjälä
1573f23fe4d7SVille Syrjälä for (i = 0; table[i].refclk; i++)
1574f23fe4d7SVille Syrjälä if (table[i].refclk == display->cdclk.hw.ref &&
1575f23fe4d7SVille Syrjälä table[i].cdclk == cdclk)
1576f23fe4d7SVille Syrjälä return display->cdclk.hw.ref * table[i].ratio;
1577f23fe4d7SVille Syrjälä
1578f23fe4d7SVille Syrjälä drm_WARN(display->drm, 1, "cdclk %d not valid for refclk %u\n",
1579f23fe4d7SVille Syrjälä cdclk, display->cdclk.hw.ref);
1580f23fe4d7SVille Syrjälä return 0;
158171dc367eSMatt Roper }
158271dc367eSMatt Roper
bxt_calc_voltage_level(int cdclk)158371dc367eSMatt Roper static u8 bxt_calc_voltage_level(int cdclk)
158471dc367eSMatt Roper {
1585f23fe4d7SVille Syrjälä return DIV_ROUND_UP(cdclk, 25000);
1586f23fe4d7SVille Syrjälä }
1587f23fe4d7SVille Syrjälä
calc_voltage_level(int cdclk,int num_voltage_levels,const int voltage_level_max_cdclk[])1588f23fe4d7SVille Syrjälä static u8 calc_voltage_level(int cdclk, int num_voltage_levels,
1589f23fe4d7SVille Syrjälä const int voltage_level_max_cdclk[])
1590f23fe4d7SVille Syrjälä {
1591f23fe4d7SVille Syrjälä int voltage_level;
1592f23fe4d7SVille Syrjälä
1593f23fe4d7SVille Syrjälä for (voltage_level = 0; voltage_level < num_voltage_levels; voltage_level++) {
1594f23fe4d7SVille Syrjälä if (cdclk <= voltage_level_max_cdclk[voltage_level])
1595f23fe4d7SVille Syrjälä return voltage_level;
1596f23fe4d7SVille Syrjälä }
1597f23fe4d7SVille Syrjälä
1598f23fe4d7SVille Syrjälä MISSING_CASE(cdclk);
159971dc367eSMatt Roper return num_voltage_levels - 1;
160071dc367eSMatt Roper }
16010fde0b1dSMatt Roper
icl_calc_voltage_level(int cdclk)16020fde0b1dSMatt Roper static u8 icl_calc_voltage_level(int cdclk)
1603f23fe4d7SVille Syrjälä {
1604f23fe4d7SVille Syrjälä static const int icl_voltage_level_max_cdclk[] = {
1605f23fe4d7SVille Syrjälä [0] = 312000,
1606f23fe4d7SVille Syrjälä [1] = 556800,
1607f23fe4d7SVille Syrjälä [2] = 652800,
1608f23fe4d7SVille Syrjälä };
1609f23fe4d7SVille Syrjälä
1610f23fe4d7SVille Syrjälä return calc_voltage_level(cdclk,
1611f23fe4d7SVille Syrjälä ARRAY_SIZE(icl_voltage_level_max_cdclk),
1612f23fe4d7SVille Syrjälä icl_voltage_level_max_cdclk);
16130fde0b1dSMatt Roper }
16140fde0b1dSMatt Roper
ehl_calc_voltage_level(int cdclk)16155a3c46b8SChaitanya Kumar Borah static u8 ehl_calc_voltage_level(int cdclk)
16165a3c46b8SChaitanya Kumar Borah {
1617f23fe4d7SVille Syrjälä static const int ehl_voltage_level_max_cdclk[] = {
1618f23fe4d7SVille Syrjälä [0] = 180000,
1619f23fe4d7SVille Syrjälä [1] = 312000,
1620f23fe4d7SVille Syrjälä [2] = 326400,
1621f23fe4d7SVille Syrjälä /*
1622f23fe4d7SVille Syrjälä * Bspec lists the limit as 556.8 MHz, but some JSL
1623f23fe4d7SVille Syrjälä * development boards (at least) boot with 652.8 MHz
1624f23fe4d7SVille Syrjälä */
1625f23fe4d7SVille Syrjälä [3] = 652800,
1626f23fe4d7SVille Syrjälä };
16275a3c46b8SChaitanya Kumar Borah
16285a3c46b8SChaitanya Kumar Borah return calc_voltage_level(cdclk,
1629b0ad56ceSRadhakrishna Sripada ARRAY_SIZE(ehl_voltage_level_max_cdclk),
1630b0ad56ceSRadhakrishna Sripada ehl_voltage_level_max_cdclk);
1631b0ad56ceSRadhakrishna Sripada }
1632b0ad56ceSRadhakrishna Sripada
tgl_calc_voltage_level(int cdclk)1633b0ad56ceSRadhakrishna Sripada static u8 tgl_calc_voltage_level(int cdclk)
1634b0ad56ceSRadhakrishna Sripada {
1635b0ad56ceSRadhakrishna Sripada static const int tgl_voltage_level_max_cdclk[] = {
1636b0ad56ceSRadhakrishna Sripada [0] = 312000,
1637b0ad56ceSRadhakrishna Sripada [1] = 326400,
1638b0ad56ceSRadhakrishna Sripada [2] = 556800,
1639d34927acSVille Syrjälä [3] = 652800,
16400bb94e03SVille Syrjälä };
164171dc367eSMatt Roper
1642d34927acSVille Syrjälä return calc_voltage_level(cdclk,
164371dc367eSMatt Roper ARRAY_SIZE(tgl_voltage_level_max_cdclk),
164471dc367eSMatt Roper tgl_voltage_level_max_cdclk);
164571dc367eSMatt Roper }
164671dc367eSMatt Roper
rplu_calc_voltage_level(int cdclk)1647df561f66SGustavo A. R. Silva static u8 rplu_calc_voltage_level(int cdclk)
164871dc367eSMatt Roper {
16490bb94e03SVille Syrjälä static const int rplu_voltage_level_max_cdclk[] = {
165071dc367eSMatt Roper [0] = 312000,
165171dc367eSMatt Roper [1] = 480000,
16520bb94e03SVille Syrjälä [2] = 556800,
165371dc367eSMatt Roper [3] = 652800,
165471dc367eSMatt Roper };
16550bb94e03SVille Syrjälä
165671dc367eSMatt Roper return calc_voltage_level(cdclk,
165771dc367eSMatt Roper ARRAY_SIZE(rplu_voltage_level_max_cdclk),
165871dc367eSMatt Roper rplu_voltage_level_max_cdclk);
165971dc367eSMatt Roper }
1660d34927acSVille Syrjälä
xe3lpd_calc_voltage_level(int cdclk)16610bb94e03SVille Syrjälä static u8 xe3lpd_calc_voltage_level(int cdclk)
166271dc367eSMatt Roper {
166371dc367eSMatt Roper /*
166471dc367eSMatt Roper * Starting with xe3lpd power controller does not need the voltage
1665f0453266SJani Nikula * index when doing the modeset update. This function is best left
16661f3e84c4SMatt Roper * defined but returning 0 to the mask.
1667d34927acSVille Syrjälä */
1668d34927acSVille Syrjälä return 0;
166971dc367eSMatt Roper }
16700bb94e03SVille Syrjälä
icl_readout_refclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)16717ff89ca2SVille Syrjälä static void icl_readout_refclk(struct intel_display *display,
1672d34927acSVille Syrjälä struct intel_cdclk_config *cdclk_config)
167371dc367eSMatt Roper {
167471dc367eSMatt Roper u32 dssm = intel_de_read(display, SKL_DSSM) & ICL_DSSM_CDCLK_PLL_REFCLK_MASK;
167571dc367eSMatt Roper
167671dc367eSMatt Roper switch (dssm) {
167771dc367eSMatt Roper default:
167871dc367eSMatt Roper MISSING_CASE(dssm);
16790bb94e03SVille Syrjälä fallthrough;
16807ff89ca2SVille Syrjälä case ICL_DSSM_CDCLK_PLL_REFCLK_24MHz:
168171dc367eSMatt Roper cdclk_config->ref = 24000;
16827ff89ca2SVille Syrjälä break;
168371dc367eSMatt Roper case ICL_DSSM_CDCLK_PLL_REFCLK_19_2MHz:
16841d89509aSLucas De Marchi cdclk_config->ref = 19200;
16851d89509aSLucas De Marchi break;
168671dc367eSMatt Roper case ICL_DSSM_CDCLK_PLL_REFCLK_38_4MHz:
1687d34927acSVille Syrjälä cdclk_config->ref = 38400;
16881d89509aSLucas De Marchi break;
168971dc367eSMatt Roper }
1690d34927acSVille Syrjälä }
16917ff89ca2SVille Syrjälä
bxt_de_pll_readout(struct intel_display * display,struct intel_cdclk_config * cdclk_config)16920bb94e03SVille Syrjälä static void bxt_de_pll_readout(struct intel_display *display,
16937ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
16947ff89ca2SVille Syrjälä {
1695d34927acSVille Syrjälä u32 val, ratio;
16960bb94e03SVille Syrjälä
16977ff89ca2SVille Syrjälä if (display->platform.dg2)
169877ab3a1eSMika Kahola cdclk_config->ref = 38400;
16997ff89ca2SVille Syrjälä else if (DISPLAY_VER(display) >= 11)
170049cd97a3SVille Syrjälä icl_readout_refclk(display, cdclk_config);
17017ff89ca2SVille Syrjälä else
1702d34927acSVille Syrjälä cdclk_config->ref = 19200;
170374689ddfSVille Syrjälä
1704d34927acSVille Syrjälä val = intel_de_read(display, BXT_DE_PLL_ENABLE);
17050bb94e03SVille Syrjälä if ((val & BXT_DE_PLL_PLL_ENABLE) == 0 ||
1706d34927acSVille Syrjälä (val & BXT_DE_PLL_LOCK) == 0) {
17070bb94e03SVille Syrjälä /*
170871dc367eSMatt Roper * CDCLK PLL is disabled, the VCO/ratio doesn't matter, but
17090bb94e03SVille Syrjälä * setting it to zero is a way to signal that.
17107ff89ca2SVille Syrjälä */
17110bb94e03SVille Syrjälä cdclk_config->vco = 0;
17120bb94e03SVille Syrjälä return;
17132123f442SVille Syrjälä }
171471dc367eSMatt Roper
17157ff89ca2SVille Syrjälä /*
1716d34927acSVille Syrjälä * DISPLAY_VER >= 11 have the ratio directly in the PLL enable register,
17177ff89ca2SVille Syrjälä * gen9lp had it in a separate PLL control register.
17187ff89ca2SVille Syrjälä */
17197ff89ca2SVille Syrjälä if (DISPLAY_VER(display) >= 11)
17207ff89ca2SVille Syrjälä ratio = val & ICL_CDCLK_PLL_RATIO_MASK;
17217ff89ca2SVille Syrjälä else
17227ff89ca2SVille Syrjälä ratio = intel_de_read(display, BXT_DE_PLL_CTL) & BXT_DE_PLL_RATIO_MASK;
17237ff89ca2SVille Syrjälä
17247ff89ca2SVille Syrjälä cdclk_config->vco = ratio * cdclk_config->ref;
17257ff89ca2SVille Syrjälä }
17267ff89ca2SVille Syrjälä
bxt_get_cdclk(struct intel_display * display,struct intel_cdclk_config * cdclk_config)17277ff89ca2SVille Syrjälä static void bxt_get_cdclk(struct intel_display *display,
17287ff89ca2SVille Syrjälä struct intel_cdclk_config *cdclk_config)
17297ff89ca2SVille Syrjälä {
17307ff89ca2SVille Syrjälä u32 squash_ctl = 0;
17317ff89ca2SVille Syrjälä u32 divider;
17327ff89ca2SVille Syrjälä int div;
173349cd97a3SVille Syrjälä
17347ff89ca2SVille Syrjälä bxt_de_pll_readout(display, cdclk_config);
17357ff89ca2SVille Syrjälä
1736d34927acSVille Syrjälä if (DISPLAY_VER(display) >= 12)
1737d34927acSVille Syrjälä cdclk_config->bypass = cdclk_config->ref / 2;
173877ab3a1eSMika Kahola else if (DISPLAY_VER(display) >= 11)
173977ab3a1eSMika Kahola cdclk_config->bypass = 50000;
174077ab3a1eSMika Kahola else
174177ab3a1eSMika Kahola cdclk_config->bypass = cdclk_config->ref;
174277ab3a1eSMika Kahola
174377ab3a1eSMika Kahola if (cdclk_config->vco == 0) {
174477ab3a1eSMika Kahola cdclk_config->cdclk = cdclk_config->bypass;
174577ab3a1eSMika Kahola goto out;
174677ab3a1eSMika Kahola }
174777ab3a1eSMika Kahola
174877ab3a1eSMika Kahola divider = intel_de_read(display, CDCLK_CTL) & BXT_CDCLK_CD2X_DIV_SEL_MASK;
17490bb94e03SVille Syrjälä
175077ab3a1eSMika Kahola switch (divider) {
17512123f442SVille Syrjälä case BXT_CDCLK_CD2X_DIV_SEL_1:
17522123f442SVille Syrjälä div = 2;
1753d34927acSVille Syrjälä break;
1754d34927acSVille Syrjälä case BXT_CDCLK_CD2X_DIV_SEL_1_5:
17552123f442SVille Syrjälä div = 3;
17562123f442SVille Syrjälä break;
17572123f442SVille Syrjälä case BXT_CDCLK_CD2X_DIV_SEL_2:
17582123f442SVille Syrjälä div = 4;
17590bb94e03SVille Syrjälä break;
1760d34927acSVille Syrjälä case BXT_CDCLK_CD2X_DIV_SEL_4:
17617ff89ca2SVille Syrjälä div = 8;
17627ff89ca2SVille Syrjälä break;
1763d34927acSVille Syrjälä default:
17647ff89ca2SVille Syrjälä MISSING_CASE(divider);
1765d34927acSVille Syrjälä return;
17667ff89ca2SVille Syrjälä }
17677ff89ca2SVille Syrjälä
1768d34927acSVille Syrjälä if (HAS_CDCLK_SQUASH(display))
17694cb3b44dSDaniele Ceraolo Spurio squash_ctl = intel_de_read(display, CDCLK_SQUASH_CTL);
1770d34927acSVille Syrjälä
17717ff89ca2SVille Syrjälä if (squash_ctl & CDCLK_SQUASH_ENABLE) {
1772d34927acSVille Syrjälä u16 waveform;
17737ff89ca2SVille Syrjälä int size;
17747ff89ca2SVille Syrjälä
1775d34927acSVille Syrjälä size = REG_FIELD_GET(CDCLK_SQUASH_WINDOW_SIZE_MASK, squash_ctl) + 1;
17767ff89ca2SVille Syrjälä waveform = REG_FIELD_GET(CDCLK_SQUASH_WAVEFORM_MASK, squash_ctl) >> (16 - size);
1777d34927acSVille Syrjälä
17787ff89ca2SVille Syrjälä cdclk_config->cdclk = DIV_ROUND_CLOSEST(hweight16(waveform) *
1779d34927acSVille Syrjälä cdclk_config->vco, size * div);
1780468f9e8dSVille Syrjälä } else {
17817ff89ca2SVille Syrjälä cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_config->vco, div);
1782d34927acSVille Syrjälä }
17837ff89ca2SVille Syrjälä
17847ff89ca2SVille Syrjälä out:
1785d34927acSVille Syrjälä if (DISPLAY_VER(display) >= 20)
17864cb3b44dSDaniele Ceraolo Spurio cdclk_config->joined_mbus = intel_de_read(display, MBUS_CTL) & MBUS_JOIN;
1787d34927acSVille Syrjälä /*
17887ff89ca2SVille Syrjälä * Can't read this out :( Let's assume it's
1789d34927acSVille Syrjälä * at least what the CDCLK frequency requires.
17907ff89ca2SVille Syrjälä */
17917ff89ca2SVille Syrjälä cdclk_config->voltage_level =
1792d34927acSVille Syrjälä intel_cdclk_calc_voltage_level(display, cdclk_config->cdclk);
17931cbcd3b4SMatt Roper }
1794d34927acSVille Syrjälä
bxt_de_pll_disable(struct intel_display * display)1795468f9e8dSVille Syrjälä static void bxt_de_pll_disable(struct intel_display *display)
17961cbcd3b4SMatt Roper {
17971cbcd3b4SMatt Roper intel_de_write(display, BXT_DE_PLL_ENABLE, 0);
1798d34927acSVille Syrjälä
1799d34927acSVille Syrjälä /* Timeout 200us */
18001cbcd3b4SMatt Roper if (intel_de_wait_for_clear(display,
1801d34927acSVille Syrjälä BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
18021cbcd3b4SMatt Roper drm_err(display->drm, "timeout waiting for DE PLL unlock\n");
18031cbcd3b4SMatt Roper
1804d34927acSVille Syrjälä display->cdclk.hw.vco = 0;
18051cbcd3b4SMatt Roper }
1806d34927acSVille Syrjälä
bxt_de_pll_enable(struct intel_display * display,int vco)18071cbcd3b4SMatt Roper static void bxt_de_pll_enable(struct intel_display *display, int vco)
18081cbcd3b4SMatt Roper {
18091d89509aSLucas De Marchi int ratio = DIV_ROUND_CLOSEST(vco, display->cdclk.hw.ref);
1810d34927acSVille Syrjälä
18111cbcd3b4SMatt Roper intel_de_rmw(display, BXT_DE_PLL_CTL,
18121cbcd3b4SMatt Roper BXT_DE_PLL_RATIO_MASK, BXT_DE_PLL_RATIO(ratio));
1813d34927acSVille Syrjälä
18141cbcd3b4SMatt Roper intel_de_write(display, BXT_DE_PLL_ENABLE, BXT_DE_PLL_PLL_ENABLE);
18151cbcd3b4SMatt Roper
1816d34927acSVille Syrjälä /* Timeout 200us */
1817d34927acSVille Syrjälä if (intel_de_wait_for_set(display,
18181cbcd3b4SMatt Roper BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
1819d34927acSVille Syrjälä drm_err(display->drm, "timeout waiting for DE PLL lock\n");
18201cbcd3b4SMatt Roper
18211cbcd3b4SMatt Roper display->cdclk.hw.vco = vco;
1822d34927acSVille Syrjälä }
1823d62686baSStanislav Lisovskiy
icl_cdclk_pll_disable(struct intel_display * display)1824d34927acSVille Syrjälä static void icl_cdclk_pll_disable(struct intel_display *display)
1825d62686baSStanislav Lisovskiy {
1826d62686baSStanislav Lisovskiy intel_de_rmw(display, BXT_DE_PLL_ENABLE,
1827d62686baSStanislav Lisovskiy BXT_DE_PLL_PLL_ENABLE, 0);
18281d89509aSLucas De Marchi
1829d34927acSVille Syrjälä /* Timeout 200us */
1830d62686baSStanislav Lisovskiy if (intel_de_wait_for_clear(display, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
1831d62686baSStanislav Lisovskiy drm_err(display->drm, "timeout waiting for CDCLK PLL unlock\n");
1832d62686baSStanislav Lisovskiy
1833d34927acSVille Syrjälä display->cdclk.hw.vco = 0;
1834d62686baSStanislav Lisovskiy }
1835d62686baSStanislav Lisovskiy
icl_cdclk_pll_enable(struct intel_display * display,int vco)1836d34927acSVille Syrjälä static void icl_cdclk_pll_enable(struct intel_display *display, int vco)
1837d62686baSStanislav Lisovskiy {
1838d34927acSVille Syrjälä int ratio = DIV_ROUND_CLOSEST(vco, display->cdclk.hw.ref);
1839d62686baSStanislav Lisovskiy u32 val;
1840d62686baSStanislav Lisovskiy
1841d34927acSVille Syrjälä val = ICL_CDCLK_PLL_RATIO(ratio);
1842d62686baSStanislav Lisovskiy intel_de_write(display, BXT_DE_PLL_ENABLE, val);
1843d34927acSVille Syrjälä
1844d62686baSStanislav Lisovskiy val |= BXT_DE_PLL_PLL_ENABLE;
1845d62686baSStanislav Lisovskiy intel_de_write(display, BXT_DE_PLL_ENABLE, val);
1846d34927acSVille Syrjälä
18470a12e437SVille Syrjälä /* Timeout 200us */
1848d34927acSVille Syrjälä if (intel_de_wait_for_set(display, BXT_DE_PLL_ENABLE, BXT_DE_PLL_LOCK, 1))
18490a12e437SVille Syrjälä drm_err(display->drm, "timeout waiting for CDCLK PLL lock\n");
18500a12e437SVille Syrjälä
18510a12e437SVille Syrjälä display->cdclk.hw.vco = vco;
18520a12e437SVille Syrjälä }
1853d34927acSVille Syrjälä
adlp_cdclk_pll_crawl(struct intel_display * display,int vco)18540a12e437SVille Syrjälä static void adlp_cdclk_pll_crawl(struct intel_display *display, int vco)
18550a12e437SVille Syrjälä {
18560a12e437SVille Syrjälä int ratio = DIV_ROUND_CLOSEST(vco, display->cdclk.hw.ref);
18570a12e437SVille Syrjälä u32 val;
18580a12e437SVille Syrjälä
18590a12e437SVille Syrjälä /* Write PLL ratio without disabling */
18600a12e437SVille Syrjälä val = ICL_CDCLK_PLL_RATIO(ratio) | BXT_DE_PLL_PLL_ENABLE;
18610a12e437SVille Syrjälä intel_de_write(display, BXT_DE_PLL_ENABLE, val);
18620a12e437SVille Syrjälä
18630a12e437SVille Syrjälä /* Submit freq change request */
18640a12e437SVille Syrjälä val |= BXT_DE_PLL_FREQ_REQ;
18650a12e437SVille Syrjälä intel_de_write(display, BXT_DE_PLL_ENABLE, val);
1866d34927acSVille Syrjälä
186726aba0d1SVille Syrjälä /* Timeout 200us */
1868b41df85aSVille Syrjälä if (intel_de_wait_for_set(display, BXT_DE_PLL_ENABLE,
1869b41df85aSVille Syrjälä BXT_DE_PLL_LOCK | BXT_DE_PLL_FREQ_REQ_ACK, 1))
187026aba0d1SVille Syrjälä drm_err(display->drm, "timeout waiting for FREQ change request ack\n");
1871b41df85aSVille Syrjälä
1872d34927acSVille Syrjälä val &= ~BXT_DE_PLL_FREQ_REQ;
1873d34927acSVille Syrjälä intel_de_write(display, BXT_DE_PLL_ENABLE, val);
1874d34927acSVille Syrjälä
1875b41df85aSVille Syrjälä display->cdclk.hw.vco = vco;
1876b41df85aSVille Syrjälä }
1877b41df85aSVille Syrjälä
bxt_cdclk_cd2x_pipe(struct intel_display * display,enum pipe pipe)1878b41df85aSVille Syrjälä static u32 bxt_cdclk_cd2x_pipe(struct intel_display *display, enum pipe pipe)
1879b41df85aSVille Syrjälä {
1880b41df85aSVille Syrjälä if (DISPLAY_VER(display) >= 12) {
1881b41df85aSVille Syrjälä if (pipe == INVALID_PIPE)
1882b41df85aSVille Syrjälä return TGL_CDCLK_CD2X_PIPE_NONE;
1883b41df85aSVille Syrjälä else
1884b41df85aSVille Syrjälä return TGL_CDCLK_CD2X_PIPE(pipe);
1885b41df85aSVille Syrjälä } else if (DISPLAY_VER(display) >= 11) {
1886b41df85aSVille Syrjälä if (pipe == INVALID_PIPE)
1887d34927acSVille Syrjälä return ICL_CDCLK_CD2X_PIPE_NONE;
18882060a689SMika Kahola else
18892060a689SMika Kahola return ICL_CDCLK_CD2X_PIPE(pipe);
1890d34927acSVille Syrjälä } else {
18912060a689SMika Kahola if (pipe == INVALID_PIPE)
18922060a689SMika Kahola return BXT_CDCLK_CD2X_PIPE_NONE;
1893d34927acSVille Syrjälä else
18942060a689SMika Kahola return BXT_CDCLK_CD2X_PIPE(pipe);
18952060a689SMika Kahola }
18962060a689SMika Kahola }
1897d34927acSVille Syrjälä
bxt_cdclk_cd2x_div_sel(struct intel_display * display,int cdclk,int vco,u16 waveform)18982060a689SMika Kahola static u32 bxt_cdclk_cd2x_div_sel(struct intel_display *display,
18992060a689SMika Kahola int cdclk, int vco, u16 waveform)
19002060a689SMika Kahola {
1901d34927acSVille Syrjälä /* cdclk = vco / 2 / div{1,1.5,2,4} */
1902d34927acSVille Syrjälä switch (cdclk_divider(cdclk, vco, waveform)) {
19032060a689SMika Kahola default:
19042060a689SMika Kahola drm_WARN_ON(display->drm,
19052060a689SMika Kahola cdclk != display->cdclk.hw.bypass);
19062060a689SMika Kahola drm_WARN_ON(display->drm, vco != 0);
1907d34927acSVille Syrjälä fallthrough;
19086688b6b1SAnusha Srivatsa case 2:
1909d34927acSVille Syrjälä return BXT_CDCLK_CD2X_DIV_SEL_1;
1910d34927acSVille Syrjälä case 3:
1911d34927acSVille Syrjälä return BXT_CDCLK_CD2X_DIV_SEL_1_5;
19126688b6b1SAnusha Srivatsa case 4:
1913d34927acSVille Syrjälä return BXT_CDCLK_CD2X_DIV_SEL_2;
1914d34927acSVille Syrjälä case 8:
19156688b6b1SAnusha Srivatsa return BXT_CDCLK_CD2X_DIV_SEL_4;
19166688b6b1SAnusha Srivatsa }
1917d34927acSVille Syrjälä }
19186688b6b1SAnusha Srivatsa
cdclk_squash_waveform(struct intel_display * display,int cdclk)1919d34927acSVille Syrjälä static u16 cdclk_squash_waveform(struct intel_display *display,
1920d34927acSVille Syrjälä int cdclk)
1921d34927acSVille Syrjälä {
19226688b6b1SAnusha Srivatsa const struct intel_cdclk_vals *table = display->cdclk.table;
1923d34927acSVille Syrjälä int i;
1924d34927acSVille Syrjälä
19256688b6b1SAnusha Srivatsa if (cdclk == display->cdclk.hw.bypass)
19266688b6b1SAnusha Srivatsa return 0;
1927d34927acSVille Syrjälä
1928fcfe55f2SAnusha Srivatsa for (i = 0; table[i].refclk; i++)
1929fcfe55f2SAnusha Srivatsa if (table[i].refclk == display->cdclk.hw.ref &&
1930fcfe55f2SAnusha Srivatsa table[i].cdclk == cdclk)
1931fcfe55f2SAnusha Srivatsa return table[i].waveform;
1932fcfe55f2SAnusha Srivatsa
1933fcfe55f2SAnusha Srivatsa drm_WARN(display->drm, 1, "cdclk %d not valid for refclk %u\n",
1934fcfe55f2SAnusha Srivatsa cdclk, display->cdclk.hw.ref);
1935fcfe55f2SAnusha Srivatsa
1936d34927acSVille Syrjälä return 0xffff;
1937fcfe55f2SAnusha Srivatsa }
1938fcfe55f2SAnusha Srivatsa
icl_cdclk_pll_update(struct intel_display * display,int vco)19399a0a4ec5SAnusha Srivatsa static void icl_cdclk_pll_update(struct intel_display *display, int vco)
19409a0a4ec5SAnusha Srivatsa {
19419a0a4ec5SAnusha Srivatsa if (display->cdclk.hw.vco != 0 &&
19429a0a4ec5SAnusha Srivatsa display->cdclk.hw.vco != vco)
19439a0a4ec5SAnusha Srivatsa icl_cdclk_pll_disable(display);
19449a0a4ec5SAnusha Srivatsa
19459a0a4ec5SAnusha Srivatsa if (display->cdclk.hw.vco != vco)
19469a0a4ec5SAnusha Srivatsa icl_cdclk_pll_enable(display, vco);
19479a0a4ec5SAnusha Srivatsa }
19489a0a4ec5SAnusha Srivatsa
bxt_cdclk_pll_update(struct intel_display * display,int vco)1949d34927acSVille Syrjälä static void bxt_cdclk_pll_update(struct intel_display *display, int vco)
19505372a54dSGustavo Sousa {
1951d34927acSVille Syrjälä if (display->cdclk.hw.vco != 0 &&
19525372a54dSGustavo Sousa display->cdclk.hw.vco != vco)
19535372a54dSGustavo Sousa bxt_de_pll_disable(display);
1954d34927acSVille Syrjälä
19555372a54dSGustavo Sousa if (display->cdclk.hw.vco != vco)
1956d34927acSVille Syrjälä bxt_de_pll_enable(display, vco);
19575372a54dSGustavo Sousa }
19585372a54dSGustavo Sousa
dg2_cdclk_squash_program(struct intel_display * display,u16 waveform)19595372a54dSGustavo Sousa static void dg2_cdclk_squash_program(struct intel_display *display,
19605372a54dSGustavo Sousa u16 waveform)
19615372a54dSGustavo Sousa {
1962d34927acSVille Syrjälä u32 squash_ctl = 0;
19639161e311SGustavo Sousa
19649161e311SGustavo Sousa if (waveform)
1965d34927acSVille Syrjälä squash_ctl = CDCLK_SQUASH_ENABLE |
19669161e311SGustavo Sousa CDCLK_SQUASH_WINDOW_SIZE(0xf) | waveform;
19679161e311SGustavo Sousa
19689161e311SGustavo Sousa intel_de_write(display, CDCLK_SQUASH_CTL, squash_ctl);
19699161e311SGustavo Sousa }
19709161e311SGustavo Sousa
cdclk_pll_is_unknown(unsigned int vco)19719161e311SGustavo Sousa static bool cdclk_pll_is_unknown(unsigned int vco)
1972d34927acSVille Syrjälä {
1973c834a080SGustavo Sousa /*
1974c834a080SGustavo Sousa * Ensure driver does not take the crawl path for the
19756fe8f9c1SJani Nikula * case when the vco is set to ~0 in the
1976d34927acSVille Syrjälä * sanitize path.
1977c834a080SGustavo Sousa */
1978c834a080SGustavo Sousa return vco == ~0;
1979c834a080SGustavo Sousa }
1980d34927acSVille Syrjälä
mdclk_source_is_cdclk_pll(struct intel_display * display)198125e0e5aeSVille Syrjälä static bool mdclk_source_is_cdclk_pll(struct intel_display *display)
198225e0e5aeSVille Syrjälä {
198325e0e5aeSVille Syrjälä return DISPLAY_VER(display) >= 20;
198425e0e5aeSVille Syrjälä }
198525e0e5aeSVille Syrjälä
xe2lpd_mdclk_source_sel(struct intel_display * display)1986c0151c69SVille Syrjälä static u32 xe2lpd_mdclk_source_sel(struct intel_display *display)
198725e0e5aeSVille Syrjälä {
198825e0e5aeSVille Syrjälä if (mdclk_source_is_cdclk_pll(display))
198925e0e5aeSVille Syrjälä return MDCLK_SOURCE_SEL_CDCLK_PLL;
199025e0e5aeSVille Syrjälä
199125e0e5aeSVille Syrjälä return MDCLK_SOURCE_SEL_CD2XCLK;
199225e0e5aeSVille Syrjälä }
1993d34927acSVille Syrjälä
intel_mdclk_cdclk_ratio(struct intel_display * display,const struct intel_cdclk_config * cdclk_config)199425e0e5aeSVille Syrjälä int intel_mdclk_cdclk_ratio(struct intel_display *display,
199525e0e5aeSVille Syrjälä const struct intel_cdclk_config *cdclk_config)
1996d34927acSVille Syrjälä {
1997d34927acSVille Syrjälä if (mdclk_source_is_cdclk_pll(display))
199825e0e5aeSVille Syrjälä return DIV_ROUND_UP(cdclk_config->vco, cdclk_config->cdclk);
199925e0e5aeSVille Syrjälä
200025e0e5aeSVille Syrjälä /* Otherwise, source for MDCLK is CD2XCLK. */
200125e0e5aeSVille Syrjälä return 2;
200225e0e5aeSVille Syrjälä }
200325e0e5aeSVille Syrjälä
xe2lpd_mdclk_cdclk_ratio_program(struct intel_display * display,const struct intel_cdclk_config * cdclk_config)200425e0e5aeSVille Syrjälä static void xe2lpd_mdclk_cdclk_ratio_program(struct intel_display *display,
2005c0151c69SVille Syrjälä const struct intel_cdclk_config *cdclk_config)
2006c0151c69SVille Syrjälä {
2007c0151c69SVille Syrjälä intel_dbuf_mdclk_cdclk_ratio_update(display,
2008c0151c69SVille Syrjälä intel_mdclk_cdclk_ratio(display, cdclk_config),
2009c0151c69SVille Syrjälä cdclk_config->joined_mbus);
2010c0151c69SVille Syrjälä }
2011c0151c69SVille Syrjälä
cdclk_compute_crawl_and_squash_midpoint(struct intel_display * display,const struct intel_cdclk_config * old_cdclk_config,const struct intel_cdclk_config * new_cdclk_config,struct intel_cdclk_config * mid_cdclk_config)2012c0151c69SVille Syrjälä static bool cdclk_compute_crawl_and_squash_midpoint(struct intel_display *display,
2013c0151c69SVille Syrjälä const struct intel_cdclk_config *old_cdclk_config,
2014d34927acSVille Syrjälä const struct intel_cdclk_config *new_cdclk_config,
2015c0151c69SVille Syrjälä struct intel_cdclk_config *mid_cdclk_config)
2016c0151c69SVille Syrjälä {
201725e0e5aeSVille Syrjälä u16 old_waveform, new_waveform, mid_waveform;
201825e0e5aeSVille Syrjälä int old_div, new_div, mid_div;
201925e0e5aeSVille Syrjälä
202025e0e5aeSVille Syrjälä /* Return if PLL is in an unknown state, force a complete disable and re-enable. */
202125e0e5aeSVille Syrjälä if (cdclk_pll_is_unknown(old_cdclk_config->vco))
202225e0e5aeSVille Syrjälä return false;
202325e0e5aeSVille Syrjälä
202425e0e5aeSVille Syrjälä /* Return if both Squash and Crawl are not present */
202525e0e5aeSVille Syrjälä if (!HAS_CDCLK_CRAWL(display) || !HAS_CDCLK_SQUASH(display))
202625e0e5aeSVille Syrjälä return false;
202725e0e5aeSVille Syrjälä
202825e0e5aeSVille Syrjälä old_waveform = cdclk_squash_waveform(display, old_cdclk_config->cdclk);
2029c0151c69SVille Syrjälä new_waveform = cdclk_squash_waveform(display, new_cdclk_config->cdclk);
203025e0e5aeSVille Syrjälä
203125e0e5aeSVille Syrjälä /* Return if Squash only or Crawl only is the desired action */
203225e0e5aeSVille Syrjälä if (old_cdclk_config->vco == 0 || new_cdclk_config->vco == 0 ||
2033c0151c69SVille Syrjälä old_cdclk_config->vco == new_cdclk_config->vco ||
203425e0e5aeSVille Syrjälä old_waveform == new_waveform)
203525e0e5aeSVille Syrjälä return false;
203625e0e5aeSVille Syrjälä
203725e0e5aeSVille Syrjälä old_div = cdclk_divider(old_cdclk_config->cdclk,
203825815473SVille Syrjälä old_cdclk_config->vco, old_waveform);
2039c0151c69SVille Syrjälä new_div = cdclk_divider(new_cdclk_config->cdclk,
204025e0e5aeSVille Syrjälä new_cdclk_config->vco, new_waveform);
204125e0e5aeSVille Syrjälä
204225e0e5aeSVille Syrjälä /*
2043d34927acSVille Syrjälä * Should not happen currently. We might need more midpoint
204425e0e5aeSVille Syrjälä * transitions if we need to also change the cd2x divider.
2045d34927acSVille Syrjälä */
2046d34927acSVille Syrjälä if (drm_WARN_ON(display->drm, old_div != new_div))
2047d34927acSVille Syrjälä return false;
204825e0e5aeSVille Syrjälä
204925e0e5aeSVille Syrjälä *mid_cdclk_config = *new_cdclk_config;
205025e0e5aeSVille Syrjälä
205125e0e5aeSVille Syrjälä /*
205225e0e5aeSVille Syrjälä * Populate the mid_cdclk_config accordingly.
2053d34927acSVille Syrjälä * - If moving to a higher cdclk, the desired action is squashing.
205433d0c67dSStanislav Lisovskiy * The mid cdclk config should have the new (squash) waveform.
20555eb2e785SJani Nikula * - If moving to a lower cdclk, the desired action is crawling.
20565eb2e785SJani Nikula * The mid cdclk config should have the new vco.
2057f0453266SJani Nikula */
2058d34927acSVille Syrjälä
205933d0c67dSStanislav Lisovskiy if (cdclk_squash_divider(new_waveform) > cdclk_squash_divider(old_waveform)) {
206033d0c67dSStanislav Lisovskiy mid_cdclk_config->vco = old_cdclk_config->vco;
2061d34927acSVille Syrjälä mid_div = old_div;
20620bb94e03SVille Syrjälä mid_waveform = new_waveform;
206359f9e9caSVille Syrjälä } else {
20647ff89ca2SVille Syrjälä mid_cdclk_config->vco = new_cdclk_config->vco;
20650bb94e03SVille Syrjälä mid_div = new_div;
20660bb94e03SVille Syrjälä mid_waveform = old_waveform;
20672060a689SMika Kahola }
2068e1a914aeSVille Syrjälä
20691cbcd3b4SMatt Roper mid_cdclk_config->cdclk = DIV_ROUND_CLOSEST(cdclk_squash_divider(mid_waveform) *
2070d34927acSVille Syrjälä mid_cdclk_config->vco,
20717af2f3e5SGustavo Sousa cdclk_squash_len * mid_div);
2072d34927acSVille Syrjälä
2073d34927acSVille Syrjälä /* make sure the mid clock came out sane */
20747af2f3e5SGustavo Sousa
20757af2f3e5SGustavo Sousa drm_WARN_ON(display->drm, mid_cdclk_config->cdclk <
20767af2f3e5SGustavo Sousa min(old_cdclk_config->cdclk, new_cdclk_config->cdclk));
20777af2f3e5SGustavo Sousa drm_WARN_ON(display->drm, mid_cdclk_config->cdclk >
20787af2f3e5SGustavo Sousa display->cdclk.max_cdclk_freq);
2079f0453266SJani Nikula drm_WARN_ON(display->drm, cdclk_squash_waveform(display, mid_cdclk_config->cdclk) !=
20807af2f3e5SGustavo Sousa mid_waveform);
20817af2f3e5SGustavo Sousa
20827af2f3e5SGustavo Sousa return true;
2083d34927acSVille Syrjälä }
2084d34927acSVille Syrjälä
pll_enable_wa_needed(struct intel_display * display)20857af2f3e5SGustavo Sousa static bool pll_enable_wa_needed(struct intel_display *display)
20867af2f3e5SGustavo Sousa {
20877af2f3e5SGustavo Sousa return (DISPLAY_VERx100(display) == 2000 ||
20887af2f3e5SGustavo Sousa DISPLAY_VERx100(display) == 1400 ||
20897af2f3e5SGustavo Sousa display->platform.dg2) &&
20907af2f3e5SGustavo Sousa display->cdclk.hw.vco > 0;
2091d34927acSVille Syrjälä }
20927af2f3e5SGustavo Sousa
bxt_cdclk_ctl(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)20937af2f3e5SGustavo Sousa static u32 bxt_cdclk_ctl(struct intel_display *display,
20947af2f3e5SGustavo Sousa const struct intel_cdclk_config *cdclk_config,
20957af2f3e5SGustavo Sousa enum pipe pipe)
20967af2f3e5SGustavo Sousa {
20977af2f3e5SGustavo Sousa int cdclk = cdclk_config->cdclk;
2098d34927acSVille Syrjälä int vco = cdclk_config->vco;
2099d34927acSVille Syrjälä u16 waveform;
2100d34927acSVille Syrjälä u32 val;
2101d34927acSVille Syrjälä
2102d34927acSVille Syrjälä waveform = cdclk_squash_waveform(display, cdclk);
210333d0c67dSStanislav Lisovskiy
2104d34927acSVille Syrjälä val = bxt_cdclk_cd2x_div_sel(display, cdclk, vco, waveform) |
2105d34927acSVille Syrjälä bxt_cdclk_cd2x_pipe(display, pipe);
210633d0c67dSStanislav Lisovskiy
2107d34927acSVille Syrjälä /*
210825dd5e98SVille Syrjälä * Disable SSA Precharge when CD clock frequency < 500 MHz,
2109d34927acSVille Syrjälä * enable otherwise.
211025dd5e98SVille Syrjälä */
21117ff89ca2SVille Syrjälä if ((display->platform.geminilake || display->platform.broxton) &&
2112d34927acSVille Syrjälä cdclk >= 500000)
2113d34927acSVille Syrjälä val |= BXT_CDCLK_SSA_PRECHARGE_ENABLE;
21142060a689SMika Kahola
2115d34927acSVille Syrjälä if (DISPLAY_VER(display) >= 20)
2116452269e2SGustavo Sousa val |= xe2lpd_mdclk_source_sel(display);
21172060a689SMika Kahola else
2118d34927acSVille Syrjälä val |= skl_cdclk_decimal(cdclk);
21197ff89ca2SVille Syrjälä
212059f9e9caSVille Syrjälä return val;
2121138d2bdaSJani Nikula }
212225e0e5aeSVille Syrjälä
_bxt_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)212359f9e9caSVille Syrjälä static void _bxt_set_cdclk(struct intel_display *display,
2124d34927acSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
212525e0e5aeSVille Syrjälä enum pipe pipe)
212625e0e5aeSVille Syrjälä {
212725e0e5aeSVille Syrjälä int cdclk = cdclk_config->cdclk;
2128d34927acSVille Syrjälä int vco = cdclk_config->vco;
212925e0e5aeSVille Syrjälä
213025e0e5aeSVille Syrjälä if (HAS_CDCLK_CRAWL(display) && display->cdclk.hw.vco > 0 && vco > 0 &&
213125e0e5aeSVille Syrjälä !cdclk_pll_is_unknown(display->cdclk.hw.vco)) {
213225e0e5aeSVille Syrjälä if (display->cdclk.hw.vco != vco)
213325e0e5aeSVille Syrjälä adlp_cdclk_pll_crawl(display, vco);
213425e0e5aeSVille Syrjälä } else if (DISPLAY_VER(display) >= 11) {
213525e0e5aeSVille Syrjälä /* wa_15010685871: dg2, mtl */
213625e0e5aeSVille Syrjälä if (pll_enable_wa_needed(display))
213725e0e5aeSVille Syrjälä dg2_cdclk_squash_program(display, 0);
213825e0e5aeSVille Syrjälä
2139f0453266SJani Nikula icl_cdclk_pll_update(display, vco);
2140f0453266SJani Nikula } else {
2141d34927acSVille Syrjälä bxt_cdclk_pll_update(display, vco);
214225e0e5aeSVille Syrjälä }
214325e0e5aeSVille Syrjälä
214425e0e5aeSVille Syrjälä if (HAS_CDCLK_SQUASH(display)) {
214525e0e5aeSVille Syrjälä u16 waveform = cdclk_squash_waveform(display, cdclk);
214625e0e5aeSVille Syrjälä
214725e0e5aeSVille Syrjälä dg2_cdclk_squash_program(display, waveform);
214825e0e5aeSVille Syrjälä }
214925e0e5aeSVille Syrjälä
215025e0e5aeSVille Syrjälä intel_de_write(display, CDCLK_CTL, bxt_cdclk_ctl(display, cdclk_config, pipe));
215125e0e5aeSVille Syrjälä
215225e0e5aeSVille Syrjälä if (pipe != INVALID_PIPE)
215325e0e5aeSVille Syrjälä intel_crtc_wait_for_next_vblank(intel_crtc_for_pipe(display, pipe));
215425e0e5aeSVille Syrjälä }
215525e0e5aeSVille Syrjälä
bxt_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe)2156d34927acSVille Syrjälä static void bxt_set_cdclk(struct intel_display *display,
215725e0e5aeSVille Syrjälä const struct intel_cdclk_config *cdclk_config,
215825e0e5aeSVille Syrjälä enum pipe pipe)
215925e0e5aeSVille Syrjälä {
216025e0e5aeSVille Syrjälä struct intel_cdclk_config mid_cdclk_config;
216125e0e5aeSVille Syrjälä int cdclk = cdclk_config->cdclk;
2162d34927acSVille Syrjälä int ret = 0;
2163d34927acSVille Syrjälä
2164c834a080SGustavo Sousa /*
2165d34927acSVille Syrjälä * Inform power controller of upcoming frequency change.
216625e0e5aeSVille Syrjälä * Display versions 14 and beyond do not follow the PUnit
2167d34927acSVille Syrjälä * mailbox communication, skip
2168d34927acSVille Syrjälä * this step.
216925e0e5aeSVille Syrjälä */
2170d34927acSVille Syrjälä if (DISPLAY_VER(display) >= 14 || display->platform.dg2)
217125e0e5aeSVille Syrjälä ; /* NOOP */
217225e0e5aeSVille Syrjälä else if (DISPLAY_VER(display) >= 11)
2173d34927acSVille Syrjälä ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
2174d34927acSVille Syrjälä SKL_CDCLK_PREPARE_FOR_CHANGE,
2175c834a080SGustavo Sousa SKL_CDCLK_READY_FOR_CHANGE,
2176d34927acSVille Syrjälä SKL_CDCLK_READY_FOR_CHANGE, 3);
217725e0e5aeSVille Syrjälä else
217825e0e5aeSVille Syrjälä /*
217925e0e5aeSVille Syrjälä * BSpec requires us to wait up to 150usec, but that leads to
218025e0e5aeSVille Syrjälä * timeouts; the 2ms used here is based on experiment.
2181f0453266SJani Nikula */
2182ee421bb4SAshutosh Dixit ret = intel_pcode_write_timeout(display->drm,
21830bb94e03SVille Syrjälä HSW_PCODE_DE_WRITE_FREQ_REQ,
2184d34927acSVille Syrjälä 0x80000000, 2);
2185e76019a8SImre Deak
2186e76019a8SImre Deak if (ret) {
2187e76019a8SImre Deak drm_err(display->drm,
21881cbcd3b4SMatt Roper "Failed to inform PCU about cdclk change (err %d, freq %d)\n",
21891cbcd3b4SMatt Roper ret, cdclk);
2190e76019a8SImre Deak return;
2191ee421bb4SAshutosh Dixit }
2192e76019a8SImre Deak
21930bb94e03SVille Syrjälä if (DISPLAY_VER(display) >= 20 && cdclk < display->cdclk.hw.cdclk)
21941cbcd3b4SMatt Roper xe2lpd_mdclk_cdclk_ratio_program(display, cdclk_config);
2195ceb0cc3bSStanislav Lisovskiy
21967ff89ca2SVille Syrjälä if (cdclk_compute_crawl_and_squash_midpoint(display, &display->cdclk.hw,
2197d34927acSVille Syrjälä cdclk_config, &mid_cdclk_config)) {
219823194610SWambui Karuga _bxt_set_cdclk(display, &mid_cdclk_config, pipe);
21997ff89ca2SVille Syrjälä _bxt_set_cdclk(display, cdclk_config, pipe);
22007ff89ca2SVille Syrjälä } else {
22017ff89ca2SVille Syrjälä _bxt_set_cdclk(display, cdclk_config, pipe);
22027ff89ca2SVille Syrjälä }
2203d34927acSVille Syrjälä
22041cbcd3b4SMatt Roper if (DISPLAY_VER(display) >= 20 && cdclk > display->cdclk.hw.cdclk)
2205d34927acSVille Syrjälä xe2lpd_mdclk_cdclk_ratio_program(display, cdclk_config);
22061cbcd3b4SMatt Roper
22071cbcd3b4SMatt Roper if (DISPLAY_VER(display) >= 14)
22081cbcd3b4SMatt Roper /*
22091cbcd3b4SMatt Roper * NOOP - No Pcode communication needed for
2210d34927acSVille Syrjälä * Display versions 14 and beyond
22117ff89ca2SVille Syrjälä */;
22127ff89ca2SVille Syrjälä else if (DISPLAY_VER(display) >= 11 && !display->platform.dg2)
2213d34927acSVille Syrjälä ret = intel_pcode_write(display->drm, SKL_PCODE_CDCLK_CONTROL,
22147ff89ca2SVille Syrjälä cdclk_config->voltage_level);
22157ff89ca2SVille Syrjälä if (DISPLAY_VER(display) < 11) {
2216935e486bSGustavo Sousa /*
22177ff89ca2SVille Syrjälä * The timeout isn't specified, the 2ms used here is based on
2218d34927acSVille Syrjälä * experiment.
2219d34927acSVille Syrjälä * FIXME: Waiting for the request completion could be delayed
22207ff89ca2SVille Syrjälä * until the next PCODE request based on BSpec.
2221d34927acSVille Syrjälä */
2222d34927acSVille Syrjälä ret = intel_pcode_write_timeout(display->drm,
22237ff89ca2SVille Syrjälä HSW_PCODE_DE_WRITE_FREQ_REQ,
22247ff89ca2SVille Syrjälä cdclk_config->voltage_level, 2);
22258f9f717dSMatt Roper }
2226d34927acSVille Syrjälä if (ret) {
2227d34927acSVille Syrjälä drm_err(display->drm,
22288f9f717dSMatt Roper "PCode CDCLK freq set failed, (err %d, freq %d)\n",
22298f9f717dSMatt Roper ret, cdclk);
22308f9f717dSMatt Roper return;
2231d34927acSVille Syrjälä }
2232d34927acSVille Syrjälä
22338f9f717dSMatt Roper intel_update_cdclk(display);
22348f9f717dSMatt Roper
2235ebb9c424SGustavo Sousa if (DISPLAY_VER(display) >= 11)
2236ebb9c424SGustavo Sousa /*
2237ebb9c424SGustavo Sousa * Can't read out the voltage level :(
2238ebb9c424SGustavo Sousa * Let's just assume everything is as expected.
2239ebb9c424SGustavo Sousa */
2240d34927acSVille Syrjälä display->cdclk.hw.voltage_level = cdclk_config->voltage_level;
2241d34927acSVille Syrjälä }
2242ebb9c424SGustavo Sousa
bxt_sanitize_cdclk(struct intel_display * display)2243ebb9c424SGustavo Sousa static void bxt_sanitize_cdclk(struct intel_display *display)
2244ebb9c424SGustavo Sousa {
2245c55af006SNitin Gote u32 cdctl, expected;
2246ebb9c424SGustavo Sousa int cdclk, vco;
2247ebb9c424SGustavo Sousa
2248d34927acSVille Syrjälä intel_update_cdclk(display);
2249d34927acSVille Syrjälä intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
22507ff89ca2SVille Syrjälä
22517ff89ca2SVille Syrjälä if (display->cdclk.hw.vco == 0 ||
22527ff89ca2SVille Syrjälä display->cdclk.hw.cdclk == display->cdclk.hw.bypass)
22537ff89ca2SVille Syrjälä goto sanitize;
22547ff89ca2SVille Syrjälä
22557ff89ca2SVille Syrjälä /* Make sure this is a legal cdclk value for the platform */
2256d34927acSVille Syrjälä cdclk = bxt_calc_cdclk(display, display->cdclk.hw.cdclk);
22577ff89ca2SVille Syrjälä if (cdclk != display->cdclk.hw.cdclk)
22587ff89ca2SVille Syrjälä goto sanitize;
2259d34927acSVille Syrjälä
22607ff89ca2SVille Syrjälä /* Make sure the VCO is correct for the cdclk */
22617ff89ca2SVille Syrjälä vco = bxt_calc_cdclk_pll_vco(display, cdclk);
2262d34927acSVille Syrjälä if (vco != display->cdclk.hw.vco)
22637ff89ca2SVille Syrjälä goto sanitize;
22647ff89ca2SVille Syrjälä
2265d34927acSVille Syrjälä /*
22667ff89ca2SVille Syrjälä * Some BIOS versions leave an incorrect decimal frequency value and
22670bb94e03SVille Syrjälä * set reserved MBZ bits in CDCLK_CTL at least during exiting from S4,
22687ff89ca2SVille Syrjälä * so sanitize this register.
2269d34927acSVille Syrjälä */
22707ff89ca2SVille Syrjälä cdctl = intel_de_read(display, CDCLK_CTL);
2271d34927acSVille Syrjälä expected = bxt_cdclk_ctl(display, &display->cdclk.hw, INVALID_PIPE);
2272d34927acSVille Syrjälä
22737ff89ca2SVille Syrjälä /*
22747ff89ca2SVille Syrjälä * Let's ignore the pipe field, since BIOS could have configured the
2275d34927acSVille Syrjälä * dividers both syncing to an active pipe, or asynchronously
227683c5fda7SVille Syrjälä * (PIPE_NONE).
22777ff89ca2SVille Syrjälä */
22787ff89ca2SVille Syrjälä cdctl &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
22797ff89ca2SVille Syrjälä expected &= ~bxt_cdclk_cd2x_pipe(display, INVALID_PIPE);
22807ff89ca2SVille Syrjälä
22817ff89ca2SVille Syrjälä if (cdctl == expected)
2282d34927acSVille Syrjälä /* All well; nothing to sanitize */
2283d34927acSVille Syrjälä return;
22840bb94e03SVille Syrjälä
2285d34927acSVille Syrjälä sanitize:
22867ff89ca2SVille Syrjälä drm_dbg_kms(display->drm, "Sanitizing cdclk programmed by pre-os\n");
2287d34927acSVille Syrjälä
22887ff89ca2SVille Syrjälä /* force cdclk programming */
22897ff89ca2SVille Syrjälä display->cdclk.hw.cdclk = 0;
2290d34927acSVille Syrjälä
22917ff89ca2SVille Syrjälä /* force full PLL disable + enable */
2292d34927acSVille Syrjälä display->cdclk.hw.vco = ~0;
229383c5fda7SVille Syrjälä }
22940bb94e03SVille Syrjälä
bxt_cdclk_init_hw(struct intel_display * display)22950bb94e03SVille Syrjälä static void bxt_cdclk_init_hw(struct intel_display *display)
22960bb94e03SVille Syrjälä {
2297d34927acSVille Syrjälä struct intel_cdclk_config cdclk_config;
229883c5fda7SVille Syrjälä
2299d34927acSVille Syrjälä bxt_sanitize_cdclk(display);
230049cd97a3SVille Syrjälä
230149cd97a3SVille Syrjälä if (display->cdclk.hw.cdclk != 0 &&
230249cd97a3SVille Syrjälä display->cdclk.hw.vco != 0)
2303ed645eeeSVille Syrjälä return;
2304d34927acSVille Syrjälä
230593a643f2SJani Nikula cdclk_config = display->cdclk.hw;
2306d34927acSVille Syrjälä
230793a643f2SJani Nikula /*
230893a643f2SJani Nikula * FIXME:
230993a643f2SJani Nikula * - The initial CDCLK needs to be read from VBT.
231093a643f2SJani Nikula * Need to make this change after VBT has changes for BXT.
2311d34927acSVille Syrjälä */
231293a643f2SJani Nikula cdclk_config.cdclk = bxt_calc_cdclk(display, 0);
2313f0453266SJani Nikula cdclk_config.vco = bxt_calc_cdclk_pll_vco(display, cdclk_config.cdclk);
2314d34927acSVille Syrjälä cdclk_config.voltage_level =
2315d34927acSVille Syrjälä intel_cdclk_calc_voltage_level(display, cdclk_config.cdclk);
2316d34927acSVille Syrjälä
231793a643f2SJani Nikula bxt_set_cdclk(display, &cdclk_config, INVALID_PIPE);
231893a643f2SJani Nikula }
231993a643f2SJani Nikula
bxt_cdclk_uninit_hw(struct intel_display * display)2320ed645eeeSVille Syrjälä static void bxt_cdclk_uninit_hw(struct intel_display *display)
2321d34927acSVille Syrjälä {
232293a643f2SJani Nikula struct intel_cdclk_config cdclk_config = display->cdclk.hw;
232393a643f2SJani Nikula
232493a643f2SJani Nikula cdclk_config.cdclk = cdclk_config.bypass;
232593a643f2SJani Nikula cdclk_config.vco = 0;
2326d34927acSVille Syrjälä cdclk_config.voltage_level =
232793a643f2SJani Nikula intel_cdclk_calc_voltage_level(display, cdclk_config.cdclk);
2328f0453266SJani Nikula
2329d34927acSVille Syrjälä bxt_set_cdclk(display, &cdclk_config, INVALID_PIPE);
2330d34927acSVille Syrjälä }
2331d34927acSVille Syrjälä
233293a643f2SJani Nikula /**
233393a643f2SJani Nikula * intel_cdclk_init_hw - Initialize CDCLK hardware
2334d34927acSVille Syrjälä * @display: display instance
233525e0e5aeSVille Syrjälä *
233625e0e5aeSVille Syrjälä * Initialize CDCLK. This consists mainly of initializing display->cdclk.hw and
233725e0e5aeSVille Syrjälä * sanitizing the state of the hardware if needed. This is generally done only
233825e0e5aeSVille Syrjälä * during the display core initialization sequence, after which the DMC will
233925e0e5aeSVille Syrjälä * take care of turning CDCLK off/on as needed.
234025e0e5aeSVille Syrjälä */
intel_cdclk_init_hw(struct intel_display * display)2341d34927acSVille Syrjälä void intel_cdclk_init_hw(struct intel_display *display)
234225e0e5aeSVille Syrjälä {
234325e0e5aeSVille Syrjälä if (DISPLAY_VER(display) >= 10 || display->platform.broxton)
234425e0e5aeSVille Syrjälä bxt_cdclk_init_hw(display);
234525e0e5aeSVille Syrjälä else if (DISPLAY_VER(display) == 9)
2346d34927acSVille Syrjälä skl_cdclk_init_hw(display);
234725e0e5aeSVille Syrjälä }
234825e0e5aeSVille Syrjälä
2349d34927acSVille Syrjälä /**
2350d34927acSVille Syrjälä * intel_cdclk_uninit_hw - Uninitialize CDCLK hardware
235125e0e5aeSVille Syrjälä * @display: display instance
235225e0e5aeSVille Syrjälä *
235325e0e5aeSVille Syrjälä * Uninitialize CDCLK. This is done only during the display core
235425e0e5aeSVille Syrjälä * uninitialization sequence.
235525e0e5aeSVille Syrjälä */
intel_cdclk_uninit_hw(struct intel_display * display)2356d34927acSVille Syrjälä void intel_cdclk_uninit_hw(struct intel_display *display)
2357d62686baSStanislav Lisovskiy {
2358d62686baSStanislav Lisovskiy if (DISPLAY_VER(display) >= 10 || display->platform.broxton)
2359d62686baSStanislav Lisovskiy bxt_cdclk_uninit_hw(display);
2360d62686baSStanislav Lisovskiy else if (DISPLAY_VER(display) == 9)
2361d62686baSStanislav Lisovskiy skl_cdclk_uninit_hw(display);
2362d34927acSVille Syrjälä }
2363d62686baSStanislav Lisovskiy
intel_cdclk_can_crawl_and_squash(struct intel_display * display,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2364d62686baSStanislav Lisovskiy static bool intel_cdclk_can_crawl_and_squash(struct intel_display *display,
2365d62686baSStanislav Lisovskiy const struct intel_cdclk_config *a,
2366d62686baSStanislav Lisovskiy const struct intel_cdclk_config *b)
2367d62686baSStanislav Lisovskiy {
2368d62686baSStanislav Lisovskiy u16 old_waveform;
2369d62686baSStanislav Lisovskiy u16 new_waveform;
2370d62686baSStanislav Lisovskiy
2371d62686baSStanislav Lisovskiy drm_WARN_ON(display->drm, cdclk_pll_is_unknown(a->vco));
2372d62686baSStanislav Lisovskiy
2373d62686baSStanislav Lisovskiy if (a->vco == 0 || b->vco == 0)
2374d62686baSStanislav Lisovskiy return false;
2375d62686baSStanislav Lisovskiy
2376d62686baSStanislav Lisovskiy if (!HAS_CDCLK_CRAWL(display) || !HAS_CDCLK_SQUASH(display))
2377d62686baSStanislav Lisovskiy return false;
2378d34927acSVille Syrjälä
2379d4a23930SVille Syrjälä old_waveform = cdclk_squash_waveform(display, a->cdclk);
2380d4a23930SVille Syrjälä new_waveform = cdclk_squash_waveform(display, b->cdclk);
2381d4a23930SVille Syrjälä
2382d4a23930SVille Syrjälä return a->vco != b->vco &&
2383d4a23930SVille Syrjälä old_waveform != new_waveform;
2384d4a23930SVille Syrjälä }
2385d4a23930SVille Syrjälä
intel_cdclk_can_crawl(struct intel_display * display,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2386d4a23930SVille Syrjälä static bool intel_cdclk_can_crawl(struct intel_display *display,
2387d4a23930SVille Syrjälä const struct intel_cdclk_config *a,
2388d34927acSVille Syrjälä const struct intel_cdclk_config *b)
2389d4a23930SVille Syrjälä {
2390d4a23930SVille Syrjälä int a_div, b_div;
2391d4a23930SVille Syrjälä
2392d4a23930SVille Syrjälä if (!HAS_CDCLK_CRAWL(display))
2393d4a23930SVille Syrjälä return false;
2394d4a23930SVille Syrjälä
2395d4a23930SVille Syrjälä /*
2396d4a23930SVille Syrjälä * The vco and cd2x divider will change independently
239793a643f2SJani Nikula * from each, so we disallow cd2x change when crawling.
2398669cf07dSGustavo Sousa */
23990bb94e03SVille Syrjälä a_div = DIV_ROUND_CLOSEST(a->vco, a->cdclk);
24000bb94e03SVille Syrjälä b_div = DIV_ROUND_CLOSEST(b->vco, b->cdclk);
240149cd97a3SVille Syrjälä
240249cd97a3SVille Syrjälä return a->vco != 0 && b->vco != 0 &&
2403669cf07dSGustavo Sousa a->vco != b->vco &&
2404669cf07dSGustavo Sousa a_div == b_div &&
240549cd97a3SVille Syrjälä a->ref == b->ref;
2406669cf07dSGustavo Sousa }
24070bb94e03SVille Syrjälä
intel_cdclk_can_squash(struct intel_display * display,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)240849cd97a3SVille Syrjälä static bool intel_cdclk_can_squash(struct intel_display *display,
240964600bd5SVille Syrjälä const struct intel_cdclk_config *a,
241064600bd5SVille Syrjälä const struct intel_cdclk_config *b)
241164600bd5SVille Syrjälä {
241264600bd5SVille Syrjälä /*
241364600bd5SVille Syrjälä * FIXME should store a bit more state in intel_cdclk_config
241464600bd5SVille Syrjälä * to differentiate squasher vs. cd2x divider properly. For
24150bb94e03SVille Syrjälä * the moment all platforms with squasher use a fixed cd2x
24160bb94e03SVille Syrjälä * divider.
2417d34927acSVille Syrjälä */
24180bb94e03SVille Syrjälä if (!HAS_CDCLK_SQUASH(display))
24190bb94e03SVille Syrjälä return false;
242059f9e9caSVille Syrjälä
242159f9e9caSVille Syrjälä return a->cdclk != b->cdclk &&
24220bb94e03SVille Syrjälä a->vco != 0 &&
24230bb94e03SVille Syrjälä a->vco == b->vco &&
242459f9e9caSVille Syrjälä a->ref == b->ref;
2425d34927acSVille Syrjälä }
24260bb94e03SVille Syrjälä
24270bb94e03SVille Syrjälä /**
242859f9e9caSVille Syrjälä * intel_cdclk_clock_changed - Check whether the clock changed
242959f9e9caSVille Syrjälä * @a: first CDCLK configuration
2430f0453266SJani Nikula * @b: second CDCLK configuration
243159f9e9caSVille Syrjälä *
243259f9e9caSVille Syrjälä * Returns:
2433d4a23930SVille Syrjälä * True if CDCLK changed in a way that requires re-programming and
2434d4a23930SVille Syrjälä * False otherwise.
2435d4a23930SVille Syrjälä */
intel_cdclk_clock_changed(const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2436d4a23930SVille Syrjälä bool intel_cdclk_clock_changed(const struct intel_cdclk_config *a,
2437d4a23930SVille Syrjälä const struct intel_cdclk_config *b)
2438d4a23930SVille Syrjälä {
2439d34927acSVille Syrjälä return a->cdclk != b->cdclk ||
2440d4a23930SVille Syrjälä a->vco != b->vco ||
2441d4a23930SVille Syrjälä a->ref != b->ref;
244259f9e9caSVille Syrjälä }
2443d4a23930SVille Syrjälä
244459f9e9caSVille Syrjälä /**
244559f9e9caSVille Syrjälä * intel_cdclk_can_cd2x_update - Determine if changing between the two CDCLK
244659f9e9caSVille Syrjälä * configurations requires only a cd2x divider update
244759f9e9caSVille Syrjälä * @display: display instance
244859f9e9caSVille Syrjälä * @a: first CDCLK configuration
24490bb94e03SVille Syrjälä * @b: second CDCLK configuration
24500bb94e03SVille Syrjälä *
24510bb94e03SVille Syrjälä * Returns:
245264600bd5SVille Syrjälä * True if changing between the two CDCLK configurations
245364600bd5SVille Syrjälä * can be done with just a cd2x divider update, false if not.
24540bb94e03SVille Syrjälä */
intel_cdclk_can_cd2x_update(struct intel_display * display,const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)245564600bd5SVille Syrjälä static bool intel_cdclk_can_cd2x_update(struct intel_display *display,
24560bb94e03SVille Syrjälä const struct intel_cdclk_config *a,
24570bb94e03SVille Syrjälä const struct intel_cdclk_config *b)
245864600bd5SVille Syrjälä {
2459669cf07dSGustavo Sousa /* Older hw doesn't have the capability */
246064600bd5SVille Syrjälä if (DISPLAY_VER(display) < 10 && !display->platform.broxton)
24617ff89ca2SVille Syrjälä return false;
24627ff89ca2SVille Syrjälä
2463d34927acSVille Syrjälä /*
2464140f70aeSJani Nikula * FIXME should store a bit more state in intel_cdclk_config
2465cfddadc9SVille Syrjälä * to differentiate squasher vs. cd2x divider properly. For
2466cfddadc9SVille Syrjälä * the moment all platforms with squasher use a fixed cd2x
2467d34927acSVille Syrjälä * divider.
24680bb94e03SVille Syrjälä */
24690bb94e03SVille Syrjälä if (HAS_CDCLK_SQUASH(display))
24700bb94e03SVille Syrjälä return false;
2471cfddadc9SVille Syrjälä
2472cfddadc9SVille Syrjälä return a->cdclk != b->cdclk &&
2473d34927acSVille Syrjälä a->vco != 0 &&
2474ceb0cc3bSStanislav Lisovskiy a->vco == b->vco &&
2475ceb0cc3bSStanislav Lisovskiy a->ref == b->ref;
2476ceb0cc3bSStanislav Lisovskiy }
2477ceb0cc3bSStanislav Lisovskiy
2478ceb0cc3bSStanislav Lisovskiy /**
2479ceb0cc3bSStanislav Lisovskiy * intel_cdclk_changed - Determine if two CDCLK configurations are different
2480d34927acSVille Syrjälä * @a: first CDCLK configuration
2481ceb0cc3bSStanislav Lisovskiy * @b: second CDCLK configuration
2482ceb0cc3bSStanislav Lisovskiy *
2483ceb0cc3bSStanislav Lisovskiy * Returns:
2484f0453266SJani Nikula * True if the CDCLK configurations don't match, false if they do.
2485ceb0cc3bSStanislav Lisovskiy */
intel_cdclk_changed(const struct intel_cdclk_config * a,const struct intel_cdclk_config * b)2486ceb0cc3bSStanislav Lisovskiy static bool intel_cdclk_changed(const struct intel_cdclk_config *a,
2487ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_config *b)
2488ceb0cc3bSStanislav Lisovskiy {
2489ceb0cc3bSStanislav Lisovskiy return intel_cdclk_clock_changed(a, b) ||
2490ceb0cc3bSStanislav Lisovskiy a->voltage_level != b->voltage_level;
2491ceb0cc3bSStanislav Lisovskiy }
2492ceb0cc3bSStanislav Lisovskiy
intel_cdclk_dump_config(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,const char * context)2493ceb0cc3bSStanislav Lisovskiy void intel_cdclk_dump_config(struct intel_display *display,
2494ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_config *cdclk_config,
2495ceb0cc3bSStanislav Lisovskiy const char *context)
2496ceb0cc3bSStanislav Lisovskiy {
2497ceb0cc3bSStanislav Lisovskiy drm_dbg_kms(display->drm, "%s %d kHz, VCO %d kHz, ref %d kHz, bypass %d kHz, voltage level %d\n",
2498ceb0cc3bSStanislav Lisovskiy context, cdclk_config->cdclk, cdclk_config->vco,
2499ceb0cc3bSStanislav Lisovskiy cdclk_config->ref, cdclk_config->bypass,
2500ceb0cc3bSStanislav Lisovskiy cdclk_config->voltage_level);
2501d34927acSVille Syrjälä }
2502ceb0cc3bSStanislav Lisovskiy
intel_pcode_notify(struct intel_display * display,u8 voltage_level,u8 active_pipe_count,u16 cdclk,bool cdclk_update_valid,bool pipe_count_update_valid)2503ceb0cc3bSStanislav Lisovskiy static void intel_pcode_notify(struct intel_display *display,
2504ceb0cc3bSStanislav Lisovskiy u8 voltage_level,
2505ceb0cc3bSStanislav Lisovskiy u8 active_pipe_count,
2506d34927acSVille Syrjälä u16 cdclk,
25070bb94e03SVille Syrjälä bool cdclk_update_valid,
250831df4904SVille Syrjälä bool pipe_count_update_valid)
2509b0587e4dSVille Syrjälä {
2510bb9ca240SVille Syrjälä int ret;
2511bb9ca240SVille Syrjälä u32 update_mask = 0;
2512d34927acSVille Syrjälä
2513b0587e4dSVille Syrjälä if (!display->platform.dg2)
2514b0587e4dSVille Syrjälä return;
2515d34927acSVille Syrjälä
2516b0587e4dSVille Syrjälä update_mask = DISPLAY_TO_PCODE_UPDATE_MASK(cdclk, active_pipe_count, voltage_level);
2517b0587e4dSVille Syrjälä
2518d34927acSVille Syrjälä if (cdclk_update_valid)
2519b0587e4dSVille Syrjälä update_mask |= DISPLAY_TO_PCODE_CDCLK_VALID;
2520d34927acSVille Syrjälä
252117c1a4b7SVille Syrjälä if (pipe_count_update_valid)
252217c1a4b7SVille Syrjälä update_mask |= DISPLAY_TO_PCODE_PIPE_COUNT_VALID;
252317c1a4b7SVille Syrjälä
252417c1a4b7SVille Syrjälä ret = intel_pcode_request(display->drm, SKL_PCODE_CDCLK_CONTROL,
252517c1a4b7SVille Syrjälä SKL_CDCLK_PREPARE_FOR_CHANGE |
25261b242ceeSJani Nikula update_mask,
2527112a87c4SKai Vehmanen SKL_CDCLK_READY_FOR_CHANGE,
2528bb9ca240SVille Syrjälä SKL_CDCLK_READY_FOR_CHANGE, 3);
2529bb9ca240SVille Syrjälä if (ret)
2530bb9ca240SVille Syrjälä drm_err(display->drm,
2531bb9ca240SVille Syrjälä "Failed to inform PCU about display config (err %d)\n",
2532bb9ca240SVille Syrjälä ret);
2533d34927acSVille Syrjälä }
2534d34927acSVille Syrjälä
intel_set_cdclk(struct intel_display * display,const struct intel_cdclk_config * cdclk_config,enum pipe pipe,const char * context)2535bb9ca240SVille Syrjälä static void intel_set_cdclk(struct intel_display *display,
2536bb9ca240SVille Syrjälä const struct intel_cdclk_config *cdclk_config,
2537bb9ca240SVille Syrjälä enum pipe pipe, const char *context)
2538d34927acSVille Syrjälä {
2539bb9ca240SVille Syrjälä struct intel_encoder *encoder;
2540bb9ca240SVille Syrjälä
2541d34927acSVille Syrjälä if (!intel_cdclk_changed(&display->cdclk.hw, cdclk_config))
2542cfddadc9SVille Syrjälä return;
2543d34927acSVille Syrjälä
2544bb9ca240SVille Syrjälä if (drm_WARN_ON_ONCE(display->drm, !display->funcs.cdclk->set_cdclk))
2545bb9ca240SVille Syrjälä return;
2546bb9ca240SVille Syrjälä
2547bb9ca240SVille Syrjälä intel_cdclk_dump_config(display, cdclk_config, context);
2548d34927acSVille Syrjälä
2549bb9ca240SVille Syrjälä for_each_intel_encoder_with_psr(display->drm, encoder) {
2550d34927acSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
255117c1a4b7SVille Syrjälä
255217c1a4b7SVille Syrjälä intel_psr_pause(intel_dp);
255317c1a4b7SVille Syrjälä }
255417c1a4b7SVille Syrjälä
255517c1a4b7SVille Syrjälä intel_audio_cdclk_change_pre(display);
25561b242ceeSJani Nikula
2557112a87c4SKai Vehmanen /*
2558d34927acSVille Syrjälä * Lock aux/gmbus while we change cdclk in case those
2559d34927acSVille Syrjälä * functions use cdclk. Not all platforms/ports do,
2560cfddadc9SVille Syrjälä * but we'll lock them all for simplicity.
2561d34927acSVille Syrjälä */
2562d34927acSVille Syrjälä mutex_lock(&display->gmbus.mutex);
2563cfddadc9SVille Syrjälä for_each_intel_dp(display->drm, encoder) {
2564b0587e4dSVille Syrjälä struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2565b0587e4dSVille Syrjälä
2566ceb0cc3bSStanislav Lisovskiy mutex_lock_nest_lock(&intel_dp->aux.hw_mutex,
2567ceb0cc3bSStanislav Lisovskiy &display->gmbus.mutex);
2568d34927acSVille Syrjälä }
2569ceb0cc3bSStanislav Lisovskiy
2570ceb0cc3bSStanislav Lisovskiy intel_cdclk_set_cdclk(display, cdclk_config, pipe);
2571ceb0cc3bSStanislav Lisovskiy
2572ceb0cc3bSStanislav Lisovskiy for_each_intel_dp(display->drm, encoder) {
2573ceb0cc3bSStanislav Lisovskiy struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2574ceb0cc3bSStanislav Lisovskiy
2575ceb0cc3bSStanislav Lisovskiy mutex_unlock(&intel_dp->aux.hw_mutex);
2576ceb0cc3bSStanislav Lisovskiy }
2577ceb0cc3bSStanislav Lisovskiy mutex_unlock(&display->gmbus.mutex);
2578ceb0cc3bSStanislav Lisovskiy
2579ceb0cc3bSStanislav Lisovskiy for_each_intel_encoder_with_psr(display->drm, encoder) {
2580ceb0cc3bSStanislav Lisovskiy struct intel_dp *intel_dp = enc_to_intel_dp(encoder);
2581ceb0cc3bSStanislav Lisovskiy
2582ceb0cc3bSStanislav Lisovskiy intel_psr_resume(intel_dp);
2583ceb0cc3bSStanislav Lisovskiy }
2584ceb0cc3bSStanislav Lisovskiy
2585ceb0cc3bSStanislav Lisovskiy intel_audio_cdclk_change_post(display);
2586ceb0cc3bSStanislav Lisovskiy
2587ceb0cc3bSStanislav Lisovskiy if (drm_WARN(display->drm,
2588ceb0cc3bSStanislav Lisovskiy intel_cdclk_changed(&display->cdclk.hw, cdclk_config),
2589ceb0cc3bSStanislav Lisovskiy "cdclk state doesn't match!\n")) {
2590ceb0cc3bSStanislav Lisovskiy intel_cdclk_dump_config(display, &display->cdclk.hw, "[hw state]");
2591ceb0cc3bSStanislav Lisovskiy intel_cdclk_dump_config(display, cdclk_config, "[sw state]");
2592ceb0cc3bSStanislav Lisovskiy }
2593ceb0cc3bSStanislav Lisovskiy }
2594ceb0cc3bSStanislav Lisovskiy
intel_cdclk_pcode_pre_notify(struct intel_atomic_state * state)2595ceb0cc3bSStanislav Lisovskiy static void intel_cdclk_pcode_pre_notify(struct intel_atomic_state *state)
2596ceb0cc3bSStanislav Lisovskiy {
2597ceb0cc3bSStanislav Lisovskiy struct intel_display *display = to_intel_display(state);
2598ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_state *old_cdclk_state =
2599ceb0cc3bSStanislav Lisovskiy intel_atomic_get_old_cdclk_state(state);
2600ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_state *new_cdclk_state =
2601ceb0cc3bSStanislav Lisovskiy intel_atomic_get_new_cdclk_state(state);
2602ceb0cc3bSStanislav Lisovskiy unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
2603ceb0cc3bSStanislav Lisovskiy bool change_cdclk, update_pipe_count;
2604ceb0cc3bSStanislav Lisovskiy
2605ceb0cc3bSStanislav Lisovskiy if (!intel_cdclk_changed(&old_cdclk_state->actual,
2606ceb0cc3bSStanislav Lisovskiy &new_cdclk_state->actual) &&
2607d34927acSVille Syrjälä new_cdclk_state->active_pipes ==
2608ceb0cc3bSStanislav Lisovskiy old_cdclk_state->active_pipes)
2609ceb0cc3bSStanislav Lisovskiy return;
2610ceb0cc3bSStanislav Lisovskiy
2611ceb0cc3bSStanislav Lisovskiy /* According to "Sequence Before Frequency Change", voltage level set to 0x3 */
2612ceb0cc3bSStanislav Lisovskiy voltage_level = DISPLAY_TO_PCODE_VOLTAGE_MAX;
2613d34927acSVille Syrjälä
2614ceb0cc3bSStanislav Lisovskiy change_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
2615ceb0cc3bSStanislav Lisovskiy update_pipe_count = hweight8(new_cdclk_state->active_pipes) >
2616ceb0cc3bSStanislav Lisovskiy hweight8(old_cdclk_state->active_pipes);
2617ceb0cc3bSStanislav Lisovskiy
2618ceb0cc3bSStanislav Lisovskiy /*
2619ceb0cc3bSStanislav Lisovskiy * According to "Sequence Before Frequency Change",
2620ceb0cc3bSStanislav Lisovskiy * if CDCLK is increasing, set bits 25:16 to upcoming CDCLK,
2621ceb0cc3bSStanislav Lisovskiy * if CDCLK is decreasing or not changing, set bits 25:16 to current CDCLK,
2622ceb0cc3bSStanislav Lisovskiy * which basically means we choose the maximum of old and new CDCLK, if we know both
2623ceb0cc3bSStanislav Lisovskiy */
2624ceb0cc3bSStanislav Lisovskiy if (change_cdclk)
2625ceb0cc3bSStanislav Lisovskiy cdclk = max(new_cdclk_state->actual.cdclk, old_cdclk_state->actual.cdclk);
2626ceb0cc3bSStanislav Lisovskiy
2627ceb0cc3bSStanislav Lisovskiy /*
2628ceb0cc3bSStanislav Lisovskiy * According to "Sequence For Pipe Count Change",
2629ceb0cc3bSStanislav Lisovskiy * if pipe count is increasing, set bits 25:16 to upcoming pipe count
2630ceb0cc3bSStanislav Lisovskiy * (power well is enabled)
2631ceb0cc3bSStanislav Lisovskiy * no action if it is decreasing, before the change
2632ceb0cc3bSStanislav Lisovskiy */
2633ceb0cc3bSStanislav Lisovskiy if (update_pipe_count)
2634ceb0cc3bSStanislav Lisovskiy num_active_pipes = hweight8(new_cdclk_state->active_pipes);
2635ceb0cc3bSStanislav Lisovskiy
2636ceb0cc3bSStanislav Lisovskiy intel_pcode_notify(display, voltage_level, num_active_pipes, cdclk,
2637ceb0cc3bSStanislav Lisovskiy change_cdclk, update_pipe_count);
2638ceb0cc3bSStanislav Lisovskiy }
2639ceb0cc3bSStanislav Lisovskiy
intel_cdclk_pcode_post_notify(struct intel_atomic_state * state)2640ceb0cc3bSStanislav Lisovskiy static void intel_cdclk_pcode_post_notify(struct intel_atomic_state *state)
2641ceb0cc3bSStanislav Lisovskiy {
2642ceb0cc3bSStanislav Lisovskiy struct intel_display *display = to_intel_display(state);
2643ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_state *new_cdclk_state =
2644d34927acSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
2645ceb0cc3bSStanislav Lisovskiy const struct intel_cdclk_state *old_cdclk_state =
2646ceb0cc3bSStanislav Lisovskiy intel_atomic_get_old_cdclk_state(state);
2647ceb0cc3bSStanislav Lisovskiy unsigned int cdclk = 0; u8 voltage_level, num_active_pipes = 0;
2648bea98985SVille Syrjälä bool update_cdclk, update_pipe_count;
2649bea98985SVille Syrjälä
2650bea98985SVille Syrjälä /* According to "Sequence After Frequency Change", set voltage to used level */
2651bea98985SVille Syrjälä voltage_level = new_cdclk_state->actual.voltage_level;
2652bea98985SVille Syrjälä
2653bea98985SVille Syrjälä update_cdclk = new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk;
2654bea98985SVille Syrjälä update_pipe_count = hweight8(new_cdclk_state->active_pipes) <
2655bea98985SVille Syrjälä hweight8(old_cdclk_state->active_pipes);
2656bea98985SVille Syrjälä
2657bea98985SVille Syrjälä /*
2658bea98985SVille Syrjälä * According to "Sequence After Frequency Change",
265959f9e9caSVille Syrjälä * set bits 25:16 to current CDCLK
26605604e9ceSVille Syrjälä */
26615604e9ceSVille Syrjälä if (update_cdclk)
266259f9e9caSVille Syrjälä cdclk = new_cdclk_state->actual.cdclk;
26635604e9ceSVille Syrjälä
26645604e9ceSVille Syrjälä /*
266559f9e9caSVille Syrjälä * According to "Sequence For Pipe Count Change",
266659f9e9caSVille Syrjälä * if pipe count is decreasing, set bits 25:16 to current pipe count,
26675604e9ceSVille Syrjälä * after the change(power well is disabled)
266859f9e9caSVille Syrjälä * no action if it is increasing, after the change
2669d34927acSVille Syrjälä */
267028a30b45SVille Syrjälä if (update_pipe_count)
267128a30b45SVille Syrjälä num_active_pipes = hweight8(new_cdclk_state->active_pipes);
267228a30b45SVille Syrjälä
267328a30b45SVille Syrjälä intel_pcode_notify(display, voltage_level, num_active_pipes, cdclk,
267434d127e2SVille Syrjälä update_cdclk, update_pipe_count);
267534d127e2SVille Syrjälä }
26765604e9ceSVille Syrjälä
intel_cdclk_is_decreasing_later(struct intel_atomic_state * state)267728a30b45SVille Syrjälä bool intel_cdclk_is_decreasing_later(struct intel_atomic_state *state)
267828a30b45SVille Syrjälä {
267928a30b45SVille Syrjälä const struct intel_cdclk_state *old_cdclk_state =
268028a30b45SVille Syrjälä intel_atomic_get_old_cdclk_state(state);
2681f0453266SJani Nikula const struct intel_cdclk_state *new_cdclk_state =
2682ceb0cc3bSStanislav Lisovskiy intel_atomic_get_new_cdclk_state(state);
2683ceb0cc3bSStanislav Lisovskiy
268434d127e2SVille Syrjälä return new_cdclk_state && !new_cdclk_state->disable_pipes &&
268534d127e2SVille Syrjälä new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk;
268634d127e2SVille Syrjälä }
268734d127e2SVille Syrjälä
268834d127e2SVille Syrjälä /**
268934d127e2SVille Syrjälä * intel_set_cdclk_pre_plane_update - Push the CDCLK state to the hardware
269034d127e2SVille Syrjälä * @state: intel atomic state
269134d127e2SVille Syrjälä *
269234d127e2SVille Syrjälä * Program the hardware before updating the HW plane state based on the
269334d127e2SVille Syrjälä * new CDCLK state, if necessary.
269434d127e2SVille Syrjälä */
269534d127e2SVille Syrjälä void
intel_set_cdclk_pre_plane_update(struct intel_atomic_state * state)269634d127e2SVille Syrjälä intel_set_cdclk_pre_plane_update(struct intel_atomic_state *state)
269734d127e2SVille Syrjälä {
269834d127e2SVille Syrjälä struct intel_display *display = to_intel_display(state);
269934d127e2SVille Syrjälä const struct intel_cdclk_state *old_cdclk_state =
270048b85304SStanislav Lisovskiy intel_atomic_get_old_cdclk_state(state);
270148b85304SStanislav Lisovskiy const struct intel_cdclk_state *new_cdclk_state =
270248b85304SStanislav Lisovskiy intel_atomic_get_new_cdclk_state(state);
270348b85304SStanislav Lisovskiy struct intel_cdclk_config cdclk_config;
270448b85304SStanislav Lisovskiy enum pipe pipe;
270548b85304SStanislav Lisovskiy
2706d34927acSVille Syrjälä if (!intel_cdclk_changed(&old_cdclk_state->actual,
270728a30b45SVille Syrjälä &new_cdclk_state->actual))
2708d34927acSVille Syrjälä return;
270931df4904SVille Syrjälä
271028a30b45SVille Syrjälä if (display->platform.dg2)
271159f9e9caSVille Syrjälä intel_cdclk_pcode_pre_notify(state);
271259f9e9caSVille Syrjälä
27135604e9ceSVille Syrjälä if (new_cdclk_state->disable_pipes) {
27145604e9ceSVille Syrjälä cdclk_config = new_cdclk_state->actual;
271559f9e9caSVille Syrjälä pipe = INVALID_PIPE;
27160b02f97fSVille Syrjälä } else {
27175604e9ceSVille Syrjälä if (new_cdclk_state->actual.cdclk >= old_cdclk_state->actual.cdclk) {
271859f9e9caSVille Syrjälä cdclk_config = new_cdclk_state->actual;
271959f9e9caSVille Syrjälä pipe = new_cdclk_state->pipe;
27205604e9ceSVille Syrjälä } else {
272159f9e9caSVille Syrjälä cdclk_config = old_cdclk_state->actual;
2722d34927acSVille Syrjälä pipe = INVALID_PIPE;
272328a30b45SVille Syrjälä }
272428a30b45SVille Syrjälä
272528a30b45SVille Syrjälä cdclk_config.voltage_level = max(new_cdclk_state->actual.voltage_level,
272628a30b45SVille Syrjälä old_cdclk_state->actual.voltage_level);
272734d127e2SVille Syrjälä }
27285604e9ceSVille Syrjälä
272928a30b45SVille Syrjälä /*
273028a30b45SVille Syrjälä * mbus joining will be changed later by
273128a30b45SVille Syrjälä * intel_dbuf_mbus_{pre,post}_ddb_update()
273228a30b45SVille Syrjälä */
2733f0453266SJani Nikula cdclk_config.joined_mbus = old_cdclk_state->actual.joined_mbus;
2734ceb0cc3bSStanislav Lisovskiy
2735ceb0cc3bSStanislav Lisovskiy drm_WARN_ON(display->drm, !new_cdclk_state->base.changed);
27363aecee90SVille Syrjälä
273734d127e2SVille Syrjälä intel_set_cdclk(display, &cdclk_config, pipe,
273834d127e2SVille Syrjälä "Pre changing CDCLK to");
273934d127e2SVille Syrjälä }
274034d127e2SVille Syrjälä
274134d127e2SVille Syrjälä /**
2742d34927acSVille Syrjälä * intel_set_cdclk_post_plane_update - Push the CDCLK state to the hardware
274328a30b45SVille Syrjälä * @state: intel atomic state
2744d34927acSVille Syrjälä *
274531df4904SVille Syrjälä * Program the hardware after updating the HW plane state based on the
274659f9e9caSVille Syrjälä * new CDCLK state, if necessary.
274759f9e9caSVille Syrjälä */
27486ad10f0bSVille Syrjälä void
intel_set_cdclk_post_plane_update(struct intel_atomic_state * state)27496ad10f0bSVille Syrjälä intel_set_cdclk_post_plane_update(struct intel_atomic_state *state)
27506ad10f0bSVille Syrjälä {
27516ad10f0bSVille Syrjälä struct intel_display *display = to_intel_display(state);
27526ad10f0bSVille Syrjälä const struct intel_cdclk_state *old_cdclk_state =
27536ad10f0bSVille Syrjälä intel_atomic_get_old_cdclk_state(state);
27546ad10f0bSVille Syrjälä const struct intel_cdclk_state *new_cdclk_state =
27556ad10f0bSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
27566ad10f0bSVille Syrjälä enum pipe pipe;
27576ad10f0bSVille Syrjälä
2758f0453266SJani Nikula if (!intel_cdclk_changed(&old_cdclk_state->actual,
27596ad10f0bSVille Syrjälä &new_cdclk_state->actual))
2760f0453266SJani Nikula return;
27616ad10f0bSVille Syrjälä
27626ad10f0bSVille Syrjälä if (display->platform.dg2)
27636ad10f0bSVille Syrjälä intel_cdclk_pcode_post_notify(state);
27646ad10f0bSVille Syrjälä
27656ad10f0bSVille Syrjälä if (!new_cdclk_state->disable_pipes &&
27663e30d708SVille Syrjälä new_cdclk_state->actual.cdclk < old_cdclk_state->actual.cdclk)
27677ff89ca2SVille Syrjälä pipe = new_cdclk_state->pipe;
2768d34927acSVille Syrjälä else
27696ad10f0bSVille Syrjälä pipe = INVALID_PIPE;
27706ad10f0bSVille Syrjälä
27713e30d708SVille Syrjälä drm_WARN_ON(display->drm, !new_cdclk_state->base.changed);
27723e30d708SVille Syrjälä
27736ad10f0bSVille Syrjälä intel_set_cdclk(display, &new_cdclk_state->actual, pipe,
2774d305e061SVille Syrjälä "Post changing CDCLK to");
2775d305e061SVille Syrjälä }
2776bb6ae9e6SVille Syrjälä
2777bb6ae9e6SVille Syrjälä /* pixels per CDCLK */
intel_cdclk_ppc(struct intel_display * display,bool double_wide)27782225f3c6SMaarten Lankhorst static int intel_cdclk_ppc(struct intel_display *display, bool double_wide)
2779d34927acSVille Syrjälä {
2780bb6ae9e6SVille Syrjälä return DISPLAY_VER(display) >= 10 || double_wide ? 2 : 1;
2781bb6ae9e6SVille Syrjälä }
2782bb6ae9e6SVille Syrjälä
2783d34927acSVille Syrjälä /* max pixel rate as % of CDCLK (not accounting for PPC) */
intel_cdclk_guardband(struct intel_display * display)27847c100577SVille Syrjälä static int intel_cdclk_guardband(struct intel_display *display)
2785bb6ae9e6SVille Syrjälä {
2786bb6ae9e6SVille Syrjälä if (DISPLAY_VER(display) >= 9 ||
2787bb6ae9e6SVille Syrjälä display->platform.broadwell || display->platform.haswell)
2788bb6ae9e6SVille Syrjälä return 100;
2789bd17fc4bSVille Syrjälä else if (display->platform.cherryview)
2790d305e061SVille Syrjälä return 95;
2791d305e061SVille Syrjälä else
2792d305e061SVille Syrjälä return 90;
27931326a92cSMaarten Lankhorst }
2794d305e061SVille Syrjälä
intel_pixel_rate_to_cdclk(const struct intel_crtc_state * crtc_state)2795d305e061SVille Syrjälä static int intel_pixel_rate_to_cdclk(const struct intel_crtc_state *crtc_state)
27963e30d708SVille Syrjälä {
27977c100577SVille Syrjälä struct intel_display *display = to_intel_display(crtc_state);
27987c100577SVille Syrjälä int ppc = intel_cdclk_ppc(display, crtc_state->double_wide);
27997c100577SVille Syrjälä int guardband = intel_cdclk_guardband(display);
28007c100577SVille Syrjälä int pixel_rate = crtc_state->pixel_rate;
28017f5ac365SAnkit Nautiyal
2802fe01883fSLee Shawn C return DIV_ROUND_UP(pixel_rate * 100, guardband * ppc);
2803d305e061SVille Syrjälä }
28048cbeb06dSPandiyan, Dhinakaran
intel_planes_min_cdclk(const struct intel_crtc_state * crtc_state)28058cbeb06dSPandiyan, Dhinakaran static int intel_planes_min_cdclk(const struct intel_crtc_state *crtc_state)
28064fab6b8bSVille Syrjälä {
28077ff89ca2SVille Syrjälä struct intel_crtc *crtc = to_intel_crtc(crtc_state->uapi.crtc);
2808d34927acSVille Syrjälä struct intel_display *display = to_intel_display(crtc);
28094fab6b8bSVille Syrjälä struct intel_plane *plane;
28104fab6b8bSVille Syrjälä int min_cdclk = 0;
28115ac860ccSVille Syrjälä
2812d305e061SVille Syrjälä for_each_intel_plane_on_crtc(display->drm, crtc, plane)
28137ff89ca2SVille Syrjälä min_cdclk = max(min_cdclk, crtc_state->min_cdclk[plane->id]);
28149c61de4cSVille Syrjälä
281519aefbc7SStanislav Lisovskiy return min_cdclk;
28167ff89ca2SVille Syrjälä }
28178b67896eSVille Syrjälä
intel_crtc_compute_min_cdclk(const struct intel_crtc_state * crtc_state)28181d5a95b5SVille Syrjälä static int intel_crtc_compute_min_cdclk(const struct intel_crtc_state *crtc_state)
28191d5a95b5SVille Syrjälä {
28209c61de4cSVille Syrjälä int min_cdclk;
28219c61de4cSVille Syrjälä
28229c61de4cSVille Syrjälä if (!crtc_state->hw.enable)
28237ff89ca2SVille Syrjälä return 0;
28246499f925SVille Syrjälä
28251d5a95b5SVille Syrjälä min_cdclk = intel_pixel_rate_to_cdclk(crtc_state);
28261d5a95b5SVille Syrjälä min_cdclk = max(min_cdclk, hsw_ips_min_cdclk(crtc_state));
28276499f925SVille Syrjälä min_cdclk = max(min_cdclk, intel_audio_min_cdclk(crtc_state));
28281d5a95b5SVille Syrjälä min_cdclk = max(min_cdclk, vlv_dsi_min_cdclk(crtc_state));
282928a30b45SVille Syrjälä min_cdclk = max(min_cdclk, intel_planes_min_cdclk(crtc_state));
28301d5a95b5SVille Syrjälä min_cdclk = max(min_cdclk, intel_vdsc_min_cdclk(crtc_state));
28311d5a95b5SVille Syrjälä
28329c61de4cSVille Syrjälä return min_cdclk;
28339c61de4cSVille Syrjälä }
28345ac860ccSVille Syrjälä
intel_compute_min_cdclk(struct intel_atomic_state * state)28355ac860ccSVille Syrjälä static int intel_compute_min_cdclk(struct intel_atomic_state *state)
2836d706998bSGustavo Sousa {
28375ac860ccSVille Syrjälä struct intel_display *display = to_intel_display(state);
28385ac860ccSVille Syrjälä struct intel_cdclk_state *cdclk_state =
28395ac860ccSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
28405ac860ccSVille Syrjälä const struct intel_bw_state *bw_state;
28415ac860ccSVille Syrjälä struct intel_crtc *crtc;
28425ac860ccSVille Syrjälä struct intel_crtc_state *crtc_state;
28435ac860ccSVille Syrjälä int min_cdclk, i;
28445ac860ccSVille Syrjälä enum pipe pipe;
28455ac860ccSVille Syrjälä
28465ac860ccSVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
28475ac860ccSVille Syrjälä int ret;
28485ac860ccSVille Syrjälä
28495ac860ccSVille Syrjälä min_cdclk = intel_crtc_compute_min_cdclk(crtc_state);
28505ac860ccSVille Syrjälä if (min_cdclk < 0)
2851d34927acSVille Syrjälä return min_cdclk;
28527c100577SVille Syrjälä
2853cd191546SStanislav Lisovskiy if (cdclk_state->min_cdclk[crtc->pipe] == min_cdclk)
2854451eaa1aSVille Syrjälä continue;
2855451eaa1aSVille Syrjälä
2856451eaa1aSVille Syrjälä cdclk_state->min_cdclk[crtc->pipe] = min_cdclk;
2857451eaa1aSVille Syrjälä
2858451eaa1aSVille Syrjälä ret = intel_atomic_lock_global_state(&cdclk_state->base);
2859451eaa1aSVille Syrjälä if (ret)
2860451eaa1aSVille Syrjälä return ret;
2861451eaa1aSVille Syrjälä }
2862f0453266SJani Nikula
2863451eaa1aSVille Syrjälä bw_state = intel_atomic_get_new_bw_state(state);
28647c100577SVille Syrjälä if (bw_state) {
2865451eaa1aSVille Syrjälä min_cdclk = intel_bw_min_cdclk(display, bw_state);
2866d34927acSVille Syrjälä
2867d34927acSVille Syrjälä if (cdclk_state->bw_min_cdclk != min_cdclk) {
28685ac860ccSVille Syrjälä int ret;
2869d34927acSVille Syrjälä
28705ac860ccSVille Syrjälä cdclk_state->bw_min_cdclk = min_cdclk;
2871cd191546SStanislav Lisovskiy
28727ff89ca2SVille Syrjälä ret = intel_atomic_lock_global_state(&cdclk_state->base);
2873d305e061SVille Syrjälä if (ret)
28747ff89ca2SVille Syrjälä return ret;
28757ff89ca2SVille Syrjälä }
287653e9bf5eSVille Syrjälä }
2877933122ccSVille Syrjälä
28781d89509aSLucas De Marchi min_cdclk = max(cdclk_state->force_min_cdclk,
2879933122ccSVille Syrjälä cdclk_state->bw_min_cdclk);
2880933122ccSVille Syrjälä for_each_pipe(display, pipe)
288153e9bf5eSVille Syrjälä min_cdclk = max(min_cdclk, cdclk_state->min_cdclk[pipe]);
288253e9bf5eSVille Syrjälä
288353e9bf5eSVille Syrjälä /*
288453e9bf5eSVille Syrjälä * Avoid glk_force_audio_cdclk() causing excessive screen
288553e9bf5eSVille Syrjälä * blinking when multiple pipes are active by making sure
288653e9bf5eSVille Syrjälä * CDCLK frequency is always high enough for audio. With a
288753e9bf5eSVille Syrjälä * single active pipe we can always change CDCLK frequency
288853e9bf5eSVille Syrjälä * by changing the cd2x divider (see glk_cdclk_table[]) and
28894fab6b8bSVille Syrjälä * thus a full modeset won't be needed then.
289053e9bf5eSVille Syrjälä */
2891d34927acSVille Syrjälä if (display->platform.geminilake && cdclk_state->active_pipes &&
28924fab6b8bSVille Syrjälä !is_power_of_2(cdclk_state->active_pipes))
28934fab6b8bSVille Syrjälä min_cdclk = max(min_cdclk, 2 * 96000);
289453e9bf5eSVille Syrjälä
289553e9bf5eSVille Syrjälä if (min_cdclk > display->cdclk.max_cdclk_freq) {
289653e9bf5eSVille Syrjälä drm_dbg_kms(display->drm,
289753e9bf5eSVille Syrjälä "required cdclk (%d kHz) exceeds max (%d kHz)\n",
289853e9bf5eSVille Syrjälä min_cdclk, display->cdclk.max_cdclk_freq);
289953e9bf5eSVille Syrjälä return -EINVAL;
290053e9bf5eSVille Syrjälä }
29011d5a95b5SVille Syrjälä
29021d5a95b5SVille Syrjälä return min_cdclk;
29031326a92cSMaarten Lankhorst }
29041d5a95b5SVille Syrjälä
290553e9bf5eSVille Syrjälä /*
29061d5a95b5SVille Syrjälä * Account for port clock min voltage level requirements.
29071d5a95b5SVille Syrjälä * This only really does something on DISPLA_VER >= 11 but can be
29086499f925SVille Syrjälä * called on earlier platforms as well.
29091d5a95b5SVille Syrjälä *
29101d5a95b5SVille Syrjälä * Note that this functions assumes that 0 is
29116499f925SVille Syrjälä * the lowest voltage value, and higher values
29121d5a95b5SVille Syrjälä * correspond to increasingly higher voltages.
291328a30b45SVille Syrjälä *
29141d5a95b5SVille Syrjälä * Should that relationship no longer hold on
29151d5a95b5SVille Syrjälä * future platforms this code will need to be
291653e9bf5eSVille Syrjälä * adjusted.
291753e9bf5eSVille Syrjälä */
bxt_compute_min_voltage_level(struct intel_atomic_state * state)291853e9bf5eSVille Syrjälä static int bxt_compute_min_voltage_level(struct intel_atomic_state *state)
2919d34927acSVille Syrjälä {
29207c100577SVille Syrjälä struct intel_display *display = to_intel_display(state);
29217c100577SVille Syrjälä struct intel_cdclk_state *cdclk_state =
292253e9bf5eSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
292353e9bf5eSVille Syrjälä struct intel_crtc *crtc;
292453e9bf5eSVille Syrjälä struct intel_crtc_state *crtc_state;
292553e9bf5eSVille Syrjälä u8 min_voltage_level;
29264fab6b8bSVille Syrjälä int i;
29277ff89ca2SVille Syrjälä enum pipe pipe;
2928d34927acSVille Syrjälä
29294fab6b8bSVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
29304fab6b8bSVille Syrjälä int ret;
29319c61de4cSVille Syrjälä
29329c61de4cSVille Syrjälä if (crtc_state->hw.enable)
29334fab6b8bSVille Syrjälä min_voltage_level = crtc_state->min_voltage_level;
29349c61de4cSVille Syrjälä else
29359c61de4cSVille Syrjälä min_voltage_level = 0;
29367ff89ca2SVille Syrjälä
2937d34927acSVille Syrjälä if (cdclk_state->min_voltage_level[crtc->pipe] == min_voltage_level)
29387ff89ca2SVille Syrjälä continue;
29391965de63SVille Syrjälä
29401965de63SVille Syrjälä cdclk_state->min_voltage_level[crtc->pipe] = min_voltage_level;
2941d34927acSVille Syrjälä
2942bb0f4aabSVille Syrjälä ret = intel_atomic_lock_global_state(&cdclk_state->base);
29430c2d5512SVille Syrjälä if (ret)
2944d34927acSVille Syrjälä return ret;
2945bb0f4aabSVille Syrjälä }
29461965de63SVille Syrjälä
29471965de63SVille Syrjälä min_voltage_level = 0;
2948d34927acSVille Syrjälä for_each_pipe(display, pipe)
2949bb0f4aabSVille Syrjälä min_voltage_level = max(min_voltage_level,
29501965de63SVille Syrjälä cdclk_state->min_voltage_level[pipe]);
2951bb0f4aabSVille Syrjälä
29527ff89ca2SVille Syrjälä return min_voltage_level;
29537ff89ca2SVille Syrjälä }
29547ff89ca2SVille Syrjälä
vlv_modeset_calc_cdclk(struct intel_atomic_state * state)29557ff89ca2SVille Syrjälä static int vlv_modeset_calc_cdclk(struct intel_atomic_state *state)
29564fab6b8bSVille Syrjälä {
29577ff89ca2SVille Syrjälä struct intel_display *display = to_intel_display(state);
29584fab6b8bSVille Syrjälä struct intel_cdclk_state *cdclk_state =
29594fab6b8bSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
29609c61de4cSVille Syrjälä int min_cdclk, cdclk;
29619c61de4cSVille Syrjälä
29624fab6b8bSVille Syrjälä min_cdclk = intel_compute_min_cdclk(state);
29639c61de4cSVille Syrjälä if (min_cdclk < 0)
29649c61de4cSVille Syrjälä return min_cdclk;
29657ff89ca2SVille Syrjälä
2966d305e061SVille Syrjälä cdclk = vlv_calc_cdclk(display, min_cdclk);
29677ff89ca2SVille Syrjälä
29681965de63SVille Syrjälä cdclk_state->logical.cdclk = cdclk;
29691965de63SVille Syrjälä cdclk_state->logical.voltage_level =
2970d7ffaeefSVille Syrjälä vlv_calc_voltage_level(display, cdclk);
2971bb0f4aabSVille Syrjälä
29720c2d5512SVille Syrjälä if (!cdclk_state->active_pipes) {
29731965de63SVille Syrjälä cdclk = vlv_calc_cdclk(display, cdclk_state->force_min_cdclk);
2974bb0f4aabSVille Syrjälä
29751965de63SVille Syrjälä cdclk_state->actual.cdclk = cdclk;
29761965de63SVille Syrjälä cdclk_state->actual.voltage_level =
2977d7ffaeefSVille Syrjälä vlv_calc_voltage_level(display, cdclk);
2978bb0f4aabSVille Syrjälä } else {
29791965de63SVille Syrjälä cdclk_state->actual = cdclk_state->logical;
2980bb0f4aabSVille Syrjälä }
29817ff89ca2SVille Syrjälä
29827ff89ca2SVille Syrjälä return 0;
29837ff89ca2SVille Syrjälä }
29847ff89ca2SVille Syrjälä
bdw_modeset_calc_cdclk(struct intel_atomic_state * state)29854fab6b8bSVille Syrjälä static int bdw_modeset_calc_cdclk(struct intel_atomic_state *state)
29863297234aSRodrigo Vivi {
2987d34927acSVille Syrjälä struct intel_cdclk_state *cdclk_state =
29884fab6b8bSVille Syrjälä intel_atomic_get_new_cdclk_state(state);
29894fab6b8bSVille Syrjälä int min_cdclk, cdclk;
29903297234aSRodrigo Vivi
29913297234aSRodrigo Vivi min_cdclk = intel_compute_min_cdclk(state);
29923297234aSRodrigo Vivi if (min_cdclk < 0)
29933297234aSRodrigo Vivi return min_cdclk;
29941965de63SVille Syrjälä
29953297234aSRodrigo Vivi cdclk = bdw_calc_cdclk(min_cdclk);
2996d34927acSVille Syrjälä
29973297234aSRodrigo Vivi cdclk_state->logical.cdclk = cdclk;
29988b67896eSVille Syrjälä cdclk_state->logical.voltage_level =
29991326a92cSMaarten Lankhorst bdw_calc_voltage_level(cdclk);
30003297234aSRodrigo Vivi
30013297234aSRodrigo Vivi if (!cdclk_state->active_pipes) {
30023297234aSRodrigo Vivi cdclk = bdw_calc_cdclk(cdclk_state->force_min_cdclk);
30033297234aSRodrigo Vivi
30043297234aSRodrigo Vivi cdclk_state->actual.cdclk = cdclk;
30053297234aSRodrigo Vivi cdclk_state->actual.voltage_level =
30063297234aSRodrigo Vivi bdw_calc_voltage_level(cdclk);
30073297234aSRodrigo Vivi } else {
30083297234aSRodrigo Vivi cdclk_state->actual = cdclk_state->logical;
30093297234aSRodrigo Vivi }
30103297234aSRodrigo Vivi
30113297234aSRodrigo Vivi return 0;
30123297234aSRodrigo Vivi }
30133297234aSRodrigo Vivi
skl_dpll0_vco(struct intel_atomic_state * state)30143297234aSRodrigo Vivi static int skl_dpll0_vco(struct intel_atomic_state *state)
30153297234aSRodrigo Vivi {
30163297234aSRodrigo Vivi struct intel_display *display = to_intel_display(state);
30173297234aSRodrigo Vivi struct intel_cdclk_state *cdclk_state =
30183297234aSRodrigo Vivi intel_atomic_get_new_cdclk_state(state);
30193297234aSRodrigo Vivi struct intel_crtc *crtc;
30203297234aSRodrigo Vivi struct intel_crtc_state *crtc_state;
30213297234aSRodrigo Vivi int vco, i;
30223297234aSRodrigo Vivi
30234fab6b8bSVille Syrjälä vco = cdclk_state->logical.vco;
30247ff89ca2SVille Syrjälä if (!vco)
30254fab6b8bSVille Syrjälä vco = display->cdclk.skl_preferred_vco_freq;
30264fab6b8bSVille Syrjälä
30279c61de4cSVille Syrjälä for_each_new_intel_crtc_in_state(state, crtc, crtc_state, i) {
30289c61de4cSVille Syrjälä if (!crtc_state->hw.enable)
30294fab6b8bSVille Syrjälä continue;
30309c61de4cSVille Syrjälä
30319c61de4cSVille Syrjälä if (!intel_crtc_has_type(crtc_state, INTEL_OUTPUT_EDP))
3032bb0f4aabSVille Syrjälä continue;
30334fab6b8bSVille Syrjälä
30347ff89ca2SVille Syrjälä /*
3035d305e061SVille Syrjälä * DPLL0 VCO may need to be adjusted to get the correct
30367ff89ca2SVille Syrjälä * clock for eDP. This will affect cdclk as well.
30371965de63SVille Syrjälä */
30381965de63SVille Syrjälä switch (crtc_state->port_clock / 2) {
30391965de63SVille Syrjälä case 108000:
30402aa97491SVille Syrjälä case 216000:
3041bb0f4aabSVille Syrjälä vco = 8640000;
30420c2d5512SVille Syrjälä break;
30431965de63SVille Syrjälä default:
3044bb0f4aabSVille Syrjälä vco = 8100000;
30451965de63SVille Syrjälä break;
30461965de63SVille Syrjälä }
30471965de63SVille Syrjälä }
30482aa97491SVille Syrjälä
3049bb0f4aabSVille Syrjälä return vco;
30501965de63SVille Syrjälä }
3051bb0f4aabSVille Syrjälä
skl_modeset_calc_cdclk(struct intel_atomic_state * state)30527ff89ca2SVille Syrjälä static int skl_modeset_calc_cdclk(struct intel_atomic_state *state)
30537ff89ca2SVille Syrjälä {
30547ff89ca2SVille Syrjälä struct intel_cdclk_state *cdclk_state =
30557ff89ca2SVille Syrjälä intel_atomic_get_new_cdclk_state(state);
30564fab6b8bSVille Syrjälä int min_cdclk, cdclk, vco;
30577ff89ca2SVille Syrjälä
3058d34927acSVille Syrjälä min_cdclk = intel_compute_min_cdclk(state);
30594fab6b8bSVille Syrjälä if (min_cdclk < 0)
30604fab6b8bSVille Syrjälä return min_cdclk;
30611d5a95b5SVille Syrjälä
30629c61de4cSVille Syrjälä vco = skl_dpll0_vco(state);
30634fab6b8bSVille Syrjälä
30649c61de4cSVille Syrjälä cdclk = skl_calc_cdclk(min_cdclk, vco);
30659c61de4cSVille Syrjälä
30667ff89ca2SVille Syrjälä cdclk_state->logical.vco = vco;
30674fab6b8bSVille Syrjälä cdclk_state->logical.cdclk = cdclk;
30681d5a95b5SVille Syrjälä cdclk_state->logical.voltage_level =
30691d5a95b5SVille Syrjälä skl_calc_voltage_level(cdclk);
30701d5a95b5SVille Syrjälä
3071d34927acSVille Syrjälä if (!cdclk_state->active_pipes) {
3072d34927acSVille Syrjälä cdclk = skl_calc_cdclk(cdclk_state->force_min_cdclk, vco);
30737ff89ca2SVille Syrjälä
30741965de63SVille Syrjälä cdclk_state->actual.vco = vco;
30751965de63SVille Syrjälä cdclk_state->actual.cdclk = cdclk;
30761965de63SVille Syrjälä cdclk_state->actual.voltage_level =
30771d5a95b5SVille Syrjälä skl_calc_voltage_level(cdclk);
3078d34927acSVille Syrjälä } else {
3079186a277eSPaulo Zanoni cdclk_state->actual = cdclk_state->logical;
30800c2d5512SVille Syrjälä }
3081d34927acSVille Syrjälä
3082d34927acSVille Syrjälä return 0;
3083186a277eSPaulo Zanoni }
30841965de63SVille Syrjälä
bxt_modeset_calc_cdclk(struct intel_atomic_state * state)30851965de63SVille Syrjälä static int bxt_modeset_calc_cdclk(struct intel_atomic_state *state)
30861965de63SVille Syrjälä {
3087d34927acSVille Syrjälä struct intel_display *display = to_intel_display(state);
3088186a277eSPaulo Zanoni struct intel_cdclk_state *cdclk_state =
30891965de63SVille Syrjälä intel_atomic_get_new_cdclk_state(state);
3090186a277eSPaulo Zanoni int min_cdclk, min_voltage_level, cdclk, vco;
3091186a277eSPaulo Zanoni
3092186a277eSPaulo Zanoni min_cdclk = intel_compute_min_cdclk(state);
3093186a277eSPaulo Zanoni if (min_cdclk < 0)
3094186a277eSPaulo Zanoni return min_cdclk;
30954fab6b8bSVille Syrjälä
30963e30d708SVille Syrjälä min_voltage_level = bxt_compute_min_voltage_level(state);
30973e30d708SVille Syrjälä if (min_voltage_level < 0)
30983e30d708SVille Syrjälä return min_voltage_level;
30993e30d708SVille Syrjälä
31003e30d708SVille Syrjälä cdclk = bxt_calc_cdclk(display, min_cdclk);
31013e30d708SVille Syrjälä vco = bxt_calc_cdclk_pll_vco(display, cdclk);
31023e30d708SVille Syrjälä
31033e30d708SVille Syrjälä cdclk_state->logical.vco = vco;
31044fab6b8bSVille Syrjälä cdclk_state->logical.cdclk = cdclk;
31053e30d708SVille Syrjälä cdclk_state->logical.voltage_level =
31063e30d708SVille Syrjälä max_t(int, min_voltage_level,
31073e30d708SVille Syrjälä intel_cdclk_calc_voltage_level(display, cdclk));
31083e30d708SVille Syrjälä
31093e30d708SVille Syrjälä if (!cdclk_state->active_pipes) {
31103e30d708SVille Syrjälä cdclk = bxt_calc_cdclk(display, cdclk_state->force_min_cdclk);
311128a30b45SVille Syrjälä vco = bxt_calc_cdclk_pll_vco(display, cdclk);
311228a30b45SVille Syrjälä
311328a30b45SVille Syrjälä cdclk_state->actual.vco = vco;
311428a30b45SVille Syrjälä cdclk_state->actual.cdclk = cdclk;
311528a30b45SVille Syrjälä cdclk_state->actual.voltage_level =
311628a30b45SVille Syrjälä intel_cdclk_calc_voltage_level(display, cdclk);
311728a30b45SVille Syrjälä } else {
311828a30b45SVille Syrjälä cdclk_state->actual = cdclk_state->logical;
311928a30b45SVille Syrjälä }
31203aecee90SVille Syrjälä
312128a30b45SVille Syrjälä return 0;
312228a30b45SVille Syrjälä }
312328a30b45SVille Syrjälä
fixed_modeset_calc_cdclk(struct intel_atomic_state * state)312428a30b45SVille Syrjälä static int fixed_modeset_calc_cdclk(struct intel_atomic_state *state)
312528a30b45SVille Syrjälä {
312628a30b45SVille Syrjälä int min_cdclk;
312728a30b45SVille Syrjälä
312828a30b45SVille Syrjälä /*
312928a30b45SVille Syrjälä * We can't change the cdclk frequency, but we still want to
313028a30b45SVille Syrjälä * check that the required minimum frequency doesn't exceed
313128a30b45SVille Syrjälä * the actual cdclk frequency.
313228a30b45SVille Syrjälä */
313328a30b45SVille Syrjälä min_cdclk = intel_compute_min_cdclk(state);
313428a30b45SVille Syrjälä if (min_cdclk < 0)
313528a30b45SVille Syrjälä return min_cdclk;
313628a30b45SVille Syrjälä
313728a30b45SVille Syrjälä return 0;
313828a30b45SVille Syrjälä }
3139d34927acSVille Syrjälä
intel_cdclk_duplicate_state(struct intel_global_obj * obj)314028a30b45SVille Syrjälä static struct intel_global_state *intel_cdclk_duplicate_state(struct intel_global_obj *obj)
314128a30b45SVille Syrjälä {
3142d34927acSVille Syrjälä struct intel_cdclk_state *cdclk_state;
314328a30b45SVille Syrjälä
314428a30b45SVille Syrjälä cdclk_state = kmemdup(obj->state, sizeof(*cdclk_state), GFP_KERNEL);
314528a30b45SVille Syrjälä if (!cdclk_state)
314628a30b45SVille Syrjälä return NULL;
314728a30b45SVille Syrjälä
314828a30b45SVille Syrjälä cdclk_state->pipe = INVALID_PIPE;
3149754d6275SJani Nikula cdclk_state->disable_pipes = false;
3150754d6275SJani Nikula
3151754d6275SJani Nikula return &cdclk_state->base;
3152754d6275SJani Nikula }
3153754d6275SJani Nikula
intel_cdclk_destroy_state(struct intel_global_obj * obj,struct intel_global_state * state)3154ace87304SJani Nikula static void intel_cdclk_destroy_state(struct intel_global_obj *obj,
3155754d6275SJani Nikula struct intel_global_state *state)
3156754d6275SJani Nikula {
3157754d6275SJani Nikula kfree(state);
3158754d6275SJani Nikula }
3159754d6275SJani Nikula
3160754d6275SJani Nikula static const struct intel_global_state_funcs intel_cdclk_funcs = {
3161754d6275SJani Nikula .atomic_duplicate_state = intel_cdclk_duplicate_state,
3162754d6275SJani Nikula .atomic_destroy_state = intel_cdclk_destroy_state,
3163754d6275SJani Nikula };
3164754d6275SJani Nikula
3165754d6275SJani Nikula struct intel_cdclk_state *
intel_atomic_get_cdclk_state(struct intel_atomic_state * state)3166754d6275SJani Nikula intel_atomic_get_cdclk_state(struct intel_atomic_state *state)
3167754d6275SJani Nikula {
3168754d6275SJani Nikula struct intel_display *display = to_intel_display(state);
3169754d6275SJani Nikula struct intel_global_state *cdclk_state;
31705ac860ccSVille Syrjälä
31715ac860ccSVille Syrjälä cdclk_state = intel_atomic_get_global_obj_state(state, &display->cdclk.obj);
31725ac860ccSVille Syrjälä if (IS_ERR(cdclk_state))
31735ac860ccSVille Syrjälä return ERR_CAST(cdclk_state);
3174754d6275SJani Nikula
3175754d6275SJani Nikula return to_intel_cdclk_state(cdclk_state);
3176754d6275SJani Nikula }
3177754d6275SJani Nikula
intel_cdclk_atomic_check(struct intel_atomic_state * state,bool * need_cdclk_calc)3178754d6275SJani Nikula int intel_cdclk_atomic_check(struct intel_atomic_state *state,
3179754d6275SJani Nikula bool *need_cdclk_calc)
3180754d6275SJani Nikula {
3181754d6275SJani Nikula const struct intel_cdclk_state *old_cdclk_state;
3182754d6275SJani Nikula const struct intel_cdclk_state *new_cdclk_state;
3183754d6275SJani Nikula struct intel_plane_state __maybe_unused *plane_state;
3184c834a080SGustavo Sousa struct intel_plane *plane;
3185c834a080SGustavo Sousa int ret;
3186c834a080SGustavo Sousa int i;
3187c834a080SGustavo Sousa
3188c834a080SGustavo Sousa /*
3189c834a080SGustavo Sousa * active_planes bitmask has been updated, and potentially affected
3190c834a080SGustavo Sousa * planes are part of the state. We can now compute the minimum cdclk
3191c834a080SGustavo Sousa * for each plane.
3192c834a080SGustavo Sousa */
3193c834a080SGustavo Sousa for_each_new_intel_plane_in_state(state, plane, plane_state, i) {
3194c834a080SGustavo Sousa ret = intel_plane_calc_min_cdclk(state, plane, need_cdclk_calc);
3195c834a080SGustavo Sousa if (ret)
3196c834a080SGustavo Sousa return ret;
3197c834a080SGustavo Sousa }
3198d34927acSVille Syrjälä
319928a30b45SVille Syrjälä ret = intel_bw_calc_min_cdclk(state, need_cdclk_calc);
320028a30b45SVille Syrjälä if (ret)
320128a30b45SVille Syrjälä return ret;
320228a30b45SVille Syrjälä
320328a30b45SVille Syrjälä old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
320428a30b45SVille Syrjälä new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
320528a30b45SVille Syrjälä
320615133582SJani Nikula if (new_cdclk_state &&
320728a30b45SVille Syrjälä old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk)
320828a30b45SVille Syrjälä *need_cdclk_calc = true;
320928a30b45SVille Syrjälä
321028a30b45SVille Syrjälä return 0;
321128a30b45SVille Syrjälä }
3212d34927acSVille Syrjälä
intel_cdclk_state_set_joined_mbus(struct intel_atomic_state * state,bool joined_mbus)3213ceb0cc3bSStanislav Lisovskiy int intel_cdclk_state_set_joined_mbus(struct intel_atomic_state *state, bool joined_mbus)
3214ceb0cc3bSStanislav Lisovskiy {
3215ceb0cc3bSStanislav Lisovskiy struct intel_cdclk_state *cdclk_state;
3216ceb0cc3bSStanislav Lisovskiy
3217ceb0cc3bSStanislav Lisovskiy cdclk_state = intel_atomic_get_cdclk_state(state);
3218ceb0cc3bSStanislav Lisovskiy if (IS_ERR(cdclk_state))
3219ceb0cc3bSStanislav Lisovskiy return PTR_ERR(cdclk_state);
3220ceb0cc3bSStanislav Lisovskiy
3221ceb0cc3bSStanislav Lisovskiy cdclk_state->actual.joined_mbus = joined_mbus;
3222ceb0cc3bSStanislav Lisovskiy cdclk_state->logical.joined_mbus = joined_mbus;
3223ceb0cc3bSStanislav Lisovskiy
3224f0453266SJani Nikula return intel_atomic_lock_global_state(&cdclk_state->base);
3225ceb0cc3bSStanislav Lisovskiy }
3226ceb0cc3bSStanislav Lisovskiy
intel_cdclk_init(struct intel_display * display)3227fe4709a8SVille Syrjälä int intel_cdclk_init(struct intel_display *display)
3228fe4709a8SVille Syrjälä {
3229138d2bdaSJani Nikula struct intel_cdclk_state *cdclk_state;
323028a30b45SVille Syrjälä
323128a30b45SVille Syrjälä cdclk_state = kzalloc(sizeof(*cdclk_state), GFP_KERNEL);
3232d62686baSStanislav Lisovskiy if (!cdclk_state)
3233fe4709a8SVille Syrjälä return -ENOMEM;
3234fe4709a8SVille Syrjälä
323528a30b45SVille Syrjälä intel_atomic_global_obj_init(display, &display->cdclk.obj,
323628a30b45SVille Syrjälä &cdclk_state->base, &intel_cdclk_funcs);
323728a30b45SVille Syrjälä
323854f09d23SVille Syrjälä return 0;
323928a30b45SVille Syrjälä }
324054f09d23SVille Syrjälä
intel_cdclk_need_serialize(struct intel_display * display,const struct intel_cdclk_state * old_cdclk_state,const struct intel_cdclk_state * new_cdclk_state)32410c2d5512SVille Syrjälä static bool intel_cdclk_need_serialize(struct intel_display *display,
32420c2d5512SVille Syrjälä const struct intel_cdclk_state *old_cdclk_state,
32430c2d5512SVille Syrjälä const struct intel_cdclk_state *new_cdclk_state)
32444fab6b8bSVille Syrjälä {
3245fe4709a8SVille Syrjälä bool power_well_cnt_changed = hweight8(old_cdclk_state->active_pipes) !=
3246fe4709a8SVille Syrjälä hweight8(new_cdclk_state->active_pipes);
3247fe4709a8SVille Syrjälä bool cdclk_changed = intel_cdclk_changed(&old_cdclk_state->actual,
3248d34927acSVille Syrjälä &new_cdclk_state->actual);
32491d5a95b5SVille Syrjälä /*
32501d5a95b5SVille Syrjälä * We need to poke hw for gen >= 12, because we notify PCode if
32511d5a95b5SVille Syrjälä * pipe power well count changes.
32521d5a95b5SVille Syrjälä */
325328a30b45SVille Syrjälä return cdclk_changed || (display->platform.dg2 && power_well_cnt_changed);
32541d5a95b5SVille Syrjälä }
3255fe4709a8SVille Syrjälä
intel_modeset_calc_cdclk(struct intel_atomic_state * state)32560c2d5512SVille Syrjälä int intel_modeset_calc_cdclk(struct intel_atomic_state *state)
3257dc98f50fSVille Syrjälä {
32580c2d5512SVille Syrjälä struct intel_display *display = to_intel_display(state);
32591965de63SVille Syrjälä const struct intel_cdclk_state *old_cdclk_state;
326028a30b45SVille Syrjälä struct intel_cdclk_state *new_cdclk_state;
32611d5a95b5SVille Syrjälä enum pipe pipe = INVALID_PIPE;
32621d5a95b5SVille Syrjälä int ret;
32631d5a95b5SVille Syrjälä
32641d5a95b5SVille Syrjälä new_cdclk_state = intel_atomic_get_cdclk_state(state);
3265fe4709a8SVille Syrjälä if (IS_ERR(new_cdclk_state))
3266fe4709a8SVille Syrjälä return PTR_ERR(new_cdclk_state);
32670c2d5512SVille Syrjälä
3268d34927acSVille Syrjälä old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
32691965de63SVille Syrjälä
32701965de63SVille Syrjälä new_cdclk_state->active_pipes =
3271fe4709a8SVille Syrjälä intel_calc_active_pipes(state, old_cdclk_state->active_pipes);
3272fe4709a8SVille Syrjälä
3273fe4709a8SVille Syrjälä ret = intel_cdclk_modeset_calc_cdclk(state);
32740c2d5512SVille Syrjälä if (ret)
3275138d2bdaSJani Nikula return ret;
32761d5a95b5SVille Syrjälä
32771d5a95b5SVille Syrjälä if (intel_cdclk_need_serialize(display, old_cdclk_state, new_cdclk_state)) {
32781d5a95b5SVille Syrjälä /*
32791d5a95b5SVille Syrjälä * Also serialize commits across all crtcs
32801d5a95b5SVille Syrjälä * if the actual hw needs to be poked.
3281882ecff7SVille Syrjälä */
3282fe4709a8SVille Syrjälä ret = intel_atomic_serialize_global_state(&new_cdclk_state->base);
3283fe4709a8SVille Syrjälä if (ret)
3284fe4709a8SVille Syrjälä return ret;
3285d34927acSVille Syrjälä } else if (old_cdclk_state->active_pipes != new_cdclk_state->active_pipes ||
328625e0e5aeSVille Syrjälä old_cdclk_state->force_min_cdclk != new_cdclk_state->force_min_cdclk ||
328725e0e5aeSVille Syrjälä intel_cdclk_changed(&old_cdclk_state->logical,
3288d34927acSVille Syrjälä &new_cdclk_state->logical)) {
328925e0e5aeSVille Syrjälä ret = intel_atomic_lock_global_state(&new_cdclk_state->base);
3290d34927acSVille Syrjälä if (ret)
3291d4a23930SVille Syrjälä return ret;
3292d4a23930SVille Syrjälä } else {
3293d34927acSVille Syrjälä return 0;
3294c74b644fSAnusha Srivatsa }
3295d34927acSVille Syrjälä
3296d62686baSStanislav Lisovskiy if (is_power_of_2(new_cdclk_state->active_pipes) &&
3297d62686baSStanislav Lisovskiy intel_cdclk_can_cd2x_update(display,
3298d34927acSVille Syrjälä &old_cdclk_state->actual,
3299c74b644fSAnusha Srivatsa &new_cdclk_state->actual)) {
3300d62686baSStanislav Lisovskiy struct intel_crtc *crtc;
33011965de63SVille Syrjälä struct intel_crtc_state *crtc_state;
33026c066f4cSVille Syrjälä
3303d34927acSVille Syrjälä pipe = ilog2(new_cdclk_state->active_pipes);
3304d62686baSStanislav Lisovskiy crtc = intel_crtc_for_pipe(display, pipe);
33056c066f4cSVille Syrjälä
3306669cf07dSGustavo Sousa crtc_state = intel_atomic_get_crtc_state(&state->base, crtc);
33071965de63SVille Syrjälä if (IS_ERR(crtc_state))
33081d5a95b5SVille Syrjälä return PTR_ERR(crtc_state);
3309e3b26904SImre Deak
3310fe4709a8SVille Syrjälä if (intel_crtc_needs_modeset(crtc_state))
3311fe4709a8SVille Syrjälä pipe = INVALID_PIPE;
3312fe4709a8SVille Syrjälä }
33133aecee90SVille Syrjälä
33143aecee90SVille Syrjälä if (intel_cdclk_can_crawl_and_squash(display,
3315d34927acSVille Syrjälä &old_cdclk_state->actual,
331623194610SWambui Karuga &new_cdclk_state->actual)) {
3317fe4709a8SVille Syrjälä drm_dbg_kms(display->drm,
3318fe4709a8SVille Syrjälä "Can change cdclk via crawling and squashing\n");
3319d34927acSVille Syrjälä } else if (intel_cdclk_can_squash(display,
3320d34927acSVille Syrjälä &old_cdclk_state->actual,
3321d34927acSVille Syrjälä &new_cdclk_state->actual)) {
33229161e311SGustavo Sousa drm_dbg_kms(display->drm,
33239161e311SGustavo Sousa "Can change cdclk via squashing\n");
33249161e311SGustavo Sousa } else if (intel_cdclk_can_crawl(display,
33259161e311SGustavo Sousa &old_cdclk_state->actual,
33269161e311SGustavo Sousa &new_cdclk_state->actual)) {
33279161e311SGustavo Sousa drm_dbg_kms(display->drm,
3328d34927acSVille Syrjälä "Can change cdclk via crawling\n");
332923194610SWambui Karuga } else if (pipe != INVALID_PIPE) {
33301965de63SVille Syrjälä new_cdclk_state->pipe = pipe;
33311965de63SVille Syrjälä
3332d34927acSVille Syrjälä drm_dbg_kms(display->drm,
333323194610SWambui Karuga "Can change cdclk cd2x divider with pipe %c active\n",
33341965de63SVille Syrjälä pipe_name(pipe));
33351965de63SVille Syrjälä } else if (intel_cdclk_clock_changed(&old_cdclk_state->actual,
3336fe4709a8SVille Syrjälä &new_cdclk_state->actual)) {
3337fe4709a8SVille Syrjälä /* All pipes must be switched off while we change the cdclk. */
3338fe4709a8SVille Syrjälä ret = intel_modeset_all_pipes_late(state, "CDCLK change");
3339fe4709a8SVille Syrjälä if (ret)
3340bd17fc4bSVille Syrjälä return ret;
3341bd17fc4bSVille Syrjälä
33420029d2f7SVille Syrjälä new_cdclk_state->disable_pipes = true;
33430029d2f7SVille Syrjälä
3344bd17fc4bSVille Syrjälä drm_dbg_kms(display->drm,
3345bd17fc4bSVille Syrjälä "Modeset required for cdclk change\n");
3346bd17fc4bSVille Syrjälä }
3347bd17fc4bSVille Syrjälä
3348bd17fc4bSVille Syrjälä if (intel_mdclk_cdclk_ratio(display, &old_cdclk_state->actual) !=
3349bd17fc4bSVille Syrjälä intel_mdclk_cdclk_ratio(display, &new_cdclk_state->actual)) {
3350bd17fc4bSVille Syrjälä int ratio = intel_mdclk_cdclk_ratio(display, &new_cdclk_state->actual);
3351bd17fc4bSVille Syrjälä
3352bd17fc4bSVille Syrjälä ret = intel_dbuf_state_set_mdclk_cdclk_ratio(state, ratio);
3353bd17fc4bSVille Syrjälä if (ret)
3354bd17fc4bSVille Syrjälä return ret;
3355e45b8192SVille Syrjälä }
3356bd17fc4bSVille Syrjälä
3357bd17fc4bSVille Syrjälä drm_dbg_kms(display->drm,
3358e45b8192SVille Syrjälä "New cdclk calculated to be logical %u kHz, actual %u kHz\n",
3359bd17fc4bSVille Syrjälä new_cdclk_state->logical.cdclk,
3360bd17fc4bSVille Syrjälä new_cdclk_state->actual.cdclk);
33610029d2f7SVille Syrjälä drm_dbg_kms(display->drm,
33620029d2f7SVille Syrjälä "New voltage level calculated to be logical %u, actual %u\n",
3363bd17fc4bSVille Syrjälä new_cdclk_state->logical.voltage_level,
3364bd17fc4bSVille Syrjälä new_cdclk_state->actual.voltage_level);
3365082ed1ffSVille Syrjälä
3366082ed1ffSVille Syrjälä return 0;
3367082ed1ffSVille Syrjälä }
3368082ed1ffSVille Syrjälä
intel_cdclk_update_hw_state(struct intel_display * display)3369003ec4ceSVille Syrjälä void intel_cdclk_update_hw_state(struct intel_display *display)
3370082ed1ffSVille Syrjälä {
3371082ed1ffSVille Syrjälä const struct intel_bw_state *bw_state =
3372d34927acSVille Syrjälä to_intel_bw_state(display->bw.obj.state);
33737ff89ca2SVille Syrjälä struct intel_cdclk_state *cdclk_state =
33746ad10f0bSVille Syrjälä to_intel_cdclk_state(display->cdclk.obj.state);
33756ad10f0bSVille Syrjälä struct intel_crtc *crtc;
3376d34927acSVille Syrjälä
33777ff89ca2SVille Syrjälä cdclk_state->active_pipes = 0;
33786ad10f0bSVille Syrjälä
33797ff89ca2SVille Syrjälä for_each_intel_crtc(display->drm, crtc) {
33807ff89ca2SVille Syrjälä const struct intel_crtc_state *crtc_state =
33817ff89ca2SVille Syrjälä to_intel_crtc_state(crtc->base.state);
33827ff89ca2SVille Syrjälä enum pipe pipe = crtc->pipe;
3383d34927acSVille Syrjälä
33847ff89ca2SVille Syrjälä if (crtc_state->hw.active)
33857ff89ca2SVille Syrjälä cdclk_state->active_pipes |= BIT(pipe);
33867ff89ca2SVille Syrjälä
33877ff89ca2SVille Syrjälä cdclk_state->min_cdclk[pipe] = intel_crtc_compute_min_cdclk(crtc_state);
33887ff89ca2SVille Syrjälä cdclk_state->min_voltage_level[pipe] = crtc_state->min_voltage_level;
3389d34927acSVille Syrjälä }
33907ff89ca2SVille Syrjälä
3391b0ad56ceSRadhakrishna Sripada cdclk_state->bw_min_cdclk = intel_bw_min_cdclk(display, bw_state);
3392b0ad56ceSRadhakrishna Sripada }
3393f0453266SJani Nikula
intel_cdclk_crtc_disable_noatomic(struct intel_crtc * crtc)3394d34927acSVille Syrjälä void intel_cdclk_crtc_disable_noatomic(struct intel_crtc *crtc)
3395d34927acSVille Syrjälä {
33966e63790eSJosé Roberto de Souza struct intel_display *display = to_intel_display(crtc);
3397d34927acSVille Syrjälä
3398d34927acSVille Syrjälä intel_cdclk_update_hw_state(display);
3399d34927acSVille Syrjälä }
3400d34927acSVille Syrjälä
intel_compute_max_dotclk(struct intel_display * display)3401186a277eSPaulo Zanoni static int intel_compute_max_dotclk(struct intel_display *display)
3402d34927acSVille Syrjälä {
3403f0453266SJani Nikula int ppc = intel_cdclk_ppc(display, HAS_DOUBLE_WIDE(display));
3404d34927acSVille Syrjälä int guardband = intel_cdclk_guardband(display);
3405f0453266SJani Nikula int max_cdclk_freq = display->cdclk.max_cdclk_freq;
3406d34927acSVille Syrjälä
3407d34927acSVille Syrjälä return ppc * max_cdclk_freq * guardband / 100;
3408d34927acSVille Syrjälä }
34097ff89ca2SVille Syrjälä
34107ff89ca2SVille Syrjälä /**
3411d34927acSVille Syrjälä * intel_update_max_cdclk - Determine the maximum support CDCLK frequency
3412d34927acSVille Syrjälä * @display: display instance
34137ff89ca2SVille Syrjälä *
34147ff89ca2SVille Syrjälä * Determine the maximum CDCLK frequency the platform supports, and also
34157ff89ca2SVille Syrjälä * derive the maximum dot clock frequency the maximum CDCLK frequency
34167ff89ca2SVille Syrjälä * allows.
34177ff89ca2SVille Syrjälä */
intel_update_max_cdclk(struct intel_display * display)34187ff89ca2SVille Syrjälä void intel_update_max_cdclk(struct intel_display *display)
34197ff89ca2SVille Syrjälä {
34207ff89ca2SVille Syrjälä if (DISPLAY_VERx100(display) >= 3002) {
34217ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 480000;
34227ff89ca2SVille Syrjälä } else if (DISPLAY_VER(display) >= 30) {
34237ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 691200;
34247ff89ca2SVille Syrjälä } else if (display->platform.jasperlake || display->platform.elkhartlake) {
34257ff89ca2SVille Syrjälä if (display->cdclk.hw.ref == 24000)
34267ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 552000;
34277ff89ca2SVille Syrjälä else
3428d34927acSVille Syrjälä display->cdclk.max_cdclk_freq = 556800;
3429f0453266SJani Nikula } else if (DISPLAY_VER(display) >= 11) {
34307ff89ca2SVille Syrjälä if (display->cdclk.hw.ref == 24000)
34317ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 648000;
34327ff89ca2SVille Syrjälä else
34337ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 652800;
34347ff89ca2SVille Syrjälä } else if (display->platform.geminilake) {
34357ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 316800;
3436d34927acSVille Syrjälä } else if (display->platform.broxton) {
3437d34927acSVille Syrjälä display->cdclk.max_cdclk_freq = 624000;
3438f0453266SJani Nikula } else if (DISPLAY_VER(display) == 9) {
3439d34927acSVille Syrjälä u32 limit = intel_de_read(display, SKL_DFSM) & SKL_DFSM_CDCLK_LIMIT_MASK;
3440f0453266SJani Nikula int max_cdclk, vco;
3441d34927acSVille Syrjälä
34427ff89ca2SVille Syrjälä vco = display->cdclk.skl_preferred_vco_freq;
3443d34927acSVille Syrjälä drm_WARN_ON(display->drm, vco != 8100000 && vco != 8640000);
3444f0453266SJani Nikula
3445d34927acSVille Syrjälä /*
3446f0453266SJani Nikula * Use the lower (vco 8640) cdclk values as a
3447d34927acSVille Syrjälä * first guess. skl_calc_cdclk() will correct it
34487ff89ca2SVille Syrjälä * if the preferred vco is 8100 instead.
34497ff89ca2SVille Syrjälä */
3450d34927acSVille Syrjälä if (limit == SKL_DFSM_CDCLK_LIMIT_675)
34517ff89ca2SVille Syrjälä max_cdclk = 617143;
34527ff89ca2SVille Syrjälä else if (limit == SKL_DFSM_CDCLK_LIMIT_540)
3453d34927acSVille Syrjälä max_cdclk = 540000;
34547ff89ca2SVille Syrjälä else if (limit == SKL_DFSM_CDCLK_LIMIT_450)
3455d34927acSVille Syrjälä max_cdclk = 432000;
3456d34927acSVille Syrjälä else
34577ff89ca2SVille Syrjälä max_cdclk = 308571;
3458d34927acSVille Syrjälä
3459d34927acSVille Syrjälä display->cdclk.max_cdclk_freq = skl_calc_cdclk(max_cdclk, vco);
34607ff89ca2SVille Syrjälä } else if (display->platform.broadwell) {
34617ff89ca2SVille Syrjälä /*
34627ff89ca2SVille Syrjälä * FIXME with extra cooling we can allow
34637ff89ca2SVille Syrjälä * 540 MHz for ULX and 675 Mhz for ULT.
3464d34927acSVille Syrjälä * How can we know if extra cooling is
34657ff89ca2SVille Syrjälä * available? PCI ID, VTB, something else?
34667ff89ca2SVille Syrjälä */
34677ff89ca2SVille Syrjälä if (intel_de_read(display, FUSE_STRAP) & HSW_CDCLK_LIMIT)
3468d34927acSVille Syrjälä display->cdclk.max_cdclk_freq = 450000;
34697ff89ca2SVille Syrjälä else if (display->platform.broadwell_ulx)
3470d34927acSVille Syrjälä display->cdclk.max_cdclk_freq = 450000;
34717ff89ca2SVille Syrjälä else if (display->platform.broadwell_ult)
34727ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 540000;
34737ff89ca2SVille Syrjälä else
34747ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 675000;
34757ff89ca2SVille Syrjälä } else if (display->platform.cherryview) {
34767ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = 320000;
34777ff89ca2SVille Syrjälä } else if (display->platform.valleyview) {
3478f0453266SJani Nikula display->cdclk.max_cdclk_freq = 400000;
3479d34927acSVille Syrjälä } else {
3480d34927acSVille Syrjälä /* otherwise assume cdclk is fixed */
34817ff89ca2SVille Syrjälä display->cdclk.max_cdclk_freq = display->cdclk.hw.cdclk;
34827ff89ca2SVille Syrjälä }
3483d34927acSVille Syrjälä
348427a6bc80SMatt Roper display->cdclk.max_dotclk_freq = intel_compute_max_dotclk(display);
348527a6bc80SMatt Roper
348627a6bc80SMatt Roper drm_dbg(display->drm, "Max CD clock rate: %d kHz\n",
348727a6bc80SMatt Roper display->cdclk.max_cdclk_freq);
348827a6bc80SMatt Roper
3489d34927acSVille Syrjälä drm_dbg(display->drm, "Max dotclock rate: %d kHz\n",
349027a6bc80SMatt Roper display->cdclk.max_dotclk_freq);
349127a6bc80SMatt Roper }
349227a6bc80SMatt Roper
349327a6bc80SMatt Roper /**
349427a6bc80SMatt Roper * intel_update_cdclk - Determine the current CDCLK frequency
3495d34927acSVille Syrjälä * @display: display instance
34969d81a997SRodrigo Vivi *
34979d81a997SRodrigo Vivi * Determine the current CDCLK frequency.
3498d34927acSVille Syrjälä */
intel_update_cdclk(struct intel_display * display)34999d81a997SRodrigo Vivi void intel_update_cdclk(struct intel_display *display)
3500d34927acSVille Syrjälä {
35019d81a997SRodrigo Vivi intel_cdclk_get_cdclk(display, &display->cdclk.hw);
35029d81a997SRodrigo Vivi
35039d81a997SRodrigo Vivi /*
35049d81a997SRodrigo Vivi * 9:0 CMBUS [sic] CDCLK frequency (cdfreq):
35059d81a997SRodrigo Vivi * Programmng [sic] note: bit[9:2] should be programmed to the number
35069d81a997SRodrigo Vivi * of cdclk that generates 4MHz reference clock freq which is used to
35079d81a997SRodrigo Vivi * generate GMBus clock. This will vary with the cdclk freq.
35089d81a997SRodrigo Vivi */
35099d81a997SRodrigo Vivi if (display->platform.valleyview || display->platform.cherryview)
3510af4de6adSPaulo Zanoni intel_de_write(display, GMBUSFREQ_VLV,
3511704e504bSPaulo Zanoni DIV_ROUND_UP(display->cdclk.hw.cdclk, 1000));
3512704e504bSPaulo Zanoni }
3513704e504bSPaulo Zanoni
dg1_rawclk(struct intel_display * display)3514704e504bSPaulo Zanoni static int dg1_rawclk(struct intel_display *display)
35159d81a997SRodrigo Vivi {
3516*4e9b0ac1SJani Nikula /*
3517704e504bSPaulo Zanoni * DG1 always uses a 38.4 MHz rawclk. The bspec tells us
3518704e504bSPaulo Zanoni * "Program Numerator=2, Denominator=4, Divider=37 decimal."
35199d81a997SRodrigo Vivi */
3520d34927acSVille Syrjälä intel_de_write(display, PCH_RAWCLK_FREQ,
35219d81a997SRodrigo Vivi CNP_RAWCLK_DEN(4) | CNP_RAWCLK_DIV(37) | ICP_RAWCLK_NUM(2));
35229d81a997SRodrigo Vivi
35239d81a997SRodrigo Vivi return 38400;
3524d34927acSVille Syrjälä }
35257ff89ca2SVille Syrjälä
cnp_rawclk(struct intel_display * display)3526d34927acSVille Syrjälä static int cnp_rawclk(struct intel_display *display)
35277ff89ca2SVille Syrjälä {
35287ff89ca2SVille Syrjälä int divider, fraction;
3529d34927acSVille Syrjälä u32 rawclk;
35307ff89ca2SVille Syrjälä
3531d34927acSVille Syrjälä if (intel_de_read(display, SFUSE_STRAP) & SFUSE_STRAP_RAW_FREQUENCY) {
3532d34927acSVille Syrjälä /* 24 MHz */
35337ff89ca2SVille Syrjälä divider = 24000;
35347ff89ca2SVille Syrjälä fraction = 0;
35357ff89ca2SVille Syrjälä } else {
35367ff89ca2SVille Syrjälä /* 19.2 MHz */
35377ff89ca2SVille Syrjälä divider = 19000;
3538d34927acSVille Syrjälä fraction = 200;
35397ff89ca2SVille Syrjälä }
3540d34927acSVille Syrjälä
3541d34927acSVille Syrjälä rawclk = CNP_RAWCLK_DIV(divider / 1000);
3542b2956099SJani Nikula if (fraction) {
35431cd377f3SJani Nikula int numerator = 1;
35447ff89ca2SVille Syrjälä
35457ff89ca2SVille Syrjälä rawclk |= CNP_RAWCLK_DEN(DIV_ROUND_CLOSEST(numerator * 1000,
35467ff89ca2SVille Syrjälä fraction) - 1);
3547b04002f4SChris Wilson if (INTEL_PCH_TYPE(display) >= PCH_ICP)
3548d34927acSVille Syrjälä rawclk |= ICP_RAWCLK_NUM(numerator);
35497ff89ca2SVille Syrjälä }
35507ff89ca2SVille Syrjälä
35517ff89ca2SVille Syrjälä intel_de_write(display, PCH_RAWCLK_FREQ, rawclk);
35527ff89ca2SVille Syrjälä return divider + fraction;
3553d34927acSVille Syrjälä }
35547ff89ca2SVille Syrjälä
pch_rawclk(struct intel_display * display)3555b04002f4SChris Wilson static int pch_rawclk(struct intel_display *display)
3556b04002f4SChris Wilson {
3557*4e9b0ac1SJani Nikula return (intel_de_read(display, PCH_RAWCLK_FREQ) & RAWCLK_FREQ_MASK) * 1000;
3558dc35583bSClint Taylor }
3559dc35583bSClint Taylor
vlv_hrawclk(struct intel_display * display)3560dc35583bSClint Taylor static int vlv_hrawclk(struct intel_display *display)
3561dc35583bSClint Taylor {
3562dc35583bSClint Taylor /* RAWCLK_FREQ_VLV register updated from power well code */
3563dc35583bSClint Taylor return vlv_get_cck_clock_hpll(display->drm, "hrawclk",
3564*4e9b0ac1SJani Nikula CCK_DISPLAY_REF_CLOCK_CONTROL);
3565d34927acSVille Syrjälä }
3566*4e9b0ac1SJani Nikula
i9xx_hrawclk(struct intel_display * display)3567d34927acSVille Syrjälä static int i9xx_hrawclk(struct intel_display *display)
3568*4e9b0ac1SJani Nikula {
3569d34927acSVille Syrjälä struct drm_i915_private *i915 = to_i915(display->drm);
3570f0453266SJani Nikula
3571d34927acSVille Syrjälä /* hrawclock is 1/4 the FSB frequency */
3572d34927acSVille Syrjälä return DIV_ROUND_CLOSEST(i9xx_fsb_freq(i915), 4);
3573d34927acSVille Syrjälä }
35747ff89ca2SVille Syrjälä
35757ff89ca2SVille Syrjälä /**
3576b04002f4SChris Wilson * intel_read_rawclk - Determine the current RAWCLK frequency
35777ff89ca2SVille Syrjälä * @display: display instance
3578b04002f4SChris Wilson *
35797ff89ca2SVille Syrjälä * Determine the current RAWCLK frequency. RAWCLK is a fixed
35807ff89ca2SVille Syrjälä * frequency clock so this needs to done only once.
3581d7c281eeSBhanuprakash Modem */
intel_read_rawclk(struct intel_display * display)3582d7c281eeSBhanuprakash Modem u32 intel_read_rawclk(struct intel_display *display)
3583d34927acSVille Syrjälä {
3584d7c281eeSBhanuprakash Modem u32 freq;
3585d34927acSVille Syrjälä
3586d34927acSVille Syrjälä if (INTEL_PCH_TYPE(display) >= PCH_MTL)
3587d34927acSVille Syrjälä /*
3588d7c281eeSBhanuprakash Modem * MTL always uses a 38.4 MHz rawclk. The bspec tells us
3589d7c281eeSBhanuprakash Modem * "RAWCLK_FREQ defaults to the values for 38.4 and does
3590d7c281eeSBhanuprakash Modem * not need to be programmed."
3591d7c281eeSBhanuprakash Modem */
3592d7c281eeSBhanuprakash Modem freq = 38400;
3593d7c281eeSBhanuprakash Modem else if (INTEL_PCH_TYPE(display) >= PCH_DG1)
3594d34927acSVille Syrjälä freq = dg1_rawclk(display);
3595d7c281eeSBhanuprakash Modem else if (INTEL_PCH_TYPE(display) >= PCH_CNP)
3596d34927acSVille Syrjälä freq = cnp_rawclk(display);
3597d7c281eeSBhanuprakash Modem else if (HAS_PCH_SPLIT(display))
3598d7c281eeSBhanuprakash Modem freq = pch_rawclk(display);
3599d34927acSVille Syrjälä else if (display->platform.valleyview || display->platform.cherryview)
3600d7c281eeSBhanuprakash Modem freq = vlv_hrawclk(display);
3601d7c281eeSBhanuprakash Modem else if (DISPLAY_VER(display) >= 3)
3602b0ad56ceSRadhakrishna Sripada freq = i9xx_hrawclk(display);
3603b0ad56ceSRadhakrishna Sripada else
3604b0ad56ceSRadhakrishna Sripada /* no rawclk on other platforms, or no need to know it */
3605b0ad56ceSRadhakrishna Sripada return 0;
3606b0ad56ceSRadhakrishna Sripada
3607b0ad56ceSRadhakrishna Sripada return freq;
3608b0ad56ceSRadhakrishna Sripada }
36095a3c46b8SChaitanya Kumar Borah
i915_cdclk_info_show(struct seq_file * m,void * unused)36105a3c46b8SChaitanya Kumar Borah static int i915_cdclk_info_show(struct seq_file *m, void *unused)
36115a3c46b8SChaitanya Kumar Borah {
36125a3c46b8SChaitanya Kumar Borah struct intel_display *display = m->private;
36135a3c46b8SChaitanya Kumar Borah
36145a3c46b8SChaitanya Kumar Borah seq_printf(m, "Current CD clock frequency: %d kHz\n", display->cdclk.hw.cdclk);
36155a3c46b8SChaitanya Kumar Borah seq_printf(m, "Max CD clock frequency: %d kHz\n", display->cdclk.max_cdclk_freq);
3616877d0749SJani Nikula seq_printf(m, "Max pixel clock frequency: %d kHz\n", display->cdclk.max_dotclk_freq);
36176b4cd9cbSDave Airlie
36186b4cd9cbSDave Airlie return 0;
36196b4cd9cbSDave Airlie }
36206b4cd9cbSDave Airlie
36216b4cd9cbSDave Airlie DEFINE_SHOW_ATTRIBUTE(i915_cdclk_info);
36226b4cd9cbSDave Airlie
intel_cdclk_debugfs_register(struct intel_display * display)3623877d0749SJani Nikula void intel_cdclk_debugfs_register(struct intel_display *display)
36246b4cd9cbSDave Airlie {
36256b4cd9cbSDave Airlie struct drm_minor *minor = display->drm->primary;
36266b4cd9cbSDave Airlie
36276b4cd9cbSDave Airlie debugfs_create_file("i915_cdclk_info", 0444, minor->debugfs_root,
36286b4cd9cbSDave Airlie display, &i915_cdclk_info_fops);
36296b4cd9cbSDave Airlie }
3630877d0749SJani Nikula
36316b4cd9cbSDave Airlie static const struct intel_cdclk_funcs xe3lpd_cdclk_funcs = {
36326b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
36336b4cd9cbSDave Airlie .set_cdclk = bxt_set_cdclk,
36346b4cd9cbSDave Airlie .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
36356b4cd9cbSDave Airlie .calc_voltage_level = xe3lpd_calc_voltage_level,
36366b4cd9cbSDave Airlie };
3637877d0749SJani Nikula
36386b4cd9cbSDave Airlie static const struct intel_cdclk_funcs rplu_cdclk_funcs = {
36396b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
36406b4cd9cbSDave Airlie .set_cdclk = bxt_set_cdclk,
36416b4cd9cbSDave Airlie .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
36426b4cd9cbSDave Airlie .calc_voltage_level = rplu_calc_voltage_level,
36436b4cd9cbSDave Airlie };
3644877d0749SJani Nikula
36456b4cd9cbSDave Airlie static const struct intel_cdclk_funcs tgl_cdclk_funcs = {
36466b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
36476b4cd9cbSDave Airlie .set_cdclk = bxt_set_cdclk,
36486b4cd9cbSDave Airlie .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
36496b4cd9cbSDave Airlie .calc_voltage_level = tgl_calc_voltage_level,
3650877d0749SJani Nikula };
36516b4cd9cbSDave Airlie
36526b4cd9cbSDave Airlie static const struct intel_cdclk_funcs ehl_cdclk_funcs = {
36536b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
36546b4cd9cbSDave Airlie .set_cdclk = bxt_set_cdclk,
36556b4cd9cbSDave Airlie .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
3656877d0749SJani Nikula .calc_voltage_level = ehl_calc_voltage_level,
36576b4cd9cbSDave Airlie };
36586b4cd9cbSDave Airlie
36596b4cd9cbSDave Airlie static const struct intel_cdclk_funcs icl_cdclk_funcs = {
36606b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
36616b4cd9cbSDave Airlie .set_cdclk = bxt_set_cdclk,
3662877d0749SJani Nikula .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
36636b4cd9cbSDave Airlie .calc_voltage_level = icl_calc_voltage_level,
36646b4cd9cbSDave Airlie };
36656b4cd9cbSDave Airlie
36666b4cd9cbSDave Airlie static const struct intel_cdclk_funcs bxt_cdclk_funcs = {
36676b4cd9cbSDave Airlie .get_cdclk = bxt_get_cdclk,
3668877d0749SJani Nikula .set_cdclk = bxt_set_cdclk,
36696b4cd9cbSDave Airlie .modeset_calc_cdclk = bxt_modeset_calc_cdclk,
36706b4cd9cbSDave Airlie .calc_voltage_level = bxt_calc_voltage_level,
36716b4cd9cbSDave Airlie };
36726b4cd9cbSDave Airlie
36736b4cd9cbSDave Airlie static const struct intel_cdclk_funcs skl_cdclk_funcs = {
3674877d0749SJani Nikula .get_cdclk = skl_get_cdclk,
36756b4cd9cbSDave Airlie .set_cdclk = skl_set_cdclk,
36766b4cd9cbSDave Airlie .modeset_calc_cdclk = skl_modeset_calc_cdclk,
36776b4cd9cbSDave Airlie };
36786b4cd9cbSDave Airlie
3679877d0749SJani Nikula static const struct intel_cdclk_funcs bdw_cdclk_funcs = {
36806b4cd9cbSDave Airlie .get_cdclk = bdw_get_cdclk,
36816b4cd9cbSDave Airlie .set_cdclk = bdw_set_cdclk,
36826b4cd9cbSDave Airlie .modeset_calc_cdclk = bdw_modeset_calc_cdclk,
36836b4cd9cbSDave Airlie };
3684877d0749SJani Nikula
36856b4cd9cbSDave Airlie static const struct intel_cdclk_funcs chv_cdclk_funcs = {
36866b4cd9cbSDave Airlie .get_cdclk = vlv_get_cdclk,
36876b4cd9cbSDave Airlie .set_cdclk = chv_set_cdclk,
36886b4cd9cbSDave Airlie .modeset_calc_cdclk = vlv_modeset_calc_cdclk,
36896b4cd9cbSDave Airlie };
36906b4cd9cbSDave Airlie
3691877d0749SJani Nikula static const struct intel_cdclk_funcs vlv_cdclk_funcs = {
36926b4cd9cbSDave Airlie .get_cdclk = vlv_get_cdclk,
36936b4cd9cbSDave Airlie .set_cdclk = vlv_set_cdclk,
36946b4cd9cbSDave Airlie .modeset_calc_cdclk = vlv_modeset_calc_cdclk,
36956b4cd9cbSDave Airlie };
36966b4cd9cbSDave Airlie
36976b4cd9cbSDave Airlie static const struct intel_cdclk_funcs hsw_cdclk_funcs = {
3698877d0749SJani Nikula .get_cdclk = hsw_get_cdclk,
36996b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37006b4cd9cbSDave Airlie };
37016b4cd9cbSDave Airlie
37026b4cd9cbSDave Airlie /* SNB, IVB, 965G, 945G */
3703877d0749SJani Nikula static const struct intel_cdclk_funcs fixed_400mhz_cdclk_funcs = {
37046b4cd9cbSDave Airlie .get_cdclk = fixed_400mhz_get_cdclk,
37056b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37066b4cd9cbSDave Airlie };
37076b4cd9cbSDave Airlie
3708877d0749SJani Nikula static const struct intel_cdclk_funcs ilk_cdclk_funcs = {
37096b4cd9cbSDave Airlie .get_cdclk = fixed_450mhz_get_cdclk,
37106b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37116b4cd9cbSDave Airlie };
37126b4cd9cbSDave Airlie
37136b4cd9cbSDave Airlie static const struct intel_cdclk_funcs gm45_cdclk_funcs = {
37146b4cd9cbSDave Airlie .get_cdclk = gm45_get_cdclk,
3715877d0749SJani Nikula .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37166b4cd9cbSDave Airlie };
37176b4cd9cbSDave Airlie
37186b4cd9cbSDave Airlie /* G45 uses G33 */
37196b4cd9cbSDave Airlie
3720877d0749SJani Nikula static const struct intel_cdclk_funcs i965gm_cdclk_funcs = {
37216b4cd9cbSDave Airlie .get_cdclk = i965gm_get_cdclk,
37226b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37236b4cd9cbSDave Airlie };
37246b4cd9cbSDave Airlie
3725877d0749SJani Nikula /* i965G uses fixed 400 */
37266b4cd9cbSDave Airlie
37276b4cd9cbSDave Airlie static const struct intel_cdclk_funcs pnv_cdclk_funcs = {
37286b4cd9cbSDave Airlie .get_cdclk = pnv_get_cdclk,
37296b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3730877d0749SJani Nikula };
37316b4cd9cbSDave Airlie
37326b4cd9cbSDave Airlie static const struct intel_cdclk_funcs g33_cdclk_funcs = {
37336b4cd9cbSDave Airlie .get_cdclk = g33_get_cdclk,
37346b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3735877d0749SJani Nikula };
37366b4cd9cbSDave Airlie
37376b4cd9cbSDave Airlie static const struct intel_cdclk_funcs i945gm_cdclk_funcs = {
37386b4cd9cbSDave Airlie .get_cdclk = i945gm_get_cdclk,
37396b4cd9cbSDave Airlie .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3740877d0749SJani Nikula };
37416b4cd9cbSDave Airlie
37426b4cd9cbSDave Airlie /* i945G uses fixed 400 */
37436b4cd9cbSDave Airlie
37446b4cd9cbSDave Airlie static const struct intel_cdclk_funcs i915gm_cdclk_funcs = {
37457ff89ca2SVille Syrjälä .get_cdclk = i915gm_get_cdclk,
37467ff89ca2SVille Syrjälä .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3747d34927acSVille Syrjälä };
37487ff89ca2SVille Syrjälä
3749d34927acSVille Syrjälä static const struct intel_cdclk_funcs i915g_cdclk_funcs = {
37507ff89ca2SVille Syrjälä .get_cdclk = fixed_333mhz_get_cdclk,
3751b0ad56ceSRadhakrishna Sripada .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3752b0ad56ceSRadhakrishna Sripada };
3753b0ad56ceSRadhakrishna Sripada
3754b0ad56ceSRadhakrishna Sripada static const struct intel_cdclk_funcs i865g_cdclk_funcs = {
3755d34927acSVille Syrjälä .get_cdclk = fixed_266mhz_get_cdclk,
3756d34927acSVille Syrjälä .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37575eb2e785SJani Nikula };
3758d34927acSVille Syrjälä
3759d34927acSVille Syrjälä static const struct intel_cdclk_funcs i85x_cdclk_funcs = {
3760d34927acSVille Syrjälä .get_cdclk = i85x_get_cdclk,
3761d34927acSVille Syrjälä .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3762d34927acSVille Syrjälä };
3763f0453266SJani Nikula
3764d34927acSVille Syrjälä static const struct intel_cdclk_funcs i845g_cdclk_funcs = {
3765d34927acSVille Syrjälä .get_cdclk = fixed_200mhz_get_cdclk,
3766f0453266SJani Nikula .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
37671d2b8fd9SJosé Roberto de Souza };
3768f0453266SJani Nikula
3769d34927acSVille Syrjälä static const struct intel_cdclk_funcs i830_cdclk_funcs = {
3770d34927acSVille Syrjälä .get_cdclk = fixed_133mhz_get_cdclk,
3771f0453266SJani Nikula .modeset_calc_cdclk = fixed_modeset_calc_cdclk,
3772d34927acSVille Syrjälä };
3773d34927acSVille Syrjälä
37745a3c46b8SChaitanya Kumar Borah /**
3775d34927acSVille Syrjälä * intel_init_cdclk_hooks - Initialize CDCLK related modesetting hooks
3776d34927acSVille Syrjälä * @display: display instance
37775a3c46b8SChaitanya Kumar Borah */
intel_init_cdclk_hooks(struct intel_display * display)3778f0453266SJani Nikula void intel_init_cdclk_hooks(struct intel_display *display)
3779d34927acSVille Syrjälä {
3780d34927acSVille Syrjälä if (DISPLAY_VER(display) >= 30) {
3781d34927acSVille Syrjälä display->funcs.cdclk = &xe3lpd_cdclk_funcs;
3782d34927acSVille Syrjälä display->cdclk.table = xe3lpd_cdclk_table;
3783d34927acSVille Syrjälä } else if (DISPLAY_VER(display) >= 20) {
3784f0453266SJani Nikula display->funcs.cdclk = &rplu_cdclk_funcs;
3785d34927acSVille Syrjälä display->cdclk.table = xe2lpd_cdclk_table;
3786d34927acSVille Syrjälä } else if (DISPLAY_VERx100(display) >= 1401) {
3787d34927acSVille Syrjälä display->funcs.cdclk = &rplu_cdclk_funcs;
3788d34927acSVille Syrjälä display->cdclk.table = xe2hpd_cdclk_table;
3789d34927acSVille Syrjälä } else if (DISPLAY_VER(display) >= 14) {
3790f0453266SJani Nikula display->funcs.cdclk = &rplu_cdclk_funcs;
3791d34927acSVille Syrjälä display->cdclk.table = mtl_cdclk_table;
3792f0453266SJani Nikula } else if (display->platform.dg2) {
3793d34927acSVille Syrjälä display->funcs.cdclk = &tgl_cdclk_funcs;
379443ed2275SChris Wilson display->cdclk.table = dg2_cdclk_table;
3795d34927acSVille Syrjälä } else if (display->platform.alderlake_p) {
3796d34927acSVille Syrjälä /* Wa_22011320316:adl-p[a0] */
3797d34927acSVille Syrjälä if (display->platform.alderlake_p && IS_DISPLAY_STEP(display, STEP_A0, STEP_B0)) {
3798f0453266SJani Nikula display->cdclk.table = adlp_a_step_cdclk_table;
3799d34927acSVille Syrjälä display->funcs.cdclk = &tgl_cdclk_funcs;
3800f0453266SJani Nikula } else if (display->platform.alderlake_p_raptorlake_u) {
3801d34927acSVille Syrjälä display->cdclk.table = rplu_cdclk_table;
3802f0453266SJani Nikula display->funcs.cdclk = &rplu_cdclk_funcs;
3803d34927acSVille Syrjälä } else {
3804f0453266SJani Nikula display->cdclk.table = adlp_cdclk_table;
3805d34927acSVille Syrjälä display->funcs.cdclk = &tgl_cdclk_funcs;
3806f0453266SJani Nikula }
3807d34927acSVille Syrjälä } else if (display->platform.rocketlake) {
3808f0453266SJani Nikula display->funcs.cdclk = &tgl_cdclk_funcs;
3809d34927acSVille Syrjälä display->cdclk.table = rkl_cdclk_table;
3810f0453266SJani Nikula } else if (DISPLAY_VER(display) >= 12) {
3811d34927acSVille Syrjälä display->funcs.cdclk = &tgl_cdclk_funcs;
3812f0453266SJani Nikula display->cdclk.table = icl_cdclk_table;
3813d34927acSVille Syrjälä } else if (display->platform.jasperlake || display->platform.elkhartlake) {
3814f0453266SJani Nikula display->funcs.cdclk = &ehl_cdclk_funcs;
3815d34927acSVille Syrjälä display->cdclk.table = icl_cdclk_table;
3816f0453266SJani Nikula } else if (DISPLAY_VER(display) >= 11) {
3817d34927acSVille Syrjälä display->funcs.cdclk = &icl_cdclk_funcs;
3818f0453266SJani Nikula display->cdclk.table = icl_cdclk_table;
3819d34927acSVille Syrjälä } else if (display->platform.geminilake || display->platform.broxton) {
3820f0453266SJani Nikula display->funcs.cdclk = &bxt_cdclk_funcs;
3821d34927acSVille Syrjälä if (display->platform.geminilake)
3822f0453266SJani Nikula display->cdclk.table = glk_cdclk_table;
3823d34927acSVille Syrjälä else
3824f0453266SJani Nikula display->cdclk.table = bxt_cdclk_table;
3825d34927acSVille Syrjälä } else if (DISPLAY_VER(display) == 9) {
3826f0453266SJani Nikula display->funcs.cdclk = &skl_cdclk_funcs;
3827d34927acSVille Syrjälä } else if (display->platform.broadwell) {
3828f0453266SJani Nikula display->funcs.cdclk = &bdw_cdclk_funcs;
3829d34927acSVille Syrjälä } else if (display->platform.haswell) {
3830f0453266SJani Nikula display->funcs.cdclk = &hsw_cdclk_funcs;
3831d34927acSVille Syrjälä } else if (display->platform.cherryview) {
3832f0453266SJani Nikula display->funcs.cdclk = &chv_cdclk_funcs;
3833d34927acSVille Syrjälä } else if (display->platform.valleyview) {
3834f0453266SJani Nikula display->funcs.cdclk = &vlv_cdclk_funcs;
3835d34927acSVille Syrjälä } else if (display->platform.sandybridge || display->platform.ivybridge) {
3836f0453266SJani Nikula display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
3837d34927acSVille Syrjälä } else if (display->platform.ironlake) {
38387ff89ca2SVille Syrjälä display->funcs.cdclk = &ilk_cdclk_funcs;
38397ff89ca2SVille Syrjälä } else if (display->platform.gm45) {
3840d34927acSVille Syrjälä display->funcs.cdclk = &gm45_cdclk_funcs;
38416b4cd9cbSDave Airlie } else if (display->platform.g45) {
3842d34927acSVille Syrjälä display->funcs.cdclk = &g33_cdclk_funcs;
38437ff89ca2SVille Syrjälä } else if (display->platform.i965gm) {
3844 display->funcs.cdclk = &i965gm_cdclk_funcs;
3845 } else if (display->platform.i965g) {
3846 display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
3847 } else if (display->platform.pineview) {
3848 display->funcs.cdclk = &pnv_cdclk_funcs;
3849 } else if (display->platform.g33) {
3850 display->funcs.cdclk = &g33_cdclk_funcs;
3851 } else if (display->platform.i945gm) {
3852 display->funcs.cdclk = &i945gm_cdclk_funcs;
3853 } else if (display->platform.i945g) {
3854 display->funcs.cdclk = &fixed_400mhz_cdclk_funcs;
3855 } else if (display->platform.i915gm) {
3856 display->funcs.cdclk = &i915gm_cdclk_funcs;
3857 } else if (display->platform.i915g) {
3858 display->funcs.cdclk = &i915g_cdclk_funcs;
3859 } else if (display->platform.i865g) {
3860 display->funcs.cdclk = &i865g_cdclk_funcs;
3861 } else if (display->platform.i85x) {
3862 display->funcs.cdclk = &i85x_cdclk_funcs;
3863 } else if (display->platform.i845g) {
3864 display->funcs.cdclk = &i845g_cdclk_funcs;
3865 } else if (display->platform.i830) {
3866 display->funcs.cdclk = &i830_cdclk_funcs;
3867 }
3868
3869 if (drm_WARN(display->drm, !display->funcs.cdclk,
3870 "Unknown platform. Assuming i830\n"))
3871 display->funcs.cdclk = &i830_cdclk_funcs;
3872 }
3873
intel_cdclk_logical(const struct intel_cdclk_state * cdclk_state)3874 int intel_cdclk_logical(const struct intel_cdclk_state *cdclk_state)
3875 {
3876 return cdclk_state->logical.cdclk;
3877 }
3878
intel_cdclk_actual(const struct intel_cdclk_state * cdclk_state)3879 int intel_cdclk_actual(const struct intel_cdclk_state *cdclk_state)
3880 {
3881 return cdclk_state->actual.cdclk;
3882 }
3883
intel_cdclk_actual_voltage_level(const struct intel_cdclk_state * cdclk_state)3884 int intel_cdclk_actual_voltage_level(const struct intel_cdclk_state *cdclk_state)
3885 {
3886 return cdclk_state->actual.voltage_level;
3887 }
3888
intel_cdclk_min_cdclk(const struct intel_cdclk_state * cdclk_state,enum pipe pipe)3889 int intel_cdclk_min_cdclk(const struct intel_cdclk_state *cdclk_state, enum pipe pipe)
3890 {
3891 return cdclk_state->min_cdclk[pipe];
3892 }
3893
intel_cdclk_bw_min_cdclk(const struct intel_cdclk_state * cdclk_state)3894 int intel_cdclk_bw_min_cdclk(const struct intel_cdclk_state *cdclk_state)
3895 {
3896 return cdclk_state->bw_min_cdclk;
3897 }
3898
intel_cdclk_pmdemand_needs_update(struct intel_atomic_state * state)3899 bool intel_cdclk_pmdemand_needs_update(struct intel_atomic_state *state)
3900 {
3901 const struct intel_cdclk_state *new_cdclk_state, *old_cdclk_state;
3902
3903 new_cdclk_state = intel_atomic_get_new_cdclk_state(state);
3904 old_cdclk_state = intel_atomic_get_old_cdclk_state(state);
3905
3906 if (new_cdclk_state &&
3907 (new_cdclk_state->actual.cdclk != old_cdclk_state->actual.cdclk ||
3908 new_cdclk_state->actual.voltage_level != old_cdclk_state->actual.voltage_level))
3909 return true;
3910
3911 return false;
3912 }
3913
intel_cdclk_force_min_cdclk(struct intel_cdclk_state * cdclk_state,int force_min_cdclk)3914 void intel_cdclk_force_min_cdclk(struct intel_cdclk_state *cdclk_state, int force_min_cdclk)
3915 {
3916 cdclk_state->force_min_cdclk = force_min_cdclk;
3917 }
3918
intel_cdclk_read_hw(struct intel_display * display)3919 void intel_cdclk_read_hw(struct intel_display *display)
3920 {
3921 struct intel_cdclk_state *cdclk_state;
3922
3923 cdclk_state = to_intel_cdclk_state(display->cdclk.obj.state);
3924
3925 intel_update_cdclk(display);
3926 intel_cdclk_dump_config(display, &display->cdclk.hw, "Current CDCLK");
3927 cdclk_state->actual = display->cdclk.hw;
3928 cdclk_state->logical = display->cdclk.hw;
3929 }
3930