linux/drivers/gpu/drm/rockchip/inno_hdmi.c
<<
>>
Prefs
   1/*
   2 * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
   3 *    Zheng Yang <zhengyang@rock-chips.com>
   4 *    Yakir Yang <ykk@rock-chips.com>
   5 *
   6 * This software is licensed under the terms of the GNU General Public
   7 * License version 2, as published by the Free Software Foundation, and
   8 * may be copied, distributed, and modified under those terms.
   9 *
  10 * This program is distributed in the hope that it will be useful,
  11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13 * GNU General Public License for more details.
  14 */
  15
  16#include <linux/irq.h>
  17#include <linux/clk.h>
  18#include <linux/delay.h>
  19#include <linux/err.h>
  20#include <linux/hdmi.h>
  21#include <linux/mfd/syscon.h>
  22#include <linux/module.h>
  23#include <linux/mutex.h>
  24#include <linux/of_device.h>
  25
  26#include <drm/drm_of.h>
  27#include <drm/drmP.h>
  28#include <drm/drm_atomic_helper.h>
  29#include <drm/drm_crtc_helper.h>
  30#include <drm/drm_edid.h>
  31
  32#include "rockchip_drm_drv.h"
  33#include "rockchip_drm_vop.h"
  34
  35#include "inno_hdmi.h"
  36
  37#define to_inno_hdmi(x) container_of(x, struct inno_hdmi, x)
  38
  39struct hdmi_data_info {
  40        int vic;
  41        bool sink_is_hdmi;
  42        bool sink_has_audio;
  43        unsigned int enc_in_format;
  44        unsigned int enc_out_format;
  45        unsigned int colorimetry;
  46};
  47
  48struct inno_hdmi_i2c {
  49        struct i2c_adapter adap;
  50
  51        u8 ddc_addr;
  52        u8 segment_addr;
  53
  54        struct mutex lock;
  55        struct completion cmp;
  56};
  57
  58struct inno_hdmi {
  59        struct device *dev;
  60        struct drm_device *drm_dev;
  61
  62        int irq;
  63        struct clk *pclk;
  64        void __iomem *regs;
  65
  66        struct drm_connector    connector;
  67        struct drm_encoder      encoder;
  68
  69        struct inno_hdmi_i2c *i2c;
  70        struct i2c_adapter *ddc;
  71
  72        unsigned int tmds_rate;
  73
  74        struct hdmi_data_info   hdmi_data;
  75        struct drm_display_mode previous_mode;
  76};
  77
  78enum {
  79        CSC_ITU601_16_235_TO_RGB_0_255_8BIT,
  80        CSC_ITU601_0_255_TO_RGB_0_255_8BIT,
  81        CSC_ITU709_16_235_TO_RGB_0_255_8BIT,
  82        CSC_RGB_0_255_TO_ITU601_16_235_8BIT,
  83        CSC_RGB_0_255_TO_ITU709_16_235_8BIT,
  84        CSC_RGB_0_255_TO_RGB_16_235_8BIT,
  85};
  86
  87static const char coeff_csc[][24] = {
  88        /*
  89         * YUV2RGB:601 SD mode(Y[16:235], UV[16:240], RGB[0:255]):
  90         *   R = 1.164*Y + 1.596*V - 204
  91         *   G = 1.164*Y - 0.391*U - 0.813*V + 154
  92         *   B = 1.164*Y + 2.018*U - 258
  93         */
  94        {
  95                0x04, 0xa7, 0x00, 0x00, 0x06, 0x62, 0x02, 0xcc,
  96                0x04, 0xa7, 0x11, 0x90, 0x13, 0x40, 0x00, 0x9a,
  97                0x04, 0xa7, 0x08, 0x12, 0x00, 0x00, 0x03, 0x02
  98        },
  99        /*
 100         * YUV2RGB:601 SD mode(YUV[0:255],RGB[0:255]):
 101         *   R = Y + 1.402*V - 248
 102         *   G = Y - 0.344*U - 0.714*V + 135
 103         *   B = Y + 1.772*U - 227
 104         */
 105        {
 106                0x04, 0x00, 0x00, 0x00, 0x05, 0x9b, 0x02, 0xf8,
 107                0x04, 0x00, 0x11, 0x60, 0x12, 0xdb, 0x00, 0x87,
 108                0x04, 0x00, 0x07, 0x16, 0x00, 0x00, 0x02, 0xe3
 109        },
 110        /*
 111         * YUV2RGB:709 HD mode(Y[16:235],UV[16:240],RGB[0:255]):
 112         *   R = 1.164*Y + 1.793*V - 248
 113         *   G = 1.164*Y - 0.213*U - 0.534*V + 77
 114         *   B = 1.164*Y + 2.115*U - 289
 115         */
 116        {
 117                0x04, 0xa7, 0x00, 0x00, 0x07, 0x2c, 0x02, 0xf8,
 118                0x04, 0xa7, 0x10, 0xda, 0x12, 0x22, 0x00, 0x4d,
 119                0x04, 0xa7, 0x08, 0x74, 0x00, 0x00, 0x03, 0x21
 120        },
 121
 122        /*
 123         * RGB2YUV:601 SD mode:
 124         *   Cb = -0.291G - 0.148R + 0.439B + 128
 125         *   Y  = 0.504G  + 0.257R + 0.098B + 16
 126         *   Cr = -0.368G + 0.439R - 0.071B + 128
 127         */
 128        {
 129                0x11, 0x5f, 0x01, 0x82, 0x10, 0x23, 0x00, 0x80,
 130                0x02, 0x1c, 0x00, 0xa1, 0x00, 0x36, 0x00, 0x1e,
 131                0x11, 0x29, 0x10, 0x59, 0x01, 0x82, 0x00, 0x80
 132        },
 133        /*
 134         * RGB2YUV:709 HD mode:
 135         *   Cb = - 0.338G - 0.101R + 0.439B + 128
 136         *   Y  = 0.614G   + 0.183R + 0.062B + 16
 137         *   Cr = - 0.399G + 0.439R - 0.040B + 128
 138         */
 139        {
 140                0x11, 0x98, 0x01, 0xc1, 0x10, 0x28, 0x00, 0x80,
 141                0x02, 0x74, 0x00, 0xbb, 0x00, 0x3f, 0x00, 0x10,
 142                0x11, 0x5a, 0x10, 0x67, 0x01, 0xc1, 0x00, 0x80
 143        },
 144        /*
 145         * RGB[0:255]2RGB[16:235]:
 146         *   R' = R x (235-16)/255 + 16;
 147         *   G' = G x (235-16)/255 + 16;
 148         *   B' = B x (235-16)/255 + 16;
 149         */
 150        {
 151                0x00, 0x00, 0x03, 0x6F, 0x00, 0x00, 0x00, 0x10,
 152                0x03, 0x6F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,
 153                0x00, 0x00, 0x00, 0x00, 0x03, 0x6F, 0x00, 0x10
 154        },
 155};
 156
 157static inline u8 hdmi_readb(struct inno_hdmi *hdmi, u16 offset)
 158{
 159        return readl_relaxed(hdmi->regs + (offset) * 0x04);
 160}
 161
 162static inline void hdmi_writeb(struct inno_hdmi *hdmi, u16 offset, u32 val)
 163{
 164        writel_relaxed(val, hdmi->regs + (offset) * 0x04);
 165}
 166
 167static inline void hdmi_modb(struct inno_hdmi *hdmi, u16 offset,
 168                             u32 msk, u32 val)
 169{
 170        u8 temp = hdmi_readb(hdmi, offset) & ~msk;
 171
 172        temp |= val & msk;
 173        hdmi_writeb(hdmi, offset, temp);
 174}
 175
 176static void inno_hdmi_i2c_init(struct inno_hdmi *hdmi)
 177{
 178        int ddc_bus_freq;
 179
 180        ddc_bus_freq = (hdmi->tmds_rate >> 2) / HDMI_SCL_RATE;
 181
 182        hdmi_writeb(hdmi, DDC_BUS_FREQ_L, ddc_bus_freq & 0xFF);
 183        hdmi_writeb(hdmi, DDC_BUS_FREQ_H, (ddc_bus_freq >> 8) & 0xFF);
 184
 185        /* Clear the EDID interrupt flag and mute the interrupt */
 186        hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
 187        hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 188}
 189
 190static void inno_hdmi_sys_power(struct inno_hdmi *hdmi, bool enable)
 191{
 192        if (enable)
 193                hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_ON);
 194        else
 195                hdmi_modb(hdmi, HDMI_SYS_CTRL, m_POWER, v_PWR_OFF);
 196}
 197
 198static void inno_hdmi_set_pwr_mode(struct inno_hdmi *hdmi, int mode)
 199{
 200        switch (mode) {
 201        case NORMAL:
 202                inno_hdmi_sys_power(hdmi, false);
 203
 204                hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x6f);
 205                hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0xbb);
 206
 207                hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
 208                hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x14);
 209                hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x10);
 210                hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x0f);
 211                hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x00);
 212                hdmi_writeb(hdmi, HDMI_PHY_SYNC, 0x01);
 213
 214                inno_hdmi_sys_power(hdmi, true);
 215                break;
 216
 217        case LOWER_PWR:
 218                inno_hdmi_sys_power(hdmi, false);
 219                hdmi_writeb(hdmi, HDMI_PHY_DRIVER, 0x00);
 220                hdmi_writeb(hdmi, HDMI_PHY_PRE_EMPHASIS, 0x00);
 221                hdmi_writeb(hdmi, HDMI_PHY_CHG_PWR, 0x00);
 222                hdmi_writeb(hdmi, HDMI_PHY_SYS_CTL, 0x15);
 223
 224                break;
 225
 226        default:
 227                DRM_DEV_ERROR(hdmi->dev, "Unknown power mode %d\n", mode);
 228        }
 229}
 230
 231static void inno_hdmi_reset(struct inno_hdmi *hdmi)
 232{
 233        u32 val;
 234        u32 msk;
 235
 236        hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_DIGITAL, v_NOT_RST_DIGITAL);
 237        udelay(100);
 238
 239        hdmi_modb(hdmi, HDMI_SYS_CTRL, m_RST_ANALOG, v_NOT_RST_ANALOG);
 240        udelay(100);
 241
 242        msk = m_REG_CLK_INV | m_REG_CLK_SOURCE | m_POWER | m_INT_POL;
 243        val = v_REG_CLK_INV | v_REG_CLK_SOURCE_SYS | v_PWR_ON | v_INT_POL_HIGH;
 244        hdmi_modb(hdmi, HDMI_SYS_CTRL, msk, val);
 245
 246        inno_hdmi_set_pwr_mode(hdmi, NORMAL);
 247}
 248
 249static int inno_hdmi_upload_frame(struct inno_hdmi *hdmi, int setup_rc,
 250                                  union hdmi_infoframe *frame, u32 frame_index,
 251                                  u32 mask, u32 disable, u32 enable)
 252{
 253        if (mask)
 254                hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, disable);
 255
 256        hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_BUF_INDEX, frame_index);
 257
 258        if (setup_rc >= 0) {
 259                u8 packed_frame[HDMI_MAXIMUM_INFO_FRAME_SIZE];
 260                ssize_t rc, i;
 261
 262                rc = hdmi_infoframe_pack(frame, packed_frame,
 263                                         sizeof(packed_frame));
 264                if (rc < 0)
 265                        return rc;
 266
 267                for (i = 0; i < rc; i++)
 268                        hdmi_writeb(hdmi, HDMI_CONTROL_PACKET_ADDR + i,
 269                                    packed_frame[i]);
 270
 271                if (mask)
 272                        hdmi_modb(hdmi, HDMI_PACKET_SEND_AUTO, mask, enable);
 273        }
 274
 275        return setup_rc;
 276}
 277
 278static int inno_hdmi_config_video_vsi(struct inno_hdmi *hdmi,
 279                                      struct drm_display_mode *mode)
 280{
 281        union hdmi_infoframe frame;
 282        int rc;
 283
 284        rc = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
 285                                                         &hdmi->connector,
 286                                                         mode);
 287
 288        return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_VSI,
 289                m_PACKET_VSI_EN, v_PACKET_VSI_EN(0), v_PACKET_VSI_EN(1));
 290}
 291
 292static int inno_hdmi_config_video_avi(struct inno_hdmi *hdmi,
 293                                      struct drm_display_mode *mode)
 294{
 295        union hdmi_infoframe frame;
 296        int rc;
 297
 298        rc = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi, mode, false);
 299
 300        if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV444)
 301                frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
 302        else if (hdmi->hdmi_data.enc_out_format == HDMI_COLORSPACE_YUV422)
 303                frame.avi.colorspace = HDMI_COLORSPACE_YUV422;
 304        else
 305                frame.avi.colorspace = HDMI_COLORSPACE_RGB;
 306
 307        return inno_hdmi_upload_frame(hdmi, rc, &frame, INFOFRAME_AVI, 0, 0, 0);
 308}
 309
 310static int inno_hdmi_config_video_csc(struct inno_hdmi *hdmi)
 311{
 312        struct hdmi_data_info *data = &hdmi->hdmi_data;
 313        int c0_c2_change = 0;
 314        int csc_enable = 0;
 315        int csc_mode = 0;
 316        int auto_csc = 0;
 317        int value;
 318        int i;
 319
 320        /* Input video mode is SDR RGB24bit, data enable signal from external */
 321        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL1, v_DE_EXTERNAL |
 322                    v_VIDEO_INPUT_FORMAT(VIDEO_INPUT_SDR_RGB444));
 323
 324        /* Input color hardcode to RGB, and output color hardcode to RGB888 */
 325        value = v_VIDEO_INPUT_BITS(VIDEO_INPUT_8BITS) |
 326                v_VIDEO_OUTPUT_COLOR(0) |
 327                v_VIDEO_INPUT_CSP(0);
 328        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL2, value);
 329
 330        if (data->enc_in_format == data->enc_out_format) {
 331                if ((data->enc_in_format == HDMI_COLORSPACE_RGB) ||
 332                    (data->enc_in_format >= HDMI_COLORSPACE_YUV444)) {
 333                        value = v_SOF_DISABLE | v_COLOR_DEPTH_NOT_INDICATED(1);
 334                        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
 335
 336                        hdmi_modb(hdmi, HDMI_VIDEO_CONTRL,
 337                                  m_VIDEO_AUTO_CSC | m_VIDEO_C0_C2_SWAP,
 338                                  v_VIDEO_AUTO_CSC(AUTO_CSC_DISABLE) |
 339                                  v_VIDEO_C0_C2_SWAP(C0_C2_CHANGE_DISABLE));
 340                        return 0;
 341                }
 342        }
 343
 344        if (data->colorimetry == HDMI_COLORIMETRY_ITU_601) {
 345                if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
 346                    (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
 347                        csc_mode = CSC_RGB_0_255_TO_ITU601_16_235_8BIT;
 348                        auto_csc = AUTO_CSC_DISABLE;
 349                        c0_c2_change = C0_C2_CHANGE_DISABLE;
 350                        csc_enable = v_CSC_ENABLE;
 351                } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
 352                           (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
 353                        csc_mode = CSC_ITU601_16_235_TO_RGB_0_255_8BIT;
 354                        auto_csc = AUTO_CSC_ENABLE;
 355                        c0_c2_change = C0_C2_CHANGE_DISABLE;
 356                        csc_enable = v_CSC_DISABLE;
 357                }
 358        } else {
 359                if ((data->enc_in_format == HDMI_COLORSPACE_RGB) &&
 360                    (data->enc_out_format == HDMI_COLORSPACE_YUV444)) {
 361                        csc_mode = CSC_RGB_0_255_TO_ITU709_16_235_8BIT;
 362                        auto_csc = AUTO_CSC_DISABLE;
 363                        c0_c2_change = C0_C2_CHANGE_DISABLE;
 364                        csc_enable = v_CSC_ENABLE;
 365                } else if ((data->enc_in_format == HDMI_COLORSPACE_YUV444) &&
 366                           (data->enc_out_format == HDMI_COLORSPACE_RGB)) {
 367                        csc_mode = CSC_ITU709_16_235_TO_RGB_0_255_8BIT;
 368                        auto_csc = AUTO_CSC_ENABLE;
 369                        c0_c2_change = C0_C2_CHANGE_DISABLE;
 370                        csc_enable = v_CSC_DISABLE;
 371                }
 372        }
 373
 374        for (i = 0; i < 24; i++)
 375                hdmi_writeb(hdmi, HDMI_VIDEO_CSC_COEF + i,
 376                            coeff_csc[csc_mode][i]);
 377
 378        value = v_SOF_DISABLE | csc_enable | v_COLOR_DEPTH_NOT_INDICATED(1);
 379        hdmi_writeb(hdmi, HDMI_VIDEO_CONTRL3, value);
 380        hdmi_modb(hdmi, HDMI_VIDEO_CONTRL, m_VIDEO_AUTO_CSC |
 381                  m_VIDEO_C0_C2_SWAP, v_VIDEO_AUTO_CSC(auto_csc) |
 382                  v_VIDEO_C0_C2_SWAP(c0_c2_change));
 383
 384        return 0;
 385}
 386
 387static int inno_hdmi_config_video_timing(struct inno_hdmi *hdmi,
 388                                         struct drm_display_mode *mode)
 389{
 390        int value;
 391
 392        /* Set detail external video timing polarity and interlace mode */
 393        value = v_EXTERANL_VIDEO(1);
 394        value |= mode->flags & DRM_MODE_FLAG_PHSYNC ?
 395                 v_HSYNC_POLARITY(1) : v_HSYNC_POLARITY(0);
 396        value |= mode->flags & DRM_MODE_FLAG_PVSYNC ?
 397                 v_VSYNC_POLARITY(1) : v_VSYNC_POLARITY(0);
 398        value |= mode->flags & DRM_MODE_FLAG_INTERLACE ?
 399                 v_INETLACE(1) : v_INETLACE(0);
 400        hdmi_writeb(hdmi, HDMI_VIDEO_TIMING_CTL, value);
 401
 402        /* Set detail external video timing */
 403        value = mode->htotal;
 404        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_L, value & 0xFF);
 405        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HTOTAL_H, (value >> 8) & 0xFF);
 406
 407        value = mode->htotal - mode->hdisplay;
 408        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_L, value & 0xFF);
 409        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HBLANK_H, (value >> 8) & 0xFF);
 410
 411        value = mode->hsync_start - mode->hdisplay;
 412        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_L, value & 0xFF);
 413        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDELAY_H, (value >> 8) & 0xFF);
 414
 415        value = mode->hsync_end - mode->hsync_start;
 416        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_L, value & 0xFF);
 417        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_HDURATION_H, (value >> 8) & 0xFF);
 418
 419        value = mode->vtotal;
 420        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_L, value & 0xFF);
 421        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VTOTAL_H, (value >> 8) & 0xFF);
 422
 423        value = mode->vtotal - mode->vdisplay;
 424        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VBLANK, value & 0xFF);
 425
 426        value = mode->vsync_start - mode->vdisplay;
 427        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDELAY, value & 0xFF);
 428
 429        value = mode->vsync_end - mode->vsync_start;
 430        hdmi_writeb(hdmi, HDMI_VIDEO_EXT_VDURATION, value & 0xFF);
 431
 432        hdmi_writeb(hdmi, HDMI_PHY_PRE_DIV_RATIO, 0x1e);
 433        hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_LOW, 0x2c);
 434        hdmi_writeb(hdmi, HDMI_PHY_FEEDBACK_DIV_RATIO_HIGH, 0x01);
 435
 436        return 0;
 437}
 438
 439static int inno_hdmi_setup(struct inno_hdmi *hdmi,
 440                           struct drm_display_mode *mode)
 441{
 442        hdmi->hdmi_data.vic = drm_match_cea_mode(mode);
 443
 444        hdmi->hdmi_data.enc_in_format = HDMI_COLORSPACE_RGB;
 445        hdmi->hdmi_data.enc_out_format = HDMI_COLORSPACE_RGB;
 446
 447        if ((hdmi->hdmi_data.vic == 6) || (hdmi->hdmi_data.vic == 7) ||
 448            (hdmi->hdmi_data.vic == 21) || (hdmi->hdmi_data.vic == 22) ||
 449            (hdmi->hdmi_data.vic == 2) || (hdmi->hdmi_data.vic == 3) ||
 450            (hdmi->hdmi_data.vic == 17) || (hdmi->hdmi_data.vic == 18))
 451                hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_601;
 452        else
 453                hdmi->hdmi_data.colorimetry = HDMI_COLORIMETRY_ITU_709;
 454
 455        /* Mute video and audio output */
 456        hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
 457                  v_AUDIO_MUTE(1) | v_VIDEO_MUTE(1));
 458
 459        /* Set HDMI Mode */
 460        hdmi_writeb(hdmi, HDMI_HDCP_CTRL,
 461                    v_HDMI_DVI(hdmi->hdmi_data.sink_is_hdmi));
 462
 463        inno_hdmi_config_video_timing(hdmi, mode);
 464
 465        inno_hdmi_config_video_csc(hdmi);
 466
 467        if (hdmi->hdmi_data.sink_is_hdmi) {
 468                inno_hdmi_config_video_avi(hdmi, mode);
 469                inno_hdmi_config_video_vsi(hdmi, mode);
 470        }
 471
 472        /*
 473         * When IP controller have configured to an accurate video
 474         * timing, then the TMDS clock source would be switched to
 475         * DCLK_LCDC, so we need to init the TMDS rate to mode pixel
 476         * clock rate, and reconfigure the DDC clock.
 477         */
 478        hdmi->tmds_rate = mode->clock * 1000;
 479        inno_hdmi_i2c_init(hdmi);
 480
 481        /* Unmute video and audio output */
 482        hdmi_modb(hdmi, HDMI_AV_MUTE, m_AUDIO_MUTE | m_VIDEO_BLACK,
 483                  v_AUDIO_MUTE(0) | v_VIDEO_MUTE(0));
 484
 485        return 0;
 486}
 487
 488static void inno_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 489                                       struct drm_display_mode *mode,
 490                                       struct drm_display_mode *adj_mode)
 491{
 492        struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 493
 494        inno_hdmi_setup(hdmi, adj_mode);
 495
 496        /* Store the display mode for plugin/DPMS poweron events */
 497        memcpy(&hdmi->previous_mode, adj_mode, sizeof(hdmi->previous_mode));
 498}
 499
 500static void inno_hdmi_encoder_enable(struct drm_encoder *encoder)
 501{
 502        struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 503
 504        inno_hdmi_set_pwr_mode(hdmi, NORMAL);
 505}
 506
 507static void inno_hdmi_encoder_disable(struct drm_encoder *encoder)
 508{
 509        struct inno_hdmi *hdmi = to_inno_hdmi(encoder);
 510
 511        inno_hdmi_set_pwr_mode(hdmi, LOWER_PWR);
 512}
 513
 514static bool inno_hdmi_encoder_mode_fixup(struct drm_encoder *encoder,
 515                                         const struct drm_display_mode *mode,
 516                                         struct drm_display_mode *adj_mode)
 517{
 518        return true;
 519}
 520
 521static int
 522inno_hdmi_encoder_atomic_check(struct drm_encoder *encoder,
 523                               struct drm_crtc_state *crtc_state,
 524                               struct drm_connector_state *conn_state)
 525{
 526        struct rockchip_crtc_state *s = to_rockchip_crtc_state(crtc_state);
 527
 528        s->output_mode = ROCKCHIP_OUT_MODE_P888;
 529        s->output_type = DRM_MODE_CONNECTOR_HDMIA;
 530
 531        return 0;
 532}
 533
 534static struct drm_encoder_helper_funcs inno_hdmi_encoder_helper_funcs = {
 535        .enable     = inno_hdmi_encoder_enable,
 536        .disable    = inno_hdmi_encoder_disable,
 537        .mode_fixup = inno_hdmi_encoder_mode_fixup,
 538        .mode_set   = inno_hdmi_encoder_mode_set,
 539        .atomic_check = inno_hdmi_encoder_atomic_check,
 540};
 541
 542static struct drm_encoder_funcs inno_hdmi_encoder_funcs = {
 543        .destroy = drm_encoder_cleanup,
 544};
 545
 546static enum drm_connector_status
 547inno_hdmi_connector_detect(struct drm_connector *connector, bool force)
 548{
 549        struct inno_hdmi *hdmi = to_inno_hdmi(connector);
 550
 551        return (hdmi_readb(hdmi, HDMI_STATUS) & m_HOTPLUG) ?
 552                connector_status_connected : connector_status_disconnected;
 553}
 554
 555static int inno_hdmi_connector_get_modes(struct drm_connector *connector)
 556{
 557        struct inno_hdmi *hdmi = to_inno_hdmi(connector);
 558        struct edid *edid;
 559        int ret = 0;
 560
 561        if (!hdmi->ddc)
 562                return 0;
 563
 564        edid = drm_get_edid(connector, hdmi->ddc);
 565        if (edid) {
 566                hdmi->hdmi_data.sink_is_hdmi = drm_detect_hdmi_monitor(edid);
 567                hdmi->hdmi_data.sink_has_audio = drm_detect_monitor_audio(edid);
 568                drm_connector_update_edid_property(connector, edid);
 569                ret = drm_add_edid_modes(connector, edid);
 570                kfree(edid);
 571        }
 572
 573        return ret;
 574}
 575
 576static enum drm_mode_status
 577inno_hdmi_connector_mode_valid(struct drm_connector *connector,
 578                               struct drm_display_mode *mode)
 579{
 580        return MODE_OK;
 581}
 582
 583static int
 584inno_hdmi_probe_single_connector_modes(struct drm_connector *connector,
 585                                       uint32_t maxX, uint32_t maxY)
 586{
 587        return drm_helper_probe_single_connector_modes(connector, 1920, 1080);
 588}
 589
 590static void inno_hdmi_connector_destroy(struct drm_connector *connector)
 591{
 592        drm_connector_unregister(connector);
 593        drm_connector_cleanup(connector);
 594}
 595
 596static const struct drm_connector_funcs inno_hdmi_connector_funcs = {
 597        .fill_modes = inno_hdmi_probe_single_connector_modes,
 598        .detect = inno_hdmi_connector_detect,
 599        .destroy = inno_hdmi_connector_destroy,
 600        .reset = drm_atomic_helper_connector_reset,
 601        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 602        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 603};
 604
 605static struct drm_connector_helper_funcs inno_hdmi_connector_helper_funcs = {
 606        .get_modes = inno_hdmi_connector_get_modes,
 607        .mode_valid = inno_hdmi_connector_mode_valid,
 608};
 609
 610static int inno_hdmi_register(struct drm_device *drm, struct inno_hdmi *hdmi)
 611{
 612        struct drm_encoder *encoder = &hdmi->encoder;
 613        struct device *dev = hdmi->dev;
 614
 615        encoder->possible_crtcs = drm_of_find_possible_crtcs(drm, dev->of_node);
 616
 617        /*
 618         * If we failed to find the CRTC(s) which this encoder is
 619         * supposed to be connected to, it's because the CRTC has
 620         * not been registered yet.  Defer probing, and hope that
 621         * the required CRTC is added later.
 622         */
 623        if (encoder->possible_crtcs == 0)
 624                return -EPROBE_DEFER;
 625
 626        drm_encoder_helper_add(encoder, &inno_hdmi_encoder_helper_funcs);
 627        drm_encoder_init(drm, encoder, &inno_hdmi_encoder_funcs,
 628                         DRM_MODE_ENCODER_TMDS, NULL);
 629
 630        hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 631
 632        drm_connector_helper_add(&hdmi->connector,
 633                                 &inno_hdmi_connector_helper_funcs);
 634        drm_connector_init(drm, &hdmi->connector, &inno_hdmi_connector_funcs,
 635                           DRM_MODE_CONNECTOR_HDMIA);
 636
 637        drm_connector_attach_encoder(&hdmi->connector, encoder);
 638
 639        return 0;
 640}
 641
 642static irqreturn_t inno_hdmi_i2c_irq(struct inno_hdmi *hdmi)
 643{
 644        struct inno_hdmi_i2c *i2c = hdmi->i2c;
 645        u8 stat;
 646
 647        stat = hdmi_readb(hdmi, HDMI_INTERRUPT_STATUS1);
 648        if (!(stat & m_INT_EDID_READY))
 649                return IRQ_NONE;
 650
 651        /* Clear HDMI EDID interrupt flag */
 652        hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 653
 654        complete(&i2c->cmp);
 655
 656        return IRQ_HANDLED;
 657}
 658
 659static irqreturn_t inno_hdmi_hardirq(int irq, void *dev_id)
 660{
 661        struct inno_hdmi *hdmi = dev_id;
 662        irqreturn_t ret = IRQ_NONE;
 663        u8 interrupt;
 664
 665        if (hdmi->i2c)
 666                ret = inno_hdmi_i2c_irq(hdmi);
 667
 668        interrupt = hdmi_readb(hdmi, HDMI_STATUS);
 669        if (interrupt & m_INT_HOTPLUG) {
 670                hdmi_modb(hdmi, HDMI_STATUS, m_INT_HOTPLUG, m_INT_HOTPLUG);
 671                ret = IRQ_WAKE_THREAD;
 672        }
 673
 674        return ret;
 675}
 676
 677static irqreturn_t inno_hdmi_irq(int irq, void *dev_id)
 678{
 679        struct inno_hdmi *hdmi = dev_id;
 680
 681        drm_helper_hpd_irq_event(hdmi->connector.dev);
 682
 683        return IRQ_HANDLED;
 684}
 685
 686static int inno_hdmi_i2c_read(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
 687{
 688        int length = msgs->len;
 689        u8 *buf = msgs->buf;
 690        int ret;
 691
 692        ret = wait_for_completion_timeout(&hdmi->i2c->cmp, HZ / 10);
 693        if (!ret)
 694                return -EAGAIN;
 695
 696        while (length--)
 697                *buf++ = hdmi_readb(hdmi, HDMI_EDID_FIFO_ADDR);
 698
 699        return 0;
 700}
 701
 702static int inno_hdmi_i2c_write(struct inno_hdmi *hdmi, struct i2c_msg *msgs)
 703{
 704        /*
 705         * The DDC module only support read EDID message, so
 706         * we assume that each word write to this i2c adapter
 707         * should be the offset of EDID word address.
 708         */
 709        if ((msgs->len != 1) ||
 710            ((msgs->addr != DDC_ADDR) && (msgs->addr != DDC_SEGMENT_ADDR)))
 711                return -EINVAL;
 712
 713        reinit_completion(&hdmi->i2c->cmp);
 714
 715        if (msgs->addr == DDC_SEGMENT_ADDR)
 716                hdmi->i2c->segment_addr = msgs->buf[0];
 717        if (msgs->addr == DDC_ADDR)
 718                hdmi->i2c->ddc_addr = msgs->buf[0];
 719
 720        /* Set edid fifo first addr */
 721        hdmi_writeb(hdmi, HDMI_EDID_FIFO_OFFSET, 0x00);
 722
 723        /* Set edid word address 0x00/0x80 */
 724        hdmi_writeb(hdmi, HDMI_EDID_WORD_ADDR, hdmi->i2c->ddc_addr);
 725
 726        /* Set edid segment pointer */
 727        hdmi_writeb(hdmi, HDMI_EDID_SEGMENT_POINTER, hdmi->i2c->segment_addr);
 728
 729        return 0;
 730}
 731
 732static int inno_hdmi_i2c_xfer(struct i2c_adapter *adap,
 733                              struct i2c_msg *msgs, int num)
 734{
 735        struct inno_hdmi *hdmi = i2c_get_adapdata(adap);
 736        struct inno_hdmi_i2c *i2c = hdmi->i2c;
 737        int i, ret = 0;
 738
 739        mutex_lock(&i2c->lock);
 740
 741        /* Clear the EDID interrupt flag and unmute the interrupt */
 742        hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, m_INT_EDID_READY);
 743        hdmi_writeb(hdmi, HDMI_INTERRUPT_STATUS1, m_INT_EDID_READY);
 744
 745        for (i = 0; i < num; i++) {
 746                DRM_DEV_DEBUG(hdmi->dev,
 747                              "xfer: num: %d/%d, len: %d, flags: %#x\n",
 748                              i + 1, num, msgs[i].len, msgs[i].flags);
 749
 750                if (msgs[i].flags & I2C_M_RD)
 751                        ret = inno_hdmi_i2c_read(hdmi, &msgs[i]);
 752                else
 753                        ret = inno_hdmi_i2c_write(hdmi, &msgs[i]);
 754
 755                if (ret < 0)
 756                        break;
 757        }
 758
 759        if (!ret)
 760                ret = num;
 761
 762        /* Mute HDMI EDID interrupt */
 763        hdmi_writeb(hdmi, HDMI_INTERRUPT_MASK1, 0);
 764
 765        mutex_unlock(&i2c->lock);
 766
 767        return ret;
 768}
 769
 770static u32 inno_hdmi_i2c_func(struct i2c_adapter *adapter)
 771{
 772        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 773}
 774
 775static const struct i2c_algorithm inno_hdmi_algorithm = {
 776        .master_xfer    = inno_hdmi_i2c_xfer,
 777        .functionality  = inno_hdmi_i2c_func,
 778};
 779
 780static struct i2c_adapter *inno_hdmi_i2c_adapter(struct inno_hdmi *hdmi)
 781{
 782        struct i2c_adapter *adap;
 783        struct inno_hdmi_i2c *i2c;
 784        int ret;
 785
 786        i2c = devm_kzalloc(hdmi->dev, sizeof(*i2c), GFP_KERNEL);
 787        if (!i2c)
 788                return ERR_PTR(-ENOMEM);
 789
 790        mutex_init(&i2c->lock);
 791        init_completion(&i2c->cmp);
 792
 793        adap = &i2c->adap;
 794        adap->class = I2C_CLASS_DDC;
 795        adap->owner = THIS_MODULE;
 796        adap->dev.parent = hdmi->dev;
 797        adap->dev.of_node = hdmi->dev->of_node;
 798        adap->algo = &inno_hdmi_algorithm;
 799        strlcpy(adap->name, "Inno HDMI", sizeof(adap->name));
 800        i2c_set_adapdata(adap, hdmi);
 801
 802        ret = i2c_add_adapter(adap);
 803        if (ret) {
 804                dev_warn(hdmi->dev, "cannot add %s I2C adapter\n", adap->name);
 805                devm_kfree(hdmi->dev, i2c);
 806                return ERR_PTR(ret);
 807        }
 808
 809        hdmi->i2c = i2c;
 810
 811        DRM_DEV_INFO(hdmi->dev, "registered %s I2C bus driver\n", adap->name);
 812
 813        return adap;
 814}
 815
 816static int inno_hdmi_bind(struct device *dev, struct device *master,
 817                                 void *data)
 818{
 819        struct platform_device *pdev = to_platform_device(dev);
 820        struct drm_device *drm = data;
 821        struct inno_hdmi *hdmi;
 822        struct resource *iores;
 823        int irq;
 824        int ret;
 825
 826        hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 827        if (!hdmi)
 828                return -ENOMEM;
 829
 830        hdmi->dev = dev;
 831        hdmi->drm_dev = drm;
 832
 833        iores = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 834        hdmi->regs = devm_ioremap_resource(dev, iores);
 835        if (IS_ERR(hdmi->regs))
 836                return PTR_ERR(hdmi->regs);
 837
 838        hdmi->pclk = devm_clk_get(hdmi->dev, "pclk");
 839        if (IS_ERR(hdmi->pclk)) {
 840                DRM_DEV_ERROR(hdmi->dev, "Unable to get HDMI pclk clk\n");
 841                return PTR_ERR(hdmi->pclk);
 842        }
 843
 844        ret = clk_prepare_enable(hdmi->pclk);
 845        if (ret) {
 846                DRM_DEV_ERROR(hdmi->dev,
 847                              "Cannot enable HDMI pclk clock: %d\n", ret);
 848                return ret;
 849        }
 850
 851        irq = platform_get_irq(pdev, 0);
 852        if (irq < 0) {
 853                ret = irq;
 854                goto err_disable_clk;
 855        }
 856
 857        inno_hdmi_reset(hdmi);
 858
 859        hdmi->ddc = inno_hdmi_i2c_adapter(hdmi);
 860        if (IS_ERR(hdmi->ddc)) {
 861                ret = PTR_ERR(hdmi->ddc);
 862                hdmi->ddc = NULL;
 863                goto err_disable_clk;
 864        }
 865
 866        /*
 867         * When IP controller haven't configured to an accurate video
 868         * timing, then the TMDS clock source would be switched to
 869         * PCLK_HDMI, so we need to init the TMDS rate to PCLK rate,
 870         * and reconfigure the DDC clock.
 871         */
 872        hdmi->tmds_rate = clk_get_rate(hdmi->pclk);
 873        inno_hdmi_i2c_init(hdmi);
 874
 875        ret = inno_hdmi_register(drm, hdmi);
 876        if (ret)
 877                goto err_put_adapter;
 878
 879        dev_set_drvdata(dev, hdmi);
 880
 881        /* Unmute hotplug interrupt */
 882        hdmi_modb(hdmi, HDMI_STATUS, m_MASK_INT_HOTPLUG, v_MASK_INT_HOTPLUG(1));
 883
 884        ret = devm_request_threaded_irq(dev, irq, inno_hdmi_hardirq,
 885                                        inno_hdmi_irq, IRQF_SHARED,
 886                                        dev_name(dev), hdmi);
 887        if (ret < 0)
 888                goto err_cleanup_hdmi;
 889
 890        return 0;
 891err_cleanup_hdmi:
 892        hdmi->connector.funcs->destroy(&hdmi->connector);
 893        hdmi->encoder.funcs->destroy(&hdmi->encoder);
 894err_put_adapter:
 895        i2c_put_adapter(hdmi->ddc);
 896err_disable_clk:
 897        clk_disable_unprepare(hdmi->pclk);
 898        return ret;
 899}
 900
 901static void inno_hdmi_unbind(struct device *dev, struct device *master,
 902                             void *data)
 903{
 904        struct inno_hdmi *hdmi = dev_get_drvdata(dev);
 905
 906        hdmi->connector.funcs->destroy(&hdmi->connector);
 907        hdmi->encoder.funcs->destroy(&hdmi->encoder);
 908
 909        i2c_put_adapter(hdmi->ddc);
 910        clk_disable_unprepare(hdmi->pclk);
 911}
 912
 913static const struct component_ops inno_hdmi_ops = {
 914        .bind   = inno_hdmi_bind,
 915        .unbind = inno_hdmi_unbind,
 916};
 917
 918static int inno_hdmi_probe(struct platform_device *pdev)
 919{
 920        return component_add(&pdev->dev, &inno_hdmi_ops);
 921}
 922
 923static int inno_hdmi_remove(struct platform_device *pdev)
 924{
 925        component_del(&pdev->dev, &inno_hdmi_ops);
 926
 927        return 0;
 928}
 929
 930static const struct of_device_id inno_hdmi_dt_ids[] = {
 931        { .compatible = "rockchip,rk3036-inno-hdmi",
 932        },
 933        {},
 934};
 935MODULE_DEVICE_TABLE(of, inno_hdmi_dt_ids);
 936
 937struct platform_driver inno_hdmi_driver = {
 938        .probe  = inno_hdmi_probe,
 939        .remove = inno_hdmi_remove,
 940        .driver = {
 941                .name = "innohdmi-rockchip",
 942                .of_match_table = inno_hdmi_dt_ids,
 943        },
 944};
 945