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