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: Krzysztof Helt <krzysztof.h1@poczta.fm> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
950bbabb5a
commit
09a2910e54
|
@ -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,
|
||||
struct fb_info *info)
|
||||
{
|
||||
int nom, den; /* translyting from pixels->bytes */
|
||||
int yres, i;
|
||||
static struct { int xres, yres; } modes[] =
|
||||
{ { 1600, 1280 },
|
||||
{ 1280, 1024 },
|
||||
{ 1024, 768 },
|
||||
{ 800, 600 },
|
||||
{ 640, 480 },
|
||||
{ -1, -1 } };
|
||||
int yres;
|
||||
/* memory size in pixels */
|
||||
unsigned pixels = info->screen_size * 8 / var->bits_per_pixel;
|
||||
|
||||
switch (var->bits_per_pixel) {
|
||||
case 1:
|
||||
nom = 4;
|
||||
den = 8;
|
||||
pixels /= 4;
|
||||
break; /* 8 pixel per byte, only 1/4th of mem usable */
|
||||
case 8:
|
||||
case 16:
|
||||
case 24:
|
||||
case 32:
|
||||
nom = var->bits_per_pixel / 8;
|
||||
den = 1;
|
||||
break; /* 1 pixel == 1 byte */
|
||||
default:
|
||||
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
|
||||
|
@ -658,43 +649,29 @@ static int cirrusfb_check_var(struct fb_var_screeninfo *var,
|
|||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (var->xres * nom / den * var->yres > info->screen_size) {
|
||||
printk(KERN_ERR "cirrusfb: mode %dx%dx%d rejected..."
|
||||
"resolution too high to fit into video memory!\n",
|
||||
var->xres, var->yres, var->bits_per_pixel);
|
||||
DPRINTK("EXIT - EINVAL error\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (var->xres_virtual < var->xres)
|
||||
var->xres_virtual = var->xres;
|
||||
/* use highest possible virtual resolution */
|
||||
if (var->xres_virtual == -1 &&
|
||||
var->yres_virtual == -1) {
|
||||
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;
|
||||
if (var->yres_virtual == -1) {
|
||||
var->yres_virtual = pixels / var->xres_virtual;
|
||||
|
||||
printk(KERN_INFO "cirrusfb: virtual resolution set to "
|
||||
"maximum of %dx%d\n", var->xres_virtual,
|
||||
var->yres_virtual);
|
||||
}
|
||||
|
||||
if (var->xres_virtual < var->xres)
|
||||
var->xres_virtual = var->xres;
|
||||
if (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)
|
||||
var->xoffset = 0;
|
||||
if (var->yoffset < 0)
|
||||
|
|
Loading…
Reference in New Issue