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