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, ®s->screen_active); writel_relaxed((mode->left_margin << 16) | mode->right_margin, ®s->screen_h_porch); writel_relaxed((mode->upper_margin << 16) | mode->lower_margin, ®s->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, ®s->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, ®s->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 {