blob: e718a0074ed6a70633209ee45e3471fd4870dcce [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>
Simon Glassbdd5f812023-09-14 18:21:46 -060013#include <linux/printk.h>
Neil Armstrongadd986c2018-07-24 17:45:28 +020014#include "meson_vpu.h"
Simon Glass0f2af882020-05-10 11:40:05 -060015#include <log.h>
Neil Armstrongadd986c2018-07-24 17:45:28 +020016#include <linux/iopoll.h>
17#include <linux/math64.h>
18
19#define writel_bits(mask, val, addr) \
20 writel((readl(addr) & ~(mask)) | (val), addr)
21
22enum {
23 MESON_VCLK_TARGET_CVBS = 0,
24 MESON_VCLK_TARGET_HDMI = 1,
25 MESON_VCLK_TARGET_DMT = 2,
26};
27
28/* HHI Registers */
29#define HHI_VID_PLL_CLK_DIV 0x1a0 /* 0x68 offset in data sheet */
30#define VID_PLL_EN BIT(19)
31#define VID_PLL_BYPASS BIT(18)
32#define VID_PLL_PRESET BIT(15)
33#define HHI_VIID_CLK_DIV 0x128 /* 0x4a offset in data sheet */
34#define VCLK2_DIV_MASK 0xff
35#define VCLK2_DIV_EN BIT(16)
36#define VCLK2_DIV_RESET BIT(17)
37#define CTS_VDAC_SEL_MASK (0xf << 28)
38#define CTS_VDAC_SEL_SHIFT 28
39#define HHI_VIID_CLK_CNTL 0x12c /* 0x4b offset in data sheet */
40#define VCLK2_EN BIT(19)
41#define VCLK2_SEL_MASK (0x7 << 16)
42#define VCLK2_SEL_SHIFT 16
43#define VCLK2_SOFT_RESET BIT(15)
44#define VCLK2_DIV1_EN BIT(0)
45#define HHI_VID_CLK_DIV 0x164 /* 0x59 offset in data sheet */
46#define VCLK_DIV_MASK 0xff
47#define VCLK_DIV_EN BIT(16)
48#define VCLK_DIV_RESET BIT(17)
49#define CTS_ENCP_SEL_MASK (0xf << 24)
50#define CTS_ENCP_SEL_SHIFT 24
51#define CTS_ENCI_SEL_MASK (0xf << 28)
52#define CTS_ENCI_SEL_SHIFT 28
53#define HHI_VID_CLK_CNTL 0x17c /* 0x5f offset in data sheet */
54#define VCLK_EN BIT(19)
55#define VCLK_SEL_MASK (0x7 << 16)
56#define VCLK_SEL_SHIFT 16
57#define VCLK_SOFT_RESET BIT(15)
58#define VCLK_DIV1_EN BIT(0)
59#define VCLK_DIV2_EN BIT(1)
60#define VCLK_DIV4_EN BIT(2)
61#define VCLK_DIV6_EN BIT(3)
62#define VCLK_DIV12_EN BIT(4)
63#define HHI_VID_CLK_CNTL2 0x194 /* 0x65 offset in data sheet */
64#define CTS_ENCI_EN BIT(0)
65#define CTS_ENCP_EN BIT(2)
66#define CTS_VDAC_EN BIT(4)
67#define HDMI_TX_PIXEL_EN BIT(5)
68#define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 offset in data sheet */
69#define HDMI_TX_PIXEL_SEL_MASK (0xf << 16)
70#define HDMI_TX_PIXEL_SEL_SHIFT 16
71#define CTS_HDMI_SYS_SEL_MASK (0x7 << 9)
72#define CTS_HDMI_SYS_DIV_MASK (0x7f)
73#define CTS_HDMI_SYS_EN BIT(8)
74
75#define HHI_HDMI_PLL_CNTL 0x320 /* 0xc8 offset in data sheet */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020076#define HHI_HDMI_PLL_CNTL_EN BIT(30)
Neil Armstrongadd986c2018-07-24 17:45:28 +020077#define HHI_HDMI_PLL_CNTL2 0x324 /* 0xc9 offset in data sheet */
78#define HHI_HDMI_PLL_CNTL3 0x328 /* 0xca offset in data sheet */
79#define HHI_HDMI_PLL_CNTL4 0x32C /* 0xcb offset in data sheet */
80#define HHI_HDMI_PLL_CNTL5 0x330 /* 0xcc offset in data sheet */
81#define HHI_HDMI_PLL_CNTL6 0x334 /* 0xcd offset in data sheet */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020082#define HHI_HDMI_PLL_CNTL7 0x338 /* 0xce offset in data sheet */
Neil Armstrongadd986c2018-07-24 17:45:28 +020083
84#define HDMI_PLL_RESET BIT(28)
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020085#define HDMI_PLL_RESET_G12A BIT(29)
Neil Armstrongadd986c2018-07-24 17:45:28 +020086#define HDMI_PLL_LOCK BIT(31)
Neil Armstrong57d6dfe2019-08-30 14:09:24 +020087#define HDMI_PLL_LOCK_G12A (3 << 30)
88
89#define FREQ_1000_1001(_freq) DIV_ROUND_CLOSEST(_freq * 1000, 1001)
Neil Armstrongadd986c2018-07-24 17:45:28 +020090
91/* VID PLL Dividers */
92enum {
93 VID_PLL_DIV_1 = 0,
94 VID_PLL_DIV_2,
95 VID_PLL_DIV_2p5,
96 VID_PLL_DIV_3,
97 VID_PLL_DIV_3p5,
98 VID_PLL_DIV_3p75,
99 VID_PLL_DIV_4,
100 VID_PLL_DIV_5,
101 VID_PLL_DIV_6,
102 VID_PLL_DIV_6p25,
103 VID_PLL_DIV_7,
104 VID_PLL_DIV_7p5,
105 VID_PLL_DIV_12,
106 VID_PLL_DIV_14,
107 VID_PLL_DIV_15,
108};
109
110void meson_vid_pll_set(struct meson_vpu_priv *priv, unsigned int div)
111{
112 unsigned int shift_val = 0;
113 unsigned int shift_sel = 0;
114
115 /* Disable vid_pll output clock */
116 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_EN, 0);
117 hhi_update_bits(HHI_VID_PLL_CLK_DIV, VID_PLL_PRESET, 0);
118
119 switch (div) {
120 case VID_PLL_DIV_2:
121 shift_val = 0x0aaa;
122 shift_sel = 0;
123 break;
124 case VID_PLL_DIV_2p5:
125 shift_val = 0x5294;
126 shift_sel = 2;
127 break;
128 case VID_PLL_DIV_3:
129 shift_val = 0x0db6;
130 shift_sel = 0;
131 break;
132 case VID_PLL_DIV_3p5:
133 shift_val = 0x36cc;
134 shift_sel = 1;
135 break;
136 case VID_PLL_DIV_3p75:
137 shift_val = 0x6666;
138 shift_sel = 2;
139 break;
140 case VID_PLL_DIV_4:
141 shift_val = 0x0ccc;
142 shift_sel = 0;
143 break;
144 case VID_PLL_DIV_5:
145 shift_val = 0x739c;
146 shift_sel = 2;
147 break;
148 case VID_PLL_DIV_6:
149 shift_val = 0x0e38;
150 shift_sel = 0;
151 break;
152 case VID_PLL_DIV_6p25:
153 shift_val = 0x0000;
154 shift_sel = 3;
155 break;
156 case VID_PLL_DIV_7:
157 shift_val = 0x3c78;
158 shift_sel = 1;
159 break;
160 case VID_PLL_DIV_7p5:
161 shift_val = 0x78f0;
162 shift_sel = 2;
163 break;
164 case VID_PLL_DIV_12:
165 shift_val = 0x0fc0;
166 shift_sel = 0;
167 break;
168 case VID_PLL_DIV_14:
169 shift_val = 0x3f80;
170 shift_sel = 1;
171 break;
172 case VID_PLL_DIV_15:
173 shift_val = 0x7f80;
174 shift_sel = 2;
175 break;
176 }
177
178 if (div == VID_PLL_DIV_1) {
179 /* Enable vid_pll bypass to HDMI pll */
180 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
181 VID_PLL_BYPASS, VID_PLL_BYPASS);
182 } else {
183 /* Disable Bypass */
184 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
185 VID_PLL_BYPASS, 0);
186 /* Clear sel */
187 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
188 3 << 16, 0);
189 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
190 VID_PLL_PRESET, 0);
191 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
192 0x7fff, 0);
193
194 /* Setup sel and val */
195 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
196 3 << 16, shift_sel << 16);
197 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
198 VID_PLL_PRESET, VID_PLL_PRESET);
199 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
200 0x7fff, shift_val);
201
202 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
203 VID_PLL_PRESET, 0);
204 }
205
206 /* Enable the vid_pll output clock */
207 hhi_update_bits(HHI_VID_PLL_CLK_DIV,
208 VID_PLL_EN, VID_PLL_EN);
209}
210
211/*
212 * Setup VCLK2 for 27MHz, and enable clocks for ENCI and VDAC
213 *
214 * TOFIX: Refactor into table to also handle HDMI frequency and paths
215 */
216static void meson_venci_cvbs_clock_config(struct meson_vpu_priv *priv)
217{
218 unsigned int val;
219
Neil Armstrongadd986c2018-07-24 17:45:28 +0200220 /* Setup PLL to output 1.485GHz */
221 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
222 hhi_write(HHI_HDMI_PLL_CNTL, 0x5800023d);
223 hhi_write(HHI_HDMI_PLL_CNTL2, 0x00404e00);
224 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
225 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
226 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
227 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
228 hhi_write(HHI_HDMI_PLL_CNTL, 0x4800023d);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200229
230 /* Poll for lock bit */
231 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
232 (val & HDMI_PLL_LOCK), 10);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200233 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
234 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
235 hhi_write(HHI_HDMI_PLL_CNTL, 0x4000027b);
236 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb300);
237 hhi_write(HHI_HDMI_PLL_CNTL3, 0xa6212844);
238 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c4d000c);
239 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
240 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
241
242 /* Reset PLL */
243 hhi_update_bits(HHI_HDMI_PLL_CNTL,
244 HDMI_PLL_RESET, HDMI_PLL_RESET);
245 hhi_update_bits(HHI_HDMI_PLL_CNTL,
246 HDMI_PLL_RESET, 0);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200247
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200248 /* Poll for lock bit */
249 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
250 (val & HDMI_PLL_LOCK), 10);
251 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
252 hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
253 hhi_write(HHI_HDMI_PLL_CNTL2, 0x00010000);
254 hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
255 hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a28dc00);
256 hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
257 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
258 hhi_write(HHI_HDMI_PLL_CNTL7, 0x56540000);
259 hhi_write(HHI_HDMI_PLL_CNTL, 0x3a0504f7);
260 hhi_write(HHI_HDMI_PLL_CNTL, 0x1a0504f7);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200261
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200262 /* Poll for lock bit */
263 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
264 ((val & HDMI_PLL_LOCK_G12A) == HDMI_PLL_LOCK_G12A),
265 10);
266 }
Neil Armstrongadd986c2018-07-24 17:45:28 +0200267
268 /* Disable VCLK2 */
269 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, 0);
270
271 /* Setup vid_pll to /1 */
272 meson_vid_pll_set(priv, VID_PLL_DIV_1);
273
274 /* Setup the VCLK2 divider value to achieve 27MHz */
275 hhi_update_bits(HHI_VIID_CLK_DIV,
276 VCLK2_DIV_MASK, (55 - 1));
277
278 /* select vid_pll for vclk2 */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200279 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
280 hhi_update_bits(HHI_VIID_CLK_CNTL,
281 VCLK2_SEL_MASK, (0 << VCLK2_SEL_SHIFT));
282 else
283 hhi_update_bits(HHI_VIID_CLK_CNTL,
284 VCLK2_SEL_MASK, (4 << VCLK2_SEL_SHIFT));
285
Neil Armstrongadd986c2018-07-24 17:45:28 +0200286 /* enable vclk2 gate */
287 hhi_update_bits(HHI_VIID_CLK_CNTL, VCLK2_EN, VCLK2_EN);
288
289 /* select vclk_div1 for enci */
290 hhi_update_bits(HHI_VID_CLK_DIV,
291 CTS_ENCI_SEL_MASK, (8 << CTS_ENCI_SEL_SHIFT));
292 /* select vclk_div1 for vdac */
293 hhi_update_bits(HHI_VIID_CLK_DIV,
294 CTS_VDAC_SEL_MASK, (8 << CTS_VDAC_SEL_SHIFT));
295
296 /* release vclk2_div_reset and enable vclk2_div */
297 hhi_update_bits(HHI_VIID_CLK_DIV,
298 VCLK2_DIV_EN | VCLK2_DIV_RESET, VCLK2_DIV_EN);
299
300 /* enable vclk2_div1 gate */
301 hhi_update_bits(HHI_VIID_CLK_CNTL,
302 VCLK2_DIV1_EN, VCLK2_DIV1_EN);
303
304 /* reset vclk2 */
305 hhi_update_bits(HHI_VIID_CLK_CNTL,
306 VCLK2_SOFT_RESET, VCLK2_SOFT_RESET);
307 hhi_update_bits(HHI_VIID_CLK_CNTL,
308 VCLK2_SOFT_RESET, 0);
309
310 /* enable enci_clk */
311 hhi_update_bits(HHI_VID_CLK_CNTL2,
312 CTS_ENCI_EN, CTS_ENCI_EN);
313 /* enable vdac_clk */
314 hhi_update_bits(HHI_VID_CLK_CNTL2,
315 CTS_VDAC_EN, CTS_VDAC_EN);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200316}
317
318enum {
319/* PLL O1 O2 O3 VP DV EN TX */
320/* 4320 /4 /4 /1 /5 /1 => /2 /2 */
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200321 MESON_VCLK_HDMI_ENCI_54000 = 0,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200322/* 4320 /4 /4 /1 /5 /1 => /1 /2 */
323 MESON_VCLK_HDMI_DDR_54000,
324/* 2970 /4 /1 /1 /5 /1 => /1 /2 */
325 MESON_VCLK_HDMI_DDR_148500,
326/* 2970 /2 /2 /2 /5 /1 => /1 /1 */
327 MESON_VCLK_HDMI_74250,
328/* 2970 /1 /2 /2 /5 /1 => /1 /1 */
329 MESON_VCLK_HDMI_148500,
330/* 2970 /1 /1 /1 /5 /2 => /1 /1 */
331 MESON_VCLK_HDMI_297000,
332/* 5940 /1 /1 /2 /5 /1 => /1 /1 */
333 MESON_VCLK_HDMI_594000
334};
335
336struct meson_vclk_params {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200337 unsigned int pixel_freq;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200338 unsigned int pll_base_freq;
339 unsigned int pll_od1;
340 unsigned int pll_od2;
341 unsigned int pll_od3;
342 unsigned int vid_pll_div;
343 unsigned int vclk_div;
344} params[] = {
345 [MESON_VCLK_HDMI_ENCI_54000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200346 .pixel_freq = 54000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200347 .pll_base_freq = 4320000,
348 .pll_od1 = 4,
349 .pll_od2 = 4,
350 .pll_od3 = 1,
351 .vid_pll_div = VID_PLL_DIV_5,
352 .vclk_div = 1,
353 },
354 [MESON_VCLK_HDMI_DDR_54000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200355 .pixel_freq = 54000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200356 .pll_base_freq = 4320000,
357 .pll_od1 = 4,
358 .pll_od2 = 4,
359 .pll_od3 = 1,
360 .vid_pll_div = VID_PLL_DIV_5,
361 .vclk_div = 1,
362 },
363 [MESON_VCLK_HDMI_DDR_148500] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200364 .pixel_freq = 148500,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200365 .pll_base_freq = 2970000,
366 .pll_od1 = 4,
367 .pll_od2 = 1,
368 .pll_od3 = 1,
369 .vid_pll_div = VID_PLL_DIV_5,
370 .vclk_div = 1,
371 },
372 [MESON_VCLK_HDMI_74250] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200373 .pixel_freq = 74250,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200374 .pll_base_freq = 2970000,
375 .pll_od1 = 2,
376 .pll_od2 = 2,
377 .pll_od3 = 2,
378 .vid_pll_div = VID_PLL_DIV_5,
379 .vclk_div = 1,
380 },
381 [MESON_VCLK_HDMI_148500] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200382 .pixel_freq = 148500,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200383 .pll_base_freq = 2970000,
384 .pll_od1 = 1,
385 .pll_od2 = 2,
386 .pll_od3 = 2,
387 .vid_pll_div = VID_PLL_DIV_5,
388 .vclk_div = 1,
389 },
390 [MESON_VCLK_HDMI_297000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200391 .pixel_freq = 297000,
392 .pll_base_freq = 5940000,
393 .pll_od1 = 2,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200394 .pll_od2 = 1,
395 .pll_od3 = 1,
396 .vid_pll_div = VID_PLL_DIV_5,
397 .vclk_div = 2,
398 },
399 [MESON_VCLK_HDMI_594000] = {
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200400 .pixel_freq = 594000,
Neil Armstrongadd986c2018-07-24 17:45:28 +0200401 .pll_base_freq = 5940000,
402 .pll_od1 = 1,
403 .pll_od2 = 1,
404 .pll_od3 = 2,
405 .vid_pll_div = VID_PLL_DIV_5,
406 .vclk_div = 1,
407 },
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200408 { /* sentinel */ },
Neil Armstrongadd986c2018-07-24 17:45:28 +0200409};
410
411static inline unsigned int pll_od_to_reg(unsigned int od)
412{
413 switch (od) {
414 case 1:
415 return 0;
416 case 2:
417 return 1;
418 case 4:
419 return 2;
420 case 8:
421 return 3;
422 }
423
424 /* Invalid */
425 return 0;
426}
427
428void meson_hdmi_pll_set_params(struct meson_vpu_priv *priv, unsigned int m,
429 unsigned int frac, unsigned int od1,
430 unsigned int od2, unsigned int od3)
431{
432 unsigned int val;
433
434 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
435 hhi_write(HHI_HDMI_PLL_CNTL, 0x58000200 | m);
436 if (frac)
437 hhi_write(HHI_HDMI_PLL_CNTL2,
438 0x00004000 | frac);
439 else
440 hhi_write(HHI_HDMI_PLL_CNTL2,
441 0x00000000);
442 hhi_write(HHI_HDMI_PLL_CNTL3, 0x0d5c5091);
443 hhi_write(HHI_HDMI_PLL_CNTL4, 0x801da72c);
444 hhi_write(HHI_HDMI_PLL_CNTL5, 0x71486980);
445 hhi_write(HHI_HDMI_PLL_CNTL6, 0x00000e55);
446
447 /* Enable and unreset */
448 hhi_update_bits(HHI_HDMI_PLL_CNTL,
449 0x7 << 28, 0x4 << 28);
450
451 /* Poll for lock bit */
452 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
453 (val & HDMI_PLL_LOCK), 10);
454 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
455 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
456 hhi_write(HHI_HDMI_PLL_CNTL, 0x40000200 | m);
457 hhi_write(HHI_HDMI_PLL_CNTL2, 0x800cb000 | frac);
458 hhi_write(HHI_HDMI_PLL_CNTL3, 0x860f30c4);
459 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0c8e0000);
460 hhi_write(HHI_HDMI_PLL_CNTL5, 0x001fa729);
461 hhi_write(HHI_HDMI_PLL_CNTL6, 0x01a31500);
462
463 /* Reset PLL */
464 hhi_update_bits(HHI_HDMI_PLL_CNTL,
465 HDMI_PLL_RESET, HDMI_PLL_RESET);
466 hhi_update_bits(HHI_HDMI_PLL_CNTL,
467 HDMI_PLL_RESET, 0);
468
469 /* Poll for lock bit */
470 readl_poll_timeout(priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
471 (val & HDMI_PLL_LOCK), 10);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200472 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
473 hhi_write(HHI_HDMI_PLL_CNTL, 0x0b3a0400 | m);
474
475 /* Enable and reset */
476 hhi_update_bits(HHI_HDMI_PLL_CNTL, 0x3 << 28, 0x3 << 28);
477
478 hhi_write(HHI_HDMI_PLL_CNTL2, frac);
479 hhi_write(HHI_HDMI_PLL_CNTL3, 0x00000000);
480
481 /* G12A HDMI PLL Needs specific parameters for 5.4GHz */
482 if (m >= 0xf7) {
483 if (frac < 0x10000) {
484 hhi_write(HHI_HDMI_PLL_CNTL4, 0x6a685c00);
485 hhi_write(HHI_HDMI_PLL_CNTL5, 0x11551293);
486 } else {
487 hhi_write(HHI_HDMI_PLL_CNTL4, 0xea68dc00);
488 hhi_write(HHI_HDMI_PLL_CNTL5, 0x65771290);
489 }
490 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39272000);
491 hhi_write(HHI_HDMI_PLL_CNTL7, 0x55540000);
492 } else {
493 hhi_write(HHI_HDMI_PLL_CNTL4, 0x0a691c00);
494 hhi_write(HHI_HDMI_PLL_CNTL5, 0x33771290);
495 hhi_write(HHI_HDMI_PLL_CNTL6, 0x39270000);
496 hhi_write(HHI_HDMI_PLL_CNTL7, 0x50540000);
497 }
498
499 do {
500 /* Reset PLL */
501 hhi_update_bits(HHI_HDMI_PLL_CNTL,
502 HDMI_PLL_RESET_G12A,
503 HDMI_PLL_RESET_G12A);
504
505 /* UN-Reset PLL */
506 hhi_update_bits(HHI_HDMI_PLL_CNTL,
507 HDMI_PLL_RESET_G12A, 0);
508
509 /* Poll for lock bits */
510 if (!readl_poll_timeout(
511 priv->hhi_base + HHI_HDMI_PLL_CNTL, val,
512 ((val & HDMI_PLL_LOCK_G12A)
513 == HDMI_PLL_LOCK_G12A), 100))
514 break;
515 } while (1);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200516 }
517
518 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
519 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
520 3 << 16, pll_od_to_reg(od1) << 16);
521 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
522 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
523 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
524 3 << 21, pll_od_to_reg(od1) << 21);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200525 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
526 hhi_update_bits(HHI_HDMI_PLL_CNTL,
527 3 << 16, pll_od_to_reg(od1) << 16);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200528
529 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
530 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
531 3 << 22, pll_od_to_reg(od2) << 22);
532 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
533 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
534 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
535 3 << 23, pll_od_to_reg(od2) << 23);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200536 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
537 hhi_update_bits(HHI_HDMI_PLL_CNTL,
538 3 << 18, pll_od_to_reg(od2) << 18);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200539
540 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
541 hhi_update_bits(HHI_HDMI_PLL_CNTL2,
542 3 << 18, pll_od_to_reg(od3) << 18);
543 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
544 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL))
545 hhi_update_bits(HHI_HDMI_PLL_CNTL3,
546 3 << 19, pll_od_to_reg(od3) << 19);
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200547 else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
548 hhi_update_bits(HHI_HDMI_PLL_CNTL,
549 3 << 20, pll_od_to_reg(od3) << 20);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200550}
551
552#define XTAL_FREQ 24000
553
554static unsigned int meson_hdmi_pll_get_m(struct meson_vpu_priv *priv,
555 unsigned int pll_freq)
556{
557 /* The GXBB PLL has a /2 pre-multiplier */
558 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB))
559 pll_freq /= 2;
560
561 return pll_freq / XTAL_FREQ;
562}
563
564#define HDMI_FRAC_MAX_GXBB 4096
565#define HDMI_FRAC_MAX_GXL 1024
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200566#define HDMI_FRAC_MAX_G12A 131072
Neil Armstrongadd986c2018-07-24 17:45:28 +0200567
568static unsigned int meson_hdmi_pll_get_frac(struct meson_vpu_priv *priv,
569 unsigned int m,
570 unsigned int pll_freq)
571{
572 unsigned int parent_freq = XTAL_FREQ;
573 unsigned int frac_max = HDMI_FRAC_MAX_GXL;
574 unsigned int frac_m;
575 unsigned int frac;
576
577 /* The GXBB PLL has a /2 pre-multiplier and a larger FRAC width */
578 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
579 frac_max = HDMI_FRAC_MAX_GXBB;
580 parent_freq *= 2;
581 }
582
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200583 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A))
584 frac_max = HDMI_FRAC_MAX_G12A;
585
Neil Armstrongadd986c2018-07-24 17:45:28 +0200586 /* We can have a perfect match !*/
587 if (pll_freq / m == parent_freq &&
588 pll_freq % m == 0)
589 return 0;
590
591 frac = div_u64((u64)pll_freq * (u64)frac_max, parent_freq);
592 frac_m = m * frac_max;
593 if (frac_m > frac)
594 return frac_max;
595 frac -= frac_m;
596
597 return min((u16)frac, (u16)(frac_max - 1));
598}
599
600static bool meson_hdmi_pll_validate_params(struct meson_vpu_priv *priv,
601 unsigned int m,
602 unsigned int frac)
603{
604 if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
605 /* Empiric supported min/max dividers */
606 if (m < 53 || m > 123)
607 return false;
608 if (frac >= HDMI_FRAC_MAX_GXBB)
609 return false;
610 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
611 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
612 /* Empiric supported min/max dividers */
613 if (m < 106 || m > 247)
614 return false;
615 if (frac >= HDMI_FRAC_MAX_GXL)
616 return false;
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200617 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
618 /* Empiric supported min/max dividers */
619 if (m < 106 || m > 247)
620 return false;
621 if (frac >= HDMI_FRAC_MAX_G12A)
622 return false;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200623 }
624
625 return true;
626}
627
628static bool meson_hdmi_pll_find_params(struct meson_vpu_priv *priv,
629 unsigned int freq,
630 unsigned int *m,
631 unsigned int *frac,
632 unsigned int *od)
633{
634 /* Cycle from /16 to /2 */
635 for (*od = 16 ; *od > 1 ; *od >>= 1) {
636 *m = meson_hdmi_pll_get_m(priv, freq * *od);
637 if (!*m)
638 continue;
639 *frac = meson_hdmi_pll_get_frac(priv, *m, freq * *od);
640
641 debug("PLL params for %dkHz: m=%x frac=%x od=%d\n",
642 freq, *m, *frac, *od);
643
644 if (meson_hdmi_pll_validate_params(priv, *m, *frac))
645 return true;
646 }
647
648 return false;
649}
650
651/* pll_freq is the frequency after the OD dividers */
652bool meson_vclk_dmt_supported_freq(struct meson_vpu_priv *priv,
653 unsigned int freq)
654{
655 unsigned int od, m, frac;
656
657 /* In DMT mode, path after PLL is always /10 */
658 freq *= 10;
659
660 if (meson_hdmi_pll_find_params(priv, freq, &m, &frac, &od))
661 return true;
662
663 return false;
664}
665
666/* pll_freq is the frequency after the OD dividers */
667static void meson_hdmi_pll_generic_set(struct meson_vpu_priv *priv,
668 unsigned int pll_freq)
669{
670 unsigned int od, m, frac, od1, od2, od3;
671
672 if (meson_hdmi_pll_find_params(priv, pll_freq, &m, &frac, &od)) {
673 od3 = 1;
674 if (od < 4) {
675 od1 = 2;
676 od2 = 1;
677 } else {
678 od2 = od / 4;
679 od1 = od / od2;
680 }
681
682 debug("PLL params for %dkHz: m=%x frac=%x od=%d/%d/%d\n",
683 pll_freq, m, frac, od1, od2, od3);
684
685 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
686
687 return;
688 }
689
690 printf("Fatal, unable to find parameters for PLL freq %d\n",
691 pll_freq);
692}
693
694static void
695meson_vclk_set(struct meson_vpu_priv *priv, unsigned int pll_base_freq,
696 unsigned int od1, unsigned int od2, unsigned int od3,
697 unsigned int vid_pll_div, unsigned int vclk_div,
698 unsigned int hdmi_tx_div, unsigned int venc_div,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200699 bool hdmi_use_enci, bool vic_alternate_clock)
Neil Armstrongadd986c2018-07-24 17:45:28 +0200700{
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200701 unsigned int m = 0, frac = 0;
702
Neil Armstrongadd986c2018-07-24 17:45:28 +0200703 /* Set HDMI-TX sys clock */
704 hhi_update_bits(HHI_HDMI_CLK_CNTL,
705 CTS_HDMI_SYS_SEL_MASK, 0);
706 hhi_update_bits(HHI_HDMI_CLK_CNTL,
707 CTS_HDMI_SYS_DIV_MASK, 0);
708 hhi_update_bits(HHI_HDMI_CLK_CNTL,
709 CTS_HDMI_SYS_EN, CTS_HDMI_SYS_EN);
710
711 /* Set HDMI PLL rate */
712 if (!od1 && !od2 && !od3) {
713 meson_hdmi_pll_generic_set(priv, pll_base_freq);
714 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXBB)) {
715 switch (pll_base_freq) {
716 case 2970000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200717 m = 0x3d;
718 frac = vic_alternate_clock ? 0xd02 : 0xe00;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200719 break;
720 case 4320000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200721 m = vic_alternate_clock ? 0x59 : 0x5a;
722 frac = vic_alternate_clock ? 0xe8f : 0;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200723 break;
724 case 5940000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200725 m = 0x7b;
726 frac = vic_alternate_clock ? 0xa05 : 0xc00;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200727 break;
728 }
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200729
730 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200731 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXM) ||
732 meson_vpu_is_compatible(priv, VPU_COMPATIBLE_GXL)) {
733 switch (pll_base_freq) {
734 case 2970000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200735 m = 0x7b;
736 frac = vic_alternate_clock ? 0x281 : 0x300;
737 break;
738 case 4320000:
739 m = vic_alternate_clock ? 0xb3 : 0xb4;
740 frac = vic_alternate_clock ? 0x347 : 0;
741 break;
742 case 5940000:
743 m = 0xf7;
744 frac = vic_alternate_clock ? 0x102 : 0x200;
745 break;
746 }
747
748 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
749 } else if (meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
750 switch (pll_base_freq) {
751 case 2970000:
752 m = 0x7b;
753 frac = vic_alternate_clock ? 0x140b4 : 0x18000;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200754 break;
755 case 4320000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200756 m = vic_alternate_clock ? 0xb3 : 0xb4;
757 frac = vic_alternate_clock ? 0x1a3ee : 0;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200758 break;
759 case 5940000:
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200760 m = 0xf7;
761 frac = vic_alternate_clock ? 0x8148 : 0x10000;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200762 break;
763 }
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200764
765 meson_hdmi_pll_set_params(priv, m, frac, od1, od2, od3);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200766 }
767
768 /* Setup vid_pll divider */
769 meson_vid_pll_set(priv, vid_pll_div);
770
771 /* Set VCLK div */
772 hhi_update_bits(HHI_VID_CLK_CNTL,
773 VCLK_SEL_MASK, 0);
774 hhi_update_bits(HHI_VID_CLK_DIV,
775 VCLK_DIV_MASK, vclk_div - 1);
776
777 /* Set HDMI-TX source */
778 switch (hdmi_tx_div) {
779 case 1:
780 /* enable vclk_div1 gate */
781 hhi_update_bits(HHI_VID_CLK_CNTL,
782 VCLK_DIV1_EN, VCLK_DIV1_EN);
783
784 /* select vclk_div1 for HDMI-TX */
785 hhi_update_bits(HHI_HDMI_CLK_CNTL,
786 HDMI_TX_PIXEL_SEL_MASK, 0);
787 break;
788 case 2:
789 /* enable vclk_div2 gate */
790 hhi_update_bits(HHI_VID_CLK_CNTL,
791 VCLK_DIV2_EN, VCLK_DIV2_EN);
792
793 /* select vclk_div2 for HDMI-TX */
794 hhi_update_bits(HHI_HDMI_CLK_CNTL,
795 HDMI_TX_PIXEL_SEL_MASK,
796 1 << HDMI_TX_PIXEL_SEL_SHIFT);
797 break;
798 case 4:
799 /* enable vclk_div4 gate */
800 hhi_update_bits(HHI_VID_CLK_CNTL,
801 VCLK_DIV4_EN, VCLK_DIV4_EN);
802
803 /* select vclk_div4 for HDMI-TX */
804 hhi_update_bits(HHI_HDMI_CLK_CNTL,
805 HDMI_TX_PIXEL_SEL_MASK,
806 2 << HDMI_TX_PIXEL_SEL_SHIFT);
807 break;
808 case 6:
809 /* enable vclk_div6 gate */
810 hhi_update_bits(HHI_VID_CLK_CNTL,
811 VCLK_DIV6_EN, VCLK_DIV6_EN);
812
813 /* select vclk_div6 for HDMI-TX */
814 hhi_update_bits(HHI_HDMI_CLK_CNTL,
815 HDMI_TX_PIXEL_SEL_MASK,
816 3 << HDMI_TX_PIXEL_SEL_SHIFT);
817 break;
818 case 12:
819 /* enable vclk_div12 gate */
820 hhi_update_bits(HHI_VID_CLK_CNTL,
821 VCLK_DIV12_EN, VCLK_DIV12_EN);
822
823 /* select vclk_div12 for HDMI-TX */
824 hhi_update_bits(HHI_HDMI_CLK_CNTL,
825 HDMI_TX_PIXEL_SEL_MASK,
826 4 << HDMI_TX_PIXEL_SEL_SHIFT);
827 break;
828 }
829 hhi_update_bits(HHI_VID_CLK_CNTL2,
830 HDMI_TX_PIXEL_EN, HDMI_TX_PIXEL_EN);
831
832 /* Set ENCI/ENCP Source */
833 switch (venc_div) {
834 case 1:
835 /* enable vclk_div1 gate */
836 hhi_update_bits(HHI_VID_CLK_CNTL,
837 VCLK_DIV1_EN, VCLK_DIV1_EN);
838
839 if (hdmi_use_enci)
840 /* select vclk_div1 for enci */
841 hhi_update_bits(HHI_VID_CLK_DIV,
842 CTS_ENCI_SEL_MASK, 0);
843 else
844 /* select vclk_div1 for encp */
845 hhi_update_bits(HHI_VID_CLK_DIV,
846 CTS_ENCP_SEL_MASK, 0);
847 break;
848 case 2:
849 /* enable vclk_div2 gate */
850 hhi_update_bits(HHI_VID_CLK_CNTL,
851 VCLK_DIV2_EN, VCLK_DIV2_EN);
852
853 if (hdmi_use_enci)
854 /* select vclk_div2 for enci */
855 hhi_update_bits(HHI_VID_CLK_DIV,
856 CTS_ENCI_SEL_MASK,
857 1 << CTS_ENCI_SEL_SHIFT);
858 else
859 /* select vclk_div2 for encp */
860 hhi_update_bits(HHI_VID_CLK_DIV,
861 CTS_ENCP_SEL_MASK,
862 1 << CTS_ENCP_SEL_SHIFT);
863 break;
864 case 4:
865 /* enable vclk_div4 gate */
866 hhi_update_bits(HHI_VID_CLK_CNTL,
867 VCLK_DIV4_EN, VCLK_DIV4_EN);
868
869 if (hdmi_use_enci)
870 /* select vclk_div4 for enci */
871 hhi_update_bits(HHI_VID_CLK_DIV,
872 CTS_ENCI_SEL_MASK,
873 2 << CTS_ENCI_SEL_SHIFT);
874 else
875 /* select vclk_div4 for encp */
876 hhi_update_bits(HHI_VID_CLK_DIV,
877 CTS_ENCP_SEL_MASK,
878 2 << CTS_ENCP_SEL_SHIFT);
879 break;
880 case 6:
881 /* enable vclk_div6 gate */
882 hhi_update_bits(HHI_VID_CLK_CNTL,
883 VCLK_DIV6_EN, VCLK_DIV6_EN);
884
885 if (hdmi_use_enci)
886 /* select vclk_div6 for enci */
887 hhi_update_bits(HHI_VID_CLK_DIV,
888 CTS_ENCI_SEL_MASK,
889 3 << CTS_ENCI_SEL_SHIFT);
890 else
891 /* select vclk_div6 for encp */
892 hhi_update_bits(HHI_VID_CLK_DIV,
893 CTS_ENCP_SEL_MASK,
894 3 << CTS_ENCP_SEL_SHIFT);
895 break;
896 case 12:
897 /* enable vclk_div12 gate */
898 hhi_update_bits(HHI_VID_CLK_CNTL,
899 VCLK_DIV12_EN, VCLK_DIV12_EN);
900
901 if (hdmi_use_enci)
902 /* select vclk_div12 for enci */
903 hhi_update_bits(HHI_VID_CLK_DIV,
904 CTS_ENCI_SEL_MASK,
905 4 << CTS_ENCI_SEL_SHIFT);
906 else
907 /* select vclk_div12 for encp */
908 hhi_update_bits(HHI_VID_CLK_DIV,
909 CTS_ENCP_SEL_MASK,
910 4 << CTS_ENCP_SEL_SHIFT);
911 break;
912 }
913
914 if (hdmi_use_enci)
915 /* Enable ENCI clock gate */
916 hhi_update_bits(HHI_VID_CLK_CNTL2,
917 CTS_ENCI_EN, CTS_ENCI_EN);
918 else
919 /* Enable ENCP clock gate */
920 hhi_update_bits(HHI_VID_CLK_CNTL2,
921 CTS_ENCP_EN, CTS_ENCP_EN);
922
923 hhi_update_bits(HHI_VID_CLK_CNTL, VCLK_EN, VCLK_EN);
924}
925
926static void meson_vclk_setup(struct meson_vpu_priv *priv, unsigned int target,
927 unsigned int vclk_freq, unsigned int venc_freq,
928 unsigned int dac_freq, bool hdmi_use_enci)
929{
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200930 bool vic_alternate_clock = false;
Neil Armstrongadd986c2018-07-24 17:45:28 +0200931 unsigned int freq;
932 unsigned int hdmi_tx_div;
933 unsigned int venc_div;
934
935 if (target == MESON_VCLK_TARGET_CVBS) {
936 meson_venci_cvbs_clock_config(priv);
937 return;
938 } else if (target == MESON_VCLK_TARGET_DMT) {
939 /* The DMT clock path is fixed after the PLL:
940 * - automatic PLL freq + OD management
941 * - vid_pll_div = VID_PLL_DIV_5
942 * - vclk_div = 2
943 * - hdmi_tx_div = 1
944 * - venc_div = 1
945 * - encp encoder
946 */
947 meson_vclk_set(priv, vclk_freq * 10, 0, 0, 0,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200948 VID_PLL_DIV_5, 2, 1, 1, false, false);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200949 return;
950 }
951
952 hdmi_tx_div = vclk_freq / dac_freq;
953
954 if (hdmi_tx_div == 0) {
955 printf("Fatal Error, invalid HDMI-TX freq %d\n",
956 dac_freq);
957 return;
958 }
959
960 venc_div = vclk_freq / venc_freq;
961
962 if (venc_div == 0) {
963 printf("Fatal Error, invalid HDMI venc freq %d\n",
964 venc_freq);
965 return;
966 }
967
Neil Armstrong57d6dfe2019-08-30 14:09:24 +0200968 for (freq = 0 ; params[freq].pixel_freq ; ++freq) {
969 if (vclk_freq == params[freq].pixel_freq ||
970 vclk_freq == FREQ_1000_1001(params[freq].pixel_freq)) {
971 if (vclk_freq != params[freq].pixel_freq)
972 vic_alternate_clock = true;
973 else
974 vic_alternate_clock = false;
975
976 if (freq == MESON_VCLK_HDMI_ENCI_54000 &&
977 !hdmi_use_enci)
978 continue;
979
980 if (freq == MESON_VCLK_HDMI_DDR_54000 &&
981 hdmi_use_enci)
982 continue;
983
984 if (freq == MESON_VCLK_HDMI_DDR_148500 &&
985 dac_freq == vclk_freq)
986 continue;
987
988 if (freq == MESON_VCLK_HDMI_148500 &&
989 dac_freq != vclk_freq)
990 continue;
991 break;
992 }
993 }
994
995 if (!params[freq].pixel_freq) {
996 pr_err("Fatal Error, invalid HDMI vclk freq %d\n", vclk_freq);
Neil Armstrongadd986c2018-07-24 17:45:28 +0200997 return;
998 }
999
1000 meson_vclk_set(priv, params[freq].pll_base_freq,
1001 params[freq].pll_od1, params[freq].pll_od2,
1002 params[freq].pll_od3, params[freq].vid_pll_div,
1003 params[freq].vclk_div, hdmi_tx_div, venc_div,
Neil Armstrong57d6dfe2019-08-30 14:09:24 +02001004 hdmi_use_enci, vic_alternate_clock);
Neil Armstrongadd986c2018-07-24 17:45:28 +02001005}
1006
1007void meson_vpu_setup_vclk(struct udevice *dev,
1008 const struct display_timing *mode, bool is_cvbs)
1009{
1010 struct meson_vpu_priv *priv = dev_get_priv(dev);
1011 unsigned int vclk_freq;
1012
1013 if (is_cvbs)
1014 return meson_vclk_setup(priv, MESON_VCLK_TARGET_CVBS,
1015 0, 0, 0, false);
1016
1017 vclk_freq = mode->pixelclock.typ / 1000;
1018
1019 return meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT,
1020 vclk_freq, vclk_freq, vclk_freq, false);
1021}