blob: cd1e69040f75686c62656c7358504b7fcfd56da8 [file] [log] [blame]
Neil Armstrongadd986c2018-07-24 17:45:28 +02001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Amlogic Meson Video Processing Unit driver
4 *
5 * Copyright (c) 2018 BayLibre, SAS.
6 * Author: Neil Armstrong <narmstrong@baylibre.com>
7 */
8
Simon Glassf74c7bd2019-10-27 09:54:03 -06009#include <common.h>
10#include <dm.h>
Neil Armstrongadd986c2018-07-24 17:45:28 +020011#include <edid.h>
Simon Glass4dcacfc2020-05-10 11:40:13 -060012#include <linux/bitops.h>
Neil Armstrongadd986c2018-07-24 17:45:28 +020013#include "meson_vpu.h"
Simon Glass0f2af882020-05-10 11:40:05 -060014#include <log.h>
Neil Armstrongadd986c2018-07-24 17:45:28 +020015#include <linux/iopoll.h>
16#include <linux/math64.h>
17
18#define writel_bits(mask, val, addr) \
19 writel((readl(addr) & ~(mask)) | (val), addr)
20
21enum {
22 MESON_VCLK_TARGET_CVBS = 0,
23 MESON_VCLK_TARGET_HDMI = 1,
24 MESON_VCLK_TARGET_DMT = 2,
25};
26
27/* HHI Registers */
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)
73
74#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020075#define HHI_HDMI_PLL_CNTL_EN BIT(30)
Neil Armstrongadd986c2018-07-24 17:45:28 +020076#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 */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020081#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
Neil Armstrongadd986c2018-07-24 17:45:28 +020082
83#define HDMI_PLL_RESET BIT(28)
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020084#define HDMI_PLL_RESET_G12A BIT(29)
Neil Armstrongadd986c2018-07-24 17:45:28 +020085#define HDMI_PLL_LOCK BIT(31)
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020086#define HDMI_PLL_LOCK_G12A (3 << 30)
87
88#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
Neil Armstrongadd986c2018-07-24 17:45:28 +020089
90/* VID PLL Dividers */
91enum {
92 VID_PLL_DIV_1 = 0,
93 VID_PLL_DIV_2,
94 VID_PLL_DIV_2p5,
95 VID_PLL_DIV_3,
96 VID_PLL_DIV_3p5,
97 VID_PLL_DIV_3p75,
98 VID_PLL_DIV_4,
99 VID_PLL_DIV_5,
100 VID_PLL_DIV_6,
101 VID_PLL_DIV_6p25,
102 VID_PLL_DIV_7,
103 VID_PLL_DIV_7p5,
104 VID_PLL_DIV_12,
105 VID_PLL_DIV_14,
106 VID_PLL_DIV_15,
107};
108
109void meson_vid_pll_set(struct meson_vpu_priv *priv, unsigned int div)
110{
111 unsigned int shift_val = 0;
112 unsigned int shift_sel = 0;
113
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);
117
118 switch (div) {
119 case VID_PLL_DIV_2:
120 shift_val = 0x0aaa;
121 shift_sel = 0;
122 break;
123 case VID_PLL_DIV_2p5:
124 shift_val = 0x5294;
125 shift_sel = 2;
126 break;
127 case VID_PLL_DIV_3:
128 shift_val = 0x0db6;
129 shift_sel = 0;
130 break;
131 case VID_PLL_DIV_3p5:
132 shift_val = 0x36cc;
133 shift_sel = 1;
134 break;
135 case VID_PLL_DIV_3p75:
136 shift_val = 0x6666;
137 shift_sel = 2;
138 break;
139 case VID_PLL_DIV_4:
140 shift_val = 0x0ccc;
141 shift_sel = 0;
142 break;
143 case VID_PLL_DIV_5:
144 shift_val = 0x739c;
145 shift_sel = 2;
146 break;
147 case VID_PLL_DIV_6:
148 shift_val = 0x0e38;
149 shift_sel = 0;
150 break;
151 case VID_PLL_DIV_6p25:
152 shift_val = 0x0000;
153 shift_sel = 3;
154 break;
155 case VID_PLL_DIV_7:
156 shift_val = 0x3c78;
157 shift_sel = 1;
158 break;
159 case VID_PLL_DIV_7p5:
160 shift_val = 0x78f0;
161 shift_sel = 2;
162 break;
163 case VID_PLL_DIV_12:
164 shift_val = 0x0fc0;
165 shift_sel = 0;
166 break;
167 case VID_PLL_DIV_14:
168 shift_val = 0x3f80;
169 shift_sel = 1;
170 break;
171 case VID_PLL_DIV_15:
172 shift_val = 0x7f80;
173 shift_sel = 2;
174 break;
175 }
176
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);
181 } else {
182 /* Disable Bypass */
183 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
184 VID_PLL_BYPASS, 0);
185 /* Clear sel */
186 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
187 3 << 16, 0);
188 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
189 VID_PLL_PRESET, 0);
190 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
191 0x7fff, 0);
192
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,
199 0x7fff, shift_val);
200
201 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
202 VID_PLL_PRESET, 0);
203 }
204
205 /* Enable the vid_pll output clock */
206 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
207 VID_PLL_EN, VID_PLL_EN);
208}
209
210/*
211 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
212 *
213 * TOFIX: Refactor into table to also handle HDMI frequency and paths
214 */
215static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
216{
217 unsigned int val;
218
Neil Armstrongadd986c2018-07-24 17:45:28 +0200219 /* 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);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200228
229 /* Poll for lock bit */
230 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
231 (val & HDMI_PLL_LOCK), 10);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200232 } 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);
240
241 /* Reset PLL */
242 hhi_update_bits(HHI_HDMI_PLL_CNTL,
243 HDMI_PLL_RESET, HDMI_PLL_RESET);
244 hhi_update_bits(HHI_HDMI_PLL_CNTL,
245 HDMI_PLL_RESET, 0);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200246
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200247 /* 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);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200260
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200261 /* 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),
264 10);
265 }
Neil Armstrongadd986c2018-07-24 17:45:28 +0200266
267 /* Disable VCLK2 */
268 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
269
270 /* Setup vid_pll to /1 */
271 meson_vid_pll_set(priv, VID_PLL_DIV_1);
272
273 /* Setup the VCLK2 divider value to achieve 27MHz */
274 hhi_update_bits(HHI_VIID_CLK_DIV,
275 VCLK2_DIV_MASK, (55 - 1));
276
277 /* select vid_pll for vclk2 */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200278 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));
281 else
282 hhi_update_bits(HHI_VIID_CLK_CNTL,
283 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
284
Neil Armstrongadd986c2018-07-24 17:45:28 +0200285 /* enable vclk2 gate */
286 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
287
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));
294
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);
298
299 /* enable vclk2_div1 gate */
300 hhi_update_bits(HHI_VIID_CLK_CNTL,
301 VCLK2_DIV1_EN, VCLK2_DIV1_EN);
302
303 /* reset vclk2 */
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);
308
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);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200315}
316
317enum {
318/* PLL O1 O2 O3 VP DV EN TX */
319/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200320 MESON_VCLK_HDMI_ENCI_54000 = 0,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200321/* 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
333};
334
335struct meson_vclk_params {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200336 unsigned int pixel_freq;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200337 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;
343} params[] = {
344 [MESON_VCLK_HDMI_ENCI_54000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200345 .pixel_freq = 54000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200346 .pll_base_freq = 4320000,
347 .pll_od1 = 4,
348 .pll_od2 = 4,
349 .pll_od3 = 1,
350 .vid_pll_div = VID_PLL_DIV_5,
351 .vclk_div = 1,
352 },
353 [MESON_VCLK_HDMI_DDR_54000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200354 .pixel_freq = 54000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200355 .pll_base_freq = 4320000,
356 .pll_od1 = 4,
357 .pll_od2 = 4,
358 .pll_od3 = 1,
359 .vid_pll_div = VID_PLL_DIV_5,
360 .vclk_div = 1,
361 },
362 [MESON_VCLK_HDMI_DDR_148500] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200363 .pixel_freq = 148500,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200364 .pll_base_freq = 2970000,
365 .pll_od1 = 4,
366 .pll_od2 = 1,
367 .pll_od3 = 1,
368 .vid_pll_div = VID_PLL_DIV_5,
369 .vclk_div = 1,
370 },
371 [MESON_VCLK_HDMI_74250] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200372 .pixel_freq = 74250,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200373 .pll_base_freq = 2970000,
374 .pll_od1 = 2,
375 .pll_od2 = 2,
376 .pll_od3 = 2,
377 .vid_pll_div = VID_PLL_DIV_5,
378 .vclk_div = 1,
379 },
380 [MESON_VCLK_HDMI_148500] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200381 .pixel_freq = 148500,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200382 .pll_base_freq = 2970000,
383 .pll_od1 = 1,
384 .pll_od2 = 2,
385 .pll_od3 = 2,
386 .vid_pll_div = VID_PLL_DIV_5,
387 .vclk_div = 1,
388 },
389 [MESON_VCLK_HDMI_297000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200390 .pixel_freq = 297000,
391 .pll_base_freq = 5940000,
392 .pll_od1 = 2,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200393 .pll_od2 = 1,
394 .pll_od3 = 1,
395 .vid_pll_div = VID_PLL_DIV_5,
396 .vclk_div = 2,
397 },
398 [MESON_VCLK_HDMI_594000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200399 .pixel_freq = 594000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200400 .pll_base_freq = 5940000,
401 .pll_od1 = 1,
402 .pll_od2 = 1,
403 .pll_od3 = 2,
404 .vid_pll_div = VID_PLL_DIV_5,
405 .vclk_div = 1,
406 },
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200407 { /* sentinel */ },
Neil Armstrongadd986c2018-07-24 17:45:28 +0200408};
409
410static inline unsigned int pll_od_to_reg(unsigned int od)
411{
412 switch (od) {
413 case 1:
414 return 0;
415 case 2:
416 return 1;
417 case 4:
418 return 2;
419 case 8:
420 return 3;
421 }
422
423 /* Invalid */
424 return 0;
425}
426
427void 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)
430{
431 unsigned int val;
432
433 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
434 hhi_write(HHI_HDMI_PLL_CNTL, 0x58000200 | m);
435 if (frac)
436 hhi_write(HHI_HDMI_PLL_CNTL2,
437 0x00004000 | frac);
438 else
439 hhi_write(HHI_HDMI_PLL_CNTL2,
440 0x00000000);
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);
445
446 /* Enable and unreset */
447 hhi_update_bits(HHI_HDMI_PLL_CNTL,
448 0x7 << 28, 0x4 << 28);
449
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);
461
462 /* Reset PLL */
463 hhi_update_bits(HHI_HDMI_PLL_CNTL,
464 HDMI_PLL_RESET, HDMI_PLL_RESET);
465 hhi_update_bits(HHI_HDMI_PLL_CNTL,
466 HDMI_PLL_RESET, 0);
467
468 /* Poll for lock bit */
469 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
470 (val & HDMI_PLL_LOCK), 10);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200471 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
472 hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
473
474 /* Enable and reset */
475 hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
476
477 hhi_write(HHI_HDMI_PLL_CNTL2, frac);
478 hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
479
480 /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
481 if (m >= 0xf7) {
482 if (frac < 0x10000) {
483 hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
484 hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
485 } else {
486 hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
487 hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
488 }
489 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
490 hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
491 } else {
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);
496 }
497
498 do {
499 /* Reset PLL */
500 hhi_update_bits(HHI_HDMI_PLL_CNTL,
501 HDMI_PLL_RESET_G12A,
502 HDMI_PLL_RESET_G12A);
503
504 /* UN-Reset PLL */
505 hhi_update_bits(HHI_HDMI_PLL_CNTL,
506 HDMI_PLL_RESET_G12A, 0);
507
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))
513 break;
514 } while (1);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200515 }
516
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);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200524 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);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200527
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);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200535 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);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200538
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);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200546 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);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200549}
550
551#define XTAL_FREQ 24000
552
553static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
554 unsigned int pll_freq)
555{
556 /* The GXBB PLL has a /2 pre-multiplier */
557 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
558 pll_freq /= 2;
559
560 return pll_freq / XTAL_FREQ;
561}
562
563#define HDMI_FRAC_MAX_GXBB 4096
564#define HDMI_FRAC_MAX_GXL 1024
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200565#define HDMI_FRAC_MAX_G12A 131072
Neil Armstrongadd986c2018-07-24 17:45:28 +0200566
567static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
568 unsigned int m,
569 unsigned int pll_freq)
570{
571 unsigned int parent_freq = XTAL_FREQ;
572 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
573 unsigned int frac_m;
574 unsigned int frac;
575
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;
579 parent_freq *= 2;
580 }
581
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200582 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
583 frac_max = HDMI_FRAC_MAX_G12A;
584
Neil Armstrongadd986c2018-07-24 17:45:28 +0200585 /* We can have a perfect match !*/
586 if (pll_freq / m == parent_freq &&
587 pll_freq % m == 0)
588 return 0;
589
590 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
591 frac_m = m * frac_max;
592 if (frac_m > frac)
593 return frac_max;
594 frac -= frac_m;
595
596 return min((u16)frac, (u16)(frac_max - 1));
597}
598
599static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
600 unsigned int m,
601 unsigned int frac)
602{
603 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
604 /* Empiric supported min/max dividers */
605 if (m < 53 || m > 123)
606 return false;
607 if (frac >= HDMI_FRAC_MAX_GXBB)
608 return false;
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)
613 return false;
614 if (frac >= HDMI_FRAC_MAX_GXL)
615 return false;
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200616 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
617 /* Empiric supported min/max dividers */
618 if (m < 106 || m > 247)
619 return false;
620 if (frac >= HDMI_FRAC_MAX_G12A)
621 return false;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200622 }
623
624 return true;
625}
626
627static bool meson_hdmi_pll_find_params(struct meson_vpu_priv *priv,
628 unsigned int freq,
629 unsigned int *m,
630 unsigned int *frac,
631 unsigned int *od)
632{
633 /* Cycle from /16 to /2 */
634 for (*od = 16 ; *od > 1 ; *od >>= 1) {
635 *m = meson_hdmi_pll_get_m(priv, freq * *od);
636 if (!*m)
637 continue;
638 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
639
640 debug("PLL params for %dkHz: m=%x frac=%x od=%d\n",
641 freq, *m, *frac, *od);
642
643 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
644 return true;
645 }
646
647 return false;
648}
649
650/* pll_freq is the frequency after the OD dividers */
651bool meson_vclk_dmt_supported_freq(struct meson_vpu_priv *priv,
652 unsigned int freq)
653{
654 unsigned int od, m, frac;
655
656 /* In DMT mode, path after PLL is always /10 */
657 freq *= 10;
658
659 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
660 return true;
661
662 return false;
663}
664
665/* pll_freq is the frequency after the OD dividers */
666static void meson_hdmi_pll_generic_set(struct meson_vpu_priv *priv,
667 unsigned int pll_freq)
668{
669 unsigned int od, m, frac, od1, od2, od3;
670
671 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
672 od3 = 1;
673 if (od < 4) {
674 od1 = 2;
675 od2 = 1;
676 } else {
677 od2 = od / 4;
678 od1 = od / od2;
679 }
680
681 debug("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
682 pll_freq, m, frac, od1, od2, od3);
683
684 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
685
686 return;
687 }
688
689 printf("Fatal, unable to find parameters for PLL freq %d\n",
690 pll_freq);
691}
692
693static void
694meson_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,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200698 bool hdmi_use_enci, bool vic_alternate_clock)
Neil Armstrongadd986c2018-07-24 17:45:28 +0200699{
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200700 unsigned int m = 0, frac = 0;
701
Neil Armstrongadd986c2018-07-24 17:45:28 +0200702 /* 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);
709
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) {
715 case 2970000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200716 m = 0x3d;
717 frac = vic_alternate_clock ? 0xd02 : 0xe00;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200718 break;
719 case 4320000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200720 m = vic_alternate_clock ? 0x59 : 0x5a;
721 frac = vic_alternate_clock ? 0xe8f : 0;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200722 break;
723 case 5940000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200724 m = 0x7b;
725 frac = vic_alternate_clock ? 0xa05 : 0xc00;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200726 break;
727 }
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200728
729 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200730 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
731 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
732 switch (pll_base_freq) {
733 case 2970000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200734 m = 0x7b;
735 frac = vic_alternate_clock ? 0x281 : 0x300;
736 break;
737 case 4320000:
738 m = vic_alternate_clock ? 0xb3 : 0xb4;
739 frac = vic_alternate_clock ? 0x347 : 0;
740 break;
741 case 5940000:
742 m = 0xf7;
743 frac = vic_alternate_clock ? 0x102 : 0x200;
744 break;
745 }
746
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) {
750 case 2970000:
751 m = 0x7b;
752 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200753 break;
754 case 4320000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200755 m = vic_alternate_clock ? 0xb3 : 0xb4;
756 frac = vic_alternate_clock ? 0x1a3ee : 0;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200757 break;
758 case 5940000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200759 m = 0xf7;
760 frac = vic_alternate_clock ? 0x8148 : 0x10000;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200761 break;
762 }
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200763
764 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200765 }
766
767 /* Setup vid_pll divider */
768 meson_vid_pll_set(priv, vid_pll_div);
769
770 /* Set VCLK div */
771 hhi_update_bits(HHI_VID_CLK_CNTL,
772 VCLK_SEL_MASK, 0);
773 hhi_update_bits(HHI_VID_CLK_DIV,
774 VCLK_DIV_MASK, vclk_div - 1);
775
776 /* Set HDMI-TX source */
777 switch (hdmi_tx_div) {
778 case 1:
779 /* enable vclk_div1 gate */
780 hhi_update_bits(HHI_VID_CLK_CNTL,
781 VCLK_DIV1_EN, VCLK_DIV1_EN);
782
783 /* select vclk_div1 for HDMI-TX */
784 hhi_update_bits(HHI_HDMI_CLK_CNTL,
785 HDMI_TX_PIXEL_SEL_MASK, 0);
786 break;
787 case 2:
788 /* enable vclk_div2 gate */
789 hhi_update_bits(HHI_VID_CLK_CNTL,
790 VCLK_DIV2_EN, VCLK_DIV2_EN);
791
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);
796 break;
797 case 4:
798 /* enable vclk_div4 gate */
799 hhi_update_bits(HHI_VID_CLK_CNTL,
800 VCLK_DIV4_EN, VCLK_DIV4_EN);
801
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);
806 break;
807 case 6:
808 /* enable vclk_div6 gate */
809 hhi_update_bits(HHI_VID_CLK_CNTL,
810 VCLK_DIV6_EN, VCLK_DIV6_EN);
811
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);
816 break;
817 case 12:
818 /* enable vclk_div12 gate */
819 hhi_update_bits(HHI_VID_CLK_CNTL,
820 VCLK_DIV12_EN, VCLK_DIV12_EN);
821
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);
826 break;
827 }
828 hhi_update_bits(HHI_VID_CLK_CNTL2,
829 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
830
831 /* Set ENCI/ENCP Source */
832 switch (venc_div) {
833 case 1:
834 /* enable vclk_div1 gate */
835 hhi_update_bits(HHI_VID_CLK_CNTL,
836 VCLK_DIV1_EN, VCLK_DIV1_EN);
837
838 if (hdmi_use_enci)
839 /* select vclk_div1 for enci */
840 hhi_update_bits(HHI_VID_CLK_DIV,
841 CTS_ENCI_SEL_MASK, 0);
842 else
843 /* select vclk_div1 for encp */
844 hhi_update_bits(HHI_VID_CLK_DIV,
845 CTS_ENCP_SEL_MASK, 0);
846 break;
847 case 2:
848 /* enable vclk_div2 gate */
849 hhi_update_bits(HHI_VID_CLK_CNTL,
850 VCLK_DIV2_EN, VCLK_DIV2_EN);
851
852 if (hdmi_use_enci)
853 /* select vclk_div2 for enci */
854 hhi_update_bits(HHI_VID_CLK_DIV,
855 CTS_ENCI_SEL_MASK,
856 1 << CTS_ENCI_SEL_SHIFT);
857 else
858 /* select vclk_div2 for encp */
859 hhi_update_bits(HHI_VID_CLK_DIV,
860 CTS_ENCP_SEL_MASK,
861 1 << CTS_ENCP_SEL_SHIFT);
862 break;
863 case 4:
864 /* enable vclk_div4 gate */
865 hhi_update_bits(HHI_VID_CLK_CNTL,
866 VCLK_DIV4_EN, VCLK_DIV4_EN);
867
868 if (hdmi_use_enci)
869 /* select vclk_div4 for enci */
870 hhi_update_bits(HHI_VID_CLK_DIV,
871 CTS_ENCI_SEL_MASK,
872 2 << CTS_ENCI_SEL_SHIFT);
873 else
874 /* select vclk_div4 for encp */
875 hhi_update_bits(HHI_VID_CLK_DIV,
876 CTS_ENCP_SEL_MASK,
877 2 << CTS_ENCP_SEL_SHIFT);
878 break;
879 case 6:
880 /* enable vclk_div6 gate */
881 hhi_update_bits(HHI_VID_CLK_CNTL,
882 VCLK_DIV6_EN, VCLK_DIV6_EN);
883
884 if (hdmi_use_enci)
885 /* select vclk_div6 for enci */
886 hhi_update_bits(HHI_VID_CLK_DIV,
887 CTS_ENCI_SEL_MASK,
888 3 << CTS_ENCI_SEL_SHIFT);
889 else
890 /* select vclk_div6 for encp */
891 hhi_update_bits(HHI_VID_CLK_DIV,
892 CTS_ENCP_SEL_MASK,
893 3 << CTS_ENCP_SEL_SHIFT);
894 break;
895 case 12:
896 /* enable vclk_div12 gate */
897 hhi_update_bits(HHI_VID_CLK_CNTL,
898 VCLK_DIV12_EN, VCLK_DIV12_EN);
899
900 if (hdmi_use_enci)
901 /* select vclk_div12 for enci */
902 hhi_update_bits(HHI_VID_CLK_DIV,
903 CTS_ENCI_SEL_MASK,
904 4 << CTS_ENCI_SEL_SHIFT);
905 else
906 /* select vclk_div12 for encp */
907 hhi_update_bits(HHI_VID_CLK_DIV,
908 CTS_ENCP_SEL_MASK,
909 4 << CTS_ENCP_SEL_SHIFT);
910 break;
911 }
912
913 if (hdmi_use_enci)
914 /* Enable ENCI clock gate */
915 hhi_update_bits(HHI_VID_CLK_CNTL2,
916 CTS_ENCI_EN, CTS_ENCI_EN);
917 else
918 /* Enable ENCP clock gate */
919 hhi_update_bits(HHI_VID_CLK_CNTL2,
920 CTS_ENCP_EN, CTS_ENCP_EN);
921
922 hhi_update_bits(HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
923}
924
925static 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)
928{
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200929 bool vic_alternate_clock = false;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200930 unsigned int freq;
931 unsigned int hdmi_tx_div;
932 unsigned int venc_div;
933
934 if (target == MESON_VCLK_TARGET_CVBS) {
935 meson_venci_cvbs_clock_config(priv);
936 return;
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
941 * - vclk_div = 2
942 * - hdmi_tx_div = 1
943 * - venc_div = 1
944 * - encp encoder
945 */
946 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200947 VID_PLL_DIV_5, 2, 1, 1, false, false);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200948 return;
949 }
950
951 hdmi_tx_div = vclk_freq / dac_freq;
952
953 if (hdmi_tx_div == 0) {
954 printf("Fatal Error, invalid HDMI-TX freq %d\n",
955 dac_freq);
956 return;
957 }
958
959 venc_div = vclk_freq / venc_freq;
960
961 if (venc_div == 0) {
962 printf("Fatal Error, invalid HDMI venc freq %d\n",
963 venc_freq);
964 return;
965 }
966
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200967 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;
972 else
973 vic_alternate_clock = false;
974
975 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
976 !hdmi_use_enci)
977 continue;
978
979 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
980 hdmi_use_enci)
981 continue;
982
983 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
984 dac_freq == vclk_freq)
985 continue;
986
987 if (freq == MESON_VCLK_HDMI_148500 &&
988 dac_freq != vclk_freq)
989 continue;
990 break;
991 }
992 }
993
994 if (!params[freq].pixel_freq) {
995 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200996 return;
997 }
998
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,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +02001003 hdmi_use_enci, vic_alternate_clock);
Neil Armstrongadd986c2018-07-24 17:45:28 +02001004}
1005
1006void meson_vpu_setup_vclk(struct udevice *dev,
1007 const struct display_timing *mode, bool is_cvbs)
1008{
1009 struct meson_vpu_priv *priv = dev_get_priv(dev);
1010 unsigned int vclk_freq;
1011
1012 if (is_cvbs)
1013 return meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
1014 0, 0, 0, false);
1015
1016 vclk_freq = mode->pixelclock.typ / 1000;
1017
1018 return meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT,
1019 vclk_freq, vclk_freq, vclk_freq, false);
1020}