linux/drivers/gpu/drm/meson/meson_dw_hdmi.c
<<
>>
Prefs
   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
 122static DEFINE_SPINLOCK(reg_lock);
 123
 124enum meson_venc_source {
 125        MESON_VENC_SOURCE_NONE = 0,
 126        MESON_VENC_SOURCE_ENCI = 1,
 127        MESON_VENC_SOURCE_ENCP = 2,
 128};
 129
 130struct 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
 147static 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
 155static 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(&reg_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(&reg_lock, flags);
 172
 173        return data;
 174}
 175
 176static 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(&reg_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(&reg_lock, flags);
 191}
 192
 193/* Helper to change specific bits in PHY registers */
 194static 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
 207static 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(&reg_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(&reg_lock, flags);
 224
 225        return data;
 226}
 227
 228static 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(&reg_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(&reg_lock, flags);
 243}
 244
 245/* Helper to change specific bits in controller registers */
 246static 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 */
 262static 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
 305static 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
 320static 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
 353static 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
 449static 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
 460static 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
 469static 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
 488static 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
 495static 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 */
 519static 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 */
 541static enum drm_mode_status
 542dw_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
 601static void meson_venc_hdmi_encoder_destroy(struct drm_encoder *encoder)
 602{
 603        drm_encoder_cleanup(encoder);
 604}
 605
 606static const struct drm_encoder_funcs meson_venc_hdmi_encoder_funcs = {
 607        .destroy        = meson_venc_hdmi_encoder_destroy,
 608};
 609
 610static 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
 617static 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
 631static 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
 644static 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
 669static 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
 679static 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
 688static 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
 696static 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
 704static 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
 726static 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
 890static void meson_dw_hdmi_unbind(struct device *dev, struct device *master,
 891                                   void *data)
 892{
 893        dw_hdmi_unbind(dev);
 894}
 895
 896static const struct component_ops meson_dw_hdmi_ops = {
 897        .bind   = meson_dw_hdmi_bind,
 898        .unbind = meson_dw_hdmi_unbind,
 899};
 900
 901static int meson_dw_hdmi_probe(struct platform_device *pdev)
 902{
 903        return component_add(&pdev->dev, &meson_dw_hdmi_ops);
 904}
 905
 906static 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
 913static 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};
 919MODULE_DEVICE_TABLE(of, meson_dw_hdmi_of_table);
 920
 921static 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};
 929module_platform_driver(meson_dw_hdmi_platform_driver);
 930
 931MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
 932MODULE_DESCRIPTION(DRIVER_DESC);
 933MODULE_LICENSE("GPL");
 934