forked from ~ljy/RK356X_SDK_RELEASE

hc
2024-05-11 04dd17822334871b23ea2862f7798fb0e0007777
kernel/drivers/gpu/drm/meson/meson_dw_hdmi.c
....@@ -1,44 +1,35 @@
1
+// SPDX-License-Identifier: GPL-2.0-or-later
12 /*
23 * Copyright (C) 2016 BayLibre, SAS
34 * Author: Neil Armstrong <narmstrong@baylibre.com>
45 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
5
- *
6
- * This program is free software; you can redistribute it and/or
7
- * modify it under the terms of the GNU General Public License as
8
- * published by the Free Software Foundation; either version 2 of the
9
- * License, or (at your option) any later version.
10
- *
11
- * This program is distributed in the hope that it will be useful, but
12
- * WITHOUT ANY WARRANTY; without even the implied warranty of
13
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14
- * General Public License for more details.
15
- *
16
- * You should have received a copy of the GNU General Public License
17
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
186 */
197
8
+#include <linux/clk.h>
9
+#include <linux/component.h>
2010 #include <linux/kernel.h>
2111 #include <linux/module.h>
22
-#include <linux/component.h>
12
+#include <linux/of_device.h>
2313 #include <linux/of_graph.h>
24
-#include <linux/reset.h>
25
-#include <linux/clk.h>
2614 #include <linux/regulator/consumer.h>
15
+#include <linux/reset.h>
2716
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>
3217 #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>
3324
34
-#include <uapi/linux/media-bus-format.h>
35
-#include <uapi/linux/videodev2.h>
25
+#include <linux/media-bus-format.h>
26
+#include <linux/videodev2.h>
3627
3728 #include "meson_drv.h"
38
-#include "meson_venc.h"
39
-#include "meson_vclk.h"
4029 #include "meson_dw_hdmi.h"
4130 #include "meson_registers.h"
31
+#include "meson_vclk.h"
32
+#include "meson_venc.h"
4233
4334 #define DRIVER_NAME "meson-dw-hdmi"
4435 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver"
....@@ -105,6 +96,7 @@
10596 #define HDMITX_TOP_ADDR_REG 0x0
10697 #define HDMITX_TOP_DATA_REG 0x4
10798 #define HDMITX_TOP_CTRL_REG 0x8
99
+#define HDMITX_TOP_G12A_OFFSET 0x8000
108100
109101 /* Controller Communication Channel */
110102 #define HDMITX_DWC_ADDR_REG 0x10
....@@ -118,6 +110,8 @@
118110 #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */
119111 #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */
120112 #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */
113
+#define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */
114
+#define HHI_HDMI_PHY_CNTL5 0x3b4 /* 0xed */
121115
122116 static DEFINE_SPINLOCK(reg_lock);
123117
....@@ -127,23 +121,39 @@
127121 MESON_VENC_SOURCE_ENCP = 2,
128122 };
129123
124
+struct meson_dw_hdmi;
125
+
126
+struct 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
+
130137 struct meson_dw_hdmi {
131138 struct drm_encoder encoder;
139
+ struct drm_bridge bridge;
132140 struct dw_hdmi_plat_data dw_plat_data;
133141 struct meson_drm *priv;
134142 struct device *dev;
135143 void __iomem *hdmitx;
144
+ const struct meson_dw_hdmi_data *data;
136145 struct reset_control *hdmitx_apb;
137146 struct reset_control *hdmitx_ctrl;
138147 struct reset_control *hdmitx_phy;
139
- struct clk *hdmi_pclk;
140
- struct clk *venci_clk;
141148 struct regulator *hdmi_supply;
142149 u32 irq_stat;
143150 struct dw_hdmi *hdmi;
151
+ unsigned long output_bus_fmt;
144152 };
145153 #define encoder_to_meson_dw_hdmi(x) \
146154 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)
147157
148158 static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
149159 const char *compat)
....@@ -174,6 +184,12 @@
174184 return data;
175185 }
176186
187
+static 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
+
177193 static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
178194 unsigned int addr, unsigned int data)
179195 {
....@@ -191,18 +207,24 @@
191207 spin_unlock_irqrestore(&reg_lock, flags);
192208 }
193209
210
+static 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
+
194216 /* Helper to change specific bits in PHY registers */
195217 static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
196218 unsigned int addr,
197219 unsigned int mask,
198220 unsigned int val)
199221 {
200
- unsigned int data = dw_hdmi_top_read(dw_hdmi, addr);
222
+ unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
201223
202224 data &= ~mask;
203225 data |= val;
204226
205
- dw_hdmi_top_write(dw_hdmi, addr, data);
227
+ dw_hdmi->data->top_write(dw_hdmi, addr, data);
206228 }
207229
208230 static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
....@@ -226,6 +248,12 @@
226248 return data;
227249 }
228250
251
+static 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
+
229257 static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
230258 unsigned int addr, unsigned int data)
231259 {
....@@ -243,28 +271,38 @@
243271 spin_unlock_irqrestore(&reg_lock, flags);
244272 }
245273
274
+static 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
+
246280 /* Helper to change specific bits in controller registers */
247281 static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
248282 unsigned int addr,
249283 unsigned int mask,
250284 unsigned int val)
251285 {
252
- unsigned int data = dw_hdmi_dwc_read(dw_hdmi, addr);
286
+ unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
253287
254288 data &= ~mask;
255289 data |= val;
256290
257
- dw_hdmi_dwc_write(dw_hdmi, addr, data);
291
+ dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
258292 }
259293
260294 /* Bridge */
261295
262296 /* Setup PHY bandwidth modes */
263297 static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
264
- struct drm_display_mode *mode)
298
+ const struct drm_display_mode *mode)
265299 {
266300 struct meson_drm *priv = dw_hdmi->priv;
267301 unsigned int pixel_clock = mode->clock;
302
+
303
+ /* For 420, pixel clock is half unlike venc clock */
304
+ if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
305
+ pixel_clock /= 2;
268306
269307 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
270308 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
....@@ -300,6 +338,24 @@
300338 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
301339 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
302340 }
341
+ } else if (dw_hdmi_is_compatible(dw_hdmi,
342
+ "amlogic,meson-g12a-dw-hdmi")) {
343
+ if (pixel_clock >= 371250) {
344
+ /* 5.94Gbps, 3.7125Gbps */
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
+ /* 2.97Gbps */
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
+ /* 1.485Gbps, and below */
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
+ }
303359 }
304360 }
305361
....@@ -319,29 +375,40 @@
319375 }
320376
321377 static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
322
- struct drm_display_mode *mode)
378
+ const struct drm_display_mode *mode)
323379 {
324380 struct meson_drm *priv = dw_hdmi->priv;
325381 int vic = drm_match_cea_mode(mode);
382
+ unsigned int phy_freq;
326383 unsigned int vclk_freq;
327384 unsigned int venc_freq;
328385 unsigned int hdmi_freq;
329386
330387 vclk_freq = mode->clock;
331388
389
+ /* For 420, pixel clock is half unlike venc clock */
390
+ if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
391
+ vclk_freq /= 2;
392
+
393
+ /* TMDS clock is pixel_clock * 10 */
394
+ phy_freq = vclk_freq * 10;
395
+
332396 if (!vic) {
333
- meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, vclk_freq,
334
- vclk_freq, vclk_freq, false);
397
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
398
+ vclk_freq, vclk_freq, vclk_freq, false);
335399 return;
336400 }
337401
402
+ /* 480i/576i needs global pixel doubling */
338403 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
339404 vclk_freq *= 2;
340405
341406 venc_freq = vclk_freq;
342407 hdmi_freq = vclk_freq;
343408
344
- if (meson_venc_hdmi_venc_repeat(vic))
409
+ /* VENC double pixels for 1080i, 720p and YUV420 modes */
410
+ if (meson_venc_hdmi_venc_repeat(vic) ||
411
+ dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
345412 venc_freq *= 2;
346413
347414 vclk_freq = max(venc_freq, hdmi_freq);
....@@ -349,23 +416,25 @@
349416 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
350417 venc_freq /= 2;
351418
352
- DRM_DEBUG_DRIVER("vclk:%d venc=%d hdmi=%d enci=%d\n",
353
- vclk_freq, venc_freq, hdmi_freq,
419
+ DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
420
+ phy_freq, vclk_freq, venc_freq, hdmi_freq,
354421 priv->venc.hdmi_use_enci);
355422
356
- meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, vclk_freq,
423
+ meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
357424 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
358425 }
359426
360427 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
361
- struct drm_display_mode *mode)
428
+ const struct drm_display_info *display,
429
+ const struct drm_display_mode *mode)
362430 {
363431 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
364432 struct meson_drm *priv = dw_hdmi->priv;
365433 unsigned int wr_clk =
366434 readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
367435
368
- DRM_DEBUG_DRIVER("%d:\"%s\"\n", mode->base.id, mode->name);
436
+ DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
437
+ mode->clock > 340000 ? 40 : 10);
369438
370439 /* Enable clocks */
371440 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
....@@ -374,25 +443,37 @@
374443 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
375444
376445 /* Bring out of reset */
377
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
446
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0);
378447
379448 /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
380449 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
381450 0x3, 0x3);
451
+
452
+ /* Enable cec_clk and hdcp22_tmdsclk_en */
382453 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
383454 0x3 << 4, 0x3 << 4);
384455
385456 /* Enable normal output to PHY */
386
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
457
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
387458
388
- /* TMDS pattern setup (TOFIX pattern for 4k2k scrambling) */
389
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 0x001f001f);
390
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 0x001f001f);
459
+ /* TMDS pattern setup */
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
+ }
391472
392473 /* Load TMDS pattern */
393
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
474
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
394475 msleep(20);
395
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
476
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
396477
397478 /* Setup PHY parameters */
398479 meson_hdmi_phy_setup_mode(dw_hdmi, mode);
....@@ -403,7 +484,8 @@
403484
404485 /* BIT_INVERT */
405486 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
406
- dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-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"))
407489 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
408490 BIT(17), 0);
409491 else
....@@ -412,6 +494,8 @@
412494
413495 /* Disable clock, fifo, fifo_wr */
414496 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
497
+
498
+ dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
415499
416500 msleep(100);
417501
....@@ -469,7 +553,7 @@
469553 {
470554 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
471555
472
- return !!dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
556
+ return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
473557 connector_status_connected : connector_status_disconnected;
474558 }
475559
....@@ -479,11 +563,11 @@
479563 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
480564
481565 /* Setup HPD Filter */
482
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
566
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
483567 (0xa << 12) | 0xa0);
484568
485569 /* Clear interrupts */
486
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
570
+ dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
487571 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
488572
489573 /* Unmask interrupts */
....@@ -504,8 +588,8 @@
504588 struct meson_dw_hdmi *dw_hdmi = dev_id;
505589 u32 stat;
506590
507
- stat = dw_hdmi_top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
508
- dw_hdmi_top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
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);
509593
510594 /* HPD Events, handle in the threaded interrupt handler */
511595 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
....@@ -545,22 +629,28 @@
545629 }
546630
547631 static enum drm_mode_status
548
-dw_hdmi_mode_valid(struct drm_connector *connector,
632
+dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
633
+ const struct drm_display_info *display_info,
549634 const struct drm_display_mode *mode)
550635 {
551
- struct meson_drm *priv = connector->dev->dev_private;
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;
552640 unsigned int vclk_freq;
553641 unsigned int venc_freq;
554642 unsigned int hdmi_freq;
555643 int vic = drm_match_cea_mode(mode);
556644 enum drm_mode_status status;
557645
558
- DRM_DEBUG_DRIVER("Modeline %d:\"%s\" %d %d %d %d %d %d %d %d %d %d 0x%x 0x%x\n",
559
- mode->base.id, mode->name, mode->vrefresh, mode->clock,
560
- mode->hdisplay, mode->hsync_start,
561
- mode->hsync_end, mode->htotal,
562
- mode->vdisplay, mode->vsync_start,
563
- mode->vsync_end, mode->vtotal, mode->type, mode->flags);
646
+ DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
647
+
648
+ /* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
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;
564654
565655 /* Check against non-VIC supported modes */
566656 if (!vic) {
....@@ -575,6 +665,15 @@
575665
576666 vclk_freq = mode->clock;
577667
668
+ /* For 420, pixel clock is half unlike venc clock */
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
+ /* TMDS clock is pixel_clock * 10 */
675
+ phy_freq = vclk_freq * 10;
676
+
578677 /* 480i/576i needs global pixel doubling */
579678 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
580679 vclk_freq *= 2;
....@@ -582,8 +681,11 @@
582681 venc_freq = vclk_freq;
583682 hdmi_freq = vclk_freq;
584683
585
- /* VENC double pixels for 1080i and 720p modes */
586
- if (meson_venc_hdmi_venc_repeat(vic))
684
+ /* VENC double pixels for 1080i, 720p and YUV420 modes */
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)))
587689 venc_freq *= 2;
588690
589691 vclk_freq = max(venc_freq, hdmi_freq);
....@@ -591,23 +693,18 @@
591693 if (mode->flags & DRM_MODE_FLAG_DBLCLK)
592694 venc_freq /= 2;
593695
594
- dev_dbg(connector->dev->dev, "%s: vclk:%d venc=%d hdmi=%d\n", __func__,
595
- vclk_freq, venc_freq, hdmi_freq);
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);
596698
597
- /* Finally filter by configurable vclk frequencies for VIC modes */
598
- switch (vclk_freq) {
599
- case 54000:
600
- case 74250:
601
- case 148500:
602
- case 297000:
603
- case 594000:
604
- return MODE_OK;
605
- }
606
-
607
- return MODE_CLOCK_RANGE;
699
+ return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
608700 }
609701
610702 /* Encoder */
703
+
704
+static const u32 meson_dw_hdmi_out_bus_fmts[] = {
705
+ MEDIA_BUS_FMT_YUV8_1X24,
706
+ MEDIA_BUS_FMT_UYYVYY8_0_5X24,
707
+};
611708
612709 static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
613710 {
....@@ -618,16 +715,54 @@
618715 .destroy = meson_venc_hdmi_encoder_destroy,
619716 };
620717
621
-static int meson_venc_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
718
+static u32 *
719
+meson_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
+
749
+static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
750
+ struct drm_bridge_state *bridge_state,
622751 struct drm_crtc_state *crtc_state,
623752 struct drm_connector_state *conn_state)
624753 {
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
+
625760 return 0;
626761 }
627762
628
-static void meson_venc_hdmi_encoder_disable(struct drm_encoder *encoder)
763
+static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
629764 {
630
- struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
765
+ struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
631766 struct meson_drm *priv = dw_hdmi->priv;
632767
633768 DRM_DEBUG_DRIVER("\n");
....@@ -639,9 +774,9 @@
639774 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
640775 }
641776
642
-static void meson_venc_hdmi_encoder_enable(struct drm_encoder *encoder)
777
+static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
643778 {
644
- struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
779
+ struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
645780 struct meson_drm *priv = dw_hdmi->priv;
646781
647782 DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
....@@ -652,33 +787,47 @@
652787 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
653788 }
654789
655
-static void meson_venc_hdmi_encoder_mode_set(struct drm_encoder *encoder,
656
- struct drm_display_mode *mode,
657
- struct drm_display_mode *adjusted_mode)
790
+static 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)
658793 {
659
- struct meson_dw_hdmi *dw_hdmi = encoder_to_meson_dw_hdmi(encoder);
794
+ struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
660795 struct meson_drm *priv = dw_hdmi->priv;
661796 int vic = drm_match_cea_mode(mode);
797
+ unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
798
+ bool yuv420_mode = false;
662799
663
- DRM_DEBUG_DRIVER("%d:\"%s\" vic %d\n",
664
- mode->base.id, mode->name, vic);
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
+ }
665806
666807 /* VENC + VENC-DVI Mode setup */
667
- meson_venc_hdmi_mode_set(priv, vic, mode);
808
+ meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
668809
669810 /* VCLK Set clock */
670811 dw_hdmi_set_vclk(dw_hdmi, mode);
671812
672
- /* Setup YUV444 to HDMI-TX, no 10bit diphering */
673
- writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
813
+ if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
814
+ /* Setup YUV420 to HDMI-TX, no 10bit diphering */
815
+ writel_relaxed(2 | (2 << 2),
816
+ priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
817
+ else
818
+ /* Setup YUV444 to HDMI-TX, no 10bit diphering */
819
+ writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
674820 }
675821
676
-static const struct drm_encoder_helper_funcs
677
- meson_venc_hdmi_encoder_helper_funcs = {
678
- .atomic_check = meson_venc_hdmi_encoder_atomic_check,
679
- .disable = meson_venc_hdmi_encoder_disable,
680
- .enable = meson_venc_hdmi_encoder_enable,
681
- .mode_set = meson_venc_hdmi_encoder_mode_set,
822
+static 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,
682831 };
683832
684833 /* DW HDMI Regmap */
....@@ -686,7 +835,9 @@
686835 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
687836 unsigned int *result)
688837 {
689
- *result = dw_hdmi_dwc_read(context, reg);
838
+ struct meson_dw_hdmi *dw_hdmi = context;
839
+
840
+ *result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
690841
691842 return 0;
692843
....@@ -695,7 +846,9 @@
695846 static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
696847 unsigned int val)
697848 {
698
- dw_hdmi_dwc_write(context, reg, val);
849
+ struct meson_dw_hdmi *dw_hdmi = context;
850
+
851
+ dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
699852
700853 return 0;
701854 }
....@@ -707,6 +860,20 @@
707860 .reg_write = meson_dw_hdmi_reg_write,
708861 .max_register = 0x10000,
709862 .fast_io = true,
863
+};
864
+
865
+static 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
+
872
+static 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,
710877 };
711878
712879 static bool meson_hdmi_connector_is_available(struct device *dev)
....@@ -731,14 +898,85 @@
731898 return false;
732899 }
733900
901
+static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
902
+{
903
+ struct meson_drm *priv = meson_dw_hdmi->priv;
904
+
905
+ /* Enable clocks */
906
+ regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
907
+
908
+ /* Bring HDMITX MEM output of power down */
909
+ regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
910
+
911
+ /* Reset HDMITX APB & TX & PHY */
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
+ /* Enable APB3 fail on error */
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
+ /* Bring out of reset */
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
+ /* Enable HDMI-TX Interrupt */
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
+
942
+static void meson_disable_regulator(void *data)
943
+{
944
+ regulator_disable(data);
945
+}
946
+
947
+static void meson_disable_clk(void *data)
948
+{
949
+ clk_disable_unprepare(data);
950
+}
951
+
952
+static 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
+
734970 static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
735971 void *data)
736972 {
737973 struct platform_device *pdev = to_platform_device(dev);
974
+ const struct meson_dw_hdmi_data *match;
738975 struct meson_dw_hdmi *meson_dw_hdmi;
739976 struct drm_device *drm = data;
740977 struct meson_drm *priv = drm->dev_private;
741978 struct dw_hdmi_plat_data *dw_plat_data;
979
+ struct drm_bridge *next_bridge;
742980 struct drm_encoder *encoder;
743981 struct resource *res;
744982 int irq;
....@@ -751,6 +989,12 @@
751989 return -ENODEV;
752990 }
753991
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
+
754998 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
755999 GFP_KERNEL);
7561000 if (!meson_dw_hdmi)
....@@ -758,6 +1002,7 @@
7581002
7591003 meson_dw_hdmi->priv = priv;
7601004 meson_dw_hdmi->dev = dev;
1005
+ meson_dw_hdmi->data = match;
7611006 dw_plat_data = &meson_dw_hdmi->dw_plat_data;
7621007 encoder = &meson_dw_hdmi->encoder;
7631008
....@@ -768,6 +1013,10 @@
7681013 meson_dw_hdmi->hdmi_supply = NULL;
7691014 } else {
7701015 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);
7711020 if (ret)
7721021 return ret;
7731022 }
....@@ -798,19 +1047,17 @@
7981047 if (IS_ERR(meson_dw_hdmi->hdmitx))
7991048 return PTR_ERR(meson_dw_hdmi->hdmitx);
8001049
801
- meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
802
- if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
803
- dev_err(dev, "Unable to get HDMI pclk\n");
804
- return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
805
- }
806
- clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
1050
+ ret = meson_enable_clk(dev, "isfr");
1051
+ if (ret)
1052
+ return ret;
8071053
808
- meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
809
- if (IS_ERR(meson_dw_hdmi->venci_clk)) {
810
- dev_err(dev, "Unable to get venci clk\n");
811
- return PTR_ERR(meson_dw_hdmi->venci_clk);
812
- }
813
- clk_prepare_enable(meson_dw_hdmi->venci_clk);
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;
8141061
8151062 dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
8161063 &meson_dw_hdmi_regmap_config);
....@@ -818,10 +1065,8 @@
8181065 return PTR_ERR(dw_plat_data->regm);
8191066
8201067 irq = platform_get_irq(pdev, 0);
821
- if (irq < 0) {
822
- dev_err(dev, "Failed to get hdmi top irq\n");
1068
+ if (irq < 0)
8231069 return irq;
824
- }
8251070
8261071 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
8271072 dw_hdmi_top_thread_irq, IRQF_SHARED,
....@@ -833,8 +1078,6 @@
8331078
8341079 /* Encoder */
8351080
836
- drm_encoder_helper_add(encoder, &meson_venc_hdmi_encoder_helper_funcs);
837
-
8381081 ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
8391082 DRM_MODE_ENCODER_TMDS, "meson_hdmi");
8401083 if (ret) {
....@@ -842,56 +1085,41 @@
8421085 return ret;
8431086 }
8441087
1088
+ meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1089
+ drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1090
+
8451091 encoder->possible_crtcs = BIT(0);
1092
+
1093
+ meson_dw_hdmi_init(meson_dw_hdmi);
8461094
8471095 DRM_DEBUG_DRIVER("encoder initialized\n");
8481096
849
- /* Enable clocks */
850
- regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
851
-
852
- /* Bring HDMITX MEM output of power down */
853
- regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
854
-
855
- /* Reset HDMITX APB & TX & PHY */
856
- reset_control_reset(meson_dw_hdmi->hdmitx_apb);
857
- reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
858
- reset_control_reset(meson_dw_hdmi->hdmitx_phy);
859
-
860
- /* Enable APB3 fail on error */
861
- writel_bits_relaxed(BIT(15), BIT(15),
862
- meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
863
- writel_bits_relaxed(BIT(15), BIT(15),
864
- meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
865
-
866
- /* Bring out of reset */
867
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_SW_RESET, 0);
868
-
869
- msleep(20);
870
-
871
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_CLK_CNTL, 0xff);
872
-
873
- /* Enable HDMI-TX Interrupt */
874
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
875
- HDMITX_TOP_INTR_CORE);
876
-
877
- dw_hdmi_top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
878
- HDMITX_TOP_INTR_CORE);
879
-
8801097 /* Bridge / Connector */
8811098
1099
+ dw_plat_data->priv_data = meson_dw_hdmi;
8821100 dw_plat_data->mode_valid = dw_hdmi_mode_valid;
8831101 dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
8841102 dw_plat_data->phy_name = "meson_dw_hdmi_phy";
8851103 dw_plat_data->phy_data = meson_dw_hdmi;
886
- dw_plat_data->input_bus_format = MEDIA_BUS_FMT_YUV8_1X24;
8871104 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
1105
+ dw_plat_data->ycbcr_420_allowed = true;
1106
+
1107
+ if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
1108
+ dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
1109
+ dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
1110
+ dw_plat_data->use_drm_infoframe = true;
8881111
8891112 platform_set_drvdata(pdev, meson_dw_hdmi);
8901113
891
- meson_dw_hdmi->hdmi = dw_hdmi_bind(pdev, encoder,
892
- &meson_dw_hdmi->dw_plat_data);
1114
+ meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1115
+ &meson_dw_hdmi->dw_plat_data);
8931116 if (IS_ERR(meson_dw_hdmi->hdmi))
8941117 return PTR_ERR(meson_dw_hdmi->hdmi);
1118
+
1119
+ next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1120
+ if (next_bridge)
1121
+ drm_bridge_attach(encoder, next_bridge,
1122
+ &meson_dw_hdmi->bridge, 0);
8951123
8961124 DRM_DEBUG_DRIVER("HDMI controller initialized\n");
8971125
....@@ -911,6 +1139,34 @@
9111139 .unbind = meson_dw_hdmi_unbind,
9121140 };
9131141
1142
+static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
1143
+{
1144
+ struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1145
+
1146
+ if (!meson_dw_hdmi)
1147
+ return 0;
1148
+
1149
+ /* Reset TOP */
1150
+ meson_dw_hdmi->data->top_write(meson_dw_hdmi,
1151
+ HDMITX_TOP_SW_RESET, 0);
1152
+
1153
+ return 0;
1154
+}
1155
+
1156
+static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
1157
+{
1158
+ struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1159
+
1160
+ if (!meson_dw_hdmi)
1161
+ return 0;
1162
+
1163
+ meson_dw_hdmi_init(meson_dw_hdmi);
1164
+
1165
+ dw_hdmi_resume(meson_dw_hdmi->hdmi);
1166
+
1167
+ return 0;
1168
+}
1169
+
9141170 static int meson_dw_hdmi_probe(struct platform_device *pdev)
9151171 {
9161172 return component_add(&pdev->dev, &meson_dw_hdmi_ops);
....@@ -923,10 +1179,20 @@
9231179 return 0;
9241180 }
9251181
1182
+static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
1183
+ SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
1184
+ meson_dw_hdmi_pm_resume)
1185
+};
1186
+
9261187 static const struct of_device_id meson_dw_hdmi_of_table[] = {
927
- { .compatible = "amlogic,meson-gxbb-dw-hdmi" },
928
- { .compatible = "amlogic,meson-gxl-dw-hdmi" },
929
- { .compatible = "amlogic,meson-gxm-dw-hdmi" },
1188
+ { .compatible = "amlogic,meson-gxbb-dw-hdmi",
1189
+ .data = &meson_dw_hdmi_gx_data },
1190
+ { .compatible = "amlogic,meson-gxl-dw-hdmi",
1191
+ .data = &meson_dw_hdmi_gx_data },
1192
+ { .compatible = "amlogic,meson-gxm-dw-hdmi",
1193
+ .data = &meson_dw_hdmi_gx_data },
1194
+ { .compatible = "amlogic,meson-g12a-dw-hdmi",
1195
+ .data = &meson_dw_hdmi_g12a_data },
9301196 { }
9311197 };
9321198 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
....@@ -937,6 +1203,7 @@
9371203 .driver = {
9381204 .name = DRIVER_NAME,
9391205 .of_match_table = meson_dw_hdmi_of_table,
1206
+ .pm = &meson_dw_hdmi_pm_ops,
9401207 },
9411208 };
9421209 module_platform_driver(meson_dw_hdmi_platform_driver);