xref: /OK3568_Linux_fs/kernel/drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 2016 Maxime Ripard <maxime.ripard@free-electrons.com>
4*4882a593Smuzhiyun  * Copyright (C) 2017 Jonathan Liu <net147@gmail.com>
5*4882a593Smuzhiyun  */
6*4882a593Smuzhiyun 
7*4882a593Smuzhiyun #include <linux/clk.h>
8*4882a593Smuzhiyun #include <linux/i2c.h>
9*4882a593Smuzhiyun #include <linux/iopoll.h>
10*4882a593Smuzhiyun 
11*4882a593Smuzhiyun #include "sun4i_hdmi.h"
12*4882a593Smuzhiyun 
13*4882a593Smuzhiyun #define SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK ( \
14*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION | \
15*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW | \
16*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_OVERFLOW | \
17*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR | \
18*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR | \
19*4882a593Smuzhiyun 	SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR \
20*4882a593Smuzhiyun )
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun /* FIFO request bit is set when FIFO level is above RX_THRESHOLD during read */
23*4882a593Smuzhiyun #define RX_THRESHOLD SUN4I_HDMI_DDC_FIFO_CTRL_RX_THRES_MAX
24*4882a593Smuzhiyun 
fifo_transfer(struct sun4i_hdmi * hdmi,u8 * buf,int len,bool read)25*4882a593Smuzhiyun static int fifo_transfer(struct sun4i_hdmi *hdmi, u8 *buf, int len, bool read)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun 	/*
28*4882a593Smuzhiyun 	 * 1 byte takes 9 clock cycles (8 bits + 1 ACK) = 90 us for 100 kHz
29*4882a593Smuzhiyun 	 * clock. As clock rate is fixed, just round it up to 100 us.
30*4882a593Smuzhiyun 	 */
31*4882a593Smuzhiyun 	const unsigned long byte_time_ns = 100;
32*4882a593Smuzhiyun 	const u32 mask = SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
33*4882a593Smuzhiyun 			 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
34*4882a593Smuzhiyun 			 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE;
35*4882a593Smuzhiyun 	u32 reg;
36*4882a593Smuzhiyun 	/*
37*4882a593Smuzhiyun 	 * If threshold is inclusive, then the FIFO may only have
38*4882a593Smuzhiyun 	 * RX_THRESHOLD number of bytes, instead of RX_THRESHOLD + 1.
39*4882a593Smuzhiyun 	 */
40*4882a593Smuzhiyun 	int read_len = RX_THRESHOLD +
41*4882a593Smuzhiyun 		(hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
42*4882a593Smuzhiyun 
43*4882a593Smuzhiyun 	/*
44*4882a593Smuzhiyun 	 * Limit transfer length by FIFO threshold or FIFO size.
45*4882a593Smuzhiyun 	 * For TX the threshold is for an empty FIFO.
46*4882a593Smuzhiyun 	 */
47*4882a593Smuzhiyun 	len = min_t(int, len, read ? read_len : SUN4I_HDMI_DDC_FIFO_SIZE);
48*4882a593Smuzhiyun 
49*4882a593Smuzhiyun 	/* Wait until error, FIFO request bit set or transfer complete */
50*4882a593Smuzhiyun 	if (regmap_field_read_poll_timeout(hdmi->field_ddc_int_status, reg,
51*4882a593Smuzhiyun 					   reg & mask, len * byte_time_ns,
52*4882a593Smuzhiyun 					   100000))
53*4882a593Smuzhiyun 		return -ETIMEDOUT;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK)
56*4882a593Smuzhiyun 		return -EIO;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun 	if (read)
59*4882a593Smuzhiyun 		readsb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
60*4882a593Smuzhiyun 	else
61*4882a593Smuzhiyun 		writesb(hdmi->base + hdmi->variant->ddc_fifo_reg, buf, len);
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun 	/* Clear FIFO request bit by forcing a write to that bit */
64*4882a593Smuzhiyun 	regmap_field_force_write(hdmi->field_ddc_int_status,
65*4882a593Smuzhiyun 				 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST);
66*4882a593Smuzhiyun 
67*4882a593Smuzhiyun 	return len;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun 
xfer_msg(struct sun4i_hdmi * hdmi,struct i2c_msg * msg)70*4882a593Smuzhiyun static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg)
71*4882a593Smuzhiyun {
72*4882a593Smuzhiyun 	int i, len;
73*4882a593Smuzhiyun 	u32 reg;
74*4882a593Smuzhiyun 
75*4882a593Smuzhiyun 	/* Set FIFO direction */
76*4882a593Smuzhiyun 	if (hdmi->variant->ddc_fifo_has_dir) {
77*4882a593Smuzhiyun 		reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
78*4882a593Smuzhiyun 		reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK;
79*4882a593Smuzhiyun 		reg |= (msg->flags & I2C_M_RD) ?
80*4882a593Smuzhiyun 		       SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ :
81*4882a593Smuzhiyun 		       SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE;
82*4882a593Smuzhiyun 		writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG);
83*4882a593Smuzhiyun 	}
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	/* Clear address register (not cleared by soft reset) */
86*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_addr_reg, 0);
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun 	/* Set I2C address */
89*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_slave_addr, msg->addr);
90*4882a593Smuzhiyun 
91*4882a593Smuzhiyun 	/*
92*4882a593Smuzhiyun 	 * Set FIFO RX/TX thresholds and clear FIFO
93*4882a593Smuzhiyun 	 *
94*4882a593Smuzhiyun 	 * If threshold is inclusive, we can set the TX threshold to
95*4882a593Smuzhiyun 	 * 0 instead of 1.
96*4882a593Smuzhiyun 	 */
97*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_fifo_tx_thres,
98*4882a593Smuzhiyun 			   hdmi->variant->ddc_fifo_thres_incl ? 0 : 1);
99*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_fifo_rx_thres, RX_THRESHOLD);
100*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_fifo_clear, 1);
101*4882a593Smuzhiyun 	if (regmap_field_read_poll_timeout(hdmi->field_ddc_fifo_clear,
102*4882a593Smuzhiyun 					   reg, !reg, 100, 2000))
103*4882a593Smuzhiyun 		return -EIO;
104*4882a593Smuzhiyun 
105*4882a593Smuzhiyun 	/* Set transfer length */
106*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_byte_count, msg->len);
107*4882a593Smuzhiyun 
108*4882a593Smuzhiyun 	/* Set command */
109*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_cmd,
110*4882a593Smuzhiyun 			   msg->flags & I2C_M_RD ?
111*4882a593Smuzhiyun 			   SUN4I_HDMI_DDC_CMD_IMPLICIT_READ :
112*4882a593Smuzhiyun 			   SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE);
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun 	/* Clear interrupt status bits by forcing a write */
115*4882a593Smuzhiyun 	regmap_field_force_write(hdmi->field_ddc_int_status,
116*4882a593Smuzhiyun 				 SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK |
117*4882a593Smuzhiyun 				 SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST |
118*4882a593Smuzhiyun 				 SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE);
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun 	/* Start command */
121*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_start, 1);
122*4882a593Smuzhiyun 
123*4882a593Smuzhiyun 	/* Transfer bytes */
124*4882a593Smuzhiyun 	for (i = 0; i < msg->len; i += len) {
125*4882a593Smuzhiyun 		len = fifo_transfer(hdmi, msg->buf + i, msg->len - i,
126*4882a593Smuzhiyun 				    msg->flags & I2C_M_RD);
127*4882a593Smuzhiyun 		if (len <= 0)
128*4882a593Smuzhiyun 			return len;
129*4882a593Smuzhiyun 	}
130*4882a593Smuzhiyun 
131*4882a593Smuzhiyun 	/* Wait for command to finish */
132*4882a593Smuzhiyun 	if (regmap_field_read_poll_timeout(hdmi->field_ddc_start,
133*4882a593Smuzhiyun 					   reg, !reg, 100, 100000))
134*4882a593Smuzhiyun 		return -EIO;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	/* Check for errors */
137*4882a593Smuzhiyun 	regmap_field_read(hdmi->field_ddc_int_status, &reg);
138*4882a593Smuzhiyun 	if ((reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) ||
139*4882a593Smuzhiyun 	    !(reg & SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE)) {
140*4882a593Smuzhiyun 		return -EIO;
141*4882a593Smuzhiyun 	}
142*4882a593Smuzhiyun 
143*4882a593Smuzhiyun 	return 0;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
sun4i_hdmi_i2c_xfer(struct i2c_adapter * adap,struct i2c_msg * msgs,int num)146*4882a593Smuzhiyun static int sun4i_hdmi_i2c_xfer(struct i2c_adapter *adap,
147*4882a593Smuzhiyun 			       struct i2c_msg *msgs, int num)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	struct sun4i_hdmi *hdmi = i2c_get_adapdata(adap);
150*4882a593Smuzhiyun 	u32 reg;
151*4882a593Smuzhiyun 	int err, i, ret = num;
152*4882a593Smuzhiyun 
153*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
154*4882a593Smuzhiyun 		if (!msgs[i].len)
155*4882a593Smuzhiyun 			return -EINVAL;
156*4882a593Smuzhiyun 		if (msgs[i].len > SUN4I_HDMI_DDC_BYTE_COUNT_MAX)
157*4882a593Smuzhiyun 			return -EINVAL;
158*4882a593Smuzhiyun 	}
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 	/* DDC clock needs to be enabled for the module to work */
161*4882a593Smuzhiyun 	clk_prepare_enable(hdmi->ddc_clk);
162*4882a593Smuzhiyun 	clk_set_rate(hdmi->ddc_clk, 100000);
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	/* Reset I2C controller */
165*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_en, 1);
166*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_reset, 1);
167*4882a593Smuzhiyun 	if (regmap_field_read_poll_timeout(hdmi->field_ddc_reset,
168*4882a593Smuzhiyun 					   reg, !reg, 100, 2000)) {
169*4882a593Smuzhiyun 		clk_disable_unprepare(hdmi->ddc_clk);
170*4882a593Smuzhiyun 		return -EIO;
171*4882a593Smuzhiyun 	}
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_sck_en, 1);
174*4882a593Smuzhiyun 	regmap_field_write(hdmi->field_ddc_sda_en, 1);
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun 	for (i = 0; i < num; i++) {
177*4882a593Smuzhiyun 		err = xfer_msg(hdmi, &msgs[i]);
178*4882a593Smuzhiyun 		if (err) {
179*4882a593Smuzhiyun 			ret = err;
180*4882a593Smuzhiyun 			break;
181*4882a593Smuzhiyun 		}
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 
184*4882a593Smuzhiyun 	clk_disable_unprepare(hdmi->ddc_clk);
185*4882a593Smuzhiyun 	return ret;
186*4882a593Smuzhiyun }
187*4882a593Smuzhiyun 
sun4i_hdmi_i2c_func(struct i2c_adapter * adap)188*4882a593Smuzhiyun static u32 sun4i_hdmi_i2c_func(struct i2c_adapter *adap)
189*4882a593Smuzhiyun {
190*4882a593Smuzhiyun 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
191*4882a593Smuzhiyun }
192*4882a593Smuzhiyun 
193*4882a593Smuzhiyun static const struct i2c_algorithm sun4i_hdmi_i2c_algorithm = {
194*4882a593Smuzhiyun 	.master_xfer	= sun4i_hdmi_i2c_xfer,
195*4882a593Smuzhiyun 	.functionality	= sun4i_hdmi_i2c_func,
196*4882a593Smuzhiyun };
197*4882a593Smuzhiyun 
sun4i_hdmi_init_regmap_fields(struct sun4i_hdmi * hdmi)198*4882a593Smuzhiyun static int sun4i_hdmi_init_regmap_fields(struct sun4i_hdmi *hdmi)
199*4882a593Smuzhiyun {
200*4882a593Smuzhiyun 	hdmi->field_ddc_en =
201*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
202*4882a593Smuzhiyun 					hdmi->variant->field_ddc_en);
203*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_en))
204*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_en);
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	hdmi->field_ddc_start =
207*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
208*4882a593Smuzhiyun 					hdmi->variant->field_ddc_start);
209*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_start))
210*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_start);
211*4882a593Smuzhiyun 
212*4882a593Smuzhiyun 	hdmi->field_ddc_reset =
213*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
214*4882a593Smuzhiyun 					hdmi->variant->field_ddc_reset);
215*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_reset))
216*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_reset);
217*4882a593Smuzhiyun 
218*4882a593Smuzhiyun 	hdmi->field_ddc_addr_reg =
219*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
220*4882a593Smuzhiyun 					hdmi->variant->field_ddc_addr_reg);
221*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_addr_reg))
222*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_addr_reg);
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	hdmi->field_ddc_slave_addr =
225*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
226*4882a593Smuzhiyun 					hdmi->variant->field_ddc_slave_addr);
227*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_slave_addr))
228*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_slave_addr);
229*4882a593Smuzhiyun 
230*4882a593Smuzhiyun 	hdmi->field_ddc_int_mask =
231*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
232*4882a593Smuzhiyun 					hdmi->variant->field_ddc_int_mask);
233*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_int_mask))
234*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_int_mask);
235*4882a593Smuzhiyun 
236*4882a593Smuzhiyun 	hdmi->field_ddc_int_status =
237*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
238*4882a593Smuzhiyun 					hdmi->variant->field_ddc_int_status);
239*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_int_status))
240*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_int_status);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	hdmi->field_ddc_fifo_clear =
243*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
244*4882a593Smuzhiyun 					hdmi->variant->field_ddc_fifo_clear);
245*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_fifo_clear))
246*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_fifo_clear);
247*4882a593Smuzhiyun 
248*4882a593Smuzhiyun 	hdmi->field_ddc_fifo_rx_thres =
249*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
250*4882a593Smuzhiyun 					hdmi->variant->field_ddc_fifo_rx_thres);
251*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_fifo_rx_thres))
252*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_fifo_rx_thres);
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	hdmi->field_ddc_fifo_tx_thres =
255*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
256*4882a593Smuzhiyun 					hdmi->variant->field_ddc_fifo_tx_thres);
257*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_fifo_tx_thres))
258*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_fifo_tx_thres);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	hdmi->field_ddc_byte_count =
261*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
262*4882a593Smuzhiyun 					hdmi->variant->field_ddc_byte_count);
263*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_byte_count))
264*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_byte_count);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun 	hdmi->field_ddc_cmd =
267*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
268*4882a593Smuzhiyun 					hdmi->variant->field_ddc_cmd);
269*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_cmd))
270*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_cmd);
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	hdmi->field_ddc_sda_en =
273*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
274*4882a593Smuzhiyun 					hdmi->variant->field_ddc_sda_en);
275*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_sda_en))
276*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_sda_en);
277*4882a593Smuzhiyun 
278*4882a593Smuzhiyun 	hdmi->field_ddc_sck_en =
279*4882a593Smuzhiyun 		devm_regmap_field_alloc(hdmi->dev, hdmi->regmap,
280*4882a593Smuzhiyun 					hdmi->variant->field_ddc_sck_en);
281*4882a593Smuzhiyun 	if (IS_ERR(hdmi->field_ddc_sck_en))
282*4882a593Smuzhiyun 		return PTR_ERR(hdmi->field_ddc_sck_en);
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun 	return 0;
285*4882a593Smuzhiyun }
286*4882a593Smuzhiyun 
sun4i_hdmi_i2c_create(struct device * dev,struct sun4i_hdmi * hdmi)287*4882a593Smuzhiyun int sun4i_hdmi_i2c_create(struct device *dev, struct sun4i_hdmi *hdmi)
288*4882a593Smuzhiyun {
289*4882a593Smuzhiyun 	struct i2c_adapter *adap;
290*4882a593Smuzhiyun 	int ret = 0;
291*4882a593Smuzhiyun 
292*4882a593Smuzhiyun 	ret = sun4i_ddc_create(hdmi, hdmi->ddc_parent_clk);
293*4882a593Smuzhiyun 	if (ret)
294*4882a593Smuzhiyun 		return ret;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	ret = sun4i_hdmi_init_regmap_fields(hdmi);
297*4882a593Smuzhiyun 	if (ret)
298*4882a593Smuzhiyun 		return ret;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	adap = devm_kzalloc(dev, sizeof(*adap), GFP_KERNEL);
301*4882a593Smuzhiyun 	if (!adap)
302*4882a593Smuzhiyun 		return -ENOMEM;
303*4882a593Smuzhiyun 
304*4882a593Smuzhiyun 	adap->owner = THIS_MODULE;
305*4882a593Smuzhiyun 	adap->class = I2C_CLASS_DDC;
306*4882a593Smuzhiyun 	adap->algo = &sun4i_hdmi_i2c_algorithm;
307*4882a593Smuzhiyun 	strlcpy(adap->name, "sun4i_hdmi_i2c adapter", sizeof(adap->name));
308*4882a593Smuzhiyun 	i2c_set_adapdata(adap, hdmi);
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	ret = i2c_add_adapter(adap);
311*4882a593Smuzhiyun 	if (ret)
312*4882a593Smuzhiyun 		return ret;
313*4882a593Smuzhiyun 
314*4882a593Smuzhiyun 	hdmi->i2c = adap;
315*4882a593Smuzhiyun 
316*4882a593Smuzhiyun 	return ret;
317*4882a593Smuzhiyun }
318