int mhl_msc_recv_set_int(struct mhl_tx_ctrl *mhl_ctrl, u8 offset, u8 set_int) { int prior; if (offset >= 2) return -EFAULT; switch (offset) { case 0: if (set_int & MHL_INT_DCAP_CHG) { /* peer dcap has changed */ mhl_ctrl->devcap_state = 0; mhl_msc_read_devcap_all(mhl_ctrl); } if (set_int & MHL_INT_DSCR_CHG) { /* peer's scratchpad reg changed */ pr_debug("%s: dscr chg\n", __func__); mhl_read_scratchpad(mhl_ctrl); mhl_ctrl->scrpd_busy = false; mhl_notify_event(mhl_ctrl, MHL_TX_EVENT_DSCR_CHG); } if (set_int & MHL_INT_REQ_WRT) { /* SET_INT: REQ_WRT */ if (mhl_ctrl->scrpd_busy) { prior = MSC_NORMAL_SEND; } else { prior = MSC_PRIORITY_SEND; mhl_ctrl->scrpd_busy = true; } mhl_msc_send_set_int( mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_GRT_WRT, prior); } if (set_int & MHL_INT_GRT_WRT) { /* SET_INT: GRT_WRT */ pr_debug("%s: recvd req to permit/grant write", __func__); complete_all(&mhl_ctrl->req_write_done); mhl_msc_write_burst( mhl_ctrl, MHL_SCRATCHPAD_OFFSET, mhl_ctrl->scrpd.data, mhl_ctrl->scrpd.length); } break; case 1: if (set_int & MHL_INT_EDID_CHG) { /* peer EDID has changed * toggle HPD to read EDID */ pr_debug("%s: EDID CHG\n", __func__); mhl_drive_hpd(mhl_ctrl, HPD_DOWN); msleep(110); mhl_drive_hpd(mhl_ctrl, HPD_UP); } } return 0; }
int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl, struct msc_command_struct *req) { bool dongle_pwr_en = false; switch (req->command) { case MHL_WRITE_STAT: if (req->offset == MHL_STATUS_REG_LINK_MODE) { if (req->payload.data[0] & MHL_STATUS_PATH_ENABLED) { /* Enable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); if (mhl_ctrl->devcap_state == MHL_DEVCAP_ALL) { dongle_pwr_en = mhl_ctrl->devcap[ MHL_DEV_CATEGORY_OFFSET] & MHL_DEV_CATEGORY_POW_BIT; if (dongle_pwr_en) mhl_drive_hpd(mhl_ctrl, HPD_UP); } } else { /* Disable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE); mhl_drive_hpd(mhl_ctrl, HPD_DOWN); } } break; case MHL_READ_DEVCAP: mhl_update_devcap(mhl_ctrl, req->offset, req->retval); mhl_ctrl->devcap_state |= BIT(req->offset); switch (req->offset) { case MHL_DEV_CATEGORY_OFFSET: if (req->retval & MHL_DEV_CATEGORY_POW_BIT) pr_debug("%s: devcap pow bit set\n", __func__); else pr_debug("%s: devcap pow bit unset\n", __func__); break; case DEVCAP_OFFSET_RESERVED: mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); mhl_drive_hpd(mhl_ctrl, HPD_UP); break; case DEVCAP_OFFSET_MHL_VERSION: case DEVCAP_OFFSET_INT_STAT_SIZE: if (mhl_qualify_path_enable(mhl_ctrl)) mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); break; } break; case MHL_WRITE_BURST: mhl_msc_send_set_int( mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_DSCR_CHG, MSC_PRIORITY_SEND); break; } return 0; }
int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl, struct msc_command_struct *req) { switch (req->command) { case MHL_WRITE_STAT: if (req->offset == MHL_STATUS_REG_LINK_MODE) { if (req->payload.data[0] & MHL_STATUS_PATH_ENABLED) { /* Enable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); if (mhl_ctrl->devcap_state == MHL_DEVCAP_ALL) { mhl_drive_hpd(mhl_ctrl, HPD_UP); mhl_ctrl->tmds_ctrl_en = true; } } else { /* Disable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE); mhl_drive_hpd(mhl_ctrl, HPD_DOWN); } } break; case MHL_READ_DEVCAP: mhl_update_devcap(mhl_ctrl, req->offset, req->retval); mhl_ctrl->devcap_state |= BIT(req->offset); switch (req->offset) { case MHL_DEV_CATEGORY_OFFSET: if (req->retval & MHL_DEV_CATEGORY_POW_BIT) pr_debug("%s: devcap pow bit set\n", __func__); else pr_debug("%s: devcap pow bit unset\n", __func__); power_supply_set_present(&mhl_ctrl->mhl_psy, !!(req->retval & MHL_DEV_CATEGORY_POW_BIT)); break; case DEVCAP_OFFSET_FEATURE_FLAG: mhl_rap_send_msc_msg(mhl_ctrl, MHL_RAP_CONTENT_ON); break; case DEVCAP_OFFSET_RESERVED: if (mhl_qualify_path_enable(mhl_ctrl)) { mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); mhl_drive_hpd(mhl_ctrl, HPD_UP); mhl_ctrl->tmds_ctrl_en = true; } break; } break; case MHL_WRITE_BURST: mhl_msc_send_set_int( mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_DSCR_CHG, MSC_PRIORITY_SEND); break; } return 0; }
static int mhl_request_write_burst(struct mhl_tx_ctrl *mhl_ctrl, u8 start_reg, u8 length, u8 *data) { int i, reg; int timeout, retry = 20; if (!(mhl_ctrl->devcap[DEVCAP_OFFSET_FEATURE_FLAG] & MHL_FEATURE_SP_SUPPORT)) { pr_debug("MHL: SCRATCHPAD_NOT_SUPPORTED\n"); return -EFAULT; } /* * scratchpad remains busy as long as a peer's permission or * write bursts are pending; experimentally it was found that * 50ms is optimal */ while (mhl_ctrl->scrpd_busy && retry--) msleep(50); if (!retry) { pr_debug("MHL: scratchpad_busy\n"); return -EBUSY; } for (i = 0, reg = start_reg; (i < length) && (reg < MHL_SCRATCHPAD_SIZE); i++, reg++) mhl_ctrl->scrpd.data[reg] = data[i]; mhl_ctrl->scrpd.length = length; mhl_ctrl->scrpd.offset = start_reg; retry = 5; do { init_completion(&mhl_ctrl->req_write_done); mhl_msc_send_set_int( mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_REQ_WRT, MSC_PRIORITY_SEND); timeout = wait_for_completion_interruptible_timeout( &mhl_ctrl->req_write_done, msecs_to_jiffies(MHL_BURST_WAIT)); if (!timeout) mhl_ctrl->scrpd_busy = false; } while (retry-- && timeout == 0); if (!timeout) { pr_err("%s: timed out!\n", __func__); return -EAGAIN; } return 0; }
int mhl_msc_command_done(struct mhl_tx_ctrl *mhl_ctrl, struct msc_command_struct *req) { switch (req->command) { case MHL_WRITE_STAT: if (req->offset == MHL_STATUS_REG_LINK_MODE) { if (req->payload.data[0] & MHL_STATUS_PATH_ENABLED) /* Enable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_ENABLE); else /* Disable TMDS output */ mhl_tmds_ctrl(mhl_ctrl, TMDS_DISABLE); } break; case MHL_READ_DEVCAP: mhl_update_devcap(mhl_ctrl, req->offset, req->retval); mhl_ctrl->devcap_state |= BIT(req->offset); switch (req->offset) { case MHL_DEV_CATEGORY_OFFSET: if (req->retval & MHL_DEV_CATEGORY_POW_BIT) pr_debug("%s: devcap pow bit set\n", __func__); else pr_debug("%s: devcap pow bit unset\n", __func__); break; case DEVCAP_OFFSET_MHL_VERSION: case DEVCAP_OFFSET_INT_STAT_SIZE: break; } break; case MHL_WRITE_BURST: mhl_msc_send_set_int( mhl_ctrl, MHL_RCHANGE_INT, MHL_INT_DSCR_CHG, MSC_PRIORITY_SEND); break; } return 0; }
static int mhl_msc_recv_set_int(u8 offset, u8 set_int) { if (offset >= 2) return -EFAULT; switch (offset) { case 0: /* DCAP_CHG */ if (set_int & MHL_INT_DCAP_CHG) { /* peer dcap has changed */ if (mhl_msc_read_devcap_all() == -EBUSY) { pr_err("READ DEVCAP FAILED to send successfully\n"); break; } } /* DSCR_CHG */ if (set_int & MHL_INT_DSCR_CHG) ; /* REQ_WRT */ if (set_int & MHL_INT_REQ_WRT) { /* SET_INT: GRT_WRT */ mhl_msc_send_set_int( MHL_RCHANGE_INT, MHL_INT_GRT_WRT); } /* GRT_WRT */ if (set_int & MHL_INT_GRT_WRT) ; break; case 1: /* EDID_CHG */ if (set_int & MHL_INT_EDID_CHG) { /* peer EDID has changed. * toggle HPD to read EDID again * In 8x30 FLUID HDMI HPD line * is not connected * with MHL 8334 transmitter */ } } return 0; }
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 int mhl_msc_recv_set_int(u8 offset, u8 set_int) { if (offset >= 2) return -EFAULT; switch (offset) { case 0: if (set_int & MHL_INT_DCAP_CHG) { if (mhl_msc_read_devcap_all() == -EBUSY) { pr_err("READ DEVCAP FAILED to send successfully\n"); break; } } if (set_int & MHL_INT_DSCR_CHG) ; if (set_int & MHL_INT_REQ_WRT) { mhl_msc_send_set_int( MHL_RCHANGE_INT, MHL_INT_GRT_WRT); } if (set_int & MHL_INT_GRT_WRT) ; break; case 1: if (set_int & MHL_INT_EDID_CHG) { } } return 0; }