xref: /openbmc/linux/drivers/gpu/drm/meson/meson_dw_hdmi.c (revision 1e1129b65ef3f72dbccf24de56b700a181b45227)
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 				      const 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 			    const struct drm_display_info *display,
431 			    const struct drm_display_mode *mode)
432 {
433 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
434 	struct meson_drm *priv = dw_hdmi->priv;
435 	unsigned int wr_clk =
436 		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
437 
438 	DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
439 			 mode->clock > 340000 ? 40 : 10);
440 
441 	/* Enable clocks */
442 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
443 
444 	/* Bring HDMITX MEM output of power down */
445 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
446 
447 	/* Bring out of reset */
448 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
449 
450 	/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
451 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
452 			       0x3, 0x3);
453 
454 	/* Enable cec_clk and hdcp22_tmdsclk_en */
455 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
456 			       0x3 << 4, 0x3 << 4);
457 
458 	/* Enable normal output to PHY */
459 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
460 
461 	/* TMDS pattern setup */
462 	if (mode->clock > 340000 &&
463 	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
464 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
465 				  0);
466 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
467 				  0x03ff03ff);
468 	} else {
469 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
470 				  0x001f001f);
471 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
472 				  0x001f001f);
473 	}
474 
475 	/* Load TMDS pattern */
476 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
477 	msleep(20);
478 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
479 
480 	/* Setup PHY parameters */
481 	meson_hdmi_phy_setup_mode(dw_hdmi, mode);
482 
483 	/* Setup PHY */
484 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
485 			   0xffff << 16, 0x0390 << 16);
486 
487 	/* BIT_INVERT */
488 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
489 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
490 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
491 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
492 				   BIT(17), 0);
493 	else
494 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
495 				   BIT(17), BIT(17));
496 
497 	/* Disable clock, fifo, fifo_wr */
498 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
499 
500 	dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
501 
502 	msleep(100);
503 
504 	/* Reset PHY 3 times in a row */
505 	meson_dw_hdmi_phy_reset(dw_hdmi);
506 	meson_dw_hdmi_phy_reset(dw_hdmi);
507 	meson_dw_hdmi_phy_reset(dw_hdmi);
508 
509 	/* Temporary Disable VENC video stream */
510 	if (priv->venc.hdmi_use_enci)
511 		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
512 	else
513 		writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
514 
515 	/* Temporary Disable HDMI video stream to HDMI-TX */
516 	writel_bits_relaxed(0x3, 0,
517 			    priv->io_base + _REG(VPU_HDMI_SETTING));
518 	writel_bits_relaxed(0xf << 8, 0,
519 			    priv->io_base + _REG(VPU_HDMI_SETTING));
520 
521 	/* Re-Enable VENC video stream */
522 	if (priv->venc.hdmi_use_enci)
523 		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
524 	else
525 		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
526 
527 	/* Push back HDMI clock settings */
528 	writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
529 			    priv->io_base + _REG(VPU_HDMI_SETTING));
530 
531 	/* Enable and Select HDMI video source for HDMI-TX */
532 	if (priv->venc.hdmi_use_enci)
533 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
534 				    priv->io_base + _REG(VPU_HDMI_SETTING));
535 	else
536 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
537 				    priv->io_base + _REG(VPU_HDMI_SETTING));
538 
539 	return 0;
540 }
541 
542 static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
543 				void *data)
544 {
545 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
546 	struct meson_drm *priv = dw_hdmi->priv;
547 
548 	DRM_DEBUG_DRIVER("\n");
549 
550 	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
551 }
552 
553 static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
554 			     void *data)
555 {
556 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
557 
558 	return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
559 		connector_status_connected : connector_status_disconnected;
560 }
561 
562 static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
563 			      void *data)
564 {
565 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
566 
567 	/* Setup HPD Filter */
568 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
569 			  (0xa << 12) | 0xa0);
570 
571 	/* Clear interrupts */
572 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
573 			  HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
574 
575 	/* Unmask interrupts */
576 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
577 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
578 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
579 }
580 
581 static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
582 	.init = dw_hdmi_phy_init,
583 	.disable = dw_hdmi_phy_disable,
584 	.read_hpd = dw_hdmi_read_hpd,
585 	.setup_hpd = dw_hdmi_setup_hpd,
586 };
587 
588 static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
589 {
590 	struct meson_dw_hdmi *dw_hdmi = dev_id;
591 	u32 stat;
592 
593 	stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
594 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
595 
596 	/* HPD Events, handle in the threaded interrupt handler */
597 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
598 		dw_hdmi->irq_stat = stat;
599 		return IRQ_WAKE_THREAD;
600 	}
601 
602 	/* HDMI Controller Interrupt */
603 	if (stat & 1)
604 		return IRQ_NONE;
605 
606 	/* TOFIX Handle HDCP Interrupts */
607 
608 	return IRQ_HANDLED;
609 }
610 
611 /* Threaded interrupt handler to manage HPD events */
612 static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
613 {
614 	struct meson_dw_hdmi *dw_hdmi = dev_id;
615 	u32 stat = dw_hdmi->irq_stat;
616 
617 	/* HPD Events */
618 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
619 		bool hpd_connected = false;
620 
621 		if (stat & HDMITX_TOP_INTR_HPD_RISE)
622 			hpd_connected = true;
623 
624 		dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
625 				       hpd_connected);
626 
627 		drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
628 	}
629 
630 	return IRQ_HANDLED;
631 }
632 
633 static enum drm_mode_status
634 dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
635 		   const struct drm_display_info *display_info,
636 		   const struct drm_display_mode *mode)
637 {
638 	struct meson_dw_hdmi *dw_hdmi = data;
639 	struct meson_drm *priv = dw_hdmi->priv;
640 	bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
641 	unsigned int phy_freq;
642 	unsigned int vclk_freq;
643 	unsigned int venc_freq;
644 	unsigned int hdmi_freq;
645 	int vic = drm_match_cea_mode(mode);
646 	enum drm_mode_status status;
647 
648 	DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
649 
650 	/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
651 	if (display_info->max_tmds_clock &&
652 	    mode->clock > display_info->max_tmds_clock &&
653 	    !drm_mode_is_420_only(display_info, mode) &&
654 	    !drm_mode_is_420_also(display_info, mode))
655 		return MODE_BAD;
656 
657 	/* Check against non-VIC supported modes */
658 	if (!vic) {
659 		status = meson_venc_hdmi_supported_mode(mode);
660 		if (status != MODE_OK)
661 			return status;
662 
663 		return meson_vclk_dmt_supported_freq(priv, mode->clock);
664 	/* Check against supported VIC modes */
665 	} else if (!meson_venc_hdmi_supported_vic(vic))
666 		return MODE_BAD;
667 
668 	vclk_freq = mode->clock;
669 
670 	/* For 420, pixel clock is half unlike venc clock */
671 	if (drm_mode_is_420_only(display_info, mode) ||
672 	    (!is_hdmi2_sink &&
673 	     drm_mode_is_420_also(display_info, mode)))
674 		vclk_freq /= 2;
675 
676 	/* TMDS clock is pixel_clock * 10 */
677 	phy_freq = vclk_freq * 10;
678 
679 	/* 480i/576i needs global pixel doubling */
680 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
681 		vclk_freq *= 2;
682 
683 	venc_freq = vclk_freq;
684 	hdmi_freq = vclk_freq;
685 
686 	/* VENC double pixels for 1080i, 720p and YUV420 modes */
687 	if (meson_venc_hdmi_venc_repeat(vic) ||
688 	    drm_mode_is_420_only(display_info, mode) ||
689 	    (!is_hdmi2_sink &&
690 	     drm_mode_is_420_also(display_info, mode)))
691 		venc_freq *= 2;
692 
693 	vclk_freq = max(venc_freq, hdmi_freq);
694 
695 	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
696 		venc_freq /= 2;
697 
698 	dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
699 		__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
700 
701 	return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
702 }
703 
704 /* Encoder */
705 
706 static const u32 meson_dw_hdmi_out_bus_fmts[] = {
707 	MEDIA_BUS_FMT_YUV8_1X24,
708 	MEDIA_BUS_FMT_UYYVYY8_0_5X24,
709 };
710 
711 static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
712 {
713 	drm_encoder_cleanup(encoder);
714 }
715 
716 static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
717 	.destroy        = meson_venc_hdmi_encoder_destroy,
718 };
719 
720 static u32 *
721 meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
722 					struct drm_bridge_state *bridge_state,
723 					struct drm_crtc_state *crtc_state,
724 					struct drm_connector_state *conn_state,
725 					u32 output_fmt,
726 					unsigned int *num_input_fmts)
727 {
728 	u32 *input_fmts = NULL;
729 	int i;
730 
731 	*num_input_fmts = 0;
732 
733 	for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
734 		if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
735 			*num_input_fmts = 1;
736 			input_fmts = kcalloc(*num_input_fmts,
737 					     sizeof(*input_fmts),
738 					     GFP_KERNEL);
739 			if (!input_fmts)
740 				return NULL;
741 
742 			input_fmts[0] = output_fmt;
743 
744 			break;
745 		}
746 	}
747 
748 	return input_fmts;
749 }
750 
751 static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
752 					struct drm_bridge_state *bridge_state,
753 					struct drm_crtc_state *crtc_state,
754 					struct drm_connector_state *conn_state)
755 {
756 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
757 
758 	dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
759 
760 	DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
761 
762 	return 0;
763 }
764 
765 static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
766 {
767 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
768 	struct meson_drm *priv = dw_hdmi->priv;
769 
770 	DRM_DEBUG_DRIVER("\n");
771 
772 	writel_bits_relaxed(0x3, 0,
773 			    priv->io_base + _REG(VPU_HDMI_SETTING));
774 
775 	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
776 	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
777 }
778 
779 static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
780 {
781 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
782 	struct meson_drm *priv = dw_hdmi->priv;
783 
784 	DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
785 
786 	if (priv->venc.hdmi_use_enci)
787 		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
788 	else
789 		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
790 }
791 
792 static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
793 				   const struct drm_display_mode *mode,
794 				   const struct drm_display_mode *adjusted_mode)
795 {
796 	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
797 	struct meson_drm *priv = dw_hdmi->priv;
798 	int vic = drm_match_cea_mode(mode);
799 	unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
800 	bool yuv420_mode = false;
801 
802 	DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
803 
804 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
805 		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
806 		yuv420_mode = true;
807 	}
808 
809 	/* VENC + VENC-DVI Mode setup */
810 	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
811 
812 	/* VCLK Set clock */
813 	dw_hdmi_set_vclk(dw_hdmi, mode);
814 
815 	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
816 		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
817 		writel_relaxed(2 | (2 << 2),
818 			       priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
819 	else
820 		/* Setup YUV444 to HDMI-TX, no 10bit diphering */
821 		writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
822 }
823 
824 static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
825 	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
826 	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
827 	.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
828 	.atomic_reset = drm_atomic_helper_bridge_reset,
829 	.atomic_check = meson_venc_hdmi_encoder_atomic_check,
830 	.enable	= meson_venc_hdmi_encoder_enable,
831 	.disable = meson_venc_hdmi_encoder_disable,
832 	.mode_set = meson_venc_hdmi_encoder_mode_set,
833 };
834 
835 /* DW HDMI Regmap */
836 
837 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
838 				  unsigned int *result)
839 {
840 	struct meson_dw_hdmi *dw_hdmi = context;
841 
842 	*result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
843 
844 	return 0;
845 
846 }
847 
848 static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
849 				   unsigned int val)
850 {
851 	struct meson_dw_hdmi *dw_hdmi = context;
852 
853 	dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
854 
855 	return 0;
856 }
857 
858 static const struct regmap_config meson_dw_hdmi_regmap_config = {
859 	.reg_bits = 32,
860 	.val_bits = 8,
861 	.reg_read = meson_dw_hdmi_reg_read,
862 	.reg_write = meson_dw_hdmi_reg_write,
863 	.max_register = 0x10000,
864 	.fast_io = true,
865 };
866 
867 static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
868 	.top_read = dw_hdmi_top_read,
869 	.top_write = dw_hdmi_top_write,
870 	.dwc_read = dw_hdmi_dwc_read,
871 	.dwc_write = dw_hdmi_dwc_write,
872 };
873 
874 static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
875 	.top_read = dw_hdmi_g12a_top_read,
876 	.top_write = dw_hdmi_g12a_top_write,
877 	.dwc_read = dw_hdmi_g12a_dwc_read,
878 	.dwc_write = dw_hdmi_g12a_dwc_write,
879 };
880 
881 static bool meson_hdmi_connector_is_available(struct device *dev)
882 {
883 	struct device_node *ep, *remote;
884 
885 	/* HDMI Connector is on the second port, first endpoint */
886 	ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
887 	if (!ep)
888 		return false;
889 
890 	/* If the endpoint node exists, consider it enabled */
891 	remote = of_graph_get_remote_port(ep);
892 	if (remote) {
893 		of_node_put(ep);
894 		return true;
895 	}
896 
897 	of_node_put(ep);
898 	of_node_put(remote);
899 
900 	return false;
901 }
902 
903 static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
904 {
905 	struct meson_drm *priv = meson_dw_hdmi->priv;
906 
907 	/* Enable clocks */
908 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
909 
910 	/* Bring HDMITX MEM output of power down */
911 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
912 
913 	/* Reset HDMITX APB & TX & PHY */
914 	reset_control_reset(meson_dw_hdmi->hdmitx_apb);
915 	reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
916 	reset_control_reset(meson_dw_hdmi->hdmitx_phy);
917 
918 	/* Enable APB3 fail on error */
919 	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
920 		writel_bits_relaxed(BIT(15), BIT(15),
921 				    meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
922 		writel_bits_relaxed(BIT(15), BIT(15),
923 				    meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
924 	}
925 
926 	/* Bring out of reset */
927 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
928 				       HDMITX_TOP_SW_RESET,  0);
929 
930 	msleep(20);
931 
932 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
933 				       HDMITX_TOP_CLK_CNTL, 0xff);
934 
935 	/* Enable HDMI-TX Interrupt */
936 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
937 				       HDMITX_TOP_INTR_CORE);
938 
939 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
940 				       HDMITX_TOP_INTR_CORE);
941 
942 }
943 
944 static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
945 				void *data)
946 {
947 	struct platform_device *pdev = to_platform_device(dev);
948 	const struct meson_dw_hdmi_data *match;
949 	struct meson_dw_hdmi *meson_dw_hdmi;
950 	struct drm_device *drm = data;
951 	struct meson_drm *priv = drm->dev_private;
952 	struct dw_hdmi_plat_data *dw_plat_data;
953 	struct drm_bridge *next_bridge;
954 	struct drm_encoder *encoder;
955 	struct resource *res;
956 	int irq;
957 	int ret;
958 
959 	DRM_DEBUG_DRIVER("\n");
960 
961 	if (!meson_hdmi_connector_is_available(dev)) {
962 		dev_info(drm->dev, "HDMI Output connector not available\n");
963 		return -ENODEV;
964 	}
965 
966 	match = of_device_get_match_data(&pdev->dev);
967 	if (!match) {
968 		dev_err(&pdev->dev, "failed to get match data\n");
969 		return -ENODEV;
970 	}
971 
972 	meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
973 				     GFP_KERNEL);
974 	if (!meson_dw_hdmi)
975 		return -ENOMEM;
976 
977 	meson_dw_hdmi->priv = priv;
978 	meson_dw_hdmi->dev = dev;
979 	meson_dw_hdmi->data = match;
980 	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
981 	encoder = &meson_dw_hdmi->encoder;
982 
983 	meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
984 	if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
985 		if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
986 			return -EPROBE_DEFER;
987 		meson_dw_hdmi->hdmi_supply = NULL;
988 	} else {
989 		ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
990 		if (ret)
991 			return ret;
992 	}
993 
994 	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
995 						"hdmitx_apb");
996 	if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
997 		dev_err(dev, "Failed to get hdmitx_apb reset\n");
998 		return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
999 	}
1000 
1001 	meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
1002 						"hdmitx");
1003 	if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
1004 		dev_err(dev, "Failed to get hdmitx reset\n");
1005 		return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
1006 	}
1007 
1008 	meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
1009 						"hdmitx_phy");
1010 	if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
1011 		dev_err(dev, "Failed to get hdmitx_phy reset\n");
1012 		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
1013 	}
1014 
1015 	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1016 	meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
1017 	if (IS_ERR(meson_dw_hdmi->hdmitx))
1018 		return PTR_ERR(meson_dw_hdmi->hdmitx);
1019 
1020 	meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
1021 	if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
1022 		dev_err(dev, "Unable to get HDMI pclk\n");
1023 		return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
1024 	}
1025 	clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
1026 
1027 	meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
1028 	if (IS_ERR(meson_dw_hdmi->venci_clk)) {
1029 		dev_err(dev, "Unable to get venci clk\n");
1030 		return PTR_ERR(meson_dw_hdmi->venci_clk);
1031 	}
1032 	clk_prepare_enable(meson_dw_hdmi->venci_clk);
1033 
1034 	dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
1035 					      &meson_dw_hdmi_regmap_config);
1036 	if (IS_ERR(dw_plat_data->regm))
1037 		return PTR_ERR(dw_plat_data->regm);
1038 
1039 	irq = platform_get_irq(pdev, 0);
1040 	if (irq < 0)
1041 		return irq;
1042 
1043 	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
1044 					dw_hdmi_top_thread_irq, IRQF_SHARED,
1045 					"dw_hdmi_top_irq", meson_dw_hdmi);
1046 	if (ret) {
1047 		dev_err(dev, "Failed to request hdmi top irq\n");
1048 		return ret;
1049 	}
1050 
1051 	/* Encoder */
1052 
1053 	ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
1054 			       DRM_MODE_ENCODER_TMDS, "meson_hdmi");
1055 	if (ret) {
1056 		dev_err(priv->dev, "Failed to init HDMI encoder\n");
1057 		return ret;
1058 	}
1059 
1060 	meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1061 	drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1062 
1063 	encoder->possible_crtcs = BIT(0);
1064 
1065 	DRM_DEBUG_DRIVER("encoder initialized\n");
1066 
1067 	meson_dw_hdmi_init(meson_dw_hdmi);
1068 
1069 	/* Bridge / Connector */
1070 
1071 	dw_plat_data->priv_data = meson_dw_hdmi;
1072 	dw_plat_data->mode_valid = dw_hdmi_mode_valid;
1073 	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
1074 	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
1075 	dw_plat_data->phy_data = meson_dw_hdmi;
1076 	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
1077 	dw_plat_data->ycbcr_420_allowed = true;
1078 
1079 	if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
1080 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
1081 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
1082 		dw_plat_data->use_drm_infoframe = true;
1083 
1084 	platform_set_drvdata(pdev, meson_dw_hdmi);
1085 
1086 	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1087 					    &meson_dw_hdmi->dw_plat_data);
1088 	if (IS_ERR(meson_dw_hdmi->hdmi))
1089 		return PTR_ERR(meson_dw_hdmi->hdmi);
1090 
1091 	next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1092 	if (next_bridge)
1093 		drm_bridge_attach(encoder, next_bridge,
1094 				  &meson_dw_hdmi->bridge, 0);
1095 
1096 	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
1097 
1098 	return 0;
1099 }
1100 
1101 static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
1102 				   void *data)
1103 {
1104 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1105 
1106 	dw_hdmi_unbind(meson_dw_hdmi->hdmi);
1107 }
1108 
1109 static const struct component_ops meson_dw_hdmi_ops = {
1110 	.bind	= meson_dw_hdmi_bind,
1111 	.unbind	= meson_dw_hdmi_unbind,
1112 };
1113 
1114 static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
1115 {
1116 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1117 
1118 	if (!meson_dw_hdmi)
1119 		return 0;
1120 
1121 	/* Reset TOP */
1122 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
1123 				       HDMITX_TOP_SW_RESET, 0);
1124 
1125 	return 0;
1126 }
1127 
1128 static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
1129 {
1130 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1131 
1132 	if (!meson_dw_hdmi)
1133 		return 0;
1134 
1135 	meson_dw_hdmi_init(meson_dw_hdmi);
1136 
1137 	dw_hdmi_resume(meson_dw_hdmi->hdmi);
1138 
1139 	return 0;
1140 }
1141 
1142 static int meson_dw_hdmi_probe(struct platform_device *pdev)
1143 {
1144 	return component_add(&pdev->dev, &meson_dw_hdmi_ops);
1145 }
1146 
1147 static int meson_dw_hdmi_remove(struct platform_device *pdev)
1148 {
1149 	component_del(&pdev->dev, &meson_dw_hdmi_ops);
1150 
1151 	return 0;
1152 }
1153 
1154 static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
1155 	SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
1156 				meson_dw_hdmi_pm_resume)
1157 };
1158 
1159 static const struct of_device_id meson_dw_hdmi_of_table[] = {
1160 	{ .compatible = "amlogic,meson-gxbb-dw-hdmi",
1161 	  .data = &meson_dw_hdmi_gx_data },
1162 	{ .compatible = "amlogic,meson-gxl-dw-hdmi",
1163 	  .data = &meson_dw_hdmi_gx_data },
1164 	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
1165 	  .data = &meson_dw_hdmi_gx_data },
1166 	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
1167 	  .data = &meson_dw_hdmi_g12a_data },
1168 	{ }
1169 };
1170 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
1171 
1172 static struct platform_driver meson_dw_hdmi_platform_driver = {
1173 	.probe		= meson_dw_hdmi_probe,
1174 	.remove		= meson_dw_hdmi_remove,
1175 	.driver		= {
1176 		.name		= DRIVER_NAME,
1177 		.of_match_table	= meson_dw_hdmi_of_table,
1178 		.pm = &meson_dw_hdmi_pm_ops,
1179 	},
1180 };
1181 module_platform_driver(meson_dw_hdmi_platform_driver);
1182 
1183 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
1184 MODULE_DESCRIPTION(DRIVER_DESC);
1185 MODULE_LICENSE("GPL");
1186