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