]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
staging: fbtft: Optimize partial write()
authorNam Cao <namcao@linutronix.de>
Mon, 16 Feb 2026 00:57:30 +0000 (07:57 +0700)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 23 Feb 2026 14:08:54 +0000 (15:08 +0100)
When user write() only to part of the screen, the driver still updates the
entire screen. That wastes CPU cycles.

Optimize by updating only the changed lines.

Also remove a "special case" in fbtft_mkdirty() as its only user is removed
in this patch.

Tested with an Adafruit ILI9340 (drivers/staging/fbtft/fb_ili9340.c).
Improvement is measured by a pair of trace_printk() at the beginning of
fb_write() and at the end of fbtft_deferred_io().

Update type         Before     After
====================================
full screen         196ms      200ms
half screen         200ms      124ms
quarter screen      193ms       81ms
one pixel           199ms       43ms

It is interesting to note that if the deferred IO's delay time (40ms) is
subtracted, then the time amount scales linearly with the write size.

Reviewed-by: Andy Shevchenko <andriy.shevchenko@intel.com>
Signed-off-by: Nam Cao <namcao@linutronix.de>
Link: https://patch.msgid.link/20260216005730.4535-1-namcao@linutronix.de
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/staging/fbtft/fbtft-core.c

index f427c0914907ef89b8036ace7ba76e0e92196e2e..3da42c8ca6e331e51327f9977c97a24787c818d3 100644 (file)
@@ -300,12 +300,6 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
        struct fbtft_par *par = info->par;
        struct fb_deferred_io *fbdefio = info->fbdefio;
 
-       /* special case, needed ? */
-       if (y == -1) {
-               y = 0;
-               height = info->var.yres;
-       }
-
        /* Mark display lines/area as dirty */
        spin_lock(&par->dirty_lock);
        if (y < par->dirty_lines_start)
@@ -413,9 +407,12 @@ static int fbtft_fb_blank(int blank, struct fb_info *info)
 static void fbtft_ops_damage_range(struct fb_info *info, off_t off, size_t len)
 {
        struct fbtft_par *par = info->par;
+       u32 start, end;
+
+       start = off / info->fix.line_length;
+       end = (off + len - 1) / info->fix.line_length;
 
-       /* TODO: only mark changed area update all for now */
-       par->fbtftops.mkdirty(info, -1, 0);
+       par->fbtftops.mkdirty(info, start, end - start + 1);
 }
 
 static void fbtft_ops_damage_area(struct fb_info *info, u32 x, u32 y, u32 width, u32 height)