xref: /rk3399_rockchip-uboot/drivers/video/drm/rockchip-inno-hdmi-phy.c (revision 5e8564cf419797f9095431e6eb6f0c00dfa423d2)
1 /*
2  * SPDX-License-Identifier:     GPL-2.0+
3  * (C) Copyright 2008-2016 Fuzhou Rockchip Electronics Co., Ltd
4  */
5 
6 #include <config.h>
7 #include <common.h>
8 #include <errno.h>
9 #include <malloc.h>
10 #include <misc.h>
11 #include <fdtdec.h>
12 #include <fdt_support.h>
13 #include <asm/unaligned.h>
14 #include <dm/device.h>
15 #include <dm/read.h>
16 #include <asm/io.h>
17 #include <linux/list.h>
18 #include <div64.h>
19 #include <linux/media-bus-format.h>
20 
21 #include "rockchip_display.h"
22 #include "rockchip_crtc.h"
23 #include "rockchip_phy.h"
24 
25 #define INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT	1000
26 #define UPDATE(x, h, l)	(((x) << (l)) & GENMASK((h), (l)))
27 
28 /* REG: 0x00 */
29 #define PRE_PLL_REFCLK_SEL_MASK			BIT(0)
30 #define PRE_PLL_REFCLK_SEL_PCLK			BIT(0)
31 #define PRE_PLL_REFCLK_SEL_OSCCLK		0
32 /* REG: 0x01 */
33 #define BYPASS_RXSENSE_EN_MASK			BIT(2)
34 #define BYPASS_RXSENSE_EN			BIT(2)
35 #define BYPASS_PWRON_EN_MASK			BIT(1)
36 #define BYPASS_PWRON_EN				BIT(1)
37 #define BYPASS_PLLPD_EN_MASK			BIT(0)
38 #define BYPASS_PLLPD_EN				BIT(0)
39 /* REG: 0x02 */
40 #define BYPASS_PDATA_EN_MASK			BIT(4)
41 #define BYPASS_PDATA_EN				BIT(4)
42 #define PDATAEN_MASK				BIT(0)
43 #define PDATAEN_DISABLE				BIT(0)
44 #define PDATAEN_ENABLE				0
45 /* REG: 0x03 */
46 #define BYPASS_AUTO_TERM_RES_CAL		BIT(7)
47 #define AUDO_TERM_RES_CAL_SPEED_14_8(x)		UPDATE(x, 6, 0)
48 /* REG: 0x04 */
49 #define AUDO_TERM_RES_CAL_SPEED_7_0(x)		UPDATE(x, 7, 0)
50 /* REG: 0xaa */
51 #define POST_PLL_CTRL_MASK			BIT(0)
52 #define POST_PLL_CTRL_MANUAL			BIT(0)
53 /* REG: 0xe0 */
54 #define POST_PLL_POWER_MASK			BIT(5)
55 #define POST_PLL_POWER_DOWN			BIT(5)
56 #define POST_PLL_POWER_UP			0
57 #define PRE_PLL_POWER_MASK			BIT(4)
58 #define PRE_PLL_POWER_DOWN			BIT(4)
59 #define PRE_PLL_POWER_UP			0
60 #define RXSENSE_CLK_CH_MASK			BIT(3)
61 #define RXSENSE_CLK_CH_ENABLE			BIT(3)
62 #define RXSENSE_DATA_CH2_MASK			BIT(2)
63 #define RXSENSE_DATA_CH2_ENABLE			BIT(2)
64 #define RXSENSE_DATA_CH1_MASK			BIT(1)
65 #define RXSENSE_DATA_CH1_ENABLE			BIT(1)
66 #define RXSENSE_DATA_CH0_MASK			BIT(0)
67 #define RXSENSE_DATA_CH0_ENABLE			BIT(0)
68 /* REG: 0xe1 */
69 #define BANDGAP_MASK				BIT(4)
70 #define BANDGAP_ENABLE				BIT(4)
71 #define BANDGAP_DISABLE				0
72 #define TMDS_DRIVER_MASK			GENMASK(3, 0)
73 #define TMDS_DRIVER_ENABLE			UPDATE(0xf, 3, 0)
74 #define TMDS_DRIVER_DISABLE			0
75 /* REG: 0xe2 */
76 #define PRE_PLL_FB_DIV_8_MASK			BIT(7)
77 #define PRE_PLL_FB_DIV_8_SHIFT			7
78 #define PRE_PLL_FB_DIV_8(x)			UPDATE(x, 7, 7)
79 #define PCLK_VCO_DIV_5_MASK			BIT(5)
80 #define PCLK_VCO_DIV_5_SHIFT			5
81 #define PCLK_VCO_DIV_5(x)			UPDATE(x, 5, 5)
82 #define PRE_PLL_PRE_DIV_MASK			GENMASK(4, 0)
83 #define PRE_PLL_PRE_DIV(x)			UPDATE(x, 4, 0)
84 /* REG: 0xe3 */
85 #define PRE_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
86 /* REG: 0xe4 */
87 #define PRE_PLL_PCLK_DIV_B_MASK			GENMASK(6, 5)
88 #define PRE_PLL_PCLK_DIV_B_SHIFT		5
89 #define PRE_PLL_PCLK_DIV_B(x)			UPDATE(x, 6, 5)
90 #define PRE_PLL_PCLK_DIV_A_MASK			GENMASK(4, 0)
91 #define PRE_PLL_PCLK_DIV_A_SHIFT		0
92 #define PRE_PLL_PCLK_DIV_A(x)			UPDATE(x, 4, 0)
93 /* REG: 0xe5 */
94 #define PRE_PLL_PCLK_DIV_C_MASK			GENMASK(6, 5)
95 #define PRE_PLL_PCLK_DIV_C_SHIFT		5
96 #define PRE_PLL_PCLK_DIV_C(x)			UPDATE(x, 6, 5)
97 #define PRE_PLL_PCLK_DIV_D_MASK			GENMASK(4, 0)
98 #define PRE_PLL_PCLK_DIV_D_SHIFT		0
99 #define PRE_PLL_PCLK_DIV_D(x)			UPDATE(x, 4, 0)
100 /* REG: 0xe6 */
101 #define PRE_PLL_TMDSCLK_DIV_C_MASK		GENMASK(5, 4)
102 #define PRE_PLL_TMDSCLK_DIV_C(x)		UPDATE(x, 5, 4)
103 #define PRE_PLL_TMDSCLK_DIV_A_MASK		GENMASK(3, 2)
104 #define PRE_PLL_TMDSCLK_DIV_A(x)		UPDATE(x, 3, 2)
105 #define PRE_PLL_TMDSCLK_DIV_B_MASK		GENMASK(1, 0)
106 #define PRE_PLL_TMDSCLK_DIV_B(x)		UPDATE(x, 1, 0)
107 /* REG: 0xe8 */
108 #define PRE_PLL_LOCK_STATUS			BIT(0)
109 /* REG: 0xe9 */
110 #define POST_PLL_POST_DIV_EN_MASK		GENMASK(7, 6)
111 #define POST_PLL_POST_DIV_ENABLE		UPDATE(3, 7, 6)
112 #define POST_PLL_POST_DIV_DISABLE		0
113 #define POST_PLL_PRE_DIV_MASK			GENMASK(4, 0)
114 #define POST_PLL_PRE_DIV(x)			UPDATE(x, 4, 0)
115 /* REG: 0xea */
116 #define POST_PLL_FB_DIV_7_0(x)			UPDATE(x, 7, 0)
117 /* REG: 0xeb */
118 #define POST_PLL_FB_DIV_8_MASK			BIT(7)
119 #define POST_PLL_FB_DIV_8(x)			UPDATE(x, 7, 7)
120 #define POST_PLL_POST_DIV_MASK			GENMASK(5, 4)
121 #define POST_PLL_POST_DIV(x)			UPDATE(x, 5, 4)
122 #define POST_PLL_LOCK_STATUS			BIT(0)
123 /* REG: 0xee */
124 #define TMDS_CH_TA_MASK				GENMASK(7, 4)
125 #define TMDS_CH_TA_ENABLE			UPDATE(0xf, 7, 4)
126 #define TMDS_CH_TA_DISABLE			0
127 /* REG: 0xef */
128 #define TMDS_CLK_CH_TA(x)			UPDATE(x, 7, 6)
129 #define TMDS_DATA_CH2_TA(x)			UPDATE(x, 5, 4)
130 #define TMDS_DATA_CH1_TA(x)			UPDATE(x, 3, 2)
131 #define TMDS_DATA_CH0_TA(x)			UPDATE(x, 1, 0)
132 /* REG: 0xf0 */
133 #define TMDS_DATA_CH2_PRE_EMPHASIS_MASK		GENMASK(5, 4)
134 #define TMDS_DATA_CH2_PRE_EMPHASIS(x)		UPDATE(x, 5, 4)
135 #define TMDS_DATA_CH1_PRE_EMPHASIS_MASK		GENMASK(3, 2)
136 #define TMDS_DATA_CH1_PRE_EMPHASIS(x)		UPDATE(x, 3, 2)
137 #define TMDS_DATA_CH0_PRE_EMPHASIS_MASK		GENMASK(1, 0)
138 #define TMDS_DATA_CH0_PRE_EMPHASIS(x)		UPDATE(x, 1, 0)
139 /* REG: 0xf1 */
140 #define TMDS_CLK_CH_OUTPUT_SWING(x)		UPDATE(x, 7, 4)
141 #define TMDS_DATA_CH2_OUTPUT_SWING(x)		UPDATE(x, 3, 0)
142 /* REG: 0xf2 */
143 #define TMDS_DATA_CH1_OUTPUT_SWING(x)		UPDATE(x, 7, 4)
144 #define TMDS_DATA_CH0_OUTPUT_SWING(x)		UPDATE(x, 3, 0)
145 
146 enum inno_hdmi_phy_type {
147 	INNO_HDMI_PHY_RK3228,
148 	INNO_HDMI_PHY_RK3328
149 };
150 
151 struct inno_hdmi_phy_drv_data;
152 
153 struct phy_config {
154 	unsigned long	tmdsclock;
155 	u8		regs[14];
156 };
157 
158 struct inno_hdmi_phy {
159 	struct udevice *dev;
160 	ofnode node;
161 	void *regs;
162 
163 	/* platform data */
164 	const struct inno_hdmi_phy_drv_data *plat_data;
165 	unsigned long pixclock;
166 	u32 bus_width;
167 	struct phy_config *phy_cfg;
168 };
169 
170 struct pre_pll_config {
171 	unsigned long pixclock;
172 	unsigned long tmdsclock;
173 	u8 prediv;
174 	u16 fbdiv;
175 	u8 tmds_div_a;
176 	u8 tmds_div_b;
177 	u8 tmds_div_c;
178 	u8 pclk_div_a;
179 	u8 pclk_div_b;
180 	u8 pclk_div_c;
181 	u8 pclk_div_d;
182 	u8 vco_div_5_en;
183 	u32 fracdiv;
184 };
185 
186 struct post_pll_config {
187 	unsigned long tmdsclock;
188 	u8 prediv;
189 	u16 fbdiv;
190 	u8 postdiv;
191 	u8 version;
192 };
193 
194 struct inno_hdmi_phy_ops {
195 	void (*init)(struct inno_hdmi_phy *inno);
196 	int (*power_on)(struct inno_hdmi_phy *inno,
197 			const struct post_pll_config *cfg,
198 			const struct phy_config *phy_cfg);
199 	void (*power_off)(struct inno_hdmi_phy *inno);
200 	int (*pre_pll_update)(struct inno_hdmi_phy *inno,
201 			      const struct pre_pll_config *cfg);
202 	unsigned long (*recalc_rate)(struct inno_hdmi_phy *inno,
203 				     unsigned long parent_rate);
204 };
205 
206 struct inno_hdmi_phy_drv_data {
207 	enum inno_hdmi_phy_type		dev_type;
208 	const struct inno_hdmi_phy_ops	*ops;
209 	const struct phy_config		*phy_cfg_table;
210 };
211 
212 struct rockchip_inno_data {
213 	char compatible[30];
214 	const void *data;
215 };
216 
217 static const struct pre_pll_config pre_pll_cfg_table[] = {
218 	{ 27000000,  27000000, 1,  90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
219 	{ 27000000,  33750000, 1,  90, 1, 3, 3, 10, 3, 3, 4, 0, 0},
220 	{ 40000000,  40000000, 1,  80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
221 	{ 59341000,  59341000, 1,  98, 3, 1, 2,  1, 3, 3, 4, 0, 0xE6AE6B},
222 	{ 59400000,  59400000, 1,  99, 3, 1, 1,  1, 3, 3, 4, 0, 0},
223 	{ 59341000,  74176250, 1,  98, 0, 3, 3,  1, 3, 3, 4, 0, 0xE6AE6B},
224 	{ 59400000,  74250000, 1,  99, 1, 2, 2,  1, 3, 3, 4, 0, 0},
225 	{ 74176000,  74176000, 1,  98, 1, 2, 2,  1, 2, 3, 4, 0, 0xE6AE6B},
226 	{ 74250000,  74250000, 1,  99, 1, 2, 2,  1, 2, 3, 4, 0, 0},
227 	{ 74176000,  92720000, 4, 494, 1, 2, 2,  1, 3, 3, 4, 0, 0x816817},
228 	{ 74250000,  92812500, 4, 495, 1, 2, 2,  1, 3, 3, 4, 0, 0},
229 	{148352000, 148352000, 1,  98, 1, 1, 1,  1, 2, 2, 2, 0, 0xE6AE6B},
230 	{148500000, 148500000, 1,  99, 1, 1, 1,  1, 2, 2, 2, 0, 0},
231 	{148352000, 185440000, 4, 494, 0, 2, 2,  1, 3, 2, 2, 0, 0x816817},
232 	{148500000, 185625000, 4, 495, 0, 2, 2,  1, 3, 2, 2, 0, 0},
233 	{296703000, 296703000, 1,  98, 0, 1, 1,  1, 0, 2, 2, 0, 0xE6AE6B},
234 	{297000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2, 2, 0, 0},
235 	{296703000, 370878750, 4, 494, 1, 2, 0,  1, 3, 1, 1, 0, 0x816817},
236 	{297000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 0, 0},
237 	{593407000, 296703500, 1,  98, 0, 1, 1,  1, 0, 2, 1, 0, 0xE6AE6B},
238 	{594000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2, 1, 0, 0},
239 	{593407000, 370879375, 4, 494, 1, 2, 0,  1, 3, 1, 1, 1, 0x816817},
240 	{594000000, 371250000, 4, 495, 1, 2, 0,  1, 3, 1, 1, 1, 0},
241 	{593407000, 593407000, 1,  98, 0, 2, 0,  1, 0, 1, 1, 0, 0xE6AE6B},
242 	{594000000, 594000000, 1,  99, 0, 2, 0,  1, 0, 1, 1, 0, 0},
243 	{     ~0UL,	    0, 0,   0, 0, 0, 0,  0, 0, 0, 0, 0, 0}
244 };
245 
246 static const struct post_pll_config post_pll_cfg_table[] = {
247 	{33750000,  1, 40, 8, 1},
248 	{33750000,  1, 80, 8, 2},
249 	{33750000,  1, 10, 2, 4},
250 	{74250000,  1, 40, 8, 1},
251 	{74250000, 18, 80, 8, 2},
252 	{148500000, 2, 40, 4, 3},
253 	{297000000, 4, 40, 2, 3},
254 	{594000000, 8, 40, 1, 3},
255 	{     ~0UL, 0,  0, 0, 0}
256 };
257 
258 static const struct phy_config rk3228_phy_cfg[] = {
259 	{	165000000, {
260 			0xaa, 0x00, 0x44, 0x44, 0x00, 0x00, 0x00, 0x00, 0x00,
261 			0x00, 0x00, 0x00, 0x00, 0x00,
262 		},
263 	}, {
264 		340000000, {
265 			0xaa, 0x15, 0x6a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
266 			0x00, 0x00, 0x00, 0x00, 0x00,
267 		},
268 	}, {
269 		594000000, {
270 			0xaa, 0x15, 0x7a, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00,
271 			0x00, 0x00, 0x00, 0x00, 0x00,
272 		},
273 	}, {
274 		~0UL, {
275 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
276 			0x00, 0x00, 0x00, 0x00, 0x00,
277 		},
278 	}
279 };
280 
281 static const struct phy_config rk3328_phy_cfg[] = {
282 	{	165000000, {
283 			0x07, 0x08, 0x08, 0x08, 0x00, 0x00, 0x08, 0x08, 0x08,
284 			0x00, 0xac, 0xcc, 0xcc, 0xcc,
285 		},
286 	}, {
287 		340000000, {
288 			0x0b, 0x0d, 0x0d, 0x0d, 0x07, 0x15, 0x08, 0x08, 0x08,
289 			0x3f, 0xac, 0xcc, 0xcd, 0xdd,
290 		},
291 	}, {
292 		594000000, {
293 			0x10, 0x1a, 0x1a, 0x1a, 0x07, 0x15, 0x08, 0x08, 0x08,
294 			0x00, 0xac, 0xcc, 0xcc, 0xcc,
295 		},
296 	}, {
297 		~0UL, {
298 			0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
299 			0x00, 0x00, 0x00, 0x00, 0x00,
300 		},
301 	}
302 };
303 
304 static inline void inno_write(struct inno_hdmi_phy *inno, u32 reg, u8 val)
305 {
306 	writel(val, inno->regs + (reg * 4));
307 }
308 
309 static inline u8 inno_read(struct inno_hdmi_phy *inno, u32 reg)
310 {
311 	u32 val;
312 
313 	val = readl(inno->regs + (reg * 4));
314 
315 	return val;
316 }
317 
318 static inline void inno_update_bits(struct inno_hdmi_phy *inno, u8 reg,
319 				    u8 mask, u8 val)
320 {
321 	u32 tmp, orig;
322 
323 	orig = inno_read(inno, reg);
324 	tmp = orig & ~mask;
325 	tmp |= val & mask;
326 	inno_write(inno, reg, tmp);
327 }
328 
329 static u32 inno_hdmi_phy_get_tmdsclk(struct inno_hdmi_phy *inno,
330 				     unsigned long rate)
331 {
332 	u32 tmdsclk;
333 
334 	switch (inno->bus_width) {
335 	case 4:
336 		tmdsclk = (u32)rate / 2;
337 		break;
338 	case 5:
339 		tmdsclk = (u32)rate * 5 / 8;
340 		break;
341 	case 6:
342 		tmdsclk = (u32)rate * 3 / 4;
343 		break;
344 	case 10:
345 		tmdsclk = (u32)rate * 5 / 4;
346 		break;
347 	case 12:
348 		tmdsclk = (u32)rate * 3 / 2;
349 		break;
350 	case 16:
351 		tmdsclk = (u32)rate * 2;
352 		break;
353 	default:
354 		tmdsclk = rate;
355 	}
356 
357 	return tmdsclk;
358 }
359 
360 static u8 rk_get_cpu_version(void)
361 {
362 	u8 val = 0;
363 #ifdef CONFIG_ROCKCHIP_EFUSE
364 	struct udevice *dev;
365 	u32 regs[2] = {0};
366 	u8 fuses[1];
367 	ofnode node;
368 	int ret;
369 
370 	ret = uclass_get_device_by_driver(UCLASS_MISC,
371 					  DM_GET_DRIVER(rockchip_efuse), &dev);
372 	if (ret) {
373 		printf("%s: no misc-device found\n", __func__);
374 		return -EINVAL;
375 	}
376 
377 	node = dev_read_subnode(dev, "cpu-version");
378 	if (!ofnode_valid(node))
379 		return -EINVAL;
380 
381 	ret = ofnode_read_u32_array(node, "reg", regs, 2);
382 	if (ret) {
383 		printf("Cannot get efuse reg\n");
384 		return -EINVAL;
385 	}
386 
387 	ret = misc_read(dev, regs[0], &fuses, regs[1]);
388 	if (ret) {
389 		printf("%s: misc_read failed\n", __func__);
390 		return 0;
391 	}
392 
393 	val = fuses[0];
394 	val = (val >> 3) & 0x1;
395 #endif
396 	return val;
397 }
398 
399 static int inno_hdmi_phy_power_on(struct rockchip_phy *phy)
400 {
401 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
402 	const struct post_pll_config *cfg = post_pll_cfg_table;
403 	const struct phy_config *phy_cfg = inno->plat_data->phy_cfg_table;
404 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, inno->pixclock);
405 	u32 chipversion = 1;
406 
407 	printf("start Inno HDMI PHY Power On\n");
408 
409 	if (inno->phy_cfg)
410 		phy_cfg = inno->phy_cfg;
411 
412 	if (!tmdsclock) {
413 		printf("TMDS clock is zero!\n");
414 		return -EINVAL;
415 	}
416 
417 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3328 &&
418 	    rk_get_cpu_version())
419 		chipversion = 2;
420 	else if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 &&
421 		 tmdsclock <= 33750000)
422 		chipversion = 4;
423 
424 	printf("tmdsclock = %d; chipversion = %d\n", tmdsclock, chipversion);
425 
426 	for (; cfg->tmdsclock != ~0UL; cfg++)
427 		if (tmdsclock <= cfg->tmdsclock &&
428 		    cfg->version & chipversion)
429 			break;
430 
431 	for (; phy_cfg->tmdsclock != ~0UL; phy_cfg++)
432 		if (tmdsclock <= phy_cfg->tmdsclock)
433 			break;
434 
435 	if (cfg->tmdsclock == ~0UL || phy_cfg->tmdsclock == ~0UL)
436 		return -EINVAL;
437 
438 	printf("Inno HDMI PHY Power On\n");
439 	if (inno->plat_data->ops->power_on)
440 		return inno->plat_data->ops->power_on(inno, cfg, phy_cfg);
441 	else
442 		return -EINVAL;
443 }
444 
445 static int inno_hdmi_phy_power_off(struct rockchip_phy *phy)
446 {
447 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
448 
449 	if (inno->plat_data->ops->power_off)
450 		inno->plat_data->ops->power_off(inno);
451 	printf("Inno HDMI PHY Power Off\n");
452 
453 	return 0;
454 }
455 
456 static int inno_hdmi_phy_clk_is_prepared(struct inno_hdmi_phy *inno)
457 {
458 	u8 status;
459 
460 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
461 		status = inno_read(inno, 0xe0) & PRE_PLL_POWER_MASK;
462 	else
463 		status = inno_read(inno, 0xa0) & 1;
464 
465 	return status ? 0 : 1;
466 }
467 
468 static int inno_hdmi_phy_clk_prepare(struct inno_hdmi_phy *inno)
469 {
470 	if (inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228)
471 		inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK,
472 				 PRE_PLL_POWER_UP);
473 	else
474 		inno_update_bits(inno, 0xa0, 1, 0);
475 
476 	return 0;
477 }
478 
479 static int inno_hdmi_phy_clk_set_rate(struct inno_hdmi_phy *inno,
480 				      unsigned long rate)
481 {
482 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
483 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
484 
485 	for (; cfg->pixclock != ~0UL; cfg++)
486 		if (cfg->pixclock == rate && cfg->tmdsclock == tmdsclock)
487 			break;
488 
489 	if (cfg->pixclock == ~0UL) {
490 		printf("unsupported rate %lu\n", rate);
491 		return -EINVAL;
492 	}
493 
494 	if (inno->plat_data->ops->pre_pll_update)
495 		inno->plat_data->ops->pre_pll_update(inno, cfg);
496 
497 	inno->pixclock = rate;
498 
499 	return 0;
500 }
501 
502 static void inno_hdmi_phy_rk3228_init(struct inno_hdmi_phy *inno)
503 {
504 	u32 m, v;
505 
506 	/*
507 	 * Use phy internal register control
508 	 * rxsense/poweron/pllpd/pdataen signal.
509 	 */
510 	m = BYPASS_RXSENSE_EN_MASK | BYPASS_PWRON_EN_MASK |
511 	    BYPASS_PLLPD_EN_MASK;
512 	v = BYPASS_RXSENSE_EN | BYPASS_PWRON_EN | BYPASS_PLLPD_EN;
513 	inno_update_bits(inno, 0x01, m, v);
514 	inno_update_bits(inno, 0x02, BYPASS_PDATA_EN_MASK, BYPASS_PDATA_EN);
515 
516 	/* manual power down post-PLL */
517 	inno_update_bits(inno, 0xaa, POST_PLL_CTRL_MASK, POST_PLL_CTRL_MANUAL);
518 }
519 
520 static int
521 inno_hdmi_phy_rk3228_power_on(struct inno_hdmi_phy *inno,
522 			      const struct post_pll_config *cfg,
523 			      const struct phy_config *phy_cfg)
524 {
525 	int pll_tries;
526 	u32 m, v;
527 
528 	/* pdata_en disable */
529 	inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_DISABLE);
530 
531 	/* Power down Post-PLL */
532 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
533 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
534 
535 	/* Post-PLL update */
536 	m = POST_PLL_PRE_DIV_MASK;
537 	v = POST_PLL_PRE_DIV(cfg->prediv);
538 	inno_update_bits(inno, 0xe9, m, v);
539 
540 	m = POST_PLL_FB_DIV_8_MASK;
541 	v = POST_PLL_FB_DIV_8(cfg->fbdiv >> 8);
542 	inno_update_bits(inno, 0xeb, m, v);
543 	inno_write(inno, 0xea, POST_PLL_FB_DIV_7_0(cfg->fbdiv));
544 
545 	if (cfg->postdiv == 1) {
546 		/* Disable Post-PLL post divider */
547 		m = POST_PLL_POST_DIV_EN_MASK;
548 		v = POST_PLL_POST_DIV_DISABLE;
549 		inno_update_bits(inno, 0xe9, m, v);
550 	} else {
551 		/* Enable Post-PLL post divider */
552 		m = POST_PLL_POST_DIV_EN_MASK;
553 		v = POST_PLL_POST_DIV_ENABLE;
554 		inno_update_bits(inno, 0xe9, m, v);
555 
556 		m = POST_PLL_POST_DIV_MASK;
557 		v = POST_PLL_POST_DIV(cfg->postdiv / 2 - 1);
558 		inno_update_bits(inno, 0xeb, m, v);
559 	}
560 
561 	for (v = 0; v < 4; v++)
562 		inno_write(inno, 0xef + v, phy_cfg->regs[v]);
563 
564 	/* Power up Post-PLL */
565 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_UP);
566 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
567 
568 	/* BandGap enable */
569 	inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_ENABLE);
570 
571 	/* TMDS driver enable */
572 	inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_ENABLE);
573 
574 	/* Wait for post PLL lock */
575 	pll_tries = 0;
576 	while (!(inno_read(inno, 0xeb) & POST_PLL_LOCK_STATUS)) {
577 		if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
578 			printf("Post-PLL unlock\n");
579 			return -ETIMEDOUT;
580 		}
581 
582 		pll_tries++;
583 		udelay(100);
584 	}
585 
586 	if (cfg->tmdsclock > 340000000)
587 		mdelay(100);
588 
589 	/* pdata_en enable */
590 	inno_update_bits(inno, 0x02, PDATAEN_MASK, PDATAEN_ENABLE);
591 	return 0;
592 }
593 
594 static void inno_hdmi_phy_rk3228_power_off(struct inno_hdmi_phy *inno)
595 {
596 	/* TMDS driver Disable */
597 	inno_update_bits(inno, 0xe1, TMDS_DRIVER_MASK, TMDS_DRIVER_DISABLE);
598 
599 	/* BandGap Disable */
600 	inno_update_bits(inno, 0xe1, BANDGAP_MASK, BANDGAP_DISABLE);
601 
602 	/* Post-PLL power down */
603 	inno_update_bits(inno, 0xe0, POST_PLL_POWER_MASK, POST_PLL_POWER_DOWN);
604 }
605 
606 static int
607 inno_hdmi_phy_rk3228_pre_pll_update(struct inno_hdmi_phy *inno,
608 				    const struct pre_pll_config *cfg)
609 {
610 	int pll_tries;
611 	u32 m, v;
612 
613 	/* Power down PRE-PLL */
614 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_DOWN);
615 
616 	m = PRE_PLL_FB_DIV_8_MASK | PCLK_VCO_DIV_5_MASK | PRE_PLL_PRE_DIV_MASK;
617 	v = PRE_PLL_FB_DIV_8(cfg->fbdiv >> 8) |
618 	    PCLK_VCO_DIV_5(cfg->vco_div_5_en) | PRE_PLL_PRE_DIV(cfg->prediv);
619 	inno_update_bits(inno, 0xe2, m, v);
620 
621 	inno_write(inno, 0xe3, PRE_PLL_FB_DIV_7_0(cfg->fbdiv));
622 
623 	m = PRE_PLL_PCLK_DIV_B_MASK | PRE_PLL_PCLK_DIV_A_MASK;
624 	v = PRE_PLL_PCLK_DIV_B(cfg->pclk_div_b) |
625 	    PRE_PLL_PCLK_DIV_A(cfg->pclk_div_a);
626 	inno_update_bits(inno, 0xe4, m, v);
627 
628 	m = PRE_PLL_PCLK_DIV_C_MASK | PRE_PLL_PCLK_DIV_D_MASK;
629 	v = PRE_PLL_PCLK_DIV_C(cfg->pclk_div_c) |
630 	    PRE_PLL_PCLK_DIV_D(cfg->pclk_div_d);
631 	inno_update_bits(inno, 0xe5, m, v);
632 
633 	m = PRE_PLL_TMDSCLK_DIV_C_MASK | PRE_PLL_TMDSCLK_DIV_A_MASK |
634 	    PRE_PLL_TMDSCLK_DIV_B_MASK;
635 	v = PRE_PLL_TMDSCLK_DIV_C(cfg->tmds_div_c) |
636 	    PRE_PLL_TMDSCLK_DIV_A(cfg->tmds_div_a) |
637 	    PRE_PLL_TMDSCLK_DIV_B(cfg->tmds_div_b);
638 	inno_update_bits(inno, 0xe6, m, v);
639 
640 	/* Power up PRE-PLL */
641 	inno_update_bits(inno, 0xe0, PRE_PLL_POWER_MASK, PRE_PLL_POWER_UP);
642 
643 	/* Wait for Pre-PLL lock */
644 	pll_tries = 0;
645 	while (!(inno_read(inno, 0xe8) & PRE_PLL_LOCK_STATUS)) {
646 		if (pll_tries == INNO_HDMI_PHY_TIMEOUT_LOOP_COUNT) {
647 			printf("Pre-PLL unlock\n");
648 			return -ETIMEDOUT;
649 		}
650 
651 		pll_tries++;
652 		udelay(100);
653 	}
654 
655 	return 0;
656 }
657 
658 static void inno_hdmi_phy_rk3328_init(struct inno_hdmi_phy *inno)
659 {
660 	/*
661 	 * Use phy internal register control
662 	 * rxsense/poweron/pllpd/pdataen signal.
663 	 */
664 	inno_write(inno, 0x01, 0x07);
665 	inno_write(inno, 0x02, 0x91);
666 }
667 
668 static int
669 inno_hdmi_phy_rk3328_power_on(struct inno_hdmi_phy *inno,
670 			      const struct post_pll_config *cfg,
671 			      const struct phy_config *phy_cfg)
672 {
673 	u32 val;
674 
675 	/* set pdata_en to 0 */
676 	inno_update_bits(inno, 0x02, 1, 0);
677 	/* Power off post PLL */
678 	inno_update_bits(inno, 0xaa, 1, 1);
679 
680 	val = cfg->fbdiv & 0xff;
681 	inno_write(inno, 0xac, val);
682 	if (cfg->postdiv == 1) {
683 		inno_write(inno, 0xaa, 2);
684 		val = (cfg->fbdiv >> 8) | cfg->prediv;
685 		inno_write(inno, 0xab, val);
686 	} else {
687 		val = (cfg->postdiv / 2) - 1;
688 		inno_write(inno, 0xad, val);
689 		val = (cfg->fbdiv >> 8) | cfg->prediv;
690 		inno_write(inno, 0xab, val);
691 		inno_write(inno, 0xaa, 0x0e);
692 	}
693 
694 	for (val = 0; val < 14; val++)
695 		inno_write(inno, 0xb5 + val, phy_cfg->regs[val]);
696 
697 	/* bit[7:6] of reg c8/c9/ca/c8 is ESD detect threshold:
698 	 * 00 - 340mV
699 	 * 01 - 280mV
700 	 * 10 - 260mV
701 	 * 11 - 240mV
702 	 * default is 240mV, now we set it to 340mV
703 	 */
704 	inno_write(inno, 0xc8, 0);
705 	inno_write(inno, 0xc9, 0);
706 	inno_write(inno, 0xca, 0);
707 	inno_write(inno, 0xcb, 0);
708 
709 	if (phy_cfg->tmdsclock > 340000000) {
710 		/* Set termination resistor to 100ohm */
711 		val = 75000000 / 100000;
712 		inno_write(inno, 0xc5, ((val >> 8) & 0xff) | 0x80);
713 		inno_write(inno, 0xc6, val & 0xff);
714 		inno_write(inno, 0xc7, 3 << 1);
715 		inno_write(inno, 0xc5, ((val >> 8) & 0xff));
716 	} else if (phy_cfg->tmdsclock > 165000000) {
717 		inno_write(inno, 0xc5, 0x81);
718 		/* clk termination resistor is 50ohm
719 		 * data termination resistor is 150ohm
720 		 */
721 		inno_write(inno, 0xc8, 0x30);
722 		inno_write(inno, 0xc9, 0x10);
723 		inno_write(inno, 0xca, 0x10);
724 		inno_write(inno, 0xcb, 0x10);
725 	} else {
726 		inno_write(inno, 0xc5, 0x81);
727 	}
728 
729 	/* set TMDS sync detection counter length */
730 	val = 47520000000UL / phy_cfg->tmdsclock;
731 	inno_write(inno, 0xd8, (val >> 8) & 0xff);
732 	inno_write(inno, 0xd9, val & 0xff);
733 
734 	/* Power up post PLL */
735 	inno_update_bits(inno, 0xaa, 1, 0);
736 	/* Power up tmds driver */
737 	inno_update_bits(inno, 0xb0, 4, 4);
738 	inno_write(inno, 0xb2, 0x0f);
739 
740 	/* Wait for post PLL lock */
741 	for (val = 0; val < 5; val++) {
742 		if (inno_read(inno, 0xaf) & 1)
743 			break;
744 		udelay(1000);
745 	}
746 	if (!(inno_read(inno, 0xaf) & 1)) {
747 		printf("HDMI PHY Post PLL unlock\n");
748 		return -ETIMEDOUT;
749 	}
750 	if (phy_cfg->tmdsclock > 340000000)
751 		mdelay(100);
752 	/* set pdata_en to 1 */
753 	inno_update_bits(inno, 0x02, 1, 1);
754 
755 	return 0;
756 }
757 
758 static void inno_hdmi_phy_rk3328_power_off(struct inno_hdmi_phy *inno)
759 {
760 	/* Power off driver */
761 	inno_write(inno, 0xb2, 0);
762 	/* Power off band gap */
763 	inno_update_bits(inno, 0xb0, 4, 0);
764 	/* Power off post pll */
765 	inno_update_bits(inno, 0xaa, 1, 1);
766 }
767 
768 static int
769 inno_hdmi_phy_rk3328_pre_pll_update(struct inno_hdmi_phy *inno,
770 				    const struct pre_pll_config *cfg)
771 {
772 	u32 val;
773 
774 	/* Power off PLL */
775 	inno_update_bits(inno, 0xa0, 1, 1);
776 	/* Configure pre-pll */
777 	inno_update_bits(inno, 0xa0, 2, (cfg->vco_div_5_en & 1) << 1);
778 	inno_write(inno, 0xa1, cfg->prediv);
779 	if (cfg->fracdiv)
780 		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xc0;
781 	else
782 		val = ((cfg->fbdiv >> 8) & 0x0f) | 0xf0;
783 	inno_write(inno, 0xa2, val);
784 	inno_write(inno, 0xa3, cfg->fbdiv & 0xff);
785 	val = (cfg->pclk_div_a & 0x1f) |
786 	      ((cfg->pclk_div_b & 3) << 5);
787 	inno_write(inno, 0xa5, val);
788 	val = (cfg->pclk_div_d & 0x1f) |
789 	      ((cfg->pclk_div_c & 3) << 5);
790 	inno_write(inno, 0xa6, val);
791 	val = ((cfg->tmds_div_a & 3) << 4) |
792 	      ((cfg->tmds_div_b & 3) << 2) |
793 	      (cfg->tmds_div_c & 3);
794 	inno_write(inno, 0xa4, val);
795 
796 	if (cfg->fracdiv) {
797 		val = cfg->fracdiv & 0xff;
798 		inno_write(inno, 0xd3, val);
799 		val = (cfg->fracdiv >> 8) & 0xff;
800 		inno_write(inno, 0xd2, val);
801 		val = (cfg->fracdiv >> 16) & 0xff;
802 		inno_write(inno, 0xd1, val);
803 	} else {
804 		inno_write(inno, 0xd3, 0);
805 		inno_write(inno, 0xd2, 0);
806 		inno_write(inno, 0xd1, 0);
807 	}
808 
809 	/* Power up PLL */
810 	inno_update_bits(inno, 0xa0, 1, 0);
811 
812 	/* Wait for PLL lock */
813 	for (val = 0; val < 5; val++) {
814 		if (inno_read(inno, 0xa9) & 1)
815 			break;
816 		udelay(1000);
817 	}
818 	if (val == 5) {
819 		printf("Pre-PLL unlock\n");
820 		return -ETIMEDOUT;
821 	}
822 
823 	return 0;
824 }
825 
826 static unsigned long
827 inno_hdmi_3328_phy_pll_recalc_rate(struct inno_hdmi_phy *inno,
828 				   unsigned long parent_rate)
829 {
830 	unsigned long rate, vco, frac;
831 	u8 nd, no_a, no_b, no_d;
832 	__maybe_unused u8 no_c;
833 	u16 nf;
834 
835 	nd = inno_read(inno, 0xa1) & 0x3f;
836 	nf = ((inno_read(inno, 0xa2) & 0x0f) << 8) | inno_read(inno, 0xa3);
837 	vco = parent_rate * nf;
838 	if ((inno_read(inno, 0xa2) & 0x30) == 0) {
839 		frac = inno_read(inno, 0xd3) |
840 		       (inno_read(inno, 0xd2) << 8) |
841 		       (inno_read(inno, 0xd1) << 16);
842 		vco += DIV_ROUND_CLOSEST(parent_rate * frac, (1 << 24));
843 	}
844 	if (inno_read(inno, 0xa0) & 2) {
845 		rate = vco / (nd * 5);
846 	} else {
847 		no_a = inno_read(inno, 0xa5) & 0x1f;
848 		no_b = ((inno_read(inno, 0xa5) >> 5) & 7) + 2;
849 		no_c = (1 << ((inno_read(inno, 0xa6) >> 5) & 7));
850 		no_d = inno_read(inno, 0xa6) & 0x1f;
851 		if (no_a == 1)
852 			rate = vco / (nd * no_b * no_d * 2);
853 		else
854 			rate = vco / (nd * no_a * no_d * 2);
855 	}
856 	inno->pixclock = rate;
857 
858 	return rate;
859 }
860 
861 #define PHY_TAB_LEN 60
862 
863 static
864 int inno_hdmi_update_phy_table(struct inno_hdmi_phy *inno, u32 *config,
865 			       struct phy_config *phy_cfg,
866 			       int phy_table_size)
867 {
868 	int i, j;
869 
870 	for (i = 0; i < phy_table_size; i++) {
871 		phy_cfg[i].tmdsclock =
872 			(unsigned long)config[i * 15];
873 
874 		debug("%ld ", phy_cfg[i].tmdsclock);
875 		for (j = 0; j < 14; j++) {
876 			phy_cfg[i].regs[j] = (u8)config[i * 15 + 1 + j];
877 			debug("0x%02x ", phy_cfg[i].regs[j]);
878 		}
879 		debug("\n");
880 	}
881 
882 	/*
883 	 * The last set of phy cfg is used to indicate whether
884 	 * there is no more phy cfg data.
885 	 */
886 	phy_cfg[i].tmdsclock = ~0UL;
887 	for (j = 0; j < 14; j++)
888 		phy_cfg[i].regs[j] = 0;
889 
890 	return 0;
891 }
892 
893 static const struct inno_hdmi_phy_ops rk3228_hdmi_phy_ops = {
894 	.init = inno_hdmi_phy_rk3228_init,
895 	.power_on = inno_hdmi_phy_rk3228_power_on,
896 	.power_off = inno_hdmi_phy_rk3228_power_off,
897 	.pre_pll_update = inno_hdmi_phy_rk3228_pre_pll_update,
898 };
899 
900 static const struct inno_hdmi_phy_ops rk3328_hdmi_phy_ops = {
901 	.init = inno_hdmi_phy_rk3328_init,
902 	.power_on = inno_hdmi_phy_rk3328_power_on,
903 	.power_off = inno_hdmi_phy_rk3328_power_off,
904 	.pre_pll_update = inno_hdmi_phy_rk3328_pre_pll_update,
905 	.recalc_rate = inno_hdmi_3328_phy_pll_recalc_rate,
906 };
907 
908 static const struct inno_hdmi_phy_drv_data rk3228_hdmi_phy_drv_data = {
909 	.dev_type = INNO_HDMI_PHY_RK3228,
910 	.ops = &rk3228_hdmi_phy_ops,
911 	.phy_cfg_table = rk3228_phy_cfg,
912 };
913 
914 static const struct inno_hdmi_phy_drv_data rk3328_hdmi_phy_drv_data = {
915 	.dev_type = INNO_HDMI_PHY_RK3328,
916 	.ops = &rk3328_hdmi_phy_ops,
917 	.phy_cfg_table = rk3328_phy_cfg,
918 };
919 
920 static const struct rockchip_inno_data inno_hdmi_phy_of_match[] = {
921 	{ .compatible = "rockchip,rk3228-hdmi-phy",
922 	  .data = &rk3228_hdmi_phy_drv_data
923 	},
924 	{ .compatible = "rockchip,rk3328-hdmi-phy",
925 	  .data = &rk3328_hdmi_phy_drv_data
926 	},
927 	{}
928 };
929 
930 static int inno_hdmi_phy_init(struct rockchip_phy *phy)
931 {
932 	struct udevice *dev = phy->dev;
933 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
934 	int i, val, phy_table_size, ret;
935 	const char *name;
936 	u32 *phy_config;
937 
938 	inno->node = dev->node;
939 
940 	inno->regs = dev_read_addr_ptr(dev);
941 	if (!inno->regs) {
942 		printf("%s: failed to get phy address\n", __func__);
943 		return -ENOMEM;
944 	}
945 
946 	name = dev_read_string(dev, "compatible");
947 	for (i = 0; i < ARRAY_SIZE(inno_hdmi_phy_of_match); i++) {
948 		if (!strcmp(name, inno_hdmi_phy_of_match[i].compatible)) {
949 			inno->plat_data = inno_hdmi_phy_of_match[i].data;
950 			break;
951 		}
952 	}
953 
954 	dev_read_prop(dev, "rockchip,phy-table", &val);
955 
956 	if (val >= 0) {
957 		if (val % PHY_TAB_LEN || !val) {
958 			printf("Invalid phy cfg table format!\n");
959 			return -EINVAL;
960 		}
961 
962 		phy_config = malloc(val);
963 		if (!phy_config) {
964 			printf("kmalloc phy table failed\n");
965 			return -ENOMEM;
966 		}
967 
968 		phy_table_size = val / PHY_TAB_LEN;
969 		/* Effective phy cfg data and the end of phy cfg table */
970 		inno->phy_cfg = malloc(val + PHY_TAB_LEN);
971 		if (!inno->phy_cfg) {
972 			free(phy_config);
973 			return -ENOMEM;
974 		}
975 
976 		dev_read_u32_array(dev, "rockchip,phy-table",
977 				   phy_config, val / sizeof(u32));
978 		ret = inno_hdmi_update_phy_table(inno, phy_config,
979 						 inno->phy_cfg,
980 						 phy_table_size);
981 		if (ret) {
982 			free(phy_config);
983 			return ret;
984 		}
985 		free(phy_config);
986 	} else {
987 		printf("use default hdmi phy table\n");
988 	}
989 
990 	if (i >= ARRAY_SIZE(inno_hdmi_phy_of_match))
991 		return 0;
992 
993 	if (!inno->plat_data || !inno->plat_data->ops)
994 		return -EINVAL;
995 
996 	if (inno->plat_data->ops->init)
997 		inno->plat_data->ops->init(inno);
998 
999 	return 0;
1000 }
1001 
1002 static unsigned long inno_hdmi_phy_set_pll(struct rockchip_phy *phy,
1003 					   unsigned long rate)
1004 {
1005 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
1006 
1007 	inno_hdmi_phy_clk_prepare(inno);
1008 	inno_hdmi_phy_clk_is_prepared(inno);
1009 	inno_hdmi_phy_clk_set_rate(inno, rate);
1010 	return 0;
1011 }
1012 
1013 static int
1014 inno_hdmi_phy_set_bus_width(struct rockchip_phy *phy, u32 bus_width)
1015 {
1016 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
1017 
1018 	inno->bus_width = bus_width;
1019 
1020 	return 0;
1021 }
1022 
1023 static long
1024 inno_hdmi_phy_clk_round_rate(struct rockchip_phy *phy, unsigned long rate)
1025 {
1026 	struct inno_hdmi_phy *inno = dev_get_priv(phy->dev);
1027 	int i;
1028 	const struct pre_pll_config *cfg = pre_pll_cfg_table;
1029 	u32 tmdsclock = inno_hdmi_phy_get_tmdsclk(inno, rate);
1030 
1031 	for (; cfg->pixclock != ~0UL; cfg++)
1032 		if (cfg->pixclock == rate)
1033 			break;
1034 
1035 	/*
1036 	 * XXX: Limit pixel clock under 600MHz
1037 	 * rk3228 does not support non-zero fracdiv
1038 	 */
1039 	if ((inno->plat_data->dev_type == INNO_HDMI_PHY_RK3228 &&
1040 	     cfg->fracdiv) || cfg->pixclock > 600000000)
1041 		return -EINVAL;
1042 
1043 	/*
1044 	 * If there is no dts phy cfg table, use default phy cfg table.
1045 	 * The tmds clock maximum is 594MHz. So there is no need to check
1046 	 * whether tmds clock is out of range.
1047 	 */
1048 	if (!inno->phy_cfg)
1049 		return cfg->pixclock;
1050 
1051 	/* Check if tmds clock is out of dts phy config's range. */
1052 	for (i = 0; inno->phy_cfg[i].tmdsclock != ~0UL; i++) {
1053 		if (inno->phy_cfg[i].tmdsclock >= tmdsclock)
1054 			break;
1055 	}
1056 
1057 	if (inno->phy_cfg[i].tmdsclock == ~0UL)
1058 		return -EINVAL;
1059 
1060 	return cfg->pixclock;
1061 }
1062 
1063 const struct rockchip_phy_funcs inno_hdmi_phy_funcs = {
1064 	.init = inno_hdmi_phy_init,
1065 	.power_on = inno_hdmi_phy_power_on,
1066 	.power_off = inno_hdmi_phy_power_off,
1067 	.set_pll = inno_hdmi_phy_set_pll,
1068 	.set_bus_width = inno_hdmi_phy_set_bus_width,
1069 	.round_rate = inno_hdmi_phy_clk_round_rate,
1070 };
1071 
1072 static struct rockchip_phy inno_hdmi_phy_driver_data = {
1073 	 .funcs = &inno_hdmi_phy_funcs,
1074 };
1075 
1076 static const struct udevice_id inno_hdmi_phy_ids[] = {
1077 	{
1078 	 .compatible = "rockchip,rk3328-hdmi-phy",
1079 	 .data = (ulong)&inno_hdmi_phy_driver_data,
1080 	},
1081 	{
1082 	 .compatible = "rockchip,rk3228-hdmi-phy",
1083 	 .data = (ulong)&inno_hdmi_phy_driver_data,
1084 	},
1085 	{}
1086 };
1087 
1088 static int inno_hdmi_phy_probe(struct udevice *dev)
1089 {
1090 	struct inno_hdmi_phy *inno = dev_get_priv(dev);
1091 	struct rockchip_phy *phy =
1092 		(struct rockchip_phy *)dev_get_driver_data(dev);
1093 
1094 	inno->dev = dev;
1095 	phy->dev = dev;
1096 
1097 	return 0;
1098 }
1099 
1100 U_BOOT_DRIVER(inno_hdmi_phy) = {
1101 	.name = "inno_hdmi_phy",
1102 	.id = UCLASS_PHY,
1103 	.of_match = inno_hdmi_phy_ids,
1104 	.probe = inno_hdmi_phy_probe,
1105 	.priv_auto_alloc_size = sizeof(struct inno_hdmi_phy),
1106 };
1107