diff options
Diffstat (limited to 'kernel/drivers/video/fbdev/vesafb.c')
-rw-r--r-- | kernel/drivers/video/fbdev/vesafb.c | 80 |
1 files changed, 28 insertions, 52 deletions
diff --git a/kernel/drivers/video/fbdev/vesafb.c b/kernel/drivers/video/fbdev/vesafb.c index d79a0ac49..528fe917d 100644 --- a/kernel/drivers/video/fbdev/vesafb.c +++ b/kernel/drivers/video/fbdev/vesafb.c @@ -19,16 +19,20 @@ #include <linux/init.h> #include <linux/platform_device.h> #include <linux/screen_info.h> +#include <linux/io.h> #include <video/vga.h> -#include <asm/io.h> -#include <asm/mtrr.h> #define dac_reg (0x3c8) #define dac_val (0x3c9) /* --------------------------------------------------------------------- */ +struct vesafb_par { + u32 pseudo_palette[256]; + int wc_cookie; +}; + static struct fb_var_screeninfo vesafb_defined = { .activate = FB_ACTIVATE_NOW, .height = -1, @@ -175,7 +179,10 @@ static int vesafb_setcolreg(unsigned regno, unsigned red, unsigned green, static void vesafb_destroy(struct fb_info *info) { + struct vesafb_par *par = info->par; + fb_dealloc_cmap(&info->cmap); + arch_phys_wc_del(par->wc_cookie); if (info->screen_base) iounmap(info->screen_base); release_mem_region(info->apertures->ranges[0].base, info->apertures->ranges[0].size); @@ -228,6 +235,7 @@ static int vesafb_setup(char *options) static int vesafb_probe(struct platform_device *dev) { struct fb_info *info; + struct vesafb_par *par; int i, err; unsigned int size_vmode; unsigned int size_remap; @@ -291,14 +299,14 @@ static int vesafb_probe(struct platform_device *dev) spaces our resource handlers simply don't know about */ } - info = framebuffer_alloc(sizeof(u32) * 256, &dev->dev); + info = framebuffer_alloc(sizeof(struct vesafb_par), &dev->dev); if (!info) { release_mem_region(vesafb_fix.smem_start, size_total); return -ENOMEM; } platform_set_drvdata(dev, info); - info->pseudo_palette = info->par; - info->par = NULL; + par = info->par; + info->pseudo_palette = par->pseudo_palette; /* set vesafb aperture size for generic probing */ info->apertures = alloc_apertures(1); @@ -404,60 +412,27 @@ static int vesafb_probe(struct platform_device *dev) * region already (FIXME) */ request_region(0x3c0, 32, "vesafb"); -#ifdef CONFIG_MTRR - if (mtrr) { + if (mtrr == 3) { unsigned int temp_size = size_total; - unsigned int type = 0; - - switch (mtrr) { - case 1: - type = MTRR_TYPE_UNCACHABLE; - break; - case 2: - type = MTRR_TYPE_WRBACK; - break; - case 3: - type = MTRR_TYPE_WRCOMB; - break; - case 4: - type = MTRR_TYPE_WRTHROUGH; - break; - default: - type = 0; - break; - } - if (type) { - int rc; + /* Find the largest power-of-two */ + temp_size = roundup_pow_of_two(temp_size); - /* Find the largest power-of-two */ - temp_size = roundup_pow_of_two(temp_size); + /* Try and find a power of two to add */ + do { + par->wc_cookie = + arch_phys_wc_add(vesafb_fix.smem_start, + temp_size); + temp_size >>= 1; + } while (temp_size >= PAGE_SIZE && par->wc_cookie < 0); - /* Try and find a power of two to add */ - do { - rc = mtrr_add(vesafb_fix.smem_start, temp_size, - type, 1); - temp_size >>= 1; - } while (temp_size >= PAGE_SIZE && rc == -EINVAL); - } - } -#endif - - switch (mtrr) { - case 1: /* uncachable */ - info->screen_base = ioremap_nocache(vesafb_fix.smem_start, vesafb_fix.smem_len); - break; - case 2: /* write-back */ - info->screen_base = ioremap_cache(vesafb_fix.smem_start, vesafb_fix.smem_len); - break; - case 3: /* write-combining */ info->screen_base = ioremap_wc(vesafb_fix.smem_start, vesafb_fix.smem_len); - break; - case 4: /* write-through */ - default: + } else { + if (mtrr && mtrr != 3) + WARN_ONCE(1, "Only MTRR_TYPE_WRCOMB (3) make sense\n"); info->screen_base = ioremap(vesafb_fix.smem_start, vesafb_fix.smem_len); - break; } + if (!info->screen_base) { printk(KERN_ERR "vesafb: abort, cannot ioremap video memory 0x%x @ 0x%lx\n", @@ -492,6 +467,7 @@ static int vesafb_probe(struct platform_device *dev) fb_info(info, "%s frame buffer device\n", info->fix.id); return 0; err: + arch_phys_wc_del(par->wc_cookie); if (info->screen_base) iounmap(info->screen_base); framebuffer_release(info); |