uboot/drivers/video/dw_hdmi.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0+
   2/*
   3 * Copyright (c) 2015 Google, Inc
   4 * Copyright 2014 Rockchip Inc.
   5 * Copyright 2017 Jernej Skrabec <jernej.skrabec@siol.net>
   6 */
   7
   8#include <common.h>
   9#include <fdtdec.h>
  10#include <log.h>
  11#include <asm/io.h>
  12#include <i2c.h>
  13#include <media_bus_format.h>
  14#include <linux/delay.h>
  15#include "dw_hdmi.h"
  16
  17struct tmds_n_cts {
  18        u32 tmds;
  19        u32 cts;
  20        u32 n;
  21};
  22
  23static const struct tmds_n_cts n_cts_table[] = {
  24        {
  25                .tmds = 25175000, .n = 6144, .cts = 25175,
  26        }, {
  27                .tmds = 25200000, .n = 6144, .cts = 25200,
  28        }, {
  29                .tmds = 27000000, .n = 6144, .cts = 27000,
  30        }, {
  31                .tmds = 27027000, .n = 6144, .cts = 27027,
  32        }, {
  33                .tmds = 40000000, .n = 6144, .cts = 40000,
  34        }, {
  35                .tmds = 54000000, .n = 6144, .cts = 54000,
  36        }, {
  37                .tmds = 54054000, .n = 6144, .cts = 54054,
  38        }, {
  39                .tmds = 65000000, .n = 6144, .cts = 65000,
  40        }, {
  41                .tmds = 74176000, .n = 11648, .cts = 140625,
  42        }, {
  43                .tmds = 74250000, .n = 6144, .cts = 74250,
  44        }, {
  45                .tmds = 83500000, .n = 6144, .cts = 83500,
  46        }, {
  47                .tmds = 106500000, .n = 6144, .cts = 106500,
  48        }, {
  49                .tmds = 108000000, .n = 6144, .cts = 108000,
  50        }, {
  51                .tmds = 148352000, .n = 5824, .cts = 140625,
  52        }, {
  53                .tmds = 148500000, .n = 6144, .cts = 148500,
  54        }, {
  55                .tmds = 297000000, .n = 5120, .cts = 247500,
  56        }
  57};
  58
  59static const u16 csc_coeff_default[3][4] = {
  60        { 0x2000, 0x0000, 0x0000, 0x0000 },
  61        { 0x0000, 0x2000, 0x0000, 0x0000 },
  62        { 0x0000, 0x0000, 0x2000, 0x0000 }
  63};
  64
  65static const u16 csc_coeff_rgb_in_eitu601[3][4] = {
  66        { 0x2591, 0x1322, 0x074b, 0x0000 },
  67        { 0x6535, 0x2000, 0x7acc, 0x0200 },
  68        { 0x6acd, 0x7534, 0x2000, 0x0200 }
  69};
  70
  71static const u16 csc_coeff_rgb_out_eitu601[3][4] = {
  72        { 0x2000, 0x6926, 0x74fd, 0x010e },
  73        { 0x2000, 0x2cdd, 0x0000, 0x7e9a },
  74        { 0x2000, 0x0000, 0x38b4, 0x7e3b }
  75};
  76
  77static void dw_hdmi_write(struct dw_hdmi *hdmi, u8 val, int offset)
  78{
  79        switch (hdmi->reg_io_width) {
  80        case 1:
  81                writeb(val, hdmi->ioaddr + offset);
  82                break;
  83        case 4:
  84                writel(val, hdmi->ioaddr + (offset << 2));
  85                break;
  86        default:
  87                debug("reg_io_width has unsupported width!\n");
  88                break;
  89        }
  90}
  91
  92static u8 dw_hdmi_read(struct dw_hdmi *hdmi, int offset)
  93{
  94        switch (hdmi->reg_io_width) {
  95        case 1:
  96                return readb(hdmi->ioaddr + offset);
  97        case 4:
  98                return readl(hdmi->ioaddr + (offset << 2));
  99        default:
 100                debug("reg_io_width has unsupported width!\n");
 101                break;
 102        }
 103
 104        return 0;
 105}
 106
 107static u8 (*hdmi_read)(struct dw_hdmi *hdmi, int offset) = dw_hdmi_read;
 108static void (*hdmi_write)(struct dw_hdmi *hdmi, u8 val, int offset) =
 109                                                                 dw_hdmi_write;
 110
 111static void hdmi_mod(struct dw_hdmi *hdmi, unsigned reg, u8 mask, u8 data)
 112{
 113        u8 val = hdmi_read(hdmi, reg) & ~mask;
 114
 115        val |= data & mask;
 116        hdmi_write(hdmi, val, reg);
 117}
 118
 119static void hdmi_set_clock_regenerator(struct dw_hdmi *hdmi, u32 n, u32 cts)
 120{
 121        uint cts3;
 122        uint n3;
 123
 124        /* first set ncts_atomic_write (if present) */
 125        n3 = HDMI_AUD_N3_NCTS_ATOMIC_WRITE;
 126        hdmi_write(hdmi, n3, HDMI_AUD_N3);
 127
 128        /* set cts_manual (if present) */
 129        cts3 = HDMI_AUD_CTS3_CTS_MANUAL;
 130
 131        cts3 |= HDMI_AUD_CTS3_N_SHIFT_1 << HDMI_AUD_CTS3_N_SHIFT_OFFSET;
 132        cts3 |= (cts >> 16) & HDMI_AUD_CTS3_AUDCTS19_16_MASK;
 133
 134        /* write cts values; cts3 must be written first */
 135        hdmi_write(hdmi, cts3, HDMI_AUD_CTS3);
 136        hdmi_write(hdmi, (cts >> 8) & 0xff, HDMI_AUD_CTS2);
 137        hdmi_write(hdmi, cts & 0xff, HDMI_AUD_CTS1);
 138
 139        /* write n values; n1 must be written last */
 140        n3 |= (n >> 16) & HDMI_AUD_N3_AUDN19_16_MASK;
 141        hdmi_write(hdmi, n3, HDMI_AUD_N3);
 142        hdmi_write(hdmi, (n >> 8) & 0xff, HDMI_AUD_N2);
 143        hdmi_write(hdmi, n & 0xff, HDMI_AUD_N3);
 144
 145        hdmi_write(hdmi, HDMI_AUD_INPUTCLKFS_128, HDMI_AUD_INPUTCLKFS);
 146}
 147
 148static int hdmi_lookup_n_cts(u32 pixel_clk)
 149{
 150        int i;
 151
 152        for (i = 0; i < ARRAY_SIZE(n_cts_table); i++)
 153                if (pixel_clk <= n_cts_table[i].tmds)
 154                        break;
 155
 156        if (i >= ARRAY_SIZE(n_cts_table))
 157                return -1;
 158
 159        return i;
 160}
 161
 162static void hdmi_audio_set_samplerate(struct dw_hdmi *hdmi, u32 pixel_clk)
 163{
 164        u32 clk_n, clk_cts;
 165        int index;
 166
 167        index = hdmi_lookup_n_cts(pixel_clk);
 168        if (index == -1) {
 169                debug("audio not supported for pixel clk %d\n", pixel_clk);
 170                return;
 171        }
 172
 173        clk_n = n_cts_table[index].n;
 174        clk_cts = n_cts_table[index].cts;
 175        hdmi_set_clock_regenerator(hdmi, clk_n, clk_cts);
 176}
 177
 178/*
 179 * this submodule is responsible for the video data synchronization.
 180 * for example, for rgb 4:4:4 input, the data map is defined as
 181 *                      pin{47~40} <==> r[7:0]
 182 *                      pin{31~24} <==> g[7:0]
 183 *                      pin{15~8}  <==> b[7:0]
 184 */
 185static void hdmi_video_sample(struct dw_hdmi *hdmi)
 186{
 187        u32 color_format;
 188        uint val;
 189
 190        switch (hdmi->hdmi_data.enc_in_bus_format) {
 191        case MEDIA_BUS_FMT_RGB888_1X24:
 192                color_format = 0x01;
 193                break;
 194        case MEDIA_BUS_FMT_RGB101010_1X30:
 195                color_format = 0x03;
 196                break;
 197        case MEDIA_BUS_FMT_RGB121212_1X36:
 198                color_format = 0x05;
 199                break;
 200        case MEDIA_BUS_FMT_RGB161616_1X48:
 201                color_format = 0x07;
 202                break;
 203        case MEDIA_BUS_FMT_YUV8_1X24:
 204        case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
 205                color_format = 0x09;
 206                break;
 207        case MEDIA_BUS_FMT_YUV10_1X30:
 208        case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
 209                color_format = 0x0B;
 210                break;
 211        case MEDIA_BUS_FMT_YUV12_1X36:
 212        case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
 213                color_format = 0x0D;
 214                break;
 215        case MEDIA_BUS_FMT_YUV16_1X48:
 216        case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
 217                color_format = 0x0F;
 218                break;
 219        case MEDIA_BUS_FMT_UYVY8_1X16:
 220                color_format = 0x16;
 221                break;
 222        case MEDIA_BUS_FMT_UYVY10_1X20:
 223                color_format = 0x14;
 224                break;
 225        case MEDIA_BUS_FMT_UYVY12_1X24:
 226                color_format = 0x12;
 227                break;
 228        default:
 229                color_format = 0x01;
 230                break;
 231        }
 232
 233        val = HDMI_TX_INVID0_INTERNAL_DE_GENERATOR_DISABLE |
 234              ((color_format << HDMI_TX_INVID0_VIDEO_MAPPING_OFFSET) &
 235              HDMI_TX_INVID0_VIDEO_MAPPING_MASK);
 236
 237        hdmi_write(hdmi, val, HDMI_TX_INVID0);
 238
 239        /* enable tx stuffing: when de is inactive, fix the output data to 0 */
 240        val = HDMI_TX_INSTUFFING_BDBDATA_STUFFING_ENABLE |
 241              HDMI_TX_INSTUFFING_RCRDATA_STUFFING_ENABLE |
 242              HDMI_TX_INSTUFFING_GYDATA_STUFFING_ENABLE;
 243        hdmi_write(hdmi, val, HDMI_TX_INSTUFFING);
 244        hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA0);
 245        hdmi_write(hdmi, 0x0, HDMI_TX_GYDATA1);
 246        hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA0);
 247        hdmi_write(hdmi, 0x0, HDMI_TX_RCRDATA1);
 248        hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA0);
 249        hdmi_write(hdmi, 0x0, HDMI_TX_BCBDATA1);
 250}
 251
 252static void hdmi_video_packetize(struct dw_hdmi *hdmi)
 253{
 254        u32 output_select = HDMI_VP_CONF_OUTPUT_SELECTOR_BYPASS;
 255        u32 remap_size = HDMI_VP_REMAP_YCC422_16BIT;
 256        u32 color_depth = 0;
 257        uint val, vp_conf;
 258
 259        /* set the packetizer registers */
 260        val = ((color_depth << HDMI_VP_PR_CD_COLOR_DEPTH_OFFSET) &
 261                HDMI_VP_PR_CD_COLOR_DEPTH_MASK) |
 262                ((0 << HDMI_VP_PR_CD_DESIRED_PR_FACTOR_OFFSET) &
 263                HDMI_VP_PR_CD_DESIRED_PR_FACTOR_MASK);
 264        hdmi_write(hdmi, val, HDMI_VP_PR_CD);
 265
 266        hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PR_STUFFING_MASK,
 267                 HDMI_VP_STUFF_PR_STUFFING_STUFFING_MODE);
 268
 269        /* data from pixel repeater block */
 270        vp_conf = HDMI_VP_CONF_PR_EN_DISABLE |
 271                  HDMI_VP_CONF_BYPASS_SELECT_VID_PACKETIZER;
 272
 273        hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_PR_EN_MASK |
 274                 HDMI_VP_CONF_BYPASS_SELECT_MASK, vp_conf);
 275
 276        hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_IDEFAULT_PHASE_MASK,
 277                 1 << HDMI_VP_STUFF_IDEFAULT_PHASE_OFFSET);
 278
 279        hdmi_write(hdmi, remap_size, HDMI_VP_REMAP);
 280
 281        vp_conf = HDMI_VP_CONF_BYPASS_EN_ENABLE |
 282                  HDMI_VP_CONF_PP_EN_DISABLE |
 283                  HDMI_VP_CONF_YCC422_EN_DISABLE;
 284
 285        hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_BYPASS_EN_MASK |
 286                 HDMI_VP_CONF_PP_EN_ENMASK | HDMI_VP_CONF_YCC422_EN_MASK,
 287                 vp_conf);
 288
 289        hdmi_mod(hdmi, HDMI_VP_STUFF, HDMI_VP_STUFF_PP_STUFFING_MASK |
 290                 HDMI_VP_STUFF_YCC422_STUFFING_MASK,
 291                 HDMI_VP_STUFF_PP_STUFFING_STUFFING_MODE |
 292                 HDMI_VP_STUFF_YCC422_STUFFING_STUFFING_MODE);
 293
 294        hdmi_mod(hdmi, HDMI_VP_CONF, HDMI_VP_CONF_OUTPUT_SELECTOR_MASK,
 295                 output_select);
 296}
 297
 298static inline void hdmi_phy_test_clear(struct dw_hdmi *hdmi, uint bit)
 299{
 300        hdmi_mod(hdmi, HDMI_PHY_TST0, HDMI_PHY_TST0_TSTCLR_MASK,
 301                 bit << HDMI_PHY_TST0_TSTCLR_OFFSET);
 302}
 303
 304static int hdmi_phy_wait_i2c_done(struct dw_hdmi *hdmi, u32 msec)
 305{
 306        ulong start;
 307        u32 val;
 308
 309        start = get_timer(0);
 310        do {
 311                val = hdmi_read(hdmi, HDMI_IH_I2CMPHY_STAT0);
 312                if (val & 0x3) {
 313                        hdmi_write(hdmi, val, HDMI_IH_I2CMPHY_STAT0);
 314                        return 0;
 315                }
 316
 317                udelay(100);
 318        } while (get_timer(start) < msec);
 319
 320        return 1;
 321}
 322
 323static void hdmi_phy_i2c_write(struct dw_hdmi *hdmi, uint data, uint addr)
 324{
 325        hdmi_write(hdmi, 0xff, HDMI_IH_I2CMPHY_STAT0);
 326        hdmi_write(hdmi, addr, HDMI_PHY_I2CM_ADDRESS_ADDR);
 327        hdmi_write(hdmi, (u8)(data >> 8), HDMI_PHY_I2CM_DATAO_1_ADDR);
 328        hdmi_write(hdmi, (u8)(data >> 0), HDMI_PHY_I2CM_DATAO_0_ADDR);
 329        hdmi_write(hdmi, HDMI_PHY_I2CM_OPERATION_ADDR_WRITE,
 330                   HDMI_PHY_I2CM_OPERATION_ADDR);
 331
 332        hdmi_phy_wait_i2c_done(hdmi, 1000);
 333}
 334
 335static void hdmi_phy_enable_power(struct dw_hdmi *hdmi, uint enable)
 336{
 337        hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_PDZ_MASK,
 338                 enable << HDMI_PHY_CONF0_PDZ_OFFSET);
 339}
 340
 341static void hdmi_phy_enable_tmds(struct dw_hdmi *hdmi, uint enable)
 342{
 343        hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_ENTMDS_MASK,
 344                 enable << HDMI_PHY_CONF0_ENTMDS_OFFSET);
 345}
 346
 347static void hdmi_phy_enable_spare(struct dw_hdmi *hdmi, uint enable)
 348{
 349        hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SPARECTRL_MASK,
 350                 enable << HDMI_PHY_CONF0_SPARECTRL_OFFSET);
 351}
 352
 353static void hdmi_phy_gen2_pddq(struct dw_hdmi *hdmi, uint enable)
 354{
 355        hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_GEN2_PDDQ_MASK,
 356                 enable << HDMI_PHY_CONF0_GEN2_PDDQ_OFFSET);
 357}
 358
 359static void hdmi_phy_gen2_txpwron(struct dw_hdmi *hdmi, uint enable)
 360{
 361        hdmi_mod(hdmi, HDMI_PHY_CONF0,
 362                 HDMI_PHY_CONF0_GEN2_TXPWRON_MASK,
 363                 enable << HDMI_PHY_CONF0_GEN2_TXPWRON_OFFSET);
 364}
 365
 366static void hdmi_phy_sel_data_en_pol(struct dw_hdmi *hdmi, uint enable)
 367{
 368        hdmi_mod(hdmi, HDMI_PHY_CONF0,
 369                 HDMI_PHY_CONF0_SELDATAENPOL_MASK,
 370                 enable << HDMI_PHY_CONF0_SELDATAENPOL_OFFSET);
 371}
 372
 373static void hdmi_phy_sel_interface_control(struct dw_hdmi *hdmi,
 374                                           uint enable)
 375{
 376        hdmi_mod(hdmi, HDMI_PHY_CONF0, HDMI_PHY_CONF0_SELDIPIF_MASK,
 377                 enable << HDMI_PHY_CONF0_SELDIPIF_OFFSET);
 378}
 379
 380static int hdmi_phy_configure(struct dw_hdmi *hdmi, u32 mpixelclock)
 381{
 382        ulong start;
 383        uint i, val;
 384
 385        if (!hdmi->mpll_cfg || !hdmi->phy_cfg)
 386                return -1;
 387
 388        /* gen2 tx power off */
 389        hdmi_phy_gen2_txpwron(hdmi, 0);
 390
 391        /* gen2 pddq */
 392        hdmi_phy_gen2_pddq(hdmi, 1);
 393
 394        /* phy reset */
 395        hdmi_write(hdmi, HDMI_MC_PHYRSTZ_DEASSERT, HDMI_MC_PHYRSTZ);
 396        hdmi_write(hdmi, HDMI_MC_PHYRSTZ_ASSERT, HDMI_MC_PHYRSTZ);
 397        hdmi_write(hdmi, HDMI_MC_HEACPHY_RST_ASSERT, HDMI_MC_HEACPHY_RST);
 398
 399        hdmi_phy_test_clear(hdmi, 1);
 400        hdmi_write(hdmi, HDMI_PHY_I2CM_SLAVE_ADDR_PHY_GEN2,
 401                   HDMI_PHY_I2CM_SLAVE_ADDR);
 402        hdmi_phy_test_clear(hdmi, 0);
 403
 404        /* pll/mpll cfg - always match on final entry */
 405        for (i = 0; hdmi->mpll_cfg[i].mpixelclock != (~0ul); i++)
 406                if (mpixelclock <= hdmi->mpll_cfg[i].mpixelclock)
 407                        break;
 408
 409        hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].cpce, PHY_OPMODE_PLLCFG);
 410        hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].gmp, PHY_PLLGMPCTRL);
 411        hdmi_phy_i2c_write(hdmi, hdmi->mpll_cfg[i].curr, PHY_PLLCURRCTRL);
 412
 413        hdmi_phy_i2c_write(hdmi, 0x0000, PHY_PLLPHBYCTRL);
 414        hdmi_phy_i2c_write(hdmi, 0x0006, PHY_PLLCLKBISTPHASE);
 415
 416        for (i = 0; hdmi->phy_cfg[i].mpixelclock != (~0ul); i++)
 417                if (mpixelclock <= hdmi->phy_cfg[i].mpixelclock)
 418                        break;
 419
 420        /*
 421         * resistance term 133ohm cfg
 422         * preemp cgf 0.00
 423         * tx/ck lvl 10
 424         */
 425        hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].term, PHY_TXTERM);
 426        hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].sym_ctr, PHY_CKSYMTXCTRL);
 427        hdmi_phy_i2c_write(hdmi, hdmi->phy_cfg[i].vlev_ctr, PHY_VLEVCTRL);
 428
 429        /* remove clk term */
 430        hdmi_phy_i2c_write(hdmi, 0x8000, PHY_CKCALCTRL);
 431
 432        hdmi_phy_enable_power(hdmi, 1);
 433
 434        /* toggle tmds enable */
 435        hdmi_phy_enable_tmds(hdmi, 0);
 436        hdmi_phy_enable_tmds(hdmi, 1);
 437
 438        /* gen2 tx power on */
 439        hdmi_phy_gen2_txpwron(hdmi, 1);
 440        hdmi_phy_gen2_pddq(hdmi, 0);
 441
 442        hdmi_phy_enable_spare(hdmi, 1);
 443
 444        /* wait for phy pll lock */
 445        start = get_timer(0);
 446        do {
 447                val = hdmi_read(hdmi, HDMI_PHY_STAT0);
 448                if (!(val & HDMI_PHY_TX_PHY_LOCK))
 449                        return 0;
 450
 451                udelay(100);
 452        } while (get_timer(start) < 5);
 453
 454        return -1;
 455}
 456
 457static void hdmi_av_composer(struct dw_hdmi *hdmi,
 458                             const struct display_timing *edid)
 459{
 460        bool mdataenablepolarity = true;
 461        uint inv_val;
 462        uint hbl;
 463        uint vbl;
 464
 465        hbl = edid->hback_porch.typ + edid->hfront_porch.typ +
 466                        edid->hsync_len.typ;
 467        vbl = edid->vback_porch.typ + edid->vfront_porch.typ +
 468                        edid->vsync_len.typ;
 469
 470        /* set up hdmi_fc_invidconf */
 471        inv_val = HDMI_FC_INVIDCONF_HDCP_KEEPOUT_INACTIVE;
 472
 473        inv_val |= (edid->flags & DISPLAY_FLAGS_VSYNC_HIGH ?
 474                   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_HIGH :
 475                   HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY_ACTIVE_LOW);
 476
 477        inv_val |= (edid->flags & DISPLAY_FLAGS_HSYNC_HIGH ?
 478                   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_HIGH :
 479                   HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY_ACTIVE_LOW);
 480
 481        inv_val |= (mdataenablepolarity ?
 482                   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_HIGH :
 483                   HDMI_FC_INVIDCONF_DE_IN_POLARITY_ACTIVE_LOW);
 484
 485        inv_val |= (edid->hdmi_monitor ?
 486                   HDMI_FC_INVIDCONF_DVI_MODEZ_HDMI_MODE :
 487                   HDMI_FC_INVIDCONF_DVI_MODEZ_DVI_MODE);
 488
 489        inv_val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC_ACTIVE_LOW;
 490
 491        inv_val |= HDMI_FC_INVIDCONF_IN_I_P_PROGRESSIVE;
 492
 493        hdmi_write(hdmi, inv_val, HDMI_FC_INVIDCONF);
 494
 495        /* set up horizontal active pixel width */
 496        hdmi_write(hdmi, edid->hactive.typ >> 8, HDMI_FC_INHACTV1);
 497        hdmi_write(hdmi, edid->hactive.typ, HDMI_FC_INHACTV0);
 498
 499        /* set up vertical active lines */
 500        hdmi_write(hdmi, edid->vactive.typ >> 8, HDMI_FC_INVACTV1);
 501        hdmi_write(hdmi, edid->vactive.typ, HDMI_FC_INVACTV0);
 502
 503        /* set up horizontal blanking pixel region width */
 504        hdmi_write(hdmi, hbl >> 8, HDMI_FC_INHBLANK1);
 505        hdmi_write(hdmi, hbl, HDMI_FC_INHBLANK0);
 506
 507        /* set up vertical blanking pixel region width */
 508        hdmi_write(hdmi, vbl, HDMI_FC_INVBLANK);
 509
 510        /* set up hsync active edge delay width (in pixel clks) */
 511        hdmi_write(hdmi, edid->hfront_porch.typ >> 8, HDMI_FC_HSYNCINDELAY1);
 512        hdmi_write(hdmi, edid->hfront_porch.typ, HDMI_FC_HSYNCINDELAY0);
 513
 514        /* set up vsync active edge delay (in lines) */
 515        hdmi_write(hdmi, edid->vfront_porch.typ, HDMI_FC_VSYNCINDELAY);
 516
 517        /* set up hsync active pulse width (in pixel clks) */
 518        hdmi_write(hdmi, edid->hsync_len.typ >> 8, HDMI_FC_HSYNCINWIDTH1);
 519        hdmi_write(hdmi, edid->hsync_len.typ, HDMI_FC_HSYNCINWIDTH0);
 520
 521        /* set up vsync active edge delay (in lines) */
 522        hdmi_write(hdmi, edid->vsync_len.typ, HDMI_FC_VSYNCINWIDTH);
 523}
 524
 525static bool hdmi_bus_fmt_is_rgb(unsigned int bus_format)
 526{
 527        switch (bus_format) {
 528        case MEDIA_BUS_FMT_RGB888_1X24:
 529        case MEDIA_BUS_FMT_RGB101010_1X30:
 530        case MEDIA_BUS_FMT_RGB121212_1X36:
 531        case MEDIA_BUS_FMT_RGB161616_1X48:
 532                return true;
 533
 534        default:
 535                return false;
 536        }
 537}
 538
 539static bool hdmi_bus_fmt_is_yuv444(unsigned int bus_format)
 540{
 541        switch (bus_format) {
 542        case MEDIA_BUS_FMT_YUV8_1X24:
 543        case MEDIA_BUS_FMT_YUV10_1X30:
 544        case MEDIA_BUS_FMT_YUV12_1X36:
 545        case MEDIA_BUS_FMT_YUV16_1X48:
 546                return true;
 547
 548        default:
 549                return false;
 550        }
 551}
 552
 553static bool hdmi_bus_fmt_is_yuv422(unsigned int bus_format)
 554{
 555        switch (bus_format) {
 556        case MEDIA_BUS_FMT_UYVY8_1X16:
 557        case MEDIA_BUS_FMT_UYVY10_1X20:
 558        case MEDIA_BUS_FMT_UYVY12_1X24:
 559                return true;
 560
 561        default:
 562                return false;
 563        }
 564}
 565
 566static int is_color_space_interpolation(struct dw_hdmi *hdmi)
 567{
 568        if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_in_bus_format))
 569                return 0;
 570
 571        if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format) ||
 572            hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_out_bus_format))
 573                return 1;
 574
 575        return 0;
 576}
 577
 578static int is_color_space_decimation(struct dw_hdmi *hdmi)
 579{
 580        if (!hdmi_bus_fmt_is_yuv422(hdmi->hdmi_data.enc_out_bus_format))
 581                return 0;
 582
 583        if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_in_bus_format) ||
 584            hdmi_bus_fmt_is_yuv444(hdmi->hdmi_data.enc_in_bus_format))
 585                return 1;
 586
 587        return 0;
 588}
 589
 590static int hdmi_bus_fmt_color_depth(unsigned int bus_format)
 591{
 592        switch (bus_format) {
 593        case MEDIA_BUS_FMT_RGB888_1X24:
 594        case MEDIA_BUS_FMT_YUV8_1X24:
 595        case MEDIA_BUS_FMT_UYVY8_1X16:
 596        case MEDIA_BUS_FMT_UYYVYY8_0_5X24:
 597                return 8;
 598
 599        case MEDIA_BUS_FMT_RGB101010_1X30:
 600        case MEDIA_BUS_FMT_YUV10_1X30:
 601        case MEDIA_BUS_FMT_UYVY10_1X20:
 602        case MEDIA_BUS_FMT_UYYVYY10_0_5X30:
 603                return 10;
 604
 605        case MEDIA_BUS_FMT_RGB121212_1X36:
 606        case MEDIA_BUS_FMT_YUV12_1X36:
 607        case MEDIA_BUS_FMT_UYVY12_1X24:
 608        case MEDIA_BUS_FMT_UYYVYY12_0_5X36:
 609                return 12;
 610
 611        case MEDIA_BUS_FMT_RGB161616_1X48:
 612        case MEDIA_BUS_FMT_YUV16_1X48:
 613        case MEDIA_BUS_FMT_UYYVYY16_0_5X48:
 614                return 16;
 615
 616        default:
 617                return 0;
 618        }
 619}
 620
 621static int is_color_space_conversion(struct dw_hdmi *hdmi)
 622{
 623        return hdmi->hdmi_data.enc_in_bus_format !=
 624               hdmi->hdmi_data.enc_out_bus_format;
 625}
 626
 627static void dw_hdmi_update_csc_coeffs(struct dw_hdmi *hdmi)
 628{
 629        const u16 (*csc_coeff)[3][4] = &csc_coeff_default;
 630        unsigned int i;
 631        u32 csc_scale = 1;
 632
 633        if (is_color_space_conversion(hdmi)) {
 634                if (hdmi_bus_fmt_is_rgb(hdmi->hdmi_data.enc_out_bus_format)) {
 635                        csc_coeff = &csc_coeff_rgb_out_eitu601;
 636                } else if (hdmi_bus_fmt_is_rgb(
 637                                        hdmi->hdmi_data.enc_in_bus_format)) {
 638                        csc_coeff = &csc_coeff_rgb_in_eitu601;
 639                        csc_scale = 0;
 640                }
 641        }
 642
 643        /* The CSC registers are sequential, alternating MSB then LSB */
 644        for (i = 0; i < ARRAY_SIZE(csc_coeff_default[0]); i++) {
 645                u16 coeff_a = (*csc_coeff)[0][i];
 646                u16 coeff_b = (*csc_coeff)[1][i];
 647                u16 coeff_c = (*csc_coeff)[2][i];
 648
 649                hdmi_write(hdmi, coeff_a & 0xff, HDMI_CSC_COEF_A1_LSB + i * 2);
 650                hdmi_write(hdmi, coeff_a >> 8, HDMI_CSC_COEF_A1_MSB + i * 2);
 651                hdmi_write(hdmi, coeff_b & 0xff, HDMI_CSC_COEF_B1_LSB + i * 2);
 652                hdmi_write(hdmi, coeff_b >> 8, HDMI_CSC_COEF_B1_MSB + i * 2);
 653                hdmi_write(hdmi, coeff_c & 0xff, HDMI_CSC_COEF_C1_LSB + i * 2);
 654                hdmi_write(hdmi, coeff_c >> 8, HDMI_CSC_COEF_C1_MSB + i * 2);
 655        }
 656
 657        hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSCSCALE_MASK, csc_scale);
 658}
 659
 660static void hdmi_video_csc(struct dw_hdmi *hdmi)
 661{
 662        int color_depth = 0;
 663        int interpolation = HDMI_CSC_CFG_INTMODE_DISABLE;
 664        int decimation = 0;
 665
 666        /* YCC422 interpolation to 444 mode */
 667        if (is_color_space_interpolation(hdmi))
 668                interpolation = HDMI_CSC_CFG_INTMODE_CHROMA_INT_FORMULA1;
 669        else if (is_color_space_decimation(hdmi))
 670                decimation = HDMI_CSC_CFG_DECMODE_CHROMA_INT_FORMULA3;
 671
 672        switch (hdmi_bus_fmt_color_depth(hdmi->hdmi_data.enc_out_bus_format)) {
 673        case 8:
 674                color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_24BPP;
 675                break;
 676        case 10:
 677                color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_30BPP;
 678                break;
 679        case 12:
 680                color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_36BPP;
 681                break;
 682        case 16:
 683                color_depth = HDMI_CSC_SCALE_CSC_COLORDE_PTH_48BPP;
 684                break;
 685
 686        default:
 687                return;
 688        }
 689
 690        /* Configure the CSC registers */
 691        hdmi_write(hdmi, interpolation | decimation, HDMI_CSC_CFG);
 692
 693        hdmi_mod(hdmi, HDMI_CSC_SCALE, HDMI_CSC_SCALE_CSC_COLORDE_PTH_MASK,
 694                 color_depth);
 695
 696        dw_hdmi_update_csc_coeffs(hdmi);
 697}
 698
 699/* hdmi initialization step b.4 */
 700static void hdmi_enable_video_path(struct dw_hdmi *hdmi, bool audio)
 701{
 702        uint clkdis;
 703
 704        /* control period minimum duration */
 705        hdmi_write(hdmi, 12, HDMI_FC_CTRLDUR);
 706        hdmi_write(hdmi, 32, HDMI_FC_EXCTRLDUR);
 707        hdmi_write(hdmi, 1, HDMI_FC_EXCTRLSPAC);
 708
 709        /* set to fill tmds data channels */
 710        hdmi_write(hdmi, 0x0b, HDMI_FC_CH0PREAM);
 711        hdmi_write(hdmi, 0x16, HDMI_FC_CH1PREAM);
 712        hdmi_write(hdmi, 0x21, HDMI_FC_CH2PREAM);
 713
 714        hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
 715                   HDMI_MC_FLOWCTRL);
 716
 717        /* enable pixel clock and tmds data path */
 718        clkdis = 0x7f;
 719        clkdis &= ~HDMI_MC_CLKDIS_PIXELCLK_DISABLE;
 720        hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
 721
 722        clkdis &= ~HDMI_MC_CLKDIS_TMDSCLK_DISABLE;
 723        hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
 724
 725        /* Enable csc path */
 726        if (is_color_space_conversion(hdmi)) {
 727                clkdis &= ~HDMI_MC_CLKDIS_CSCCLK_DISABLE;
 728                hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
 729        }
 730
 731        /* Enable color space conversion if needed */
 732        if (is_color_space_conversion(hdmi))
 733                hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_IN_PATH,
 734                           HDMI_MC_FLOWCTRL);
 735        else
 736                hdmi_write(hdmi, HDMI_MC_FLOWCTRL_FEED_THROUGH_OFF_CSC_BYPASS,
 737                           HDMI_MC_FLOWCTRL);
 738
 739        if (audio) {
 740                clkdis &= ~HDMI_MC_CLKDIS_AUDCLK_DISABLE;
 741                hdmi_write(hdmi, clkdis, HDMI_MC_CLKDIS);
 742        }
 743}
 744
 745/* workaround to clear the overflow condition */
 746static void hdmi_clear_overflow(struct dw_hdmi *hdmi)
 747{
 748        uint val, count;
 749
 750        /* tmds software reset */
 751        hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_TMDSSWRST_REQ, HDMI_MC_SWRSTZ);
 752
 753        val = hdmi_read(hdmi, HDMI_FC_INVIDCONF);
 754
 755        for (count = 0; count < 4; count++)
 756                hdmi_write(hdmi, val, HDMI_FC_INVIDCONF);
 757}
 758
 759static void hdmi_audio_set_format(struct dw_hdmi *hdmi)
 760{
 761        hdmi_write(hdmi, HDMI_AUD_CONF0_I2S_SELECT | HDMI_AUD_CONF0_I2S_IN_EN_0,
 762                   HDMI_AUD_CONF0);
 763
 764
 765        hdmi_write(hdmi, HDMI_AUD_CONF1_I2S_MODE_STANDARD_MODE |
 766                   HDMI_AUD_CONF1_I2S_WIDTH_16BIT, HDMI_AUD_CONF1);
 767
 768        hdmi_write(hdmi, 0x00, HDMI_AUD_CONF2);
 769}
 770
 771static void hdmi_audio_fifo_reset(struct dw_hdmi *hdmi)
 772{
 773        hdmi_write(hdmi, (u8)~HDMI_MC_SWRSTZ_II2SSWRST_REQ, HDMI_MC_SWRSTZ);
 774        hdmi_write(hdmi, HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST, HDMI_AUD_CONF0);
 775
 776        hdmi_write(hdmi, 0x00, HDMI_AUD_INT);
 777        hdmi_write(hdmi, 0x00, HDMI_AUD_INT1);
 778}
 779
 780static int hdmi_get_plug_in_status(struct dw_hdmi *hdmi)
 781{
 782        uint val = hdmi_read(hdmi, HDMI_PHY_STAT0) & HDMI_PHY_HPD;
 783
 784        return !!val;
 785}
 786
 787static int hdmi_ddc_wait_i2c_done(struct dw_hdmi *hdmi, int msec)
 788{
 789        u32 val;
 790        ulong start;
 791
 792        start = get_timer(0);
 793        do {
 794                val = hdmi_read(hdmi, HDMI_IH_I2CM_STAT0);
 795                if (val & 0x2) {
 796                        hdmi_write(hdmi, val, HDMI_IH_I2CM_STAT0);
 797                        return 0;
 798                }
 799
 800                udelay(100);
 801        } while (get_timer(start) < msec);
 802
 803        return 1;
 804}
 805
 806static void hdmi_ddc_reset(struct dw_hdmi *hdmi)
 807{
 808        hdmi_mod(hdmi, HDMI_I2CM_SOFTRSTZ, HDMI_I2CM_SOFTRSTZ_MASK, 0);
 809}
 810
 811static int hdmi_read_edid(struct dw_hdmi *hdmi, int block, u8 *buff)
 812{
 813        int shift = (block % 2) * 0x80;
 814        int edid_read_err = 0;
 815        u32 trytime = 5;
 816        u32 n;
 817
 818        if (CONFIG_IS_ENABLED(DM_I2C) && hdmi->ddc_bus) {
 819                struct udevice *chip;
 820
 821                edid_read_err = i2c_get_chip(hdmi->ddc_bus,
 822                                             HDMI_I2CM_SLAVE_DDC_ADDR,
 823                                             1, &chip);
 824                if (edid_read_err)
 825                        return edid_read_err;
 826
 827                return dm_i2c_read(chip, shift, buff, HDMI_EDID_BLOCK_SIZE);
 828        }
 829
 830        /* set ddc i2c clk which devided from ddc_clk to 100khz */
 831        hdmi_write(hdmi, hdmi->i2c_clk_high, HDMI_I2CM_SS_SCL_HCNT_0_ADDR);
 832        hdmi_write(hdmi, hdmi->i2c_clk_low, HDMI_I2CM_SS_SCL_LCNT_0_ADDR);
 833        hdmi_mod(hdmi, HDMI_I2CM_DIV, HDMI_I2CM_DIV_FAST_STD_MODE,
 834                 HDMI_I2CM_DIV_STD_MODE);
 835
 836        hdmi_write(hdmi, HDMI_I2CM_SLAVE_DDC_ADDR, HDMI_I2CM_SLAVE);
 837        hdmi_write(hdmi, HDMI_I2CM_SEGADDR_DDC, HDMI_I2CM_SEGADDR);
 838        hdmi_write(hdmi, block >> 1, HDMI_I2CM_SEGPTR);
 839
 840        while (trytime--) {
 841                edid_read_err = 0;
 842
 843                for (n = 0; n < HDMI_EDID_BLOCK_SIZE; n++) {
 844                        hdmi_write(hdmi, shift + n, HDMI_I2CM_ADDRESS);
 845
 846                        if (block == 0)
 847                                hdmi_write(hdmi, HDMI_I2CM_OP_RD8,
 848                                           HDMI_I2CM_OPERATION);
 849                        else
 850                                hdmi_write(hdmi, HDMI_I2CM_OP_RD8_EXT,
 851                                           HDMI_I2CM_OPERATION);
 852
 853                        if (hdmi_ddc_wait_i2c_done(hdmi, 10)) {
 854                                hdmi_ddc_reset(hdmi);
 855                                edid_read_err = 1;
 856                                break;
 857                        }
 858
 859                        buff[n] = hdmi_read(hdmi, HDMI_I2CM_DATAI);
 860                }
 861
 862                if (!edid_read_err)
 863                        break;
 864        }
 865
 866        return edid_read_err;
 867}
 868
 869static const u8 pre_buf[] = {
 870        0x00, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00,
 871        0x04, 0x69, 0xfa, 0x23, 0xc8, 0x28, 0x01, 0x00,
 872        0x10, 0x17, 0x01, 0x03, 0x80, 0x33, 0x1d, 0x78,
 873        0x2a, 0xd9, 0x45, 0xa2, 0x55, 0x4d, 0xa0, 0x27,
 874        0x12, 0x50, 0x54, 0xb7, 0xef, 0x00, 0x71, 0x4f,
 875        0x81, 0x40, 0x81, 0x80, 0x95, 0x00, 0xb3, 0x00,
 876        0xd1, 0xc0, 0x81, 0xc0, 0x81, 0x00, 0x02, 0x3a,
 877        0x80, 0x18, 0x71, 0x38, 0x2d, 0x40, 0x58, 0x2c,
 878        0x45, 0x00, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
 879        0x00, 0x00, 0x00, 0xff, 0x00, 0x44, 0x34, 0x4c,
 880        0x4d, 0x54, 0x46, 0x30, 0x37, 0x35, 0x39, 0x37,
 881        0x36, 0x0a, 0x00, 0x00, 0x00, 0xfd, 0x00, 0x32,
 882        0x4b, 0x18, 0x53, 0x11, 0x00, 0x0a, 0x20, 0x20,
 883        0x20, 0x20, 0x20, 0x20, 0x00, 0x00, 0x00, 0xfc,
 884        0x00, 0x41, 0x53, 0x55, 0x53, 0x20, 0x56, 0x53,
 885        0x32, 0x33, 0x38, 0x0a, 0x20, 0x20, 0x01, 0xb0,
 886        0x02, 0x03, 0x22, 0x71, 0x4f, 0x01, 0x02, 0x03,
 887        0x11, 0x12, 0x13, 0x04, 0x14, 0x05, 0x0e, 0x0f,
 888        0x1d, 0x1e, 0x1f, 0x10, 0x23, 0x09, 0x17, 0x07,
 889        0x83, 0x01, 0x00, 0x00, 0x65, 0x03, 0x0c, 0x00,
 890        0x10, 0x00, 0x8c, 0x0a, 0xd0, 0x8a, 0x20, 0xe0,
 891        0x2d, 0x10, 0x10, 0x3e, 0x96, 0x00, 0xfd, 0x1e,
 892        0x11, 0x00, 0x00, 0x18, 0x01, 0x1d, 0x00, 0x72,
 893        0x51, 0xd0, 0x1e, 0x20, 0x6e, 0x28, 0x55, 0x00,
 894        0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e, 0x01, 0x1d,
 895        0x00, 0xbc, 0x52, 0xd0, 0x1e, 0x20, 0xb8, 0x28,
 896        0x55, 0x40, 0xfd, 0x1e, 0x11, 0x00, 0x00, 0x1e,
 897        0x8c, 0x0a, 0xd0, 0x90, 0x20, 0x40, 0x31, 0x20,
 898        0x0c, 0x40, 0x55, 0x00, 0xfd, 0x1e, 0x11, 0x00,
 899        0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 900        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
 901        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe9,
 902};
 903
 904int dw_hdmi_phy_cfg(struct dw_hdmi *hdmi, uint mpixelclock)
 905{
 906        int i, ret;
 907
 908        /* hdmi phy spec says to do the phy initialization sequence twice */
 909        for (i = 0; i < 2; i++) {
 910                hdmi_phy_sel_data_en_pol(hdmi, 1);
 911                hdmi_phy_sel_interface_control(hdmi, 0);
 912                hdmi_phy_enable_tmds(hdmi, 0);
 913                hdmi_phy_enable_power(hdmi, 0);
 914
 915                ret = hdmi_phy_configure(hdmi, mpixelclock);
 916                if (ret) {
 917                        debug("hdmi phy config failure %d\n", ret);
 918                        return ret;
 919                }
 920        }
 921
 922        return 0;
 923}
 924
 925int dw_hdmi_phy_wait_for_hpd(struct dw_hdmi *hdmi)
 926{
 927        ulong start;
 928
 929        start = get_timer(0);
 930        do {
 931                if (hdmi_get_plug_in_status(hdmi))
 932                        return 0;
 933                udelay(100);
 934        } while (get_timer(start) < 300);
 935
 936        return -1;
 937}
 938
 939void dw_hdmi_phy_init(struct dw_hdmi *hdmi)
 940{
 941        /* enable phy i2cm done irq */
 942        hdmi_write(hdmi, HDMI_PHY_I2CM_INT_ADDR_DONE_POL,
 943                   HDMI_PHY_I2CM_INT_ADDR);
 944
 945        /* enable phy i2cm nack & arbitration error irq */
 946        hdmi_write(hdmi, HDMI_PHY_I2CM_CTLINT_ADDR_NAC_POL |
 947                   HDMI_PHY_I2CM_CTLINT_ADDR_ARBITRATION_POL,
 948                   HDMI_PHY_I2CM_CTLINT_ADDR);
 949
 950        /* enable cable hot plug irq */
 951        hdmi_write(hdmi, (u8)~HDMI_PHY_HPD, HDMI_PHY_MASK0);
 952
 953        /* clear hotplug interrupts */
 954        hdmi_write(hdmi, HDMI_IH_PHY_STAT0_HPD, HDMI_IH_PHY_STAT0);
 955}
 956
 957int dw_hdmi_read_edid(struct dw_hdmi *hdmi, u8 *buf, int buf_size)
 958{
 959        u32 edid_size = HDMI_EDID_BLOCK_SIZE;
 960        int ret;
 961
 962        if (0) {
 963                edid_size = sizeof(pre_buf);
 964                memcpy(buf, pre_buf, edid_size);
 965        } else {
 966                ret = hdmi_read_edid(hdmi, 0, buf);
 967                if (ret) {
 968                        debug("failed to read edid.\n");
 969                        return -1;
 970                }
 971
 972                if (buf[0x7e] != 0) {
 973                        hdmi_read_edid(hdmi, 1, buf + HDMI_EDID_BLOCK_SIZE);
 974                        edid_size += HDMI_EDID_BLOCK_SIZE;
 975                }
 976        }
 977
 978        return edid_size;
 979}
 980
 981int dw_hdmi_enable(struct dw_hdmi *hdmi, const struct display_timing *edid)
 982{
 983        int ret;
 984
 985        debug("%s, mode info : clock %d hdis %d vdis %d\n",
 986              edid->hdmi_monitor ? "hdmi" : "dvi",
 987              edid->pixelclock.typ, edid->hactive.typ, edid->vactive.typ);
 988
 989        hdmi_av_composer(hdmi, edid);
 990
 991        ret = hdmi->phy_set(hdmi, edid->pixelclock.typ);
 992        if (ret)
 993                return ret;
 994
 995        hdmi_enable_video_path(hdmi, edid->hdmi_monitor);
 996
 997        if (edid->hdmi_monitor) {
 998                hdmi_audio_fifo_reset(hdmi);
 999                hdmi_audio_set_format(hdmi);
1000                hdmi_audio_set_samplerate(hdmi, edid->pixelclock.typ);
1001        }
1002
1003        hdmi_video_packetize(hdmi);
1004        hdmi_video_csc(hdmi);
1005        hdmi_video_sample(hdmi);
1006
1007        hdmi_clear_overflow(hdmi);
1008
1009        return 0;
1010}
1011
1012void dw_hdmi_init(struct dw_hdmi *hdmi)
1013{
1014        uint ih_mute;
1015
1016        /*
1017         * boot up defaults are:
1018         * hdmi_ih_mute   = 0x03 (disabled)
1019         * hdmi_ih_mute_* = 0x00 (enabled)
1020         *
1021         * disable top level interrupt bits in hdmi block
1022         */
1023        ih_mute = /*hdmi_read(hdmi, HDMI_IH_MUTE) |*/
1024                  HDMI_IH_MUTE_MUTE_WAKEUP_INTERRUPT |
1025                  HDMI_IH_MUTE_MUTE_ALL_INTERRUPT;
1026
1027        if (hdmi->write_reg)
1028                hdmi_write = hdmi->write_reg;
1029
1030        if (hdmi->read_reg)
1031                hdmi_read = hdmi->read_reg;
1032
1033        hdmi_write(hdmi, ih_mute, HDMI_IH_MUTE);
1034
1035        /* enable i2c master done irq */
1036        hdmi_write(hdmi, ~0x04, HDMI_I2CM_INT);
1037
1038        /* enable i2c client nack % arbitration error irq */
1039        hdmi_write(hdmi, ~0x44, HDMI_I2CM_CTLINT);
1040}
1041