/* disp_pm_add_refcount - it is called in the early start of the
 * update_reg_handler */
int disp_pm_add_refcount(struct display_driver *dispdrv)
{
	unsigned long flags;

	if (dispdrv->platform_status == DISP_STATUS_PM0) return 0;

	if (!dispdrv->pm_status.clock_gating_on) return 0;

	if (dispdrv->decon_driver.sfb->power_state == POWER_DOWN)
		return 0;

	init_gating_idle_count(dispdrv);

	flush_kthread_worker(&dispdrv->pm_status.control_clock_gating);
	flush_kthread_worker(&dispdrv->pm_status.control_power_gating);
	if (dispdrv->decon_driver.sfb->power_state == POWER_HIBER_DOWN)
		display_hibernation_power_on(dispdrv);

	display_block_clock_on(dispdrv);

	spin_lock_irqsave(&dispdrv->pm_status.slock, flags);
	if (dispdrv->pm_status.trigger_masked) {
		disable_mask(dispdrv);
	}
	spin_unlock_irqrestore(&dispdrv->pm_status.slock, flags);
	return 0;
}
/* disp_pm_sched_power_on - it is called in the early start of the
 * fb_ioctl to exit HDM */
int disp_pm_sched_power_on(struct display_driver *dispdrv, unsigned int cmd)
{
	struct s3c_fb *sfb = dispdrv->decon_driver.sfb;

	init_gating_idle_count(dispdrv);

	if (dispdrv->platform_status < DISP_STATUS_PM1) {
		if (cmd == S3CFB_WIN_CONFIG)
			disp_pm_init_status(dispdrv);
	}

	flush_kthread_worker(&dispdrv->pm_status.control_power_gating);
	if (sfb->power_state == POWER_HIBER_DOWN) {
		switch (cmd) {
		case S3CFB_WIN_PSR_EXIT:
		case S3CFB_WIN_CONFIG:
			queue_kthread_work(&dispdrv->pm_status.control_power_gating,
				&dispdrv->pm_status.control_power_gating_work);
			break;
		default:
			return -EBUSY;
		}
	}

	return 0;
}
static void decon_clock_gating_handler(struct kthread_work *work)
{
	struct display_driver *dispdrv = get_display_driver();

	if (dispdrv->pm_status.clk_idle_count > MAX_CLK_GATING_COUNT)
		display_block_clock_off(dispdrv);

	init_gating_idle_count(dispdrv);
	disp_pm_gate_lock(dispdrv, false);
	pm_debug("display_block_clock_off -");
}
static void decon_power_gating_handler(struct kthread_work *work)
{
	struct display_driver *dispdrv = get_display_driver();

	if (dispdrv->pm_status.pwr_idle_count > MAX_PWR_GATING_COUNT) {
		if (!check_camera_is_running()) {
			display_hibernation_power_off(dispdrv);
			init_gating_idle_count(dispdrv);
		}
	} else if (dispdrv->decon_driver.sfb->power_state == POWER_HIBER_DOWN) {
		display_hibernation_power_on(dispdrv);
	}
}
int disp_pm_runtime_get_sync(struct display_driver *dispdrv)
{
	if (!dispdrv->pm_status.clock_gating_on) {
		pm_runtime_get_sync(dispdrv->display_driver);
		return 0;
	}

	init_gating_idle_count(dispdrv);

	/* guarantee clock and power gating */
	flush_kthread_worker(&dispdrv->pm_status.control_power_gating);
	pm_runtime_get_sync(dispdrv->display_driver);
	display_block_clock_on(dispdrv);

	return 0;
}
/* disp_pm_sched_power_on - it is called in the early start of the
 * fb_ioctl to exit HDM */
int disp_pm_sched_power_on(struct display_driver *dispdrv, unsigned int cmd)
{
	struct s3c_fb *sfb = dispdrv->decon_driver.sfb;

	init_gating_idle_count(dispdrv);

	/* First WIN_CONFIG should be on clock and power-gating */
	if (dispdrv->platform_status < DISP_STATUS_PM1) {
		if (cmd == S3CFB_WIN_CONFIG)
			disp_pm_set_plat_status(dispdrv, true);
	}

	flush_kthread_worker(&dispdrv->pm_status.control_power_gating);
	if (sfb->power_state == POWER_HIBER_DOWN) {
		switch (cmd) {
		case S3CFB_PLATFORM_RESET:
			disp_pm_gate_lock(dispdrv, true);
			queue_kthread_work(&dispdrv->pm_status.control_power_gating,
				&dispdrv->pm_status.control_power_gating_work);
			/* Prevent next clock and power-gating */
			disp_pm_set_plat_status(dispdrv, false);
			break;
		case S3CFB_WIN_PSR_EXIT:
		case S3CFB_WIN_CONFIG:
		case S3CFB_SET_VSYNC_INT:
			request_dynamic_hotplug(false);
			disp_pm_gate_lock(dispdrv, true);
			queue_kthread_work(&dispdrv->pm_status.control_power_gating,
				&dispdrv->pm_status.control_power_gating_work);
			break;
		default:
			return -EBUSY;
		}
	} else {
		switch (cmd) {
		case S3CFB_PLATFORM_RESET:
			/* Prevent next clock and power-gating */
			disp_pm_set_plat_status(dispdrv, false);
			break;
		}
	}

	return 0;
}
/* disp_pm_add_refcount - it is called in the early start of the
 * update_reg_handler */
int disp_pm_add_refcount(struct display_driver *dispdrv)
{
	if (dispdrv->platform_status == DISP_STATUS_PM0) return 0;

	if (!dispdrv->pm_status.clock_gating_on) return 0;

	if (dispdrv->decon_driver.sfb->power_state == POWER_DOWN)
		return 0;

	init_gating_idle_count(dispdrv);

	flush_kthread_worker(&dispdrv->pm_status.control_power_gating);
	if (dispdrv->decon_driver.sfb->power_state == POWER_HIBER_DOWN) {
		request_dynamic_hotplug(false);
		display_hibernation_power_on(dispdrv);
	}

	display_block_clock_on(dispdrv);

	return 0;
}