diff options
Diffstat (limited to 'drivers/video')
-rw-r--r-- | drivers/video/Kconfig | 21 | ||||
-rw-r--r-- | drivers/video/Makefile | 1 | ||||
-rw-r--r-- | drivers/video/acornfb.c | 20 | ||||
-rw-r--r-- | drivers/video/bw2.c | 105 | ||||
-rw-r--r-- | drivers/video/cg14.c | 150 | ||||
-rw-r--r-- | drivers/video/cg3.c | 136 | ||||
-rw-r--r-- | drivers/video/cg6.c | 161 | ||||
-rw-r--r-- | drivers/video/chipsfb.c | 3 | ||||
-rw-r--r-- | drivers/video/console/fonts.c | 4 | ||||
-rw-r--r-- | drivers/video/fbmem.c | 42 | ||||
-rw-r--r-- | drivers/video/ffb.c | 170 | ||||
-rw-r--r-- | drivers/video/geode/Kconfig | 15 | ||||
-rw-r--r-- | drivers/video/geode/Makefile | 2 | ||||
-rw-r--r-- | drivers/video/geode/lxfb.h | 199 | ||||
-rw-r--r-- | drivers/video/geode/lxfb_core.c | 621 | ||||
-rw-r--r-- | drivers/video/geode/lxfb_ops.c | 536 | ||||
-rw-r--r-- | drivers/video/leo.c | 147 | ||||
-rw-r--r-- | drivers/video/p9100.c | 138 | ||||
-rw-r--r-- | drivers/video/s3c2410fb.c | 88 | ||||
-rw-r--r-- | drivers/video/s3c2410fb.h | 3 | ||||
-rw-r--r-- | drivers/video/sbuslib.c | 25 | ||||
-rw-r--r-- | drivers/video/tcx.c | 184 | ||||
-rw-r--r-- | drivers/video/tgafb.c | 2 | ||||
-rw-r--r-- | drivers/video/tx3912fb.c | 326 | ||||
-rw-r--r-- | drivers/video/xilinxfb.c | 23 |
25 files changed, 2048 insertions, 1074 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 564cc9b5182..5216c11d4de 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1571,7 +1571,14 @@ config FB_PM3 config FB_AU1100 bool "Au1100 LCD Driver" - depends on (FB = y) && EXPERIMENTAL && PCI && MIPS && MIPS_PB1100=y + depends on (FB = y) && MIPS && SOC_AU1100 + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + help + This is the framebuffer driver for the AMD Au1100 SOC. It can drive + various panels and CRTs by passing in kernel cmd line option + au1100fb:panel=<name>. config FB_AU1200 bool "Au1200 LCD Driver" @@ -1638,18 +1645,6 @@ config FB_MAXINE DECstation series (Personal DECstation 5000/20, /25, /33, /50, Codename "Maxine"). -config FB_TX3912 - bool "TMPTX3912/PR31700 frame buffer support" - depends on (FB = y) && NINO - select FB_CFB_FILLRECT - select FB_CFB_COPYAREA - select FB_CFB_IMAGEBLIT - help - The TX3912 is a Toshiba RISC processor based on the MIPS 3900 core - see <http://www.toshiba.com/taec/components/Generic/risc/tx3912.htm>. - - Say Y here to enable kernel support for the on-board framebuffer. - config FB_G364 bool "G364 frame buffer support" depends on (FB = y) && (MIPS_MAGNUM_4000 || OLIVETTI_M700) diff --git a/drivers/video/Makefile b/drivers/video/Makefile index 518933d4905..06eec7b182b 100644 --- a/drivers/video/Makefile +++ b/drivers/video/Makefile @@ -103,7 +103,6 @@ obj-$(CONFIG_FB_PMAG_AA) += pmag-aa-fb.o obj-$(CONFIG_FB_PMAG_BA) += pmag-ba-fb.o obj-$(CONFIG_FB_PMAGB_B) += pmagb-b-fb.o obj-$(CONFIG_FB_MAXINE) += maxinefb.o -obj-$(CONFIG_FB_TX3912) += tx3912fb.o obj-$(CONFIG_FB_S1D13XXX) += s1d13xxxfb.o obj-$(CONFIG_FB_IMX) += imxfb.o obj-$(CONFIG_FB_S3C2410) += s3c2410fb.o diff --git a/drivers/video/acornfb.c b/drivers/video/acornfb.c index 61a8bf159cb..eedb8285e32 100644 --- a/drivers/video/acornfb.c +++ b/drivers/video/acornfb.c @@ -138,17 +138,6 @@ static struct pixclock arc_clocks[] = { { 41250, 42083, VIDC_CTRL_DIV1, VID_CTL_24MHz }, /* 24.000MHz */ }; -#ifdef CONFIG_ARCH_A5K -static struct pixclock a5k_clocks[] = { - { 117974, 120357, VIDC_CTRL_DIV3, VID_CTL_25MHz }, /* 8.392MHz */ - { 78649, 80238, VIDC_CTRL_DIV2, VID_CTL_25MHz }, /* 12.588MHz */ - { 58987, 60178, VIDC_CTRL_DIV1_5, VID_CTL_25MHz }, /* 16.588MHz */ - { 55000, 56111, VIDC_CTRL_DIV2, VID_CTL_36MHz }, /* 18.000MHz */ - { 39325, 40119, VIDC_CTRL_DIV1, VID_CTL_25MHz }, /* 25.175MHz */ - { 27500, 28055, VIDC_CTRL_DIV1, VID_CTL_36MHz }, /* 36.000MHz */ -}; -#endif - static struct pixclock * acornfb_valid_pixrate(struct fb_var_screeninfo *var) { @@ -163,15 +152,6 @@ acornfb_valid_pixrate(struct fb_var_screeninfo *var) pixclock < arc_clocks[i].max_clock) return arc_clocks + i; -#ifdef CONFIG_ARCH_A5K - if (machine_is_a5k()) { - for (i = 0; i < ARRAY_SIZE(a5k_clocks); i++) - if (pixclock > a5k_clocks[i].min_clock && - pixclock < a5k_clocks[i].max_clock) - return a5k_clocks + i; - } -#endif - return NULL; } diff --git a/drivers/video/bw2.c b/drivers/video/bw2.c index b0b2e40bbd9..718b9f83736 100644 --- a/drivers/video/bw2.c +++ b/drivers/video/bw2.c @@ -279,90 +279,91 @@ static void __devinit bw2_do_default_mode(struct bw2_par *par, } } -struct all_info { - struct fb_info info; - struct bw2_par par; -}; - -static int __devinit bw2_init_one(struct of_device *op) +static int __devinit bw2_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct bw2_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct bw2_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 1); + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; + + sbusfb_fill_var(&info->var, dp->node, 1); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); + info->var.xres); - all->info.var.red.length = all->info.var.green.length = - all->info.var.blue.length = all->info.var.bits_per_pixel; - all->info.var.red.offset = all->info.var.green.offset = - all->info.var.blue.offset = 0; + info->var.red.length = info->var.green.length = + info->var.blue.length = info->var.bits_per_pixel; + info->var.red.offset = info->var.green.offset = + info->var.blue.offset = 0; - all->par.regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, - sizeof(struct bw2_regs), "bw2 regs"); + par->regs = of_ioremap(&op->resource[0], BWTWO_REGISTER_OFFSET, + sizeof(struct bw2_regs), "bw2 regs"); + if (!par->regs) + goto out_release_fb; if (!of_find_property(dp, "width", NULL)) - bw2_do_default_mode(&all->par, &all->info, &linebytes); + bw2_do_default_mode(par, info, &linebytes); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &bw2_ops; + info->flags = FBINFO_DEFAULT; + info->fbops = &bw2_ops; - all->info.screen_base = - of_ioremap(&op->resource[0], 0, all->par.fbsize, "bw2 ram"); - all->info.par = &all->par; + info->screen_base = of_ioremap(&op->resource[0], 0, + par->fbsize, "bw2 ram"); + if (!info->screen_base) + goto out_unmap_regs; - bw2_blank(0, &all->info); + bw2_blank(0, info); - bw2_init_fix(&all->info, linebytes); + bw2_init_fix(info, linebytes); - err= register_framebuffer(&all->info); - if (err < 0) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct bw2_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_unmap_screen; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: bwtwo at %lx:%lx\n", - dp->full_name, - all->par.which_io, all->par.physbase); + dp->full_name, par->which_io, par->physbase); return 0; -} -static int __devinit bw2_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_unmap_screen: + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs)); + +out_release_fb: + framebuffer_release(info); - return bw2_init_one(op); +out_err: + return err; } static int __devexit bw2_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct bw2_par *par = info->par; - unregister_framebuffer(&all->info); + unregister_framebuffer(info); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct bw2_regs)); - of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct bw2_regs)); + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg14.c b/drivers/video/cg14.c index b071bb632b9..41f6dbf61be 100644 --- a/drivers/video/cg14.c +++ b/drivers/video/cg14.c @@ -448,81 +448,79 @@ static struct sbus_mmap_map __cg14_mmap_map[CG14_MMAP_ENTRIES] __devinitdata = { { .size = 0 } }; -struct all_info { - struct fb_info info; - struct cg14_par par; -}; - -static void cg14_unmap_regs(struct of_device *op, struct all_info *all) +static void cg14_unmap_regs(struct of_device *op, struct fb_info *info, + struct cg14_par *par) { - if (all->par.regs) + if (par->regs) of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg14_regs)); - if (all->par.clut) + par->regs, sizeof(struct cg14_regs)); + if (par->clut) of_iounmap(&op->resource[0], - all->par.clut, sizeof(struct cg14_clut)); - if (all->par.cursor) + par->clut, sizeof(struct cg14_clut)); + if (par->cursor) of_iounmap(&op->resource[0], - all->par.cursor, sizeof(struct cg14_cursor)); - if (all->info.screen_base) + par->cursor, sizeof(struct cg14_cursor)); + if (info->screen_base) of_iounmap(&op->resource[1], - all->info.screen_base, all->par.fbsize); + info->screen_base, par->fbsize); } -static int __devinit cg14_init_one(struct of_device *op) +static int __devinit cg14_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg14_par *par; int is_8mb, linebytes, i, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg14_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); if (!strcmp(dp->parent->name, "sbus") || !strcmp(dp->parent->name, "sbi")) { - all->par.physbase = op->resource[0].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->iospace = op->resource[0].flags & IORESOURCE_BITS; } else { - all->par.physbase = op->resource[1].start; - all->par.iospace = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[1].start; + par->iospace = op->resource[0].flags & IORESOURCE_BITS; } - all->par.regs = of_ioremap(&op->resource[0], 0, - sizeof(struct cg14_regs), "cg14 regs"); - all->par.clut = of_ioremap(&op->resource[0], CG14_CLUT1, - sizeof(struct cg14_clut), "cg14 clut"); - all->par.cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, - sizeof(struct cg14_cursor), "cg14 cursor"); + par->regs = of_ioremap(&op->resource[0], 0, + sizeof(struct cg14_regs), "cg14 regs"); + par->clut = of_ioremap(&op->resource[0], CG14_CLUT1, + sizeof(struct cg14_clut), "cg14 clut"); + par->cursor = of_ioremap(&op->resource[0], CG14_CURSORREGS, + sizeof(struct cg14_cursor), "cg14 cursor"); - all->info.screen_base = of_ioremap(&op->resource[1], 0, - all->par.fbsize, "cg14 ram"); + info->screen_base = of_ioremap(&op->resource[1], 0, + par->fbsize, "cg14 ram"); - if (!all->par.regs || !all->par.clut || !all->par.cursor || - !all->info.screen_base) - cg14_unmap_regs(op, all); + if (!par->regs || !par->clut || !par->cursor || !info->screen_base) + goto out_unmap_regs; is_8mb = (((op->resource[1].end - op->resource[1].start) + 1) == (8 * 1024 * 1024)); - BUILD_BUG_ON(sizeof(all->par.mmap_map) != sizeof(__cg14_mmap_map)); + BUILD_BUG_ON(sizeof(par->mmap_map) != sizeof(__cg14_mmap_map)); - memcpy(&all->par.mmap_map, &__cg14_mmap_map, - sizeof(all->par.mmap_map)); + memcpy(&par->mmap_map, &__cg14_mmap_map, sizeof(par->mmap_map)); for (i = 0; i < CG14_MMAP_ENTRIES; i++) { - struct sbus_mmap_map *map = &all->par.mmap_map[i]; + struct sbus_mmap_map *map = &par->mmap_map[i]; if (!map->size) break; @@ -536,59 +534,55 @@ static int __devinit cg14_init_one(struct of_device *op) map->size *= 2; } - all->par.mode = MDI_8_PIX; - all->par.ramsize = (is_8mb ? 0x800000 : 0x400000); + par->mode = MDI_8_PIX; + par->ramsize = (is_8mb ? 0x800000 : 0x400000); - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - all->info.fbops = &cg14_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->fbops = &cg14_ops; - __cg14_reset(&all->par); + __cg14_reset(par); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - cg14_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } - fb_set_cmap(&all->info.cmap, &all->info); + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - cg14_init_fix(&all->info, linebytes, dp); + fb_set_cmap(&info->cmap, info); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - cg14_unmap_regs(op, all); - kfree(all); - return err; - } + cg14_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: cgfourteen at %lx:%lx, %dMB\n", dp->full_name, - all->par.iospace, all->par.physbase, - all->par.ramsize >> 20); + par->iospace, par->physbase, + par->ramsize >> 20); return 0; -} -static int __devinit cg14_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + cg14_unmap_regs(op, info, par); - return cg14_init_one(op); +out_err: + return err; } static int __devexit cg14_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg14_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - cg14_unmap_regs(op, all); + cg14_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg3.c b/drivers/video/cg3.c index f042428a84f..5741b46ade1 100644 --- a/drivers/video/cg3.c +++ b/drivers/video/cg3.c @@ -353,104 +353,102 @@ static void __devinit cg3_do_default_mode(struct cg3_par *par) } } -struct all_info { - struct fb_info info; - struct cg3_par par; -}; - -static int __devinit cg3_init_one(struct of_device *op) +static int __devinit cg3_probe(struct of_device *op, + const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg3_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg3_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + spin_lock_init(&par->lock); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; + + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; if (!strcmp(dp->name, "cgRDI")) - all->par.flags |= CG3_FLAG_RDI; - if (all->par.flags & CG3_FLAG_RDI) - cg3_rdi_maybe_fixup_var(&all->info.var, dp); + par->flags |= CG3_FLAG_RDI; + if (par->flags & CG3_FLAG_RDI) + cg3_rdi_maybe_fixup_var(&info->var, dp); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET, - sizeof(struct cg3_regs), "cg3 regs"); + par->regs = of_ioremap(&op->resource[0], CG3_REGS_OFFSET, + sizeof(struct cg3_regs), "cg3 regs"); + if (!par->regs) + goto out_release_fb; - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &cg3_ops; - all->info.screen_base = - of_ioremap(&op->resource[0], CG3_RAM_OFFSET, - all->par.fbsize, "cg3 ram"); - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT; + info->fbops = &cg3_ops; + info->screen_base = of_ioremap(&op->resource[0], CG3_RAM_OFFSET, + par->fbsize, "cg3 ram"); + if (!info->screen_base) + goto out_unmap_regs; - cg3_blank(0, &all->info); + cg3_blank(0, info); if (!of_find_property(dp, "width", NULL)) - cg3_do_default_mode(&all->par); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return -ENOMEM; - } - fb_set_cmap(&all->info.cmap, &all->info); - - cg3_init_fix(&all->info, linebytes, dp); - - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } + cg3_do_default_mode(par); + + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_screen; + + fb_set_cmap(&info->cmap, info); - dev_set_drvdata(&op->dev, all); + cg3_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + dev_set_drvdata(&op->dev, info); printk("%s: cg3 at %lx:%lx\n", - dp->full_name, all->par.which_io, all->par.physbase); + dp->full_name, par->which_io, par->physbase); return 0; -} -static int __devinit cg3_probe(struct of_device *dev, - const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_screen: + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs)); + +out_release_fb: + framebuffer_release(info); - return cg3_init_one(op); +out_err: + return err; } static int __devexit cg3_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg3_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct cg3_regs)); - of_iounmap(&op->resource[0], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct cg3_regs)); + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/cg6.c b/drivers/video/cg6.c index 4dad23a28f5..87c74712353 100644 --- a/drivers/video/cg6.c +++ b/drivers/video/cg6.c @@ -653,135 +653,120 @@ static void cg6_chip_init(struct fb_info *info) sbus_writel(info->var.yres - 1, &fbc->clipmaxy); } -struct all_info { - struct fb_info info; - struct cg6_par par; -}; - -static void cg6_unmap_regs(struct of_device *op, struct all_info *all) +static void cg6_unmap_regs(struct of_device *op, struct fb_info *info, + struct cg6_par *par) { - if (all->par.fbc) - of_iounmap(&op->resource[0], all->par.fbc, 4096); - if (all->par.tec) - of_iounmap(&op->resource[0], - all->par.tec, sizeof(struct cg6_tec)); - if (all->par.thc) - of_iounmap(&op->resource[0], - all->par.thc, sizeof(struct cg6_thc)); - if (all->par.bt) - of_iounmap(&op->resource[0], - all->par.bt, sizeof(struct bt_regs)); - if (all->par.fhc) - of_iounmap(&op->resource[0], - all->par.fhc, sizeof(u32)); - - if (all->info.screen_base) - of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); + if (par->fbc) + of_iounmap(&op->resource[0], par->fbc, 4096); + if (par->tec) + of_iounmap(&op->resource[0], par->tec, sizeof(struct cg6_tec)); + if (par->thc) + of_iounmap(&op->resource[0], par->thc, sizeof(struct cg6_thc)); + if (par->bt) + of_iounmap(&op->resource[0], par->bt, sizeof(struct bt_regs)); + if (par->fhc) + of_iounmap(&op->resource[0], par->fhc, sizeof(u32)); + + if (info->screen_base) + of_iounmap(&op->resource[0], info->screen_base, par->fbsize); } -static int __devinit cg6_init_one(struct of_device *op) +static int __devinit cg6_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct cg6_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct cg6_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); if (of_find_property(dp, "dblbuf", NULL)) - all->par.fbsize *= 4; + par->fbsize *= 4; - all->par.fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, + par->fbc = of_ioremap(&op->resource[0], CG6_FBC_OFFSET, 4096, "cgsix fbc"); - all->par.tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, + par->tec = of_ioremap(&op->resource[0], CG6_TEC_OFFSET, sizeof(struct cg6_tec), "cgsix tec"); - all->par.thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, + par->thc = of_ioremap(&op->resource[0], CG6_THC_OFFSET, sizeof(struct cg6_thc), "cgsix thc"); - all->par.bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, + par->bt = of_ioremap(&op->resource[0], CG6_BROOKTREE_OFFSET, sizeof(struct bt_regs), "cgsix dac"); - all->par.fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, + par->fhc = of_ioremap(&op->resource[0], CG6_FHC_OFFSET, sizeof(u32), "cgsix fhc"); - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_IMAGEBLIT | FBINFO_HWACCEL_COPYAREA | FBINFO_HWACCEL_FILLRECT; - all->info.fbops = &cg6_ops; - - all->info.screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, - all->par.fbsize, "cgsix ram"); - if (!all->par.fbc || !all->par.tec || !all->par.thc || - !all->par.bt || !all->par.fhc || !all->info.screen_base) { - cg6_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + info->fbops = &cg6_ops; - all->info.par = &all->par; + info->screen_base = of_ioremap(&op->resource[0], CG6_RAM_OFFSET, + par->fbsize, "cgsix ram"); + if (!par->fbc || !par->tec || !par->thc || + !par->bt || !par->fhc || !info->screen_base) + goto out_unmap_regs; - all->info.var.accel_flags = FB_ACCELF_TEXT; + info->var.accel_flags = FB_ACCELF_TEXT; - cg6_bt_init(&all->par); - cg6_chip_init(&all->info); - cg6_blank(0, &all->info); + cg6_bt_init(par); + cg6_chip_init(info); + cg6_blank(0, info); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - cg6_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - fb_set_cmap(&all->info.cmap, &all->info); - cg6_init_fix(&all->info, linebytes); + fb_set_cmap(&info->cmap, info); + cg6_init_fix(info, linebytes); - err = register_framebuffer(&all->info); - if (err < 0) { - cg6_unmap_regs(op, all); - fb_dealloc_cmap(&all->info.cmap); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: CGsix [%s] at %lx:%lx\n", - dp->full_name, - all->info.fix.id, - all->par.which_io, all->par.physbase); + dp->full_name, info->fix.id, + par->which_io, par->physbase); return 0; -} -static int __devinit cg6_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + cg6_unmap_regs(op, info, par); - return cg6_init_one(op); +out_err: + return err; } static int __devexit cg6_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct cg6_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - cg6_unmap_regs(op, all); + cg6_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/chipsfb.c b/drivers/video/chipsfb.c index f48e8c534c8..6796ba62c3c 100644 --- a/drivers/video/chipsfb.c +++ b/drivers/video/chipsfb.c @@ -24,6 +24,7 @@ #include <linux/delay.h> #include <linux/interrupt.h> #include <linux/fb.h> +#include <linux/pm.h> #include <linux/init.h> #include <linux/pci.h> #include <linux/console.h> @@ -458,7 +459,7 @@ static int chipsfb_pci_suspend(struct pci_dev *pdev, pm_message_t state) if (state.event == pdev->dev.power.power_state.event) return 0; - if (state.event != PM_SUSPEND_MEM) + if (state.event != PM_EVENT_SUSPEND) goto done; acquire_console_sem(); diff --git a/drivers/video/console/fonts.c b/drivers/video/console/fonts.c index a6828d0a4c5..96979c37751 100644 --- a/drivers/video/console/fonts.c +++ b/drivers/video/console/fonts.c @@ -133,8 +133,8 @@ const struct font_desc *get_default_font(int xres, int yres, u32 font_w, if ((yres < 400) == (f->height <= 8)) c += 1000; - if (!(font_w & (1 << (f->width - 1))) || - !(font_w & (1 << (f->height - 1)))) + if ((font_w & (1 << (f->width - 1))) && + (font_h & (1 << (f->height - 1)))) c += 1000; if (c > cc) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index 215ac579f90..07402720470 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -244,8 +244,17 @@ static void fb_set_logo(struct fb_info *info, u8 xor = (info->fix.visual == FB_VISUAL_MONO01) ? 0xff : 0; u8 fg = 1, d; - if (fb_get_color_depth(&info->var, &info->fix) == 3) + switch (fb_get_color_depth(&info->var, &info->fix)) { + case 1: + fg = 1; + break; + case 2: + fg = 3; + break; + default: fg = 7; + break; + } if (info->fix.visual == FB_VISUAL_MONO01 || info->fix.visual == FB_VISUAL_MONO10) @@ -564,21 +573,6 @@ int fb_prepare_logo(struct fb_info *info, int rotate) depth = 4; } - if (depth >= 8) { - switch (info->fix.visual) { - case FB_VISUAL_TRUECOLOR: - fb_logo.needs_truepalette = 1; - break; - case FB_VISUAL_DIRECTCOLOR: - fb_logo.needs_directpalette = 1; - fb_logo.needs_cmapreset = 1; - break; - case FB_VISUAL_PSEUDOCOLOR: - fb_logo.needs_cmapreset = 1; - break; - } - } - /* Return if no suitable logo was found */ fb_logo.logo = fb_find_logo(depth); @@ -604,6 +598,22 @@ int fb_prepare_logo(struct fb_info *info, int rotate) else fb_logo.depth = 1; + + if (fb_logo.depth > 4 && depth > 4) { + switch (info->fix.visual) { + case FB_VISUAL_TRUECOLOR: + fb_logo.needs_truepalette = 1; + break; + case FB_VISUAL_DIRECTCOLOR: + fb_logo.needs_directpalette = 1; + fb_logo.needs_cmapreset = 1; + break; + case FB_VISUAL_PSEUDOCOLOR: + fb_logo.needs_cmapreset = 1; + break; + } + } + return fb_prepare_extra_logos(info, fb_logo.logo->height, yres); } diff --git a/drivers/video/ffb.c b/drivers/video/ffb.c index 3f6c98fad43..4b520b57391 100644 --- a/drivers/video/ffb.c +++ b/drivers/video/ffb.c @@ -371,6 +371,8 @@ struct ffb_par { unsigned long fbsize; int board_type; + + u32 pseudo_palette[16]; }; static void FFBFifo(struct ffb_par *par, int n) @@ -900,75 +902,67 @@ ffb_init_fix(struct fb_info *info) info->fix.accel = FB_ACCEL_SUN_CREATOR; } -struct all_info { - struct fb_info info; - struct ffb_par par; - u32 pseudo_palette[16]; -}; - -static int ffb_init_one(struct of_device *op) +static int __devinit ffb_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; struct ffb_fbc __iomem *fbc; struct ffb_dac __iomem *dac; - struct all_info *all; - int err; + struct fb_info *info; + struct ffb_par *par; u32 dac_pnum, dac_rev, dac_mrev; + int err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct ffb_par), &op->dev); - spin_lock_init(&all->par.lock); - all->par.fbc = of_ioremap(&op->resource[2], 0, - sizeof(struct ffb_fbc), "ffb fbc"); - if (!all->par.fbc) { - kfree(all); - return -ENOMEM; - } + err = -ENOMEM; + if (!info) + goto out_err; - all->par.dac = of_ioremap(&op->resource[1], 0, - sizeof(struct ffb_dac), "ffb dac"); - if (!all->par.dac) { - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - kfree(all); - return -ENOMEM; - } + par = info->par; + + spin_lock_init(&par->lock); + par->fbc = of_ioremap(&op->resource[2], 0, + sizeof(struct ffb_fbc), "ffb fbc"); + if (!par->fbc) + goto out_release_fb; + + par->dac = of_ioremap(&op->resource[1], 0, + sizeof(struct ffb_dac), "ffb dac"); + if (!par->dac) + goto out_unmap_fbc; - all->par.rop_cache = FFB_ROP_NEW; - all->par.physbase = op->resource[0].start; + par->rop_cache = FFB_ROP_NEW; + par->physbase = op->resource[0].start; /* Don't mention copyarea, so SCROLL_REDRAW is always * used. It is the fastest on this chip. */ - all->info.flags = (FBINFO_DEFAULT | - /* FBINFO_HWACCEL_COPYAREA | */ - FBINFO_HWACCEL_FILLRECT | - FBINFO_HWACCEL_IMAGEBLIT); - all->info.fbops = &ffb_ops; - all->info.screen_base = (char *) all->par.physbase + FFB_DFB24_POFF; - all->info.par = &all->par; - all->info.pseudo_palette = all->pseudo_palette; - - sbusfb_fill_var(&all->info.var, dp->node, 32); - all->par.fbsize = PAGE_ALIGN(all->info.var.xres * - all->info.var.yres * - 4); - ffb_fixup_var_rgb(&all->info.var); - - all->info.var.accel_flags = FB_ACCELF_TEXT; + info->flags = (FBINFO_DEFAULT | + /* FBINFO_HWACCEL_COPYAREA | */ + FBINFO_HWACCEL_FILLRECT | + FBINFO_HWACCEL_IMAGEBLIT); + + info->fbops = &ffb_ops; + + info->screen_base = (char *) par->physbase + FFB_DFB24_POFF; + info->pseudo_palette = par->pseudo_palette; + + sbusfb_fill_var(&info->var, dp->node, 32); + par->fbsize = PAGE_ALIGN(info->var.xres * info->var.yres * 4); + ffb_fixup_var_rgb(&info->var); + + info->var.accel_flags = FB_ACCELF_TEXT; if (!strcmp(dp->name, "SUNW,afb")) - all->par.flags |= FFB_FLAG_AFB; + par->flags |= FFB_FLAG_AFB; - all->par.board_type = of_getintprop_default(dp, "board_type", 0); + par->board_type = of_getintprop_default(dp, "board_type", 0); - fbc = all->par.fbc; + fbc = par->fbc; if ((upa_readl(&fbc->ucsr) & FFB_UCSR_ALL_ERRORS) != 0) upa_writel(FFB_UCSR_ALL_ERRORS, &fbc->ucsr); - dac = all->par.dac; + dac = par->dac; upa_writel(FFB_DAC_DID, &dac->type); dac_pnum = upa_readl(&dac->value); dac_rev = (dac_pnum & FFB_DAC_DID_REV) >> FFB_DAC_DID_REV_SHIFT; @@ -985,76 +979,70 @@ static int ffb_init_one(struct of_device *op) * cursor logic. We identify Pacifica 1 as not Pacifica 2, the * latter having a part number value of 0x236e. */ - if ((all->par.flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { - all->par.flags &= ~FFB_FLAG_INVCURSOR; + if ((par->flags & FFB_FLAG_AFB) || dac_pnum == 0x236e) { + par->flags &= ~FFB_FLAG_INVCURSOR; } else { if (dac_mrev < 3) - all->par.flags |= FFB_FLAG_INVCURSOR; + par->flags |= FFB_FLAG_INVCURSOR; } - ffb_switch_from_graph(&all->par); + ffb_switch_from_graph(par); /* Unblank it just to be sure. When there are multiple * FFB/AFB cards in the system, or it is not the OBP * chosen console, it will have video outputs off in * the DAC. */ - ffb_blank(0, &all->info); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - printk(KERN_ERR "ffb: Could not allocate color map.\n"); - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], - all->par.dac, sizeof(struct ffb_dac)); - kfree(all); - return -ENOMEM; - } + ffb_blank(0, info); - ffb_init_fix(&all->info); - - err = register_framebuffer(&all->info); - if (err < 0) { - printk(KERN_ERR "ffb: Could not register framebuffer.\n"); - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[2], - all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], - all->par.dac, sizeof(struct ffb_dac)); - kfree(all); - return err; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_dac; + + ffb_init_fix(info); - dev_set_drvdata(&op->dev, all); + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + dev_set_drvdata(&op->dev, info); printk("%s: %s at %016lx, type %d, " "DAC pnum[%x] rev[%d] manuf_rev[%d]\n", dp->full_name, - ((all->par.flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), - all->par.physbase, all->par.board_type, + ((par->flags & FFB_FLAG_AFB) ? "AFB" : "FFB"), + par->physbase, par->board_type, dac_pnum, dac_rev, dac_mrev); return 0; -} -static int __devinit ffb_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_dac: + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + +out_unmap_fbc: + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + +out_release_fb: + framebuffer_release(info); - return ffb_init_one(op); +out_err: + return err; } static int __devexit ffb_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct ffb_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[2], all->par.fbc, sizeof(struct ffb_fbc)); - of_iounmap(&op->resource[1], all->par.dac, sizeof(struct ffb_dac)); + of_iounmap(&op->resource[2], par->fbc, sizeof(struct ffb_fbc)); + of_iounmap(&op->resource[1], par->dac, sizeof(struct ffb_dac)); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/geode/Kconfig b/drivers/video/geode/Kconfig index a814b6c2605..7608429b394 100644 --- a/drivers/video/geode/Kconfig +++ b/drivers/video/geode/Kconfig @@ -8,6 +8,21 @@ config FB_GEODE Say 'Y' here to allow you to select framebuffer drivers for the AMD Geode family of processors. +config FB_GEODE_LX + tristate "AMD Geode LX framebuffer support (EXPERIMENTAL)" + depends on FB && FB_GEODE + select FB_CFB_FILLRECT + select FB_CFB_COPYAREA + select FB_CFB_IMAGEBLIT + ---help--- + Framebuffer driver for the display controller integrated into the + AMD Geode LX processors. + + To compile this driver as a module, choose M here: the module will + be called lxfb. + + If unsure, say N. + config FB_GEODE_GX tristate "AMD Geode GX framebuffer support (EXPERIMENTAL)" depends on FB && FB_GEODE && EXPERIMENTAL diff --git a/drivers/video/geode/Makefile b/drivers/video/geode/Makefile index f896565bc31..957304b45fb 100644 --- a/drivers/video/geode/Makefile +++ b/drivers/video/geode/Makefile @@ -2,6 +2,8 @@ obj-$(CONFIG_FB_GEODE_GX1) += gx1fb.o obj-$(CONFIG_FB_GEODE_GX) += gxfb.o +obj-$(CONFIG_FB_GEODE_LX) += lxfb.o gx1fb-objs := gx1fb_core.o display_gx1.o video_cs5530.o gxfb-objs := gxfb_core.o display_gx.o video_gx.o +lxfb-objs := lxfb_core.o lxfb_ops.o diff --git a/drivers/video/geode/lxfb.h b/drivers/video/geode/lxfb.h new file mode 100644 index 00000000000..6c227f9592a --- /dev/null +++ b/drivers/video/geode/lxfb.h @@ -0,0 +1,199 @@ +#ifndef _LXFB_H_ +#define _LXFB_H_ + +#include <linux/fb.h> + +#define OUTPUT_CRT 0x01 +#define OUTPUT_PANEL 0x02 + +struct lxfb_par { + int output; + int panel_width; + int panel_height; + + void __iomem *gp_regs; + void __iomem *dc_regs; + void __iomem *df_regs; +}; + +static inline unsigned int lx_get_pitch(unsigned int xres, int bpp) +{ + return (((xres * (bpp >> 3)) + 7) & ~7); +} + +void lx_set_mode(struct fb_info *); +void lx_get_gamma(struct fb_info *, unsigned int *, int); +void lx_set_gamma(struct fb_info *, unsigned int *, int); +unsigned int lx_framebuffer_size(void); +int lx_blank_display(struct fb_info *, int); +void lx_set_palette_reg(struct fb_info *, unsigned int, unsigned int, + unsigned int, unsigned int); + +/* MSRS */ + +#define MSR_LX_GLD_CONFIG 0x48002001 +#define MSR_LX_GLCP_DOTPLL 0x4c000015 +#define MSR_LX_DF_PADSEL 0x48000011 +#define MSR_LX_DC_SPARE 0x80000011 +#define MSR_LX_DF_GLCONFIG 0x48002001 + +#define MSR_LX_GLIU0_P2D_RO0 0x10000029 + +#define GLCP_DOTPLL_RESET (1 << 0) +#define GLCP_DOTPLL_BYPASS (1 << 15) +#define GLCP_DOTPLL_HALFPIX (1 << 24) +#define GLCP_DOTPLL_LOCK (1 << 25) + +#define DF_CONFIG_OUTPUT_MASK 0x38 +#define DF_OUTPUT_PANEL 0x08 +#define DF_OUTPUT_CRT 0x00 +#define DF_SIMULTANEOUS_CRT_AND_FP (1 << 15) + +#define DF_DEFAULT_TFT_PAD_SEL_LOW 0xDFFFFFFF +#define DF_DEFAULT_TFT_PAD_SEL_HIGH 0x0000003F + +#define DC_SPARE_DISABLE_CFIFO_HGO 0x00000800 +#define DC_SPARE_VFIFO_ARB_SELECT 0x00000400 +#define DC_SPARE_WM_LPEN_OVRD 0x00000200 +#define DC_SPARE_LOAD_WM_LPEN_MASK 0x00000100 +#define DC_SPARE_DISABLE_INIT_VID_PRI 0x00000080 +#define DC_SPARE_DISABLE_VFIFO_WM 0x00000040 +#define DC_SPARE_DISABLE_CWD_CHECK 0x00000020 +#define DC_SPARE_PIX8_PAN_FIX 0x00000010 +#define DC_SPARE_FIRST_REQ_MASK 0x00000002 + +/* Registers */ + +#define DC_UNLOCK 0x00 +#define DC_UNLOCK_CODE 0x4758 + +#define DC_GENERAL_CFG 0x04 +#define DC_GCFG_DFLE (1 << 0) +#define DC_GCFG_VIDE (1 << 3) +#define DC_GCFG_VGAE (1 << 7) +#define DC_GCFG_CMPE (1 << 5) +#define DC_GCFG_DECE (1 << 6) +#define DC_GCFG_FDTY (1 << 17) + +#define DC_DISPLAY_CFG 0x08 +#define DC_DCFG_TGEN (1 << 0) +#define DC_DCFG_GDEN (1 << 3) +#define DC_DCFG_VDEN (1 << 4) +#define DC_DCFG_TRUP (1 << 6) +#define DC_DCFG_DCEN (1 << 24) +#define DC_DCFG_PALB (1 << 25) +#define DC_DCFG_VISL (1 << 27) + +#define DC_DCFG_16BPP 0x0 + +#define DC_DCFG_DISP_MODE_MASK 0x00000300 +#define DC_DCFG_DISP_MODE_8BPP 0x00000000 +#define DC_DCFG_DISP_MODE_16BPP 0x00000100 +#define DC_DCFG_DISP_MODE_24BPP 0x00000200 +#define DC_DCFG_DISP_MODE_32BPP 0x00000300 + + +#define DC_ARB_CFG 0x0C + +#define DC_FB_START 0x10 +#define DC_CB_START 0x14 +#define DC_CURSOR_START 0x18 + +#define DC_DV_TOP 0x2C +#define DC_DV_TOP_ENABLE (1 << 0) + +#define DC_LINE_SIZE 0x30 +#define DC_GRAPHICS_PITCH 0x34 +#define DC_H_ACTIVE_TIMING 0x40 +#define DC_H_BLANK_TIMING 0x44 +#define DC_H_SYNC_TIMING 0x48 +#define DC_V_ACTIVE_TIMING 0x50 +#define DC_V_BLANK_TIMING 0x54 +#define DC_V_SYNC_TIMING 0x58 +#define DC_FB_ACTIVE 0x5C + +#define DC_PAL_ADDRESS 0x70 +#define DC_PAL_DATA 0x74 + +#define DC_PHY_MEM_OFFSET 0x84 + +#define DC_DV_CTL 0x88 +#define DC_DV_LINE_SIZE_MASK 0x00000C00 +#define DC_DV_LINE_SIZE_1024 0x00000000 +#define DC_DV_LINE_SIZE_2048 0x00000400 +#define DC_DV_LINE_SIZE_4096 0x00000800 +#define DC_DV_LINE_SIZE_8192 0x00000C00 + + +#define DC_GFX_SCALE 0x90 +#define DC_IRQ_FILT_CTL 0x94 + + +#define DC_IRQ 0xC8 +#define DC_IRQ_MASK (1 << 0) +#define DC_VSYNC_IRQ_MASK (1 << 1) +#define DC_IRQ_STATUS (1 << 20) +#define DC_VSYNC_IRQ_STATUS (1 << 21) + +#define DC_GENLCK_CTRL 0xD4 +#define DC_GENLCK_ENABLE (1 << 18) +#define DC_GC_ALPHA_FLICK_ENABLE (1 << 25) +#define DC_GC_FLICKER_FILTER_ENABLE (1 << 24) +#define DC_GC_FLICKER_FILTER_MASK (0x0F << 28) + +#define DC_COLOR_KEY 0xB8 +#define DC_CLR_KEY_ENABLE (1 << 24) + + +#define DC3_DV_LINE_SIZE_MASK 0x00000C00 +#define DC3_DV_LINE_SIZE_1024 0x00000000 +#define DC3_DV_LINE_SIZE_2048 0x00000400 +#define DC3_DV_LINE_SIZE_4096 0x00000800 +#define DC3_DV_LINE_SIZE_8192 0x00000C00 + +#define DF_VIDEO_CFG 0x0 +#define DF_VCFG_VID_EN (1 << 0) + +#define DF_DISPLAY_CFG 0x08 + +#define DF_DCFG_CRT_EN (1 << 0) +#define DF_DCFG_HSYNC_EN (1 << 1) +#define DF_DCFG_VSYNC_EN (1 << 2) +#define DF_DCFG_DAC_BL_EN (1 << 3) +#define DF_DCFG_CRT_HSYNC_POL (1 << 8) +#define DF_DCFG_CRT_VSYNC_POL (1 << 9) +#define DF_DCFG_GV_PAL_BYP (1 << 21) + +#define DF_DCFG_CRT_SYNC_SKW_INIT 0x10000 +#define DF_DCFG_CRT_SYNC_SKW_MASK 0x1c000 + +#define DF_DCFG_PWR_SEQ_DLY_INIT 0x80000 +#define DF_DCFG_PWR_SEQ_DLY_MASK 0xe0000 + +#define DF_MISC 0x50 + +#define DF_MISC_GAM_BYPASS (1 << 0) +#define DF_MISC_DAC_PWRDN (1 << 10) +#define DF_MISC_A_PWRDN (1 << 11) + +#define DF_PAR 0x38 +#define DF_PDR 0x40 +#define DF_ALPHA_CONTROL_1 0xD8 +#define DF_VIDEO_REQUEST 0x120 + +#define DF_PANEL_TIM1 0x400 +#define DF_DEFAULT_TFT_PMTIM1 0x0 + +#define DF_PANEL_TIM2 0x408 +#define DF_DEFAULT_TFT_PMTIM2 0x08000000 + +#define DF_FP_PM 0x410 +#define DF_FP_PM_P (1 << 24) + +#define DF_DITHER_CONTROL 0x418 +#define DF_DEFAULT_TFT_DITHCTL 0x00000070 +#define GP_BLT_STATUS 0x44 +#define GP_BS_BLT_BUSY (1 << 0) +#define GP_BS_CB_EMPTY (1 << 4) + +#endif diff --git a/drivers/video/geode/lxfb_core.c b/drivers/video/geode/lxfb_core.c new file mode 100644 index 00000000000..5e30b40c8c0 --- /dev/null +++ b/drivers/video/geode/lxfb_core.c @@ -0,0 +1,621 @@ +/* + * Geode LX framebuffer driver. + * + * Copyright (C) 2007 Advanced Micro Devices, Inc. + * Built from gxfb (which is Copyright (C) 2006 Arcom Control Systems Ltd.) + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/module.h> +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/string.h> +#include <linux/console.h> +#include <linux/mm.h> +#include <linux/slab.h> +#include <linux/delay.h> +#include <linux/fb.h> +#include <linux/init.h> +#include <linux/pci.h> +#include <linux/uaccess.h> + +#include "lxfb.h" + +static char *mode_option; +static int noclear, nopanel, nocrt; +static int fbsize; + +/* Most of these modes are sorted in ascending order, but + * since the first entry in this table is the "default" mode, + * we try to make it something sane - 640x480-60 is sane + */ + +const struct fb_videomode geode_modedb[] __initdata = { + /* 640x480-60 */ + { NULL, 60, 640, 480, 39682, 48, 8, 25, 2, 88, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x400-70 */ + { NULL, 70, 640, 400, 39770, 40, 8, 28, 5, 96, 2, + FB_SYNC_HOR_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-70 */ + { NULL, 70, 640, 480, 35014, 88, 24, 15, 2, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-72 */ + { NULL, 72, 640, 480, 32102, 120, 16, 20, 1, 40, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-75 */ + { NULL, 75, 640, 480, 31746, 120, 16, 16, 1, 64, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-85 */ + { NULL, 85, 640, 480, 27780, 80, 56, 25, 1, 56, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-90 */ + { NULL, 90, 640, 480, 26392, 96, 32, 22, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-100 */ + { NULL, 100, 640, 480, 23167, 104, 40, 25, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 640x480-60 */ + { NULL, 60, 640, 480, 39682, 48, 16, 25, 10, 88, 2, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-56 */ + { NULL, 56, 800, 600, 27901, 128, 24, 22, 1, 72, 2, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-60 */ + { NULL, 60, 800, 600, 25131, 72, 32, 23, 1, 136, 4, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-70 */ + { NULL, 70, 800, 600, 21873, 120, 40, 21, 4, 80, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-72 */ + { NULL, 72, 800, 600, 20052, 64, 56, 23, 37, 120, 6, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-75 */ + { NULL, 75, 800, 600, 20202, 160, 16, 21, 1, 80, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-85 */ + { NULL, 85, 800, 600, 17790, 152, 32, 27, 1, 64, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-90 */ + { NULL, 90, 800, 600, 16648, 128, 40, 28, 1, 88, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-100 */ + { NULL, 100, 800, 600, 14667, 136, 48, 27, 1, 88, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 800x600-60 */ + { NULL, 60, 800, 600, 25131, 88, 40, 23, 1, 128, 4, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-60 */ + { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-70 */ + { NULL, 70, 1024, 768, 13346, 144, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-72 */ + { NULL, 72, 1024, 768, 12702, 168, 56, 29, 4, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-75 */ + { NULL, 75, 1024, 768, 12703, 176, 16, 28, 1, 96, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-85 */ + { NULL, 85, 1024, 768, 10581, 208, 48, 36, 1, 96, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-90 */ + { NULL, 90, 1024, 768, 9981, 176, 64, 37, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-100 */ + { NULL, 100, 1024, 768, 8825, 184, 72, 42, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1024x768-60 */ + { NULL, 60, 1024, 768, 15385, 160, 24, 29, 3, 136, 6, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-60 */ + { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-70 */ + { NULL, 70, 1152, 864, 10254, 192, 72, 32, 8, 120, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-72 */ + { NULL, 72, 1152, 864, 9866, 200, 72, 33, 7, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-75 */ + { NULL, 75, 1152, 864, 9259, 256, 64, 32, 1, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-85 */ + { NULL, 85, 1152, 864, 8357, 200, 72, 37, 3, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-90 */ + { NULL, 90, 1152, 864, 7719, 208, 80, 42, 9, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-100 */ + { NULL, 100, 1152, 864, 6947, 208, 80, 48, 3, 128, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1152x864-60 */ + { NULL, 60, 1152, 864, 12251, 184, 64, 27, 1, 120, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-60 */ + { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-70 */ + { NULL, 70, 1280, 1024, 7719, 224, 88, 38, 6, 136, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-72 */ + { NULL, 72, 1280, 1024, 7490, 224, 88, 39, 7, 136, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-75 */ + { NULL, 75, 1280, 1024, 7409, 248, 16, 38, 1, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-85 */ + { NULL, 85, 1280, 1024, 6351, 224, 64, 44, 1, 160, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-90 */ + { NULL, 90, 1280, 1024, 5791, 240, 96, 51, 12, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-100 */ + { NULL, 100, 1280, 1024, 5212, 240, 96, 57, 6, 144, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1280x1024-60 */ + { NULL, 60, 1280, 1024, 9262, 248, 48, 38, 1, 112, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-60 */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-70 */ + { NULL, 70, 1600, 1200, 5291, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-72 */ + { NULL, 72, 1600, 1200, 5053, 288, 112, 47, 13, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-75 */ + { NULL, 75, 1600, 1200, 4938, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-85 */ + { NULL, 85, 1600, 1200, 4357, 304, 64, 46, 1, 192, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-90 */ + { NULL, 90, 1600, 1200, 3981, 304, 128, 60, 1, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-100 */ + { NULL, 100, 1600, 1200, 3563, 304, 128, 67, 1, 176, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1600x1200-60 */ + { NULL, 60, 1600, 1200, 6172, 304, 64, 46, 1, 192, 3, + FB_SYNC_HOR_HIGH_ACT | FB_SYNC_VERT_HIGH_ACT, + FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-60 */ + { NULL, 60, 1920, 1440, 4273, 344, 128, 56, 1, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-70 */ + { NULL, 70, 1920, 1440, 3593, 360, 152, 55, 8, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-72 */ + { NULL, 72, 1920, 1440, 3472, 360, 152, 68, 4, 208, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-75 */ + { NULL, 75, 1920, 1440, 3367, 352, 144, 56, 1, 224, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, + /* 1920x1440-85 */ + { NULL, 85, 1920, 1440, 2929, 368, 152, 68, 1, 216, 3, + 0, FB_VMODE_NONINTERLACED, 0 }, +}; + +static int lxfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) +{ + if (var->xres > 1920 || var->yres > 1440) + return -EINVAL; + + if (var->bits_per_pixel == 32) { + var->red.offset = 16; var->red.length = 8; + var->green.offset = 8; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else if (var->bits_per_pixel == 16) { + var->red.offset = 11; var->red.length = 5; + var->green.offset = 5; var->green.length = 6; + var->blue.offset = 0; var->blue.length = 5; + } else if (var->bits_per_pixel == 8) { + var->red.offset = 0; var->red.length = 8; + var->green.offset = 0; var->green.length = 8; + var->blue.offset = 0; var->blue.length = 8; + } else + return -EINVAL; + + var->transp.offset = 0; var->transp.length = 0; + + /* Enough video memory? */ + if ((lx_get_pitch(var->xres, var->bits_per_pixel) * var->yres) + > info->fix.smem_len) + return -EINVAL; + + return 0; +} + +static int lxfb_set_par(struct fb_info *info) +{ + if (info->var.bits_per_pixel > 8) { + info->fix.visual = FB_VISUAL_TRUECOLOR; + fb_dealloc_cmap(&info->cmap); + } else { + info->fix.visual = FB_VISUAL_PSEUDOCOLOR; + fb_alloc_cmap(&info->cmap, 1<<info->var.bits_per_pixel, 0); + } + + info->fix.line_length = lx_get_pitch(info->var.xres, + info->var.bits_per_pixel); + + lx_set_mode(info); + return 0; +} + +static inline u_int chan_to_field(u_int chan, struct fb_bitfield *bf) +{ + chan &= 0xffff; + chan >>= 16 - bf->length; + return chan << bf->offset; +} + +static int lxfb_setcolreg(unsigned regno, unsigned red, unsigned green, + unsigned blue, unsigned transp, + struct fb_info *info) +{ + if (info->var.grayscale) { + /* grayscale = 0.30*R + 0.59*G + 0.11*B */ + red = green = blue = (red * 77 + green * 151 + blue * 28) >> 8; + } + + /* Truecolor has hardware independent palette */ + if (info->fix.visual == FB_VISUAL_TRUECOLOR) { + u32 *pal = info->pseudo_palette; + u32 v; + + if (regno >= 16) + return -EINVAL; + + v = chan_to_field(red, &info->var.red); + v |= chan_to_field(green, &info->var.green); + v |= chan_to_field(blue, &info->var.blue); + + pal[regno] = v; + } else { + if (regno >= 256) + return -EINVAL; + + lx_set_palette_reg(info, regno, red, green, blue); + } + + return 0; +} + +static int lxfb_blank(int blank_mode, struct fb_info *info) +{ + return lx_blank_display(info, blank_mode); +} + + +static int __init lxfb_map_video_memory(struct fb_info *info, + struct pci_dev *dev) +{ + struct lxfb_par *par = info->par; + int ret; + + ret = pci_enable_device(dev); + + if (ret) + return ret; + + ret = pci_request_region(dev, 0, "lxfb-framebuffer"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 1, "lxfb-gp"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 2, "lxfb-vg"); + + if (ret) + return ret; + + ret = pci_request_region(dev, 3, "lxfb-vip"); + + if (ret) + return ret; + + info->fix.smem_start = pci_resource_start(dev, 0); + info->fix.smem_len = fbsize ? fbsize : lx_framebuffer_size(); + + info->screen_base = ioremap(info->fix.smem_start, info->fix.smem_len); + + ret = -ENOMEM; + + if (info->screen_base == NULL) + return ret; + + par->gp_regs = ioremap(pci_resource_start(dev, 1), + pci_resource_len(dev, 1)); + + if (par->gp_regs == NULL) + return ret; + + par->dc_regs = ioremap(pci_resource_start(dev, 2), + pci_resource_len(dev, 2)); + + if (par->dc_regs == NULL) + return ret; + + par->df_regs = ioremap(pci_resource_start(dev, 3), + pci_resource_len(dev, 3)); + + if (par->df_regs == NULL) + return ret; + + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); + + writel(info->fix.smem_start & 0xFF000000, + par->dc_regs + DC_PHY_MEM_OFFSET); + + writel(0, par->dc_regs + DC_UNLOCK); + + dev_info(&dev->dev, "%d KB of video memory at 0x%lx\n", + info->fix.smem_len / 1024, info->fix.smem_start); + + return 0; +} + +static struct fb_ops lxfb_ops = { + .owner = THIS_MODULE, + .fb_check_var = lxfb_check_var, + .fb_set_par = lxfb_set_par, + .fb_setcolreg = lxfb_setcolreg, + .fb_blank = lxfb_blank, + /* No HW acceleration for now. */ + .fb_fillrect = cfb_fillrect, + .fb_copyarea = cfb_copyarea, + .fb_imageblit = cfb_imageblit, +}; + +static struct fb_info * __init lxfb_init_fbinfo(struct device *dev) +{ + struct lxfb_par *par; + struct fb_info *info; + + /* Alloc enough space for the pseudo palette. */ + info = framebuffer_alloc(sizeof(struct lxfb_par) + sizeof(u32) * 16, + dev); + if (!info) + return NULL; + + par = info->par; + + strcpy(info->fix.id, "Geode LX"); + + info->fix.type = FB_TYPE_PACKED_PIXELS; + info->fix.type_aux = 0; + info->fix.xpanstep = 0; + info->fix.ypanstep = 0; + info->fix.ywrapstep = 0; + info->fix.accel = FB_ACCEL_NONE; + + info->var.nonstd = 0; + info->var.activate = FB_ACTIVATE_NOW; + info->var.height = -1; + info->var.width = -1; + info->var.accel_flags = 0; + info->var.vmode = FB_VMODE_NONINTERLACED; + + info->fbops = &lxfb_ops; + info->flags = FBINFO_DEFAULT; + info->node = -1; + + info->pseudo_palette = (void *)par + sizeof(struct lxfb_par); + + info->var.grayscale = 0; + + return info; +} + +static int __init lxfb_probe(struct pci_dev *pdev, + const struct pci_device_id *id) +{ + struct lxfb_par *par; + struct fb_info *info; + int ret; + + struct fb_videomode *modedb_ptr; + int modedb_size; + + info = lxfb_init_fbinfo(&pdev->dev); + + if (info == NULL) + return -ENOMEM; + + par = info->par; + + ret = lxfb_map_video_memory(info, pdev); + + if (ret < 0) { + dev_err(&pdev->dev, + "failed to map frame buffer or controller registers\n"); + goto err; + } + + /* Set up the desired outputs */ + + par->output = 0; + par->output |= (nopanel) ? 0 : OUTPUT_PANEL; + par->output |= (nocrt) ? 0 : OUTPUT_CRT; + + /* Set up the mode database */ + + modedb_ptr = (struct fb_videomode *) geode_modedb; + modedb_size = ARRAY_SIZE(geode_modedb); + + ret = fb_find_mode(&info->var, info, mode_option, + modedb_ptr, modedb_size, NULL, 16); + + if (ret == 0 || ret == 4) { + dev_err(&pdev->dev, "could not find valid video mode\n"); + ret = -EINVAL; + goto err; + } + + /* Clear the screen of garbage, unless noclear was specified, + * in which case we assume the user knows what he is doing */ + + if (!noclear) + memset_io(info->screen_base, 0, info->fix.smem_len); + + /* Set the mode */ + + lxfb_check_var(&info->var, info); + lxfb_set_par(info); + + if (register_framebuffer(info) < 0) { + ret = -EINVAL; + goto err; + } + pci_set_drvdata(pdev, info); + printk(KERN_INFO "fb%d: %s frame buffer device\n", + info->node, info->fix.id); + + return 0; + +err: + if (info->screen_base) { + iounmap(info->screen_base); + pci_release_region(pdev, 0); + } + if (par->gp_regs) { + iounmap(par->gp_regs); + pci_release_region(pdev, 1); + } + if (par->dc_regs) { + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + } + if (par->df_regs) { + iounmap(par->df_regs); + pci_release_region(pdev, 3); + } + + if (info) + framebuffer_release(info); + + return ret; +} + +static void lxfb_remove(struct pci_dev *pdev) +{ + struct fb_info *info = pci_get_drvdata(pdev); + struct lxfb_par *par = info->par; + + unregister_framebuffer(info); + + iounmap(info->screen_base); + pci_release_region(pdev, 0); + + iounmap(par->gp_regs); + pci_release_region(pdev, 1); + + iounmap(par->dc_regs); + pci_release_region(pdev, 2); + + iounmap(par->df_regs); + pci_release_region(pdev, 3); + + pci_set_drvdata(pdev, NULL); + framebuffer_release(info); +} + +static struct pci_device_id lxfb_id_table[] = { + { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_LX_VIDEO) }, + { 0, } +}; + +MODULE_DEVICE_TABLE(pci, lxfb_id_table); + +static struct pci_driver lxfb_driver = { + .name = "lxfb", + .id_table = lxfb_id_table, + .probe = lxfb_probe, + .remove = lxfb_remove, +}; + +#ifndef MODULE +static int __init lxfb_setup(char *options) +{ + char *opt; + + if (!options || !*options) + return 0; + + while (1) { + char *opt = strsep(&options, ","); + + if (opt == NULL) + break; + + if (!*opt) + continue; + + if (!strncmp(opt, "fbsize:", 7)) + fbsize = simple_strtoul(opt+7, NULL, 0); + else if (!strcmp(opt, "noclear")) + noclear = 1; + else if (!strcmp(opt, "nopanel")) + nopanel = 1; + else if (!strcmp(opt, "nocrt")) + nocrt = 1; + else + mode_option = opt; + } + + return 0; +} +#endif + +static int __init lxfb_init(void) +{ +#ifndef MODULE + char *option = NULL; + + if (fb_get_options("lxfb", &option)) + return -ENODEV; + + lxfb_setup(option); +#endif + return pci_register_driver(&lxfb_driver); +} +static void __exit lxfb_cleanup(void) +{ + pci_unregister_driver(&lxfb_driver); +} + +module_init(lxfb_init); +module_exit(lxfb_cleanup); + +module_param(mode_option, charp, 0); +MODULE_PARM_DESC(mode_option, "video mode (<x>x<y>[-<bpp>][@<refr>])"); + +module_param(fbsize, int, 0); +MODULE_PARM_DESC(fbsize, "video memory size"); + +MODULE_DESCRIPTION("Framebuffer driver for the AMD Geode LX"); +MODULE_LICENSE("GPL"); diff --git a/drivers/video/geode/lxfb_ops.c b/drivers/video/geode/lxfb_ops.c new file mode 100644 index 00000000000..4fbc99be96e --- /dev/null +++ b/drivers/video/geode/lxfb_ops.c @@ -0,0 +1,536 @@ +/* Geode LX framebuffer driver + * + * Copyright (C) 2006-2007, Advanced Micro Devices,Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. + */ + +#include <linux/kernel.h> +#include <linux/errno.h> +#include <linux/fb.h> +#include <linux/uaccess.h> +#include <linux/delay.h> + +#include "lxfb.h" + +/* TODO + * Support panel scaling + * Add acceleration + * Add support for interlacing (TV out) + * Support compression + */ + +/* This is the complete list of PLL frequencies that we can set - + * we will choose the closest match to the incoming clock. + * freq is the frequency of the dotclock * 1000 (for example, + * 24823 = 24.983 Mhz). + * pllval is the corresponding PLL value +*/ + +static const struct { + unsigned int pllval; + unsigned int freq; +} pll_table[] = { + { 0x000031AC, 24923 }, + { 0x0000215D, 25175 }, + { 0x00001087, 27000 }, + { 0x0000216C, 28322 }, + { 0x0000218D, 28560 }, + { 0x000010C9, 31200 }, + { 0x00003147, 31500 }, + { 0x000010A7, 33032 }, + { 0x00002159, 35112 }, + { 0x00004249, 35500 }, + { 0x00000057, 36000 }, + { 0x0000219A, 37889 }, + { 0x00002158, 39168 }, + { 0x00000045, 40000 }, + { 0x00000089, 43163 }, + { 0x000010E7, 44900 }, + { 0x00002136, 45720 }, + { 0x00003207, 49500 }, + { 0x00002187, 50000 }, + { 0x00004286, 56250 }, + { 0x000010E5, 60065 }, + { 0x00004214, 65000 }, + { 0x00001105, 68179 }, + { 0x000031E4, 74250 }, + { 0x00003183, 75000 }, + { 0x00004284, 78750 }, + { 0x00001104, 81600 }, + { 0x00006363, 94500 }, + { 0x00005303, 97520 }, + { 0x00002183, 100187 }, + { 0x00002122, 101420 }, + { 0x00001081, 108000 }, + { 0x00006201, 113310 }, + { 0x00000041, 119650 }, + { 0x000041A1, 129600 }, + { 0x00002182, 133500 }, + { 0x000041B1, 135000 }, + { 0x00000051, 144000 }, + { 0x000041E1, 148500 }, + { 0x000062D1, 157500 }, + { 0x000031A1, 162000 }, + { 0x00000061, 169203 }, + { 0x00004231, 172800 }, + { 0x00002151, 175500 }, + { 0x000052E1, 189000 }, + { 0x00000071, 192000 }, + { 0x00003201, 198000 }, + { 0x00004291, 202500 }, + { 0x00001101, 204750 }, + { 0x00007481, 218250 }, + { 0x00004170, 229500 }, + { 0x00006210, 234000 }, + { 0x00003140, 251182 }, + { 0x00006250, 261000 }, + { 0x000041C0, 278400 }, + { 0x00005220, 280640 }, + { 0x00000050, 288000 }, + { 0x000041E0, 297000 }, + { 0x00002130, 320207 } +}; + + +static void lx_set_dotpll(u32 pllval) +{ + u32 dotpll_lo, dotpll_hi; + int i; + + rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + + if ((dotpll_lo & GLCP_DOTPLL_LOCK) && (dotpll_hi == pllval)) + return; + + dotpll_hi = pllval; + dotpll_lo &= ~(GLCP_DOTPLL_BYPASS | GLCP_DOTPLL_HALFPIX); + dotpll_lo |= GLCP_DOTPLL_RESET; + + wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + + /* Wait 100us for the PLL to lock */ + + udelay(100); + + /* Now, loop for the lock bit */ + + for (i = 0; i < 1000; i++) { + rdmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); + if (dotpll_lo & GLCP_DOTPLL_LOCK) + break; + } + + /* Clear the reset bit */ + + dotpll_lo &= ~GLCP_DOTPLL_RESET; + wrmsr(MSR_LX_GLCP_DOTPLL, dotpll_lo, dotpll_hi); +} + +/* Set the clock based on the frequency specified by the current mode */ + +static void lx_set_clock(struct fb_info *info) +{ + unsigned int diff, min, best = 0; + unsigned int freq, i; + + freq = (unsigned int) (0x3b9aca00 / info->var.pixclock); + + min = abs(pll_table[0].freq - freq); + + for (i = 0; i < ARRAY_SIZE(pll_table); i++) { + diff = abs(pll_table[i].freq - freq); + if (diff < min) { + min = diff; + best = i; + } + } + + lx_set_dotpll(pll_table[best].pllval & 0x7FFF); +} + +static void lx_graphics_disable(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + unsigned int val, gcfg; + + /* Note: This assumes that the video is in a quitet state */ + + writel(0, par->df_regs + DF_ALPHA_CONTROL_1); + writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 32); + writel(0, par->df_regs + DF_ALPHA_CONTROL_1 + 64); + + /* Turn off the VGA and video enable */ + val = readl (par->dc_regs + DC_GENERAL_CFG) & + ~(DC_GCFG_VGAE | DC_GCFG_VIDE); + + writel(val, par->dc_regs + DC_GENERAL_CFG); + + val = readl(par->df_regs + DF_VIDEO_CFG) & ~DF_VCFG_VID_EN; + writel(val, par->df_regs + DF_VIDEO_CFG); + + writel( DC_IRQ_MASK | DC_VSYNC_IRQ_MASK | + DC_IRQ_STATUS | DC_VSYNC_IRQ_STATUS, + par->dc_regs + DC_IRQ); + + val = readl(par->dc_regs + DC_GENLCK_CTRL) & ~DC_GENLCK_ENABLE; + writel(val, par->dc_regs + DC_GENLCK_CTRL); + + val = readl(par->dc_regs + DC_COLOR_KEY) & ~DC_CLR_KEY_ENABLE; + writel(val & ~DC_CLR_KEY_ENABLE, par->dc_regs + DC_COLOR_KEY); + + /* We don't actually blank the panel, due to the long latency + involved with bringing it back */ + + val = readl(par->df_regs + DF_MISC) | DF_MISC_DAC_PWRDN; + writel(val, par->df_regs + DF_MISC); + + /* Turn off the display */ + + val = readl(par->df_regs + DF_DISPLAY_CFG); + writel(val & ~(DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN | + DF_DCFG_DAC_BL_EN), par->df_regs + DF_DISPLAY_CFG); + + gcfg = readl(par->dc_regs + DC_GENERAL_CFG); + gcfg &= ~(DC_GCFG_CMPE | DC_GCFG_DECE); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Turn off the TGEN */ + val = readl(par->dc_regs + DC_DISPLAY_CFG); + val &= ~DC_DCFG_TGEN; + writel(val, par->dc_regs + DC_DISPLAY_CFG); + + /* Wait 1000 usecs to ensure that the TGEN is clear */ + udelay(1000); + + /* Turn off the FIFO loader */ + + gcfg &= ~DC_GCFG_DFLE; + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Lastly, wait for the GP to go idle */ + + do { + val = readl(par->gp_regs + GP_BLT_STATUS); + } while ((val & GP_BS_BLT_BUSY) || !(val & GP_BS_CB_EMPTY)); +} + +static void lx_graphics_enable(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + u32 temp, config; + + /* Set the video request register */ + writel(0, par->df_regs + DF_VIDEO_REQUEST); + + /* Set up the polarities */ + + config = readl(par->df_regs + DF_DISPLAY_CFG); + + config &= ~(DF_DCFG_CRT_SYNC_SKW_MASK | DF_DCFG_PWR_SEQ_DLY_MASK | + DF_DCFG_CRT_HSYNC_POL | DF_DCFG_CRT_VSYNC_POL); + + config |= (DF_DCFG_CRT_SYNC_SKW_INIT | DF_DCFG_PWR_SEQ_DLY_INIT | + DF_DCFG_GV_PAL_BYP); + + if (info->var.sync & FB_SYNC_HOR_HIGH_ACT) + config |= DF_DCFG_CRT_HSYNC_POL; + + if (info->var.sync & FB_SYNC_VERT_HIGH_ACT) + config |= DF_DCFG_CRT_VSYNC_POL; + + if (par->output & OUTPUT_PANEL) { + u32 msrlo, msrhi; + + writel(DF_DEFAULT_TFT_PMTIM1, + par->df_regs + DF_PANEL_TIM1); + writel(DF_DEFAULT_TFT_PMTIM2, + par->df_regs + DF_PANEL_TIM2); + writel(DF_DEFAULT_TFT_DITHCTL, + par->df_regs + DF_DITHER_CONTROL); + + msrlo = DF_DEFAULT_TFT_PAD_SEL_LOW; + msrhi = DF_DEFAULT_TFT_PAD_SEL_HIGH; + + wrmsr(MSR_LX_DF_PADSEL, msrlo, msrhi); + } + + if (par->output & OUTPUT_CRT) { + config |= DF_DCFG_CRT_EN | DF_DCFG_HSYNC_EN | + DF_DCFG_VSYNC_EN | DF_DCFG_DAC_BL_EN; + } + + writel(config, par->df_regs + DF_DISPLAY_CFG); + + /* Turn the CRT dacs back on */ + + if (par->output & OUTPUT_CRT) { + temp = readl(par->df_regs + DF_MISC); + temp &= ~(DF_MISC_DAC_PWRDN | DF_MISC_A_PWRDN); + writel(temp, par->df_regs + DF_MISC); + } + + /* Turn the panel on (if it isn't already) */ + + if (par->output & OUTPUT_PANEL) { + temp = readl(par->df_regs + DF_FP_PM); + + if (!(temp & 0x09)) + writel(temp | DF_FP_PM_P, par->df_regs + DF_FP_PM); + } + + temp = readl(par->df_regs + DF_MISC); + temp = readl(par->df_regs + DF_DISPLAY_CFG); +} + +unsigned int lx_framebuffer_size(void) +{ + unsigned int val; + + /* The frame buffer size is reported by a VSM in VSA II */ + /* Virtual Register Class = 0x02 */ + /* VG_MEM_SIZE (1MB units) = 0x00 */ + + outw(0xFC53, 0xAC1C); + outw(0x0200, 0xAC1C); + + val = (unsigned int)(inw(0xAC1E)) & 0xFE; + return (val << 20); +} + +void lx_set_mode(struct fb_info *info) +{ + struct lxfb_par *par = info->par; + u64 msrval; + + unsigned int max, dv, val, size; + + unsigned int gcfg, dcfg; + int hactive, hblankstart, hsyncstart, hsyncend, hblankend, htotal; + int vactive, vblankstart, vsyncstart, vsyncend, vblankend, vtotal; + + /* Unlock the DC registers */ + writel(DC_UNLOCK_CODE, par->dc_regs + DC_UNLOCK); + + lx_graphics_disable(info); + + lx_set_clock(info); + + /* Set output mode */ + + rdmsrl(MSR_LX_DF_GLCONFIG, msrval); + msrval &= ~DF_CONFIG_OUTPUT_MASK; + + if (par->output & OUTPUT_PANEL) { + msrval |= DF_OUTPUT_PANEL; + + if (par->output & OUTPUT_CRT) + msrval |= DF_SIMULTANEOUS_CRT_AND_FP; + else + msrval &= ~DF_SIMULTANEOUS_CRT_AND_FP; + } else { + msrval |= DF_OUTPUT_CRT; + } + + wrmsrl(MSR_LX_DF_GLCONFIG, msrval); + + /* Clear the various buffers */ + /* FIXME: Adjust for panning here */ + + writel(0, par->dc_regs + DC_FB_START); + writel(0, par->dc_regs + DC_CB_START); + writel(0, par->dc_regs + DC_CURSOR_START); + + /* FIXME: Add support for interlacing */ + /* FIXME: Add support for scaling */ + + val = readl(par->dc_regs + DC_GENLCK_CTRL); + val &= ~(DC_GC_ALPHA_FLICK_ENABLE | + DC_GC_FLICKER_FILTER_ENABLE | DC_GC_FLICKER_FILTER_MASK); + + /* Default scaling params */ + + writel((0x4000 << 16) | 0x4000, par->dc_regs + DC_GFX_SCALE); + writel(0, par->dc_regs + DC_IRQ_FILT_CTL); + writel(val, par->dc_regs + DC_GENLCK_CTRL); + + /* FIXME: Support compression */ + + if (info->fix.line_length > 4096) + dv = DC_DV_LINE_SIZE_8192; + else if (info->fix.line_length > 2048) + dv = DC_DV_LINE_SIZE_4096; + else if (info->fix.line_length > 1024) + dv = DC_DV_LINE_SIZE_2048; + else + dv = DC_DV_LINE_SIZE_1024; + + max = info->fix.line_length * info->var.yres; + max = (max + 0x3FF) & 0xFFFFFC00; + + writel(max | DC_DV_TOP_ENABLE, par->dc_regs + DC_DV_TOP); + + val = readl(par->dc_regs + DC_DV_CTL) & ~DC_DV_LINE_SIZE_MASK; + writel(val | dv, par->dc_regs + DC_DV_CTL); + + size = info->var.xres * (info->var.bits_per_pixel >> 3); + + writel(info->fix.line_length >> 3, par->dc_regs + DC_GRAPHICS_PITCH); + writel((size + 7) >> 3, par->dc_regs + DC_LINE_SIZE); + + /* Set default watermark values */ + + rdmsrl(MSR_LX_DC_SPARE, msrval); + + msrval &= ~(DC_SPARE_DISABLE_CFIFO_HGO | DC_SPARE_VFIFO_ARB_SELECT | + DC_SPARE_LOAD_WM_LPEN_MASK | DC_SPARE_WM_LPEN_OVRD | + DC_SPARE_DISABLE_INIT_VID_PRI | DC_SPARE_DISABLE_VFIFO_WM); + msrval |= DC_SPARE_DISABLE_VFIFO_WM | DC_SPARE_DISABLE_INIT_VID_PRI; + wrmsrl(MSR_LX_DC_SPARE, msrval); + + gcfg = DC_GCFG_DFLE; /* Display fifo enable */ + gcfg |= 0xB600; /* Set default priority */ + gcfg |= DC_GCFG_FDTY; /* Set the frame dirty mode */ + + dcfg = DC_DCFG_VDEN; /* Enable video data */ + dcfg |= DC_DCFG_GDEN; /* Enable graphics */ + dcfg |= DC_DCFG_TGEN; /* Turn on the timing generator */ + dcfg |= DC_DCFG_TRUP; /* Update timings immediately */ + dcfg |= DC_DCFG_PALB; /* Palette bypass in > 8 bpp modes */ + dcfg |= DC_DCFG_VISL; + dcfg |= DC_DCFG_DCEN; /* Always center the display */ + + /* Set the current BPP mode */ + + switch (info->var.bits_per_pixel) { + case 8: + dcfg |= DC_DCFG_DISP_MODE_8BPP; + break; + + case 16: + dcfg |= DC_DCFG_DISP_MODE_16BPP | DC_DCFG_16BPP; + break; + + case 32: + case 24: + dcfg |= DC_DCFG_DISP_MODE_24BPP; + break; + } + + /* Now - set up the timings */ + + hactive = info->var.xres; + hblankstart = hactive; + hsyncstart = hblankstart + info->var.right_margin; + hsyncend = hsyncstart + info->var.hsync_len; + hblankend = hsyncend + info->var.left_margin; + htotal = hblankend; + + vactive = info->var.yres; + vblankstart = vactive; + vsyncstart = vblankstart + info->var.lower_margin; + vsyncend = vsyncstart + info->var.vsync_len; + vblankend = vsyncend + info->var.upper_margin; + vtotal = vblankend; + + writel((hactive - 1) | ((htotal - 1) << 16), + par->dc_regs + DC_H_ACTIVE_TIMING); + writel((hblankstart - 1) | ((hblankend - 1) << 16), + par->dc_regs + DC_H_BLANK_TIMING); + writel((hsyncstart - 1) | ((hsyncend - 1) << 16), + par->dc_regs + DC_H_SYNC_TIMING); + + writel((vactive - 1) | ((vtotal - 1) << 16), + par->dc_regs + DC_V_ACTIVE_TIMING); + + writel((vblankstart - 1) | ((vblankend - 1) << 16), + par->dc_regs + DC_V_BLANK_TIMING); + + writel((vsyncstart - 1) | ((vsyncend - 1) << 16), + par->dc_regs + DC_V_SYNC_TIMING); + + writel( (info->var.xres - 1) << 16 | (info->var.yres - 1), + par->dc_regs + DC_FB_ACTIVE); + + /* And re-enable the graphics output */ + lx_graphics_enable(info); + + /* Write the two main configuration registers */ + writel(dcfg, par->dc_regs + DC_DISPLAY_CFG); + writel(0, par->dc_regs + DC_ARB_CFG); + writel(gcfg, par->dc_regs + DC_GENERAL_CFG); + + /* Lock the DC registers */ + writel(0, par->dc_regs + DC_UNLOCK); +} + +void lx_set_palette_reg(struct fb_info *info, unsigned regno, + unsigned red, unsigned green, unsigned blue) +{ + struct lxfb_par *par = info->par; + int val; + + /* Hardware palette is in RGB 8-8-8 format. */ + + val = (red << 8) & 0xff0000; + val |= (green) & 0x00ff00; + val |= (blue >> 8) & 0x0000ff; + + writel(regno, par->dc_regs + DC_PAL_ADDRESS); + writel(val, par->dc_regs + DC_PAL_DATA); +} + +int lx_blank_display(struct fb_info *info, int blank_mode) +{ + struct lxfb_par *par = info->par; + u32 dcfg, fp_pm; + int blank, hsync, vsync; + + /* CRT power saving modes. */ + switch (blank_mode) { + case FB_BLANK_UNBLANK: + blank = 0; hsync = 1; vsync = 1; + break; + case FB_BLANK_NORMAL: + blank = 1; hsync = 1; vsync = 1; + break; + case FB_BLANK_VSYNC_SUSPEND: + blank = 1; hsync = 1; vsync = 0; + break; + case FB_BLANK_HSYNC_SUSPEND: + blank = 1; hsync = 0; vsync = 1; + break; + case FB_BLANK_POWERDOWN: + blank = 1; hsync = 0; vsync = 0; + break; + default: + return -EINVAL; + } + + dcfg = readl(par->df_regs + DF_DISPLAY_CFG); + dcfg &= ~(DF_DCFG_DAC_BL_EN + | DF_DCFG_HSYNC_EN | DF_DCFG_VSYNC_EN); + if (!blank) + dcfg |= DF_DCFG_DAC_BL_EN; + if (hsync) + dcfg |= DF_DCFG_HSYNC_EN; + if (vsync) + dcfg |= DF_DCFG_VSYNC_EN; + writel(dcfg, par->df_regs + DF_DISPLAY_CFG); + + /* Power on/off flat panel */ + + if (par->output & OUTPUT_PANEL) { + fp_pm = readl(par->df_regs + DF_FP_PM); + if (blank_mode == FB_BLANK_POWERDOWN) + fp_pm &= ~DF_FP_PM_P; + else + fp_pm |= DF_FP_PM_P; + writel(fp_pm, par->df_regs + DF_FP_PM); + } + + return 0; +} diff --git a/drivers/video/leo.c b/drivers/video/leo.c index a038aa5a9e1..45b9a5d55de 100644 --- a/drivers/video/leo.c +++ b/drivers/video/leo.c @@ -525,130 +525,123 @@ static void leo_fixup_var_rgb(struct fb_var_screeninfo *var) var->transp.length = 0; } -struct all_info { - struct fb_info info; - struct leo_par par; -}; - -static void leo_unmap_regs(struct of_device *op, struct all_info *all) +static void leo_unmap_regs(struct of_device *op, struct fb_info *info, + struct leo_par *par) { - if (all->par.lc_ss0_usr) - of_iounmap(&op->resource[0], all->par.lc_ss0_usr, 0x1000); - if (all->par.ld_ss0) - of_iounmap(&op->resource[0], all->par.ld_ss0, 0x1000); - if (all->par.ld_ss1) - of_iounmap(&op->resource[0], all->par.ld_ss1, 0x1000); - if (all->par.lx_krn) - of_iounmap(&op->resource[0], all->par.lx_krn, 0x1000); - if (all->par.cursor) + if (par->lc_ss0_usr) + of_iounmap(&op->resource[0], par->lc_ss0_usr, 0x1000); + if (par->ld_ss0) + of_iounmap(&op->resource[0], par->ld_ss0, 0x1000); + if (par->ld_ss1) + of_iounmap(&op->resource[0], par->ld_ss1, 0x1000); + if (par->lx_krn) + of_iounmap(&op->resource[0], par->lx_krn, 0x1000); + if (par->cursor) of_iounmap(&op->resource[0], - all->par.cursor, sizeof(struct leo_cursor)); - if (all->info.screen_base) - of_iounmap(&op->resource[0], all->info.screen_base, 0x800000); + par->cursor, sizeof(struct leo_cursor)); + if (info->screen_base) + of_iounmap(&op->resource[0], info->screen_base, 0x800000); } -static int __devinit leo_init_one(struct of_device *op) +static int __devinit leo_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct leo_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct leo_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); - all->par.physbase = op->resource[0].start; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = op->resource[0].start; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; - sbusfb_fill_var(&all->info.var, dp->node, 32); - leo_fixup_var_rgb(&all->info.var); + sbusfb_fill_var(&info->var, dp->node, 32); + leo_fixup_var_rgb(&info->var); linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.lc_ss0_usr = + par->lc_ss0_usr = of_ioremap(&op->resource[0], LEO_OFF_LC_SS0_USR, 0x1000, "leolc ss0usr"); - all->par.ld_ss0 = + par->ld_ss0 = of_ioremap(&op->resource[0], LEO_OFF_LD_SS0, 0x1000, "leold ss0"); - all->par.ld_ss1 = + par->ld_ss1 = of_ioremap(&op->resource[0], LEO_OFF_LD_SS1, 0x1000, "leold ss1"); - all->par.lx_krn = + par->lx_krn = of_ioremap(&op->resource[0], LEO_OFF_LX_KRN, 0x1000, "leolx krn"); - all->par.cursor = + par->cursor = of_ioremap(&op->resource[0], LEO_OFF_LX_CURSOR, sizeof(struct leo_cursor), "leolx cursor"); - all->info.screen_base = + info->screen_base = of_ioremap(&op->resource[0], LEO_OFF_SS0, 0x800000, "leo ram"); - if (!all->par.lc_ss0_usr || - !all->par.ld_ss0 || - !all->par.ld_ss1 || - !all->par.lx_krn || - !all->par.cursor || - !all->info.screen_base) { - leo_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (!par->lc_ss0_usr || + !par->ld_ss0 || + !par->ld_ss1 || + !par->lx_krn || + !par->cursor || + !info->screen_base) + goto out_unmap_regs; - all->info.flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; - all->info.fbops = &leo_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_YPAN; + info->fbops = &leo_ops; - leo_init_wids(&all->info); - leo_init_hw(&all->info); + leo_init_wids(info); + leo_init_hw(info); - leo_blank(0, &all->info); + leo_blank(0, info); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - leo_unmap_regs(op, all); - kfree(all); - return -ENOMEM;; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; - leo_init_fix(&all->info, dp); + leo_init_fix(info, dp); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - leo_unmap_regs(op, all); - kfree(all); - return err; - } + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: leo at %lx:%lx\n", dp->full_name, - all->par.which_io, all->par.physbase); + par->which_io, par->physbase); return 0; -} -static int __devinit leo_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + leo_unmap_regs(op, info, par); + framebuffer_release(info); - return leo_init_one(op); +out_err: + return err; } static int __devexit leo_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct leo_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - leo_unmap_regs(op, all); + leo_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/p9100.c b/drivers/video/p9100.c index 637b78bb4bf..58496061142 100644 --- a/drivers/video/p9100.c +++ b/drivers/video/p9100.c @@ -255,107 +255,95 @@ static void p9100_init_fix(struct fb_info *info, int linebytes, struct device_no info->fix.accel = FB_ACCEL_SUN_CGTHREE; } -struct all_info { - struct fb_info info; - struct p9100_par par; -}; - -static int __devinit p9100_init_one(struct of_device *op) +static int __devinit p9100_probe(struct of_device *op, const struct of_device_id *match) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct p9100_par *par; int linebytes, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct p9100_par), &op->dev); + + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - spin_lock_init(&all->par.lock); + spin_lock_init(&par->lock); /* This is the framebuffer and the only resource apps can mmap. */ - all->par.physbase = op->resource[2].start; - all->par.which_io = op->resource[2].flags & IORESOURCE_BITS; - - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; - - linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); - - all->par.regs = of_ioremap(&op->resource[0], 0, - sizeof(struct p9100_regs), "p9100 regs"); - if (!all->par.regs) { - kfree(all); - return -ENOMEM; - } + par->physbase = op->resource[2].start; + par->which_io = op->resource[2].flags & IORESOURCE_BITS; - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &p9100_ops; - all->info.screen_base = of_ioremap(&op->resource[2], 0, - all->par.fbsize, "p9100 ram"); - if (!all->info.screen_base) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - kfree(all); - return -ENOMEM; - } - all->info.par = &all->par; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; - p9100_blank(0, &all->info); + linebytes = of_getintprop_default(dp, "linebytes", info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], - all->info.screen_base, all->par.fbsize); - kfree(all); - return -ENOMEM; - } + par->regs = of_ioremap(&op->resource[0], 0, + sizeof(struct p9100_regs), "p9100 regs"); + if (!par->regs) + goto out_release_fb; - p9100_init_fix(&all->info, linebytes, dp); - - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - of_iounmap(&op->resource[0], - all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], - all->info.screen_base, all->par.fbsize); - kfree(all); - return err; - } - fb_set_cmap(&all->info.cmap, &all->info); + info->flags = FBINFO_DEFAULT; + info->fbops = &p9100_ops; + info->screen_base = of_ioremap(&op->resource[2], 0, + par->fbsize, "p9100 ram"); + if (!info->screen_base) + goto out_unmap_regs; + + p9100_blank(0, info); + + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_screen; - dev_set_drvdata(&op->dev, all); + p9100_init_fix(info, linebytes, dp); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; + + fb_set_cmap(&info->cmap, info); + + dev_set_drvdata(&op->dev, info); printk("%s: p9100 at %lx:%lx\n", dp->full_name, - all->par.which_io, all->par.physbase); + par->which_io, par->physbase); return 0; -} -static int __devinit p9100_probe(struct of_device *dev, const struct of_device_id *match) -{ - struct of_device *op = to_of_device(&dev->dev); +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_screen: + of_iounmap(&op->resource[2], info->screen_base, par->fbsize); + +out_unmap_regs: + of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs)); + +out_release_fb: + framebuffer_release(info); - return p9100_init_one(op); +out_err: + return err; } static int __devexit p9100_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct p9100_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - of_iounmap(&op->resource[0], all->par.regs, sizeof(struct p9100_regs)); - of_iounmap(&op->resource[2], all->info.screen_base, all->par.fbsize); + of_iounmap(&op->resource[0], par->regs, sizeof(struct p9100_regs)); + of_iounmap(&op->resource[2], info->screen_base, par->fbsize); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/s3c2410fb.c b/drivers/video/s3c2410fb.c index ed3426062a8..8a4c6470d79 100644 --- a/drivers/video/s3c2410fb.c +++ b/drivers/video/s3c2410fb.c @@ -474,6 +474,7 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, { unsigned long flags; unsigned long irqen; + void __iomem *regs = fbi->io; local_irq_save(flags); @@ -483,9 +484,9 @@ static void schedule_palette_update(struct s3c2410fb_info *fbi, fbi->palette_ready = 1; /* enable IRQ */ - irqen = readl(S3C2410_LCDINTMSK); + irqen = readl(regs + S3C2410_LCDINTMSK); irqen &= ~S3C2410_LCDINT_FRSYNC; - writel(irqen, S3C2410_LCDINTMSK); + writel(irqen, regs + S3C2410_LCDINTMSK); } local_irq_restore(flags); @@ -680,6 +681,7 @@ static inline void modify_gpio(void __iomem *reg, static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) { unsigned long flags; + void __iomem *regs = fbi->io; /* Initialise LCD with values from haret */ @@ -694,25 +696,25 @@ static int s3c2410fb_init_registers(struct s3c2410fb_info *fbi) local_irq_restore(flags); - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); - writel(fbi->regs.lcdcon2, S3C2410_LCDCON2); - writel(fbi->regs.lcdcon3, S3C2410_LCDCON3); - writel(fbi->regs.lcdcon4, S3C2410_LCDCON4); - writel(fbi->regs.lcdcon5, S3C2410_LCDCON5); + writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); + writel(fbi->regs.lcdcon2, regs + S3C2410_LCDCON2); + writel(fbi->regs.lcdcon3, regs + S3C2410_LCDCON3); + writel(fbi->regs.lcdcon4, regs + S3C2410_LCDCON4); + writel(fbi->regs.lcdcon5, regs + S3C2410_LCDCON5); s3c2410fb_set_lcdaddr(fbi); dprintk("LPCSEL = 0x%08lx\n", mach_info->lpcsel); - writel(mach_info->lpcsel, S3C2410_LPCSEL); + writel(mach_info->lpcsel, regs + S3C2410_LPCSEL); - dprintk("replacing TPAL %08x\n", readl(S3C2410_TPAL)); + dprintk("replacing TPAL %08x\n", readl(regs + S3C2410_TPAL)); /* ensure temporary palette disabled */ - writel(0x00, S3C2410_TPAL); + writel(0x00, regs + S3C2410_TPAL); /* Enable video by setting the ENVID bit to 1 */ fbi->regs.lcdcon1 |= S3C2410_LCDCON1_ENVID; - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); + writel(fbi->regs.lcdcon1, regs + S3C2410_LCDCON1); return 0; } @@ -720,6 +722,7 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) { unsigned int i; unsigned long ent; + void __iomem *regs = fbi->io; fbi->palette_ready = 0; @@ -727,14 +730,14 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) if ((ent = fbi->palette_buffer[i]) == PALETTE_BUFF_CLEAR) continue; - writel(ent, S3C2410_TFTPAL(i)); + writel(ent, regs + S3C2410_TFTPAL(i)); /* it seems the only way to know exactly * if the palette wrote ok, is to check * to see if the value verifies ok */ - if (readw(S3C2410_TFTPAL(i)) == ent) + if (readw(regs + S3C2410_TFTPAL(i)) == ent) fbi->palette_buffer[i] = PALETTE_BUFF_CLEAR; else fbi->palette_ready = 1; /* retry */ @@ -744,14 +747,15 @@ static void s3c2410fb_write_palette(struct s3c2410fb_info *fbi) static irqreturn_t s3c2410fb_irq(int irq, void *dev_id) { struct s3c2410fb_info *fbi = dev_id; - unsigned long lcdirq = readl(S3C2410_LCDINTPND); + void __iomem *regs = fbi->io; + unsigned long lcdirq = readl(regs + S3C2410_LCDINTPND); if (lcdirq & S3C2410_LCDINT_FRSYNC) { if (fbi->palette_ready) s3c2410fb_write_palette(fbi); - writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDINTPND); - writel(S3C2410_LCDINT_FRSYNC, S3C2410_LCDSRCPND); + writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDINTPND); + writel(S3C2410_LCDINT_FRSYNC, regs + S3C2410_LCDSRCPND); } return IRQ_HANDLED; @@ -764,9 +768,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) struct s3c2410fb_info *info; struct fb_info *fbinfo; struct s3c2410fb_hw *mregs; + struct resource *res; int ret; int irq; int i; + int size; u32 lcdcon1; mach_info = pdev->dev.platform_data; @@ -788,11 +794,32 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) return -ENOMEM; } - info = fbinfo->par; info->fb = fbinfo; info->dev = &pdev->dev; + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + if (res == NULL) { + dev_err(&pdev->dev, "failed to get memory registersn"); + ret = -ENXIO; + goto dealloc_fb; + } + + size = (res->end - res->start)+1; + info->mem = request_mem_region(res->start, size, pdev->name); + if (info->mem == NULL) { + dev_err(&pdev->dev, "failed to get memory region\n"); + ret = -ENOENT; + goto dealloc_fb; + } + + info->io = ioremap(res->start, size); + if (info->io == NULL) { + dev_err(&pdev->dev, "ioremap() of registers failed\n"); + ret = -ENXIO; + goto release_mem; + } + platform_set_drvdata(pdev, fbinfo); dprintk("devinit\n"); @@ -803,8 +830,8 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) /* Stop the video and unset ENVID if set */ info->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; - lcdcon1 = readl(S3C2410_LCDCON1); - writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, S3C2410_LCDCON1); + lcdcon1 = readl(info->io + S3C2410_LCDCON1); + writel(lcdcon1 & ~S3C2410_LCDCON1_ENVID, info->io + S3C2410_LCDCON1); info->mach_info = pdev->dev.platform_data; @@ -855,19 +882,11 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) for (i = 0; i < 256; i++) info->palette_buffer[i] = PALETTE_BUFF_CLEAR; - if (!request_mem_region((unsigned long)S3C24XX_VA_LCD, SZ_1M, "s3c2410-lcd")) { - ret = -EBUSY; - goto dealloc_fb; - } - - - dprintk("got LCD region\n"); - ret = request_irq(irq, s3c2410fb_irq, IRQF_DISABLED, pdev->name, info); if (ret) { dev_err(&pdev->dev, "cannot get irq %d - err %d\n", irq, ret); ret = -EBUSY; - goto release_mem; + goto release_regs; } info->clk = clk_get(NULL, "lcd"); @@ -889,6 +908,7 @@ static int __init s3c2410fb_probe(struct platform_device *pdev) ret = -ENOMEM; goto release_clock; } + dprintk("got video memory\n"); ret = s3c2410fb_init_registers(info); @@ -916,8 +936,11 @@ release_clock: clk_put(info->clk); release_irq: free_irq(irq,info); +release_regs: + iounmap(info->io); release_mem: - release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); + release_resource(info->mem); + kfree(info->mem); dealloc_fb: framebuffer_release(fbinfo); return ret; @@ -935,7 +958,7 @@ static void s3c2410fb_stop_lcd(struct s3c2410fb_info *fbi) local_irq_save(flags); fbi->regs.lcdcon1 &= ~S3C2410_LCDCON1_ENVID; - writel(fbi->regs.lcdcon1, S3C2410_LCDCON1); + writel(fbi->regs.lcdcon1, fbi->io + S3C2410_LCDCON1); local_irq_restore(flags); } @@ -962,7 +985,10 @@ static int s3c2410fb_remove(struct platform_device *pdev) irq = platform_get_irq(pdev, 0); free_irq(irq,info); - release_mem_region((unsigned long)S3C24XX_VA_LCD, S3C24XX_SZ_LCD); + + release_resource(info->mem); + kfree(info->mem); + iounmap(info->io); unregister_framebuffer(fbinfo); return 0; diff --git a/drivers/video/s3c2410fb.h b/drivers/video/s3c2410fb.h index f3f8a8e1501..17c7915b7ac 100644 --- a/drivers/video/s3c2410fb.h +++ b/drivers/video/s3c2410fb.h @@ -30,6 +30,9 @@ struct s3c2410fb_info { struct device *dev; struct clk *clk; + struct resource *mem; + void __iomem *io; + struct s3c2410fb_mach_info *mach_info; /* raw memory addresses */ diff --git a/drivers/video/sbuslib.c b/drivers/video/sbuslib.c index 34ef859ee41..963a454b707 100644 --- a/drivers/video/sbuslib.c +++ b/drivers/video/sbuslib.c @@ -190,17 +190,6 @@ int sbusfb_ioctl_helper(unsigned long cmd, unsigned long arg, EXPORT_SYMBOL(sbusfb_ioctl_helper); #ifdef CONFIG_COMPAT -struct fbcmap32 { - int index; /* first element (0 origin) */ - int count; - u32 red; - u32 green; - u32 blue; -}; - -#define FBIOPUTCMAP32 _IOW('F', 3, struct fbcmap32) -#define FBIOGETCMAP32 _IOW('F', 4, struct fbcmap32) - static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long arg) { struct fbcmap32 __user *argp = (void __user *)arg; @@ -223,20 +212,6 @@ static int fbiogetputcmap(struct fb_info *info, unsigned int cmd, unsigned long (unsigned long)p); } -struct fbcursor32 { - short set; /* what to set, choose from the list above */ - short enable; /* cursor on/off */ - struct fbcurpos pos; /* cursor position */ - struct fbcurpos hot; /* cursor hot spot */ - struct fbcmap32 cmap; /* color map info */ - struct fbcurpos size; /* cursor bit map size */ - u32 image; /* cursor image bits */ - u32 mask; /* cursor mask bits */ -}; - -#define FBIOSCURSOR32 _IOW('F', 24, struct fbcursor32) -#define FBIOGCURSOR32 _IOW('F', 25, struct fbcursor32) - static int fbiogscursor(struct fb_info *info, unsigned long arg) { struct fbcursor __user *p = compat_alloc_user_space(sizeof(*p)); diff --git a/drivers/video/tcx.c b/drivers/video/tcx.c index 5a99669232c..e5a9ddb3c8b 100644 --- a/drivers/video/tcx.c +++ b/drivers/video/tcx.c @@ -345,88 +345,82 @@ tcx_init_fix(struct fb_info *info, int linebytes) info->fix.accel = FB_ACCEL_SUN_TCX; } -struct all_info { - struct fb_info info; - struct tcx_par par; -}; - -static void tcx_unmap_regs(struct of_device *op, struct all_info *all) +static void tcx_unmap_regs(struct of_device *op, struct fb_info *info, + struct tcx_par *par) { - if (all->par.tec) + if (par->tec) of_iounmap(&op->resource[7], - all->par.tec, sizeof(struct tcx_tec)); - if (all->par.thc) + par->tec, sizeof(struct tcx_tec)); + if (par->thc) of_iounmap(&op->resource[9], - all->par.thc, sizeof(struct tcx_thc)); - if (all->par.bt) + par->thc, sizeof(struct tcx_thc)); + if (par->bt) of_iounmap(&op->resource[8], - all->par.bt, sizeof(struct bt_regs)); - if (all->par.cplane) + par->bt, sizeof(struct bt_regs)); + if (par->cplane) of_iounmap(&op->resource[4], - all->par.cplane, all->par.fbsize * sizeof(u32)); - if (all->info.screen_base) + par->cplane, par->fbsize * sizeof(u32)); + if (info->screen_base) of_iounmap(&op->resource[0], - all->info.screen_base, all->par.fbsize); + info->screen_base, par->fbsize); } static int __devinit tcx_init_one(struct of_device *op) { struct device_node *dp = op->node; - struct all_info *all; + struct fb_info *info; + struct tcx_par *par; int linebytes, i, err; - all = kzalloc(sizeof(*all), GFP_KERNEL); - if (!all) - return -ENOMEM; + info = framebuffer_alloc(sizeof(struct tcx_par), &op->dev); - spin_lock_init(&all->par.lock); + err = -ENOMEM; + if (!info) + goto out_err; + par = info->par; - all->par.lowdepth = + spin_lock_init(&par->lock); + + par->lowdepth = (of_find_property(dp, "tcx-8-bit", NULL) != NULL); - sbusfb_fill_var(&all->info.var, dp->node, 8); - all->info.var.red.length = 8; - all->info.var.green.length = 8; - all->info.var.blue.length = 8; + sbusfb_fill_var(&info->var, dp->node, 8); + info->var.red.length = 8; + info->var.green.length = 8; + info->var.blue.length = 8; linebytes = of_getintprop_default(dp, "linebytes", - all->info.var.xres); - all->par.fbsize = PAGE_ALIGN(linebytes * all->info.var.yres); + info->var.xres); + par->fbsize = PAGE_ALIGN(linebytes * info->var.yres); - all->par.tec = of_ioremap(&op->resource[7], 0, + par->tec = of_ioremap(&op->resource[7], 0, sizeof(struct tcx_tec), "tcx tec"); - all->par.thc = of_ioremap(&op->resource[9], 0, + par->thc = of_ioremap(&op->resource[9], 0, sizeof(struct tcx_thc), "tcx thc"); - all->par.bt = of_ioremap(&op->resource[8], 0, + par->bt = of_ioremap(&op->resource[8], 0, sizeof(struct bt_regs), "tcx dac"); - all->info.screen_base = of_ioremap(&op->resource[0], 0, - all->par.fbsize, "tcx ram"); - if (!all->par.tec || !all->par.thc || - !all->par.bt || !all->info.screen_base) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } - - memcpy(&all->par.mmap_map, &__tcx_mmap_map, sizeof(all->par.mmap_map)); - if (!all->par.lowdepth) { - all->par.cplane = of_ioremap(&op->resource[4], 0, - all->par.fbsize * sizeof(u32), + info->screen_base = of_ioremap(&op->resource[0], 0, + par->fbsize, "tcx ram"); + if (!par->tec || !par->thc || + !par->bt || !info->screen_base) + goto out_unmap_regs; + + memcpy(&par->mmap_map, &__tcx_mmap_map, sizeof(par->mmap_map)); + if (!par->lowdepth) { + par->cplane = of_ioremap(&op->resource[4], 0, + par->fbsize * sizeof(u32), "tcx cplane"); - if (!all->par.cplane) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + if (!par->cplane) + goto out_unmap_regs; } else { - all->par.mmap_map[1].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[4].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[5].size = SBUS_MMAP_EMPTY; - all->par.mmap_map[6].size = SBUS_MMAP_EMPTY; + par->mmap_map[1].size = SBUS_MMAP_EMPTY; + par->mmap_map[4].size = SBUS_MMAP_EMPTY; + par->mmap_map[5].size = SBUS_MMAP_EMPTY; + par->mmap_map[6].size = SBUS_MMAP_EMPTY; } - all->par.physbase = 0; - all->par.which_io = op->resource[0].flags & IORESOURCE_BITS; + par->physbase = 0; + par->which_io = op->resource[0].flags & IORESOURCE_BITS; for (i = 0; i < TCX_MMAP_ENTRIES; i++) { int j; @@ -444,53 +438,54 @@ static int __devinit tcx_init_one(struct of_device *op) j = i; break; }; - all->par.mmap_map[i].poff = op->resource[j].start; + par->mmap_map[i].poff = op->resource[j].start; } - all->info.flags = FBINFO_DEFAULT; - all->info.fbops = &tcx_ops; - all->info.par = &all->par; + info->flags = FBINFO_DEFAULT; + info->fbops = &tcx_ops; /* Initialize brooktree DAC. */ - sbus_writel(0x04 << 24, &all->par.bt->addr); /* color planes */ - sbus_writel(0xff << 24, &all->par.bt->control); - sbus_writel(0x05 << 24, &all->par.bt->addr); - sbus_writel(0x00 << 24, &all->par.bt->control); - sbus_writel(0x06 << 24, &all->par.bt->addr); /* overlay plane */ - sbus_writel(0x73 << 24, &all->par.bt->control); - sbus_writel(0x07 << 24, &all->par.bt->addr); - sbus_writel(0x00 << 24, &all->par.bt->control); - - tcx_reset(&all->info); - - tcx_blank(FB_BLANK_UNBLANK, &all->info); - - if (fb_alloc_cmap(&all->info.cmap, 256, 0)) { - tcx_unmap_regs(op, all); - kfree(all); - return -ENOMEM; - } + sbus_writel(0x04 << 24, &par->bt->addr); /* color planes */ + sbus_writel(0xff << 24, &par->bt->control); + sbus_writel(0x05 << 24, &par->bt->addr); + sbus_writel(0x00 << 24, &par->bt->control); + sbus_writel(0x06 << 24, &par->bt->addr); /* overlay plane */ + sbus_writel(0x73 << 24, &par->bt->control); + sbus_writel(0x07 << 24, &par->bt->addr); + sbus_writel(0x00 << 24, &par->bt->control); + + tcx_reset(info); - fb_set_cmap(&all->info.cmap, &all->info); - tcx_init_fix(&all->info, linebytes); + tcx_blank(FB_BLANK_UNBLANK, info); - err = register_framebuffer(&all->info); - if (err < 0) { - fb_dealloc_cmap(&all->info.cmap); - tcx_unmap_regs(op, all); - kfree(all); - return err; - } + if (fb_alloc_cmap(&info->cmap, 256, 0)) + goto out_unmap_regs; + + fb_set_cmap(&info->cmap, info); + tcx_init_fix(info, linebytes); + + err = register_framebuffer(info); + if (err < 0) + goto out_dealloc_cmap; - dev_set_drvdata(&op->dev, all); + dev_set_drvdata(&op->dev, info); printk("%s: TCX at %lx:%lx, %s\n", dp->full_name, - all->par.which_io, + par->which_io, op->resource[0].start, - all->par.lowdepth ? "8-bit only" : "24-bit depth"); + par->lowdepth ? "8-bit only" : "24-bit depth"); return 0; + +out_dealloc_cmap: + fb_dealloc_cmap(&info->cmap); + +out_unmap_regs: + tcx_unmap_regs(op, info, par); + +out_err: + return err; } static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id *match) @@ -502,14 +497,15 @@ static int __devinit tcx_probe(struct of_device *dev, const struct of_device_id static int __devexit tcx_remove(struct of_device *op) { - struct all_info *all = dev_get_drvdata(&op->dev); + struct fb_info *info = dev_get_drvdata(&op->dev); + struct tcx_par *par = info->par; - unregister_framebuffer(&all->info); - fb_dealloc_cmap(&all->info.cmap); + unregister_framebuffer(info); + fb_dealloc_cmap(&info->cmap); - tcx_unmap_regs(op, all); + tcx_unmap_regs(op, info, par); - kfree(all); + framebuffer_release(info); dev_set_drvdata(&op->dev, NULL); diff --git a/drivers/video/tgafb.c b/drivers/video/tgafb.c index 89facb73edf..d292a37ec7d 100644 --- a/drivers/video/tgafb.c +++ b/drivers/video/tgafb.c @@ -849,7 +849,7 @@ tgafb_clut_imageblit(struct fb_info *info, const struct fb_image *image) u32 *palette = ((u32 *)info->pseudo_palette); unsigned long pos, line_length, i, j; const unsigned char *data; - void *regs_base, *fb_base; + void __iomem *regs_base, *fb_base; dx = image->dx; dy = image->dy; diff --git a/drivers/video/tx3912fb.c b/drivers/video/tx3912fb.c deleted file mode 100644 index e6f7c78da68..00000000000 --- a/drivers/video/tx3912fb.c +++ /dev/null @@ -1,326 +0,0 @@ -/* - * drivers/video/tx3912fb.c - * - * Copyright (C) 1999 Harald Koerfgen - * Copyright (C) 2001 Steven Hill (sjhill@realitydiluted.com) - * - * This file is subject to the terms and conditions of the GNU General Public - * License. See the file COPYING in the main directory of this archive for - * more details. - * - * Framebuffer for LCD controller in TMPR3912/05 and PR31700 processors - */ -#include <linux/module.h> -#include <linux/kernel.h> -#include <linux/errno.h> -#include <linux/string.h> -#include <linux/delay.h> -#include <linux/interrupt.h> -#include <linux/init.h> -#include <linux/pm.h> -#include <linux/fb.h> -#include <asm/io.h> -#include <asm/bootinfo.h> -#include <asm/uaccess.h> -#include <asm/tx3912.h> -#include <video/tx3912.h> - -/* - * Frame buffer, palette and console structures - */ -static struct fb_info fb_info; -static u32 cfb8[16]; - -static struct fb_fix_screeninfo tx3912fb_fix __initdata = { - .id = "tx3912fb", - .smem_len = ((240 * 320)/2), - .type = FB_TYPE_PACKED_PIXELS, - .visual = FB_VISUAL_TRUECOLOR, - .xpanstep = 1, - .ypanstep = 1, - .ywrapstep = 1, - .accel = FB_ACCEL_NONE, -}; - -static struct fb_var_screeninfo tx3912fb_var = { - .xres = 240, - .yres = 320, - .xres_virtual = 240, - .yres_virtual = 320, - .bits_per_pixel =4, - .red = { 0, 4, 0 }, /* ??? */ - .green = { 0, 4, 0 }, - .blue = { 0, 4, 0 }, - .activate = FB_ACTIVATE_NOW, - .width = -1, - .height = -1, - .pixclock = 20000, - .left_margin = 64, - .right_margin = 64, - .upper_margin = 32, - .lower_margin = 32, - .hsync_len = 64, - .vsync_len = 2, - .vmode = FB_VMODE_NONINTERLACED, -}; - -/* - * Interface used by the world - */ -int tx3912fb_init(void); - -static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info); - -/* - * Macros - */ -#define get_line_length(xres_virtual, bpp) \ - (u_long) (((int) xres_virtual * (int) bpp + 7) >> 3) - -/* - * Frame buffer operations structure used by console driver - */ -static struct fb_ops tx3912fb_ops = { - .owner = THIS_MODULE, - .fb_setcolreg = tx3912fb_setcolreg, - .fb_fillrect = cfb_fillrect, - .fb_copyarea = cfb_copyarea, - .fb_imageblit = cfb_imageblit, -}; - -static int tx3912fb_check_var(struct fb_var_screeninfo *var, struct fb_info *info) -{ - /* - * Memory limit - */ - line_length = - get_line_length(var->xres_virtual, var->bits_per_pixel); - if ((line_length * var->yres_virtual) > info->fix.smem_len) - return -ENOMEM; - - return 0; -} - -static int tx3912fb_set_par(struct fb_info *info) -{ - u_long tx3912fb_paddr = 0; - - /* Disable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Set start address for DMA transfer */ - outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3); - - /* Set end address for DMA transfer */ - outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4); - - /* Set the pixel depth */ - switch (info->var.bits_per_pixel) { - case 1: - /* Monochrome */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_MONO10; - break; - case 4: - /* 4-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 8: - /* 8-bit color */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 2: - default: - /* 2-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY, - TX3912_VIDEO_CTRL1); - info->fix.visual = FB_VISUAL_PSEUDOCOLOR; - break; - } - - /* Enable the video clock */ - outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK, - TX3912_CLK_CTRL); - - /* Unfreeze video logic and enable DF toggle */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | - TX3912_VIDEO_CTRL1_DFMODE) - , TX3912_VIDEO_CTRL1); - udelay(200); - - /* Enable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) | - (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - - info->fix.line_length = get_line_length(var->xres_virtual, - var->bits_per_pixel); -} - -/* - * Set a single color register - */ -static int tx3912fb_setcolreg(u_int regno, u_int red, u_int green, - u_int blue, u_int transp, - struct fb_info *info) -{ - if (regno > 255) - return 1; - - if (regno < 16) - ((u32 *)(info->pseudo_palette))[regno] = ((red & 0xe000) >> 8) - | ((green & 0xe000) >> 11) - | ((blue & 0xc000) >> 14); - return 0; -} - -int __init tx3912fb_setup(char *options); - -/* - * Initialization of the framebuffer - */ -int __init tx3912fb_init(void) -{ - u_long tx3912fb_paddr = 0; - int size = (info->var.bits_per_pixel == 8) ? 256 : 16; - char *option = NULL; - - if (fb_get_options("tx3912fb", &option)) - return -ENODEV; - tx3912fb_setup(option); - - /* Disable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Set start address for DMA transfer */ - outl(tx3912fb_paddr, TX3912_VIDEO_CTRL3); - - /* Set end address for DMA transfer */ - outl((tx3912fb_paddr + tx3912fb_fix.smem_len + 1), TX3912_VIDEO_CTRL4); - - /* Set the pixel depth */ - switch (tx3912fb_var.bits_per_pixel) { - case 1: - /* Monochrome */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_MONO10; - break; - case 4: - /* 4-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_4BIT_GRAY, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR; - tx3912fb_fix.grayscale = 1; - break; - case 8: - /* 8-bit color */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_8BIT_COLOR, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_TRUECOLOR; - break; - case 2: - default: - /* 2-bit gray */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~TX3912_VIDEO_CTRL1_BITSEL_MASK, TX3912_VIDEO_CTRL1); - outl(inl(TX3912_VIDEO_CTRL1) | - TX3912_VIDEO_CTRL1_BITSEL_2BIT_GRAY, - TX3912_VIDEO_CTRL1); - tx3912fb_fix.visual = FB_VISUAL_PSEUDOCOLOR; - tx3912fb_fix.grayscale = 1; - break; - } - - /* Enable the video clock */ - outl(inl(TX3912_CLK_CTRL) | TX3912_CLK_CTRL_ENVIDCLK, - TX3912_CLK_CTRL); - - /* Unfreeze video logic and enable DF toggle */ - outl(inl(TX3912_VIDEO_CTRL1) & - ~(TX3912_VIDEO_CTRL1_ENFREEZEFRAME | TX3912_VIDEO_CTRL1_DFMODE), - TX3912_VIDEO_CTRL1); - udelay(200); - - /* Clear the framebuffer */ - memset((void *) tx3912fb_fix.smem_start, 0xff, tx3912fb_fix.smem_len); - udelay(200); - - /* Enable the video logic */ - outl(inl(TX3912_VIDEO_CTRL1) | - (TX3912_VIDEO_CTRL1_ENVID | TX3912_VIDEO_CTRL1_DISPON), - TX3912_VIDEO_CTRL1); - - /* - * Memory limit - */ - tx3912fb_fix.line_length = - get_line_length(tx3912fb_var.xres_virtual, tx3912fb_var.bits_per_pixel); - if ((tx3912fb_fix.line_length * tx3912fb_var.yres_virtual) > tx3912fb_fix.smem_len) - return -ENOMEM; - - fb_info.fbops = &tx3912fb_ops; - fb_info.var = tx3912fb_var; - fb_info.fix = tx3912fb_fix; - fb_info.pseudo_palette = cfb8; - fb_info.flags = FBINFO_DEFAULT; - - /* Clear the framebuffer */ - memset((void *) fb_info.fix.smem_start, 0xff, fb_info.fix.smem_len); - udelay(200); - - fb_alloc_cmap(&info->cmap, size, 0); - - if (register_framebuffer(&fb_info) < 0) - return -1; - - printk(KERN_INFO "fb%d: TX3912 frame buffer using %uKB.\n", - fb_info.node, (u_int) (fb_info.fix.smem_len >> 10)); - return 0; -} - -int __init tx3912fb_setup(char *options) -{ - char *this_opt; - - if (!options || !*options) - return 0; - - while ((this_opt = strsep(&options, ","))) { - if (!strncmp(options, "bpp:", 4)) - tx3912fb_var.bits_per_pixel = simple_strtoul(options+4, NULL, 0); - } - return 0; -} - -module_init(tx3912fb_init); -MODULE_LICENSE("GPL"); diff --git a/drivers/video/xilinxfb.c b/drivers/video/xilinxfb.c index 1d29a89a86b..6ef9733a18d 100644 --- a/drivers/video/xilinxfb.c +++ b/drivers/video/xilinxfb.c @@ -79,7 +79,7 @@ /* * Here are the default fb_fix_screeninfo and fb_var_screeninfo structures */ -static struct fb_fix_screeninfo xilinx_fb_fix __initdata = { +static struct fb_fix_screeninfo xilinx_fb_fix = { .id = "Xilinx", .type = FB_TYPE_PACKED_PIXELS, .visual = FB_VISUAL_TRUECOLOR, @@ -88,7 +88,7 @@ static struct fb_fix_screeninfo xilinx_fb_fix __initdata = { .accel = FB_ACCEL_NONE }; -static struct fb_var_screeninfo xilinx_fb_var __initdata = { +static struct fb_var_screeninfo xilinx_fb_var = { .xres = XRES, .yres = YRES, .xres_virtual = XRES_VIRTUAL, @@ -212,11 +212,6 @@ xilinxfb_drv_probe(struct device *dev) pdev = to_platform_device(dev); pdata = pdev->dev.platform_data; - if (pdata == NULL) { - printk(KERN_ERR "Couldn't find platform data.\n"); - return -EFAULT; - } - drvdata = kzalloc(sizeof(*drvdata), GFP_KERNEL); if (!drvdata) { printk(KERN_ERR "Couldn't allocate device private record\n"); @@ -258,11 +253,9 @@ xilinxfb_drv_probe(struct device *dev) xilinx_fb_out_be32(drvdata, REG_FB_ADDR, drvdata->fb_phys); /* Turn on the display */ - if (pdata->rotate_screen) { - drvdata->reg_ctrl_default = REG_CTRL_ENABLE | REG_CTRL_ROTATE; - } else { - drvdata->reg_ctrl_default = REG_CTRL_ENABLE; - } + drvdata->reg_ctrl_default = REG_CTRL_ENABLE; + if (pdata && pdata->rotate_screen) + drvdata->reg_ctrl_default |= REG_CTRL_ROTATE; xilinx_fb_out_be32(drvdata, REG_CTRL, drvdata->reg_ctrl_default); /* Fill struct fb_info */ @@ -281,8 +274,10 @@ xilinxfb_drv_probe(struct device *dev) } drvdata->info.flags = FBINFO_DEFAULT; - xilinx_fb_var.height = pdata->screen_height_mm; - xilinx_fb_var.width = pdata->screen_width_mm; + if (pdata) { + xilinx_fb_var.height = pdata->screen_height_mm; + xilinx_fb_var.width = pdata->screen_width_mm; + } drvdata->info.var = xilinx_fb_var; /* Register new frame buffer */ |