/* Pen */
DECLARE_DVFS_DELAYED_WORK_FUNC(CHG, PEN)
{
	struct input_booster *data =
		container_of(work, struct input_booster, dvfses[BOOSTER_DEVICE_PEN].dvfs_chg_work.work);
	struct booster_dvfs *dvfs = &data->dvfses[BOOSTER_DEVICE_PEN];

	mutex_lock(&dvfs->lock);

	switch (dvfs->level) {
	case BOOSTER_LEVEL0:
	case BOOSTER_LEVEL1:
	case BOOSTER_LEVEL3:
		remove_qos(&dvfs->cpu_qos);
		remove_qos(&dvfs->mif_qos);
		remove_qos(&dvfs->int_qos);
		dvfs->lock_status = false;
		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);
	break;
	case BOOSTER_LEVEL2:
		set_qos(&dvfs->cpu_qos, PM_QOS_CPU_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL2].cpu_freq);
		set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL2].mif_freq);
		set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL2].int_freq);
		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS CHANGED [level %d]\n", __func__, dvfs->level);
	break;
	default:
		dev_err(data->dev, "%s : Undefined type passed[%d]\n", __func__, dvfs->level);
	break;
	}

	mutex_unlock(&dvfs->lock);
}
void wacom_change_dvfs_lock(struct work_struct *work)
{
	struct wacom_i2c *wac_i2c =
		container_of(work, struct wacom_i2c, dvfs_chg_work.work);

	mutex_lock(&wac_i2c->dvfs_lock);

	if (wac_i2c->boost_level == WACOM_BOOSTER_LEVEL1 || \
		wac_i2c->boost_level == WACOM_BOOSTER_LEVEL3) {
		remove_qos(&wac_i2c->cpu_qos);
		remove_qos(&wac_i2c->mif_qos);
		remove_qos(&wac_i2c->int_qos);

		wac_i2c->dvfs_lock_status = false;
		printk(KERN_DEBUG"epen:DVFS Off, %d\n", wac_i2c->boost_level);
	} else {
		set_qos(&wac_i2c->cpu_qos, PM_QOS_CPU_FREQ_MIN, WACOM_BOOSTER_CPU_FREQ2);
		set_qos(&wac_i2c->mif_qos, PM_QOS_BUS_THROUGHPUT, WACOM_BOOSTER_MIF_FREQ2);
		set_qos(&wac_i2c->int_qos, PM_QOS_DEVICE_THROUGHPUT, WACOM_BOOSTER_INT_FREQ2);

		printk(KERN_DEBUG"epen:change_mif_dvfs_lock\n");
	}

	mutex_unlock(&wac_i2c->dvfs_lock);
}
void wacom_set_dvfs_off(struct work_struct *work)
{
	struct wacom_i2c *wac_i2c =
		container_of(work,
				struct wacom_i2c, dvfs_off_work.work);

	mutex_lock(&wac_i2c->dvfs_lock);

	remove_qos(&wac_i2c->cpu_qos);
	remove_qos(&wac_i2c->mif_qos);
	remove_qos(&wac_i2c->int_qos);

	wac_i2c->dvfs_lock_status = false;
	mutex_unlock(&wac_i2c->dvfs_lock);

	printk(KERN_DEBUG"epen:DVFS Off, %d\n", wac_i2c->boost_level);
}
static void gpio_key_set_dvfs_off(struct work_struct *work)
{
	struct gpio_button_data *bdata =
				container_of(work,
					struct gpio_button_data, key_work_dvfs_off.work);

	mutex_lock(&bdata->key_dvfs_lock);

	remove_qos(&bdata->cpu_qos);
	remove_qos(&bdata->mif_qos);
	remove_qos(&bdata->int_qos);

	bdata->key_dvfs_lock_status = false;
	bdata->dvfs_signal = false;
	mutex_unlock(&bdata->key_dvfs_lock);

	printk(KERN_DEBUG "keys:DVFS Off\n");
}
DECLARE_DVFS_DELAYED_WORK_FUNC(OFF, PEN)
{
	struct input_booster *data =
		container_of(work, struct input_booster, dvfses[BOOSTER_DEVICE_PEN].dvfs_off_work.work);
	struct booster_dvfs *dvfs = &data->dvfses[BOOSTER_DEVICE_PEN];

	mutex_lock(&dvfs->lock);

	remove_qos(&dvfs->cpu_qos);
	remove_qos(&dvfs->mif_qos);
	remove_qos(&dvfs->int_qos);

	dvfs->lock_status = false;

	DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);

	mutex_unlock(&dvfs->lock);
}
DECLARE_DVFS_DELAYED_WORK_FUNC(OFF, PEN)
{
	struct booster_dvfs *dvfs =
		container_of(work, struct booster_dvfs, dvfs_off_work.work);
	struct input_booster *data = dev_get_drvdata(dvfs->parent_dev);

	mutex_lock(&dvfs->lock);

	remove_qos(&dvfs->cpu_qos);
	remove_qos(&dvfs->mif_qos);
	remove_qos(&dvfs->int_qos);

	dvfs->lock_status = false;

	DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);

	mutex_unlock(&dvfs->lock);
}
DECLARE_DVFS_DELAYED_WORK_FUNC(OFF, TOUCH)
{
	struct booster_dvfs *dvfs =
		container_of(work, struct booster_dvfs, dvfs_off_work.work);
	struct input_booster *data = dev_get_drvdata(dvfs->parent_dev);

	mutex_lock(&dvfs->lock);
	if (dvfs->lock_status) {
		remove_qos(&dvfs->cpu_qos);
		remove_qos(&dvfs->kfc_qos);
		remove_qos(&dvfs->mif_qos);
		remove_qos(&dvfs->int_qos);
		SET_HMP(data, BOOSTER_DEVICE_TOUCH, false);
		dvfs->lock_status = false;
		dvfs->phase_excuted = false;

		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);
	}
	mutex_unlock(&dvfs->lock);
}
/* Touch */
DECLARE_DVFS_DELAYED_WORK_FUNC(CHG, TOUCH)
{
	struct booster_dvfs *dvfs =
		container_of(work, struct booster_dvfs, dvfs_chg_work.work);
	struct input_booster *data = dev_get_drvdata(dvfs->parent_dev);

	mutex_lock(&dvfs->lock);

	if (!dvfs->times[dvfs->level].phase_time)
		dvfs->phase_excuted = false;

	switch (dvfs->level) {
	case BOOSTER_LEVEL0:
	case BOOSTER_LEVEL1:
	case BOOSTER_LEVEL3:
		remove_qos(&dvfs->cpu_qos);
		remove_qos(&dvfs->kfc_qos);
		remove_qos(&dvfs->mif_qos);
		remove_qos(&dvfs->int_qos);
		SET_HMP(data, BOOSTER_DEVICE_TOUCH, false);
		dvfs->lock_status = false;

		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);
	break;
	case BOOSTER_LEVEL2:
		set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL2].kfc_freq);
		set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL2].int_freq);
		set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL2].mif_freq);
		remove_qos(&dvfs->cpu_qos);
		SET_HMP(data, BOOSTER_DEVICE_TOUCH, false);

		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS CHANGED [level %d]\n", __func__, dvfs->level);
	break;
	case BOOSTER_LEVEL4:
		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS CHANGED [level %d]\n", __func__, dvfs->level);
	break;
	case BOOSTER_LEVEL5:
		if (dvfs->phase_excuted) {
			remove_qos(&dvfs->cpu_qos);
			remove_qos(&dvfs->kfc_qos);
			remove_qos(&dvfs->mif_qos);
			remove_qos(&dvfs->int_qos);
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, false);
			dvfs->lock_status = false;
			dvfs->phase_excuted = false;

			DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS OFF\n", __func__);
		} else {
			set_qos(&dvfs->cpu_qos, PM_QOS_CPU_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL5].cpu_freq);
			schedule_delayed_work(&dvfs->dvfs_chg_work,
				msecs_to_jiffies(dvfs->times[BOOSTER_LEVEL5].head_time - dvfs->times[BOOSTER_LEVEL5].phase_time));
			dvfs->phase_excuted = true;
			DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS CHANGED [level %d, start time[%d]]\n",
				__func__, dvfs->level, dvfs->times[BOOSTER_LEVEL5].head_time - dvfs->times[BOOSTER_LEVEL5].phase_time);
		}
	break;
	case BOOSTER_LEVEL9:
		SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL9_CHG].hmp_boost);
		set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL9_CHG].kfc_freq);
		set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL9_CHG].int_freq);
		set_qos(&dvfs->cpu_qos, PM_QOS_CPU_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL9_CHG].cpu_freq);
		set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL9_CHG].mif_freq);

		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS CHANGED [level %d]\n", __func__, dvfs->level);
	break;
	default:
		dev_err(data->dev, "%s : Undefined type passed[%d]\n", __func__, dvfs->level);
	break;
	}

	if (!dvfs->lock_status)
		dvfs->phase_excuted = false;

	mutex_unlock(&dvfs->lock);
}
DECLARE_DVFS_WORK_FUNC(SET, TOUCH)
{
	struct input_booster *data = (struct input_booster *)booster_data;
	struct booster_dvfs *dvfs = data->dvfses[BOOSTER_DEVICE_TOUCH];

	if (!dvfs || !dvfs->initialized) {
		dev_err(data->dev, "%s: Dvfs is not initialized\n",	__func__);
		return;
	}

	mutex_lock(&dvfs->lock);

	if (!dvfs->level) {
		dev_err(data->dev, "%s : Skip to set booster due to level 0\n", __func__);
		goto out;
	}

	switch (booster_mode) {
	case BOOSTER_MODE_ON:
		cancel_delayed_work(&dvfs->dvfs_off_work);
		cancel_delayed_work(&dvfs->dvfs_chg_work);
		switch (dvfs->level) {
		case BOOSTER_LEVEL1:
		case BOOSTER_LEVEL2:
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL1].hmp_boost);
			set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL1].kfc_freq);
			set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL1].int_freq);
			set_qos(&dvfs->cpu_qos, PM_QOS_CPU_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL1].cpu_freq);
			set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL1].mif_freq);
		break;
		case BOOSTER_LEVEL3:
			set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL3].kfc_freq);
			set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL3].int_freq);
			set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL3].mif_freq);
			remove_qos(&dvfs->cpu_qos);
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL3].hmp_boost);
		break;
		case BOOSTER_LEVEL4:
			set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL4].kfc_freq);
			set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL4].int_freq);
			set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL4].mif_freq);
			remove_qos(&dvfs->cpu_qos);
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL4].hmp_boost);
		break;
		case BOOSTER_LEVEL5:
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL5].hmp_boost);
			set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL5].kfc_freq);
			set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL5].int_freq);
			set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL5].mif_freq);
		break;
		case BOOSTER_LEVEL9:
			SET_HMP(data, BOOSTER_DEVICE_TOUCH, dvfs->freqs[BOOSTER_LEVEL9].hmp_boost);
			set_qos(&dvfs->kfc_qos, PM_QOS_KFC_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL9].kfc_freq);
			set_qos(&dvfs->int_qos, PM_QOS_DEVICE_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL9].int_freq);
			set_qos(&dvfs->cpu_qos, PM_QOS_CPU_FREQ_MIN, dvfs->freqs[BOOSTER_LEVEL9].cpu_freq);
			set_qos(&dvfs->mif_qos, PM_QOS_BUS_THROUGHPUT, dvfs->freqs[BOOSTER_LEVEL9].mif_freq);
		break;
		default:
			dev_err(data->dev, "%s : Undefined type passed[%d]\n", __func__, dvfs->level);
		break;
		}

		if (dvfs->times[dvfs->level].phase_time) {
			schedule_delayed_work(&dvfs->dvfs_chg_work,
								msecs_to_jiffies(dvfs->times[dvfs->level].phase_time));
			if (dvfs->phase_excuted)
				dvfs->phase_excuted = false;
		} else {
			schedule_delayed_work(&dvfs->dvfs_chg_work,
								msecs_to_jiffies(dvfs->times[dvfs->level].head_time));
		}
		dvfs->lock_status = true;

		DVFS_DEV_DBG(DBG_DVFS, data->dev, "%s : DVFS ON [level %d][start time [%d]]\n",
			__func__, dvfs->level, dvfs->times[dvfs->level].phase_time ?: dvfs->times[dvfs->level].head_time);

	break;
	case BOOSTER_MODE_OFF:
		if (dvfs->lock_status)
			schedule_delayed_work(&dvfs->dvfs_off_work,
						msecs_to_jiffies(dvfs->times[dvfs->level].tail_time));
	break;
	case BOOSTER_MODE_FORCE_OFF:
		if (dvfs->lock_status) {
			cancel_delayed_work(&dvfs->dvfs_chg_work);
			cancel_delayed_work(&dvfs->dvfs_off_work);
			schedule_work(&dvfs->dvfs_off_work.work);
		}
	break;
	default:
	break;
	}

out:
	mutex_unlock(&dvfs->lock);
	return;
}