1 // SPDX-License-Identifier: GPL-2.0-only
3 * Copyright (C) 2023 StarFive Technology Co., Ltd.
7 #include <linux/component.h>
8 #include <linux/delay.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>
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>
27 #include "starfive_hdmi.h"
30 static struct starfive_hdmi *encoder_to_hdmi(struct drm_encoder *encoder)
32 return container_of(encoder, struct starfive_hdmi, encoder);
35 static struct starfive_hdmi *connector_to_hdmi(struct drm_connector *connector)
37 return container_of(connector, struct starfive_hdmi, connector);
40 struct starfive_hdmi_i2c {
41 struct i2c_adapter adap;
45 /* protects the edid data when use i2c cmd to read edid */
47 struct completion cmp;
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},
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},
130 inline u8 hdmi_readb(struct starfive_hdmi *hdmi, u16 offset)
132 return readl_relaxed(hdmi->regs + (offset) * 0x04);
135 inline void hdmi_writeb(struct starfive_hdmi *hdmi, u16 offset, u32 val)
137 writel_relaxed(val, hdmi->regs + (offset) * 0x04);
140 inline void hdmi_modb(struct starfive_hdmi *hdmi, u16 offset,
143 u8 temp = hdmi_readb(hdmi, offset) & ~msk;
146 hdmi_writeb(hdmi, offset, temp);
149 static int starfive_hdmi_enable_clk_deassert_rst(struct device *dev, struct starfive_hdmi *hdmi)
153 ret = clk_prepare_enable(hdmi->sys_clk);
155 DRM_DEV_ERROR(dev, "Cannot enable HDMI sys clock: %d\n", ret);
159 ret = clk_prepare_enable(hdmi->mclk);
161 DRM_DEV_ERROR(dev, "Cannot enable HDMI mclk clock: %d\n", ret);
164 ret = clk_prepare_enable(hdmi->bclk);
166 DRM_DEV_ERROR(dev, "Cannot enable HDMI bclk clock: %d\n", ret);
169 ret = reset_control_deassert(hdmi->tx_rst);
171 dev_err(dev, "failed to deassert tx_rst\n");
177 static void starfive_hdmi_disable_clk_assert_rst(struct device *dev, struct starfive_hdmi *hdmi)
181 ret = reset_control_assert(hdmi->tx_rst);
183 dev_err(dev, "failed to assert tx_rst\n");
185 clk_disable_unprepare(hdmi->sys_clk);
186 clk_disable_unprepare(hdmi->mclk);
187 clk_disable_unprepare(hdmi->bclk);
190 #ifdef CONFIG_PM_SLEEP
191 static int hdmi_system_pm_suspend(struct device *dev)
193 return pm_runtime_force_suspend(dev);
196 static int hdmi_system_pm_resume(struct device *dev)
198 return pm_runtime_force_resume(dev);
203 static int hdmi_runtime_suspend(struct device *dev)
205 struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
207 starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
212 static int hdmi_runtime_resume(struct device *dev)
214 struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
216 return starfive_hdmi_enable_clk_deassert_rst(dev, hdmi);
220 static void starfive_hdmi_tx_phy_power_down(struct starfive_hdmi *hdmi)
222 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
225 static void starfive_hdmi_tx_phy_power_on(struct starfive_hdmi *hdmi)
227 hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
230 static void starfive_hdmi_config_pll(struct starfive_hdmi *hdmi)
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 ?
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));
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));
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));
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));
273 /*pre-pll power down*/
274 hdmi_modb(hdmi, STARFIVE_PRE_PLL_CONTROL, STARFIVE_PRE_PLL_POWER_DOWN, 0);
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);
283 static void starfive_hdmi_tmds_driver_on(struct starfive_hdmi *hdmi)
285 hdmi_modb(hdmi, STARFIVE_TMDS_CONTROL,
286 STARFIVE_TMDS_DRIVER_ENABLE, STARFIVE_TMDS_DRIVER_ENABLE);
289 static void starfive_hdmi_sync_tmds(struct starfive_hdmi *hdmi)
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);
296 static void starfive_hdmi_i2c_init(struct starfive_hdmi *hdmi)
300 ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
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);
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);
311 struct pre_pll_config *starfive_hdmi_phy_get_pre_pll_cfg(struct starfive_hdmi *hdmi,
314 const struct pre_pll_config *cfg = pre_pll_cfg_table;
316 rate = (rate / 1000) * 1000;
317 for (; cfg->pixclock != 0; cfg++)
318 if (cfg->tmdsclock == rate && cfg->pixclock == rate)
321 if (cfg->pixclock == 0)
322 return ERR_PTR(-EINVAL);
327 static int starfive_hdmi_phy_clk_set_rate(struct starfive_hdmi *hdmi)
329 hdmi->post_cfg = post_pll_cfg_table;
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);
335 for (; hdmi->post_cfg->tmdsclock != 0; hdmi->post_cfg++)
336 if (hdmi->tmds_rate <= hdmi->post_cfg->tmdsclock)
339 starfive_hdmi_config_pll(hdmi);
344 static int starfive_hdmi_config_video_timing(struct starfive_hdmi *hdmi,
345 struct drm_display_mode *mode)
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);
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);
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);
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);
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);
369 value = mode->vtotal - mode->vdisplay;
370 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
372 value = mode->vtotal - mode->vsync_start;
373 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
375 value = mode->vsync_end - mode->vsync_start;
376 hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
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);
387 hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
391 static void starfive_hdmi_improve_eye_diagram(struct starfive_hdmi *hdmi)
393 switch (hdmi->hdmi_data.vic) {
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);
406 hdmi_writeb(hdmi, 0x1bf, 0x02);
407 hdmi_writeb(hdmi, 0x1c0, 0x22);
412 hdmi_writeb(hdmi, 0x1bf, 0x00);
413 hdmi_writeb(hdmi, 0x1c0, 0x00);
419 static int starfive_hdmi_setup(struct starfive_hdmi *hdmi,
420 struct drm_display_mode *mode)
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);
426 hdmi->tmds_rate = mode->clock * 1000;
427 starfive_hdmi_phy_clk_set_rate(hdmi);
429 while (!(hdmi_readb(hdmi, STARFIVE_PRE_PLL_LOCK_STATUS) & 0x1))
431 while (!(hdmi_readb(hdmi, STARFIVE_POST_PLL_LOCK_STATUS) & 0x1))
435 hdmi_writeb(hdmi, STARFIVE_LDO_CONTROL, STARFIVE_LDO_ENABLE);
436 /*turn on serializer*/
437 hdmi_writeb(hdmi, STARFIVE_SERIALIER_CONTROL, STARFIVE_SERIALIER_ENABLE);
439 starfive_hdmi_improve_eye_diagram(hdmi);
441 starfive_hdmi_tx_phy_power_down(hdmi);
442 starfive_hdmi_config_video_timing(hdmi, mode);
443 starfive_hdmi_tx_phy_power_on(hdmi);
445 starfive_hdmi_tmds_driver_on(hdmi);
446 starfive_hdmi_sync_tmds(hdmi);
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)
455 struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
457 memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
460 static void starfive_hdmi_encoder_enable(struct drm_encoder *encoder)
462 struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
464 pm_runtime_get_sync(hdmi->dev);
467 starfive_hdmi_setup(hdmi, &hdmi->previous_mode);
470 static void starfive_hdmi_encoder_disable(struct drm_encoder *encoder)
472 struct starfive_hdmi *hdmi = encoder_to_hdmi(encoder);
474 pm_runtime_put(hdmi->dev);
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)
485 starfive_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
486 struct drm_crtc_state *crtc_state,
487 struct drm_connector_state *conn_state)
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,
500 static enum drm_connector_status
501 starfive_hdmi_connector_detect(struct drm_connector *connector, bool force)
503 struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
506 ret = pm_runtime_get_sync(hdmi->dev);
510 ret = (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
511 connector_status_connected : connector_status_disconnected;
513 pm_runtime_put(hdmi->dev);
518 static int starfive_hdmi_connector_get_modes(struct drm_connector *connector)
520 struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
527 edid = drm_get_edid(connector, hdmi->ddc);
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);
539 static enum drm_mode_status
540 starfive_hdmi_connector_mode_valid(struct drm_connector *connector,
541 struct drm_display_mode *mode)
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;
550 if (pclk > 297000000)
553 for (i = 0; cfg[i].pixclock != (~0UL); i++) {
554 if (pclk == cfg[i].pixclock) {
570 starfive_hdmi_probe_single_connector_modes(struct drm_connector *connector,
573 struct starfive_hdmi *hdmi = connector_to_hdmi(connector);
576 pm_runtime_get_sync(hdmi->dev);
578 ret = drm_helper_probe_single_connector_modes(connector, 3840, 2160);
580 pm_runtime_put(hdmi->dev);
585 static void starfive_hdmi_connector_destroy(struct drm_connector *connector)
587 drm_connector_unregister(connector);
588 drm_connector_cleanup(connector);
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,
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,
605 static int starfive_hdmi_register(struct drm_device *drm, struct starfive_hdmi *hdmi)
607 struct drm_encoder *encoder = &hdmi->encoder;
608 struct device *dev = hdmi->dev;
610 encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
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.
618 if (encoder->possible_crtcs == 0)
619 return -EPROBE_DEFER;
621 drm_encoder_helper_add(encoder, &starfive_hdmi_encoder_helper_funcs);
622 drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
624 hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
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,
633 drm_connector_attach_encoder(&hdmi->connector, encoder);
638 static irqreturn_t starfive_hdmi_i2c_irq(struct starfive_hdmi *hdmi)
640 struct starfive_hdmi_i2c *i2c = hdmi->i2c;
643 stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
644 if (!(stat & m_INT_EDID_READY))
647 /* Clear HDMI EDID interrupt flag */
648 hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
655 static irqreturn_t starfive_hdmi_hardirq(int irq, void *dev_id)
657 struct starfive_hdmi *hdmi = dev_id;
658 irqreturn_t ret = IRQ_NONE;
662 ret = starfive_hdmi_i2c_irq(hdmi);
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;
673 static irqreturn_t starfive_hdmi_irq(int irq, void *dev_id)
675 struct starfive_hdmi *hdmi = dev_id;
677 drm_helper_hpd_irq_event(hdmi->connector.dev);
682 static int starfive_hdmi_i2c_read(struct starfive_hdmi *hdmi, struct i2c_msg *msgs)
684 int length = msgs->len;
688 ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
693 *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
698 static int starfive_hdmi_i2c_write(struct starfive_hdmi *hdmi, struct i2c_msg *msgs)
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.
705 if (msgs->len != 1 ||
706 (msgs->addr != DDC_ADDR && msgs->addr != DDC_SEGMENT_ADDR))
709 reinit_completion(&hdmi->i2c->cmp);
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];
716 /* Set edid fifo first addr */
717 hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
719 /* Set edid word address 0x00/0x80 */
720 hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
722 /* Set edid segment pointer */
723 hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
728 static int starfive_hdmi_i2c_xfer(struct i2c_adapter *adap,
729 struct i2c_msg *msgs, int num)
731 struct starfive_hdmi *hdmi = i2c_get_adapdata(adap);
732 struct starfive_hdmi_i2c *i2c = hdmi->i2c;
735 mutex_lock(&i2c->lock);
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);
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);
746 if (msgs[i].flags & I2C_M_RD)
747 ret = starfive_hdmi_i2c_read(hdmi, &msgs[i]);
749 ret = starfive_hdmi_i2c_write(hdmi, &msgs[i]);
758 /* Mute HDMI EDID interrupt */
759 hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
761 mutex_unlock(&i2c->lock);
766 static u32 starfive_hdmi_i2c_func(struct i2c_adapter *adapter)
768 return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
771 static const struct i2c_algorithm starfive_hdmi_algorithm = {
772 .master_xfer = starfive_hdmi_i2c_xfer,
773 .functionality = starfive_hdmi_i2c_func,
776 static struct i2c_adapter *starfive_hdmi_i2c_adapter(struct starfive_hdmi *hdmi)
778 struct i2c_adapter *adap;
779 struct starfive_hdmi_i2c *i2c;
782 i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
784 return ERR_PTR(-ENOMEM);
786 mutex_init(&i2c->lock);
787 init_completion(&i2c->cmp);
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);
797 ret = i2c_add_adapter(adap);
799 dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
800 devm_kfree(hdmi->dev, i2c);
806 DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver success\n", adap->name);
811 static int starfive_hdmi_get_clk_rst(struct device *dev, struct starfive_hdmi *hdmi)
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);
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);
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);
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);
836 static int starfive_hdmi_bind(struct device *dev, struct device *master,
839 struct platform_device *pdev = to_platform_device(dev);
840 struct drm_device *drm = data;
841 struct starfive_hdmi *hdmi;
842 struct resource *iores;
846 hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
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);
858 ret = starfive_hdmi_get_clk_rst(dev, hdmi);
859 ret = starfive_hdmi_enable_clk_deassert_rst(dev, hdmi);
861 irq = platform_get_irq(pdev, 0);
864 goto err_disable_clk;
867 hdmi->ddc = starfive_hdmi_i2c_adapter(hdmi);
868 if (IS_ERR(hdmi->ddc)) {
869 ret = PTR_ERR(hdmi->ddc);
871 goto err_disable_clk;
874 hdmi->tmds_rate = clk_get_rate(hdmi->sys_clk);
876 starfive_hdmi_i2c_init(hdmi);
878 ret = starfive_hdmi_register(drm, hdmi);
880 goto err_put_adapter;
882 dev_set_drvdata(dev, hdmi);
884 /* Unmute hotplug interrupt */
885 hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
887 ret = devm_request_threaded_irq(dev, irq, starfive_hdmi_hardirq,
888 starfive_hdmi_irq, IRQF_SHARED,
889 dev_name(dev), hdmi);
891 goto err_cleanup_hdmi;
893 ret = starfive_hdmi_audio_init(hdmi);
895 dev_err(dev, "failed to audio init\n");
897 pm_runtime_use_autosuspend(&pdev->dev);
898 pm_runtime_set_autosuspend_delay(&pdev->dev, 500);
899 pm_runtime_enable(&pdev->dev);
901 starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
905 hdmi->connector.funcs->destroy(&hdmi->connector);
906 hdmi->encoder.funcs->destroy(&hdmi->encoder);
908 i2c_put_adapter(hdmi->ddc);
910 clk_disable_unprepare(hdmi->sys_clk);
911 clk_disable_unprepare(hdmi->mclk);
912 clk_disable_unprepare(hdmi->bclk);
917 static void starfive_hdmi_unbind(struct device *dev, struct device *master,
920 struct starfive_hdmi *hdmi = dev_get_drvdata(dev);
922 hdmi->connector.funcs->destroy(&hdmi->connector);
923 hdmi->encoder.funcs->destroy(&hdmi->encoder);
925 i2c_put_adapter(hdmi->ddc);
927 starfive_hdmi_disable_clk_assert_rst(dev, hdmi);
930 static const struct component_ops starfive_hdmi_ops = {
931 .bind = starfive_hdmi_bind,
932 .unbind = starfive_hdmi_unbind,
935 static int starfive_hdmi_probe(struct platform_device *pdev)
937 return component_add(&pdev->dev, &starfive_hdmi_ops);
940 static int starfive_hdmi_remove(struct platform_device *pdev)
942 component_del(&pdev->dev, &starfive_hdmi_ops);
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)
952 static const struct of_device_id starfive_hdmi_dt_ids[] = {
953 { .compatible = "starfive,hdmi",
957 MODULE_DEVICE_TABLE(of, starfive_hdmi_dt_ids);
959 struct platform_driver starfive_hdmi_driver = {
960 .probe = starfive_hdmi_probe,
961 .remove = starfive_hdmi_remove,
963 .name = "starfive-hdmi",
964 .of_match_table = starfive_hdmi_dt_ids,
969 MODULE_AUTHOR("StarFive Corporation");
970 MODULE_DESCRIPTION("Starfive HDMI Driver");
971 MODULE_LICENSE("GPL");