static void mhl_msm_connection(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t val; struct i2c_client *client = mhl_ctrl->i2c_handle; pr_debug("%s: cur st [0x%x]\n", __func__, mhl_ctrl->cur_state); if (mhl_ctrl->cur_state == POWER_STATE_D0_MHL) { /* Already in D0 - MHL power state */ pr_err("%s: cur st not D0\n", __func__); return; } /* spin_lock_irqsave(&mhl_state_lock, flags); */ switch_mode(mhl_ctrl, POWER_STATE_D0_MHL); /* spin_unlock_irqrestore(&mhl_state_lock, flags); */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10); MHL_SII_CBUS_WR(0x07, 0xF2); /* * Keep the discovery enabled. Need RGND interrupt * Possibly chip disables discovery after MHL_EST?? * Need to re-enable here */ val = MHL_SII_PAGE3_RD(0x10); MHL_SII_PAGE3_WR(0x10, val | BIT0); return; }
static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl, enum mhl_st_type to_mode, bool hpd_off) { struct i2c_client *client = mhl_ctrl->i2c_handle; unsigned long flags; int rc; struct msm_hdmi_mhl_ops *hdmi_mhl_ops = mhl_ctrl->hdmi_mhl_ops; pr_debug("%s: tx pwr on\n", __func__); spin_lock_irqsave(&mhl_ctrl->lock, flags); mhl_ctrl->tx_powered_off = false; spin_unlock_irqrestore(&mhl_ctrl->lock, flags); switch (to_mode) { case POWER_STATE_D0_NO_MHL: mhl_ctrl->cur_state = to_mode; mhl_init_reg_settings(mhl_ctrl, true); /* REG_DISC_CTRL1 */ MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, BIT0); /* TPI_DEVICE_POWER_STATE_CTRL_REG */ mhl_i2c_reg_modify(client, TX_PAGE_TPI, 0x001E, BIT1 | BIT0, 0x00); break; case POWER_STATE_D0_MHL: mhl_ctrl->cur_state = to_mode; break; case POWER_STATE_D3: if (mhl_ctrl->cur_state == POWER_STATE_D3) { pr_debug("%s: mhl tx already in low power mode\n", __func__); break; } /* Force HPD to 0 when not in MHL mode. */ mhl_drive_hpd(mhl_ctrl, HPD_DOWN); mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE); /* * Change TMDS termination to high impedance * on disconnection. */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0); msleep(50); if (!mhl_ctrl->disc_enabled) MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00); if (hdmi_mhl_ops && hpd_off) { rc = hdmi_mhl_ops->set_upstream_hpd( mhl_ctrl->pdata->hdmi_pdev, 0); pr_debug("%s: hdmi unset hpd %s\n", __func__, rc ? "failed" : "passed"); } mhl_ctrl->cur_state = POWER_STATE_D3; break; default: break; } }
static void cbus_reset(struct i2c_client *client) { uint8_t i; /* * REG_SRST */ MHL_SII_REG_NAME_MOD(REG_SRST, BIT3, BIT3); msleep(20); MHL_SII_REG_NAME_MOD(REG_SRST, BIT3, 0x00); /* * REG_INTR1 and REG_INTR4 */ MHL_SII_REG_NAME_WR(REG_INTR1_MASK, BIT6); MHL_SII_REG_NAME_WR(REG_INTR4_MASK, BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6); MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00); /* Unmask CBUS1 Intrs */ MHL_SII_CBUS_WR(0x0009, BIT2 | BIT3 | BIT4 | BIT5 | BIT6); /* Unmask CBUS2 Intrs */ MHL_SII_CBUS_WR(0x001F, BIT2 | BIT3); for (i = 0; i < 4; i++) { /* * Enable WRITE_STAT interrupt for writes to * all 4 MSC Status registers. */ MHL_SII_CBUS_WR((0xE0 + i), 0xFF); /* * Enable SET_INT interrupt for writes to * all 4 MSC Interrupt registers. */ MHL_SII_CBUS_WR((0xF0 + i), 0xFF); } return; }
static void force_usb_switch_open(struct mhl_tx_ctrl *mhl_ctrl) { struct i2c_client *client = mhl_ctrl->i2c_handle; /*disable discovery*/ MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT0, 0); /* force USB ID switch to open*/ MHL_SII_REG_NAME_MOD(REG_DISC_CTRL6, BIT6, BIT6); MHL_SII_REG_NAME_WR(REG_DISC_CTRL3, 0x86); /* force HPD to 0 when not in mhl mode. */ MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT5 | BIT4, BIT4); }
static void mhl_msm_disconnection(struct mhl_tx_ctrl *mhl_ctrl) { struct i2c_client *client = mhl_ctrl->i2c_handle; unsigned long flags; spin_lock_irqsave(&mhl_ctrl->lock, flags); mhl_ctrl->dwnstream_hpd &= ~BIT6; spin_unlock_irqrestore(&mhl_ctrl->lock, flags); /* disabling Tx termination */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0); switch_mode(mhl_ctrl, POWER_STATE_D3, true); }
static void mhl_misc_isr(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t intr_5_stat; struct i2c_client *client = mhl_ctrl->i2c_handle; /* * Clear INT 5 * INTR5 is related to FIFO underflow/overflow reset * which is handled in 8334 by auto FIFO reset */ intr_5_stat = MHL_SII_REG_NAME_RD(REG_INTR5); MHL_SII_REG_NAME_WR(REG_INTR5, intr_5_stat); }
static void scdt_st_chg(struct i2c_client *client) { uint8_t tmds_cstat; uint8_t mhl_fifo_status; /* tmds cstat */ tmds_cstat = MHL_SII_PAGE3_RD(0x0040); pr_debug("%s: tmds cstat: 0x%02x\n", __func__, tmds_cstat); if (!(tmds_cstat & BIT1)) return; mhl_fifo_status = MHL_SII_REG_NAME_RD(REG_INTR5); pr_debug("%s: mhl fifo st: 0x%02x\n", __func__, mhl_fifo_status); if (mhl_fifo_status & 0x0C) { MHL_SII_REG_NAME_WR(REG_INTR5, 0x0C); pr_debug("%s: mhl fifo rst\n", __func__); MHL_SII_REG_NAME_WR(REG_SRST, 0x94); MHL_SII_REG_NAME_WR(REG_SRST, 0x84); } }
static void mhl_sii_cbus_process_errors(struct i2c_client *client, u8 int_status) { u8 abort_reason = 0; if (int_status & BIT2) { abort_reason = MHL_SII_REG_NAME_RD(REG_DDC_ABORT_REASON); pr_debug("%s: CBUS DDC Abort Reason(0x%02x)\n", __func__, abort_reason); } if (int_status & BIT5) { abort_reason = MHL_SII_REG_NAME_RD(REG_PRI_XFR_ABORT_REASON); pr_debug("%s: CBUS MSC Requestor Abort Reason(0x%02x)\n", __func__, abort_reason); MHL_SII_REG_NAME_WR(REG_PRI_XFR_ABORT_REASON, 0xFF); } if (int_status & BIT6) { abort_reason = MHL_SII_REG_NAME_RD( REG_CBUS_PRI_FWR_ABORT_REASON); pr_debug("%s: CBUS MSC Responder Abort Reason(0x%02x)\n", __func__, abort_reason); MHL_SII_REG_NAME_WR(REG_CBUS_PRI_FWR_ABORT_REASON, 0xFF); } }
static void mhl_msm_connection(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t val; struct i2c_client *client = mhl_ctrl->i2c_handle; pr_debug("%s: cur st [0x%x]\n", __func__, mhl_ctrl->cur_state); if (mhl_ctrl->cur_state == POWER_STATE_D0_MHL) { /* Already in D0 - MHL power state */ pr_err("%s: cur st not D0\n", __func__); return; } switch_mode(mhl_ctrl, POWER_STATE_D0_MHL, true); MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10); MHL_SII_CBUS_WR(0x07, 0xF2); /* * Keep the discovery enabled. Need RGND interrupt * Possibly chip disables discovery after MHL_EST?? * Need to re-enable here */ val = MHL_SII_PAGE3_RD(0x10); MHL_SII_PAGE3_WR(0x10, val | BIT0); /* * indicate DCAP_RDY and DCAP_CHG * to the peer only after * msm conn has been established */ mhl_msc_send_write_stat(mhl_ctrl, MHL_STATUS_REG_CONNECTED_RDY, MHL_STATUS_DCAP_RDY); mhl_msc_send_set_int(mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_DCAP_CHG, MSC_PRIORITY_SEND); }
static void switch_mode(struct mhl_tx_ctrl *mhl_ctrl, enum mhl_st_type to_mode) { struct i2c_client *client = mhl_ctrl->i2c_handle; switch (to_mode) { case POWER_STATE_D0_NO_MHL: mhl_ctrl->cur_state = to_mode; mhl_init_reg_settings(mhl_ctrl, true); /* REG_DISC_CTRL1 */ MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, BIT0); /* TPI_DEVICE_POWER_STATE_CTRL_REG */ mhl_i2c_reg_modify(client, TX_PAGE_TPI, 0x001E, BIT1 | BIT0, 0x00); break; case POWER_STATE_D0_MHL: mhl_ctrl->cur_state = to_mode; break; case POWER_STATE_D3: if (mhl_ctrl->cur_state == POWER_STATE_D3) break; /* Force HPD to 0 when not in MHL mode. */ mhl_drive_hpd(mhl_ctrl, HPD_DOWN); /* * Change TMDS termination to high impedance * on disconnection. */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0xD0); msleep(50); if (!mhl_ctrl->disc_enabled) MHL_SII_REG_NAME_MOD(REG_DISC_CTRL1, BIT1 | BIT0, 0x00); MHL_SII_PAGE3_MOD(0x003D, BIT0, 0x00); mhl_ctrl->cur_state = POWER_STATE_D3; break; default: break; } }
static void cbus_reset(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t i; struct i2c_client *client = mhl_ctrl->i2c_handle; /* * REG_SRST */ MHL_SII_REG_NAME_MOD(REG_SRST, BIT3, BIT3); msleep(20); MHL_SII_REG_NAME_MOD(REG_SRST, BIT3, 0x00); /* * REG_INTR1 and REG_INTR4 */ MHL_SII_REG_NAME_WR(REG_INTR1_MASK, BIT6); MHL_SII_REG_NAME_WR(REG_INTR4_MASK, BIT0 | BIT2 | BIT3 | BIT4 | BIT5 | BIT6); if (mhl_ctrl->chip_rev_id < 1) MHL_SII_REG_NAME_WR(REG_INTR5_MASK, BIT3 | BIT4); else MHL_SII_REG_NAME_WR(REG_INTR5_MASK, 0x00); /* Unmask CBUS1 Intrs */ MHL_SII_REG_NAME_WR(REG_CBUS_INTR_ENABLE, BIT2 | BIT3 | BIT4 | BIT5 | BIT6); /* Unmask CBUS2 Intrs */ MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_ENABLE, BIT2 | BIT3); for (i = 0; i < 4; i++) { /* * Enable WRITE_STAT interrupt for writes to * all 4 MSC Status registers. */ MHL_SII_CBUS_WR((0xE0 + i), 0xFF); /* * Enable SET_INT interrupt for writes to * all 4 MSC Interrupt registers. */ MHL_SII_CBUS_WR((0xF0 + i), 0xFF); } }
static int dev_detect_isr(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t status, reg; struct i2c_client *client = mhl_ctrl->i2c_handle; /* INTR_STATUS4 */ status = MHL_SII_REG_NAME_RD(REG_INTR4); pr_debug("%s: reg int4 st=%02X\n", __func__, status); if ((0x00 == status) &&\ (mhl_ctrl->cur_state == POWER_STATE_D3)) { pr_err("%s: invalid intr\n", __func__); return 0; } if (0xFF == status) { pr_debug("%s: invalid intr 0xff\n", __func__); MHL_SII_REG_NAME_WR(REG_INTR4, status); return 0; } if ((status & BIT0) && (mhl_ctrl->chip_rev_id < 1)) { pr_debug("%s: scdt intr\n", __func__); scdt_st_chg(client); } if (status & BIT1) pr_debug("mhl: int4 bit1 set\n"); /* mhl_est interrupt */ if (status & BIT2) { pr_debug("%s: mhl_est st=%02X\n", __func__, (int) status); mhl_msm_connection(mhl_ctrl); } else if (status & BIT3) { pr_debug("%s: uUSB-a type dev detct\n", __func__); /* Short RGND */ MHL_SII_REG_NAME_MOD(REG_DISC_STAT2, BIT0 | BIT1, 0x00); mhl_msm_disconnection(mhl_ctrl); power_supply_changed(&mhl_ctrl->mhl_psy); if (mhl_ctrl->notify_usb_online) mhl_ctrl->notify_usb_online(0); return -EACCES; } if (status & BIT5) { /* clr intr - reg int4 */ pr_debug("%s: mhl discon: int4 st=%02X\n", __func__, (int)status); reg = MHL_SII_REG_NAME_RD(REG_INTR4); MHL_SII_REG_NAME_WR(REG_INTR4, reg); mhl_msm_disconnection(mhl_ctrl); power_supply_changed(&mhl_ctrl->mhl_psy); if (mhl_ctrl->notify_usb_online) mhl_ctrl->notify_usb_online(0); return -EACCES; } if ((mhl_ctrl->cur_state != POWER_STATE_D0_NO_MHL) &&\ (status & BIT6)) { /* rgnd rdy Intr */ pr_debug("%s: rgnd ready intr\n", __func__); switch_mode(mhl_ctrl, POWER_STATE_D0_NO_MHL, true); mhl_msm_read_rgnd_int(mhl_ctrl); } /* Can't succeed at these in D3 */ if ((mhl_ctrl->cur_state != POWER_STATE_D3) &&\ (status & BIT4)) { /* cbus lockout interrupt? * Hardware detection mechanism figures that * CBUS line is latched and raises this intr * where we force usb switch open and release */ pr_warn("%s: cbus locked out!\n", __func__); force_usb_switch_open(mhl_ctrl); release_usb_switch_open(mhl_ctrl); } MHL_SII_REG_NAME_WR(REG_INTR4, status); return 0; }
/* * Configure the initial reg settings */ static void mhl_init_reg_settings(struct mhl_tx_ctrl *mhl_ctrl, bool mhl_disc_en) { uint8_t regval; /* * ============================================ * POWER UP * ============================================ */ struct i2c_client *client = mhl_ctrl->i2c_handle; /* Power up 1.2V core */ MHL_SII_PAGE1_WR(0x003D, 0x3F); /* Enable Tx PLL Clock */ MHL_SII_PAGE2_WR(0x0011, 0x01); /* Enable Tx Clock Path and Equalizer */ MHL_SII_PAGE2_WR(0x0012, 0x11); /* Tx Source Termination ON */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL1, 0x10); /* Enable 1X MHL Clock output */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL6, 0xBC); /* Tx Differential Driver Config */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL2, 0x3C); MHL_SII_REG_NAME_WR(REG_MHLTX_CTL4, 0xC8); /* PLL Bandwidth Control */ MHL_SII_REG_NAME_WR(REG_MHLTX_CTL7, 0x03); MHL_SII_REG_NAME_WR(REG_MHLTX_CTL8, 0x0A); /* * ============================================ * Analog PLL Control * ============================================ */ /* Enable Rx PLL clock */ MHL_SII_REG_NAME_WR(REG_TMDS_CCTRL, 0x08); MHL_SII_PAGE0_WR(0x00F8, 0x8C); MHL_SII_PAGE0_WR(0x0085, 0x02); MHL_SII_PAGE2_WR(0x0000, 0x00); regval = MHL_SII_PAGE2_RD(0x0005); regval &= ~BIT5; MHL_SII_PAGE2_WR(0x0005, regval); MHL_SII_PAGE2_WR(0x0013, 0x60); /* PLL Cal ref sel */ MHL_SII_PAGE2_WR(0x0017, 0x03); /* VCO Cal */ MHL_SII_PAGE2_WR(0x001A, 0x20); /* Auto EQ */ MHL_SII_PAGE2_WR(0x0022, 0xE0); MHL_SII_PAGE2_WR(0x0023, 0xC0); MHL_SII_PAGE2_WR(0x0024, 0xA0); MHL_SII_PAGE2_WR(0x0025, 0x80); MHL_SII_PAGE2_WR(0x0026, 0x60); MHL_SII_PAGE2_WR(0x0027, 0x40); MHL_SII_PAGE2_WR(0x0028, 0x20); MHL_SII_PAGE2_WR(0x0029, 0x00); /* Rx PLL Bandwidth 4MHz */ MHL_SII_PAGE2_WR(0x0031, 0x0A); /* Rx PLL Bandwidth value from I2C */ MHL_SII_PAGE2_WR(0x0045, 0x06); MHL_SII_PAGE2_WR(0x004B, 0x06); MHL_SII_PAGE2_WR(0x004C, 0x60); /* Manual zone control */ MHL_SII_PAGE2_WR(0x004C, 0xE0); /* PLL Mode value */ MHL_SII_PAGE2_WR(0x004D, 0x00); MHL_SII_PAGE0_WR(0x0008, 0x35); /* * Discovery Control and Status regs * Setting De-glitch time to 50 ms (default) * Switch Control Disabled */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL2, 0xAD); /* 1.8V CBUS VTH */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL5, 0x57); /* RGND and single Discovery attempt */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL6, 0x11); /* Ignore VBUS */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL8, 0x82); /* Enable CBUS Discovery */ if (mhl_disc_en) { MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x24); /* Enable MHL Discovery */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x27); /* Pull-up resistance off for IDLE state */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C); } else { MHL_SII_REG_NAME_WR(REG_DISC_CTRL9, 0x26); /* Disable MHL Discovery */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL1, 0x26); MHL_SII_REG_NAME_WR(REG_DISC_CTRL4, 0x8C); } MHL_SII_REG_NAME_WR(REG_DISC_CTRL7, 0x20); /* MHL CBUS Discovery - immediate comm. */ MHL_SII_REG_NAME_WR(REG_DISC_CTRL3, 0x86); MHL_SII_PAGE3_WR(0x3C, 0x80); if (mhl_ctrl->cur_state != POWER_STATE_D3) MHL_SII_REG_NAME_MOD(REG_INT_CTRL, BIT6 | BIT5 | BIT4, BIT4); /* Enable Auto Soft RESET */ MHL_SII_REG_NAME_WR(REG_SRST, 0x084); /* HDMI Transcode mode enable */ MHL_SII_PAGE0_WR(0x000D, 0x1C); cbus_reset(mhl_ctrl); init_cbus_regs(client); }
static void mhl_cbus_isr(struct mhl_tx_ctrl *mhl_ctrl) { uint8_t regval; int req_done = 0; uint8_t sub_cmd = 0x0; uint8_t cmd_data = 0x0; int msc_msg_recved = 0; int rc = -1; struct i2c_client *client = mhl_ctrl->i2c_handle; regval = MHL_SII_REG_NAME_RD(REG_CBUS_INTR_STATUS); if (regval == 0xff) return; if (regval) MHL_SII_REG_NAME_WR(REG_CBUS_INTR_STATUS, regval); pr_debug("%s: CBUS_INT = %02x\n", __func__, regval); /* MSC_MSG (RCP/RAP) */ if (regval & BIT3) { sub_cmd = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_CMD); cmd_data = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_VS_DATA); msc_msg_recved = 1; } /* MSC_MT_ABRT/MSC_MR_ABRT/DDC_ABORT */ if (regval & (BIT6 | BIT5 | BIT2)) mhl_sii_cbus_process_errors(client, regval); /* MSC_REQ_DONE */ if (regval & BIT4) req_done = 1; /* look for interrupts on CBUS_MSC_INT2 */ regval = MHL_SII_REG_NAME_RD(REG_CBUS_MSC_INT2_STATUS); /* clear all interrupts */ if (regval) MHL_SII_REG_NAME_WR(REG_CBUS_MSC_INT2_STATUS, regval); pr_debug("%s: CBUS_MSC_INT2 = %02x\n", __func__, regval); /* received SET_INT */ if (regval & BIT2) { uint8_t intr; intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_0); MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_0, intr); mhl_msc_recv_set_int(mhl_ctrl, 0, intr); pr_debug("%s: MHL_INT_0 = %02x\n", __func__, intr); intr = MHL_SII_REG_NAME_RD(REG_CBUS_SET_INT_1); MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_1, intr); mhl_msc_recv_set_int(mhl_ctrl, 1, intr); pr_debug("%s: MHL_INT_1 = %02x\n", __func__, intr); MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_2, 0xFF); MHL_SII_REG_NAME_WR(REG_CBUS_SET_INT_3, 0xFF); } /* received WRITE_STAT */ if (regval & BIT3) { uint8_t stat; stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_0); mhl_msc_recv_write_stat(mhl_ctrl, 0, stat); pr_debug("%s: MHL_STATUS_0 = %02x\n", __func__, stat); stat = MHL_SII_REG_NAME_RD(REG_CBUS_WRITE_STAT_1); mhl_msc_recv_write_stat(mhl_ctrl, 1, stat); pr_debug("%s: MHL_STATUS_1 = %02x\n", __func__, stat); MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_0, 0xFF); MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_1, 0xFF); MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_2, 0xFF); MHL_SII_REG_NAME_WR(REG_CBUS_WRITE_STAT_3, 0xFF); } /* received MSC_MSG */ if (msc_msg_recved) { /*mhl msc recv msc msg*/ rc = mhl_msc_recv_msc_msg(mhl_ctrl, 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_ctrl->msc_cmd_done); }
int mhl_send_msc_command(struct mhl_tx_ctrl *mhl_ctrl, struct msc_command_struct *req) { int timeout; u8 start_bit = 0x00; u8 *burst_data; int i; struct i2c_client *client = mhl_ctrl->i2c_handle; if (mhl_ctrl->cur_state != POWER_STATE_D0_MHL) { pr_debug("%s: power_state:%02x CBUS(0x0A):%02x\n", __func__, mhl_ctrl->cur_state, MHL_SII_REG_NAME_RD(REG_CBUS_BUS_STATUS)); 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]); /* REG_CBUS_PRI_ADDR_CMD = REQ CBUS CMD or OFFSET */ MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->offset); MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_1ST, 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_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command); break; case MHL_MSC_MSG: start_bit = MSC_START_BIT_VS_CMD; MHL_SII_REG_NAME_WR(REG_CBUS_PRI_WR_DATA_2ND, req->payload.data[1]); MHL_SII_REG_NAME_WR(REG_CBUS_PRI_ADDR_CMD, req->command); break; case MHL_WRITE_BURST: start_bit = MSC_START_BIT_WRITE_BURST; MHL_SII_REG_NAME_WR(REG_MSC_WRITE_BURST_LEN, 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_SII_REG_NAME_WR(REG_CBUS_SCRATCHPAD_0 + i, *burst_data); break; default: pr_err("%s: unknown command! (%02x)\n", __func__, req->command); goto cbus_send_fail; } INIT_COMPLETION(mhl_ctrl->msc_cmd_done); MHL_SII_REG_NAME_WR(REG_CBUS_PRI_START, start_bit); timeout = wait_for_completion_interruptible_timeout (&mhl_ctrl->msc_cmd_done, msecs_to_jiffies(T_ABORT_NEXT)); if (!timeout) { pr_err("%s: cbus_command_send timed out!\n", __func__); goto cbus_send_fail; } switch (req->command) { case MHL_READ_DEVCAP: req->retval = MHL_SII_REG_NAME_RD(REG_CBUS_PRI_RD_DATA_1ST); break; case MHL_MSC_MSG: /* check if MSC_MSG NACKed */ if (MHL_SII_REG_NAME_RD(REG_MSC_WRITE_BURST_LEN) & BIT6) return -EAGAIN; default: req->retval = 0; break; } mhl_msc_command_done(mhl_ctrl, req); pr_debug("%s: msc cmd done\n", __func__); return 0; cbus_send_fail: return -EFAULT; }
static void clear_all_intrs(struct i2c_client *client) { uint8_t regval = 0x00; pr_debug_intr("********* exiting isr mask check ?? *************\n"); pr_debug_intr("int1 mask = %02X\n", (int) MHL_SII_REG_NAME_RD(REG_INTR1)); pr_debug_intr("int3 mask = %02X\n", (int) MHL_SII_PAGE0_RD(0x0077)); pr_debug_intr("int4 mask = %02X\n", (int) MHL_SII_REG_NAME_RD(REG_INTR4)); pr_debug_intr("int5 mask = %02X\n", (int) MHL_SII_REG_NAME_RD(REG_INTR5)); pr_debug_intr("cbus1 mask = %02X\n", (int) MHL_SII_CBUS_RD(0x0009)); pr_debug_intr("cbus2 mask = %02X\n", (int) MHL_SII_CBUS_RD(0x001F)); pr_debug_intr("********* end of isr mask check *************\n"); regval = MHL_SII_REG_NAME_RD(REG_INTR1); pr_debug_intr("int1 st = %02X\n", (int)regval); MHL_SII_REG_NAME_WR(REG_INTR1, regval); regval = MHL_SII_REG_NAME_RD(REG_INTR2); pr_debug_intr("int2 st = %02X\n", (int)regval); MHL_SII_REG_NAME_WR(REG_INTR2, regval); regval = MHL_SII_PAGE0_RD(0x0073); pr_debug_intr("int3 st = %02X\n", (int)regval); MHL_SII_PAGE0_WR(0x0073, regval); regval = MHL_SII_REG_NAME_RD(REG_INTR4); pr_debug_intr("int4 st = %02X\n", (int)regval); MHL_SII_REG_NAME_WR(REG_INTR4, regval); regval = MHL_SII_REG_NAME_RD(REG_INTR5); pr_debug_intr("int5 st = %02X\n", (int)regval); MHL_SII_REG_NAME_WR(REG_INTR5, regval); regval = MHL_SII_CBUS_RD(0x0008); pr_debug_intr("cbusInt st = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x0008, regval); regval = MHL_SII_CBUS_RD(0x001E); pr_debug_intr("CBUS intR_2: %d\n", (int)regval); MHL_SII_CBUS_WR(0x001E, regval); regval = MHL_SII_CBUS_RD(0x00A0); pr_debug_intr("A0 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00A0, regval); regval = MHL_SII_CBUS_RD(0x00A1); pr_debug_intr("A1 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00A1, regval); regval = MHL_SII_CBUS_RD(0x00A2); pr_debug_intr("A2 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00A2, regval); regval = MHL_SII_CBUS_RD(0x00A3); pr_debug_intr("A3 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00A3, regval); regval = MHL_SII_CBUS_RD(0x00B0); pr_debug_intr("B0 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00B0, regval); regval = MHL_SII_CBUS_RD(0x00B1); pr_debug_intr("B1 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00B1, regval); regval = MHL_SII_CBUS_RD(0x00B2); pr_debug_intr("B2 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00B2, regval); regval = MHL_SII_CBUS_RD(0x00B3); pr_debug_intr("B3 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00B3, regval); regval = MHL_SII_CBUS_RD(0x00E0); pr_debug_intr("E0 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00E0, regval); regval = MHL_SII_CBUS_RD(0x00E1); pr_debug_intr("E1 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00E1, regval); regval = MHL_SII_CBUS_RD(0x00E2); pr_debug_intr("E2 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00E2, regval); regval = MHL_SII_CBUS_RD(0x00E3); pr_debug_intr("E3 st set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00E3, regval); regval = MHL_SII_CBUS_RD(0x00F0); pr_debug_intr("F0 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00F0, regval); regval = MHL_SII_CBUS_RD(0x00F1); pr_debug_intr("F1 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00F1, regval); regval = MHL_SII_CBUS_RD(0x00F2); pr_debug_intr("F2 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00F2, regval); regval = MHL_SII_CBUS_RD(0x00F3); pr_debug_intr("F3 int set = %02X\n", (int)regval); MHL_SII_CBUS_WR(0x00F3, regval); pr_debug_intr("********* end of exiting in isr *************\n"); }