예제 #1
0
/*MHL call this function to change VAUDIO path*/
void FSA9480_CheckAndHookAudioDock(void)
{
   struct fsa9480_platform_data *pdata = chip->pdata;
   struct i2c_client *client = chip->client;

   printk("[FSA9480] %s: FSA9485 VAUDIO\n",__func__);
   
   isMHLconnected = 0;
   isDeskdockconnected = 1;
   
   if (pdata->mhl_cb)
   	       pdata->mhl_cb(FSA9480_DETACHED);

   EnableFSA9480Interrupts();

   if(chip->id == 0)
	chip->mansw = VAUDIO_9485;
   else
	chip->mansw = VAUDIO;

   /*make ID change report*/
   fsa9480_write_reg(client,FSA9480_REG_CTRL, 0x16);
   
   if(pdata->deskdock_cb)
           pdata->deskdock_cb(FSA9480_ATTACHED);   

}
예제 #2
0
static irqreturn_t fsa9485_irq_thread(int irq, void *data)
{
	struct fsa9485_usbsw *usbsw = data;
	struct i2c_client *client = usbsw->client;
	int intr, intr2, detect;

	DisableFSA9480Interrupts();
	/* FSA9485 : Read interrupt -> Read Device
	 FSA9485 : Read Device -> Read interrupt */
	mutex_lock(&usbsw->mutex);
	if (is_ti_muic())
		msleep(50);
	pr_info("fsa9485_irq_thread is called\n");

	/* read and clear interrupt status bits */
	intr = i2c_smbus_read_byte_data(client, FSA9485_REG_INT1);
	dev_info(&client->dev, "%s: intr : 0x%x",
					__func__, intr & 0xff);

	intr2 = i2c_smbus_read_byte_data(client, FSA9485_REG_INT2);
	dev_info(&client->dev, "%s: intr2 : 0x%x\n",
					__func__, intr2 & 0xff);

	local_usbsw->last_state.int1 = intr;
	local_usbsw->last_state.int2 = intr2;

	if (intr & INT_OVP_EN)
		usbsw->pdata->oxp_callback(ENABLE);
	else if (intr & INT_OXP_DISABLE)
		usbsw->pdata->oxp_callback(DISABLE);

	if (intr == (INT_ATTACH + INT_DETACH)) {
		fsa9485_detach_dev(usbsw);
		EnableFSA9480Interrupts();
		return IRQ_HANDLED;
	}

	/* device detection */
	detect = fsa9485_detect_dev(usbsw);
	mutex_unlock(&usbsw->mutex);
	pr_info("%s: detect dev_adc: %x\n", __func__, detect);

	EnableFSA9480Interrupts();

	return IRQ_HANDLED;
}
예제 #3
0
void FSA9480_MhlSwitchSel(bool sw) 
{
	struct i2c_client *client = local_usbsw->client;
	//struct power_supply *mhl_power_supply = power_supply_get_by_name("battery");
	//	union power_supply_propval value;
    printk("[FSA] mutex_lock\n");
	//mutex_lock(&FSA9480_MhlSwitchSel_lock);//avoid race condtion between mhl and hpd
	if(sw)
	{
               sii9234_cfg_power(1);
		if (gv_intr2&0x1) //cts: fix for 3355
		{
			mhl_vbus = true;
			mhl_power_supply=1;
			local_pdata->charger_cb(FSA9480_ATTACHED);
			gv_intr2=0;
			printk("vbus_power is detected\n");
		}

		SiI9234_init();
	}
	
	else
	{
		if (tegra_dc_hdmi_hpd())
		{
			printk("[FSA] Turn off hdmi\n");
			mhl_hpd_handler(false);
		}
                      if(mhl_power_supply==1)
			{
				mhl_power_supply=0;
				local_pdata->charger_cb(FSA9480_DETACHED);
                       	}
		mhl_vbus = false;
		sii9234_cfg_power(0);	//Turn Off power to SiI9234
	}

	/********************FSA-MHL-FSA Switching start***************************/
	DisableFSA9480Interrupts();
	{
		//gpio_set_value_cansleep(GPIO_MHL_SEL, sw);
		sii9234_switch_onoff(sw);
		
		i2c_smbus_read_byte_data(client, FSA9480_REG_INT1);
	}
	EnableFSA9480Interrupts();
	/******************FSA-MHL-FSA Switching End*******************************/
	//mutex_unlock(&FSA9480_MhlSwitchSel_lock);

    printk("[FSA] mutex_unlock\n");
}
예제 #4
0
void FSA9480_EnableIntrruptByMHL(bool _bDo)
{
	struct fsa9480_platform_data *pdata = chip->pdata;
	struct i2c_client *client = chip->client;
	char buf[16];

	if(true == _bDo)
	{
		fsa9480_write_reg(client,FSA9480_REG_CTRL, 0x1E);
		EnableFSA9480Interrupts();
	}
	else
	{
		DisableFSA9480Interrupts();
	}

	fsa9480_get_switch(buf);
	printk("[%s] fsa switch status = %s\n",__func__, buf);
}
예제 #5
0
void FSA9480_MhlTvOff(void)
{
	struct i2c_client *client =  local_usbsw->client;
	int intr1;
	DisableFSA9480Interrupts();
	//printk(KERN_ERR "%s: started######\n", __func__);
	intr1 = i2c_smbus_read_word_data(client, FSA9480_REG_INT1);
	gpio_set_value(GPIO_MHL_SEL, 0);	
	do
	{
		msleep(5);
		intr1 = i2c_smbus_read_byte_data(client, FSA9480_REG_INT1);
	}while(!intr1);

	mhl_cable_status =0x08;//MHL_TV_OFF_CABLE_CONNECT;
	EnableFSA9480Interrupts();
	//printk(KERN_ERR "%s: End######\n",__func__);
	printk("%s:  interrupt1= %d\n", __func__, intr1);
}
예제 #6
0
static int fsa9485_detect_dev(struct fsa9485_usbsw *usbsw)
{
	int device_type, ret;
	unsigned int val1, val2, adc;
	struct fsa9485_platform_data *pdata = usbsw->pdata;
	struct i2c_client *client = usbsw->client;
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
	u8 mhl_ret = 0;
#endif
	device_type = i2c_smbus_read_word_data(client, FSA9485_REG_DEV_T1);
	if (device_type < 0) {
		dev_err(&client->dev, "%s: err %d\n", __func__, device_type);
		return device_type;
	}
	val1 = device_type & 0xff;
	val2 = device_type >> 8;
	adc = i2c_smbus_read_byte_data(client, FSA9485_REG_ADC);

	if (usbsw->dock_attached)
		pdata->dock_cb(FSA9485_DETACHED_DOCK);

	if (adc == 0x10)
		val2 = DEV_SMARTDOCK;
	else if (adc == 0x12)
		val2 = DEV_AUDIO_DOCK;

	dev_info(&client->dev, "dev1: 0x%x, dev2: 0x%x adc : 0x%x\n", val1, val2, adc);

	/* Attached */
	if (val1 || val2) {
		/* USB */
		if (val1 & DEV_USB || val2 & DEV_T2_USB_MASK) {
			dev_info(&client->dev, "usb connect\n");

		if (pdata->usb_cb) {
				if (force_fast_charge != 0) {
				  dev_info(&client->dev, "[imoseyon] fastcharge\n");
				  pdata->charger_cb(FSA9485_ATTACHED);
				} else pdata->usb_cb(FSA9485_ATTACHED);
			}

			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
				FSA9485_REG_MANSW1, usbsw->mansw);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}
		/* USB_CDP */
		} else if (val1 & DEV_USB_CHG) {
			dev_info(&client->dev, "usb_cdp connect\n");

			if (pdata->usb_cdp_cb)
				pdata->usb_cdp_cb(FSA9485_ATTACHED);
			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
				FSA9485_REG_MANSW1, usbsw->mansw);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}

		/* UART */
		} else if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
			uart_connecting = 1;
			dev_info(&client->dev, "uart connect\n");
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1E);
			if (pdata->uart_cb)
				pdata->uart_cb(FSA9485_ATTACHED);

			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_UART);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}
		/* CHARGER */
		} else if (val1 & DEV_T1_CHARGER_MASK) {
			dev_info(&client->dev, "charger connect\n");

			if (pdata->charger_cb)
				pdata->charger_cb(FSA9485_ATTACHED);
		/* for SAMSUNG OTG */
		} else if (val1 & DEV_USB_OTG) {
			dev_info(&client->dev, "otg connect\n");
			if (pdata->otg_cb)
				pdata->otg_cb(FSA9485_ATTACHED);
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_MANSW1, 0x27);
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_MANSW2, 0x02);
			msleep(50);
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1a);
		/* JIG */
		} else if (val2 & DEV_T2_JIG_MASK) {
			dev_info(&client->dev, "jig connect\n");

			if (pdata->jig_cb)
				pdata->jig_cb(FSA9485_ATTACHED);
		/* Desk Dock */
		} else if (val2 & DEV_AV) {
			if ((adc & 0x1F) == ADC_DESKDOCK) {
				pr_info("FSA Deskdock Attach\n");
				FSA9485_CheckAndHookAudioDock(1);
				usbsw->deskdock = 1;
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
				isDeskdockconnected = 1;
#endif
				i2c_smbus_write_byte_data(client,
						FSA9485_REG_RESERVED_20, 0x08);
			} else {
				pr_info("FSA MHL Attach\n");
				i2c_smbus_write_byte_data(client,
						FSA9485_REG_RESERVED_20, 0x08);
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
				DisableFSA9480Interrupts();
				if (!isDeskdockconnected)
					mhl_ret = mhl_onoff_ex(1);

				if (mhl_ret != MHL_DEVICE &&
						(adc & 0x1F) == 0x1A) {
					FSA9485_CheckAndHookAudioDock(1);
					isDeskdockconnected = 1;
				}
				EnableFSA9480Interrupts();
#else
				pr_info("FSA mhl attach, but not support MHL feature!\n");
#endif
			}
		/* Car Dock */
		} else if (val2 & DEV_JIG_UART_ON) {
			if (pdata->dock_cb)
				pdata->dock_cb(FSA9485_ATTACHED_CAR_DOCK);
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_AUDIO);

			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			usbsw->dock_attached = FSA9485_ATTACHED;
		/* SmartDock */
		} else if (val2 & DEV_SMARTDOCK) {
			usbsw->adc = adc;
			dev_info(&client->dev, "smart dock connect\n");

			usbsw->mansw = SW_DHOST;
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_DHOST);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			if (pdata->smartdock_cb)
				pdata->smartdock_cb(FSA9485_ATTACHED);
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
			mhl_onoff_ex(1);
#endif
		} else if (val2 & DEV_AUDIO_DOCK) {
			usbsw->adc = adc;
			dev_info(&client->dev, "audio dock connect\n");

			usbsw->mansw = SW_DHOST;
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_DHOST);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			if (pdata->smartdock_cb)
				pdata->audio_dock_cb(FSA9485_ATTACHED);
		}
	/* Detached */
	} else {
		/* USB */
		if (usbsw->dev1 & DEV_USB ||
				usbsw->dev2 & DEV_T2_USB_MASK) {
			if (pdata->usb_cb)
				pdata->usb_cb(FSA9485_DETACHED);
		} else if (usbsw->dev1 & DEV_USB_CHG) {
			if (pdata->usb_cdp_cb)
				pdata->usb_cdp_cb(FSA9485_DETACHED);

		/* UART */
		} else if (usbsw->dev1 & DEV_T1_UART_MASK ||
				usbsw->dev2 & DEV_T2_UART_MASK) {
			if (pdata->uart_cb)
				pdata->uart_cb(FSA9485_DETACHED);
			uart_connecting = 0;
			dev_info(&client->dev, "[FSA9485] uart disconnect\n");

		/* CHARGER */
		} else if (usbsw->dev1 & DEV_T1_CHARGER_MASK) {
			if (pdata->charger_cb)
				pdata->charger_cb(FSA9485_DETACHED);
		/* for SAMSUNG OTG */
		} else if (usbsw->dev1 & DEV_USB_OTG) {
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1E);
		/* JIG */
		} else if (usbsw->dev2 & DEV_T2_JIG_MASK) {
			if (pdata->jig_cb)
				pdata->jig_cb(FSA9485_DETACHED);
		/* Desk Dock */
		} else if (usbsw->dev2 & DEV_AV) {

			pr_info("FSA MHL Detach\n");
			i2c_smbus_write_byte_data(client,
					FSA9485_REG_RESERVED_20, 0x04);
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
			if (isDeskdockconnected)
				FSA9485_CheckAndHookAudioDock(0);
#if defined CONFIG_MHL_D3_SUPPORT
			mhl_onoff_ex(false);
			detached_status = 1;
#endif
			isDeskdockconnected = 0;
#else
			if (usbsw->deskdock) {
				FSA9485_CheckAndHookAudioDock(0);
				usbsw->deskdock = 0;
			} else {
				pr_info("FSA detach mhl cable, but not support MHL feature\n");
			}
#endif
		/* Car Dock */
		} else if (usbsw->dev2 & DEV_JIG_UART_ON) {
			if (pdata->dock_cb)
				pdata->dock_cb(FSA9485_DETACHED_DOCK);
				ret = i2c_smbus_read_byte_data(client,
						FSA9485_REG_CTRL);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

				ret = i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL,
						ret | CON_MANUAL_SW);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
				usbsw->dock_attached = FSA9485_DETACHED;
		} else if (usbsw->adc == 0x10) {
			dev_info(&client->dev, "smart dock disconnect\n");

			ret = i2c_smbus_read_byte_data(client,
						FSA9485_REG_CTRL);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
				ret = i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL,
						ret | CON_MANUAL_SW);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			if (pdata->smartdock_cb)
				pdata->smartdock_cb(FSA9485_DETACHED);
			usbsw->adc = 0;
#if defined(CONFIG_VIDEO_MHL_V1) || defined(CONFIG_VIDEO_MHL_V2)
			mhl_onoff_ex(false);
#endif
		} else if (usbsw->adc == 0x12) {
			dev_info(&client->dev, "audio dock disconnect\n");

			ret = i2c_smbus_read_byte_data(client,
						FSA9485_REG_CTRL);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
				ret = i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL,
						ret | CON_MANUAL_SW);
				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			if (pdata->smartdock_cb)
				pdata->audio_dock_cb(FSA9485_DETACHED);
			usbsw->adc = 0;
		}

	}
	usbsw->dev1 = val1;
	usbsw->dev2 = val2;

	return adc;
}
예제 #7
0
void mhl_onff_handler(struct work_struct *work) //Rajucm
{	
	// struct i2c_client *client = local_usbsw->client;
	printk("praveen: mhl on off handler\n");

	//Rajucm: phone Power on with MHL Cable,avoid crash
	while((!SII9234_i2c_status))
	{	//4Control enters into while loop only when fsa9480 detects MHL-cable @ phone bootup
		//printk(KERN_ERR"[FSA9480]## mhl cable detected during boot ## \n");
		//i2c_smbus_write_byte_data(client, 0x02, (0x01|i2c_smbus_read_byte_data(client, 0x02)));	//DisableFSA9480Interrupts
		if(!sec_get_lpm_mode())
		{
			printk(KERN_ERR "[FSA9480]## %s ## \n", SII9234_i2c_status? "Ready to start MHL":"Let's Sleep untill MHL condition comes true");
			wait_event_interruptible_timeout(fsa9480_MhlWaitEvent, SII9234_i2c_status, msecs_to_jiffies(5*1000)); //5sec:
		}

		//skip controlling the sii9234 on lpm mode
		if(sec_get_lpm_mode())
		{
			//ignore turn on mhl because of only charging mode in power off state!
			printk(KERN_DEBUG "lpm_mode booting, so there is no to turn on mhl:mhl_onoff[%d]\n",mhl_onoff);
			//only desk_dock without mhl cable!
			DisableFSA9480Interrupts();
			FSA9480_CheckAndHookAudioDock(USE_DESK_DOCK,mhl_onoff);
			return;					
		}
	}
	if(mhl_onoff)
	{
		sii9234_cfg_power(1);	//Turn On power to SiI9234
		printk("Praveen:The value of mhl_cable_status is %d\n", mhl_cable_status);
		if(mhl_cable_status == 0x08 || mhl_cable_status == 0x00 || mhl_cable_status == 0x03)
		{
			SiI9234_init();
			local_usbsw->check_watchdog=0;
			schedule_delayed_work(&local_usbsw->fsa_watchdog, msecs_to_jiffies(3000));
			DisableFSA9480Interrupts();
			gpio_set_value_cansleep(GPIO_MHL_SEL, mhl_onoff);
		}
	}
	else
	{
		sii9234_cfg_power(0);	//Turn Off power to SiI9234
		DisableFSA9480Interrupts();
		gpio_set_value_cansleep(GPIO_MHL_SEL, mhl_onoff);
		mhl_cable_status = 0x08;	//Once mhl powered off cable status cannot be 0x07;
	}

// this code only for deskdock [
	if (!mhl_onoff)
	{
		if (usedeskdock)
		{
			FSA9480_CheckAndHookAudioDock(USE_DESK_DOCK, 0);
		}
		else
		{
			FSA9480_CheckAndHookAudioDock(USB_HDMI_CABLE,0);
			EnableFSA9480Interrupts();
		}
	}
// ]	
}
예제 #8
0
void FSA9480_CheckAndHookAudioDock(int value, int onoff)
{
	struct i2c_client *client = local_usbsw->client;
	struct fsa9480_platform_data *pdata = local_usbsw->pdata;
	int ret = 0;
	// unsigned int ctrl = CON_MASK;

	if (onoff)
		local_usbsw->check_watchdog=1;

	if (value == USE_DESK_DOCK)
	{
		if (onoff)
		{
			//skip controlling the sii9234 on lpm mode
			if(!sec_get_lpm_mode())
			{
#if defined(CONFIG_VIDEO_MHL_V1)
				sii9234_cfg_power(0);	//Turn Off power to SiI9234
#elif defined(CONFIG_VIDEO_MHL_V2)
				mhl_onoff_ex(0);		//will call hw_onoff(0)
#endif
				gpio_set_value_cansleep(GPIO_MHL_SEL, 0);
			}

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);

			dev_info(&client->dev, "FSA9480_CheckAndHookAudioDock On ctrl reg: 0x%x\n", ret);

			if (pdata->deskdock_cb)
				pdata->deskdock_cb(FSA9480_ATTACHED);

//#if !defined(CONFIG_USA_MODEL_SGH_I717) && !defined (CONFIG_USA_MODEL_SGH_T769)
			if (!get_sec_det_jack_state()) {
				if (HWversion ==VERSION_FSA9480)
				{
					ret = i2c_smbus_write_byte_data(client,FSA9480_REG_MANSW1,SW_AUDIO);
				}
				else
				{
					ret = i2c_smbus_write_byte_data(client,FSA9480_REG_MANSW1,AUDIO_9485);
				}
			
				if (ret < 0)
					dev_err(&client->dev,"%s: err %d\n", __func__, ret);
			}
			else
				printk("%s: Earjack exist..\n", __func__);
//#endif

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,FSA9480_REG_CTRL, ret & ~CON_MANUAL_SW & ~CON_RAW_DATA);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_INT2_MASK);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client, FSA9480_REG_INT2_MASK, ret & ~INT_MASK_ADC_CHANGE);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			usedeskdock= true;
			isDeskdockconnected=1;
			Dockconnected = 1;
		}
		else
		{
			dev_info(&client->dev, "FSA9480_CheckAndHookAudioDock  Off ctrl reg: 0x%x\n", ret);
			if (pdata->deskdock_cb)
				pdata->deskdock_cb(FSA9480_DETACHED);

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,FSA9480_REG_CTRL, ret | CON_MANUAL_SW | CON_RAW_DATA);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_INT2_MASK);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client, FSA9480_REG_INT2_MASK, ret | INT_MASK_ADC_CHANGE);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			usedeskdock= false;
			isDeskdockconnected=0;
			Dockconnected = 0;
		}

		EnableFSA9480Interrupts();
	}
	else if (value == USB_HDMI_CABLE)
	{
		if (onoff)
		{	
			if (pdata->mhl_cb)
				pdata->mhl_cb(FSA9480_ATTACHED);
		}
		else
		{
			if (pdata->mhl_cb)
				pdata->mhl_cb(FSA9480_DETACHED);

			if (local_usbsw!=NULL)
				fsa9480_reg_init(local_usbsw);
		}
		usedeskdock= false;	
		isDeskdockconnected=0;		
		Dockconnected = 0;
	} else if (value == USE_VEHICLE_DOCK) {
		if (onoff) {

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);

			dev_info(&client->dev, "FSA9480_CheckAndHookAudioDock On ctrl reg: 0x%x\n", ret);


//#if !defined(CONFIG_USA_MODEL_SGH_I717) && !defined (CONFIG_USA_MODEL_SGH_T769)
			if (!get_sec_det_jack_state()) {
				if (HWversion ==VERSION_FSA9480)
				{
					ret = i2c_smbus_write_byte_data(client,FSA9480_REG_MANSW1,SW_AUDIO);
				}
				else
				{
					ret = i2c_smbus_write_byte_data(client,FSA9480_REG_MANSW1,AUDIO_9485);
				}
			
				if (ret < 0)
					dev_err(&client->dev,"%s: err %d\n", __func__, ret);
			}
			else
				printk("%s: Earjack exist..\n", __func__);
//#endif

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,FSA9480_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			Dockconnected = 1;
		}
		else
		{
			dev_info(&client->dev, "FSA9480_CheckAndHookAudioDock  Off ctrl reg: 0x%x\n", ret);

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,FSA9480_REG_CTRL, ret | CON_MANUAL_SW | CON_RAW_DATA);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,FSA9480_REG_INT2_MASK);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client, FSA9480_REG_INT2_MASK, ret | INT_MASK_ADC_CHANGE);
			if (ret < 0)
				dev_err(&client->dev,"%s: err %d\n", __func__, ret);

			Dockconnected = 0;
		}
		
	}
	
}
예제 #9
0
static int fsa9485_detect_dev(struct fsa9485_usbsw *usbsw)
{
	int ret, adc;
	unsigned int val1, val2, val3;
	struct fsa9485_platform_data *pdata = usbsw->pdata;
	struct i2c_client *client = usbsw->client;
#if defined(CONFIG_VIDEO_MHL_V2)
	u8 mhl_ret = 0;
#endif

	val1 = i2c_smbus_read_byte_data(client, FSA9485_REG_DEV_T1);
	if (val1 < 0) {
		dev_err(&client->dev, "%s: err %d\n", __func__, val1);
		return val1;
	}

	val2 = i2c_smbus_read_byte_data(client, FSA9485_REG_DEV_T2);
	if (val2 < 0) {
		dev_err(&client->dev, "%s: err %d\n", __func__, val2);
		return val2;
	}
	jig_state =  (val2 & DEV_T2_JIG_ALL_MASK) ? 1 : 0;

	if (is_ti_muic()) {
		val3 = i2c_smbus_read_byte_data(client, FSA9485_REG_DEV_T3);
		if (val3 < 0) {
			dev_err(&client->dev, "%s: err %d\n", __func__, val3);
			return val3;
		}
	} else {
		val3 = i2c_smbus_read_byte_data(client,
				FSA9485_REG_RESERVED_1D);
		if (val3 < 0) {
			dev_err(&client->dev, "%s: err %d\n", __func__, val3);
			return val3;
		}
		val3 = val3 & 0x02;
	}

	adc = i2c_smbus_read_byte_data(client, FSA9485_REG_ADC);

	if (adc == 0x10)
		val2 = DEV_SMARTDOCK;
	else if (adc == 0x11 || adc == 0x12) {
		val2 = DEV_AUDIO_DOCK;
		dev_err(&client->dev, "adc is audio");
		val1 = 0;
	}
	dev_err(&client->dev,
			"dev1: 0x%x, dev2: 0x%x, dev3: 0x%x, ADC: 0x%x Jig:%s\n",
			val1, val2, val3, adc,
			(check_jig_state() ? "ON" : "OFF"));

	if ((val1+val2+val3 != 0)) {
		pr_info("%s Save state\n", __func__);
		local_usbsw->last_state.dev1 = val1;
		local_usbsw->last_state.dev2 = val2;
		local_usbsw->last_state.dev3 = val3;
	}

	/* Attached */
	if (val1 || val2 || (val3 & ~DEV_VBUS_DEBOUNCE) ||
			((val3 & DEV_VBUS_DEBOUNCE) && (adc != ADC_OPEN))) {
		/* USB */
		if (val1 & DEV_USB || val2 & DEV_T2_USB_MASK) {
			dev_info(&client->dev, "usb connect\n");
			pdata->callback(CABLE_TYPE_USB, FSA9485_ATTACHED);
			local_usbsw->last_state.attach = USB_CALL;

			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, usbsw->mansw);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}
		/* USB_CDP */
		} else if (val1 & DEV_USB_CHG) {
			dev_info(&client->dev, "usb_cdp connect\n");
#ifdef CONFIG_TSU6721_CDP_FIX
			pdata->callback(CABLE_TYPE_CDP, is_ti_muic() ? 
					TSU6721_ATTACHED : FSA9485_ATTACHED);
#else
			pdata->callback(CABLE_TYPE_CDP, FSA9485_ATTACHED);
#endif
			local_usbsw->last_state.attach = CDP_CALL;

			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, usbsw->mansw);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}

		/* UART */
		} else if (val1 & DEV_T1_UART_MASK || val2 & DEV_T2_UART_MASK) {
			uart_connecting = 1;
			dev_info(&client->dev, "uart connect\n");
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1E);
			pdata->callback(CABLE_TYPE_UARTOFF, FSA9485_ATTACHED);
			local_usbsw->last_state.attach = UART_CALL;

			if (usbsw->mansw) {
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_UART);

				if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			}
		/* CHARGER */
		} else if ((val1 & DEV_T1_CHARGER_MASK) ||
				(val3 & DEV_T3_CHARGER_MASK)) {
			dev_info(&client->dev, "charger connect\n");
			pdata->callback(CABLE_TYPE_AC, FSA9485_ATTACHED);
			local_usbsw->last_state.attach = CHARGER_CALL;
		/* for SAMSUNG OTG */
#if defined(CONFIG_USB_HOST_NOTIFY)
		} else if (val1 & DEV_USB_OTG) {
			dev_info(&client->dev, "otg connect\n");
			pdata->callback(CABLE_TYPE_OTG, FSA9485_ATTACHED);
			local_usbsw->last_state.attach = OTG_CALL;

			i2c_smbus_write_byte_data(client, FSA9485_REG_MANSW1,
					is_ti_muic() ? 0x25 : 0x27);
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_MANSW2, 0x02);
			msleep(50);
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1a);
#endif
		/* JIG */
		} else if (val2 & DEV_T2_JIG_MASK) {
			dev_info(&client->dev, "jig connect\n");
			pdata->callback(CABLE_TYPE_JIG, FSA9485_ATTACHED);
			local_usbsw->last_state.attach = JIG_CALL;
		/* Desk Dock */
		} else if ((val2 & DEV_AV) || (val3 & DEV_MHL) ||
			(val3 & DEV_AV_VBUS)) {
			if ((!is_ti_muic()) && ((adc & 0x1F) == 0x1A)) {
				pr_info("FSA Deskdock Attach\n");
				FSA9485_CheckAndHookAudioDock(1);
#if defined(CONFIG_VIDEO_MHL_V2)
				isDeskdockconnected = 1;
#endif
				i2c_smbus_write_byte_data(client,
					FSA9485_REG_RESERVED_20, 0x08);
			} else if ((is_ti_muic()) && !(val3 & DEV_MHL)) {
				pr_info("TI Deskdock Attach\n");
				FSA9485_CheckAndHookAudioDock(1);
#if defined(CONFIG_VIDEO_MHL_V2)
				isDeskdockconnected = 1;
#endif
			} else {
				pr_info("MHL Attach\n");
				if (!is_ti_muic())
					i2c_smbus_write_byte_data(client,
						FSA9485_REG_RESERVED_20, 0x08);
#if defined(CONFIG_VIDEO_MHL_V2)
				DisableFSA9480Interrupts();
				if (!isDeskdockconnected) {
					if (!poweroff_charging)
						mhl_ret = mhl_onoff_ex(1);
					else
						pr_info("LPM mode, skip MHL sequence\n");
				}
			local_usbsw->last_state.device = MHL_CALL;
				if (mhl_ret != MHL_DEVICE &&
						(adc & 0x1F) == 0x1A) {
					FSA9485_CheckAndHookAudioDock(1);
					isDeskdockconnected = 1;
				}
				EnableFSA9480Interrupts();
#else
				FSA9485_CheckAndHookAudioDock(1);
#endif
			}
		/* Car Dock */
		} else if (val2 & DEV_JIG_UART_ON) {
			pdata->callback(CABLE_TYPE_CARDOCK,
				FSA9485_ATTACHED);
			local_usbsw->last_state.attach = CARDOCK_CALL;
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_AUDIO);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			usbsw->dock_attached = FSA9485_ATTACHED;
		/* SmartDock */
		} else if (val2 & DEV_SMARTDOCK) {
			usbsw->adc = adc;
			dev_info(&client->dev, "smart dock connect\n");

			usbsw->mansw = SW_DHOST;
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_DHOST);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			pdata->callback(CABLE_TYPE_SMART_DOCK,
				FSA9485_ATTACHED);
			local_usbsw->last_state.attach = SMARTDOCK_CALL;
#if defined(CONFIG_VIDEO_MHL_V2)
			mhl_onoff_ex(1);
#endif
#if defined(CONFIG_USB_HOST_NOTIFY)
		/* Audio Dock */
		} else if (val2 & DEV_AUDIO_DOCK) {
			usbsw->adc = adc;
			dev_info(&client->dev, "audio dock connect\n");

			usbsw->mansw = SW_DHOST;

			if (is_ti_muic())
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_DHOST_TSU);
			else
				ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_MANSW1, SW_DHOST);

			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_read_byte_data(client,
				FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);
			ret = i2c_smbus_write_byte_data(client,
				FSA9485_REG_CTRL, ret & ~CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			pdata->callback(CABLE_TYPE_AUDIO_DOCK,
				FSA9485_ATTACHED);
			local_usbsw->last_state.attach = AUDIODOCK_CALL;
#endif
		/* Incompatible */
		} else if (val3 & DEV_VBUS_DEBOUNCE) {
			dev_info(&client->dev,
					"Incompatible Charger connect\n");
			pdata->callback(CABLE_TYPE_INCOMPATIBLE,
					FSA9485_ATTACHED);
			local_usbsw->last_state.attach = INCOMPATIBLE_CALL;
		}
	/* Detached */
	} else {
		/* USB */
		if (usbsw->dev1 & DEV_USB ||
				usbsw->dev2 & DEV_T2_USB_MASK) {
			pdata->callback(CABLE_TYPE_USB, FSA9485_DETACHED);
			local_usbsw->last_state.detach = USB_CALL;
		} else if (usbsw->dev1 & DEV_USB_CHG) {
			pdata->callback(CABLE_TYPE_CDP, FSA9485_DETACHED);
			local_usbsw->last_state.detach = CDP_CALL;

		/* UART */
		} else if (usbsw->dev1 & DEV_T1_UART_MASK ||
				usbsw->dev2 & DEV_T2_UART_MASK) {
			pdata->callback(CABLE_TYPE_UARTOFF, FSA9485_DETACHED);
			local_usbsw->last_state.detach = UART_CALL;
			uart_connecting = 0;
			dev_info(&client->dev, "[FSA9485] uart disconnect\n");

		/* CHARGER */
		} else if ((usbsw->dev1 & DEV_T1_CHARGER_MASK) ||
				(usbsw->dev3 & DEV_T3_CHARGER_MASK)) {
			pdata->callback(CABLE_TYPE_AC, FSA9485_DETACHED);
			local_usbsw->last_state.detach = CHARGER_CALL;
		/* for SAMSUNG OTG */
		} else if (usbsw->dev1 & DEV_USB_OTG) {
			i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL, 0x1E);
		/* JIG */
		} else if (usbsw->dev2 & DEV_T2_JIG_MASK) {
			pdata->callback(CABLE_TYPE_JIG, FSA9485_DETACHED);
			local_usbsw->last_state.detach = JIG_CALL;
		/* Desk Dock */
		} else if ((usbsw->dev2 & DEV_AV) || (usbsw->dev3 & DEV_MHL) ||
				(usbsw->dev3 & DEV_AV_VBUS)) {

			pr_info("Deskdock/MHL Detach\n");

			if (!is_ti_muic())
				i2c_smbus_write_byte_data(client,
					FSA9485_REG_RESERVED_20, 0x04);
#if defined(CONFIG_VIDEO_MHL_V2)
			if (isDeskdockconnected)
				FSA9485_CheckAndHookAudioDock(0);
#if defined CONFIG_MHL_D3_SUPPORT
			mhl_onoff_ex(false);
			detached_status = 1;
#endif
			isDeskdockconnected = 0;
#else
			FSA9485_CheckAndHookAudioDock(0);
#endif
		/* Car Dock */
		} else if (usbsw->dev2 & DEV_JIG_UART_ON) {
			pdata->callback(CABLE_TYPE_CARDOCK,
				FSA9485_DETACHED_DOCK);
			local_usbsw->last_state.detach = CARDOCK_CALL;
			ret = i2c_smbus_read_byte_data(client,
					FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
					"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL,
					ret | CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
					"%s: err %d\n", __func__, ret);
			usbsw->dock_attached = FSA9485_DETACHED;
		} else if (usbsw->adc == 0x10) {
			dev_info(&client->dev, "smart dock disconnect\n");
			ret = i2c_smbus_read_byte_data(client,
						FSA9485_REG_CTRL);
			if (ret < 0)
				dev_err(&client->dev,
					"%s: err %d\n", __func__, ret);

			ret = i2c_smbus_write_byte_data(client,
					FSA9485_REG_CTRL,
					ret | CON_MANUAL_SW);
			if (ret < 0)
				dev_err(&client->dev,
					"%s: err %d\n", __func__, ret);

			pdata->callback(CABLE_TYPE_SMART_DOCK,
				FSA9485_DETACHED);
			local_usbsw->last_state.detach = SMARTDOCK_CALL;
			usbsw->adc = 0;
#if defined(CONFIG_VIDEO_MHL_V2)
			mhl_onoff_ex(false);
#endif
		} else if (usbsw->dev2 == DEV_AUDIO_DOCK) {
			dev_info(&client->dev, "audio dock disconnect\n");
			ret = i2c_smbus_read_byte_data(client,
				    FSA9485_REG_CTRL);
			    if (ret < 0)
					dev_err(&client->dev,
					    "%s: err %d\n", __func__, ret);
				ret = i2c_smbus_write_byte_data(client,
						FSA9485_REG_CTRL,
						ret | CON_MANUAL_SW);
			    if (ret < 0)
					dev_err(&client->dev,
						"%s: err %d\n", __func__, ret);

			pdata->callback(CABLE_TYPE_AUDIO_DOCK,
					FSA9485_DETACHED);
			local_usbsw->last_state.detach = AUDIODOCK_CALL;
			usbsw->adc = 0;
		} else if (usbsw->dev3 & DEV_VBUS_DEBOUNCE) {
			dev_info(&client->dev,
					"Incompatible Charger disconnect\n");
			pdata->callback(CABLE_TYPE_INCOMPATIBLE,
					FSA9485_DETACHED);
			local_usbsw->last_state.detach = INCOMPATIBLE_CALL;
		}
	}
	usbsw->dev1 = val1;
	usbsw->dev2 = val2;
	usbsw->dev3 = val3;

	return adc;
}