static int mhl_send_msc_command(struct msc_command_struct *req) { int timeout; u8 start_bit = 0x00; u8 *burst_data; int i; if (mhl_msm_state->cur_state != POWER_STATE_D0_MHL) { pr_debug("%s: power_state:%02x CBUS(0x0A):%02x\n", __func__, mhl_msm_state->cur_state, mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0A)); return -EFAULT; } if (!req) return -EFAULT; pr_debug("%s: command=0x%02x offset=0x%02x %02x %02x", __func__, req->command, req->offset, req->payload.data[0], req->payload.data[1]); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x13, req->offset); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x14, req->payload.data[0]); switch (req->command) { case MHL_SET_INT: case MHL_WRITE_STAT: start_bit = MSC_START_BIT_WRITE_REG; break; case MHL_READ_DEVCAP: start_bit = MSC_START_BIT_READ_REG; break; case MHL_GET_STATE: case MHL_GET_VENDOR_ID: case MHL_SET_HPD: case MHL_CLR_HPD: case MHL_GET_SC1_ERRORCODE: case MHL_GET_DDC_ERRORCODE: case MHL_GET_MSC_ERRORCODE: case MHL_GET_SC3_ERRORCODE: start_bit = MSC_START_BIT_MSC_CMD; mhl_i2c_reg_write(TX_PAGE_CBUS, 0x13, req->command); break; case MHL_MSC_MSG: start_bit = MSC_START_BIT_VS_CMD; mhl_i2c_reg_write(TX_PAGE_CBUS, 0x15, req->payload.data[1]); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x13, req->command); break; case MHL_WRITE_BURST: start_bit = MSC_START_BIT_WRITE_BURST; mhl_i2c_reg_write(TX_PAGE_CBUS, 0x20, req->length - 1); if (!(req->payload.burst_data)) { pr_err("%s: burst data is null!\n", __func__); goto cbus_send_fail; } burst_data = req->payload.burst_data; for (i = 0; i < req->length; i++, burst_data++) mhl_i2c_reg_write(TX_PAGE_CBUS, 0xC0 + i, *burst_data); break; default: pr_err("%s: unknown command! (%02x)\n", __func__, req->command); goto cbus_send_fail; } INIT_COMPLETION(mhl_msm_state->msc_cmd_done); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x12, start_bit); timeout = wait_for_completion_interruptible_timeout (&mhl_msm_state->msc_cmd_done, HZ); if (!timeout) { pr_err("%s: cbus_command_send timed out!\n", __func__); goto cbus_send_fail; } switch (req->command) { case MHL_READ_DEVCAP: /* devcap */ req->retval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x16); pr_debug("Read CBUS[0x16]=[%02x]\n", req->retval); break; case MHL_MSC_MSG: /* check if MSC_MSG NACKed */ if (mhl_i2c_reg_read(TX_PAGE_CBUS, 0x20) & BIT6) return -EAGAIN; default: req->retval = 0; break; } mhl_msc_command_done(req); pr_debug("%s: msc cmd done\n", __func__); return 0; cbus_send_fail: return -EFAULT; }
static void mhl_init_reg_settings(bool mhl_disc_en) { mhl_i2c_reg_write(TX_PAGE_L1, 0x003D, 0x3F); msleep(50); mhl_i2c_reg_write(TX_PAGE_2, 0x0011, 0x01); mhl_i2c_reg_write(TX_PAGE_2, 0x0012, 0x11); mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0x10); mhl_i2c_reg_write(TX_PAGE_3, 0x0035, 0xAC); mhl_i2c_reg_write(TX_PAGE_3, 0x0031, 0x3C); mhl_i2c_reg_write(TX_PAGE_3, 0x0033, 0xD9); mhl_i2c_reg_write(TX_PAGE_3, 0x0037, 0x02); mhl_i2c_reg_write(TX_PAGE_L0, 0x0080, 0x00); mhl_i2c_reg_write(TX_PAGE_L0, 0x00F8, 0x0C); mhl_i2c_reg_write(TX_PAGE_L0, 0x0085, 0x02); mhl_i2c_reg_write(TX_PAGE_2, 0x0000, 0x00); mhl_i2c_reg_write(TX_PAGE_2, 0x0013, 0x60); mhl_i2c_reg_write(TX_PAGE_2, 0x0017, 0x03); mhl_i2c_reg_write(TX_PAGE_2, 0x001A, 0x20); mhl_i2c_reg_write(TX_PAGE_2, 0x0022, 0xE0); mhl_i2c_reg_write(TX_PAGE_2, 0x0023, 0xC0); mhl_i2c_reg_write(TX_PAGE_2, 0x0024, 0xA0); mhl_i2c_reg_write(TX_PAGE_2, 0x0025, 0x80); mhl_i2c_reg_write(TX_PAGE_2, 0x0026, 0x60); mhl_i2c_reg_write(TX_PAGE_2, 0x0027, 0x40); mhl_i2c_reg_write(TX_PAGE_2, 0x0028, 0x20); mhl_i2c_reg_write(TX_PAGE_2, 0x0029, 0x00); mhl_i2c_reg_write(TX_PAGE_2, 0x0031, 0x0A); mhl_i2c_reg_write(TX_PAGE_2, 0x0045, 0x06); mhl_i2c_reg_write(TX_PAGE_2, 0x004B, 0x06); mhl_i2c_reg_write(TX_PAGE_2, 0x004C, 0xE0); mhl_i2c_reg_write(TX_PAGE_2, 0x004D, 0x00); mhl_i2c_reg_write(TX_PAGE_L0, 0x0008, 0x35); mhl_i2c_reg_write(TX_PAGE_3, 0x0011, 0xAD); mhl_i2c_reg_write(TX_PAGE_3, 0x0014, 0x55); mhl_i2c_reg_write(TX_PAGE_3, 0x0015, 0x11); mhl_i2c_reg_write(TX_PAGE_3, 0x0017, 0x82); mhl_i2c_reg_write(TX_PAGE_3, 0x0018, 0x24); mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x8C); if (mhl_disc_en) mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x27); else mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x26); mhl_i2c_reg_write(TX_PAGE_3, 0x0016, 0x20); mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86); if (mhl_msm_state->cur_state != POWER_STATE_D0_MHL) mhl_drive_hpd(HPD_DOWN); mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x084); mhl_i2c_reg_write(TX_PAGE_L0, 0x000D, 0x1C); cbus_reset(); init_cbus_regs(); }
static void int_4_isr(void) { uint8_t status, reg ; status = mhl_i2c_reg_read(TX_PAGE_3, 0x0021); if ((0x00 == status) && (mhl_msm_state->cur_state == POWER_STATE_D3)) { pr_debug("MHL: spurious interrupt\n"); return; } if (0xFF != status) { if ((status & BIT0) && (mhl_msm_state->chip_rev_id < 1)) { uint8_t tmds_cstat; uint8_t mhl_fifo_status; tmds_cstat = mhl_i2c_reg_read(TX_PAGE_3, 0x0040); pr_debug("TMDS CSTAT: 0x%02x\n", tmds_cstat); if (tmds_cstat & 0x02) { mhl_fifo_status = mhl_i2c_reg_read(TX_PAGE_3, 0x0023); pr_debug("MHL FIFO status: 0x%02x\n", mhl_fifo_status); if (mhl_fifo_status & 0x0C) { mhl_i2c_reg_write(TX_PAGE_3, 0x0023, 0x0C); pr_debug("Apply MHL FIFO Reset\n"); mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x94); mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x84); } } } if (status & BIT1) pr_debug("MHL: INT4 BIT1 is set\n"); if (status & BIT2) { pr_debug("mhl_msm_connection() from ISR\n"); mhl_connect_api(true); mhl_msm_connection(); pr_debug("MHL Connect Drv: INT4 Status = %02X\n", (int) status); } else if (status & BIT3) { pr_debug("MHL: uUSB-A type device detected.\n"); mhl_i2c_reg_write(TX_PAGE_3, 0x001C, 0x80); switch_mode(POWER_STATE_D3); } if (status & BIT5) { mhl_connect_api(false); reg = mhl_i2c_reg_read(TX_PAGE_3, 0x0021); mhl_i2c_reg_write(TX_PAGE_3, 0x0021, reg); mhl_msm_disconnection(); if (notify_usb_online) notify_usb_online(0); pr_debug("MHL Disconnect Drv: INT4 Status = %02X\n", (int)status); } if ((mhl_msm_state->cur_state != POWER_STATE_D0_MHL) &&\ (status & BIT6)) { switch_mode(POWER_STATE_D0_MHL); mhl_msm_read_rgnd_int(); } if (mhl_msm_state->cur_state != POWER_STATE_D3) { if (status & BIT4) { force_usb_switch_open(); release_usb_switch_open(); } } } pr_debug("MHL END Drv: INT4 Status = %02X\n", (int) status); mhl_i2c_reg_write(TX_PAGE_3, 0x0021, status); return; }
static void clear_all_intrs(void) { uint8_t regval = 0x00; pr_debug("********* EXITING ISR MASK CHECK ?? *************\n"); pr_debug("Drv: INT1 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_L0, 0x0071)); pr_debug("Drv: INT3 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_L0, 0x0077)); pr_debug("Drv: INT4 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_3, 0x0021)); pr_debug("Drv: INT5 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_3, 0x0023)); pr_debug("Drv: CBUS1 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0009)); pr_debug("Drv: CBUS2 MASK = %02X\n", (int) mhl_i2c_reg_read(TX_PAGE_CBUS, 0x001F)); pr_debug("********* END OF ISR MASK CHECK *************\n"); pr_debug("********* EXITING IN ISR ?? *************\n"); regval = mhl_i2c_reg_read(TX_PAGE_L0, 0x0071); pr_debug("Drv: INT1 Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_L0, 0x0071, regval); regval = mhl_i2c_reg_read(TX_PAGE_L0, 0x0072); pr_debug("Drv: INT2 Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_L0, 0x0072, regval); regval = mhl_i2c_reg_read(TX_PAGE_L0, 0x0073); pr_debug("Drv: INT3 Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_L0, 0x0073, regval); regval = mhl_i2c_reg_read(TX_PAGE_3, 0x0021); pr_debug("Drv: INT4 Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_3, 0x0021, regval); regval = mhl_i2c_reg_read(TX_PAGE_3, 0x0023); pr_debug("Drv: INT5 Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_3, 0x0023, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0008); pr_debug("Drv: cbusInt Status = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0008, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x001E); pr_debug("Drv: CBUS INTR_2: %d\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x001E, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00A0); pr_debug("Drv: A0 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00A0, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00A1); pr_debug("Drv: A1 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00A1, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00A2); pr_debug("Drv: A2 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00A2, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00A3); pr_debug("Drv: A3 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00A3, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00B0); pr_debug("Drv: B0 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00B0, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00B1); pr_debug("Drv: B1 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00B1, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00B2); pr_debug("Drv: B2 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00B2, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00B3); pr_debug("Drv: B3 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00B3, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00E0); pr_debug("Drv: E0 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00E0, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00E1); pr_debug("Drv: E1 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00E1, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00E2); pr_debug("Drv: E2 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00E2, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00E3); pr_debug("Drv: E3 STATUS Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00E3, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00F0); pr_debug("Drv: F0 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00F0, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00F1); pr_debug("Drv: F1 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00F1, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00F2); pr_debug("Drv: F2 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00F2, regval); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x00F3); pr_debug("Drv: F3 INT Set = %02X\n", (int)regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x00F3, regval); pr_debug("********* END OF EXITING IN ISR *************\n"); }
static void init_cbus_regs(void) { uint8_t regval; mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0007, 0xF2); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0036, 0x03); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0039, 0x30); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0040, 0x03); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_STATE, DEVCAP_VAL_DEV_STATE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_MHL_VERSION, DEVCAP_VAL_MHL_VERSION); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_CAT, DEVCAP_VAL_DEV_CAT); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_H, DEVCAP_VAL_ADOPTER_ID_H); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_L, DEVCAP_VAL_ADOPTER_ID_L); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VID_LINK_MODE, DEVCAP_VAL_VID_LINK_MODE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_AUD_LINK_MODE, DEVCAP_VAL_AUD_LINK_MODE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VIDEO_TYPE, DEVCAP_VAL_VIDEO_TYPE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_LOG_DEV_MAP, DEVCAP_VAL_LOG_DEV_MAP); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_BANDWIDTH, DEVCAP_VAL_BANDWIDTH); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_FEATURE_FLAG, DEVCAP_VAL_FEATURE_FLAG); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_H, DEVCAP_VAL_DEVICE_ID_H); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_L, DEVCAP_VAL_DEVICE_ID_L); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_SCRATCHPAD_SIZE, DEVCAP_VAL_SCRATCHPAD_SIZE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_INT_STAT_SIZE, DEVCAP_VAL_INT_STAT_SIZE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_RESERVED, DEVCAP_VAL_RESERVED); regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0031); regval = (regval | 0x0C); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0031, regval); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0022, 0x0F); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0030, 0x01); mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x002E, BIT4, BIT4); }
static void mhl_cbus_isr(void) { uint8_t regval; int req_done = FALSE; uint8_t sub_cmd = 0x0; uint8_t cmd_data = 0x0; int msc_msg_recved = FALSE; int rc = -1; regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x08); if (regval == 0xff) return; if (regval) mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval); pr_debug("%s: CBUS_INT = %02x\n", __func__, regval); if (regval & BIT3) { sub_cmd = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x18); cmd_data = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x19); msc_msg_recved = TRUE; } if (regval & (BIT6 | BIT5 | BIT2)) mhl_cbus_process_errors(regval); if (regval & BIT4) req_done = TRUE; regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x1E); if (regval) mhl_i2c_reg_write(TX_PAGE_CBUS, 0x1E, regval); pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval); if (regval & BIT2) { uint8_t intr; intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA0); mhl_msc_recv_set_int(0, intr); pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr); intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA1); mhl_msc_recv_set_int(1, intr); pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA0, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA1, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA2, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA3, 0xFF); } if (regval & BIT3) { uint8_t stat; stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB0); mhl_msc_recv_write_stat(0, stat); pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat); stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB1); mhl_msc_recv_write_stat(1, stat); pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB0, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB1, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB2, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB3, 0xFF); } if (msc_msg_recved) { rc = mhl_msc_recv_msc_msg(sub_cmd, cmd_data); if (rc) pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc); } if (req_done) complete_all(&mhl_msm_state->msc_cmd_done); return; }
static void int_4_isr(void) { uint8_t status, reg ; /* INTR_STATUS4 */ status = mhl_i2c_reg_read(TX_PAGE_3, 0x0021); /* * When I2C is inoperational (D3) and * a previous interrupt brought us here, * do nothing. */ if ((0x00 == status) && (mhl_msm_state->cur_state == POWER_STATE_D3)) { pr_debug("MHL: spurious interrupt\n"); return; } if (0xFF != status) { if ((status & BIT0) && (mhl_msm_state->chip_rev_id < 1)) { uint8_t tmds_cstat; uint8_t mhl_fifo_status; /* TMDS CSTAT */ tmds_cstat = mhl_i2c_reg_read(TX_PAGE_3, 0x0040); pr_debug("TMDS CSTAT: 0x%02x\n", tmds_cstat); if (tmds_cstat & 0x02) { mhl_fifo_status = mhl_i2c_reg_read(TX_PAGE_3, 0x0023); pr_debug("MHL FIFO status: 0x%02x\n", mhl_fifo_status); if (mhl_fifo_status & 0x0C) { mhl_i2c_reg_write(TX_PAGE_3, 0x0023, 0x0C); pr_debug("Apply MHL FIFO Reset\n"); mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x94); mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x84); } } } if (status & BIT1) pr_debug("MHL: INT4 BIT1 is set\n"); /* MHL_EST interrupt */ if (status & BIT2) { pr_debug("mhl_msm_connection() from ISR\n"); mhl_connect_api(true); mhl_msm_connection(); pr_debug("MHL Connect Drv: INT4 Status = %02X\n", (int) status); } else if (status & BIT3) { pr_debug("MHL: uUSB-A type device detected.\n"); mhl_i2c_reg_write(TX_PAGE_3, 0x001C, 0x80); switch_mode(POWER_STATE_D3); } if (status & BIT5) { mhl_connect_api(false); /* Clear interrupts - REG INTR4 */ reg = mhl_i2c_reg_read(TX_PAGE_3, 0x0021); mhl_i2c_reg_write(TX_PAGE_3, 0x0021, reg); mhl_msm_disconnection(); if (notify_usb_online) notify_usb_online(0); pr_debug("MHL Disconnect Drv: INT4 Status = %02X\n", (int)status); } if ((mhl_msm_state->cur_state != POWER_STATE_D0_MHL) &&\ (status & BIT6)) { /* RGND READY Intr */ switch_mode(POWER_STATE_D0_MHL); mhl_msm_read_rgnd_int(); } /* Can't succeed at these in D3 */ if (mhl_msm_state->cur_state != POWER_STATE_D3) { /* CBUS Lockout interrupt? */ /* * Hardware detection mechanism figures that * CBUS line is latched and raises this intr * where we force usb switch open and release */ if (status & BIT4) { force_usb_switch_open(); release_usb_switch_open(); } } } pr_debug("MHL END Drv: INT4 Status = %02X\n", (int) status); mhl_i2c_reg_write(TX_PAGE_3, 0x0021, status); return; }
/* * Configure the initial reg settings */ static void mhl_init_reg_settings(bool mhl_disc_en) { /* * ============================================ * POWER UP * ============================================ */ /* Power up 1.2V core */ mhl_i2c_reg_write(TX_PAGE_L1, 0x003D, 0x3F); /* * Wait for the source power to be enabled * before enabling pll clocks. */ msleep(50); /* Enable Tx PLL Clock */ mhl_i2c_reg_write(TX_PAGE_2, 0x0011, 0x01); /* Enable Tx Clock Path and Equalizer */ mhl_i2c_reg_write(TX_PAGE_2, 0x0012, 0x11); /* Tx Source Termination ON */ mhl_i2c_reg_write(TX_PAGE_3, 0x0030, 0x10); /* Enable 1X MHL Clock output */ mhl_i2c_reg_write(TX_PAGE_3, 0x0035, 0xAC); /* Tx Differential Driver Config */ mhl_i2c_reg_write(TX_PAGE_3, 0x0031, 0x3C); mhl_i2c_reg_write(TX_PAGE_3, 0x0033, 0xD9); /* PLL Bandwidth Control */ mhl_i2c_reg_write(TX_PAGE_3, 0x0037, 0x02); /* * ============================================ * Analog PLL Control * ============================================ */ /* Enable Rx PLL clock */ mhl_i2c_reg_write(TX_PAGE_L0, 0x0080, 0x00); mhl_i2c_reg_write(TX_PAGE_L0, 0x00F8, 0x0C); mhl_i2c_reg_write(TX_PAGE_L0, 0x0085, 0x02); mhl_i2c_reg_write(TX_PAGE_2, 0x0000, 0x00); mhl_i2c_reg_write(TX_PAGE_2, 0x0013, 0x60); /* PLL Cal ref sel */ mhl_i2c_reg_write(TX_PAGE_2, 0x0017, 0x03); /* VCO Cal */ mhl_i2c_reg_write(TX_PAGE_2, 0x001A, 0x20); /* Auto EQ */ mhl_i2c_reg_write(TX_PAGE_2, 0x0022, 0xE0); mhl_i2c_reg_write(TX_PAGE_2, 0x0023, 0xC0); mhl_i2c_reg_write(TX_PAGE_2, 0x0024, 0xA0); mhl_i2c_reg_write(TX_PAGE_2, 0x0025, 0x80); mhl_i2c_reg_write(TX_PAGE_2, 0x0026, 0x60); mhl_i2c_reg_write(TX_PAGE_2, 0x0027, 0x40); mhl_i2c_reg_write(TX_PAGE_2, 0x0028, 0x20); mhl_i2c_reg_write(TX_PAGE_2, 0x0029, 0x00); /* Rx PLL Bandwidth 4MHz */ mhl_i2c_reg_write(TX_PAGE_2, 0x0031, 0x0A); /* Rx PLL Bandwidth value from I2C */ mhl_i2c_reg_write(TX_PAGE_2, 0x0045, 0x06); mhl_i2c_reg_write(TX_PAGE_2, 0x004B, 0x06); /* Manual zone control */ mhl_i2c_reg_write(TX_PAGE_2, 0x004C, 0xE0); /* PLL Mode value */ mhl_i2c_reg_write(TX_PAGE_2, 0x004D, 0x00); mhl_i2c_reg_write(TX_PAGE_L0, 0x0008, 0x35); /* * Discovery Control and Status regs * Setting De-glitch time to 50 ms (default) * Switch Control Disabled */ mhl_i2c_reg_write(TX_PAGE_3, 0x0011, 0xAD); /* 1.8V CBUS VTH */ mhl_i2c_reg_write(TX_PAGE_3, 0x0014, 0x55); /* RGND and single Discovery attempt */ mhl_i2c_reg_write(TX_PAGE_3, 0x0015, 0x11); /* Ignore VBUS */ mhl_i2c_reg_write(TX_PAGE_3, 0x0017, 0x82); mhl_i2c_reg_write(TX_PAGE_3, 0x0018, 0x24); /* Pull-up resistance off for IDLE state */ mhl_i2c_reg_write(TX_PAGE_3, 0x0013, 0x8C); /* Enable CBUS Discovery */ if (mhl_disc_en) /* Enable MHL Discovery */ mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x27); else /* Disable MHL Discovery */ mhl_i2c_reg_write(TX_PAGE_3, 0x0010, 0x26); mhl_i2c_reg_write(TX_PAGE_3, 0x0016, 0x20); /* MHL CBUS Discovery - immediate comm. */ mhl_i2c_reg_write(TX_PAGE_3, 0x0012, 0x86); /* Do not force HPD to 0 during wake-up from D3 */ if (mhl_msm_state->cur_state != POWER_STATE_D0_MHL) mhl_drive_hpd(HPD_DOWN); /* Enable Auto Soft RESET */ mhl_i2c_reg_write(TX_PAGE_3, 0x0000, 0x084); /* HDMI Transcode mode enable */ mhl_i2c_reg_write(TX_PAGE_L0, 0x000D, 0x1C); cbus_reset(); init_cbus_regs(); }
static void init_cbus_regs(void) { uint8_t regval; /* Increase DDC translation layer timer*/ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0007, 0xF2); /* Drive High Time */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0036, 0x03); /* Use programmed timing */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0039, 0x30); /* CBUS Drive Strength */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0040, 0x03); /* * Write initial default settings * to devcap regs: default settings */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_STATE, DEVCAP_VAL_DEV_STATE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_MHL_VERSION, DEVCAP_VAL_MHL_VERSION); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEV_CAT, DEVCAP_VAL_DEV_CAT); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_H, DEVCAP_VAL_ADOPTER_ID_H); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_ADOPTER_ID_L, DEVCAP_VAL_ADOPTER_ID_L); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VID_LINK_MODE, DEVCAP_VAL_VID_LINK_MODE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_AUD_LINK_MODE, DEVCAP_VAL_AUD_LINK_MODE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_VIDEO_TYPE, DEVCAP_VAL_VIDEO_TYPE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_LOG_DEV_MAP, DEVCAP_VAL_LOG_DEV_MAP); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_BANDWIDTH, DEVCAP_VAL_BANDWIDTH); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_FEATURE_FLAG, DEVCAP_VAL_FEATURE_FLAG); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_H, DEVCAP_VAL_DEVICE_ID_H); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_DEVICE_ID_L, DEVCAP_VAL_DEVICE_ID_L); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_SCRATCHPAD_SIZE, DEVCAP_VAL_SCRATCHPAD_SIZE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_INT_STAT_SIZE, DEVCAP_VAL_INT_STAT_SIZE); mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0080 | DEVCAP_OFFSET_RESERVED, DEVCAP_VAL_RESERVED); /* Make bits 2,3 (initiator timeout) to 1,1 * for register CBUS_LINK_CONTROL_2 * REG_CBUS_LINK_CONTROL_2 */ regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x0031); regval = (regval | 0x0C); /* REG_CBUS_LINK_CONTROL_2 */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0031, regval); /* REG_MSC_TIMEOUT_LIMIT */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0022, 0x0F); /* REG_CBUS_LINK_CONTROL_1 */ mhl_i2c_reg_write(TX_PAGE_CBUS, 0x0030, 0x01); /* disallow vendor specific commands */ mhl_i2c_reg_modify(TX_PAGE_CBUS, 0x002E, BIT4, BIT4); }
/* MSC, RCP, RAP messages - mandatory for compliance */ static void mhl_cbus_isr(void) { uint8_t regval; int req_done = FALSE; uint8_t sub_cmd = 0x0; uint8_t cmd_data = 0x0; int msc_msg_recved = FALSE; int rc = -1; regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x08); if (regval == 0xff) return; /* clear all interrupts that were raised even if we did not process */ if (regval) mhl_i2c_reg_write(TX_PAGE_CBUS, 0x08, regval); pr_debug("%s: CBUS_INT = %02x\n", __func__, regval); /* MSC_MSG (RCP/RAP) */ if (regval & BIT3) { sub_cmd = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x18); cmd_data = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x19); msc_msg_recved = TRUE; } /* MSC_MT_ABRT/MSC_MR_ABRT/DDC_ABORT */ if (regval & (BIT6 | BIT5 | BIT2)) mhl_cbus_process_errors(regval); /* MSC_REQ_DONE */ if (regval & BIT4) req_done = TRUE; /* Now look for interrupts on CBUS_MSC_INT2 */ regval = mhl_i2c_reg_read(TX_PAGE_CBUS, 0x1E); /* clear all interrupts that were raised */ /* even if we did not process */ if (regval) mhl_i2c_reg_write(TX_PAGE_CBUS, 0x1E, regval); pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval); /* received SET_INT */ if (regval & BIT2) { uint8_t intr; intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA0); mhl_msc_recv_set_int(0, intr); pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr); intr = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xA1); mhl_msc_recv_set_int(1, intr); pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA0, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA1, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA2, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xA3, 0xFF); } /* received WRITE_STAT */ if (regval & BIT3) { uint8_t stat; stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB0); mhl_msc_recv_write_stat(0, stat); pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat); stat = mhl_i2c_reg_read(TX_PAGE_CBUS, 0xB1); mhl_msc_recv_write_stat(1, stat); pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB0, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB1, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB2, 0xFF); mhl_i2c_reg_write(TX_PAGE_CBUS, 0xB3, 0xFF); } /* received MSC_MSG */ if (msc_msg_recved) { /*mhl msc recv msc msg*/ rc = mhl_msc_recv_msc_msg(sub_cmd, cmd_data); if (rc) pr_err("MHL: mhl msc recv msc msg failed(%d)!\n", rc); } /* complete last command */ if (req_done) complete_all(&mhl_msm_state->msc_cmd_done); return; }