Merge tag 'hwmon-for-v6.3-rc3' of git://git.kernel.org/pub/scm/linux/kernel/git/groec...
[linux-2.6-microblaze.git] / drivers / gpu / drm / meson / meson_dw_hdmi.c
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");