treewide: Remove uninitialized_var() usage
[sfrench/cifs-2.6.git] / drivers / gpu / drm / bridge / sil-sii8620.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Silicon Image SiI8620 HDMI/MHL bridge driver
4  *
5  * Copyright (C) 2015, Samsung Electronics Co., Ltd.
6  * Andrzej Hajda <a.hajda@samsung.com>
7  */
8
9 #include <asm/unaligned.h>
10
11 #include <drm/bridge/mhl.h>
12 #include <drm/drm_bridge.h>
13 #include <drm/drm_crtc.h>
14 #include <drm/drm_edid.h>
15 #include <drm/drm_encoder.h>
16
17 #include <linux/clk.h>
18 #include <linux/delay.h>
19 #include <linux/extcon.h>
20 #include <linux/gpio/consumer.h>
21 #include <linux/i2c.h>
22 #include <linux/interrupt.h>
23 #include <linux/irq.h>
24 #include <linux/kernel.h>
25 #include <linux/list.h>
26 #include <linux/module.h>
27 #include <linux/mutex.h>
28 #include <linux/of_graph.h>
29 #include <linux/regulator/consumer.h>
30 #include <linux/slab.h>
31
32 #include <media/rc-core.h>
33
34 #include "sil-sii8620.h"
35
36 #define SII8620_BURST_BUF_LEN 288
37 #define VAL_RX_HDMI_CTRL2_DEFVAL VAL_RX_HDMI_CTRL2_IDLE_CNT(3)
38
39 #define MHL1_MAX_PCLK 75000
40 #define MHL1_MAX_PCLK_PP_MODE 150000
41 #define MHL3_MAX_PCLK 200000
42 #define MHL3_MAX_PCLK_PP_MODE 300000
43
44 enum sii8620_mode {
45         CM_DISCONNECTED,
46         CM_DISCOVERY,
47         CM_MHL1,
48         CM_MHL3,
49         CM_ECBUS_S
50 };
51
52 enum sii8620_sink_type {
53         SINK_NONE,
54         SINK_HDMI,
55         SINK_DVI
56 };
57
58 enum sii8620_mt_state {
59         MT_STATE_READY,
60         MT_STATE_BUSY,
61         MT_STATE_DONE
62 };
63
64 struct sii8620 {
65         struct drm_bridge bridge;
66         struct device *dev;
67         struct rc_dev *rc_dev;
68         struct clk *clk_xtal;
69         struct gpio_desc *gpio_reset;
70         struct gpio_desc *gpio_int;
71         struct regulator_bulk_data supplies[2];
72         struct mutex lock; /* context lock, protects fields below */
73         int error;
74         unsigned int use_packed_pixel:1;
75         enum sii8620_mode mode;
76         enum sii8620_sink_type sink_type;
77         u8 cbus_status;
78         u8 stat[MHL_DST_SIZE];
79         u8 xstat[MHL_XDS_SIZE];
80         u8 devcap[MHL_DCAP_SIZE];
81         u8 xdevcap[MHL_XDC_SIZE];
82         bool feature_complete;
83         bool devcap_read;
84         bool sink_detected;
85         struct edid *edid;
86         unsigned int gen2_write_burst:1;
87         enum sii8620_mt_state mt_state;
88         struct extcon_dev *extcon;
89         struct notifier_block extcon_nb;
90         struct work_struct extcon_wq;
91         int cable_state;
92         struct list_head mt_queue;
93         struct {
94                 int r_size;
95                 int r_count;
96                 int rx_ack;
97                 int rx_count;
98                 u8 rx_buf[32];
99                 int tx_count;
100                 u8 tx_buf[32];
101         } burst;
102 };
103
104 struct sii8620_mt_msg;
105
106 typedef void (*sii8620_mt_msg_cb)(struct sii8620 *ctx,
107                                   struct sii8620_mt_msg *msg);
108
109 typedef void (*sii8620_cb)(struct sii8620 *ctx, int ret);
110
111 struct sii8620_mt_msg {
112         struct list_head node;
113         u8 reg[4];
114         u8 ret;
115         sii8620_mt_msg_cb send;
116         sii8620_mt_msg_cb recv;
117         sii8620_cb continuation;
118 };
119
120 static const u8 sii8620_i2c_page[] = {
121         0x39, /* Main System */
122         0x3d, /* TDM and HSIC */
123         0x49, /* TMDS Receiver, MHL EDID */
124         0x4d, /* eMSC, HDCP, HSIC */
125         0x5d, /* MHL Spec */
126         0x64, /* MHL CBUS */
127         0x59, /* Hardware TPI (Transmitter Programming Interface) */
128         0x61, /* eCBUS-S, eCBUS-D */
129 };
130
131 static void sii8620_fetch_edid(struct sii8620 *ctx);
132 static void sii8620_set_upstream_edid(struct sii8620 *ctx);
133 static void sii8620_enable_hpd(struct sii8620 *ctx);
134 static void sii8620_mhl_disconnected(struct sii8620 *ctx);
135 static void sii8620_disconnect(struct sii8620 *ctx);
136
137 static int sii8620_clear_error(struct sii8620 *ctx)
138 {
139         int ret = ctx->error;
140
141         ctx->error = 0;
142         return ret;
143 }
144
145 static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len)
146 {
147         struct device *dev = ctx->dev;
148         struct i2c_client *client = to_i2c_client(dev);
149         u8 data = addr;
150         struct i2c_msg msg[] = {
151                 {
152                         .addr = sii8620_i2c_page[addr >> 8],
153                         .flags = client->flags,
154                         .len = 1,
155                         .buf = &data
156                 },
157                 {
158                         .addr = sii8620_i2c_page[addr >> 8],
159                         .flags = client->flags | I2C_M_RD,
160                         .len = len,
161                         .buf = buf
162                 },
163         };
164         int ret;
165
166         if (ctx->error)
167                 return;
168
169         ret = i2c_transfer(client->adapter, msg, 2);
170         dev_dbg(dev, "read at %04x: %*ph, %d\n", addr, len, buf, ret);
171
172         if (ret != 2) {
173                 dev_err(dev, "Read at %#06x of %d bytes failed with code %d.\n",
174                         addr, len, ret);
175                 ctx->error = ret < 0 ? ret : -EIO;
176         }
177 }
178
179 static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
180 {
181         u8 ret;
182
183         sii8620_read_buf(ctx, addr, &ret, 1);
184         return ret;
185 }
186
187 static void sii8620_write_buf(struct sii8620 *ctx, u16 addr, const u8 *buf,
188                               int len)
189 {
190         struct device *dev = ctx->dev;
191         struct i2c_client *client = to_i2c_client(dev);
192         u8 data[2];
193         struct i2c_msg msg = {
194                 .addr = sii8620_i2c_page[addr >> 8],
195                 .flags = client->flags,
196                 .len = len + 1,
197         };
198         int ret;
199
200         if (ctx->error)
201                 return;
202
203         if (len > 1) {
204                 msg.buf = kmalloc(len + 1, GFP_KERNEL);
205                 if (!msg.buf) {
206                         ctx->error = -ENOMEM;
207                         return;
208                 }
209                 memcpy(msg.buf + 1, buf, len);
210         } else {
211                 msg.buf = data;
212                 msg.buf[1] = *buf;
213         }
214
215         msg.buf[0] = addr;
216
217         ret = i2c_transfer(client->adapter, &msg, 1);
218         dev_dbg(dev, "write at %04x: %*ph, %d\n", addr, len, buf, ret);
219
220         if (ret != 1) {
221                 dev_err(dev, "Write at %#06x of %*ph failed with code %d.\n",
222                         addr, len, buf, ret);
223                 ctx->error = ret ?: -EIO;
224         }
225
226         if (len > 1)
227                 kfree(msg.buf);
228 }
229
230 #define sii8620_write(ctx, addr, arr...) \
231 ({\
232         u8 d[] = { arr }; \
233         sii8620_write_buf(ctx, addr, d, ARRAY_SIZE(d)); \
234 })
235
236 static void __sii8620_write_seq(struct sii8620 *ctx, const u16 *seq, int len)
237 {
238         int i;
239
240         for (i = 0; i < len; i += 2)
241                 sii8620_write(ctx, seq[i], seq[i + 1]);
242 }
243
244 #define sii8620_write_seq(ctx, seq...) \
245 ({\
246         const u16 d[] = { seq }; \
247         __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
248 })
249
250 #define sii8620_write_seq_static(ctx, seq...) \
251 ({\
252         static const u16 d[] = { seq }; \
253         __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
254 })
255
256 static void sii8620_setbits(struct sii8620 *ctx, u16 addr, u8 mask, u8 val)
257 {
258         val = (val & mask) | (sii8620_readb(ctx, addr) & ~mask);
259         sii8620_write(ctx, addr, val);
260 }
261
262 static inline bool sii8620_is_mhl3(struct sii8620 *ctx)
263 {
264         return ctx->mode >= CM_MHL3;
265 }
266
267 static void sii8620_mt_cleanup(struct sii8620 *ctx)
268 {
269         struct sii8620_mt_msg *msg, *n;
270
271         list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) {
272                 list_del(&msg->node);
273                 kfree(msg);
274         }
275         ctx->mt_state = MT_STATE_READY;
276 }
277
278 static void sii8620_mt_work(struct sii8620 *ctx)
279 {
280         struct sii8620_mt_msg *msg;
281
282         if (ctx->error)
283                 return;
284         if (ctx->mt_state == MT_STATE_BUSY || list_empty(&ctx->mt_queue))
285                 return;
286
287         if (ctx->mt_state == MT_STATE_DONE) {
288                 ctx->mt_state = MT_STATE_READY;
289                 msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg,
290                                        node);
291                 list_del(&msg->node);
292                 if (msg->recv)
293                         msg->recv(ctx, msg);
294                 if (msg->continuation)
295                         msg->continuation(ctx, msg->ret);
296                 kfree(msg);
297         }
298
299         if (ctx->mt_state != MT_STATE_READY || list_empty(&ctx->mt_queue))
300                 return;
301
302         ctx->mt_state = MT_STATE_BUSY;
303         msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
304         if (msg->send)
305                 msg->send(ctx, msg);
306 }
307
308 static void sii8620_enable_gen2_write_burst(struct sii8620 *ctx)
309 {
310         u8 ctrl = BIT_MDT_RCV_CTRL_MDT_RCV_EN;
311
312         if (ctx->gen2_write_burst)
313                 return;
314
315         if (ctx->mode >= CM_MHL1)
316                 ctrl |= BIT_MDT_RCV_CTRL_MDT_DELAY_RCV_EN;
317
318         sii8620_write_seq(ctx,
319                 REG_MDT_RCV_TIMEOUT, 100,
320                 REG_MDT_RCV_CTRL, ctrl
321         );
322         ctx->gen2_write_burst = 1;
323 }
324
325 static void sii8620_disable_gen2_write_burst(struct sii8620 *ctx)
326 {
327         if (!ctx->gen2_write_burst)
328                 return;
329
330         sii8620_write_seq_static(ctx,
331                 REG_MDT_XMIT_CTRL, 0,
332                 REG_MDT_RCV_CTRL, 0
333         );
334         ctx->gen2_write_burst = 0;
335 }
336
337 static void sii8620_start_gen2_write_burst(struct sii8620 *ctx)
338 {
339         sii8620_write_seq_static(ctx,
340                 REG_MDT_INT_1_MASK, BIT_MDT_RCV_TIMEOUT
341                         | BIT_MDT_RCV_SM_ABORT_PKT_RCVD | BIT_MDT_RCV_SM_ERROR
342                         | BIT_MDT_XMIT_TIMEOUT | BIT_MDT_XMIT_SM_ABORT_PKT_RCVD
343                         | BIT_MDT_XMIT_SM_ERROR,
344                 REG_MDT_INT_0_MASK, BIT_MDT_XFIFO_EMPTY
345                         | BIT_MDT_IDLE_AFTER_HAWB_DISABLE
346                         | BIT_MDT_RFIFO_DATA_RDY
347         );
348         sii8620_enable_gen2_write_burst(ctx);
349 }
350
351 static void sii8620_mt_msc_cmd_send(struct sii8620 *ctx,
352                                     struct sii8620_mt_msg *msg)
353 {
354         if (msg->reg[0] == MHL_SET_INT &&
355             msg->reg[1] == MHL_INT_REG(RCHANGE) &&
356             msg->reg[2] == MHL_INT_RC_FEAT_REQ)
357                 sii8620_enable_gen2_write_burst(ctx);
358         else
359                 sii8620_disable_gen2_write_burst(ctx);
360
361         switch (msg->reg[0]) {
362         case MHL_WRITE_STAT:
363         case MHL_SET_INT:
364                 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2);
365                 sii8620_write(ctx, REG_MSC_COMMAND_START,
366                               BIT_MSC_COMMAND_START_WRITE_STAT);
367                 break;
368         case MHL_MSC_MSG:
369                 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3);
370                 sii8620_write(ctx, REG_MSC_COMMAND_START,
371                               BIT_MSC_COMMAND_START_MSC_MSG);
372                 break;
373         case MHL_READ_DEVCAP_REG:
374         case MHL_READ_XDEVCAP_REG:
375                 sii8620_write(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg[1]);
376                 sii8620_write(ctx, REG_MSC_COMMAND_START,
377                               BIT_MSC_COMMAND_START_READ_DEVCAP);
378                 break;
379         default:
380                 dev_err(ctx->dev, "%s: command %#x not supported\n", __func__,
381                         msg->reg[0]);
382         }
383 }
384
385 static struct sii8620_mt_msg *sii8620_mt_msg_new(struct sii8620 *ctx)
386 {
387         struct sii8620_mt_msg *msg = kzalloc(sizeof(*msg), GFP_KERNEL);
388
389         if (!msg)
390                 ctx->error = -ENOMEM;
391         else
392                 list_add_tail(&msg->node, &ctx->mt_queue);
393
394         return msg;
395 }
396
397 static void sii8620_mt_set_cont(struct sii8620 *ctx, sii8620_cb cont)
398 {
399         struct sii8620_mt_msg *msg;
400
401         if (ctx->error)
402                 return;
403
404         if (list_empty(&ctx->mt_queue)) {
405                 ctx->error = -EINVAL;
406                 return;
407         }
408         msg = list_last_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
409         msg->continuation = cont;
410 }
411
412 static void sii8620_mt_msc_cmd(struct sii8620 *ctx, u8 cmd, u8 arg1, u8 arg2)
413 {
414         struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
415
416         if (!msg)
417                 return;
418
419         msg->reg[0] = cmd;
420         msg->reg[1] = arg1;
421         msg->reg[2] = arg2;
422         msg->send = sii8620_mt_msc_cmd_send;
423 }
424
425 static void sii8620_mt_write_stat(struct sii8620 *ctx, u8 reg, u8 val)
426 {
427         sii8620_mt_msc_cmd(ctx, MHL_WRITE_STAT, reg, val);
428 }
429
430 static inline void sii8620_mt_set_int(struct sii8620 *ctx, u8 irq, u8 mask)
431 {
432         sii8620_mt_msc_cmd(ctx, MHL_SET_INT, irq, mask);
433 }
434
435 static void sii8620_mt_msc_msg(struct sii8620 *ctx, u8 cmd, u8 data)
436 {
437         sii8620_mt_msc_cmd(ctx, MHL_MSC_MSG, cmd, data);
438 }
439
440 static void sii8620_mt_rap(struct sii8620 *ctx, u8 code)
441 {
442         sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code);
443 }
444
445 static void sii8620_mt_rcpk(struct sii8620 *ctx, u8 code)
446 {
447         sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPK, code);
448 }
449
450 static void sii8620_mt_rcpe(struct sii8620 *ctx, u8 code)
451 {
452         sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPE, code);
453 }
454
455 static void sii8620_mt_read_devcap_send(struct sii8620 *ctx,
456                                         struct sii8620_mt_msg *msg)
457 {
458         u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
459                         | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
460                         | BIT_EDID_CTRL_EDID_MODE_EN;
461
462         if (msg->reg[0] == MHL_READ_XDEVCAP)
463                 ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
464
465         sii8620_write_seq(ctx,
466                 REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE,
467                 REG_EDID_CTRL, ctrl,
468                 REG_TPI_CBUS_START, BIT_TPI_CBUS_START_GET_DEVCAP_START
469         );
470 }
471
472 /* copy src to dst and set changed bits in src */
473 static void sii8620_update_array(u8 *dst, u8 *src, int count)
474 {
475         while (--count >= 0) {
476                 *src ^= *dst;
477                 *dst++ ^= *src++;
478         }
479 }
480
481 static void sii8620_identify_sink(struct sii8620 *ctx)
482 {
483         static const char * const sink_str[] = {
484                 [SINK_NONE] = "NONE",
485                 [SINK_HDMI] = "HDMI",
486                 [SINK_DVI] = "DVI"
487         };
488
489         char sink_name[20];
490         struct device *dev = ctx->dev;
491
492         if (!ctx->sink_detected || !ctx->devcap_read)
493                 return;
494
495         sii8620_fetch_edid(ctx);
496         if (!ctx->edid) {
497                 dev_err(ctx->dev, "Cannot fetch EDID\n");
498                 sii8620_mhl_disconnected(ctx);
499                 return;
500         }
501         sii8620_set_upstream_edid(ctx);
502
503         if (drm_detect_hdmi_monitor(ctx->edid))
504                 ctx->sink_type = SINK_HDMI;
505         else
506                 ctx->sink_type = SINK_DVI;
507
508         drm_edid_get_monitor_name(ctx->edid, sink_name, ARRAY_SIZE(sink_name));
509
510         dev_info(dev, "detected sink(type: %s): %s\n",
511                  sink_str[ctx->sink_type], sink_name);
512 }
513
514 static void sii8620_mr_devcap(struct sii8620 *ctx)
515 {
516         u8 dcap[MHL_DCAP_SIZE];
517         struct device *dev = ctx->dev;
518
519         sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, dcap, MHL_DCAP_SIZE);
520         if (ctx->error < 0)
521                 return;
522
523         dev_info(dev, "detected dongle MHL %d.%d, ChipID %02x%02x:%02x%02x\n",
524                  dcap[MHL_DCAP_MHL_VERSION] / 16,
525                  dcap[MHL_DCAP_MHL_VERSION] % 16,
526                  dcap[MHL_DCAP_ADOPTER_ID_H], dcap[MHL_DCAP_ADOPTER_ID_L],
527                  dcap[MHL_DCAP_DEVICE_ID_H], dcap[MHL_DCAP_DEVICE_ID_L]);
528         sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
529         ctx->devcap_read = true;
530         sii8620_identify_sink(ctx);
531 }
532
533 static void sii8620_mr_xdevcap(struct sii8620 *ctx)
534 {
535         sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap,
536                          MHL_XDC_SIZE);
537 }
538
539 static void sii8620_mt_read_devcap_recv(struct sii8620 *ctx,
540                                         struct sii8620_mt_msg *msg)
541 {
542         u8 ctrl = BIT_EDID_CTRL_DEVCAP_SELECT_DEVCAP
543                 | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
544                 | BIT_EDID_CTRL_EDID_MODE_EN;
545
546         if (msg->reg[0] == MHL_READ_XDEVCAP)
547                 ctrl |= BIT_EDID_CTRL_XDEVCAP_EN;
548
549         sii8620_write_seq(ctx,
550                 REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE | BIT_INTR9_EDID_DONE
551                         | BIT_INTR9_EDID_ERROR,
552                 REG_EDID_CTRL, ctrl,
553                 REG_EDID_FIFO_ADDR, 0
554         );
555
556         if (msg->reg[0] == MHL_READ_XDEVCAP)
557                 sii8620_mr_xdevcap(ctx);
558         else
559                 sii8620_mr_devcap(ctx);
560 }
561
562 static void sii8620_mt_read_devcap(struct sii8620 *ctx, bool xdevcap)
563 {
564         struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
565
566         if (!msg)
567                 return;
568
569         msg->reg[0] = xdevcap ? MHL_READ_XDEVCAP : MHL_READ_DEVCAP;
570         msg->send = sii8620_mt_read_devcap_send;
571         msg->recv = sii8620_mt_read_devcap_recv;
572 }
573
574 static void sii8620_mt_read_devcap_reg_recv(struct sii8620 *ctx,
575                 struct sii8620_mt_msg *msg)
576 {
577         u8 reg = msg->reg[1] & 0x7f;
578
579         if (msg->reg[1] & 0x80)
580                 ctx->xdevcap[reg] = msg->ret;
581         else
582                 ctx->devcap[reg] = msg->ret;
583 }
584
585 static void sii8620_mt_read_devcap_reg(struct sii8620 *ctx, u8 reg)
586 {
587         struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
588
589         if (!msg)
590                 return;
591
592         msg->reg[0] = (reg & 0x80) ? MHL_READ_XDEVCAP_REG : MHL_READ_DEVCAP_REG;
593         msg->reg[1] = reg;
594         msg->send = sii8620_mt_msc_cmd_send;
595         msg->recv = sii8620_mt_read_devcap_reg_recv;
596 }
597
598 static inline void sii8620_mt_read_xdevcap_reg(struct sii8620 *ctx, u8 reg)
599 {
600         sii8620_mt_read_devcap_reg(ctx, reg | 0x80);
601 }
602
603 static void *sii8620_burst_get_tx_buf(struct sii8620 *ctx, int len)
604 {
605         u8 *buf = &ctx->burst.tx_buf[ctx->burst.tx_count];
606         int size = len + 2;
607
608         if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) {
609                 dev_err(ctx->dev, "TX-BLK buffer exhausted\n");
610                 ctx->error = -EINVAL;
611                 return NULL;
612         }
613
614         ctx->burst.tx_count += size;
615         buf[1] = len;
616
617         return buf + 2;
618 }
619
620 static u8 *sii8620_burst_get_rx_buf(struct sii8620 *ctx, int len)
621 {
622         u8 *buf = &ctx->burst.rx_buf[ctx->burst.rx_count];
623         int size = len + 1;
624
625         if (ctx->burst.tx_count + size > ARRAY_SIZE(ctx->burst.tx_buf)) {
626                 dev_err(ctx->dev, "RX-BLK buffer exhausted\n");
627                 ctx->error = -EINVAL;
628                 return NULL;
629         }
630
631         ctx->burst.rx_count += size;
632         buf[0] = len;
633
634         return buf + 1;
635 }
636
637 static void sii8620_burst_send(struct sii8620 *ctx)
638 {
639         int tx_left = ctx->burst.tx_count;
640         u8 *d = ctx->burst.tx_buf;
641
642         while (tx_left > 0) {
643                 int len = d[1] + 2;
644
645                 if (ctx->burst.r_count + len > ctx->burst.r_size)
646                         break;
647                 d[0] = min(ctx->burst.rx_ack, 255);
648                 ctx->burst.rx_ack -= d[0];
649                 sii8620_write_buf(ctx, REG_EMSC_XMIT_WRITE_PORT, d, len);
650                 ctx->burst.r_count += len;
651                 tx_left -= len;
652                 d += len;
653         }
654
655         ctx->burst.tx_count = tx_left;
656
657         while (ctx->burst.rx_ack > 0) {
658                 u8 b[2] = { min(ctx->burst.rx_ack, 255), 0 };
659
660                 if (ctx->burst.r_count + 2 > ctx->burst.r_size)
661                         break;
662                 ctx->burst.rx_ack -= b[0];
663                 sii8620_write_buf(ctx, REG_EMSC_XMIT_WRITE_PORT, b, 2);
664                 ctx->burst.r_count += 2;
665         }
666 }
667
668 static void sii8620_burst_receive(struct sii8620 *ctx)
669 {
670         u8 buf[3], *d;
671         int count;
672
673         sii8620_read_buf(ctx, REG_EMSCRFIFOBCNTL, buf, 2);
674         count = get_unaligned_le16(buf);
675         while (count > 0) {
676                 int len = min(count, 3);
677
678                 sii8620_read_buf(ctx, REG_EMSC_RCV_READ_PORT, buf, len);
679                 count -= len;
680                 ctx->burst.rx_ack += len - 1;
681                 ctx->burst.r_count -= buf[1];
682                 if (ctx->burst.r_count < 0)
683                         ctx->burst.r_count = 0;
684
685                 if (len < 3 || !buf[2])
686                         continue;
687
688                 len = buf[2];
689                 d = sii8620_burst_get_rx_buf(ctx, len);
690                 if (!d)
691                         continue;
692                 sii8620_read_buf(ctx, REG_EMSC_RCV_READ_PORT, d, len);
693                 count -= len;
694                 ctx->burst.rx_ack += len;
695         }
696 }
697
698 static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
699 {
700         struct mhl_burst_blk_rcv_buffer_info *d =
701                 sii8620_burst_get_tx_buf(ctx, sizeof(*d));
702         if (!d)
703                 return;
704
705         d->id = cpu_to_be16(MHL_BURST_ID_BLK_RCV_BUFFER_INFO);
706         d->size = cpu_to_le16(size);
707 }
708
709 static u8 sii8620_checksum(void *ptr, int size)
710 {
711         u8 *d = ptr, sum = 0;
712
713         while (size--)
714                 sum += *d++;
715
716         return sum;
717 }
718
719 static void sii8620_mhl_burst_hdr_set(struct mhl3_burst_header *h,
720         enum mhl_burst_id id)
721 {
722         h->id = cpu_to_be16(id);
723         h->total_entries = 1;
724         h->sequence_index = 1;
725 }
726
727 static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
728 {
729         struct mhl_burst_bits_per_pixel_fmt *d;
730         const int size = sizeof(*d) + sizeof(d->desc[0]);
731
732         d = sii8620_burst_get_tx_buf(ctx, size);
733         if (!d)
734                 return;
735
736         sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_BITS_PER_PIXEL_FMT);
737         d->num_entries = 1;
738         d->desc[0].stream_id = 0;
739         d->desc[0].pixel_format = fmt;
740         d->hdr.checksum -= sii8620_checksum(d, size);
741 }
742
743 static void sii8620_burst_rx_all(struct sii8620 *ctx)
744 {
745         u8 *d = ctx->burst.rx_buf;
746         int count = ctx->burst.rx_count;
747
748         while (count-- > 0) {
749                 int len = *d++;
750                 int id = get_unaligned_be16(&d[0]);
751
752                 switch (id) {
753                 case MHL_BURST_ID_BLK_RCV_BUFFER_INFO:
754                         ctx->burst.r_size = get_unaligned_le16(&d[2]);
755                         break;
756                 default:
757                         break;
758                 }
759                 count -= len;
760                 d += len;
761         }
762         ctx->burst.rx_count = 0;
763 }
764
765 static void sii8620_fetch_edid(struct sii8620 *ctx)
766 {
767         u8 lm_ddc, ddc_cmd, int3, cbus;
768         unsigned long timeout;
769         int fetched, i;
770         int edid_len = EDID_LENGTH;
771         u8 *edid;
772
773         sii8620_readb(ctx, REG_CBUS_STATUS);
774         lm_ddc = sii8620_readb(ctx, REG_LM_DDC);
775         ddc_cmd = sii8620_readb(ctx, REG_DDC_CMD);
776
777         sii8620_write_seq(ctx,
778                 REG_INTR9_MASK, 0,
779                 REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
780                 REG_HDCP2X_POLL_CS, 0x71,
781                 REG_HDCP2X_CTRL_0, BIT_HDCP2X_CTRL_0_HDCP2X_HDCPTX,
782                 REG_LM_DDC, lm_ddc | BIT_LM_DDC_SW_TPI_EN_DISABLED,
783         );
784
785         for (i = 0; i < 256; ++i) {
786                 u8 ddc_stat = sii8620_readb(ctx, REG_DDC_STATUS);
787
788                 if (!(ddc_stat & BIT_DDC_STATUS_DDC_I2C_IN_PROG))
789                         break;
790                 sii8620_write(ctx, REG_DDC_STATUS,
791                               BIT_DDC_STATUS_DDC_FIFO_EMPTY);
792         }
793
794         sii8620_write(ctx, REG_DDC_ADDR, 0x50 << 1);
795
796         edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
797         if (!edid) {
798                 ctx->error = -ENOMEM;
799                 return;
800         }
801
802 #define FETCH_SIZE 16
803         for (fetched = 0; fetched < edid_len; fetched += FETCH_SIZE) {
804                 sii8620_readb(ctx, REG_DDC_STATUS);
805                 sii8620_write_seq(ctx,
806                         REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_ABORT,
807                         REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_DDC_CMD_CLEAR_FIFO,
808                         REG_DDC_STATUS, BIT_DDC_STATUS_DDC_FIFO_EMPTY
809                 );
810                 sii8620_write_seq(ctx,
811                         REG_DDC_SEGM, fetched >> 8,
812                         REG_DDC_OFFSET, fetched & 0xff,
813                         REG_DDC_DIN_CNT1, FETCH_SIZE,
814                         REG_DDC_DIN_CNT2, 0,
815                         REG_DDC_CMD, ddc_cmd | VAL_DDC_CMD_ENH_DDC_READ_NO_ACK
816                 );
817
818                 int3 = 0;
819                 timeout = jiffies + msecs_to_jiffies(200);
820                 for (;;) {
821                         cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
822                         if (~cbus & BIT_CBUS_STATUS_CBUS_CONNECTED) {
823                                 kfree(edid);
824                                 edid = NULL;
825                                 goto end;
826                         }
827                         if (int3 & BIT_DDC_CMD_DONE) {
828                                 if (sii8620_readb(ctx, REG_DDC_DOUT_CNT)
829                                     >= FETCH_SIZE)
830                                         break;
831                         } else {
832                                 int3 = sii8620_readb(ctx, REG_INTR3);
833                         }
834                         if (time_is_before_jiffies(timeout)) {
835                                 ctx->error = -ETIMEDOUT;
836                                 dev_err(ctx->dev, "timeout during EDID read\n");
837                                 kfree(edid);
838                                 edid = NULL;
839                                 goto end;
840                         }
841                         usleep_range(10, 20);
842                 }
843
844                 sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
845                 if (fetched + FETCH_SIZE == EDID_LENGTH) {
846                         u8 ext = ((struct edid *)edid)->extensions;
847
848                         if (ext) {
849                                 u8 *new_edid;
850
851                                 edid_len += ext * EDID_LENGTH;
852                                 new_edid = krealloc(edid, edid_len, GFP_KERNEL);
853                                 if (!new_edid) {
854                                         kfree(edid);
855                                         ctx->error = -ENOMEM;
856                                         return;
857                                 }
858                                 edid = new_edid;
859                         }
860                 }
861         }
862
863         sii8620_write_seq(ctx,
864                 REG_INTR3_MASK, BIT_DDC_CMD_DONE,
865                 REG_LM_DDC, lm_ddc
866         );
867
868 end:
869         kfree(ctx->edid);
870         ctx->edid = (struct edid *)edid;
871 }
872
873 static void sii8620_set_upstream_edid(struct sii8620 *ctx)
874 {
875         sii8620_setbits(ctx, REG_DPD, BIT_DPD_PDNRX12 | BIT_DPD_PDIDCK_N
876                         | BIT_DPD_PD_MHL_CLK_N, 0xff);
877
878         sii8620_write_seq_static(ctx,
879                 REG_RX_HDMI_CTRL3, 0x00,
880                 REG_PKT_FILTER_0, 0xFF,
881                 REG_PKT_FILTER_1, 0xFF,
882                 REG_ALICE0_BW_I2C, 0x06
883         );
884
885         sii8620_setbits(ctx, REG_RX_HDMI_CLR_BUFFER,
886                         BIT_RX_HDMI_CLR_BUFFER_VSI_CLR_EN, 0xff);
887
888         sii8620_write_seq_static(ctx,
889                 REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
890                         | BIT_EDID_CTRL_EDID_MODE_EN,
891                 REG_EDID_FIFO_ADDR, 0,
892         );
893
894         sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid,
895                           (ctx->edid->extensions + 1) * EDID_LENGTH);
896
897         sii8620_write_seq_static(ctx,
898                 REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID
899                         | BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO
900                         | BIT_EDID_CTRL_EDID_MODE_EN,
901                 REG_INTR5_MASK, BIT_INTR_SCDT_CHANGE,
902                 REG_INTR9_MASK, 0
903         );
904 }
905
906 static void sii8620_xtal_set_rate(struct sii8620 *ctx)
907 {
908         static const struct {
909                 unsigned int rate;
910                 u8 div;
911                 u8 tp1;
912         } rates[] = {
913                 { 19200, 0x04, 0x53 },
914                 { 20000, 0x04, 0x62 },
915                 { 24000, 0x05, 0x75 },
916                 { 30000, 0x06, 0x92 },
917                 { 38400, 0x0c, 0xbc },
918         };
919         unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000;
920         int i;
921
922         for (i = 0; i < ARRAY_SIZE(rates) - 1; ++i)
923                 if (rate <= rates[i].rate)
924                         break;
925
926         if (rate != rates[i].rate)
927                 dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n",
928                         rate, rates[i].rate);
929
930         sii8620_write(ctx, REG_DIV_CTL_MAIN, rates[i].div);
931         sii8620_write(ctx, REG_HDCP2X_TP1, rates[i].tp1);
932 }
933
934 static int sii8620_hw_on(struct sii8620 *ctx)
935 {
936         int ret;
937
938         ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
939         if (ret)
940                 return ret;
941
942         usleep_range(10000, 20000);
943         ret = clk_prepare_enable(ctx->clk_xtal);
944         if (ret)
945                 return ret;
946
947         msleep(100);
948         gpiod_set_value(ctx->gpio_reset, 0);
949         msleep(100);
950
951         return 0;
952 }
953
954 static int sii8620_hw_off(struct sii8620 *ctx)
955 {
956         clk_disable_unprepare(ctx->clk_xtal);
957         gpiod_set_value(ctx->gpio_reset, 1);
958         return regulator_bulk_disable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
959 }
960
961 static void sii8620_cbus_reset(struct sii8620 *ctx)
962 {
963         sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
964                       | BIT_PWD_SRST_CBUS_RST_SW_EN);
965         usleep_range(10000, 20000);
966         sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN);
967 }
968
969 static void sii8620_set_auto_zone(struct sii8620 *ctx)
970 {
971         if (ctx->mode != CM_MHL1) {
972                 sii8620_write_seq_static(ctx,
973                         REG_TX_ZONE_CTL1, 0x0,
974                         REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
975                                 | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
976                                 | BIT_MHL_PLL_CTL0_ZONE_MASK_OE
977                 );
978         } else {
979                 sii8620_write_seq_static(ctx,
980                         REG_TX_ZONE_CTL1, VAL_TX_ZONE_CTL1_TX_ZONE_CTRL_MODE,
981                         REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
982                                 | BIT_MHL_PLL_CTL0_ZONE_MASK_OE
983                 );
984         }
985 }
986
987 static void sii8620_stop_video(struct sii8620 *ctx)
988 {
989         u8 val;
990
991         sii8620_write_seq_static(ctx,
992                 REG_TPI_INTR_EN, 0,
993                 REG_HDCP2X_INTR0_MASK, 0,
994                 REG_TPI_COPP_DATA2, 0,
995                 REG_TPI_INTR_ST0, ~0,
996         );
997
998         switch (ctx->sink_type) {
999         case SINK_DVI:
1000                 val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
1001                         | BIT_TPI_SC_TPI_AV_MUTE;
1002                 break;
1003         case SINK_HDMI:
1004         default:
1005                 val = BIT_TPI_SC_REG_TMDS_OE_POWER_DOWN
1006                         | BIT_TPI_SC_TPI_AV_MUTE
1007                         | BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI;
1008                 break;
1009         }
1010
1011         sii8620_write(ctx, REG_TPI_SC, val);
1012 }
1013
1014 static void sii8620_set_format(struct sii8620 *ctx)
1015 {
1016         u8 out_fmt;
1017
1018         if (sii8620_is_mhl3(ctx)) {
1019                 sii8620_setbits(ctx, REG_M3_P0CTRL,
1020                                 BIT_M3_P0CTRL_MHL3_P0_PIXEL_MODE_PACKED,
1021                                 ctx->use_packed_pixel ? ~0 : 0);
1022         } else {
1023                 if (ctx->use_packed_pixel) {
1024                         sii8620_write_seq_static(ctx,
1025                                 REG_VID_MODE, BIT_VID_MODE_M1080P,
1026                                 REG_MHL_TOP_CTL, BIT_MHL_TOP_CTL_MHL_PP_SEL | 1,
1027                                 REG_MHLTX_CTL6, 0x60
1028                         );
1029                 } else {
1030                         sii8620_write_seq_static(ctx,
1031                                 REG_VID_MODE, 0,
1032                                 REG_MHL_TOP_CTL, 1,
1033                                 REG_MHLTX_CTL6, 0xa0
1034                         );
1035                 }
1036         }
1037
1038         if (ctx->use_packed_pixel)
1039                 out_fmt = VAL_TPI_FORMAT(YCBCR422, FULL);
1040         else
1041                 out_fmt = VAL_TPI_FORMAT(RGB, FULL);
1042
1043         sii8620_write_seq(ctx,
1044                 REG_TPI_INPUT, VAL_TPI_FORMAT(RGB, FULL),
1045                 REG_TPI_OUTPUT, out_fmt,
1046         );
1047 }
1048
1049 static int mhl3_infoframe_init(struct mhl3_infoframe *frame)
1050 {
1051         memset(frame, 0, sizeof(*frame));
1052
1053         frame->version = 3;
1054         frame->hev_format = -1;
1055         return 0;
1056 }
1057
1058 static ssize_t mhl3_infoframe_pack(struct mhl3_infoframe *frame,
1059                  void *buffer, size_t size)
1060 {
1061         const int frm_len = HDMI_INFOFRAME_HEADER_SIZE + MHL3_INFOFRAME_SIZE;
1062         u8 *ptr = buffer;
1063
1064         if (size < frm_len)
1065                 return -ENOSPC;
1066
1067         memset(buffer, 0, size);
1068         ptr[0] = HDMI_INFOFRAME_TYPE_VENDOR;
1069         ptr[1] = frame->version;
1070         ptr[2] = MHL3_INFOFRAME_SIZE;
1071         ptr[4] = MHL3_IEEE_OUI & 0xff;
1072         ptr[5] = (MHL3_IEEE_OUI >> 8) & 0xff;
1073         ptr[6] = (MHL3_IEEE_OUI >> 16) & 0xff;
1074         ptr[7] = frame->video_format & 0x3;
1075         ptr[7] |= (frame->format_type & 0x7) << 2;
1076         ptr[7] |= frame->sep_audio ? BIT(5) : 0;
1077         if (frame->hev_format >= 0) {
1078                 ptr[9] = 1;
1079                 ptr[10] = (frame->hev_format >> 8) & 0xff;
1080                 ptr[11] = frame->hev_format & 0xff;
1081         }
1082         if (frame->av_delay) {
1083                 bool sign = frame->av_delay < 0;
1084                 int delay = sign ? -frame->av_delay : frame->av_delay;
1085
1086                 ptr[12] = (delay >> 16) & 0xf;
1087                 if (sign)
1088                         ptr[12] |= BIT(4);
1089                 ptr[13] = (delay >> 8) & 0xff;
1090                 ptr[14] = delay & 0xff;
1091         }
1092         ptr[3] -= sii8620_checksum(buffer, frm_len);
1093         return frm_len;
1094 }
1095
1096 static void sii8620_set_infoframes(struct sii8620 *ctx,
1097                                    struct drm_display_mode *mode)
1098 {
1099         struct mhl3_infoframe mhl_frm;
1100         union hdmi_infoframe frm;
1101         u8 buf[31];
1102         int ret;
1103
1104         ret = drm_hdmi_avi_infoframe_from_display_mode(&frm.avi,
1105                                                        NULL, mode);
1106         if (ctx->use_packed_pixel)
1107                 frm.avi.colorspace = HDMI_COLORSPACE_YUV422;
1108
1109         if (!ret)
1110                 ret = hdmi_avi_infoframe_pack(&frm.avi, buf, ARRAY_SIZE(buf));
1111         if (ret > 0)
1112                 sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
1113
1114         if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) {
1115                 sii8620_write(ctx, REG_TPI_SC,
1116                         BIT_TPI_SC_TPI_OUTPUT_MODE_0_HDMI);
1117                 sii8620_write(ctx, REG_PKT_FILTER_0,
1118                         BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
1119                         BIT_PKT_FILTER_0_DROP_MPEG_PKT |
1120                         BIT_PKT_FILTER_0_DROP_GCP_PKT,
1121                         BIT_PKT_FILTER_1_DROP_GEN_PKT);
1122                 return;
1123         }
1124
1125         sii8620_write(ctx, REG_PKT_FILTER_0,
1126                 BIT_PKT_FILTER_0_DROP_CEA_GAMUT_PKT |
1127                 BIT_PKT_FILTER_0_DROP_MPEG_PKT |
1128                 BIT_PKT_FILTER_0_DROP_AVI_PKT |
1129                 BIT_PKT_FILTER_0_DROP_GCP_PKT,
1130                 BIT_PKT_FILTER_1_VSI_OVERRIDE_DIS |
1131                 BIT_PKT_FILTER_1_DROP_GEN_PKT |
1132                 BIT_PKT_FILTER_1_DROP_VSIF_PKT);
1133
1134         sii8620_write(ctx, REG_TPI_INFO_FSEL, BIT_TPI_INFO_FSEL_EN
1135                 | BIT_TPI_INFO_FSEL_RPT | VAL_TPI_INFO_FSEL_VSI);
1136         ret = mhl3_infoframe_init(&mhl_frm);
1137         if (!ret)
1138                 ret = mhl3_infoframe_pack(&mhl_frm, buf, ARRAY_SIZE(buf));
1139         sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ret);
1140 }
1141
1142 static void sii8620_start_video(struct sii8620 *ctx)
1143 {
1144         struct drm_display_mode *mode =
1145                 &ctx->bridge.encoder->crtc->state->adjusted_mode;
1146
1147         if (!sii8620_is_mhl3(ctx))
1148                 sii8620_stop_video(ctx);
1149
1150         if (ctx->sink_type == SINK_DVI && !sii8620_is_mhl3(ctx)) {
1151                 sii8620_write(ctx, REG_RX_HDMI_CTRL2,
1152                               VAL_RX_HDMI_CTRL2_DEFVAL);
1153                 sii8620_write(ctx, REG_TPI_SC, 0);
1154                 return;
1155         }
1156
1157         sii8620_write_seq_static(ctx,
1158                 REG_RX_HDMI_CTRL2, VAL_RX_HDMI_CTRL2_DEFVAL
1159                         | BIT_RX_HDMI_CTRL2_USE_AV_MUTE,
1160                 REG_VID_OVRRD, BIT_VID_OVRRD_PP_AUTO_DISABLE
1161                         | BIT_VID_OVRRD_M1080P_OVRRD);
1162         sii8620_set_format(ctx);
1163
1164         if (!sii8620_is_mhl3(ctx)) {
1165                 u8 link_mode = MHL_DST_LM_PATH_ENABLED;
1166
1167                 if (ctx->use_packed_pixel)
1168                         link_mode |= MHL_DST_LM_CLK_MODE_PACKED_PIXEL;
1169                 else
1170                         link_mode |= MHL_DST_LM_CLK_MODE_NORMAL;
1171
1172                 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), link_mode);
1173                 sii8620_set_auto_zone(ctx);
1174         } else {
1175                 static const struct {
1176                         int max_clk;
1177                         u8 zone;
1178                         u8 link_rate;
1179                         u8 rrp_decode;
1180                 } clk_spec[] = {
1181                         { 150000, VAL_TX_ZONE_CTL3_TX_ZONE_1_5GBPS,
1182                           MHL_XDS_LINK_RATE_1_5_GBPS, 0x38 },
1183                         { 300000, VAL_TX_ZONE_CTL3_TX_ZONE_3GBPS,
1184                           MHL_XDS_LINK_RATE_3_0_GBPS, 0x40 },
1185                         { 600000, VAL_TX_ZONE_CTL3_TX_ZONE_6GBPS,
1186                           MHL_XDS_LINK_RATE_6_0_GBPS, 0x40 },
1187                 };
1188                 u8 p0_ctrl = BIT_M3_P0CTRL_MHL3_P0_PORT_EN;
1189                 int clk = mode->clock * (ctx->use_packed_pixel ? 2 : 3);
1190                 int i;
1191
1192                 for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i)
1193                         if (clk < clk_spec[i].max_clk)
1194                                 break;
1195
1196                 if (100 * clk >= 98 * clk_spec[i].max_clk)
1197                         p0_ctrl |= BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN;
1198
1199                 sii8620_burst_tx_bits_per_pixel_fmt(ctx, ctx->use_packed_pixel);
1200                 sii8620_burst_send(ctx);
1201                 sii8620_write_seq(ctx,
1202                         REG_MHL_DP_CTL0, 0xf0,
1203                         REG_MHL3_TX_ZONE_CTL, clk_spec[i].zone);
1204                 sii8620_setbits(ctx, REG_M3_P0CTRL,
1205                         BIT_M3_P0CTRL_MHL3_P0_PORT_EN
1206                         | BIT_M3_P0CTRL_MHL3_P0_UNLIMIT_EN, p0_ctrl);
1207                 sii8620_setbits(ctx, REG_M3_POSTM, MSK_M3_POSTM_RRP_DECODE,
1208                         clk_spec[i].rrp_decode);
1209                 sii8620_write_seq_static(ctx,
1210                         REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
1211                                 | BIT_M3_CTRL_H2M_SWRST,
1212                         REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE
1213                 );
1214                 sii8620_mt_write_stat(ctx, MHL_XDS_REG(AVLINK_MODE_CONTROL),
1215                         clk_spec[i].link_rate);
1216         }
1217
1218         sii8620_set_infoframes(ctx, mode);
1219 }
1220
1221 static void sii8620_disable_hpd(struct sii8620 *ctx)
1222 {
1223         sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
1224         sii8620_write_seq_static(ctx,
1225                 REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN,
1226                 REG_INTR8_MASK, 0
1227         );
1228 }
1229
1230 static void sii8620_enable_hpd(struct sii8620 *ctx)
1231 {
1232         sii8620_setbits(ctx, REG_TMDS_CSTAT_P3,
1233                         BIT_TMDS_CSTAT_P3_SCDT_CLR_AVI_DIS
1234                         | BIT_TMDS_CSTAT_P3_CLR_AVI, ~0);
1235         sii8620_write_seq_static(ctx,
1236                 REG_HPD_CTRL, BIT_HPD_CTRL_HPD_OUT_OVR_EN
1237                         | BIT_HPD_CTRL_HPD_HIGH,
1238         );
1239 }
1240
1241 static void sii8620_mhl_discover(struct sii8620 *ctx)
1242 {
1243         sii8620_write_seq_static(ctx,
1244                 REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
1245                         | BIT_DISC_CTRL9_DISC_PULSE_PROCEED,
1246                 REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_5K, VAL_PUP_20K),
1247                 REG_CBUS_DISC_INTR0_MASK, BIT_MHL3_EST_INT
1248                         | BIT_MHL_EST_INT
1249                         | BIT_NOT_MHL_EST_INT
1250                         | BIT_CBUS_MHL3_DISCON_INT
1251                         | BIT_CBUS_MHL12_DISCON_INT
1252                         | BIT_RGND_READY_INT,
1253                 REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
1254                         | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
1255                         | BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
1256                 REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
1257                         | BIT_MHL_DP_CTL0_TX_OE_OVR,
1258                 REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
1259                 REG_MHL_DP_CTL1, 0xA2,
1260                 REG_MHL_DP_CTL2, 0x03,
1261                 REG_MHL_DP_CTL3, 0x35,
1262                 REG_MHL_DP_CTL5, 0x02,
1263                 REG_MHL_DP_CTL6, 0x02,
1264                 REG_MHL_DP_CTL7, 0x03,
1265                 REG_COC_CTLC, 0xFF,
1266                 REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
1267                         | BIT_DPD_OSC_EN | BIT_DPD_PWRON_HSIC,
1268                 REG_COC_INTR_MASK, BIT_COC_PLL_LOCK_STATUS_CHANGE
1269                         | BIT_COC_CALIBRATION_DONE,
1270                 REG_CBUS_INT_1_MASK, BIT_CBUS_MSC_ABORT_RCVD
1271                         | BIT_CBUS_CMD_ABORT,
1272                 REG_CBUS_INT_0_MASK, BIT_CBUS_MSC_MT_DONE
1273                         | BIT_CBUS_HPD_CHG
1274                         | BIT_CBUS_MSC_MR_WRITE_STAT
1275                         | BIT_CBUS_MSC_MR_MSC_MSG
1276                         | BIT_CBUS_MSC_MR_WRITE_BURST
1277                         | BIT_CBUS_MSC_MR_SET_INT
1278                         | BIT_CBUS_MSC_MT_DONE_NACK
1279         );
1280 }
1281
1282 static void sii8620_peer_specific_init(struct sii8620 *ctx)
1283 {
1284         if (sii8620_is_mhl3(ctx))
1285                 sii8620_write_seq_static(ctx,
1286                         REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD,
1287                         REG_EMSCINTRMASK1,
1288                                 BIT_EMSCINTR1_EMSC_TRAINING_COMMA_ERR
1289                 );
1290         else
1291                 sii8620_write_seq_static(ctx,
1292                         REG_HDCP2X_INTR0_MASK, 0x00,
1293                         REG_EMSCINTRMASK1, 0x00,
1294                         REG_HDCP2X_INTR0, 0xFF,
1295                         REG_INTR1, 0xFF,
1296                         REG_SYS_CTRL1, BIT_SYS_CTRL1_BLOCK_DDC_BY_HPD
1297                                 | BIT_SYS_CTRL1_TX_CTRL_HDMI
1298                 );
1299 }
1300
1301 #define SII8620_MHL_VERSION                     0x32
1302 #define SII8620_SCRATCHPAD_SIZE                 16
1303 #define SII8620_INT_STAT_SIZE                   0x33
1304
1305 static void sii8620_set_dev_cap(struct sii8620 *ctx)
1306 {
1307         static const u8 devcap[MHL_DCAP_SIZE] = {
1308                 [MHL_DCAP_MHL_VERSION] = SII8620_MHL_VERSION,
1309                 [MHL_DCAP_CAT] = MHL_DCAP_CAT_SOURCE | MHL_DCAP_CAT_POWER,
1310                 [MHL_DCAP_ADOPTER_ID_H] = 0x01,
1311                 [MHL_DCAP_ADOPTER_ID_L] = 0x41,
1312                 [MHL_DCAP_VID_LINK_MODE] = MHL_DCAP_VID_LINK_RGB444
1313                         | MHL_DCAP_VID_LINK_PPIXEL
1314                         | MHL_DCAP_VID_LINK_16BPP,
1315                 [MHL_DCAP_AUD_LINK_MODE] = MHL_DCAP_AUD_LINK_2CH,
1316                 [MHL_DCAP_VIDEO_TYPE] = MHL_DCAP_VT_GRAPHICS,
1317                 [MHL_DCAP_LOG_DEV_MAP] = MHL_DCAP_LD_GUI,
1318                 [MHL_DCAP_BANDWIDTH] = 0x0f,
1319                 [MHL_DCAP_FEATURE_FLAG] = MHL_DCAP_FEATURE_RCP_SUPPORT
1320                         | MHL_DCAP_FEATURE_RAP_SUPPORT
1321                         | MHL_DCAP_FEATURE_SP_SUPPORT,
1322                 [MHL_DCAP_SCRATCHPAD_SIZE] = SII8620_SCRATCHPAD_SIZE,
1323                 [MHL_DCAP_INT_STAT_SIZE] = SII8620_INT_STAT_SIZE,
1324         };
1325         static const u8 xdcap[MHL_XDC_SIZE] = {
1326                 [MHL_XDC_ECBUS_SPEEDS] = MHL_XDC_ECBUS_S_075
1327                         | MHL_XDC_ECBUS_S_8BIT,
1328                 [MHL_XDC_TMDS_SPEEDS] = MHL_XDC_TMDS_150
1329                         | MHL_XDC_TMDS_300 | MHL_XDC_TMDS_600,
1330                 [MHL_XDC_ECBUS_ROLES] = MHL_XDC_DEV_HOST,
1331                 [MHL_XDC_LOG_DEV_MAPX] = MHL_XDC_LD_PHONE,
1332         };
1333
1334         sii8620_write_buf(ctx, REG_MHL_DEVCAP_0, devcap, ARRAY_SIZE(devcap));
1335         sii8620_write_buf(ctx, REG_MHL_EXTDEVCAP_0, xdcap, ARRAY_SIZE(xdcap));
1336 }
1337
1338 static void sii8620_mhl_init(struct sii8620 *ctx)
1339 {
1340         sii8620_write_seq_static(ctx,
1341                 REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
1342                 REG_CBUS_MSC_COMPAT_CTRL,
1343                         BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN,
1344         );
1345
1346         sii8620_peer_specific_init(ctx);
1347
1348         sii8620_disable_hpd(ctx);
1349
1350         sii8620_write_seq_static(ctx,
1351                 REG_EDID_CTRL, BIT_EDID_CTRL_EDID_FIFO_ADDR_AUTO,
1352                 REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
1353                         | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
1354                 REG_TMDS0_CCTRL1, 0x90,
1355                 REG_TMDS_CLK_EN, 0x01,
1356                 REG_TMDS_CH_EN, 0x11,
1357                 REG_BGR_BIAS, 0x87,
1358                 REG_ALICE0_ZONE_CTRL, 0xE8,
1359                 REG_ALICE0_MODE_CTRL, 0x04,
1360         );
1361         sii8620_setbits(ctx, REG_LM_DDC, BIT_LM_DDC_SW_TPI_EN_DISABLED, 0);
1362         sii8620_write_seq_static(ctx,
1363                 REG_TPI_HW_OPT3, 0x76,
1364                 REG_TMDS_CCTRL, BIT_TMDS_CCTRL_TMDS_OE,
1365                 REG_TPI_DTD_B2, 79,
1366         );
1367         sii8620_set_dev_cap(ctx);
1368         sii8620_write_seq_static(ctx,
1369                 REG_MDT_XMIT_TIMEOUT, 100,
1370                 REG_MDT_XMIT_CTRL, 0x03,
1371                 REG_MDT_XFIFO_STAT, 0x00,
1372                 REG_MDT_RCV_TIMEOUT, 100,
1373                 REG_CBUS_LINK_CTRL_8, 0x1D,
1374         );
1375
1376         sii8620_start_gen2_write_burst(ctx);
1377         sii8620_write_seq_static(ctx,
1378                 REG_BIST_CTRL, 0x00,
1379                 REG_COC_CTL1, 0x10,
1380                 REG_COC_CTL2, 0x18,
1381                 REG_COC_CTLF, 0x07,
1382                 REG_COC_CTL11, 0xF8,
1383                 REG_COC_CTL17, 0x61,
1384                 REG_COC_CTL18, 0x46,
1385                 REG_COC_CTL19, 0x15,
1386                 REG_COC_CTL1A, 0x01,
1387                 REG_MHL_COC_CTL3, BIT_MHL_COC_CTL3_COC_AECHO_EN,
1388                 REG_MHL_COC_CTL4, 0x2D,
1389                 REG_MHL_COC_CTL5, 0xF9,
1390                 REG_MSC_HEARTBEAT_CTRL, 0x27,
1391         );
1392         sii8620_disable_gen2_write_burst(ctx);
1393
1394         sii8620_mt_write_stat(ctx, MHL_DST_REG(VERSION), SII8620_MHL_VERSION);
1395         sii8620_mt_write_stat(ctx, MHL_DST_REG(CONNECTED_RDY),
1396                               MHL_DST_CONN_DCAP_RDY | MHL_DST_CONN_XDEVCAPP_SUPP
1397                               | MHL_DST_CONN_POW_STAT);
1398         sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), MHL_INT_RC_DCAP_CHG);
1399 }
1400
1401 static void sii8620_emsc_enable(struct sii8620 *ctx)
1402 {
1403         u8 reg;
1404
1405         sii8620_setbits(ctx, REG_GENCTL, BIT_GENCTL_EMSC_EN
1406                                          | BIT_GENCTL_CLR_EMSC_RFIFO
1407                                          | BIT_GENCTL_CLR_EMSC_XFIFO, ~0);
1408         sii8620_setbits(ctx, REG_GENCTL, BIT_GENCTL_CLR_EMSC_RFIFO
1409                                          | BIT_GENCTL_CLR_EMSC_XFIFO, 0);
1410         sii8620_setbits(ctx, REG_COMMECNT, BIT_COMMECNT_I2C_TO_EMSC_EN, ~0);
1411         reg = sii8620_readb(ctx, REG_EMSCINTR);
1412         sii8620_write(ctx, REG_EMSCINTR, reg);
1413         sii8620_write(ctx, REG_EMSCINTRMASK, BIT_EMSCINTR_SPI_DVLD);
1414 }
1415
1416 static int sii8620_wait_for_fsm_state(struct sii8620 *ctx, u8 state)
1417 {
1418         int i;
1419
1420         for (i = 0; i < 10; ++i) {
1421                 u8 s = sii8620_readb(ctx, REG_COC_STAT_0);
1422
1423                 if ((s & MSK_COC_STAT_0_FSM_STATE) == state)
1424                         return 0;
1425                 if (!(s & BIT_COC_STAT_0_PLL_LOCKED))
1426                         return -EBUSY;
1427                 usleep_range(4000, 6000);
1428         }
1429         return -ETIMEDOUT;
1430 }
1431
1432 static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
1433 {
1434         int ret;
1435
1436         if (ctx->mode == mode)
1437                 return;
1438
1439         switch (mode) {
1440         case CM_MHL1:
1441                 sii8620_write_seq_static(ctx,
1442                         REG_CBUS_MSC_COMPAT_CTRL, 0x02,
1443                         REG_M3_CTRL, VAL_M3_CTRL_MHL1_2_VALUE,
1444                         REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12
1445                                 | BIT_DPD_OSC_EN,
1446                         REG_COC_INTR_MASK, 0
1447                 );
1448                 ctx->mode = mode;
1449                 break;
1450         case CM_MHL3:
1451                 sii8620_write(ctx, REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE);
1452                 ctx->mode = mode;
1453                 return;
1454         case CM_ECBUS_S:
1455                 sii8620_emsc_enable(ctx);
1456                 sii8620_write_seq_static(ctx,
1457                         REG_TTXSPINUMS, 4,
1458                         REG_TRXSPINUMS, 4,
1459                         REG_TTXHSICNUMS, 0x14,
1460                         REG_TRXHSICNUMS, 0x14,
1461                         REG_TTXTOTNUMS, 0x18,
1462                         REG_TRXTOTNUMS, 0x18,
1463                         REG_PWD_SRST, BIT_PWD_SRST_COC_DOC_RST
1464                                       | BIT_PWD_SRST_CBUS_RST_SW_EN,
1465                         REG_MHL_COC_CTL1, 0xbd,
1466                         REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN,
1467                         REG_COC_CTLB, 0x01,
1468                         REG_COC_CTL0, 0x5c,
1469                         REG_COC_CTL14, 0x03,
1470                         REG_COC_CTL15, 0x80,
1471                         REG_MHL_DP_CTL6, BIT_MHL_DP_CTL6_DP_TAP1_SGN
1472                                          | BIT_MHL_DP_CTL6_DP_TAP1_EN
1473                                          | BIT_MHL_DP_CTL6_DT_PREDRV_FEEDCAP_EN,
1474                         REG_MHL_DP_CTL8, 0x03
1475                 );
1476                 ret = sii8620_wait_for_fsm_state(ctx, 0x03);
1477                 sii8620_write_seq_static(ctx,
1478                         REG_COC_CTL14, 0x00,
1479                         REG_COC_CTL15, 0x80
1480                 );
1481                 if (!ret)
1482                         sii8620_write(ctx, REG_CBUS3_CNVT, 0x85);
1483                 else
1484                         sii8620_disconnect(ctx);
1485                 return;
1486         case CM_DISCONNECTED:
1487                 ctx->mode = mode;
1488                 break;
1489         default:
1490                 dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode);
1491                 break;
1492         }
1493
1494         sii8620_set_auto_zone(ctx);
1495
1496         if (mode != CM_MHL1)
1497                 return;
1498
1499         sii8620_write_seq_static(ctx,
1500                 REG_MHL_DP_CTL0, 0xBC,
1501                 REG_MHL_DP_CTL1, 0xBB,
1502                 REG_MHL_DP_CTL3, 0x48,
1503                 REG_MHL_DP_CTL5, 0x39,
1504                 REG_MHL_DP_CTL2, 0x2A,
1505                 REG_MHL_DP_CTL6, 0x2A,
1506                 REG_MHL_DP_CTL7, 0x08
1507         );
1508 }
1509
1510 static void sii8620_hpd_unplugged(struct sii8620 *ctx)
1511 {
1512         sii8620_disable_hpd(ctx);
1513         ctx->sink_type = SINK_NONE;
1514         ctx->sink_detected = false;
1515         ctx->feature_complete = false;
1516         kfree(ctx->edid);
1517         ctx->edid = NULL;
1518 }
1519
1520 static void sii8620_disconnect(struct sii8620 *ctx)
1521 {
1522         sii8620_disable_gen2_write_burst(ctx);
1523         sii8620_stop_video(ctx);
1524         msleep(100);
1525         sii8620_cbus_reset(ctx);
1526         sii8620_set_mode(ctx, CM_DISCONNECTED);
1527         sii8620_write_seq_static(ctx,
1528                 REG_TX_ZONE_CTL1, 0,
1529                 REG_MHL_PLL_CTL0, 0x07,
1530                 REG_COC_CTL0, 0x40,
1531                 REG_CBUS3_CNVT, 0x84,
1532                 REG_COC_CTL14, 0x00,
1533                 REG_COC_CTL0, 0x40,
1534                 REG_HRXCTRL3, 0x07,
1535                 REG_MHL_PLL_CTL0, VAL_MHL_PLL_CTL0_HDMI_CLK_RATIO_1X
1536                         | BIT_MHL_PLL_CTL0_CRYSTAL_CLK_SEL
1537                         | BIT_MHL_PLL_CTL0_ZONE_MASK_OE,
1538                 REG_MHL_DP_CTL0, BIT_MHL_DP_CTL0_DP_OE
1539                         | BIT_MHL_DP_CTL0_TX_OE_OVR,
1540                 REG_MHL_DP_CTL1, 0xBB,
1541                 REG_MHL_DP_CTL3, 0x48,
1542                 REG_MHL_DP_CTL5, 0x3F,
1543                 REG_MHL_DP_CTL2, 0x2F,
1544                 REG_MHL_DP_CTL6, 0x2A,
1545                 REG_MHL_DP_CTL7, 0x03
1546         );
1547         sii8620_hpd_unplugged(ctx);
1548         sii8620_write_seq_static(ctx,
1549                 REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE,
1550                 REG_MHL_COC_CTL1, 0x07,
1551                 REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
1552                 REG_DISC_CTRL8, 0x00,
1553                 REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
1554                         | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
1555                 REG_INT_CTRL, 0x00,
1556                 REG_MSC_HEARTBEAT_CTRL, 0x27,
1557                 REG_DISC_CTRL1, 0x25,
1558                 REG_CBUS_DISC_INTR0, (u8)~BIT_RGND_READY_INT,
1559                 REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT,
1560                 REG_MDT_INT_1, 0xff,
1561                 REG_MDT_INT_1_MASK, 0x00,
1562                 REG_MDT_INT_0, 0xff,
1563                 REG_MDT_INT_0_MASK, 0x00,
1564                 REG_COC_INTR, 0xff,
1565                 REG_COC_INTR_MASK, 0x00,
1566                 REG_TRXINTH, 0xff,
1567                 REG_TRXINTMH, 0x00,
1568                 REG_CBUS_INT_0, 0xff,
1569                 REG_CBUS_INT_0_MASK, 0x00,
1570                 REG_CBUS_INT_1, 0xff,
1571                 REG_CBUS_INT_1_MASK, 0x00,
1572                 REG_EMSCINTR, 0xff,
1573                 REG_EMSCINTRMASK, 0x00,
1574                 REG_EMSCINTR1, 0xff,
1575                 REG_EMSCINTRMASK1, 0x00,
1576                 REG_INTR8, 0xff,
1577                 REG_INTR8_MASK, 0x00,
1578                 REG_TPI_INTR_ST0, 0xff,
1579                 REG_TPI_INTR_EN, 0x00,
1580                 REG_HDCP2X_INTR0, 0xff,
1581                 REG_HDCP2X_INTR0_MASK, 0x00,
1582                 REG_INTR9, 0xff,
1583                 REG_INTR9_MASK, 0x00,
1584                 REG_INTR3, 0xff,
1585                 REG_INTR3_MASK, 0x00,
1586                 REG_INTR5, 0xff,
1587                 REG_INTR5_MASK, 0x00,
1588                 REG_INTR2, 0xff,
1589                 REG_INTR2_MASK, 0x00,
1590         );
1591         memset(ctx->stat, 0, sizeof(ctx->stat));
1592         memset(ctx->xstat, 0, sizeof(ctx->xstat));
1593         memset(ctx->devcap, 0, sizeof(ctx->devcap));
1594         memset(ctx->xdevcap, 0, sizeof(ctx->xdevcap));
1595         ctx->devcap_read = false;
1596         ctx->cbus_status = 0;
1597         sii8620_mt_cleanup(ctx);
1598 }
1599
1600 static void sii8620_mhl_disconnected(struct sii8620 *ctx)
1601 {
1602         sii8620_write_seq_static(ctx,
1603                 REG_DISC_CTRL4, VAL_DISC_CTRL4(VAL_PUP_OFF, VAL_PUP_20K),
1604                 REG_CBUS_MSC_COMPAT_CTRL,
1605                         BIT_CBUS_MSC_COMPAT_CTRL_XDEVCAP_EN
1606         );
1607         sii8620_disconnect(ctx);
1608 }
1609
1610 static void sii8620_irq_disc(struct sii8620 *ctx)
1611 {
1612         u8 stat = sii8620_readb(ctx, REG_CBUS_DISC_INTR0);
1613
1614         if (stat & VAL_CBUS_MHL_DISCON)
1615                 sii8620_mhl_disconnected(ctx);
1616
1617         if (stat & BIT_RGND_READY_INT) {
1618                 u8 stat2 = sii8620_readb(ctx, REG_DISC_STAT2);
1619
1620                 if ((stat2 & MSK_DISC_STAT2_RGND) == VAL_RGND_1K) {
1621                         sii8620_mhl_discover(ctx);
1622                 } else {
1623                         sii8620_write_seq_static(ctx,
1624                                 REG_DISC_CTRL9, BIT_DISC_CTRL9_WAKE_DRVFLT
1625                                         | BIT_DISC_CTRL9_NOMHL_EST
1626                                         | BIT_DISC_CTRL9_WAKE_PULSE_BYPASS,
1627                                 REG_CBUS_DISC_INTR0_MASK, BIT_RGND_READY_INT
1628                                         | BIT_CBUS_MHL3_DISCON_INT
1629                                         | BIT_CBUS_MHL12_DISCON_INT
1630                                         | BIT_NOT_MHL_EST_INT
1631                         );
1632                 }
1633         }
1634         if (stat & BIT_MHL_EST_INT)
1635                 sii8620_mhl_init(ctx);
1636
1637         sii8620_write(ctx, REG_CBUS_DISC_INTR0, stat);
1638 }
1639
1640 static void sii8620_read_burst(struct sii8620 *ctx)
1641 {
1642         u8 buf[17];
1643
1644         sii8620_read_buf(ctx, REG_MDT_RCV_READ_PORT, buf, ARRAY_SIZE(buf));
1645         sii8620_write(ctx, REG_MDT_RCV_CTRL, BIT_MDT_RCV_CTRL_MDT_RCV_EN |
1646                       BIT_MDT_RCV_CTRL_MDT_DELAY_RCV_EN |
1647                       BIT_MDT_RCV_CTRL_MDT_RFIFO_CLR_CUR);
1648         sii8620_readb(ctx, REG_MDT_RFIFO_STAT);
1649 }
1650
1651 static void sii8620_irq_g2wb(struct sii8620 *ctx)
1652 {
1653         u8 stat = sii8620_readb(ctx, REG_MDT_INT_0);
1654
1655         if (stat & BIT_MDT_IDLE_AFTER_HAWB_DISABLE)
1656                 if (sii8620_is_mhl3(ctx))
1657                         sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE),
1658                                 MHL_INT_RC_FEAT_COMPLETE);
1659
1660         if (stat & BIT_MDT_RFIFO_DATA_RDY)
1661                 sii8620_read_burst(ctx);
1662
1663         if (stat & BIT_MDT_XFIFO_EMPTY)
1664                 sii8620_write(ctx, REG_MDT_XMIT_CTRL, 0);
1665
1666         sii8620_write(ctx, REG_MDT_INT_0, stat);
1667 }
1668
1669 static void sii8620_status_dcap_ready(struct sii8620 *ctx)
1670 {
1671         enum sii8620_mode mode;
1672
1673         mode = ctx->stat[MHL_DST_VERSION] >= 0x30 ? CM_MHL3 : CM_MHL1;
1674         if (mode > ctx->mode)
1675                 sii8620_set_mode(ctx, mode);
1676         sii8620_peer_specific_init(ctx);
1677         sii8620_write(ctx, REG_INTR9_MASK, BIT_INTR9_DEVCAP_DONE
1678                       | BIT_INTR9_EDID_DONE | BIT_INTR9_EDID_ERROR);
1679 }
1680
1681 static void sii8620_status_changed_path(struct sii8620 *ctx)
1682 {
1683         u8 link_mode;
1684
1685         if (ctx->use_packed_pixel)
1686                 link_mode = MHL_DST_LM_CLK_MODE_PACKED_PIXEL;
1687         else
1688                 link_mode = MHL_DST_LM_CLK_MODE_NORMAL;
1689
1690         if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
1691                 link_mode |= MHL_DST_LM_PATH_ENABLED;
1692
1693         sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
1694                               link_mode);
1695 }
1696
1697 static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
1698 {
1699         u8 st[MHL_DST_SIZE], xst[MHL_XDS_SIZE];
1700
1701         sii8620_read_buf(ctx, REG_MHL_STAT_0, st, MHL_DST_SIZE);
1702         sii8620_read_buf(ctx, REG_MHL_EXTSTAT_0, xst, MHL_XDS_SIZE);
1703
1704         sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
1705         sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
1706
1707         if (ctx->stat[MHL_DST_CONNECTED_RDY] & st[MHL_DST_CONNECTED_RDY] &
1708             MHL_DST_CONN_DCAP_RDY) {
1709                 sii8620_status_dcap_ready(ctx);
1710
1711                 if (!sii8620_is_mhl3(ctx))
1712                         sii8620_mt_read_devcap(ctx, false);
1713         }
1714
1715         if (st[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
1716                 sii8620_status_changed_path(ctx);
1717 }
1718
1719 static void sii8620_ecbus_up(struct sii8620 *ctx, int ret)
1720 {
1721         if (ret < 0)
1722                 return;
1723
1724         sii8620_set_mode(ctx, CM_ECBUS_S);
1725 }
1726
1727 static void sii8620_got_ecbus_speed(struct sii8620 *ctx, int ret)
1728 {
1729         if (ret < 0)
1730                 return;
1731
1732         sii8620_mt_write_stat(ctx, MHL_XDS_REG(CURR_ECBUS_MODE),
1733                               MHL_XDS_ECBUS_S | MHL_XDS_SLOT_MODE_8BIT);
1734         sii8620_mt_rap(ctx, MHL_RAP_CBUS_MODE_UP);
1735         sii8620_mt_set_cont(ctx, sii8620_ecbus_up);
1736 }
1737
1738 static void sii8620_mhl_burst_emsc_support_set(struct mhl_burst_emsc_support *d,
1739         enum mhl_burst_id id)
1740 {
1741         sii8620_mhl_burst_hdr_set(&d->hdr, MHL_BURST_ID_EMSC_SUPPORT);
1742         d->num_entries = 1;
1743         d->burst_id[0] = cpu_to_be16(id);
1744 }
1745
1746 static void sii8620_send_features(struct sii8620 *ctx)
1747 {
1748         u8 buf[16];
1749
1750         sii8620_write(ctx, REG_MDT_XMIT_CTRL, BIT_MDT_XMIT_CTRL_EN
1751                 | BIT_MDT_XMIT_CTRL_FIXED_BURST_LEN);
1752         sii8620_mhl_burst_emsc_support_set((void *)buf,
1753                 MHL_BURST_ID_HID_PAYLOAD);
1754         sii8620_write_buf(ctx, REG_MDT_XMIT_WRITE_PORT, buf, ARRAY_SIZE(buf));
1755 }
1756
1757 static bool sii8620_rcp_consume(struct sii8620 *ctx, u8 scancode)
1758 {
1759         bool pressed = !(scancode & MHL_RCP_KEY_RELEASED_MASK);
1760
1761         scancode &= MHL_RCP_KEY_ID_MASK;
1762
1763         if (!IS_ENABLED(CONFIG_RC_CORE) || !ctx->rc_dev)
1764                 return false;
1765
1766         if (pressed)
1767                 rc_keydown(ctx->rc_dev, RC_PROTO_CEC, scancode, 0);
1768         else
1769                 rc_keyup(ctx->rc_dev);
1770
1771         return true;
1772 }
1773
1774 static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
1775 {
1776         u8 ints[MHL_INT_SIZE];
1777
1778         sii8620_read_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
1779         sii8620_write_buf(ctx, REG_MHL_INT_0, ints, MHL_INT_SIZE);
1780
1781         if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_DCAP_CHG) {
1782                 switch (ctx->mode) {
1783                 case CM_MHL3:
1784                         sii8620_mt_read_xdevcap_reg(ctx, MHL_XDC_ECBUS_SPEEDS);
1785                         sii8620_mt_set_cont(ctx, sii8620_got_ecbus_speed);
1786                         break;
1787                 case CM_ECBUS_S:
1788                         sii8620_mt_read_devcap(ctx, true);
1789                         break;
1790                 default:
1791                         break;
1792                 }
1793         }
1794         if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_REQ)
1795                 sii8620_send_features(ctx);
1796         if (ints[MHL_INT_RCHANGE] & MHL_INT_RC_FEAT_COMPLETE) {
1797                 ctx->feature_complete = true;
1798                 if (ctx->edid)
1799                         sii8620_enable_hpd(ctx);
1800         }
1801 }
1802
1803 static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
1804 {
1805         struct device *dev = ctx->dev;
1806
1807         if (list_empty(&ctx->mt_queue)) {
1808                 dev_err(dev, "unexpected MSC MT response\n");
1809                 return NULL;
1810         }
1811
1812         return list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
1813 }
1814
1815 static void sii8620_msc_mt_done(struct sii8620 *ctx)
1816 {
1817         struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
1818
1819         if (!msg)
1820                 return;
1821
1822         msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0);
1823         ctx->mt_state = MT_STATE_DONE;
1824 }
1825
1826 static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx)
1827 {
1828         struct sii8620_mt_msg *msg;
1829         u8 buf[2];
1830
1831         sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2);
1832
1833         switch (buf[0]) {
1834         case MHL_MSC_MSG_RAPK:
1835                 msg = sii8620_msc_msg_first(ctx);
1836                 if (!msg)
1837                         return;
1838                 msg->ret = buf[1];
1839                 ctx->mt_state = MT_STATE_DONE;
1840                 break;
1841         case MHL_MSC_MSG_RCP:
1842                 if (!sii8620_rcp_consume(ctx, buf[1]))
1843                         sii8620_mt_rcpe(ctx,
1844                                         MHL_RCPE_STATUS_INEFFECTIVE_KEY_CODE);
1845                 sii8620_mt_rcpk(ctx, buf[1]);
1846                 break;
1847         default:
1848                 dev_err(ctx->dev, "%s message type %d,%d not supported",
1849                         __func__, buf[0], buf[1]);
1850         }
1851 }
1852
1853 static void sii8620_irq_msc(struct sii8620 *ctx)
1854 {
1855         u8 stat = sii8620_readb(ctx, REG_CBUS_INT_0);
1856
1857         if (stat & ~BIT_CBUS_HPD_CHG)
1858                 sii8620_write(ctx, REG_CBUS_INT_0, stat & ~BIT_CBUS_HPD_CHG);
1859
1860         if (stat & BIT_CBUS_HPD_CHG) {
1861                 u8 cbus_stat = sii8620_readb(ctx, REG_CBUS_STATUS);
1862
1863                 if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) {
1864                         sii8620_write(ctx, REG_CBUS_INT_0, BIT_CBUS_HPD_CHG);
1865                 } else {
1866                         stat ^= BIT_CBUS_STATUS_CBUS_HPD;
1867                         cbus_stat ^= BIT_CBUS_STATUS_CBUS_HPD;
1868                 }
1869                 ctx->cbus_status = cbus_stat;
1870         }
1871
1872         if (stat & BIT_CBUS_MSC_MR_WRITE_STAT)
1873                 sii8620_msc_mr_write_stat(ctx);
1874
1875         if (stat & BIT_CBUS_HPD_CHG) {
1876                 if (ctx->cbus_status & BIT_CBUS_STATUS_CBUS_HPD) {
1877                         ctx->sink_detected = true;
1878                         sii8620_identify_sink(ctx);
1879                 } else {
1880                         sii8620_hpd_unplugged(ctx);
1881                 }
1882         }
1883
1884         if (stat & BIT_CBUS_MSC_MR_SET_INT)
1885                 sii8620_msc_mr_set_int(ctx);
1886
1887         if (stat & BIT_CBUS_MSC_MT_DONE)
1888                 sii8620_msc_mt_done(ctx);
1889
1890         if (stat & BIT_CBUS_MSC_MR_MSC_MSG)
1891                 sii8620_msc_mr_msc_msg(ctx);
1892 }
1893
1894 static void sii8620_irq_coc(struct sii8620 *ctx)
1895 {
1896         u8 stat = sii8620_readb(ctx, REG_COC_INTR);
1897
1898         if (stat & BIT_COC_CALIBRATION_DONE) {
1899                 u8 cstat = sii8620_readb(ctx, REG_COC_STAT_0);
1900
1901                 cstat &= BIT_COC_STAT_0_PLL_LOCKED | MSK_COC_STAT_0_FSM_STATE;
1902                 if (cstat == (BIT_COC_STAT_0_PLL_LOCKED | 0x02)) {
1903                         sii8620_write_seq_static(ctx,
1904                                 REG_COC_CTLB, 0,
1905                                 REG_TRXINTMH, BIT_TDM_INTR_SYNC_DATA
1906                                               | BIT_TDM_INTR_SYNC_WAIT
1907                         );
1908                 }
1909         }
1910
1911         sii8620_write(ctx, REG_COC_INTR, stat);
1912 }
1913
1914 static void sii8620_irq_merr(struct sii8620 *ctx)
1915 {
1916         u8 stat = sii8620_readb(ctx, REG_CBUS_INT_1);
1917
1918         sii8620_write(ctx, REG_CBUS_INT_1, stat);
1919 }
1920
1921 static void sii8620_irq_edid(struct sii8620 *ctx)
1922 {
1923         u8 stat = sii8620_readb(ctx, REG_INTR9);
1924
1925         sii8620_write(ctx, REG_INTR9, stat);
1926
1927         if (stat & BIT_INTR9_DEVCAP_DONE)
1928                 ctx->mt_state = MT_STATE_DONE;
1929 }
1930
1931 static void sii8620_irq_scdt(struct sii8620 *ctx)
1932 {
1933         u8 stat = sii8620_readb(ctx, REG_INTR5);
1934
1935         if (stat & BIT_INTR_SCDT_CHANGE) {
1936                 u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
1937
1938                 if (cstat & BIT_TMDS_CSTAT_P3_SCDT)
1939                         sii8620_start_video(ctx);
1940         }
1941
1942         sii8620_write(ctx, REG_INTR5, stat);
1943 }
1944
1945 static void sii8620_got_xdevcap(struct sii8620 *ctx, int ret)
1946 {
1947         if (ret < 0)
1948                 return;
1949
1950         sii8620_mt_read_devcap(ctx, false);
1951 }
1952
1953 static void sii8620_irq_tdm(struct sii8620 *ctx)
1954 {
1955         u8 stat = sii8620_readb(ctx, REG_TRXINTH);
1956         u8 tdm = sii8620_readb(ctx, REG_TRXSTA2);
1957
1958         if ((tdm & MSK_TDM_SYNCHRONIZED) == VAL_TDM_SYNCHRONIZED) {
1959                 ctx->mode = CM_ECBUS_S;
1960                 ctx->burst.rx_ack = 0;
1961                 ctx->burst.r_size = SII8620_BURST_BUF_LEN;
1962                 sii8620_burst_tx_rbuf_info(ctx, SII8620_BURST_BUF_LEN);
1963                 sii8620_mt_read_devcap(ctx, true);
1964                 sii8620_mt_set_cont(ctx, sii8620_got_xdevcap);
1965         } else {
1966                 sii8620_write_seq_static(ctx,
1967                         REG_MHL_PLL_CTL2, 0,
1968                         REG_MHL_PLL_CTL2, BIT_MHL_PLL_CTL2_CLKDETECT_EN
1969                 );
1970         }
1971
1972         sii8620_write(ctx, REG_TRXINTH, stat);
1973 }
1974
1975 static void sii8620_irq_block(struct sii8620 *ctx)
1976 {
1977         u8 stat = sii8620_readb(ctx, REG_EMSCINTR);
1978
1979         if (stat & BIT_EMSCINTR_SPI_DVLD) {
1980                 u8 bstat = sii8620_readb(ctx, REG_SPIBURSTSTAT);
1981
1982                 if (bstat & BIT_SPIBURSTSTAT_EMSC_NORMAL_MODE)
1983                         sii8620_burst_receive(ctx);
1984         }
1985
1986         sii8620_write(ctx, REG_EMSCINTR, stat);
1987 }
1988
1989 static void sii8620_irq_ddc(struct sii8620 *ctx)
1990 {
1991         u8 stat = sii8620_readb(ctx, REG_INTR3);
1992
1993         if (stat & BIT_DDC_CMD_DONE) {
1994                 sii8620_write(ctx, REG_INTR3_MASK, 0);
1995                 if (sii8620_is_mhl3(ctx) && !ctx->feature_complete)
1996                         sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE),
1997                                            MHL_INT_RC_FEAT_REQ);
1998                 else
1999                         sii8620_enable_hpd(ctx);
2000         }
2001         sii8620_write(ctx, REG_INTR3, stat);
2002 }
2003
2004 /* endian agnostic, non-volatile version of test_bit */
2005 static bool sii8620_test_bit(unsigned int nr, const u8 *addr)
2006 {
2007         return 1 & (addr[nr / BITS_PER_BYTE] >> (nr % BITS_PER_BYTE));
2008 }
2009
2010 static irqreturn_t sii8620_irq_thread(int irq, void *data)
2011 {
2012         static const struct {
2013                 int bit;
2014                 void (*handler)(struct sii8620 *ctx);
2015         } irq_vec[] = {
2016                 { BIT_FAST_INTR_STAT_DISC, sii8620_irq_disc },
2017                 { BIT_FAST_INTR_STAT_G2WB, sii8620_irq_g2wb },
2018                 { BIT_FAST_INTR_STAT_COC, sii8620_irq_coc },
2019                 { BIT_FAST_INTR_STAT_TDM, sii8620_irq_tdm },
2020                 { BIT_FAST_INTR_STAT_MSC, sii8620_irq_msc },
2021                 { BIT_FAST_INTR_STAT_MERR, sii8620_irq_merr },
2022                 { BIT_FAST_INTR_STAT_BLOCK, sii8620_irq_block },
2023                 { BIT_FAST_INTR_STAT_EDID, sii8620_irq_edid },
2024                 { BIT_FAST_INTR_STAT_DDC, sii8620_irq_ddc },
2025                 { BIT_FAST_INTR_STAT_SCDT, sii8620_irq_scdt },
2026         };
2027         struct sii8620 *ctx = data;
2028         u8 stats[LEN_FAST_INTR_STAT];
2029         int i, ret;
2030
2031         mutex_lock(&ctx->lock);
2032
2033         sii8620_read_buf(ctx, REG_FAST_INTR_STAT, stats, ARRAY_SIZE(stats));
2034         for (i = 0; i < ARRAY_SIZE(irq_vec); ++i)
2035                 if (sii8620_test_bit(irq_vec[i].bit, stats))
2036                         irq_vec[i].handler(ctx);
2037
2038         sii8620_burst_rx_all(ctx);
2039         sii8620_mt_work(ctx);
2040         sii8620_burst_send(ctx);
2041
2042         ret = sii8620_clear_error(ctx);
2043         if (ret) {
2044                 dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret);
2045                 sii8620_mhl_disconnected(ctx);
2046         }
2047         mutex_unlock(&ctx->lock);
2048
2049         return IRQ_HANDLED;
2050 }
2051
2052 static void sii8620_cable_in(struct sii8620 *ctx)
2053 {
2054         struct device *dev = ctx->dev;
2055         u8 ver[5];
2056         int ret;
2057
2058         ret = sii8620_hw_on(ctx);
2059         if (ret) {
2060                 dev_err(dev, "Error powering on, %d.\n", ret);
2061                 return;
2062         }
2063
2064         sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
2065         ret = sii8620_clear_error(ctx);
2066         if (ret) {
2067                 dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
2068                 return;
2069         }
2070
2071         dev_info(dev, "ChipID %02x%02x:%02x%02x rev %02x.\n", ver[1], ver[0],
2072                  ver[3], ver[2], ver[4]);
2073
2074         sii8620_write(ctx, REG_DPD,
2075                       BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN);
2076
2077         sii8620_xtal_set_rate(ctx);
2078         sii8620_disconnect(ctx);
2079
2080         sii8620_write_seq_static(ctx,
2081                 REG_MHL_CBUS_CTL0, VAL_MHL_CBUS_CTL0_CBUS_DRV_SEL_STRONG
2082                         | VAL_MHL_CBUS_CTL0_CBUS_RGND_VBIAS_734,
2083                 REG_MHL_CBUS_CTL1, VAL_MHL_CBUS_CTL1_1115_OHM,
2084                 REG_DPD, BIT_DPD_PWRON_PLL | BIT_DPD_PDNTX12 | BIT_DPD_OSC_EN,
2085         );
2086
2087         ret = sii8620_clear_error(ctx);
2088         if (ret) {
2089                 dev_err(dev, "Error accessing I2C bus, %d.\n", ret);
2090                 return;
2091         }
2092
2093         enable_irq(to_i2c_client(ctx->dev)->irq);
2094 }
2095
2096 static void sii8620_init_rcp_input_dev(struct sii8620 *ctx)
2097 {
2098         struct rc_dev *rc_dev;
2099         int ret;
2100
2101         if (!IS_ENABLED(CONFIG_RC_CORE))
2102                 return;
2103
2104         rc_dev = rc_allocate_device(RC_DRIVER_SCANCODE);
2105         if (!rc_dev) {
2106                 dev_err(ctx->dev, "Failed to allocate RC device\n");
2107                 ctx->error = -ENOMEM;
2108                 return;
2109         }
2110
2111         rc_dev->input_phys = "sii8620/input0";
2112         rc_dev->input_id.bustype = BUS_VIRTUAL;
2113         rc_dev->map_name = RC_MAP_CEC;
2114         rc_dev->allowed_protocols = RC_PROTO_BIT_CEC;
2115         rc_dev->driver_name = "sii8620";
2116         rc_dev->device_name = "sii8620";
2117
2118         ret = rc_register_device(rc_dev);
2119
2120         if (ret) {
2121                 dev_err(ctx->dev, "Failed to register RC device\n");
2122                 ctx->error = ret;
2123                 rc_free_device(ctx->rc_dev);
2124                 return;
2125         }
2126         ctx->rc_dev = rc_dev;
2127 }
2128
2129 static void sii8620_cable_out(struct sii8620 *ctx)
2130 {
2131         disable_irq(to_i2c_client(ctx->dev)->irq);
2132         sii8620_hw_off(ctx);
2133 }
2134
2135 static void sii8620_extcon_work(struct work_struct *work)
2136 {
2137         struct sii8620 *ctx =
2138                 container_of(work, struct sii8620, extcon_wq);
2139         int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL);
2140
2141         if (state == ctx->cable_state)
2142                 return;
2143
2144         ctx->cable_state = state;
2145
2146         if (state > 0)
2147                 sii8620_cable_in(ctx);
2148         else
2149                 sii8620_cable_out(ctx);
2150 }
2151
2152 static int sii8620_extcon_notifier(struct notifier_block *self,
2153                         unsigned long event, void *ptr)
2154 {
2155         struct sii8620 *ctx =
2156                 container_of(self, struct sii8620, extcon_nb);
2157
2158         schedule_work(&ctx->extcon_wq);
2159
2160         return NOTIFY_DONE;
2161 }
2162
2163 static int sii8620_extcon_init(struct sii8620 *ctx)
2164 {
2165         struct extcon_dev *edev;
2166         struct device_node *musb, *muic;
2167         int ret;
2168
2169         /* get micro-USB connector node */
2170         musb = of_graph_get_remote_node(ctx->dev->of_node, 1, -1);
2171         /* next get micro-USB Interface Controller node */
2172         muic = of_get_next_parent(musb);
2173
2174         if (!muic) {
2175                 dev_info(ctx->dev, "no extcon found, switching to 'always on' mode\n");
2176                 return 0;
2177         }
2178
2179         edev = extcon_find_edev_by_node(muic);
2180         of_node_put(muic);
2181         if (IS_ERR(edev)) {
2182                 if (PTR_ERR(edev) == -EPROBE_DEFER)
2183                         return -EPROBE_DEFER;
2184                 dev_err(ctx->dev, "Invalid or missing extcon\n");
2185                 return PTR_ERR(edev);
2186         }
2187
2188         ctx->extcon = edev;
2189         ctx->extcon_nb.notifier_call = sii8620_extcon_notifier;
2190         INIT_WORK(&ctx->extcon_wq, sii8620_extcon_work);
2191         ret = extcon_register_notifier(edev, EXTCON_DISP_MHL, &ctx->extcon_nb);
2192         if (ret) {
2193                 dev_err(ctx->dev, "failed to register notifier for MHL\n");
2194                 return ret;
2195         }
2196
2197         return 0;
2198 }
2199
2200 static inline struct sii8620 *bridge_to_sii8620(struct drm_bridge *bridge)
2201 {
2202         return container_of(bridge, struct sii8620, bridge);
2203 }
2204
2205 static int sii8620_attach(struct drm_bridge *bridge,
2206                           enum drm_bridge_attach_flags flags)
2207 {
2208         struct sii8620 *ctx = bridge_to_sii8620(bridge);
2209
2210         sii8620_init_rcp_input_dev(ctx);
2211
2212         return sii8620_clear_error(ctx);
2213 }
2214
2215 static void sii8620_detach(struct drm_bridge *bridge)
2216 {
2217         struct sii8620 *ctx = bridge_to_sii8620(bridge);
2218
2219         if (!IS_ENABLED(CONFIG_RC_CORE))
2220                 return;
2221
2222         rc_unregister_device(ctx->rc_dev);
2223 }
2224
2225 static int sii8620_is_packing_required(struct sii8620 *ctx,
2226                                        const struct drm_display_mode *mode)
2227 {
2228         int max_pclk, max_pclk_pp_mode;
2229
2230         if (sii8620_is_mhl3(ctx)) {
2231                 max_pclk = MHL3_MAX_PCLK;
2232                 max_pclk_pp_mode = MHL3_MAX_PCLK_PP_MODE;
2233         } else {
2234                 max_pclk = MHL1_MAX_PCLK;
2235                 max_pclk_pp_mode = MHL1_MAX_PCLK_PP_MODE;
2236         }
2237
2238         if (mode->clock < max_pclk)
2239                 return 0;
2240         else if (mode->clock < max_pclk_pp_mode)
2241                 return 1;
2242         else
2243                 return -1;
2244 }
2245
2246 static enum drm_mode_status sii8620_mode_valid(struct drm_bridge *bridge,
2247                                          const struct drm_display_mode *mode)
2248 {
2249         struct sii8620 *ctx = bridge_to_sii8620(bridge);
2250         int pack_required = sii8620_is_packing_required(ctx, mode);
2251         bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
2252                         MHL_DCAP_VID_LINK_PPIXEL;
2253
2254         switch (pack_required) {
2255         case 0:
2256                 return MODE_OK;
2257         case 1:
2258                 return (can_pack) ? MODE_OK : MODE_CLOCK_HIGH;
2259         default:
2260                 return MODE_CLOCK_HIGH;
2261         }
2262 }
2263
2264 static bool sii8620_mode_fixup(struct drm_bridge *bridge,
2265                                const struct drm_display_mode *mode,
2266                                struct drm_display_mode *adjusted_mode)
2267 {
2268         struct sii8620 *ctx = bridge_to_sii8620(bridge);
2269
2270         mutex_lock(&ctx->lock);
2271
2272         ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2273
2274         mutex_unlock(&ctx->lock);
2275
2276         return true;
2277 }
2278
2279 static const struct drm_bridge_funcs sii8620_bridge_funcs = {
2280         .attach = sii8620_attach,
2281         .detach = sii8620_detach,
2282         .mode_fixup = sii8620_mode_fixup,
2283         .mode_valid = sii8620_mode_valid,
2284 };
2285
2286 static int sii8620_probe(struct i2c_client *client,
2287                          const struct i2c_device_id *id)
2288 {
2289         struct device *dev = &client->dev;
2290         struct sii8620 *ctx;
2291         int ret;
2292
2293         ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
2294         if (!ctx)
2295                 return -ENOMEM;
2296
2297         ctx->dev = dev;
2298         mutex_init(&ctx->lock);
2299         INIT_LIST_HEAD(&ctx->mt_queue);
2300
2301         ctx->clk_xtal = devm_clk_get(dev, "xtal");
2302         if (IS_ERR(ctx->clk_xtal)) {
2303                 dev_err(dev, "failed to get xtal clock from DT\n");
2304                 return PTR_ERR(ctx->clk_xtal);
2305         }
2306
2307         if (!client->irq) {
2308                 dev_err(dev, "no irq provided\n");
2309                 return -EINVAL;
2310         }
2311         irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
2312         ret = devm_request_threaded_irq(dev, client->irq, NULL,
2313                                         sii8620_irq_thread,
2314                                         IRQF_TRIGGER_HIGH | IRQF_ONESHOT,
2315                                         "sii8620", ctx);
2316         if (ret < 0) {
2317                 dev_err(dev, "failed to install IRQ handler\n");
2318                 return ret;
2319         }
2320
2321         ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
2322         if (IS_ERR(ctx->gpio_reset)) {
2323                 dev_err(dev, "failed to get reset gpio from DT\n");
2324                 return PTR_ERR(ctx->gpio_reset);
2325         }
2326
2327         ctx->supplies[0].supply = "cvcc10";
2328         ctx->supplies[1].supply = "iovcc18";
2329         ret = devm_regulator_bulk_get(dev, 2, ctx->supplies);
2330         if (ret)
2331                 return ret;
2332
2333         ret = sii8620_extcon_init(ctx);
2334         if (ret < 0) {
2335                 dev_err(ctx->dev, "failed to initialize EXTCON\n");
2336                 return ret;
2337         }
2338
2339         i2c_set_clientdata(client, ctx);
2340
2341         ctx->bridge.funcs = &sii8620_bridge_funcs;
2342         ctx->bridge.of_node = dev->of_node;
2343         drm_bridge_add(&ctx->bridge);
2344
2345         if (!ctx->extcon)
2346                 sii8620_cable_in(ctx);
2347
2348         return 0;
2349 }
2350
2351 static int sii8620_remove(struct i2c_client *client)
2352 {
2353         struct sii8620 *ctx = i2c_get_clientdata(client);
2354
2355         if (ctx->extcon) {
2356                 extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL,
2357                                            &ctx->extcon_nb);
2358                 flush_work(&ctx->extcon_wq);
2359                 if (ctx->cable_state > 0)
2360                         sii8620_cable_out(ctx);
2361         } else {
2362                 sii8620_cable_out(ctx);
2363         }
2364         drm_bridge_remove(&ctx->bridge);
2365
2366         return 0;
2367 }
2368
2369 static const struct of_device_id sii8620_dt_match[] = {
2370         { .compatible = "sil,sii8620" },
2371         { },
2372 };
2373 MODULE_DEVICE_TABLE(of, sii8620_dt_match);
2374
2375 static const struct i2c_device_id sii8620_id[] = {
2376         { "sii8620", 0 },
2377         { },
2378 };
2379
2380 MODULE_DEVICE_TABLE(i2c, sii8620_id);
2381 static struct i2c_driver sii8620_driver = {
2382         .driver = {
2383                 .name   = "sii8620",
2384                 .of_match_table = of_match_ptr(sii8620_dt_match),
2385         },
2386         .probe          = sii8620_probe,
2387         .remove         = sii8620_remove,
2388         .id_table = sii8620_id,
2389 };
2390
2391 module_i2c_driver(sii8620_driver);
2392 MODULE_LICENSE("GPL v2");