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>
10 #include "meson_vpu.h"
11 #include <linux/iopoll.h>
12 #include <linux/math64.h>
14 #define writel_bits(mask, val, addr) \
15 writel((readl(addr) & ~(mask)) | (val), addr)
18 MESON_VCLK_TARGET_CVBS = 0,
19 MESON_VCLK_TARGET_HDMI = 1,
20 MESON_VCLK_TARGET_DMT = 2,
24 #define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
25 #define VID_PLL_EN BIT(19)
26 #define VID_PLL_BYPASS BIT(18)
27 #define VID_PLL_PRESET BIT(15)
28 #define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
29 #define VCLK2_DIV_MASK 0xff
30 #define VCLK2_DIV_EN BIT(16)
31 #define VCLK2_DIV_RESET BIT(17)
32 #define CTS_VDAC_SEL_MASK (0xf << 28)
33 #define CTS_VDAC_SEL_SHIFT 28
34 #define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
35 #define VCLK2_EN BIT(19)
36 #define VCLK2_SEL_MASK (0x7 << 16)
37 #define VCLK2_SEL_SHIFT 16
38 #define VCLK2_SOFT_RESET BIT(15)
39 #define VCLK2_DIV1_EN BIT(0)
40 #define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
41 #define VCLK_DIV_MASK 0xff
42 #define VCLK_DIV_EN BIT(16)
43 #define VCLK_DIV_RESET BIT(17)
44 #define CTS_ENCP_SEL_MASK (0xf << 24)
45 #define CTS_ENCP_SEL_SHIFT 24
46 #define CTS_ENCI_SEL_MASK (0xf << 28)
47 #define CTS_ENCI_SEL_SHIFT 28
48 #define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
49 #define VCLK_EN BIT(19)
50 #define VCLK_SEL_MASK (0x7 << 16)
51 #define VCLK_SEL_SHIFT 16
52 #define VCLK_SOFT_RESET BIT(15)
53 #define VCLK_DIV1_EN BIT(0)
54 #define VCLK_DIV2_EN BIT(1)
55 #define VCLK_DIV4_EN BIT(2)
56 #define VCLK_DIV6_EN BIT(3)
57 #define VCLK_DIV12_EN BIT(4)
58 #define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
59 #define CTS_ENCI_EN BIT(0)
60 #define CTS_ENCP_EN BIT(2)
61 #define CTS_VDAC_EN BIT(4)
62 #define HDMI_TX_PIXEL_EN BIT(5)
63 #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
64 #define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
65 #define HDMI_TX_PIXEL_SEL_SHIFT 16
66 #define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
67 #define CTS_HDMI_SYS_DIV_MASK (0x7f)
68 #define CTS_HDMI_SYS_EN BIT(8)
70 #define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
71 #define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
72 #define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
73 #define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
74 #define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
75 #define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
77 #define HDMI_PLL_RESET BIT(28)
78 #define HDMI_PLL_LOCK BIT(31)
80 /* VID PLL Dividers */
99 void meson_vid_pll_set(struct meson_vpu_priv *priv, unsigned int div)
101 unsigned int shift_val = 0;
102 unsigned int shift_sel = 0;
104 /* Disable vid_pll output clock */
105 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
106 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
113 case VID_PLL_DIV_2p5:
121 case VID_PLL_DIV_3p5:
125 case VID_PLL_DIV_3p75:
141 case VID_PLL_DIV_6p25:
149 case VID_PLL_DIV_7p5:
167 if (div == VID_PLL_DIV_1) {
168 /* Enable vid_pll bypass to HDMI pll */
169 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
170 VID_PLL_BYPASS, VID_PLL_BYPASS);
173 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
176 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
178 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
180 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
183 /* Setup sel and val */
184 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
185 3 << 16, shift_sel << 16);
186 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
187 VID_PLL_PRESET, VID_PLL_PRESET);
188 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
191 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
195 /* Enable the vid_pll output clock */
196 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
197 VID_PLL_EN, VID_PLL_EN);
201 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
203 * TOFIX: Refactor into table to also handle HDMI frequency and paths
205 static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
209 debug("%s:%d\n", __func__, __LINE__);
211 /* Setup PLL to output 1.485GHz */
212 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
213 hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
214 hhi_write(HHI_HDMI_PLL_CNTL2, 0x00404e00);
215 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
216 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
217 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
218 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
219 hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
220 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
221 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
222 hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
223 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb300);
224 hhi_write(HHI_HDMI_PLL_CNTL3, 0xa6212844);
225 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
226 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
227 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
230 hhi_update_bits(HHI_HDMI_PLL_CNTL,
231 HDMI_PLL_RESET, HDMI_PLL_RESET);
232 hhi_update_bits(HHI_HDMI_PLL_CNTL,
236 debug("%s:%d\n", __func__, __LINE__);
238 /* Poll for lock bit */
239 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
240 (val & HDMI_PLL_LOCK), 10);
243 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
245 /* Setup vid_pll to /1 */
246 meson_vid_pll_set(priv, VID_PLL_DIV_1);
248 /* Setup the VCLK2 divider value to achieve 27MHz */
249 hhi_update_bits(HHI_VIID_CLK_DIV,
250 VCLK2_DIV_MASK, (55 - 1));
252 /* select vid_pll for vclk2 */
253 hhi_update_bits(HHI_VIID_CLK_CNTL,
254 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
255 /* enable vclk2 gate */
256 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
258 /* select vclk_div1 for enci */
259 hhi_update_bits(HHI_VID_CLK_DIV,
260 CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
261 /* select vclk_div1 for vdac */
262 hhi_update_bits(HHI_VIID_CLK_DIV,
263 CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
265 /* release vclk2_div_reset and enable vclk2_div */
266 hhi_update_bits(HHI_VIID_CLK_DIV,
267 VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
269 /* enable vclk2_div1 gate */
270 hhi_update_bits(HHI_VIID_CLK_CNTL,
271 VCLK2_DIV1_EN, VCLK2_DIV1_EN);
274 hhi_update_bits(HHI_VIID_CLK_CNTL,
275 VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
276 hhi_update_bits(HHI_VIID_CLK_CNTL,
277 VCLK2_SOFT_RESET, 0);
279 /* enable enci_clk */
280 hhi_update_bits(HHI_VID_CLK_CNTL2,
281 CTS_ENCI_EN, CTS_ENCI_EN);
282 /* enable vdac_clk */
283 hhi_update_bits(HHI_VID_CLK_CNTL2,
284 CTS_VDAC_EN, CTS_VDAC_EN);
286 debug("%s:%d\n", __func__, __LINE__);
290 /* PLL O1 O2 O3 VP DV EN TX */
291 /* 4320 /4 /4 /1 /5 /1 => /2 /2 */
292 MESON_VCLK_HDMI_ENCI_54000 = 1,
293 /* 4320 /4 /4 /1 /5 /1 => /1 /2 */
294 MESON_VCLK_HDMI_DDR_54000,
295 /* 2970 /4 /1 /1 /5 /1 => /1 /2 */
296 MESON_VCLK_HDMI_DDR_148500,
297 /* 2970 /2 /2 /2 /5 /1 => /1 /1 */
298 MESON_VCLK_HDMI_74250,
299 /* 2970 /1 /2 /2 /5 /1 => /1 /1 */
300 MESON_VCLK_HDMI_148500,
301 /* 2970 /1 /1 /1 /5 /2 => /1 /1 */
302 MESON_VCLK_HDMI_297000,
303 /* 5940 /1 /1 /2 /5 /1 => /1 /1 */
304 MESON_VCLK_HDMI_594000
307 struct meson_vclk_params {
308 unsigned int pll_base_freq;
309 unsigned int pll_od1;
310 unsigned int pll_od2;
311 unsigned int pll_od3;
312 unsigned int vid_pll_div;
313 unsigned int vclk_div;
315 [MESON_VCLK_HDMI_ENCI_54000] = {
316 .pll_base_freq = 4320000,
320 .vid_pll_div = VID_PLL_DIV_5,
323 [MESON_VCLK_HDMI_DDR_54000] = {
324 .pll_base_freq = 4320000,
328 .vid_pll_div = VID_PLL_DIV_5,
331 [MESON_VCLK_HDMI_DDR_148500] = {
332 .pll_base_freq = 2970000,
336 .vid_pll_div = VID_PLL_DIV_5,
339 [MESON_VCLK_HDMI_74250] = {
340 .pll_base_freq = 2970000,
344 .vid_pll_div = VID_PLL_DIV_5,
347 [MESON_VCLK_HDMI_148500] = {
348 .pll_base_freq = 2970000,
352 .vid_pll_div = VID_PLL_DIV_5,
355 [MESON_VCLK_HDMI_297000] = {
356 .pll_base_freq = 2970000,
360 .vid_pll_div = VID_PLL_DIV_5,
363 [MESON_VCLK_HDMI_594000] = {
364 .pll_base_freq = 5940000,
368 .vid_pll_div = VID_PLL_DIV_5,
373 static inline unsigned int pll_od_to_reg(unsigned int od)
390 void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
391 unsigned int frac, unsigned int od1,
392 unsigned int od2, unsigned int od3)
396 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
397 hhi_write(HHI_HDMI_PLL_CNTL, 0x58000200 | m);
399 hhi_write(HHI_HDMI_PLL_CNTL2,
402 hhi_write(HHI_HDMI_PLL_CNTL2,
404 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
405 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
406 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
407 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
409 /* Enable and unreset */
410 hhi_update_bits(HHI_HDMI_PLL_CNTL,
411 0x7 << 28, 0x4 << 28);
413 /* Poll for lock bit */
414 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
415 (val & HDMI_PLL_LOCK), 10);
416 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
417 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
418 hhi_write(HHI_HDMI_PLL_CNTL, 0x40000200 | m);
419 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
420 hhi_write(HHI_HDMI_PLL_CNTL3, 0x860f30c4);
421 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
422 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
423 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
426 hhi_update_bits(HHI_HDMI_PLL_CNTL,
427 HDMI_PLL_RESET, HDMI_PLL_RESET);
428 hhi_update_bits(HHI_HDMI_PLL_CNTL,
431 /* Poll for lock bit */
432 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
433 (val & HDMI_PLL_LOCK), 10);
436 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
437 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
438 3 << 16, pll_od_to_reg(od1) << 16);
439 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
440 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
441 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
442 3 << 21, pll_od_to_reg(od1) << 21);
444 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
445 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
446 3 << 22, pll_od_to_reg(od2) << 22);
447 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
448 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
449 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
450 3 << 23, pll_od_to_reg(od2) << 23);
452 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
453 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
454 3 << 18, pll_od_to_reg(od3) << 18);
455 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
456 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
457 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
458 3 << 19, pll_od_to_reg(od3) << 19);
461 #define XTAL_FREQ 24000
463 static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
464 unsigned int pll_freq)
466 /* The GXBB PLL has a /2 pre-multiplier */
467 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
470 return pll_freq / XTAL_FREQ;
473 #define HDMI_FRAC_MAX_GXBB 4096
474 #define HDMI_FRAC_MAX_GXL 1024
476 static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
478 unsigned int pll_freq)
480 unsigned int parent_freq = XTAL_FREQ;
481 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
485 /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
486 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
487 frac_max = HDMI_FRAC_MAX_GXBB;
491 /* We can have a perfect match !*/
492 if (pll_freq / m == parent_freq &&
496 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
497 frac_m = m * frac_max;
502 return min((u16)frac, (u16)(frac_max - 1));
505 static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
509 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
510 /* Empiric supported min/max dividers */
511 if (m < 53 || m > 123)
513 if (frac >= HDMI_FRAC_MAX_GXBB)
515 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
516 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
517 /* Empiric supported min/max dividers */
518 if (m < 106 || m > 247)
520 if (frac >= HDMI_FRAC_MAX_GXL)
527 static bool meson_hdmi_pll_find_params(struct meson_vpu_priv *priv,
533 /* Cycle from /16 to /2 */
534 for (*od = 16 ; *od > 1 ; *od >>= 1) {
535 *m = meson_hdmi_pll_get_m(priv, freq * *od);
538 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
540 debug("PLL params for %dkHz: m=%x frac=%x od=%d\n",
541 freq, *m, *frac, *od);
543 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
550 /* pll_freq is the frequency after the OD dividers */
551 bool meson_vclk_dmt_supported_freq(struct meson_vpu_priv *priv,
554 unsigned int od, m, frac;
556 /* In DMT mode, path after PLL is always /10 */
559 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
565 /* pll_freq is the frequency after the OD dividers */
566 static void meson_hdmi_pll_generic_set(struct meson_vpu_priv *priv,
567 unsigned int pll_freq)
569 unsigned int od, m, frac, od1, od2, od3;
571 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
581 debug("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
582 pll_freq, m, frac, od1, od2, od3);
584 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
589 printf("Fatal, unable to find parameters for PLL freq %d\n",
594 meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
595 unsigned int od1, unsigned int od2, unsigned int od3,
596 unsigned int vid_pll_div, unsigned int vclk_div,
597 unsigned int hdmi_tx_div, unsigned int venc_div,
600 /* Set HDMI-TX sys clock */
601 hhi_update_bits(HHI_HDMI_CLK_CNTL,
602 CTS_HDMI_SYS_SEL_MASK, 0);
603 hhi_update_bits(HHI_HDMI_CLK_CNTL,
604 CTS_HDMI_SYS_DIV_MASK, 0);
605 hhi_update_bits(HHI_HDMI_CLK_CNTL,
606 CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
608 /* Set HDMI PLL rate */
609 if (!od1 && !od2 && !od3) {
610 meson_hdmi_pll_generic_set(priv, pll_base_freq);
611 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
612 switch (pll_base_freq) {
614 meson_hdmi_pll_set_params(priv, 0x3d, 0xe00,
618 meson_hdmi_pll_set_params(priv, 0x5a, 0,
622 meson_hdmi_pll_set_params(priv, 0x7b, 0xc00,
626 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
627 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
628 switch (pll_base_freq) {
630 meson_hdmi_pll_set_params(priv, 0x7b, 0x300,
634 meson_hdmi_pll_set_params(priv, 0xb4, 0,
638 meson_hdmi_pll_set_params(priv, 0xf7, 0x200,
644 /* Setup vid_pll divider */
645 meson_vid_pll_set(priv, vid_pll_div);
648 hhi_update_bits(HHI_VID_CLK_CNTL,
650 hhi_update_bits(HHI_VID_CLK_DIV,
651 VCLK_DIV_MASK, vclk_div - 1);
653 /* Set HDMI-TX source */
654 switch (hdmi_tx_div) {
656 /* enable vclk_div1 gate */
657 hhi_update_bits(HHI_VID_CLK_CNTL,
658 VCLK_DIV1_EN, VCLK_DIV1_EN);
660 /* select vclk_div1 for HDMI-TX */
661 hhi_update_bits(HHI_HDMI_CLK_CNTL,
662 HDMI_TX_PIXEL_SEL_MASK, 0);
665 /* enable vclk_div2 gate */
666 hhi_update_bits(HHI_VID_CLK_CNTL,
667 VCLK_DIV2_EN, VCLK_DIV2_EN);
669 /* select vclk_div2 for HDMI-TX */
670 hhi_update_bits(HHI_HDMI_CLK_CNTL,
671 HDMI_TX_PIXEL_SEL_MASK,
672 1 << HDMI_TX_PIXEL_SEL_SHIFT);
675 /* enable vclk_div4 gate */
676 hhi_update_bits(HHI_VID_CLK_CNTL,
677 VCLK_DIV4_EN, VCLK_DIV4_EN);
679 /* select vclk_div4 for HDMI-TX */
680 hhi_update_bits(HHI_HDMI_CLK_CNTL,
681 HDMI_TX_PIXEL_SEL_MASK,
682 2 << HDMI_TX_PIXEL_SEL_SHIFT);
685 /* enable vclk_div6 gate */
686 hhi_update_bits(HHI_VID_CLK_CNTL,
687 VCLK_DIV6_EN, VCLK_DIV6_EN);
689 /* select vclk_div6 for HDMI-TX */
690 hhi_update_bits(HHI_HDMI_CLK_CNTL,
691 HDMI_TX_PIXEL_SEL_MASK,
692 3 << HDMI_TX_PIXEL_SEL_SHIFT);
695 /* enable vclk_div12 gate */
696 hhi_update_bits(HHI_VID_CLK_CNTL,
697 VCLK_DIV12_EN, VCLK_DIV12_EN);
699 /* select vclk_div12 for HDMI-TX */
700 hhi_update_bits(HHI_HDMI_CLK_CNTL,
701 HDMI_TX_PIXEL_SEL_MASK,
702 4 << HDMI_TX_PIXEL_SEL_SHIFT);
705 hhi_update_bits(HHI_VID_CLK_CNTL2,
706 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
708 /* Set ENCI/ENCP Source */
711 /* enable vclk_div1 gate */
712 hhi_update_bits(HHI_VID_CLK_CNTL,
713 VCLK_DIV1_EN, VCLK_DIV1_EN);
716 /* select vclk_div1 for enci */
717 hhi_update_bits(HHI_VID_CLK_DIV,
718 CTS_ENCI_SEL_MASK, 0);
720 /* select vclk_div1 for encp */
721 hhi_update_bits(HHI_VID_CLK_DIV,
722 CTS_ENCP_SEL_MASK, 0);
725 /* enable vclk_div2 gate */
726 hhi_update_bits(HHI_VID_CLK_CNTL,
727 VCLK_DIV2_EN, VCLK_DIV2_EN);
730 /* select vclk_div2 for enci */
731 hhi_update_bits(HHI_VID_CLK_DIV,
733 1 << CTS_ENCI_SEL_SHIFT);
735 /* select vclk_div2 for encp */
736 hhi_update_bits(HHI_VID_CLK_DIV,
738 1 << CTS_ENCP_SEL_SHIFT);
741 /* enable vclk_div4 gate */
742 hhi_update_bits(HHI_VID_CLK_CNTL,
743 VCLK_DIV4_EN, VCLK_DIV4_EN);
746 /* select vclk_div4 for enci */
747 hhi_update_bits(HHI_VID_CLK_DIV,
749 2 << CTS_ENCI_SEL_SHIFT);
751 /* select vclk_div4 for encp */
752 hhi_update_bits(HHI_VID_CLK_DIV,
754 2 << CTS_ENCP_SEL_SHIFT);
757 /* enable vclk_div6 gate */
758 hhi_update_bits(HHI_VID_CLK_CNTL,
759 VCLK_DIV6_EN, VCLK_DIV6_EN);
762 /* select vclk_div6 for enci */
763 hhi_update_bits(HHI_VID_CLK_DIV,
765 3 << CTS_ENCI_SEL_SHIFT);
767 /* select vclk_div6 for encp */
768 hhi_update_bits(HHI_VID_CLK_DIV,
770 3 << CTS_ENCP_SEL_SHIFT);
773 /* enable vclk_div12 gate */
774 hhi_update_bits(HHI_VID_CLK_CNTL,
775 VCLK_DIV12_EN, VCLK_DIV12_EN);
778 /* select vclk_div12 for enci */
779 hhi_update_bits(HHI_VID_CLK_DIV,
781 4 << CTS_ENCI_SEL_SHIFT);
783 /* select vclk_div12 for encp */
784 hhi_update_bits(HHI_VID_CLK_DIV,
786 4 << CTS_ENCP_SEL_SHIFT);
791 /* Enable ENCI clock gate */
792 hhi_update_bits(HHI_VID_CLK_CNTL2,
793 CTS_ENCI_EN, CTS_ENCI_EN);
795 /* Enable ENCP clock gate */
796 hhi_update_bits(HHI_VID_CLK_CNTL2,
797 CTS_ENCP_EN, CTS_ENCP_EN);
799 hhi_update_bits(HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
802 static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
803 unsigned int vclk_freq, unsigned int venc_freq,
804 unsigned int dac_freq, bool hdmi_use_enci)
807 unsigned int hdmi_tx_div;
808 unsigned int venc_div;
810 if (target == MESON_VCLK_TARGET_CVBS) {
811 meson_venci_cvbs_clock_config(priv);
813 } else if (target == MESON_VCLK_TARGET_DMT) {
814 /* The DMT clock path is fixed after the PLL:
815 * - automatic PLL freq + OD management
816 * - vid_pll_div = VID_PLL_DIV_5
822 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
823 VID_PLL_DIV_5, 2, 1, 1, false);
828 hdmi_tx_div = vclk_freq / dac_freq;
830 if (hdmi_tx_div == 0) {
831 printf("Fatal Error, invalid HDMI-TX freq %d\n",
836 venc_div = vclk_freq / venc_freq;
839 printf("Fatal Error, invalid HDMI venc freq %d\n",
847 freq = MESON_VCLK_HDMI_ENCI_54000;
849 freq = MESON_VCLK_HDMI_DDR_54000;
852 freq = MESON_VCLK_HDMI_74250;
855 if (dac_freq != 148500)
856 freq = MESON_VCLK_HDMI_DDR_148500;
858 freq = MESON_VCLK_HDMI_148500;
861 freq = MESON_VCLK_HDMI_297000;
864 freq = MESON_VCLK_HDMI_594000;
867 printf("Fatal Error, invalid HDMI vclk freq %d\n",
872 meson_vclk_set(priv, params[freq].pll_base_freq,
873 params[freq].pll_od1, params[freq].pll_od2,
874 params[freq].pll_od3, params[freq].vid_pll_div,
875 params[freq].vclk_div, hdmi_tx_div, venc_div,
879 void meson_vpu_setup_vclk(struct udevice *dev,
880 const struct display_timing *mode, bool is_cvbs)
882 struct meson_vpu_priv *priv = dev_get_priv(dev);
883 unsigned int vclk_freq;
886 return meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
889 vclk_freq = mode->pixelclock.typ / 1000;
891 return meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT,
892 vclk_freq, vclk_freq, vclk_freq, false);