Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3 * Copyright (C) 2016 BayLibre, SAS
   4 * Author: Neil Armstrong <narmstrong@baylibre.com>
   5 * Copyright (C) 2015 Amlogic, Inc. All rights reserved.
   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 * DOC: HDMI Output
  39 *
  40 * HDMI Output is composed of :
  41 *
  42 * - A Synopsys DesignWare HDMI Controller IP
  43 * - A TOP control block controlling the Clocks and PHY
  44 * - A custom HDMI PHY in order convert video to TMDS signal
  45 *
  46 * .. code::
  47 *
  48 *    ___________________________________
  49 *   |            HDMI TOP               |<= HPD
  50 *   |___________________________________|
  51 *   |                  |                |
  52 *   |  Synopsys HDMI   |   HDMI PHY     |=> TMDS
  53 *   |    Controller    |________________|
  54 *   |___________________________________|<=> DDC
  55 *
  56 *
  57 * The HDMI TOP block only supports HPD sensing.
  58 * The Synopsys HDMI Controller interrupt is routed
  59 * through the TOP Block interrupt.
  60 * Communication to the TOP Block and the Synopsys
  61 * HDMI Controller is done a pair of addr+read/write
  62 * registers.
  63 * The HDMI PHY is configured by registers in the
  64 * HHI register block.
  65 *
  66 * Pixel data arrives in 4:4:4 format from the VENC
  67 * block and the VPU HDMI mux selects either the ENCI
  68 * encoder for the 576i or 480i formats or the ENCP
  69 * encoder for all the other formats including
  70 * interlaced HD formats.
  71 * The VENC uses a DVI encoder on top of the ENCI
  72 * or ENCP encoders to generate DVI timings for the
  73 * HDMI controller.
  74 *
  75 * GXBB, GXL and GXM embeds the Synopsys DesignWare
  76 * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF
  77 * audio source interfaces.
  78 *
  79 * We handle the following features :
  80 *
  81 * - HPD Rise & Fall interrupt
  82 * - HDMI Controller Interrupt
  83 * - HDMI PHY Init for 480i to 1080p60
  84 * - VENC & HDMI Clock setup for 480i to 1080p60
  85 * - VENC Mode setup for 480i to 1080p60
  86 *
  87 * What is missing :
  88 *
  89 * - PHY, Clock and Mode setup for 2k && 4k modes
  90 * - SDDC Scrambling mode for HDMI 2.0a
  91 * - HDCP Setup
  92 * - CEC Management
  93 */
  94
  95/* TOP Block Communication Channel */
  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/* Controller Communication Channel */
 102#define HDMITX_DWC_ADDR_REG	0x10
 103#define HDMITX_DWC_DATA_REG	0x14
 104#define HDMITX_DWC_CTRL_REG	0x18
 105
 106/* HHI Registers */
 107#define HHI_MEM_PD_REG0		0x100 /* 0x40 */
 108#define HHI_HDMI_CLK_CNTL	0x1cc /* 0x73 */
 109#define HHI_HDMI_PHY_CNTL0	0x3a0 /* 0xe8 */
 110#define HHI_HDMI_PHY_CNTL1	0x3a4 /* 0xe9 */
 111#define HHI_HDMI_PHY_CNTL2	0x3a8 /* 0xea */
 112#define HHI_HDMI_PHY_CNTL3	0x3ac /* 0xeb */
 113#define HHI_HDMI_PHY_CNTL4	0x3b0 /* 0xec */
 114#define HHI_HDMI_PHY_CNTL5	0x3b4 /* 0xed */
 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 clk *hdmi_pclk;
 149	struct clk *venci_clk;
 150	struct regulator *hdmi_supply;
 151	u32 irq_stat;
 152	struct dw_hdmi *hdmi;
 153	unsigned long output_bus_fmt;
 154};
 155#define encoder_to_meson_dw_hdmi(x) \
 156	container_of(x, struct meson_dw_hdmi, encoder)
 157#define bridge_to_meson_dw_hdmi(x) \
 158	container_of(x, struct meson_dw_hdmi, bridge)
 159
 160static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi,
 161					const char *compat)
 162{
 163	return of_device_is_compatible(dw_hdmi->dev->of_node, compat);
 164}
 165
 166/* PHY (via TOP bridge) and Controller dedicated register interface */
 167
 168static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi,
 169				     unsigned int addr)
 170{
 171	unsigned long flags;
 172	unsigned int data;
 173
 174	spin_lock_irqsave(&reg_lock, flags);
 175
 176	/* ADDR must be written twice */
 177	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
 178	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
 179
 180	/* Read needs a second DATA read */
 181	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
 182	data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
 183
 184	spin_unlock_irqrestore(&reg_lock, flags);
 185
 186	return data;
 187}
 188
 189static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi,
 190					  unsigned int addr)
 191{
 192	return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
 193}
 194
 195static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi,
 196				     unsigned int addr, unsigned int data)
 197{
 198	unsigned long flags;
 199
 200	spin_lock_irqsave(&reg_lock, flags);
 201
 202	/* ADDR must be written twice */
 203	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
 204	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG);
 205
 206	/* Write needs single DATA write */
 207	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG);
 208
 209	spin_unlock_irqrestore(&reg_lock, flags);
 210}
 211
 212static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi,
 213					  unsigned int addr, unsigned int data)
 214{
 215	writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2));
 216}
 217
 218/* Helper to change specific bits in PHY registers */
 219static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi,
 220					  unsigned int addr,
 221					  unsigned int mask,
 222					  unsigned int val)
 223{
 224	unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr);
 225
 226	data &= ~mask;
 227	data |= val;
 228
 229	dw_hdmi->data->top_write(dw_hdmi, addr, data);
 230}
 231
 232static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi,
 233				     unsigned int addr)
 234{
 235	unsigned long flags;
 236	unsigned int data;
 237
 238	spin_lock_irqsave(&reg_lock, flags);
 239
 240	/* ADDR must be written twice */
 241	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
 242	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
 243
 244	/* Read needs a second DATA read */
 245	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
 246	data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
 247
 248	spin_unlock_irqrestore(&reg_lock, flags);
 249
 250	return data;
 251}
 252
 253static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi,
 254					  unsigned int addr)
 255{
 256	return readb(dw_hdmi->hdmitx + addr);
 257}
 258
 259static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi,
 260				     unsigned int addr, unsigned int data)
 261{
 262	unsigned long flags;
 263
 264	spin_lock_irqsave(&reg_lock, flags);
 265
 266	/* ADDR must be written twice */
 267	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
 268	writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG);
 269
 270	/* Write needs single DATA write */
 271	writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG);
 272
 273	spin_unlock_irqrestore(&reg_lock, flags);
 274}
 275
 276static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi,
 277					  unsigned int addr, unsigned int data)
 278{
 279	writeb(data, dw_hdmi->hdmitx + addr);
 280}
 281
 282/* Helper to change specific bits in controller registers */
 283static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi,
 284					  unsigned int addr,
 285					  unsigned int mask,
 286					  unsigned int val)
 287{
 288	unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr);
 289
 290	data &= ~mask;
 291	data |= val;
 292
 293	dw_hdmi->data->dwc_write(dw_hdmi, addr, data);
 294}
 295
 296/* Bridge */
 297
 298/* Setup PHY bandwidth modes */
 299static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi,
 300				      const struct drm_display_mode *mode)
 301{
 302	struct meson_drm *priv = dw_hdmi->priv;
 303	unsigned int pixel_clock = mode->clock;
 304
 305	/* For 420, pixel clock is half unlike venc clock */
 306	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
 307		pixel_clock /= 2;
 308
 309	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
 310	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) {
 311		if (pixel_clock >= 371250) {
 312			/* 5.94Gbps, 3.7125Gbps */
 313			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282);
 314			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b);
 315		} else if (pixel_clock >= 297000) {
 316			/* 2.97Gbps */
 317			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382);
 318			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b);
 319		} else if (pixel_clock >= 148500) {
 320			/* 1.485Gbps */
 321			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362);
 322			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b);
 323		} else {
 324			/* 742.5Mbps, and below */
 325			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142);
 326			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b);
 327		}
 328	} else if (dw_hdmi_is_compatible(dw_hdmi,
 329					 "amlogic,meson-gxbb-dw-hdmi")) {
 330		if (pixel_clock >= 371250) {
 331			/* 5.94Gbps, 3.7125Gbps */
 332			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245);
 333			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b);
 334		} else if (pixel_clock >= 297000) {
 335			/* 2.97Gbps */
 336			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283);
 337			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b);
 338		} else {
 339			/* 1.485Gbps, and below */
 340			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122);
 341			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b);
 342		}
 343	} else if (dw_hdmi_is_compatible(dw_hdmi,
 344					 "amlogic,meson-g12a-dw-hdmi")) {
 345		if (pixel_clock >= 371250) {
 346			/* 5.94Gbps, 3.7125Gbps */
 347			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4);
 348			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 349			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b);
 350		} else if (pixel_clock >= 297000) {
 351			/* 2.97Gbps */
 352			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262);
 353			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 354			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
 355		} else {
 356			/* 1.485Gbps, and below */
 357			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242);
 358			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b);
 359			regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003);
 360		}
 361	}
 362}
 363
 364static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi)
 365{
 366	struct meson_drm *priv = dw_hdmi->priv;
 367
 368	/* Enable and software reset */
 369	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf);
 370
 371	mdelay(2);
 372
 373	/* Enable and unreset */
 374	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe);
 375
 376	mdelay(2);
 377}
 378
 379static void dw_hdmi_set_vclk(struct meson_dw_hdmi *dw_hdmi,
 380			     const struct drm_display_mode *mode)
 381{
 382	struct meson_drm *priv = dw_hdmi->priv;
 383	int vic = drm_match_cea_mode(mode);
 384	unsigned int phy_freq;
 385	unsigned int vclk_freq;
 386	unsigned int venc_freq;
 387	unsigned int hdmi_freq;
 388
 389	vclk_freq = mode->clock;
 390
 391	/* For 420, pixel clock is half unlike venc clock */
 392	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
 393		vclk_freq /= 2;
 394
 395	/* TMDS clock is pixel_clock * 10 */
 396	phy_freq = vclk_freq * 10;
 397
 398	if (!vic) {
 399		meson_vclk_setup(priv, MESON_VCLK_TARGET_DMT, phy_freq,
 400				 vclk_freq, vclk_freq, vclk_freq, false);
 401		return;
 402	}
 403
 404	/* 480i/576i needs global pixel doubling */
 405	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 406		vclk_freq *= 2;
 407
 408	venc_freq = vclk_freq;
 409	hdmi_freq = vclk_freq;
 410
 411	/* VENC double pixels for 1080i, 720p and YUV420 modes */
 412	if (meson_venc_hdmi_venc_repeat(vic) ||
 413	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
 414		venc_freq *= 2;
 415
 416	vclk_freq = max(venc_freq, hdmi_freq);
 417
 418	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 419		venc_freq /= 2;
 420
 421	DRM_DEBUG_DRIVER("vclk:%d phy=%d venc=%d hdmi=%d enci=%d\n",
 422		phy_freq, vclk_freq, venc_freq, hdmi_freq,
 423		priv->venc.hdmi_use_enci);
 424
 425	meson_vclk_setup(priv, MESON_VCLK_TARGET_HDMI, phy_freq, vclk_freq,
 426			 venc_freq, hdmi_freq, priv->venc.hdmi_use_enci);
 427}
 428
 429static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data,
 430			    const struct drm_display_info *display,
 431			    const struct drm_display_mode *mode)
 432{
 433	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
 434	struct meson_drm *priv = dw_hdmi->priv;
 435	unsigned int wr_clk =
 436		readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING));
 437
 438	DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name,
 439			 mode->clock > 340000 ? 40 : 10);
 440
 441	/* Enable clocks */
 442	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
 443
 444	/* Bring HDMITX MEM output of power down */
 445	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
 446
 447	/* Bring out of reset */
 448	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET,  0);
 449
 450	/* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */
 451	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
 452			       0x3, 0x3);
 453
 454	/* Enable cec_clk and hdcp22_tmdsclk_en */
 455	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL,
 456			       0x3 << 4, 0x3 << 4);
 457
 458	/* Enable normal output to PHY */
 459	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12));
 460
 461	/* TMDS pattern setup */
 462	if (mode->clock > 340000 &&
 463	    dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_YUV8_1X24) {
 464		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
 465				  0);
 466		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
 467				  0x03ff03ff);
 468	} else {
 469		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01,
 470				  0x001f001f);
 471		dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23,
 472				  0x001f001f);
 473	}
 474
 475	/* Load TMDS pattern */
 476	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1);
 477	msleep(20);
 478	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2);
 479
 480	/* Setup PHY parameters */
 481	meson_hdmi_phy_setup_mode(dw_hdmi, mode);
 482
 483	/* Setup PHY */
 484	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
 485			   0xffff << 16, 0x0390 << 16);
 486
 487	/* BIT_INVERT */
 488	if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
 489	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
 490	    dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
 491		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
 492				   BIT(17), 0);
 493	else
 494		regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1,
 495				   BIT(17), BIT(17));
 496
 497	/* Disable clock, fifo, fifo_wr */
 498	regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0);
 499
 500	dw_hdmi_set_high_tmds_clock_ratio(hdmi, display);
 501
 502	msleep(100);
 503
 504	/* Reset PHY 3 times in a row */
 505	meson_dw_hdmi_phy_reset(dw_hdmi);
 506	meson_dw_hdmi_phy_reset(dw_hdmi);
 507	meson_dw_hdmi_phy_reset(dw_hdmi);
 508
 509	/* Temporary Disable VENC video stream */
 510	if (priv->venc.hdmi_use_enci)
 511		writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
 512	else
 513		writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
 514
 515	/* Temporary Disable HDMI video stream to HDMI-TX */
 516	writel_bits_relaxed(0x3, 0,
 517			    priv->io_base + _REG(VPU_HDMI_SETTING));
 518	writel_bits_relaxed(0xf << 8, 0,
 519			    priv->io_base + _REG(VPU_HDMI_SETTING));
 520
 521	/* Re-Enable VENC video stream */
 522	if (priv->venc.hdmi_use_enci)
 523		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
 524	else
 525		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
 526
 527	/* Push back HDMI clock settings */
 528	writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8),
 529			    priv->io_base + _REG(VPU_HDMI_SETTING));
 530
 531	/* Enable and Select HDMI video source for HDMI-TX */
 532	if (priv->venc.hdmi_use_enci)
 533		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI,
 534				    priv->io_base + _REG(VPU_HDMI_SETTING));
 535	else
 536		writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP,
 537				    priv->io_base + _REG(VPU_HDMI_SETTING));
 538
 539	return 0;
 540}
 541
 542static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi,
 543				void *data)
 544{
 545	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
 546	struct meson_drm *priv = dw_hdmi->priv;
 547
 548	DRM_DEBUG_DRIVER("\n");
 549
 550	regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0);
 551}
 552
 553static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi,
 554			     void *data)
 555{
 556	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
 557
 558	return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ?
 559		connector_status_connected : connector_status_disconnected;
 560}
 561
 562static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi,
 563			      void *data)
 564{
 565	struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data;
 566
 567	/* Setup HPD Filter */
 568	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER,
 569			  (0xa << 12) | 0xa0);
 570
 571	/* Clear interrupts */
 572	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
 573			  HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
 574
 575	/* Unmask interrupts */
 576	dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN,
 577			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL,
 578			HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL);
 579}
 580
 581static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = {
 582	.init = dw_hdmi_phy_init,
 583	.disable = dw_hdmi_phy_disable,
 584	.read_hpd = dw_hdmi_read_hpd,
 585	.setup_hpd = dw_hdmi_setup_hpd,
 586};
 587
 588static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id)
 589{
 590	struct meson_dw_hdmi *dw_hdmi = dev_id;
 591	u32 stat;
 592
 593	stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT);
 594	dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat);
 595
 596	/* HPD Events, handle in the threaded interrupt handler */
 597	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
 598		dw_hdmi->irq_stat = stat;
 599		return IRQ_WAKE_THREAD;
 600	}
 601
 602	/* HDMI Controller Interrupt */
 603	if (stat & 1)
 604		return IRQ_NONE;
 605
 606	/* TOFIX Handle HDCP Interrupts */
 607
 608	return IRQ_HANDLED;
 609}
 610
 611/* Threaded interrupt handler to manage HPD events */
 612static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id)
 613{
 614	struct meson_dw_hdmi *dw_hdmi = dev_id;
 615	u32 stat = dw_hdmi->irq_stat;
 616
 617	/* HPD Events */
 618	if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) {
 619		bool hpd_connected = false;
 620
 621		if (stat & HDMITX_TOP_INTR_HPD_RISE)
 622			hpd_connected = true;
 623
 624		dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected,
 625				       hpd_connected);
 626
 627		drm_helper_hpd_irq_event(dw_hdmi->encoder.dev);
 628	}
 629
 630	return IRQ_HANDLED;
 631}
 632
 633static enum drm_mode_status
 634dw_hdmi_mode_valid(struct dw_hdmi *hdmi, void *data,
 635		   const struct drm_display_info *display_info,
 636		   const struct drm_display_mode *mode)
 637{
 638	struct meson_dw_hdmi *dw_hdmi = data;
 639	struct meson_drm *priv = dw_hdmi->priv;
 640	bool is_hdmi2_sink = display_info->hdmi.scdc.supported;
 641	unsigned int phy_freq;
 642	unsigned int vclk_freq;
 643	unsigned int venc_freq;
 644	unsigned int hdmi_freq;
 645	int vic = drm_match_cea_mode(mode);
 646	enum drm_mode_status status;
 647
 648	DRM_DEBUG_DRIVER("Modeline " DRM_MODE_FMT "\n", DRM_MODE_ARG(mode));
 649
 650	/* If sink does not support 540MHz, reject the non-420 HDMI2 modes */
 651	if (display_info->max_tmds_clock &&
 652	    mode->clock > display_info->max_tmds_clock &&
 653	    !drm_mode_is_420_only(display_info, mode) &&
 654	    !drm_mode_is_420_also(display_info, mode))
 655		return MODE_BAD;
 656
 657	/* Check against non-VIC supported modes */
 658	if (!vic) {
 659		status = meson_venc_hdmi_supported_mode(mode);
 660		if (status != MODE_OK)
 661			return status;
 662
 663		return meson_vclk_dmt_supported_freq(priv, mode->clock);
 664	/* Check against supported VIC modes */
 665	} else if (!meson_venc_hdmi_supported_vic(vic))
 666		return MODE_BAD;
 667
 668	vclk_freq = mode->clock;
 669
 670	/* For 420, pixel clock is half unlike venc clock */
 671	if (drm_mode_is_420_only(display_info, mode) ||
 672	    (!is_hdmi2_sink &&
 673	     drm_mode_is_420_also(display_info, mode)))
 674		vclk_freq /= 2;
 675
 676	/* TMDS clock is pixel_clock * 10 */
 677	phy_freq = vclk_freq * 10;
 678
 679	/* 480i/576i needs global pixel doubling */
 680	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 681		vclk_freq *= 2;
 682
 683	venc_freq = vclk_freq;
 684	hdmi_freq = vclk_freq;
 685
 686	/* VENC double pixels for 1080i, 720p and YUV420 modes */
 687	if (meson_venc_hdmi_venc_repeat(vic) ||
 688	    drm_mode_is_420_only(display_info, mode) ||
 689	    (!is_hdmi2_sink &&
 690	     drm_mode_is_420_also(display_info, mode)))
 691		venc_freq *= 2;
 692
 693	vclk_freq = max(venc_freq, hdmi_freq);
 694
 695	if (mode->flags & DRM_MODE_FLAG_DBLCLK)
 696		venc_freq /= 2;
 697
 698	dev_dbg(dw_hdmi->dev, "%s: vclk:%d phy=%d venc=%d hdmi=%d\n",
 699		__func__, phy_freq, vclk_freq, venc_freq, hdmi_freq);
 700
 701	return meson_vclk_vic_supported_freq(priv, phy_freq, vclk_freq);
 702}
 703
 704/* Encoder */
 705
 706static const u32 meson_dw_hdmi_out_bus_fmts[] = {
 707	MEDIA_BUS_FMT_YUV8_1X24,
 708	MEDIA_BUS_FMT_UYYVYY8_0_5X24,
 709};
 710
 711static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
 712{
 713	drm_encoder_cleanup(encoder);
 714}
 715
 716static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
 717	.destroy        = meson_venc_hdmi_encoder_destroy,
 718};
 719
 720static u32 *
 721meson_venc_hdmi_encoder_get_inp_bus_fmts(struct drm_bridge *bridge,
 722					struct drm_bridge_state *bridge_state,
 723					struct drm_crtc_state *crtc_state,
 724					struct drm_connector_state *conn_state,
 725					u32 output_fmt,
 726					unsigned int *num_input_fmts)
 727{
 728	u32 *input_fmts = NULL;
 729	int i;
 730
 731	*num_input_fmts = 0;
 732
 733	for (i = 0 ; i < ARRAY_SIZE(meson_dw_hdmi_out_bus_fmts) ; ++i) {
 734		if (output_fmt == meson_dw_hdmi_out_bus_fmts[i]) {
 735			*num_input_fmts = 1;
 736			input_fmts = kcalloc(*num_input_fmts,
 737					     sizeof(*input_fmts),
 738					     GFP_KERNEL);
 739			if (!input_fmts)
 740				return NULL;
 741
 742			input_fmts[0] = output_fmt;
 743
 744			break;
 745		}
 746	}
 747
 748	return input_fmts;
 749}
 750
 751static int meson_venc_hdmi_encoder_atomic_check(struct drm_bridge *bridge,
 752					struct drm_bridge_state *bridge_state,
 753					struct drm_crtc_state *crtc_state,
 754					struct drm_connector_state *conn_state)
 755{
 756	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
 757
 758	dw_hdmi->output_bus_fmt = bridge_state->output_bus_cfg.format;
 759
 760	DRM_DEBUG_DRIVER("output_bus_fmt %lx\n", dw_hdmi->output_bus_fmt);
 761
 762	return 0;
 763}
 764
 765static void meson_venc_hdmi_encoder_disable(struct drm_bridge *bridge)
 766{
 767	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
 768	struct meson_drm *priv = dw_hdmi->priv;
 769
 770	DRM_DEBUG_DRIVER("\n");
 771
 772	writel_bits_relaxed(0x3, 0,
 773			    priv->io_base + _REG(VPU_HDMI_SETTING));
 774
 775	writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN));
 776	writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN));
 777}
 778
 779static void meson_venc_hdmi_encoder_enable(struct drm_bridge *bridge)
 780{
 781	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
 782	struct meson_drm *priv = dw_hdmi->priv;
 783
 784	DRM_DEBUG_DRIVER("%s\n", priv->venc.hdmi_use_enci ? "VENCI" : "VENCP");
 785
 786	if (priv->venc.hdmi_use_enci)
 787		writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN));
 788	else
 789		writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN));
 790}
 791
 792static void meson_venc_hdmi_encoder_mode_set(struct drm_bridge *bridge,
 793				   const struct drm_display_mode *mode,
 794				   const struct drm_display_mode *adjusted_mode)
 795{
 796	struct meson_dw_hdmi *dw_hdmi = bridge_to_meson_dw_hdmi(bridge);
 797	struct meson_drm *priv = dw_hdmi->priv;
 798	int vic = drm_match_cea_mode(mode);
 799	unsigned int ycrcb_map = VPU_HDMI_OUTPUT_CBYCR;
 800	bool yuv420_mode = false;
 801
 802	DRM_DEBUG_DRIVER("\"%s\" vic %d\n", mode->name, vic);
 803
 804	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24) {
 805		ycrcb_map = VPU_HDMI_OUTPUT_CRYCB;
 806		yuv420_mode = true;
 807	}
 808
 809	/* VENC + VENC-DVI Mode setup */
 810	meson_venc_hdmi_mode_set(priv, vic, ycrcb_map, yuv420_mode, mode);
 811
 812	/* VCLK Set clock */
 813	dw_hdmi_set_vclk(dw_hdmi, mode);
 814
 815	if (dw_hdmi->output_bus_fmt == MEDIA_BUS_FMT_UYYVYY8_0_5X24)
 816		/* Setup YUV420 to HDMI-TX, no 10bit diphering */
 817		writel_relaxed(2 | (2 << 2),
 818			       priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
 819	else
 820		/* Setup YUV444 to HDMI-TX, no 10bit diphering */
 821		writel_relaxed(0, priv->io_base + _REG(VPU_HDMI_FMT_CTRL));
 822}
 823
 824static const struct drm_bridge_funcs meson_venc_hdmi_encoder_bridge_funcs = {
 825	.atomic_duplicate_state = drm_atomic_helper_bridge_duplicate_state,
 826	.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
 827	.atomic_get_input_bus_fmts = meson_venc_hdmi_encoder_get_inp_bus_fmts,
 828	.atomic_reset = drm_atomic_helper_bridge_reset,
 829	.atomic_check = meson_venc_hdmi_encoder_atomic_check,
 830	.enable	= meson_venc_hdmi_encoder_enable,
 831	.disable = meson_venc_hdmi_encoder_disable,
 832	.mode_set = meson_venc_hdmi_encoder_mode_set,
 833};
 834
 835/* DW HDMI Regmap */
 836
 837static int meson_dw_hdmi_reg_read(void *context, unsigned int reg,
 838				  unsigned int *result)
 839{
 840	struct meson_dw_hdmi *dw_hdmi = context;
 841
 842	*result = dw_hdmi->data->dwc_read(dw_hdmi, reg);
 843
 844	return 0;
 845
 846}
 847
 848static int meson_dw_hdmi_reg_write(void *context, unsigned int reg,
 849				   unsigned int val)
 850{
 851	struct meson_dw_hdmi *dw_hdmi = context;
 852
 853	dw_hdmi->data->dwc_write(dw_hdmi, reg, val);
 854
 855	return 0;
 856}
 857
 858static const struct regmap_config meson_dw_hdmi_regmap_config = {
 859	.reg_bits = 32,
 860	.val_bits = 8,
 861	.reg_read = meson_dw_hdmi_reg_read,
 862	.reg_write = meson_dw_hdmi_reg_write,
 863	.max_register = 0x10000,
 864	.fast_io = true,
 865};
 866
 867static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = {
 868	.top_read = dw_hdmi_top_read,
 869	.top_write = dw_hdmi_top_write,
 870	.dwc_read = dw_hdmi_dwc_read,
 871	.dwc_write = dw_hdmi_dwc_write,
 872};
 873
 874static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = {
 875	.top_read = dw_hdmi_g12a_top_read,
 876	.top_write = dw_hdmi_g12a_top_write,
 877	.dwc_read = dw_hdmi_g12a_dwc_read,
 878	.dwc_write = dw_hdmi_g12a_dwc_write,
 879};
 880
 881static bool meson_hdmi_connector_is_available(struct device *dev)
 882{
 883	struct device_node *ep, *remote;
 884
 885	/* HDMI Connector is on the second port, first endpoint */
 886	ep = of_graph_get_endpoint_by_regs(dev->of_node, 1, 0);
 887	if (!ep)
 888		return false;
 889
 890	/* If the endpoint node exists, consider it enabled */
 891	remote = of_graph_get_remote_port(ep);
 892	if (remote) {
 893		of_node_put(ep);
 894		return true;
 895	}
 896
 897	of_node_put(ep);
 898	of_node_put(remote);
 899
 900	return false;
 901}
 902
 903static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi)
 904{
 905	struct meson_drm *priv = meson_dw_hdmi->priv;
 906
 907	/* Enable clocks */
 908	regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100);
 909
 910	/* Bring HDMITX MEM output of power down */
 911	regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0);
 912
 913	/* Reset HDMITX APB & TX & PHY */
 914	reset_control_reset(meson_dw_hdmi->hdmitx_apb);
 915	reset_control_reset(meson_dw_hdmi->hdmitx_ctrl);
 916	reset_control_reset(meson_dw_hdmi->hdmitx_phy);
 917
 918	/* Enable APB3 fail on error */
 919	if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) {
 920		writel_bits_relaxed(BIT(15), BIT(15),
 921				    meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG);
 922		writel_bits_relaxed(BIT(15), BIT(15),
 923				    meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG);
 924	}
 925
 926	/* Bring out of reset */
 927	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
 928				       HDMITX_TOP_SW_RESET,  0);
 929
 930	msleep(20);
 931
 932	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
 933				       HDMITX_TOP_CLK_CNTL, 0xff);
 934
 935	/* Enable HDMI-TX Interrupt */
 936	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR,
 937				       HDMITX_TOP_INTR_CORE);
 938
 939	meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN,
 940				       HDMITX_TOP_INTR_CORE);
 941
 942}
 943
 944static int meson_dw_hdmi_bind(struct device *dev, struct device *master,
 945				void *data)
 946{
 947	struct platform_device *pdev = to_platform_device(dev);
 948	const struct meson_dw_hdmi_data *match;
 949	struct meson_dw_hdmi *meson_dw_hdmi;
 950	struct drm_device *drm = data;
 951	struct meson_drm *priv = drm->dev_private;
 952	struct dw_hdmi_plat_data *dw_plat_data;
 953	struct drm_bridge *next_bridge;
 954	struct drm_encoder *encoder;
 955	struct resource *res;
 956	int irq;
 957	int ret;
 958
 959	DRM_DEBUG_DRIVER("\n");
 960
 961	if (!meson_hdmi_connector_is_available(dev)) {
 962		dev_info(drm->dev, "HDMI Output connector not available\n");
 963		return -ENODEV;
 964	}
 965
 966	match = of_device_get_match_data(&pdev->dev);
 967	if (!match) {
 968		dev_err(&pdev->dev, "failed to get match data\n");
 969		return -ENODEV;
 970	}
 971
 972	meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi),
 973				     GFP_KERNEL);
 974	if (!meson_dw_hdmi)
 975		return -ENOMEM;
 976
 977	meson_dw_hdmi->priv = priv;
 978	meson_dw_hdmi->dev = dev;
 979	meson_dw_hdmi->data = match;
 980	dw_plat_data = &meson_dw_hdmi->dw_plat_data;
 981	encoder = &meson_dw_hdmi->encoder;
 982
 983	meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi");
 984	if (IS_ERR(meson_dw_hdmi->hdmi_supply)) {
 985		if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER)
 986			return -EPROBE_DEFER;
 987		meson_dw_hdmi->hdmi_supply = NULL;
 988	} else {
 989		ret = regulator_enable(meson_dw_hdmi->hdmi_supply);
 990		if (ret)
 991			return ret;
 992	}
 993
 994	meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev,
 995						"hdmitx_apb");
 996	if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) {
 997		dev_err(dev, "Failed to get hdmitx_apb reset\n");
 998		return PTR_ERR(meson_dw_hdmi->hdmitx_apb);
 999	}
1000
1001	meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev,
1002						"hdmitx");
1003	if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) {
1004		dev_err(dev, "Failed to get hdmitx reset\n");
1005		return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl);
1006	}
1007
1008	meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev,
1009						"hdmitx_phy");
1010	if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) {
1011		dev_err(dev, "Failed to get hdmitx_phy reset\n");
1012		return PTR_ERR(meson_dw_hdmi->hdmitx_phy);
1013	}
1014
1015	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1016	meson_dw_hdmi->hdmitx = devm_ioremap_resource(dev, res);
1017	if (IS_ERR(meson_dw_hdmi->hdmitx))
1018		return PTR_ERR(meson_dw_hdmi->hdmitx);
1019
1020	meson_dw_hdmi->hdmi_pclk = devm_clk_get(dev, "isfr");
1021	if (IS_ERR(meson_dw_hdmi->hdmi_pclk)) {
1022		dev_err(dev, "Unable to get HDMI pclk\n");
1023		return PTR_ERR(meson_dw_hdmi->hdmi_pclk);
1024	}
1025	clk_prepare_enable(meson_dw_hdmi->hdmi_pclk);
1026
1027	meson_dw_hdmi->venci_clk = devm_clk_get(dev, "venci");
1028	if (IS_ERR(meson_dw_hdmi->venci_clk)) {
1029		dev_err(dev, "Unable to get venci clk\n");
1030		return PTR_ERR(meson_dw_hdmi->venci_clk);
1031	}
1032	clk_prepare_enable(meson_dw_hdmi->venci_clk);
1033
1034	dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi,
1035					      &meson_dw_hdmi_regmap_config);
1036	if (IS_ERR(dw_plat_data->regm))
1037		return PTR_ERR(dw_plat_data->regm);
1038
1039	irq = platform_get_irq(pdev, 0);
1040	if (irq < 0)
1041		return irq;
1042
1043	ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq,
1044					dw_hdmi_top_thread_irq, IRQF_SHARED,
1045					"dw_hdmi_top_irq", meson_dw_hdmi);
1046	if (ret) {
1047		dev_err(dev, "Failed to request hdmi top irq\n");
1048		return ret;
1049	}
1050
1051	/* Encoder */
1052
1053	ret = drm_encoder_init(drm, encoder, &meson_venc_hdmi_encoder_funcs,
1054			       DRM_MODE_ENCODER_TMDS, "meson_hdmi");
1055	if (ret) {
1056		dev_err(priv->dev, "Failed to init HDMI encoder\n");
1057		return ret;
1058	}
1059
1060	meson_dw_hdmi->bridge.funcs = &meson_venc_hdmi_encoder_bridge_funcs;
1061	drm_bridge_attach(encoder, &meson_dw_hdmi->bridge, NULL, 0);
1062
1063	encoder->possible_crtcs = BIT(0);
1064
1065	DRM_DEBUG_DRIVER("encoder initialized\n");
1066
1067	meson_dw_hdmi_init(meson_dw_hdmi);
1068
1069	/* Bridge / Connector */
1070
1071	dw_plat_data->priv_data = meson_dw_hdmi;
1072	dw_plat_data->mode_valid = dw_hdmi_mode_valid;
1073	dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops;
1074	dw_plat_data->phy_name = "meson_dw_hdmi_phy";
1075	dw_plat_data->phy_data = meson_dw_hdmi;
1076	dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709;
1077	dw_plat_data->ycbcr_420_allowed = true;
1078
1079	if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") ||
1080	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") ||
1081	    dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi"))
1082		dw_plat_data->use_drm_infoframe = true;
1083
1084	platform_set_drvdata(pdev, meson_dw_hdmi);
1085
1086	meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev,
1087					    &meson_dw_hdmi->dw_plat_data);
1088	if (IS_ERR(meson_dw_hdmi->hdmi))
1089		return PTR_ERR(meson_dw_hdmi->hdmi);
1090
1091	next_bridge = of_drm_find_bridge(pdev->dev.of_node);
1092	if (next_bridge)
1093		drm_bridge_attach(encoder, next_bridge,
1094				  &meson_dw_hdmi->bridge, 0);
1095
1096	DRM_DEBUG_DRIVER("HDMI controller initialized\n");
1097
1098	return 0;
1099}
1100
1101static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
1102				   void *data)
1103{
1104	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1105
1106	dw_hdmi_unbind(meson_dw_hdmi->hdmi);
1107}
1108
1109static const struct component_ops meson_dw_hdmi_ops = {
1110	.bind	= meson_dw_hdmi_bind,
1111	.unbind	= meson_dw_hdmi_unbind,
1112};
1113
1114static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev)
1115{
1116	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1117
1118	if (!meson_dw_hdmi)
1119		return 0;
1120
1121	/* Reset TOP */
1122	meson_dw_hdmi->data->top_write(meson_dw_hdmi,
1123				       HDMITX_TOP_SW_RESET, 0);
1124
1125	return 0;
1126}
1127
1128static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev)
1129{
1130	struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev);
1131
1132	if (!meson_dw_hdmi)
1133		return 0;
1134
1135	meson_dw_hdmi_init(meson_dw_hdmi);
1136
1137	dw_hdmi_resume(meson_dw_hdmi->hdmi);
1138
1139	return 0;
1140}
1141
1142static int meson_dw_hdmi_probe(struct platform_device *pdev)
1143{
1144	return component_add(&pdev->dev, &meson_dw_hdmi_ops);
1145}
1146
1147static int meson_dw_hdmi_remove(struct platform_device *pdev)
1148{
1149	component_del(&pdev->dev, &meson_dw_hdmi_ops);
1150
1151	return 0;
1152}
1153
1154static const struct dev_pm_ops meson_dw_hdmi_pm_ops = {
1155	SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend,
1156				meson_dw_hdmi_pm_resume)
1157};
1158
1159static const struct of_device_id meson_dw_hdmi_of_table[] = {
1160	{ .compatible = "amlogic,meson-gxbb-dw-hdmi",
1161	  .data = &meson_dw_hdmi_gx_data },
1162	{ .compatible = "amlogic,meson-gxl-dw-hdmi",
1163	  .data = &meson_dw_hdmi_gx_data },
1164	{ .compatible = "amlogic,meson-gxm-dw-hdmi",
1165	  .data = &meson_dw_hdmi_gx_data },
1166	{ .compatible = "amlogic,meson-g12a-dw-hdmi",
1167	  .data = &meson_dw_hdmi_g12a_data },
1168	{ }
1169};
1170MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
1171
1172static struct platform_driver meson_dw_hdmi_platform_driver = {
1173	.probe		= meson_dw_hdmi_probe,
1174	.remove		= meson_dw_hdmi_remove,
1175	.driver		= {
1176		.name		= DRIVER_NAME,
1177		.of_match_table	= meson_dw_hdmi_of_table,
1178		.pm = &meson_dw_hdmi_pm_ops,
1179	},
1180};
1181module_platform_driver(meson_dw_hdmi_platform_driver);
1182
1183MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
1184MODULE_DESCRIPTION(DRIVER_DESC);
1185MODULE_LICENSE("GPL");