xref: /linux/drivers/gpu/drm/rockchip/dw_hdmi_qp-rockchip.c (revision d3b402c5a2d47f51eb0581da1a7b142f82cb10d1)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (c) 2021-2022 Rockchip Electronics Co., Ltd.
4  * Copyright (c) 2024 Collabora Ltd.
5  *
6  * Author: Algea Cao <algea.cao@rock-chips.com>
7  * Author: Cristian Ciocaltea <cristian.ciocaltea@collabora.com>
8  */
9 
10 #include <linux/clk.h>
11 #include <linux/gpio/consumer.h>
12 #include <linux/hw_bitfield.h>
13 #include <linux/mfd/syscon.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/phy/phy.h>
17 #include <linux/phy/phy-hdmi.h>
18 #include <linux/regmap.h>
19 #include <linux/workqueue.h>
20 
21 #include <drm/bridge/dw_hdmi_qp.h>
22 #include <drm/display/drm_hdmi_helper.h>
23 #include <drm/drm_bridge_connector.h>
24 #include <drm/drm_of.h>
25 #include <drm/drm_probe_helper.h>
26 #include <drm/drm_simple_kms_helper.h>
27 
28 #include "rockchip_drm_drv.h"
29 
30 #define RK3576_IOC_MISC_CON0		0xa400
31 #define RK3576_HDMI_HPD_INT_MSK		BIT(2)
32 #define RK3576_HDMI_HPD_INT_CLR		BIT(1)
33 
34 #define RK3576_IOC_HDMI_HPD_STATUS	0xa440
35 #define RK3576_HDMI_LEVEL_INT		BIT(3)
36 
37 #define RK3576_VO0_GRF_SOC_CON1		0x0004
38 #define RK3576_HDMI_FRL_MOD		BIT(0)
39 #define RK3576_HDMI_HDCP14_MEM_EN	BIT(15)
40 
41 #define RK3576_VO0_GRF_SOC_CON8		0x0020
42 #define RK3576_COLOR_DEPTH_MASK		GENMASK(11, 8)
43 #define RK3576_8BPC			0x0
44 #define RK3576_10BPC			0x6
45 #define RK3576_COLOR_FORMAT_MASK	GENMASK(7, 4)
46 #define RK3576_RGB			0x9
47 #define RK3576_YUV422			0x1
48 #define RK3576_YUV444			0x2
49 #define RK3576_YUV420			0x3
50 #define RK3576_CECIN_MASK		BIT(3)
51 
52 #define RK3576_VO0_GRF_SOC_CON14	0x0038
53 #define RK3576_I2S_SEL_MASK		BIT(0)
54 #define RK3576_SPDIF_SEL_MASK		BIT(1)
55 #define HDCP0_P1_GPIO_IN		BIT(2)
56 #define RK3576_SCLIN_MASK		BIT(4)
57 #define RK3576_SDAIN_MASK		BIT(5)
58 #define RK3576_HDMI_GRANT_SEL		BIT(6)
59 
60 #define RK3588_GRF_SOC_CON2		0x0308
61 #define RK3588_HDMI0_HPD_INT_MSK	BIT(13)
62 #define RK3588_HDMI0_HPD_INT_CLR	BIT(12)
63 #define RK3588_HDMI1_HPD_INT_MSK	BIT(15)
64 #define RK3588_HDMI1_HPD_INT_CLR	BIT(14)
65 #define RK3588_GRF_SOC_CON7		0x031c
66 #define RK3588_HPD_HDMI0_IO_EN_MASK	BIT(12)
67 #define RK3588_HPD_HDMI1_IO_EN_MASK	BIT(13)
68 #define RK3588_GRF_SOC_STATUS1		0x0384
69 #define RK3588_HDMI0_LEVEL_INT		BIT(16)
70 #define RK3588_HDMI1_LEVEL_INT		BIT(24)
71 #define RK3588_GRF_VO1_CON3		0x000c
72 #define RK3588_GRF_VO1_CON6		0x0018
73 #define RK3588_COLOR_DEPTH_MASK		GENMASK(7, 4)
74 #define RK3588_8BPC			0x0
75 #define RK3588_10BPC			0x6
76 #define RK3588_COLOR_FORMAT_MASK	GENMASK(3, 0)
77 #define RK3588_RGB			0x0
78 #define RK3588_YUV420			0x3
79 #define RK3588_SCLIN_MASK		BIT(9)
80 #define RK3588_SDAIN_MASK		BIT(10)
81 #define RK3588_MODE_MASK		BIT(11)
82 #define RK3588_I2S_SEL_MASK		BIT(13)
83 #define RK3588_GRF_VO1_CON9		0x0024
84 #define RK3588_HDMI0_GRANT_SEL		BIT(10)
85 #define RK3588_HDMI1_GRANT_SEL		BIT(12)
86 
87 #define HOTPLUG_DEBOUNCE_MS		150
88 #define MAX_HDMI_PORT_NUM		2
89 
90 struct rockchip_hdmi_qp {
91 	struct device *dev;
92 	struct regmap *regmap;
93 	struct regmap *vo_regmap;
94 	struct rockchip_encoder encoder;
95 	struct dw_hdmi_qp *hdmi;
96 	struct phy *phy;
97 	struct gpio_desc *frl_enable_gpio;
98 	struct delayed_work hpd_work;
99 	int port_id;
100 	const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
101 	unsigned long long tmds_char_rate;
102 };
103 
104 struct rockchip_hdmi_qp_ctrl_ops {
105 	void (*io_init)(struct rockchip_hdmi_qp *hdmi);
106 	void (*enc_init)(struct rockchip_hdmi_qp *hdmi, struct rockchip_crtc_state *state);
107 	irqreturn_t (*irq_callback)(int irq, void *dev_id);
108 	irqreturn_t (*hardirq_callback)(int irq, void *dev_id);
109 };
110 
to_rockchip_hdmi_qp(struct drm_encoder * encoder)111 static struct rockchip_hdmi_qp *to_rockchip_hdmi_qp(struct drm_encoder *encoder)
112 {
113 	struct rockchip_encoder *rkencoder = to_rockchip_encoder(encoder);
114 
115 	return container_of(rkencoder, struct rockchip_hdmi_qp, encoder);
116 }
117 
dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder * encoder)118 static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
119 {
120 	struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
121 	struct drm_crtc *crtc = encoder->crtc;
122 
123 	/* Unconditionally switch to TMDS as FRL is not yet supported */
124 	gpiod_set_value_cansleep(hdmi->frl_enable_gpio, 0);
125 
126 	if (!crtc || !crtc->state)
127 		return;
128 
129 	if (hdmi->ctrl_ops->enc_init)
130 		hdmi->ctrl_ops->enc_init(hdmi, to_rockchip_crtc_state(crtc->state));
131 }
132 
133 static int
dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder * encoder,struct drm_crtc_state * crtc_state,struct drm_connector_state * conn_state)134 dw_hdmi_qp_rockchip_encoder_atomic_check(struct drm_encoder *encoder,
135 					 struct drm_crtc_state *crtc_state,
136 					 struct drm_connector_state *conn_state)
137 {
138 	struct rockchip_hdmi_qp *hdmi = to_rockchip_hdmi_qp(encoder);
139 	struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
140 	union phy_configure_opts phy_cfg = {};
141 	int ret;
142 
143 	if (hdmi->tmds_char_rate == conn_state->hdmi.tmds_char_rate &&
144 	    s->output_bpc == conn_state->hdmi.output_bpc)
145 		return 0;
146 
147 	phy_cfg.hdmi.tmds_char_rate = conn_state->hdmi.tmds_char_rate;
148 	phy_cfg.hdmi.bpc = conn_state->hdmi.output_bpc;
149 
150 	ret = phy_configure(hdmi->phy, &phy_cfg);
151 	if (!ret) {
152 		hdmi->tmds_char_rate = conn_state->hdmi.tmds_char_rate;
153 		s->output_mode = ROCKCHIP_OUT_MODE_AAAA;
154 		s->output_type = DRM_MODE_CONNECTOR_HDMIA;
155 		s->output_bpc = conn_state->hdmi.output_bpc;
156 	} else {
157 		dev_err(hdmi->dev, "Failed to configure phy: %d\n", ret);
158 	}
159 
160 	return ret;
161 }
162 
163 static const struct
164 drm_encoder_helper_funcs dw_hdmi_qp_rockchip_encoder_helper_funcs = {
165 	.enable		= dw_hdmi_qp_rockchip_encoder_enable,
166 	.atomic_check	= dw_hdmi_qp_rockchip_encoder_atomic_check,
167 };
168 
dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp * dw_hdmi,void * data)169 static int dw_hdmi_qp_rk3588_phy_init(struct dw_hdmi_qp *dw_hdmi, void *data)
170 {
171 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
172 
173 	return phy_power_on(hdmi->phy);
174 }
175 
dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp * dw_hdmi,void * data)176 static void dw_hdmi_qp_rk3588_phy_disable(struct dw_hdmi_qp *dw_hdmi,
177 					  void *data)
178 {
179 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
180 
181 	phy_power_off(hdmi->phy);
182 }
183 
184 static enum drm_connector_status
dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp * dw_hdmi,void * data)185 dw_hdmi_qp_rk3588_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
186 {
187 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
188 	u32 val;
189 
190 	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &val);
191 	val &= hdmi->port_id ? RK3588_HDMI1_LEVEL_INT : RK3588_HDMI0_LEVEL_INT;
192 
193 	return val ? connector_status_connected : connector_status_disconnected;
194 }
195 
dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp * dw_hdmi,void * data)196 static void dw_hdmi_qp_rk3588_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
197 {
198 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
199 	u32 val;
200 
201 	if (hdmi->port_id)
202 		val = (FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1) |
203 		       FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0));
204 	else
205 		val = (FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1) |
206 		       FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0));
207 
208 	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
209 }
210 
211 static const struct dw_hdmi_qp_phy_ops rk3588_hdmi_phy_ops = {
212 	.init		= dw_hdmi_qp_rk3588_phy_init,
213 	.disable	= dw_hdmi_qp_rk3588_phy_disable,
214 	.read_hpd	= dw_hdmi_qp_rk3588_read_hpd,
215 	.setup_hpd	= dw_hdmi_qp_rk3588_setup_hpd,
216 };
217 
218 static enum drm_connector_status
dw_hdmi_qp_rk3576_read_hpd(struct dw_hdmi_qp * dw_hdmi,void * data)219 dw_hdmi_qp_rk3576_read_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
220 {
221 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
222 	u32 val;
223 
224 	regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &val);
225 
226 	return val & RK3576_HDMI_LEVEL_INT ?
227 		connector_status_connected : connector_status_disconnected;
228 }
229 
dw_hdmi_qp_rk3576_setup_hpd(struct dw_hdmi_qp * dw_hdmi,void * data)230 static void dw_hdmi_qp_rk3576_setup_hpd(struct dw_hdmi_qp *dw_hdmi, void *data)
231 {
232 	struct rockchip_hdmi_qp *hdmi = (struct rockchip_hdmi_qp *)data;
233 	u32 val;
234 
235 	val = (FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1) |
236 	       FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0));
237 
238 	regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
239 	regmap_write(hdmi->regmap, 0xa404, 0xffff0102);
240 }
241 
242 static const struct dw_hdmi_qp_phy_ops rk3576_hdmi_phy_ops = {
243 	.init		= dw_hdmi_qp_rk3588_phy_init,
244 	.disable	= dw_hdmi_qp_rk3588_phy_disable,
245 	.read_hpd	= dw_hdmi_qp_rk3576_read_hpd,
246 	.setup_hpd	= dw_hdmi_qp_rk3576_setup_hpd,
247 };
248 
dw_hdmi_qp_rk3588_hpd_work(struct work_struct * work)249 static void dw_hdmi_qp_rk3588_hpd_work(struct work_struct *work)
250 {
251 	struct rockchip_hdmi_qp *hdmi = container_of(work,
252 						     struct rockchip_hdmi_qp,
253 						     hpd_work.work);
254 	struct drm_device *drm = hdmi->encoder.encoder.dev;
255 	bool changed;
256 
257 	if (drm) {
258 		changed = drm_helper_hpd_irq_event(drm);
259 		if (changed)
260 			dev_dbg(hdmi->dev, "connector status changed\n");
261 	}
262 }
263 
dw_hdmi_qp_rk3576_hardirq(int irq,void * dev_id)264 static irqreturn_t dw_hdmi_qp_rk3576_hardirq(int irq, void *dev_id)
265 {
266 	struct rockchip_hdmi_qp *hdmi = dev_id;
267 	u32 intr_stat, val;
268 
269 	regmap_read(hdmi->regmap, RK3576_IOC_HDMI_HPD_STATUS, &intr_stat);
270 	if (intr_stat) {
271 		val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 1);
272 
273 		regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
274 		return IRQ_WAKE_THREAD;
275 	}
276 
277 	return IRQ_NONE;
278 }
279 
dw_hdmi_qp_rk3576_irq(int irq,void * dev_id)280 static irqreturn_t dw_hdmi_qp_rk3576_irq(int irq, void *dev_id)
281 {
282 	struct rockchip_hdmi_qp *hdmi = dev_id;
283 	u32 val;
284 
285 	val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_CLR, 1);
286 	regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
287 	mod_delayed_work(system_percpu_wq, &hdmi->hpd_work,
288 			 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
289 
290 	val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0);
291 	regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
292 
293 	return IRQ_HANDLED;
294 }
295 
dw_hdmi_qp_rk3588_hardirq(int irq,void * dev_id)296 static irqreturn_t dw_hdmi_qp_rk3588_hardirq(int irq, void *dev_id)
297 {
298 	struct rockchip_hdmi_qp *hdmi = dev_id;
299 	u32 intr_stat, val;
300 
301 	regmap_read(hdmi->regmap, RK3588_GRF_SOC_STATUS1, &intr_stat);
302 
303 	if (intr_stat) {
304 		if (hdmi->port_id)
305 			val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1);
306 		else
307 			val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1);
308 		regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
309 		return IRQ_WAKE_THREAD;
310 	}
311 
312 	return IRQ_NONE;
313 }
314 
dw_hdmi_qp_rk3588_irq(int irq,void * dev_id)315 static irqreturn_t dw_hdmi_qp_rk3588_irq(int irq, void *dev_id)
316 {
317 	struct rockchip_hdmi_qp *hdmi = dev_id;
318 	u32 val;
319 
320 	if (hdmi->port_id)
321 		val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_CLR, 1);
322 	else
323 		val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_CLR, 1);
324 	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
325 
326 	mod_delayed_work(system_percpu_wq, &hdmi->hpd_work,
327 			 msecs_to_jiffies(HOTPLUG_DEBOUNCE_MS));
328 
329 	if (hdmi->port_id)
330 		val |= FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 0);
331 	else
332 		val |= FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 0);
333 	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
334 
335 	return IRQ_HANDLED;
336 }
337 
dw_hdmi_qp_rk3576_io_init(struct rockchip_hdmi_qp * hdmi)338 static void dw_hdmi_qp_rk3576_io_init(struct rockchip_hdmi_qp *hdmi)
339 {
340 	u32 val;
341 
342 	val = FIELD_PREP_WM16(RK3576_SCLIN_MASK, 1) |
343 	      FIELD_PREP_WM16(RK3576_SDAIN_MASK, 1) |
344 	      FIELD_PREP_WM16(RK3576_HDMI_GRANT_SEL, 1) |
345 	      FIELD_PREP_WM16(RK3576_I2S_SEL_MASK, 1);
346 
347 	regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON14, val);
348 
349 	val = FIELD_PREP_WM16(RK3576_HDMI_HPD_INT_MSK, 0);
350 	regmap_write(hdmi->regmap, RK3576_IOC_MISC_CON0, val);
351 }
352 
dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp * hdmi)353 static void dw_hdmi_qp_rk3588_io_init(struct rockchip_hdmi_qp *hdmi)
354 {
355 	u32 val;
356 
357 	val = FIELD_PREP_WM16(RK3588_SCLIN_MASK, 1) |
358 	      FIELD_PREP_WM16(RK3588_SDAIN_MASK, 1) |
359 	      FIELD_PREP_WM16(RK3588_MODE_MASK, 1) |
360 	      FIELD_PREP_WM16(RK3588_I2S_SEL_MASK, 1);
361 	regmap_write(hdmi->vo_regmap,
362 		     hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
363 		     val);
364 
365 	val = FIELD_PREP_WM16(RK3588_HPD_HDMI0_IO_EN_MASK, 1) |
366 	      FIELD_PREP_WM16(RK3588_HPD_HDMI1_IO_EN_MASK, 1);
367 	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON7, val);
368 
369 	if (hdmi->port_id)
370 		val = FIELD_PREP_WM16(RK3588_HDMI1_GRANT_SEL, 1);
371 	else
372 		val = FIELD_PREP_WM16(RK3588_HDMI0_GRANT_SEL, 1);
373 	regmap_write(hdmi->vo_regmap, RK3588_GRF_VO1_CON9, val);
374 
375 	if (hdmi->port_id)
376 		val = FIELD_PREP_WM16(RK3588_HDMI1_HPD_INT_MSK, 1);
377 	else
378 		val = FIELD_PREP_WM16(RK3588_HDMI0_HPD_INT_MSK, 1);
379 	regmap_write(hdmi->regmap, RK3588_GRF_SOC_CON2, val);
380 }
381 
dw_hdmi_qp_rk3576_enc_init(struct rockchip_hdmi_qp * hdmi,struct rockchip_crtc_state * state)382 static void dw_hdmi_qp_rk3576_enc_init(struct rockchip_hdmi_qp *hdmi,
383 				       struct rockchip_crtc_state *state)
384 {
385 	u32 val;
386 
387 	if (state->output_bpc == 10)
388 		val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_10BPC);
389 	else
390 		val = FIELD_PREP_WM16(RK3576_COLOR_DEPTH_MASK, RK3576_8BPC);
391 
392 	regmap_write(hdmi->vo_regmap, RK3576_VO0_GRF_SOC_CON8, val);
393 }
394 
dw_hdmi_qp_rk3588_enc_init(struct rockchip_hdmi_qp * hdmi,struct rockchip_crtc_state * state)395 static void dw_hdmi_qp_rk3588_enc_init(struct rockchip_hdmi_qp *hdmi,
396 				       struct rockchip_crtc_state *state)
397 {
398 	u32 val;
399 
400 	if (state->output_bpc == 10)
401 		val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_10BPC);
402 	else
403 		val = FIELD_PREP_WM16(RK3588_COLOR_DEPTH_MASK, RK3588_8BPC);
404 
405 	regmap_write(hdmi->vo_regmap,
406 		     hdmi->port_id ? RK3588_GRF_VO1_CON6 : RK3588_GRF_VO1_CON3,
407 		     val);
408 }
409 
410 static const struct rockchip_hdmi_qp_ctrl_ops rk3576_hdmi_ctrl_ops = {
411 	.io_init		= dw_hdmi_qp_rk3576_io_init,
412 	.enc_init		= dw_hdmi_qp_rk3576_enc_init,
413 	.irq_callback		= dw_hdmi_qp_rk3576_irq,
414 	.hardirq_callback	= dw_hdmi_qp_rk3576_hardirq,
415 };
416 
417 static const struct rockchip_hdmi_qp_ctrl_ops rk3588_hdmi_ctrl_ops = {
418 	.io_init		= dw_hdmi_qp_rk3588_io_init,
419 	.enc_init		= dw_hdmi_qp_rk3588_enc_init,
420 	.irq_callback		= dw_hdmi_qp_rk3588_irq,
421 	.hardirq_callback	= dw_hdmi_qp_rk3588_hardirq,
422 };
423 
424 struct rockchip_hdmi_qp_cfg {
425 	unsigned int num_ports;
426 	unsigned int port_ids[MAX_HDMI_PORT_NUM];
427 	const struct rockchip_hdmi_qp_ctrl_ops *ctrl_ops;
428 	const struct dw_hdmi_qp_phy_ops *phy_ops;
429 };
430 
431 static const struct rockchip_hdmi_qp_cfg rk3576_hdmi_cfg = {
432 	.num_ports = 1,
433 	.port_ids = {
434 		0x27da0000,
435 	},
436 	.ctrl_ops = &rk3576_hdmi_ctrl_ops,
437 	.phy_ops = &rk3576_hdmi_phy_ops,
438 };
439 
440 static const struct rockchip_hdmi_qp_cfg rk3588_hdmi_cfg = {
441 	.num_ports = 2,
442 	.port_ids = {
443 		0xfde80000,
444 		0xfdea0000,
445 	},
446 	.ctrl_ops = &rk3588_hdmi_ctrl_ops,
447 	.phy_ops = &rk3588_hdmi_phy_ops,
448 };
449 
450 static const struct of_device_id dw_hdmi_qp_rockchip_dt_ids[] = {
451 	{
452 		.compatible = "rockchip,rk3576-dw-hdmi-qp",
453 		.data = &rk3576_hdmi_cfg
454 	}, {
455 		.compatible = "rockchip,rk3588-dw-hdmi-qp",
456 		.data = &rk3588_hdmi_cfg
457 	},
458 	{},
459 };
460 MODULE_DEVICE_TABLE(of, dw_hdmi_qp_rockchip_dt_ids);
461 
dw_hdmi_qp_rockchip_bind(struct device * dev,struct device * master,void * data)462 static int dw_hdmi_qp_rockchip_bind(struct device *dev, struct device *master,
463 				    void *data)
464 {
465 	struct platform_device *pdev = to_platform_device(dev);
466 	struct dw_hdmi_qp_plat_data plat_data = {};
467 	const struct rockchip_hdmi_qp_cfg *cfg;
468 	struct drm_device *drm = data;
469 	struct drm_connector *connector;
470 	struct drm_encoder *encoder;
471 	struct rockchip_hdmi_qp *hdmi;
472 	struct resource *res;
473 	struct clk_bulk_data *clks;
474 	struct clk *ref_clk;
475 	int ret, irq, i;
476 
477 	if (!pdev->dev.of_node)
478 		return -ENODEV;
479 
480 	hdmi = devm_kzalloc(&pdev->dev, sizeof(*hdmi), GFP_KERNEL);
481 	if (!hdmi)
482 		return -ENOMEM;
483 
484 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
485 	if (!res)
486 		return -ENODEV;
487 
488 	cfg = of_device_get_match_data(dev);
489 	if (!cfg)
490 		return -ENODEV;
491 
492 	if (!cfg->ctrl_ops || !cfg->ctrl_ops->io_init ||
493 	    !cfg->ctrl_ops->irq_callback || !cfg->ctrl_ops->hardirq_callback)
494 		return dev_err_probe(dev, -ENODEV, "Missing platform ctrl ops\n");
495 
496 	hdmi->ctrl_ops = cfg->ctrl_ops;
497 	hdmi->dev = &pdev->dev;
498 	hdmi->port_id = -ENODEV;
499 
500 	/* Identify port ID by matching base IO address */
501 	for (i = 0; i < cfg->num_ports; i++) {
502 		if (res->start == cfg->port_ids[i]) {
503 			hdmi->port_id = i;
504 			break;
505 		}
506 	}
507 	if (hdmi->port_id < 0)
508 		return dev_err_probe(hdmi->dev, hdmi->port_id,
509 				     "Failed to match HDMI port ID\n");
510 
511 	plat_data.phy_ops = cfg->phy_ops;
512 	plat_data.phy_data = hdmi;
513 	plat_data.max_bpc = 10;
514 
515 	encoder = &hdmi->encoder.encoder;
516 	encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
517 
518 	rockchip_drm_encoder_set_crtc_endpoint_id(&hdmi->encoder,
519 						  dev->of_node, 0, 0);
520 	/*
521 	 * If we failed to find the CRTC(s) which this encoder is
522 	 * supposed to be connected to, it's because the CRTC has
523 	 * not been registered yet.  Defer probing, and hope that
524 	 * the required CRTC is added later.
525 	 */
526 	if (encoder->possible_crtcs == 0)
527 		return -EPROBE_DEFER;
528 
529 	hdmi->regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
530 						       "rockchip,grf");
531 	if (IS_ERR(hdmi->regmap))
532 		return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->regmap),
533 				     "Unable to get rockchip,grf\n");
534 
535 	hdmi->vo_regmap = syscon_regmap_lookup_by_phandle(dev->of_node,
536 							  "rockchip,vo-grf");
537 	if (IS_ERR(hdmi->vo_regmap))
538 		return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->vo_regmap),
539 				     "Unable to get rockchip,vo-grf\n");
540 
541 	ret = devm_clk_bulk_get_all_enabled(hdmi->dev, &clks);
542 	if (ret < 0)
543 		return dev_err_probe(hdmi->dev, ret, "Failed to get clocks\n");
544 
545 	ref_clk = clk_get(hdmi->dev, "ref");
546 	if (IS_ERR(ref_clk))
547 		return dev_err_probe(hdmi->dev, PTR_ERR(ref_clk),
548 				     "Failed to get ref clock\n");
549 
550 	plat_data.ref_clk_rate = clk_get_rate(ref_clk);
551 	clk_put(ref_clk);
552 
553 	hdmi->frl_enable_gpio = devm_gpiod_get_optional(hdmi->dev, "frl-enable",
554 							GPIOD_OUT_LOW);
555 	if (IS_ERR(hdmi->frl_enable_gpio))
556 		return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->frl_enable_gpio),
557 				     "Failed to request FRL enable GPIO\n");
558 
559 	hdmi->phy = devm_of_phy_get_by_index(dev, dev->of_node, 0);
560 	if (IS_ERR(hdmi->phy))
561 		return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->phy),
562 				     "Failed to get phy\n");
563 
564 	cfg->ctrl_ops->io_init(hdmi);
565 
566 	INIT_DELAYED_WORK(&hdmi->hpd_work, dw_hdmi_qp_rk3588_hpd_work);
567 
568 	plat_data.main_irq = platform_get_irq_byname(pdev, "main");
569 	if (plat_data.main_irq < 0)
570 		return plat_data.main_irq;
571 
572 	plat_data.cec_irq = platform_get_irq_byname(pdev, "cec");
573 	if (plat_data.cec_irq < 0)
574 		return plat_data.cec_irq;
575 
576 	irq = platform_get_irq_byname(pdev, "hpd");
577 	if (irq < 0)
578 		return irq;
579 
580 	ret = devm_request_threaded_irq(hdmi->dev, irq,
581 					cfg->ctrl_ops->hardirq_callback,
582 					cfg->ctrl_ops->irq_callback,
583 					IRQF_SHARED, "dw-hdmi-qp-hpd",
584 					hdmi);
585 	if (ret)
586 		return ret;
587 
588 	drm_encoder_helper_add(encoder, &dw_hdmi_qp_rockchip_encoder_helper_funcs);
589 	drm_simple_encoder_init(drm, encoder, DRM_MODE_ENCODER_TMDS);
590 
591 	platform_set_drvdata(pdev, hdmi);
592 
593 	hdmi->hdmi = dw_hdmi_qp_bind(pdev, encoder, &plat_data);
594 	if (IS_ERR(hdmi->hdmi)) {
595 		drm_encoder_cleanup(encoder);
596 		return dev_err_probe(hdmi->dev, PTR_ERR(hdmi->hdmi),
597 				     "Failed to bind dw-hdmi-qp");
598 	}
599 
600 	connector = drm_bridge_connector_init(drm, encoder);
601 	if (IS_ERR(connector))
602 		return dev_err_probe(hdmi->dev, PTR_ERR(connector),
603 				     "Failed to init bridge connector\n");
604 
605 	return drm_connector_attach_encoder(connector, encoder);
606 }
607 
dw_hdmi_qp_rockchip_unbind(struct device * dev,struct device * master,void * data)608 static void dw_hdmi_qp_rockchip_unbind(struct device *dev,
609 				       struct device *master,
610 				       void *data)
611 {
612 	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
613 
614 	cancel_delayed_work_sync(&hdmi->hpd_work);
615 
616 	drm_encoder_cleanup(&hdmi->encoder.encoder);
617 }
618 
619 static const struct component_ops dw_hdmi_qp_rockchip_ops = {
620 	.bind	= dw_hdmi_qp_rockchip_bind,
621 	.unbind	= dw_hdmi_qp_rockchip_unbind,
622 };
623 
dw_hdmi_qp_rockchip_probe(struct platform_device * pdev)624 static int dw_hdmi_qp_rockchip_probe(struct platform_device *pdev)
625 {
626 	return component_add(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
627 }
628 
dw_hdmi_qp_rockchip_remove(struct platform_device * pdev)629 static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
630 {
631 	component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
632 }
633 
dw_hdmi_qp_rockchip_suspend(struct device * dev)634 static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev)
635 {
636 	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
637 
638 	dw_hdmi_qp_suspend(dev, hdmi->hdmi);
639 
640 	return 0;
641 }
642 
dw_hdmi_qp_rockchip_resume(struct device * dev)643 static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
644 {
645 	struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
646 
647 	hdmi->ctrl_ops->io_init(hdmi);
648 
649 	dw_hdmi_qp_resume(dev, hdmi->hdmi);
650 
651 	if (hdmi->encoder.encoder.dev)
652 		drm_helper_hpd_irq_event(hdmi->encoder.encoder.dev);
653 
654 	return 0;
655 }
656 
657 static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
658 	SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend,
659 				dw_hdmi_qp_rockchip_resume)
660 };
661 
662 struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
663 	.probe = dw_hdmi_qp_rockchip_probe,
664 	.remove = dw_hdmi_qp_rockchip_remove,
665 	.driver = {
666 		.name = "dwhdmiqp-rockchip",
667 		.pm = &dw_hdmi_qp_rockchip_pm,
668 		.of_match_table = dw_hdmi_qp_rockchip_dt_ids,
669 	},
670 };
671