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