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