xref: /linux/drivers/gpu/drm/meson/meson_dw_hdmi.c (revision 52990390f91c1c39ca742fc8f390b29891d95127)
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/videodev2.h>
26 
27 #include "meson_drv.h"
28 #include "meson_dw_hdmi.h"
29 #include "meson_registers.h"
30 
31 #define DRIVER_NAME "meson-dw-hdmi"
32 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
33 
34 /**
35  * DOC: HDMI Output
36  *
37  * HDMI Output is composed of :
38  *
39  * - A Synopsys DesignWare HDMI Controller IP
40  * - A TOP control block controlling the Clocks and PHY
41  * - A custom HDMI PHY in order convert video to TMDS signal
42  *
43  * .. code::
44  *
45  *    ___________________________________
46  *   |            HDMI TOP               |<= HPD
47  *   |___________________________________|
48  *   |                  |                |
49  *   |  Synopsys HDMI   |   HDMI PHY     |=> TMDS
50  *   |    Controller    |________________|
51  *   |___________________________________|<=> DDC
52  *
53  *
54  * The HDMI TOP block only supports HPD sensing.
55  * The Synopsys HDMI Controller interrupt is routed
56  * through the TOP Block interrupt.
57  * Communication to the TOP Block and the Synopsys
58  * HDMI Controller is done a pair of addr+read/write
59  * registers.
60  * The HDMI PHY is configured by registers in the
61  * HHI register block.
62  *
63  * Pixel data arrives in 4:4:4 format from the VENC
64  * block and the VPU HDMI mux selects either the ENCI
65  * encoder for the 576i or 480i formats or the ENCP
66  * encoder for all the other formats including
67  * interlaced HD formats.
68  * The VENC uses a DVI encoder on top of the ENCI
69  * or ENCP encoders to generate DVI timings for the
70  * HDMI controller.
71  *
72  * GXBB, GXL and GXM embeds the Synopsys DesignWare
73  * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
74  * audio source interfaces.
75  *
76  * We handle the following features :
77  *
78  * - HPD Rise & Fall interrupt
79  * - HDMI Controller Interrupt
80  * - HDMI PHY Init for 480i to 1080p60
81  * - VENC & HDMI Clock setup for 480i to 1080p60
82  * - VENC Mode setup for 480i to 1080p60
83  *
84  * What is missing :
85  *
86  * - PHY, Clock and Mode setup for 2k && 4k modes
87  * - SDDC Scrambling mode for HDMI 2.0a
88  * - HDCP Setup
89  * - CEC Management
90  */
91 
92 /* TOP Block Communication Channel */
93 #define HDMITX_TOP_ADDR_REG	0x0
94 #define HDMITX_TOP_DATA_REG	0x4
95 #define HDMITX_TOP_CTRL_REG	0x8
96 #define HDMITX_TOP_G12A_OFFSET	0x8000
97 
98 /* Controller Communication Channel */
99 #define HDMITX_DWC_ADDR_REG	0x10
100 #define HDMITX_DWC_DATA_REG	0x14
101 #define HDMITX_DWC_CTRL_REG	0x18
102 
103 /* HHI Registers */
104 #define HHI_MEM_PD_REG0		0x100 /* 0x40 */
105 #define HHI_HDMI_CLK_CNTL	0x1cc /* 0x73 */
106 #define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 */
107 #define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
108 #define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
109 #define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
110 #define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
111 #define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
112 
113 static DEFINE_SPINLOCK(reg_lock);
114 
115 enum meson_venc_source {
116 	MESON_VENC_SOURCE_NONE = 0,
117 	MESON_VENC_SOURCE_ENCI = 1,
118 	MESON_VENC_SOURCE_ENCP = 2,
119 };
120 
121 struct meson_dw_hdmi;
122 
123 struct meson_dw_hdmi_data {
124 	unsigned int	(*top_read)(struct meson_dw_hdmi *dw_hdmi,
125 				    unsigned int addr);
126 	void		(*top_write)(struct meson_dw_hdmi *dw_hdmi,
127 				     unsigned int addr, unsigned int data);
128 	unsigned int	(*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
129 				    unsigned int addr);
130 	void		(*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
131 				     unsigned int addr, unsigned int data);
132 };
133 
134 struct meson_dw_hdmi {
135 	struct dw_hdmi_plat_data dw_plat_data;
136 	struct meson_drm *priv;
137 	struct device *dev;
138 	void __iomem *hdmitx;
139 	const struct meson_dw_hdmi_data *data;
140 	struct reset_control *hdmitx_apb;
141 	struct reset_control *hdmitx_ctrl;
142 	struct reset_control *hdmitx_phy;
143 	u32 irq_stat;
144 	struct dw_hdmi *hdmi;
145 	struct drm_bridge *bridge;
146 };
147 
148 static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
149 					const char *compat)
150 {
151 	return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
152 }
153 
154 /* PHY (via TOP bridge) and Controller dedicated register interface */
155 
156 static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
157 				     unsigned int addr)
158 {
159 	unsigned long flags;
160 	unsigned int data;
161 
162 	spin_lock_irqsave(&reg_lock, flags);
163 
164 	/* ADDR must be written twice */
165 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
166 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
167 
168 	/* Read needs a second DATA read */
169 	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
170 	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
171 
172 	spin_unlock_irqrestore(&reg_lock, flags);
173 
174 	return data;
175 }
176 
177 static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
178 					  unsigned int addr)
179 {
180 	return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
181 }
182 
183 static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
184 				     unsigned int addr, unsigned int data)
185 {
186 	unsigned long flags;
187 
188 	spin_lock_irqsave(&reg_lock, flags);
189 
190 	/* ADDR must be written twice */
191 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
192 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
193 
194 	/* Write needs single DATA write */
195 	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
196 
197 	spin_unlock_irqrestore(&reg_lock, flags);
198 }
199 
200 static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
201 					  unsigned int addr, unsigned int data)
202 {
203 	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
204 }
205 
206 /* Helper to change specific bits in PHY registers */
207 static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
208 					  unsigned int addr,
209 					  unsigned int mask,
210 					  unsigned int val)
211 {
212 	unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
213 
214 	data &= ~mask;
215 	data |= val;
216 
217 	dw_hdmi->data->top_write(dw_hdmi, addr, data);
218 }
219 
220 static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
221 				     unsigned int addr)
222 {
223 	unsigned long flags;
224 	unsigned int data;
225 
226 	spin_lock_irqsave(&reg_lock, flags);
227 
228 	/* ADDR must be written twice */
229 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
230 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
231 
232 	/* Read needs a second DATA read */
233 	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
234 	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
235 
236 	spin_unlock_irqrestore(&reg_lock, flags);
237 
238 	return data;
239 }
240 
241 static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
242 					  unsigned int addr)
243 {
244 	return readb(dw_hdmi->hdmitx + addr);
245 }
246 
247 static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
248 				     unsigned int addr, unsigned int data)
249 {
250 	unsigned long flags;
251 
252 	spin_lock_irqsave(&reg_lock, flags);
253 
254 	/* ADDR must be written twice */
255 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
256 	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
257 
258 	/* Write needs single DATA write */
259 	writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
260 
261 	spin_unlock_irqrestore(&reg_lock, flags);
262 }
263 
264 static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
265 					  unsigned int addr, unsigned int data)
266 {
267 	writeb(data, dw_hdmi->hdmitx + addr);
268 }
269 
270 /* Helper to change specific bits in controller registers */
271 static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
272 					  unsigned int addr,
273 					  unsigned int mask,
274 					  unsigned int val)
275 {
276 	unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
277 
278 	data &= ~mask;
279 	data |= val;
280 
281 	dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
282 }
283 
284 /* Bridge */
285 
286 /* Setup PHY bandwidth modes */
287 static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
288 				      const struct drm_display_mode *mode,
289 				      bool mode_is_420)
290 {
291 	struct meson_drm *priv = dw_hdmi->priv;
292 	unsigned int pixel_clock = mode->clock;
293 
294 	/* For 420, pixel clock is half unlike venc clock */
295 	if (mode_is_420) pixel_clock /= 2;
296 
297 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
298 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
299 		if (pixel_clock >= 371250) {
300 			/* 5.94Gbps, 3.7125Gbps */
301 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
302 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
303 		} else if (pixel_clock >= 297000) {
304 			/* 2.97Gbps */
305 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
306 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
307 		} else if (pixel_clock >= 148500) {
308 			/* 1.485Gbps */
309 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
310 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
311 		} else {
312 			/* 742.5Mbps, and below */
313 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
314 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
315 		}
316 	} else if (dw_hdmi_is_compatible(dw_hdmi,
317 					 "amlogic,meson-gxbb-dw-hdmi")) {
318 		if (pixel_clock >= 371250) {
319 			/* 5.94Gbps, 3.7125Gbps */
320 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
321 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
322 		} else if (pixel_clock >= 297000) {
323 			/* 2.97Gbps */
324 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
325 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
326 		} else {
327 			/* 1.485Gbps, and below */
328 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
329 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
330 		}
331 	} else if (dw_hdmi_is_compatible(dw_hdmi,
332 					 "amlogic,meson-g12a-dw-hdmi")) {
333 		if (pixel_clock >= 371250) {
334 			/* 5.94Gbps, 3.7125Gbps */
335 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
336 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
337 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
338 		} else if (pixel_clock >= 297000) {
339 			/* 2.97Gbps */
340 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
341 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
342 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
343 		} else {
344 			/* 1.485Gbps, and below */
345 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
346 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
347 			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
348 		}
349 	}
350 }
351 
352 static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
353 {
354 	struct meson_drm *priv = dw_hdmi->priv;
355 
356 	/* Enable and software reset */
357 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
358 
359 	mdelay(2);
360 
361 	/* Enable and unreset */
362 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
363 
364 	mdelay(2);
365 }
366 
367 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
368 			    const struct drm_display_info *display,
369 			    const struct drm_display_mode *mode)
370 {
371 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
372 	bool is_hdmi2_sink = display->hdmi.scdc.supported;
373 	struct meson_drm *priv = dw_hdmi->priv;
374 	unsigned int wr_clk =
375 		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
376 	bool mode_is_420 = false;
377 
378 	DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
379 			 mode->clock > 340000 ? 40 : 10);
380 
381 	if (drm_mode_is_420_only(display, mode) ||
382 	    (!is_hdmi2_sink &&
383 	     drm_mode_is_420_also(display, mode)))
384 		mode_is_420 = true;
385 
386 	/* Enable clocks */
387 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
388 
389 	/* Bring HDMITX MEM output of power down */
390 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
391 
392 	/* Bring out of reset */
393 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
394 
395 	/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
396 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
397 			       0x3, 0x3);
398 
399 	/* Enable cec_clk and hdcp22_tmdsclk_en */
400 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
401 			       0x3 << 4, 0x3 << 4);
402 
403 	/* Enable normal output to PHY */
404 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
405 
406 	/* TMDS pattern setup */
407 	if (mode->clock > 340000 && !mode_is_420) {
408 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
409 				  0);
410 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
411 				  0x03ff03ff);
412 	} else {
413 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
414 				  0x001f001f);
415 		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
416 				  0x001f001f);
417 	}
418 
419 	/* Load TMDS pattern */
420 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
421 	msleep(20);
422 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
423 
424 	/* Setup PHY parameters */
425 	meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420);
426 
427 	/* Setup PHY */
428 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
429 			   0xffff << 16, 0x0390 << 16);
430 
431 	/* BIT_INVERT */
432 	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
433 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
434 	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
435 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
436 				   BIT(17), 0);
437 	else
438 		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
439 				   BIT(17), BIT(17));
440 
441 	/* Disable clock, fifo, fifo_wr */
442 	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
443 
444 	dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
445 
446 	msleep(100);
447 
448 	/* Reset PHY 3 times in a row */
449 	meson_dw_hdmi_phy_reset(dw_hdmi);
450 	meson_dw_hdmi_phy_reset(dw_hdmi);
451 	meson_dw_hdmi_phy_reset(dw_hdmi);
452 
453 	/* Temporary Disable VENC video stream */
454 	if (priv->venc.hdmi_use_enci)
455 		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
456 	else
457 		writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
458 
459 	/* Temporary Disable HDMI video stream to HDMI-TX */
460 	writel_bits_relaxed(0x3, 0,
461 			    priv->io_base + _REG(VPU_HDMI_SETTING));
462 	writel_bits_relaxed(0xf << 8, 0,
463 			    priv->io_base + _REG(VPU_HDMI_SETTING));
464 
465 	/* Re-Enable VENC video stream */
466 	if (priv->venc.hdmi_use_enci)
467 		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
468 	else
469 		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
470 
471 	/* Push back HDMI clock settings */
472 	writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
473 			    priv->io_base + _REG(VPU_HDMI_SETTING));
474 
475 	/* Enable and Select HDMI video source for HDMI-TX */
476 	if (priv->venc.hdmi_use_enci)
477 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
478 				    priv->io_base + _REG(VPU_HDMI_SETTING));
479 	else
480 		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
481 				    priv->io_base + _REG(VPU_HDMI_SETTING));
482 
483 	return 0;
484 }
485 
486 static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
487 				void *data)
488 {
489 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
490 	struct meson_drm *priv = dw_hdmi->priv;
491 
492 	DRM_DEBUG_DRIVER("\n");
493 
494 	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
495 }
496 
497 static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
498 			     void *data)
499 {
500 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
501 
502 	return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
503 		connector_status_connected : connector_status_disconnected;
504 }
505 
506 static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
507 			      void *data)
508 {
509 	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
510 
511 	/* Setup HPD Filter */
512 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
513 			  (0xa << 12) | 0xa0);
514 
515 	/* Clear interrupts */
516 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
517 			  HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
518 
519 	/* Unmask interrupts */
520 	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
521 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
522 			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
523 }
524 
525 static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
526 	.init = dw_hdmi_phy_init,
527 	.disable = dw_hdmi_phy_disable,
528 	.read_hpd = dw_hdmi_read_hpd,
529 	.setup_hpd = dw_hdmi_setup_hpd,
530 };
531 
532 static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
533 {
534 	struct meson_dw_hdmi *dw_hdmi = dev_id;
535 	u32 stat;
536 
537 	stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
538 	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
539 
540 	/* HPD Events, handle in the threaded interrupt handler */
541 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
542 		dw_hdmi->irq_stat = stat;
543 		return IRQ_WAKE_THREAD;
544 	}
545 
546 	/* HDMI Controller Interrupt */
547 	if (stat & 1)
548 		return IRQ_NONE;
549 
550 	/* TOFIX Handle HDCP Interrupts */
551 
552 	return IRQ_HANDLED;
553 }
554 
555 /* Threaded interrupt handler to manage HPD events */
556 static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
557 {
558 	struct meson_dw_hdmi *dw_hdmi = dev_id;
559 	u32 stat = dw_hdmi->irq_stat;
560 
561 	/* HPD Events */
562 	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
563 		bool hpd_connected = false;
564 
565 		if (stat & HDMITX_TOP_INTR_HPD_RISE)
566 			hpd_connected = true;
567 
568 		dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
569 				       hpd_connected);
570 
571 		drm_helper_hpd_irq_event(dw_hdmi->bridge->dev);
572 		drm_bridge_hpd_notify(dw_hdmi->bridge,
573 				      hpd_connected ? connector_status_connected
574 						    : connector_status_disconnected);
575 	}
576 
577 	return IRQ_HANDLED;
578 }
579 
580 /* DW HDMI Regmap */
581 
582 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
583 				  unsigned int *result)
584 {
585 	struct meson_dw_hdmi *dw_hdmi = context;
586 
587 	*result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
588 
589 	return 0;
590 
591 }
592 
593 static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
594 				   unsigned int val)
595 {
596 	struct meson_dw_hdmi *dw_hdmi = context;
597 
598 	dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
599 
600 	return 0;
601 }
602 
603 static const struct regmap_config meson_dw_hdmi_regmap_config = {
604 	.reg_bits = 32,
605 	.val_bits = 8,
606 	.reg_read = meson_dw_hdmi_reg_read,
607 	.reg_write = meson_dw_hdmi_reg_write,
608 	.max_register = 0x10000,
609 	.fast_io = true,
610 };
611 
612 static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
613 	.top_read = dw_hdmi_top_read,
614 	.top_write = dw_hdmi_top_write,
615 	.dwc_read = dw_hdmi_dwc_read,
616 	.dwc_write = dw_hdmi_dwc_write,
617 };
618 
619 static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
620 	.top_read = dw_hdmi_g12a_top_read,
621 	.top_write = dw_hdmi_g12a_top_write,
622 	.dwc_read = dw_hdmi_g12a_dwc_read,
623 	.dwc_write = dw_hdmi_g12a_dwc_write,
624 };
625 
626 static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
627 {
628 	struct meson_drm *priv = meson_dw_hdmi->priv;
629 
630 	/* Enable clocks */
631 	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
632 
633 	/* Bring HDMITX MEM output of power down */
634 	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
635 
636 	/* Reset HDMITX APB & TX & PHY */
637 	reset_control_reset(meson_dw_hdmi->hdmitx_apb);
638 	reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
639 	reset_control_reset(meson_dw_hdmi->hdmitx_phy);
640 
641 	/* Enable APB3 fail on error */
642 	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
643 		writel_bits_relaxed(BIT(15), BIT(15),
644 				    meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
645 		writel_bits_relaxed(BIT(15), BIT(15),
646 				    meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
647 	}
648 
649 	/* Bring out of reset */
650 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
651 				       HDMITX_TOP_SW_RESET,  0);
652 
653 	msleep(20);
654 
655 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
656 				       HDMITX_TOP_CLK_CNTL, 0xff);
657 
658 	/* Enable HDMI-TX Interrupt */
659 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
660 				       HDMITX_TOP_INTR_CORE);
661 
662 	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
663 				       HDMITX_TOP_INTR_CORE);
664 
665 }
666 
667 static void meson_disable_clk(void *data)
668 {
669 	clk_disable_unprepare(data);
670 }
671 
672 static int meson_enable_clk(struct device *dev, char *name)
673 {
674 	struct clk *clk;
675 	int ret;
676 
677 	clk = devm_clk_get(dev, name);
678 	if (IS_ERR(clk)) {
679 		dev_err(dev, "Unable to get %s pclk\n", name);
680 		return PTR_ERR(clk);
681 	}
682 
683 	ret = clk_prepare_enable(clk);
684 	if (!ret)
685 		ret = devm_add_action_or_reset(dev, meson_disable_clk, clk);
686 
687 	return ret;
688 }
689 
690 static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
691 				void *data)
692 {
693 	struct platform_device *pdev = to_platform_device(dev);
694 	const struct meson_dw_hdmi_data *match;
695 	struct meson_dw_hdmi *meson_dw_hdmi;
696 	struct drm_device *drm = data;
697 	struct meson_drm *priv = drm->dev_private;
698 	struct dw_hdmi_plat_data *dw_plat_data;
699 	int irq;
700 	int ret;
701 
702 	DRM_DEBUG_DRIVER("\n");
703 
704 	match = of_device_get_match_data(&pdev->dev);
705 	if (!match) {
706 		dev_err(&pdev->dev, "failed to get match data\n");
707 		return -ENODEV;
708 	}
709 
710 	meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
711 				     GFP_KERNEL);
712 	if (!meson_dw_hdmi)
713 		return -ENOMEM;
714 
715 	meson_dw_hdmi->priv = priv;
716 	meson_dw_hdmi->dev = dev;
717 	meson_dw_hdmi->data = match;
718 	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
719 
720 	ret = devm_regulator_get_enable_optional(dev, "hdmi");
721 	if (ret < 0 && ret != -ENODEV)
722 		return ret;
723 
724 	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
725 						"hdmitx_apb");
726 	if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
727 		dev_err(dev, "Failed to get hdmitx_apb reset\n");
728 		return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
729 	}
730 
731 	meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
732 						"hdmitx");
733 	if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
734 		dev_err(dev, "Failed to get hdmitx reset\n");
735 		return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
736 	}
737 
738 	meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
739 						"hdmitx_phy");
740 	if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
741 		dev_err(dev, "Failed to get hdmitx_phy reset\n");
742 		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
743 	}
744 
745 	meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0);
746 	if (IS_ERR(meson_dw_hdmi->hdmitx))
747 		return PTR_ERR(meson_dw_hdmi->hdmitx);
748 
749 	ret = meson_enable_clk(dev, "isfr");
750 	if (ret)
751 		return ret;
752 
753 	ret = meson_enable_clk(dev, "iahb");
754 	if (ret)
755 		return ret;
756 
757 	ret = meson_enable_clk(dev, "venci");
758 	if (ret)
759 		return ret;
760 
761 	dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
762 					      &meson_dw_hdmi_regmap_config);
763 	if (IS_ERR(dw_plat_data->regm))
764 		return PTR_ERR(dw_plat_data->regm);
765 
766 	irq = platform_get_irq(pdev, 0);
767 	if (irq < 0)
768 		return irq;
769 
770 	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
771 					dw_hdmi_top_thread_irq, IRQF_SHARED,
772 					"dw_hdmi_top_irq", meson_dw_hdmi);
773 	if (ret) {
774 		dev_err(dev, "Failed to request hdmi top irq\n");
775 		return ret;
776 	}
777 
778 	meson_dw_hdmi_init(meson_dw_hdmi);
779 
780 	/* Bridge / Connector */
781 
782 	dw_plat_data->priv_data = meson_dw_hdmi;
783 	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
784 	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
785 	dw_plat_data->phy_data = meson_dw_hdmi;
786 	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
787 	dw_plat_data->ycbcr_420_allowed = true;
788 	dw_plat_data->disable_cec = true;
789 	dw_plat_data->output_port = 1;
790 
791 	if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
792 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
793 	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
794 		dw_plat_data->use_drm_infoframe = true;
795 
796 	platform_set_drvdata(pdev, meson_dw_hdmi);
797 
798 	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev, &meson_dw_hdmi->dw_plat_data);
799 	if (IS_ERR(meson_dw_hdmi->hdmi))
800 		return PTR_ERR(meson_dw_hdmi->hdmi);
801 
802 	meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node);
803 
804 	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
805 
806 	return 0;
807 }
808 
809 static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
810 				   void *data)
811 {
812 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
813 
814 	dw_hdmi_unbind(meson_dw_hdmi->hdmi);
815 }
816 
817 static const struct component_ops meson_dw_hdmi_ops = {
818 	.bind	= meson_dw_hdmi_bind,
819 	.unbind	= meson_dw_hdmi_unbind,
820 };
821 
822 static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
823 {
824 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
825 
826 	if (!meson_dw_hdmi)
827 		return 0;
828 
829 	/* Reset TOP */
830 	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
831 				       HDMITX_TOP_SW_RESET, 0);
832 
833 	return 0;
834 }
835 
836 static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
837 {
838 	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
839 
840 	if (!meson_dw_hdmi)
841 		return 0;
842 
843 	meson_dw_hdmi_init(meson_dw_hdmi);
844 
845 	dw_hdmi_resume(meson_dw_hdmi->hdmi);
846 
847 	return 0;
848 }
849 
850 static int meson_dw_hdmi_probe(struct platform_device *pdev)
851 {
852 	return component_add(&pdev->dev, &meson_dw_hdmi_ops);
853 }
854 
855 static int meson_dw_hdmi_remove(struct platform_device *pdev)
856 {
857 	component_del(&pdev->dev, &meson_dw_hdmi_ops);
858 
859 	return 0;
860 }
861 
862 static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
863 	SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
864 				meson_dw_hdmi_pm_resume)
865 };
866 
867 static const struct of_device_id meson_dw_hdmi_of_table[] = {
868 	{ .compatible = "amlogic,meson-gxbb-dw-hdmi",
869 	  .data = &meson_dw_hdmi_gx_data },
870 	{ .compatible = "amlogic,meson-gxl-dw-hdmi",
871 	  .data = &meson_dw_hdmi_gx_data },
872 	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
873 	  .data = &meson_dw_hdmi_gx_data },
874 	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
875 	  .data = &meson_dw_hdmi_g12a_data },
876 	{ }
877 };
878 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
879 
880 static struct platform_driver meson_dw_hdmi_platform_driver = {
881 	.probe		= meson_dw_hdmi_probe,
882 	.remove		= meson_dw_hdmi_remove,
883 	.driver		= {
884 		.name		= DRIVER_NAME,
885 		.of_match_table	= meson_dw_hdmi_of_table,
886 		.pm = &meson_dw_hdmi_pm_ops,
887 	},
888 };
889 module_platform_driver(meson_dw_hdmi_platform_driver);
890 
891 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
892 MODULE_DESCRIPTION(DRIVER_DESC);
893 MODULE_LICENSE("GPL");
894