예제 #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;
}
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;
}
예제 #7
0
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;
}
예제 #8
0
/*
 * 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();
}
예제 #9
0
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);
}
예제 #10
0
/* 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;
}