linux/drivers/gpu/drm/sti/sti_hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) STMicroelectronics SA 2014
   3 * Author: Vincent Abriou <vincent.abriou@st.com> for STMicroelectronics.
   4 * License terms:  GNU General Public License (GPL), version 2
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/component.h>
   9#include <linux/debugfs.h>
  10#include <linux/hdmi.h>
  11#include <linux/module.h>
  12#include <linux/of_gpio.h>
  13#include <linux/platform_device.h>
  14#include <linux/reset.h>
  15
  16#include <drm/drmP.h>
  17#include <drm/drm_atomic_helper.h>
  18#include <drm/drm_crtc_helper.h>
  19#include <drm/drm_edid.h>
  20
  21#include "sti_hdmi.h"
  22#include "sti_hdmi_tx3g4c28phy.h"
  23#include "sti_hdmi_tx3g0c55phy.h"
  24#include "sti_vtg.h"
  25
  26#define HDMI_CFG                        0x0000
  27#define HDMI_INT_EN                     0x0004
  28#define HDMI_INT_STA                    0x0008
  29#define HDMI_INT_CLR                    0x000C
  30#define HDMI_STA                        0x0010
  31#define HDMI_ACTIVE_VID_XMIN            0x0100
  32#define HDMI_ACTIVE_VID_XMAX            0x0104
  33#define HDMI_ACTIVE_VID_YMIN            0x0108
  34#define HDMI_ACTIVE_VID_YMAX            0x010C
  35#define HDMI_DFLT_CHL0_DAT              0x0110
  36#define HDMI_DFLT_CHL1_DAT              0x0114
  37#define HDMI_DFLT_CHL2_DAT              0x0118
  38#define HDMI_SW_DI_1_HEAD_WORD          0x0210
  39#define HDMI_SW_DI_1_PKT_WORD0          0x0214
  40#define HDMI_SW_DI_1_PKT_WORD1          0x0218
  41#define HDMI_SW_DI_1_PKT_WORD2          0x021C
  42#define HDMI_SW_DI_1_PKT_WORD3          0x0220
  43#define HDMI_SW_DI_1_PKT_WORD4          0x0224
  44#define HDMI_SW_DI_1_PKT_WORD5          0x0228
  45#define HDMI_SW_DI_1_PKT_WORD6          0x022C
  46#define HDMI_SW_DI_CFG                  0x0230
  47#define HDMI_SW_DI_2_HEAD_WORD          0x0600
  48#define HDMI_SW_DI_2_PKT_WORD0          0x0604
  49#define HDMI_SW_DI_2_PKT_WORD1          0x0608
  50#define HDMI_SW_DI_2_PKT_WORD2          0x060C
  51#define HDMI_SW_DI_2_PKT_WORD3          0x0610
  52#define HDMI_SW_DI_2_PKT_WORD4          0x0614
  53#define HDMI_SW_DI_2_PKT_WORD5          0x0618
  54#define HDMI_SW_DI_2_PKT_WORD6          0x061C
  55#define HDMI_SW_DI_3_HEAD_WORD          0x0620
  56#define HDMI_SW_DI_3_PKT_WORD0          0x0624
  57#define HDMI_SW_DI_3_PKT_WORD1          0x0628
  58#define HDMI_SW_DI_3_PKT_WORD2          0x062C
  59#define HDMI_SW_DI_3_PKT_WORD3          0x0630
  60#define HDMI_SW_DI_3_PKT_WORD4          0x0634
  61#define HDMI_SW_DI_3_PKT_WORD5          0x0638
  62#define HDMI_SW_DI_3_PKT_WORD6          0x063C
  63
  64#define HDMI_IFRAME_SLOT_AVI            1
  65#define HDMI_IFRAME_SLOT_AUDIO          2
  66#define HDMI_IFRAME_SLOT_VENDOR         3
  67
  68#define  XCAT(prefix, x, suffix)        prefix ## x ## suffix
  69#define  HDMI_SW_DI_N_HEAD_WORD(x)      XCAT(HDMI_SW_DI_, x, _HEAD_WORD)
  70#define  HDMI_SW_DI_N_PKT_WORD0(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD0)
  71#define  HDMI_SW_DI_N_PKT_WORD1(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD1)
  72#define  HDMI_SW_DI_N_PKT_WORD2(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD2)
  73#define  HDMI_SW_DI_N_PKT_WORD3(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD3)
  74#define  HDMI_SW_DI_N_PKT_WORD4(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD4)
  75#define  HDMI_SW_DI_N_PKT_WORD5(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD5)
  76#define  HDMI_SW_DI_N_PKT_WORD6(x)      XCAT(HDMI_SW_DI_, x, _PKT_WORD6)
  77
  78#define HDMI_SW_DI_MAX_WORD             7
  79
  80#define HDMI_IFRAME_DISABLED            0x0
  81#define HDMI_IFRAME_SINGLE_SHOT         0x1
  82#define HDMI_IFRAME_FIELD               0x2
  83#define HDMI_IFRAME_FRAME               0x3
  84#define HDMI_IFRAME_MASK                0x3
  85#define HDMI_IFRAME_CFG_DI_N(x, n)       ((x) << ((n-1)*4)) /* n from 1 to 6 */
  86
  87#define HDMI_CFG_DEVICE_EN              BIT(0)
  88#define HDMI_CFG_HDMI_NOT_DVI           BIT(1)
  89#define HDMI_CFG_HDCP_EN                BIT(2)
  90#define HDMI_CFG_ESS_NOT_OESS           BIT(3)
  91#define HDMI_CFG_H_SYNC_POL_NEG         BIT(4)
  92#define HDMI_CFG_SINK_TERM_DET_EN       BIT(5)
  93#define HDMI_CFG_V_SYNC_POL_NEG         BIT(6)
  94#define HDMI_CFG_422_EN                 BIT(8)
  95#define HDMI_CFG_FIFO_OVERRUN_CLR       BIT(12)
  96#define HDMI_CFG_FIFO_UNDERRUN_CLR      BIT(13)
  97#define HDMI_CFG_SW_RST_EN              BIT(31)
  98
  99#define HDMI_INT_GLOBAL                 BIT(0)
 100#define HDMI_INT_SW_RST                 BIT(1)
 101#define HDMI_INT_PIX_CAP                BIT(3)
 102#define HDMI_INT_HOT_PLUG               BIT(4)
 103#define HDMI_INT_DLL_LCK                BIT(5)
 104#define HDMI_INT_NEW_FRAME              BIT(6)
 105#define HDMI_INT_GENCTRL_PKT            BIT(7)
 106#define HDMI_INT_SINK_TERM_PRESENT      BIT(11)
 107
 108#define HDMI_DEFAULT_INT (HDMI_INT_SINK_TERM_PRESENT \
 109                        | HDMI_INT_DLL_LCK \
 110                        | HDMI_INT_HOT_PLUG \
 111                        | HDMI_INT_GLOBAL)
 112
 113#define HDMI_WORKING_INT (HDMI_INT_SINK_TERM_PRESENT \
 114                        | HDMI_INT_GENCTRL_PKT \
 115                        | HDMI_INT_NEW_FRAME \
 116                        | HDMI_INT_DLL_LCK \
 117                        | HDMI_INT_HOT_PLUG \
 118                        | HDMI_INT_PIX_CAP \
 119                        | HDMI_INT_SW_RST \
 120                        | HDMI_INT_GLOBAL)
 121
 122#define HDMI_STA_SW_RST                 BIT(1)
 123
 124#define HDMI_INFOFRAME_HEADER_TYPE(x)    (((x) & 0xff) <<  0)
 125#define HDMI_INFOFRAME_HEADER_VERSION(x) (((x) & 0xff) <<  8)
 126#define HDMI_INFOFRAME_HEADER_LEN(x)     (((x) & 0x0f) << 16)
 127
 128struct sti_hdmi_connector {
 129        struct drm_connector drm_connector;
 130        struct drm_encoder *encoder;
 131        struct sti_hdmi *hdmi;
 132        struct drm_property *colorspace_property;
 133        struct drm_property *hdmi_mode_property;
 134};
 135
 136#define to_sti_hdmi_connector(x) \
 137        container_of(x, struct sti_hdmi_connector, drm_connector)
 138
 139u32 hdmi_read(struct sti_hdmi *hdmi, int offset)
 140{
 141        return readl(hdmi->regs + offset);
 142}
 143
 144void hdmi_write(struct sti_hdmi *hdmi, u32 val, int offset)
 145{
 146        writel(val, hdmi->regs + offset);
 147}
 148
 149/**
 150 * HDMI interrupt handler threaded
 151 *
 152 * @irq: irq number
 153 * @arg: connector structure
 154 */
 155static irqreturn_t hdmi_irq_thread(int irq, void *arg)
 156{
 157        struct sti_hdmi *hdmi = arg;
 158
 159        /* Hot plug/unplug IRQ */
 160        if (hdmi->irq_status & HDMI_INT_HOT_PLUG) {
 161                hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
 162                if (hdmi->drm_dev)
 163                        drm_helper_hpd_irq_event(hdmi->drm_dev);
 164        }
 165
 166        /* Sw reset and PLL lock are exclusive so we can use the same
 167         * event to signal them
 168         */
 169        if (hdmi->irq_status & (HDMI_INT_SW_RST | HDMI_INT_DLL_LCK)) {
 170                hdmi->event_received = true;
 171                wake_up_interruptible(&hdmi->wait_event);
 172        }
 173
 174        return IRQ_HANDLED;
 175}
 176
 177/**
 178 * HDMI interrupt handler
 179 *
 180 * @irq: irq number
 181 * @arg: connector structure
 182 */
 183static irqreturn_t hdmi_irq(int irq, void *arg)
 184{
 185        struct sti_hdmi *hdmi = arg;
 186
 187        /* read interrupt status */
 188        hdmi->irq_status = hdmi_read(hdmi, HDMI_INT_STA);
 189
 190        /* clear interrupt status */
 191        hdmi_write(hdmi, hdmi->irq_status, HDMI_INT_CLR);
 192
 193        /* force sync bus write */
 194        hdmi_read(hdmi, HDMI_INT_STA);
 195
 196        return IRQ_WAKE_THREAD;
 197}
 198
 199/**
 200 * Set hdmi active area depending on the drm display mode selected
 201 *
 202 * @hdmi: pointer on the hdmi internal structure
 203 */
 204static void hdmi_active_area(struct sti_hdmi *hdmi)
 205{
 206        u32 xmin, xmax;
 207        u32 ymin, ymax;
 208
 209        xmin = sti_vtg_get_pixel_number(hdmi->mode, 1);
 210        xmax = sti_vtg_get_pixel_number(hdmi->mode, hdmi->mode.hdisplay);
 211        ymin = sti_vtg_get_line_number(hdmi->mode, 0);
 212        ymax = sti_vtg_get_line_number(hdmi->mode, hdmi->mode.vdisplay - 1);
 213
 214        hdmi_write(hdmi, xmin, HDMI_ACTIVE_VID_XMIN);
 215        hdmi_write(hdmi, xmax, HDMI_ACTIVE_VID_XMAX);
 216        hdmi_write(hdmi, ymin, HDMI_ACTIVE_VID_YMIN);
 217        hdmi_write(hdmi, ymax, HDMI_ACTIVE_VID_YMAX);
 218}
 219
 220/**
 221 * Overall hdmi configuration
 222 *
 223 * @hdmi: pointer on the hdmi internal structure
 224 */
 225static void hdmi_config(struct sti_hdmi *hdmi)
 226{
 227        u32 conf;
 228
 229        DRM_DEBUG_DRIVER("\n");
 230
 231        /* Clear overrun and underrun fifo */
 232        conf = HDMI_CFG_FIFO_OVERRUN_CLR | HDMI_CFG_FIFO_UNDERRUN_CLR;
 233
 234        /* Select encryption type and the framing mode */
 235        conf |= HDMI_CFG_ESS_NOT_OESS;
 236        if (hdmi->hdmi_mode == HDMI_MODE_HDMI)
 237                conf |= HDMI_CFG_HDMI_NOT_DVI;
 238
 239        /* Enable sink term detection */
 240        conf |= HDMI_CFG_SINK_TERM_DET_EN;
 241
 242        /* Set Hsync polarity */
 243        if (hdmi->mode.flags & DRM_MODE_FLAG_NHSYNC) {
 244                DRM_DEBUG_DRIVER("H Sync Negative\n");
 245                conf |= HDMI_CFG_H_SYNC_POL_NEG;
 246        }
 247
 248        /* Set Vsync polarity */
 249        if (hdmi->mode.flags & DRM_MODE_FLAG_NVSYNC) {
 250                DRM_DEBUG_DRIVER("V Sync Negative\n");
 251                conf |= HDMI_CFG_V_SYNC_POL_NEG;
 252        }
 253
 254        /* Enable HDMI */
 255        conf |= HDMI_CFG_DEVICE_EN;
 256
 257        hdmi_write(hdmi, conf, HDMI_CFG);
 258}
 259
 260/*
 261 * Helper to reset info frame
 262 *
 263 * @hdmi: pointer on the hdmi internal structure
 264 * @slot: infoframe to reset
 265 */
 266static void hdmi_infoframe_reset(struct sti_hdmi *hdmi,
 267                                 u32 slot)
 268{
 269        u32 val, i;
 270        u32 head_offset, pack_offset;
 271
 272        switch (slot) {
 273        case HDMI_IFRAME_SLOT_AVI:
 274                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
 275                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
 276                break;
 277        case HDMI_IFRAME_SLOT_AUDIO:
 278                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
 279                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
 280                break;
 281        case HDMI_IFRAME_SLOT_VENDOR:
 282                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);
 283                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);
 284                break;
 285        default:
 286                DRM_ERROR("unsupported infoframe slot: %#x\n", slot);
 287                return;
 288        }
 289
 290        /* Disable transmission for the selected slot */
 291        val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
 292        val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);
 293        hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
 294
 295        /* Reset info frame registers */
 296        hdmi_write(hdmi, 0x0, head_offset);
 297        for (i = 0; i < HDMI_SW_DI_MAX_WORD; i += sizeof(u32))
 298                hdmi_write(hdmi, 0x0, pack_offset + i);
 299}
 300
 301/**
 302 * Helper to concatenate infoframe in 32 bits word
 303 *
 304 * @ptr: pointer on the hdmi internal structure
 305 * @data: infoframe to write
 306 * @size: size to write
 307 */
 308static inline unsigned int hdmi_infoframe_subpack(const u8 *ptr, size_t size)
 309{
 310        unsigned long value = 0;
 311        size_t i;
 312
 313        for (i = size; i > 0; i--)
 314                value = (value << 8) | ptr[i - 1];
 315
 316        return value;
 317}
 318
 319/**
 320 * Helper to write info frame
 321 *
 322 * @hdmi: pointer on the hdmi internal structure
 323 * @data: infoframe to write
 324 * @size: size to write
 325 */
 326static void hdmi_infoframe_write_infopack(struct sti_hdmi *hdmi,
 327                                          const u8 *data,
 328                                          size_t size)
 329{
 330        const u8 *ptr = data;
 331        u32 val, slot, mode, i;
 332        u32 head_offset, pack_offset;
 333
 334        switch (*ptr) {
 335        case HDMI_INFOFRAME_TYPE_AVI:
 336                slot = HDMI_IFRAME_SLOT_AVI;
 337                mode = HDMI_IFRAME_FIELD;
 338                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AVI);
 339                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AVI);
 340                break;
 341        case HDMI_INFOFRAME_TYPE_AUDIO:
 342                slot = HDMI_IFRAME_SLOT_AUDIO;
 343                mode = HDMI_IFRAME_FRAME;
 344                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_AUDIO);
 345                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_AUDIO);
 346                break;
 347        case HDMI_INFOFRAME_TYPE_VENDOR:
 348                slot = HDMI_IFRAME_SLOT_VENDOR;
 349                mode = HDMI_IFRAME_FRAME;
 350                head_offset = HDMI_SW_DI_N_HEAD_WORD(HDMI_IFRAME_SLOT_VENDOR);
 351                pack_offset = HDMI_SW_DI_N_PKT_WORD0(HDMI_IFRAME_SLOT_VENDOR);
 352                break;
 353        default:
 354                DRM_ERROR("unsupported infoframe type: %#x\n", *ptr);
 355                return;
 356        }
 357
 358        /* Disable transmission slot for updated infoframe */
 359        val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
 360        val &= ~HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, slot);
 361        hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
 362
 363        val = HDMI_INFOFRAME_HEADER_TYPE(*ptr++);
 364        val |= HDMI_INFOFRAME_HEADER_VERSION(*ptr++);
 365        val |= HDMI_INFOFRAME_HEADER_LEN(*ptr++);
 366        writel(val, hdmi->regs + head_offset);
 367
 368        /*
 369         * Each subpack contains 4 bytes
 370         * The First Bytes of the first subpacket must contain the checksum
 371         * Packet size is increase by one.
 372         */
 373        size = size - HDMI_INFOFRAME_HEADER_SIZE + 1;
 374        for (i = 0; i < size; i += sizeof(u32)) {
 375                size_t num;
 376
 377                num = min_t(size_t, size - i, sizeof(u32));
 378                val = hdmi_infoframe_subpack(ptr, num);
 379                ptr += sizeof(u32);
 380                writel(val, hdmi->regs + pack_offset + i);
 381        }
 382
 383        /* Enable transmission slot for updated infoframe */
 384        val = hdmi_read(hdmi, HDMI_SW_DI_CFG);
 385        val |= HDMI_IFRAME_CFG_DI_N(mode, slot);
 386        hdmi_write(hdmi, val, HDMI_SW_DI_CFG);
 387}
 388
 389/**
 390 * Prepare and configure the AVI infoframe
 391 *
 392 * AVI infoframe are transmitted at least once per two video field and
 393 * contains information about HDMI transmission mode such as color space,
 394 * colorimetry, ...
 395 *
 396 * @hdmi: pointer on the hdmi internal structure
 397 *
 398 * Return negative value if error occurs
 399 */
 400static int hdmi_avi_infoframe_config(struct sti_hdmi *hdmi)
 401{
 402        struct drm_display_mode *mode = &hdmi->mode;
 403        struct hdmi_avi_infoframe infoframe;
 404        u8 buffer[HDMI_INFOFRAME_SIZE(AVI)];
 405        int ret;
 406
 407        DRM_DEBUG_DRIVER("\n");
 408
 409        ret = drm_hdmi_avi_infoframe_from_display_mode(&infoframe, mode);
 410        if (ret < 0) {
 411                DRM_ERROR("failed to setup AVI infoframe: %d\n", ret);
 412                return ret;
 413        }
 414
 415        /* fixed infoframe configuration not linked to the mode */
 416        infoframe.colorspace = hdmi->colorspace;
 417        infoframe.quantization_range = HDMI_QUANTIZATION_RANGE_DEFAULT;
 418        infoframe.colorimetry = HDMI_COLORIMETRY_NONE;
 419
 420        ret = hdmi_avi_infoframe_pack(&infoframe, buffer, sizeof(buffer));
 421        if (ret < 0) {
 422                DRM_ERROR("failed to pack AVI infoframe: %d\n", ret);
 423                return ret;
 424        }
 425
 426        hdmi_infoframe_write_infopack(hdmi, buffer, ret);
 427
 428        return 0;
 429}
 430
 431/**
 432 * Prepare and configure the AUDIO infoframe
 433 *
 434 * AUDIO infoframe are transmitted once per frame and
 435 * contains information about HDMI transmission mode such as audio codec,
 436 * sample size, ...
 437 *
 438 * @hdmi: pointer on the hdmi internal structure
 439 *
 440 * Return negative value if error occurs
 441 */
 442static int hdmi_audio_infoframe_config(struct sti_hdmi *hdmi)
 443{
 444        struct hdmi_audio_infoframe infofame;
 445        u8 buffer[HDMI_INFOFRAME_SIZE(AUDIO)];
 446        int ret;
 447
 448        ret = hdmi_audio_infoframe_init(&infofame);
 449        if (ret < 0) {
 450                DRM_ERROR("failed to setup audio infoframe: %d\n", ret);
 451                return ret;
 452        }
 453
 454        infofame.channels = 2;
 455
 456        ret = hdmi_audio_infoframe_pack(&infofame, buffer, sizeof(buffer));
 457        if (ret < 0) {
 458                DRM_ERROR("failed to pack audio infoframe: %d\n", ret);
 459                return ret;
 460        }
 461
 462        hdmi_infoframe_write_infopack(hdmi, buffer, ret);
 463
 464        return 0;
 465}
 466
 467/*
 468 * Prepare and configure the VS infoframe
 469 *
 470 * Vendor Specific infoframe are transmitted once per frame and
 471 * contains vendor specific information.
 472 *
 473 * @hdmi: pointer on the hdmi internal structure
 474 *
 475 * Return negative value if error occurs
 476 */
 477#define HDMI_VENDOR_INFOFRAME_MAX_SIZE 6
 478static int hdmi_vendor_infoframe_config(struct sti_hdmi *hdmi)
 479{
 480        struct drm_display_mode *mode = &hdmi->mode;
 481        struct hdmi_vendor_infoframe infoframe;
 482        u8 buffer[HDMI_INFOFRAME_HEADER_SIZE + HDMI_VENDOR_INFOFRAME_MAX_SIZE];
 483        int ret;
 484
 485        DRM_DEBUG_DRIVER("\n");
 486
 487        ret = drm_hdmi_vendor_infoframe_from_display_mode(&infoframe, mode);
 488        if (ret < 0) {
 489                /*
 490                 * Going into that statement does not means vendor infoframe
 491                 * fails. It just informed us that vendor infoframe is not
 492                 * needed for the selected mode. Only  4k or stereoscopic 3D
 493                 * mode requires vendor infoframe. So just simply return 0.
 494                 */
 495                return 0;
 496        }
 497
 498        ret = hdmi_vendor_infoframe_pack(&infoframe, buffer, sizeof(buffer));
 499        if (ret < 0) {
 500                DRM_ERROR("failed to pack VS infoframe: %d\n", ret);
 501                return ret;
 502        }
 503
 504        hdmi_infoframe_write_infopack(hdmi, buffer, ret);
 505
 506        return 0;
 507}
 508
 509/**
 510 * Software reset of the hdmi subsystem
 511 *
 512 * @hdmi: pointer on the hdmi internal structure
 513 *
 514 */
 515#define HDMI_TIMEOUT_SWRESET  100   /*milliseconds */
 516static void hdmi_swreset(struct sti_hdmi *hdmi)
 517{
 518        u32 val;
 519
 520        DRM_DEBUG_DRIVER("\n");
 521
 522        /* Enable hdmi_audio clock only during hdmi reset */
 523        if (clk_prepare_enable(hdmi->clk_audio))
 524                DRM_INFO("Failed to prepare/enable hdmi_audio clk\n");
 525
 526        /* Sw reset */
 527        hdmi->event_received = false;
 528
 529        val = hdmi_read(hdmi, HDMI_CFG);
 530        val |= HDMI_CFG_SW_RST_EN;
 531        hdmi_write(hdmi, val, HDMI_CFG);
 532
 533        /* Wait reset completed */
 534        wait_event_interruptible_timeout(hdmi->wait_event,
 535                                         hdmi->event_received == true,
 536                                         msecs_to_jiffies
 537                                         (HDMI_TIMEOUT_SWRESET));
 538
 539        /*
 540         * HDMI_STA_SW_RST bit is set to '1' when SW_RST bit in HDMI_CFG is
 541         * set to '1' and clk_audio is running.
 542         */
 543        if ((hdmi_read(hdmi, HDMI_STA) & HDMI_STA_SW_RST) == 0)
 544                DRM_DEBUG_DRIVER("Warning: HDMI sw reset timeout occurs\n");
 545
 546        val = hdmi_read(hdmi, HDMI_CFG);
 547        val &= ~HDMI_CFG_SW_RST_EN;
 548        hdmi_write(hdmi, val, HDMI_CFG);
 549
 550        /* Disable hdmi_audio clock. Not used anymore for drm purpose */
 551        clk_disable_unprepare(hdmi->clk_audio);
 552}
 553
 554#define DBGFS_PRINT_STR(str1, str2) seq_printf(s, "%-24s %s\n", str1, str2)
 555#define DBGFS_PRINT_INT(str1, int2) seq_printf(s, "%-24s %d\n", str1, int2)
 556#define DBGFS_DUMP(str, reg) seq_printf(s, "%s  %-25s 0x%08X", str, #reg, \
 557                                        hdmi_read(hdmi, reg))
 558#define DBGFS_DUMP_DI(reg, slot) DBGFS_DUMP("\n", reg(slot))
 559
 560static void hdmi_dbg_cfg(struct seq_file *s, int val)
 561{
 562        int tmp;
 563
 564        seq_puts(s, "\t");
 565        tmp = val & HDMI_CFG_HDMI_NOT_DVI;
 566        DBGFS_PRINT_STR("mode:", tmp ? "HDMI" : "DVI");
 567        seq_puts(s, "\t\t\t\t\t");
 568        tmp = val & HDMI_CFG_HDCP_EN;
 569        DBGFS_PRINT_STR("HDCP:", tmp ? "enable" : "disable");
 570        seq_puts(s, "\t\t\t\t\t");
 571        tmp = val & HDMI_CFG_ESS_NOT_OESS;
 572        DBGFS_PRINT_STR("HDCP mode:", tmp ? "ESS enable" : "OESS enable");
 573        seq_puts(s, "\t\t\t\t\t");
 574        tmp = val & HDMI_CFG_SINK_TERM_DET_EN;
 575        DBGFS_PRINT_STR("Sink term detection:", tmp ? "enable" : "disable");
 576        seq_puts(s, "\t\t\t\t\t");
 577        tmp = val & HDMI_CFG_H_SYNC_POL_NEG;
 578        DBGFS_PRINT_STR("Hsync polarity:", tmp ? "inverted" : "normal");
 579        seq_puts(s, "\t\t\t\t\t");
 580        tmp = val & HDMI_CFG_V_SYNC_POL_NEG;
 581        DBGFS_PRINT_STR("Vsync polarity:", tmp ? "inverted" : "normal");
 582        seq_puts(s, "\t\t\t\t\t");
 583        tmp = val & HDMI_CFG_422_EN;
 584        DBGFS_PRINT_STR("YUV422 format:", tmp ? "enable" : "disable");
 585}
 586
 587static void hdmi_dbg_sta(struct seq_file *s, int val)
 588{
 589        int tmp;
 590
 591        seq_puts(s, "\t");
 592        tmp = (val & HDMI_STA_DLL_LCK);
 593        DBGFS_PRINT_STR("pll:", tmp ? "locked" : "not locked");
 594        seq_puts(s, "\t\t\t\t\t");
 595        tmp = (val & HDMI_STA_HOT_PLUG);
 596        DBGFS_PRINT_STR("hdmi cable:", tmp ? "connected" : "not connected");
 597}
 598
 599static void hdmi_dbg_sw_di_cfg(struct seq_file *s, int val)
 600{
 601        int tmp;
 602        char *const en_di[] = {"no transmission",
 603                               "single transmission",
 604                               "once every field",
 605                               "once every frame"};
 606
 607        seq_puts(s, "\t");
 608        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 1));
 609        DBGFS_PRINT_STR("Data island 1:", en_di[tmp]);
 610        seq_puts(s, "\t\t\t\t\t");
 611        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 2)) >> 4;
 612        DBGFS_PRINT_STR("Data island 2:", en_di[tmp]);
 613        seq_puts(s, "\t\t\t\t\t");
 614        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 3)) >> 8;
 615        DBGFS_PRINT_STR("Data island 3:", en_di[tmp]);
 616        seq_puts(s, "\t\t\t\t\t");
 617        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 4)) >> 12;
 618        DBGFS_PRINT_STR("Data island 4:", en_di[tmp]);
 619        seq_puts(s, "\t\t\t\t\t");
 620        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 5)) >> 16;
 621        DBGFS_PRINT_STR("Data island 5:", en_di[tmp]);
 622        seq_puts(s, "\t\t\t\t\t");
 623        tmp = (val & HDMI_IFRAME_CFG_DI_N(HDMI_IFRAME_MASK, 6)) >> 20;
 624        DBGFS_PRINT_STR("Data island 6:", en_di[tmp]);
 625}
 626
 627static int hdmi_dbg_show(struct seq_file *s, void *data)
 628{
 629        struct drm_info_node *node = s->private;
 630        struct sti_hdmi *hdmi = (struct sti_hdmi *)node->info_ent->data;
 631        struct drm_device *dev = node->minor->dev;
 632        int ret;
 633
 634        ret = mutex_lock_interruptible(&dev->struct_mutex);
 635        if (ret)
 636                return ret;
 637
 638        seq_printf(s, "HDMI: (vaddr = 0x%p)", hdmi->regs);
 639        DBGFS_DUMP("\n", HDMI_CFG);
 640        hdmi_dbg_cfg(s, hdmi_read(hdmi, HDMI_CFG));
 641        DBGFS_DUMP("", HDMI_INT_EN);
 642        DBGFS_DUMP("\n", HDMI_STA);
 643        hdmi_dbg_sta(s, hdmi_read(hdmi, HDMI_STA));
 644        DBGFS_DUMP("", HDMI_ACTIVE_VID_XMIN);
 645        seq_puts(s, "\t");
 646        DBGFS_PRINT_INT("Xmin:", hdmi_read(hdmi, HDMI_ACTIVE_VID_XMIN));
 647        DBGFS_DUMP("", HDMI_ACTIVE_VID_XMAX);
 648        seq_puts(s, "\t");
 649        DBGFS_PRINT_INT("Xmax:", hdmi_read(hdmi, HDMI_ACTIVE_VID_XMAX));
 650        DBGFS_DUMP("", HDMI_ACTIVE_VID_YMIN);
 651        seq_puts(s, "\t");
 652        DBGFS_PRINT_INT("Ymin:", hdmi_read(hdmi, HDMI_ACTIVE_VID_YMIN));
 653        DBGFS_DUMP("", HDMI_ACTIVE_VID_YMAX);
 654        seq_puts(s, "\t");
 655        DBGFS_PRINT_INT("Ymax:", hdmi_read(hdmi, HDMI_ACTIVE_VID_YMAX));
 656        DBGFS_DUMP("", HDMI_SW_DI_CFG);
 657        hdmi_dbg_sw_di_cfg(s, hdmi_read(hdmi, HDMI_SW_DI_CFG));
 658
 659        seq_printf(s, "\n AVI Infoframe (Data Island slot N=%d):",
 660                   HDMI_IFRAME_SLOT_AVI);
 661        DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AVI);
 662        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_AVI);
 663        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_AVI);
 664        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_AVI);
 665        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_AVI);
 666        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_AVI);
 667        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_AVI);
 668        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_AVI);
 669        seq_puts(s, "\n");
 670        seq_printf(s, "\n AUDIO Infoframe (Data Island slot N=%d):",
 671                   HDMI_IFRAME_SLOT_AUDIO);
 672        DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_AUDIO);
 673        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_AUDIO);
 674        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_AUDIO);
 675        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_AUDIO);
 676        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_AUDIO);
 677        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_AUDIO);
 678        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_AUDIO);
 679        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_AUDIO);
 680        seq_puts(s, "\n");
 681        seq_printf(s, "\n VENDOR SPECIFIC Infoframe (Data Island slot N=%d):",
 682                   HDMI_IFRAME_SLOT_VENDOR);
 683        DBGFS_DUMP_DI(HDMI_SW_DI_N_HEAD_WORD, HDMI_IFRAME_SLOT_VENDOR);
 684        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD0, HDMI_IFRAME_SLOT_VENDOR);
 685        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD1, HDMI_IFRAME_SLOT_VENDOR);
 686        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD2, HDMI_IFRAME_SLOT_VENDOR);
 687        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD3, HDMI_IFRAME_SLOT_VENDOR);
 688        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD4, HDMI_IFRAME_SLOT_VENDOR);
 689        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD5, HDMI_IFRAME_SLOT_VENDOR);
 690        DBGFS_DUMP_DI(HDMI_SW_DI_N_PKT_WORD6, HDMI_IFRAME_SLOT_VENDOR);
 691        seq_puts(s, "\n");
 692
 693        mutex_unlock(&dev->struct_mutex);
 694        return 0;
 695}
 696
 697static struct drm_info_list hdmi_debugfs_files[] = {
 698        { "hdmi", hdmi_dbg_show, 0, NULL },
 699};
 700
 701static void hdmi_debugfs_exit(struct sti_hdmi *hdmi, struct drm_minor *minor)
 702{
 703        drm_debugfs_remove_files(hdmi_debugfs_files,
 704                                 ARRAY_SIZE(hdmi_debugfs_files),
 705                                 minor);
 706}
 707
 708static int hdmi_debugfs_init(struct sti_hdmi *hdmi, struct drm_minor *minor)
 709{
 710        unsigned int i;
 711
 712        for (i = 0; i < ARRAY_SIZE(hdmi_debugfs_files); i++)
 713                hdmi_debugfs_files[i].data = hdmi;
 714
 715        return drm_debugfs_create_files(hdmi_debugfs_files,
 716                                        ARRAY_SIZE(hdmi_debugfs_files),
 717                                        minor->debugfs_root, minor);
 718}
 719
 720static void sti_hdmi_disable(struct drm_bridge *bridge)
 721{
 722        struct sti_hdmi *hdmi = bridge->driver_private;
 723
 724        u32 val = hdmi_read(hdmi, HDMI_CFG);
 725
 726        if (!hdmi->enabled)
 727                return;
 728
 729        DRM_DEBUG_DRIVER("\n");
 730
 731        /* Disable HDMI */
 732        val &= ~HDMI_CFG_DEVICE_EN;
 733        hdmi_write(hdmi, val, HDMI_CFG);
 734
 735        hdmi_write(hdmi, 0xffffffff, HDMI_INT_CLR);
 736
 737        /* Stop the phy */
 738        hdmi->phy_ops->stop(hdmi);
 739
 740        /* Reset info frame transmission */
 741        hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AVI);
 742        hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_AUDIO);
 743        hdmi_infoframe_reset(hdmi, HDMI_IFRAME_SLOT_VENDOR);
 744
 745        /* Set the default channel data to be a dark red */
 746        hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL0_DAT);
 747        hdmi_write(hdmi, 0x0000, HDMI_DFLT_CHL1_DAT);
 748        hdmi_write(hdmi, 0x0060, HDMI_DFLT_CHL2_DAT);
 749
 750        /* Disable/unprepare hdmi clock */
 751        clk_disable_unprepare(hdmi->clk_phy);
 752        clk_disable_unprepare(hdmi->clk_tmds);
 753        clk_disable_unprepare(hdmi->clk_pix);
 754
 755        hdmi->enabled = false;
 756}
 757
 758static void sti_hdmi_pre_enable(struct drm_bridge *bridge)
 759{
 760        struct sti_hdmi *hdmi = bridge->driver_private;
 761
 762        DRM_DEBUG_DRIVER("\n");
 763
 764        if (hdmi->enabled)
 765                return;
 766
 767        /* Prepare/enable clocks */
 768        if (clk_prepare_enable(hdmi->clk_pix))
 769                DRM_ERROR("Failed to prepare/enable hdmi_pix clk\n");
 770        if (clk_prepare_enable(hdmi->clk_tmds))
 771                DRM_ERROR("Failed to prepare/enable hdmi_tmds clk\n");
 772        if (clk_prepare_enable(hdmi->clk_phy))
 773                DRM_ERROR("Failed to prepare/enable hdmi_rejec_pll clk\n");
 774
 775        hdmi->enabled = true;
 776
 777        /* Program hdmi serializer and start phy */
 778        if (!hdmi->phy_ops->start(hdmi)) {
 779                DRM_ERROR("Unable to start hdmi phy\n");
 780                return;
 781        }
 782
 783        /* Program hdmi active area */
 784        hdmi_active_area(hdmi);
 785
 786        /* Enable working interrupts */
 787        hdmi_write(hdmi, HDMI_WORKING_INT, HDMI_INT_EN);
 788
 789        /* Program hdmi config */
 790        hdmi_config(hdmi);
 791
 792        /* Program AVI infoframe */
 793        if (hdmi_avi_infoframe_config(hdmi))
 794                DRM_ERROR("Unable to configure AVI infoframe\n");
 795
 796        /* Program AUDIO infoframe */
 797        if (hdmi_audio_infoframe_config(hdmi))
 798                DRM_ERROR("Unable to configure AUDIO infoframe\n");
 799
 800        /* Program VS infoframe */
 801        if (hdmi_vendor_infoframe_config(hdmi))
 802                DRM_ERROR("Unable to configure VS infoframe\n");
 803
 804        /* Sw reset */
 805        hdmi_swreset(hdmi);
 806}
 807
 808static void sti_hdmi_set_mode(struct drm_bridge *bridge,
 809                struct drm_display_mode *mode,
 810                struct drm_display_mode *adjusted_mode)
 811{
 812        struct sti_hdmi *hdmi = bridge->driver_private;
 813        int ret;
 814
 815        DRM_DEBUG_DRIVER("\n");
 816
 817        /* Copy the drm display mode in the connector local structure */
 818        memcpy(&hdmi->mode, mode, sizeof(struct drm_display_mode));
 819
 820        /* Update clock framerate according to the selected mode */
 821        ret = clk_set_rate(hdmi->clk_pix, mode->clock * 1000);
 822        if (ret < 0) {
 823                DRM_ERROR("Cannot set rate (%dHz) for hdmi_pix clk\n",
 824                          mode->clock * 1000);
 825                return;
 826        }
 827        ret = clk_set_rate(hdmi->clk_phy, mode->clock * 1000);
 828        if (ret < 0) {
 829                DRM_ERROR("Cannot set rate (%dHz) for hdmi_rejection_pll clk\n",
 830                          mode->clock * 1000);
 831                return;
 832        }
 833}
 834
 835static void sti_hdmi_bridge_nope(struct drm_bridge *bridge)
 836{
 837        /* do nothing */
 838}
 839
 840static const struct drm_bridge_funcs sti_hdmi_bridge_funcs = {
 841        .pre_enable = sti_hdmi_pre_enable,
 842        .enable = sti_hdmi_bridge_nope,
 843        .disable = sti_hdmi_disable,
 844        .post_disable = sti_hdmi_bridge_nope,
 845        .mode_set = sti_hdmi_set_mode,
 846};
 847
 848static int sti_hdmi_connector_get_modes(struct drm_connector *connector)
 849{
 850        struct sti_hdmi_connector *hdmi_connector
 851                = to_sti_hdmi_connector(connector);
 852        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
 853        struct edid *edid;
 854        int count;
 855
 856        DRM_DEBUG_DRIVER("\n");
 857
 858        edid = drm_get_edid(connector, hdmi->ddc_adapt);
 859        if (!edid)
 860                goto fail;
 861
 862        count = drm_add_edid_modes(connector, edid);
 863        drm_mode_connector_update_edid_property(connector, edid);
 864
 865        kfree(edid);
 866        return count;
 867
 868fail:
 869        DRM_ERROR("Can't read HDMI EDID\n");
 870        return 0;
 871}
 872
 873#define CLK_TOLERANCE_HZ 50
 874
 875static int sti_hdmi_connector_mode_valid(struct drm_connector *connector,
 876                                        struct drm_display_mode *mode)
 877{
 878        int target = mode->clock * 1000;
 879        int target_min = target - CLK_TOLERANCE_HZ;
 880        int target_max = target + CLK_TOLERANCE_HZ;
 881        int result;
 882        struct sti_hdmi_connector *hdmi_connector
 883                = to_sti_hdmi_connector(connector);
 884        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
 885
 886
 887        result = clk_round_rate(hdmi->clk_pix, target);
 888
 889        DRM_DEBUG_DRIVER("target rate = %d => available rate = %d\n",
 890                         target, result);
 891
 892        if ((result < target_min) || (result > target_max)) {
 893                DRM_DEBUG_DRIVER("hdmi pixclk=%d not supported\n", target);
 894                return MODE_BAD;
 895        }
 896
 897        return MODE_OK;
 898}
 899
 900struct drm_encoder *sti_hdmi_best_encoder(struct drm_connector *connector)
 901{
 902        struct sti_hdmi_connector *hdmi_connector
 903                = to_sti_hdmi_connector(connector);
 904
 905        /* Best encoder is the one associated during connector creation */
 906        return hdmi_connector->encoder;
 907}
 908
 909static const
 910struct drm_connector_helper_funcs sti_hdmi_connector_helper_funcs = {
 911        .get_modes = sti_hdmi_connector_get_modes,
 912        .mode_valid = sti_hdmi_connector_mode_valid,
 913        .best_encoder = sti_hdmi_best_encoder,
 914};
 915
 916/* get detection status of display device */
 917static enum drm_connector_status
 918sti_hdmi_connector_detect(struct drm_connector *connector, bool force)
 919{
 920        struct sti_hdmi_connector *hdmi_connector
 921                = to_sti_hdmi_connector(connector);
 922        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
 923
 924        DRM_DEBUG_DRIVER("\n");
 925
 926        if (hdmi->hpd) {
 927                DRM_DEBUG_DRIVER("hdmi cable connected\n");
 928                return connector_status_connected;
 929        }
 930
 931        DRM_DEBUG_DRIVER("hdmi cable disconnected\n");
 932        return connector_status_disconnected;
 933}
 934
 935static void sti_hdmi_connector_destroy(struct drm_connector *connector)
 936{
 937        struct sti_hdmi_connector *hdmi_connector
 938                = to_sti_hdmi_connector(connector);
 939
 940        drm_connector_unregister(connector);
 941        drm_connector_cleanup(connector);
 942        kfree(hdmi_connector);
 943}
 944
 945static void sti_hdmi_connector_init_property(struct drm_device *drm_dev,
 946                                             struct drm_connector *connector)
 947{
 948        struct sti_hdmi_connector *hdmi_connector
 949                = to_sti_hdmi_connector(connector);
 950        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
 951        struct drm_property *prop;
 952
 953        /* colorspace property */
 954        hdmi->colorspace = DEFAULT_COLORSPACE_MODE;
 955        prop = drm_property_create_enum(drm_dev, 0, "colorspace",
 956                                        colorspace_mode_names,
 957                                        ARRAY_SIZE(colorspace_mode_names));
 958        if (!prop) {
 959                DRM_ERROR("fails to create colorspace property\n");
 960                return;
 961        }
 962        hdmi_connector->colorspace_property = prop;
 963        drm_object_attach_property(&connector->base, prop, hdmi->colorspace);
 964
 965        /* hdmi_mode property */
 966        hdmi->hdmi_mode = DEFAULT_HDMI_MODE;
 967        prop = drm_property_create_enum(drm_dev, 0, "hdmi_mode",
 968                                        hdmi_mode_names,
 969                                        ARRAY_SIZE(hdmi_mode_names));
 970        if (!prop) {
 971                DRM_ERROR("fails to create colorspace property\n");
 972                return;
 973        }
 974        hdmi_connector->hdmi_mode_property = prop;
 975        drm_object_attach_property(&connector->base, prop, hdmi->hdmi_mode);
 976
 977}
 978
 979static int
 980sti_hdmi_connector_set_property(struct drm_connector *connector,
 981                                struct drm_connector_state *state,
 982                                struct drm_property *property,
 983                                uint64_t val)
 984{
 985        struct sti_hdmi_connector *hdmi_connector
 986                = to_sti_hdmi_connector(connector);
 987        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
 988
 989        if (property == hdmi_connector->colorspace_property) {
 990                hdmi->colorspace = val;
 991                return 0;
 992        }
 993
 994        if (property == hdmi_connector->hdmi_mode_property) {
 995                hdmi->hdmi_mode = val;
 996                return 0;
 997        }
 998
 999        DRM_ERROR("failed to set hdmi connector property\n");
1000        return -EINVAL;
1001}
1002
1003static int
1004sti_hdmi_connector_get_property(struct drm_connector *connector,
1005                                const struct drm_connector_state *state,
1006                                struct drm_property *property,
1007                                uint64_t *val)
1008{
1009        struct sti_hdmi_connector *hdmi_connector
1010                = to_sti_hdmi_connector(connector);
1011        struct sti_hdmi *hdmi = hdmi_connector->hdmi;
1012
1013        if (property == hdmi_connector->colorspace_property) {
1014                *val = hdmi->colorspace;
1015                return 0;
1016        }
1017
1018        if (property == hdmi_connector->hdmi_mode_property) {
1019                *val = hdmi->hdmi_mode;
1020                return 0;
1021        }
1022
1023        DRM_ERROR("failed to get hdmi connector property\n");
1024        return -EINVAL;
1025}
1026
1027static const struct drm_connector_funcs sti_hdmi_connector_funcs = {
1028        .dpms = drm_atomic_helper_connector_dpms,
1029        .fill_modes = drm_helper_probe_single_connector_modes,
1030        .detect = sti_hdmi_connector_detect,
1031        .destroy = sti_hdmi_connector_destroy,
1032        .reset = drm_atomic_helper_connector_reset,
1033        .set_property = drm_atomic_helper_connector_set_property,
1034        .atomic_set_property = sti_hdmi_connector_set_property,
1035        .atomic_get_property = sti_hdmi_connector_get_property,
1036        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
1037        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
1038};
1039
1040static struct drm_encoder *sti_hdmi_find_encoder(struct drm_device *dev)
1041{
1042        struct drm_encoder *encoder;
1043
1044        list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) {
1045                if (encoder->encoder_type == DRM_MODE_ENCODER_TMDS)
1046                        return encoder;
1047        }
1048
1049        return NULL;
1050}
1051
1052static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
1053{
1054        struct sti_hdmi *hdmi = dev_get_drvdata(dev);
1055        struct drm_device *drm_dev = data;
1056        struct drm_encoder *encoder;
1057        struct sti_hdmi_connector *connector;
1058        struct drm_connector *drm_connector;
1059        struct drm_bridge *bridge;
1060        int err;
1061
1062        /* Set the drm device handle */
1063        hdmi->drm_dev = drm_dev;
1064
1065        encoder = sti_hdmi_find_encoder(drm_dev);
1066        if (!encoder)
1067                return -EINVAL;
1068
1069        connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL);
1070        if (!connector)
1071                return -EINVAL;
1072
1073        connector->hdmi = hdmi;
1074
1075        bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL);
1076        if (!bridge)
1077                return -EINVAL;
1078
1079        bridge->driver_private = hdmi;
1080        bridge->funcs = &sti_hdmi_bridge_funcs;
1081        drm_bridge_attach(drm_dev, bridge);
1082
1083        encoder->bridge = bridge;
1084        connector->encoder = encoder;
1085
1086        drm_connector = (struct drm_connector *)connector;
1087
1088        drm_connector->polled = DRM_CONNECTOR_POLL_HPD;
1089
1090        drm_connector_init(drm_dev, drm_connector,
1091                        &sti_hdmi_connector_funcs, DRM_MODE_CONNECTOR_HDMIA);
1092        drm_connector_helper_add(drm_connector,
1093                        &sti_hdmi_connector_helper_funcs);
1094
1095        /* initialise property */
1096        sti_hdmi_connector_init_property(drm_dev, drm_connector);
1097
1098        err = drm_connector_register(drm_connector);
1099        if (err)
1100                goto err_connector;
1101
1102        err = drm_mode_connector_attach_encoder(drm_connector, encoder);
1103        if (err) {
1104                DRM_ERROR("Failed to attach a connector to a encoder\n");
1105                goto err_sysfs;
1106        }
1107
1108        /* Enable default interrupts */
1109        hdmi_write(hdmi, HDMI_DEFAULT_INT, HDMI_INT_EN);
1110
1111        if (hdmi_debugfs_init(hdmi, drm_dev->primary))
1112                DRM_ERROR("HDMI debugfs setup failed\n");
1113
1114        return 0;
1115
1116err_sysfs:
1117        drm_connector_unregister(drm_connector);
1118err_connector:
1119        drm_connector_cleanup(drm_connector);
1120
1121        return -EINVAL;
1122}
1123
1124static void sti_hdmi_unbind(struct device *dev,
1125                struct device *master, void *data)
1126{
1127        struct sti_hdmi *hdmi = dev_get_drvdata(dev);
1128        struct drm_device *drm_dev = data;
1129
1130        hdmi_debugfs_exit(hdmi, drm_dev->primary);
1131}
1132
1133static const struct component_ops sti_hdmi_ops = {
1134        .bind = sti_hdmi_bind,
1135        .unbind = sti_hdmi_unbind,
1136};
1137
1138static const struct of_device_id hdmi_of_match[] = {
1139        {
1140                .compatible = "st,stih416-hdmi",
1141                .data = &tx3g0c55phy_ops,
1142        }, {
1143                .compatible = "st,stih407-hdmi",
1144                .data = &tx3g4c28phy_ops,
1145        }, {
1146                /* end node */
1147        }
1148};
1149MODULE_DEVICE_TABLE(of, hdmi_of_match);
1150
1151static int sti_hdmi_probe(struct platform_device *pdev)
1152{
1153        struct device *dev = &pdev->dev;
1154        struct sti_hdmi *hdmi;
1155        struct device_node *np = dev->of_node;
1156        struct resource *res;
1157        struct device_node *ddc;
1158        int ret;
1159
1160        DRM_INFO("%s\n", __func__);
1161
1162        hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
1163        if (!hdmi)
1164                return -ENOMEM;
1165
1166        ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0);
1167        if (ddc) {
1168                hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
1169                of_node_put(ddc);
1170                if (!hdmi->ddc_adapt)
1171                        return -EPROBE_DEFER;
1172        }
1173
1174        hdmi->dev = pdev->dev;
1175
1176        /* Get resources */
1177        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg");
1178        if (!res) {
1179                DRM_ERROR("Invalid hdmi resource\n");
1180                ret = -ENOMEM;
1181                goto release_adapter;
1182        }
1183        hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res));
1184        if (!hdmi->regs) {
1185                ret = -ENOMEM;
1186                goto release_adapter;
1187        }
1188
1189        if (of_device_is_compatible(np, "st,stih416-hdmi")) {
1190                res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
1191                                                   "syscfg");
1192                if (!res) {
1193                        DRM_ERROR("Invalid syscfg resource\n");
1194                        ret = -ENOMEM;
1195                        goto release_adapter;
1196                }
1197                hdmi->syscfg = devm_ioremap_nocache(dev, res->start,
1198                                                    resource_size(res));
1199                if (!hdmi->syscfg) {
1200                        ret = -ENOMEM;
1201                        goto release_adapter;
1202                }
1203        }
1204
1205        hdmi->phy_ops = (struct hdmi_phy_ops *)
1206                of_match_node(hdmi_of_match, np)->data;
1207
1208        /* Get clock resources */
1209        hdmi->clk_pix = devm_clk_get(dev, "pix");
1210        if (IS_ERR(hdmi->clk_pix)) {
1211                DRM_ERROR("Cannot get hdmi_pix clock\n");
1212                ret = PTR_ERR(hdmi->clk_pix);
1213                goto release_adapter;
1214        }
1215
1216        hdmi->clk_tmds = devm_clk_get(dev, "tmds");
1217        if (IS_ERR(hdmi->clk_tmds)) {
1218                DRM_ERROR("Cannot get hdmi_tmds clock\n");
1219                ret = PTR_ERR(hdmi->clk_tmds);
1220                goto release_adapter;
1221        }
1222
1223        hdmi->clk_phy = devm_clk_get(dev, "phy");
1224        if (IS_ERR(hdmi->clk_phy)) {
1225                DRM_ERROR("Cannot get hdmi_phy clock\n");
1226                ret = PTR_ERR(hdmi->clk_phy);
1227                goto release_adapter;
1228        }
1229
1230        hdmi->clk_audio = devm_clk_get(dev, "audio");
1231        if (IS_ERR(hdmi->clk_audio)) {
1232                DRM_ERROR("Cannot get hdmi_audio clock\n");
1233                ret = PTR_ERR(hdmi->clk_audio);
1234                goto release_adapter;
1235        }
1236
1237        hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG;
1238
1239        init_waitqueue_head(&hdmi->wait_event);
1240
1241        hdmi->irq = platform_get_irq_byname(pdev, "irq");
1242
1243        ret = devm_request_threaded_irq(dev, hdmi->irq, hdmi_irq,
1244                        hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi);
1245        if (ret) {
1246                DRM_ERROR("Failed to register HDMI interrupt\n");
1247                goto release_adapter;
1248        }
1249
1250        hdmi->reset = devm_reset_control_get(dev, "hdmi");
1251        /* Take hdmi out of reset */
1252        if (!IS_ERR(hdmi->reset))
1253                reset_control_deassert(hdmi->reset);
1254
1255        platform_set_drvdata(pdev, hdmi);
1256
1257        return component_add(&pdev->dev, &sti_hdmi_ops);
1258
1259 release_adapter:
1260        i2c_put_adapter(hdmi->ddc_adapt);
1261
1262        return ret;
1263}
1264
1265static int sti_hdmi_remove(struct platform_device *pdev)
1266{
1267        struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
1268
1269        i2c_put_adapter(hdmi->ddc_adapt);
1270        component_del(&pdev->dev, &sti_hdmi_ops);
1271
1272        return 0;
1273}
1274
1275struct platform_driver sti_hdmi_driver = {
1276        .driver = {
1277                .name = "sti-hdmi",
1278                .owner = THIS_MODULE,
1279                .of_match_table = hdmi_of_match,
1280        },
1281        .probe = sti_hdmi_probe,
1282        .remove = sti_hdmi_remove,
1283};
1284
1285MODULE_AUTHOR("Benjamin Gaignard <benjamin.gaignard@st.com>");
1286MODULE_DESCRIPTION("STMicroelectronics SoC DRM driver");
1287MODULE_LICENSE("GPL");
1288