int mmdvfs_set_step(MTK_SMI_BWC_SCEN scenario, mmdvfs_voltage_enum step)
{
	int i, scen_index;
	mmdvfs_voltage_enum final_step = mmdvfs_get_default_step();

#if !MMDVFS_ENABLE
	return 0;
#endif

#if defined(SMI_D1)
	/* D1 FHD always HPM. do not have to trigger vcore dvfs. */
	if (mmdvfs_get_lcd_resolution() == MMDVFS_LCD_SIZE_FHD)
		return 0;

#endif

	MMDVFSMSG("MMDVFS set voltage scen %d step %d\n", scenario, step);

	if ((scenario >= MMDVFS_SCEN_COUNT) || (scenario < SMI_BWC_SCEN_NORMAL)) {
		MMDVFSERR("invalid scenario\n");
		return -1;
	}

	/* dump information */
	mmdvfs_dump_info();

	/* go through all scenarios to decide the final step */
	scen_index = (int)scenario;

	spin_lock(&g_mmdvfs_mgr->scen_lock);

	g_mmdvfs_scenario_voltage[scen_index] = step;

	/* one high = final high */
	for (i = 0; i < MMDVFS_SCEN_COUNT; i++) {
		if (g_mmdvfs_scenario_voltage[i] == MMDVFS_VOLTAGE_HIGH) {
			final_step = MMDVFS_VOLTAGE_HIGH;
			break;
		}
	}

	g_mmdvfs_current_step = final_step;

	spin_unlock(&g_mmdvfs_mgr->scen_lock);

	MMDVFSMSG("MMDVFS set voltage scen %d step %d final %d\n", scenario,
	step, final_step);

#if MMDVFS_ENABLE
	/* call vcore dvfs API */
	if (final_step == MMDVFS_VOLTAGE_HIGH)
		vcorefs_request_dvfs_opp(KIR_MM, OPPI_PERF);
	else
		vcorefs_request_dvfs_opp(KIR_MM, OPPI_UNREQ);

#endif

	return 0;
}
int wait_sdio_autok_ready(void *data)
{
	int i;
	int ret = 0;
	enum boot_mode_t btmod;
	struct mmc_host *mmc = (struct mmc_host *)data;
	struct msdc_host *host = NULL;
	int id;
	unsigned int vcore_uv = 0;

	btmod = get_boot_mode();

	pr_debug("btmod = %d\n", btmod);

	if ((btmod != NORMAL_BOOT) && (btmod != META_BOOT)) {
		pr_debug("Not META or normal boot, return directly\n");
		return 0;
	}

	if (1 /*(btmod!=META_BOOT) && (btmod!=FACTORY_BOOT) && (btmod!=ATE_FACTORY_BOOT) */) {
		sdio_host_debug = 0;
		/* host = mtk_msdc_host[id]; */
		host = mmc_priv(mmc);
		id = host->id;

#ifndef UT_TEST
		/* claim host */
#ifdef CONFIG_SDIOAUTOK_SUPPORT

		/* ALPS02017456 */
		/* true if dwork was pending, false otherwise */
		if (cancel_delayed_work_sync(&(host->set_vcore_workq)) == 0)
			pr_debug("** no pending vcore_workq\n");
		else
			pr_debug("** cancel vcore_workq\n");
		/* ALPS02017456 */

		pr_debug("wait_sdio_autok_ready(): is_vcorefs_can_work= %d\n",
			is_vcorefs_can_work());
		if (vcorefs_request_dvfs_opp(KIR_SDIO, OPPI_PERF) != 0) {	/* performance mode, return 0 pass */
			/* BUG_ON("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n"); */
			pr_err("vcorefs_request_dvfs_opp@OPPI_PERF fail!\n");
		}

		g_autok_vcore_sel[0] = vcorefs_get_curr_voltage();
		pr_debug("wait_sdio_autok_ready(): vcorefs_get_curr_voltage= %d\n",
			vcorefs_get_curr_voltage());

		/* mt_cpufreq_disable(0, true); */
		/* FIXME@CCJ mt_vcore_dvfs_disable_by_sdio(0, true); */
		/* vcorefs_sdio_lock_dvfs(0); //ccyeh */
#endif
#ifdef MTK_SDIO30_ONLINE_TUNING_SUPPORT
		/* ccyeh atomic_set(&host->ot_work.ot_disable, 1); */
#endif				/* MTK_SDIO30_ONLINE_TUNING_SUPPORT */
		autok_claim_host(host);
#endif

#ifdef AUTOK_THREAD
		for (i = 0; i < HOST_MAX_NUM; i++) {
			if (p_autok_thread_data->p_autok_progress[i].host_id == id &&
			    p_autok_thread_data->p_autok_progress[i].done == 1 &&
			    p_autok_thread_data->p_autok_progress[i].fail == 0) {
				vcore_uv = autok_get_current_vcore_offset();
				msdc_autok_stg2_cal(host, &p_autok_predata[id], vcore_uv);
				break;
			}
		}

		if (i != HOST_MAX_NUM)
			goto EXIT_WAIT_AUTOK_READY;

#endif

		for (i = 0; i < HOST_MAX_NUM; i++) {
			if (p_autok_thread_data->p_autok_progress[i].host_id == -1
			    || p_autok_thread_data->p_autok_progress[i].host_id == id) {
				send_autok_uevent("s2_ready", host);
				init_completion(&p_autok_thread_data->autok_completion[i]);
				p_autok_thread_data->p_autok_progress[i].done = 0;
				p_autok_thread_data->p_autok_progress[i].fail = 0;
				p_autok_thread_data->p_autok_progress[i].host_id = id;
				wait_for_completion_interruptible
				    (&p_autok_thread_data->autok_completion[i]);
				for (i = 0; i < HOST_MAX_NUM; i++) {
					if (p_autok_thread_data->p_autok_progress[i].host_id == id
					    && p_autok_thread_data->p_autok_progress[i].fail == 1) {
						ret = -1;
						break;
					}
				}
				send_autok_uevent("s2_done", host);

				break;
			}
		}

		/* reset_autok_cursor(0); */
EXIT_WAIT_AUTOK_READY:
#ifndef UT_TEST
		/* release host */
		autok_release_host(host);
#ifdef CONFIG_SDIOAUTOK_SUPPORT
		/* mt_cpufreq_disable(0, false); */
		/* FIXME@CCJ mt_vcore_dvfs_disable_by_sdio(0, false); */
		/* vcorefs_sdio_unlock_dvfs(0);//ccyeh */

		if (vcorefs_request_dvfs_opp(KIR_SDIO, OPPI_UNREQ) != 0) {	/* un-request, return 0 pass */
			/* BUG_ON("vcorefs_request_dvfs_opp@OPPI_UNREQ fail!\n"); */
			pr_err("vcorefs_request_dvfs_opp@OPPI_UNREQ fail!\n");
		}
#endif
#ifdef MTK_SDIO30_ONLINE_TUNING_SUPPORT
		atomic_set(&host->ot_work.autok_done, 1);
		atomic_set(&host->ot_work.ot_disable, 0);
#endif				/* MTK_SDIO30_ONLINE_TUNING_SUPPORT */
#endif
	}

	return ret;
}
int mmdvfs_set_step(MTK_SMI_BWC_SCEN scenario, mmdvfs_voltage_enum step)
{
	int i, scen_index;
	mmdvfs_voltage_enum final_step = mmdvfs_get_default_step();

#if !MMDVFS_ENABLE
	return 0;
#endif

#if !MMDVFS_ENABLE_WQHD
	/* do nothing if disable MMDVFS in WQHD */
	if (mmdvfs_get_lcd_resolution() == MMDVFS_LCD_SIZE_WQHD) {
		return 0;
	}
#endif /* MMDVFS_ENABLE_WQHD */

	MMDVFSMSG("MMDVFS set voltage scen %d step %d\n", scenario, step);

	if (scenario >= SMI_BWC_SCEN_CNT || (scenario < SMI_BWC_SCEN_NORMAL))
	{
		MMDVFSERR("invalid scenario\n");
		return -1;
	}

	/* dump information */
	mmdvfs_dump_info();

	/* go through all scenarios to decide the final step */
	scen_index = (int)scenario;

	spin_lock(&g_mmdvfs_mgr->scen_lock);
	
	g_mmdvfs_scenario_voltage[scen_index] = step;

	/* one high = final high */
	for (i = 0; i < SMI_BWC_SCEN_CNT; i++) {
		if (g_mmdvfs_scenario_voltage[i] == MMDVFS_VOLTAGE_HIGH) {
			final_step = MMDVFS_VOLTAGE_HIGH;
			break;
		}
	}

	g_mmdvfs_current_step = final_step;
	
	spin_unlock(&g_mmdvfs_mgr->scen_lock);

	MMDVFSMSG("MMDVFS set voltage scen %d step %d final %d\n", scenario, step, final_step);

#if	MMDVFS_ENABLE
	/* call vcore dvfs API */
    if (mmdvfs_get_lcd_resolution() == MMDVFS_LCD_SIZE_WQHD) {	/* WQHD */
    	// TODO: use final_step and retry vcore dvfs
		MMDVFSMSG("HIGH to %d\n", step);
		if (step == MMDVFS_VOLTAGE_LOW) {
			vcorefs_request_dvfs_opp(KR_MM_SCEN, OPPI_LOW_PWR);
		} else {
			vcorefs_request_dvfs_opp(KR_MM_SCEN, OPPI_UNREQ);	
		}
	} else { /* FHD */
		MMDVFSMSG("FHD %d\n", final_step);	
		if (final_step == MMDVFS_VOLTAGE_HIGH) {
			vcorefs_request_dvfs_opp(KR_MM_SCEN, OPPI_PERF);
		} else {
			vcorefs_request_dvfs_opp(KR_MM_SCEN, OPPI_UNREQ);
		}
	}
#endif

	return 0;
}