Example #1
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;
	}
	/* 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;
	}
}
Example #3
0
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);

}
Example #10
0
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;
	}
}
Example #11
0
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);
	}
}
Example #12
0
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;
}
Example #13
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);
}
Example #14
0
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);

}
Example #15
0
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;
}
Example #16
0
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");
}