Beispiel #1
0
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;
}
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;
}