Commit 09a2910e authored by Krzysztof Helt's avatar Krzysztof Helt Committed by Linus Torvalds

cirrusfb: check_par fixes

1. Check if virtual resolution fits into memory.
   Otherwise, Linux hangs during panning.
2. When selected use all available memory to
    maximize yres_virtual to speed up panning
   (previously also xres_virtual was increased).
3. Simplify memory restriction calculations.
Signed-off-by: default avatarKrzysztof Helt <krzysztof.h1@poczta.fm>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 950bbabb
...@@ -628,27 +628,18 @@ static long cirrusfb_get_mclk(long freq, int bpp, long *div) ...@@ -628,27 +628,18 @@ static long cirrusfb_get_mclk(long freq, int bpp, long *div)
static int cirrusfb_check_var(struct fb_var_screeninfo *var, static int cirrusfb_check_var(struct fb_var_screeninfo *var,
struct fb_info *info) struct fb_info *info)
{ {
int nom, den; /* translyting from pixels->bytes */ int yres;
int yres, i; /* memory size in pixels */
static struct { int xres, yres; } modes[] = unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
{ { 1600, 1280 },
{ 1280, 1024 },
{ 1024, 768 },
{ 800, 600 },
{ 640, 480 },
{ -1, -1 } };
switch (var->bits_per_pixel) { switch (var->bits_per_pixel) {
case 1: case 1:
nom = 4; pixels /= 4;
den = 8;
break; /* 8 pixel per byte, only 1/4th of mem usable */ break; /* 8 pixel per byte, only 1/4th of mem usable */
case 8: case 8:
case 16: case 16:
case 24: case 24:
case 32: case 32:
nom = var->bits_per_pixel / 8;
den = 1;
break; /* 1 pixel == 1 byte */ break; /* 1 pixel == 1 byte */
default: default:
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
...@@ -658,43 +649,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var, ...@@ -658,43 +649,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
return -EINVAL; return -EINVAL;
} }
if (var->xres * nom / den * var->yres > info->screen_size) { if (var->xres_virtual < var->xres)
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..." var->xres_virtual = var->xres;
"resolution too high to fit into video memory!\n",
var->xres, var->yres, var->bits_per_pixel);
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
/* use highest possible virtual resolution */ /* use highest possible virtual resolution */
if (var->xres_virtual == -1 && if (var->yres_virtual == -1) {
var->yres_virtual == -1) { var->yres_virtual = pixels / var->xres_virtual;
printk(KERN_INFO
"cirrusfb: using maximum available virtual resolution\n");
for (i = 0; modes[i].xres != -1; i++) {
int size = modes[i].xres * nom / den * modes[i].yres;
if (size < info->screen_size / 2)
break;
}
if (modes[i].xres == -1) {
printk(KERN_ERR "cirrusfb: could not find a virtual "
"resolution that fits into video memory!!\n");
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
var->xres_virtual = modes[i].xres;
var->yres_virtual = modes[i].yres;
printk(KERN_INFO "cirrusfb: virtual resolution set to " printk(KERN_INFO "cirrusfb: virtual resolution set to "
"maximum of %dx%d\n", var->xres_virtual, "maximum of %dx%d\n", var->xres_virtual,
var->yres_virtual); var->yres_virtual);
} }
if (var->xres_virtual < var->xres)
var->xres_virtual = var->xres;
if (var->yres_virtual < var->yres) if (var->yres_virtual < var->yres)
var->yres_virtual = var->yres; var->yres_virtual = var->yres;
if (var->xres_virtual * var->yres_virtual > pixels) {
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected... "
"virtual resolution too high to fit into video memory!\n",
var->xres_virtual, var->yres_virtual,
var->bits_per_pixel);
DPRINTK("EXIT - EINVAL error\n");
return -EINVAL;
}
if (var->xoffset < 0) if (var->xoffset < 0)
var->xoffset = 0; var->xoffset = 0;
if (var->yoffset < 0) if (var->yoffset < 0)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment