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
Solved! Go to Solution.
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.
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.
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.