xref: /linux/drivers/gpu/drm/meson/meson_dw_hdmi.c (revision 0ad53fe3ae82443c74ff8cfd7bd13377cc1134a3)
1 // SPDX-License-Identifier: GPL-2.0-or-later
2 /*
3  * Copyright (C) 2016 BayLibre, SAS
4  * Author: Neil Armstrong <narmstrong@baylibre.com>
5  * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
6  */
7 
8 #include <linux/clk.h>
9 #include <linux/component.h>
10 #include <linux/kernel.h>
11 #include <linux/module.h>
12 #include <linux/of_device.h>
13 #include <linux/of_graph.h>
14 #include <linux/regulator/consumer.h>
15 #include <linux/reset.h>
16 
17 #include <drm/bridge/dw_hdmi.h>
18 #include <drm/drm_atomic_helper.h>
19 #include <drm/drm_bridge.h>
20 #include <drm/drm_device.h>
21 #include <drm/drm_edid.h>
22 #include <drm/drm_probe_helper.h>
23 #include <drm/drm_print.h>
24 
25 #include <linux/media-bus-format.h>
26 #include <linux/videodev2.h>
27 
28 #include "meson_drv.h"
29 #include "meson_dw_hdmi.h"
30 #include "meson_registers.h"
31 #include "meson_vclk.h"
32 #include "meson_venc.h"
33 
34 #define DRIVER_NAME "meson-dw-hdmi"
35 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
36 
37 /**
38  * DOC: HDMI Output
39  *
40  * HDMI Output is composed of :
41  *
42  * - A Synopsys DesignWare HDMI Controller IP
43  * - A TOP control block controlling the Clocks and PHY
44  * - A custom HDMI PHY in order convert video to TMDS signal
45  *
46  * .. code::
47  *
48  *    ___________________________________
49  *   |            HDMI TOP               |<= HPD
50  *   |___________________________________|
51  *   |                  |                |
52  *   |  Synopsys HDMI   |   HDMI PHY     |=> TMDS
53  *   |    Controller    |________________|
54  *   |___________________________________|<=> DDC
55  *
56  *
57  * The HDMI TOP block only supports HPD sensing.
58  * The Synopsys HDMI Controller interrupt is routed
59  * through the TOP Block interrupt.
60  * Communication to the TOP Block and the Synopsys
61  * HDMI Controller is done a pair of addr+read/write
62  * registers.
63  * The HDMI PHY is configured by registers in the
64  * HHI register block.
65  *
66  * Pixel data arrives in 4:4:4 format from the VENC
67  * block and the VPU HDMI mux selects either the ENCI
68  * encoder for the 576i or 480i formats or the ENCP
69  * encoder for all the other formats including
70  * interlaced HD formats.
71  * The VENC uses a DVI encoder on top of the ENCI
72  * or ENCP encoders to generate DVI timings for the
73  * HDMI controller.
74  *
75  * GXBB, GXL and GXM embeds the Synopsys DesignWare
76  * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
77  * audio source interfaces.
78  *
79  * We handle the following features :
80  *
81  * - HPD Rise & Fall interrupt
82  * - HDMI Controller Interrupt
83  * - HDMI PHY Init for 480i to 1080p60
84  * - VENC & HDMI Clock setup for 480i to 1080p60
85  * - VENC Mode setup for 480i to 1080p60
86  *
87  * What is missing :
88  *
89  * - PHY, Clock and Mode setup for 2k && 4k modes
90  * - SDDC Scrambling mode for HDMI 2.0a
91  * - HDCP Setup
92  * - CEC Management
93  */
94 
95 /* TOP Block Communication Channel */
96 #define HDMITX_TOP_ADDR_REG	0x0
97 #define HDMITX_TOP_DATA_REG	0x4
98 #define HDMITX_TOP_CTRL_REG	0x8
99 #define HDMITX_TOP_G12A_OFFSET	0x8000
100 
101 /* Controller Communication Channel */
102 #define HDMITX_DWC_ADDR_REG	0x10
103 #define HDMITX_DWC_DATA_REG	0x14
104 #define HDMITX_DWC_CTRL_REG	0x18
105 
106 /* HHI Registers */
107 #define HHI_MEM_PD_REG0		0x100 /* 0x40 */
108 #define HHI_HDMI_CLK_CNTL	0x1cc /* 0x73 */
109 #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 */
110 #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
111 #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
112 #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
113 #define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
114 #define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
115 
116 static DEFINE_SPINLOCK(reg_lock);
117 
118 enum meson_venc_source {
119 	MESON_VENC_SOURCE_NONE = 0,
120 	MESON_VENC_SOURCE_ENCI = 1,
121 	MESON_VENC_SOURCE_ENCP = 2,
122 };
123 
124 struct meson_dw_hdmi;
125 
126 struct meson_dw_hdmi_data {
127 	unsigned int	(*top_read)(struct meson_dw_hdmi *dw_hdmi,
128 				    unsigned int addr);
129 	void		(*top_write)(struct meson_dw_hdmi *dw_hdmi,
130 				     unsigned int addr, unsigned int data);
131 	unsigned int	(*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
132 				    unsigned int addr);
133 	void		(*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
134 				     unsigned int addr, unsigned int data);
135 };
136 
137 struct meson_dw_hdmi {
138 	struct drm_encoder encoder;
139 	struct drm_bridge bridge;
140 	struct dw_hdmi_plat_data dw_plat_data;
141 	struct meson_drm *priv;
142 	struct device *dev;
143 	void __iomem *hdmitx;
144 	const struct meson_dw_hdmi_data *data;
145 	struct reset_control *hdmitx_apb;
146 	struct reset_control *hdmitx_ctrl;
147 	struct reset_control *hdmitx_phy;
148 	struct regulator *hdmi_supply;
149 	u32 irq_stat;
150 	struct dw_hdmi *hdmi;
151 	unsigned long output_bus_fmt;
152 };
153 #define encoder_to_meson_dw_hdmi(x) \
154 	container_of(x, struct meson_dw_hdmi, encoder)
155 #define bridge_to_meson_dw_hdmi(x) \
156 	container_of(x, struct meson_dw_hdmi, bridge)
157 
158 static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
159 					const char *compat)
160 {
161 	return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
162 }
163 
164 /* PHY (via TOP bridge) and Controller dedicated register interface */
165 
166 static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
167 				     unsigned int addr)
168 {
169 	unsigned long flags;
170 	unsigned int data;
171 
172 	spin_lock_irqsave(&reg_lock, flags);
173 
174 	/* ADDR must be written twice */
175 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
176 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
177 
178 	/* Read needs a second DATA read */
179 	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
180 	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
181 
182 	spin_unlock_irqrestore(&reg_lock, flags);
183 
184 	return data;
185 }
186 
187 static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
188 					  unsigned int addr)
189 {
190 	return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
191 }
192 
193 static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
194 				     unsigned int addr, unsigned int data)
195 {
196 	unsigned long flags;
197 
198 	spin_lock_irqsave(&reg_lock, flags);
199 
200 	/* ADDR must be written twice */
201 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
202 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
203 
204 	/* Write needs single DATA write */
205 	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
206 
207 	spin_unlock_irqrestore(&reg_lock, flags);
208 }
209 
210 static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
211 					  unsigned int addr, unsigned int data)
212 {
213 	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
214 }
215 
216 /* Helper to change specific bits in PHY registers */
217 static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
218 					  unsigned int addr,
219 					  unsigned int mask,
220 					  unsigned int val)
221 {
222 	unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
223 
224 	data &= ~mask;
225 	data |= val;
226 
227 	dw_hdmi->data->top_write(dw_hdmi, addr, data);
228 }
229 
230 static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
231 				     unsigned int addr)
232 {
233 	unsigned long flags;
234 	unsigned int data;
235 
236 	spin_lock_irqsave(&reg_lock, flags);
237 
238 	/* ADDR must be written twice */
239 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
240 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
241 
242 	/* Read needs a second DATA read */
243 	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
244 	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
245 
246 	spin_unlock_irqrestore(&reg_lock, flags);
247 
248 	return data;
249 }
250 
251 static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
252 					  unsigned int addr)
253 {
254 	return readb(dw_hdmi->hdmitx + addr);
255 }
256 
257 static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
258 				     unsigned int addr, unsigned int data)
259 {
260 	unsigned long flags;
261 
262 	spin_lock_irqsave(&reg_lock, flags);
263 
264 	/* ADDR must be written twice */
265 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
266 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
267 
268 	/* Write needs single DATA write */
269 	writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
270 
271 	spin_unlock_irqrestore(&reg_lock, flags);
272 }
273 
274 static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
275 					  unsigned int addr, unsigned int data)
276 {
277 	writeb(data, dw_hdmi->hdmitx + addr);
278 }
279 
280 /* Helper to change specific bits in controller registers */
281 static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
282 					  unsigned int addr,
283 					  unsigned int mask,
284 					  unsigned int val)
285 {
286 	unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
287 
288 	data &= ~mask;
289 	data |= val;
290 
291 	dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
292 }
293 
294 /* Bridge */
295 
296 /* Setup PHY bandwidth modes */
297 static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
298 				      const struct drm_display_mode *mode)
299 {
300 	struct meson_drm *priv = dw_hdmi->priv;
301 	unsigned int pixel_clock = mode->clock;
302 
303 	/* For 420, pixel clock is half unlike venc clock */
304 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
305 		pixel_clock /= 2;
306 
307 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
308 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
309 		if (pixel_clock >= 371250) {
310 			/* 5.94Gbps, 3.7125Gbps */
311 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
312 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
313 		} else if (pixel_clock >= 297000) {
314 			/* 2.97Gbps */
315 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
316 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
317 		} else if (pixel_clock >= 148500) {
318 			/* 1.485Gbps */
319 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
320 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
321 		} else {
322 			/* 742.5Mbps, and below */
323 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
324 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
325 		}
326 	} else if (dw_hdmi_is_compatible(dw_hdmi,
327 					 "amlogic,meson-gxbb-dw-hdmi")) {
328 		if (pixel_clock >= 371250) {
329 			/* 5.94Gbps, 3.7125Gbps */
330 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
331 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
332 		} else if (pixel_clock >= 297000) {
333 			/* 2.97Gbps */
334 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
335 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
336 		} else {
337 			/* 1.485Gbps, and below */
338 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
339 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
340 		}
341 	} else if (dw_hdmi_is_compatible(dw_hdmi,
342 					 "amlogic,meson-g12a-dw-hdmi")) {
343 		if (pixel_clock >= 371250) {
344 			/* 5.94Gbps, 3.7125Gbps */
345 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
346 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
347 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
348 		} else if (pixel_clock >= 297000) {
349 			/* 2.97Gbps */
350 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
351 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
352 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
353 		} else {
354 			/* 1.485Gbps, and below */
355 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
356 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
357 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
358 		}
359 	}
360 }
361 
362 static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
363 {
364 	struct meson_drm *priv = dw_hdmi->priv;
365 
366 	/* Enable and software reset */
367 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
368 
369 	mdelay(2);
370 
371 	/* Enable and unreset */
372 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
373 
374 	mdelay(2);
375 }
376 
377 static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
378 			     const struct drm_display_mode *mode)
379 {
380 	struct meson_drm *priv = dw_hdmi->priv;
381 	int vic = drm_match_cea_mode(mode);
382 	unsigned int phy_freq;
383 	unsigned int vclk_freq;
384 	unsigned int venc_freq;
385 	unsigned int hdmi_freq;
386 
387 	vclk_freq = mode->clock;
388 
389 	/* For 420, pixel clock is half unlike venc clock */
390 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
391 		vclk_freq /= 2;
392 
393 	/* TMDS clock is pixel_clock * 10 */
394 	phy_freq = vclk_freq * 10;
395 
396 	if (!vic) {
397 		meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
398 				 vclk_freq, vclk_freq, vclk_freq, false);
399 		return;
400 	}
401 
402 	/* 480i/576i needs global pixel doubling */
403 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
404 		vclk_freq *= 2;
405 
406 	venc_freq = vclk_freq;
407 	hdmi_freq = vclk_freq;
408 
409 	/* VENC double pixels for 1080i, 720p and YUV420 modes */
410 	if (meson_venc_hdmi_venc_repeat(vic) ||
411 	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
412 		venc_freq *= 2;
413 
414 	vclk_freq = max(venc_freq, hdmi_freq);
415 
416 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
417 		venc_freq /= 2;
418 
419 	DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
420 		phy_freq, vclk_freq, venc_freq, hdmi_freq,
421 		priv->venc.hdmi_use_enci);
422 
423 	meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
424 			 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
425 }
426 
427 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
428 			    const struct drm_display_info *display,
429 			    const struct drm_display_mode *mode)
430 {
431 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
432 	struct meson_drm *priv = dw_hdmi->priv;
433 	unsigned int wr_clk =
434 		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
435 
436 	DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
437 			 mode->clock > 340000 ? 40 : 10);
438 
439 	/* Enable clocks */
440 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
441 
442 	/* Bring HDMITX MEM output of power down */
443 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
444 
445 	/* Bring out of reset */
446 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
447 
448 	/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
449 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
450 			       0x3, 0x3);
451 
452 	/* Enable cec_clk and hdcp22_tmdsclk_en */
453 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
454 			       0x3 << 4, 0x3 << 4);
455 
456 	/* Enable normal output to PHY */
457 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
458 
459 	/* TMDS pattern setup */
460 	if (mode->clock > 340000 &&
461 	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
462 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
463 				  0);
464 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
465 				  0x03ff03ff);
466 	} else {
467 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
468 				  0x001f001f);
469 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
470 				  0x001f001f);
471 	}
472 
473 	/* Load TMDS pattern */
474 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
475 	msleep(20);
476 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
477 
478 	/* Setup PHY parameters */
479 	meson_hdmi_phy_setup_mode(dw_hdmi, mode);
480 
481 	/* Setup PHY */
482 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
483 			   0xffff << 16, 0x0390 << 16);
484 
485 	/* BIT_INVERT */
486 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
487 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
488 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
489 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
490 				   BIT(17), 0);
491 	else
492 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
493 				   BIT(17), BIT(17));
494 
495 	/* Disable clock, fifo, fifo_wr */
496 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
497 
498 	dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
499 
500 	msleep(100);
501 
502 	/* Reset PHY 3 times in a row */
503 	meson_dw_hdmi_phy_reset(dw_hdmi);
504 	meson_dw_hdmi_phy_reset(dw_hdmi);
505 	meson_dw_hdmi_phy_reset(dw_hdmi);
506 
507 	/* Temporary Disable VENC video stream */
508 	if (priv->venc.hdmi_use_enci)
509 		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
510 	else
511 		writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
512 
513 	/* Temporary Disable HDMI video stream to HDMI-TX */
514 	writel_bits_relaxed(0x3, 0,
515 			    priv->io_base + _REG(VPU_HDMI_SETTING));
516 	writel_bits_relaxed(0xf << 8, 0,
517 			    priv->io_base + _REG(VPU_HDMI_SETTING));
518 
519 	/* Re-Enable VENC video stream */
520 	if (priv->venc.hdmi_use_enci)
521 		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
522 	else
523 		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
524 
525 	/* Push back HDMI clock settings */
526 	writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
527 			    priv->io_base + _REG(VPU_HDMI_SETTING));
528 
529 	/* Enable and Select HDMI video source for HDMI-TX */
530 	if (priv->venc.hdmi_use_enci)
531 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
532 				    priv->io_base + _REG(VPU_HDMI_SETTING));
533 	else
534 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
535 				    priv->io_base + _REG(VPU_HDMI_SETTING));
536 
537 	return 0;
538 }
539 
540 static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
541 				void *data)
542 {
543 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
544 	struct meson_drm *priv = dw_hdmi->priv;
545 
546 	DRM_DEBUG_DRIVER("\n");
547 
548 	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
549 }
550 
551 static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
552 			     void *data)
553 {
554 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
555 
556 	return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
557 		connector_status_connected : connector_status_disconnected;
558 }
559 
560 static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
561 			      void *data)
562 {
563 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
564 
565 	/* Setup HPD Filter */
566 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
567 			  (0xa << 12) | 0xa0);
568 
569 	/* Clear interrupts */
570 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
571 			  HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
572 
573 	/* Unmask interrupts */
574 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
575 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
576 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
577 }
578 
579 static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
580 	.init = dw_hdmi_phy_init,
581 	.disable = dw_hdmi_phy_disable,
582 	.read_hpd = dw_hdmi_read_hpd,
583 	.setup_hpd = dw_hdmi_setup_hpd,
584 };
585 
586 static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
587 {
588 	struct meson_dw_hdmi *dw_hdmi = dev_id;
589 	u32 stat;
590 
591 	stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
592 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
593 
594 	/* HPD Events, handle in the threaded interrupt handler */
595 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
596 		dw_hdmi->irq_stat = stat;
597 		return IRQ_WAKE_THREAD;
598 	}
599 
600 	/* HDMI Controller Interrupt */
601 	if (stat & 1)
602 		return IRQ_NONE;
603 
604 	/* TOFIX Handle HDCP Interrupts */
605 
606 	return IRQ_HANDLED;
607 }
608 
609 /* Threaded interrupt handler to manage HPD events */
610 static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
611 {
612 	struct meson_dw_hdmi *dw_hdmi = dev_id;
613 	u32 stat = dw_hdmi->irq_stat;
614 
615 	/* HPD Events */
616 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
617 		bool hpd_connected = false;
618 
619 		if (stat & HDMITX_TOP_INTR_HPD_RISE)
620 			hpd_connected = true;
621 
622 		dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
623 				       hpd_connected);
624 
625 		drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
626 	}
627 
628 	return IRQ_HANDLED;
629 }
630 
631 static enum drm_mode_status
632 dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
633 		   const struct drm_display_info *display_info,
634 		   const struct drm_display_mode *mode)
635 {
636 	struct meson_dw_hdmi *dw_hdmi = data;
637 	struct meson_drm *priv = dw_hdmi->priv;
638 	bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
639 	unsigned int phy_freq;
640 	unsigned int vclk_freq;
641 	unsigned int venc_freq;
642 	unsigned int hdmi_freq;
643 	int vic = drm_match_cea_mode(mode);
644 	enum drm_mode_status status;
645 
646 	DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
647 
648 	/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
649 	if (display_info->max_tmds_clock &&
650 	    mode->clock > display_info->max_tmds_clock &&
651 	    !drm_mode_is_420_only(display_info, mode) &&
652 	    !drm_mode_is_420_also(display_info, mode))
653 		return MODE_BAD;
654 
655 	/* Check against non-VIC supported modes */
656 	if (!vic) {
657 		status = meson_venc_hdmi_supported_mode(mode);
658 		if (status != MODE_OK)
659 			return status;
660 
661 		return meson_vclk_dmt_supported_freq(priv, mode->clock);
662 	/* Check against supported VIC modes */
663 	} else if (!meson_venc_hdmi_supported_vic(vic))
664 		return MODE_BAD;
665 
666 	vclk_freq = mode->clock;
667 
668 	/* For 420, pixel clock is half unlike venc clock */
669 	if (drm_mode_is_420_only(display_info, mode) ||
670 	    (!is_hdmi2_sink &&
671 	     drm_mode_is_420_also(display_info, mode)))
672 		vclk_freq /= 2;
673 
674 	/* TMDS clock is pixel_clock * 10 */
675 	phy_freq = vclk_freq * 10;
676 
677 	/* 480i/576i needs global pixel doubling */
678 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
679 		vclk_freq *= 2;
680 
681 	venc_freq = vclk_freq;
682 	hdmi_freq = vclk_freq;
683 
684 	/* VENC double pixels for 1080i, 720p and YUV420 modes */
685 	if (meson_venc_hdmi_venc_repeat(vic) ||
686 	    drm_mode_is_420_only(display_info, mode) ||
687 	    (!is_hdmi2_sink &&
688 	     drm_mode_is_420_also(display_info, mode)))
689 		venc_freq *= 2;
690 
691 	vclk_freq = max(venc_freq, hdmi_freq);
692 
693 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
694 		venc_freq /= 2;
695 
696 	dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
697 		__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
698 
699 	return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
700 }
701 
702 /* Encoder */
703 
704 static const u32 meson_dw_hdmi_out_bus_fmts[] = {
705 	MEDIA_BUS_FMT_YUV8_1X24,
706 	MEDIA_BUS_FMT_UYYVYY8_0_5X24,
707 };
708 
709 static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
710 {
711 	drm_encoder_cleanup(encoder);
712 }
713 
714 static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
715 	.destroy        = meson_venc_hdmi_encoder_destroy,
716 };
717 
718 static u32 *
719 meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
720 					struct drm_bridge_state *bridge_state,
721 					struct drm_crtc_state *crtc_state,
722 					struct drm_connector_state *conn_state,
723 					u32 output_fmt,
724 					unsigned int *num_input_fmts)
725 {
726 	u32 *input_fmts = NULL;
727 	int i;
728 
729 	*num_input_fmts = 0;
730 
731 	for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
732 		if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
733 			*num_input_fmts = 1;
734 			input_fmts = kcalloc(*num_input_fmts,
735 					     sizeof(*input_fmts),
736 					     GFP_KERNEL);
737 			if (!input_fmts)
738 				return NULL;
739 
740 			input_fmts[0] = output_fmt;
741 
742 			break;
743 		}
744 	}
745 
746 	return input_fmts;
747 }
748 
749 static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
750 					struct drm_bridge_state *bridge_state,
751 					struct drm_crtc_state *crtc_state,
752 					struct drm_connector_state *conn_state)
753 {
754 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
755 
756 	dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
757 
758 	DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
759 
760 	return 0;
761 }
762 
763 static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
764 {
765 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
766 	struct meson_drm *priv = dw_hdmi->priv;
767 
768 	DRM_DEBUG_DRIVER("\n");
769 
770 	writel_bits_relaxed(0x3, 0,
771 			    priv->io_base + _REG(VPU_HDMI_SETTING));
772 
773 	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
774 	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
775 }
776 
777 static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
778 {
779 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
780 	struct meson_drm *priv = dw_hdmi->priv;
781 
782 	DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
783 
784 	if (priv->venc.hdmi_use_enci)
785 		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
786 	else
787 		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
788 }
789 
790 static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
791 				   const struct drm_display_mode *mode,
792 				   const struct drm_display_mode *adjusted_mode)
793 {
794 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
795 	struct meson_drm *priv = dw_hdmi->priv;
796 	int vic = drm_match_cea_mode(mode);
797 	unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
798 	bool yuv420_mode = false;
799 
800 	DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
801 
802 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
803 		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
804 		yuv420_mode = true;
805 	}
806 
807 	/* VENC + VENC-DVI Mode setup */
808 	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
809 
810 	/* VCLK Set clock */
811 	dw_hdmi_set_vclk(dw_hdmi, mode);
812 
813 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
814 		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
815 		writel_relaxed(2 | (2 << 2),
816 			       priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
817 	else
818 		/* Setup YUV444 to HDMI-TX, no 10bit diphering */
819 		writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
820 }
821 
822 static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
823 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
824 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
825 	.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
826 	.atomic_reset = drm_atomic_helper_bridge_reset,
827 	.atomic_check = meson_venc_hdmi_encoder_atomic_check,
828 	.enable	= meson_venc_hdmi_encoder_enable,
829 	.disable = meson_venc_hdmi_encoder_disable,
830 	.mode_set = meson_venc_hdmi_encoder_mode_set,
831 };
832 
833 /* DW HDMI Regmap */
834 
835 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
836 				  unsigned int *result)
837 {
838 	struct meson_dw_hdmi *dw_hdmi = context;
839 
840 	*result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
841 
842 	return 0;
843 
844 }
845 
846 static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
847 				   unsigned int val)
848 {
849 	struct meson_dw_hdmi *dw_hdmi = context;
850 
851 	dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
852 
853 	return 0;
854 }
855 
856 static const struct regmap_config meson_dw_hdmi_regmap_config = {
857 	.reg_bits = 32,
858 	.val_bits = 8,
859 	.reg_read = meson_dw_hdmi_reg_read,
860 	.reg_write = meson_dw_hdmi_reg_write,
861 	.max_register = 0x10000,
862 	.fast_io = true,
863 };
864 
865 static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
866 	.top_read = dw_hdmi_top_read,
867 	.top_write = dw_hdmi_top_write,
868 	.dwc_read = dw_hdmi_dwc_read,
869 	.dwc_write = dw_hdmi_dwc_write,
870 };
871 
872 static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
873 	.top_read = dw_hdmi_g12a_top_read,
874 	.top_write = dw_hdmi_g12a_top_write,
875 	.dwc_read = dw_hdmi_g12a_dwc_read,
876 	.dwc_write = dw_hdmi_g12a_dwc_write,
877 };
878 
879 static bool meson_hdmi_connector_is_available(struct device *dev)
880 {
881 	struct device_node *ep, *remote;
882 
883 	/* HDMI Connector is on the second port, first endpoint */
884 	ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
885 	if (!ep)
886 		return false;
887 
888 	/* If the endpoint node exists, consider it enabled */
889 	remote = of_graph_get_remote_port(ep);
890 	if (remote) {
891 		of_node_put(ep);
892 		return true;
893 	}
894 
895 	of_node_put(ep);
896 	of_node_put(remote);
897 
898 	return false;
899 }
900 
901 static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
902 {
903 	struct meson_drm *priv = meson_dw_hdmi->priv;
904 
905 	/* Enable clocks */
906 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
907 
908 	/* Bring HDMITX MEM output of power down */
909 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
910 
911 	/* Reset HDMITX APB & TX & PHY */
912 	reset_control_reset(meson_dw_hdmi->hdmitx_apb);
913 	reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
914 	reset_control_reset(meson_dw_hdmi->hdmitx_phy);
915 
916 	/* Enable APB3 fail on error */
917 	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
918 		writel_bits_relaxed(BIT(15), BIT(15),
919 				    meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
920 		writel_bits_relaxed(BIT(15), BIT(15),
921 				    meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
922 	}
923 
924 	/* Bring out of reset */
925 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
926 				       HDMITX_TOP_SW_RESET,  0);
927 
928 	msleep(20);
929 
930 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
931 				       HDMITX_TOP_CLK_CNTL, 0xff);
932 
933 	/* Enable HDMI-TX Interrupt */
934 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
935 				       HDMITX_TOP_INTR_CORE);
936 
937 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
938 				       HDMITX_TOP_INTR_CORE);
939 
940 }
941 
942 static void meson_disable_regulator(void *data)
943 {
944 	regulator_disable(data);
945 }
946 
947 static void meson_disable_clk(void *data)
948 {
949 	clk_disable_unprepare(data);
950 }
951 
952 static int meson_enable_clk(struct device *dev, char *name)
953 {
954 	struct clk *clk;
955 	int ret;
956 
957 	clk = devm_clk_get(dev, name);
958 	if (IS_ERR(clk)) {
959 		dev_err(dev, "Unable to get %s pclk\n", name);
960 		return PTR_ERR(clk);
961 	}
962 
963 	ret = clk_prepare_enable(clk);
964 	if (!ret)
965 		ret = devm_add_action_or_reset(dev, meson_disable_clk, clk);
966 
967 	return ret;
968 }
969 
970 static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
971 				void *data)
972 {
973 	struct platform_device *pdev = to_platform_device(dev);
974 	const struct meson_dw_hdmi_data *match;
975 	struct meson_dw_hdmi *meson_dw_hdmi;
976 	struct drm_device *drm = data;
977 	struct meson_drm *priv = drm->dev_private;
978 	struct dw_hdmi_plat_data *dw_plat_data;
979 	struct drm_bridge *next_bridge;
980 	struct drm_encoder *encoder;
981 	int irq;
982 	int ret;
983 
984 	DRM_DEBUG_DRIVER("\n");
985 
986 	if (!meson_hdmi_connector_is_available(dev)) {
987 		dev_info(drm->dev, "HDMI Output connector not available\n");
988 		return -ENODEV;
989 	}
990 
991 	match = of_device_get_match_data(&pdev->dev);
992 	if (!match) {
993 		dev_err(&pdev->dev, "failed to get match data\n");
994 		return -ENODEV;
995 	}
996 
997 	meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
998 				     GFP_KERNEL);
999 	if (!meson_dw_hdmi)
1000 		return -ENOMEM;
1001 
1002 	meson_dw_hdmi->priv = priv;
1003 	meson_dw_hdmi->dev = dev;
1004 	meson_dw_hdmi->data = match;
1005 	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
1006 	encoder = &meson_dw_hdmi->encoder;
1007 
1008 	meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
1009 	if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
1010 		if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
1011 			return -EPROBE_DEFER;
1012 		meson_dw_hdmi->hdmi_supply = NULL;
1013 	} else {
1014 		ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
1015 		if (ret)
1016 			return ret;
1017 		ret = devm_add_action_or_reset(dev, meson_disable_regulator,
1018 					       meson_dw_hdmi->hdmi_supply);
1019 		if (ret)
1020 			return ret;
1021 	}
1022 
1023 	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
1024 						"hdmitx_apb");
1025 	if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
1026 		dev_err(dev, "Failed to get hdmitx_apb reset\n");
1027 		return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
1028 	}
1029 
1030 	meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
1031 						"hdmitx");
1032 	if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
1033 		dev_err(dev, "Failed to get hdmitx reset\n");
1034 		return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
1035 	}
1036 
1037 	meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
1038 						"hdmitx_phy");
1039 	if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
1040 		dev_err(dev, "Failed to get hdmitx_phy reset\n");
1041 		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
1042 	}
1043 
1044 	meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0);
1045 	if (IS_ERR(meson_dw_hdmi->hdmitx))
1046 		return PTR_ERR(meson_dw_hdmi->hdmitx);
1047 
1048 	ret = meson_enable_clk(dev, "isfr");
1049 	if (ret)
1050 		return ret;
1051 
1052 	ret = meson_enable_clk(dev, "iahb");
1053 	if (ret)
1054 		return ret;
1055 
1056 	ret = meson_enable_clk(dev, "venci");
1057 	if (ret)
1058 		return ret;
1059 
1060 	dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
1061 					      &meson_dw_hdmi_regmap_config);
1062 	if (IS_ERR(dw_plat_data->regm))
1063 		return PTR_ERR(dw_plat_data->regm);
1064 
1065 	irq = platform_get_irq(pdev, 0);
1066 	if (irq < 0)
1067 		return irq;
1068 
1069 	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
1070 					dw_hdmi_top_thread_irq, IRQF_SHARED,
1071 					"dw_hdmi_top_irq", meson_dw_hdmi);
1072 	if (ret) {
1073 		dev_err(dev, "Failed to request hdmi top irq\n");
1074 		return ret;
1075 	}
1076 
1077 	/* Encoder */
1078 
1079 	ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
1080 			       DRM_MODE_ENCODER_TMDS, "meson_hdmi");
1081 	if (ret) {
1082 		dev_err(priv->dev, "Failed to init HDMI encoder\n");
1083 		return ret;
1084 	}
1085 
1086 	meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1087 	drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1088 
1089 	encoder->possible_crtcs = BIT(0);
1090 
1091 	meson_dw_hdmi_init(meson_dw_hdmi);
1092 
1093 	DRM_DEBUG_DRIVER("encoder initialized\n");
1094 
1095 	/* Bridge / Connector */
1096 
1097 	dw_plat_data->priv_data = meson_dw_hdmi;
1098 	dw_plat_data->mode_valid = dw_hdmi_mode_valid;
1099 	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
1100 	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
1101 	dw_plat_data->phy_data = meson_dw_hdmi;
1102 	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
1103 	dw_plat_data->ycbcr_420_allowed = true;
1104 	dw_plat_data->disable_cec = true;
1105 
1106 	if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
1107 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
1108 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
1109 		dw_plat_data->use_drm_infoframe = true;
1110 
1111 	platform_set_drvdata(pdev, meson_dw_hdmi);
1112 
1113 	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1114 					    &meson_dw_hdmi->dw_plat_data);
1115 	if (IS_ERR(meson_dw_hdmi->hdmi))
1116 		return PTR_ERR(meson_dw_hdmi->hdmi);
1117 
1118 	next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1119 	if (next_bridge)
1120 		drm_bridge_attach(encoder, next_bridge,
1121 				  &meson_dw_hdmi->bridge, 0);
1122 
1123 	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
1124 
1125 	return 0;
1126 }
1127 
1128 static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
1129 				   void *data)
1130 {
1131 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1132 
1133 	dw_hdmi_unbind(meson_dw_hdmi->hdmi);
1134 }
1135 
1136 static const struct component_ops meson_dw_hdmi_ops = {
1137 	.bind	= meson_dw_hdmi_bind,
1138 	.unbind	= meson_dw_hdmi_unbind,
1139 };
1140 
1141 static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
1142 {
1143 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1144 
1145 	if (!meson_dw_hdmi)
1146 		return 0;
1147 
1148 	/* Reset TOP */
1149 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
1150 				       HDMITX_TOP_SW_RESET, 0);
1151 
1152 	return 0;
1153 }
1154 
1155 static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
1156 {
1157 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1158 
1159 	if (!meson_dw_hdmi)
1160 		return 0;
1161 
1162 	meson_dw_hdmi_init(meson_dw_hdmi);
1163 
1164 	dw_hdmi_resume(meson_dw_hdmi->hdmi);
1165 
1166 	return 0;
1167 }
1168 
1169 static int meson_dw_hdmi_probe(struct platform_device *pdev)
1170 {
1171 	return component_add(&pdev->dev, &meson_dw_hdmi_ops);
1172 }
1173 
1174 static int meson_dw_hdmi_remove(struct platform_device *pdev)
1175 {
1176 	component_del(&pdev->dev, &meson_dw_hdmi_ops);
1177 
1178 	return 0;
1179 }
1180 
1181 static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
1182 	SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
1183 				meson_dw_hdmi_pm_resume)
1184 };
1185 
1186 static const struct of_device_id meson_dw_hdmi_of_table[] = {
1187 	{ .compatible = "amlogic,meson-gxbb-dw-hdmi",
1188 	  .data = &meson_dw_hdmi_gx_data },
1189 	{ .compatible = "amlogic,meson-gxl-dw-hdmi",
1190 	  .data = &meson_dw_hdmi_gx_data },
1191 	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
1192 	  .data = &meson_dw_hdmi_gx_data },
1193 	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
1194 	  .data = &meson_dw_hdmi_g12a_data },
1195 	{ }
1196 };
1197 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
1198 
1199 static struct platform_driver meson_dw_hdmi_platform_driver = {
1200 	.probe		= meson_dw_hdmi_probe,
1201 	.remove		= meson_dw_hdmi_remove,
1202 	.driver		= {
1203 		.name		= DRIVER_NAME,
1204 		.of_match_table	= meson_dw_hdmi_of_table,
1205 		.pm = &meson_dw_hdmi_pm_ops,
1206 	},
1207 };
1208 module_platform_driver(meson_dw_hdmi_platform_driver);
1209 
1210 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
1211 MODULE_DESCRIPTION(DRIVER_DESC);
1212 MODULE_LICENSE("GPL");
1213