Home | History | Annotate | Line # | Download | only in ic
dw_hdmi.c revision 1.4
      1 /* $NetBSD: dw_hdmi.c,v 1.4 2019/11/16 13:10:07 jmcneill Exp $ */
      2 
      3 /*-
      4  * Copyright (c) 2019 Jared D. McNeill <jmcneill (at) invisible.ca>
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
     21  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
     23  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
     24  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     26  * SUCH DAMAGE.
     27  */
     28 
     29 #include <sys/cdefs.h>
     30 __KERNEL_RCSID(0, "$NetBSD: dw_hdmi.c,v 1.4 2019/11/16 13:10:07 jmcneill Exp $");
     31 
     32 #include <sys/param.h>
     33 #include <sys/bus.h>
     34 #include <sys/device.h>
     35 #include <sys/intr.h>
     36 #include <sys/systm.h>
     37 #include <sys/kernel.h>
     38 #include <sys/conf.h>
     39 
     40 #include <dev/ic/dw_hdmi.h>
     41 
     42 #include <dev/i2c/i2cvar.h>
     43 #include <dev/i2c/ddcvar.h>
     44 #include <dev/i2c/ddcreg.h>
     45 #include <dev/videomode/videomode.h>
     46 #include <dev/videomode/edidvar.h>
     47 
     48 #include <dev/audio/audio_dai.h>
     49 
     50 #include <drm/drmP.h>
     51 #include <drm/drm_crtc.h>
     52 #include <drm/drm_crtc_helper.h>
     53 #include <drm/drm_edid.h>
     54 
     55 #define	HDMI_DESIGN_ID		0x0000
     56 #define	HDMI_REVISION_ID	0x0001
     57 #define	HDMI_CONFIG0_ID		0x0004
     58 #define	 HDMI_CONFIG0_ID_AUDI2S			__BIT(4)
     59 #define	HDMI_CONFIG2_ID		0x0006
     60 
     61 #define	HDMI_IH_I2CM_STAT0	0x0105
     62 #define	 HDMI_IH_I2CM_STAT0_DONE		__BIT(1)
     63 #define	 HDMI_IH_I2CM_STAT0_ERROR		__BIT(0)
     64 #define	HDMI_IH_MUTE		0x01ff
     65 #define	 HDMI_IH_MUTE_WAKEUP_INTERRUPT		__BIT(1)
     66 #define	 HDMI_IH_MUTE_ALL_INTERRUPT		__BIT(0)
     67 
     68 #define	HDMI_TX_INVID0		0x0200
     69 #define	 HDMI_TX_INVID0_VIDEO_MAPPING		__BITS(4,0)
     70 #define	  HDMI_TX_INVID0_VIDEO_MAPPING_DEFAULT	1
     71 #define	HDMI_TX_INSTUFFING	0x0201
     72 #define	 HDMI_TX_INSTUFFING_BCBDATA_STUFFING	__BIT(2)
     73 #define	 HDMI_TX_INSTUFFING_RCRDATA_STUFFING	__BIT(1)
     74 #define	 HDMI_TX_INSTUFFING_GYDATA_STUFFING	__BIT(0)
     75 #define	HDMI_TX_GYDATA0		0x0202
     76 #define	HDMI_TX_GYDATA1		0x0203
     77 #define	HDMI_TX_RCRDATA0	0x0204
     78 #define	HDMI_TX_RCRDATA1	0x0205
     79 #define	HDMI_TX_BCBDATA0	0x0206
     80 #define	HDMI_TX_BCBDATA1	0x0207
     81 
     82 #define	HDMI_VP_STATUS		0x0800
     83 #define	HDMI_VP_PR_CD		0x0801
     84 #define	 HDMI_VP_PR_CD_COLOR_DEPTH		__BITS(7,4)
     85 #define	  HDMI_VP_PR_CD_COLOR_DEPTH_24		0
     86 #define	 HDMI_VP_PR_CD_DESIRED_PR_FACTOR	__BITS(3,0)
     87 #define	  HDMI_VP_PR_CD_DESIRED_PR_FACTOR_NONE	0
     88 #define	HDMI_VP_STUFF		0x0802
     89 #define	 HDMI_VP_STUFF_IDEFAULT_PHASE		__BIT(5)
     90 #define	 HDMI_VP_STUFF_YCC422_STUFFING		__BIT(2)
     91 #define	 HDMI_VP_STUFF_PP_STUFFING		__BIT(1)
     92 #define	 HDMI_VP_STUFF_PR_STUFFING		__BIT(0)
     93 #define	HDMI_VP_REMAP		0x0803
     94 #define	 HDMI_VP_REMAP_YCC422_SIZE		__BITS(1,0)
     95 #define	  HDMI_VP_REMAP_YCC422_SIZE_16		0
     96 #define	HDMI_VP_CONF		0x0804
     97 #define	 HDMI_VP_CONF_BYPASS_EN			__BIT(6)
     98 #define	 HDMI_VP_CONF_BYPASS_SELECT		__BIT(2)
     99 #define	 HDMI_VP_CONF_OUTPUT_SELECT		__BITS(1,0)
    100 #define	  HDMI_VP_CONF_OUTPUT_SELECT_BYPASS	2
    101 #define	HDMI_VP_STAT		0x0805
    102 #define	HDMI_VP_INT		0x0806
    103 #define	HDMI_VP_MASK		0x0807
    104 #define	HDMI_VP_POL		0x0808
    105 
    106 #define	HDMI_FC_INVIDCONF	0x1000
    107 #define	 HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY	__BIT(6)
    108 #define	 HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY	__BIT(5)
    109 #define	 HDMI_FC_INVIDCONF_DE_IN_POLARITY	__BIT(4)
    110 #define	 HDMI_FC_INVIDCONF_DVI_MODE		__BIT(3)
    111 #define	 HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC	__BIT(1)
    112 #define	 HDMI_FC_INVIDCONF_IN_I_P		__BIT(0)
    113 #define	HDMI_FC_INHACTIV0	0x1001
    114 #define	HDMI_FC_INHACTIV1	0x1002
    115 #define	HDMI_FC_INHBLANK0	0x1003
    116 #define	HDMI_FC_INHBLANK1	0x1004
    117 #define	HDMI_FC_INVACTIV0	0x1005
    118 #define	HDMI_FC_INVACTIV1	0x1006
    119 #define	HDMI_FC_INVBLANK	0x1007
    120 #define	HDMI_FC_HSYNCINDELAY0	0x1008
    121 #define	HDMI_FC_HSYNCINDELAY1	0x1009
    122 #define	HDMI_FC_HSYNCINWIDTH0	0x100a
    123 #define	HDMI_FC_HSYNCINWIDTH1	0x100b
    124 #define	HDMI_FC_VSYNCINDELAY	0x100c
    125 #define	HDMI_FC_VSYNCINWIDTH	0x100d
    126 #define	HDMI_FC_CTRLDUR		0x1011
    127 #define	 HDMI_FC_CTRLDUR_DEFAULT		12
    128 #define	HDMI_FC_EXCTRLDUR	0x1012
    129 #define	 HDMI_FC_EXCTRLDUR_DEFAULT		32
    130 #define	HDMI_FC_EXCTRLSPAC	0x1013
    131 #define	 HDMI_FC_EXCTRLSPAC_DEFAULT		1
    132 #define	HDMI_FC_CH0PREAM	0x1014
    133 #define	 HDMI_FC_CH0PREAM_DEFAULT		0x0b
    134 #define	HDMI_FC_CH1PREAM	0x1015
    135 #define	 HDMI_FC_CH1PREAM_DEFAULT		0x16
    136 #define	HDMI_FC_CH2PREAM	0x1016
    137 #define	 HDMI_FC_CH2PREAM_DEFAULT		0x21
    138 #define	HDMI_FC_AUDCONF0	0x1025
    139 #define	HDMI_FC_AUDCONF1	0x1026
    140 #define	HDMI_FC_AUDCONF2	0x1027
    141 #define	HDMI_FC_AUDCONF3	0x1028
    142 
    143 #define	HDMI_PHY_CONF0		0x3000
    144 #define	 HDMI_PHY_CONF0_PDZ			__BIT(7)
    145 #define	 HDMI_PHY_CONF0_ENTMDS			__BIT(6)
    146 #define	 HDMI_PHY_CONF0_SVSRET			__BIT(5)
    147 #define	 HDMI_PHY_CONF0_PDDQ			__BIT(4)
    148 #define	 HDMI_PHY_CONF0_TXPWRON			__BIT(3)
    149 #define	 HDMI_PHY_CONF0_ENHPDRXSENSE		__BIT(2)
    150 #define	 HDMI_PHY_CONF0_SELDATAENPOL		__BIT(1)
    151 #define	 HDMI_PHY_CONF0_SELDIPIF		__BIT(0)
    152 #define	HDMI_PHY_STAT0		0x3004
    153 #define	 HDMI_PHY_STAT0_RX_SENSE_3		__BIT(7)
    154 #define	 HDMI_PHY_STAT0_RX_SENSE_2		__BIT(6)
    155 #define	 HDMI_PHY_STAT0_RX_SENSE_1		__BIT(5)
    156 #define	 HDMI_PHY_STAT0_RX_SENSE_0		__BIT(4)
    157 #define	 HDMI_PHY_STAT0_HPD			__BIT(1)
    158 #define	 HDMI_PHY_STAT0_TX_PHY_LOCK		__BIT(0)
    159 
    160 #define	HDMI_AUD_CONF0		0x3100
    161 #define	 HDMI_AUD_CONF0_SW_AUDIO_FIFO_RST	__BIT(7)
    162 #define	 HDMI_AUD_CONF0_I2S_SELECT		__BIT(5)
    163 #define	 HDMI_AUD_CONF0_I2S_IN_EN		__BITS(3,0)
    164 #define	HDMI_AUD_CONF1		0x3101
    165 #define	 HDMI_AUD_CONF1_I2S_WIDTH		__BITS(4,0)
    166 #define	HDMI_AUD_INT		0x3102
    167 #define	HDMI_AUD_CONF2		0x3103
    168 #define	 HDMI_AUD_CONF2_INSERT_PCUV		__BIT(2)
    169 #define	 HDMI_AUD_CONF2_NLPCM			__BIT(1)
    170 #define	 HDMI_AUD_CONF2_HBR			__BIT(0)
    171 #define	HDMI_AUD_INT1		0x3104
    172 
    173 #define	HDMI_AUD_N1		0x3200
    174 #define	HDMI_AUD_N2		0x3201
    175 #define	HDMI_AUD_N3		0x3202
    176 #define	HDMI_AUD_CTS1		0x3203
    177 #define	HDMI_AUD_CTS2		0x3204
    178 #define	HDMI_AUD_CTS3		0x3205
    179 #define	HDMI_AUD_INPUTCLKFS	0x3206
    180 #define	 HDMI_AUD_INPUTCLKFS_IFSFACTOR		__BITS(2,0)
    181 
    182 #define	HDMI_MC_CLKDIS		0x4001
    183 #define	 HDMI_MC_CLKDIS_HDCPCLK_DISABLE		__BIT(6)
    184 #define	 HDMI_MC_CLKDIS_CECCLK_DISABLE		__BIT(5)
    185 #define	 HDMI_MC_CLKDIS_CSCCLK_DISABLE		__BIT(4)
    186 #define	 HDMI_MC_CLKDIS_AUDCLK_DISABLE		__BIT(3)
    187 #define	 HDMI_MC_CLKDIS_PREPCLK_DISABLE		__BIT(2)
    188 #define	 HDMI_MC_CLKDIS_TMDSCLK_DISABLE		__BIT(1)
    189 #define	 HDMI_MC_CLKDIS_PIXELCLK_DISABLE	__BIT(0)
    190 #define	HDMI_MC_SWRSTZREQ	0x4002
    191 #define	 HDMI_MC_SWRSTZREQ_CECSWRST_REQ		__BIT(6)
    192 #define	 HDMI_MC_SWRSTZREQ_PREPSWRST_REQ	__BIT(2)
    193 #define	 HDMI_MC_SWRSTZREQ_TMDSSWRST_REQ	__BIT(1)
    194 #define	 HDMI_MC_SWRSTZREQ_PIXELSWRST_REQ	__BIT(0)
    195 #define	HDMI_MC_FLOWCTRL	0x4004
    196 #define	HDMI_MC_PHYRSTZ		0x4005
    197 #define	 HDMI_MC_PHYRSTZ_ASSERT			__BIT(0)
    198 #define	 HDMI_MC_PHYRSTZ_DEASSERT		0
    199 #define	HDMI_MC_LOCKONCLOCK	0x4006
    200 #define	HDMI_MC_HEACPHY_RST	0x4007
    201 
    202 #define	HDMI_I2CM_SLAVE		0x7e00
    203 #define	HDMI_I2CM_ADDRESS	0x7e01
    204 #define	HDMI_I2CM_DATAO		0x7e02
    205 #define	HDMI_I2CM_DATAI		0x7e03
    206 #define	HDMI_I2CM_OPERATION	0x7e04
    207 #define	 HDMI_I2CM_OPERATION_WR			__BIT(4)
    208 #define	 HDMI_I2CM_OPERATION_RD_EXT		__BIT(1)
    209 #define	 HDMI_I2CM_OPERATION_RD			__BIT(0)
    210 #define	HDMI_I2CM_INT		0x7e05
    211 #define	 HDMI_I2CM_INT_DONE_POL			__BIT(3)
    212 #define	 HDMI_I2CM_INT_DONE_MASK		__BIT(2)
    213 #define	 HDMI_I2CM_INT_DONE_INTERRUPT		__BIT(1)
    214 #define	 HDMI_I2CM_INT_DONE_STATUS		__BIT(0)
    215 #define	 HDMI_I2CM_INT_DEFAULT			\
    216 	(HDMI_I2CM_INT_DONE_POL|		\
    217 	 HDMI_I2CM_INT_DONE_INTERRUPT|		\
    218 	 HDMI_I2CM_INT_DONE_STATUS)
    219 #define	HDMI_I2CM_CTLINT	0x7e06
    220 #define	 HDMI_I2CM_CTLINT_NACK_POL		__BIT(7)
    221 #define	 HDMI_I2CM_CTLINT_NACK_MASK		__BIT(6)
    222 #define	 HDMI_I2CM_CTLINT_NACK_INTERRUPT	__BIT(5)
    223 #define	 HDMI_I2CM_CTLINT_NACK_STATUS		__BIT(4)
    224 #define	 HDMI_I2CM_CTLINT_ARB_POL		__BIT(3)
    225 #define	 HDMI_I2CM_CTLINT_ARB_MASK		__BIT(2)
    226 #define	 HDMI_I2CM_CTLINT_ARB_INTERRUPT		__BIT(1)
    227 #define	 HDMI_I2CM_CTLINT_ARB_STATUS		__BIT(0)
    228 #define	 HDMI_I2CM_CTLINT_DEFAULT		\
    229 	(HDMI_I2CM_CTLINT_NACK_POL|		\
    230 	 HDMI_I2CM_CTLINT_NACK_INTERRUPT|	\
    231 	 HDMI_I2CM_CTLINT_NACK_STATUS|		\
    232 	 HDMI_I2CM_CTLINT_ARB_POL|		\
    233 	 HDMI_I2CM_CTLINT_ARB_INTERRUPT|	\
    234 	 HDMI_I2CM_CTLINT_ARB_STATUS)
    235 #define	HDMI_I2CM_DIV		0x7e07
    236 #define	 HDMI_I2CM_DIV_FAST_STD_MODE		__BIT(3)
    237 #define	HDMI_I2CM_SEGADDR	0x7e08
    238 #define	 HDMI_I2CM_SEGADDR_SEGADDR		__BITS(6,0)
    239 #define	HDMI_I2CM_SOFTRSTZ	0x7e09
    240 #define	 HDMI_I2CM_SOFTRSTZ_I2C_SOFTRST		__BIT(0)
    241 #define	HDMI_I2CM_SEGPTR	0x7e0a
    242 
    243 enum dwhdmi_dai_mixer_ctrl {
    244 	DWHDMI_DAI_OUTPUT_CLASS,
    245 	DWHDMI_DAI_INPUT_CLASS,
    246 
    247 	DWHDMI_DAI_OUTPUT_MASTER_VOLUME,
    248 	DWHDMI_DAI_INPUT_DAC_VOLUME,
    249 
    250 	DWHDMI_DAI_MIXER_CTRL_LAST
    251 };
    252 
    253 static int
    254 dwhdmi_ddc_acquire_bus(void *priv, int flags)
    255 {
    256 	struct dwhdmi_softc * const sc = priv;
    257 
    258 	mutex_enter(&sc->sc_ic_lock);
    259 
    260 	return 0;
    261 }
    262 
    263 static void
    264 dwhdmi_ddc_release_bus(void *priv, int flags)
    265 {
    266 	struct dwhdmi_softc * const sc = priv;
    267 
    268 	mutex_exit(&sc->sc_ic_lock);
    269 }
    270 
    271 static int
    272 dwhdmi_ddc_exec(void *priv, i2c_op_t op, i2c_addr_t addr,
    273     const void *cmdbuf, size_t cmdlen, void *buf, size_t len, int flags)
    274 {
    275 	struct dwhdmi_softc * const sc = priv;
    276 	uint8_t block, operation, val;
    277 	uint8_t *pbuf = buf;
    278 	int off, n, retry;
    279 
    280 	KASSERT(mutex_owned(&sc->sc_ic_lock));
    281 
    282 	if (addr != DDC_ADDR || op != I2C_OP_READ_WITH_STOP || cmdlen == 0 || buf == NULL) {
    283 		printf("dwhdmi_ddc_exec: bad args addr=%#x op=%#x cmdlen=%d buf=%p\n",
    284 		    addr, op, (int)cmdlen, buf);
    285 		return ENXIO;
    286 	}
    287 	if (len > 256) {
    288 		printf("dwhdmi_ddc_exec: bad len %d\n", (int)len);
    289 		return ERANGE;
    290 	}
    291 
    292 	dwhdmi_write(sc, HDMI_I2CM_SOFTRSTZ, 0);
    293 	dwhdmi_write(sc, HDMI_IH_I2CM_STAT0, dwhdmi_read(sc, HDMI_IH_I2CM_STAT0));
    294 	dwhdmi_write(sc, HDMI_I2CM_DIV, 0);
    295 	dwhdmi_write(sc, HDMI_I2CM_SLAVE, DDC_ADDR);
    296 	dwhdmi_write(sc, HDMI_I2CM_SEGADDR, DDC_SEGMENT_ADDR);
    297 
    298 	block = *(const uint8_t *)cmdbuf;
    299 	operation = block ? HDMI_I2CM_OPERATION_RD_EXT : HDMI_I2CM_OPERATION_RD;
    300 	off = (block & 1) ? 128 : 0;
    301 
    302 	for (n = 0; n < len; n++) {
    303 		dwhdmi_write(sc, HDMI_I2CM_ADDRESS, n + off);
    304 		dwhdmi_write(sc, HDMI_I2CM_OPERATION, operation);
    305 		for (retry = 10000; retry > 0; retry--) {
    306 			val = dwhdmi_read(sc, HDMI_IH_I2CM_STAT0);
    307 			if (val & HDMI_IH_I2CM_STAT0_ERROR) {
    308 				return EIO;
    309 			}
    310 			if (val & HDMI_IH_I2CM_STAT0_DONE) {
    311 				dwhdmi_write(sc, HDMI_IH_I2CM_STAT0, val);
    312 				break;
    313 			}
    314 			delay(1);
    315 		}
    316 		if (retry == 0) {
    317 			printf("dwhdmi_ddc_exec: timeout waiting for xfer, stat0=%#x\n", dwhdmi_read(sc, HDMI_IH_I2CM_STAT0));
    318 			return ETIMEDOUT;
    319 		}
    320 
    321 		pbuf[n] = dwhdmi_read(sc, HDMI_I2CM_DATAI);
    322 	}
    323 
    324 	return 0;
    325 }
    326 
    327 uint8_t
    328 dwhdmi_read(struct dwhdmi_softc *sc, bus_size_t reg)
    329 {
    330 	uint8_t val;
    331 
    332 	switch (sc->sc_reg_width) {
    333 	case 1:
    334 		val = bus_space_read_1(sc->sc_bst, sc->sc_bsh, reg);
    335 		break;
    336 	case 4:
    337 		val = bus_space_read_4(sc->sc_bst, sc->sc_bsh, reg * 4) & 0xff;
    338 		break;
    339 	default:
    340 		val = 0;
    341 		break;
    342 	}
    343 
    344 	return val;
    345 }
    346 
    347 void
    348 dwhdmi_write(struct dwhdmi_softc *sc, bus_size_t reg, uint8_t val)
    349 {
    350 	switch (sc->sc_reg_width) {
    351 	case 1:
    352 		bus_space_write_1(sc->sc_bst, sc->sc_bsh, reg, val);
    353 		break;
    354 	case 4:
    355 		bus_space_write_4(sc->sc_bst, sc->sc_bsh, reg * 4, val);
    356 		break;
    357 	}
    358 }
    359 
    360 static void
    361 dwhdmi_vp_init(struct dwhdmi_softc *sc)
    362 {
    363 	uint8_t val;
    364 
    365 	/* Select 24-bits per pixel video, 8-bit packing mode and disable pixel repetition */
    366 	val = __SHIFTIN(HDMI_VP_PR_CD_COLOR_DEPTH_24, HDMI_VP_PR_CD_COLOR_DEPTH) |
    367 	      __SHIFTIN(HDMI_VP_PR_CD_DESIRED_PR_FACTOR_NONE, HDMI_VP_PR_CD_DESIRED_PR_FACTOR);
    368 	dwhdmi_write(sc, HDMI_VP_PR_CD, val);
    369 
    370 	/* Configure stuffing */
    371 	val = HDMI_VP_STUFF_IDEFAULT_PHASE |
    372 	      HDMI_VP_STUFF_YCC422_STUFFING |
    373 	      HDMI_VP_STUFF_PP_STUFFING |
    374 	      HDMI_VP_STUFF_PR_STUFFING;
    375 	dwhdmi_write(sc, HDMI_VP_STUFF, val);
    376 
    377 	/* Set YCC422 remap to 16-bit input video */
    378 	val = __SHIFTIN(HDMI_VP_REMAP_YCC422_SIZE_16, HDMI_VP_REMAP_YCC422_SIZE);
    379 	dwhdmi_write(sc, HDMI_VP_REMAP, val);
    380 
    381 	/* Configure video packetizer */
    382 	val = HDMI_VP_CONF_BYPASS_EN |
    383 	      HDMI_VP_CONF_BYPASS_SELECT |
    384 	      __SHIFTIN(HDMI_VP_CONF_OUTPUT_SELECT_BYPASS, HDMI_VP_CONF_OUTPUT_SELECT);
    385 	dwhdmi_write(sc, HDMI_VP_CONF, val);
    386 }
    387 
    388 static void
    389 dwhdmi_tx_init(struct dwhdmi_softc *sc)
    390 {
    391 	uint8_t val;
    392 
    393 	/* Disable internal data enable generator and set default video mapping */
    394 	val = __SHIFTIN(HDMI_TX_INVID0_VIDEO_MAPPING_DEFAULT, HDMI_TX_INVID0_VIDEO_MAPPING);
    395 	dwhdmi_write(sc, HDMI_TX_INVID0, val);
    396 
    397 	/* Enable video sampler stuffing */
    398 	val = HDMI_TX_INSTUFFING_BCBDATA_STUFFING |
    399 	      HDMI_TX_INSTUFFING_RCRDATA_STUFFING |
    400 	      HDMI_TX_INSTUFFING_GYDATA_STUFFING;
    401 	dwhdmi_write(sc, HDMI_TX_INSTUFFING, val);
    402 }
    403 
    404 static bool
    405 dwhdmi_cea_mode_uses_fractional_vblank(uint8_t vic)
    406 {
    407 	const uint8_t match[] = { 5, 6, 7, 10, 11, 20, 21, 22 };
    408 	u_int n;
    409 
    410 	for (n = 0; n < __arraycount(match); n++)
    411 		if (match[n] == vic)
    412 			return true;
    413 
    414 	return false;
    415 }
    416 
    417 static void
    418 dwhdmi_fc_init(struct dwhdmi_softc *sc, struct drm_display_mode *mode)
    419 {
    420 	struct dwhdmi_connector *dwhdmi_connector = &sc->sc_connector;
    421 	uint8_t val;
    422 
    423 	const uint8_t vic = drm_match_cea_mode(mode);
    424 	const uint16_t inhactiv = mode->hdisplay;
    425 	const uint16_t inhblank = mode->htotal - mode->hdisplay;
    426 	const uint16_t invactiv = mode->vdisplay;
    427 	const uint8_t invblank = mode->vtotal - mode->vdisplay;
    428 	const uint16_t hsyncindelay = mode->hsync_start - mode->hdisplay;
    429 	const uint16_t hsyncinwidth = mode->hsync_end - mode->hsync_start;
    430 	const uint8_t vsyncindelay = mode->vsync_start - mode->vdisplay;
    431 	const uint8_t vsyncinwidth = mode->vsync_end - mode->vsync_start;
    432 
    433 	/* Input video configuration for frame composer */
    434 	val = HDMI_FC_INVIDCONF_DE_IN_POLARITY;
    435 	if ((mode->flags & DRM_MODE_FLAG_PVSYNC) != 0)
    436 		val |= HDMI_FC_INVIDCONF_VSYNC_IN_POLARITY;
    437 	if ((mode->flags & DRM_MODE_FLAG_PHSYNC) != 0)
    438 		val |= HDMI_FC_INVIDCONF_HSYNC_IN_POLARITY;
    439 	if ((mode->flags & DRM_MODE_FLAG_INTERLACE) != 0)
    440 		val |= HDMI_FC_INVIDCONF_IN_I_P;
    441 	if (dwhdmi_connector->hdmi_monitor)
    442 		val |= HDMI_FC_INVIDCONF_DVI_MODE;
    443 	if (dwhdmi_cea_mode_uses_fractional_vblank(vic))
    444 		val |= HDMI_FC_INVIDCONF_R_V_BLANK_IN_OSC;
    445 	dwhdmi_write(sc, HDMI_FC_INVIDCONF, val);
    446 
    447 	/* Input video mode timings */
    448 	dwhdmi_write(sc, HDMI_FC_INHACTIV0, inhactiv & 0xff);
    449 	dwhdmi_write(sc, HDMI_FC_INHACTIV1, inhactiv >> 8);
    450 	dwhdmi_write(sc, HDMI_FC_INHBLANK0, inhblank & 0xff);
    451 	dwhdmi_write(sc, HDMI_FC_INHBLANK1, inhblank >> 8);
    452 	dwhdmi_write(sc, HDMI_FC_INVACTIV0, invactiv & 0xff);
    453 	dwhdmi_write(sc, HDMI_FC_INVACTIV1, invactiv >> 8);
    454 	dwhdmi_write(sc, HDMI_FC_INVBLANK, invblank);
    455 	dwhdmi_write(sc, HDMI_FC_HSYNCINDELAY0, hsyncindelay & 0xff);
    456 	dwhdmi_write(sc, HDMI_FC_HSYNCINDELAY1, hsyncindelay >> 8);
    457 	dwhdmi_write(sc, HDMI_FC_HSYNCINWIDTH0, hsyncinwidth & 0xff);
    458 	dwhdmi_write(sc, HDMI_FC_HSYNCINWIDTH1, hsyncinwidth >> 8);
    459 	dwhdmi_write(sc, HDMI_FC_VSYNCINDELAY, vsyncindelay);
    460 	dwhdmi_write(sc, HDMI_FC_VSYNCINWIDTH, vsyncinwidth);
    461 
    462 	/* Setup control period minimum durations */
    463 	dwhdmi_write(sc, HDMI_FC_CTRLDUR, HDMI_FC_CTRLDUR_DEFAULT);
    464 	dwhdmi_write(sc, HDMI_FC_EXCTRLDUR, HDMI_FC_EXCTRLDUR_DEFAULT);
    465 	dwhdmi_write(sc, HDMI_FC_EXCTRLSPAC, HDMI_FC_EXCTRLSPAC_DEFAULT);
    466 
    467 	/* Setup channel preamble filters */
    468 	dwhdmi_write(sc, HDMI_FC_CH0PREAM, HDMI_FC_CH0PREAM_DEFAULT);
    469 	dwhdmi_write(sc, HDMI_FC_CH1PREAM, HDMI_FC_CH1PREAM_DEFAULT);
    470 	dwhdmi_write(sc, HDMI_FC_CH2PREAM, HDMI_FC_CH2PREAM_DEFAULT);
    471 }
    472 
    473 static void
    474 dwhdmi_mc_init(struct dwhdmi_softc *sc)
    475 {
    476 	uint8_t val;
    477 	u_int n, iter;
    478 
    479 	/* Bypass colour space converter */
    480 	dwhdmi_write(sc, HDMI_MC_FLOWCTRL, 0);
    481 
    482 	/* Enable TMDS, pixel, and (if required) audio sampler clocks */
    483 	val = HDMI_MC_CLKDIS_HDCPCLK_DISABLE |
    484 	      HDMI_MC_CLKDIS_CECCLK_DISABLE |
    485 	      HDMI_MC_CLKDIS_CSCCLK_DISABLE |
    486 	      HDMI_MC_CLKDIS_PREPCLK_DISABLE;
    487 	dwhdmi_write(sc, HDMI_MC_CLKDIS, val);
    488 
    489 	/* Soft reset TMDS */
    490 	val = 0xff & ~HDMI_MC_SWRSTZREQ_TMDSSWRST_REQ;
    491 	dwhdmi_write(sc, HDMI_MC_SWRSTZREQ, val);
    492 
    493 	iter = sc->sc_version == 0x130a ? 4 : 1;
    494 
    495 	val = dwhdmi_read(sc, HDMI_FC_INVIDCONF);
    496 	for (n = 0; n < iter; n++)
    497 		dwhdmi_write(sc, HDMI_FC_INVIDCONF, val);
    498 }
    499 
    500 static void
    501 dwhdmi_mc_disable(struct dwhdmi_softc *sc)
    502 {
    503 	/* Disable clocks */
    504 	dwhdmi_write(sc, HDMI_MC_CLKDIS, 0xff);
    505 }
    506 
    507 static void
    508 dwhdmi_audio_init(struct dwhdmi_softc *sc)
    509 {
    510 	uint8_t val;
    511 	u_int n;
    512 
    513 	/* The following values are for 48 kHz */
    514 	switch (sc->sc_curmode.clock) {
    515 	case 25170:
    516 		n = 6864;
    517 		break;
    518 	case 74170:
    519 		n = 11648;
    520 		break;
    521 	case 148350:
    522 		n = 5824;
    523 		break;
    524 	default:
    525 		n = 6144;
    526 		break;
    527 	}
    528 
    529 	/* Use automatic CTS generation */
    530 	dwhdmi_write(sc, HDMI_AUD_CTS1, 0);
    531 	dwhdmi_write(sc, HDMI_AUD_CTS2, 0);
    532 	dwhdmi_write(sc, HDMI_AUD_CTS3, 0);
    533 
    534 	/* Set N factor for audio clock regeneration */
    535 	dwhdmi_write(sc, HDMI_AUD_N1, n & 0xff);
    536 	dwhdmi_write(sc, HDMI_AUD_N2, (n >> 8) & 0xff);
    537 	dwhdmi_write(sc, HDMI_AUD_N3, (n >> 16) & 0xff);
    538 
    539 	val = dwhdmi_read(sc, HDMI_AUD_CONF0);
    540 	val |= HDMI_AUD_CONF0_I2S_SELECT;		/* XXX i2s mode */
    541 	val &= ~HDMI_AUD_CONF0_I2S_IN_EN;
    542 	val |= __SHIFTIN(1, HDMI_AUD_CONF0_I2S_IN_EN);	/* XXX 2ch */
    543 	dwhdmi_write(sc, HDMI_AUD_CONF0, val);
    544 
    545 	val = __SHIFTIN(16, HDMI_AUD_CONF1_I2S_WIDTH);
    546 	dwhdmi_write(sc, HDMI_AUD_CONF1, val);
    547 
    548 	dwhdmi_write(sc, HDMI_AUD_INPUTCLKFS, 4);	/* XXX 64 FS */
    549 
    550 	dwhdmi_write(sc, HDMI_FC_AUDCONF0, 1 << 4);	/* XXX 2ch */
    551 	dwhdmi_write(sc, HDMI_FC_AUDCONF1, 0);
    552 	dwhdmi_write(sc, HDMI_FC_AUDCONF2, 0);
    553 	dwhdmi_write(sc, HDMI_FC_AUDCONF3, 0);
    554 
    555 	val = dwhdmi_read(sc, HDMI_MC_CLKDIS);
    556 	val &= ~HDMI_MC_CLKDIS_PREPCLK_DISABLE;
    557 	dwhdmi_write(sc, HDMI_MC_CLKDIS, val);
    558 }
    559 
    560 static enum drm_connector_status
    561 dwhdmi_connector_detect(struct drm_connector *connector, bool force)
    562 {
    563 	struct dwhdmi_connector *dwhdmi_connector = to_dwhdmi_connector(connector);
    564 	struct dwhdmi_softc * const sc = dwhdmi_connector->sc;
    565 
    566 	if (sc->sc_detect != NULL)
    567 		return sc->sc_detect(sc, force);
    568 
    569 	return connector_status_connected;
    570 }
    571 
    572 static void
    573 dwhdmi_connector_destroy(struct drm_connector *connector)
    574 {
    575 	drm_connector_unregister(connector);
    576 	drm_connector_cleanup(connector);
    577 }
    578 
    579 static const struct drm_connector_funcs dwhdmi_connector_funcs = {
    580 	.dpms = drm_helper_connector_dpms,
    581 	.detect = dwhdmi_connector_detect,
    582 	.fill_modes = drm_helper_probe_single_connector_modes,
    583 	.destroy = dwhdmi_connector_destroy,
    584 };
    585 
    586 static int
    587 dwhdmi_connector_get_modes(struct drm_connector *connector)
    588 {
    589 	struct dwhdmi_connector *dwhdmi_connector = to_dwhdmi_connector(connector);
    590 	struct dwhdmi_softc * const sc = dwhdmi_connector->sc;
    591 	char edid[EDID_LENGTH * 4];
    592 	struct edid *pedid = NULL;
    593 	int error, block;
    594 
    595 	memset(edid, 0, sizeof(edid));
    596 	for (block = 0; block < 4; block++) {
    597 		error = ddc_read_edid_block(sc->sc_ic,
    598 		    &edid[block * EDID_LENGTH], EDID_LENGTH, block);
    599 		if (error != 0)
    600 			break;
    601 		if (block == 0) {
    602 			pedid = (struct edid *)edid;
    603 			if (edid[0x7e] == 0)
    604 				break;
    605 		}
    606 	}
    607 
    608 	if (pedid) {
    609 		dwhdmi_connector->hdmi_monitor = drm_detect_hdmi_monitor(pedid);
    610 		dwhdmi_connector->monitor_audio = drm_detect_monitor_audio(pedid);
    611 	} else {
    612 		dwhdmi_connector->hdmi_monitor = false;
    613 		dwhdmi_connector->monitor_audio = false;
    614 	}
    615 
    616 	drm_mode_connector_update_edid_property(connector, pedid);
    617 	if (pedid == NULL)
    618 		return 0;
    619 
    620 	error = drm_add_edid_modes(connector, pedid);
    621 	drm_edid_to_eld(connector, pedid);
    622 
    623 	return error;
    624 }
    625 
    626 static struct drm_encoder *
    627 dwhdmi_connector_best_encoder(struct drm_connector *connector)
    628 {
    629 	int enc_id = connector->encoder_ids[0];
    630 	struct drm_mode_object *obj;
    631 	struct drm_encoder *encoder = NULL;
    632 
    633 	if (enc_id) {
    634 		obj = drm_mode_object_find(connector->dev, enc_id,
    635 		    DRM_MODE_OBJECT_ENCODER);
    636 		if (obj == NULL)
    637 			return NULL;
    638 		encoder = obj_to_encoder(obj);
    639 	}
    640 
    641 	return encoder;
    642 }
    643 
    644 static const struct drm_connector_helper_funcs dwhdmi_connector_helper_funcs = {
    645 	.get_modes = dwhdmi_connector_get_modes,
    646 	.best_encoder = dwhdmi_connector_best_encoder,
    647 };
    648 
    649 static int
    650 dwhdmi_bridge_attach(struct drm_bridge *bridge)
    651 {
    652 	struct dwhdmi_softc * const sc = bridge->driver_private;
    653 	struct dwhdmi_connector *dwhdmi_connector = &sc->sc_connector;
    654 	struct drm_connector *connector = &dwhdmi_connector->base;
    655 	int error;
    656 
    657 	dwhdmi_connector->sc = sc;
    658 
    659 	connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
    660 	connector->interlace_allowed = 0;
    661 	connector->doublescan_allowed = 0;
    662 
    663 	drm_connector_init(bridge->dev, connector, &dwhdmi_connector_funcs,
    664 	    DRM_MODE_CONNECTOR_HDMIA);
    665 	drm_connector_helper_add(connector, &dwhdmi_connector_helper_funcs);
    666 
    667 	error = drm_mode_connector_attach_encoder(connector, bridge->encoder);
    668 	if (error != 0)
    669 		return error;
    670 
    671 	return drm_connector_register(connector);
    672 }
    673 
    674 static void
    675 dwhdmi_bridge_enable(struct drm_bridge *bridge)
    676 {
    677 	struct dwhdmi_softc * const sc = bridge->driver_private;
    678 
    679 	dwhdmi_vp_init(sc);
    680 	dwhdmi_fc_init(sc, &sc->sc_curmode);
    681 
    682 	if (sc->sc_enable)
    683 		sc->sc_enable(sc);
    684 
    685 	dwhdmi_tx_init(sc);
    686 	dwhdmi_mc_init(sc);
    687 
    688 	if (sc->sc_connector.monitor_audio)
    689 		dwhdmi_audio_init(sc);
    690 }
    691 
    692 static void
    693 dwhdmi_bridge_pre_enable(struct drm_bridge *bridge)
    694 {
    695 }
    696 
    697 static void
    698 dwhdmi_bridge_disable(struct drm_bridge *bridge)
    699 {
    700 	struct dwhdmi_softc * const sc = bridge->driver_private;
    701 
    702 	if (sc->sc_disable)
    703 		sc->sc_disable(sc);
    704 
    705 	dwhdmi_mc_disable(sc);
    706 }
    707 
    708 static void
    709 dwhdmi_bridge_post_disable(struct drm_bridge *bridge)
    710 {
    711 }
    712 
    713 static void
    714 dwhdmi_bridge_mode_set(struct drm_bridge *bridge,
    715     struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
    716 {
    717 	struct dwhdmi_softc * const sc = bridge->driver_private;
    718 
    719 	if (sc->sc_mode_set)
    720 		sc->sc_mode_set(sc, mode, adjusted_mode);
    721 
    722 	sc->sc_curmode = *adjusted_mode;
    723 }
    724 
    725 static bool
    726 dwhdmi_bridge_mode_fixup(struct drm_bridge *bridge,
    727     const struct drm_display_mode *mode, struct drm_display_mode *adjusted_mode)
    728 {
    729 	return true;
    730 }
    731 
    732 static const struct drm_bridge_funcs dwhdmi_bridge_funcs = {
    733 	.attach = dwhdmi_bridge_attach,
    734 	.enable = dwhdmi_bridge_enable,
    735 	.pre_enable = dwhdmi_bridge_pre_enable,
    736 	.disable = dwhdmi_bridge_disable,
    737 	.post_disable = dwhdmi_bridge_post_disable,
    738 	.mode_set = dwhdmi_bridge_mode_set,
    739 	.mode_fixup = dwhdmi_bridge_mode_fixup,
    740 };
    741 
    742 static int
    743 dwhdmi_dai_set_format(audio_dai_tag_t dai, u_int format)
    744 {
    745 	return 0;
    746 }
    747 
    748 static int
    749 dwhdmi_dai_add_device(audio_dai_tag_t dai, audio_dai_tag_t aux)
    750 {
    751 	/* Not supported */
    752 	return 0;
    753 }
    754 
    755 static void
    756 dwhdmi_audio_swvol_codec(audio_filter_arg_t *arg)
    757 {
    758 	struct dwhdmi_softc * const sc = arg->context;
    759 	const aint_t *src;
    760 	aint_t *dst;
    761 	u_int sample_count;
    762 	u_int i;
    763 
    764 	src = arg->src;
    765 	dst = arg->dst;
    766 	sample_count = arg->count * arg->srcfmt->channels;
    767 	for (i = 0; i < sample_count; i++) {
    768 		aint2_t v = (aint2_t)(*src++);
    769 		v = v * sc->sc_swvol / 255;
    770 		*dst++ = (aint_t)v;
    771 	}
    772 }
    773 
    774 static int
    775 dwhdmi_audio_set_format(void *priv, int setmode,
    776     const audio_params_t *play, const audio_params_t *rec,
    777     audio_filter_reg_t *pfil, audio_filter_reg_t *rfil)
    778 {
    779 	struct dwhdmi_softc * const sc = priv;
    780 
    781 	pfil->codec = dwhdmi_audio_swvol_codec;
    782 	pfil->context = sc;
    783 
    784 	return 0;
    785 }
    786 
    787 static int
    788 dwhdmi_audio_set_port(void *priv, mixer_ctrl_t *mc)
    789 {
    790 	struct dwhdmi_softc * const sc = priv;
    791 
    792 	switch (mc->dev) {
    793 	case DWHDMI_DAI_OUTPUT_MASTER_VOLUME:
    794 	case DWHDMI_DAI_INPUT_DAC_VOLUME:
    795 		sc->sc_swvol = mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT];
    796 		return 0;
    797 	default:
    798 		return ENXIO;
    799 	}
    800 }
    801 
    802 static int
    803 dwhdmi_audio_get_port(void *priv, mixer_ctrl_t *mc)
    804 {
    805 	struct dwhdmi_softc * const sc = priv;
    806 
    807 	switch (mc->dev) {
    808 	case DWHDMI_DAI_OUTPUT_MASTER_VOLUME:
    809 	case DWHDMI_DAI_INPUT_DAC_VOLUME:
    810 		mc->un.value.level[AUDIO_MIXER_LEVEL_LEFT] = sc->sc_swvol;
    811 		mc->un.value.level[AUDIO_MIXER_LEVEL_RIGHT] = sc->sc_swvol;
    812 		return 0;
    813 	default:
    814 		return ENXIO;
    815 	}
    816 }
    817 
    818 static int
    819 dwhdmi_audio_query_devinfo(void *priv, mixer_devinfo_t *di)
    820 {
    821 	switch (di->index) {
    822 	case DWHDMI_DAI_OUTPUT_CLASS:
    823 		di->mixer_class = di->index;
    824 		strcpy(di->label.name, AudioCoutputs);
    825 		di->type = AUDIO_MIXER_CLASS;
    826 		di->next = di->prev = AUDIO_MIXER_LAST;
    827 		return 0;
    828 
    829 	case DWHDMI_DAI_INPUT_CLASS:
    830 		di->mixer_class = di->index;
    831 		strcpy(di->label.name, AudioCinputs);
    832 		di->type = AUDIO_MIXER_CLASS;
    833 		di->next = di->prev = AUDIO_MIXER_LAST;
    834 		return 0;
    835 
    836 	case DWHDMI_DAI_OUTPUT_MASTER_VOLUME:
    837 		di->mixer_class = DWHDMI_DAI_OUTPUT_CLASS;
    838 		strcpy(di->label.name, AudioNmaster);
    839 		di->un.v.delta = 1;
    840 		di->un.v.num_channels = 2;
    841 		strcpy(di->un.v.units.name, AudioNvolume);
    842 		di->type = AUDIO_MIXER_VALUE;
    843 		di->next = di->prev = AUDIO_MIXER_LAST;
    844 		return 0;
    845 
    846 	case DWHDMI_DAI_INPUT_DAC_VOLUME:
    847 		di->mixer_class = DWHDMI_DAI_INPUT_CLASS;
    848 		strcpy(di->label.name, AudioNdac);
    849 		di->un.v.delta = 1;
    850 		di->un.v.num_channels = 2;
    851 		strcpy(di->un.v.units.name, AudioNvolume);
    852 		di->type = AUDIO_MIXER_VALUE;
    853 		di->next = di->prev = AUDIO_MIXER_LAST;
    854 		return 0;
    855 
    856 	default:
    857 		return ENXIO;
    858 	}
    859 }
    860 
    861 static const struct audio_hw_if dwhdmi_dai_hw_if = {
    862 	.set_format = dwhdmi_audio_set_format,
    863 	.set_port = dwhdmi_audio_set_port,
    864 	.get_port = dwhdmi_audio_get_port,
    865 	.query_devinfo = dwhdmi_audio_query_devinfo,
    866 };
    867 
    868 int
    869 dwhdmi_attach(struct dwhdmi_softc *sc)
    870 {
    871 	uint8_t val;
    872 
    873 	if (sc->sc_reg_width != 1 && sc->sc_reg_width != 4) {
    874 		aprint_error_dev(sc->sc_dev, "unsupported register width %d\n", sc->sc_reg_width);
    875 		return EINVAL;
    876 	}
    877 
    878 	mutex_init(&sc->sc_ic_lock, MUTEX_DEFAULT, IPL_NONE);
    879 
    880 	sc->sc_version = dwhdmi_read(sc, HDMI_DESIGN_ID);
    881 	sc->sc_version <<= 8;
    882 	sc->sc_version |= dwhdmi_read(sc, HDMI_REVISION_ID);
    883 
    884 	sc->sc_phytype = dwhdmi_read(sc, HDMI_CONFIG2_ID);
    885 
    886 	aprint_normal_dev(sc->sc_dev, "version %x.%03x, phytype 0x%02x\n",
    887 	    sc->sc_version >> 12, sc->sc_version & 0xfff,
    888 	    sc->sc_phytype);
    889 
    890 	sc->sc_swvol = 255;
    891 
    892 	/*
    893 	 * If a DDC i2c bus tag is provided by the caller, use it. Otherwise,
    894 	 * use the I2C master built-in to DWC HDMI.
    895 	 */
    896 	if (sc->sc_ic == NULL) {
    897 		struct i2c_controller *ic = &sc->sc_ic_builtin;
    898 		ic->ic_cookie = sc;
    899 		ic->ic_acquire_bus = dwhdmi_ddc_acquire_bus;
    900 		ic->ic_release_bus = dwhdmi_ddc_release_bus;
    901 		ic->ic_exec = dwhdmi_ddc_exec;
    902 		sc->sc_ic = ic;
    903 	}
    904 
    905 	/*
    906 	 * Enable HPD on internal PHY
    907 	 */
    908 	if ((sc->sc_flags & DWHDMI_USE_INTERNAL_PHY) != 0) {
    909 		val = dwhdmi_read(sc, HDMI_PHY_CONF0);
    910 		val |= HDMI_PHY_CONF0_ENHPDRXSENSE;
    911 		dwhdmi_write(sc, HDMI_PHY_CONF0, val);
    912 	}
    913 
    914 	/*
    915 	 * Initialize audio DAI
    916 	 */
    917 	sc->sc_dai.dai_set_format = dwhdmi_dai_set_format;
    918 	sc->sc_dai.dai_add_device = dwhdmi_dai_add_device;
    919 	sc->sc_dai.dai_hw_if = &dwhdmi_dai_hw_if;
    920 	sc->sc_dai.dai_dev = sc->sc_dev;
    921 	sc->sc_dai.dai_priv = sc;
    922 
    923 	return 0;
    924 }
    925 
    926 int
    927 dwhdmi_bind(struct dwhdmi_softc *sc, struct drm_encoder *encoder)
    928 {
    929 	int error;
    930 
    931 	sc->sc_bridge.driver_private = sc;
    932 	sc->sc_bridge.funcs = &dwhdmi_bridge_funcs;
    933 	sc->sc_bridge.encoder = encoder;
    934 
    935 	error = drm_bridge_attach(encoder->dev, &sc->sc_bridge);
    936 	if (error != 0)
    937 		return EIO;
    938 
    939 	encoder->bridge = &sc->sc_bridge;
    940 
    941 	return 0;
    942 }
    943