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