/* usb cable call back function */
void max77803_muic_usb_cb(u8 usb_mode)
{
#ifdef CONFIG_USB_HOST_NOTIFY
	struct host_notifier_platform_data *host_noti_pdata =
	    host_notifier_device.dev.platform_data;
	int cable_type = max77803_muic_get_charging_type();
#endif

	if (is_usb_locked) {
		pr_info("%s: usb locked by mdm\n", __func__);
		return;
	}

	if (usb_mode == USB_CABLE_ATTACHED) {
#if defined(CONFIG_MFD_MAX77803) || defined(CONFIG_MFD_MAX77888)
		g_usbvbus = USB_CABLE_ATTACHED;
#endif
#ifdef CONFIG_HA_3G
		if(system_rev >= 6)
			usb30_redriver_en(1);
#elif defined(CONFIG_V1A) || defined(CONFIG_V2A)
		usb30_redriver_en(1);
#endif
		max77803_set_vbus_state(USB_CABLE_ATTACHED);
		pr_info("%s - USB_CABLE_ATTACHED\n", __func__);
	} else if (usb_mode == USB_CABLE_DETACHED) {
#if defined(CONFIG_MFD_MAX77803) || defined(CONFIG_MFD_MAX77888)
		g_usbvbus = USB_CABLE_DETACHED;
#endif
#ifdef CONFIG_USB_ANDROID_SAMSUNG_COMPOSITE
#ifdef CONFIG_HA_3G
		usb30en = 0;
#endif
#endif

#ifdef CONFIG_HA_3G
		if(system_rev >= 6)
			usb30_redriver_en(0);
#elif defined(CONFIG_V1A) || defined(CONFIG_V2A)
		usb30_redriver_en(0);
#endif
		max77803_set_vbus_state(USB_CABLE_DETACHED);
		pr_info("%s - USB_CABLE_DETACHED\n", __func__);
	} else if (usb_mode == USB_OTGHOST_ATTACHED) {
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->booster(1);
		host_noti_pdata->ndev.mode = NOTIFY_HOST_MODE;
		if (host_noti_pdata->usbhostd_start)
			host_noti_pdata->usbhostd_start();
		/* defense code for otg mis-detecing issue */
		msleep(50);
#endif
		max77803_check_id_state(0);
		pr_info("%s - USB_OTGHOST_ATTACHED\n", __func__);
	} else if (usb_mode == USB_OTGHOST_DETACHED) {
		max77803_check_id_state(1);
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->ndev.mode = NOTIFY_NONE_MODE;
		if (host_noti_pdata->usbhostd_stop)
			host_noti_pdata->usbhostd_stop();
		host_noti_pdata->booster(0);
#endif
		pr_info("%s - USB_OTGHOST_DETACHED\n", __func__);
	} else if (usb_mode == USB_POWERED_HOST_ATTACHED) {
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->powered_booster(1);

		if (cable_type == CABLE_TYPE_MMDOCK_MUIC) {
			enable_ovc(1);
			host_state_notify(&host_noti_pdata->ndev,
				NOTIFY_HOST_NONE);
		}

		if (cable_type == CABLE_TYPE_LANHUB_MUIC)
		{
			host_noti_pdata->ndev.mode = NOTIFY_HOST_MODE;
			if (host_noti_pdata->usbhostd_start)
				host_noti_pdata->usbhostd_start();
		}
		else
			start_usbhostd_wakelock();
#endif
		max77803_check_id_state(0);
		pr_info("%s - USB_POWERED_HOST_ATTACHED\n", __func__);
	} else if (usb_mode == USB_POWERED_HOST_DETACHED) {
		max77803_check_id_state(1);
#ifdef CONFIG_USB_HOST_NOTIFY
		host_noti_pdata->powered_booster(0);

		if (cable_type == CABLE_TYPE_MMDOCK_MUIC) {
			enable_ovc(0);
		}

		if (host_noti_pdata->ndev.mode == NOTIFY_HOST_MODE)
		{
			host_noti_pdata->ndev.mode = NOTIFY_NONE_MODE;
			if (host_noti_pdata->usbhostd_stop)
				host_noti_pdata->usbhostd_stop();
		}
		else
			stop_usbhostd_wakelock();
#endif
		pr_info("%s - USB_POWERED_HOST_DETACHED\n", __func__);
	}
}
static void otg_notify_state(unsigned long event, int enable)
{
	struct otg_notify *notify = NULL;

	if (!u_notify) {
		pr_err("u_notify is NULL\n");
		goto no_save_event;
	}

	pr_info("%s+ event=%s(%lu), enable=%s\n", __func__,
		event_string(event), event, enable == 0 ? "off" : "on");

	notify = get_otg_notify();

	switch (event) {
	case NOTIFY_EVENT_NONE:
		break;
	case NOTIFY_EVENT_SMARTDOCK_USB:
	case NOTIFY_EVENT_VBUS:
		if (enable) {
			u_notify->ndev.mode = NOTIFY_PERIPHERAL_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->set_peripheral)
				notify->set_peripheral(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_peripheral)
				notify->set_peripheral(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_LANHUB_TA:
		u_notify->diable_v_drive = enable;
		if (enable)
			u_notify->oc_noti = 0;
		if (notify->set_lanhubta)
			notify->set_lanhubta(enable);
		break;
	case NOTIFY_EVENT_LANHUB:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = enable;
		if (enable) {
			u_notify->oc_noti = 0;
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_ADD);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_host)
				notify->set_host(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_REMOVE);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_HOST:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = 0;
		if (enable) {
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_ADD);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 1);
			if (notify->auto_drive_vbus) {
				u_notify->oc_noti = 1;
				if (notify->vbus_drive)
					notify->vbus_drive(1);
			}
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->auto_drive_vbus) {
				u_notify->oc_noti = 0;
				if (notify->vbus_drive)
					notify->vbus_drive(0);
			}
			if (notify->set_host)
				notify->set_host(false);
			if (gpio_is_valid(notify->redriver_en_gpio))
				gpio_direction_output
					(notify->redriver_en_gpio, 0);
			host_state_notify(&u_notify->ndev, NOTIFY_HOST_REMOVE);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_CHARGER:
		if (notify->set_charger)
			notify->set_charger(enable);
		break;
	case NOTIFY_EVENT_MMDOCK:
		enable_ovc(u_notify, enable);
		/* To detect overcurrent, ndev state is initialized */
		if (enable)
			host_state_notify(&u_notify->ndev,
							NOTIFY_HOST_NONE);
	case NOTIFY_EVENT_SMARTDOCK_TA:
	case NOTIFY_EVENT_AUDIODOCK:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto err;
		}
		u_notify->diable_v_drive = enable;
		if (enable) {
			u_notify->ndev.mode = NOTIFY_HOST_MODE;
			if (notify->is_wakelock)
				wake_lock(&u_notify->wlock);
			if (notify->set_host)
				notify->set_host(true);
		} else {
			u_notify->ndev.mode = NOTIFY_NONE_MODE;
			if (notify->set_host)
				notify->set_host(false);
			if (notify->is_wakelock)
				wake_unlock(&u_notify->wlock);
		}
		break;
	case NOTIFY_EVENT_DRIVE_VBUS:
		if (notify->unsupport_host) {
			pr_err("This model doesn't support usb host\n");
			goto no_save_event;
		}
		if (u_notify->diable_v_drive) {
			pr_info("cable type=%s disable vbus draw\n",
					event_string(u_notify->c_type));
			goto no_save_event;
		}
		u_notify->oc_noti = enable;
		if (notify->vbus_drive)
			notify->vbus_drive((bool)enable);
		goto no_save_event;
	default:
		break;
	}
err:
	if (enable)
		u_notify->c_type = event;
	else
		u_notify->c_type = NOTIFY_EVENT_NONE;

no_save_event:
	pr_info("%s- event=%s, cable=%s\n", __func__,
		event_string(event),
			event_string(u_notify->c_type));
}