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