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 if (frac < 0x10000) {
507 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
509 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
512 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4,
514 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5,
517 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39272000);
518 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x55540000);
520 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL4, 0x0a691c00);
521 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL5, 0x33771290);
522 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL6, 0x39270000);
523 regmap_write(priv->hhi, HHI_HDMI_PLL_CNTL7, 0x50540000);
528 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
529 HDMI_PLL_RESET_G12A, HDMI_PLL_RESET_G12A);
532 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
533 HDMI_PLL_RESET_G12A, 0);
535 /* Poll for lock bits */
536 if (!regmap_read_poll_timeout(priv->hhi,
537 HHI_HDMI_PLL_CNTL, val,
538 ((val & HDMI_PLL_LOCK_G12A)
539 == HDMI_PLL_LOCK_G12A),
545 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
546 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
547 3 << 16, pll_od_to_reg(od1) << 16);
548 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
549 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
550 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
551 3 << 21, pll_od_to_reg(od1) << 21);
552 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
553 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
554 3 << 16, pll_od_to_reg(od1) << 16);
556 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
557 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
558 3 << 22, pll_od_to_reg(od2) << 22);
559 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
560 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
561 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
562 3 << 23, pll_od_to_reg(od2) << 23);
563 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
564 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
565 3 << 18, pll_od_to_reg(od2) << 18);
567 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
568 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL2,
569 3 << 18, pll_od_to_reg(od3) << 18);
570 else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
571 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu"))
572 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL3,
573 3 << 19, pll_od_to_reg(od3) << 19);
574 else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
575 regmap_update_bits(priv->hhi, HHI_HDMI_PLL_CNTL,
576 3 << 20, pll_od_to_reg(od3) << 20);
579 #define XTAL_FREQ 24000
581 static unsigned int meson_hdmi_pll_get_m(struct meson_drm *priv,
582 unsigned int pll_freq)
584 /* The GXBB PLL has a /2 pre-multiplier */
585 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu"))
588 return pll_freq / XTAL_FREQ;
591 #define HDMI_FRAC_MAX_GXBB 4096
592 #define HDMI_FRAC_MAX_GXL 1024
593 #define HDMI_FRAC_MAX_G12A 131072
595 static unsigned int meson_hdmi_pll_get_frac(struct meson_drm *priv,
597 unsigned int pll_freq)
599 unsigned int parent_freq = XTAL_FREQ;
600 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
604 /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
605 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
606 frac_max = HDMI_FRAC_MAX_GXBB;
610 if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu"))
611 frac_max = HDMI_FRAC_MAX_G12A;
613 /* We can have a perfect match !*/
614 if (pll_freq / m == parent_freq &&
618 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
619 frac_m = m * frac_max;
624 return min((u16)frac, (u16)(frac_max - 1));
627 static bool meson_hdmi_pll_validate_params(struct meson_drm *priv,
631 if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
632 /* Empiric supported min/max dividers */
633 if (m < 53 || m > 123)
635 if (frac >= HDMI_FRAC_MAX_GXBB)
637 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
638 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu") ||
639 meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
640 /* Empiric supported min/max dividers */
641 if (m < 106 || m > 247)
643 if (frac >= HDMI_FRAC_MAX_GXL)
650 static bool meson_hdmi_pll_find_params(struct meson_drm *priv,
656 /* Cycle from /16 to /2 */
657 for (*od = 16 ; *od > 1 ; *od >>= 1) {
658 *m = meson_hdmi_pll_get_m(priv, freq * *od);
661 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
663 DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d\n",
664 freq, *m, *frac, *od);
666 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
673 /* pll_freq is the frequency after the OD dividers */
675 meson_vclk_dmt_supported_freq(struct meson_drm *priv, unsigned int freq)
677 unsigned int od, m, frac;
679 /* In DMT mode, path after PLL is always /10 */
682 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
685 return MODE_CLOCK_RANGE;
687 EXPORT_SYMBOL_GPL(meson_vclk_dmt_supported_freq);
689 /* pll_freq is the frequency after the OD dividers */
690 static void meson_hdmi_pll_generic_set(struct meson_drm *priv,
691 unsigned int pll_freq)
693 unsigned int od, m, frac, od1, od2, od3;
695 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
705 DRM_DEBUG_DRIVER("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
706 pll_freq, m, frac, od1, od2, od3);
708 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
713 DRM_ERROR("Fatal, unable to find parameters for PLL freq %d\n",
718 meson_vclk_vic_supported_freq(unsigned int freq)
722 DRM_DEBUG_DRIVER("freq = %d\n", freq);
724 for (i = 0 ; params[i].pixel_freq ; ++i) {
725 DRM_DEBUG_DRIVER("i = %d pixel_freq = %d alt = %d\n",
726 i, params[i].pixel_freq,
727 FREQ_1000_1001(params[i].pixel_freq));
728 /* Match strict frequency */
729 if (freq == params[i].pixel_freq)
731 /* Match 1000/1001 variant */
732 if (freq == FREQ_1000_1001(params[i].pixel_freq))
736 return MODE_CLOCK_RANGE;
738 EXPORT_SYMBOL_GPL(meson_vclk_vic_supported_freq);
740 static void meson_vclk_set(struct meson_drm *priv, unsigned int pll_base_freq,
741 unsigned int od1, unsigned int od2, unsigned int od3,
742 unsigned int vid_pll_div, unsigned int vclk_div,
743 unsigned int hdmi_tx_div, unsigned int venc_div,
744 bool hdmi_use_enci, bool vic_alternate_clock)
746 unsigned int m = 0, frac = 0;
748 /* Set HDMI-TX sys clock */
749 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
750 CTS_HDMI_SYS_SEL_MASK, 0);
751 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
752 CTS_HDMI_SYS_DIV_MASK, 0);
753 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
754 CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
756 /* Set HDMI PLL rate */
757 if (!od1 && !od2 && !od3) {
758 meson_hdmi_pll_generic_set(priv, pll_base_freq);
759 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxbb-vpu")) {
760 switch (pll_base_freq) {
763 frac = vic_alternate_clock ? 0xd02 : 0xe00;
766 m = vic_alternate_clock ? 0x59 : 0x5a;
767 frac = vic_alternate_clock ? 0xe8f : 0;
771 frac = vic_alternate_clock ? 0xa05 : 0xc00;
775 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
776 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-gxm-vpu") ||
777 meson_vpu_is_compatible(priv, "amlogic,meson-gxl-vpu")) {
778 switch (pll_base_freq) {
781 frac = vic_alternate_clock ? 0x281 : 0x300;
784 m = vic_alternate_clock ? 0xb3 : 0xb4;
785 frac = vic_alternate_clock ? 0x347 : 0;
789 frac = vic_alternate_clock ? 0x102 : 0x200;
793 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
794 } else if (meson_vpu_is_compatible(priv, "amlogic,meson-g12a-vpu")) {
795 switch (pll_base_freq) {
798 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
801 m = vic_alternate_clock ? 0xb3 : 0xb4;
802 frac = vic_alternate_clock ? 0x1a3ee : 0;
806 frac = vic_alternate_clock ? 0x8148 : 0x10000;
810 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
813 /* Setup vid_pll divider */
814 meson_vid_pll_set(priv, vid_pll_div);
817 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
819 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
820 VCLK_DIV_MASK, vclk_div - 1);
822 /* Set HDMI-TX source */
823 switch (hdmi_tx_div) {
825 /* enable vclk_div1 gate */
826 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
827 VCLK_DIV1_EN, VCLK_DIV1_EN);
829 /* select vclk_div1 for HDMI-TX */
830 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
831 HDMI_TX_PIXEL_SEL_MASK, 0);
834 /* enable vclk_div2 gate */
835 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
836 VCLK_DIV2_EN, VCLK_DIV2_EN);
838 /* select vclk_div2 for HDMI-TX */
839 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
840 HDMI_TX_PIXEL_SEL_MASK, 1 << HDMI_TX_PIXEL_SEL_SHIFT);
843 /* enable vclk_div4 gate */
844 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
845 VCLK_DIV4_EN, VCLK_DIV4_EN);
847 /* select vclk_div4 for HDMI-TX */
848 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
849 HDMI_TX_PIXEL_SEL_MASK, 2 << HDMI_TX_PIXEL_SEL_SHIFT);
852 /* enable vclk_div6 gate */
853 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
854 VCLK_DIV6_EN, VCLK_DIV6_EN);
856 /* select vclk_div6 for HDMI-TX */
857 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
858 HDMI_TX_PIXEL_SEL_MASK, 3 << HDMI_TX_PIXEL_SEL_SHIFT);
861 /* enable vclk_div12 gate */
862 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
863 VCLK_DIV12_EN, VCLK_DIV12_EN);
865 /* select vclk_div12 for HDMI-TX */
866 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL,
867 HDMI_TX_PIXEL_SEL_MASK, 4 << HDMI_TX_PIXEL_SEL_SHIFT);
870 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
871 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
873 /* Set ENCI/ENCP Source */
876 /* enable vclk_div1 gate */
877 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
878 VCLK_DIV1_EN, VCLK_DIV1_EN);
881 /* select vclk_div1 for enci */
882 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
883 CTS_ENCI_SEL_MASK, 0);
885 /* select vclk_div1 for encp */
886 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
887 CTS_ENCP_SEL_MASK, 0);
890 /* enable vclk_div2 gate */
891 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
892 VCLK_DIV2_EN, VCLK_DIV2_EN);
895 /* select vclk_div2 for enci */
896 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
897 CTS_ENCI_SEL_MASK, 1 << CTS_ENCI_SEL_SHIFT);
899 /* select vclk_div2 for encp */
900 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
901 CTS_ENCP_SEL_MASK, 1 << CTS_ENCP_SEL_SHIFT);
904 /* enable vclk_div4 gate */
905 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
906 VCLK_DIV4_EN, VCLK_DIV4_EN);
909 /* select vclk_div4 for enci */
910 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
911 CTS_ENCI_SEL_MASK, 2 << CTS_ENCI_SEL_SHIFT);
913 /* select vclk_div4 for encp */
914 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
915 CTS_ENCP_SEL_MASK, 2 << CTS_ENCP_SEL_SHIFT);
918 /* enable vclk_div6 gate */
919 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
920 VCLK_DIV6_EN, VCLK_DIV6_EN);
923 /* select vclk_div6 for enci */
924 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
925 CTS_ENCI_SEL_MASK, 3 << CTS_ENCI_SEL_SHIFT);
927 /* select vclk_div6 for encp */
928 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
929 CTS_ENCP_SEL_MASK, 3 << CTS_ENCP_SEL_SHIFT);
932 /* enable vclk_div12 gate */
933 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL,
934 VCLK_DIV12_EN, VCLK_DIV12_EN);
937 /* select vclk_div12 for enci */
938 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
939 CTS_ENCI_SEL_MASK, 4 << CTS_ENCI_SEL_SHIFT);
941 /* select vclk_div12 for encp */
942 regmap_update_bits(priv->hhi, HHI_VID_CLK_DIV,
943 CTS_ENCP_SEL_MASK, 4 << CTS_ENCP_SEL_SHIFT);
948 /* Enable ENCI clock gate */
949 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
950 CTS_ENCI_EN, CTS_ENCI_EN);
952 /* Enable ENCP clock gate */
953 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL2,
954 CTS_ENCP_EN, CTS_ENCP_EN);
956 regmap_update_bits(priv->hhi, HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
959 void meson_vclk_setup(struct meson_drm *priv, unsigned int target,
960 unsigned int vclk_freq, unsigned int venc_freq,
961 unsigned int dac_freq, bool hdmi_use_enci)
963 bool vic_alternate_clock = false;
965 unsigned int hdmi_tx_div;
966 unsigned int venc_div;
968 if (target == MESON_VCLK_TARGET_CVBS) {
969 meson_venci_cvbs_clock_config(priv);
971 } else if (target == MESON_VCLK_TARGET_DMT) {
972 /* The DMT clock path is fixed after the PLL:
973 * - automatic PLL freq + OD management
974 * - vid_pll_div = VID_PLL_DIV_5
980 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
981 VID_PLL_DIV_5, 2, 1, 1, false, false);
985 hdmi_tx_div = vclk_freq / dac_freq;
987 if (hdmi_tx_div == 0) {
988 pr_err("Fatal Error, invalid HDMI-TX freq %d\n",
993 venc_div = vclk_freq / venc_freq;
996 pr_err("Fatal Error, invalid HDMI venc freq %d\n",
1001 for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
1002 if (vclk_freq == params[freq].pixel_freq ||
1003 vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
1004 if (vclk_freq != params[freq].pixel_freq)
1005 vic_alternate_clock = true;
1007 vic_alternate_clock = false;
1009 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
1013 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
1017 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
1018 dac_freq == vclk_freq)
1021 if (freq == MESON_VCLK_HDMI_148500 &&
1022 dac_freq != vclk_freq)
1028 if (!params[freq].pixel_freq) {
1029 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
1033 meson_vclk_set(priv, params[freq].pll_base_freq,
1034 params[freq].pll_od1, params[freq].pll_od2,
1035 params[freq].pll_od3, params[freq].vid_pll_div,
1036 params[freq].vclk_div, hdmi_tx_div, venc_div,
1037 hdmi_use_enci, vic_alternate_clock);
1039 EXPORT_SYMBOL_GPL(meson_vclk_setup);