1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Copyright (C) 2016 BayLibre, SAS
4 * Author: Neil Armstrong <narmstrong@baylibre.com>
5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
8 #include <linux/kernel.h>
9 #include <linux/module.h>
11 #include "meson_drv.h"
12 #include "meson_vclk.h"
17 * VCLK is the "Pixel Clock" frequency generator from a dedicated PLL.
18 * We handle the following encodings :
20 * - CVBS 27MHz generator via the VCLK2 to the VENCI and VDAC blocks
21 * - HDMI Pixel Clocks generation
25 * - Genenate Pixel clocks for 2K/4K 10bit formats
27 * Clock generator scheme :
31 * __________ _________ _____
33 * | HDMI PLL |-| PLL_DIV |--- VCLK--| |--ENCL
34 * |__________| |_________| \ | MUX |--ENCP
38 * Final clocks can take input for either VCLK or VCLK2, but
39 * VCLK is the preferred path for HDMI clocking and VCLK2 is the
40 * preferred path for CVBS VDAC clocking.
42 * VCLK and VCLK2 have fixed divided clocks paths for /1, /2, /4, /6 or /12.
44 * The PLL_DIV can achieve an additional fractional dividing like
45 * 1.5, 3.5, 3.75... to generate special 2K and 4K 10bit clocks.
49 #define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
50 #define VID_PLL_EN BIT(19)
51 #define VID_PLL_BYPASS BIT(18)
52 #define VID_PLL_PRESET BIT(15)
53 #define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
54 #define VCLK2_DIV_MASK 0xff
55 #define VCLK2_DIV_EN BIT(16)
56 #define VCLK2_DIV_RESET BIT(17)
57 #define CTS_VDAC_SEL_MASK (0xf << 28)
58 #define CTS_VDAC_SEL_SHIFT 28
59 #define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
60 #define VCLK2_EN BIT(19)
61 #define VCLK2_SEL_MASK (0x7 << 16)
62 #define VCLK2_SEL_SHIFT 16
63 #define VCLK2_SOFT_RESET BIT(15)
64 #define VCLK2_DIV1_EN BIT(0)
65 #define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
66 #define VCLK_DIV_MASK 0xff
67 #define VCLK_DIV_EN BIT(16)
68 #define VCLK_DIV_RESET BIT(17)
69 #define CTS_ENCP_SEL_MASK (0xf << 24)
70 #define CTS_ENCP_SEL_SHIFT 24
71 #define CTS_ENCI_SEL_MASK (0xf << 28)
72 #define CTS_ENCI_SEL_SHIFT 28
73 #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
74 #define VCLK_EN BIT(19)
75 #define VCLK_SEL_MASK (0x7 << 16)
76 #define VCLK_SEL_SHIFT 16
77 #define VCLK_SOFT_RESET BIT(15)
78 #define VCLK_DIV1_EN BIT(0)
79 #define VCLK_DIV2_EN BIT(1)
80 #define VCLK_DIV4_EN BIT(2)
81 #define VCLK_DIV6_EN BIT(3)
82 #define VCLK_DIV12_EN BIT(4)
83 #define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
84 #define CTS_ENCI_EN BIT(0)
85 #define CTS_ENCP_EN BIT(2)
86 #define CTS_VDAC_EN BIT(4)
87 #define HDMI_TX_PIXEL_EN BIT(5)
88 #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
89 #define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
90 #define HDMI_TX_PIXEL_SEL_SHIFT 16
91 #define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
92 #define CTS_HDMI_SYS_DIV_MASK (0x7f)
93 #define CTS_HDMI_SYS_EN BIT(8)
95 #define HHI_VDAC_CNTL0 0x2F4 /* 0xbd offset in data sheet */
96 #define HHI_VDAC_CNTL1 0x2F8 /* 0xbe offset in data sheet */
98 #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
99 #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
100 #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
101 #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
102 #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
103 #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
104 #define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
106 #define HDMI_PLL_RESET BIT(28)
107 #define HDMI_PLL_RESET_G12A BIT(29)
108 #define HDMI_PLL_LOCK BIT(31)
109 #define HDMI_PLL_LOCK_G12A (3 << 30)
111 #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
113 /* VID PLL Dividers */
132 void meson_vid_pll_set(struct meson_drm *priv, unsigned int div)
134 unsigned int shift_val = 0;
135 unsigned int shift_sel = 0;
137 /* Disable vid_pll output clock */
138 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
139 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
146 case VID_PLL_DIV_2p5:
154 case VID_PLL_DIV_3p5:
158 case VID_PLL_DIV_3p75:
174 case VID_PLL_DIV_6p25:
182 case VID_PLL_DIV_7p5:
200 if (div == VID_PLL_DIV_1)
201 /* Enable vid_pll bypass to HDMI pll */
202 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
203 VID_PLL_BYPASS, VID_PLL_BYPASS);
206 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
209 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
211 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
213 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
216 /* Setup sel and val */
217 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
218 3 << 16, shift_sel << 16);
219 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
220 VID_PLL_PRESET, VID_PLL_PRESET);
221 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
224 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
228 /* Enable the vid_pll output clock */
229 regmap_update_bits(priv->hhi, HHI_VID_PLL_CLK_DIV,
230 VID_PLL_EN, VID_PLL_EN);
234 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
236 * TOFIX: Refactor into table to also handle HDMI frequency and paths
238 static void meson_venci_cvbs_clock_config(struct meson_drm *priv)
242 /* Setup PLL to output 1.485GHz */
243 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
244 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x5800023d);
245 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00404e00);
246 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
247 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
248 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
249 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
250 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4800023d);
252 /* Poll for lock bit */
253 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
254 (val & HDMI_PLL_LOCK), 10, 0);
255 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
256 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
257 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x4000027b);
258 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb300);
259 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0xa6212844);
260 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
261 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
262 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
265 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
266 HDMI_PLL_RESET, HDMI_PLL_RESET);
267 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
270 /* Poll for lock bit */
271 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
272 (val & HDMI_PLL_LOCK), 10, 0);
273 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
274 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
275 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x00010000);
276 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
277 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
278 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
279 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
280 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x56540000);
281 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x3a0504f7);
282 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x1a0504f7);
284 /* Poll for lock bit */
285 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
286 ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
291 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
293 /* Setup vid_pll to /1 */
294 meson_vid_pll_set(priv, VID_PLL_DIV_1);
296 /* Setup the VCLK2 divider value to achieve 27MHz */
297 regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
298 VCLK2_DIV_MASK, (55 - 1));
300 /* select vid_pll for vclk2 */
301 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
302 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
303 VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
305 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
306 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
308 /* enable vclk2 gate */
309 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
311 /* select vclk_div1 for enci */
312 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
313 CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
314 /* select vclk_div1 for vdac */
315 regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
316 CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
318 /* release vclk2_div_reset and enable vclk2_div */
319 regmap_update_bits(priv->hhi, HHI_VIID_CLK_DIV,
320 VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
322 /* enable vclk2_div1 gate */
323 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
324 VCLK2_DIV1_EN, VCLK2_DIV1_EN);
327 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
328 VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
329 regmap_update_bits(priv->hhi, HHI_VIID_CLK_CNTL,
330 VCLK2_SOFT_RESET, 0);
332 /* enable enci_clk */
333 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
334 CTS_ENCI_EN, CTS_ENCI_EN);
335 /* enable vdac_clk */
336 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
337 CTS_VDAC_EN, CTS_VDAC_EN);
341 /* PLL O1 O2 O3 VP DV EN TX */
342 /* 4320 /4 /4 /1 /5 /1 => /2 /2 */
343 MESON_VCLK_HDMI_ENCI_54000 = 0,
344 /* 4320 /4 /4 /1 /5 /1 => /1 /2 */
345 MESON_VCLK_HDMI_DDR_54000,
346 /* 2970 /4 /1 /1 /5 /1 => /1 /2 */
347 MESON_VCLK_HDMI_DDR_148500,
348 /* 2970 /2 /2 /2 /5 /1 => /1 /1 */
349 MESON_VCLK_HDMI_74250,
350 /* 2970 /1 /2 /2 /5 /1 => /1 /1 */
351 MESON_VCLK_HDMI_148500,
352 /* 2970 /1 /1 /1 /5 /2 => /1 /1 */
353 MESON_VCLK_HDMI_297000,
354 /* 5940 /1 /1 /2 /5 /1 => /1 /1 */
355 MESON_VCLK_HDMI_594000
358 struct meson_vclk_params {
359 unsigned int pixel_freq;
360 unsigned int pll_base_freq;
361 unsigned int pll_od1;
362 unsigned int pll_od2;
363 unsigned int pll_od3;
364 unsigned int vid_pll_div;
365 unsigned int vclk_div;
367 [MESON_VCLK_HDMI_ENCI_54000] = {
369 .pll_base_freq = 4320000,
373 .vid_pll_div = VID_PLL_DIV_5,
376 [MESON_VCLK_HDMI_DDR_54000] = {
378 .pll_base_freq = 4320000,
382 .vid_pll_div = VID_PLL_DIV_5,
385 [MESON_VCLK_HDMI_DDR_148500] = {
386 .pixel_freq = 148500,
387 .pll_base_freq = 2970000,
391 .vid_pll_div = VID_PLL_DIV_5,
394 [MESON_VCLK_HDMI_74250] = {
396 .pll_base_freq = 2970000,
400 .vid_pll_div = VID_PLL_DIV_5,
403 [MESON_VCLK_HDMI_148500] = {
404 .pixel_freq = 148500,
405 .pll_base_freq = 2970000,
409 .vid_pll_div = VID_PLL_DIV_5,
412 [MESON_VCLK_HDMI_297000] = {
413 .pixel_freq = 297000,
414 .pll_base_freq = 5940000,
418 .vid_pll_div = VID_PLL_DIV_5,
421 [MESON_VCLK_HDMI_594000] = {
422 .pixel_freq = 594000,
423 .pll_base_freq = 5940000,
427 .vid_pll_div = VID_PLL_DIV_5,
433 static inline unsigned int pll_od_to_reg(unsigned int od)
450 void meson_hdmi_pll_set_params(struct meson_drm *priv, unsigned int m,
451 unsigned int frac, unsigned int od1,
452 unsigned int od2, unsigned int od3)
456 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
457 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x58000200 | m);
459 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
462 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2,
464 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
465 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x801da72c);
466 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x71486980);
467 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x00000e55);
469 /* Enable and unreset */
470 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
471 0x7 << 28, 0x4 << 28);
473 /* Poll for lock bit */
474 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL,
475 val, (val & HDMI_PLL_LOCK), 10, 0);
476 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
477 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
478 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x40000200 | m);
479 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
480 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x860f30c4);
481 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
482 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x001fa729);
483 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x01a31500);
486 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
487 HDMI_PLL_RESET, HDMI_PLL_RESET);
488 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
491 /* Poll for lock bit */
492 regmap_read_poll_timeout(priv->hhi, HHI_HDMI_PLL_CNTL, val,
493 (val & HDMI_PLL_LOCK), 10, 0);
494 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
495 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
497 /* Enable and reset */
498 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
499 0x3 << 28, 0x3 << 28);
501 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL2, frac);
502 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL3, 0x00000000);
504 /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
506 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0xea68dc00);
507 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x65771290);
508 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
509 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
511 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
512 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
513 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
514 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
519 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
520 HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
523 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
524 HDMI_PLL_RESET_G12A, 0);
526 /* Poll for lock bits */
527 if (!regmap_read_poll_timeout(priv->hhi,
528 HHI_HDMI_PLL_CNTL, val,
529 ((val & HDMI_PLL_LOCK_G12A)
530 == HDMI_PLL_LOCK_G12A),
536 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
537 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
538 3 << 16, pll_od_to_reg(od1) << 16);
539 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
540 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
541 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
542 3 << 21, pll_od_to_reg(od1) << 21);
543 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
544 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
545 3 << 16, pll_od_to_reg(od1) << 16);
547 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
548 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
549 3 << 22, pll_od_to_reg(od2) << 22);
550 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
551 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
552 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
553 3 << 23, pll_od_to_reg(od2) << 23);
554 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
555 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
556 3 << 18, pll_od_to_reg(od2) << 18);
558 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
559 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
560 3 << 18, pll_od_to_reg(od3) << 18);
561 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
562 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
563 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
564 3 << 19, pll_od_to_reg(od3) << 19);
565 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
566 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
567 3 << 20, pll_od_to_reg(od3) << 20);
570 #define XTAL_FREQ 24000
572 static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
573 unsigned int pll_freq)
575 /* The GXBB PLL has a /2 pre-multiplier */
576 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
579 return pll_freq / XTAL_FREQ;
582 #define HDMI_FRAC_MAX_GXBB 4096
583 #define HDMI_FRAC_MAX_GXL 1024
584 #define HDMI_FRAC_MAX_G12A 131072
586 static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
588 unsigned int pll_freq)
590 unsigned int parent_freq = XTAL_FREQ;
591 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
595 /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
596 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
597 frac_max = HDMI_FRAC_MAX_GXBB;
601 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
602 frac_max = HDMI_FRAC_MAX_G12A;
604 /* We can have a perfect match !*/
605 if (pll_freq / m == parent_freq &&
609 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
610 frac_m = m * frac_max;
615 return min((u16)frac, (u16)(frac_max - 1));
618 static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
622 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
623 /* Empiric supported min/max dividers */
624 if (m < 53 || m > 123)
626 if (frac >= HDMI_FRAC_MAX_GXBB)
628 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
629 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
630 meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
631 /* Empiric supported min/max dividers */
632 if (m < 106 || m > 247)
634 if (frac >= HDMI_FRAC_MAX_GXL)
641 static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
647 /* Cycle from /16 to /2 */
648 for (*od = 16 ; *od > 1 ; *od >>= 1) {
649 *m = meson_hdmi_pll_get_m(priv, freq * *od);
652 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
654 DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
655 freq, *m, *frac, *od);
657 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
664 /* pll_freq is the frequency after the OD dividers */
666 meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
668 unsigned int od, m, frac;
670 /* In DMT mode, path after PLL is always /10 */
673 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
676 return MODE_CLOCK_RANGE;
678 EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
680 /* pll_freq is the frequency after the OD dividers */
681 static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
682 unsigned int pll_freq)
684 unsigned int od, m, frac, od1, od2, od3;
686 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
696 DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
697 pll_freq, m, frac, od1, od2, od3);
699 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
704 DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
709 meson_vclk_vic_supported_freq(unsigned int freq)
713 DRM_DEBUG_DRIVER("freq = %d\n", freq);
715 for (i = 0 ; params[i].pixel_freq ; ++i) {
716 DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
717 i, params[i].pixel_freq,
718 FREQ_1000_1001(params[i].pixel_freq));
719 /* Match strict frequency */
720 if (freq == params[i].pixel_freq)
722 /* Match 1000/1001 variant */
723 if (freq == FREQ_1000_1001(params[i].pixel_freq))
727 return MODE_CLOCK_RANGE;
729 EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
731 static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
732 unsigned int od1, unsigned int od2, unsigned int od3,
733 unsigned int vid_pll_div, unsigned int vclk_div,
734 unsigned int hdmi_tx_div, unsigned int venc_div,
735 bool hdmi_use_enci, bool vic_alternate_clock)
737 unsigned int m = 0, frac = 0;
739 /* Set HDMI-TX sys clock */
740 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
741 CTS_HDMI_SYS_SEL_MASK, 0);
742 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
743 CTS_HDMI_SYS_DIV_MASK, 0);
744 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
745 CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
747 /* Set HDMI PLL rate */
748 if (!od1 && !od2 && !od3) {
749 meson_hdmi_pll_generic_set(priv, pll_base_freq);
750 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
751 switch (pll_base_freq) {
754 frac = vic_alternate_clock ? 0xd02 : 0xe00;
757 m = vic_alternate_clock ? 0x59 : 0x5a;
758 frac = vic_alternate_clock ? 0xe8f : 0;
762 frac = vic_alternate_clock ? 0xa05 : 0xc00;
766 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
767 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
768 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
769 switch (pll_base_freq) {
772 frac = vic_alternate_clock ? 0x281 : 0x300;
775 m = vic_alternate_clock ? 0xb3 : 0xb4;
776 frac = vic_alternate_clock ? 0x347 : 0;
780 frac = vic_alternate_clock ? 0x102 : 0x200;
784 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
785 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
786 switch (pll_base_freq) {
789 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
792 m = vic_alternate_clock ? 0xb3 : 0xb4;
793 frac = vic_alternate_clock ? 0x1a3ee : 0;
797 frac = vic_alternate_clock ? 0x8148 : 0x10000;
801 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
804 /* Setup vid_pll divider */
805 meson_vid_pll_set(priv, vid_pll_div);
808 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
810 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
811 VCLK_DIV_MASK, vclk_div - 1);
813 /* Set HDMI-TX source */
814 switch (hdmi_tx_div) {
816 /* enable vclk_div1 gate */
817 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
818 VCLK_DIV1_EN, VCLK_DIV1_EN);
820 /* select vclk_div1 for HDMI-TX */
821 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
822 HDMI_TX_PIXEL_SEL_MASK, 0);
825 /* enable vclk_div2 gate */
826 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
827 VCLK_DIV2_EN, VCLK_DIV2_EN);
829 /* select vclk_div2 for HDMI-TX */
830 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
831 HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
834 /* enable vclk_div4 gate */
835 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
836 VCLK_DIV4_EN, VCLK_DIV4_EN);
838 /* select vclk_div4 for HDMI-TX */
839 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
840 HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
843 /* enable vclk_div6 gate */
844 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
845 VCLK_DIV6_EN, VCLK_DIV6_EN);
847 /* select vclk_div6 for HDMI-TX */
848 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
849 HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
852 /* enable vclk_div12 gate */
853 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
854 VCLK_DIV12_EN, VCLK_DIV12_EN);
856 /* select vclk_div12 for HDMI-TX */
857 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
858 HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
861 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
862 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
864 /* Set ENCI/ENCP Source */
867 /* enable vclk_div1 gate */
868 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
869 VCLK_DIV1_EN, VCLK_DIV1_EN);
872 /* select vclk_div1 for enci */
873 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
874 CTS_ENCI_SEL_MASK, 0);
876 /* select vclk_div1 for encp */
877 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
878 CTS_ENCP_SEL_MASK, 0);
881 /* enable vclk_div2 gate */
882 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
883 VCLK_DIV2_EN, VCLK_DIV2_EN);
886 /* select vclk_div2 for enci */
887 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
888 CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
890 /* select vclk_div2 for encp */
891 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
892 CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
895 /* enable vclk_div4 gate */
896 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
897 VCLK_DIV4_EN, VCLK_DIV4_EN);
900 /* select vclk_div4 for enci */
901 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
902 CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
904 /* select vclk_div4 for encp */
905 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
906 CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
909 /* enable vclk_div6 gate */
910 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
911 VCLK_DIV6_EN, VCLK_DIV6_EN);
914 /* select vclk_div6 for enci */
915 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
916 CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
918 /* select vclk_div6 for encp */
919 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
920 CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
923 /* enable vclk_div12 gate */
924 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
925 VCLK_DIV12_EN, VCLK_DIV12_EN);
928 /* select vclk_div12 for enci */
929 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
930 CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
932 /* select vclk_div12 for encp */
933 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
934 CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
939 /* Enable ENCI clock gate */
940 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
941 CTS_ENCI_EN, CTS_ENCI_EN);
943 /* Enable ENCP clock gate */
944 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
945 CTS_ENCP_EN, CTS_ENCP_EN);
947 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
950 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
951 unsigned int vclk_freq, unsigned int venc_freq,
952 unsigned int dac_freq, bool hdmi_use_enci)
954 bool vic_alternate_clock = false;
956 unsigned int hdmi_tx_div;
957 unsigned int venc_div;
959 if (target == MESON_VCLK_TARGET_CVBS) {
960 meson_venci_cvbs_clock_config(priv);
962 } else if (target == MESON_VCLK_TARGET_DMT) {
963 /* The DMT clock path is fixed after the PLL:
964 * - automatic PLL freq + OD management
965 * - vid_pll_div = VID_PLL_DIV_5
971 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
972 VID_PLL_DIV_5, 2, 1, 1, false, false);
976 hdmi_tx_div = vclk_freq / dac_freq;
978 if (hdmi_tx_div == 0) {
979 pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
984 venc_div = vclk_freq / venc_freq;
987 pr_err("Fatal Error, invalid HDMI venc freq %d\n",
992 for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
993 if (vclk_freq == params[freq].pixel_freq ||
994 vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
995 if (vclk_freq != params[freq].pixel_freq)
996 vic_alternate_clock = true;
998 vic_alternate_clock = false;
1000 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
1004 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
1008 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
1009 dac_freq == vclk_freq)
1012 if (freq == MESON_VCLK_HDMI_148500 &&
1013 dac_freq != vclk_freq)
1019 if (!params[freq].pixel_freq) {
1020 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
1024 meson_vclk_set(priv, params[freq].pll_base_freq,
1025 params[freq].pll_od1, params[freq].pll_od2,
1026 params[freq].pll_od3, params[freq].vid_pll_div,
1027 params[freq].vclk_div, hdmi_tx_div, venc_div,
1028 hdmi_use_enci, vic_alternate_clock);
1030 EXPORT_SYMBOL_GPL(meson_vclk_setup);