diff options
Diffstat (limited to 'drivers/video')
37 files changed, 1807 insertions, 668 deletions
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig index 6e16244f3ed..fd55c279915 100644 --- a/drivers/video/Kconfig +++ b/drivers/video/Kconfig @@ -1511,6 +1511,7 @@ config FB_VIA select FB_CFB_IMAGEBLIT select I2C_ALGOBIT select I2C + select GPIOLIB help This is the frame buffer device driver for Graphics chips of VIA UniChrome (Pro) Family (CLE266,PM800/CN400,P4M800CE/P4M800Pro/ @@ -1520,6 +1521,21 @@ config FB_VIA To compile this driver as a module, choose M here: the module will be called viafb. + +if FB_VIA + +config FB_VIA_DIRECT_PROCFS + bool "direct hardware access via procfs (DEPRECATED)(DANGEROUS)" + depends on FB_VIA + default n + help + Allow direct hardware access to some output registers via procfs. + This is dangerous but may provide the only chance to get the + correct output device configuration. + Its use is strongly discouraged. + +endif + config FB_NEOMAGIC tristate "NeoMagic display support" depends on FB && PCI diff --git a/drivers/video/amifb.c b/drivers/video/amifb.c index dca48df9844..e5d6b56d444 100644 --- a/drivers/video/amifb.c +++ b/drivers/video/amifb.c @@ -50,8 +50,9 @@ #include <linux/fb.h> #include <linux/init.h> #include <linux/ioport.h> - +#include <linux/platform_device.h> #include <linux/uaccess.h> + #include <asm/system.h> #include <asm/irq.h> #include <asm/amigahw.h> @@ -1135,7 +1136,7 @@ static int amifb_ioctl(struct fb_info *info, unsigned int cmd, unsigned long arg * Interface to the low level console driver */ -static void amifb_deinit(void); +static void amifb_deinit(struct platform_device *pdev); /* * Internal routines @@ -2246,7 +2247,7 @@ static inline void chipfree(void) * Initialisation */ -static int __init amifb_init(void) +static int __init amifb_probe(struct platform_device *pdev) { int tag, i, err = 0; u_long chipptr; @@ -2261,16 +2262,6 @@ static int __init amifb_init(void) } amifb_setup(option); #endif - if (!MACH_IS_AMIGA || !AMIGAHW_PRESENT(AMI_VIDEO)) - return -ENODEV; - - /* - * We request all registers starting from bplpt[0] - */ - if (!request_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120, - "amifb [Denise/Lisa]")) - return -EBUSY; - custom.dmacon = DMAF_ALL | DMAF_MASTER; switch (amiga_chipset) { @@ -2377,6 +2368,7 @@ default_chipset: fb_info.fbops = &amifb_ops; fb_info.par = ¤tpar; fb_info.flags = FBINFO_DEFAULT; + fb_info.device = &pdev->dev; if (!fb_find_mode(&fb_info.var, &fb_info, mode_option, ami_modedb, NUM_TOTAL_MODES, &ami_modedb[defmode], 4)) { @@ -2451,18 +2443,18 @@ default_chipset: return 0; amifb_error: - amifb_deinit(); + amifb_deinit(pdev); return err; } -static void amifb_deinit(void) +static void amifb_deinit(struct platform_device *pdev) { if (fb_info.cmap.len) fb_dealloc_cmap(&fb_info.cmap); + fb_dealloc_cmap(&fb_info.cmap); chipfree(); if (videomemory) iounmap((void*)videomemory); - release_mem_region(CUSTOM_PHYSADDR+0xe0, 0x120); custom.dmacon = DMAF_ALL | DMAF_MASTER; } @@ -3794,14 +3786,35 @@ static void ami_rebuild_copper(void) } } -static void __exit amifb_exit(void) +static int __exit amifb_remove(struct platform_device *pdev) { unregister_framebuffer(&fb_info); - amifb_deinit(); + amifb_deinit(pdev); amifb_video_off(); + return 0; +} + +static struct platform_driver amifb_driver = { + .remove = __exit_p(amifb_remove), + .driver = { + .name = "amiga-video", + .owner = THIS_MODULE, + }, +}; + +static int __init amifb_init(void) +{ + return platform_driver_probe(&amifb_driver, amifb_probe); } module_init(amifb_init); + +static void __exit amifb_exit(void) +{ + platform_driver_unregister(&amifb_driver); +} + module_exit(amifb_exit); MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:amiga-video"); diff --git a/drivers/video/aty/radeon_base.c b/drivers/video/aty/radeon_base.c index 6c37e8ee5ef..3c1e13ed1cb 100644 --- a/drivers/video/aty/radeon_base.c +++ b/drivers/video/aty/radeon_base.c @@ -2099,7 +2099,7 @@ static ssize_t radeon_show_one_edid(char *buf, loff_t off, size_t count, const u } -static ssize_t radeon_show_edid1(struct kobject *kobj, +static ssize_t radeon_show_edid1(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { @@ -2112,7 +2112,7 @@ static ssize_t radeon_show_edid1(struct kobject *kobj, } -static ssize_t radeon_show_edid2(struct kobject *kobj, +static ssize_t radeon_show_edid2(struct file *filp, struct kobject *kobj, struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count) { diff --git a/drivers/video/bfin-t350mcqb-fb.c b/drivers/video/bfin-t350mcqb-fb.c index 44e49c28b2a..c2ec3dcd4e9 100644 --- a/drivers/video/bfin-t350mcqb-fb.c +++ b/drivers/video/bfin-t350mcqb-fb.c @@ -488,9 +488,9 @@ static int __devinit bfin_t350mcqb_probe(struct platform_device *pdev) fbinfo->fbops = &bfin_t350mcqb_fb_ops; fbinfo->flags = FBINFO_FLAG_DEFAULT; - info->fb_buffer = - dma_alloc_coherent(NULL, fbinfo->fix.smem_len, &info->dma_handle, - GFP_KERNEL); + info->fb_buffer = dma_alloc_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, + &info->dma_handle, GFP_KERNEL); if (NULL == info->fb_buffer) { printk(KERN_ERR DRIVER_NAME @@ -568,8 +568,8 @@ out7: out6: fb_dealloc_cmap(&fbinfo->cmap); out4: - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + ACTIVE_VIDEO_MEM_OFFSET, + info->fb_buffer, info->dma_handle); out3: framebuffer_release(fbinfo); out2: @@ -592,8 +592,9 @@ static int __devexit bfin_t350mcqb_remove(struct platform_device *pdev) free_irq(info->irq, info); if (info->fb_buffer != NULL) - dma_free_coherent(NULL, fbinfo->fix.smem_len, info->fb_buffer, - info->dma_handle); + dma_free_coherent(NULL, fbinfo->fix.smem_len + + ACTIVE_VIDEO_MEM_OFFSET, info->fb_buffer, + info->dma_handle); fb_dealloc_cmap(&fbinfo->cmap); diff --git a/drivers/video/cirrusfb.c b/drivers/video/cirrusfb.c index 8d8dfda2f86..6df7c54db0a 100644 --- a/drivers/video/cirrusfb.c +++ b/drivers/video/cirrusfb.c @@ -299,6 +299,7 @@ static const struct zorro_device_id cirrusfb_zorro_table[] = { }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, cirrusfb_zorro_table); static const struct { zorro_id id2; diff --git a/drivers/video/cobalt_lcdfb.c b/drivers/video/cobalt_lcdfb.c index 5eb61b5adfe..42fe155aba0 100644 --- a/drivers/video/cobalt_lcdfb.c +++ b/drivers/video/cobalt_lcdfb.c @@ -123,7 +123,7 @@ static void lcd_clear(struct fb_info *info) lcd_write_control(info, LCD_RESET); } -static struct fb_fix_screeninfo cobalt_lcdfb_fix __initdata = { +static struct fb_fix_screeninfo cobalt_lcdfb_fix __devinitdata = { .id = "cobalt-lcd", .type = FB_TYPE_TEXT, .type_aux = FB_AUX_TEXT_MDA, diff --git a/drivers/video/efifb.c b/drivers/video/efifb.c index ecf405562f5..4a56f46af40 100644 --- a/drivers/video/efifb.c +++ b/drivers/video/efifb.c @@ -168,7 +168,7 @@ static void efifb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -292,8 +292,13 @@ static int __devinit efifb_probe(struct platform_device *dev) info->pseudo_palette = info->par; info->par = NULL; - info->aperture_base = efifb_fix.smem_start; - info->aperture_size = size_remap; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + err = -ENOMEM; + goto err_release_fb; + } + info->apertures->ranges[0].base = efifb_fix.smem_start; + info->apertures->ranges[0].size = size_remap; info->screen_base = ioremap(efifb_fix.smem_start, efifb_fix.smem_len); if (!info->screen_base) { diff --git a/drivers/video/fbmem.c b/drivers/video/fbmem.c index a15b44e9c00..e08b7b5cb32 100644 --- a/drivers/video/fbmem.c +++ b/drivers/video/fbmem.c @@ -1468,16 +1468,67 @@ static int fb_check_foreignness(struct fb_info *fi) return 0; } -static bool fb_do_apertures_overlap(struct fb_info *gen, struct fb_info *hw) +static bool apertures_overlap(struct aperture *gen, struct aperture *hw) { /* is the generic aperture base the same as the HW one */ - if (gen->aperture_base == hw->aperture_base) + if (gen->base == hw->base) return true; /* is the generic aperture base inside the hw base->hw base+size */ - if (gen->aperture_base > hw->aperture_base && gen->aperture_base <= hw->aperture_base + hw->aperture_size) + if (gen->base > hw->base && gen->base <= hw->base + hw->size) return true; return false; } + +static bool fb_do_apertures_overlap(struct apertures_struct *gena, + struct apertures_struct *hwa) +{ + int i, j; + if (!hwa || !gena) + return false; + + for (i = 0; i < hwa->count; ++i) { + struct aperture *h = &hwa->ranges[i]; + for (j = 0; j < gena->count; ++j) { + struct aperture *g = &gena->ranges[j]; + printk(KERN_DEBUG "checking generic (%llx %llx) vs hw (%llx %llx)\n", + g->base, g->size, h->base, h->size); + if (apertures_overlap(g, h)) + return true; + } + } + + return false; +} + +#define VGA_FB_PHYS 0xA0000 +void remove_conflicting_framebuffers(struct apertures_struct *a, + const char *name, bool primary) +{ + int i; + + /* check all firmware fbs and kick off if the base addr overlaps */ + for (i = 0 ; i < FB_MAX; i++) { + struct apertures_struct *gen_aper; + if (!registered_fb[i]) + continue; + + if (!(registered_fb[i]->flags & FBINFO_MISC_FIRMWARE)) + continue; + + gen_aper = registered_fb[i]->apertures; + if (fb_do_apertures_overlap(gen_aper, a) || + (primary && gen_aper && gen_aper->count && + gen_aper->ranges[0].base == VGA_FB_PHYS)) { + + printk(KERN_ERR "fb: conflicting fb hw usage " + "%s vs %s - removing generic driver\n", + name, registered_fb[i]->fix.id); + unregister_framebuffer(registered_fb[i]); + } + } +} +EXPORT_SYMBOL(remove_conflicting_framebuffers); + /** * register_framebuffer - registers a frame buffer device * @fb_info: frame buffer info structure @@ -1501,21 +1552,8 @@ register_framebuffer(struct fb_info *fb_info) if (fb_check_foreignness(fb_info)) return -ENOSYS; - /* check all firmware fbs and kick off if the base addr overlaps */ - for (i = 0 ; i < FB_MAX; i++) { - if (!registered_fb[i]) - continue; - - if (registered_fb[i]->flags & FBINFO_MISC_FIRMWARE) { - if (fb_do_apertures_overlap(registered_fb[i], fb_info)) { - printk(KERN_ERR "fb: conflicting fb hw usage " - "%s vs %s - removing generic driver\n", - fb_info->fix.id, - registered_fb[i]->fix.id); - unregister_framebuffer(registered_fb[i]); - } - } - } + remove_conflicting_framebuffers(fb_info->apertures, fb_info->fix.id, + fb_is_primary_device(fb_info)); num_registered_fb++; for (i = 0 ; i < FB_MAX; i++) diff --git a/drivers/video/fbsysfs.c b/drivers/video/fbsysfs.c index 81aa3129c17..0a08f134122 100644 --- a/drivers/video/fbsysfs.c +++ b/drivers/video/fbsysfs.c @@ -80,6 +80,7 @@ EXPORT_SYMBOL(framebuffer_alloc); */ void framebuffer_release(struct fb_info *info) { + kfree(info->apertures); kfree(info); } EXPORT_SYMBOL(framebuffer_release); diff --git a/drivers/video/fm2fb.c b/drivers/video/fm2fb.c index 6c91c61cdb6..1b0feb8e724 100644 --- a/drivers/video/fm2fb.c +++ b/drivers/video/fm2fb.c @@ -219,6 +219,7 @@ static struct zorro_device_id fm2fb_devices[] __devinitdata = { { ZORRO_PROD_HELFRICH_RAINBOW_II }, { 0 } }; +MODULE_DEVICE_TABLE(zorro, fm2fb_devices); static struct zorro_driver fm2fb_driver = { .name = "fm2fb", diff --git a/drivers/video/offb.c b/drivers/video/offb.c index 61f8b8f919b..46dda7d8aae 100644 --- a/drivers/video/offb.c +++ b/drivers/video/offb.c @@ -285,7 +285,7 @@ static void offb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -491,8 +491,11 @@ static void __init offb_init_fb(const char *name, const char *full_name, var->vmode = FB_VMODE_NONINTERLACED; /* set offb aperture size for generic probing */ - info->aperture_base = address; - info->aperture_size = fix->smem_len; + info->apertures = alloc_apertures(1); + if (!info->apertures) + goto out_aper; + info->apertures->ranges[0].base = address; + info->apertures->ranges[0].size = fix->smem_len; info->fbops = &offb_ops; info->screen_base = ioremap(address, fix->smem_len); @@ -501,17 +504,20 @@ static void __init offb_init_fb(const char *name, const char *full_name, fb_alloc_cmap(&info->cmap, 256, 0); - if (register_framebuffer(info) < 0) { - iounmap(par->cmap_adr); - par->cmap_adr = NULL; - iounmap(info->screen_base); - framebuffer_release(info); - release_mem_region(res_start, res_size); - return; - } + if (register_framebuffer(info) < 0) + goto out_err; printk(KERN_INFO "fb%d: Open Firmware frame buffer device on %s\n", info->node, full_name); + return; + +out_err: + iounmap(info->screen_base); +out_aper: + iounmap(par->cmap_adr); + par->cmap_adr = NULL; + framebuffer_release(info); + release_mem_region(res_start, res_size); } diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c index e14bd074912..e8c76994481 100644 --- a/drivers/video/sh_mobile_lcdcfb.c +++ b/drivers/video/sh_mobile_lcdcfb.c @@ -695,6 +695,7 @@ static int sh_mobile_lcdc_setup_clocks(struct platform_device *pdev, * 1) Enable Runtime PM * 2) Force Runtime PM Resume since hardware is accessed from probe() */ + priv->dev = &pdev->dev; pm_runtime_enable(priv->dev); pm_runtime_resume(priv->dev); return 0; @@ -957,25 +958,24 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) if (!pdev->dev.platform_data) { dev_err(&pdev->dev, "no platform data defined\n"); - error = -EINVAL; - goto err0; + return -EINVAL; } res = platform_get_resource(pdev, IORESOURCE_MEM, 0); i = platform_get_irq(pdev, 0); if (!res || i < 0) { dev_err(&pdev->dev, "cannot get platform resources\n"); - error = -ENOENT; - goto err0; + return -ENOENT; } priv = kzalloc(sizeof(*priv), GFP_KERNEL); if (!priv) { dev_err(&pdev->dev, "cannot allocate device data\n"); - error = -ENOMEM; - goto err0; + return -ENOMEM; } + platform_set_drvdata(pdev, priv); + error = request_irq(i, sh_mobile_lcdc_irq, IRQF_DISABLED, dev_name(&pdev->dev), priv); if (error) { @@ -984,8 +984,6 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) } priv->irq = i; - priv->dev = &pdev->dev; - platform_set_drvdata(pdev, priv); pdata = pdev->dev.platform_data; j = 0; @@ -1099,9 +1097,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) info = ch->info; if (info->fbdefio) { - priv->ch->sglist = vmalloc(sizeof(struct scatterlist) * + ch->sglist = vmalloc(sizeof(struct scatterlist) * info->fix.smem_len >> PAGE_SHIFT); - if (!priv->ch->sglist) { + if (!ch->sglist) { dev_err(&pdev->dev, "cannot allocate sglist\n"); goto err1; } @@ -1126,9 +1124,9 @@ static int __devinit sh_mobile_lcdc_probe(struct platform_device *pdev) } return 0; - err1: +err1: sh_mobile_lcdc_remove(pdev); - err0: + return error; } @@ -1139,7 +1137,7 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) int i; for (i = 0; i < ARRAY_SIZE(priv->ch); i++) - if (priv->ch[i].info->dev) + if (priv->ch[i].info && priv->ch[i].info->dev) unregister_framebuffer(priv->ch[i].info); sh_mobile_lcdc_stop(priv); @@ -1162,7 +1160,8 @@ static int sh_mobile_lcdc_remove(struct platform_device *pdev) if (priv->dot_clk) clk_put(priv->dot_clk); - pm_runtime_disable(priv->dev); + if (priv->dev) + pm_runtime_disable(priv->dev); if (priv->base) iounmap(priv->base); diff --git a/drivers/video/vesafb.c b/drivers/video/vesafb.c index 0cadf7aee27..090aa1a9be6 100644 --- a/drivers/video/vesafb.c +++ b/drivers/video/vesafb.c @@ -177,7 +177,7 @@ static void vesafb_destroy(struct fb_info *info) { if (info->screen_base) iounmap(info->screen_base); - release_mem_region(info->aperture_base, info->aperture_size); + release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); framebuffer_release(info); } @@ -295,8 +295,13 @@ static int __init vesafb_probe(struct platform_device *dev) info->par = NULL; /* set vesafb aperture size for generic probing */ - info->aperture_base = screen_info.lfb_base; - info->aperture_size = size_total; + info->apertures = alloc_apertures(1); + if (!info->apertures) { + err = -ENOMEM; + goto err; + } + info->apertures->ranges[0].base = screen_info.lfb_base; + info->apertures->ranges[0].size = size_total; info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); if (!info->screen_base) { diff --git a/drivers/video/vga16fb.c b/drivers/video/vga16fb.c index bf638a47a5b..149c47ac7e9 100644 --- a/drivers/video/vga16fb.c +++ b/drivers/video/vga16fb.c @@ -1263,10 +1263,19 @@ static void vga16fb_imageblit(struct fb_info *info, const struct fb_image *image vga_imageblit_color(info, image); } +static void vga16fb_destroy(struct fb_info *info) +{ + iounmap(info->screen_base); + fb_dealloc_cmap(&info->cmap); + /* XXX unshare VGA regions */ + framebuffer_release(info); +} + static struct fb_ops vga16fb_ops = { .owner = THIS_MODULE, .fb_open = vga16fb_open, .fb_release = vga16fb_release, + .fb_destroy = vga16fb_destroy, .fb_check_var = vga16fb_check_var, .fb_set_par = vga16fb_set_par, .fb_setcolreg = vga16fb_setcolreg, @@ -1306,6 +1315,11 @@ static int __devinit vga16fb_probe(struct platform_device *dev) ret = -ENOMEM; goto err_fb_alloc; } + info->apertures = alloc_apertures(1); + if (!info->apertures) { + ret = -ENOMEM; + goto err_ioremap; + } /* XXX share VGA_FB_PHYS and I/O region with vgacon and others */ info->screen_base = (void __iomem *)VGA_MAP_MEM(VGA_FB_PHYS, 0); @@ -1335,7 +1349,7 @@ static int __devinit vga16fb_probe(struct platform_device *dev) info->fix = vga16fb_fix; /* supports rectangles with widths of multiples of 8 */ info->pixmap.blit_x = 1 << 7 | 1 << 15 | 1 << 23 | 1 << 31; - info->flags = FBINFO_FLAG_DEFAULT | + info->flags = FBINFO_FLAG_DEFAULT | FBINFO_MISC_FIRMWARE | FBINFO_HWACCEL_YPAN; i = (info->var.bits_per_pixel == 8) ? 256 : 16; @@ -1354,6 +1368,9 @@ static int __devinit vga16fb_probe(struct platform_device *dev) vga16fb_update_fix(info); + info->apertures->ranges[0].base = VGA_FB_PHYS; + info->apertures->ranges[0].size = VGA_FB_PHYS_LEN; + if (register_framebuffer(info) < 0) { printk(KERN_ERR "vga16fb: unable to register framebuffer\n"); ret = -EINVAL; @@ -1380,13 +1397,8 @@ static int vga16fb_remove(struct platform_device *dev) { struct fb_info *info = platform_get_drvdata(dev); - if (info) { + if (info) unregister_framebuffer(info); - iounmap(info->screen_base); - fb_dealloc_cmap(&info->cmap); - /* XXX unshare VGA regions */ - framebuffer_release(info); - } return 0; } diff --git a/drivers/video/via/Makefile b/drivers/video/via/Makefile index eeed238ad6a..d496adb0f83 100644 --- a/drivers/video/via/Makefile +++ b/drivers/video/via/Makefile @@ -4,4 +4,6 @@ obj-$(CONFIG_FB_VIA) += viafb.o -viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o +viafb-y :=viafbdev.o hw.o via_i2c.o dvi.o lcd.o ioctl.o accel.o \ + via_utility.o vt1636.o global.o tblDPASetting.o viamode.o tbl1636.o \ + via-core.o via-gpio.o via_modesetting.o diff --git a/drivers/video/via/accel.c b/drivers/video/via/accel.c index d5077dfa9e0..e44893ea590 100644 --- a/drivers/video/via/accel.c +++ b/drivers/video/via/accel.c @@ -18,14 +18,45 @@ * Foundation, Inc., * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +#include <linux/via-core.h> #include "global.h" +/* + * Figure out an appropriate bytes-per-pixel setting. + */ +static int viafb_set_bpp(void __iomem *engine, u8 bpp) +{ + u32 gemode; + + /* Preserve the reserved bits */ + /* Lowest 2 bits to zero gives us no rotation */ + gemode = readl(engine + VIA_REG_GEMODE) & 0xfffffcfc; + switch (bpp) { + case 8: + gemode |= VIA_GEM_8bpp; + break; + case 16: + gemode |= VIA_GEM_16bpp; + break; + case 32: + gemode |= VIA_GEM_32bpp; + break; + default: + printk(KERN_WARNING "viafb_set_bpp: Unsupported bpp %d\n", bpp); + return -EINVAL; + } + writel(gemode, engine + VIA_REG_GEMODE); + return 0; +} + + static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, u8 dst_bpp, u32 dst_addr, u32 dst_pitch, u32 dst_x, u32 dst_y, u32 *src_mem, u32 src_addr, u32 src_pitch, u32 src_x, u32 src_y, u32 fg_color, u32 bg_color, u8 fill_rop) { u32 ge_cmd = 0, tmp, i; + int ret; if (!op || op > 3) { printk(KERN_WARNING "hw_bitblt_1: Invalid operation: %d\n", op); @@ -59,22 +90,9 @@ static int hw_bitblt_1(void __iomem *engine, u8 op, u32 width, u32 height, } } - switch (dst_bpp) { - case 8: - tmp = 0x00000000; - break; - case 16: - tmp = 0x00000100; - break; - case 32: - tmp = 0x00000300; - break; - default: - printk(KERN_WARNING "hw_bitblt_1: Unsupported bpp %d\n", - dst_bpp); - return -EINVAL; - } - writel(tmp, engine + 0x04); + ret = viafb_set_bpp(engine, dst_bpp); + if (ret) + return ret; if (op != VIA_BITBLT_FILL) { if (src_x & (op == VIA_BITBLT_MONO ? 0xFFFF8000 : 0xFFFFF000) @@ -171,6 +189,7 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, u32 fg_color, u32 bg_color, u8 fill_rop) { u32 ge_cmd = 0, tmp, i; + int ret; if (!op || op > 3) { printk(KERN_WARNING "hw_bitblt_2: Invalid operation: %d\n", op); @@ -204,22 +223,9 @@ static int hw_bitblt_2(void __iomem *engine, u8 op, u32 width, u32 height, } } - switch (dst_bpp) { - case 8: - tmp = 0x00000000; - break; - case 16: - tmp = 0x00000100; - break; - case 32: - tmp = 0x00000300; - break; - default: - printk(KERN_WARNING "hw_bitblt_2: Unsupported bpp %d\n", - dst_bpp); - return -EINVAL; - } - writel(tmp, engine + 0x04); + ret = viafb_set_bpp(engine, dst_bpp); + if (ret) + return ret; if (op == VIA_BITBLT_FILL) tmp = 0; @@ -312,17 +318,29 @@ int viafb_init_engine(struct fb_info *info) { struct viafb_par *viapar = info->par; void __iomem *engine; + int highest_reg, i; u32 vq_start_addr, vq_end_addr, vq_start_low, vq_end_low, vq_high, vq_len, chip_name = viapar->shared->chip_info.gfx_chip_name; - engine = ioremap_nocache(info->fix.mmio_start, info->fix.mmio_len); - viapar->shared->engine_mmio = engine; + engine = viapar->shared->vdev->engine_mmio; if (!engine) { printk(KERN_WARNING "viafb_init_accel: ioremap failed, " "hardware acceleration disabled\n"); return -ENOMEM; } + /* Initialize registers to reset the 2D engine */ + switch (viapar->shared->chip_info.twod_engine) { + case VIA_2D_ENG_M1: + highest_reg = 0x5c; + break; + default: + highest_reg = 0x40; + break; + } + for (i = 0; i <= highest_reg; i += 4) + writel(0x0, engine + i); + switch (chip_name) { case UNICHROME_CLE266: case UNICHROME_K400: @@ -352,13 +370,28 @@ int viafb_init_engine(struct fb_info *info) viapar->shared->vq_vram_addr = viapar->fbmem_free; viapar->fbmem_used += VQ_SIZE; - /* Init 2D engine reg to reset 2D engine */ - writel(0x0, engine + VIA_REG_KEYCONTROL); +#if defined(CONFIG_FB_VIA_CAMERA) || defined(CONFIG_FB_VIA_CAMERA_MODULE) + |