static void path_set_mode(struct mmp_path *path, struct mmp_mode *mode)
{
	struct lcd_regs *regs = path_regs(path);
	u32 total_x, total_y, vsync_ctrl, tmp, sclk_src, sclk_div,
		link_config = path_to_path_plat(path)->link_config;

	/* FIXME: assert videomode supported */
	memcpy(&path->mode, mode, sizeof(struct mmp_mode));

	mutex_lock(&path->access_ok);

	/* polarity of timing signals */
	tmp = readl_relaxed(ctrl_regs(path) + intf_ctrl(path->id)) & 0x1;
	tmp |= mode->vsync_invert ? 0x8 : 0;
	tmp |= mode->hsync_invert ? 0x4 : 0;
	tmp |= link_config & CFG_DUMBMODE_MASK;
	tmp |= CFG_DUMB_ENA(1);
	writel_relaxed(tmp, ctrl_regs(path) + intf_ctrl(path->id));

	/* interface rb_swap setting */
	tmp = readl_relaxed(ctrl_regs(path) + intf_rbswap_ctrl(path->id)) &
		(~(CFG_INTFRBSWAP_MASK));
	tmp |= link_config & CFG_INTFRBSWAP_MASK;
	writel_relaxed(tmp, ctrl_regs(path) + intf_rbswap_ctrl(path->id));

	writel_relaxed((mode->yres << 16) | mode->xres, &regs->screen_active);
	writel_relaxed((mode->left_margin << 16) | mode->right_margin,
		&regs->screen_h_porch);
	writel_relaxed((mode->upper_margin << 16) | mode->lower_margin,
		&regs->screen_v_porch);
	total_x = mode->xres + mode->left_margin + mode->right_margin +
		mode->hsync_len;
	total_y = mode->yres + mode->upper_margin + mode->lower_margin +
		mode->vsync_len;
	writel_relaxed((total_y << 16) | total_x, &regs->screen_size);

	/* vsync ctrl */
	if (path->output_type == PATH_OUT_DSI)
		vsync_ctrl = 0x01330133;
	else
		vsync_ctrl = ((mode->xres + mode->right_margin) << 16)
					| (mode->xres + mode->right_margin);
	writel_relaxed(vsync_ctrl, &regs->vsync_ctrl);

	/* set pixclock div */
	sclk_src = clk_get_rate(path_to_ctrl(path)->clk);
	sclk_div = sclk_src / mode->pixclock_freq;
	if (sclk_div * mode->pixclock_freq < sclk_src)
		sclk_div++;

	dev_info(path->dev, "%s sclk_src %d sclk_div 0x%x pclk %d\n",
			__func__, sclk_src, sclk_div, mode->pixclock_freq);

	tmp = readl_relaxed(ctrl_regs(path) + LCD_SCLK(path));
	tmp &= ~CLK_INT_DIV_MASK;
	tmp |= sclk_div;
	writel_relaxed(tmp, ctrl_regs(path) + LCD_SCLK(path));

	mutex_unlock(&path->access_ok);
}
int pxa688_cmu_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg)
{
	struct pxa168fb_info *fbi = info->par;
	void __user *argp = (void __user *)arg;
	struct _pxa168fb_cmu_config cmu_config;
	struct _pxa168fb_cmu_pip rect;
	struct pxa168fb_mach_info *mi = fbi->dev->platform_data;
	struct cmu_res res;
	int val, val_top, val_io_overl, val_bln_ctl, vsync_enable, hsync_enable;
	unsigned int pip_h, pip_v, main_h, main_v;
	static int path = 0;
	unsigned hsync_len = gfx_info.fbi[path]->fb_info->var.hsync_len;
	unsigned vsync_len = gfx_info.fbi[path]->fb_info->var.vsync_len;
	unsigned left_margin = gfx_info.fbi[path]->fb_info->var.left_margin;
	unsigned upper_margin = gfx_info.fbi[path]->fb_info->var.upper_margin;
	unsigned yres = gfx_info.fbi[path]->fb_info->var.yres;
	unsigned xres = gfx_info.fbi[path]->fb_info->var.xres;

	switch (cmd) {
		case FB_IOCTL_CMU_GET_RES:
			if (copy_from_user(&res, argp, sizeof(res)))
				return -EFAULT;
			res.width = xres;
			res.height = yres;
			return copy_to_user(argp, &res, sizeof(res)) ? -EFAULT : 0;
			break;
		case FB_IOCTL_CMU_SWITCH:	/* FIXME */
			if (arg) {
				writel(0x1, fbi->reg_base + 0x400 + CMU_CTRL);
				val = readl(fbi->reg_base + LCD_TOP_CTRL);
				if (fbi->id == 0)
					val |= 0x1;
				else
					val |= 0x3;
				writel(val, fbi->reg_base + LCD_TOP_CTRL);
			} else {
				val = readl(fbi->reg_base + LCD_TOP_CTRL);
				val &= (~0x3);
				writel(val, fbi->reg_base + LCD_TOP_CTRL);
				writel(0x0, fbi->reg_base + 0x400 + CMU_CTRL);
			}
			break;
		case FB_IOCTL_CMU_SET_PIP:
			if ( !cpu_is_mmp2_z0() && !cpu_is_mmp2_z1()) {
				if(copy_from_user(&rect, argp, sizeof(rect)))
					return -EFAULT;
				/*
				*if vsync/hsync inverted,
				*exclude hsync_len and vsync_len
				*/
				hsync_enable = (readl(fbi->reg_base +
					intf_ctrl(fbi->id)) & HINVERT_MSK)
					>> HINVERT_LEN;
				vsync_enable = (readl(fbi->reg_base +
					intf_ctrl(fbi->id)) & VINVERT_MSK)
					>> VINVERT_LEN;
				if (hsync_enable)
					hsync_len = 0;
				if (vsync_enable)
					vsync_len = 0;
				/*calculate pip setting data*/
				pip_h = ((rect.left + left_margin + hsync_len
					+ mi->cmu_cal[path].left) & 0xfff) |
					((rect.right + left_margin + hsync_len
					+ mi->cmu_cal[path].right)<<12 &
					0xfff000);
				pip_v = ((rect.top + upper_margin + vsync_len
					+ mi->cmu_cal[path].top) & 0xfff) |
					((rect.bottom + upper_margin +
					vsync_len + mi->cmu_cal[path].bottom)
					<<12 & 0xfff000);
				main_h = ((left_margin + hsync_len) & 0xfff) |
					((xres + hsync_len + left_margin)<<12
					 & 0xfff000);
				main_v = ((upper_margin + vsync_len) & 0xfff) |
					((yres + upper_margin + vsync_len)<<12
					 & 0xfff000);
				/*set pip register*/
				writel(pip_h, fbi->reg_base + 0x400 + 0x08);// ACE_PIP_DE
				writel(pip_v, fbi->reg_base + 0x400 + 0x0c);
				writel(pip_h, fbi->reg_base + 0x400 + 0x28);// PIP_DE
				writel(pip_v, fbi->reg_base + 0x400 + 0x2c);
				writel(pip_h, fbi->reg_base + 0x400 + 0x10);// PRI
				writel(pip_v, fbi->reg_base + 0x400 + 0x14);

				writel(main_h, fbi->reg_base + 0x400 + 0x20);// ACE_MAIN_DE
				writel(main_v, fbi->reg_base + 0x400 + 0x24);
				writel(0x3f, fbi->reg_base + 0x400 + 0x30);
			} else {
				printk(KERN_INFO"Z stepping doesn't support\
					 PIP mode!\n");
			}
			break;
		case FB_IOCTL_CMU_SET_LETTER_BOX:
			if (!cpu_is_mmp2_z0() && !cpu_is_mmp2_z1()) {
				if (copy_from_user(&rect, argp, sizeof(rect)))
					return -EFAULT;
				/*
				* if vsync/hsync inverted,
				* exclude hsync_len and vsync_len
				*/
				hsync_enable = (readl(fbi->reg_base +
					intf_ctrl(fbi->id)) & HINVERT_MSK)
					>> HINVERT_LEN;
				vsync_enable = (readl(fbi->reg_base +
					intf_ctrl(fbi->id)) & VINVERT_MSK)
					 >> VINVERT_LEN;
				if (hsync_enable)
					hsync_len = 0;
				if (vsync_enable)
					vsync_len = 0;
				/* calculate letter box setting data */
				pip_h = ((rect.left + left_margin + hsync_len +
					mi->cmu_cal_letter_box[path].left)
					& 0xfff) |
					((rect.right + left_margin + hsync_len
					+ mi->cmu_cal_letter_box[path].right)
					<<12 & 0xfff000);
				pip_v = ((rect.top + upper_margin + vsync_len +
					mi->cmu_cal_letter_box[path].top)
					& 0xfff) |
					((rect.bottom + upper_margin + vsync_len
					+ mi->cmu_cal_letter_box[path].bottom)
					<<12 & 0xfff000);
				/* set letter box register */
				/* ACE_LETTER_BOX_DE */
				writel(pip_h, fbi->reg_base + 0x400 + 0x18);
				writel(pip_v, fbi->reg_base + 0x400 + 0x1c);
				val = readl(fbi->reg_base + 0x400 + 0x30);
				/* Enable Letter box setting */
				writel(val|0x3, fbi->reg_base + 0x400 + 0x30);
			} else {