1 // SPDX-License-Identifier: GPL-2.0
3 * Amlogic Meson Video Processing Unit driver
5 * Copyright (c) 2018 BayLibre, SAS.
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
12 #include <linux/bitops.h>
13 #include "meson_vpu.h"
15 #include <linux/iopoll.h>
16 #include <linux/math64.h>
18 #define writel_bits(mask, val, addr) \
19 writel((readl(addr) & ~(mask)) | (val), addr)
22 MESON_VCLK_TARGET_CVBS = 0,
23 MESON_VCLK_TARGET_HDMI = 1,
24 MESON_VCLK_TARGET_DMT = 2,
28 #define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
29 #define VID_PLL_EN BIT(19)
30 #define VID_PLL_BYPASS BIT(18)
31 #define VID_PLL_PRESET BIT(15)
32 #define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
33 #define VCLK2_DIV_MASK 0xff
34 #define VCLK2_DIV_EN BIT(16)
35 #define VCLK2_DIV_RESET BIT(17)
36 #define CTS_VDAC_SEL_MASK (0xf << 28)
37 #define CTS_VDAC_SEL_SHIFT 28
38 #define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
39 #define VCLK2_EN BIT(19)
40 #define VCLK2_SEL_MASK (0x7 << 16)
41 #define VCLK2_SEL_SHIFT 16
42 #define VCLK2_SOFT_RESET BIT(15)
43 #define VCLK2_DIV1_EN BIT(0)
44 #define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
45 #define VCLK_DIV_MASK 0xff
46 #define VCLK_DIV_EN BIT(16)
47 #define VCLK_DIV_RESET BIT(17)
48 #define CTS_ENCP_SEL_MASK (0xf << 24)
49 #define CTS_ENCP_SEL_SHIFT 24
50 #define CTS_ENCI_SEL_MASK (0xf << 28)
51 #define CTS_ENCI_SEL_SHIFT 28
52 #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
53 #define VCLK_EN BIT(19)
54 #define VCLK_SEL_MASK (0x7 << 16)
55 #define VCLK_SEL_SHIFT 16
56 #define VCLK_SOFT_RESET BIT(15)
57 #define VCLK_DIV1_EN BIT(0)
58 #define VCLK_DIV2_EN BIT(1)
59 #define VCLK_DIV4_EN BIT(2)
60 #define VCLK_DIV6_EN BIT(3)
61 #define VCLK_DIV12_EN BIT(4)
62 #define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
63 #define CTS_ENCI_EN BIT(0)
64 #define CTS_ENCP_EN BIT(2)
65 #define CTS_VDAC_EN BIT(4)
66 #define HDMI_TX_PIXEL_EN BIT(5)
67 #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
68 #define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
69 #define HDMI_TX_PIXEL_SEL_SHIFT 16
70 #define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
71 #define CTS_HDMI_SYS_DIV_MASK (0x7f)
72 #define CTS_HDMI_SYS_EN BIT(8)
74 #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
75 #define HHI_HDMI_PLL_CNTL_EN BIT(30)
76 #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
77 #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
78 #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
79 #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
80 #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
81 #define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
83 #define HDMI_PLL_RESET BIT(28)
84 #define HDMI_PLL_RESET_G12A BIT(29)
85 #define HDMI_PLL_LOCK BIT(31)
86 #define HDMI_PLL_LOCK_G12A (3 << 30)
88 #define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
90 /* VID PLL Dividers */
109 void meson_vid_pll_set(struct meson_vpu_priv *priv, unsigned int div)
111 unsigned int shift_val = 0;
112 unsigned int shift_sel = 0;
114 /* Disable vid_pll output clock */
115 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
116 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
123 case VID_PLL_DIV_2p5:
131 case VID_PLL_DIV_3p5:
135 case VID_PLL_DIV_3p75:
151 case VID_PLL_DIV_6p25:
159 case VID_PLL_DIV_7p5:
177 if (div == VID_PLL_DIV_1) {
178 /* Enable vid_pll bypass to HDMI pll */
179 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
180 VID_PLL_BYPASS, VID_PLL_BYPASS);
183 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
186 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
188 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
190 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
193 /* Setup sel and val */
194 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
195 3 << 16, shift_sel << 16);
196 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
197 VID_PLL_PRESET, VID_PLL_PRESET);
198 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
201 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
205 /* Enable the vid_pll output clock */
206 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
207 VID_PLL_EN, VID_PLL_EN);
211 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
213 * TOFIX: Refactor into table to also handle HDMI frequency and paths
215 static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
219 /* Setup PLL to output 1.485GHz */
220 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
221 hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
222 hhi_write(HHI_HDMI_PLL_CNTL2, 0x00404e00);
223 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
224 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
225 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
226 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
227 hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
229 /* Poll for lock bit */
230 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
231 (val & HDMI_PLL_LOCK), 10);
232 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
233 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
234 hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
235 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb300);
236 hhi_write(HHI_HDMI_PLL_CNTL3, 0xa6212844);
237 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
238 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
239 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
242 hhi_update_bits(HHI_HDMI_PLL_CNTL,
243 HDMI_PLL_RESET, HDMI_PLL_RESET);
244 hhi_update_bits(HHI_HDMI_PLL_CNTL,
247 /* Poll for lock bit */
248 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
249 (val & HDMI_PLL_LOCK), 10);
250 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
251 hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
252 hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
253 hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
254 hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
255 hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
256 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
257 hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
258 hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
259 hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
261 /* Poll for lock bit */
262 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
263 ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
268 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
270 /* Setup vid_pll to /1 */
271 meson_vid_pll_set(priv, VID_PLL_DIV_1);
273 /* Setup the VCLK2 divider value to achieve 27MHz */
274 hhi_update_bits(HHI_VIID_CLK_DIV,
275 VCLK2_DIV_MASK, (55 - 1));
277 /* select vid_pll for vclk2 */
278 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
279 hhi_update_bits(HHI_VIID_CLK_CNTL,
280 VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
282 hhi_update_bits(HHI_VIID_CLK_CNTL,
283 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
285 /* enable vclk2 gate */
286 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
288 /* select vclk_div1 for enci */
289 hhi_update_bits(HHI_VID_CLK_DIV,
290 CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
291 /* select vclk_div1 for vdac */
292 hhi_update_bits(HHI_VIID_CLK_DIV,
293 CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
295 /* release vclk2_div_reset and enable vclk2_div */
296 hhi_update_bits(HHI_VIID_CLK_DIV,
297 VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
299 /* enable vclk2_div1 gate */
300 hhi_update_bits(HHI_VIID_CLK_CNTL,
301 VCLK2_DIV1_EN, VCLK2_DIV1_EN);
304 hhi_update_bits(HHI_VIID_CLK_CNTL,
305 VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
306 hhi_update_bits(HHI_VIID_CLK_CNTL,
307 VCLK2_SOFT_RESET, 0);
309 /* enable enci_clk */
310 hhi_update_bits(HHI_VID_CLK_CNTL2,
311 CTS_ENCI_EN, CTS_ENCI_EN);
312 /* enable vdac_clk */
313 hhi_update_bits(HHI_VID_CLK_CNTL2,
314 CTS_VDAC_EN, CTS_VDAC_EN);
318 /* PLL O1 O2 O3 VP DV EN TX */
319 /* 4320 /4 /4 /1 /5 /1 => /2 /2 */
320 MESON_VCLK_HDMI_ENCI_54000 = 0,
321 /* 4320 /4 /4 /1 /5 /1 => /1 /2 */
322 MESON_VCLK_HDMI_DDR_54000,
323 /* 2970 /4 /1 /1 /5 /1 => /1 /2 */
324 MESON_VCLK_HDMI_DDR_148500,
325 /* 2970 /2 /2 /2 /5 /1 => /1 /1 */
326 MESON_VCLK_HDMI_74250,
327 /* 2970 /1 /2 /2 /5 /1 => /1 /1 */
328 MESON_VCLK_HDMI_148500,
329 /* 2970 /1 /1 /1 /5 /2 => /1 /1 */
330 MESON_VCLK_HDMI_297000,
331 /* 5940 /1 /1 /2 /5 /1 => /1 /1 */
332 MESON_VCLK_HDMI_594000
335 struct meson_vclk_params {
336 unsigned int pixel_freq;
337 unsigned int pll_base_freq;
338 unsigned int pll_od1;
339 unsigned int pll_od2;
340 unsigned int pll_od3;
341 unsigned int vid_pll_div;
342 unsigned int vclk_div;
344 [MESON_VCLK_HDMI_ENCI_54000] = {
346 .pll_base_freq = 4320000,
350 .vid_pll_div = VID_PLL_DIV_5,
353 [MESON_VCLK_HDMI_DDR_54000] = {
355 .pll_base_freq = 4320000,
359 .vid_pll_div = VID_PLL_DIV_5,
362 [MESON_VCLK_HDMI_DDR_148500] = {
363 .pixel_freq = 148500,
364 .pll_base_freq = 2970000,
368 .vid_pll_div = VID_PLL_DIV_5,
371 [MESON_VCLK_HDMI_74250] = {
373 .pll_base_freq = 2970000,
377 .vid_pll_div = VID_PLL_DIV_5,
380 [MESON_VCLK_HDMI_148500] = {
381 .pixel_freq = 148500,
382 .pll_base_freq = 2970000,
386 .vid_pll_div = VID_PLL_DIV_5,
389 [MESON_VCLK_HDMI_297000] = {
390 .pixel_freq = 297000,
391 .pll_base_freq = 5940000,
395 .vid_pll_div = VID_PLL_DIV_5,
398 [MESON_VCLK_HDMI_594000] = {
399 .pixel_freq = 594000,
400 .pll_base_freq = 5940000,
404 .vid_pll_div = VID_PLL_DIV_5,
410 static inline unsigned int pll_od_to_reg(unsigned int od)
427 void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
428 unsigned int frac, unsigned int od1,
429 unsigned int od2, unsigned int od3)
433 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
434 hhi_write(HHI_HDMI_PLL_CNTL, 0x58000200 | m);
436 hhi_write(HHI_HDMI_PLL_CNTL2,
439 hhi_write(HHI_HDMI_PLL_CNTL2,
441 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
442 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
443 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
444 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
446 /* Enable and unreset */
447 hhi_update_bits(HHI_HDMI_PLL_CNTL,
448 0x7 << 28, 0x4 << 28);
450 /* Poll for lock bit */
451 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
452 (val & HDMI_PLL_LOCK), 10);
453 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
454 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
455 hhi_write(HHI_HDMI_PLL_CNTL, 0x40000200 | m);
456 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
457 hhi_write(HHI_HDMI_PLL_CNTL3, 0x860f30c4);
458 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
459 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
460 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
463 hhi_update_bits(HHI_HDMI_PLL_CNTL,
464 HDMI_PLL_RESET, HDMI_PLL_RESET);
465 hhi_update_bits(HHI_HDMI_PLL_CNTL,
468 /* Poll for lock bit */
469 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
470 (val & HDMI_PLL_LOCK), 10);
471 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
472 hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
474 /* Enable and reset */
475 hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
477 hhi_write(HHI_HDMI_PLL_CNTL2, frac);
478 hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
480 /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
482 if (frac < 0x10000) {
483 hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
484 hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
486 hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
487 hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
489 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
490 hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
492 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
493 hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
494 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
495 hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
500 hhi_update_bits(HHI_HDMI_PLL_CNTL,
502 HDMI_PLL_RESET_G12A);
505 hhi_update_bits(HHI_HDMI_PLL_CNTL,
506 HDMI_PLL_RESET_G12A, 0);
508 /* Poll for lock bits */
509 if (!readl_poll_timeout(
510 priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
511 ((val & HDMI_PLL_LOCK_G12A)
512 == HDMI_PLL_LOCK_G12A), 100))
517 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
518 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
519 3 << 16, pll_od_to_reg(od1) << 16);
520 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
521 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
522 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
523 3 << 21, pll_od_to_reg(od1) << 21);
524 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
525 hhi_update_bits(HHI_HDMI_PLL_CNTL,
526 3 << 16, pll_od_to_reg(od1) << 16);
528 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
529 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
530 3 << 22, pll_od_to_reg(od2) << 22);
531 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
532 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
533 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
534 3 << 23, pll_od_to_reg(od2) << 23);
535 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
536 hhi_update_bits(HHI_HDMI_PLL_CNTL,
537 3 << 18, pll_od_to_reg(od2) << 18);
539 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
540 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
541 3 << 18, pll_od_to_reg(od3) << 18);
542 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
543 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
544 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
545 3 << 19, pll_od_to_reg(od3) << 19);
546 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
547 hhi_update_bits(HHI_HDMI_PLL_CNTL,
548 3 << 20, pll_od_to_reg(od3) << 20);
551 #define XTAL_FREQ 24000
553 static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
554 unsigned int pll_freq)
556 /* The GXBB PLL has a /2 pre-multiplier */
557 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
560 return pll_freq / XTAL_FREQ;
563 #define HDMI_FRAC_MAX_GXBB 4096
564 #define HDMI_FRAC_MAX_GXL 1024
565 #define HDMI_FRAC_MAX_G12A 131072
567 static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
569 unsigned int pll_freq)
571 unsigned int parent_freq = XTAL_FREQ;
572 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
576 /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
577 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
578 frac_max = HDMI_FRAC_MAX_GXBB;
582 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
583 frac_max = HDMI_FRAC_MAX_G12A;
585 /* We can have a perfect match !*/
586 if (pll_freq / m == parent_freq &&
590 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
591 frac_m = m * frac_max;
596 return min((u16)frac, (u16)(frac_max - 1));
599 static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
603 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
604 /* Empiric supported min/max dividers */
605 if (m < 53 || m > 123)
607 if (frac >= HDMI_FRAC_MAX_GXBB)
609 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
610 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
611 /* Empiric supported min/max dividers */
612 if (m < 106 || m > 247)
614 if (frac >= HDMI_FRAC_MAX_GXL)
616 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
617 /* Empiric supported min/max dividers */
618 if (m < 106 || m > 247)
620 if (frac >= HDMI_FRAC_MAX_G12A)
627 static bool meson_hdmi_pll_find_params(struct meson_vpu_priv *priv,
633 /* Cycle from /16 to /2 */
634 for (*od = 16 ; *od > 1 ; *od >>= 1) {
635 *m = meson_hdmi_pll_get_m(priv, freq * *od);
638 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
640 debug("PLL params for %dkHz: m=%x frac=%x od=%d\n",
641 freq, *m, *frac, *od);
643 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
650 /* pll_freq is the frequency after the OD dividers */
651 bool meson_vclk_dmt_supported_freq(struct meson_vpu_priv *priv,
654 unsigned int od, m, frac;
656 /* In DMT mode, path after PLL is always /10 */
659 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
665 /* pll_freq is the frequency after the OD dividers */
666 static void meson_hdmi_pll_generic_set(struct meson_vpu_priv *priv,
667 unsigned int pll_freq)
669 unsigned int od, m, frac, od1, od2, od3;
671 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
681 debug("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
682 pll_freq, m, frac, od1, od2, od3);
684 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
689 printf("Fatal, unable to find parameters for PLL freq %d\n",
694 meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
695 unsigned int od1, unsigned int od2, unsigned int od3,
696 unsigned int vid_pll_div, unsigned int vclk_div,
697 unsigned int hdmi_tx_div, unsigned int venc_div,
698 bool hdmi_use_enci, bool vic_alternate_clock)
700 unsigned int m = 0, frac = 0;
702 /* Set HDMI-TX sys clock */
703 hhi_update_bits(HHI_HDMI_CLK_CNTL,
704 CTS_HDMI_SYS_SEL_MASK, 0);
705 hhi_update_bits(HHI_HDMI_CLK_CNTL,
706 CTS_HDMI_SYS_DIV_MASK, 0);
707 hhi_update_bits(HHI_HDMI_CLK_CNTL,
708 CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
710 /* Set HDMI PLL rate */
711 if (!od1 && !od2 && !od3) {
712 meson_hdmi_pll_generic_set(priv, pll_base_freq);
713 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
714 switch (pll_base_freq) {
717 frac = vic_alternate_clock ? 0xd02 : 0xe00;
720 m = vic_alternate_clock ? 0x59 : 0x5a;
721 frac = vic_alternate_clock ? 0xe8f : 0;
725 frac = vic_alternate_clock ? 0xa05 : 0xc00;
729 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
730 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
731 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
732 switch (pll_base_freq) {
735 frac = vic_alternate_clock ? 0x281 : 0x300;
738 m = vic_alternate_clock ? 0xb3 : 0xb4;
739 frac = vic_alternate_clock ? 0x347 : 0;
743 frac = vic_alternate_clock ? 0x102 : 0x200;
747 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
748 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
749 switch (pll_base_freq) {
752 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
755 m = vic_alternate_clock ? 0xb3 : 0xb4;
756 frac = vic_alternate_clock ? 0x1a3ee : 0;
760 frac = vic_alternate_clock ? 0x8148 : 0x10000;
764 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
767 /* Setup vid_pll divider */
768 meson_vid_pll_set(priv, vid_pll_div);
771 hhi_update_bits(HHI_VID_CLK_CNTL,
773 hhi_update_bits(HHI_VID_CLK_DIV,
774 VCLK_DIV_MASK, vclk_div - 1);
776 /* Set HDMI-TX source */
777 switch (hdmi_tx_div) {
779 /* enable vclk_div1 gate */
780 hhi_update_bits(HHI_VID_CLK_CNTL,
781 VCLK_DIV1_EN, VCLK_DIV1_EN);
783 /* select vclk_div1 for HDMI-TX */
784 hhi_update_bits(HHI_HDMI_CLK_CNTL,
785 HDMI_TX_PIXEL_SEL_MASK, 0);
788 /* enable vclk_div2 gate */
789 hhi_update_bits(HHI_VID_CLK_CNTL,
790 VCLK_DIV2_EN, VCLK_DIV2_EN);
792 /* select vclk_div2 for HDMI-TX */
793 hhi_update_bits(HHI_HDMI_CLK_CNTL,
794 HDMI_TX_PIXEL_SEL_MASK,
795 1 << HDMI_TX_PIXEL_SEL_SHIFT);
798 /* enable vclk_div4 gate */
799 hhi_update_bits(HHI_VID_CLK_CNTL,
800 VCLK_DIV4_EN, VCLK_DIV4_EN);
802 /* select vclk_div4 for HDMI-TX */
803 hhi_update_bits(HHI_HDMI_CLK_CNTL,
804 HDMI_TX_PIXEL_SEL_MASK,
805 2 << HDMI_TX_PIXEL_SEL_SHIFT);
808 /* enable vclk_div6 gate */
809 hhi_update_bits(HHI_VID_CLK_CNTL,
810 VCLK_DIV6_EN, VCLK_DIV6_EN);
812 /* select vclk_div6 for HDMI-TX */
813 hhi_update_bits(HHI_HDMI_CLK_CNTL,
814 HDMI_TX_PIXEL_SEL_MASK,
815 3 << HDMI_TX_PIXEL_SEL_SHIFT);
818 /* enable vclk_div12 gate */
819 hhi_update_bits(HHI_VID_CLK_CNTL,
820 VCLK_DIV12_EN, VCLK_DIV12_EN);
822 /* select vclk_div12 for HDMI-TX */
823 hhi_update_bits(HHI_HDMI_CLK_CNTL,
824 HDMI_TX_PIXEL_SEL_MASK,
825 4 << HDMI_TX_PIXEL_SEL_SHIFT);
828 hhi_update_bits(HHI_VID_CLK_CNTL2,
829 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
831 /* Set ENCI/ENCP Source */
834 /* enable vclk_div1 gate */
835 hhi_update_bits(HHI_VID_CLK_CNTL,
836 VCLK_DIV1_EN, VCLK_DIV1_EN);
839 /* select vclk_div1 for enci */
840 hhi_update_bits(HHI_VID_CLK_DIV,
841 CTS_ENCI_SEL_MASK, 0);
843 /* select vclk_div1 for encp */
844 hhi_update_bits(HHI_VID_CLK_DIV,
845 CTS_ENCP_SEL_MASK, 0);
848 /* enable vclk_div2 gate */
849 hhi_update_bits(HHI_VID_CLK_CNTL,
850 VCLK_DIV2_EN, VCLK_DIV2_EN);
853 /* select vclk_div2 for enci */
854 hhi_update_bits(HHI_VID_CLK_DIV,
856 1 << CTS_ENCI_SEL_SHIFT);
858 /* select vclk_div2 for encp */
859 hhi_update_bits(HHI_VID_CLK_DIV,
861 1 << CTS_ENCP_SEL_SHIFT);
864 /* enable vclk_div4 gate */
865 hhi_update_bits(HHI_VID_CLK_CNTL,
866 VCLK_DIV4_EN, VCLK_DIV4_EN);
869 /* select vclk_div4 for enci */
870 hhi_update_bits(HHI_VID_CLK_DIV,
872 2 << CTS_ENCI_SEL_SHIFT);
874 /* select vclk_div4 for encp */
875 hhi_update_bits(HHI_VID_CLK_DIV,
877 2 << CTS_ENCP_SEL_SHIFT);
880 /* enable vclk_div6 gate */
881 hhi_update_bits(HHI_VID_CLK_CNTL,
882 VCLK_DIV6_EN, VCLK_DIV6_EN);
885 /* select vclk_div6 for enci */
886 hhi_update_bits(HHI_VID_CLK_DIV,
888 3 << CTS_ENCI_SEL_SHIFT);
890 /* select vclk_div6 for encp */
891 hhi_update_bits(HHI_VID_CLK_DIV,
893 3 << CTS_ENCP_SEL_SHIFT);
896 /* enable vclk_div12 gate */
897 hhi_update_bits(HHI_VID_CLK_CNTL,
898 VCLK_DIV12_EN, VCLK_DIV12_EN);
901 /* select vclk_div12 for enci */
902 hhi_update_bits(HHI_VID_CLK_DIV,
904 4 << CTS_ENCI_SEL_SHIFT);
906 /* select vclk_div12 for encp */
907 hhi_update_bits(HHI_VID_CLK_DIV,
909 4 << CTS_ENCP_SEL_SHIFT);
914 /* Enable ENCI clock gate */
915 hhi_update_bits(HHI_VID_CLK_CNTL2,
916 CTS_ENCI_EN, CTS_ENCI_EN);
918 /* Enable ENCP clock gate */
919 hhi_update_bits(HHI_VID_CLK_CNTL2,
920 CTS_ENCP_EN, CTS_ENCP_EN);
922 hhi_update_bits(HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
925 static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
926 unsigned int vclk_freq, unsigned int venc_freq,
927 unsigned int dac_freq, bool hdmi_use_enci)
929 bool vic_alternate_clock = false;
931 unsigned int hdmi_tx_div;
932 unsigned int venc_div;
934 if (target == MESON_VCLK_TARGET_CVBS) {
935 meson_venci_cvbs_clock_config(priv);
937 } else if (target == MESON_VCLK_TARGET_DMT) {
938 /* The DMT clock path is fixed after the PLL:
939 * - automatic PLL freq + OD management
940 * - vid_pll_div = VID_PLL_DIV_5
946 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
947 VID_PLL_DIV_5, 2, 1, 1, false, false);
951 hdmi_tx_div = vclk_freq / dac_freq;
953 if (hdmi_tx_div == 0) {
954 printf("Fatal Error, invalid HDMI-TX freq %d\n",
959 venc_div = vclk_freq / venc_freq;
962 printf("Fatal Error, invalid HDMI venc freq %d\n",
967 for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
968 if (vclk_freq == params[freq].pixel_freq ||
969 vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
970 if (vclk_freq != params[freq].pixel_freq)
971 vic_alternate_clock = true;
973 vic_alternate_clock = false;
975 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
979 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
983 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
984 dac_freq == vclk_freq)
987 if (freq == MESON_VCLK_HDMI_148500 &&
988 dac_freq != vclk_freq)
994 if (!params[freq].pixel_freq) {
995 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
999 meson_vclk_set(priv, params[freq].pll_base_freq,
1000 params[freq].pll_od1, params[freq].pll_od2,
1001 params[freq].pll_od3, params[freq].vid_pll_div,
1002 params[freq].vclk_div, hdmi_tx_div, venc_div,
1003 hdmi_use_enci, vic_alternate_clock);
1006 void meson_vpu_setup_vclk(struct udevice *dev,
1007 const struct display_timing *mode, bool is_cvbs)
1009 struct meson_vpu_priv *priv = dev_get_priv(dev);
1010 unsigned int vclk_freq;
1013 return meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
1016 vclk_freq = mode->pixelclock.typ / 1000;
1018 return meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT,
1019 vclk_freq, vclk_freq, vclk_freq, false);