Lines Matching refs:ctx

106 typedef void (*sii8620_mt_msg_cb)(struct sii8620 *ctx,
109 typedef void (*sii8620_cb)(struct sii8620 *ctx, int ret);
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);
137 static int sii8620_clear_error(struct sii8620 *ctx)
139 int ret = ctx->error;
141 ctx->error = 0;
145 static void sii8620_read_buf(struct sii8620 *ctx, u16 addr, u8 *buf, int len)
147 struct device *dev = ctx->dev;
166 if (ctx->error)
175 ctx->error = ret < 0 ? ret : -EIO;
179 static u8 sii8620_readb(struct sii8620 *ctx, u16 addr)
183 sii8620_read_buf(ctx, addr, &ret, 1);
187 static void sii8620_write_buf(struct sii8620 *ctx, u16 addr, const u8 *buf,
190 struct device *dev = ctx->dev;
200 if (ctx->error)
206 ctx->error = -ENOMEM;
223 ctx->error = ret ?: -EIO;
230 #define sii8620_write(ctx, addr, arr...) \
233 sii8620_write_buf(ctx, addr, d, ARRAY_SIZE(d)); \
236 static void __sii8620_write_seq(struct sii8620 *ctx, const u16 *seq, int len)
241 sii8620_write(ctx, seq[i], seq[i + 1]);
244 #define sii8620_write_seq(ctx, seq...) \
247 __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
250 #define sii8620_write_seq_static(ctx, seq...) \
253 __sii8620_write_seq(ctx, d, ARRAY_SIZE(d)); \
256 static void sii8620_setbits(struct sii8620 *ctx, u16 addr, u8 mask, u8 val)
258 val = (val & mask) | (sii8620_readb(ctx, addr) & ~mask);
259 sii8620_write(ctx, addr, val);
262 static inline bool sii8620_is_mhl3(struct sii8620 *ctx)
264 return ctx->mode >= CM_MHL3;
267 static void sii8620_mt_cleanup(struct sii8620 *ctx)
271 list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) {
275 ctx->mt_state = MT_STATE_READY;
278 static void sii8620_mt_work(struct sii8620 *ctx)
282 if (ctx->error)
284 if (ctx->mt_state == MT_STATE_BUSY || list_empty(&ctx->mt_queue))
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,
293 msg->recv(ctx, msg);
295 msg->continuation(ctx, msg->ret);
299 if (ctx->mt_state != MT_STATE_READY || list_empty(&ctx->mt_queue))
302 ctx->mt_state = MT_STATE_BUSY;
303 msg = list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
305 msg->send(ctx, msg);
308 static void sii8620_enable_gen2_write_burst(struct sii8620 *ctx)
312 if (ctx->gen2_write_burst)
315 if (ctx->mode >= CM_MHL1)
318 sii8620_write_seq(ctx,
322 ctx->gen2_write_burst = 1;
325 static void sii8620_disable_gen2_write_burst(struct sii8620 *ctx)
327 if (!ctx->gen2_write_burst)
330 sii8620_write_seq_static(ctx,
334 ctx->gen2_write_burst = 0;
337 static void sii8620_start_gen2_write_burst(struct sii8620 *ctx)
339 sii8620_write_seq_static(ctx,
348 sii8620_enable_gen2_write_burst(ctx);
351 static void sii8620_mt_msc_cmd_send(struct sii8620 *ctx,
357 sii8620_enable_gen2_write_burst(ctx);
359 sii8620_disable_gen2_write_burst(ctx);
364 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2);
365 sii8620_write(ctx, REG_MSC_COMMAND_START,
369 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3);
370 sii8620_write(ctx, REG_MSC_COMMAND_START,
375 sii8620_write(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg[1]);
376 sii8620_write(ctx, REG_MSC_COMMAND_START,
380 dev_err(ctx->dev, "%s: command %#x not supported\n", __func__,
385 static struct sii8620_mt_msg *sii8620_mt_msg_new(struct sii8620 *ctx)
390 ctx->error = -ENOMEM;
392 list_add_tail(&msg->node, &ctx->mt_queue);
397 static void sii8620_mt_set_cont(struct sii8620 *ctx, sii8620_cb cont)
401 if (ctx->error)
404 if (list_empty(&ctx->mt_queue)) {
405 ctx->error = -EINVAL;
408 msg = list_last_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
412 static void sii8620_mt_msc_cmd(struct sii8620 *ctx, u8 cmd, u8 arg1, u8 arg2)
414 struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
425 static void sii8620_mt_write_stat(struct sii8620 *ctx, u8 reg, u8 val)
427 sii8620_mt_msc_cmd(ctx, MHL_WRITE_STAT, reg, val);
430 static inline void sii8620_mt_set_int(struct sii8620 *ctx, u8 irq, u8 mask)
432 sii8620_mt_msc_cmd(ctx, MHL_SET_INT, irq, mask);
435 static void sii8620_mt_msc_msg(struct sii8620 *ctx, u8 cmd, u8 data)
437 sii8620_mt_msc_cmd(ctx, MHL_MSC_MSG, cmd, data);
440 static void sii8620_mt_rap(struct sii8620 *ctx, u8 code)
442 sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RAP, code);
445 static void sii8620_mt_rcpk(struct sii8620 *ctx, u8 code)
447 sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPK, code);
450 static void sii8620_mt_rcpe(struct sii8620 *ctx, u8 code)
452 sii8620_mt_msc_msg(ctx, MHL_MSC_MSG_RCPE, code);
455 static void sii8620_mt_read_devcap_send(struct sii8620 *ctx,
465 sii8620_write_seq(ctx,
481 static void sii8620_identify_sink(struct sii8620 *ctx)
490 struct device *dev = ctx->dev;
492 if (!ctx->sink_detected || !ctx->devcap_read)
495 sii8620_fetch_edid(ctx);
496 if (!ctx->edid) {
497 dev_err(ctx->dev, "Cannot fetch EDID\n");
498 sii8620_mhl_disconnected(ctx);
501 sii8620_set_upstream_edid(ctx);
503 if (drm_detect_hdmi_monitor(ctx->edid))
504 ctx->sink_type = SINK_HDMI;
506 ctx->sink_type = SINK_DVI;
508 drm_edid_get_monitor_name(ctx->edid, sink_name, ARRAY_SIZE(sink_name));
511 sink_str[ctx->sink_type], sink_name);
514 static void sii8620_mr_devcap(struct sii8620 *ctx)
517 struct device *dev = ctx->dev;
519 sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, dcap, MHL_DCAP_SIZE);
520 if (ctx->error < 0)
528 sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
529 ctx->devcap_read = true;
530 sii8620_identify_sink(ctx);
533 static void sii8620_mr_xdevcap(struct sii8620 *ctx)
535 sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap,
539 static void sii8620_mt_read_devcap_recv(struct sii8620 *ctx,
549 sii8620_write_seq(ctx,
557 sii8620_mr_xdevcap(ctx);
559 sii8620_mr_devcap(ctx);
562 static void sii8620_mt_read_devcap(struct sii8620 *ctx, bool xdevcap)
564 struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
574 static void sii8620_mt_read_devcap_reg_recv(struct sii8620 *ctx,
580 ctx->xdevcap[reg] = msg->ret;
582 ctx->devcap[reg] = msg->ret;
585 static void sii8620_mt_read_devcap_reg(struct sii8620 *ctx, u8 reg)
587 struct sii8620_mt_msg *msg = sii8620_mt_msg_new(ctx);
598 static inline void sii8620_mt_read_xdevcap_reg(struct sii8620 *ctx, u8 reg)
600 sii8620_mt_read_devcap_reg(ctx, reg | 0x80);
603 static void *sii8620_burst_get_tx_buf(struct sii8620 *ctx, int len)
605 u8 *buf = &ctx->burst.tx_buf[ctx->burst.tx_count];
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;
614 ctx->burst.tx_count += size;
620 static u8 *sii8620_burst_get_rx_buf(struct sii8620 *ctx, int len)
622 u8 *buf = &ctx->burst.rx_buf[ctx->burst.rx_count];
625 if (ctx->burst.rx_count + size >= ARRAY_SIZE(ctx->burst.rx_buf)) {
626 dev_err(ctx->dev, "RX-BLK buffer exhausted\n");
627 ctx->error = -EINVAL;
631 ctx->burst.rx_count += size;
637 static void sii8620_burst_send(struct sii8620 *ctx)
639 int tx_left = ctx->burst.tx_count;
640 u8 *d = ctx->burst.tx_buf;
645 if (ctx->burst.r_count + len > ctx->burst.r_size)
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;
655 ctx->burst.tx_count = tx_left;
657 while (ctx->burst.rx_ack > 0) {
658 u8 b[2] = { min(ctx->burst.rx_ack, 255), 0 };
660 if (ctx->burst.r_count + 2 > ctx->burst.r_size)
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;
668 static void sii8620_burst_receive(struct sii8620 *ctx)
673 sii8620_read_buf(ctx, REG_EMSCRFIFOBCNTL, buf, 2);
678 sii8620_read_buf(ctx, REG_EMSC_RCV_READ_PORT, buf, 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;
689 d = sii8620_burst_get_rx_buf(ctx, len);
692 sii8620_read_buf(ctx, REG_EMSC_RCV_READ_PORT, d, len);
694 ctx->burst.rx_ack += len;
698 static void sii8620_burst_tx_rbuf_info(struct sii8620 *ctx, int size)
701 sii8620_burst_get_tx_buf(ctx, sizeof(*d));
727 static void sii8620_burst_tx_bits_per_pixel_fmt(struct sii8620 *ctx, u8 fmt)
732 d = sii8620_burst_get_tx_buf(ctx, size);
743 static void sii8620_burst_rx_all(struct sii8620 *ctx)
745 u8 *d = ctx->burst.rx_buf;
746 int count = ctx->burst.rx_count;
754 ctx->burst.r_size = get_unaligned_le16(&d[2]);
762 ctx->burst.rx_count = 0;
765 static void sii8620_fetch_edid(struct sii8620 *ctx)
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);
777 sii8620_write_seq(ctx,
786 u8 ddc_stat = sii8620_readb(ctx, REG_DDC_STATUS);
790 sii8620_write(ctx, REG_DDC_STATUS,
794 sii8620_write(ctx, REG_DDC_ADDR, 0x50 << 1);
798 ctx->error = -ENOMEM;
804 sii8620_readb(ctx, REG_DDC_STATUS);
805 sii8620_write_seq(ctx,
810 sii8620_write_seq(ctx,
821 cbus = sii8620_readb(ctx, REG_CBUS_STATUS);
828 if (sii8620_readb(ctx, REG_DDC_DOUT_CNT)
832 int3 = sii8620_readb(ctx, REG_INTR3);
835 ctx->error = -ETIMEDOUT;
836 dev_err(ctx->dev, "timeout during EDID read\n");
844 sii8620_read_buf(ctx, REG_DDC_DATA, edid + fetched, FETCH_SIZE);
855 ctx->error = -ENOMEM;
863 sii8620_write_seq(ctx,
869 kfree(ctx->edid);
870 ctx->edid = (struct edid *)edid;
873 static void sii8620_set_upstream_edid(struct sii8620 *ctx)
875 sii8620_setbits(ctx, REG_DPD, BIT_DPD_PDNRX12 | BIT_DPD_PDIDCK_N
878 sii8620_write_seq_static(ctx,
885 sii8620_setbits(ctx, REG_RX_HDMI_CLR_BUFFER,
888 sii8620_write_seq_static(ctx,
894 sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid,
895 (ctx->edid->extensions + 1) * EDID_LENGTH);
897 sii8620_write_seq_static(ctx,
906 static void sii8620_xtal_set_rate(struct sii8620 *ctx)
919 unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000;
927 dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n",
930 sii8620_write(ctx, REG_DIV_CTL_MAIN, rates[i].div);
931 sii8620_write(ctx, REG_HDCP2X_TP1, rates[i].tp1);
934 static int sii8620_hw_on(struct sii8620 *ctx)
938 ret = regulator_bulk_enable(ARRAY_SIZE(ctx->supplies), ctx->supplies);
943 ret = clk_prepare_enable(ctx->clk_xtal);
948 gpiod_set_value(ctx->gpio_reset, 0);
954 static int sii8620_hw_off(struct sii8620 *ctx)
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);
961 static void sii8620_cbus_reset(struct sii8620 *ctx)
963 sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST
966 sii8620_write(ctx, REG_PWD_SRST, BIT_PWD_SRST_CBUS_RST_SW_EN);
969 static void sii8620_set_auto_zone(struct sii8620 *ctx)
971 if (ctx->mode != CM_MHL1) {
972 sii8620_write_seq_static(ctx,
979 sii8620_write_seq_static(ctx,
987 static void sii8620_stop_video(struct sii8620 *ctx)
991 sii8620_write_seq_static(ctx,
998 switch (ctx->sink_type) {
1011 sii8620_write(ctx, REG_TPI_SC, val);
1014 static void sii8620_set_format(struct sii8620 *ctx)
1018 if (sii8620_is_mhl3(ctx)) {
1019 sii8620_setbits(ctx, REG_M3_P0CTRL,
1021 ctx->use_packed_pixel ? ~0 : 0);
1023 if (ctx->use_packed_pixel) {
1024 sii8620_write_seq_static(ctx,
1030 sii8620_write_seq_static(ctx,
1038 if (ctx->use_packed_pixel)
1043 sii8620_write_seq(ctx,
1096 static void sii8620_set_infoframes(struct sii8620 *ctx,
1106 if (ctx->use_packed_pixel)
1112 sii8620_write_buf(ctx, REG_TPI_AVI_CHSUM, buf + 3, ret - 3);
1114 if (!sii8620_is_mhl3(ctx) || !ctx->use_packed_pixel) {
1115 sii8620_write(ctx, REG_TPI_SC,
1117 sii8620_write(ctx, REG_PKT_FILTER_0,
1125 sii8620_write(ctx, REG_PKT_FILTER_0,
1134 sii8620_write(ctx, REG_TPI_INFO_FSEL, BIT_TPI_INFO_FSEL_EN
1139 sii8620_write_buf(ctx, REG_TPI_INFO_B0, buf, ret);
1142 static void sii8620_start_video(struct sii8620 *ctx)
1145 &ctx->bridge.encoder->crtc->state->adjusted_mode;
1147 if (!sii8620_is_mhl3(ctx))
1148 sii8620_stop_video(ctx);
1150 if (ctx->sink_type == SINK_DVI && !sii8620_is_mhl3(ctx)) {
1151 sii8620_write(ctx, REG_RX_HDMI_CTRL2,
1153 sii8620_write(ctx, REG_TPI_SC, 0);
1157 sii8620_write_seq_static(ctx,
1162 sii8620_set_format(ctx);
1164 if (!sii8620_is_mhl3(ctx)) {
1167 if (ctx->use_packed_pixel)
1172 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE), link_mode);
1173 sii8620_set_auto_zone(ctx);
1189 int clk = mode->clock * (ctx->use_packed_pixel ? 2 : 3);
1199 sii8620_burst_tx_bits_per_pixel_fmt(ctx, ctx->use_packed_pixel);
1200 sii8620_burst_send(ctx);
1201 sii8620_write_seq(ctx,
1204 sii8620_setbits(ctx, REG_M3_P0CTRL,
1207 sii8620_setbits(ctx, REG_M3_POSTM, MSK_M3_POSTM_RRP_DECODE,
1209 sii8620_write_seq_static(ctx,
1214 sii8620_mt_write_stat(ctx, MHL_XDS_REG(AVLINK_MODE_CONTROL),
1218 sii8620_set_infoframes(ctx, mode);
1221 static void sii8620_disable_hpd(struct sii8620 *ctx)
1223 sii8620_setbits(ctx, REG_EDID_CTRL, BIT_EDID_CTRL_EDID_PRIME_VALID, 0);
1224 sii8620_write_seq_static(ctx,
1230 static void sii8620_enable_hpd(struct sii8620 *ctx)
1232 sii8620_setbits(ctx, REG_TMDS_CSTAT_P3,
1235 sii8620_write_seq_static(ctx,
1241 static void sii8620_mhl_discover(struct sii8620 *ctx)
1243 sii8620_write_seq_static(ctx,
1282 static void sii8620_peer_specific_init(struct sii8620 *ctx)
1284 if (sii8620_is_mhl3(ctx))
1285 sii8620_write_seq_static(ctx,
1291 sii8620_write_seq_static(ctx,
1305 static void sii8620_set_dev_cap(struct sii8620 *ctx)
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));
1338 static void sii8620_mhl_init(struct sii8620 *ctx)
1340 sii8620_write_seq_static(ctx,
1346 sii8620_peer_specific_init(ctx);
1348 sii8620_disable_hpd(ctx);
1350 sii8620_write_seq_static(ctx,
1361 sii8620_setbits(ctx, REG_LM_DDC, BIT_LM_DDC_SW_TPI_EN_DISABLED, 0);
1362 sii8620_write_seq_static(ctx,
1367 sii8620_set_dev_cap(ctx);
1368 sii8620_write_seq_static(ctx,
1376 sii8620_start_gen2_write_burst(ctx);
1377 sii8620_write_seq_static(ctx,
1392 sii8620_disable_gen2_write_burst(ctx);
1394 sii8620_mt_write_stat(ctx, MHL_DST_REG(VERSION), SII8620_MHL_VERSION);
1395 sii8620_mt_write_stat(ctx, MHL_DST_REG(CONNECTED_RDY),
1398 sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE), MHL_INT_RC_DCAP_CHG);
1401 static void sii8620_emsc_enable(struct sii8620 *ctx)
1405 sii8620_setbits(ctx, REG_GENCTL, BIT_GENCTL_EMSC_EN
1408 sii8620_setbits(ctx, REG_GENCTL, BIT_GENCTL_CLR_EMSC_RFIFO
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);
1416 static int sii8620_wait_for_fsm_state(struct sii8620 *ctx, u8 state)
1421 u8 s = sii8620_readb(ctx, REG_COC_STAT_0);
1432 static void sii8620_set_mode(struct sii8620 *ctx, enum sii8620_mode mode)
1436 if (ctx->mode == mode)
1441 sii8620_write_seq_static(ctx,
1448 ctx->mode = mode;
1451 sii8620_write(ctx, REG_M3_CTRL, VAL_M3_CTRL_MHL3_VALUE);
1452 ctx->mode = mode;
1455 sii8620_emsc_enable(ctx);
1456 sii8620_write_seq_static(ctx,
1476 ret = sii8620_wait_for_fsm_state(ctx, 0x03);
1477 sii8620_write_seq_static(ctx,
1482 sii8620_write(ctx, REG_CBUS3_CNVT, 0x85);
1484 sii8620_disconnect(ctx);
1487 ctx->mode = mode;
1490 dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode);
1494 sii8620_set_auto_zone(ctx);
1499 sii8620_write_seq_static(ctx,
1510 static void sii8620_hpd_unplugged(struct sii8620 *ctx)
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;
1520 static void sii8620_disconnect(struct sii8620 *ctx)
1522 sii8620_disable_gen2_write_burst(ctx);
1523 sii8620_stop_video(ctx);
1525 sii8620_cbus_reset(ctx);
1526 sii8620_set_mode(ctx, CM_DISCONNECTED);
1527 sii8620_write_seq_static(ctx,
1547 sii8620_hpd_unplugged(ctx);
1548 sii8620_write_seq_static(ctx,
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);
1600 static void sii8620_mhl_disconnected(struct sii8620 *ctx)
1602 sii8620_write_seq_static(ctx,
1607 sii8620_disconnect(ctx);
1610 static void sii8620_irq_disc(struct sii8620 *ctx)
1612 u8 stat = sii8620_readb(ctx, REG_CBUS_DISC_INTR0);
1615 sii8620_mhl_disconnected(ctx);
1618 u8 stat2 = sii8620_readb(ctx, REG_DISC_STAT2);
1621 sii8620_mhl_discover(ctx);
1623 sii8620_write_seq_static(ctx,
1635 sii8620_mhl_init(ctx);
1637 sii8620_write(ctx, REG_CBUS_DISC_INTR0, stat);
1640 static void sii8620_read_burst(struct sii8620 *ctx)
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 |
1648 sii8620_readb(ctx, REG_MDT_RFIFO_STAT);
1651 static void sii8620_irq_g2wb(struct sii8620 *ctx)
1653 u8 stat = sii8620_readb(ctx, REG_MDT_INT_0);
1656 if (sii8620_is_mhl3(ctx))
1657 sii8620_mt_set_int(ctx, MHL_INT_REG(RCHANGE),
1661 sii8620_read_burst(ctx);
1664 sii8620_write(ctx, REG_MDT_XMIT_CTRL, 0);
1666 sii8620_write(ctx, REG_MDT_INT_0, stat);
1669 static void sii8620_status_dcap_ready(struct sii8620 *ctx)
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
1681 static void sii8620_status_changed_path(struct sii8620 *ctx)
1685 if (ctx->use_packed_pixel)
1690 if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
1693 sii8620_mt_write_stat(ctx, MHL_DST_REG(LINK_MODE),
1697 static void sii8620_msc_mr_write_stat(struct sii8620 *ctx)
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);
1704 sii8620_update_array(ctx->stat, st, MHL_DST_SIZE);
1705 sii8620_update_array(ctx->xstat, xst, MHL_XDS_SIZE);
1707 if (ctx->stat[MHL_DST_CONNECTED_RDY] & st[MHL_DST_CONNECTED_RDY] &
1709 sii8620_status_dcap_ready(ctx);
1711 if (!sii8620_is_mhl3(ctx))
1712 sii8620_mt_read_devcap(ctx, false);
1716 sii8620_status_changed_path(ctx);
1719 static void sii8620_ecbus_up(struct sii8620 *ctx, int ret)
1724 sii8620_set_mode(ctx, CM_ECBUS_S);
1727 static void sii8620_got_ecbus_speed(struct sii8620 *ctx, int ret)
1732 sii8620_mt_write_stat(ctx, MHL_XDS_REG(CURR_ECBUS_MODE),
1734 sii8620_mt_rap(ctx, MHL_RAP_CBUS_MODE_UP);
1735 sii8620_mt_set_cont(ctx, sii8620_ecbus_up);
1746 static void sii8620_send_features(struct sii8620 *ctx)
1750 sii8620_write(ctx, REG_MDT_XMIT_CTRL, BIT_MDT_XMIT_CTRL_EN
1754 sii8620_write_buf(ctx, REG_MDT_XMIT_WRITE_PORT, buf, ARRAY_SIZE(buf));
1757 static bool sii8620_rcp_consume(struct sii8620 *ctx, u8 scancode)
1763 if (!IS_ENABLED(CONFIG_RC_CORE) || !ctx->rc_dev)
1767 rc_keydown(ctx->rc_dev, RC_PROTO_CEC, scancode, 0);
1769 rc_keyup(ctx->rc_dev);
1774 static void sii8620_msc_mr_set_int(struct sii8620 *ctx)
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);
1782 switch (ctx->mode) {
1784 sii8620_mt_read_xdevcap_reg(ctx, MHL_XDC_ECBUS_SPEEDS);
1785 sii8620_mt_set_cont(ctx, sii8620_got_ecbus_speed);
1788 sii8620_mt_read_devcap(ctx, true);
1795 sii8620_send_features(ctx);
1797 ctx->feature_complete = true;
1798 if (ctx->edid)
1799 sii8620_enable_hpd(ctx);
1803 static struct sii8620_mt_msg *sii8620_msc_msg_first(struct sii8620 *ctx)
1805 struct device *dev = ctx->dev;
1807 if (list_empty(&ctx->mt_queue)) {
1812 return list_first_entry(&ctx->mt_queue, struct sii8620_mt_msg, node);
1815 static void sii8620_msc_mt_done(struct sii8620 *ctx)
1817 struct sii8620_mt_msg *msg = sii8620_msc_msg_first(ctx);
1822 msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0);
1823 ctx->mt_state = MT_STATE_DONE;
1826 static void sii8620_msc_mr_msc_msg(struct sii8620 *ctx)
1831 sii8620_read_buf(ctx, REG_MSC_MR_MSC_MSG_RCVD_1ST_DATA, buf, 2);
1835 msg = sii8620_msc_msg_first(ctx);
1839 ctx->mt_state = MT_STATE_DONE;
1842 if (!sii8620_rcp_consume(ctx, buf[1]))
1843 sii8620_mt_rcpe(ctx,
1845 sii8620_mt_rcpk(ctx, buf[1]);
1848 dev_err(ctx->dev, "%s message type %d,%d not supported",
1853 static void sii8620_irq_msc(struct sii8620 *ctx)
1855 u8 stat = sii8620_readb(ctx, REG_CBUS_INT_0);
1858 sii8620_write(ctx, REG_CBUS_INT_0, stat & ~BIT_CBUS_HPD_CHG);
1861 u8 cbus_stat = sii8620_readb(ctx, REG_CBUS_STATUS);
1863 if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) {
1864 sii8620_write(ctx, REG_CBUS_INT_0, BIT_CBUS_HPD_CHG);
1869 ctx->cbus_status = cbus_stat;
1873 sii8620_msc_mr_write_stat(ctx);
1876 if (ctx->cbus_status & BIT_CBUS_STATUS_CBUS_HPD) {
1877 ctx->sink_detected = true;
1878 sii8620_identify_sink(ctx);
1880 sii8620_hpd_unplugged(ctx);
1885 sii8620_msc_mr_set_int(ctx);
1888 sii8620_msc_mt_done(ctx);
1891 sii8620_msc_mr_msc_msg(ctx);
1894 static void sii8620_irq_coc(struct sii8620 *ctx)
1896 u8 stat = sii8620_readb(ctx, REG_COC_INTR);
1899 u8 cstat = sii8620_readb(ctx, REG_COC_STAT_0);
1903 sii8620_write_seq_static(ctx,
1911 sii8620_write(ctx, REG_COC_INTR, stat);
1914 static void sii8620_irq_merr(struct sii8620 *ctx)
1916 u8 stat = sii8620_readb(ctx, REG_CBUS_INT_1);
1918 sii8620_write(ctx, REG_CBUS_INT_1, stat);
1921 static void sii8620_irq_edid(struct sii8620 *ctx)
1923 u8 stat = sii8620_readb(ctx, REG_INTR9);
1925 sii8620_write(ctx, REG_INTR9, stat);
1928 ctx->mt_state = MT_STATE_DONE;
1931 static void sii8620_irq_scdt(struct sii8620 *ctx)
1933 u8 stat = sii8620_readb(ctx, REG_INTR5);
1936 u8 cstat = sii8620_readb(ctx, REG_TMDS_CSTAT_P3);
1939 sii8620_start_video(ctx);
1942 sii8620_write(ctx, REG_INTR5, stat);
1945 static void sii8620_got_xdevcap(struct sii8620 *ctx, int ret)
1950 sii8620_mt_read_devcap(ctx, false);
1953 static void sii8620_irq_tdm(struct sii8620 *ctx)
1955 u8 stat = sii8620_readb(ctx, REG_TRXINTH);
1956 u8 tdm = sii8620_readb(ctx, REG_TRXSTA2);
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);
1966 sii8620_write_seq_static(ctx,
1972 sii8620_write(ctx, REG_TRXINTH, stat);
1975 static void sii8620_irq_block(struct sii8620 *ctx)
1977 u8 stat = sii8620_readb(ctx, REG_EMSCINTR);
1980 u8 bstat = sii8620_readb(ctx, REG_SPIBURSTSTAT);
1983 sii8620_burst_receive(ctx);
1986 sii8620_write(ctx, REG_EMSCINTR, stat);
1989 static void sii8620_irq_ddc(struct sii8620 *ctx)
1991 u8 stat = sii8620_readb(ctx, REG_INTR3);
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),
1999 sii8620_enable_hpd(ctx);
2001 sii8620_write(ctx, REG_INTR3, stat);
2014 void (*handler)(struct sii8620 *ctx);
2027 struct sii8620 *ctx = data;
2031 mutex_lock(&ctx->lock);
2033 sii8620_read_buf(ctx, REG_FAST_INTR_STAT, stats, ARRAY_SIZE(stats));
2036 irq_vec[i].handler(ctx);
2038 sii8620_burst_rx_all(ctx);
2039 sii8620_mt_work(ctx);
2040 sii8620_burst_send(ctx);
2042 ret = sii8620_clear_error(ctx);
2044 dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret);
2045 sii8620_mhl_disconnected(ctx);
2047 mutex_unlock(&ctx->lock);
2052 static void sii8620_cable_in(struct sii8620 *ctx)
2054 struct device *dev = ctx->dev;
2058 ret = sii8620_hw_on(ctx);
2064 sii8620_read_buf(ctx, REG_VND_IDL, ver, ARRAY_SIZE(ver));
2065 ret = sii8620_clear_error(ctx);
2074 sii8620_write(ctx, REG_DPD,
2077 sii8620_xtal_set_rate(ctx);
2078 sii8620_disconnect(ctx);
2080 sii8620_write_seq_static(ctx,
2087 ret = sii8620_clear_error(ctx);
2093 enable_irq(to_i2c_client(ctx->dev)->irq);
2096 static void sii8620_init_rcp_input_dev(struct sii8620 *ctx)
2106 dev_err(ctx->dev, "Failed to allocate RC device\n");
2107 ctx->error = -ENOMEM;
2121 dev_err(ctx->dev, "Failed to register RC device\n");
2122 ctx->error = ret;
2126 ctx->rc_dev = rc_dev;
2129 static void sii8620_cable_out(struct sii8620 *ctx)
2131 disable_irq(to_i2c_client(ctx->dev)->irq);
2132 sii8620_hw_off(ctx);
2137 struct sii8620 *ctx =
2139 int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL);
2141 if (state == ctx->cable_state)
2144 ctx->cable_state = state;
2147 sii8620_cable_in(ctx);
2149 sii8620_cable_out(ctx);
2155 struct sii8620 *ctx =
2158 schedule_work(&ctx->extcon_wq);
2163 static int sii8620_extcon_init(struct sii8620 *ctx)
2170 musb = of_graph_get_remote_node(ctx->dev->of_node, 1, -1);
2175 dev_info(ctx->dev, "no extcon found, switching to 'always on' mode\n");
2184 dev_err(ctx->dev, "Invalid or missing extcon\n");
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);
2193 dev_err(ctx->dev, "failed to register notifier for MHL\n");
2208 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2210 sii8620_init_rcp_input_dev(ctx);
2212 return sii8620_clear_error(ctx);
2217 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2222 rc_unregister_device(ctx->rc_dev);
2225 static int sii8620_is_packing_required(struct sii8620 *ctx,
2230 if (sii8620_is_mhl3(ctx)) {
2250 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2251 int pack_required = sii8620_is_packing_required(ctx, mode);
2252 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
2269 struct sii8620 *ctx = bridge_to_sii8620(bridge);
2271 mutex_lock(&ctx->lock);
2273 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2275 mutex_unlock(&ctx->lock);
2290 struct sii8620 *ctx;
2293 ctx = devm_kzalloc(dev, sizeof(*ctx), GFP_KERNEL);
2294 if (!ctx)
2297 ctx->dev = dev;
2298 mutex_init(&ctx->lock);
2299 INIT_LIST_HEAD(&ctx->mt_queue);
2301 ctx->clk_xtal = devm_clk_get(dev, "xtal");
2302 if (IS_ERR(ctx->clk_xtal))
2303 return dev_err_probe(dev, PTR_ERR(ctx->clk_xtal),
2314 "sii8620", ctx);
2319 ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
2320 if (IS_ERR(ctx->gpio_reset))
2321 return dev_err_probe(dev, PTR_ERR(ctx->gpio_reset),
2324 ctx->supplies[0].supply = "cvcc10";
2325 ctx->supplies[1].supply = "iovcc18";
2326 ret = devm_regulator_bulk_get(dev, 2, ctx->supplies);
2330 ret = sii8620_extcon_init(ctx);
2332 dev_err(ctx->dev, "failed to initialize EXTCON\n");
2336 i2c_set_clientdata(client, ctx);
2338 ctx->bridge.funcs = &sii8620_bridge_funcs;
2339 ctx->bridge.of_node = dev->of_node;
2340 drm_bridge_add(&ctx->bridge);
2342 if (!ctx->extcon)
2343 sii8620_cable_in(ctx);
2350 struct sii8620 *ctx = i2c_get_clientdata(client);
2352 if (ctx->extcon) {
2353 extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL,
2354 &ctx->extcon_nb);
2355 flush_work(&ctx->extcon_wq);
2356 if (ctx->cable_state > 0)
2357 sii8620_cable_out(ctx);
2359 sii8620_cable_out(ctx);
2361 drm_bridge_remove(&ctx->bridge);