Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+18 −41
Original line number Original line Diff line number Diff line
@@ -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,
		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)