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/videodev2.h> 26 27 #include "meson_drv.h" 28 #include "meson_dw_hdmi.h" 29 #include "meson_registers.h" 30 31 #define DRIVER_NAME "meson-dw-hdmi" 32 #define DRIVER_DESC "Amlogic Meson HDMI-TX DRM driver" 33 34 /** 35 * DOC: HDMI Output 36 * 37 * HDMI Output is composed of : 38 * 39 * - A Synopsys DesignWare HDMI Controller IP 40 * - A TOP control block controlling the Clocks and PHY 41 * - A custom HDMI PHY in order convert video to TMDS signal 42 * 43 * .. code:: 44 * 45 * ___________________________________ 46 * | HDMI TOP |<= HPD 47 * |___________________________________| 48 * | | | 49 * | Synopsys HDMI | HDMI PHY |=> TMDS 50 * | Controller |________________| 51 * |___________________________________|<=> DDC 52 * 53 * 54 * The HDMI TOP block only supports HPD sensing. 55 * The Synopsys HDMI Controller interrupt is routed 56 * through the TOP Block interrupt. 57 * Communication to the TOP Block and the Synopsys 58 * HDMI Controller is done a pair of addr+read/write 59 * registers. 60 * The HDMI PHY is configured by registers in the 61 * HHI register block. 62 * 63 * Pixel data arrives in 4:4:4 format from the VENC 64 * block and the VPU HDMI mux selects either the ENCI 65 * encoder for the 576i or 480i formats or the ENCP 66 * encoder for all the other formats including 67 * interlaced HD formats. 68 * The VENC uses a DVI encoder on top of the ENCI 69 * or ENCP encoders to generate DVI timings for the 70 * HDMI controller. 71 * 72 * GXBB, GXL and GXM embeds the Synopsys DesignWare 73 * HDMI TX IP version 2.01a with HDCP and I2C & S/PDIF 74 * audio source interfaces. 75 * 76 * We handle the following features : 77 * 78 * - HPD Rise & Fall interrupt 79 * - HDMI Controller Interrupt 80 * - HDMI PHY Init for 480i to 1080p60 81 * - VENC & HDMI Clock setup for 480i to 1080p60 82 * - VENC Mode setup for 480i to 1080p60 83 * 84 * What is missing : 85 * 86 * - PHY, Clock and Mode setup for 2k && 4k modes 87 * - SDDC Scrambling mode for HDMI 2.0a 88 * - HDCP Setup 89 * - CEC Management 90 */ 91 92 /* TOP Block Communication Channel */ 93 #define HDMITX_TOP_ADDR_REG 0x0 94 #define HDMITX_TOP_DATA_REG 0x4 95 #define HDMITX_TOP_CTRL_REG 0x8 96 #define HDMITX_TOP_G12A_OFFSET 0x8000 97 98 /* Controller Communication Channel */ 99 #define HDMITX_DWC_ADDR_REG 0x10 100 #define HDMITX_DWC_DATA_REG 0x14 101 #define HDMITX_DWC_CTRL_REG 0x18 102 103 /* HHI Registers */ 104 #define HHI_MEM_PD_REG0 0x100 /* 0x40 */ 105 #define HHI_HDMI_CLK_CNTL 0x1cc /* 0x73 */ 106 #define HHI_HDMI_PHY_CNTL0 0x3a0 /* 0xe8 */ 107 #define HHI_HDMI_PHY_CNTL1 0x3a4 /* 0xe9 */ 108 #define HHI_HDMI_PHY_CNTL2 0x3a8 /* 0xea */ 109 #define HHI_HDMI_PHY_CNTL3 0x3ac /* 0xeb */ 110 #define HHI_HDMI_PHY_CNTL4 0x3b0 /* 0xec */ 111 #define HHI_HDMI_PHY_CNTL5 0x3b4 /* 0xed */ 112 113 static DEFINE_SPINLOCK(reg_lock); 114 115 enum meson_venc_source { 116 MESON_VENC_SOURCE_NONE = 0, 117 MESON_VENC_SOURCE_ENCI = 1, 118 MESON_VENC_SOURCE_ENCP = 2, 119 }; 120 121 struct meson_dw_hdmi; 122 123 struct meson_dw_hdmi_data { 124 unsigned int (*top_read)(struct meson_dw_hdmi *dw_hdmi, 125 unsigned int addr); 126 void (*top_write)(struct meson_dw_hdmi *dw_hdmi, 127 unsigned int addr, unsigned int data); 128 unsigned int (*dwc_read)(struct meson_dw_hdmi *dw_hdmi, 129 unsigned int addr); 130 void (*dwc_write)(struct meson_dw_hdmi *dw_hdmi, 131 unsigned int addr, unsigned int data); 132 }; 133 134 struct meson_dw_hdmi { 135 struct dw_hdmi_plat_data dw_plat_data; 136 struct meson_drm *priv; 137 struct device *dev; 138 void __iomem *hdmitx; 139 const struct meson_dw_hdmi_data *data; 140 struct reset_control *hdmitx_apb; 141 struct reset_control *hdmitx_ctrl; 142 struct reset_control *hdmitx_phy; 143 struct regulator *hdmi_supply; 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 && 384 drm_mode_is_420_also(display, mode))) 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_regulator(void *data) 669 { 670 regulator_disable(data); 671 } 672 673 static void meson_disable_clk(void *data) 674 { 675 clk_disable_unprepare(data); 676 } 677 678 static int meson_enable_clk(struct device *dev, char *name) 679 { 680 struct clk *clk; 681 int ret; 682 683 clk = devm_clk_get(dev, name); 684 if (IS_ERR(clk)) { 685 dev_err(dev, "Unable to get %s pclk\n", name); 686 return PTR_ERR(clk); 687 } 688 689 ret = clk_prepare_enable(clk); 690 if (!ret) 691 ret = devm_add_action_or_reset(dev, meson_disable_clk, clk); 692 693 return ret; 694 } 695 696 static int meson_dw_hdmi_bind(struct device *dev, struct device *master, 697 void *data) 698 { 699 struct platform_device *pdev = to_platform_device(dev); 700 const struct meson_dw_hdmi_data *match; 701 struct meson_dw_hdmi *meson_dw_hdmi; 702 struct drm_device *drm = data; 703 struct meson_drm *priv = drm->dev_private; 704 struct dw_hdmi_plat_data *dw_plat_data; 705 int irq; 706 int ret; 707 708 DRM_DEBUG_DRIVER("\n"); 709 710 match = of_device_get_match_data(&pdev->dev); 711 if (!match) { 712 dev_err(&pdev->dev, "failed to get match data\n"); 713 return -ENODEV; 714 } 715 716 meson_dw_hdmi = devm_kzalloc(dev, sizeof(*meson_dw_hdmi), 717 GFP_KERNEL); 718 if (!meson_dw_hdmi) 719 return -ENOMEM; 720 721 meson_dw_hdmi->priv = priv; 722 meson_dw_hdmi->dev = dev; 723 meson_dw_hdmi->data = match; 724 dw_plat_data = &meson_dw_hdmi->dw_plat_data; 725 726 meson_dw_hdmi->hdmi_supply = devm_regulator_get_optional(dev, "hdmi"); 727 if (IS_ERR(meson_dw_hdmi->hdmi_supply)) { 728 if (PTR_ERR(meson_dw_hdmi->hdmi_supply) == -EPROBE_DEFER) 729 return -EPROBE_DEFER; 730 meson_dw_hdmi->hdmi_supply = NULL; 731 } else { 732 ret = regulator_enable(meson_dw_hdmi->hdmi_supply); 733 if (ret) 734 return ret; 735 ret = devm_add_action_or_reset(dev, meson_disable_regulator, 736 meson_dw_hdmi->hdmi_supply); 737 if (ret) 738 return ret; 739 } 740 741 meson_dw_hdmi->hdmitx_apb = devm_reset_control_get_exclusive(dev, 742 "hdmitx_apb"); 743 if (IS_ERR(meson_dw_hdmi->hdmitx_apb)) { 744 dev_err(dev, "Failed to get hdmitx_apb reset\n"); 745 return PTR_ERR(meson_dw_hdmi->hdmitx_apb); 746 } 747 748 meson_dw_hdmi->hdmitx_ctrl = devm_reset_control_get_exclusive(dev, 749 "hdmitx"); 750 if (IS_ERR(meson_dw_hdmi->hdmitx_ctrl)) { 751 dev_err(dev, "Failed to get hdmitx reset\n"); 752 return PTR_ERR(meson_dw_hdmi->hdmitx_ctrl); 753 } 754 755 meson_dw_hdmi->hdmitx_phy = devm_reset_control_get_exclusive(dev, 756 "hdmitx_phy"); 757 if (IS_ERR(meson_dw_hdmi->hdmitx_phy)) { 758 dev_err(dev, "Failed to get hdmitx_phy reset\n"); 759 return PTR_ERR(meson_dw_hdmi->hdmitx_phy); 760 } 761 762 meson_dw_hdmi->hdmitx = devm_platform_ioremap_resource(pdev, 0); 763 if (IS_ERR(meson_dw_hdmi->hdmitx)) 764 return PTR_ERR(meson_dw_hdmi->hdmitx); 765 766 ret = meson_enable_clk(dev, "isfr"); 767 if (ret) 768 return ret; 769 770 ret = meson_enable_clk(dev, "iahb"); 771 if (ret) 772 return ret; 773 774 ret = meson_enable_clk(dev, "venci"); 775 if (ret) 776 return ret; 777 778 dw_plat_data->regm = devm_regmap_init(dev, NULL, meson_dw_hdmi, 779 &meson_dw_hdmi_regmap_config); 780 if (IS_ERR(dw_plat_data->regm)) 781 return PTR_ERR(dw_plat_data->regm); 782 783 irq = platform_get_irq(pdev, 0); 784 if (irq < 0) 785 return irq; 786 787 ret = devm_request_threaded_irq(dev, irq, dw_hdmi_top_irq, 788 dw_hdmi_top_thread_irq, IRQF_SHARED, 789 "dw_hdmi_top_irq", meson_dw_hdmi); 790 if (ret) { 791 dev_err(dev, "Failed to request hdmi top irq\n"); 792 return ret; 793 } 794 795 meson_dw_hdmi_init(meson_dw_hdmi); 796 797 /* Bridge / Connector */ 798 799 dw_plat_data->priv_data = meson_dw_hdmi; 800 dw_plat_data->phy_ops = &meson_dw_hdmi_phy_ops; 801 dw_plat_data->phy_name = "meson_dw_hdmi_phy"; 802 dw_plat_data->phy_data = meson_dw_hdmi; 803 dw_plat_data->input_bus_encoding = V4L2_YCBCR_ENC_709; 804 dw_plat_data->ycbcr_420_allowed = true; 805 dw_plat_data->disable_cec = true; 806 dw_plat_data->output_port = 1; 807 808 if (dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxl-dw-hdmi") || 809 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-gxm-dw-hdmi") || 810 dw_hdmi_is_compatible(meson_dw_hdmi, "amlogic,meson-g12a-dw-hdmi")) 811 dw_plat_data->use_drm_infoframe = true; 812 813 platform_set_drvdata(pdev, meson_dw_hdmi); 814 815 meson_dw_hdmi->hdmi = dw_hdmi_probe(pdev, &meson_dw_hdmi->dw_plat_data); 816 if (IS_ERR(meson_dw_hdmi->hdmi)) 817 return PTR_ERR(meson_dw_hdmi->hdmi); 818 819 meson_dw_hdmi->bridge = of_drm_find_bridge(pdev->dev.of_node); 820 821 DRM_DEBUG_DRIVER("HDMI controller initialized\n"); 822 823 return 0; 824 } 825 826 static void meson_dw_hdmi_unbind(struct device *dev, struct device *master, 827 void *data) 828 { 829 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 830 831 dw_hdmi_unbind(meson_dw_hdmi->hdmi); 832 } 833 834 static const struct component_ops meson_dw_hdmi_ops = { 835 .bind = meson_dw_hdmi_bind, 836 .unbind = meson_dw_hdmi_unbind, 837 }; 838 839 static int __maybe_unused meson_dw_hdmi_pm_suspend(struct device *dev) 840 { 841 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 842 843 if (!meson_dw_hdmi) 844 return 0; 845 846 /* Reset TOP */ 847 meson_dw_hdmi->data->top_write(meson_dw_hdmi, 848 HDMITX_TOP_SW_RESET, 0); 849 850 return 0; 851 } 852 853 static int __maybe_unused meson_dw_hdmi_pm_resume(struct device *dev) 854 { 855 struct meson_dw_hdmi *meson_dw_hdmi = dev_get_drvdata(dev); 856 857 if (!meson_dw_hdmi) 858 return 0; 859 860 meson_dw_hdmi_init(meson_dw_hdmi); 861 862 dw_hdmi_resume(meson_dw_hdmi->hdmi); 863 864 return 0; 865 } 866 867 static int meson_dw_hdmi_probe(struct platform_device *pdev) 868 { 869 return component_add(&pdev->dev, &meson_dw_hdmi_ops); 870 } 871 872 static int meson_dw_hdmi_remove(struct platform_device *pdev) 873 { 874 component_del(&pdev->dev, &meson_dw_hdmi_ops); 875 876 return 0; 877 } 878 879 static const struct dev_pm_ops meson_dw_hdmi_pm_ops = { 880 SET_SYSTEM_SLEEP_PM_OPS(meson_dw_hdmi_pm_suspend, 881 meson_dw_hdmi_pm_resume) 882 }; 883 884 static const struct of_device_id meson_dw_hdmi_of_table[] = { 885 { .compatible = "amlogic,meson-gxbb-dw-hdmi", 886 .data = &meson_dw_hdmi_gx_data }, 887 { .compatible = "amlogic,meson-gxl-dw-hdmi", 888 .data = &meson_dw_hdmi_gx_data }, 889 { .compatible = "amlogic,meson-gxm-dw-hdmi", 890 .data = &meson_dw_hdmi_gx_data }, 891 { .compatible = "amlogic,meson-g12a-dw-hdmi", 892 .data = &meson_dw_hdmi_g12a_data }, 893 { } 894 }; 895 MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table); 896 897 static struct platform_driver meson_dw_hdmi_platform_driver = { 898 .probe = meson_dw_hdmi_probe, 899 .remove = meson_dw_hdmi_remove, 900 .driver = { 901 .name = DRIVER_NAME, 902 .of_match_table = meson_dw_hdmi_of_table, 903 .pm = &meson_dw_hdmi_pm_ops, 904 }, 905 }; 906 module_platform_driver(meson_dw_hdmi_platform_driver); 907 908 MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>"); 909 MODULE_DESCRIPTION(DRIVER_DESC); 910 MODULE_LICENSE("GPL"); 911