1
2
3
4
5
6
7
8#include <linux/clk.h>
9#include <linux/component.h>
10#include <linux/kernel.h>
11#include <linux/module.h>
12#include <linux/of_device.h>
13#include <linux/of_graph.h>
14#include <linux/regulator/consumer.h>
15#include <linux/reset.h>
16
17#include <drm/bridge/dw_hdmi.h>
18#include <drm/drm_atomic_helper.h>
19#include <drm/drm_bridge.h>
20#include <drm/drm_device.h>
21#include <drm/drm_edid.h>
22#include <drm/drm_probe_helper.h>
23#include <drm/drm_print.h>
24
25#include <linux/media-bus-format.h>
26#include <linux/videodev2.h>
27
28#include "meson_drv.h"
29#include "meson_dw_hdmi.h"
30#include "meson_registers.h"
31#include "meson_vclk.h"
32#include "meson_venc.h"
33
34#define DRIVER_NAME "meson-dw-hdmi"
35#define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
36
37
38
39
40
41
42
43
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#define HDMITX_TOP_ADDR_REG 0x0
97#define HDMITX_TOP_DATA_REG 0x4
98#define HDMITX_TOP_CTRL_REG 0x8
99#define HDMITX_TOP_G12A_OFFSET 0x8000
100
101
102#define HDMITX_DWC_ADDR_REG 0x10
103#define HDMITX_DWC_DATA_REG 0x14
104#define HDMITX_DWC_CTRL_REG 0x18
105
106
107#define HHI_MEM_PD_REG0 0x100
108#define HHI_HDMI_CLK_CNTL 0x1cc
109#define HHI_HDMI_PHY_CNTL0 0x3a0
110#define HHI_HDMI_PHY_CNTL1 0x3a4
111#define HHI_HDMI_PHY_CNTL2 0x3a8
112#define HHI_HDMI_PHY_CNTL3 0x3ac
113#define HHI_HDMI_PHY_CNTL4 0x3b0
114#define HHI_HDMI_PHY_CNTL5 0x3b4
115
116static DEFINE_SPINLOCK(reg_lock);
117
118enum meson_venc_source {
119 MESON_VENC_SOURCE_NONE = 0,
120 MESON_VENC_SOURCE_ENCI = 1,
121 MESON_VENC_SOURCE_ENCP = 2,
122};
123
124struct meson_dw_hdmi;
125
126struct meson_dw_hdmi_data {
127 unsigned int (*top_read)(struct meson_dw_hdmi *dw_hdmi,
128 unsigned int addr);
129 void (*top_write)(struct meson_dw_hdmi *dw_hdmi,
130 unsigned int addr, unsigned int data);
131 unsigned int (*dwc_read)(struct meson_dw_hdmi *dw_hdmi,
132 unsigned int addr);
133 void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi,
134 unsigned int addr, unsigned int data);
135};
136
137struct meson_dw_hdmi {
138 struct drm_encoder encoder;
139 struct drm_bridge bridge;
140 struct dw_hdmi_plat_data dw_plat_data;
141 struct meson_drm *priv;
142 struct device *dev;
143 void __iomem *hdmitx;
144 const struct meson_dw_hdmi_data *data;
145 struct reset_control *hdmitx_apb;
146 struct reset_control *hdmitx_ctrl;
147 struct reset_control *hdmitx_phy;
148 struct regulator *hdmi_supply;
149 u32 irq_stat;
150 struct dw_hdmi *hdmi;
151 unsigned long output_bus_fmt;
152};
153#define encoder_to_meson_dw_hdmi(x) \
154 container_of(x, struct meson_dw_hdmi, encoder)
155#define bridge_to_meson_dw_hdmi(x) \
156 container_of(x, struct meson_dw_hdmi, bridge)
157
158static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
159 const char *compat)
160{
161 return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
162}
163
164
165
166static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
167 unsigned int addr)
168{
169 unsigned long flags;
170 unsigned int data;
171
172 spin_lock_irqsave(®_lock, flags);
173
174
175 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
176 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
177
178
179 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
180 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
181
182 spin_unlock_irqrestore(®_lock, flags);
183
184 return data;
185}
186
187static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
188 unsigned int addr)
189{
190 return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
191}
192
193static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
194 unsigned int addr, unsigned int data)
195{
196 unsigned long flags;
197
198 spin_lock_irqsave(®_lock, flags);
199
200
201 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
202 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
203
204
205 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
206
207 spin_unlock_irqrestore(®_lock, flags);
208}
209
210static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
211 unsigned int addr, unsigned int data)
212{
213 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
214}
215
216
217static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
218 unsigned int addr,
219 unsigned int mask,
220 unsigned int val)
221{
222 unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
223
224 data &= ~mask;
225 data |= val;
226
227 dw_hdmi->data->top_write(dw_hdmi, addr, data);
228}
229
230static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
231 unsigned int addr)
232{
233 unsigned long flags;
234 unsigned int data;
235
236 spin_lock_irqsave(®_lock, flags);
237
238
239 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
240 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
241
242
243 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
244 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
245
246 spin_unlock_irqrestore(®_lock, flags);
247
248 return data;
249}
250
251static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
252 unsigned int addr)
253{
254 return readb(dw_hdmi->hdmitx + addr);
255}
256
257static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
258 unsigned int addr, unsigned int data)
259{
260 unsigned long flags;
261
262 spin_lock_irqsave(®_lock, flags);
263
264
265 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
266 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
267
268
269 writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
270
271 spin_unlock_irqrestore(®_lock, flags);
272}
273
274static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
275 unsigned int addr, unsigned int data)
276{
277 writeb(data, dw_hdmi->hdmitx + addr);
278}
279
280
281static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
282 unsigned int addr,
283 unsigned int mask,
284 unsigned int val)
285{
286 unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
287
288 data &= ~mask;
289 data |= val;
290
291 dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
292}
293
294
295
296
297static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
298 const struct drm_display_mode *mode)
299{
300 struct meson_drm *priv = dw_hdmi->priv;
301 unsigned int pixel_clock = mode->clock;
302
303
304 if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
305 pixel_clock /= 2;
306
307 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
308 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
309 if (pixel_clock >= 371250) {
310
311 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
312 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
313 } else if (pixel_clock >= 297000) {
314
315 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
316 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
317 } else if (pixel_clock >= 148500) {
318
319 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
320 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
321 } else {
322
323 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
324 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
325 }
326 } else if (dw_hdmi_is_compatible(dw_hdmi,
327 "amlogic,meson-gxbb-dw-hdmi")) {
328 if (pixel_clock >= 371250) {
329
330 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
331 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
332 } else if (pixel_clock >= 297000) {
333
334 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
335 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
336 } else {
337
338 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
339 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
340 }
341 } else if (dw_hdmi_is_compatible(dw_hdmi,
342 "amlogic,meson-g12a-dw-hdmi")) {
343 if (pixel_clock >= 371250) {
344
345 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
346 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
347 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
348 } else if (pixel_clock >= 297000) {
349
350 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
351 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
352 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
353 } else {
354
355 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
356 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
357 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
358 }
359 }
360}
361
362static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
363{
364 struct meson_drm *priv = dw_hdmi->priv;
365
366
367 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
368
369 mdelay(2);
370
371
372 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
373
374 mdelay(2);
375}
376
377static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
378 const struct drm_display_mode *mode)
379{
380 struct meson_drm *priv = dw_hdmi->priv;
381 int vic = drm_match_cea_mode(mode);
382 unsigned int phy_freq;
383 unsigned int vclk_freq;
384 unsigned int venc_freq;
385 unsigned int hdmi_freq;
386
387 vclk_freq = mode->clock;
388
389
390 if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
391 vclk_freq /= 2;
392
393
394 phy_freq = vclk_freq * 10;
395
396 if (!vic) {
397 meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
398 vclk_freq, vclk_freq, vclk_freq, false);
399 return;
400 }
401
402
403 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
404 vclk_freq *= 2;
405
406 venc_freq = vclk_freq;
407 hdmi_freq = vclk_freq;
408
409
410 if (meson_venc_hdmi_venc_repeat(vic) ||
411 dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
412 venc_freq *= 2;
413
414 vclk_freq = max(venc_freq, hdmi_freq);
415
416 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
417 venc_freq /= 2;
418
419 DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
420 phy_freq, vclk_freq, venc_freq, hdmi_freq,
421 priv->venc.hdmi_use_enci);
422
423 meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
424 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
425}
426
427static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
428 const struct drm_display_info *display,
429 const struct drm_display_mode *mode)
430{
431 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
432 struct meson_drm *priv = dw_hdmi->priv;
433 unsigned int wr_clk =
434 readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
435
436 DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
437 mode->clock > 340000 ? 40 : 10);
438
439
440 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
441
442
443 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
444
445
446 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
447
448
449 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
450 0x3, 0x3);
451
452
453 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
454 0x3 << 4, 0x3 << 4);
455
456
457 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
458
459
460 if (mode->clock > 340000 &&
461 dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
462 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
463 0);
464 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
465 0x03ff03ff);
466 } else {
467 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
468 0x001f001f);
469 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
470 0x001f001f);
471 }
472
473
474 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
475 msleep(20);
476 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
477
478
479 meson_hdmi_phy_setup_mode(dw_hdmi, mode);
480
481
482 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
483 0xffff << 16, 0x0390 << 16);
484
485
486 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
487 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
488 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
489 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
490 BIT(17), 0);
491 else
492 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
493 BIT(17), BIT(17));
494
495
496 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
497
498 dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
499
500 msleep(100);
501
502
503 meson_dw_hdmi_phy_reset(dw_hdmi);
504 meson_dw_hdmi_phy_reset(dw_hdmi);
505 meson_dw_hdmi_phy_reset(dw_hdmi);
506
507
508 if (priv->venc.hdmi_use_enci)
509 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
510 else
511 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
512
513
514 writel_bits_relaxed(0x3, 0,
515 priv->io_base + _REG(VPU_HDMI_SETTING));
516 writel_bits_relaxed(0xf << 8, 0,
517 priv->io_base + _REG(VPU_HDMI_SETTING));
518
519
520 if (priv->venc.hdmi_use_enci)
521 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
522 else
523 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
524
525
526 writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
527 priv->io_base + _REG(VPU_HDMI_SETTING));
528
529
530 if (priv->venc.hdmi_use_enci)
531 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
532 priv->io_base + _REG(VPU_HDMI_SETTING));
533 else
534 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
535 priv->io_base + _REG(VPU_HDMI_SETTING));
536
537 return 0;
538}
539
540static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
541 void *data)
542{
543 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
544 struct meson_drm *priv = dw_hdmi->priv;
545
546 DRM_DEBUG_DRIVER("\n");
547
548 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
549}
550
551static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
552 void *data)
553{
554 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
555
556 return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
557 connector_status_connected : connector_status_disconnected;
558}
559
560static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
561 void *data)
562{
563 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
564
565
566 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
567 (0xa << 12) | 0xa0);
568
569
570 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
571 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
572
573
574 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
575 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
576 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
577}
578
579static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
580 .init = dw_hdmi_phy_init,
581 .disable = dw_hdmi_phy_disable,
582 .read_hpd = dw_hdmi_read_hpd,
583 .setup_hpd = dw_hdmi_setup_hpd,
584};
585
586static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
587{
588 struct meson_dw_hdmi *dw_hdmi = dev_id;
589 u32 stat;
590
591 stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
592 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
593
594
595 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
596 dw_hdmi->irq_stat = stat;
597 return IRQ_WAKE_THREAD;
598 }
599
600
601 if (stat & 1)
602 return IRQ_NONE;
603
604
605
606 return IRQ_HANDLED;
607}
608
609
610static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
611{
612 struct meson_dw_hdmi *dw_hdmi = dev_id;
613 u32 stat = dw_hdmi->irq_stat;
614
615
616 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
617 bool hpd_connected = false;
618
619 if (stat & HDMITX_TOP_INTR_HPD_RISE)
620 hpd_connected = true;
621
622 dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
623 hpd_connected);
624
625 drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
626 }
627
628 return IRQ_HANDLED;
629}
630
631static enum drm_mode_status
632dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
633 const struct drm_display_info *display_info,
634 const struct drm_display_mode *mode)
635{
636 struct meson_dw_hdmi *dw_hdmi = data;
637 struct meson_drm *priv = dw_hdmi->priv;
638 bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
639 unsigned int phy_freq;
640 unsigned int vclk_freq;
641 unsigned int venc_freq;
642 unsigned int hdmi_freq;
643 int vic = drm_match_cea_mode(mode);
644 enum drm_mode_status status;
645
646 DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
647
648
649 if (display_info->max_tmds_clock &&
650 mode->clock > display_info->max_tmds_clock &&
651 !drm_mode_is_420_only(display_info, mode) &&
652 !drm_mode_is_420_also(display_info, mode))
653 return MODE_BAD;
654
655
656 if (!vic) {
657 status = meson_venc_hdmi_supported_mode(mode);
658 if (status != MODE_OK)
659 return status;
660
661 return meson_vclk_dmt_supported_freq(priv, mode->clock);
662
663 } else if (!meson_venc_hdmi_supported_vic(vic))
664 return MODE_BAD;
665
666 vclk_freq = mode->clock;
667
668
669 if (drm_mode_is_420_only(display_info, mode) ||
670 (!is_hdmi2_sink &&
671 drm_mode_is_420_also(display_info, mode)))
672 vclk_freq /= 2;
673
674
675 phy_freq = vclk_freq * 10;
676
677
678 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
679 vclk_freq *= 2;
680
681 venc_freq = vclk_freq;
682 hdmi_freq = vclk_freq;
683
684
685 if (meson_venc_hdmi_venc_repeat(vic) ||
686 drm_mode_is_420_only(display_info, mode) ||
687 (!is_hdmi2_sink &&
688 drm_mode_is_420_also(display_info, mode)))
689 venc_freq *= 2;
690
691 vclk_freq = max(venc_freq, hdmi_freq);
692
693 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
694 venc_freq /= 2;
695
696 dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
697 __func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
698
699 return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
700}
701
702
703
704static const u32 meson_dw_hdmi_out_bus_fmts[] = {
705 MEDIA_BUS_FMT_YUV8_1X24,
706 MEDIA_BUS_FMT_UYYVYY8_0_5X24,
707};
708
709static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
710{
711 drm_encoder_cleanup(encoder);
712}
713
714static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
715 .destroy = meson_venc_hdmi_encoder_destroy,
716};
717
718static u32 *
719meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
720 struct drm_bridge_state *bridge_state,
721 struct drm_crtc_state *crtc_state,
722 struct drm_connector_state *conn_state,
723 u32 output_fmt,
724 unsigned int *num_input_fmts)
725{
726 u32 *input_fmts = NULL;
727 int i;
728
729 *num_input_fmts = 0;
730
731 for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
732 if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
733 *num_input_fmts = 1;
734 input_fmts = kcalloc(*num_input_fmts,
735 sizeof(*input_fmts),
736 GFP_KERNEL);
737 if (!input_fmts)
738 return NULL;
739
740 input_fmts[0] = output_fmt;
741
742 break;
743 }
744 }
745
746 return input_fmts;
747}
748
749static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
750 struct drm_bridge_state *bridge_state,
751 struct drm_crtc_state *crtc_state,
752 struct drm_connector_state *conn_state)
753{
754 struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
755
756 dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
757
758 DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
759
760 return 0;
761}
762
763static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
764{
765 struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
766 struct meson_drm *priv = dw_hdmi->priv;
767
768 DRM_DEBUG_DRIVER("\n");
769
770 writel_bits_relaxed(0x3, 0,
771 priv->io_base + _REG(VPU_HDMI_SETTING));
772
773 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
774 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
775}
776
777static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
778{
779 struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
780 struct meson_drm *priv = dw_hdmi->priv;
781
782 DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
783
784 if (priv->venc.hdmi_use_enci)
785 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
786 else
787 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
788}
789
790static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
791 const struct drm_display_mode *mode,
792 const struct drm_display_mode *adjusted_mode)
793{
794 struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
795 struct meson_drm *priv = dw_hdmi->priv;
796 int vic = drm_match_cea_mode(mode);
797 unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
798 bool yuv420_mode = false;
799
800 DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
801
802 if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
803 ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
804 yuv420_mode = true;
805 }
806
807
808 meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
809
810
811 dw_hdmi_set_vclk(dw_hdmi, mode);
812
813 if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
814
815 writel_relaxed(2 | (2 << 2),
816 priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
817 else
818
819 writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
820}
821
822static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
823 .atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
824 .atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
825 .atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
826 .atomic_reset = drm_atomic_helper_bridge_reset,
827 .atomic_check = meson_venc_hdmi_encoder_atomic_check,
828 .enable = meson_venc_hdmi_encoder_enable,
829 .disable = meson_venc_hdmi_encoder_disable,
830 .mode_set = meson_venc_hdmi_encoder_mode_set,
831};
832
833
834
835static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
836 unsigned int *result)
837{
838 struct meson_dw_hdmi *dw_hdmi = context;
839
840 *result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
841
842 return 0;
843
844}
845
846static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
847 unsigned int val)
848{
849 struct meson_dw_hdmi *dw_hdmi = context;
850
851 dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
852
853 return 0;
854}
855
856static const struct regmap_config meson_dw_hdmi_regmap_config = {
857 .reg_bits = 32,
858 .val_bits = 8,
859 .reg_read = meson_dw_hdmi_reg_read,
860 .reg_write = meson_dw_hdmi_reg_write,
861 .max_register = 0x10000,
862 .fast_io = true,
863};
864
865static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
866 .top_read = dw_hdmi_top_read,
867 .top_write = dw_hdmi_top_write,
868 .dwc_read = dw_hdmi_dwc_read,
869 .dwc_write = dw_hdmi_dwc_write,
870};
871
872static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
873 .top_read = dw_hdmi_g12a_top_read,
874 .top_write = dw_hdmi_g12a_top_write,
875 .dwc_read = dw_hdmi_g12a_dwc_read,
876 .dwc_write = dw_hdmi_g12a_dwc_write,
877};
878
879static bool meson_hdmi_connector_is_available(struct device *dev)
880{
881 struct device_node *ep, *remote;
882
883
884 ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
885 if (!ep)
886 return false;
887
888
889 remote = of_graph_get_remote_port(ep);
890 if (remote) {
891 of_node_put(ep);
892 return true;
893 }
894
895 of_node_put(ep);
896 of_node_put(remote);
897
898 return false;
899}
900
901static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
902{
903 struct meson_drm *priv = meson_dw_hdmi->priv;
904
905
906 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
907
908
909 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
910
911
912 reset_control_reset(meson_dw_hdmi->hdmitx_apb);
913 reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
914 reset_control_reset(meson_dw_hdmi->hdmitx_phy);
915
916
917 if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
918 writel_bits_relaxed(BIT(15), BIT(15),
919 meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
920 writel_bits_relaxed(BIT(15), BIT(15),
921 meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
922 }
923
924
925 meson_dw_hdmi->data->top_write(meson_dw_hdmi,
926 HDMITX_TOP_SW_RESET, 0);
927
928 msleep(20);
929
930 meson_dw_hdmi->data->top_write(meson_dw_hdmi,
931 HDMITX_TOP_CLK_CNTL, 0xff);
932
933
934 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
935 HDMITX_TOP_INTR_CORE);
936
937 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
938 HDMITX_TOP_INTR_CORE);
939
940}
941
942static void meson_disable_regulator(void *data)
943{
944 regulator_disable(data);
945}
946
947static void meson_disable_clk(void *data)
948{
949 clk_disable_unprepare(data);
950}
951
952static int meson_enable_clk(struct device *dev, char *name)
953{
954 struct clk *clk;
955 int ret;
956
957 clk = devm_clk_get(dev, name);
958 if (IS_ERR(clk)) {
959 dev_err(dev, "Unable to get %s pclk\n", name);
960 return PTR_ERR(clk);
961 }
962
963 ret = clk_prepare_enable(clk);
964 if (!ret)
965 ret = devm_add_action_or_reset(dev, meson_disable_clk, clk);
966
967 return ret;
968}
969
970static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
971 void *data)
972{
973 struct platform_device *pdev = to_platform_device(dev);
974 const struct meson_dw_hdmi_data *match;
975 struct meson_dw_hdmi *meson_dw_hdmi;
976 struct drm_device *drm = data;
977 struct meson_drm *priv = drm->dev_private;
978 struct dw_hdmi_plat_data *dw_plat_data;
979 struct drm_bridge *next_bridge;
980 struct drm_encoder *encoder;
981 struct resource *res;
982 int irq;
983 int ret;
984
985 DRM_DEBUG_DRIVER("\n");
986
987 if (!meson_hdmi_connector_is_available(dev)) {
988 dev_info(drm->dev, "HDMI Output connector not available\n");
989 return -ENODEV;
990 }
991
992 match = of_device_get_match_data(&pdev->dev);
993 if (!match) {
994 dev_err(&pdev->dev, "failed to get match data\n");
995 return -ENODEV;
996 }
997
998 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
999 GFP_KERNEL);
1000 if (!meson_dw_hdmi)
1001 return -ENOMEM;
1002
1003 meson_dw_hdmi->priv = priv;
1004 meson_dw_hdmi->dev = dev;
1005 meson_dw_hdmi->data = match;
1006 dw_plat_data = &meson_dw_hdmi->dw_plat_data;
1007 encoder = &meson_dw_hdmi->encoder;
1008
1009 meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
1010 if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
1011 if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
1012 return -EPROBE_DEFER;
1013 meson_dw_hdmi->hdmi_supply = NULL;
1014 } else {
1015 ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
1016 if (ret)
1017 return ret;
1018 ret = devm_add_action_or_reset(dev, meson_disable_regulator,
1019 meson_dw_hdmi->hdmi_supply);
1020 if (ret)
1021 return ret;
1022 }
1023
1024 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
1025 "hdmitx_apb");
1026 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
1027 dev_err(dev, "Failed to get hdmitx_apb reset\n");
1028 return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
1029 }
1030
1031 meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
1032 "hdmitx");
1033 if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
1034 dev_err(dev, "Failed to get hdmitx reset\n");
1035 return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
1036 }
1037
1038 meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
1039 "hdmitx_phy");
1040 if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
1041 dev_err(dev, "Failed to get hdmitx_phy reset\n");
1042 return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
1043 }
1044
1045 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1046 meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
1047 if (IS_ERR(meson_dw_hdmi->hdmitx))
1048 return PTR_ERR(meson_dw_hdmi->hdmitx);
1049
1050 ret = meson_enable_clk(dev, "isfr");
1051 if (ret)
1052 return ret;
1053
1054 ret = meson_enable_clk(dev, "iahb");
1055 if (ret)
1056 return ret;
1057
1058 ret = meson_enable_clk(dev, "venci");
1059 if (ret)
1060 return ret;
1061
1062 dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
1063 &meson_dw_hdmi_regmap_config);
1064 if (IS_ERR(dw_plat_data->regm))
1065 return PTR_ERR(dw_plat_data->regm);
1066
1067 irq = platform_get_irq(pdev, 0);
1068 if (irq < 0)
1069 return irq;
1070
1071 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
1072 dw_hdmi_top_thread_irq, IRQF_SHARED,
1073 "dw_hdmi_top_irq", meson_dw_hdmi);
1074 if (ret) {
1075 dev_err(dev, "Failed to request hdmi top irq\n");
1076 return ret;
1077 }
1078
1079
1080
1081 ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
1082 DRM_MODE_ENCODER_TMDS, "meson_hdmi");
1083 if (ret) {
1084 dev_err(priv->dev, "Failed to init HDMI encoder\n");
1085 return ret;
1086 }
1087
1088 meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1089 drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1090
1091 encoder->possible_crtcs = BIT(0);
1092
1093 meson_dw_hdmi_init(meson_dw_hdmi);
1094
1095 DRM_DEBUG_DRIVER("encoder initialized\n");
1096
1097
1098
1099 dw_plat_data->priv_data = meson_dw_hdmi;
1100 dw_plat_data->mode_valid = dw_hdmi_mode_valid;
1101 dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
1102 dw_plat_data->phy_name = "meson_dw_hdmi_phy";
1103 dw_plat_data->phy_data = meson_dw_hdmi;
1104 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
1105 dw_plat_data->ycbcr_420_allowed = true;
1106 dw_plat_data->disable_cec = true;
1107
1108 if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
1109 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
1110 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
1111 dw_plat_data->use_drm_infoframe = true;
1112
1113 platform_set_drvdata(pdev, meson_dw_hdmi);
1114
1115 meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1116 &meson_dw_hdmi->dw_plat_data);
1117 if (IS_ERR(meson_dw_hdmi->hdmi))
1118 return PTR_ERR(meson_dw_hdmi->hdmi);
1119
1120 next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1121 if (next_bridge)
1122 drm_bridge_attach(encoder, next_bridge,
1123 &meson_dw_hdmi->bridge, 0);
1124
1125 DRM_DEBUG_DRIVER("HDMI controller initialized\n");
1126
1127 return 0;
1128}
1129
1130static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
1131 void *data)
1132{
1133 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1134
1135 dw_hdmi_unbind(meson_dw_hdmi->hdmi);
1136}
1137
1138static const struct component_ops meson_dw_hdmi_ops = {
1139 .bind = meson_dw_hdmi_bind,
1140 .unbind = meson_dw_hdmi_unbind,
1141};
1142
1143static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
1144{
1145 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1146
1147 if (!meson_dw_hdmi)
1148 return 0;
1149
1150
1151 meson_dw_hdmi->data->top_write(meson_dw_hdmi,
1152 HDMITX_TOP_SW_RESET, 0);
1153
1154 return 0;
1155}
1156
1157static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
1158{
1159 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1160
1161 if (!meson_dw_hdmi)
1162 return 0;
1163
1164 meson_dw_hdmi_init(meson_dw_hdmi);
1165
1166 dw_hdmi_resume(meson_dw_hdmi->hdmi);
1167
1168 return 0;
1169}
1170
1171static int meson_dw_hdmi_probe(struct platform_device *pdev)
1172{
1173 return component_add(&pdev->dev, &meson_dw_hdmi_ops);
1174}
1175
1176static int meson_dw_hdmi_remove(struct platform_device *pdev)
1177{
1178 component_del(&pdev->dev, &meson_dw_hdmi_ops);
1179
1180 return 0;
1181}
1182
1183static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
1184 SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
1185 meson_dw_hdmi_pm_resume)
1186};
1187
1188static const struct of_device_id meson_dw_hdmi_of_table[] = {
1189 { .compatible = "amlogic,meson-gxbb-dw-hdmi",
1190 .data = &meson_dw_hdmi_gx_data },
1191 { .compatible = "amlogic,meson-gxl-dw-hdmi",
1192 .data = &meson_dw_hdmi_gx_data },
1193 { .compatible = "amlogic,meson-gxm-dw-hdmi",
1194 .data = &meson_dw_hdmi_gx_data },
1195 { .compatible = "amlogic,meson-g12a-dw-hdmi",
1196 .data = &meson_dw_hdmi_g12a_data },
1197 { }
1198};
1199MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
1200
1201static struct platform_driver meson_dw_hdmi_platform_driver = {
1202 .probe = meson_dw_hdmi_probe,
1203 .remove = meson_dw_hdmi_remove,
1204 .driver = {
1205 .name = DRIVER_NAME,
1206 .of_match_table = meson_dw_hdmi_of_table,
1207 .pm = &meson_dw_hdmi_pm_ops,
1208 },
1209};
1210module_platform_driver(meson_dw_hdmi_platform_driver);
1211
1212MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
1213MODULE_DESCRIPTION(DRIVER_DESC);
1214MODULE_LICENSE("GPL");
1215