Lines Matching +full:cvcc10 +full:- +full:supply

1 // SPDX-License-Identifier: GPL-2.0-only
32 #include <media/rc-core.h>
34 #include "sil-sii8620.h"
128 0x61, /* eCBUS-S, eCBUS-D */
139 int ret = ctx->error;
141 ctx->error = 0;
147 struct device *dev = ctx->dev;
153 .flags = client->flags,
159 .flags = client->flags | I2C_M_RD,
166 if (ctx->error)
169 ret = i2c_transfer(client->adapter, msg, 2);
175 ctx->error = ret < 0 ? ret : -EIO;
190 struct device *dev = ctx->dev;
195 .flags = client->flags,
200 if (ctx->error)
206 ctx->error = -ENOMEM;
217 ret = i2c_transfer(client->adapter, &msg, 1);
223 ctx->error = ret ?: -EIO;
264 return ctx->mode >= CM_MHL3;
271 list_for_each_entry_safe(msg, n, &ctx->mt_queue, node) {
272 list_del(&msg->node);
275 ctx->mt_state = MT_STATE_READY;
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,
291 list_del(&msg->node);
292 if (msg->recv)
293 msg->recv(ctx, msg);
294 if (msg->continuation)
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);
304 if (msg->send)
305 msg->send(ctx, msg);
312 if (ctx->gen2_write_burst)
315 if (ctx->mode >= CM_MHL1)
322 ctx->gen2_write_burst = 1;
327 if (!ctx->gen2_write_burst)
334 ctx->gen2_write_burst = 0;
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)
361 switch (msg->reg[0]) {
364 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg + 1, 2);
369 sii8620_write_buf(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg, 3);
375 sii8620_write(ctx, REG_MSC_CMD_OR_OFFSET, msg->reg[1]);
380 dev_err(ctx->dev, "%s: command %#x not supported\n", __func__,
381 msg->reg[0]);
390 ctx->error = -ENOMEM;
392 list_add_tail(&msg->node, &ctx->mt_queue);
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);
409 msg->continuation = cont;
419 msg->reg[0] = cmd;
420 msg->reg[1] = arg1;
421 msg->reg[2] = arg2;
422 msg->send = sii8620_mt_msc_cmd_send;
462 if (msg->reg[0] == MHL_READ_XDEVCAP)
475 while (--count >= 0) {
490 struct device *dev = ctx->dev;
492 if (!ctx->sink_detected || !ctx->devcap_read)
496 if (!ctx->edid) {
497 dev_err(ctx->dev, "Cannot fetch EDID\n");
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);
517 struct device *dev = ctx->dev;
520 if (ctx->error < 0)
528 sii8620_update_array(ctx->devcap, dcap, MHL_DCAP_SIZE);
529 ctx->devcap_read = true;
535 sii8620_read_buf(ctx, REG_EDID_FIFO_RD_DATA, ctx->xdevcap,
546 if (msg->reg[0] == MHL_READ_XDEVCAP)
556 if (msg->reg[0] == MHL_READ_XDEVCAP)
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;
577 u8 reg = msg->reg[1] & 0x7f;
579 if (msg->reg[1] & 0x80)
580 ctx->xdevcap[reg] = msg->ret;
582 ctx->devcap[reg] = msg->ret;
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;
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;
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;
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];
650 ctx->burst.r_count += len;
651 tx_left -= 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];
664 ctx->burst.r_count += 2;
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;
693 count -= len;
694 ctx->burst.rx_ack += len;
705 d->id = cpu_to_be16(MHL_BURST_ID_BLK_RCV_BUFFER_INFO);
706 d->size = cpu_to_le16(size);
713 while (size--)
722 h->id = cpu_to_be16(id);
723 h->total_entries = 1;
724 h->sequence_index = 1;
730 const int size = sizeof(*d) + sizeof(d->desc[0]);
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);
745 u8 *d = ctx->burst.rx_buf;
746 int count = ctx->burst.rx_count;
748 while (count-- > 0) {
754 ctx->burst.r_size = get_unaligned_le16(&d[2]);
759 count -= len;
762 ctx->burst.rx_count = 0;
798 ctx->error = -ENOMEM;
835 ctx->error = -ETIMEDOUT;
836 dev_err(ctx->dev, "timeout during EDID read\n");
846 u8 ext = ((struct edid *)edid)->extensions;
855 ctx->error = -ENOMEM;
869 kfree(ctx->edid);
870 ctx->edid = (struct edid *)edid;
894 sii8620_write_buf(ctx, REG_EDID_FIFO_WR_DATA, (u8 *)ctx->edid,
895 (ctx->edid->extensions + 1) * EDID_LENGTH);
919 unsigned long rate = clk_get_rate(ctx->clk_xtal) / 1000;
922 for (i = 0; i < ARRAY_SIZE(rates) - 1; ++i)
927 dev_err(ctx->dev, "xtal clock rate(%lukHz) not supported, setting MHL for %ukHz.\n",
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);
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);
971 if (ctx->mode != CM_MHL1) {
998 switch (ctx->sink_type) {
1021 ctx->use_packed_pixel ? ~0 : 0);
1023 if (ctx->use_packed_pixel) {
1038 if (ctx->use_packed_pixel)
1053 frame->version = 3;
1054 frame->hev_format = -1;
1065 return -ENOSPC;
1069 ptr[1] = frame->version;
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) {
1079 ptr[10] = (frame->hev_format >> 8) & 0xff;
1080 ptr[11] = frame->hev_format & 0xff;
1082 if (frame->av_delay) {
1083 bool sign = frame->av_delay < 0;
1084 int delay = sign ? -frame->av_delay : frame->av_delay;
1092 ptr[3] -= sii8620_checksum(buffer, frm_len);
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) {
1145 &ctx->bridge.encoder->crtc->state->adjusted_mode;
1150 if (ctx->sink_type == SINK_DVI && !sii8620_is_mhl3(ctx)) {
1167 if (ctx->use_packed_pixel)
1189 int clk = mode->clock * (ctx->use_packed_pixel ? 2 : 3);
1192 for (i = 0; i < ARRAY_SIZE(clk_spec) - 1; ++i)
1199 sii8620_burst_tx_bits_per_pixel_fmt(ctx, ctx->use_packed_pixel);
1426 return -EBUSY;
1429 return -ETIMEDOUT;
1436 if (ctx->mode == mode)
1448 ctx->mode = mode;
1452 ctx->mode = mode;
1487 ctx->mode = mode;
1490 dev_err(ctx->dev, "%s mode %d not supported\n", __func__, mode);
1513 ctx->sink_type = SINK_NONE;
1514 ctx->sink_detected = false;
1515 ctx->feature_complete = false;
1516 kfree(ctx->edid);
1517 ctx->edid = NULL;
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;
1673 mode = ctx->stat[MHL_DST_VERSION] >= 0x30 ? CM_MHL3 : CM_MHL1;
1674 if (mode > ctx->mode)
1685 if (ctx->use_packed_pixel)
1690 if (ctx->stat[MHL_DST_LINK_MODE] & MHL_DST_LM_PATH_ENABLED)
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] &
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);
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);
1782 switch (ctx->mode) {
1797 ctx->feature_complete = true;
1798 if (ctx->edid)
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);
1822 msg->ret = sii8620_readb(ctx, REG_MSC_MT_RCVD_DATA0);
1823 ctx->mt_state = MT_STATE_DONE;
1838 msg->ret = buf[1];
1839 ctx->mt_state = MT_STATE_DONE;
1848 dev_err(ctx->dev, "%s message type %d,%d not supported",
1863 if ((cbus_stat ^ ctx->cbus_status) & BIT_CBUS_STATUS_CBUS_HPD) {
1869 ctx->cbus_status = cbus_stat;
1876 if (ctx->cbus_status & BIT_CBUS_STATUS_CBUS_HPD) {
1877 ctx->sink_detected = true;
1928 ctx->mt_state = MT_STATE_DONE;
1959 ctx->mode = CM_ECBUS_S;
1960 ctx->burst.rx_ack = 0;
1961 ctx->burst.r_size = SII8620_BURST_BUF_LEN;
1995 if (sii8620_is_mhl3(ctx) && !ctx->feature_complete)
2004 /* endian agnostic, non-volatile version of test_bit */
2031 mutex_lock(&ctx->lock);
2044 dev_err(ctx->dev, "Error during IRQ handling, %d.\n", ret);
2047 mutex_unlock(&ctx->lock);
2054 struct device *dev = ctx->dev;
2093 enable_irq(to_i2c_client(ctx->dev)->irq);
2106 dev_err(ctx->dev, "Failed to allocate RC device\n");
2107 ctx->error = -ENOMEM;
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";
2121 dev_err(ctx->dev, "Failed to register RC device\n");
2122 ctx->error = ret;
2126 ctx->rc_dev = rc_dev;
2131 disable_irq(to_i2c_client(ctx->dev)->irq);
2139 int state = extcon_get_state(ctx->extcon, EXTCON_DISP_MHL);
2141 if (state == ctx->cable_state)
2144 ctx->cable_state = state;
2158 schedule_work(&ctx->extcon_wq);
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 */
2175 dev_info(ctx->dev, "no extcon found, switching to 'always on' mode\n");
2182 if (PTR_ERR(edev) == -EPROBE_DEFER)
2183 return -EPROBE_DEFER;
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");
2223 rc_unregister_device(ctx->rc_dev);
2239 if (mode->clock < max_pclk)
2241 else if (mode->clock < max_pclk_pp_mode)
2244 return -1;
2253 bool can_pack = ctx->devcap[MHL_DCAP_VID_LINK_MODE] &
2272 mutex_lock(&ctx->lock);
2274 ctx->use_packed_pixel = sii8620_is_packing_required(ctx, adjusted_mode);
2276 mutex_unlock(&ctx->lock);
2290 struct device *dev = &client->dev;
2299 ctx->dev = dev;
2300 mutex_init(&ctx->lock);
2301 INIT_LIST_HEAD(&ctx->mt_queue);
2303 ctx->clk_xtal = devm_clk_get(dev, "xtal");
2304 if (IS_ERR(ctx->clk_xtal))
2305 return dev_err_probe(dev, PTR_ERR(ctx->clk_xtal),
2308 if (!client->irq) {
2310 return -EINVAL;
2312 irq_set_status_flags(client->irq, IRQ_NOAUTOEN);
2313 ret = devm_request_threaded_irq(dev, client->irq, NULL,
2321 ctx->gpio_reset = devm_gpiod_get(dev, "reset", GPIOD_OUT_HIGH);
2322 if (IS_ERR(ctx->gpio_reset))
2323 return dev_err_probe(dev, PTR_ERR(ctx->gpio_reset),
2326 ctx->supplies[0].supply = "cvcc10";
2327 ctx->supplies[1].supply = "iovcc18";
2328 ret = devm_regulator_bulk_get(dev, 2, ctx->supplies);
2334 dev_err(ctx->dev, "failed to initialize EXTCON\n");
2340 ctx->bridge.of_node = dev->of_node;
2341 drm_bridge_add(&ctx->bridge);
2343 if (!ctx->extcon)
2353 if (ctx->extcon) {
2354 extcon_unregister_notifier(ctx->extcon, EXTCON_DISP_MHL,
2355 &ctx->extcon_nb);
2356 flush_work(&ctx->extcon_wq);
2357 if (ctx->cable_state > 0)
2362 drm_bridge_remove(&ctx->bridge);