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