fbdev/arcfb: Use generator macros for deferred I/O

Implement the driver's fops with the generator macros for deferred
I/O. Only requires per-driver code for the on-scren scanout buffer.
The generated helpers implement reading, writing and drawing on top
of that. Also update the selected Kconfig tokens accordingly.

Actual support for deferred I/O is missing from the driver. So
writing to memory-mapped pages does not automatically update the
scanout buffer.

Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de>
Cc: Jaya Kumar <jayalk@intworks.biz>
Acked-by: Javier Martinez Canillas <javierm@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20231127131655.4020-7-tzimmermann@suse.de
This commit is contained in:
Thomas Zimmermann 2023-11-27 14:15:35 +01:00
parent 30b72c0bde
commit 28f57d03f5
2 changed files with 27 additions and 91 deletions

View File

@ -272,10 +272,7 @@ config FB_FM2
config FB_ARC
tristate "Arc Monochrome LCD board support"
depends on FB && (X86 || COMPILE_TEST)
select FB_SYS_FILLRECT
select FB_SYS_COPYAREA
select FB_SYS_IMAGEBLIT
select FB_SYS_FOPS
select FB_SYSMEM_HELPERS_DEFERRED
help
This enables support for the Arc Monochrome LCD board. The board
is based on the KS-108 lcd controller and is typically a matrix

View File

@ -363,39 +363,6 @@ static void arcfb_lcd_update(struct arcfb_par *par, unsigned int dx,
}
}
static void arcfb_fillrect(struct fb_info *info,
const struct fb_fillrect *rect)
{
struct arcfb_par *par = info->par;
sys_fillrect(info, rect);
/* update the physical lcd */
arcfb_lcd_update(par, rect->dx, rect->dy, rect->width, rect->height);
}
static void arcfb_copyarea(struct fb_info *info,
const struct fb_copyarea *area)
{
struct arcfb_par *par = info->par;
sys_copyarea(info, area);
/* update the physical lcd */
arcfb_lcd_update(par, area->dx, area->dy, area->width, area->height);
}
static void arcfb_imageblit(struct fb_info *info, const struct fb_image *image)
{
struct arcfb_par *par = info->par;
sys_imageblit(info, image);
/* update the physical lcd */
arcfb_lcd_update(par, image->dx, image->dy, image->width,
image->height);
}
static int arcfb_ioctl(struct fb_info *info,
unsigned int cmd, unsigned long arg)
{
@ -436,76 +403,48 @@ static int arcfb_ioctl(struct fb_info *info,
}
}
/*
* this is the access path from userspace. they can seek and write to
* the fb. it's inefficient for them to do anything less than 64*8
* writes since we update the lcd in each write() anyway.
*/
static ssize_t arcfb_write(struct fb_info *info, const char __user *buf,
size_t count, loff_t *ppos)
static void arcfb_damage_range(struct fb_info *info, off_t off, size_t len)
{
/* modded from epson 1355 */
struct arcfb_par *par = info->par;
unsigned int xres = info->var.xres;
unsigned int bitppos, startpos, endpos, bitcount;
unsigned int x, y, width, height;
unsigned long p;
int err;
unsigned int fbmemlength,x,y,w,h, bitppos, startpos, endpos, bitcount;
struct arcfb_par *par;
unsigned int xres;
if (!info->screen_buffer)
return -ENODEV;
p = *ppos;
par = info->par;
xres = info->var.xres;
fbmemlength = (xres * info->var.yres)/8;
if (p > fbmemlength)
return -ENOSPC;
err = 0;
if ((count + p) > fbmemlength) {
count = fbmemlength - p;
err = -ENOSPC;
}
if (count) {
char *base_addr;
base_addr = info->screen_buffer;
count -= copy_from_user(base_addr + p, buf, count);
*ppos += count;
err = -EFAULT;
}
bitppos = p*8;
bitppos = off * 8;
startpos = floorXres(bitppos, xres);
endpos = ceilXres((bitppos + (count*8)), xres);
endpos = ceilXres((bitppos + (len * 8)), xres);
bitcount = endpos - startpos;
x = startpos % xres;
y = startpos / xres;
w = xres;
h = bitcount / xres;
arcfb_lcd_update(par, x, y, w, h);
width = xres;
height = bitcount / xres;
if (count)
return count;
return err;
arcfb_lcd_update(par, x, y, width, height);
}
static void arcfb_damage_area(struct fb_info *info, u32 x, u32 y,
u32 width, u32 height)
{
struct arcfb_par *par = info->par;
/* update the physical lcd */
arcfb_lcd_update(par, x, y, width, height);
}
FB_GEN_DEFAULT_DEFERRED_SYSMEM_OPS(arcfb,
arcfb_damage_range,
arcfb_damage_area)
static const struct fb_ops arcfb_ops = {
.owner = THIS_MODULE,
.fb_open = arcfb_open,
.fb_read = fb_sys_read,
.fb_write = arcfb_write,
__FB_DEFAULT_DEFERRED_OPS_RDWR(arcfb),
.fb_release = arcfb_release,
.fb_pan_display = arcfb_pan_display,
.fb_fillrect = arcfb_fillrect,
.fb_copyarea = arcfb_copyarea,
.fb_imageblit = arcfb_imageblit,
__FB_DEFAULT_DEFERRED_OPS_DRAW(arcfb),
.fb_ioctl = arcfb_ioctl,
// .fb_mmap reqires deferred I/O
};
static int arcfb_probe(struct platform_device *dev)