1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20#include <linux/kernel.h>
21#include <linux/module.h>
22#include <linux/component.h>
23#include <linux/of_graph.h>
24#include <linux/reset.h>
25#include <linux/clk.h>
26#include <linux/regulator/consumer.h>
27
28#include <drm/drmP.h>
29#include <drm/drm_edid.h>
30#include <drm/drm_crtc_helper.h>
31#include <drm/drm_atomic_helper.h>
32#include <drm/bridge/dw_hdmi.h>
33
34#include <uapi/linux/media-bus-format.h>
35#include <uapi/linux/videodev2.h>
36
37#include "meson_drv.h"
38#include "meson_venc.h"
39#include "meson_vclk.h"
40#include "meson_dw_hdmi.h"
41#include "meson_registers.h"
42
43#define DRIVER_NAME "meson-dw-hdmi"
44#define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105#define HDMITX_TOP_ADDR_REG 0x0
106#define HDMITX_TOP_DATA_REG 0x4
107#define HDMITX_TOP_CTRL_REG 0x8
108
109
110#define HDMITX_DWC_ADDR_REG 0x10
111#define HDMITX_DWC_DATA_REG 0x14
112#define HDMITX_DWC_CTRL_REG 0x18
113
114
115#define HHI_MEM_PD_REG0 0x100
116#define HHI_HDMI_CLK_CNTL 0x1cc
117#define HHI_HDMI_PHY_CNTL0 0x3a0
118#define HHI_HDMI_PHY_CNTL1 0x3a4
119#define HHI_HDMI_PHY_CNTL2 0x3a8
120#define HHI_HDMI_PHY_CNTL3 0x3ac
121
122static DEFINE_SPINLOCK(reg_lock);
123
124enum meson_venc_source {
125 MESON_VENC_SOURCE_NONE = 0,
126 MESON_VENC_SOURCE_ENCI = 1,
127 MESON_VENC_SOURCE_ENCP = 2,
128};
129
130struct meson_dw_hdmi {
131 struct drm_encoder encoder;
132 struct dw_hdmi_plat_data dw_plat_data;
133 struct meson_drm *priv;
134 struct device *dev;
135 void __iomem *hdmitx;
136 struct reset_control *hdmitx_apb;
137 struct reset_control *hdmitx_ctrl;
138 struct reset_control *hdmitx_phy;
139 struct clk *hdmi_pclk;
140 struct clk *venci_clk;
141 struct regulator *hdmi_supply;
142 u32 irq_stat;
143};
144#define encoder_to_meson_dw_hdmi(x) \
145 container_of(x, struct meson_dw_hdmi, encoder)
146
147static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
148 const char *compat)
149{
150 return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
151}
152
153
154
155static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
156 unsigned int addr)
157{
158 unsigned long flags;
159 unsigned int data;
160
161 spin_lock_irqsave(®_lock, flags);
162
163
164 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
165 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
166
167
168 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
169 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
170
171 spin_unlock_irqrestore(®_lock, flags);
172
173 return data;
174}
175
176static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
177 unsigned int addr, unsigned int data)
178{
179 unsigned long flags;
180
181 spin_lock_irqsave(®_lock, flags);
182
183
184 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
185 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
186
187
188 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
189
190 spin_unlock_irqrestore(®_lock, flags);
191}
192
193
194static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
195 unsigned int addr,
196 unsigned int mask,
197 unsigned int val)
198{
199 unsigned int data = dw_hdmi_top_read(dw_hdmi, addr);
200
201 data &= ~mask;
202 data |= val;
203
204 dw_hdmi_top_write(dw_hdmi, addr, data);
205}
206
207static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
208 unsigned int addr)
209{
210 unsigned long flags;
211 unsigned int data;
212
213 spin_lock_irqsave(®_lock, flags);
214
215
216 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
217 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
218
219
220 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
221 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
222
223 spin_unlock_irqrestore(®_lock, flags);
224
225 return data;
226}
227
228static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
229 unsigned int addr, unsigned int data)
230{
231 unsigned long flags;
232
233 spin_lock_irqsave(®_lock, flags);
234
235
236 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
237 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
238
239
240 writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
241
242 spin_unlock_irqrestore(®_lock, flags);
243}
244
245
246static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
247 unsigned int addr,
248 unsigned int mask,
249 unsigned int val)
250{
251 unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr);
252
253 data &= ~mask;
254 data |= val;
255
256 dw_hdmi_dwc_write(dw_hdmi, addr, data);
257}
258
259
260
261
262static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
263 struct drm_display_mode *mode)
264{
265 struct meson_drm *priv = dw_hdmi->priv;
266 unsigned int pixel_clock = mode->clock;
267
268 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
269 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
270 if (pixel_clock >= 371250) {
271
272 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
273 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
274 } else if (pixel_clock >= 297000) {
275
276 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
277 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
278 } else if (pixel_clock >= 148500) {
279
280 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
281 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
282 } else {
283
284 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
285 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
286 }
287 } else if (dw_hdmi_is_compatible(dw_hdmi,
288 "amlogic,meson-gxbb-dw-hdmi")) {
289 if (pixel_clock >= 371250) {
290
291 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
292 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
293 } else if (pixel_clock >= 297000) {
294
295 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
296 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
297 } else {
298
299 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
300 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
301 }
302 }
303}
304
305static inline void dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
306{
307 struct meson_drm *priv = dw_hdmi->priv;
308
309
310 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
311
312 mdelay(2);
313
314
315 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
316
317 mdelay(2);
318}
319
320static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
321 struct drm_display_mode *mode)
322{
323 struct meson_drm *priv = dw_hdmi->priv;
324 int vic = drm_match_cea_mode(mode);
325 unsigned int vclk_freq;
326 unsigned int venc_freq;
327 unsigned int hdmi_freq;
328
329 vclk_freq = mode->clock;
330
331 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
332 vclk_freq *= 2;
333
334 venc_freq = vclk_freq;
335 hdmi_freq = vclk_freq;
336
337 if (meson_venc_hdmi_venc_repeat(vic))
338 venc_freq *= 2;
339
340 vclk_freq = max(venc_freq, hdmi_freq);
341
342 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
343 venc_freq /= 2;
344
345 DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
346 vclk_freq, venc_freq, hdmi_freq,
347 priv->venc.hdmi_use_enci);
348
349 meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
350 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
351}
352
353static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
354 struct drm_display_mode *mode)
355{
356 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
357 struct meson_drm *priv = dw_hdmi->priv;
358 unsigned int wr_clk =
359 readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
360
361 DRM_DEBUG_DRIVER("%d:\"%s\"\n", mode->base.id, mode->name);
362
363
364 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
365
366
367 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
368
369
370 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
371
372
373 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
374 0x3, 0x3);
375 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
376 0x3 << 4, 0x3 << 4);
377
378
379 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
380
381
382 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f);
383 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f);
384
385
386 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
387 msleep(20);
388 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
389
390
391 meson_hdmi_phy_setup_mode(dw_hdmi, mode);
392
393
394 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
395 0xffff << 16, 0x0390 << 16);
396
397
398 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
399 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi"))
400 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
401 BIT(17), 0);
402 else
403 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
404 BIT(17), BIT(17));
405
406
407 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
408
409 msleep(100);
410
411
412 dw_hdmi_phy_reset(dw_hdmi);
413 dw_hdmi_phy_reset(dw_hdmi);
414 dw_hdmi_phy_reset(dw_hdmi);
415
416
417 if (priv->venc.hdmi_use_enci)
418 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
419 else
420 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
421
422
423 writel_bits_relaxed(0x3, 0,
424 priv->io_base + _REG(VPU_HDMI_SETTING));
425 writel_bits_relaxed(0xf << 8, 0,
426 priv->io_base + _REG(VPU_HDMI_SETTING));
427
428
429 if (priv->venc.hdmi_use_enci)
430 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
431 else
432 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
433
434
435 writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
436 priv->io_base + _REG(VPU_HDMI_SETTING));
437
438
439 if (priv->venc.hdmi_use_enci)
440 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
441 priv->io_base + _REG(VPU_HDMI_SETTING));
442 else
443 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
444 priv->io_base + _REG(VPU_HDMI_SETTING));
445
446 return 0;
447}
448
449static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
450 void *data)
451{
452 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
453 struct meson_drm *priv = dw_hdmi->priv;
454
455 DRM_DEBUG_DRIVER("\n");
456
457 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
458}
459
460static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
461 void *data)
462{
463 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
464
465 return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
466 connector_status_connected : connector_status_disconnected;
467}
468
469static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
470 void *data)
471{
472 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
473
474
475 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
476 (0xa << 12) | 0xa0);
477
478
479 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
480 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
481
482
483 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
484 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
485 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
486}
487
488static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
489 .init = dw_hdmi_phy_init,
490 .disable = dw_hdmi_phy_disable,
491 .read_hpd = dw_hdmi_read_hpd,
492 .setup_hpd = dw_hdmi_setup_hpd,
493};
494
495static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
496{
497 struct meson_dw_hdmi *dw_hdmi = dev_id;
498 u32 stat;
499
500 stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
501 dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
502
503
504 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
505 dw_hdmi->irq_stat = stat;
506 return IRQ_WAKE_THREAD;
507 }
508
509
510 if (stat & 1)
511 return IRQ_NONE;
512
513
514
515 return IRQ_HANDLED;
516}
517
518
519static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
520{
521 struct meson_dw_hdmi *dw_hdmi = dev_id;
522 u32 stat = dw_hdmi->irq_stat;
523
524
525 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
526 bool hpd_connected = false;
527
528 if (stat & HDMITX_TOP_INTR_HPD_RISE)
529 hpd_connected = true;
530
531 dw_hdmi_setup_rx_sense(dw_hdmi->dev, hpd_connected,
532 hpd_connected);
533
534 drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
535 }
536
537 return IRQ_HANDLED;
538}
539
540
541static enum drm_mode_status
542dw_hdmi_mode_valid(struct drm_connector *connector,
543 const struct drm_display_mode *mode)
544{
545 unsigned int vclk_freq;
546 unsigned int venc_freq;
547 unsigned int hdmi_freq;
548 int vic = drm_match_cea_mode(mode);
549
550 DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
551 mode->base.id, mode->name, mode->vrefresh, mode->clock,
552 mode->hdisplay, mode->hsync_start,
553 mode->hsync_end, mode->htotal,
554 mode->vdisplay, mode->vsync_start,
555 mode->vsync_end, mode->vtotal, mode->type, mode->flags);
556
557
558 if (!vic)
559 return MODE_BAD;
560
561
562 if (!meson_venc_hdmi_supported_vic(vic))
563 return MODE_BAD;
564
565 vclk_freq = mode->clock;
566
567
568 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
569 vclk_freq *= 2;
570
571 venc_freq = vclk_freq;
572 hdmi_freq = vclk_freq;
573
574
575 if (meson_venc_hdmi_venc_repeat(vic))
576 venc_freq *= 2;
577
578 vclk_freq = max(venc_freq, hdmi_freq);
579
580 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
581 venc_freq /= 2;
582
583 dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
584 vclk_freq, venc_freq, hdmi_freq);
585
586
587 switch (vclk_freq) {
588 case 54000:
589 case 74250:
590 case 148500:
591 case 297000:
592 case 594000:
593 return MODE_OK;
594 }
595
596 return MODE_CLOCK_RANGE;
597}
598
599
600
601static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
602{
603 drm_encoder_cleanup(encoder);
604}
605
606static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
607 .destroy = meson_venc_hdmi_encoder_destroy,
608};
609
610static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
611 struct drm_crtc_state *crtc_state,
612 struct drm_connector_state *conn_state)
613{
614 return 0;
615}
616
617static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
618{
619 struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
620 struct meson_drm *priv = dw_hdmi->priv;
621
622 DRM_DEBUG_DRIVER("\n");
623
624 writel_bits_relaxed(0x3, 0,
625 priv->io_base + _REG(VPU_HDMI_SETTING));
626
627 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
628 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
629}
630
631static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
632{
633 struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
634 struct meson_drm *priv = dw_hdmi->priv;
635
636 DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
637
638 if (priv->venc.hdmi_use_enci)
639 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
640 else
641 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
642}
643
644static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
645 struct drm_display_mode *mode,
646 struct drm_display_mode *adjusted_mode)
647{
648 struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
649 struct meson_drm *priv = dw_hdmi->priv;
650 int vic = drm_match_cea_mode(mode);
651
652 DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
653 mode->base.id, mode->name, vic);
654
655
656 if (!vic)
657 return;
658
659
660 meson_venc_hdmi_mode_set(priv, vic, mode);
661
662
663 dw_hdmi_set_vclk(dw_hdmi, mode);
664
665
666 writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
667}
668
669static const struct drm_encoder_helper_funcs
670 meson_venc_hdmi_encoder_helper_funcs = {
671 .atomic_check = meson_venc_hdmi_encoder_atomic_check,
672 .disable = meson_venc_hdmi_encoder_disable,
673 .enable = meson_venc_hdmi_encoder_enable,
674 .mode_set = meson_venc_hdmi_encoder_mode_set,
675};
676
677
678
679static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
680 unsigned int *result)
681{
682 *result = dw_hdmi_dwc_read(context, reg);
683
684 return 0;
685
686}
687
688static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
689 unsigned int val)
690{
691 dw_hdmi_dwc_write(context, reg, val);
692
693 return 0;
694}
695
696static const struct regmap_config meson_dw_hdmi_regmap_config = {
697 .reg_bits = 32,
698 .val_bits = 8,
699 .reg_read = meson_dw_hdmi_reg_read,
700 .reg_write = meson_dw_hdmi_reg_write,
701 .max_register = 0x10000,
702};
703
704static bool meson_hdmi_connector_is_available(struct device *dev)
705{
706 struct device_node *ep, *remote;
707
708
709 ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
710 if (!ep)
711 return false;
712
713
714 remote = of_graph_get_remote_port(ep);
715 if (remote) {
716 of_node_put(ep);
717 return true;
718 }
719
720 of_node_put(ep);
721 of_node_put(remote);
722
723 return false;
724}
725
726static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
727 void *data)
728{
729 struct platform_device *pdev = to_platform_device(dev);
730 struct meson_dw_hdmi *meson_dw_hdmi;
731 struct drm_device *drm = data;
732 struct meson_drm *priv = drm->dev_private;
733 struct dw_hdmi_plat_data *dw_plat_data;
734 struct drm_encoder *encoder;
735 struct resource *res;
736 int irq;
737 int ret;
738
739 DRM_DEBUG_DRIVER("\n");
740
741 if (!meson_hdmi_connector_is_available(dev)) {
742 dev_info(drm->dev, "HDMI Output connector not available\n");
743 return -ENODEV;
744 }
745
746 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
747 GFP_KERNEL);
748 if (!meson_dw_hdmi)
749 return -ENOMEM;
750
751 meson_dw_hdmi->priv = priv;
752 meson_dw_hdmi->dev = dev;
753 dw_plat_data = &meson_dw_hdmi->dw_plat_data;
754 encoder = &meson_dw_hdmi->encoder;
755
756 meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
757 if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
758 if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
759 return -EPROBE_DEFER;
760 meson_dw_hdmi->hdmi_supply = NULL;
761 } else {
762 ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
763 if (ret)
764 return ret;
765 }
766
767 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
768 "hdmitx_apb");
769 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
770 dev_err(dev, "Failed to get hdmitx_apb reset\n");
771 return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
772 }
773
774 meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
775 "hdmitx");
776 if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
777 dev_err(dev, "Failed to get hdmitx reset\n");
778 return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
779 }
780
781 meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
782 "hdmitx_phy");
783 if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
784 dev_err(dev, "Failed to get hdmitx_phy reset\n");
785 return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
786 }
787
788 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
789 meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
790 if (IS_ERR(meson_dw_hdmi->hdmitx))
791 return PTR_ERR(meson_dw_hdmi->hdmitx);
792
793 meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
794 if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
795 dev_err(dev, "Unable to get HDMI pclk\n");
796 return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
797 }
798 clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
799
800 meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
801 if (IS_ERR(meson_dw_hdmi->venci_clk)) {
802 dev_err(dev, "Unable to get venci clk\n");
803 return PTR_ERR(meson_dw_hdmi->venci_clk);
804 }
805 clk_prepare_enable(meson_dw_hdmi->venci_clk);
806
807 dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
808 &meson_dw_hdmi_regmap_config);
809 if (IS_ERR(dw_plat_data->regm))
810 return PTR_ERR(dw_plat_data->regm);
811
812 irq = platform_get_irq(pdev, 0);
813 if (irq < 0) {
814 dev_err(dev, "Failed to get hdmi top irq\n");
815 return irq;
816 }
817
818 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
819 dw_hdmi_top_thread_irq, IRQF_SHARED,
820 "dw_hdmi_top_irq", meson_dw_hdmi);
821 if (ret) {
822 dev_err(dev, "Failed to request hdmi top irq\n");
823 return ret;
824 }
825
826
827
828 drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs);
829
830 ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
831 DRM_MODE_ENCODER_TMDS, "meson_hdmi");
832 if (ret) {
833 dev_err(priv->dev, "Failed to init HDMI encoder\n");
834 return ret;
835 }
836
837 encoder->possible_crtcs = BIT(0);
838
839 DRM_DEBUG_DRIVER("encoder initialized\n");
840
841
842 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
843
844
845 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
846
847
848 reset_control_reset(meson_dw_hdmi->hdmitx_apb);
849 reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
850 reset_control_reset(meson_dw_hdmi->hdmitx_phy);
851
852
853 writel_bits_relaxed(BIT(15), BIT(15),
854 meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
855 writel_bits_relaxed(BIT(15), BIT(15),
856 meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
857
858
859 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET, 0);
860
861 msleep(20);
862
863 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff);
864
865
866 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
867 HDMITX_TOP_INTR_CORE);
868
869 dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
870 HDMITX_TOP_INTR_CORE);
871
872
873
874 dw_plat_data->mode_valid = dw_hdmi_mode_valid;
875 dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
876 dw_plat_data->phy_name = "meson_dw_hdmi_phy";
877 dw_plat_data->phy_data = meson_dw_hdmi;
878 dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
879 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
880
881 ret = dw_hdmi_bind(pdev, encoder, &meson_dw_hdmi->dw_plat_data);
882 if (ret)
883 return ret;
884
885 DRM_DEBUG_DRIVER("HDMI controller initialized\n");
886
887 return 0;
888}
889
890static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
891 void *data)
892{
893 dw_hdmi_unbind(dev);
894}
895
896static const struct component_ops meson_dw_hdmi_ops = {
897 .bind = meson_dw_hdmi_bind,
898 .unbind = meson_dw_hdmi_unbind,
899};
900
901static int meson_dw_hdmi_probe(struct platform_device *pdev)
902{
903 return component_add(&pdev->dev, &meson_dw_hdmi_ops);
904}
905
906static int meson_dw_hdmi_remove(struct platform_device *pdev)
907{
908 component_del(&pdev->dev, &meson_dw_hdmi_ops);
909
910 return 0;
911}
912
913static const struct of_device_id meson_dw_hdmi_of_table[] = {
914 { .compatible = "amlogic,meson-gxbb-dw-hdmi" },
915 { .compatible = "amlogic,meson-gxl-dw-hdmi" },
916 { .compatible = "amlogic,meson-gxm-dw-hdmi" },
917 { }
918};
919MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
920
921static struct platform_driver meson_dw_hdmi_platform_driver = {
922 .probe = meson_dw_hdmi_probe,
923 .remove = meson_dw_hdmi_remove,
924 .driver = {
925 .name = DRIVER_NAME,
926 .of_match_table = meson_dw_hdmi_of_table,
927 },
928};
929module_platform_driver(meson_dw_hdmi_platform_driver);
930
931MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
932MODULE_DESCRIPTION(DRIVER_DESC);
933MODULE_LICENSE("GPL");
934