iMX7 framebuffer ioctl fails

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

iMX7 framebuffer ioctl fails

Jump to solution
3,847 Views
michalhorn
Contributor II

Hello,

I came accross strange behavior of psplash, that it draws only every second frame on the display. I have found out that it fails to wait to vsync and pan the buffers.

From the psplash debug messages I am getting:

 

Error, FB vsync ioctl [-1]
psplash_fb_flip: FBIOPAN_DISPLAY failed

 

In the code handling the FB, these parts are

 

 int err = ioctl(fb->fd, FBIO_WAITFORVSYNC, 0);
  if (err != 0)
    fprintf(stderr, "Error, FB vsync ioctl [%d]\n", err);

...

    if (ioctl(fb->fd, FBIOPAN_DISPLAY, &fb->fb_var) == -1 ) {
      fprintf(stderr, "psplash_fb_flip: FBIOPAN_DISPLAY failed\n");
    }

 

So it means both are failing with error -1. I added some more debug code to the source code to get the exact error and these are:

Error, FB vsync ioctl [-1]: Inappropriate ioctl for device
psplash_fb_flip: FBIOPAN_DISPLAY failed: Invalid argument

When the fb is created in psplash, the double buffering would be disabled by 

 

 /* Setup double virtual resolution for double buffering */
  if (ioctl(fb->fd, FBIOPAN_DISPLAY, &fb_var) == -1) {
    fprintf(stderr, "FBIOPAN_DISPLAY not supported, double buffering disabled");

 

But it is not disabled, so this means the ioctl must have passed once before. By adding more verbose debug messages into the code, I see it really passes. I don't know why now and not afterwards.

And that is where I end, because I have no experience with framebuffers.

So I would like to ask for help. Is there some settings needed in DTS to enable double buffering? Disabling it completely would also be fine for me. But I don't know how.

Any hints will be appreciated.

Thanks, Michal

 

Labels (1)
0 Kudos
Reply
1 Solution
3,822 Views
michalhorn
Contributor II

Thanks for the pointer.

I have found the issue. The problem of getting the error 

 

psplash_fb_flip: FBIOPAN_DISPLAY failed: Invalid argument

 

is caused by a check on fb_pan_display 

if (err || !info->fbops->fb_pan_display ||
	    var->yoffset > info->var.yres_virtual - yres ||
	    var->xoffset > info->var.xres_virtual - info->var.xres)
		return -EINVAL;

where yres_virtual == yres, so the offset would overrun the buffer.

 

The psplash, when creating the FB, tries to detect the yres_virtual==yres and if so, tries to set it to 2*yres by FBIOPUT_VSCREENINFO ioctl. But his is handled in the mxsfb driver in such way that it resets the yres_virtual back to yres:

static int mxsfb_check_var(struct fb_var_screeninfo *var,
		struct fb_info *fb_info)
{
	...

	var->xres_virtual = var->xres;

	var->yres_virtual = var->yres;
...
}

Is that on purpose? Or is that an imperfection in the driver?

Anyway, I have created a patch for psplas: Fix double buffering initialization, to double check the yres_virtual, should any other driver behave the same.

View solution in original post

0 Kudos
Reply
2 Replies
3,835 Views
Zhiming_Liu
NXP TechSupport
NXP TechSupport

The ioctl in fb driver:

/drivers/video/fbdev/core/fbmem.c

case FBIOPAN_DISPLAY:
		if (copy_from_user(&var, argp, sizeof(var)))
			return -EFAULT;
		console_lock();
		lock_fb_info(info);
		ret = fb_pan_display(info, &var);
		unlock_fb_info(info);
		console_unlock();
		if (ret == 0 && copy_to_user(argp, &var, sizeof(var)))
			return -EFAULT;
		break;

 

drivers/video/fbdev/mxsfb.c(imx7 fd driver)

 

static int mxsfb_ioctl(struct fb_info *fb_info, unsigned int cmd,
			unsigned long arg)
{
	int ret = -EINVAL;

	switch (cmd) {
	case MXCFB_WAIT_FOR_VSYNC:
		ret = mxsfb_wait_for_vsync(fb_info);
		break;
	default:
		break;
	}
	return ret;
}

 

You need to debug these two drivers to see it's call process.

 

0 Kudos
Reply
3,823 Views
michalhorn
Contributor II

Thanks for the pointer.

I have found the issue. The problem of getting the error 

 

psplash_fb_flip: FBIOPAN_DISPLAY failed: Invalid argument

 

is caused by a check on fb_pan_display 

if (err || !info->fbops->fb_pan_display ||
	    var->yoffset > info->var.yres_virtual - yres ||
	    var->xoffset > info->var.xres_virtual - info->var.xres)
		return -EINVAL;

where yres_virtual == yres, so the offset would overrun the buffer.

 

The psplash, when creating the FB, tries to detect the yres_virtual==yres and if so, tries to set it to 2*yres by FBIOPUT_VSCREENINFO ioctl. But his is handled in the mxsfb driver in such way that it resets the yres_virtual back to yres:

static int mxsfb_check_var(struct fb_var_screeninfo *var,
		struct fb_info *fb_info)
{
	...

	var->xres_virtual = var->xres;

	var->yres_virtual = var->yres;
...
}

Is that on purpose? Or is that an imperfection in the driver?

Anyway, I have created a patch for psplas: Fix double buffering initialization, to double check the yres_virtual, should any other driver behave the same.

0 Kudos
Reply