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