aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/mediatek
diff options
context:
space:
mode:
authorJie Qiu <jie.qiu@mediatek.com>2016-01-04 12:36:38 -0500
committerPhilipp Zabel <p.zabel@pengutronix.de>2016-06-16 10:30:38 -0400
commit8f83f26891e12570780dcfc8ae376b655915ff6d (patch)
tree92acfec15b83acebdf74d5ab879b4c88693728c7 /drivers/gpu/drm/mediatek
parent7cdeb24db4d12d42c237f28afade69c09e8a85e2 (diff)
drm/mediatek: Add HDMI support
This patch adds drivers for the HDMI bridge connected to the DPI0 display subsystem function block, for the HDMI DDC block, and for the HDMI PHY to support HDMI output. This includes an interface to the generic hdmi-codec driver to start or stop audio playback and to retrieve ELD (EDID like data) to limit the supported audio formats to the HDMI sink capabilities. Signed-off-by: Jie Qiu <jie.qiu@mediatek.com> Signed-off-by: Junzhi Zhao <junzhi.zhao@mediatek.com> Signed-off-by: Philipp Zabel <p.zabel@pengutronix.de>
Diffstat (limited to 'drivers/gpu/drm/mediatek')
-rw-r--r--drivers/gpu/drm/mediatek/Kconfig8
-rw-r--r--drivers/gpu/drm/mediatek/Makefile7
-rw-r--r--drivers/gpu/drm/mediatek/mtk_cec.c265
-rw-r--r--drivers/gpu/drm/mediatek/mtk_cec.h26
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.c1816
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi.h23
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c358
-rw-r--r--drivers/gpu/drm/mediatek/mtk_hdmi_regs.h237
-rw-r--r--drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c515
9 files changed, 3255 insertions, 0 deletions
diff --git a/drivers/gpu/drm/mediatek/Kconfig b/drivers/gpu/drm/mediatek/Kconfig
index eeefc971801a..a6898d5dcc98 100644
--- a/drivers/gpu/drm/mediatek/Kconfig
+++ b/drivers/gpu/drm/mediatek/Kconfig
@@ -14,3 +14,11 @@ config DRM_MEDIATEK
14 The module will be called mediatek-drm 14 The module will be called mediatek-drm
15 This driver provides kernel mode setting and 15 This driver provides kernel mode setting and
16 buffer management to userspace. 16 buffer management to userspace.
17
18config DRM_MEDIATEK_HDMI
19 tristate "DRM HDMI Support for Mediatek SoCs"
20 depends on DRM_MEDIATEK
21 select SND_SOC_HDMI_CODEC if SND_SOC
22 select GENERIC_PHY
23 help
24 DRM/KMS HDMI driver for Mediatek SoCs
diff --git a/drivers/gpu/drm/mediatek/Makefile b/drivers/gpu/drm/mediatek/Makefile
index 5fcf58e87786..bf2e5be1ab30 100644
--- a/drivers/gpu/drm/mediatek/Makefile
+++ b/drivers/gpu/drm/mediatek/Makefile
@@ -12,3 +12,10 @@ mediatek-drm-y := mtk_disp_ovl.o \
12 mtk_dpi.o 12 mtk_dpi.o
13 13
14obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o 14obj-$(CONFIG_DRM_MEDIATEK) += mediatek-drm.o
15
16mediatek-drm-hdmi-objs := mtk_cec.o \
17 mtk_hdmi.o \
18 mtk_hdmi_ddc.o \
19 mtk_mt8173_hdmi_phy.o
20
21obj-$(CONFIG_DRM_MEDIATEK_HDMI) += mediatek-drm-hdmi.o
diff --git a/drivers/gpu/drm/mediatek/mtk_cec.c b/drivers/gpu/drm/mediatek/mtk_cec.c
new file mode 100644
index 000000000000..7a3eb8c17ef9
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_cec.c
@@ -0,0 +1,265 @@
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#include <linux/clk.h>
15#include <linux/delay.h>
16#include <linux/io.h>
17#include <linux/interrupt.h>
18#include <linux/platform_device.h>
19
20#include "mtk_cec.h"
21
22#define TR_CONFIG 0x00
23#define CLEAR_CEC_IRQ BIT(15)
24
25#define CEC_CKGEN 0x04
26#define CEC_32K_PDN BIT(19)
27#define PDN BIT(16)
28
29#define RX_EVENT 0x54
30#define HDMI_PORD BIT(25)
31#define HDMI_HTPLG BIT(24)
32#define HDMI_PORD_INT_EN BIT(9)
33#define HDMI_HTPLG_INT_EN BIT(8)
34
35#define RX_GEN_WD 0x58
36#define HDMI_PORD_INT_32K_STATUS BIT(26)
37#define RX_RISC_INT_32K_STATUS BIT(25)
38#define HDMI_HTPLG_INT_32K_STATUS BIT(24)
39#define HDMI_PORD_INT_32K_CLR BIT(18)
40#define RX_INT_32K_CLR BIT(17)
41#define HDMI_HTPLG_INT_32K_CLR BIT(16)
42#define HDMI_PORD_INT_32K_STA_MASK BIT(10)
43#define RX_RISC_INT_32K_STA_MASK BIT(9)
44#define HDMI_HTPLG_INT_32K_STA_MASK BIT(8)
45#define HDMI_PORD_INT_32K_EN BIT(2)
46#define RX_INT_32K_EN BIT(1)
47#define HDMI_HTPLG_INT_32K_EN BIT(0)
48
49#define NORMAL_INT_CTRL 0x5C
50#define HDMI_HTPLG_INT_STA BIT(0)
51#define HDMI_PORD_INT_STA BIT(1)
52#define HDMI_HTPLG_INT_CLR BIT(16)
53#define HDMI_PORD_INT_CLR BIT(17)
54#define HDMI_FULL_INT_CLR BIT(20)
55
56struct mtk_cec {
57 void __iomem *regs;
58 struct clk *clk;
59 int irq;
60 bool hpd;
61 void (*hpd_event)(bool hpd, struct device *dev);
62 struct device *hdmi_dev;
63 spinlock_t lock;
64};
65
66static void mtk_cec_clear_bits(struct mtk_cec *cec, unsigned int offset,
67 unsigned int bits)
68{
69 void __iomem *reg = cec->regs + offset;
70 u32 tmp;
71
72 tmp = readl(reg);
73 tmp &= ~bits;
74 writel(tmp, reg);
75}
76
77static void mtk_cec_set_bits(struct mtk_cec *cec, unsigned int offset,
78 unsigned int bits)
79{
80 void __iomem *reg = cec->regs + offset;
81 u32 tmp;
82
83 tmp = readl(reg);
84 tmp |= bits;
85 writel(tmp, reg);
86}
87
88static void mtk_cec_mask(struct mtk_cec *cec, unsigned int offset,
89 unsigned int val, unsigned int mask)
90{
91 u32 tmp = readl(cec->regs + offset) & ~mask;
92
93 tmp |= val & mask;
94 writel(val, cec->regs + offset);
95}
96
97void mtk_cec_set_hpd_event(struct device *dev,
98 void (*hpd_event)(bool hpd, struct device *dev),
99 struct device *hdmi_dev)
100{
101 struct mtk_cec *cec = dev_get_drvdata(dev);
102 unsigned long flags;
103
104 spin_lock_irqsave(&cec->lock, flags);
105 cec->hdmi_dev = hdmi_dev;
106 cec->hpd_event = hpd_event;
107 spin_unlock_irqrestore(&cec->lock, flags);
108}
109
110bool mtk_cec_hpd_high(struct device *dev)
111{
112 struct mtk_cec *cec = dev_get_drvdata(dev);
113 unsigned int status;
114
115 status = readl(cec->regs + RX_EVENT);
116
117 return (status & (HDMI_PORD | HDMI_HTPLG)) == (HDMI_PORD | HDMI_HTPLG);
118}
119
120static void mtk_cec_htplg_irq_init(struct mtk_cec *cec)
121{
122 mtk_cec_mask(cec, CEC_CKGEN, 0 | CEC_32K_PDN, PDN | CEC_32K_PDN);
123 mtk_cec_set_bits(cec, RX_GEN_WD, HDMI_PORD_INT_32K_CLR |
124 RX_INT_32K_CLR | HDMI_HTPLG_INT_32K_CLR);
125 mtk_cec_mask(cec, RX_GEN_WD, 0, HDMI_PORD_INT_32K_CLR | RX_INT_32K_CLR |
126 HDMI_HTPLG_INT_32K_CLR | HDMI_PORD_INT_32K_EN |
127 RX_INT_32K_EN | HDMI_HTPLG_INT_32K_EN);
128}
129
130static void mtk_cec_htplg_irq_enable(struct mtk_cec *cec)
131{
132 mtk_cec_set_bits(cec, RX_EVENT, HDMI_PORD_INT_EN | HDMI_HTPLG_INT_EN);
133}
134
135static void mtk_cec_htplg_irq_disable(struct mtk_cec *cec)
136{
137 mtk_cec_clear_bits(cec, RX_EVENT, HDMI_PORD_INT_EN | HDMI_HTPLG_INT_EN);
138}
139
140static void mtk_cec_clear_htplg_irq(struct mtk_cec *cec)
141{
142 mtk_cec_set_bits(cec, TR_CONFIG, CLEAR_CEC_IRQ);
143 mtk_cec_set_bits(cec, NORMAL_INT_CTRL, HDMI_HTPLG_INT_CLR |
144 HDMI_PORD_INT_CLR | HDMI_FULL_INT_CLR);
145 mtk_cec_set_bits(cec, RX_GEN_WD, HDMI_PORD_INT_32K_CLR |
146 RX_INT_32K_CLR | HDMI_HTPLG_INT_32K_CLR);
147 usleep_range(5, 10);
148 mtk_cec_clear_bits(cec, NORMAL_INT_CTRL, HDMI_HTPLG_INT_CLR |
149 HDMI_PORD_INT_CLR | HDMI_FULL_INT_CLR);
150 mtk_cec_clear_bits(cec, TR_CONFIG, CLEAR_CEC_IRQ);
151 mtk_cec_clear_bits(cec, RX_GEN_WD, HDMI_PORD_INT_32K_CLR |
152 RX_INT_32K_CLR | HDMI_HTPLG_INT_32K_CLR);
153}
154
155static void mtk_cec_hpd_event(struct mtk_cec *cec, bool hpd)
156{
157 void (*hpd_event)(bool hpd, struct device *dev);
158 struct device *hdmi_dev;
159 unsigned long flags;
160
161 spin_lock_irqsave(&cec->lock, flags);
162 hpd_event = cec->hpd_event;
163 hdmi_dev = cec->hdmi_dev;
164 spin_unlock_irqrestore(&cec->lock, flags);
165
166 if (hpd_event)
167 hpd_event(hpd, hdmi_dev);
168}
169
170static irqreturn_t mtk_cec_htplg_isr_thread(int irq, void *arg)
171{
172 struct device *dev = arg;
173 struct mtk_cec *cec = dev_get_drvdata(dev);
174 bool hpd;
175
176 mtk_cec_clear_htplg_irq(cec);
177 hpd = mtk_cec_hpd_high(dev);
178
179 if (cec->hpd != hpd) {
180 dev_dbg(dev, "hotplug event! cur hpd = %d, hpd = %d\n",
181 cec->hpd, hpd);
182 cec->hpd = hpd;
183 mtk_cec_hpd_event(cec, hpd);
184 }
185 return IRQ_HANDLED;
186}
187
188static int mtk_cec_probe(struct platform_device *pdev)
189{
190 struct device *dev = &pdev->dev;
191 struct mtk_cec *cec;
192 struct resource *res;
193 int ret;
194
195 cec = devm_kzalloc(dev, sizeof(*cec), GFP_KERNEL);
196 if (!cec)
197 return -ENOMEM;
198
199 platform_set_drvdata(pdev, cec);
200 spin_lock_init(&cec->lock);
201
202 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
203 cec->regs = devm_ioremap_resource(dev, res);
204 if (IS_ERR(cec->regs)) {
205 ret = PTR_ERR(cec->regs);
206 dev_err(dev, "Failed to ioremap cec: %d\n", ret);
207 return ret;
208 }
209
210 cec->clk = devm_clk_get(dev, NULL);
211 if (IS_ERR(cec->clk)) {
212 ret = PTR_ERR(cec->clk);
213 dev_err(dev, "Failed to get cec clock: %d\n", ret);
214 return ret;
215 }
216
217 cec->irq = platform_get_irq(pdev, 0);
218 if (cec->irq < 0) {
219 dev_err(dev, "Failed to get cec irq: %d\n", cec->irq);
220 return cec->irq;
221 }
222
223 ret = devm_request_threaded_irq(dev, cec->irq, NULL,
224 mtk_cec_htplg_isr_thread,
225 IRQF_SHARED | IRQF_TRIGGER_LOW |
226 IRQF_ONESHOT, "hdmi hpd", dev);
227 if (ret) {
228 dev_err(dev, "Failed to register cec irq: %d\n", ret);
229 return ret;
230 }
231
232 ret = clk_prepare_enable(cec->clk);
233 if (ret) {
234 dev_err(dev, "Failed to enable cec clock: %d\n", ret);
235 return ret;
236 }
237
238 mtk_cec_htplg_irq_init(cec);
239 mtk_cec_htplg_irq_enable(cec);
240
241 return 0;
242}
243
244static int mtk_cec_remove(struct platform_device *pdev)
245{
246 struct mtk_cec *cec = platform_get_drvdata(pdev);
247
248 mtk_cec_htplg_irq_disable(cec);
249 clk_disable_unprepare(cec->clk);
250 return 0;
251}
252
253static const struct of_device_id mtk_cec_of_ids[] = {
254 { .compatible = "mediatek,mt8173-cec", },
255 {}
256};
257
258struct platform_driver mtk_cec_driver = {
259 .probe = mtk_cec_probe,
260 .remove = mtk_cec_remove,
261 .driver = {
262 .name = "mediatek-cec",
263 .of_match_table = mtk_cec_of_ids,
264 },
265};
diff --git a/drivers/gpu/drm/mediatek/mtk_cec.h b/drivers/gpu/drm/mediatek/mtk_cec.h
new file mode 100644
index 000000000000..10057b7eabec
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_cec.h
@@ -0,0 +1,26 @@
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#ifndef _MTK_CEC_H
15#define _MTK_CEC_H
16
17#include <linux/types.h>
18
19struct device;
20
21void mtk_cec_set_hpd_event(struct device *dev,
22 void (*hotplug_event)(bool hpd, struct device *dev),
23 struct device *hdmi_dev);
24bool mtk_cec_hpd_high(struct device *dev);
25
26#endif /* _MTK_CEC_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.c b/drivers/gpu/drm/mediatek/mtk_hdmi.c
new file mode 100644
index 000000000000..8ec1ea4477e2
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.c
@@ -0,0 +1,1816 @@
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#include <drm/drmP.h>
15#include <drm/drm_atomic_helper.h>
16#include <drm/drm_crtc.h>
17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_edid.h>
19#include <linux/clk.h>
20#include <linux/delay.h>
21#include <linux/hdmi.h>
22#include <linux/i2c.h>
23#include <linux/io.h>
24#include <linux/kernel.h>
25#include <linux/mfd/syscon.h>
26#include <linux/of_platform.h>
27#include <linux/of.h>
28#include <linux/of_gpio.h>
29#include <linux/of_graph.h>
30#include <linux/phy/phy.h>
31#include <linux/platform_device.h>
32#include <linux/regmap.h>
33#include <sound/hdmi-codec.h>
34#include "mtk_cec.h"
35#include "mtk_hdmi.h"
36#include "mtk_hdmi_regs.h"
37
38#define NCTS_BYTES 7
39
40enum mtk_hdmi_clk_id {
41 MTK_HDMI_CLK_HDMI_PIXEL,
42 MTK_HDMI_CLK_HDMI_PLL,
43 MTK_HDMI_CLK_AUD_BCLK,
44 MTK_HDMI_CLK_AUD_SPDIF,
45 MTK_HDMI_CLK_COUNT
46};
47
48enum hdmi_aud_input_type {
49 HDMI_AUD_INPUT_I2S = 0,
50 HDMI_AUD_INPUT_SPDIF,
51};
52
53enum hdmi_aud_i2s_fmt {
54 HDMI_I2S_MODE_RJT_24BIT = 0,
55 HDMI_I2S_MODE_RJT_16BIT,
56 HDMI_I2S_MODE_LJT_24BIT,
57 HDMI_I2S_MODE_LJT_16BIT,
58 HDMI_I2S_MODE_I2S_24BIT,
59 HDMI_I2S_MODE_I2S_16BIT
60};
61
62enum hdmi_aud_mclk {
63 HDMI_AUD_MCLK_128FS,
64 HDMI_AUD_MCLK_192FS,
65 HDMI_AUD_MCLK_256FS,
66 HDMI_AUD_MCLK_384FS,
67 HDMI_AUD_MCLK_512FS,
68 HDMI_AUD_MCLK_768FS,
69 HDMI_AUD_MCLK_1152FS,
70};
71
72enum hdmi_aud_channel_type {
73 HDMI_AUD_CHAN_TYPE_1_0 = 0,
74 HDMI_AUD_CHAN_TYPE_1_1,
75 HDMI_AUD_CHAN_TYPE_2_0,
76 HDMI_AUD_CHAN_TYPE_2_1,
77 HDMI_AUD_CHAN_TYPE_3_0,
78 HDMI_AUD_CHAN_TYPE_3_1,
79 HDMI_AUD_CHAN_TYPE_4_0,
80 HDMI_AUD_CHAN_TYPE_4_1,
81 HDMI_AUD_CHAN_TYPE_5_0,
82 HDMI_AUD_CHAN_TYPE_5_1,
83 HDMI_AUD_CHAN_TYPE_6_0,
84 HDMI_AUD_CHAN_TYPE_6_1,
85 HDMI_AUD_CHAN_TYPE_7_0,
86 HDMI_AUD_CHAN_TYPE_7_1,
87 HDMI_AUD_CHAN_TYPE_3_0_LRS,
88 HDMI_AUD_CHAN_TYPE_3_1_LRS,
89 HDMI_AUD_CHAN_TYPE_4_0_CLRS,
90 HDMI_AUD_CHAN_TYPE_4_1_CLRS,
91 HDMI_AUD_CHAN_TYPE_6_1_CS,
92 HDMI_AUD_CHAN_TYPE_6_1_CH,
93 HDMI_AUD_CHAN_TYPE_6_1_OH,
94 HDMI_AUD_CHAN_TYPE_6_1_CHR,
95 HDMI_AUD_CHAN_TYPE_7_1_LH_RH,
96 HDMI_AUD_CHAN_TYPE_7_1_LSR_RSR,
97 HDMI_AUD_CHAN_TYPE_7_1_LC_RC,
98 HDMI_AUD_CHAN_TYPE_7_1_LW_RW,
99 HDMI_AUD_CHAN_TYPE_7_1_LSD_RSD,
100 HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS,
101 HDMI_AUD_CHAN_TYPE_7_1_LHS_RHS,
102 HDMI_AUD_CHAN_TYPE_7_1_CS_CH,
103 HDMI_AUD_CHAN_TYPE_7_1_CS_OH,
104 HDMI_AUD_CHAN_TYPE_7_1_CS_CHR,
105 HDMI_AUD_CHAN_TYPE_7_1_CH_OH,
106 HDMI_AUD_CHAN_TYPE_7_1_CH_CHR,
107 HDMI_AUD_CHAN_TYPE_7_1_OH_CHR,
108 HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS_LSR_RSR,
109 HDMI_AUD_CHAN_TYPE_6_0_CS,
110 HDMI_AUD_CHAN_TYPE_6_0_CH,
111 HDMI_AUD_CHAN_TYPE_6_0_OH,
112 HDMI_AUD_CHAN_TYPE_6_0_CHR,
113 HDMI_AUD_CHAN_TYPE_7_0_LH_RH,
114 HDMI_AUD_CHAN_TYPE_7_0_LSR_RSR,
115 HDMI_AUD_CHAN_TYPE_7_0_LC_RC,
116 HDMI_AUD_CHAN_TYPE_7_0_LW_RW,
117 HDMI_AUD_CHAN_TYPE_7_0_LSD_RSD,
118 HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS,
119 HDMI_AUD_CHAN_TYPE_7_0_LHS_RHS,
120 HDMI_AUD_CHAN_TYPE_7_0_CS_CH,
121 HDMI_AUD_CHAN_TYPE_7_0_CS_OH,
122 HDMI_AUD_CHAN_TYPE_7_0_CS_CHR,
123 HDMI_AUD_CHAN_TYPE_7_0_CH_OH,
124 HDMI_AUD_CHAN_TYPE_7_0_CH_CHR,
125 HDMI_AUD_CHAN_TYPE_7_0_OH_CHR,
126 HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS_LSR_RSR,
127 HDMI_AUD_CHAN_TYPE_8_0_LH_RH_CS,
128 HDMI_AUD_CHAN_TYPE_UNKNOWN = 0xFF
129};
130
131enum hdmi_aud_channel_swap_type {
132 HDMI_AUD_SWAP_LR,
133 HDMI_AUD_SWAP_LFE_CC,
134 HDMI_AUD_SWAP_LSRS,
135 HDMI_AUD_SWAP_RLS_RRS,
136 HDMI_AUD_SWAP_LR_STATUS,
137};
138
139struct hdmi_audio_param {
140 enum hdmi_audio_coding_type aud_codec;
141 enum hdmi_audio_sample_size aud_sampe_size;
142 enum hdmi_aud_input_type aud_input_type;
143 enum hdmi_aud_i2s_fmt aud_i2s_fmt;
144 enum hdmi_aud_mclk aud_mclk;
145 enum hdmi_aud_channel_type aud_input_chan_type;
146 struct hdmi_codec_params codec_params;
147};
148
149struct mtk_hdmi {
150 struct drm_bridge bridge;
151 struct drm_connector conn;
152 struct device *dev;
153 struct phy *phy;
154 struct device *cec_dev;
155 struct i2c_adapter *ddc_adpt;
156 struct clk *clk[MTK_HDMI_CLK_COUNT];
157 struct drm_display_mode mode;
158 bool dvi_mode;
159 u32 min_clock;
160 u32 max_clock;
161 u32 max_hdisplay;
162 u32 max_vdisplay;
163 u32 ibias;
164 u32 ibias_up;
165 struct regmap *sys_regmap;
166 unsigned int sys_offset;
167 void __iomem *regs;
168 enum hdmi_colorspace csp;
169 struct hdmi_audio_param aud_param;
170 bool audio_enable;
171 bool powered;
172 bool enabled;
173};
174
175static inline struct mtk_hdmi *hdmi_ctx_from_bridge(struct drm_bridge *b)
176{
177 return container_of(b, struct mtk_hdmi, bridge);
178}
179
180static inline struct mtk_hdmi *hdmi_ctx_from_conn(struct drm_connector *c)
181{
182 return container_of(c, struct mtk_hdmi, conn);
183}
184
185static u32 mtk_hdmi_read(struct mtk_hdmi *hdmi, u32 offset)
186{
187 return readl(hdmi->regs + offset);
188}
189
190static void mtk_hdmi_write(struct mtk_hdmi *hdmi, u32 offset, u32 val)
191{
192 writel(val, hdmi->regs + offset);
193}
194
195static void mtk_hdmi_clear_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits)
196{
197 void __iomem *reg = hdmi->regs + offset;
198 u32 tmp;
199
200 tmp = readl(reg);
201 tmp &= ~bits;
202 writel(tmp, reg);
203}
204
205static void mtk_hdmi_set_bits(struct mtk_hdmi *hdmi, u32 offset, u32 bits)
206{
207 void __iomem *reg = hdmi->regs + offset;
208 u32 tmp;
209
210 tmp = readl(reg);
211 tmp |= bits;
212 writel(tmp, reg);
213}
214
215static void mtk_hdmi_mask(struct mtk_hdmi *hdmi, u32 offset, u32 val, u32 mask)
216{
217 void __iomem *reg = hdmi->regs + offset;
218 u32 tmp;
219
220 tmp = readl(reg);
221 tmp = (tmp & ~mask) | (val & mask);
222 writel(tmp, reg);
223}
224
225static void mtk_hdmi_hw_vid_black(struct mtk_hdmi *hdmi, bool black)
226{
227 mtk_hdmi_mask(hdmi, VIDEO_CFG_4, black ? GEN_RGB : NORMAL_PATH,
228 VIDEO_SOURCE_SEL);
229}
230
231static void mtk_hdmi_hw_make_reg_writable(struct mtk_hdmi *hdmi, bool enable)
232{
233 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
234 HDMI_PCLK_FREE_RUN, enable ? HDMI_PCLK_FREE_RUN : 0);
235 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
236 HDMI_ON | ANLG_ON, enable ? (HDMI_ON | ANLG_ON) : 0);
237}
238
239static void mtk_hdmi_hw_1p4_version_enable(struct mtk_hdmi *hdmi, bool enable)
240{
241 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
242 HDMI2P0_EN, enable ? 0 : HDMI2P0_EN);
243}
244
245static void mtk_hdmi_hw_aud_mute(struct mtk_hdmi *hdmi)
246{
247 mtk_hdmi_set_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO);
248}
249
250static void mtk_hdmi_hw_aud_unmute(struct mtk_hdmi *hdmi)
251{
252 mtk_hdmi_clear_bits(hdmi, GRL_AUDIO_CFG, AUDIO_ZERO);
253}
254
255static void mtk_hdmi_hw_reset(struct mtk_hdmi *hdmi)
256{
257 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
258 HDMI_RST, HDMI_RST);
259 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
260 HDMI_RST, 0);
261 mtk_hdmi_clear_bits(hdmi, GRL_CFG3, CFG3_CONTROL_PACKET_DELAY);
262 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG1C,
263 ANLG_ON, ANLG_ON);
264}
265
266static void mtk_hdmi_hw_enable_notice(struct mtk_hdmi *hdmi, bool enable_notice)
267{
268 mtk_hdmi_mask(hdmi, GRL_CFG2, enable_notice ? CFG2_NOTICE_EN : 0,
269 CFG2_NOTICE_EN);
270}
271
272static void mtk_hdmi_hw_write_int_mask(struct mtk_hdmi *hdmi, u32 int_mask)
273{
274 mtk_hdmi_write(hdmi, GRL_INT_MASK, int_mask);
275}
276
277static void mtk_hdmi_hw_enable_dvi_mode(struct mtk_hdmi *hdmi, bool enable)
278{
279 mtk_hdmi_mask(hdmi, GRL_CFG1, enable ? CFG1_DVI : 0, CFG1_DVI);
280}
281
282static void mtk_hdmi_hw_send_info_frame(struct mtk_hdmi *hdmi, u8 *buffer,
283 u8 len)
284{
285 u32 ctrl_reg = GRL_CTRL;
286 int i;
287 u8 *frame_data;
288 enum hdmi_infoframe_type frame_type;
289 u8 frame_ver;
290 u8 frame_len;
291 u8 checksum;
292 int ctrl_frame_en = 0;
293
294 frame_type = *buffer;
295 buffer += 1;
296 frame_ver = *buffer;
297 buffer += 1;
298 frame_len = *buffer;
299 buffer += 1;
300 checksum = *buffer;
301 buffer += 1;
302 frame_data = buffer;
303
304 dev_dbg(hdmi->dev,
305 "frame_type:0x%x,frame_ver:0x%x,frame_len:0x%x,checksum:0x%x\n",
306 frame_type, frame_ver, frame_len, checksum);
307
308 switch (frame_type) {
309 case HDMI_INFOFRAME_TYPE_AVI:
310 ctrl_frame_en = CTRL_AVI_EN;
311 ctrl_reg = GRL_CTRL;
312 break;
313 case HDMI_INFOFRAME_TYPE_SPD:
314 ctrl_frame_en = CTRL_SPD_EN;
315 ctrl_reg = GRL_CTRL;
316 break;
317 case HDMI_INFOFRAME_TYPE_AUDIO:
318 ctrl_frame_en = CTRL_AUDIO_EN;
319 ctrl_reg = GRL_CTRL;
320 break;
321 case HDMI_INFOFRAME_TYPE_VENDOR:
322 ctrl_frame_en = VS_EN;
323 ctrl_reg = GRL_ACP_ISRC_CTRL;
324 break;
325 }
326 mtk_hdmi_clear_bits(hdmi, ctrl_reg, ctrl_frame_en);
327 mtk_hdmi_write(hdmi, GRL_INFOFRM_TYPE, frame_type);
328 mtk_hdmi_write(hdmi, GRL_INFOFRM_VER, frame_ver);
329 mtk_hdmi_write(hdmi, GRL_INFOFRM_LNG, frame_len);
330
331 mtk_hdmi_write(hdmi, GRL_IFM_PORT, checksum);
332 for (i = 0; i < frame_len; i++)
333 mtk_hdmi_write(hdmi, GRL_IFM_PORT, frame_data[i]);
334
335 mtk_hdmi_set_bits(hdmi, ctrl_reg, ctrl_frame_en);
336}
337
338static void mtk_hdmi_hw_send_aud_packet(struct mtk_hdmi *hdmi, bool enable)
339{
340 mtk_hdmi_mask(hdmi, GRL_SHIFT_R2, enable ? 0 : AUDIO_PACKET_OFF,
341 AUDIO_PACKET_OFF);
342}
343
344static void mtk_hdmi_hw_config_sys(struct mtk_hdmi *hdmi)
345{
346 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
347 HDMI_OUT_FIFO_EN | MHL_MODE_ON, 0);
348 usleep_range(2000, 4000);
349 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
350 HDMI_OUT_FIFO_EN | MHL_MODE_ON, HDMI_OUT_FIFO_EN);
351}
352
353static void mtk_hdmi_hw_set_deep_color_mode(struct mtk_hdmi *hdmi)
354{
355 regmap_update_bits(hdmi->sys_regmap, hdmi->sys_offset + HDMI_SYS_CFG20,
356 DEEP_COLOR_MODE_MASK | DEEP_COLOR_EN,
357 COLOR_8BIT_MODE);
358}
359
360static void mtk_hdmi_hw_send_av_mute(struct mtk_hdmi *hdmi)
361{
362 mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CTRL_AVMUTE);
363 usleep_range(2000, 4000);
364 mtk_hdmi_set_bits(hdmi, GRL_CFG4, CTRL_AVMUTE);
365}
366
367static void mtk_hdmi_hw_send_av_unmute(struct mtk_hdmi *hdmi)
368{
369 mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_EN,
370 CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET);
371 usleep_range(2000, 4000);
372 mtk_hdmi_mask(hdmi, GRL_CFG4, CFG4_AV_UNMUTE_SET,
373 CFG4_AV_UNMUTE_EN | CFG4_AV_UNMUTE_SET);
374}
375
376static void mtk_hdmi_hw_ncts_enable(struct mtk_hdmi *hdmi, bool on)
377{
378 mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, on ? 0 : CTS_CTRL_SOFT,
379 CTS_CTRL_SOFT);
380}
381
382static void mtk_hdmi_hw_ncts_auto_write_enable(struct mtk_hdmi *hdmi,
383 bool enable)
384{
385 mtk_hdmi_mask(hdmi, GRL_CTS_CTRL, enable ? NCTS_WRI_ANYTIME : 0,
386 NCTS_WRI_ANYTIME);
387}
388
389static void mtk_hdmi_hw_msic_setting(struct mtk_hdmi *hdmi,
390 struct drm_display_mode *mode)
391{
392 mtk_hdmi_clear_bits(hdmi, GRL_CFG4, CFG4_MHL_MODE);
393
394 if (mode->flags & DRM_MODE_FLAG_INTERLACE &&
395 mode->clock == 74250 &&
396 mode->vdisplay == 1080)
397 mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL);
398 else
399 mtk_hdmi_set_bits(hdmi, GRL_CFG2, CFG2_MHL_DE_SEL);
400}
401
402static void mtk_hdmi_hw_aud_set_channel_swap(struct mtk_hdmi *hdmi,
403 enum hdmi_aud_channel_swap_type swap)
404{
405 u8 swap_bit;
406
407 switch (swap) {
408 case HDMI_AUD_SWAP_LR:
409 swap_bit = LR_SWAP;
410 break;
411 case HDMI_AUD_SWAP_LFE_CC:
412 swap_bit = LFE_CC_SWAP;
413 break;
414 case HDMI_AUD_SWAP_LSRS:
415 swap_bit = LSRS_SWAP;
416 break;
417 case HDMI_AUD_SWAP_RLS_RRS:
418 swap_bit = RLS_RRS_SWAP;
419 break;
420 case HDMI_AUD_SWAP_LR_STATUS:
421 swap_bit = LR_STATUS_SWAP;
422 break;
423 default:
424 swap_bit = LFE_CC_SWAP;
425 break;
426 }
427 mtk_hdmi_mask(hdmi, GRL_CH_SWAP, swap_bit, 0xff);
428}
429
430static void mtk_hdmi_hw_aud_set_bit_num(struct mtk_hdmi *hdmi,
431 enum hdmi_audio_sample_size bit_num)
432{
433 u32 val;
434
435 switch (bit_num) {
436 case HDMI_AUDIO_SAMPLE_SIZE_16:
437 val = AOUT_16BIT;
438 break;
439 case HDMI_AUDIO_SAMPLE_SIZE_20:
440 val = AOUT_20BIT;
441 break;
442 case HDMI_AUDIO_SAMPLE_SIZE_24:
443 case HDMI_AUDIO_SAMPLE_SIZE_STREAM:
444 val = AOUT_24BIT;
445 break;
446 }
447
448 mtk_hdmi_mask(hdmi, GRL_AOUT_CFG, val, AOUT_BNUM_SEL_MASK);
449}
450
451static void mtk_hdmi_hw_aud_set_i2s_fmt(struct mtk_hdmi *hdmi,
452 enum hdmi_aud_i2s_fmt i2s_fmt)
453{
454 u32 val;
455
456 val = mtk_hdmi_read(hdmi, GRL_CFG0);
457 val &= ~(CFG0_W_LENGTH_MASK | CFG0_I2S_MODE_MASK);
458
459 switch (i2s_fmt) {
460 case HDMI_I2S_MODE_RJT_24BIT:
461 val |= CFG0_I2S_MODE_RTJ | CFG0_W_LENGTH_24BIT;
462 break;
463 case HDMI_I2S_MODE_RJT_16BIT:
464 val |= CFG0_I2S_MODE_RTJ | CFG0_W_LENGTH_16BIT;
465 break;
466 case HDMI_I2S_MODE_LJT_24BIT:
467 default:
468 val |= CFG0_I2S_MODE_LTJ | CFG0_W_LENGTH_24BIT;
469 break;
470 case HDMI_I2S_MODE_LJT_16BIT:
471 val |= CFG0_I2S_MODE_LTJ | CFG0_W_LENGTH_16BIT;
472 break;
473 case HDMI_I2S_MODE_I2S_24BIT:
474 val |= CFG0_I2S_MODE_I2S | CFG0_W_LENGTH_24BIT;
475 break;
476 case HDMI_I2S_MODE_I2S_16BIT:
477 val |= CFG0_I2S_MODE_I2S | CFG0_W_LENGTH_16BIT;
478 break;
479 }
480 mtk_hdmi_write(hdmi, GRL_CFG0, val);
481}
482
483static void mtk_hdmi_hw_audio_config(struct mtk_hdmi *hdmi, bool dst)
484{
485 const u8 mask = HIGH_BIT_RATE | DST_NORMAL_DOUBLE | SACD_DST | DSD_SEL;
486 u8 val;
487
488 /* Disable high bitrate, set DST packet normal/double */
489 mtk_hdmi_clear_bits(hdmi, GRL_AOUT_CFG, HIGH_BIT_RATE_PACKET_ALIGN);
490
491 if (dst)
492 val = DST_NORMAL_DOUBLE | SACD_DST;
493 else
494 val = 0;
495
496 mtk_hdmi_mask(hdmi, GRL_AUDIO_CFG, val, mask);
497}
498
499static void mtk_hdmi_hw_aud_set_i2s_chan_num(struct mtk_hdmi *hdmi,
500 enum hdmi_aud_channel_type channel_type,
501 u8 channel_count)
502{
503 unsigned int ch_switch;
504 u8 i2s_uv;
505
506 ch_switch = CH_SWITCH(7, 7) | CH_SWITCH(6, 6) |
507 CH_SWITCH(5, 5) | CH_SWITCH(4, 4) |
508 CH_SWITCH(3, 3) | CH_SWITCH(1, 2) |
509 CH_SWITCH(2, 1) | CH_SWITCH(0, 0);
510
511 if (channel_count == 2) {
512 i2s_uv = I2S_UV_CH_EN(0);
513 } else if (channel_count == 3 || channel_count == 4) {
514 if (channel_count == 4 &&
515 (channel_type == HDMI_AUD_CHAN_TYPE_3_0_LRS ||
516 channel_type == HDMI_AUD_CHAN_TYPE_4_0))
517 i2s_uv = I2S_UV_CH_EN(2) | I2S_UV_CH_EN(0);
518 else
519 i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2);
520 } else if (channel_count == 6 || channel_count == 5) {
521 if (channel_count == 6 &&
522 channel_type != HDMI_AUD_CHAN_TYPE_5_1 &&
523 channel_type != HDMI_AUD_CHAN_TYPE_4_1_CLRS) {
524 i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2) |
525 I2S_UV_CH_EN(1) | I2S_UV_CH_EN(0);
526 } else {
527 i2s_uv = I2S_UV_CH_EN(2) | I2S_UV_CH_EN(1) |
528 I2S_UV_CH_EN(0);
529 }
530 } else if (channel_count == 8 || channel_count == 7) {
531 i2s_uv = I2S_UV_CH_EN(3) | I2S_UV_CH_EN(2) |
532 I2S_UV_CH_EN(1) | I2S_UV_CH_EN(0);
533 } else {
534 i2s_uv = I2S_UV_CH_EN(0);
535 }
536
537 mtk_hdmi_write(hdmi, GRL_CH_SW0, ch_switch & 0xff);
538 mtk_hdmi_write(hdmi, GRL_CH_SW1, (ch_switch >> 8) & 0xff);
539 mtk_hdmi_write(hdmi, GRL_CH_SW2, (ch_switch >> 16) & 0xff);
540 mtk_hdmi_write(hdmi, GRL_I2S_UV, i2s_uv);
541}
542
543static void mtk_hdmi_hw_aud_set_input_type(struct mtk_hdmi *hdmi,
544 enum hdmi_aud_input_type input_type)
545{
546 u32 val;
547
548 val = mtk_hdmi_read(hdmi, GRL_CFG1);
549 if (input_type == HDMI_AUD_INPUT_I2S &&
550 (val & CFG1_SPDIF) == CFG1_SPDIF) {
551 val &= ~CFG1_SPDIF;
552 } else if (input_type == HDMI_AUD_INPUT_SPDIF &&
553 (val & CFG1_SPDIF) == 0) {
554 val |= CFG1_SPDIF;
555 }
556 mtk_hdmi_write(hdmi, GRL_CFG1, val);
557}
558
559static void mtk_hdmi_hw_aud_set_channel_status(struct mtk_hdmi *hdmi,
560 u8 *channel_status)
561{
562 int i;
563
564 for (i = 0; i < 5; i++) {
565 mtk_hdmi_write(hdmi, GRL_I2S_C_STA0 + i * 4, channel_status[i]);
566 mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, channel_status[i]);
567 mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, channel_status[i]);
568 }
569 for (; i < 24; i++) {
570 mtk_hdmi_write(hdmi, GRL_L_STATUS_0 + i * 4, 0);
571 mtk_hdmi_write(hdmi, GRL_R_STATUS_0 + i * 4, 0);
572 }
573}
574
575static void mtk_hdmi_hw_aud_src_reenable(struct mtk_hdmi *hdmi)
576{
577 u32 val;
578
579 val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL);
580 if (val & MIX_CTRL_SRC_EN) {
581 val &= ~MIX_CTRL_SRC_EN;
582 mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val);
583 usleep_range(255, 512);
584 val |= MIX_CTRL_SRC_EN;
585 mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val);
586 }
587}
588
589static void mtk_hdmi_hw_aud_src_disable(struct mtk_hdmi *hdmi)
590{
591 u32 val;
592
593 val = mtk_hdmi_read(hdmi, GRL_MIX_CTRL);
594 val &= ~MIX_CTRL_SRC_EN;
595 mtk_hdmi_write(hdmi, GRL_MIX_CTRL, val);
596 mtk_hdmi_write(hdmi, GRL_SHIFT_L1, 0x00);
597}
598
599static void mtk_hdmi_hw_aud_set_mclk(struct mtk_hdmi *hdmi,
600 enum hdmi_aud_mclk mclk)
601{
602 u32 val;
603
604 val = mtk_hdmi_read(hdmi, GRL_CFG5);
605 val &= CFG5_CD_RATIO_MASK;
606
607 switch (mclk) {
608 case HDMI_AUD_MCLK_128FS:
609 val |= CFG5_FS128;
610 break;
611 case HDMI_AUD_MCLK_256FS:
612 val |= CFG5_FS256;
613 break;
614 case HDMI_AUD_MCLK_384FS:
615 val |= CFG5_FS384;
616 break;
617 case HDMI_AUD_MCLK_512FS:
618 val |= CFG5_FS512;
619 break;
620 case HDMI_AUD_MCLK_768FS:
621 val |= CFG5_FS768;
622 break;
623 default:
624 val |= CFG5_FS256;
625 break;
626 }
627 mtk_hdmi_write(hdmi, GRL_CFG5, val);
628}
629
630struct hdmi_acr_n {
631 unsigned int clock;
632 unsigned int n[3];
633};
634
635/* Recommended N values from HDMI specification, tables 7-1 to 7-3 */
636static const struct hdmi_acr_n hdmi_rec_n_table[] = {
637 /* Clock, N: 32kHz 44.1kHz 48kHz */
638 { 25175, { 4576, 7007, 6864 } },
639 { 74176, { 11648, 17836, 11648 } },
640 { 148352, { 11648, 8918, 5824 } },
641 { 296703, { 5824, 4459, 5824 } },
642 { 297000, { 3072, 4704, 5120 } },
643 { 0, { 4096, 6272, 6144 } }, /* all other TMDS clocks */
644};
645
646/**
647 * hdmi_recommended_n() - Return N value recommended by HDMI specification
648 * @freq: audio sample rate in Hz
649 * @clock: rounded TMDS clock in kHz
650 */
651static unsigned int hdmi_recommended_n(unsigned int freq, unsigned int clock)
652{
653 const struct hdmi_acr_n *recommended;
654 unsigned int i;
655
656 for (i = 0; i < ARRAY_SIZE(hdmi_rec_n_table) - 1; i++) {
657 if (clock == hdmi_rec_n_table[i].clock)
658 break;
659 }
660 recommended = hdmi_rec_n_table + i;
661
662 switch (freq) {
663 case 32000:
664 return recommended->n[0];
665 case 44100:
666 return recommended->n[1];
667 case 48000:
668 return recommended->n[2];
669 case 88200:
670 return recommended->n[1] * 2;
671 case 96000:
672 return recommended->n[2] * 2;
673 case 176400:
674 return recommended->n[1] * 4;
675 case 192000:
676 return recommended->n[2] * 4;
677 default:
678 return (128 * freq) / 1000;
679 }
680}
681
682static unsigned int hdmi_mode_clock_to_hz(unsigned int clock)
683{
684 switch (clock) {
685 case 25175:
686 return 25174825; /* 25.2/1.001 MHz */
687 case 74176:
688 return 74175824; /* 74.25/1.001 MHz */
689 case 148352:
690 return 148351648; /* 148.5/1.001 MHz */
691 case 296703:
692 return 296703297; /* 297/1.001 MHz */
693 default:
694 return clock * 1000;
695 }
696}
697
698static unsigned int hdmi_expected_cts(unsigned int audio_sample_rate,
699 unsigned int tmds_clock, unsigned int n)
700{
701 return DIV_ROUND_CLOSEST_ULL((u64)hdmi_mode_clock_to_hz(tmds_clock) * n,
702 128 * audio_sample_rate);
703}
704
705static void do_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi, unsigned int n,
706 unsigned int cts)
707{
708 unsigned char val[NCTS_BYTES];
709 int i;
710
711 mtk_hdmi_write(hdmi, GRL_NCTS, 0);
712 mtk_hdmi_write(hdmi, GRL_NCTS, 0);
713 mtk_hdmi_write(hdmi, GRL_NCTS, 0);
714 memset(val, 0, sizeof(val));
715
716 val[0] = (cts >> 24) & 0xff;
717 val[1] = (cts >> 16) & 0xff;
718 val[2] = (cts >> 8) & 0xff;
719 val[3] = cts & 0xff;
720
721 val[4] = (n >> 16) & 0xff;
722 val[5] = (n >> 8) & 0xff;
723 val[6] = n & 0xff;
724
725 for (i = 0; i < NCTS_BYTES; i++)
726 mtk_hdmi_write(hdmi, GRL_NCTS, val[i]);
727}
728
729static void mtk_hdmi_hw_aud_set_ncts(struct mtk_hdmi *hdmi,
730 unsigned int sample_rate,
731 unsigned int clock)
732{
733 unsigned int n, cts;
734
735 n = hdmi_recommended_n(sample_rate, clock);
736 cts = hdmi_expected_cts(sample_rate, clock, n);
737
738 dev_dbg(hdmi->dev, "%s: sample_rate=%u, clock=%d, cts=%u, n=%u\n",
739 __func__, sample_rate, clock, n, cts);
740
741 mtk_hdmi_mask(hdmi, DUMMY_304, AUDIO_I2S_NCTS_SEL_64,
742 AUDIO_I2S_NCTS_SEL);
743 do_hdmi_hw_aud_set_ncts(hdmi, n, cts);
744}
745
746static u8 mtk_hdmi_aud_get_chnl_count(enum hdmi_aud_channel_type channel_type)
747{
748 switch (channel_type) {
749 case HDMI_AUD_CHAN_TYPE_1_0:
750 case HDMI_AUD_CHAN_TYPE_1_1:
751 case HDMI_AUD_CHAN_TYPE_2_0:
752 return 2;
753 case HDMI_AUD_CHAN_TYPE_2_1:
754 case HDMI_AUD_CHAN_TYPE_3_0:
755 return 3;
756 case HDMI_AUD_CHAN_TYPE_3_1:
757 case HDMI_AUD_CHAN_TYPE_4_0:
758 case HDMI_AUD_CHAN_TYPE_3_0_LRS:
759 return 4;
760 case HDMI_AUD_CHAN_TYPE_4_1:
761 case HDMI_AUD_CHAN_TYPE_5_0:
762 case HDMI_AUD_CHAN_TYPE_3_1_LRS:
763 case HDMI_AUD_CHAN_TYPE_4_0_CLRS:
764 return 5;
765 case HDMI_AUD_CHAN_TYPE_5_1:
766 case HDMI_AUD_CHAN_TYPE_6_0:
767 case HDMI_AUD_CHAN_TYPE_4_1_CLRS:
768 case HDMI_AUD_CHAN_TYPE_6_0_CS:
769 case HDMI_AUD_CHAN_TYPE_6_0_CH:
770 case HDMI_AUD_CHAN_TYPE_6_0_OH:
771 case HDMI_AUD_CHAN_TYPE_6_0_CHR:
772 return 6;
773 case HDMI_AUD_CHAN_TYPE_6_1:
774 case HDMI_AUD_CHAN_TYPE_6_1_CS:
775 case HDMI_AUD_CHAN_TYPE_6_1_CH:
776 case HDMI_AUD_CHAN_TYPE_6_1_OH:
777 case HDMI_AUD_CHAN_TYPE_6_1_CHR:
778 case HDMI_AUD_CHAN_TYPE_7_0:
779 case HDMI_AUD_CHAN_TYPE_7_0_LH_RH:
780 case HDMI_AUD_CHAN_TYPE_7_0_LSR_RSR:
781 case HDMI_AUD_CHAN_TYPE_7_0_LC_RC:
782 case HDMI_AUD_CHAN_TYPE_7_0_LW_RW:
783 case HDMI_AUD_CHAN_TYPE_7_0_LSD_RSD:
784 case HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS:
785 case HDMI_AUD_CHAN_TYPE_7_0_LHS_RHS:
786 case HDMI_AUD_CHAN_TYPE_7_0_CS_CH:
787 case HDMI_AUD_CHAN_TYPE_7_0_CS_OH:
788 case HDMI_AUD_CHAN_TYPE_7_0_CS_CHR:
789 case HDMI_AUD_CHAN_TYPE_7_0_CH_OH:
790 case HDMI_AUD_CHAN_TYPE_7_0_CH_CHR:
791 case HDMI_AUD_CHAN_TYPE_7_0_OH_CHR:
792 case HDMI_AUD_CHAN_TYPE_7_0_LSS_RSS_LSR_RSR:
793 case HDMI_AUD_CHAN_TYPE_8_0_LH_RH_CS:
794 return 7;
795 case HDMI_AUD_CHAN_TYPE_7_1:
796 case HDMI_AUD_CHAN_TYPE_7_1_LH_RH:
797 case HDMI_AUD_CHAN_TYPE_7_1_LSR_RSR:
798 case HDMI_AUD_CHAN_TYPE_7_1_LC_RC:
799 case HDMI_AUD_CHAN_TYPE_7_1_LW_RW:
800 case HDMI_AUD_CHAN_TYPE_7_1_LSD_RSD:
801 case HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS:
802 case HDMI_AUD_CHAN_TYPE_7_1_LHS_RHS:
803 case HDMI_AUD_CHAN_TYPE_7_1_CS_CH:
804 case HDMI_AUD_CHAN_TYPE_7_1_CS_OH:
805 case HDMI_AUD_CHAN_TYPE_7_1_CS_CHR:
806 case HDMI_AUD_CHAN_TYPE_7_1_CH_OH:
807 case HDMI_AUD_CHAN_TYPE_7_1_CH_CHR:
808 case HDMI_AUD_CHAN_TYPE_7_1_OH_CHR:
809 case HDMI_AUD_CHAN_TYPE_7_1_LSS_RSS_LSR_RSR:
810 return 8;
811 default:
812 return 2;
813 }
814}
815
816static int mtk_hdmi_video_change_vpll(struct mtk_hdmi *hdmi, u32 clock)
817{
818 unsigned long rate;
819 int ret;
820
821 /* The DPI driver already should have set TVDPLL to the correct rate */
822 ret = clk_set_rate(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL], clock);
823 if (ret) {
824 dev_err(hdmi->dev, "Failed to set PLL to %u Hz: %d\n", clock,
825 ret);
826 return ret;
827 }
828
829 rate = clk_get_rate(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
830
831 if (DIV_ROUND_CLOSEST(rate, 1000) != DIV_ROUND_CLOSEST(clock, 1000))
832 dev_warn(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n", clock,
833 rate);
834 else
835 dev_dbg(hdmi->dev, "Want PLL %u Hz, got %lu Hz\n", clock, rate);
836
837 mtk_hdmi_hw_config_sys(hdmi);
838 mtk_hdmi_hw_set_deep_color_mode(hdmi);
839 return 0;
840}
841
842static void mtk_hdmi_video_set_display_mode(struct mtk_hdmi *hdmi,
843 struct drm_display_mode *mode)
844{
845 mtk_hdmi_hw_reset(hdmi);
846 mtk_hdmi_hw_enable_notice(hdmi, true);
847 mtk_hdmi_hw_write_int_mask(hdmi, 0xff);
848 mtk_hdmi_hw_enable_dvi_mode(hdmi, hdmi->dvi_mode);
849 mtk_hdmi_hw_ncts_auto_write_enable(hdmi, true);
850
851 mtk_hdmi_hw_msic_setting(hdmi, mode);
852}
853
854static int mtk_hdmi_aud_enable_packet(struct mtk_hdmi *hdmi, bool enable)
855{
856 mtk_hdmi_hw_send_aud_packet(hdmi, enable);
857 return 0;
858}
859
860static int mtk_hdmi_aud_on_off_hw_ncts(struct mtk_hdmi *hdmi, bool on)
861{
862 mtk_hdmi_hw_ncts_enable(hdmi, on);
863 return 0;
864}
865
866static int mtk_hdmi_aud_set_input(struct mtk_hdmi *hdmi)
867{
868 enum hdmi_aud_channel_type chan_type;
869 u8 chan_count;
870 bool dst;
871
872 mtk_hdmi_hw_aud_set_channel_swap(hdmi, HDMI_AUD_SWAP_LFE_CC);
873 mtk_hdmi_set_bits(hdmi, GRL_MIX_CTRL, MIX_CTRL_FLAT);
874
875 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF &&
876 hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST) {
877 mtk_hdmi_hw_aud_set_bit_num(hdmi, HDMI_AUDIO_SAMPLE_SIZE_24);
878 } else if (hdmi->aud_param.aud_i2s_fmt == HDMI_I2S_MODE_LJT_24BIT) {
879 hdmi->aud_param.aud_i2s_fmt = HDMI_I2S_MODE_LJT_16BIT;
880 }
881
882 mtk_hdmi_hw_aud_set_i2s_fmt(hdmi, hdmi->aud_param.aud_i2s_fmt);
883 mtk_hdmi_hw_aud_set_bit_num(hdmi, HDMI_AUDIO_SAMPLE_SIZE_24);
884
885 dst = ((hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF) &&
886 (hdmi->aud_param.aud_codec == HDMI_AUDIO_CODING_TYPE_DST));
887 mtk_hdmi_hw_audio_config(hdmi, dst);
888
889 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_SPDIF)
890 chan_type = HDMI_AUD_CHAN_TYPE_2_0;
891 else
892 chan_type = hdmi->aud_param.aud_input_chan_type;
893 chan_count = mtk_hdmi_aud_get_chnl_count(chan_type);
894 mtk_hdmi_hw_aud_set_i2s_chan_num(hdmi, chan_type, chan_count);
895 mtk_hdmi_hw_aud_set_input_type(hdmi, hdmi->aud_param.aud_input_type);
896
897 return 0;
898}
899
900static int mtk_hdmi_aud_set_src(struct mtk_hdmi *hdmi,
901 struct drm_display_mode *display_mode)
902{
903 unsigned int sample_rate = hdmi->aud_param.codec_params.sample_rate;
904
905 mtk_hdmi_aud_on_off_hw_ncts(hdmi, false);
906 mtk_hdmi_hw_aud_src_disable(hdmi);
907 mtk_hdmi_clear_bits(hdmi, GRL_CFG2, CFG2_ACLK_INV);
908
909 if (hdmi->aud_param.aud_input_type == HDMI_AUD_INPUT_I2S) {
910 switch (sample_rate) {
911 case 32000:
912 case 44100:
913 case 48000:
914 case 88200:
915 case 96000:
916 break;
917 default:
918 return -EINVAL;
919 }
920 mtk_hdmi_hw_aud_set_mclk(hdmi, hdmi->aud_param.aud_mclk);
921 } else {
922 switch (sample_rate) {
923 case 32000:
924 case 44100:
925 case 48000:
926 break;
927 default:
928 return -EINVAL;
929 }
930 mtk_hdmi_hw_aud_set_mclk(hdmi, HDMI_AUD_MCLK_128FS);
931 }
932
933 mtk_hdmi_hw_aud_set_ncts(hdmi, sample_rate, display_mode->clock);
934
935 mtk_hdmi_hw_aud_src_reenable(hdmi);
936 return 0;
937}
938
939static int mtk_hdmi_aud_output_config(struct mtk_hdmi *hdmi,
940 struct drm_display_mode *display_mode)
941{
942 mtk_hdmi_hw_aud_mute(hdmi);
943 mtk_hdmi_aud_enable_packet(hdmi, false);
944
945 mtk_hdmi_aud_set_input(hdmi);
946 mtk_hdmi_aud_set_src(hdmi, display_mode);
947 mtk_hdmi_hw_aud_set_channel_status(hdmi,
948 hdmi->aud_param.codec_params.iec.status);
949
950 usleep_range(50, 100);
951
952 mtk_hdmi_aud_on_off_hw_ncts(hdmi, true);
953 mtk_hdmi_aud_enable_packet(hdmi, true);
954 mtk_hdmi_hw_aud_unmute(hdmi);
955 return 0;
956}
957
958static int mtk_hdmi_setup_avi_infoframe(struct mtk_hdmi *hdmi,
959 struct drm_display_mode *mode)
960{
961 struct hdmi_avi_infoframe frame;
962 u8 buffer[17];
963 ssize_t err;
964
965 err = drm_hdmi_avi_infoframe_from_display_mode(&frame, mode);
966 if (err < 0) {
967 dev_err(hdmi->dev,
968 "Failed to get AVI infoframe from mode: %zd\n", err);
969 return err;
970 }
971
972 err = hdmi_avi_infoframe_pack(&frame, buffer, sizeof(buffer));
973 if (err < 0) {
974 dev_err(hdmi->dev, "Failed to pack AVI infoframe: %zd\n", err);
975 return err;
976 }
977
978 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
979 return 0;
980}
981
982static int mtk_hdmi_setup_spd_infoframe(struct mtk_hdmi *hdmi,
983 const char *vendor,
984 const char *product)
985{
986 struct hdmi_spd_infoframe frame;
987 u8 buffer[29];
988 ssize_t err;
989
990 err = hdmi_spd_infoframe_init(&frame, vendor, product);
991 if (err < 0) {
992 dev_err(hdmi->dev, "Failed to initialize SPD infoframe: %zd\n",
993 err);
994 return err;
995 }
996
997 err = hdmi_spd_infoframe_pack(&frame, buffer, sizeof(buffer));
998 if (err < 0) {
999 dev_err(hdmi->dev, "Failed to pack SDP infoframe: %zd\n", err);
1000 return err;
1001 }
1002
1003 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
1004 return 0;
1005}
1006
1007static int mtk_hdmi_setup_audio_infoframe(struct mtk_hdmi *hdmi)
1008{
1009 struct hdmi_audio_infoframe frame;
1010 u8 buffer[14];
1011 ssize_t err;
1012
1013 err = hdmi_audio_infoframe_init(&frame);
1014 if (err < 0) {
1015 dev_err(hdmi->dev, "Failed to setup audio infoframe: %zd\n",
1016 err);
1017 return err;
1018 }
1019
1020 frame.coding_type = HDMI_AUDIO_CODING_TYPE_STREAM;
1021 frame.sample_frequency = HDMI_AUDIO_SAMPLE_FREQUENCY_STREAM;
1022 frame.sample_size = HDMI_AUDIO_SAMPLE_SIZE_STREAM;
1023 frame.channels = mtk_hdmi_aud_get_chnl_count(
1024 hdmi->aud_param.aud_input_chan_type);
1025
1026 err = hdmi_audio_infoframe_pack(&frame, buffer, sizeof(buffer));
1027 if (err < 0) {
1028 dev_err(hdmi->dev, "Failed to pack audio infoframe: %zd\n",
1029 err);
1030 return err;
1031 }
1032
1033 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
1034 return 0;
1035}
1036
1037static int mtk_hdmi_setup_vendor_specific_infoframe(struct mtk_hdmi *hdmi,
1038 struct drm_display_mode *mode)
1039{
1040 struct hdmi_vendor_infoframe frame;
1041 u8 buffer[10];
1042 ssize_t err;
1043
1044 err = drm_hdmi_vendor_infoframe_from_display_mode(&frame, mode);
1045 if (err) {
1046 dev_err(hdmi->dev,
1047 "Failed to get vendor infoframe from mode: %zd\n", err);
1048 return err;
1049 }
1050
1051 err = hdmi_vendor_infoframe_pack(&frame, buffer, sizeof(buffer));
1052 if (err) {
1053 dev_err(hdmi->dev, "Failed to pack vendor infoframe: %zd\n",
1054 err);
1055 return err;
1056 }
1057
1058 mtk_hdmi_hw_send_info_frame(hdmi, buffer, sizeof(buffer));
1059 return 0;
1060}
1061
1062static int mtk_hdmi_output_init(struct mtk_hdmi *hdmi)
1063{
1064 struct hdmi_audio_param *aud_param = &hdmi->aud_param;
1065
1066 hdmi->csp = HDMI_COLORSPACE_RGB;
1067 aud_param->aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
1068 aud_param->aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
1069 aud_param->aud_input_type = HDMI_AUD_INPUT_I2S;
1070 aud_param->aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
1071 aud_param->aud_mclk = HDMI_AUD_MCLK_128FS;
1072 aud_param->aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0;
1073
1074 return 0;
1075}
1076
1077void mtk_hdmi_audio_enable(struct mtk_hdmi *hdmi)
1078{
1079 mtk_hdmi_aud_enable_packet(hdmi, true);
1080 hdmi->audio_enable = true;
1081}
1082
1083void mtk_hdmi_audio_disable(struct mtk_hdmi *hdmi)
1084{
1085 mtk_hdmi_aud_enable_packet(hdmi, false);
1086 hdmi->audio_enable = false;
1087}
1088
1089int mtk_hdmi_audio_set_param(struct mtk_hdmi *hdmi,
1090 struct hdmi_audio_param *param)
1091{
1092 if (!hdmi->audio_enable) {
1093 dev_err(hdmi->dev, "hdmi audio is in disable state!\n");
1094 return -EINVAL;
1095 }
1096 dev_dbg(hdmi->dev, "codec:%d, input:%d, channel:%d, fs:%d\n",
1097 param->aud_codec, param->aud_input_type,
1098 param->aud_input_chan_type, param->codec_params.sample_rate);
1099 memcpy(&hdmi->aud_param, param, sizeof(*param));
1100 return mtk_hdmi_aud_output_config(hdmi, &hdmi->mode);
1101}
1102
1103static int mtk_hdmi_output_set_display_mode(struct mtk_hdmi *hdmi,
1104 struct drm_display_mode *mode)
1105{
1106 int ret;
1107
1108 mtk_hdmi_hw_vid_black(hdmi, true);
1109 mtk_hdmi_hw_aud_mute(hdmi);
1110 mtk_hdmi_hw_send_av_mute(hdmi);
1111 phy_power_off(hdmi->phy);
1112
1113 ret = mtk_hdmi_video_change_vpll(hdmi,
1114 mode->clock * 1000);
1115 if (ret) {
1116 dev_err(hdmi->dev, "Failed to set vpll: %d\n", ret);
1117 return ret;
1118 }
1119 mtk_hdmi_video_set_display_mode(hdmi, mode);
1120
1121 phy_power_on(hdmi->phy);
1122 mtk_hdmi_aud_output_config(hdmi, mode);
1123
1124 mtk_hdmi_setup_audio_infoframe(hdmi);
1125 mtk_hdmi_setup_avi_infoframe(hdmi, mode);
1126 mtk_hdmi_setup_spd_infoframe(hdmi, "mediatek", "On-chip HDMI");
1127 if (mode->flags & DRM_MODE_FLAG_3D_MASK)
1128 mtk_hdmi_setup_vendor_specific_infoframe(hdmi, mode);
1129
1130 mtk_hdmi_hw_vid_black(hdmi, false);
1131 mtk_hdmi_hw_aud_unmute(hdmi);
1132 mtk_hdmi_hw_send_av_unmute(hdmi);
1133
1134 return 0;
1135}
1136
1137static const char * const mtk_hdmi_clk_names[MTK_HDMI_CLK_COUNT] = {
1138 [MTK_HDMI_CLK_HDMI_PIXEL] = "pixel",
1139 [MTK_HDMI_CLK_HDMI_PLL] = "pll",
1140 [MTK_HDMI_CLK_AUD_BCLK] = "bclk",
1141 [MTK_HDMI_CLK_AUD_SPDIF] = "spdif",
1142};
1143
1144static int mtk_hdmi_get_all_clk(struct mtk_hdmi *hdmi,
1145 struct device_node *np)
1146{
1147 int i;
1148
1149 for (i = 0; i < ARRAY_SIZE(mtk_hdmi_clk_names); i++) {
1150 hdmi->clk[i] = of_clk_get_by_name(np,
1151 mtk_hdmi_clk_names[i]);
1152 if (IS_ERR(hdmi->clk[i]))
1153 return PTR_ERR(hdmi->clk[i]);
1154 }
1155 return 0;
1156}
1157
1158static int mtk_hdmi_clk_enable_audio(struct mtk_hdmi *hdmi)
1159{
1160 int ret;
1161
1162 ret = clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1163 if (ret)
1164 return ret;
1165
1166 ret = clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]);
1167 if (ret)
1168 goto err;
1169
1170 return 0;
1171err:
1172 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1173 return ret;
1174}
1175
1176static void mtk_hdmi_clk_disable_audio(struct mtk_hdmi *hdmi)
1177{
1178 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_BCLK]);
1179 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_AUD_SPDIF]);
1180}
1181
1182static enum drm_connector_status hdmi_conn_detect(struct drm_connector *conn,
1183 bool force)
1184{
1185 struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
1186
1187 return mtk_cec_hpd_high(hdmi->cec_dev) ?
1188 connector_status_connected : connector_status_disconnected;
1189}
1190
1191static void hdmi_conn_destroy(struct drm_connector *conn)
1192{
1193 struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
1194
1195 mtk_cec_set_hpd_event(hdmi->cec_dev, NULL, NULL);
1196
1197 drm_connector_cleanup(conn);
1198}
1199
1200static int mtk_hdmi_conn_get_modes(struct drm_connector *conn)
1201{
1202 struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
1203 struct edid *edid;
1204 int ret;
1205
1206 if (!hdmi->ddc_adpt)
1207 return -ENODEV;
1208
1209 edid = drm_get_edid(conn, hdmi->ddc_adpt);
1210 if (!edid)
1211 return -ENODEV;
1212
1213 hdmi->dvi_mode = !drm_detect_monitor_audio(edid);
1214
1215 drm_mode_connector_update_edid_property(conn, edid);
1216
1217 ret = drm_add_edid_modes(conn, edid);
1218 drm_edid_to_eld(conn, edid);
1219 kfree(edid);
1220 return ret;
1221}
1222
1223static int mtk_hdmi_conn_mode_valid(struct drm_connector *conn,
1224 struct drm_display_mode *mode)
1225{
1226 struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
1227
1228 dev_dbg(hdmi->dev, "xres=%d, yres=%d, refresh=%d, intl=%d clock=%d\n",
1229 mode->hdisplay, mode->vdisplay, mode->vrefresh,
1230 !!(mode->flags & DRM_MODE_FLAG_INTERLACE), mode->clock * 1000);
1231
1232 if (hdmi->bridge.next) {
1233 struct drm_display_mode adjusted_mode;
1234
1235 drm_mode_copy(&adjusted_mode, mode);
1236 if (!drm_bridge_mode_fixup(hdmi->bridge.next, mode,
1237 &adjusted_mode))
1238 return MODE_BAD;
1239 }
1240
1241 if (mode->clock < 27000)
1242 return MODE_CLOCK_LOW;
1243 if (mode->clock > 297000)
1244 return MODE_CLOCK_HIGH;
1245
1246 return drm_mode_validate_size(mode, 0x1fff, 0x1fff);
1247}
1248
1249static struct drm_encoder *mtk_hdmi_conn_best_enc(struct drm_connector *conn)
1250{
1251 struct mtk_hdmi *hdmi = hdmi_ctx_from_conn(conn);
1252
1253 return hdmi->bridge.encoder;
1254}
1255
1256static const struct drm_connector_funcs mtk_hdmi_connector_funcs = {
1257 .dpms = drm_atomic_helper_connector_dpms,
1258 .detect = hdmi_conn_detect,
1259 .fill_modes = drm_helper_probe_single_connector_modes,
1260 .destroy = hdmi_conn_destroy,
1261 .reset = drm_atomic_helper_connector_reset,
1262 .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1263 .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1264};
1265
1266static const struct drm_connector_helper_funcs
1267 mtk_hdmi_connector_helper_funcs = {
1268 .get_modes = mtk_hdmi_conn_get_modes,
1269 .mode_valid = mtk_hdmi_conn_mode_valid,
1270 .best_encoder = mtk_hdmi_conn_best_enc,
1271};
1272
1273static void mtk_hdmi_hpd_event(bool hpd, struct device *dev)
1274{
1275 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1276
1277 if (hdmi && hdmi->bridge.encoder && hdmi->bridge.encoder->dev)
1278 drm_helper_hpd_irq_event(hdmi->bridge.encoder->dev);
1279}
1280
1281/*
1282 * Bridge callbacks
1283 */
1284
1285static int mtk_hdmi_bridge_attach(struct drm_bridge *bridge)
1286{
1287 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1288 int ret;
1289
1290 ret = drm_connector_init(bridge->encoder->dev, &hdmi->conn,
1291 &mtk_hdmi_connector_funcs,
1292 DRM_MODE_CONNECTOR_HDMIA);
1293 if (ret) {
1294 dev_err(hdmi->dev, "Failed to initialize connector: %d\n", ret);
1295 return ret;
1296 }
1297 drm_connector_helper_add(&hdmi->conn, &mtk_hdmi_connector_helper_funcs);
1298
1299 hdmi->conn.polled = DRM_CONNECTOR_POLL_HPD;
1300 hdmi->conn.interlace_allowed = true;
1301 hdmi->conn.doublescan_allowed = false;
1302
1303 ret = drm_mode_connector_attach_encoder(&hdmi->conn,
1304 bridge->encoder);
1305 if (ret) {
1306 dev_err(hdmi->dev,
1307 "Failed to attach connector to encoder: %d\n", ret);
1308 return ret;
1309 }
1310
1311 if (bridge->next) {
1312 bridge->next->encoder = bridge->encoder;
1313 ret = drm_bridge_attach(bridge->encoder->dev, bridge->next);
1314 if (ret) {
1315 dev_err(hdmi->dev,
1316 "Failed to attach external bridge: %d\n", ret);
1317 return ret;
1318 }
1319 }
1320
1321 mtk_cec_set_hpd_event(hdmi->cec_dev, mtk_hdmi_hpd_event, hdmi->dev);
1322
1323 return 0;
1324}
1325
1326static bool mtk_hdmi_bridge_mode_fixup(struct drm_bridge *bridge,
1327 const struct drm_display_mode *mode,
1328 struct drm_display_mode *adjusted_mode)
1329{
1330 return true;
1331}
1332
1333static void mtk_hdmi_bridge_disable(struct drm_bridge *bridge)
1334{
1335 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1336
1337 if (!hdmi->enabled)
1338 return;
1339
1340 phy_power_off(hdmi->phy);
1341 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]);
1342 clk_disable_unprepare(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
1343
1344 hdmi->enabled = false;
1345}
1346
1347static void mtk_hdmi_bridge_post_disable(struct drm_bridge *bridge)
1348{
1349 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1350
1351 if (!hdmi->powered)
1352 return;
1353
1354 mtk_hdmi_hw_1p4_version_enable(hdmi, true);
1355 mtk_hdmi_hw_make_reg_writable(hdmi, false);
1356
1357 hdmi->powered = false;
1358}
1359
1360static void mtk_hdmi_bridge_mode_set(struct drm_bridge *bridge,
1361 struct drm_display_mode *mode,
1362 struct drm_display_mode *adjusted_mode)
1363{
1364 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1365
1366 dev_dbg(hdmi->dev, "cur info: name:%s, hdisplay:%d\n",
1367 adjusted_mode->name, adjusted_mode->hdisplay);
1368 dev_dbg(hdmi->dev, "hsync_start:%d,hsync_end:%d, htotal:%d",
1369 adjusted_mode->hsync_start, adjusted_mode->hsync_end,
1370 adjusted_mode->htotal);
1371 dev_dbg(hdmi->dev, "hskew:%d, vdisplay:%d\n",
1372 adjusted_mode->hskew, adjusted_mode->vdisplay);
1373 dev_dbg(hdmi->dev, "vsync_start:%d, vsync_end:%d, vtotal:%d",
1374 adjusted_mode->vsync_start, adjusted_mode->vsync_end,
1375 adjusted_mode->vtotal);
1376 dev_dbg(hdmi->dev, "vscan:%d, flag:%d\n",
1377 adjusted_mode->vscan, adjusted_mode->flags);
1378
1379 drm_mode_copy(&hdmi->mode, adjusted_mode);
1380}
1381
1382static void mtk_hdmi_bridge_pre_enable(struct drm_bridge *bridge)
1383{
1384 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1385
1386 mtk_hdmi_hw_make_reg_writable(hdmi, true);
1387 mtk_hdmi_hw_1p4_version_enable(hdmi, true);
1388
1389 hdmi->powered = true;
1390}
1391
1392static void mtk_hdmi_bridge_enable(struct drm_bridge *bridge)
1393{
1394 struct mtk_hdmi *hdmi = hdmi_ctx_from_bridge(bridge);
1395
1396 mtk_hdmi_output_set_display_mode(hdmi, &hdmi->mode);
1397 clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PLL]);
1398 clk_prepare_enable(hdmi->clk[MTK_HDMI_CLK_HDMI_PIXEL]);
1399 phy_power_on(hdmi->phy);
1400
1401 hdmi->enabled = true;
1402}
1403
1404static const struct drm_bridge_funcs mtk_hdmi_bridge_funcs = {
1405 .attach = mtk_hdmi_bridge_attach,
1406 .mode_fixup = mtk_hdmi_bridge_mode_fixup,
1407 .disable = mtk_hdmi_bridge_disable,
1408 .post_disable = mtk_hdmi_bridge_post_disable,
1409 .mode_set = mtk_hdmi_bridge_mode_set,
1410 .pre_enable = mtk_hdmi_bridge_pre_enable,
1411 .enable = mtk_hdmi_bridge_enable,
1412};
1413
1414static int mtk_hdmi_dt_parse_pdata(struct mtk_hdmi *hdmi,
1415 struct platform_device *pdev)
1416{
1417 struct device *dev = &pdev->dev;
1418 struct device_node *np = dev->of_node;
1419 struct device_node *cec_np, *port, *ep, *remote, *i2c_np;
1420 struct platform_device *cec_pdev;
1421 struct regmap *regmap;
1422 struct resource *mem;
1423 int ret;
1424
1425 ret = mtk_hdmi_get_all_clk(hdmi, np);
1426 if (ret) {
1427 dev_err(dev, "Failed to get clocks: %d\n", ret);
1428 return ret;
1429 }
1430
1431 /* The CEC module handles HDMI hotplug detection */
1432 cec_np = of_find_compatible_node(np->parent, NULL,
1433 "mediatek,mt8173-cec");
1434 if (!cec_np) {
1435 dev_err(dev, "Failed to find CEC node\n");
1436 return -EINVAL;
1437 }
1438
1439 cec_pdev = of_find_device_by_node(cec_np);
1440 if (!cec_pdev) {
1441 dev_err(hdmi->dev, "Waiting for CEC device %s\n",
1442 cec_np->full_name);
1443 return -EPROBE_DEFER;
1444 }
1445 hdmi->cec_dev = &cec_pdev->dev;
1446
1447 /*
1448 * The mediatek,syscon-hdmi property contains a phandle link to the
1449 * MMSYS_CONFIG device and the register offset of the HDMI_SYS_CFG
1450 * registers it contains.
1451 */
1452 regmap = syscon_regmap_lookup_by_phandle(np, "mediatek,syscon-hdmi");
1453 ret = of_property_read_u32_index(np, "mediatek,syscon-hdmi", 1,
1454 &hdmi->sys_offset);
1455 if (IS_ERR(regmap))
1456 ret = PTR_ERR(regmap);
1457 if (ret) {
1458 ret = PTR_ERR(regmap);
1459 dev_err(dev,
1460 "Failed to get system configuration registers: %d\n",
1461 ret);
1462 return ret;
1463 }
1464 hdmi->sys_regmap = regmap;
1465
1466 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1467 hdmi->regs = devm_ioremap_resource(dev, mem);
1468 if (IS_ERR(hdmi->regs))
1469 return PTR_ERR(hdmi->regs);
1470
1471 port = of_graph_get_port_by_id(np, 1);
1472 if (!port) {
1473 dev_err(dev, "Missing output port node\n");
1474 return -EINVAL;
1475 }
1476
1477 ep = of_get_child_by_name(port, "endpoint");
1478 if (!ep) {
1479 dev_err(dev, "Missing endpoint node in port %s\n",
1480 port->full_name);
1481 of_node_put(port);
1482 return -EINVAL;
1483 }
1484 of_node_put(port);
1485
1486 remote = of_graph_get_remote_port_parent(ep);
1487 if (!remote) {
1488 dev_err(dev, "Missing connector/bridge node for endpoint %s\n",
1489 ep->full_name);
1490 of_node_put(ep);
1491 return -EINVAL;
1492 }
1493 of_node_put(ep);
1494
1495 if (!of_device_is_compatible(remote, "hdmi-connector")) {
1496 hdmi->bridge.next = of_drm_find_bridge(remote);
1497 if (!hdmi->bridge.next) {
1498 dev_err(dev, "Waiting for external bridge\n");
1499 of_node_put(remote);
1500 return -EPROBE_DEFER;
1501 }
1502 }
1503
1504 i2c_np = of_parse_phandle(remote, "ddc-i2c-bus", 0);
1505 if (!i2c_np) {
1506 dev_err(dev, "Failed to find ddc-i2c-bus node in %s\n",
1507 remote->full_name);
1508 of_node_put(remote);
1509 return -EINVAL;
1510 }
1511 of_node_put(remote);
1512
1513 hdmi->ddc_adpt = of_find_i2c_adapter_by_node(i2c_np);
1514 if (!hdmi->ddc_adpt) {
1515 dev_err(dev, "Failed to get ddc i2c adapter by node\n");
1516 return -EINVAL;
1517 }
1518
1519 return 0;
1520}
1521
1522/*
1523 * HDMI audio codec callbacks
1524 */
1525
1526static int mtk_hdmi_audio_hw_params(struct device *dev,
1527 struct hdmi_codec_daifmt *daifmt,
1528 struct hdmi_codec_params *params)
1529{
1530 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1531 struct hdmi_audio_param hdmi_params;
1532 unsigned int chan = params->cea.channels;
1533
1534 dev_dbg(hdmi->dev, "%s: %u Hz, %d bit, %d channels\n", __func__,
1535 params->sample_rate, params->sample_width, chan);
1536
1537 if (!hdmi->bridge.encoder)
1538 return -ENODEV;
1539
1540 switch (chan) {
1541 case 2:
1542 hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_2_0;
1543 break;
1544 case 4:
1545 hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_4_0;
1546 break;
1547 case 6:
1548 hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_5_1;
1549 break;
1550 case 8:
1551 hdmi_params.aud_input_chan_type = HDMI_AUD_CHAN_TYPE_7_1;
1552 break;
1553 default:
1554 dev_err(hdmi->dev, "channel[%d] not supported!\n", chan);
1555 return -EINVAL;
1556 }
1557
1558 switch (params->sample_rate) {
1559 case 32000:
1560 case 44100:
1561 case 48000:
1562 case 88200:
1563 case 96000:
1564 case 176400:
1565 case 192000:
1566 break;
1567 default:
1568 dev_err(hdmi->dev, "rate[%d] not supported!\n",
1569 params->sample_rate);
1570 return -EINVAL;
1571 }
1572
1573 switch (daifmt->fmt) {
1574 case HDMI_I2S:
1575 hdmi_params.aud_codec = HDMI_AUDIO_CODING_TYPE_PCM;
1576 hdmi_params.aud_sampe_size = HDMI_AUDIO_SAMPLE_SIZE_16;
1577 hdmi_params.aud_input_type = HDMI_AUD_INPUT_I2S;
1578 hdmi_params.aud_i2s_fmt = HDMI_I2S_MODE_I2S_24BIT;
1579 hdmi_params.aud_mclk = HDMI_AUD_MCLK_128FS;
1580 break;
1581 default:
1582 dev_err(hdmi->dev, "%s: Invalid DAI format %d\n", __func__,
1583 daifmt->fmt);
1584 return -EINVAL;
1585 }
1586
1587 memcpy(&hdmi_params.codec_params, params,
1588 sizeof(hdmi_params.codec_params));
1589
1590 mtk_hdmi_audio_set_param(hdmi, &hdmi_params);
1591
1592 return 0;
1593}
1594
1595static int mtk_hdmi_audio_startup(struct device *dev)
1596{
1597 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1598
1599 dev_dbg(dev, "%s\n", __func__);
1600
1601 mtk_hdmi_audio_enable(hdmi);
1602
1603 return 0;
1604}
1605
1606static void mtk_hdmi_audio_shutdown(struct device *dev)
1607{
1608 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1609
1610 dev_dbg(dev, "%s\n", __func__);
1611
1612 mtk_hdmi_audio_disable(hdmi);
1613}
1614
1615int mtk_hdmi_audio_digital_mute(struct device *dev, bool enable)
1616{
1617 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1618
1619 dev_dbg(dev, "%s(%d)\n", __func__, enable);
1620
1621 if (enable)
1622 mtk_hdmi_hw_aud_mute(hdmi);
1623 else
1624 mtk_hdmi_hw_aud_unmute(hdmi);
1625
1626 return 0;
1627}
1628
1629static int mtk_hdmi_audio_get_eld(struct device *dev, uint8_t *buf, size_t len)
1630{
1631 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1632
1633 dev_dbg(dev, "%s\n", __func__);
1634
1635 memcpy(buf, hdmi->conn.eld, min(sizeof(hdmi->conn.eld), len));
1636
1637 return 0;
1638}
1639
1640static const struct hdmi_codec_ops mtk_hdmi_audio_codec_ops = {
1641 .hw_params = mtk_hdmi_audio_hw_params,
1642 .audio_startup = mtk_hdmi_audio_startup,
1643 .audio_shutdown = mtk_hdmi_audio_shutdown,
1644 .digital_mute = mtk_hdmi_audio_digital_mute,
1645 .get_eld = mtk_hdmi_audio_get_eld,
1646};
1647
1648static void mtk_hdmi_register_audio_driver(struct device *dev)
1649{
1650 struct hdmi_codec_pdata codec_data = {
1651 .ops = &mtk_hdmi_audio_codec_ops,
1652 .max_i2s_channels = 2,
1653 .i2s = 1,
1654 };
1655 struct platform_device *pdev;
1656
1657 pdev = platform_device_register_data(dev, HDMI_CODEC_DRV_NAME,
1658 PLATFORM_DEVID_AUTO, &codec_data,
1659 sizeof(codec_data));
1660 if (IS_ERR(pdev))
1661 return;
1662
1663 DRM_INFO("%s driver bound to HDMI\n", HDMI_CODEC_DRV_NAME);
1664}
1665
1666static int mtk_drm_hdmi_probe(struct platform_device *pdev)
1667{
1668 struct mtk_hdmi *hdmi;
1669 struct device *dev = &pdev->dev;
1670 int ret;
1671
1672 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1673 if (!hdmi)
1674 return -ENOMEM;
1675
1676 hdmi->dev = dev;
1677
1678 ret = mtk_hdmi_dt_parse_pdata(hdmi, pdev);
1679 if (ret)
1680 return ret;
1681
1682 hdmi->phy = devm_phy_get(dev, "hdmi");
1683 if (IS_ERR(hdmi->phy)) {
1684 ret = PTR_ERR(hdmi->phy);
1685 dev_err(dev, "Failed to get HDMI PHY: %d\n", ret);
1686 return ret;
1687 }
1688
1689 platform_set_drvdata(pdev, hdmi);
1690
1691 ret = mtk_hdmi_output_init(hdmi);
1692 if (ret) {
1693 dev_err(dev, "Failed to initialize hdmi output\n");
1694 return ret;
1695 }
1696
1697 mtk_hdmi_register_audio_driver(dev);
1698
1699 hdmi->bridge.funcs = &mtk_hdmi_bridge_funcs;
1700 hdmi->bridge.of_node = pdev->dev.of_node;
1701 ret = drm_bridge_add(&hdmi->bridge);
1702 if (ret) {
1703 dev_err(dev, "failed to add bridge, ret = %d\n", ret);
1704 return ret;
1705 }
1706
1707 ret = mtk_hdmi_clk_enable_audio(hdmi);
1708 if (ret) {
1709 dev_err(dev, "Failed to enable audio clocks: %d\n", ret);
1710 goto err_bridge_remove;
1711 }
1712
1713 dev_dbg(dev, "mediatek hdmi probe success\n");
1714 return 0;
1715
1716err_bridge_remove:
1717 drm_bridge_remove(&hdmi->bridge);
1718 return ret;
1719}
1720
1721static int mtk_drm_hdmi_remove(struct platform_device *pdev)
1722{
1723 struct mtk_hdmi *hdmi = platform_get_drvdata(pdev);
1724
1725 drm_bridge_remove(&hdmi->bridge);
1726 mtk_hdmi_clk_disable_audio(hdmi);
1727 return 0;
1728}
1729
1730#ifdef CONFIG_PM_SLEEP
1731static int mtk_hdmi_suspend(struct device *dev)
1732{
1733 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1734
1735 mtk_hdmi_clk_disable_audio(hdmi);
1736 dev_dbg(dev, "hdmi suspend success!\n");
1737 return 0;
1738}
1739
1740static int mtk_hdmi_resume(struct device *dev)
1741{
1742 struct mtk_hdmi *hdmi = dev_get_drvdata(dev);
1743 int ret = 0;
1744
1745 ret = mtk_hdmi_clk_enable_audio(hdmi);
1746 if (ret) {
1747 dev_err(dev, "hdmi resume failed!\n");
1748 return ret;
1749 }
1750
1751 dev_dbg(dev, "hdmi resume success!\n");
1752 return 0;
1753}
1754#endif
1755static SIMPLE_DEV_PM_OPS(mtk_hdmi_pm_ops,
1756 mtk_hdmi_suspend, mtk_hdmi_resume);
1757
1758static const struct of_device_id mtk_drm_hdmi_of_ids[] = {
1759 { .compatible = "mediatek,mt8173-hdmi", },
1760 {}
1761};
1762
1763static struct platform_driver mtk_hdmi_driver = {
1764 .probe = mtk_drm_hdmi_probe,
1765 .remove = mtk_drm_hdmi_remove,
1766 .driver = {
1767 .name = "mediatek-drm-hdmi",
1768 .of_match_table = mtk_drm_hdmi_of_ids,
1769 .pm = &mtk_hdmi_pm_ops,
1770 },
1771};
1772
1773static struct platform_driver * const mtk_hdmi_drivers[] = {
1774 &mtk_hdmi_phy_driver,
1775 &mtk_hdmi_ddc_driver,
1776 &mtk_cec_driver,
1777 &mtk_hdmi_driver,
1778};
1779
1780static int __init mtk_hdmitx_init(void)
1781{
1782 int ret;
1783 int i;
1784
1785 for (i = 0; i < ARRAY_SIZE(mtk_hdmi_drivers); i++) {
1786 ret = platform_driver_register(mtk_hdmi_drivers[i]);
1787 if (ret < 0) {
1788 pr_err("Failed to register %s driver: %d\n",
1789 mtk_hdmi_drivers[i]->driver.name, ret);
1790 goto err;
1791 }
1792 }
1793
1794 return 0;
1795
1796err:
1797 while (--i >= 0)
1798 platform_driver_unregister(mtk_hdmi_drivers[i]);
1799
1800 return ret;
1801}
1802
1803static void __exit mtk_hdmitx_exit(void)
1804{
1805 int i;
1806
1807 for (i = ARRAY_SIZE(mtk_hdmi_drivers) - 1; i >= 0; i--)
1808 platform_driver_unregister(mtk_hdmi_drivers[i]);
1809}
1810
1811module_init(mtk_hdmitx_init);
1812module_exit(mtk_hdmitx_exit);
1813
1814MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
1815MODULE_DESCRIPTION("MediaTek HDMI Driver");
1816MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi.h b/drivers/gpu/drm/mediatek/mtk_hdmi.h
new file mode 100644
index 000000000000..6371b3de1ff6
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi.h
@@ -0,0 +1,23 @@
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#ifndef _MTK_HDMI_CTRL_H
15#define _MTK_HDMI_CTRL_H
16
17struct platform_driver;
18
19extern struct platform_driver mtk_cec_driver;
20extern struct platform_driver mtk_hdmi_ddc_driver;
21extern struct platform_driver mtk_hdmi_phy_driver;
22
23#endif /* _MTK_HDMI_CTRL_H */
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
new file mode 100644
index 000000000000..33c9e1bdb114
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_ddc.c
@@ -0,0 +1,358 @@
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#include <linux/kernel.h>
15#include <linux/module.h>
16#include <linux/i2c.h>
17#include <linux/time.h>
18#include <linux/delay.h>
19#include <linux/errno.h>
20#include <linux/err.h>
21#include <linux/platform_device.h>
22#include <linux/clk.h>
23#include <linux/slab.h>
24#include <linux/io.h>
25#include <linux/iopoll.h>
26#include <linux/of_address.h>
27#include <linux/of_irq.h>
28#include <linux/of_platform.h>
29
30#define SIF1_CLOK (288)
31#define DDC_DDCMCTL0 (0x0)
32#define DDCM_ODRAIN BIT(31)
33#define DDCM_CLK_DIV_OFFSET (16)
34#define DDCM_CLK_DIV_MASK (0xfff << 16)
35#define DDCM_CS_STATUS BIT(4)
36#define DDCM_SCL_STATE BIT(3)
37#define DDCM_SDA_STATE BIT(2)
38#define DDCM_SM0EN BIT(1)
39#define DDCM_SCL_STRECH BIT(0)
40#define DDC_DDCMCTL1 (0x4)
41#define DDCM_ACK_OFFSET (16)
42#define DDCM_ACK_MASK (0xff << 16)
43#define DDCM_PGLEN_OFFSET (8)
44#define DDCM_PGLEN_MASK (0x7 << 8)
45#define DDCM_SIF_MODE_OFFSET (4)
46#define DDCM_SIF_MODE_MASK (0x7 << 4)
47#define DDCM_START (0x1)
48#define DDCM_WRITE_DATA (0x2)
49#define DDCM_STOP (0x3)
50#define DDCM_READ_DATA_NO_ACK (0x4)
51#define DDCM_READ_DATA_ACK (0x5)
52#define DDCM_TRI BIT(0)
53#define DDC_DDCMD0 (0x8)
54#define DDCM_DATA3 (0xff << 24)
55#define DDCM_DATA2 (0xff << 16)
56#define DDCM_DATA1 (0xff << 8)
57#define DDCM_DATA0 (0xff << 0)
58#define DDC_DDCMD1 (0xc)
59#define DDCM_DATA7 (0xff << 24)
60#define DDCM_DATA6 (0xff << 16)
61#define DDCM_DATA5 (0xff << 8)
62#define DDCM_DATA4 (0xff << 0)
63
64struct mtk_hdmi_ddc {
65 struct i2c_adapter adap;
66 struct clk *clk;
67 void __iomem *regs;
68};
69
70static inline void sif_set_bit(struct mtk_hdmi_ddc *ddc, unsigned int offset,
71 unsigned int val)
72{
73 writel(readl(ddc->regs + offset) | val, ddc->regs + offset);
74}
75
76static inline void sif_clr_bit(struct mtk_hdmi_ddc *ddc, unsigned int offset,
77 unsigned int val)
78{
79 writel(readl(ddc->regs + offset) & ~val, ddc->regs + offset);
80}
81
82static inline bool sif_bit_is_set(struct mtk_hdmi_ddc *ddc, unsigned int offset,
83 unsigned int val)
84{
85 return (readl(ddc->regs + offset) & val) == val;
86}
87
88static inline void sif_write_mask(struct mtk_hdmi_ddc *ddc, unsigned int offset,
89 unsigned int mask, unsigned int shift,
90 unsigned int val)
91{
92 unsigned int tmp;
93
94 tmp = readl(ddc->regs + offset);
95 tmp &= ~mask;
96 tmp |= (val << shift) & mask;
97 writel(tmp, ddc->regs + offset);
98}
99
100static inline unsigned int sif_read_mask(struct mtk_hdmi_ddc *ddc,
101 unsigned int offset, unsigned int mask,
102 unsigned int shift)
103{
104 return (readl(ddc->regs + offset) & mask) >> shift;
105}
106
107static void ddcm_trigger_mode(struct mtk_hdmi_ddc *ddc, int mode)
108{
109 u32 val;
110
111 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_SIF_MODE_MASK,
112 DDCM_SIF_MODE_OFFSET, mode);
113 sif_set_bit(ddc, DDC_DDCMCTL1, DDCM_TRI);
114 readl_poll_timeout(ddc->regs + DDC_DDCMCTL1, val,
115 (val & DDCM_TRI) != DDCM_TRI, 4, 20000);
116}
117
118static int mtk_hdmi_ddc_read_msg(struct mtk_hdmi_ddc *ddc, struct i2c_msg *msg)
119{
120 struct device *dev = ddc->adap.dev.parent;
121 u32 remain_count, ack_count, ack_final, read_count, temp_count;
122 u32 index = 0;
123 u32 ack;
124 int i;
125
126 ddcm_trigger_mode(ddc, DDCM_START);
127 sif_write_mask(ddc, DDC_DDCMD0, 0xff, 0, (msg->addr << 1) | 0x01);
128 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET,
129 0x00);
130 ddcm_trigger_mode(ddc, DDCM_WRITE_DATA);
131 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK, DDCM_ACK_OFFSET);
132 dev_dbg(dev, "ack = 0x%x\n", ack);
133 if (ack != 0x01) {
134 dev_err(dev, "i2c ack err!\n");
135 return -ENXIO;
136 }
137
138 remain_count = msg->len;
139 ack_count = (msg->len - 1) / 8;
140 ack_final = 0;
141
142 while (remain_count > 0) {
143 if (ack_count > 0) {
144 read_count = 8;
145 ack_final = 0;
146 ack_count--;
147 } else {
148 read_count = remain_count;
149 ack_final = 1;
150 }
151
152 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK,
153 DDCM_PGLEN_OFFSET, read_count - 1);
154 ddcm_trigger_mode(ddc, (ack_final == 1) ?
155 DDCM_READ_DATA_NO_ACK :
156 DDCM_READ_DATA_ACK);
157
158 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK,
159 DDCM_ACK_OFFSET);
160 temp_count = 0;
161 while (((ack & (1 << temp_count)) != 0) && (temp_count < 8))
162 temp_count++;
163 if (((ack_final == 1) && (temp_count != (read_count - 1))) ||
164 ((ack_final == 0) && (temp_count != read_count))) {
165 dev_err(dev, "Address NACK! ACK(0x%x)\n", ack);
166 break;
167 }
168
169 for (i = read_count; i >= 1; i--) {
170 int shift;
171 int offset;
172
173 if (i > 4) {
174 offset = DDC_DDCMD1;
175 shift = (i - 5) * 8;
176 } else {
177 offset = DDC_DDCMD0;
178 shift = (i - 1) * 8;
179 }
180
181 msg->buf[index + i - 1] = sif_read_mask(ddc, offset,
182 0xff << shift,
183 shift);
184 }
185
186 remain_count -= read_count;
187 index += read_count;
188 }
189
190 return 0;
191}
192
193static int mtk_hdmi_ddc_write_msg(struct mtk_hdmi_ddc *ddc, struct i2c_msg *msg)
194{
195 struct device *dev = ddc->adap.dev.parent;
196 u32 ack;
197
198 ddcm_trigger_mode(ddc, DDCM_START);
199 sif_write_mask(ddc, DDC_DDCMD0, DDCM_DATA0, 0, msg->addr << 1);
200 sif_write_mask(ddc, DDC_DDCMD0, DDCM_DATA1, 8, msg->buf[0]);
201 sif_write_mask(ddc, DDC_DDCMCTL1, DDCM_PGLEN_MASK, DDCM_PGLEN_OFFSET,
202 0x1);
203 ddcm_trigger_mode(ddc, DDCM_WRITE_DATA);
204
205 ack = sif_read_mask(ddc, DDC_DDCMCTL1, DDCM_ACK_MASK, DDCM_ACK_OFFSET);
206 dev_dbg(dev, "ack = %d\n", ack);
207
208 if (ack != 0x03) {
209 dev_err(dev, "i2c ack err!\n");
210 return -EIO;
211 }
212
213 return 0;
214}
215
216static int mtk_hdmi_ddc_xfer(struct i2c_adapter *adapter,
217 struct i2c_msg *msgs, int num)
218{
219 struct mtk_hdmi_ddc *ddc = adapter->algo_data;
220 struct device *dev = adapter->dev.parent;
221 int ret;
222 int i;
223
224 if (!ddc) {
225 dev_err(dev, "invalid arguments\n");
226 return -EINVAL;
227 }
228
229 sif_set_bit(ddc, DDC_DDCMCTL0, DDCM_SCL_STRECH);
230 sif_set_bit(ddc, DDC_DDCMCTL0, DDCM_SM0EN);
231 sif_clr_bit(ddc, DDC_DDCMCTL0, DDCM_ODRAIN);
232
233 if (sif_bit_is_set(ddc, DDC_DDCMCTL1, DDCM_TRI)) {
234 dev_err(dev, "ddc line is busy!\n");
235 return -EBUSY;
236 }
237
238 sif_write_mask(ddc, DDC_DDCMCTL0, DDCM_CLK_DIV_MASK,
239 DDCM_CLK_DIV_OFFSET, SIF1_CLOK);
240
241 for (i = 0; i < num; i++) {
242 struct i2c_msg *msg = &msgs[i];
243
244 dev_dbg(dev, "i2c msg, adr:0x%x, flags:%d, len :0x%x\n",
245 msg->addr, msg->flags, msg->len);
246
247 if (msg->flags & I2C_M_RD)
248 ret = mtk_hdmi_ddc_read_msg(ddc, msg);
249 else
250 ret = mtk_hdmi_ddc_write_msg(ddc, msg);
251 if (ret < 0)
252 goto xfer_end;
253 }
254
255 ddcm_trigger_mode(ddc, DDCM_STOP);
256
257 return i;
258
259xfer_end:
260 ddcm_trigger_mode(ddc, DDCM_STOP);
261 dev_err(dev, "ddc failed!\n");
262 return ret;
263}
264
265static u32 mtk_hdmi_ddc_func(struct i2c_adapter *adapter)
266{
267 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
268}
269
270static const struct i2c_algorithm mtk_hdmi_ddc_algorithm = {
271 .master_xfer = mtk_hdmi_ddc_xfer,
272 .functionality = mtk_hdmi_ddc_func,
273};
274
275static int mtk_hdmi_ddc_probe(struct platform_device *pdev)
276{
277 struct device *dev = &pdev->dev;
278 struct mtk_hdmi_ddc *ddc;
279 struct resource *mem;
280 int ret;
281
282 ddc = devm_kzalloc(dev, sizeof(struct mtk_hdmi_ddc), GFP_KERNEL);
283 if (!ddc)
284 return -ENOMEM;
285
286 ddc->clk = devm_clk_get(dev, "ddc-i2c");
287 if (IS_ERR(ddc->clk)) {
288 dev_err(dev, "get ddc_clk failed: %p ,\n", ddc->clk);
289 return PTR_ERR(ddc->clk);
290 }
291
292 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
293 ddc->regs = devm_ioremap_resource(&pdev->dev, mem);
294 if (IS_ERR(ddc->regs))
295 return PTR_ERR(ddc->regs);
296
297 ret = clk_prepare_enable(ddc->clk);
298 if (ret) {
299 dev_err(dev, "enable ddc clk failed!\n");
300 return ret;
301 }
302
303 strlcpy(ddc->adap.name, "mediatek-hdmi-ddc", sizeof(ddc->adap.name));
304 ddc->adap.owner = THIS_MODULE;
305 ddc->adap.class = I2C_CLASS_DDC;
306 ddc->adap.algo = &mtk_hdmi_ddc_algorithm;
307 ddc->adap.retries = 3;
308 ddc->adap.dev.of_node = dev->of_node;
309 ddc->adap.algo_data = ddc;
310 ddc->adap.dev.parent = &pdev->dev;
311
312 ret = i2c_add_adapter(&ddc->adap);
313 if (ret < 0) {
314 dev_err(dev, "failed to add bus to i2c core\n");
315 goto err_clk_disable;
316 }
317
318 platform_set_drvdata(pdev, ddc);
319
320 dev_dbg(dev, "ddc->adap: %p\n", &ddc->adap);
321 dev_dbg(dev, "ddc->clk: %p\n", ddc->clk);
322 dev_dbg(dev, "physical adr: %pa, end: %pa\n", &mem->start,
323 &mem->end);
324
325 return 0;
326
327err_clk_disable:
328 clk_disable_unprepare(ddc->clk);
329 return ret;
330}
331
332static int mtk_hdmi_ddc_remove(struct platform_device *pdev)
333{
334 struct mtk_hdmi_ddc *ddc = platform_get_drvdata(pdev);
335
336 i2c_del_adapter(&ddc->adap);
337 clk_disable_unprepare(ddc->clk);
338
339 return 0;
340}
341
342static const struct of_device_id mtk_hdmi_ddc_match[] = {
343 { .compatible = "mediatek,mt8173-hdmi-ddc", },
344 {},
345};
346
347struct platform_driver mtk_hdmi_ddc_driver = {
348 .probe = mtk_hdmi_ddc_probe,
349 .remove = mtk_hdmi_ddc_remove,
350 .driver = {
351 .name = "mediatek-hdmi-ddc",
352 .of_match_table = mtk_hdmi_ddc_match,
353 },
354};
355
356MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
357MODULE_DESCRIPTION("MediaTek HDMI DDC Driver");
358MODULE_LICENSE("GPL v2");
diff --git a/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h
new file mode 100644
index 000000000000..209fbe194442
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_hdmi_regs.h
@@ -0,0 +1,237 @@
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#ifndef _MTK_HDMI_REGS_H
15#define _MTK_HDMI_REGS_H
16
17#define GRL_INT_MASK 0x18
18#define GRL_IFM_PORT 0x188
19#define GRL_CH_SWAP 0x198
20#define LR_SWAP BIT(0)
21#define LFE_CC_SWAP BIT(1)
22#define LSRS_SWAP BIT(2)
23#define RLS_RRS_SWAP BIT(3)
24#define LR_STATUS_SWAP BIT(4)
25#define GRL_I2S_C_STA0 0x140
26#define GRL_I2S_C_STA1 0x144
27#define GRL_I2S_C_STA2 0x148
28#define GRL_I2S_C_STA3 0x14C
29#define GRL_I2S_C_STA4 0x150
30#define GRL_I2S_UV 0x154
31#define I2S_UV_V BIT(0)
32#define I2S_UV_U BIT(1)
33#define I2S_UV_CH_EN_MASK 0x3c
34#define I2S_UV_CH_EN(x) BIT((x) + 2)
35#define I2S_UV_TMDS_DEBUG BIT(6)
36#define I2S_UV_NORMAL_INFO_INV BIT(7)
37#define GRL_ACP_ISRC_CTRL 0x158
38#define VS_EN BIT(0)
39#define ACP_EN BIT(1)
40#define ISRC1_EN BIT(2)
41#define ISRC2_EN BIT(3)
42#define GAMUT_EN BIT(4)
43#define GRL_CTS_CTRL 0x160
44#define CTS_CTRL_SOFT BIT(0)
45#define GRL_INT 0x14
46#define INT_MDI BIT(0)
47#define INT_HDCP BIT(1)
48#define INT_FIFO_O BIT(2)
49#define INT_FIFO_U BIT(3)
50#define INT_IFM_ERR BIT(4)
51#define INT_INF_DONE BIT(5)
52#define INT_NCTS_DONE BIT(6)
53#define INT_CTRL_PKT_DONE BIT(7)
54#define GRL_INT_MASK 0x18
55#define GRL_CTRL 0x1C
56#define CTRL_GEN_EN BIT(2)
57#define CTRL_SPD_EN BIT(3)
58#define CTRL_MPEG_EN BIT(4)
59#define CTRL_AUDIO_EN BIT(5)
60#define CTRL_AVI_EN BIT(6)
61#define CTRL_AVMUTE BIT(7)
62#define GRL_STATUS 0x20
63#define STATUS_HTPLG BIT(0)
64#define STATUS_PORD BIT(1)
65#define GRL_DIVN 0x170
66#define NCTS_WRI_ANYTIME BIT(6)
67#define GRL_AUDIO_CFG 0x17C
68#define AUDIO_ZERO BIT(0)
69#define HIGH_BIT_RATE BIT(1)
70#define SACD_DST BIT(2)
71#define DST_NORMAL_DOUBLE BIT(3)
72#define DSD_INV BIT(4)
73#define LR_INV BIT(5)
74#define LR_MIX BIT(6)
75#define DSD_SEL BIT(7)
76#define GRL_NCTS 0x184
77#define GRL_CH_SW0 0x18C
78#define GRL_CH_SW1 0x190
79#define GRL_CH_SW2 0x194
80#define CH_SWITCH(from, to) ((from) << ((to) * 3))
81#define GRL_INFOFRM_VER 0x19C
82#define GRL_INFOFRM_TYPE 0x1A0
83#define GRL_INFOFRM_LNG 0x1A4
84#define GRL_MIX_CTRL 0x1B4
85#define MIX_CTRL_SRC_EN BIT(0)
86#define BYPASS_VOLUME BIT(1)
87#define MIX_CTRL_FLAT BIT(7)
88#define GRL_AOUT_CFG 0x1C4
89#define AOUT_BNUM_SEL_MASK 0x03
90#define AOUT_24BIT 0x00
91#define AOUT_20BIT 0x02
92#define AOUT_16BIT 0x03
93#define AOUT_FIFO_ADAP_CTRL BIT(6)
94#define AOUT_BURST_PREAMBLE_EN BIT(7)
95#define HIGH_BIT_RATE_PACKET_ALIGN (AOUT_BURST_PREAMBLE_EN | \
96 AOUT_FIFO_ADAP_CTRL)
97#define GRL_SHIFT_L1 0x1C0
98#define GRL_SHIFT_R2 0x1B0
99#define AUDIO_PACKET_OFF BIT(6)
100#define GRL_CFG0 0x24
101#define CFG0_I2S_MODE_MASK 0x3
102#define CFG0_I2S_MODE_RTJ 0x1
103#define CFG0_I2S_MODE_LTJ 0x0
104#define CFG0_I2S_MODE_I2S 0x2
105#define CFG0_W_LENGTH_MASK 0x30
106#define CFG0_W_LENGTH_24BIT 0x00
107#define CFG0_W_LENGTH_16BIT 0x10
108#define GRL_CFG1 0x28
109#define CFG1_EDG_SEL BIT(0)
110#define CFG1_SPDIF BIT(1)
111#define CFG1_DVI BIT(2)
112#define CFG1_HDCP_DEBUG BIT(3)
113#define GRL_CFG2 0x2c
114#define CFG2_MHL_DE_SEL BIT(3)
115#define CFG2_MHL_FAKE_DE_SEL BIT(4)
116#define CFG2_MHL_DATA_REMAP BIT(5)
117#define CFG2_NOTICE_EN BIT(6)
118#define CFG2_ACLK_INV BIT(7)
119#define GRL_CFG3 0x30
120#define CFG3_AES_KEY_INDEX_MASK 0x3f
121#define CFG3_CONTROL_PACKET_DELAY BIT(6)
122#define CFG3_KSV_LOAD_START BIT(7)
123#define GRL_CFG4 0x34
124#define CFG4_AES_KEY_LOAD BIT(4)
125#define CFG4_AV_UNMUTE_EN BIT(5)
126#define CFG4_AV_UNMUTE_SET BIT(6)
127#define CFG4_MHL_MODE BIT(7)
128#define GRL_CFG5 0x38
129#define CFG5_CD_RATIO_MASK 0x8F
130#define CFG5_FS128 (0x1 << 4)
131#define CFG5_FS256 (0x2 << 4)
132#define CFG5_FS384 (0x3 << 4)
133#define CFG5_FS512 (0x4 << 4)
134#define CFG5_FS768 (0x6 << 4)
135#define DUMMY_304 0x304
136#define CHMO_SEL (0x3 << 2)
137#define CHM1_SEL (0x3 << 4)
138#define CHM2_SEL (0x3 << 6)
139#define AUDIO_I2S_NCTS_SEL BIT(1)
140#define AUDIO_I2S_NCTS_SEL_64 (1 << 1)
141#define AUDIO_I2S_NCTS_SEL_128 (0 << 1)
142#define NEW_GCP_CTRL BIT(0)
143#define NEW_GCP_CTRL_MERGE BIT(0)
144#define GRL_L_STATUS_0 0x200
145#define GRL_L_STATUS_1 0x204
146#define GRL_L_STATUS_2 0x208
147#define GRL_L_STATUS_3 0x20c
148#define GRL_L_STATUS_4 0x210
149#define GRL_L_STATUS_5 0x214
150#define GRL_L_STATUS_6 0x218
151#define GRL_L_STATUS_7 0x21c
152#define GRL_L_STATUS_8 0x220
153#define GRL_L_STATUS_9 0x224
154#define GRL_L_STATUS_10 0x228
155#define GRL_L_STATUS_11 0x22c
156#define GRL_L_STATUS_12 0x230
157#define GRL_L_STATUS_13 0x234
158#define GRL_L_STATUS_14 0x238
159#define GRL_L_STATUS_15 0x23c
160#define GRL_L_STATUS_16 0x240
161#define GRL_L_STATUS_17 0x244
162#define GRL_L_STATUS_18 0x248
163#define GRL_L_STATUS_19 0x24c
164#define GRL_L_STATUS_20 0x250
165#define GRL_L_STATUS_21 0x254
166#define GRL_L_STATUS_22 0x258
167#define GRL_L_STATUS_23 0x25c
168#define GRL_R_STATUS_0 0x260
169#define GRL_R_STATUS_1 0x264
170#define GRL_R_STATUS_2 0x268
171#define GRL_R_STATUS_3 0x26c
172#define GRL_R_STATUS_4 0x270
173#define GRL_R_STATUS_5 0x274
174#define GRL_R_STATUS_6 0x278
175#define GRL_R_STATUS_7 0x27c
176#define GRL_R_STATUS_8 0x280
177#define GRL_R_STATUS_9 0x284
178#define GRL_R_STATUS_10 0x288
179#define GRL_R_STATUS_11 0x28c
180#define GRL_R_STATUS_12 0x290
181#define GRL_R_STATUS_13 0x294
182#define GRL_R_STATUS_14 0x298
183#define GRL_R_STATUS_15 0x29c
184#define GRL_R_STATUS_16 0x2a0
185#define GRL_R_STATUS_17 0x2a4
186#define GRL_R_STATUS_18 0x2a8
187#define GRL_R_STATUS_19 0x2ac
188#define GRL_R_STATUS_20 0x2b0
189#define GRL_R_STATUS_21 0x2b4
190#define GRL_R_STATUS_22 0x2b8
191#define GRL_R_STATUS_23 0x2bc
192#define GRL_ABIST_CTRL0 0x2D4
193#define GRL_ABIST_CTRL1 0x2D8
194#define ABIST_EN BIT(7)
195#define ABIST_DATA_FMT (0x7 << 0)
196#define VIDEO_CFG_0 0x380
197#define VIDEO_CFG_1 0x384
198#define VIDEO_CFG_2 0x388
199#define VIDEO_CFG_3 0x38c
200#define VIDEO_CFG_4 0x390
201#define VIDEO_SOURCE_SEL BIT(7)
202#define NORMAL_PATH (1 << 7)
203#define GEN_RGB (0 << 7)
204
205#define HDMI_SYS_CFG1C 0x000
206#define HDMI_ON BIT(0)
207#define HDMI_RST BIT(1)
208#define ANLG_ON BIT(2)
209#define CFG10_DVI BIT(3)
210#define HDMI_TST BIT(3)
211#define SYS_KEYMASK1 (0xff << 8)
212#define SYS_KEYMASK2 (0xff << 16)
213#define AUD_OUTSYNC_EN BIT(24)
214#define AUD_OUTSYNC_PRE_EN BIT(25)
215#define I2CM_ON BIT(26)
216#define E2PROM_TYPE_8BIT BIT(27)
217#define MCM_E2PROM_ON BIT(28)
218#define EXT_E2PROM_ON BIT(29)
219#define HTPLG_PIN_SEL_OFF BIT(30)
220#define AES_EFUSE_ENABLE BIT(31)
221#define HDMI_SYS_CFG20 0x004
222#define DEEP_COLOR_MODE_MASK (3 << 1)
223#define COLOR_8BIT_MODE (0 << 1)
224#define COLOR_10BIT_MODE (1 << 1)
225#define COLOR_12BIT_MODE (2 << 1)
226#define COLOR_16BIT_MODE (3 << 1)
227#define DEEP_COLOR_EN BIT(0)
228#define HDMI_AUDIO_TEST_SEL BIT(8)
229#define HDMI2P0_EN BIT(11)
230#define HDMI_OUT_FIFO_EN BIT(16)
231#define HDMI_OUT_FIFO_CLK_INV BIT(17)
232#define MHL_MODE_ON BIT(28)
233#define MHL_PP_MODE BIT(29)
234#define MHL_SYNC_AUTO_EN BIT(30)
235#define HDMI_PCLK_FREE_RUN BIT(31)
236
237#endif
diff --git a/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
new file mode 100644
index 000000000000..8a24754b440f
--- /dev/null
+++ b/drivers/gpu/drm/mediatek/mtk_mt8173_hdmi_phy.c
@@ -0,0 +1,515 @@
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
269 dev_dbg(hdmi_phy->dev, "%s: %lu Hz, parent: %lu Hz\n", __func__,
270 rate, parent_rate);
271
272 if (rate <= 27000000) {
273 pre_div = 0;
274 div = 3;
275 } else if (rate <= 74250000) {
276 pre_div = 1;
277 div = 2;
278 } else {
279 pre_div = 1;
280 div = 1;
281 }
282
283 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
284 (pre_div << PREDIV_SHIFT), RG_HDMITX_PLL_PREDIV);
285 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON0, RG_HDMITX_PLL_POSDIV);
286 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
287 (0x1 << PLL_IC_SHIFT) | (0x1 << PLL_IR_SHIFT),
288 RG_HDMITX_PLL_IC | RG_HDMITX_PLL_IR);
289 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
290 (div << PLL_TXDIV_SHIFT), RG_HDMITX_PLL_TXDIV);
291 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
292 (0x1 << PLL_FBKSEL_SHIFT) | (19 << PLL_FBKDIV_SHIFT),
293 RG_HDMITX_PLL_FBKSEL | RG_HDMITX_PLL_FBKDIV);
294 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON1,
295 (0x2 << PLL_DIVEN_SHIFT), RG_HDMITX_PLL_DIVEN);
296 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON0,
297 (0xc << PLL_BP_SHIFT) | (0x2 << PLL_BC_SHIFT) |
298 (0x1 << PLL_BR_SHIFT),
299 RG_HDMITX_PLL_BP | RG_HDMITX_PLL_BC |
300 RG_HDMITX_PLL_BR);
301 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3, RG_HDMITX_PRD_IMP_EN);
302 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON4,
303 (0x3 << PRD_IBIAS_CLK_SHIFT) |
304 (0x3 << PRD_IBIAS_D2_SHIFT) |
305 (0x3 << PRD_IBIAS_D1_SHIFT) |
306 (0x3 << PRD_IBIAS_D0_SHIFT),
307 RG_HDMITX_PRD_IBIAS_CLK |
308 RG_HDMITX_PRD_IBIAS_D2 |
309 RG_HDMITX_PRD_IBIAS_D1 |
310 RG_HDMITX_PRD_IBIAS_D0);
311 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON3,
312 (0x0 << DRV_IMP_EN_SHIFT), RG_HDMITX_DRV_IMP_EN);
313 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON6,
314 (hdmi_phy->drv_imp_clk << DRV_IMP_CLK_SHIFT) |
315 (hdmi_phy->drv_imp_d2 << DRV_IMP_D2_SHIFT) |
316 (hdmi_phy->drv_imp_d1 << DRV_IMP_D1_SHIFT) |
317 (hdmi_phy->drv_imp_d0 << DRV_IMP_D0_SHIFT),
318 RG_HDMITX_DRV_IMP_CLK | RG_HDMITX_DRV_IMP_D2 |
319 RG_HDMITX_DRV_IMP_D1 | RG_HDMITX_DRV_IMP_D0);
320 mtk_hdmi_phy_mask(hdmi_phy, HDMI_CON5,
321 (hdmi_phy->ibias << DRV_IBIAS_CLK_SHIFT) |
322 (hdmi_phy->ibias << DRV_IBIAS_D2_SHIFT) |
323 (hdmi_phy->ibias << DRV_IBIAS_D1_SHIFT) |
324 (hdmi_phy->ibias << DRV_IBIAS_D0_SHIFT),
325 RG_HDMITX_DRV_IBIAS_CLK | RG_HDMITX_DRV_IBIAS_D2 |
326 RG_HDMITX_DRV_IBIAS_D1 | RG_HDMITX_DRV_IBIAS_D0);
327 return 0;
328}
329
330static long mtk_hdmi_pll_round_rate(struct clk_hw *hw, unsigned long rate,
331 unsigned long *parent_rate)
332{
333 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
334
335 hdmi_phy->pll_rate = rate;
336 if (rate <= 74250000)
337 *parent_rate = rate;
338 else
339 *parent_rate = rate / 2;
340
341 return rate;
342}
343
344static unsigned long mtk_hdmi_pll_recalc_rate(struct clk_hw *hw,
345 unsigned long parent_rate)
346{
347 struct mtk_hdmi_phy *hdmi_phy = to_mtk_hdmi_phy(hw);
348
349 return hdmi_phy->pll_rate;
350}
351
352static const struct clk_ops mtk_hdmi_pll_ops = {
353 .prepare = mtk_hdmi_pll_prepare,
354 .unprepare = mtk_hdmi_pll_unprepare,
355 .set_rate = mtk_hdmi_pll_set_rate,
356 .round_rate = mtk_hdmi_pll_round_rate,
357 .recalc_rate = mtk_hdmi_pll_recalc_rate,
358};
359
360static void mtk_hdmi_phy_enable_tmds(struct mtk_hdmi_phy *hdmi_phy)
361{
362 mtk_hdmi_phy_set_bits(hdmi_phy, HDMI_CON3,
363 RG_HDMITX_SER_EN | RG_HDMITX_PRD_EN |
364 RG_HDMITX_DRV_EN);
365 usleep_range(100, 150);
366}
367
368static void mtk_hdmi_phy_disable_tmds(struct mtk_hdmi_phy *hdmi_phy)
369{
370 mtk_hdmi_phy_clear_bits(hdmi_phy, HDMI_CON3,
371 RG_HDMITX_DRV_EN | RG_HDMITX_PRD_EN |
372 RG_HDMITX_SER_EN);
373}
374
375static int mtk_hdmi_phy_power_on(struct phy *phy)
376{
377 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
378 int ret;
379
380 ret = clk_prepare_enable(hdmi_phy->pll);
381 if (ret < 0)
382 return ret;
383
384 mtk_hdmi_phy_enable_tmds(hdmi_phy);
385
386 return 0;
387}
388
389static int mtk_hdmi_phy_power_off(struct phy *phy)
390{
391 struct mtk_hdmi_phy *hdmi_phy = phy_get_drvdata(phy);
392
393 mtk_hdmi_phy_disable_tmds(hdmi_phy);
394 clk_disable_unprepare(hdmi_phy->pll);
395
396 return 0;
397}
398
399static const struct phy_ops mtk_hdmi_phy_ops = {
400 .power_on = mtk_hdmi_phy_power_on,
401 .power_off = mtk_hdmi_phy_power_off,
402 .owner = THIS_MODULE,
403};
404
405static int mtk_hdmi_phy_probe(struct platform_device *pdev)
406{
407 struct device *dev = &pdev->dev;
408 struct mtk_hdmi_phy *hdmi_phy;
409 struct resource *mem;
410 struct clk *ref_clk;
411 const char *ref_clk_name;
412 struct clk_init_data clk_init = {
413 .ops = &mtk_hdmi_pll_ops,
414 .num_parents = 1,
415 .parent_names = (const char * const *)&ref_clk_name,
416 .flags = CLK_SET_RATE_PARENT | CLK_SET_RATE_GATE,
417 };
418 struct phy *phy;
419 struct phy_provider *phy_provider;
420 int ret;
421
422 hdmi_phy = devm_kzalloc(dev, sizeof(*hdmi_phy), GFP_KERNEL);
423 if (!hdmi_phy)
424 return -ENOMEM;
425
426 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
427 hdmi_phy->regs = devm_ioremap_resource(dev, mem);
428 if (IS_ERR(hdmi_phy->regs)) {
429 ret = PTR_ERR(hdmi_phy->regs);
430 dev_err(dev, "Failed to get memory resource: %d\n", ret);
431 return ret;
432 }
433
434 ref_clk = devm_clk_get(dev, "pll_ref");
435 if (IS_ERR(ref_clk)) {
436 ret = PTR_ERR(ref_clk);
437 dev_err(&pdev->dev, "Failed to get PLL reference clock: %d\n",
438 ret);
439 return ret;
440 }
441 ref_clk_name = __clk_get_name(ref_clk);
442
443 ret = of_property_read_string(dev->of_node, "clock-output-names",
444 &clk_init.name);
445 if (ret < 0) {
446 dev_err(dev, "Failed to read clock-output-names: %d\n", ret);
447 return ret;
448 }
449
450 hdmi_phy->pll_hw.init = &clk_init;
451 hdmi_phy->pll = devm_clk_register(dev, &hdmi_phy->pll_hw);
452 if (IS_ERR(hdmi_phy->pll)) {
453 ret = PTR_ERR(hdmi_phy->pll);
454 dev_err(dev, "Failed to register PLL: %d\n", ret);
455 return ret;
456 }
457
458 ret = of_property_read_u32(dev->of_node, "mediatek,ibias",
459 &hdmi_phy->ibias);
460 if (ret < 0) {
461 dev_err(&pdev->dev, "Failed to get ibias: %d\n", ret);
462 return ret;
463 }
464
465 ret = of_property_read_u32(dev->of_node, "mediatek,ibias_up",
466 &hdmi_phy->ibias_up);
467 if (ret < 0) {
468 dev_err(&pdev->dev, "Failed to get ibias up: %d\n", ret);
469 return ret;
470 }
471
472 dev_info(dev, "Using default TX DRV impedance: 4.2k/36\n");
473 hdmi_phy->drv_imp_clk = 0x30;
474 hdmi_phy->drv_imp_d2 = 0x30;
475 hdmi_phy->drv_imp_d1 = 0x30;
476 hdmi_phy->drv_imp_d0 = 0x30;
477
478 phy = devm_phy_create(dev, NULL, &mtk_hdmi_phy_ops);
479 if (IS_ERR(phy)) {
480 dev_err(dev, "Failed to create HDMI PHY\n");
481 return PTR_ERR(phy);
482 }
483 phy_set_drvdata(phy, hdmi_phy);
484
485 phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate);
486 if (IS_ERR(phy_provider))
487 return PTR_ERR(phy_provider);
488
489 hdmi_phy->dev = dev;
490 return of_clk_add_provider(dev->of_node, of_clk_src_simple_get,
491 hdmi_phy->pll);
492}
493
494static int mtk_hdmi_phy_remove(struct platform_device *pdev)
495{
496 return 0;
497}
498
499static const struct of_device_id mtk_hdmi_phy_match[] = {
500 { .compatible = "mediatek,mt8173-hdmi-phy", },
501 {},
502};
503
504struct platform_driver mtk_hdmi_phy_driver = {
505 .probe = mtk_hdmi_phy_probe,
506 .remove = mtk_hdmi_phy_remove,
507 .driver = {
508 .name = "mediatek-hdmi-phy",
509 .of_match_table = mtk_hdmi_phy_match,
510 },
511};
512
513MODULE_AUTHOR("Jie Qiu <jie.qiu@mediatek.com>");
514MODULE_DESCRIPTION("MediaTek MT8173 HDMI PHY Driver");
515MODULE_LICENSE("GPL v2");