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