linux/drivers/gpu/drm/zte/zx_hdmi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-only
   2/*
   3 * Copyright 2016 Linaro Ltd.
   4 * Copyright 2016 ZTE Corporation.
   5 */
   6
   7#include <linux/clk.h>
   8#include <linux/component.h>
   9#include <linux/delay.h>
  10#include <linux/err.h>
  11#include <linux/hdmi.h>
  12#include <linux/irq.h>
  13#include <linux/mfd/syscon.h>
  14#include <linux/module.h>
  15#include <linux/mutex.h>
  16#include <linux/of_device.h>
  17
  18#include <drm/drm_atomic_helper.h>
  19#include <drm/drm_edid.h>
  20#include <drm/drm_of.h>
  21#include <drm/drm_probe_helper.h>
  22#include <drm/drmP.h>
  23
  24#include <sound/hdmi-codec.h>
  25
  26#include "zx_hdmi_regs.h"
  27#include "zx_vou.h"
  28
  29#define ZX_HDMI_INFOFRAME_SIZE          31
  30#define DDC_SEGMENT_ADDR                0x30
  31
  32struct zx_hdmi_i2c {
  33        struct i2c_adapter adap;
  34        struct mutex lock;
  35};
  36
  37struct zx_hdmi {
  38        struct drm_connector connector;
  39        struct drm_encoder encoder;
  40        struct zx_hdmi_i2c *ddc;
  41        struct device *dev;
  42        struct drm_device *drm;
  43        void __iomem *mmio;
  44        struct clk *cec_clk;
  45        struct clk *osc_clk;
  46        struct clk *xclk;
  47        bool sink_is_hdmi;
  48        bool sink_has_audio;
  49        struct platform_device *audio_pdev;
  50};
  51
  52#define to_zx_hdmi(x) container_of(x, struct zx_hdmi, x)
  53
  54static inline u8 hdmi_readb(struct zx_hdmi *hdmi, u16 offset)
  55{
  56        return readl_relaxed(hdmi->mmio + offset * 4);
  57}
  58
  59static inline void hdmi_writeb(struct zx_hdmi *hdmi, u16 offset, u8 val)
  60{
  61        writel_relaxed(val, hdmi->mmio + offset * 4);
  62}
  63
  64static inline void hdmi_writeb_mask(struct zx_hdmi *hdmi, u16 offset,
  65                                    u8 mask, u8 val)
  66{
  67        u8 tmp;
  68
  69        tmp = hdmi_readb(hdmi, offset);
  70        tmp = (tmp & ~mask) | (val & mask);
  71        hdmi_writeb(hdmi, offset, tmp);
  72}
  73
  74static int zx_hdmi_infoframe_trans(struct zx_hdmi *hdmi,
  75                                   union hdmi_infoframe *frame, u8 fsel)
  76{
  77        u8 buffer[ZX_HDMI_INFOFRAME_SIZE];
  78        int num;
  79        int i;
  80
  81        hdmi_writeb(hdmi, TPI_INFO_FSEL, fsel);
  82
  83        num = hdmi_infoframe_pack(frame, buffer, ZX_HDMI_INFOFRAME_SIZE);
  84        if (num < 0) {
  85                DRM_DEV_ERROR(hdmi->dev, "failed to pack infoframe: %d\n", num);
  86                return num;
  87        }
  88
  89        for (i = 0; i < num; i++)
  90                hdmi_writeb(hdmi, TPI_INFO_B0 + i, buffer[i]);
  91
  92        hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_RPT,
  93                         TPI_INFO_TRANS_RPT);
  94        hdmi_writeb_mask(hdmi, TPI_INFO_EN, TPI_INFO_TRANS_EN,
  95                         TPI_INFO_TRANS_EN);
  96
  97        return num;
  98}
  99
 100static int zx_hdmi_config_video_vsi(struct zx_hdmi *hdmi,
 101                                    struct drm_display_mode *mode)
 102{
 103        union hdmi_infoframe frame;
 104        int ret;
 105
 106        ret = drm_hdmi_vendor_infoframe_from_display_mode(&frame.vendor.hdmi,
 107                                                          &hdmi->connector,
 108                                                          mode);
 109        if (ret) {
 110                DRM_DEV_ERROR(hdmi->dev, "failed to get vendor infoframe: %d\n",
 111                              ret);
 112                return ret;
 113        }
 114
 115        return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_VSIF);
 116}
 117
 118static int zx_hdmi_config_video_avi(struct zx_hdmi *hdmi,
 119                                    struct drm_display_mode *mode)
 120{
 121        union hdmi_infoframe frame;
 122        int ret;
 123
 124        ret = drm_hdmi_avi_infoframe_from_display_mode(&frame.avi,
 125                                                       &hdmi->connector,
 126                                                       mode);
 127        if (ret) {
 128                DRM_DEV_ERROR(hdmi->dev, "failed to get avi infoframe: %d\n",
 129                              ret);
 130                return ret;
 131        }
 132
 133        /* We always use YUV444 for HDMI output. */
 134        frame.avi.colorspace = HDMI_COLORSPACE_YUV444;
 135
 136        return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AVI);
 137}
 138
 139static void zx_hdmi_encoder_mode_set(struct drm_encoder *encoder,
 140                                     struct drm_display_mode *mode,
 141                                     struct drm_display_mode *adj_mode)
 142{
 143        struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
 144
 145        if (hdmi->sink_is_hdmi) {
 146                zx_hdmi_config_video_avi(hdmi, mode);
 147                zx_hdmi_config_video_vsi(hdmi, mode);
 148        }
 149}
 150
 151static void zx_hdmi_phy_start(struct zx_hdmi *hdmi)
 152{
 153        /* Copy from ZTE BSP code */
 154        hdmi_writeb(hdmi, 0x222, 0x0);
 155        hdmi_writeb(hdmi, 0x224, 0x4);
 156        hdmi_writeb(hdmi, 0x909, 0x0);
 157        hdmi_writeb(hdmi, 0x7b0, 0x90);
 158        hdmi_writeb(hdmi, 0x7b1, 0x00);
 159        hdmi_writeb(hdmi, 0x7b2, 0xa7);
 160        hdmi_writeb(hdmi, 0x7b8, 0xaa);
 161        hdmi_writeb(hdmi, 0x7b2, 0xa7);
 162        hdmi_writeb(hdmi, 0x7b3, 0x0f);
 163        hdmi_writeb(hdmi, 0x7b4, 0x0f);
 164        hdmi_writeb(hdmi, 0x7b5, 0x55);
 165        hdmi_writeb(hdmi, 0x7b7, 0x03);
 166        hdmi_writeb(hdmi, 0x7b9, 0x12);
 167        hdmi_writeb(hdmi, 0x7ba, 0x32);
 168        hdmi_writeb(hdmi, 0x7bc, 0x68);
 169        hdmi_writeb(hdmi, 0x7be, 0x40);
 170        hdmi_writeb(hdmi, 0x7bf, 0x84);
 171        hdmi_writeb(hdmi, 0x7c1, 0x0f);
 172        hdmi_writeb(hdmi, 0x7c8, 0x02);
 173        hdmi_writeb(hdmi, 0x7c9, 0x03);
 174        hdmi_writeb(hdmi, 0x7ca, 0x40);
 175        hdmi_writeb(hdmi, 0x7dc, 0x31);
 176        hdmi_writeb(hdmi, 0x7e2, 0x04);
 177        hdmi_writeb(hdmi, 0x7e0, 0x06);
 178        hdmi_writeb(hdmi, 0x7cb, 0x68);
 179        hdmi_writeb(hdmi, 0x7f9, 0x02);
 180        hdmi_writeb(hdmi, 0x7b6, 0x02);
 181        hdmi_writeb(hdmi, 0x7f3, 0x0);
 182}
 183
 184static void zx_hdmi_hw_enable(struct zx_hdmi *hdmi)
 185{
 186        /* Enable pclk */
 187        hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, CLKPWD_PDIDCK);
 188
 189        /* Enable HDMI for TX */
 190        hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, FUNC_HDMI_EN);
 191
 192        /* Enable deep color packet */
 193        hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
 194
 195        /* Enable HDMI/MHL mode for output */
 196        hdmi_writeb_mask(hdmi, TEST_TXCTRL, TEST_TXCTRL_HDMI_MODE,
 197                         TEST_TXCTRL_HDMI_MODE);
 198
 199        /* Configure reg_qc_sel */
 200        hdmi_writeb(hdmi, HDMICTL4, 0x3);
 201
 202        /* Enable interrupt */
 203        hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT,
 204                         INTR1_MONITOR_DETECT);
 205
 206        /* Start up phy */
 207        zx_hdmi_phy_start(hdmi);
 208}
 209
 210static void zx_hdmi_hw_disable(struct zx_hdmi *hdmi)
 211{
 212        /* Disable interrupt */
 213        hdmi_writeb_mask(hdmi, INTR1_MASK, INTR1_MONITOR_DETECT, 0);
 214
 215        /* Disable deep color packet */
 216        hdmi_writeb_mask(hdmi, P2T_CTRL, P2T_DC_PKT_EN, P2T_DC_PKT_EN);
 217
 218        /* Disable HDMI for TX */
 219        hdmi_writeb_mask(hdmi, FUNC_SEL, FUNC_HDMI_EN, 0);
 220
 221        /* Disable pclk */
 222        hdmi_writeb_mask(hdmi, CLKPWD, CLKPWD_PDIDCK, 0);
 223}
 224
 225static void zx_hdmi_encoder_enable(struct drm_encoder *encoder)
 226{
 227        struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
 228
 229        clk_prepare_enable(hdmi->cec_clk);
 230        clk_prepare_enable(hdmi->osc_clk);
 231        clk_prepare_enable(hdmi->xclk);
 232
 233        zx_hdmi_hw_enable(hdmi);
 234
 235        vou_inf_enable(VOU_HDMI, encoder->crtc);
 236}
 237
 238static void zx_hdmi_encoder_disable(struct drm_encoder *encoder)
 239{
 240        struct zx_hdmi *hdmi = to_zx_hdmi(encoder);
 241
 242        vou_inf_disable(VOU_HDMI, encoder->crtc);
 243
 244        zx_hdmi_hw_disable(hdmi);
 245
 246        clk_disable_unprepare(hdmi->xclk);
 247        clk_disable_unprepare(hdmi->osc_clk);
 248        clk_disable_unprepare(hdmi->cec_clk);
 249}
 250
 251static const struct drm_encoder_helper_funcs zx_hdmi_encoder_helper_funcs = {
 252        .enable = zx_hdmi_encoder_enable,
 253        .disable = zx_hdmi_encoder_disable,
 254        .mode_set = zx_hdmi_encoder_mode_set,
 255};
 256
 257static const struct drm_encoder_funcs zx_hdmi_encoder_funcs = {
 258        .destroy = drm_encoder_cleanup,
 259};
 260
 261static int zx_hdmi_connector_get_modes(struct drm_connector *connector)
 262{
 263        struct zx_hdmi *hdmi = to_zx_hdmi(connector);
 264        struct edid *edid;
 265        int ret;
 266
 267        edid = drm_get_edid(connector, &hdmi->ddc->adap);
 268        if (!edid)
 269                return 0;
 270
 271        hdmi->sink_is_hdmi = drm_detect_hdmi_monitor(edid);
 272        hdmi->sink_has_audio = drm_detect_monitor_audio(edid);
 273        drm_connector_update_edid_property(connector, edid);
 274        ret = drm_add_edid_modes(connector, edid);
 275        kfree(edid);
 276
 277        return ret;
 278}
 279
 280static enum drm_mode_status
 281zx_hdmi_connector_mode_valid(struct drm_connector *connector,
 282                             struct drm_display_mode *mode)
 283{
 284        return MODE_OK;
 285}
 286
 287static struct drm_connector_helper_funcs zx_hdmi_connector_helper_funcs = {
 288        .get_modes = zx_hdmi_connector_get_modes,
 289        .mode_valid = zx_hdmi_connector_mode_valid,
 290};
 291
 292static enum drm_connector_status
 293zx_hdmi_connector_detect(struct drm_connector *connector, bool force)
 294{
 295        struct zx_hdmi *hdmi = to_zx_hdmi(connector);
 296
 297        return (hdmi_readb(hdmi, TPI_HPD_RSEN) & TPI_HPD_CONNECTION) ?
 298                connector_status_connected : connector_status_disconnected;
 299}
 300
 301static const struct drm_connector_funcs zx_hdmi_connector_funcs = {
 302        .fill_modes = drm_helper_probe_single_connector_modes,
 303        .detect = zx_hdmi_connector_detect,
 304        .destroy = drm_connector_cleanup,
 305        .reset = drm_atomic_helper_connector_reset,
 306        .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
 307        .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
 308};
 309
 310static int zx_hdmi_register(struct drm_device *drm, struct zx_hdmi *hdmi)
 311{
 312        struct drm_encoder *encoder = &hdmi->encoder;
 313
 314        encoder->possible_crtcs = VOU_CRTC_MASK;
 315
 316        drm_encoder_init(drm, encoder, &zx_hdmi_encoder_funcs,
 317                         DRM_MODE_ENCODER_TMDS, NULL);
 318        drm_encoder_helper_add(encoder, &zx_hdmi_encoder_helper_funcs);
 319
 320        hdmi->connector.polled = DRM_CONNECTOR_POLL_HPD;
 321
 322        drm_connector_init(drm, &hdmi->connector, &zx_hdmi_connector_funcs,
 323                           DRM_MODE_CONNECTOR_HDMIA);
 324        drm_connector_helper_add(&hdmi->connector,
 325                                 &zx_hdmi_connector_helper_funcs);
 326
 327        drm_connector_attach_encoder(&hdmi->connector, encoder);
 328
 329        return 0;
 330}
 331
 332static irqreturn_t zx_hdmi_irq_thread(int irq, void *dev_id)
 333{
 334        struct zx_hdmi *hdmi = dev_id;
 335
 336        drm_helper_hpd_irq_event(hdmi->connector.dev);
 337
 338        return IRQ_HANDLED;
 339}
 340
 341static irqreturn_t zx_hdmi_irq_handler(int irq, void *dev_id)
 342{
 343        struct zx_hdmi *hdmi = dev_id;
 344        u8 lstat;
 345
 346        lstat = hdmi_readb(hdmi, L1_INTR_STAT);
 347
 348        /* Monitor detect/HPD interrupt */
 349        if (lstat & L1_INTR_STAT_INTR1) {
 350                u8 stat;
 351
 352                stat = hdmi_readb(hdmi, INTR1_STAT);
 353                hdmi_writeb(hdmi, INTR1_STAT, stat);
 354
 355                if (stat & INTR1_MONITOR_DETECT)
 356                        return IRQ_WAKE_THREAD;
 357        }
 358
 359        return IRQ_NONE;
 360}
 361
 362static int zx_hdmi_audio_startup(struct device *dev, void *data)
 363{
 364        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 365        struct drm_encoder *encoder = &hdmi->encoder;
 366
 367        vou_inf_hdmi_audio_sel(encoder->crtc, VOU_HDMI_AUD_SPDIF);
 368
 369        return 0;
 370}
 371
 372static void zx_hdmi_audio_shutdown(struct device *dev, void *data)
 373{
 374        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 375
 376        /* Disable audio input */
 377        hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, 0);
 378}
 379
 380static inline int zx_hdmi_audio_get_n(unsigned int fs)
 381{
 382        unsigned int n;
 383
 384        if (fs && (fs % 44100) == 0)
 385                n = 6272 * (fs / 44100);
 386        else
 387                n = fs * 128 / 1000;
 388
 389        return n;
 390}
 391
 392static int zx_hdmi_audio_hw_params(struct device *dev,
 393                                   void *data,
 394                                   struct hdmi_codec_daifmt *daifmt,
 395                                   struct hdmi_codec_params *params)
 396{
 397        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 398        struct hdmi_audio_infoframe *cea = &params->cea;
 399        union hdmi_infoframe frame;
 400        int n;
 401
 402        /* We only support spdif for now */
 403        if (daifmt->fmt != HDMI_SPDIF) {
 404                DRM_DEV_ERROR(hdmi->dev, "invalid daifmt %d\n", daifmt->fmt);
 405                return -EINVAL;
 406        }
 407
 408        switch (params->sample_width) {
 409        case 16:
 410                hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
 411                                 SPDIF_SAMPLE_SIZE_16BIT);
 412                break;
 413        case 20:
 414                hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
 415                                 SPDIF_SAMPLE_SIZE_20BIT);
 416                break;
 417        case 24:
 418                hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, SPDIF_SAMPLE_SIZE_MASK,
 419                                 SPDIF_SAMPLE_SIZE_24BIT);
 420                break;
 421        default:
 422                DRM_DEV_ERROR(hdmi->dev, "invalid sample width %d\n",
 423                              params->sample_width);
 424                return -EINVAL;
 425        }
 426
 427        /* CTS is calculated by hardware, and we only need to take care of N */
 428        n = zx_hdmi_audio_get_n(params->sample_rate);
 429        hdmi_writeb(hdmi, N_SVAL1, n & 0xff);
 430        hdmi_writeb(hdmi, N_SVAL2, (n >> 8) & 0xff);
 431        hdmi_writeb(hdmi, N_SVAL3, (n >> 16) & 0xf);
 432
 433        /* Enable spdif mode */
 434        hdmi_writeb_mask(hdmi, AUD_MODE, SPDIF_EN, SPDIF_EN);
 435
 436        /* Enable audio input */
 437        hdmi_writeb_mask(hdmi, AUD_EN, AUD_IN_EN, AUD_IN_EN);
 438
 439        memcpy(&frame.audio, cea, sizeof(*cea));
 440
 441        return zx_hdmi_infoframe_trans(hdmi, &frame, FSEL_AUDIO);
 442}
 443
 444static int zx_hdmi_audio_digital_mute(struct device *dev, void *data,
 445                                      bool enable)
 446{
 447        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 448
 449        if (enable)
 450                hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE,
 451                                 TPI_AUD_MUTE);
 452        else
 453                hdmi_writeb_mask(hdmi, TPI_AUD_CONFIG, TPI_AUD_MUTE, 0);
 454
 455        return 0;
 456}
 457
 458static int zx_hdmi_audio_get_eld(struct device *dev, void *data,
 459                                 uint8_t *buf, size_t len)
 460{
 461        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 462        struct drm_connector *connector = &hdmi->connector;
 463
 464        memcpy(buf, connector->eld, min(sizeof(connector->eld), len));
 465
 466        return 0;
 467}
 468
 469static const struct hdmi_codec_ops zx_hdmi_codec_ops = {
 470        .audio_startup = zx_hdmi_audio_startup,
 471        .hw_params = zx_hdmi_audio_hw_params,
 472        .audio_shutdown = zx_hdmi_audio_shutdown,
 473        .digital_mute = zx_hdmi_audio_digital_mute,
 474        .get_eld = zx_hdmi_audio_get_eld,
 475};
 476
 477static struct hdmi_codec_pdata zx_hdmi_codec_pdata = {
 478        .ops = &zx_hdmi_codec_ops,
 479        .spdif = 1,
 480};
 481
 482static int zx_hdmi_audio_register(struct zx_hdmi *hdmi)
 483{
 484        struct platform_device *pdev;
 485
 486        pdev = platform_device_register_data(hdmi->dev, HDMI_CODEC_DRV_NAME,
 487                                             PLATFORM_DEVID_AUTO,
 488                                             &zx_hdmi_codec_pdata,
 489                                             sizeof(zx_hdmi_codec_pdata));
 490        if (IS_ERR(pdev))
 491                return PTR_ERR(pdev);
 492
 493        hdmi->audio_pdev = pdev;
 494
 495        return 0;
 496}
 497
 498static int zx_hdmi_i2c_read(struct zx_hdmi *hdmi, struct i2c_msg *msg)
 499{
 500        int len = msg->len;
 501        u8 *buf = msg->buf;
 502        int retry = 0;
 503        int ret = 0;
 504
 505        /* Bits [9:8] of bytes */
 506        hdmi_writeb(hdmi, ZX_DDC_DIN_CNT2, (len >> 8) & 0xff);
 507        /* Bits [7:0] of bytes */
 508        hdmi_writeb(hdmi, ZX_DDC_DIN_CNT1, len & 0xff);
 509
 510        /* Clear FIFO */
 511        hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK, DDC_CMD_CLEAR_FIFO);
 512
 513        /* Kick off the read */
 514        hdmi_writeb_mask(hdmi, ZX_DDC_CMD, DDC_CMD_MASK,
 515                         DDC_CMD_SEQUENTIAL_READ);
 516
 517        while (len > 0) {
 518                int cnt, i;
 519
 520                /* FIFO needs some time to get ready */
 521                usleep_range(500, 1000);
 522
 523                cnt = hdmi_readb(hdmi, ZX_DDC_DOUT_CNT) & DDC_DOUT_CNT_MASK;
 524                if (cnt == 0) {
 525                        if (++retry > 5) {
 526                                DRM_DEV_ERROR(hdmi->dev,
 527                                              "DDC FIFO read timed out!");
 528                                return -ETIMEDOUT;
 529                        }
 530                        continue;
 531                }
 532
 533                for (i = 0; i < cnt; i++)
 534                        *buf++ = hdmi_readb(hdmi, ZX_DDC_DATA);
 535                len -= cnt;
 536        }
 537
 538        return ret;
 539}
 540
 541static int zx_hdmi_i2c_write(struct zx_hdmi *hdmi, struct i2c_msg *msg)
 542{
 543        /*
 544         * The DDC I2C adapter is only for reading EDID data, so we assume
 545         * that the write to this adapter must be the EDID data offset.
 546         */
 547        if ((msg->len != 1) ||
 548            ((msg->addr != DDC_ADDR) && (msg->addr != DDC_SEGMENT_ADDR)))
 549                return -EINVAL;
 550
 551        if (msg->addr == DDC_SEGMENT_ADDR)
 552                hdmi_writeb(hdmi, ZX_DDC_SEGM, msg->addr << 1);
 553        else if (msg->addr == DDC_ADDR)
 554                hdmi_writeb(hdmi, ZX_DDC_ADDR, msg->addr << 1);
 555
 556        hdmi_writeb(hdmi, ZX_DDC_OFFSET, msg->buf[0]);
 557
 558        return 0;
 559}
 560
 561static int zx_hdmi_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs,
 562                            int num)
 563{
 564        struct zx_hdmi *hdmi = i2c_get_adapdata(adap);
 565        struct zx_hdmi_i2c *ddc = hdmi->ddc;
 566        int i, ret = 0;
 567
 568        mutex_lock(&ddc->lock);
 569
 570        /* Enable DDC master access */
 571        hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, HW_DDC_MASTER);
 572
 573        for (i = 0; i < num; i++) {
 574                DRM_DEV_DEBUG(hdmi->dev,
 575                              "xfer: num: %d/%d, len: %d, flags: %#x\n",
 576                              i + 1, num, msgs[i].len, msgs[i].flags);
 577
 578                if (msgs[i].flags & I2C_M_RD)
 579                        ret = zx_hdmi_i2c_read(hdmi, &msgs[i]);
 580                else
 581                        ret = zx_hdmi_i2c_write(hdmi, &msgs[i]);
 582
 583                if (ret < 0)
 584                        break;
 585        }
 586
 587        if (!ret)
 588                ret = num;
 589
 590        /* Disable DDC master access */
 591        hdmi_writeb_mask(hdmi, TPI_DDC_MASTER_EN, HW_DDC_MASTER, 0);
 592
 593        mutex_unlock(&ddc->lock);
 594
 595        return ret;
 596}
 597
 598static u32 zx_hdmi_i2c_func(struct i2c_adapter *adapter)
 599{
 600        return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 601}
 602
 603static const struct i2c_algorithm zx_hdmi_algorithm = {
 604        .master_xfer    = zx_hdmi_i2c_xfer,
 605        .functionality  = zx_hdmi_i2c_func,
 606};
 607
 608static int zx_hdmi_ddc_register(struct zx_hdmi *hdmi)
 609{
 610        struct i2c_adapter *adap;
 611        struct zx_hdmi_i2c *ddc;
 612        int ret;
 613
 614        ddc = devm_kzalloc(hdmi->dev, sizeof(*ddc), GFP_KERNEL);
 615        if (!ddc)
 616                return -ENOMEM;
 617
 618        hdmi->ddc = ddc;
 619        mutex_init(&ddc->lock);
 620
 621        adap = &ddc->adap;
 622        adap->owner = THIS_MODULE;
 623        adap->class = I2C_CLASS_DDC;
 624        adap->dev.parent = hdmi->dev;
 625        adap->algo = &zx_hdmi_algorithm;
 626        snprintf(adap->name, sizeof(adap->name), "zx hdmi i2c");
 627
 628        ret = i2c_add_adapter(adap);
 629        if (ret) {
 630                DRM_DEV_ERROR(hdmi->dev, "failed to add I2C adapter: %d\n",
 631                              ret);
 632                return ret;
 633        }
 634
 635        i2c_set_adapdata(adap, hdmi);
 636
 637        return 0;
 638}
 639
 640static int zx_hdmi_bind(struct device *dev, struct device *master, void *data)
 641{
 642        struct platform_device *pdev = to_platform_device(dev);
 643        struct drm_device *drm = data;
 644        struct resource *res;
 645        struct zx_hdmi *hdmi;
 646        int irq;
 647        int ret;
 648
 649        hdmi = devm_kzalloc(dev, sizeof(*hdmi), GFP_KERNEL);
 650        if (!hdmi)
 651                return -ENOMEM;
 652
 653        hdmi->dev = dev;
 654        hdmi->drm = drm;
 655
 656        dev_set_drvdata(dev, hdmi);
 657
 658        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 659        hdmi->mmio = devm_ioremap_resource(dev, res);
 660        if (IS_ERR(hdmi->mmio)) {
 661                ret = PTR_ERR(hdmi->mmio);
 662                DRM_DEV_ERROR(dev, "failed to remap hdmi region: %d\n", ret);
 663                return ret;
 664        }
 665
 666        irq = platform_get_irq(pdev, 0);
 667        if (irq < 0)
 668                return irq;
 669
 670        hdmi->cec_clk = devm_clk_get(hdmi->dev, "osc_cec");
 671        if (IS_ERR(hdmi->cec_clk)) {
 672                ret = PTR_ERR(hdmi->cec_clk);
 673                DRM_DEV_ERROR(dev, "failed to get cec_clk: %d\n", ret);
 674                return ret;
 675        }
 676
 677        hdmi->osc_clk = devm_clk_get(hdmi->dev, "osc_clk");
 678        if (IS_ERR(hdmi->osc_clk)) {
 679                ret = PTR_ERR(hdmi->osc_clk);
 680                DRM_DEV_ERROR(dev, "failed to get osc_clk: %d\n", ret);
 681                return ret;
 682        }
 683
 684        hdmi->xclk = devm_clk_get(hdmi->dev, "xclk");
 685        if (IS_ERR(hdmi->xclk)) {
 686                ret = PTR_ERR(hdmi->xclk);
 687                DRM_DEV_ERROR(dev, "failed to get xclk: %d\n", ret);
 688                return ret;
 689        }
 690
 691        ret = zx_hdmi_ddc_register(hdmi);
 692        if (ret) {
 693                DRM_DEV_ERROR(dev, "failed to register ddc: %d\n", ret);
 694                return ret;
 695        }
 696
 697        ret = zx_hdmi_audio_register(hdmi);
 698        if (ret) {
 699                DRM_DEV_ERROR(dev, "failed to register audio: %d\n", ret);
 700                return ret;
 701        }
 702
 703        ret = zx_hdmi_register(drm, hdmi);
 704        if (ret) {
 705                DRM_DEV_ERROR(dev, "failed to register hdmi: %d\n", ret);
 706                return ret;
 707        }
 708
 709        ret = devm_request_threaded_irq(dev, irq, zx_hdmi_irq_handler,
 710                                        zx_hdmi_irq_thread, IRQF_SHARED,
 711                                        dev_name(dev), hdmi);
 712        if (ret) {
 713                DRM_DEV_ERROR(dev, "failed to request threaded irq: %d\n", ret);
 714                return ret;
 715        }
 716
 717        return 0;
 718}
 719
 720static void zx_hdmi_unbind(struct device *dev, struct device *master,
 721                           void *data)
 722{
 723        struct zx_hdmi *hdmi = dev_get_drvdata(dev);
 724
 725        hdmi->connector.funcs->destroy(&hdmi->connector);
 726        hdmi->encoder.funcs->destroy(&hdmi->encoder);
 727
 728        if (hdmi->audio_pdev)
 729                platform_device_unregister(hdmi->audio_pdev);
 730}
 731
 732static const struct component_ops zx_hdmi_component_ops = {
 733        .bind = zx_hdmi_bind,
 734        .unbind = zx_hdmi_unbind,
 735};
 736
 737static int zx_hdmi_probe(struct platform_device *pdev)
 738{
 739        return component_add(&pdev->dev, &zx_hdmi_component_ops);
 740}
 741
 742static int zx_hdmi_remove(struct platform_device *pdev)
 743{
 744        component_del(&pdev->dev, &zx_hdmi_component_ops);
 745        return 0;
 746}
 747
 748static const struct of_device_id zx_hdmi_of_match[] = {
 749        { .compatible = "zte,zx296718-hdmi", },
 750        { /* end */ },
 751};
 752MODULE_DEVICE_TABLE(of, zx_hdmi_of_match);
 753
 754struct platform_driver zx_hdmi_driver = {
 755        .probe = zx_hdmi_probe,
 756        .remove = zx_hdmi_remove,
 757        .driver = {
 758                .name = "zx-hdmi",
 759                .of_match_table = zx_hdmi_of_match,
 760        },
 761};
 762