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