Linux Audio

Check our new training course

Linux kernel drivers training

Mar 31-Apr 9, 2025, special US time zones
Register
Loading...
Note: File does not exist in v4.6.
  1/*
  2 * Copyright (c) 2014 MediaTek Inc.
  3 * Author: Jie Qiu <jie.qiu@mediatek.com>
  4 *
  5 * This program is free software; you can redistribute it and/or modify
  6 * it under the terms of the GNU General Public License version 2 as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it will be useful,
 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 * GNU General Public License for more details.
 13 */
 14
 15#include <linux/clk.h>
 16#include <linux/clk-provider.h>
 17#include <linux/delay.h>
 18#include <linux/io.h>
 19#include <linux/mfd/syscon.h>
 20#include <linux/module.h>
 21#include <linux/phy/phy.h>
 22#include <linux/platform_device.h>
 23#include <linux/types.h>
 24
 25#define HDMI_CON0		0x00
 26#define RG_HDMITX_PLL_EN		BIT(31)
 27#define RG_HDMITX_PLL_FBKDIV		(0x7f << 24)
 28#define PLL_FBKDIV_SHIFT		24
 29#define RG_HDMITX_PLL_FBKSEL		(0x3 << 22)
 30#define PLL_FBKSEL_SHIFT		22
 31#define RG_HDMITX_PLL_PREDIV		(0x3 << 20)
 32#define PREDIV_SHIFT			20
 33#define RG_HDMITX_PLL_POSDIV		(0x3 << 18)
 34#define POSDIV_SHIFT			18
 35#define RG_HDMITX_PLL_RST_DLY		(0x3 << 16)
 36#define RG_HDMITX_PLL_IR		(0xf << 12)
 37#define PLL_IR_SHIFT			12
 38#define RG_HDMITX_PLL_IC		(0xf << 8)
 39#define PLL_IC_SHIFT			8
 40#define RG_HDMITX_PLL_BP		(0xf << 4)
 41#define PLL_BP_SHIFT			4
 42#define RG_HDMITX_PLL_BR		(0x3 << 2)
 43#define PLL_BR_SHIFT			2
 44#define RG_HDMITX_PLL_BC		(0x3 << 0)
 45#define PLL_BC_SHIFT			0
 46#define HDMI_CON1		0x04
 47#define RG_HDMITX_PLL_DIVEN		(0x7 << 29)
 48#define PLL_DIVEN_SHIFT			29
 49#define RG_HDMITX_PLL_AUTOK_EN		BIT(28)
 50#define RG_HDMITX_PLL_AUTOK_KF		(0x3 << 26)
 51#define RG_HDMITX_PLL_AUTOK_KS		(0x3 << 24)
 52#define RG_HDMITX_PLL_AUTOK_LOAD	BIT(23)
 53#define RG_HDMITX_PLL_BAND		(0x3f << 16)
 54#define RG_HDMITX_PLL_REF_SEL		BIT(15)
 55#define RG_HDMITX_PLL_BIAS_EN		BIT(14)
 56#define RG_HDMITX_PLL_BIAS_LPF_EN	BIT(13)
 57#define RG_HDMITX_PLL_TXDIV_EN		BIT(12)
 58#define RG_HDMITX_PLL_TXDIV		(0x3 << 10)
 59#define PLL_TXDIV_SHIFT			10
 60#define RG_HDMITX_PLL_LVROD_EN		BIT(9)
 61#define RG_HDMITX_PLL_MONVC_EN		BIT(8)
 62#define RG_HDMITX_PLL_MONCK_EN		BIT(7)
 63#define RG_HDMITX_PLL_MONREF_EN		BIT(6)
 64#define RG_HDMITX_PLL_TST_EN		BIT(5)
 65#define RG_HDMITX_PLL_TST_CK_EN		BIT(4)
 66#define RG_HDMITX_PLL_TST_SEL		(0xf << 0)
 67#define HDMI_CON2		0x08
 68#define RGS_HDMITX_PLL_AUTOK_BAND	(0x7f << 8)
 69#define RGS_HDMITX_PLL_AUTOK_FAIL	BIT(1)
 70#define RG_HDMITX_EN_TX_CKLDO		BIT(0)
 71#define HDMI_CON3		0x0c
 72#define RG_HDMITX_SER_EN		(0xf << 28)
 73#define RG_HDMITX_PRD_EN		(0xf << 24)
 74#define RG_HDMITX_PRD_IMP_EN		(0xf << 20)
 75#define RG_HDMITX_DRV_EN		(0xf << 16)
 76#define RG_HDMITX_DRV_IMP_EN		(0xf << 12)
 77#define DRV_IMP_EN_SHIFT		12
 78#define RG_HDMITX_MHLCK_FORCE		BIT(10)
 79#define RG_HDMITX_MHLCK_PPIX_EN		BIT(9)
 80#define RG_HDMITX_MHLCK_EN		BIT(8)
 81#define RG_HDMITX_SER_DIN_SEL		(0xf << 4)
 82#define RG_HDMITX_SER_5T1_BIST_EN	BIT(3)
 83#define RG_HDMITX_SER_BIST_TOG		BIT(2)
 84#define RG_HDMITX_SER_DIN_TOG		BIT(1)
 85#define RG_HDMITX_SER_CLKDIG_INV	BIT(0)
 86#define HDMI_CON4		0x10
 87#define RG_HDMITX_PRD_IBIAS_CLK		(0xf << 24)
 88#define RG_HDMITX_PRD_IBIAS_D2		(0xf << 16)
 89#define RG_HDMITX_PRD_IBIAS_D1		(0xf << 8)
 90#define RG_HDMITX_PRD_IBIAS_D0		(0xf << 0)
 91#define PRD_IBIAS_CLK_SHIFT		24
 92#define PRD_IBIAS_D2_SHIFT		16
 93#define PRD_IBIAS_D1_SHIFT		8
 94#define PRD_IBIAS_D0_SHIFT		0
 95#define HDMI_CON5		0x14
 96#define RG_HDMITX_DRV_IBIAS_CLK		(0x3f << 24)
 97#define RG_HDMITX_DRV_IBIAS_D2		(0x3f << 16)
 98#define RG_HDMITX_DRV_IBIAS_D1		(0x3f << 8)
 99#define RG_HDMITX_DRV_IBIAS_D0		(0x3f << 0)
100#define DRV_IBIAS_CLK_SHIFT		24
101#define DRV_IBIAS_D2_SHIFT		16
102#define DRV_IBIAS_D1_SHIFT		8
103#define DRV_IBIAS_D0_SHIFT		0
104#define HDMI_CON6		0x18
105#define RG_HDMITX_DRV_IMP_CLK		(0x3f << 24)
106#define RG_HDMITX_DRV_IMP_D2		(0x3f << 16)
107#define RG_HDMITX_DRV_IMP_D1		(0x3f << 8)
108#define RG_HDMITX_DRV_IMP_D0		(0x3f << 0)
109#define DRV_IMP_CLK_SHIFT		24
110#define DRV_IMP_D2_SHIFT		16
111#define DRV_IMP_D1_SHIFT		8
112#define DRV_IMP_D0_SHIFT		0
113#define HDMI_CON7		0x1c
114#define RG_HDMITX_MHLCK_DRV_IBIAS	(0x1f << 27)
115#define RG_HDMITX_SER_DIN		(0x3ff << 16)
116#define RG_HDMITX_CHLDC_TST		(0xf << 12)
117#define RG_HDMITX_CHLCK_TST		(0xf << 8)
118#define RG_HDMITX_RESERVE		(0xff << 0)
119#define HDMI_CON8		0x20
120#define RGS_HDMITX_2T1_LEV		(0xf << 16)
121#define RGS_HDMITX_2T1_EDG		(0xf << 12)
122#define RGS_HDMITX_5T1_LEV		(0xf << 8)
123#define RGS_HDMITX_5T1_EDG		(0xf << 4)
124#define RGS_HDMITX_PLUG_TST		BIT(0)
125
126struct mtk_hdmi_phy {
127	void __iomem *regs;
128	struct device *dev;
129	struct clk *pll;
130	struct clk_hw pll_hw;
131	unsigned long pll_rate;
132	u8 drv_imp_clk;
133	u8 drv_imp_d2;
134	u8 drv_imp_d1;
135	u8 drv_imp_d0;
136	u32 ibias;
137	u32 ibias_up;
138};
139
140static const u8 PREDIV[3][4] = {
141	{0x0, 0x0, 0x0, 0x0},	/* 27Mhz */
142	{0x1, 0x1, 0x1, 0x1},	/* 74Mhz */
143	{0x1, 0x1, 0x1, 0x1}	/* 148Mhz */
144};
145
146static const u8 TXDIV[3][4] = {
147	{0x3, 0x3, 0x3, 0x2},	/* 27Mhz */
148	{0x2, 0x1, 0x1, 0x1},	/* 74Mhz */
149	{0x1, 0x0, 0x0, 0x0}	/* 148Mhz */
150};
151
152static const u8 FBKSEL[3][4] = {
153	{0x1, 0x1, 0x1, 0x1},	/* 27Mhz */
154	{0x1, 0x0, 0x1, 0x1},	/* 74Mhz */
155	{0x1, 0x0, 0x1, 0x1}	/* 148Mhz */
156};
157
158static const u8 FBKDIV[3][4] = {
159	{19, 24, 29, 19},	/* 27Mhz */
160	{19, 24, 14, 19},	/* 74Mhz */
161	{19, 24, 14, 19}	/* 148Mhz */
162};
163
164static const u8 DIVEN[3][4] = {
165	{0x2, 0x1, 0x1, 0x2},	/* 27Mhz */
166	{0x2, 0x2, 0x2, 0x2},	/* 74Mhz */
167	{0x2, 0x2, 0x2, 0x2}	/* 148Mhz */
168};
169
170static const u8 HTPLLBP[3][4] = {
171	{0xc, 0xc, 0x8, 0xc},	/* 27Mhz */
172	{0xc, 0xf, 0xf, 0xc},	/* 74Mhz */
173	{0xc, 0xf, 0xf, 0xc}	/* 148Mhz */
174};
175
176static const u8 HTPLLBC[3][4] = {
177	{0x2, 0x3, 0x3, 0x2},	/* 27Mhz */
178	{0x2, 0x3, 0x3, 0x2},	/* 74Mhz */
179	{0x2, 0x3, 0x3, 0x2}	/* 148Mhz */
180};
181
182static const u8 HTPLLBR[3][4] = {
183	{0x1, 0x1, 0x0, 0x1},	/* 27Mhz */
184	{0x1, 0x2, 0x2, 0x1},	/* 74Mhz */
185	{0x1, 0x2, 0x2, 0x1}	/* 148Mhz */
186};
187
188static void mtk_hdmi_phy_clear_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
189				    u32 bits)
190{
191	void __iomem *reg = hdmi_phy->regs + offset;
192	u32 tmp;
193
194	tmp = readl(reg);
195	tmp &= ~bits;
196	writel(tmp, reg);
197}
198
199static void mtk_hdmi_phy_set_bits(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
200				  u32 bits)
201{
202	void __iomem *reg = hdmi_phy->regs + offset;
203	u32 tmp;
204
205	tmp = readl(reg);
206	tmp |= bits;
207	writel(tmp, reg);
208}
209
210static void mtk_hdmi_phy_mask(struct mtk_hdmi_phy *hdmi_phy, u32 offset,
211			      u32 val, u32 mask)
212{
213	void __iomem *reg = hdmi_phy->regs + offset;
214	u32 tmp;
215
216	tmp = readl(reg);
217	tmp = (tmp & ~mask) | (val & mask);
218	writel(tmp, reg);
219}
220
221static inline struct mtk_hdmi_phy *to_mtk_hdmi_phy(struct clk_hw *hw)
222{
223	return container_of(hw, struct mtk_hdmi_phy, pll_hw);
224}
225
226static int mtk_hdmi_pll_prepare(struct clk_hw *hw)
227{
228	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
229
230	dev_dbg(hdmi_phy->dev, "%s\n", __func__);
231
232	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
233	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
234	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_MHLCK_EN);
235	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
236	usleep_range(100, 150);
237	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
238	usleep_range(100, 150);
239	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
240	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
241
242	return 0;
243}
244
245static void mtk_hdmi_pll_unprepare(struct clk_hw *hw)
246{
247	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
248
249	dev_dbg(hdmi_phy->dev, "%s\n", __func__);
250
251	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_TXDIV_EN);
252	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_LPF_EN);
253	usleep_range(100, 150);
254	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_EN);
255	usleep_range(100, 150);
256	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_BIAS_EN);
257	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
258	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON1, RG_HDMITX_PLL_AUTOK_EN);
259	usleep_range(100, 150);
260}
261
262static int mtk_hdmi_pll_set_rate(struct clk_hw *hw, unsigned long rate,
263				 unsigned long parent_rate)
264{
265	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
266	unsigned int pre_div;
267	unsigned int div;
268	unsigned int pre_ibias;
269	unsigned int hdmi_ibias;
270	unsigned int imp_en;
271
272	dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
273		rate, parent_rate);
274
275	if (rate <= 27000000) {
276		pre_div = 0;
277		div = 3;
278	} else if (rate <= 74250000) {
279		pre_div = 1;
280		div = 2;
281	} else {
282		pre_div = 1;
283		div = 1;
284	}
285
286	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
287			  (pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
288	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
289	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
290			  (0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
291			  RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
292	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
293			  (div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
294	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
295			  (0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
296			  RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
297	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
298			  (0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
299	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
300			  (0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
301			  (0x1 << PLL_BR_SHIFT),
302			  RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
303			  RG_HDMITX_PLL_BR);
304	if (rate < 165000000) {
305		mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
306					RG_HDMITX_PRD_IMP_EN);
307		pre_ibias = 0x3;
308		imp_en = 0x0;
309		hdmi_ibias = hdmi_phy->ibias;
310	} else {
311		mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
312				      RG_HDMITX_PRD_IMP_EN);
313		pre_ibias = 0x6;
314		imp_en = 0xf;
315		hdmi_ibias = hdmi_phy->ibias_up;
316	}
317	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
318			  (pre_ibias << PRD_IBIAS_CLK_SHIFT) |
319			  (pre_ibias << PRD_IBIAS_D2_SHIFT) |
320			  (pre_ibias << PRD_IBIAS_D1_SHIFT) |
321			  (pre_ibias << PRD_IBIAS_D0_SHIFT),
322			  RG_HDMITX_PRD_IBIAS_CLK |
323			  RG_HDMITX_PRD_IBIAS_D2 |
324			  RG_HDMITX_PRD_IBIAS_D1 |
325			  RG_HDMITX_PRD_IBIAS_D0);
326	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
327			  (imp_en << DRV_IMP_EN_SHIFT),
328			  RG_HDMITX_DRV_IMP_EN);
329	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
330			  (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
331			  (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
332			  (hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
333			  (hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
334			  RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
335			  RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
336	mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
337			  (hdmi_ibias << DRV_IBIAS_CLK_SHIFT) |
338			  (hdmi_ibias << DRV_IBIAS_D2_SHIFT) |
339			  (hdmi_ibias << DRV_IBIAS_D1_SHIFT) |
340			  (hdmi_ibias << DRV_IBIAS_D0_SHIFT),
341			  RG_HDMITX_DRV_IBIAS_CLK |
342			  RG_HDMITX_DRV_IBIAS_D2 |
343			  RG_HDMITX_DRV_IBIAS_D1 |
344			  RG_HDMITX_DRV_IBIAS_D0);
345	return 0;
346}
347
348static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
349				    unsigned long *parent_rate)
350{
351	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
352
353	hdmi_phy->pll_rate = rate;
354	if (rate <= 74250000)
355		*parent_rate = rate;
356	else
357		*parent_rate = rate / 2;
358
359	return rate;
360}
361
362static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
363					      unsigned long parent_rate)
364{
365	struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
366
367	return hdmi_phy->pll_rate;
368}
369
370static const struct clk_ops mtk_hdmi_pll_ops = {
371	.prepare = mtk_hdmi_pll_prepare,
372	.unprepare = mtk_hdmi_pll_unprepare,
373	.set_rate = mtk_hdmi_pll_set_rate,
374	.round_rate = mtk_hdmi_pll_round_rate,
375	.recalc_rate = mtk_hdmi_pll_recalc_rate,
376};
377
378static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
379{
380	mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
381			      RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
382			      RG_HDMITX_DRV_EN);
383	usleep_range(100, 150);
384}
385
386static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
387{
388	mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
389				RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
390				RG_HDMITX_SER_EN);
391}
392
393static int mtk_hdmi_phy_power_on(struct phy *phy)
394{
395	struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
396	int ret;
397
398	ret = clk_prepare_enable(hdmi_phy->pll);
399	if (ret < 0)
400		return ret;
401
402	mtk_hdmi_phy_enable_tmds(hdmi_phy);
403
404	return 0;
405}
406
407static int mtk_hdmi_phy_power_off(struct phy *phy)
408{
409	struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
410
411	mtk_hdmi_phy_disable_tmds(hdmi_phy);
412	clk_disable_unprepare(hdmi_phy->pll);
413
414	return 0;
415}
416
417static const struct phy_ops mtk_hdmi_phy_ops = {
418	.power_on = mtk_hdmi_phy_power_on,
419	.power_off = mtk_hdmi_phy_power_off,
420	.owner = THIS_MODULE,
421};
422
423static int mtk_hdmi_phy_probe(struct platform_device *pdev)
424{
425	struct device *dev = &pdev->dev;
426	struct mtk_hdmi_phy *hdmi_phy;
427	struct resource *mem;
428	struct clk *ref_clk;
429	const char *ref_clk_name;
430	struct clk_init_data clk_init = {
431		.ops = &mtk_hdmi_pll_ops,
432		.num_parents = 1,
433		.parent_names = (const char * const *)&ref_clk_name,
434		.flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
435	};
436	struct phy *phy;
437	struct phy_provider *phy_provider;
438	int ret;
439
440	hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
441	if (!hdmi_phy)
442		return -ENOMEM;
443
444	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
445	hdmi_phy->regs = devm_ioremap_resource(dev, mem);
446	if (IS_ERR(hdmi_phy->regs)) {
447		ret = PTR_ERR(hdmi_phy->regs);
448		dev_err(dev, "Failed to get memory resource: %d\n", ret);
449		return ret;
450	}
451
452	ref_clk = devm_clk_get(dev, "pll_ref");
453	if (IS_ERR(ref_clk)) {
454		ret = PTR_ERR(ref_clk);
455		dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
456			ret);
457		return ret;
458	}
459	ref_clk_name = __clk_get_name(ref_clk);
460
461	ret = of_property_read_string(dev->of_node, "clock-output-names",
462				      &clk_init.name);
463	if (ret < 0) {
464		dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
465		return ret;
466	}
467
468	hdmi_phy->pll_hw.init = &clk_init;
469	hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
470	if (IS_ERR(hdmi_phy->pll)) {
471		ret = PTR_ERR(hdmi_phy->pll);
472		dev_err(dev, "Failed to register PLL: %d\n", ret);
473		return ret;
474	}
475
476	ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
477				   &hdmi_phy->ibias);
478	if (ret < 0) {
479		dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
480		return ret;
481	}
482
483	ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
484				   &hdmi_phy->ibias_up);
485	if (ret < 0) {
486		dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
487		return ret;
488	}
489
490	dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
491	hdmi_phy->drv_imp_clk = 0x30;
492	hdmi_phy->drv_imp_d2 = 0x30;
493	hdmi_phy->drv_imp_d1 = 0x30;
494	hdmi_phy->drv_imp_d0 = 0x30;
495
496	phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
497	if (IS_ERR(phy)) {
498		dev_err(dev, "Failed to create HDMI PHY\n");
499		return PTR_ERR(phy);
500	}
501	phy_set_drvdata(phy, hdmi_phy);
502
503	phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
504	if (IS_ERR(phy_provider))
505		return PTR_ERR(phy_provider);
506
507	hdmi_phy->dev = dev;
508	return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
509				   hdmi_phy->pll);
510}
511
512static int mtk_hdmi_phy_remove(struct platform_device *pdev)
513{
514	return 0;
515}
516
517static const struct of_device_id mtk_hdmi_phy_match[] = {
518	{ .compatible = "mediatek,mt8173-hdmi-phy", },
519	{},
520};
521
522struct platform_driver mtk_hdmi_phy_driver = {
523	.probe = mtk_hdmi_phy_probe,
524	.remove = mtk_hdmi_phy_remove,
525	.driver = {
526		.name = "mediatek-hdmi-phy",
527		.of_match_table = mtk_hdmi_phy_match,
528	},
529};
530
531MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
532MODULE_DESCRIPTION("MediaTek MT8173 HDMI PHY Driver");
533MODULE_LICENSE("GPL v2");