Example #1
0
int s3cfb_open_fifo(int id, int ch, int (*do_priv) (void *), void *param)
{
	struct s3cfb_global *fbdev = get_fimd_global(id);
	struct s3cfb_window *win = fbdev->fb[id]->par;

	dev_dbg(fbdev->dev, "[fb%d] open fifo\n", win->id);

	if (win->path == DATA_PATH_DMA) {
		dev_err(fbdev->dev, "WIN%d is busy.\n", id);
		return -EFAULT;
	}

	win->local_channel = ch;

	if (do_priv) {
		if (do_priv(param)) {
			dev_err(fbdev->dev, "failed to run for "
				"private fifo open\n");
			s3cfb_enable_window(fbdev, id);
			return -EFAULT;
		}
	}

	s3cfb_set_window_control(fbdev, id);
	s3cfb_enable_window(fbdev, id);
	s3cfb_enable_localpath(fbdev, id);

	return 0;
}
Example #2
0
static int lcdfreq_lock(struct device *dev)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;

	int ret;

	if (!atomic_read(&lcdfreq->usage))
		ret = set_lcdfreq_div(dev, LEVEL_LIMIT);
	else {
		dev_err(dev, "lcd freq is already limit state\n");
		return -EINVAL;
	}

	if (!ret) {
		mutex_lock(&lcdfreq->lock);
		atomic_inc(&lcdfreq->usage);
		mutex_unlock(&lcdfreq->lock);
		schedule_delayed_work(&lcdfreq->work, 0);
	}

	return ret;
}
Example #3
0
static int lcdfreq_lock_free(struct device *dev)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;

	int ret;

	if (atomic_read(&lcdfreq->usage))
		ret = set_lcdfreq_div(dev, LEVEL_NORMAL);
	else {
		dev_err(dev, "lcd freq is already normal state\n");
		return -EINVAL;
	}

	if (!ret) {
		mutex_lock(&lcdfreq->lock);
		atomic_dec(&lcdfreq->usage);
		mutex_unlock(&lcdfreq->lock);
		cancel_delayed_work(&lcdfreq->work);
	}

	return ret;
}
Example #4
0
int s3cfb_open(struct fb_info *fb, int user)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);
	struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
	int ret = 0;

	mutex_lock(&fbdev->lock);

	if (atomic_read(&win->in_use)) {
		if (win->id == pdata->default_win) {
			dev_dbg(fbdev->dev,
				"mutiple open for default window\n");
			ret = 0;
		} else {
			dev_dbg(fbdev->dev,
				"do not allow multiple open for non-default window\n");
			ret = -EBUSY;
		}
	} else {
		atomic_inc(&win->in_use);
	}

	mutex_unlock(&fbdev->lock);

	return ret;
}
Example #5
0
int s3cfb_close_fifo(int id, int (*do_priv) (void *), void *param)
{
	struct s3cfb_global *fbdev = get_fimd_global(id);
	struct s3cfb_window *win = fbdev->fb[id]->par;
	win->path = DATA_PATH_DMA;

	dev_dbg(fbdev->dev, "[fb%d] close fifo\n", win->id);

	if (do_priv) {
		s3cfb_display_off(fbdev);

		if (do_priv(param)) {
			dev_err(fbdev->dev, "failed to run for"
				"private fifo close\n");
			s3cfb_enable_window(fbdev, id);
			s3cfb_display_on(fbdev);
			return -EFAULT;
		}

		s3cfb_disable_window(fbdev, id);
		s3cfb_disable_localpath(fbdev, id);
		s3cfb_display_on(fbdev);
	} else {
		s3cfb_disable_window(fbdev, id);
		s3cfb_disable_localpath(fbdev, id);
	}

	return 0;
}
Example #6
0
static ssize_t freq_store(struct device *dev,
		struct device_attribute *attr, const char *buf, size_t count)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct s3cfb_lcd *lcd = fbdev->lcd;
	struct s3cfb_lcd_timing *timing = &lcd->timing;
	struct fb_var_screeninfo *var = &fb->var;

	lcd->freq_limit = 0;
	sscanf(buf, "%d %d %d %d", &lcd->freq,
		&timing->h_fp, &timing->h_bp, &timing->h_sw);

	var->hsync_len = timing->h_sw;
	var->left_margin = timing->h_bp;
	var->right_margin = timing->h_fp;

	var->pixclock = (lcd->freq *
		(var->left_margin + var->right_margin
		+ var->hsync_len + var->xres) *
		(var->upper_margin + var->lower_margin
		+ var->vsync_len + var->yres));
	var->pixclock = KHZ2PICOS(var->pixclock/1000);

	s5p_dsim_set_lcd_freq_change(timing);

	return count;
}
Example #7
0
int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
{
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);

	s3cfb_check_var_window(fbdev, var, fb);

	return 0;
}
Example #8
0
int s3cfb_set_par(struct fb_info *fb)
{
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);

	s3cfb_set_par_window(fbdev, fb);

	return 0;
}
int s3cfb_set_par(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);

	s3cfb_set_par_window(fbdev, fb);

	return 0;
}
int s3cfb_check_var(struct fb_var_screeninfo *var, struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);

	s3cfb_check_var_window(fbdev, var, fb);

	return 0;
}
Example #11
0
static ssize_t usage_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;

	return sprintf(buf, "%d\n", atomic_read(&lcdfreq->usage));
}
Example #12
0
static ssize_t freq_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct s3cfb_lcd *lcd = fbdev->lcd;

	return sprintf(buf, "%dhz, hfp=%d, hbp=%d, hsw=%d, div=%d\n", lcd->freq,
	lcd->timing.h_fp, lcd->timing.h_bp, lcd->timing.h_sw, get_div(fbdev)+1);
}
Example #13
0
int fb_is_primary_device(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);
	struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);

	dev_dbg(fbdev->dev, "[fb%d] checking for primary device\n", win->id);

	if (win->id == pdata->default_win)
		return 1;
	else
		return 0;
}
Example #14
0
int s3cfb_release(struct fb_info *fb, int user)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);

	s3cfb_release_window(fb);

	mutex_lock(&fbdev->lock);
	atomic_dec(&win->in_use);
	mutex_unlock(&fbdev->lock);

	return 0;
}
Example #15
0
static ssize_t time_in_state_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;

	do_time_slice(lcdfreq->level);

	return sprintf(buf, "%llu %d (60Hz)\n%llu %d (40Hz)\n", 
		(unsigned long long)time_in_state[LEVEL_NORMAL], LEVEL_NORMAL,
		(unsigned long long)time_in_state[LEVEL_LIMIT], LEVEL_LIMIT);
}
Example #16
0
static ssize_t level_show(struct device *dev,
		struct device_attribute *attr, char *buf)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;

	if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) {
		dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable);
		return -EINVAL;
	}

	return sprintf(buf, "%dhz, div=%d\n", lcdfreq->table[lcdfreq->level].hz, get_div(fbdev));
}
Example #17
0
int s3cfb_set_par(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	int ret = 0;
#ifdef CONFIG_EXYNOS_DEV_PD
	struct platform_device *pdev = to_platform_device(fbdev->dev);

	pm_runtime_get_sync(&pdev->dev);
#endif
	ret = s3cfb_set_par_window(fbdev, fb);
#ifdef CONFIG_EXYNOS_DEV_PD
	pm_runtime_put(&pdev->dev);
#endif
	return ret;
}
Example #18
0
int s3cfb_release_window(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);
	struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);

	if (win->id != pdata->default_win) {
		s3cfb_disable_window(fbdev, win->id);
		s3cfb_unmap_video_memory(fbdev, fb);
		s3cfb_set_buffer_address(fbdev, win->id);
	}

	win->x = 0;
	win->y = 0;

	return 0;
}
int s3cfb_set_par(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	int ret = 0;

#ifdef CONFIG_EXYNOS_DEV_PD
	if (unlikely(fbdev->system_state == POWER_OFF)) {
		dev_err(fbdev->dev, "%s::system_state is POWER_OFF, fb%d\n", __func__, win->id);
		return 0;
	}
#endif

	ret = s3cfb_set_par_window(fbdev, fb);

	return ret;
}
Example #20
0
int s3cfb_pan_display(struct fb_var_screeninfo *var, struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);

	if (var->yoffset + var->yres > var->yres_virtual) {
		dev_err(fbdev->dev, "invalid yoffset value\n");
		return -EINVAL;
	}

	fb->var.yoffset = var->yoffset;

	dev_dbg(fbdev->dev, "[fb%d] yoffset for pan display: %d\n", win->id,
		var->yoffset);

	s3cfb_set_buffer_address(fbdev, win->id);

	return 0;
}
Example #21
0
static int set_lcdfreq_div(struct device *dev, enum lcdfreq_level_idx level)
{
	struct fb_info *fb = dev_get_drvdata(dev);
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);

	struct lcdfreq_info *lcdfreq = fbdev->data;

	u32 div, ret;

	mutex_lock(&lcdfreq->lock);

	if (unlikely(fbdev->system_state == POWER_OFF || !lcdfreq->enable)) {
		dev_err(dev, "%s reject. %d, %d\n", __func__, fbdev->system_state, lcdfreq->enable);
		ret = -EINVAL;
		goto exit;
	}

	div = lcdfreq->table[level].cmu_clkdiv;

	ret = set_div(fbdev, div);

	if (ret) {
		dev_err(dev, "fail to change lcd freq\n");
		goto exit;
	}

#ifdef CONFIG_LCD_FREQ_SWITCH_ACCOUNTING
  do_time_slice(lcdfreq->level);
#endif

	lcdfreq->level = level;

exit:
	mutex_unlock(&lcdfreq->lock);

	return ret;
}
Example #22
0
int s3cfb_ioctl(struct fb_info *fb, unsigned int cmd, unsigned long arg)
{
	struct fb_var_screeninfo *var = &fb->var;
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);
	struct s3cfb_lcd *lcd = fbdev->lcd;
	int ret = 0;

	union {
		struct s3cfb_user_window user_window;
		struct s3cfb_user_plane_alpha user_alpha;
		struct s3cfb_user_chroma user_chroma;
		int vsync;
	} p;

	switch (cmd) {
	case FBIO_WAITFORVSYNC:
		s3cfb_wait_for_vsync(fbdev);
		break;

	case S3CFB_WIN_POSITION:
		if (copy_from_user(&p.user_window,
				   (struct s3cfb_user_window __user *)arg,
				   sizeof(p.user_window)))
			ret = -EFAULT;
		else {
			if (p.user_window.x < 0)
				p.user_window.x = 0;

			if (p.user_window.y < 0)
				p.user_window.y = 0;

			if (p.user_window.x + var->xres > lcd->width)
				win->x = lcd->width - var->xres;
			else
				win->x = p.user_window.x;

			if (p.user_window.y + var->yres > lcd->height)
				win->y = lcd->height - var->yres;
			else
				win->y = p.user_window.y;

			s3cfb_set_window_position(fbdev, win->id);
		}
		break;

	case S3CFB_WIN_SET_PLANE_ALPHA:
		if (copy_from_user(&p.user_alpha,
				   (struct s3cfb_user_plane_alpha __user *)arg,
				   sizeof(p.user_alpha)))
			ret = -EFAULT;
		else {
			win->alpha.mode = PLANE_BLENDING;
			win->alpha.channel = p.user_alpha.channel;
			win->alpha.value =
			    S3CFB_AVALUE(p.user_alpha.red,
					 p.user_alpha.green, p.user_alpha.blue);

			s3cfb_set_alpha_blending(fbdev, win->id);
		}
		break;

	case S3CFB_WIN_SET_CHROMA:
		if (copy_from_user(&p.user_chroma,
				   (struct s3cfb_user_chroma __user *)arg,
				   sizeof(p.user_chroma)))
			ret = -EFAULT;
		else {
			win->chroma.enabled = p.user_chroma.enabled;
			win->chroma.key = S3CFB_CHROMA(p.user_chroma.red,
						       p.user_chroma.green,
						       p.user_chroma.blue);

			s3cfb_set_chroma_key(fbdev, win->id);
		}
		break;

	case S3CFB_SET_VSYNC_INT:
		if (get_user(p.vsync, (int __user *)arg))
			ret = -EFAULT;
		else {
			if (p.vsync)
				s3cfb_set_global_interrupt(fbdev, 1);
			s3cfb_set_vsync_interrupt(fbdev, p.vsync);
		}
		break;

#if MALI_USE_UNIFIED_MEMORY_PROVIDER
	case S3CFB_GET_FB_UMP_SECURE_ID_0:
		{
			u32 __user *psecureid = (u32 __user *) arg;
			ump_secure_id secure_id;

			dev_info(fbdev->dev, "ump_dd_secure_id_get\n");
			secure_id = ump_dd_secure_id_get(ump_wrapped_buffer);
			dev_info(fbdev->dev,
				"Saving secure id 0x%x in userptr %p\n"
				, (unsigned int)secure_id, psecureid);
			dev_dbg(fbdev->dev,
				"Saving secure id 0x%x in userptr %p\n"
				, (unsigned int)secure_id, psecureid);
			return put_user((unsigned int)secure_id, psecureid);
		}
		break;
#endif
	}

	return ret;
}
Example #23
0
int s3cfb_direct_ioctl(int id, unsigned int cmd, unsigned long arg)
{
	struct s3cfb_global *fbdev = get_fimd_global(id);
	struct fb_info *fb = fbdev->fb[id];
	struct fb_var_screeninfo *var = &fb->var;
	struct fb_fix_screeninfo *fix = &fb->fix;
	struct s3cfb_window *win = fb->par;
	struct s3cfb_lcd *lcd = fbdev->lcd;
	struct s3cfb_user_window user_win;
	void *argp = (void *)arg;
	int ret = 0;

	switch (cmd) {
	case FBIOGET_FSCREENINFO:
		ret = memcpy(argp, &fb->fix, sizeof(fb->fix)) ? 0 : -EFAULT;
		break;

	case FBIOGET_VSCREENINFO:
		ret = memcpy(argp, &fb->var, sizeof(fb->var)) ? 0 : -EFAULT;
		break;

	case FBIOPUT_VSCREENINFO:
		ret = s3cfb_check_var((struct fb_var_screeninfo *)argp, fb);
		if (ret) {
			dev_err(fbdev->dev, "invalid vscreeninfo\n");
			break;
		}

		ret = memcpy(&fb->var, (struct fb_var_screeninfo *)argp,
			     sizeof(fb->var)) ? 0 : -EFAULT;
		if (ret) {
			dev_err(fbdev->dev, "failed to put new vscreeninfo\n");
			break;
		}

		fix->line_length = var->xres_virtual * var->bits_per_pixel / 8;
		fix->smem_len = fix->line_length * var->yres_virtual;

		s3cfb_set_win_params(fbdev, id);
		break;

	case S3CFB_WIN_POSITION:
		ret = memcpy(&user_win, (struct s3cfb_user_window __user *)arg,
			     sizeof(user_win)) ? 0 : -EFAULT;
		if (ret) {
			dev_err(fbdev->dev, "failed to S3CFB_WIN_POSITION\n");
			break;
		}

		if (user_win.x < 0)
			user_win.x = 0;

		if (user_win.y < 0)
			user_win.y = 0;

		if (user_win.x + var->xres > lcd->width)
			win->x = lcd->width - var->xres;
		else
			win->x = user_win.x;

		if (user_win.y + var->yres > lcd->height)
			win->y = lcd->height - var->yres;
		else
			win->y = user_win.y;

		s3cfb_set_window_position(fbdev, win->id);
		break;

	case S3CFB_GET_LCD_WIDTH:
		ret = memcpy(argp, &lcd->width, sizeof(int)) ? 0 : -EFAULT;
		if (ret) {
			dev_err(fbdev->dev, "failed to S3CFB_GET_LCD_WIDTH\n");
			break;
		}

		break;

	case S3CFB_GET_LCD_HEIGHT:
		ret = memcpy(argp, &lcd->height, sizeof(int)) ? 0 : -EFAULT;
		if (ret) {
			dev_err(fbdev->dev, "failed to S3CFB_GET_LCD_HEIGHT\n");
			break;
		}

		break;

	case S3CFB_SET_WRITEBACK:
		if ((u32)argp == 1)
			fbdev->output = OUTPUT_WB_RGB;
		else
			fbdev->output = OUTPUT_RGB;

		s3cfb_set_output(fbdev);

		break;

	case S3CFB_SET_WIN_ON:
		s3cfb_enable_window(fbdev, id);
		break;

	case S3CFB_SET_WIN_OFF:
		s3cfb_disable_window(fbdev, id);
		break;

	case S3CFB_SET_WIN_PATH:
		win->path = (enum s3cfb_data_path_t)argp;
		break;

	case S3CFB_SET_WIN_ADDR:
		fix->smem_start = (unsigned long)argp;
		s3cfb_set_buffer_address(fbdev, id);
		break;

	case S3CFB_SET_WIN_MEM:
		win->owner = (enum s3cfb_mem_owner_t)argp;
		break;

	case S3CFB_SET_VSYNC_INT:
		if (argp)
			s3cfb_set_global_interrupt(fbdev, 1);

		s3cfb_set_vsync_interrupt(fbdev, (int)argp);
		break;

	case S3CFB_GET_VSYNC_INT_STATUS:
		ret = s3cfb_get_vsync_interrupt(fbdev);
		break;

	default:
		ret = s3cfb_ioctl(fb, cmd, arg);
		break;
	}

	return ret;
}
Example #24
0
int get_divider(struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_global *fbdev = get_fimd_global(win->id);
	struct lcdfreq_info *lcdfreq = fbdev->data;
	struct clksrc_clk *sclk;
	struct clk *clk;
	u32 rate, reg, i;
	u8 fimd_div;

	sclk = container_of(fbdev->clock, struct clksrc_clk, clk);
	clk = clk_get_parent(clk_get_parent(fbdev->clock));
	rate = clk_get_rate(clk);

	lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv =
		DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_NORMAL].vclk);

	lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv =
		DIV_ROUND_CLOSEST(rate, lcdfreq->table[LEVEL_LIMIT].vclk);

	fimd_div = gcd(lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv, lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv);

	if ((!fimd_div) || (fimd_div > 16)) {
		dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__);
		goto err;
	}

	lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv /= fimd_div;
	lcdfreq->table[LEVEL_LIMIT].cmu_clkdiv /= fimd_div;

	dev_info(fb->dev, "%s rate is %d, fimd divider=%d\n", clk->name, rate, fimd_div);

	fimd_div--;
	for (i = 0; i < LCDFREQ_LEVEL_END; i++) {
		if (lcdfreq->table[i].cmu_clkdiv > 16) {
			dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__);
			goto err;
		}
		dev_info(fb->dev, "%dhz div is %d\n",
		lcdfreq->table[i].hz, lcdfreq->table[i].cmu_clkdiv);
		lcdfreq->table[i].cmu_clkdiv--;
	}

	reg = (readl(fbdev->regs + S3C_VIDCON0) & (S3C_VIDCON0_CLKVAL_F(0xff))) >> 6;
	if (fimd_div != reg) {
		dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__);
		goto err;
	}

	reg = (readl(sclk->reg_div.reg)) >> sclk->reg_div.shift;
	reg &= 0xf;
	if (lcdfreq->table[LEVEL_NORMAL].cmu_clkdiv != reg) {
		dev_info(fb->dev, "%s skip, %d\n", __func__, __LINE__);
		goto err;
	}

	return 0;

err:
	return -EINVAL;
}
Example #25
0
int s3cfb_blank(int blank_mode, struct fb_info *fb)
{
	struct s3cfb_window *win = fb->par;
	struct s3cfb_window *tmp_win;
	struct s3cfb_global *fbdev = get_fimd_global(fb->node);
	struct platform_device *pdev = to_platform_device(fbdev->dev);
	struct s3c_platform_fb *pdata = to_fb_plat(fbdev->dev);
	int enabled_win = 0;
	int i;

	dev_dbg(fbdev->dev, "change blank mode\n");

	switch (blank_mode) {
	case FB_BLANK_UNBLANK:
		if (!fb->fix.smem_start) {
			dev_info(fbdev->dev, \
			"[fb%d] no allocated memory for unblank\n", win->id);
			break;
		}

		if (win->power_state == FB_BLANK_UNBLANK) {
			dev_info(fbdev->dev, \
			"[fb%d] already in FB_BLANK_UNBLANK\n", win->id);
			break;
		} else {
			s3cfb_update_power_state(fbdev, win->id,
						FB_BLANK_UNBLANK);
		}

		enabled_win = atomic_read(&fbdev->enabled_win);
		if (enabled_win == 0) {
			pdata->clk_on(pdev, &fbdev->clock);
			s3cfb_init_global(fbdev);
			s3cfb_set_clock(fbdev);
				for (i = 0; i < pdata->nr_wins; i++) {
					tmp_win = fbdev->fb[i]->par;
					if (tmp_win->owner == DMA_MEM_FIMD)
						s3cfb_set_win_params(fbdev,
								tmp_win->id);
				}
		}

		if (win->enabled)	/* from FB_BLANK_NORMAL */
			s3cfb_win_map_off(fbdev, win->id);
		else			/* from FB_BLANK_POWERDOWN */
			s3cfb_enable_window(fbdev, win->id);

		if (enabled_win == 0) {
			s3cfb_display_on(fbdev);

			if (pdata->backlight_on)
				pdata->backlight_on(pdev);
			if (pdata->lcd_on)
				pdata->lcd_on(pdev);
			if (fbdev->lcd->init_ldi)
				fbdev->lcd->init_ldi();
		}

		break;

	case FB_BLANK_NORMAL:
		if (win->power_state == FB_BLANK_NORMAL) {
			dev_info(fbdev->dev, \
			"[fb%d] already in FB_BLANK_NORMAL\n", win->id);
			break;
		} else {
			s3cfb_update_power_state(fbdev, win->id,
						FB_BLANK_NORMAL);
		}

		enabled_win = atomic_read(&fbdev->enabled_win);
		if (enabled_win == 0) {
			pdata->clk_on(pdev, &fbdev->clock);
			s3cfb_init_global(fbdev);
			s3cfb_set_clock(fbdev);

			for (i = 0; i < pdata->nr_wins; i++) {
				tmp_win = fbdev->fb[i]->par;
				if (tmp_win->owner == DMA_MEM_FIMD)
					s3cfb_set_win_params(fbdev,
							tmp_win->id);
			}
		}

		s3cfb_win_map_on(fbdev, win->id, 0x0);

		if (!win->enabled)	/* from FB_BLANK_POWERDOWN */
			s3cfb_enable_window(fbdev, win->id);

		if (enabled_win == 0) {
			s3cfb_display_on(fbdev);

			if (pdata->backlight_on)
				pdata->backlight_on(pdev);
			if (pdata->lcd_on)
				pdata->lcd_on(pdev);
			if (fbdev->lcd->init_ldi)
				fbdev->lcd->init_ldi();
		}

		break;

	case FB_BLANK_POWERDOWN:
		if (win->power_state == FB_BLANK_POWERDOWN) {
			dev_info(fbdev->dev, \
			"[fb%d] already in FB_BLANK_POWERDOWN\n", win->id);
			break;
		} else {
			s3cfb_update_power_state(fbdev, win->id,
						FB_BLANK_POWERDOWN);
		}

		s3cfb_disable_window(fbdev, win->id);
		s3cfb_win_map_off(fbdev, win->id);

		if (atomic_read(&fbdev->enabled_win) == 0) {
			if (pdata->backlight_off)
				pdata->backlight_off(pdev);
			if (fbdev->lcd->deinit_ldi)
				fbdev->lcd->deinit_ldi();
			if (pdata->lcd_off)
				pdata->lcd_off(pdev);
			s3cfb_display_off(fbdev);
			pdata->clk_off(pdev, &fbdev->clock);
		}

		break;

	case FB_BLANK_VSYNC_SUSPEND:	/* fall through */
	case FB_BLANK_HSYNC_SUSPEND:	/* fall through */
	default:
		dev_dbg(fbdev->dev, "unsupported blank mode\n");
		return -EINVAL;
	}

	return 0;
}