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 116 static DEFINE_SPINLOCK(reg_lock); 117 118 enum meson_venc_source { 119 MESON_VENC_SOURCE_NONE = 0, 120 MESON_VENC_SOURCE_ENCI = 1, 121 MESON_VENC_SOURCE_ENCP = 2, 122 }; 123 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 137 struct 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 160 static 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 168 static 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(®_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(®_lock, flags); 185 186 return data; 187 } 188 189 static 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 195 static 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(®_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(®_lock, flags); 210 } 211 212 static 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 */ 219 static 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 232 static 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(®_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(®_lock, flags); 249 250 return data; 251 } 252 253 static 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 259 static 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(®_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(®_lock, flags); 274 } 275 276 static 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 */ 283 static 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 */ 299 static 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 364 static 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 379 static 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 429 static 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 542 static 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 553 static 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 562 static 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 581 static 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 588 static 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 */ 612 static 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 633 static enum drm_mode_status 634 dw_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 706 static const u32 meson_dw_hdmi_out_bus_fmts[] = { 707 MEDIA_BUS_FMT_YUV8_1X24, 708 MEDIA_BUS_FMT_UYYVYY8_0_5X24, 709 }; 710 711 static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder) 712 { 713 drm_encoder_cleanup(encoder); 714 } 715 716 static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = { 717 .destroy = meson_venc_hdmi_encoder_destroy, 718 }; 719 720 static u32 * 721 meson_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 751 static 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 765 static 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 779 static 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 792 static 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 824 static 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 837 static 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 848 static 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 858 static 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 867 static 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 874 static 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 881 static 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 903 static 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 944 static 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 1101 static 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 1109 static const struct component_ops meson_dw_hdmi_ops = { 1110 .bind = meson_dw_hdmi_bind, 1111 .unbind = meson_dw_hdmi_unbind, 1112 }; 1113 1114 static 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 1128 static 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 1142 static int meson_dw_hdmi_probe(struct platform_device *pdev) 1143 { 1144 return component_add(&pdev->dev, &meson_dw_hdmi_ops); 1145 } 1146 1147 static 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 1154 static 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 1159 static 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 }; 1170 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table); 1171 1172 static 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 }; 1181 module_platform_driver(meson_dw_hdmi_platform_driver); 1182 1183 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 1184 MODULE_DESCRIPTION(DRIVER_DESC); 1185 MODULE_LICENSE("GPL"); 1186