drm/verisilicon: hdmi: Add feature to check cea mode
[platform/kernel/linux-starfive.git] / drivers / gpu / drm / verisilicon / starfive_hdmi.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2023 StarFive Technology Co., Ltd.
4  */
5
6 #include <linux/clk.h>
7 #include <linux/component.h>
8 #include <linux/delay.h>
9 #include <linux/err.h>
10 #include <linux/hdmi.h>
11 #include <linux/i2c.h>
12 #include <linux/irq.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/mutex.h>
16 #include <linux/of_device.h>
17 #include <linux/pm_runtime.h>
18 #include <linux/reset.h>
19
20 #include <drm/bridge/dw_hdmi.h>
21 #include <drm/drm_atomic_helper.h>
22 #include <drm/drm_edid.h>
23 #include <drm/drm_of.h>
24 #include <drm/drm_probe_helper.h>
25 #include <drm/drm_simple_kms_helper.h>
26
27 #include "starfive_hdmi.h"
28 #include "vs_drv.h"
29
30 static struct starfive_hdmi *encoder_to_hdmi(struct drm_encoder *encoder)
31 {
32         return container_of(encoder, struct starfive_hdmi, encoder);
33 }
34
35 static struct starfive_hdmi *connector_to_hdmi(struct drm_connector *connector)
36 {
37         return container_of(connector, struct starfive_hdmi, connector);
38 }
39
40 struct starfive_hdmi_i2c {
41         struct i2c_adapter adap;
42
43         u8 ddc_addr;
44         u8 segment_addr;
45         /* protects the edid data when use i2c cmd to read edid */
46         struct mutex lock;
47         struct completion cmp;
48 };
49
50 static const struct pre_pll_config pre_pll_cfg_table[] = {
51         { 25175000,  25175000, 1,  100, 2, 3, 3, 12, 3, 3, 4, 0, 0xf55555},
52         { 25200000,  25200000, 1,  100, 2, 3, 3, 12, 3, 3, 4, 0, 0},
53         { 27000000,  27000000, 1,  90, 3, 2, 2, 10, 3, 3, 4, 0, 0},
54         { 27027000,  27027000, 1,  90, 3, 2, 2, 10, 3, 3, 4, 0, 0x170a3d},
55         { 28320000,  28320000, 1,  28, 2, 1, 1,  3, 0, 3, 4, 0, 0x51eb85},
56         { 30240000,  30240000, 1,  30, 2, 1, 1,  3, 0, 3, 4, 0, 0x3d70a3},
57         { 31500000,  31500000, 1,  31, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
58         { 33750000,  33750000, 1,  33, 2, 1, 1,  3, 0, 3, 4, 0, 0xcfffff},
59         { 36000000,  36000000, 1,  36, 2, 1, 1,  3, 0, 3, 4, 0, 0},
60         { 40000000,  40000000, 1,  80, 2, 2, 2, 12, 2, 2, 2, 0, 0},
61         { 46970000,  46970000, 1,  46, 2, 1, 1,  3, 0, 3, 4, 0, 0xf851eb},
62         { 49500000,  49500000, 1,  49, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
63         { 49000000,  49000000, 1,  49, 2, 1, 1,  3, 0, 3, 4, 0, 0},
64         { 50000000,  50000000, 1,  50, 2, 1, 1,  3, 0, 3, 4, 0, 0},
65         { 54000000,  54000000, 1,  54, 2, 1, 1,  3, 0, 3, 4, 0, 0},
66         { 54054000,  54054000, 1,  54, 2, 1, 1,  3, 0, 3, 4, 0, 0x0dd2f1},
67         { 57284000,  57284000, 1,  57, 2, 1, 1,  3, 0, 3, 4, 0, 0x48b439},
68         { 58230000,  58230000, 1,  58, 2, 1, 1,  3, 0, 3, 4, 0, 0x3ae147},
69         { 59341000,  59341000, 1,  59, 2, 1, 1,  3, 0, 3, 4, 0, 0x574bc6},
70         { 59400000,  59400000, 1,  99, 3, 1, 1,  1, 3, 3, 4, 0, 0},
71         { 65000000,  65000000, 1, 130, 2, 2, 2,  12, 0, 2, 2, 0, 0},
72         { 68250000,  68250000, 1, 68,  2, 1, 1,  3,  0, 3, 4, 0, 0x3fffff},
73         { 71000000,  71000000, 1,  71, 2, 1, 1,  3, 0, 3,  4, 0, 0},
74         { 74176000,  74176000, 1,  98, 1, 2, 2,  1, 2, 3, 4, 0, 0xe6ae6b},
75         { 74250000,  74250000, 1,  99, 1, 2, 2,  1, 2, 3, 4, 0, 0},
76         { 75000000,  75000000, 1,  75, 2, 1, 1,  3, 0, 3, 4, 0, 0},
77         { 78750000,  78750000, 1,  78, 2, 1, 1,  3, 0, 3, 4, 0, 0xcfffff},
78         { 79500000,  79500000, 1,  79, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
79         { 83500000,  83500000, 2, 167, 2, 1, 1,  1, 0, 0,  6, 0, 0},
80         { 83500000, 104375000, 1, 104, 2, 1, 1,  1, 1, 0,  5, 0, 0x600000},
81         { 84858000,  84858000, 1,  85, 2, 1, 1,  3, 0, 3,  4, 0, 0xdba5e2},
82         { 85500000,  85500000, 1,  85, 2, 1, 1,  3, 0, 3,  4, 0, 0x7fffff},
83         { 85750000,  85750000, 1,  85, 2, 1, 1,  3, 0, 3,  4, 0, 0xcfffff},
84         { 85800000,  85800000, 1,  85, 2, 1, 1,  3, 0, 3,  4, 0, 0xcccccc},
85         { 88750000,  88750000, 1,  88, 2, 1, 1,  3, 0, 3,  4, 0, 0xcfffff},
86         { 89910000,  89910000, 1,  89, 2, 1, 1,  3, 0, 3, 4, 0, 0xe8f5c1},
87         { 90000000,  90000000, 1,  90, 2, 1, 1,  3, 0, 3, 4, 0, 0},
88         {101000000, 101000000, 1, 101, 2, 1, 1,  3, 0, 3, 4, 0, 0},
89         {102250000, 102250000, 1, 102, 2, 1, 1,  3, 0, 3, 4, 0, 0x3fffff},
90         {106500000, 106500000, 1, 106, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
91         {108000000, 108000000, 1,  90, 3, 0, 0,  5, 0, 2,  2, 0, 0},
92         {119000000, 119000000, 1, 119, 2, 1, 1,  3, 0, 3,  4, 0, 0},
93         {131481000, 131481000, 1,  131, 2, 1, 1,  3, 0, 3,  4, 0, 0x7b22d1},
94         {135000000, 135000000, 1,  135, 2, 1, 1,  3, 0, 3, 4, 0, 0},
95         {136750000, 136750000, 1,  136, 2, 1, 1,  3, 0, 3, 4, 0, 0xcfffff},
96         {147180000, 147180000, 1,  147, 2, 1, 1,  3, 0, 3, 4, 0, 0x2e147a},
97         {148352000, 148352000, 1,  98, 1, 1, 1,  1, 2, 2, 2, 0, 0xe6ae6b},
98         {148500000, 148500000, 1,  99, 1, 1, 1,  1, 2, 2, 2, 0, 0},
99         {154000000, 154000000, 1, 154, 2, 1, 1,  3, 0, 3, 4, 0, 0},
100         {156000000, 156000000, 1, 156, 2, 1, 1,  3, 0, 3, 4, 0, 0},
101         {157000000, 157000000, 1, 157, 2, 1, 1,  3, 0, 3, 4, 0, 0},
102         {162000000, 162000000, 1, 162, 2, 1, 1,  3, 0, 3, 4, 0, 0},
103         {174250000, 174250000, 1, 145, 3, 0, 0,  5, 0, 2, 2, 0, 0x355555},
104         {174500000, 174500000, 1, 174, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
105         {174570000, 174570000, 1, 174, 2, 1, 1,  3, 0, 3, 4, 0, 0x91eb84},
106         {175500000, 175500000, 1, 175, 2, 1, 1,  3, 0, 3, 4, 0, 0x7fffff},
107         {185590000, 185590000, 1, 185, 2, 1, 1,  3, 0, 3, 4, 0, 0x970a3c},
108         {187000000, 187000000, 1, 187, 2, 1, 1,  3, 0, 3, 4, 0, 0},
109         {241500000, 241500000, 1, 161, 1, 1, 1,  4, 0, 2,  2, 0, 0},
110         {241700000, 241700000, 1, 241, 2, 1, 1,  3, 0, 3,  4, 0, 0xb33332},
111         {262750000, 262750000, 1, 262, 2, 1, 1,  3, 0, 3,  4, 0, 0xcfffff},
112         {296500000, 296500000, 1, 296, 2, 1, 1,  3, 0, 3,  4, 0, 0x7fffff},
113         {296703000, 296703000, 1,  98, 0, 1, 1,  1, 0, 2,  2, 0, 0xe6ae6b},
114         {297000000, 297000000, 1,  99, 0, 1, 1,  1, 0, 2,  2, 0, 0},
115         {594000000, 594000000, 1,  99, 0, 2, 0,  1, 0, 1,  1, 0, 0},
116         {0, 0, 0,  0, 0, 0, 0,  0, 0, 0,  0, 0, 0},
117 };
118
119 static const struct post_pll_config post_pll_cfg_table[] = {
120         {25200000,      1, 80, 13, 3, 1},
121         {27000000,      1, 40, 11, 3, 1},
122         {33750000,      1, 40, 11, 3, 1},
123         {49000000,      1, 20, 1, 3, 3},
124         {241700000, 1, 20, 1, 3, 3},
125         {297000000, 4, 20, 0, 0, 3},
126         {594000000, 4, 20, 0, 0, 0},
127         { /* sentinel */ }
128 };
129
130 inline u8 hdmi_readb(struct starfive_hdmi *hdmi, u16 offset)
131 {
132         return readl_relaxed(hdmi->regs + (offset) * 0x04);
133 }
134
135 inline void hdmi_writeb(struct starfive_hdmi *hdmi, u16 offset, u32 val)
136 {
137         writel_relaxed(val, hdmi->regs + (offset) * 0x04);
138 }
139
140 inline void hdmi_modb(struct starfive_hdmi *hdmi, u16 offset,
141                              u32 msk, u32 val)
142 {
143         u8 temp = hdmi_readb(hdmi, offset) & ~msk;
144
145         temp |= val & msk;
146         hdmi_writeb(hdmi, offset, temp);
147 }
148
149 static int starfive_hdmi_enable_clk_deassert_rst(struct device *dev, struct starfive_hdmi *hdmi)
150 {
151         int ret;
152
153         ret = clk_prepare_enable(hdmi->sys_clk);
154         if (ret) {
155                 DRM_DEV_ERROR(dev, "Cannot enable HDMI sys clock: %d\n", ret);
156                 return ret;
157         }
158
159         ret = clk_prepare_enable(hdmi->mclk);
160         if (ret) {
161                 DRM_DEV_ERROR(dev, "Cannot enable HDMI mclk clock: %d\n", ret);
162                 return ret;
163         }
164         ret = clk_prepare_enable(hdmi->bclk);
165         if (ret) {
166                 DRM_DEV_ERROR(dev, "Cannot enable HDMI bclk clock: %d\n", ret);
167                 return ret;
168         }
169         ret = reset_control_deassert(hdmi->tx_rst);
170         if (ret < 0) {
171                 dev_err(dev, "failed to deassert tx_rst\n");
172                 return ret;
173         }
174         return 0;
175 }
176
177 static void starfive_hdmi_disable_clk_assert_rst(struct device *dev, struct starfive_hdmi *hdmi)
178 {
179         int ret;
180
181         ret = reset_control_assert(hdmi->tx_rst);
182         if (ret < 0)
183                 dev_err(dev, "failed to assert tx_rst\n");
184
185         clk_disable_unprepare(hdmi->sys_clk);
186         clk_disable_unprepare(hdmi->mclk);
187         clk_disable_unprepare(hdmi->bclk);
188 }
189
190 #ifdef CONFIG_PM_SLEEP
191 static int hdmi_system_pm_suspend(struct device *dev)
192 {
193         return pm_runtime_force_suspend(dev);
194 }
195
196 static int hdmi_system_pm_resume(struct device *dev)
197 {
198         return pm_runtime_force_resume(dev);
199 }
200 #endif
201
202 #ifdef CONFIG_PM
203 static int hdmi_runtime_suspend(struct device *dev)
204 {
205         struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
206
207         starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
208
209         return 0;
210 }
211
212 static int hdmi_runtime_resume(struct device *dev)
213 {
214         struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
215
216         return starfive_hdmi_enable_clk_deassert_rst(dev, hdmi);
217 }
218 #endif
219
220 static void starfive_hdmi_tx_phy_power_down(struct starfive_hdmi *hdmi)
221 {
222         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
223 }
224
225 static void starfive_hdmi_tx_phy_power_on(struct starfive_hdmi *hdmi)
226 {
227         hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
228 }
229
230 static void starfive_hdmi_config_pll(struct starfive_hdmi *hdmi)
231 {
232         u32 val;
233         u8 reg_1ad_value = hdmi->post_cfg->post_div_en ?
234                  hdmi->post_cfg->postdiv : 0x00;
235         u8 reg_1aa_value = hdmi->post_cfg->post_div_en ?
236                  0x0e : 0x02;
237
238         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_CONTROL, STARFIVE_PRE_PLL_POWER_DOWN);
239         hdmi_writeb(hdmi, STARFIVE_POST_PLL_DIV_1,
240                     STARFIVE_POST_PLL_POST_DIV_ENABLE |
241                     STARFIVE_POST_PLL_REFCLK_SEL_TMDS |
242                     STARFIVE_POST_PLL_POWER_DOWN);
243         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_1, STARFIVE_PRE_PLL_PRE_DIV(hdmi->pre_cfg->prediv));
244
245         val = STARFIVE_SPREAD_SPECTRUM_MOD_DISABLE | STARFIVE_SPREAD_SPECTRUM_MOD_DOWN;
246         if (!hdmi->pre_cfg->fracdiv)
247                 val |= STARFIVE_PRE_PLL_FRAC_DIV_DISABLE;
248         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_2,
249                     STARFIVE_PRE_PLL_FB_DIV_11_8(hdmi->pre_cfg->fbdiv) | val);
250         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_3,
251                     STARFIVE_PRE_PLL_FB_DIV_7_0(hdmi->pre_cfg->fbdiv));
252         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_4,
253                     STARFIVE_PRE_PLL_TMDSCLK_DIV_C(hdmi->pre_cfg->tmds_div_c) |
254                     STARFIVE_PRE_PLL_TMDSCLK_DIV_A(hdmi->pre_cfg->tmds_div_a) |
255                     STARFIVE_PRE_PLL_TMDSCLK_DIV_B(hdmi->pre_cfg->tmds_div_b));
256
257         if (hdmi->pre_cfg->fracdiv) {
258                 hdmi_writeb(hdmi, STARFIVE_PRE_PLL_FRAC_DIV_L,
259                             STARFIVE_PRE_PLL_FRAC_DIV_7_0(hdmi->pre_cfg->fracdiv));
260                 hdmi_writeb(hdmi, STARFIVE_PRE_PLL_FRAC_DIV_M,
261                             STARFIVE_PRE_PLL_FRAC_DIV_15_8(hdmi->pre_cfg->fracdiv));
262                 hdmi_writeb(hdmi, STARFIVE_PRE_PLL_FRAC_DIV_H,
263                             STARFIVE_PRE_PLL_FRAC_DIV_23_16(hdmi->pre_cfg->fracdiv));
264         }
265
266         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_5,
267                     STARFIVE_PRE_PLL_PCLK_DIV_A(hdmi->pre_cfg->pclk_div_a) |
268                     STARFIVE_PRE_PLL_PCLK_DIV_B(hdmi->pre_cfg->pclk_div_b));
269         hdmi_writeb(hdmi, STARFIVE_PRE_PLL_DIV_6,
270                     STARFIVE_PRE_PLL_PCLK_DIV_C(hdmi->pre_cfg->pclk_div_c) |
271                     STARFIVE_PRE_PLL_PCLK_DIV_D(hdmi->pre_cfg->pclk_div_d));
272
273         /*pre-pll power down*/
274         hdmi_modb(hdmi, STARFIVE_PRE_PLL_CONTROL, STARFIVE_PRE_PLL_POWER_DOWN, 0);
275
276         hdmi_modb(hdmi, STARFIVE_POST_PLL_DIV_2, STARFIVE_POST_PLL_Pre_DIV_MASK,
277                   STARFIVE_POST_PLL_PRE_DIV(hdmi->post_cfg->prediv));
278         hdmi_writeb(hdmi, STARFIVE_POST_PLL_DIV_3, hdmi->post_cfg->fbdiv & 0xff);
279         hdmi_writeb(hdmi, STARFIVE_POST_PLL_DIV_4, reg_1ad_value);
280         hdmi_writeb(hdmi, STARFIVE_POST_PLL_DIV_1, reg_1aa_value);
281 }
282
283 static void starfive_hdmi_tmds_driver_on(struct starfive_hdmi *hdmi)
284 {
285         hdmi_modb(hdmi, STARFIVE_TMDS_CONTROL,
286                   STARFIVE_TMDS_DRIVER_ENABLE, STARFIVE_TMDS_DRIVER_ENABLE);
287 }
288
289 static void starfive_hdmi_sync_tmds(struct starfive_hdmi *hdmi)
290 {
291         /*first send 0 to this bit, then send 1 and keep 1 into this bit*/
292         hdmi_writeb(hdmi, HDMI_SYNC, 0x0);
293         hdmi_writeb(hdmi, HDMI_SYNC, 0x1);
294 }
295
296 static void starfive_hdmi_i2c_init(struct starfive_hdmi *hdmi)
297 {
298         int ddc_bus_freq;
299
300         ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
301
302         hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
303         hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
304
305         /* Clear the EDID interrupt flag and mute the interrupt */
306         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
307         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
308 }
309
310 static const
311 struct pre_pll_config *starfive_hdmi_phy_get_pre_pll_cfg(struct starfive_hdmi *hdmi,
312                                                          unsigned long rate)
313 {
314         const struct pre_pll_config *cfg = pre_pll_cfg_table;
315
316         rate = (rate / 1000) * 1000;
317         for (; cfg->pixclock != 0; cfg++)
318                 if (cfg->tmdsclock == rate && cfg->pixclock == rate)
319                         break;
320
321         if (cfg->pixclock == 0)
322                 return ERR_PTR(-EINVAL);
323
324         return cfg;
325 }
326
327 static int starfive_hdmi_phy_clk_set_rate(struct starfive_hdmi *hdmi)
328 {
329         hdmi->post_cfg = post_pll_cfg_table;
330
331         hdmi->pre_cfg = starfive_hdmi_phy_get_pre_pll_cfg(hdmi, hdmi->tmds_rate);
332         if (IS_ERR(hdmi->pre_cfg))
333                 return PTR_ERR(hdmi->pre_cfg);
334
335         for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
336                 if (hdmi->tmds_rate <= hdmi->post_cfg->tmdsclock)
337                         break;
338
339         starfive_hdmi_config_pll(hdmi);
340
341         return 0;
342 }
343
344 static int starfive_hdmi_config_video_timing(struct starfive_hdmi *hdmi,
345                                              struct drm_display_mode *mode)
346 {
347         int value;
348         /* Set detail external video timing */
349         value = mode->htotal;
350         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
351         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
352
353         value = mode->htotal - mode->hdisplay;
354         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
355         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
356
357         value = mode->htotal - mode->hsync_start;
358         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
359         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
360
361         value = mode->hsync_end - mode->hsync_start;
362         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
363         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
364
365         value = mode->vtotal;
366         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
367         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
368
369         value = mode->vtotal - mode->vdisplay;
370         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
371
372         value = mode->vtotal - mode->vsync_start;
373         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
374
375         value = mode->vsync_end - mode->vsync_start;
376         hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
377
378         /* Set detail external video timing polarity and interlace mode */
379         value = v_EXTERANL_VIDEO(1);
380         value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
381                 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
382         value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
383                 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
384         value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
385                 v_INETLACE(1) : v_INETLACE(0);
386
387         hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
388         return 0;
389 }
390
391 static void starfive_hdmi_improve_eye_diagram(struct starfive_hdmi *hdmi)
392 {
393         switch (hdmi->hdmi_data.vic) {
394         case 95:
395         case 94:
396         case 93:
397                 hdmi_writeb(hdmi, 0x100, 0x00);
398                 hdmi_writeb(hdmi, 0x1bb, 0x40);
399                 hdmi_writeb(hdmi, 0x1bc, 0x40);
400                 hdmi_writeb(hdmi, 0x1bd, 0x40);
401                 hdmi_writeb(hdmi, 0x1bf, 0x02);
402                 hdmi_writeb(hdmi, 0x1c0, 0x22);
403                 break;
404         case 16:
405         case 31:
406                 hdmi_writeb(hdmi, 0x1bf, 0x02);
407                 hdmi_writeb(hdmi, 0x1c0, 0x22);
408                 break;
409         case 4:
410         case 3:
411         case 1:
412                 hdmi_writeb(hdmi, 0x1bf, 0x00);
413                 hdmi_writeb(hdmi, 0x1c0, 0x00);
414                 break;
415
416         }
417 }
418
419 static int starfive_hdmi_setup(struct starfive_hdmi *hdmi,
420                                struct drm_display_mode *mode)
421 {
422         hdmi_modb(hdmi, STARFIVE_BIAS_CONTROL, STARFIVE_BIAS_ENABLE, STARFIVE_BIAS_ENABLE);
423         hdmi_writeb(hdmi, STARFIVE_RX_CONTROL, STARFIVE_RX_ENABLE);
424         hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
425
426         hdmi->tmds_rate = mode->clock * 1000;
427         starfive_hdmi_phy_clk_set_rate(hdmi);
428
429         while (!(hdmi_readb(hdmi, STARFIVE_PRE_PLL_LOCK_STATUS) & 0x1))
430                 continue;
431         while (!(hdmi_readb(hdmi, STARFIVE_POST_PLL_LOCK_STATUS) & 0x1))
432                 continue;
433
434         /*turn on LDO*/
435         hdmi_writeb(hdmi, STARFIVE_LDO_CONTROL, STARFIVE_LDO_ENABLE);
436         /*turn on serializer*/
437         hdmi_writeb(hdmi, STARFIVE_SERIALIER_CONTROL, STARFIVE_SERIALIER_ENABLE);
438
439         starfive_hdmi_improve_eye_diagram(hdmi);
440
441         starfive_hdmi_tx_phy_power_down(hdmi);
442         starfive_hdmi_config_video_timing(hdmi, mode);
443         starfive_hdmi_tx_phy_power_on(hdmi);
444
445         starfive_hdmi_tmds_driver_on(hdmi);
446         starfive_hdmi_sync_tmds(hdmi);
447
448         return 0;
449 }
450
451 static void starfive_hdmi_encoder_mode_set(struct drm_encoder *encoder,
452                                            struct drm_display_mode *mode,
453                                            struct drm_display_mode *adj_mode)
454 {
455         struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
456
457         memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
458 }
459
460 static void starfive_hdmi_encoder_enable(struct drm_encoder *encoder)
461 {
462         struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
463
464         pm_runtime_get_sync(hdmi->dev);
465
466         mdelay(10);
467         starfive_hdmi_setup(hdmi, &hdmi->previous_mode);
468 }
469
470 static void starfive_hdmi_encoder_disable(struct drm_encoder *encoder)
471 {
472         struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
473
474         pm_runtime_put(hdmi->dev);
475 }
476
477 static bool starfive_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
478                                              const struct drm_display_mode *mode,
479                                              struct drm_display_mode *adj_mode)
480 {
481         return true;
482 }
483
484 static int
485 starfive_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
486                                    struct drm_crtc_state *crtc_state,
487                                    struct drm_connector_state *conn_state)
488 {
489         return 0;
490 }
491
492 static const struct drm_encoder_helper_funcs starfive_hdmi_encoder_helper_funcs = {
493         .enable     = starfive_hdmi_encoder_enable,
494         .disable    = starfive_hdmi_encoder_disable,
495         .mode_fixup = starfive_hdmi_encoder_mode_fixup,
496         .mode_set   = starfive_hdmi_encoder_mode_set,
497         .atomic_check = starfive_hdmi_encoder_atomic_check,
498 };
499
500 static enum drm_connector_status
501 starfive_hdmi_connector_detect(struct drm_connector *connector, bool force)
502 {
503         struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
504         int ret;
505
506         ret = pm_runtime_get_sync(hdmi->dev);
507         if (ret < 0)
508                 return ret;
509
510         ret = (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
511                 connector_status_connected : connector_status_disconnected;
512
513         pm_runtime_put(hdmi->dev);
514
515         return ret;
516 }
517
518 static int starfive_hdmi_connector_get_modes(struct drm_connector *connector)
519 {
520         struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
521         struct edid *edid;
522         int ret = 0;
523
524         if (!hdmi->ddc)
525                 return 0;
526
527         edid = drm_get_edid(connector, hdmi->ddc);
528         if (edid) {
529                 hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
530                 hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
531                 drm_connector_update_edid_property(connector, edid);
532                 ret = drm_add_edid_modes(connector, edid);
533                 kfree(edid);
534         }
535
536         return ret;
537 }
538
539 static enum drm_mode_status
540 starfive_hdmi_connector_mode_valid(struct drm_connector *connector,
541                                    struct drm_display_mode *mode)
542 {
543         const struct pre_pll_config *cfg = pre_pll_cfg_table;
544         u32 vic = drm_match_cea_mode(mode);
545         int pclk = mode->clock * 1000;
546         bool valid = false;
547         int i;
548
549
550         if (pclk > 297000000)
551                 return MODE_BAD;
552
553         for (i = 0; cfg[i].pixclock != (~0UL); i++) {
554                 if (pclk == cfg[i].pixclock) {
555                         valid = true;
556                         break;
557                 }
558         }
559
560         if (!valid)
561                 return MODE_BAD;
562
563         if (vic >= 1)
564                 return MODE_OK;
565         else
566                 return MODE_BAD;
567 }
568
569 static int
570 starfive_hdmi_probe_single_connector_modes(struct drm_connector *connector,
571                                            u32 maxX, u32 maxY)
572 {
573         struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
574         int ret;
575
576         pm_runtime_get_sync(hdmi->dev);
577
578         ret = drm_helper_probe_single_connector_modes(connector, 3840, 2160);
579
580         pm_runtime_put(hdmi->dev);
581
582         return ret;
583 }
584
585 static void starfive_hdmi_connector_destroy(struct drm_connector *connector)
586 {
587         drm_connector_unregister(connector);
588         drm_connector_cleanup(connector);
589 }
590
591 static const struct drm_connector_funcs starfive_hdmi_connector_funcs = {
592         .fill_modes = starfive_hdmi_probe_single_connector_modes,
593         .detect = starfive_hdmi_connector_detect,
594         .destroy = starfive_hdmi_connector_destroy,
595         .reset = drm_atomic_helper_connector_reset,
596         .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
597         .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
598 };
599
600 static struct drm_connector_helper_funcs starfive_hdmi_connector_helper_funcs = {
601         .get_modes = starfive_hdmi_connector_get_modes,
602         .mode_valid = starfive_hdmi_connector_mode_valid,
603 };
604
605 static int starfive_hdmi_register(struct drm_device *drm, struct starfive_hdmi *hdmi)
606 {
607         struct drm_encoder *encoder = &hdmi->encoder;
608         struct device *dev = hdmi->dev;
609
610         encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
611
612         /*
613          * If we failed to find the CRTC(s) which this encoder is
614          * supposed to be connected to, it's because the CRTC has
615          * not been registered yet.  Defer probing, and hope that
616          * the required CRTC is added later.
617          */
618         if (encoder->possible_crtcs == 0)
619                 return -EPROBE_DEFER;
620
621         drm_encoder_helper_add(encoder, &starfive_hdmi_encoder_helper_funcs);
622         drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
623
624         hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
625
626         drm_connector_helper_add(&hdmi->connector,
627                                  &starfive_hdmi_connector_helper_funcs);
628         drm_connector_init_with_ddc(drm, &hdmi->connector,
629                                     &starfive_hdmi_connector_funcs,
630                                     DRM_MODE_CONNECTOR_HDMIA,
631                                     hdmi->ddc);
632
633         drm_connector_attach_encoder(&hdmi->connector, encoder);
634
635         return 0;
636 }
637
638 static irqreturn_t starfive_hdmi_i2c_irq(struct starfive_hdmi *hdmi)
639 {
640         struct starfive_hdmi_i2c *i2c = hdmi->i2c;
641         u8 stat;
642
643         stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
644         if (!(stat & m_INT_EDID_READY))
645                 return IRQ_NONE;
646
647         /* Clear HDMI EDID interrupt flag */
648         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
649
650         complete(&i2c->cmp);
651
652         return IRQ_HANDLED;
653 }
654
655 static irqreturn_t starfive_hdmi_hardirq(int irq, void *dev_id)
656 {
657         struct starfive_hdmi *hdmi = dev_id;
658         irqreturn_t ret = IRQ_NONE;
659         u8 interrupt;
660
661         if (hdmi->i2c)
662                 ret = starfive_hdmi_i2c_irq(hdmi);
663
664         interrupt = hdmi_readb(hdmi, HDMI_STATUS);
665         if (interrupt & m_INT_HOTPLUG) {
666                 hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
667                 ret = IRQ_WAKE_THREAD;
668         }
669
670         return ret;
671 }
672
673 static irqreturn_t starfive_hdmi_irq(int irq, void *dev_id)
674 {
675         struct starfive_hdmi *hdmi = dev_id;
676
677         drm_helper_hpd_irq_event(hdmi->connector.dev);
678
679         return IRQ_HANDLED;
680 }
681
682 static int starfive_hdmi_i2c_read(struct starfive_hdmi *hdmi, struct i2c_msg *msgs)
683 {
684         int length = msgs->len;
685         u8 *buf = msgs->buf;
686         int ret;
687
688         ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
689         if (!ret)
690                 return -EAGAIN;
691
692         while (length--)
693                 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
694
695         return 0;
696 }
697
698 static int starfive_hdmi_i2c_write(struct starfive_hdmi *hdmi, struct i2c_msg *msgs)
699 {
700         /*
701          * The DDC module only support read EDID message, so
702          * we assume that each word write to this i2c adapter
703          * should be the offset of EDID word address.
704          */
705         if (msgs->len != 1 ||
706             (msgs->addr != DDC_ADDR && msgs->addr != DDC_SEGMENT_ADDR))
707                 return -EINVAL;
708
709         reinit_completion(&hdmi->i2c->cmp);
710
711         if (msgs->addr == DDC_SEGMENT_ADDR)
712                 hdmi->i2c->segment_addr = msgs->buf[0];
713         if (msgs->addr == DDC_ADDR)
714                 hdmi->i2c->ddc_addr = msgs->buf[0];
715
716         /* Set edid fifo first addr */
717         hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
718
719         /* Set edid word address 0x00/0x80 */
720         hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
721
722         /* Set edid segment pointer */
723         hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
724
725         return 0;
726 }
727
728 static int starfive_hdmi_i2c_xfer(struct i2c_adapter *adap,
729                                   struct i2c_msg *msgs, int num)
730 {
731         struct starfive_hdmi *hdmi = i2c_get_adapdata(adap);
732         struct starfive_hdmi_i2c *i2c = hdmi->i2c;
733         int i, ret = 0;
734
735         mutex_lock(&i2c->lock);
736
737         /* Clear the EDID interrupt flag and unmute the interrupt */
738         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
739         hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
740
741         for (i = 0; i < num; i++) {
742                 DRM_DEV_DEBUG(hdmi->dev,
743                               "xfer: num: %d/%d, len: %d, flags: %#x\n",
744                               i + 1, num, msgs[i].len, msgs[i].flags);
745
746                 if (msgs[i].flags & I2C_M_RD)
747                         ret = starfive_hdmi_i2c_read(hdmi, &msgs[i]);
748                 else
749                         ret = starfive_hdmi_i2c_write(hdmi, &msgs[i]);
750
751                 if (ret < 0)
752                         break;
753         }
754
755         if (!ret)
756                 ret = num;
757
758         /* Mute HDMI EDID interrupt */
759         hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
760
761         mutex_unlock(&i2c->lock);
762
763         return ret;
764 }
765
766 static u32 starfive_hdmi_i2c_func(struct i2c_adapter *adapter)
767 {
768         return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
769 }
770
771 static const struct i2c_algorithm starfive_hdmi_algorithm = {
772         .master_xfer    = starfive_hdmi_i2c_xfer,
773         .functionality  = starfive_hdmi_i2c_func,
774 };
775
776 static struct i2c_adapter *starfive_hdmi_i2c_adapter(struct starfive_hdmi *hdmi)
777 {
778         struct i2c_adapter *adap;
779         struct starfive_hdmi_i2c *i2c;
780         int ret;
781
782         i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
783         if (!i2c)
784                 return ERR_PTR(-ENOMEM);
785
786         mutex_init(&i2c->lock);
787         init_completion(&i2c->cmp);
788
789         adap = &i2c->adap;
790         adap->class = I2C_CLASS_DDC;
791         adap->owner = THIS_MODULE;
792         adap->dev.parent = hdmi->dev;
793         adap->algo = &starfive_hdmi_algorithm;
794         strscpy(adap->name, "Starfive HDMI", sizeof(adap->name));
795         i2c_set_adapdata(adap, hdmi);
796
797         ret = i2c_add_adapter(adap);
798         if (ret) {
799                 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
800                 devm_kfree(hdmi->dev, i2c);
801                 return ERR_PTR(ret);
802         }
803
804         hdmi->i2c = i2c;
805
806         DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver success\n", adap->name);
807
808         return adap;
809 }
810
811 static int starfive_hdmi_get_clk_rst(struct device *dev, struct starfive_hdmi *hdmi)
812 {
813         hdmi->sys_clk = devm_clk_get(dev, "sysclk");
814         if (IS_ERR(hdmi->sys_clk)) {
815                 DRM_DEV_ERROR(dev, "Unable to get HDMI sysclk clk\n");
816                 return PTR_ERR(hdmi->sys_clk);
817         }
818         hdmi->mclk = devm_clk_get(dev, "mclk");
819         if (IS_ERR(hdmi->mclk)) {
820                 DRM_DEV_ERROR(dev, "Unable to get HDMI mclk clk\n");
821                 return PTR_ERR(hdmi->mclk);
822         }
823         hdmi->bclk = devm_clk_get(dev, "bclk");
824         if (IS_ERR(hdmi->bclk)) {
825                 DRM_DEV_ERROR(dev, "Unable to get HDMI bclk clk\n");
826                 return PTR_ERR(hdmi->bclk);
827         }
828         hdmi->tx_rst = reset_control_get_shared(dev, "hdmi_tx");
829         if (IS_ERR(hdmi->tx_rst)) {
830                 DRM_DEV_ERROR(dev, "Unable to get HDMI tx rst\n");
831                 return PTR_ERR(hdmi->tx_rst);
832         }
833         return 0;
834 }
835
836 static int starfive_hdmi_bind(struct device *dev, struct device *master,
837                               void *data)
838 {
839         struct platform_device *pdev = to_platform_device(dev);
840         struct drm_device *drm = data;
841         struct starfive_hdmi *hdmi;
842         struct resource *iores;
843         int irq;
844         int ret;
845
846         hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
847         if (!hdmi)
848                 return -ENOMEM;
849
850         hdmi->dev = dev;
851         hdmi->drm_dev = drm;
852
853         iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
854         hdmi->regs = devm_ioremap_resource(dev, iores);
855         if (IS_ERR(hdmi->regs))
856                 return PTR_ERR(hdmi->regs);
857
858         ret = starfive_hdmi_get_clk_rst(dev, hdmi);
859         ret = starfive_hdmi_enable_clk_deassert_rst(dev, hdmi);
860
861         irq = platform_get_irq(pdev, 0);
862         if (irq < 0) {
863                 ret = irq;
864                 goto err_disable_clk;
865         }
866
867         hdmi->ddc = starfive_hdmi_i2c_adapter(hdmi);
868         if (IS_ERR(hdmi->ddc)) {
869                 ret = PTR_ERR(hdmi->ddc);
870                 hdmi->ddc = NULL;
871                 goto err_disable_clk;
872         }
873
874         hdmi->tmds_rate = clk_get_rate(hdmi->sys_clk);
875
876         starfive_hdmi_i2c_init(hdmi);
877
878         ret = starfive_hdmi_register(drm, hdmi);
879         if (ret)
880                 goto err_put_adapter;
881
882         dev_set_drvdata(dev, hdmi);
883
884         /* Unmute hotplug interrupt */
885         hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
886
887         ret = devm_request_threaded_irq(dev, irq, starfive_hdmi_hardirq,
888                                         starfive_hdmi_irq, IRQF_SHARED,
889                                         dev_name(dev), hdmi);
890         if (ret < 0)
891                 goto err_cleanup_hdmi;
892
893         ret = starfive_hdmi_audio_init(hdmi);
894         if (ret)
895                 dev_err(dev, "failed to audio init\n");
896
897         pm_runtime_use_autosuspend(&pdev->dev);
898         pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
899         pm_runtime_enable(&pdev->dev);
900
901         starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
902
903         return 0;
904 err_cleanup_hdmi:
905         hdmi->connector.funcs->destroy(&hdmi->connector);
906         hdmi->encoder.funcs->destroy(&hdmi->encoder);
907 err_put_adapter:
908         i2c_put_adapter(hdmi->ddc);
909 err_disable_clk:
910         clk_disable_unprepare(hdmi->sys_clk);
911         clk_disable_unprepare(hdmi->mclk);
912         clk_disable_unprepare(hdmi->bclk);
913
914         return ret;
915 }
916
917 static void starfive_hdmi_unbind(struct device *dev, struct device *master,
918                                  void *data)
919 {
920         struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
921
922         hdmi->connector.funcs->destroy(&hdmi->connector);
923         hdmi->encoder.funcs->destroy(&hdmi->encoder);
924
925         i2c_put_adapter(hdmi->ddc);
926
927         starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
928 }
929
930 static const struct component_ops starfive_hdmi_ops = {
931         .bind   = starfive_hdmi_bind,
932         .unbind = starfive_hdmi_unbind,
933 };
934
935 static int starfive_hdmi_probe(struct platform_device *pdev)
936 {
937         return component_add(&pdev->dev, &starfive_hdmi_ops);
938 }
939
940 static int starfive_hdmi_remove(struct platform_device *pdev)
941 {
942         component_del(&pdev->dev, &starfive_hdmi_ops);
943
944         return 0;
945 }
946
947 static const struct dev_pm_ops hdmi_pm_ops = {
948         SET_RUNTIME_PM_OPS(hdmi_runtime_suspend, hdmi_runtime_resume, NULL)
949         SET_LATE_SYSTEM_SLEEP_PM_OPS(hdmi_system_pm_suspend, hdmi_system_pm_resume)
950 };
951
952 static const struct of_device_id starfive_hdmi_dt_ids[] = {
953         { .compatible = "starfive,hdmi",
954         },
955         {},
956 };
957 MODULE_DEVICE_TABLE(of, starfive_hdmi_dt_ids);
958
959 struct platform_driver starfive_hdmi_driver = {
960         .probe  = starfive_hdmi_probe,
961         .remove = starfive_hdmi_remove,
962         .driver = {
963                 .name = "starfive-hdmi",
964                 .of_match_table = starfive_hdmi_dt_ids,
965                 .pm = &hdmi_pm_ops,
966         },
967 };
968
969 MODULE_AUTHOR("StarFive Corporation");
970 MODULE_DESCRIPTION("Starfive HDMI Driver");
971 MODULE_LICENSE("GPL");