Linux-libre 4.15.7-gnu
[librecmc/linux-libre.git] / drivers / gpu / drm / bridge / sii9234.c
1 /*
2  * Copyright (C) 2017 Samsung Electronics
3  *
4  * Authors:
5  *    Tomasz Stanislawski <t.stanislaws@samsung.com>
6  *    Maciej Purski <m.purski@samsung.com>
7  *
8  * Based on sii9234 driver created by:
9  *    Adam Hampson <ahampson@sta.samsung.com>
10  *    Erik Gilling <konkers@android.com>
11  *    Shankar Bandal <shankar.b@samsung.com>
12  *    Dharam Kumar <dharam.kr@samsung.com>
13  *
14  * This program is free software; you can redistribute it and/or modify
15  * it under the terms of the GNU General Public License as published by
16  * the Free Software Foundation; either version 2 of the License, or
17  * (at your option) any later version.
18  *
19  * This program is distributed in the hope that it will be useful,
20  * but WITHOUT ANY WARRANTY; without even the implied warranty of
21  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22  * GNU General Public License for more details.
23  *
24  * You should have received a copy of the GNU General Public License
25  * along with this program
26  *
27  */
28 #include <drm/bridge/mhl.h>
29 #include <drm/drm_crtc.h>
30 #include <drm/drm_edid.h>
31
32 #include <linux/delay.h>
33 #include <linux/err.h>
34 #include <linux/gpio/consumer.h>
35 #include <linux/i2c.h>
36 #include <linux/interrupt.h>
37 #include <linux/irq.h>
38 #include <linux/kernel.h>
39 #include <linux/module.h>
40 #include <linux/mutex.h>
41 #include <linux/regulator/consumer.h>
42 #include <linux/slab.h>
43
44 #define CBUS_DEVCAP_OFFSET              0x80
45
46 #define SII9234_MHL_VERSION             0x11
47 #define SII9234_SCRATCHPAD_SIZE         0x10
48 #define SII9234_INT_STAT_SIZE           0x33
49
50 #define BIT_TMDS_CCTRL_TMDS_OE          BIT(4)
51 #define MHL_HPD_OUT_OVR_EN              BIT(4)
52 #define MHL_HPD_OUT_OVR_VAL             BIT(5)
53 #define MHL_INIT_TIMEOUT                0x0C
54
55 /* MHL Tx registers and bits */
56 #define MHL_TX_SRST                     0x05
57 #define MHL_TX_SYSSTAT_REG              0x09
58 #define MHL_TX_INTR1_REG                0x71
59 #define MHL_TX_INTR4_REG                0x74
60 #define MHL_TX_INTR1_ENABLE_REG         0x75
61 #define MHL_TX_INTR4_ENABLE_REG         0x78
62 #define MHL_TX_INT_CTRL_REG             0x79
63 #define MHL_TX_TMDS_CCTRL               0x80
64 #define MHL_TX_DISC_CTRL1_REG           0x90
65 #define MHL_TX_DISC_CTRL2_REG           0x91
66 #define MHL_TX_DISC_CTRL3_REG           0x92
67 #define MHL_TX_DISC_CTRL4_REG           0x93
68 #define MHL_TX_DISC_CTRL5_REG           0x94
69 #define MHL_TX_DISC_CTRL6_REG           0x95
70 #define MHL_TX_DISC_CTRL7_REG           0x96
71 #define MHL_TX_DISC_CTRL8_REG           0x97
72 #define MHL_TX_STAT2_REG                0x99
73 #define MHL_TX_MHLTX_CTL1_REG           0xA0
74 #define MHL_TX_MHLTX_CTL2_REG           0xA1
75 #define MHL_TX_MHLTX_CTL4_REG           0xA3
76 #define MHL_TX_MHLTX_CTL6_REG           0xA5
77 #define MHL_TX_MHLTX_CTL7_REG           0xA6
78
79 #define RSEN_STATUS                     BIT(2)
80 #define HPD_CHANGE_INT                  BIT(6)
81 #define RSEN_CHANGE_INT                 BIT(5)
82 #define RGND_READY_INT                  BIT(6)
83 #define VBUS_LOW_INT                    BIT(5)
84 #define CBUS_LKOUT_INT                  BIT(4)
85 #define MHL_DISC_FAIL_INT               BIT(3)
86 #define MHL_EST_INT                     BIT(2)
87 #define HPD_CHANGE_INT_MASK             BIT(6)
88 #define RSEN_CHANGE_INT_MASK            BIT(5)
89
90 #define RGND_READY_MASK                 BIT(6)
91 #define CBUS_LKOUT_MASK                 BIT(4)
92 #define MHL_DISC_FAIL_MASK              BIT(3)
93 #define MHL_EST_MASK                    BIT(2)
94
95 #define SKIP_GND                        BIT(6)
96
97 #define ATT_THRESH_SHIFT                0x04
98 #define ATT_THRESH_MASK                 (0x03 << ATT_THRESH_SHIFT)
99 #define USB_D_OEN                       BIT(3)
100 #define DEGLITCH_TIME_MASK              0x07
101 #define DEGLITCH_TIME_2MS               0
102 #define DEGLITCH_TIME_4MS               1
103 #define DEGLITCH_TIME_8MS               2
104 #define DEGLITCH_TIME_16MS              3
105 #define DEGLITCH_TIME_40MS              4
106 #define DEGLITCH_TIME_50MS              5
107 #define DEGLITCH_TIME_60MS              6
108 #define DEGLITCH_TIME_128MS             7
109
110 #define USB_D_OVR                       BIT(7)
111 #define USB_ID_OVR                      BIT(6)
112 #define DVRFLT_SEL                      BIT(5)
113 #define BLOCK_RGND_INT                  BIT(4)
114 #define SKIP_DEG                        BIT(3)
115 #define CI2CA_POL                       BIT(2)
116 #define CI2CA_WKUP                      BIT(1)
117 #define SINGLE_ATT                      BIT(0)
118
119 #define USB_D_ODN                       BIT(5)
120 #define VBUS_CHECK                      BIT(2)
121 #define RGND_INTP_MASK                  0x03
122 #define RGND_INTP_OPEN                  0
123 #define RGND_INTP_2K                    1
124 #define RGND_INTP_1K                    2
125 #define RGND_INTP_SHORT                 3
126
127 /* HDMI registers */
128 #define HDMI_RX_TMDS0_CCTRL1_REG        0x10
129 #define HDMI_RX_TMDS_CLK_EN_REG         0x11
130 #define HDMI_RX_TMDS_CH_EN_REG          0x12
131 #define HDMI_RX_PLL_CALREFSEL_REG       0x17
132 #define HDMI_RX_PLL_VCOCAL_REG          0x1A
133 #define HDMI_RX_EQ_DATA0_REG            0x22
134 #define HDMI_RX_EQ_DATA1_REG            0x23
135 #define HDMI_RX_EQ_DATA2_REG            0x24
136 #define HDMI_RX_EQ_DATA3_REG            0x25
137 #define HDMI_RX_EQ_DATA4_REG            0x26
138 #define HDMI_RX_TMDS_ZONE_CTRL_REG      0x4C
139 #define HDMI_RX_TMDS_MODE_CTRL_REG      0x4D
140
141 /* CBUS registers */
142 #define CBUS_INT_STATUS_1_REG           0x08
143 #define CBUS_INTR1_ENABLE_REG           0x09
144 #define CBUS_MSC_REQ_ABORT_REASON_REG   0x0D
145 #define CBUS_INT_STATUS_2_REG           0x1E
146 #define CBUS_INTR2_ENABLE_REG           0x1F
147 #define CBUS_LINK_CONTROL_2_REG         0x31
148 #define CBUS_MHL_STATUS_REG_0           0xB0
149 #define CBUS_MHL_STATUS_REG_1           0xB1
150
151 #define BIT_CBUS_RESET                  BIT(3)
152 #define SET_HPD_DOWNSTREAM              BIT(6)
153
154 /* TPI registers */
155 #define TPI_DPD_REG                     0x3D
156
157 /* Timeouts in msec */
158 #define T_SRC_VBUS_CBUS_TO_STABLE       200
159 #define T_SRC_CBUS_FLOAT                100
160 #define T_SRC_CBUS_DEGLITCH             2
161 #define T_SRC_RXSENSE_DEGLITCH          110
162
163 #define MHL1_MAX_CLK                    75000 /* in kHz */
164
165 #define I2C_TPI_ADDR                    0x3D
166 #define I2C_HDMI_ADDR                   0x49
167 #define I2C_CBUS_ADDR                   0x64
168
169 enum sii9234_state {
170         ST_OFF,
171         ST_D3,
172         ST_RGND_INIT,
173         ST_RGND_1K,
174         ST_RSEN_HIGH,
175         ST_MHL_ESTABLISHED,
176         ST_FAILURE_DISCOVERY,
177         ST_FAILURE,
178 };
179
180 struct sii9234 {
181         struct i2c_client *client[4];
182         struct drm_bridge bridge;
183         struct device *dev;
184         struct gpio_desc *gpio_reset;
185         int i2c_error;
186         struct regulator_bulk_data supplies[4];
187
188         struct mutex lock; /* Protects fields below and device registers */
189         enum sii9234_state state;
190 };
191
192 enum sii9234_client_id {
193         I2C_MHL,
194         I2C_TPI,
195         I2C_HDMI,
196         I2C_CBUS,
197 };
198
199 static const char * const sii9234_client_name[] = {
200         [I2C_MHL] = "MHL",
201         [I2C_TPI] = "TPI",
202         [I2C_HDMI] = "HDMI",
203         [I2C_CBUS] = "CBUS",
204 };
205
206 static int sii9234_writeb(struct sii9234 *ctx, int id, int offset,
207                           int value)
208 {
209         int ret;
210         struct i2c_client *client = ctx->client[id];
211
212         if (ctx->i2c_error)
213                 return ctx->i2c_error;
214
215         ret = i2c_smbus_write_byte_data(client, offset, value);
216         if (ret < 0)
217                 dev_err(ctx->dev, "writeb: %4s[0x%02x] <- 0x%02x\n",
218                         sii9234_client_name[id], offset, value);
219         ctx->i2c_error = ret;
220
221         return ret;
222 }
223
224 static int sii9234_writebm(struct sii9234 *ctx, int id, int offset,
225                            int value, int mask)
226 {
227         int ret;
228         struct i2c_client *client = ctx->client[id];
229
230         if (ctx->i2c_error)
231                 return ctx->i2c_error;
232
233         ret = i2c_smbus_write_byte(client, offset);
234         if (ret < 0) {
235                 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
236                         sii9234_client_name[id], offset, value);
237                 ctx->i2c_error = ret;
238                 return ret;
239         }
240
241         ret = i2c_smbus_read_byte(client);
242         if (ret < 0) {
243                 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
244                         sii9234_client_name[id], offset, value);
245                 ctx->i2c_error = ret;
246                 return ret;
247         }
248
249         value = (value & mask) | (ret & ~mask);
250
251         ret = i2c_smbus_write_byte_data(client, offset, value);
252         if (ret < 0) {
253                 dev_err(ctx->dev, "writebm: %4s[0x%02x] <- 0x%02x\n",
254                         sii9234_client_name[id], offset, value);
255                 ctx->i2c_error = ret;
256         }
257
258         return ret;
259 }
260
261 static int sii9234_readb(struct sii9234 *ctx, int id, int offset)
262 {
263         int ret;
264         struct i2c_client *client = ctx->client[id];
265
266         if (ctx->i2c_error)
267                 return ctx->i2c_error;
268
269         ret = i2c_smbus_write_byte(client, offset);
270         if (ret < 0) {
271                 dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
272                         sii9234_client_name[id], offset);
273                 ctx->i2c_error = ret;
274                 return ret;
275         }
276
277         ret = i2c_smbus_read_byte(client);
278         if (ret < 0) {
279                 dev_err(ctx->dev, "readb: %4s[0x%02x]\n",
280                         sii9234_client_name[id], offset);
281                 ctx->i2c_error = ret;
282         }
283
284         return ret;
285 }
286
287 static int sii9234_clear_error(struct sii9234 *ctx)
288 {
289         int ret = ctx->i2c_error;
290
291         ctx->i2c_error = 0;
292
293         return ret;
294 }
295
296 #define mhl_tx_writeb(sii9234, offset, value) \
297         sii9234_writeb(sii9234, I2C_MHL, offset, value)
298 #define mhl_tx_writebm(sii9234, offset, value, mask) \
299         sii9234_writebm(sii9234, I2C_MHL, offset, value, mask)
300 #define mhl_tx_readb(sii9234, offset) \
301         sii9234_readb(sii9234, I2C_MHL, offset)
302 #define cbus_writeb(sii9234, offset, value) \
303         sii9234_writeb(sii9234, I2C_CBUS, offset, value)
304 #define cbus_writebm(sii9234, offset, value, mask) \
305         sii9234_writebm(sii9234, I2C_CBUS, offset, value, mask)
306 #define cbus_readb(sii9234, offset) \
307         sii9234_readb(sii9234, I2C_CBUS, offset)
308 #define hdmi_writeb(sii9234, offset, value) \
309         sii9234_writeb(sii9234, I2C_HDMI, offset, value)
310 #define hdmi_writebm(sii9234, offset, value, mask) \
311         sii9234_writebm(sii9234, I2C_HDMI, offset, value, mask)
312 #define hdmi_readb(sii9234, offset) \
313         sii9234_readb(sii9234, I2C_HDMI, offset)
314 #define tpi_writeb(sii9234, offset, value) \
315         sii9234_writeb(sii9234, I2C_TPI, offset, value)
316 #define tpi_writebm(sii9234, offset, value, mask) \
317         sii9234_writebm(sii9234, I2C_TPI, offset, value, mask)
318 #define tpi_readb(sii9234, offset) \
319         sii9234_readb(sii9234, I2C_TPI, offset)
320
321 static u8 sii9234_tmds_control(struct sii9234 *ctx, bool enable)
322 {
323         mhl_tx_writebm(ctx, MHL_TX_TMDS_CCTRL, enable ? ~0 : 0,
324                        BIT_TMDS_CCTRL_TMDS_OE);
325         mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, enable ? ~0 : 0,
326                        MHL_HPD_OUT_OVR_EN | MHL_HPD_OUT_OVR_VAL);
327         return sii9234_clear_error(ctx);
328 }
329
330 static int sii9234_cbus_reset(struct sii9234 *ctx)
331 {
332         int i;
333
334         mhl_tx_writebm(ctx, MHL_TX_SRST, ~0, BIT_CBUS_RESET);
335         msleep(T_SRC_CBUS_DEGLITCH);
336         mhl_tx_writebm(ctx, MHL_TX_SRST, 0, BIT_CBUS_RESET);
337
338         for (i = 0; i < 4; i++) {
339                 /*
340                  * Enable WRITE_STAT interrupt for writes to all
341                  * 4 MSC Status registers.
342                  */
343                 cbus_writeb(ctx, 0xE0 + i, 0xF2);
344                 /*
345                  * Enable SET_INT interrupt for writes to all
346                  * 4 MSC Interrupt registers.
347                  */
348                 cbus_writeb(ctx, 0xF0 + i, 0xF2);
349         }
350
351         return sii9234_clear_error(ctx);
352 }
353
354 /* Require to chek mhl imformation of samsung in cbus_init_register */
355 static int sii9234_cbus_init(struct sii9234 *ctx)
356 {
357         cbus_writeb(ctx, 0x07, 0xF2);
358         cbus_writeb(ctx, 0x40, 0x03);
359         cbus_writeb(ctx, 0x42, 0x06);
360         cbus_writeb(ctx, 0x36, 0x0C);
361         cbus_writeb(ctx, 0x3D, 0xFD);
362         cbus_writeb(ctx, 0x1C, 0x01);
363         cbus_writeb(ctx, 0x1D, 0x0F);
364         cbus_writeb(ctx, 0x44, 0x02);
365         /* Setup our devcap */
366         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEV_STATE, 0x00);
367         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_MHL_VERSION,
368                     SII9234_MHL_VERSION);
369         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_CAT,
370                     MHL_DCAP_CAT_SOURCE);
371         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_H, 0x01);
372         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_ADOPTER_ID_L, 0x41);
373         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VID_LINK_MODE,
374                     MHL_DCAP_VID_LINK_RGB444 | MHL_DCAP_VID_LINK_YCBCR444);
375         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_VIDEO_TYPE,
376                     MHL_DCAP_VT_GRAPHICS);
377         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_LOG_DEV_MAP,
378                     MHL_DCAP_LD_GUI);
379         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_BANDWIDTH, 0x0F);
380         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_FEATURE_FLAG,
381                     MHL_DCAP_FEATURE_RCP_SUPPORT | MHL_DCAP_FEATURE_RAP_SUPPORT
382                         | MHL_DCAP_FEATURE_SP_SUPPORT);
383         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_H, 0x0);
384         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_DEVICE_ID_L, 0x0);
385         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_SCRATCHPAD_SIZE,
386                     SII9234_SCRATCHPAD_SIZE);
387         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_INT_STAT_SIZE,
388                     SII9234_INT_STAT_SIZE);
389         cbus_writeb(ctx, CBUS_DEVCAP_OFFSET + MHL_DCAP_RESERVED, 0);
390         cbus_writebm(ctx, 0x31, 0x0C, 0x0C);
391         cbus_writeb(ctx, 0x30, 0x01);
392         cbus_writebm(ctx, 0x3C, 0x30, 0x38);
393         cbus_writebm(ctx, 0x22, 0x0D, 0x0F);
394         cbus_writebm(ctx, 0x2E, 0x15, 0x15);
395         cbus_writeb(ctx, CBUS_INTR1_ENABLE_REG, 0);
396         cbus_writeb(ctx, CBUS_INTR2_ENABLE_REG, 0);
397
398         return sii9234_clear_error(ctx);
399 }
400
401 static void force_usb_id_switch_open(struct sii9234 *ctx)
402 {
403         /* Disable CBUS discovery */
404         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0, 0x01);
405         /* Force USB ID switch to open */
406         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
407         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
408         /* Force upstream HPD to 0 when not in MHL mode. */
409         mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x30);
410 }
411
412 static void release_usb_id_switch_open(struct sii9234 *ctx)
413 {
414         msleep(T_SRC_CBUS_FLOAT);
415         /* Clear USB ID switch to open */
416         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0, USB_ID_OVR);
417         /* Enable CBUS discovery */
418         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 0x01);
419 }
420
421 static int sii9234_power_init(struct sii9234 *ctx)
422 {
423         /* Force the SiI9234 into the D0 state. */
424         tpi_writeb(ctx, TPI_DPD_REG, 0x3F);
425         /* Enable TxPLL Clock */
426         hdmi_writeb(ctx, HDMI_RX_TMDS_CLK_EN_REG, 0x01);
427         /* Enable Tx Clock Path & Equalizer */
428         hdmi_writeb(ctx, HDMI_RX_TMDS_CH_EN_REG, 0x15);
429         /* Power Up TMDS */
430         mhl_tx_writeb(ctx, 0x08, 0x35);
431         return sii9234_clear_error(ctx);
432 }
433
434 static int sii9234_hdmi_init(struct sii9234 *ctx)
435 {
436         hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
437         hdmi_writeb(ctx, HDMI_RX_PLL_CALREFSEL_REG, 0x03);
438         hdmi_writeb(ctx, HDMI_RX_PLL_VCOCAL_REG, 0x20);
439         hdmi_writeb(ctx, HDMI_RX_EQ_DATA0_REG, 0x8A);
440         hdmi_writeb(ctx, HDMI_RX_EQ_DATA1_REG, 0x6A);
441         hdmi_writeb(ctx, HDMI_RX_EQ_DATA2_REG, 0xAA);
442         hdmi_writeb(ctx, HDMI_RX_EQ_DATA3_REG, 0xCA);
443         hdmi_writeb(ctx, HDMI_RX_EQ_DATA4_REG, 0xEA);
444         hdmi_writeb(ctx, HDMI_RX_TMDS_ZONE_CTRL_REG, 0xA0);
445         hdmi_writeb(ctx, HDMI_RX_TMDS_MODE_CTRL_REG, 0x00);
446         mhl_tx_writeb(ctx, MHL_TX_TMDS_CCTRL, 0x34);
447         hdmi_writeb(ctx, 0x45, 0x44);
448         hdmi_writeb(ctx, 0x31, 0x0A);
449         hdmi_writeb(ctx, HDMI_RX_TMDS0_CCTRL1_REG, 0xC1);
450
451         return sii9234_clear_error(ctx);
452 }
453
454 static int sii9234_mhl_tx_ctl_int(struct sii9234 *ctx)
455 {
456         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0xD0);
457         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL2_REG, 0xFC);
458         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL4_REG, 0xEB);
459         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL7_REG, 0x0C);
460
461         return sii9234_clear_error(ctx);
462 }
463
464 static int sii9234_reset(struct sii9234 *ctx)
465 {
466         int ret;
467
468         sii9234_clear_error(ctx);
469
470         ret = sii9234_power_init(ctx);
471         if (ret < 0)
472                 return ret;
473         ret = sii9234_cbus_reset(ctx);
474         if (ret < 0)
475                 return ret;
476         ret = sii9234_hdmi_init(ctx);
477         if (ret < 0)
478                 return ret;
479         ret = sii9234_mhl_tx_ctl_int(ctx);
480         if (ret < 0)
481                 return ret;
482
483         /* Enable HDCP Compliance safety */
484         mhl_tx_writeb(ctx, 0x2B, 0x01);
485         /* CBUS discovery cycle time for each drive and float = 150us */
486         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, 0x04, 0x06);
487         /* Clear bit 6 (reg_skip_rgnd) */
488         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL2_REG, (1 << 7) /* Reserved */
489                       | 2 << ATT_THRESH_SHIFT | DEGLITCH_TIME_50MS);
490         /*
491          * Changed from 66 to 65 for 94[1:0] = 01 = 5k reg_cbusmhl_pup_sel
492          * 1.8V CBUS VTH & GND threshold
493          * to meet CTS 3.3.7.2 spec
494          */
495         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
496         cbus_writebm(ctx, CBUS_LINK_CONTROL_2_REG, ~0, MHL_INIT_TIMEOUT);
497         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL6_REG, 0xA0);
498         /* RGND & single discovery attempt (RGND blocking) */
499         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL6_REG, BLOCK_RGND_INT |
500                       DVRFLT_SEL | SINGLE_ATT);
501         /* Use VBUS path of discovery state machine */
502         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL8_REG, 0);
503         /* 0x92[3] sets the CBUS / ID switch */
504         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, USB_ID_OVR);
505         /*
506          * To allow RGND engine to operate correctly.
507          * When moving the chip from D2 to D0 (power up, init regs)
508          * the values should be
509          * 94[1:0] = 01  reg_cbusmhl_pup_sel[1:0] should be set for 5k
510          * 93[7:6] = 10  reg_cbusdisc_pup_sel[1:0] should be
511          * set for 10k (default)
512          * 93[5:4] = 00  reg_cbusidle_pup_sel[1:0] = open (default)
513          */
514         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL3_REG, ~0, 0x86);
515         /*
516          * Change from CC to 8C to match 5K
517          * to meet CTS 3.3.72 spec
518          */
519         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
520         /* Configure the interrupt as active high */
521         mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 0x06);
522
523         msleep(25);
524
525         /* Release usb_id switch */
526         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, 0,  USB_ID_OVR);
527         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL1_REG, 0x27);
528
529         ret = sii9234_clear_error(ctx);
530         if (ret < 0)
531                 return ret;
532         ret = sii9234_cbus_init(ctx);
533         if (ret < 0)
534                 return ret;
535
536         /* Enable Auto soft reset on SCDT = 0 */
537         mhl_tx_writeb(ctx, 0x05, 0x04);
538         /* HDMI Transcode mode enable */
539         mhl_tx_writeb(ctx, 0x0D, 0x1C);
540         mhl_tx_writeb(ctx, MHL_TX_INTR4_ENABLE_REG,
541                       RGND_READY_MASK | CBUS_LKOUT_MASK
542                         | MHL_DISC_FAIL_MASK | MHL_EST_MASK);
543         mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG, 0x60);
544
545         /* This point is very important before measure RGND impedance */
546         force_usb_id_switch_open(ctx);
547         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, 0, 0xF0);
548         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL5_REG, 0, 0x03);
549         release_usb_id_switch_open(ctx);
550
551         /* Force upstream HPD to 0 when not in MHL mode */
552         mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, 0, 1 << 5);
553         mhl_tx_writebm(ctx, MHL_TX_INT_CTRL_REG, ~0, 1 << 4);
554
555         return sii9234_clear_error(ctx);
556 }
557
558 static int sii9234_goto_d3(struct sii9234 *ctx)
559 {
560         int ret;
561
562         dev_dbg(ctx->dev, "sii9234: detection started d3\n");
563
564         ret = sii9234_reset(ctx);
565         if (ret < 0)
566                 goto exit;
567
568         hdmi_writeb(ctx, 0x01, 0x03);
569         tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
570         /* I2C above is expected to fail because power goes down */
571         sii9234_clear_error(ctx);
572
573         ctx->state = ST_D3;
574
575         return 0;
576  exit:
577         dev_err(ctx->dev, "%s failed\n", __func__);
578         return -1;
579 }
580
581 static int sii9234_hw_on(struct sii9234 *ctx)
582 {
583         return regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
584 }
585
586 static void sii9234_hw_off(struct sii9234 *ctx)
587 {
588         gpiod_set_value(ctx->gpio_reset, 1);
589         msleep(20);
590         regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
591 }
592
593 static void sii9234_hw_reset(struct sii9234 *ctx)
594 {
595         gpiod_set_value(ctx->gpio_reset, 1);
596         msleep(20);
597         gpiod_set_value(ctx->gpio_reset, 0);
598 }
599
600 static void sii9234_cable_in(struct sii9234 *ctx)
601 {
602         int ret;
603
604         mutex_lock(&ctx->lock);
605         if (ctx->state != ST_OFF)
606                 goto unlock;
607         ret = sii9234_hw_on(ctx);
608         if (ret < 0)
609                 goto unlock;
610
611         sii9234_hw_reset(ctx);
612         sii9234_goto_d3(ctx);
613         /* To avoid irq storm, when hw is in meta state */
614         enable_irq(to_i2c_client(ctx->dev)->irq);
615
616 unlock:
617         mutex_unlock(&ctx->lock);
618 }
619
620 static void sii9234_cable_out(struct sii9234 *ctx)
621 {
622         mutex_lock(&ctx->lock);
623
624         if (ctx->state == ST_OFF)
625                 goto unlock;
626
627         disable_irq(to_i2c_client(ctx->dev)->irq);
628         tpi_writeb(ctx, TPI_DPD_REG, 0);
629         /* Turn on&off hpd festure for only QCT HDMI */
630         sii9234_hw_off(ctx);
631
632         ctx->state = ST_OFF;
633
634 unlock:
635         mutex_unlock(&ctx->lock);
636 }
637
638 static enum sii9234_state sii9234_rgnd_ready_irq(struct sii9234 *ctx)
639 {
640         int value;
641
642         if (ctx->state == ST_D3) {
643                 int ret;
644
645                 dev_dbg(ctx->dev, "RGND_READY_INT\n");
646                 sii9234_hw_reset(ctx);
647
648                 ret = sii9234_reset(ctx);
649                 if (ret < 0) {
650                         dev_err(ctx->dev, "sii9234_reset() failed\n");
651                         return ST_FAILURE;
652                 }
653
654                 return ST_RGND_INIT;
655         }
656
657         /* Got interrupt in inappropriate state */
658         if (ctx->state != ST_RGND_INIT)
659                 return ST_FAILURE;
660
661         value = mhl_tx_readb(ctx, MHL_TX_STAT2_REG);
662         if (sii9234_clear_error(ctx))
663                 return ST_FAILURE;
664
665         if ((value & RGND_INTP_MASK) != RGND_INTP_1K) {
666                 dev_warn(ctx->dev, "RGND is not 1k\n");
667                 return ST_RGND_INIT;
668         }
669         dev_dbg(ctx->dev, "RGND 1K!!\n");
670         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL4_REG, ~0, 0x8C);
671         mhl_tx_writeb(ctx, MHL_TX_DISC_CTRL5_REG, 0x77);
672         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL6_REG, ~0, 0x05);
673         if (sii9234_clear_error(ctx))
674                 return ST_FAILURE;
675
676         msleep(T_SRC_VBUS_CBUS_TO_STABLE);
677         return ST_RGND_1K;
678 }
679
680 static enum sii9234_state sii9234_mhl_established(struct sii9234 *ctx)
681 {
682         dev_dbg(ctx->dev, "mhl est interrupt\n");
683
684         /* Discovery override */
685         mhl_tx_writeb(ctx, MHL_TX_MHLTX_CTL1_REG, 0x10);
686         /* Increase DDC translation layer timer (byte mode) */
687         cbus_writeb(ctx, 0x07, 0x32);
688         cbus_writebm(ctx, 0x44, ~0, 1 << 1);
689         /* Keep the discovery enabled. Need RGND interrupt */
690         mhl_tx_writebm(ctx, MHL_TX_DISC_CTRL1_REG, ~0, 1);
691         mhl_tx_writeb(ctx, MHL_TX_INTR1_ENABLE_REG,
692                       RSEN_CHANGE_INT_MASK | HPD_CHANGE_INT_MASK);
693
694         if (sii9234_clear_error(ctx))
695                 return ST_FAILURE;
696
697         return ST_MHL_ESTABLISHED;
698 }
699
700 static enum sii9234_state sii9234_hpd_change(struct sii9234 *ctx)
701 {
702         int value;
703
704         value = cbus_readb(ctx, CBUS_MSC_REQ_ABORT_REASON_REG);
705         if (sii9234_clear_error(ctx))
706                 return ST_FAILURE;
707
708         if (value & SET_HPD_DOWNSTREAM) {
709                 /* Downstream HPD High, Enable TMDS */
710                 sii9234_tmds_control(ctx, true);
711         } else {
712                 /* Downstream HPD Low, Disable TMDS */
713                 sii9234_tmds_control(ctx, false);
714         }
715
716         return ctx->state;
717 }
718
719 static enum sii9234_state sii9234_rsen_change(struct sii9234 *ctx)
720 {
721         int value;
722
723         /* Work_around code to handle wrong interrupt */
724         if (ctx->state != ST_RGND_1K) {
725                 dev_err(ctx->dev, "RSEN_HIGH without RGND_1K\n");
726                 return ST_FAILURE;
727         }
728         value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
729         if (value < 0)
730                 return ST_FAILURE;
731
732         if (value & RSEN_STATUS) {
733                 dev_dbg(ctx->dev, "MHL cable connected.. RSEN High\n");
734                 return ST_RSEN_HIGH;
735         }
736         dev_dbg(ctx->dev, "RSEN lost\n");
737         /*
738          * Once RSEN loss is confirmed,we need to check
739          * based on cable status and chip power status,whether
740          * it is SINK Loss(HDMI cable not connected, TV Off)
741          * or MHL cable disconnection
742          * TODO: Define the below mhl_disconnection()
743          */
744         msleep(T_SRC_RXSENSE_DEGLITCH);
745         value = mhl_tx_readb(ctx, MHL_TX_SYSSTAT_REG);
746         if (value < 0)
747                 return ST_FAILURE;
748         dev_dbg(ctx->dev, "sys_stat: %x\n", value);
749
750         if (value & RSEN_STATUS) {
751                 dev_dbg(ctx->dev, "RSEN recovery\n");
752                 return ST_RSEN_HIGH;
753         }
754         dev_dbg(ctx->dev, "RSEN Really LOW\n");
755         /* To meet CTS 3.3.22.2 spec */
756         sii9234_tmds_control(ctx, false);
757         force_usb_id_switch_open(ctx);
758         release_usb_id_switch_open(ctx);
759
760         return ST_FAILURE;
761 }
762
763 static irqreturn_t sii9234_irq_thread(int irq, void *data)
764 {
765         struct sii9234 *ctx = data;
766         int intr1, intr4;
767         int intr1_en, intr4_en;
768         int cbus_intr1, cbus_intr2;
769
770         dev_dbg(ctx->dev, "%s\n", __func__);
771
772         mutex_lock(&ctx->lock);
773
774         intr1 = mhl_tx_readb(ctx, MHL_TX_INTR1_REG);
775         intr4 = mhl_tx_readb(ctx, MHL_TX_INTR4_REG);
776         intr1_en = mhl_tx_readb(ctx, MHL_TX_INTR1_ENABLE_REG);
777         intr4_en = mhl_tx_readb(ctx, MHL_TX_INTR4_ENABLE_REG);
778         cbus_intr1 = cbus_readb(ctx, CBUS_INT_STATUS_1_REG);
779         cbus_intr2 = cbus_readb(ctx, CBUS_INT_STATUS_2_REG);
780
781         if (sii9234_clear_error(ctx))
782                 goto done;
783
784         dev_dbg(ctx->dev, "irq %02x/%02x %02x/%02x %02x/%02x\n",
785                 intr1, intr1_en, intr4, intr4_en, cbus_intr1, cbus_intr2);
786
787         if (intr4 & RGND_READY_INT)
788                 ctx->state = sii9234_rgnd_ready_irq(ctx);
789         if (intr1 & RSEN_CHANGE_INT)
790                 ctx->state = sii9234_rsen_change(ctx);
791         if (intr4 & MHL_EST_INT)
792                 ctx->state = sii9234_mhl_established(ctx);
793         if (intr1 & HPD_CHANGE_INT)
794                 ctx->state = sii9234_hpd_change(ctx);
795         if (intr4 & CBUS_LKOUT_INT)
796                 ctx->state = ST_FAILURE;
797         if (intr4 & MHL_DISC_FAIL_INT)
798                 ctx->state = ST_FAILURE_DISCOVERY;
799
800  done:
801         /* Clean interrupt status and pending flags */
802         mhl_tx_writeb(ctx, MHL_TX_INTR1_REG, intr1);
803         mhl_tx_writeb(ctx, MHL_TX_INTR4_REG, intr4);
804         cbus_writeb(ctx, CBUS_MHL_STATUS_REG_0, 0xFF);
805         cbus_writeb(ctx, CBUS_MHL_STATUS_REG_1, 0xFF);
806         cbus_writeb(ctx, CBUS_INT_STATUS_1_REG, cbus_intr1);
807         cbus_writeb(ctx, CBUS_INT_STATUS_2_REG, cbus_intr2);
808
809         sii9234_clear_error(ctx);
810
811         if (ctx->state == ST_FAILURE) {
812                 dev_dbg(ctx->dev, "try to reset after failure\n");
813                 sii9234_hw_reset(ctx);
814                 sii9234_goto_d3(ctx);
815         }
816
817         if (ctx->state == ST_FAILURE_DISCOVERY) {
818                 dev_err(ctx->dev, "discovery failed, no power for MHL?\n");
819                 tpi_writebm(ctx, TPI_DPD_REG, 0, 1);
820                 ctx->state = ST_D3;
821         }
822
823         mutex_unlock(&ctx->lock);
824
825         return IRQ_HANDLED;
826 }
827
828 static int sii9234_init_resources(struct sii9234 *ctx,
829                                   struct i2c_client *client)
830 {
831         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
832         int ret;
833
834         if (!ctx->dev->of_node) {
835                 dev_err(ctx->dev, "not DT device\n");
836                 return -ENODEV;
837         }
838
839         ctx->gpio_reset = devm_gpiod_get(ctx->dev, "reset", GPIOD_OUT_LOW);
840         if (IS_ERR(ctx->gpio_reset)) {
841                 dev_err(ctx->dev, "failed to get reset gpio from DT\n");
842                 return PTR_ERR(ctx->gpio_reset);
843         }
844
845         ctx->supplies[0].supply = "avcc12";
846         ctx->supplies[1].supply = "avcc33";
847         ctx->supplies[2].supply = "iovcc18";
848         ctx->supplies[3].supply = "cvcc12";
849         ret = devm_regulator_bulk_get(ctx->dev, 4, ctx->supplies);
850         if (ret) {
851                 dev_err(ctx->dev, "regulator_bulk failed\n");
852                 return ret;
853         }
854
855         ctx->client[I2C_MHL] = client;
856
857         ctx->client[I2C_TPI] = i2c_new_dummy(adapter, I2C_TPI_ADDR);
858         if (!ctx->client[I2C_TPI]) {
859                 dev_err(ctx->dev, "failed to create TPI client\n");
860                 return -ENODEV;
861         }
862
863         ctx->client[I2C_HDMI] = i2c_new_dummy(adapter, I2C_HDMI_ADDR);
864         if (!ctx->client[I2C_HDMI]) {
865                 dev_err(ctx->dev, "failed to create HDMI RX client\n");
866                 goto fail_tpi;
867         }
868
869         ctx->client[I2C_CBUS] = i2c_new_dummy(adapter, I2C_CBUS_ADDR);
870         if (!ctx->client[I2C_CBUS]) {
871                 dev_err(ctx->dev, "failed to create CBUS client\n");
872                 goto fail_hdmi;
873         }
874
875         return 0;
876
877 fail_hdmi:
878         i2c_unregister_device(ctx->client[I2C_HDMI]);
879 fail_tpi:
880         i2c_unregister_device(ctx->client[I2C_TPI]);
881
882         return -ENODEV;
883 }
884
885 static void sii9234_deinit_resources(struct sii9234 *ctx)
886 {
887         i2c_unregister_device(ctx->client[I2C_CBUS]);
888         i2c_unregister_device(ctx->client[I2C_HDMI]);
889         i2c_unregister_device(ctx->client[I2C_TPI]);
890 }
891
892 static inline struct sii9234 *bridge_to_sii9234(struct drm_bridge *bridge)
893 {
894         return container_of(bridge, struct sii9234, bridge);
895 }
896
897 static enum drm_mode_status sii9234_mode_valid(struct drm_bridge *bridge,
898                                          const struct drm_display_mode *mode)
899 {
900         if (mode->clock > MHL1_MAX_CLK)
901                 return MODE_CLOCK_HIGH;
902
903         return MODE_OK;
904 }
905
906 static const struct drm_bridge_funcs sii9234_bridge_funcs = {
907         .mode_valid = sii9234_mode_valid,
908 };
909
910 static int sii9234_probe(struct i2c_client *client,
911                          const struct i2c_device_id *id)
912 {
913         struct i2c_adapter *adapter = to_i2c_adapter(client->dev.parent);
914         struct sii9234 *ctx;
915         struct device *dev = &client->dev;
916         int ret;
917
918         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
919         if (!ctx)
920                 return -ENOMEM;
921
922         ctx->dev = dev;
923         mutex_init(&ctx->lock);
924
925         if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
926                 dev_err(dev, "I2C adapter lacks SMBUS feature\n");
927                 return -EIO;
928         }
929
930         if (!client->irq) {
931                 dev_err(dev, "no irq provided\n");
932                 return -EINVAL;
933         }
934
935         irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
936         ret = devm_request_threaded_irq(dev, client->irq, NULL,
937                                         sii9234_irq_thread,
938                                         IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
939                                         "sii9234", ctx);
940         if (ret < 0) {
941                 dev_err(dev, "failed to install IRQ handler\n");
942                 return ret;
943         }
944
945         ret = sii9234_init_resources(ctx, client);
946         if (ret < 0)
947                 return ret;
948
949         i2c_set_clientdata(client, ctx);
950
951         ctx->bridge.funcs = &sii9234_bridge_funcs;
952         ctx->bridge.of_node = dev->of_node;
953         drm_bridge_add(&ctx->bridge);
954
955         sii9234_cable_in(ctx);
956
957         return 0;
958 }
959
960 static int sii9234_remove(struct i2c_client *client)
961 {
962         struct sii9234 *ctx = i2c_get_clientdata(client);
963
964         sii9234_cable_out(ctx);
965         drm_bridge_remove(&ctx->bridge);
966         sii9234_deinit_resources(ctx);
967
968         return 0;
969 }
970
971 static const struct of_device_id sii9234_dt_match[] = {
972         { .compatible = "sil,sii9234" },
973         { },
974 };
975 MODULE_DEVICE_TABLE(of, sii9234_dt_match);
976
977 static const struct i2c_device_id sii9234_id[] = {
978         { "SII9234", 0 },
979         { },
980 };
981 MODULE_DEVICE_TABLE(i2c, sii9234_id);
982
983 static struct i2c_driver sii9234_driver = {
984         .driver = {
985                 .name   = "sii9234",
986                 .of_match_table = sii9234_dt_match,
987         },
988         .probe = sii9234_probe,
989         .remove = sii9234_remove,
990         .id_table = sii9234_id,
991 };
992
993 module_i2c_driver(sii9234_driver);
994 MODULE_LICENSE("GPL");