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.h> 13 #include <linux/of_graph.h> 14 #include <linux/platform_device.h> 15 #include <linux/regulator/consumer.h> 16 #include <linux/reset.h> 17 18 #include <drm/bridge/dw_hdmi.h> 19 #include <drm/drm_atomic_helper.h> 20 #include <drm/drm_bridge.h> 21 #include <drm/drm_device.h> 22 #include <drm/drm_edid.h> 23 #include <drm/drm_probe_helper.h> 24 #include <drm/drm_print.h> 25 26 #include <linux/videodev2.h> 27 28 #include "meson_drv.h" 29 #include "meson_dw_hdmi.h" 30 #include "meson_registers.h" 31 32 #define DRIVER_NAME "meson-dw-hdmi" 33 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver" 34 35 /** 36 * DOC: HDMI Output 37 * 38 * HDMI Output is composed of : 39 * 40 * - A Synopsys DesignWare HDMI Controller IP 41 * - A TOP control block controlling the Clocks and PHY 42 * - A custom HDMI PHY in order convert video to TMDS signal 43 * 44 * .. code:: 45 * 46 * ___________________________________ 47 * | HDMI TOP |<= HPD 48 * |___________________________________| 49 * | | | 50 * | Synopsys HDMI | HDMI PHY |=> TMDS 51 * | Controller |________________| 52 * |___________________________________|<=> DDC 53 * 54 * 55 * The HDMI TOP block only supports HPD sensing. 56 * The Synopsys HDMI Controller interrupt is routed 57 * through the TOP Block interrupt. 58 * Communication to the TOP Block and the Synopsys 59 * HDMI Controller is done a pair of addr+read/write 60 * registers. 61 * The HDMI PHY is configured by registers in the 62 * HHI register block. 63 * 64 * Pixel data arrives in 4:4:4 format from the VENC 65 * block and the VPU HDMI mux selects either the ENCI 66 * encoder for the 576i or 480i formats or the ENCP 67 * encoder for all the other formats including 68 * interlaced HD formats. 69 * The VENC uses a DVI encoder on top of the ENCI 70 * or ENCP encoders to generate DVI timings for the 71 * HDMI controller. 72 * 73 * GXBB, GXL and GXM embeds the Synopsys DesignWare 74 * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF 75 * audio source interfaces. 76 * 77 * We handle the following features : 78 * 79 * - HPD Rise & Fall interrupt 80 * - HDMI Controller Interrupt 81 * - HDMI PHY Init for 480i to 1080p60 82 * - VENC & HDMI Clock setup for 480i to 1080p60 83 * - VENC Mode setup for 480i to 1080p60 84 * 85 * What is missing : 86 * 87 * - PHY, Clock and Mode setup for 2k && 4k modes 88 * - SDDC Scrambling mode for HDMI 2.0a 89 * - HDCP Setup 90 * - CEC Management 91 */ 92 93 /* TOP Block Communication Channel */ 94 #define HDMITX_TOP_ADDR_REG 0x0 95 #define HDMITX_TOP_DATA_REG 0x4 96 #define HDMITX_TOP_CTRL_REG 0x8 97 #define HDMITX_TOP_G12A_OFFSET 0x8000 98 99 /* Controller Communication Channel */ 100 #define HDMITX_DWC_ADDR_REG 0x10 101 #define HDMITX_DWC_DATA_REG 0x14 102 #define HDMITX_DWC_CTRL_REG 0x18 103 104 /* HHI Registers */ 105 #define HHI_MEM_PD_REG0 0x100 /* 0x40 */ 106 #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 */ 107 #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 */ 108 #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */ 109 #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */ 110 #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */ 111 #define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */ 112 #define HHI_HDMI_PHY_CNTL5 0x3b4 /* 0xed */ 113 114 static DEFINE_SPINLOCK(reg_lock); 115 116 enum meson_venc_source { 117 MESON_VENC_SOURCE_NONE = 0, 118 MESON_VENC_SOURCE_ENCI = 1, 119 MESON_VENC_SOURCE_ENCP = 2, 120 }; 121 122 struct meson_dw_hdmi; 123 124 struct meson_dw_hdmi_data { 125 unsigned int (*top_read)(struct meson_dw_hdmi *dw_hdmi, 126 unsigned int addr); 127 void (*top_write)(struct meson_dw_hdmi *dw_hdmi, 128 unsigned int addr, unsigned int data); 129 unsigned int (*dwc_read)(struct meson_dw_hdmi *dw_hdmi, 130 unsigned int addr); 131 void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi, 132 unsigned int addr, unsigned int data); 133 }; 134 135 struct meson_dw_hdmi { 136 struct dw_hdmi_plat_data dw_plat_data; 137 struct meson_drm *priv; 138 struct device *dev; 139 void __iomem *hdmitx; 140 const struct meson_dw_hdmi_data *data; 141 struct reset_control *hdmitx_apb; 142 struct reset_control *hdmitx_ctrl; 143 struct reset_control *hdmitx_phy; 144 u32 irq_stat; 145 struct dw_hdmi *hdmi; 146 struct drm_bridge *bridge; 147 }; 148 149 static inline int dw_hdmi_is_compatible(struct meson_dw_hdmi *dw_hdmi, 150 const char *compat) 151 { 152 return of_device_is_compatible(dw_hdmi->dev->of_node, compat); 153 } 154 155 /* PHY (via TOP bridge) and Controller dedicated register interface */ 156 157 static unsigned int dw_hdmi_top_read(struct meson_dw_hdmi *dw_hdmi, 158 unsigned int addr) 159 { 160 unsigned long flags; 161 unsigned int data; 162 163 spin_lock_irqsave(®_lock, flags); 164 165 /* ADDR must be written twice */ 166 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 167 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 168 169 /* Read needs a second DATA read */ 170 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 171 data = readl(dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 172 173 spin_unlock_irqrestore(®_lock, flags); 174 175 return data; 176 } 177 178 static unsigned int dw_hdmi_g12a_top_read(struct meson_dw_hdmi *dw_hdmi, 179 unsigned int addr) 180 { 181 return readl(dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2)); 182 } 183 184 static inline void dw_hdmi_top_write(struct meson_dw_hdmi *dw_hdmi, 185 unsigned int addr, unsigned int data) 186 { 187 unsigned long flags; 188 189 spin_lock_irqsave(®_lock, flags); 190 191 /* ADDR must be written twice */ 192 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 193 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_TOP_ADDR_REG); 194 195 /* Write needs single DATA write */ 196 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_DATA_REG); 197 198 spin_unlock_irqrestore(®_lock, flags); 199 } 200 201 static inline void dw_hdmi_g12a_top_write(struct meson_dw_hdmi *dw_hdmi, 202 unsigned int addr, unsigned int data) 203 { 204 writel(data, dw_hdmi->hdmitx + HDMITX_TOP_G12A_OFFSET + (addr << 2)); 205 } 206 207 /* Helper to change specific bits in PHY registers */ 208 static inline void dw_hdmi_top_write_bits(struct meson_dw_hdmi *dw_hdmi, 209 unsigned int addr, 210 unsigned int mask, 211 unsigned int val) 212 { 213 unsigned int data = dw_hdmi->data->top_read(dw_hdmi, addr); 214 215 data &= ~mask; 216 data |= val; 217 218 dw_hdmi->data->top_write(dw_hdmi, addr, data); 219 } 220 221 static unsigned int dw_hdmi_dwc_read(struct meson_dw_hdmi *dw_hdmi, 222 unsigned int addr) 223 { 224 unsigned long flags; 225 unsigned int data; 226 227 spin_lock_irqsave(®_lock, flags); 228 229 /* ADDR must be written twice */ 230 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 231 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 232 233 /* Read needs a second DATA read */ 234 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 235 data = readl(dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 236 237 spin_unlock_irqrestore(®_lock, flags); 238 239 return data; 240 } 241 242 static unsigned int dw_hdmi_g12a_dwc_read(struct meson_dw_hdmi *dw_hdmi, 243 unsigned int addr) 244 { 245 return readb(dw_hdmi->hdmitx + addr); 246 } 247 248 static inline void dw_hdmi_dwc_write(struct meson_dw_hdmi *dw_hdmi, 249 unsigned int addr, unsigned int data) 250 { 251 unsigned long flags; 252 253 spin_lock_irqsave(®_lock, flags); 254 255 /* ADDR must be written twice */ 256 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 257 writel(addr & 0xffff, dw_hdmi->hdmitx + HDMITX_DWC_ADDR_REG); 258 259 /* Write needs single DATA write */ 260 writel(data, dw_hdmi->hdmitx + HDMITX_DWC_DATA_REG); 261 262 spin_unlock_irqrestore(®_lock, flags); 263 } 264 265 static inline void dw_hdmi_g12a_dwc_write(struct meson_dw_hdmi *dw_hdmi, 266 unsigned int addr, unsigned int data) 267 { 268 writeb(data, dw_hdmi->hdmitx + addr); 269 } 270 271 /* Helper to change specific bits in controller registers */ 272 static inline void dw_hdmi_dwc_write_bits(struct meson_dw_hdmi *dw_hdmi, 273 unsigned int addr, 274 unsigned int mask, 275 unsigned int val) 276 { 277 unsigned int data = dw_hdmi->data->dwc_read(dw_hdmi, addr); 278 279 data &= ~mask; 280 data |= val; 281 282 dw_hdmi->data->dwc_write(dw_hdmi, addr, data); 283 } 284 285 /* Bridge */ 286 287 /* Setup PHY bandwidth modes */ 288 static void meson_hdmi_phy_setup_mode(struct meson_dw_hdmi *dw_hdmi, 289 const struct drm_display_mode *mode, 290 bool mode_is_420) 291 { 292 struct meson_drm *priv = dw_hdmi->priv; 293 unsigned int pixel_clock = mode->clock; 294 295 /* For 420, pixel clock is half unlike venc clock */ 296 if (mode_is_420) pixel_clock /= 2; 297 298 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 299 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi")) { 300 if (pixel_clock >= 371250) { 301 /* 5.94Gbps, 3.7125Gbps */ 302 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x333d3282); 303 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2136315b); 304 } else if (pixel_clock >= 297000) { 305 /* 2.97Gbps */ 306 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303382); 307 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2036315b); 308 } else if (pixel_clock >= 148500) { 309 /* 1.485Gbps */ 310 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33303362); 311 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2016315b); 312 } else { 313 /* 742.5Mbps, and below */ 314 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33604142); 315 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x0016315b); 316 } 317 } else if (dw_hdmi_is_compatible(dw_hdmi, 318 "amlogic,meson-gxbb-dw-hdmi")) { 319 if (pixel_clock >= 371250) { 320 /* 5.94Gbps, 3.7125Gbps */ 321 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33353245); 322 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2100115b); 323 } else if (pixel_clock >= 297000) { 324 /* 2.97Gbps */ 325 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33634283); 326 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0xb000115b); 327 } else { 328 /* 1.485Gbps, and below */ 329 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33632122); 330 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2000115b); 331 } 332 } else if (dw_hdmi_is_compatible(dw_hdmi, 333 "amlogic,meson-g12a-dw-hdmi")) { 334 if (pixel_clock >= 371250) { 335 /* 5.94Gbps, 3.7125Gbps */ 336 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x37eb65c4); 337 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); 338 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x0000080b); 339 } else if (pixel_clock >= 297000) { 340 /* 2.97Gbps */ 341 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb6262); 342 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); 343 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003); 344 } else { 345 /* 1.485Gbps, and below */ 346 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0x33eb4242); 347 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL3, 0x2ab0ff3b); 348 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL5, 0x00000003); 349 } 350 } 351 } 352 353 static inline void meson_dw_hdmi_phy_reset(struct meson_dw_hdmi *dw_hdmi) 354 { 355 struct meson_drm *priv = dw_hdmi->priv; 356 357 /* Enable and software reset */ 358 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xf); 359 360 mdelay(2); 361 362 /* Enable and unreset */ 363 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0xe); 364 365 mdelay(2); 366 } 367 368 static int dw_hdmi_phy_init(struct dw_hdmi *hdmi, void *data, 369 const struct drm_display_info *display, 370 const struct drm_display_mode *mode) 371 { 372 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 373 bool is_hdmi2_sink = display->hdmi.scdc.supported; 374 struct meson_drm *priv = dw_hdmi->priv; 375 unsigned int wr_clk = 376 readl_relaxed(priv->io_base + _REG(VPU_HDMI_SETTING)); 377 bool mode_is_420 = false; 378 379 DRM_DEBUG_DRIVER("\"%s\" div%d\n", mode->name, 380 mode->clock > 340000 ? 40 : 10); 381 382 if (drm_mode_is_420_only(display, mode) || 383 (!is_hdmi2_sink && drm_mode_is_420_also(display, mode)) || 384 dw_hdmi_bus_fmt_is_420(hdmi)) 385 mode_is_420 = true; 386 387 /* Enable clocks */ 388 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100); 389 390 /* Bring HDMITX MEM output of power down */ 391 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); 392 393 /* Bring out of reset */ 394 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_SW_RESET, 0); 395 396 /* Enable internal pixclk, tmds_clk, spdif_clk, i2s_clk, cecclk */ 397 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 398 0x3, 0x3); 399 400 /* Enable cec_clk and hdcp22_tmdsclk_en */ 401 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_CLK_CNTL, 402 0x3 << 4, 0x3 << 4); 403 404 /* Enable normal output to PHY */ 405 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_BIST_CNTL, BIT(12)); 406 407 /* TMDS pattern setup */ 408 if (mode->clock > 340000 && !mode_is_420) { 409 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 410 0); 411 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 412 0x03ff03ff); 413 } else { 414 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_01, 415 0x001f001f); 416 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_23, 417 0x001f001f); 418 } 419 420 /* Load TMDS pattern */ 421 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x1); 422 msleep(20); 423 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_TMDS_CLK_PTTN_CNTL, 0x2); 424 425 /* Setup PHY parameters */ 426 meson_hdmi_phy_setup_mode(dw_hdmi, mode, mode_is_420); 427 428 /* Setup PHY */ 429 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 430 0xffff << 16, 0x0390 << 16); 431 432 /* BIT_INVERT */ 433 if (dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 434 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-gxm-dw-hdmi") || 435 dw_hdmi_is_compatible(dw_hdmi, "amlogic,meson-g12a-dw-hdmi")) 436 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 437 BIT(17), 0); 438 else 439 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 440 BIT(17), BIT(17)); 441 442 /* Disable clock, fifo, fifo_wr */ 443 regmap_update_bits(priv->hhi, HHI_HDMI_PHY_CNTL1, 0xf, 0); 444 445 dw_hdmi_set_high_tmds_clock_ratio(hdmi, display); 446 447 msleep(100); 448 449 /* Reset PHY 3 times in a row */ 450 meson_dw_hdmi_phy_reset(dw_hdmi); 451 meson_dw_hdmi_phy_reset(dw_hdmi); 452 meson_dw_hdmi_phy_reset(dw_hdmi); 453 454 /* Temporary Disable VENC video stream */ 455 if (priv->venc.hdmi_use_enci) 456 writel_relaxed(0, priv->io_base + _REG(ENCI_VIDEO_EN)); 457 else 458 writel_relaxed(0, priv->io_base + _REG(ENCP_VIDEO_EN)); 459 460 /* Temporary Disable HDMI video stream to HDMI-TX */ 461 writel_bits_relaxed(0x3, 0, 462 priv->io_base + _REG(VPU_HDMI_SETTING)); 463 writel_bits_relaxed(0xf << 8, 0, 464 priv->io_base + _REG(VPU_HDMI_SETTING)); 465 466 /* Re-Enable VENC video stream */ 467 if (priv->venc.hdmi_use_enci) 468 writel_relaxed(1, priv->io_base + _REG(ENCI_VIDEO_EN)); 469 else 470 writel_relaxed(1, priv->io_base + _REG(ENCP_VIDEO_EN)); 471 472 /* Push back HDMI clock settings */ 473 writel_bits_relaxed(0xf << 8, wr_clk & (0xf << 8), 474 priv->io_base + _REG(VPU_HDMI_SETTING)); 475 476 /* Enable and Select HDMI video source for HDMI-TX */ 477 if (priv->venc.hdmi_use_enci) 478 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCI, 479 priv->io_base + _REG(VPU_HDMI_SETTING)); 480 else 481 writel_bits_relaxed(0x3, MESON_VENC_SOURCE_ENCP, 482 priv->io_base + _REG(VPU_HDMI_SETTING)); 483 484 return 0; 485 } 486 487 static void dw_hdmi_phy_disable(struct dw_hdmi *hdmi, 488 void *data) 489 { 490 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 491 struct meson_drm *priv = dw_hdmi->priv; 492 493 DRM_DEBUG_DRIVER("\n"); 494 495 regmap_write(priv->hhi, HHI_HDMI_PHY_CNTL0, 0); 496 } 497 498 static enum drm_connector_status dw_hdmi_read_hpd(struct dw_hdmi *hdmi, 499 void *data) 500 { 501 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 502 503 return !!dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_STAT0) ? 504 connector_status_connected : connector_status_disconnected; 505 } 506 507 static void dw_hdmi_setup_hpd(struct dw_hdmi *hdmi, 508 void *data) 509 { 510 struct meson_dw_hdmi *dw_hdmi = (struct meson_dw_hdmi *)data; 511 512 /* Setup HPD Filter */ 513 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_HPD_FILTER, 514 (0xa << 12) | 0xa0); 515 516 /* Clear interrupts */ 517 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 518 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL); 519 520 /* Unmask interrupts */ 521 dw_hdmi_top_write_bits(dw_hdmi, HDMITX_TOP_INTR_MASKN, 522 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL, 523 HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL); 524 } 525 526 static const struct dw_hdmi_phy_ops meson_dw_hdmi_phy_ops = { 527 .init = dw_hdmi_phy_init, 528 .disable = dw_hdmi_phy_disable, 529 .read_hpd = dw_hdmi_read_hpd, 530 .setup_hpd = dw_hdmi_setup_hpd, 531 }; 532 533 static irqreturn_t dw_hdmi_top_irq(int irq, void *dev_id) 534 { 535 struct meson_dw_hdmi *dw_hdmi = dev_id; 536 u32 stat; 537 538 stat = dw_hdmi->data->top_read(dw_hdmi, HDMITX_TOP_INTR_STAT); 539 dw_hdmi->data->top_write(dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, stat); 540 541 /* HPD Events, handle in the threaded interrupt handler */ 542 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) { 543 dw_hdmi->irq_stat = stat; 544 return IRQ_WAKE_THREAD; 545 } 546 547 /* HDMI Controller Interrupt */ 548 if (stat & 1) 549 return IRQ_NONE; 550 551 /* TOFIX Handle HDCP Interrupts */ 552 553 return IRQ_HANDLED; 554 } 555 556 /* Threaded interrupt handler to manage HPD events */ 557 static irqreturn_t dw_hdmi_top_thread_irq(int irq, void *dev_id) 558 { 559 struct meson_dw_hdmi *dw_hdmi = dev_id; 560 u32 stat = dw_hdmi->irq_stat; 561 562 /* HPD Events */ 563 if (stat & (HDMITX_TOP_INTR_HPD_RISE | HDMITX_TOP_INTR_HPD_FALL)) { 564 bool hpd_connected = false; 565 566 if (stat & HDMITX_TOP_INTR_HPD_RISE) 567 hpd_connected = true; 568 569 dw_hdmi_setup_rx_sense(dw_hdmi->hdmi, hpd_connected, 570 hpd_connected); 571 572 drm_helper_hpd_irq_event(dw_hdmi->bridge->dev); 573 drm_bridge_hpd_notify(dw_hdmi->bridge, 574 hpd_connected ? connector_status_connected 575 : connector_status_disconnected); 576 } 577 578 return IRQ_HANDLED; 579 } 580 581 /* DW HDMI Regmap */ 582 583 static int meson_dw_hdmi_reg_read(void *context, unsigned int reg, 584 unsigned int *result) 585 { 586 struct meson_dw_hdmi *dw_hdmi = context; 587 588 *result = dw_hdmi->data->dwc_read(dw_hdmi, reg); 589 590 return 0; 591 592 } 593 594 static int meson_dw_hdmi_reg_write(void *context, unsigned int reg, 595 unsigned int val) 596 { 597 struct meson_dw_hdmi *dw_hdmi = context; 598 599 dw_hdmi->data->dwc_write(dw_hdmi, reg, val); 600 601 return 0; 602 } 603 604 static const struct regmap_config meson_dw_hdmi_regmap_config = { 605 .reg_bits = 32, 606 .val_bits = 8, 607 .reg_read = meson_dw_hdmi_reg_read, 608 .reg_write = meson_dw_hdmi_reg_write, 609 .max_register = 0x10000, 610 .fast_io = true, 611 }; 612 613 static const struct meson_dw_hdmi_data meson_dw_hdmi_gx_data = { 614 .top_read = dw_hdmi_top_read, 615 .top_write = dw_hdmi_top_write, 616 .dwc_read = dw_hdmi_dwc_read, 617 .dwc_write = dw_hdmi_dwc_write, 618 }; 619 620 static const struct meson_dw_hdmi_data meson_dw_hdmi_g12a_data = { 621 .top_read = dw_hdmi_g12a_top_read, 622 .top_write = dw_hdmi_g12a_top_write, 623 .dwc_read = dw_hdmi_g12a_dwc_read, 624 .dwc_write = dw_hdmi_g12a_dwc_write, 625 }; 626 627 static void meson_dw_hdmi_init(struct meson_dw_hdmi *meson_dw_hdmi) 628 { 629 struct meson_drm *priv = meson_dw_hdmi->priv; 630 631 /* Enable clocks */ 632 regmap_update_bits(priv->hhi, HHI_HDMI_CLK_CNTL, 0xffff, 0x100); 633 634 /* Bring HDMITX MEM output of power down */ 635 regmap_update_bits(priv->hhi, HHI_MEM_PD_REG0, 0xff << 8, 0); 636 637 /* Reset HDMITX APB & TX & PHY */ 638 reset_control_reset(meson_dw_hdmi->hdmitx_apb); 639 reset_control_reset(meson_dw_hdmi->hdmitx_ctrl); 640 reset_control_reset(meson_dw_hdmi->hdmitx_phy); 641 642 /* Enable APB3 fail on error */ 643 if (!meson_vpu_is_compatible(priv, VPU_COMPATIBLE_G12A)) { 644 writel_bits_relaxed(BIT(15), BIT(15), 645 meson_dw_hdmi->hdmitx + HDMITX_TOP_CTRL_REG); 646 writel_bits_relaxed(BIT(15), BIT(15), 647 meson_dw_hdmi->hdmitx + HDMITX_DWC_CTRL_REG); 648 } 649 650 /* Bring out of reset */ 651 meson_dw_hdmi->data->top_write(meson_dw_hdmi, 652 HDMITX_TOP_SW_RESET, 0); 653 654 msleep(20); 655 656 meson_dw_hdmi->data->top_write(meson_dw_hdmi, 657 HDMITX_TOP_CLK_CNTL, 0xff); 658 659 /* Enable HDMI-TX Interrupt */ 660 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_STAT_CLR, 661 HDMITX_TOP_INTR_CORE); 662 663 meson_dw_hdmi->data->top_write(meson_dw_hdmi, HDMITX_TOP_INTR_MASKN, 664 HDMITX_TOP_INTR_CORE); 665 666 } 667 668 static void meson_disable_clk(void *data) 669 { 670 clk_disable_unprepare(data); 671 } 672 673 static int meson_enable_clk(struct device *dev, char *name) 674 { 675 struct clk *clk; 676 int ret; 677 678 clk = devm_clk_get(dev, name); 679 if (IS_ERR(clk)) { 680 dev_err(dev, "Unable to get %s pclk\n", name); 681 return PTR_ERR(clk); 682 } 683 684 ret = clk_prepare_enable(clk); 685 if (!ret) 686 ret = devm_add_action_or_reset(dev, meson_disable_clk, clk); 687 688 return ret; 689 } 690 691 static int meson_dw_hdmi_bind(struct device *dev, struct device *master, 692 void *data) 693 { 694 struct platform_device *pdev = to_platform_device(dev); 695 const struct meson_dw_hdmi_data *match; 696 struct meson_dw_hdmi *meson_dw_hdmi; 697 struct drm_device *drm = data; 698 struct meson_drm *priv = drm->dev_private; 699 struct dw_hdmi_plat_data *dw_plat_data; 700 int irq; 701 int ret; 702 703 DRM_DEBUG_DRIVER("\n"); 704 705 match = of_device_get_match_data(&pdev->dev); 706 if (!match) { 707 dev_err(&pdev->dev, "failed to get match data\n"); 708 return -ENODEV; 709 } 710 711 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi), 712 GFP_KERNEL); 713 if (!meson_dw_hdmi) 714 return -ENOMEM; 715 716 meson_dw_hdmi->priv = priv; 717 meson_dw_hdmi->dev = dev; 718 meson_dw_hdmi->data = match; 719 dw_plat_data = &meson_dw_hdmi->dw_plat_data; 720 721 ret = devm_regulator_get_enable_optional(dev, "hdmi"); 722 if (ret < 0 && ret != -ENODEV) 723 return ret; 724 725 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, 726 "hdmitx_apb"); 727 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) { 728 dev_err(dev, "Failed to get hdmitx_apb reset\n"); 729 return PTR_ERR(meson_dw_hdmi->hdmitx_apb); 730 } 731 732 meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev, 733 "hdmitx"); 734 if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) { 735 dev_err(dev, "Failed to get hdmitx reset\n"); 736 return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl); 737 } 738 739 meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev, 740 "hdmitx_phy"); 741 if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) { 742 dev_err(dev, "Failed to get hdmitx_phy reset\n"); 743 return PTR_ERR(meson_dw_hdmi->hdmitx_phy); 744 } 745 746 meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0); 747 if (IS_ERR(meson_dw_hdmi->hdmitx)) 748 return PTR_ERR(meson_dw_hdmi->hdmitx); 749 750 ret = meson_enable_clk(dev, "isfr"); 751 if (ret) 752 return ret; 753 754 ret = meson_enable_clk(dev, "iahb"); 755 if (ret) 756 return ret; 757 758 ret = meson_enable_clk(dev, "venci"); 759 if (ret) 760 return ret; 761 762 dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi, 763 &meson_dw_hdmi_regmap_config); 764 if (IS_ERR(dw_plat_data->regm)) 765 return PTR_ERR(dw_plat_data->regm); 766 767 irq = platform_get_irq(pdev, 0); 768 if (irq < 0) 769 return irq; 770 771 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq, 772 dw_hdmi_top_thread_irq, IRQF_SHARED, 773 "dw_hdmi_top_irq", meson_dw_hdmi); 774 if (ret) { 775 dev_err(dev, "Failed to request hdmi top irq\n"); 776 return ret; 777 } 778 779 meson_dw_hdmi_init(meson_dw_hdmi); 780 781 /* Bridge / Connector */ 782 783 dw_plat_data->priv_data = meson_dw_hdmi; 784 dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops; 785 dw_plat_data->phy_name = "meson_dw_hdmi_phy"; 786 dw_plat_data->phy_data = meson_dw_hdmi; 787 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; 788 dw_plat_data->ycbcr_420_allowed = true; 789 dw_plat_data->disable_cec = true; 790 dw_plat_data->output_port = 1; 791 792 if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 793 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") || 794 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi")) 795 dw_plat_data->use_drm_infoframe = true; 796 797 platform_set_drvdata(pdev, meson_dw_hdmi); 798 799 meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev, &meson_dw_hdmi->dw_plat_data); 800 if (IS_ERR(meson_dw_hdmi->hdmi)) 801 return PTR_ERR(meson_dw_hdmi->hdmi); 802 803 meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node); 804 805 DRM_DEBUG_DRIVER("HDMI controller initialized\n"); 806 807 return 0; 808 } 809 810 static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, 811 void *data) 812 { 813 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 814 815 dw_hdmi_unbind(meson_dw_hdmi->hdmi); 816 } 817 818 static const struct component_ops meson_dw_hdmi_ops = { 819 .bind = meson_dw_hdmi_bind, 820 .unbind = meson_dw_hdmi_unbind, 821 }; 822 823 static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev) 824 { 825 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 826 827 if (!meson_dw_hdmi) 828 return 0; 829 830 /* Reset TOP */ 831 meson_dw_hdmi->data->top_write(meson_dw_hdmi, 832 HDMITX_TOP_SW_RESET, 0); 833 834 return 0; 835 } 836 837 static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev) 838 { 839 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 840 841 if (!meson_dw_hdmi) 842 return 0; 843 844 meson_dw_hdmi_init(meson_dw_hdmi); 845 846 dw_hdmi_resume(meson_dw_hdmi->hdmi); 847 848 return 0; 849 } 850 851 static int meson_dw_hdmi_probe(struct platform_device *pdev) 852 { 853 return component_add(&pdev->dev, &meson_dw_hdmi_ops); 854 } 855 856 static void meson_dw_hdmi_remove(struct platform_device *pdev) 857 { 858 component_del(&pdev->dev, &meson_dw_hdmi_ops); 859 } 860 861 static const struct dev_pm_ops meson_dw_hdmi_pm_ops = { 862 SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend, 863 meson_dw_hdmi_pm_resume) 864 }; 865 866 static const struct of_device_id meson_dw_hdmi_of_table[] = { 867 { .compatible = "amlogic,meson-gxbb-dw-hdmi", 868 .data = &meson_dw_hdmi_gx_data }, 869 { .compatible = "amlogic,meson-gxl-dw-hdmi", 870 .data = &meson_dw_hdmi_gx_data }, 871 { .compatible = "amlogic,meson-gxm-dw-hdmi", 872 .data = &meson_dw_hdmi_gx_data }, 873 { .compatible = "amlogic,meson-g12a-dw-hdmi", 874 .data = &meson_dw_hdmi_g12a_data }, 875 { } 876 }; 877 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table); 878 879 static struct platform_driver meson_dw_hdmi_platform_driver = { 880 .probe = meson_dw_hdmi_probe, 881 .remove_new = meson_dw_hdmi_remove, 882 .driver = { 883 .name = DRIVER_NAME, 884 .of_match_table = meson_dw_hdmi_of_table, 885 .pm = &meson_dw_hdmi_pm_ops, 886 }, 887 }; 888 module_platform_driver(meson_dw_hdmi_platform_driver); 889 890 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 891 MODULE_DESCRIPTION(DRIVER_DESC); 892 MODULE_LICENSE("GPL"); 893