static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) { unsigned long control; void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; control = readl(ctrl_reg); if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { /* enable panel power */ control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control |= SM501_DC_PANEL_CONTROL_BIAS; /* VBIASEN */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control |= SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { /* disable panel power */ control &= ~SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control &= ~SM501_DC_PANEL_CONTROL_BIAS; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control &= ~SM501_DC_PANEL_CONTROL_DATA; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control &= ~SM501_DC_PANEL_CONTROL_VDD; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } sm501fb_sync_regs(fbi); }
static int sm501fb_pan_pnl(struct fb_var_screeninfo *var, struct fb_info *info) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; unsigned long reg; reg = var->xoffset | (var->xres_virtual << 16); writel(reg, fbi->regs + SM501_DC_PANEL_FB_WIDTH); reg = var->yoffset | (var->yres_virtual << 16); writel(reg, fbi->regs + SM501_DC_PANEL_FB_HEIGHT); sm501fb_sync_regs(fbi); return 0; }
static int sm501fb_pan_crt(struct fb_var_screeninfo *var, struct fb_info *info) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; unsigned int bytes_pixel = var->bits_per_pixel / 8; unsigned long reg; unsigned long xoffs; xoffs = var->xoffset * bytes_pixel; reg = readl(fbi->regs + SM501_DC_CRT_CONTROL); reg &= ~SM501_DC_CRT_CONTROL_PIXEL_MASK; reg |= ((xoffs & 15) / bytes_pixel) << 4; writel(reg, fbi->regs + SM501_DC_CRT_CONTROL); reg = (par->screen.sm_addr + xoffs + var->yoffset * info->fix.line_length); writel(reg | SM501_ADDR_FLIP, fbi->regs + SM501_DC_CRT_FB_ADDR); sm501fb_sync_regs(fbi); return 0; }
static int sm501fb_set_par_pnl(struct fb_info *info) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; struct fb_var_screeninfo *var = &info->var; unsigned long control; unsigned long reg; int ret; dev_dbg(fbi->dev, "%s(%p)\n", __func__, info); /* activate this new configuration */ ret = sm501fb_set_par_common(info, var); if (ret) return ret; sm501fb_pan_pnl(var, info); sm501fb_set_par_geometry(info, var); /* update control register */ control = readl(fbi->regs + SM501_DC_PANEL_CONTROL); control &= (SM501_DC_PANEL_CONTROL_GAMMA | SM501_DC_PANEL_CONTROL_VDD | SM501_DC_PANEL_CONTROL_DATA | SM501_DC_PANEL_CONTROL_BIAS | SM501_DC_PANEL_CONTROL_FPEN | SM501_DC_PANEL_CONTROL_CP | SM501_DC_PANEL_CONTROL_CK | SM501_DC_PANEL_CONTROL_HP | SM501_DC_PANEL_CONTROL_VP | SM501_DC_PANEL_CONTROL_HPD | SM501_DC_PANEL_CONTROL_VPD); control |= SM501_FIFO_3; /* fill if >3 free slots */ switch(var->bits_per_pixel) { case 8: control |= SM501_DC_PANEL_CONTROL_8BPP; break; case 16: control |= SM501_DC_PANEL_CONTROL_16BPP; break; case 32: control |= SM501_DC_PANEL_CONTROL_32BPP; sm501fb_setup_gamma(fbi, SM501_DC_PANEL_PALETTE); break; default: BUG(); } writel(0x0, fbi->regs + SM501_DC_PANEL_PANNING_CONTROL); /* panel plane top left and bottom right location */ writel(0x00, fbi->regs + SM501_DC_PANEL_TL_LOC); reg = var->xres - 1; reg |= (var->yres - 1) << 16; writel(reg, fbi->regs + SM501_DC_PANEL_BR_LOC); /* program panel control register */ control |= SM501_DC_PANEL_CONTROL_TE; /* enable PANEL timing */ control |= SM501_DC_PANEL_CONTROL_EN; /* enable PANEL gfx plane */ if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0) control |= SM501_DC_PANEL_CONTROL_HSP; if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) control |= SM501_DC_PANEL_CONTROL_VSP; writel(control, fbi->regs + SM501_DC_PANEL_CONTROL); sm501fb_sync_regs(fbi); /* power the panel up */ sm501fb_panel_power(fbi, 1); return 0; }
static int sm501fb_set_par_crt(struct fb_info *info) { struct sm501fb_par *par = info->par; struct sm501fb_info *fbi = par->info; struct fb_var_screeninfo *var = &info->var; unsigned long control; /* control register */ int ret; /* activate new configuration */ dev_dbg(fbi->dev, "%s(%p)\n", __func__, info); /* enable CRT DAC - note 0 is on!*/ sm501_misc_control(fbi->dev->parent, 0, SM501_MISC_DAC_POWER); control = readl(fbi->regs + SM501_DC_CRT_CONTROL); control &= (SM501_DC_CRT_CONTROL_PIXEL_MASK | SM501_DC_CRT_CONTROL_GAMMA | SM501_DC_CRT_CONTROL_BLANK | SM501_DC_CRT_CONTROL_SEL | SM501_DC_CRT_CONTROL_CP | SM501_DC_CRT_CONTROL_TVP); /* set the sync polarities before we check data source */ if ((var->sync & FB_SYNC_HOR_HIGH_ACT) == 0) control |= SM501_DC_CRT_CONTROL_HSP; if ((var->sync & FB_SYNC_VERT_HIGH_ACT) == 0) control |= SM501_DC_CRT_CONTROL_VSP; if ((control & SM501_DC_CRT_CONTROL_SEL) == 0) { /* the head is displaying panel data... */ sm501_alloc_mem(fbi, &par->screen, SM501_MEMF_CRT, 0); goto out_update; } ret = sm501fb_set_par_common(info, var); if (ret) { dev_err(fbi->dev, "failed to set common parameters\n"); return ret; } sm501fb_pan_crt(var, info); sm501fb_set_par_geometry(info, var); control |= SM501_FIFO_3; /* fill if >3 free slots */ switch(var->bits_per_pixel) { case 8: control |= SM501_DC_CRT_CONTROL_8BPP; break; case 16: control |= SM501_DC_CRT_CONTROL_16BPP; break; case 32: control |= SM501_DC_CRT_CONTROL_32BPP; sm501fb_setup_gamma(fbi, SM501_DC_CRT_PALETTE); break; default: BUG(); } control |= SM501_DC_CRT_CONTROL_SEL; /* CRT displays CRT data */ control |= SM501_DC_CRT_CONTROL_TE; /* enable CRT timing */ control |= SM501_DC_CRT_CONTROL_ENABLE; /* enable CRT plane */ out_update: dev_dbg(fbi->dev, "new control is %08lx\n", control); writel(control, fbi->regs + SM501_DC_CRT_CONTROL); sm501fb_sync_regs(fbi); return 0; }
static void sm501fb_panel_power(struct sm501fb_info *fbi, int to) { unsigned long control; void __iomem *ctrl_reg = fbi->regs + SM501_DC_PANEL_CONTROL; struct sm501_platdata_fbsub *pd = fbi->pdata->fb_pnl; control = readl(ctrl_reg); if (to && (control & SM501_DC_PANEL_CONTROL_VDD) == 0) { /* enable panel power */ control |= SM501_DC_PANEL_CONTROL_VDD; /* FPVDDEN */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control |= SM501_DC_PANEL_CONTROL_DATA; /* DATA */ writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); /* VBIASEN */ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) control &= ~SM501_DC_PANEL_CONTROL_BIAS; else control |= SM501_DC_PANEL_CONTROL_BIAS; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) control &= ~SM501_DC_PANEL_CONTROL_FPEN; else control |= SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } } else if (!to && (control & SM501_DC_PANEL_CONTROL_VDD) != 0) { /* disable panel power */ if (!(pd->flags & SM501FB_FLAG_PANEL_NO_FPEN)) { if (pd->flags & SM501FB_FLAG_PANEL_INV_FPEN) control |= SM501_DC_PANEL_CONTROL_FPEN; else control &= ~SM501_DC_PANEL_CONTROL_FPEN; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } if (!(pd->flags & SM501FB_FLAG_PANEL_NO_VBIASEN)) { if (pd->flags & SM501FB_FLAG_PANEL_INV_VBIASEN) control |= SM501_DC_PANEL_CONTROL_BIAS; else control &= ~SM501_DC_PANEL_CONTROL_BIAS; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } control &= ~SM501_DC_PANEL_CONTROL_DATA; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); control &= ~SM501_DC_PANEL_CONTROL_VDD; writel(control, ctrl_reg); sm501fb_sync_regs(fbi); mdelay(10); } sm501fb_sync_regs(fbi); }