From: Geert Uytterhoeven <geert@linux-m68k.org> To: Sam Ravnborg <sam@ravnborg.org>, Maxime Ripard <mripard@kernel.org> Cc: linux-fbdev@vger.kernel.org, dri-devel@lists.freedesktop.org, linux-kernel@vger.kernel.org, Geert Uytterhoeven <geert@linux-m68k.org> Subject: [PATCH v2 4/5] video: fbdev: ssd1307fb: Optimize screen updates Date: Tue, 27 Jul 2021 15:47:29 +0200 [thread overview] Message-ID: <20210727134730.3765898-5-geert@linux-m68k.org> (raw) In-Reply-To: <20210727134730.3765898-1-geert@linux-m68k.org> Currently, each screen update triggers an I2C transfer of all screen data, up to 1 KiB of data for a 128x64 display, which takes at least 20 ms in Fast mode. Reduce the amount of transferred data by only updating the rectangle that changed. Remove the calls to ssd1307fb_set_col_range() and ssd1307fb_set_page_range() during initialization, as ssd1307fb_update_rect() now takes care of that. Note that for now the optimized operation is only used for fillrect, copyarea, and imageblit, which are used by fbcon. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- v2: - Reorder operands in DIV_ROUND_UP() to improve readability, - Rebase. --- drivers/video/fbdev/ssd1307fb.c | 50 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 86eb9c99a783f0da..9aed5ee0094f2d95 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -186,16 +186,18 @@ static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start, return ssd1307fb_write_cmd(par->client, page_end); } -static int ssd1307fb_update_display(struct ssd1307fb_par *par) +static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x, + unsigned int y, unsigned int width, + unsigned int height) { struct ssd1307fb_array *array; u8 *vmem = par->info->screen_buffer; unsigned int line_length = par->info->fix.line_length; - unsigned int pages = DIV_ROUND_UP(par->height, 8); + unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8); u32 array_idx = 0; int ret, i, j, k; - array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA); + array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA); if (!array) return -ENOMEM; @@ -228,13 +230,21 @@ static int ssd1307fb_update_display(struct ssd1307fb_par *par) * (5) A4 B4 C4 D4 E4 F4 G4 H4 */ - for (i = 0; i < pages; i++) { + ret = ssd1307fb_set_col_range(par, par->col_offset + x, width); + if (ret < 0) + goto out_free; + + ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages); + if (ret < 0) + goto out_free; + + for (i = y / 8; i < y / 8 + pages; i++) { int m = 8; /* Last page may be partial */ - if (i + 1 == pages && par->height % 8) + if (8 * (i + 1) > par->height) m = par->height % 8; - for (j = 0; j < par->width; j++) { + for (j = x; j < x + width; j++) { u8 data = 0; for (k = 0; k < m; k++) { @@ -247,11 +257,17 @@ static int ssd1307fb_update_display(struct ssd1307fb_par *par) } } - ret = ssd1307fb_write_array(par->client, array, par->width * pages); + ret = ssd1307fb_write_array(par->client, array, width * pages); + +out_free: kfree(array); return ret; } +static int ssd1307fb_update_display(struct ssd1307fb_par *par) +{ + return ssd1307fb_update_rect(par, 0, 0, par->width, par->height); +} static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) @@ -301,21 +317,24 @@ static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *r { struct ssd1307fb_par *par = info->par; sys_fillrect(info, rect); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, rect->dx, rect->dy, rect->width, + rect->height); } static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { struct ssd1307fb_par *par = info->par; sys_copyarea(info, area); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, area->dx, area->dy, area->width, + area->height); } static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image) { struct ssd1307fb_par *par = info->par; sys_imageblit(info, image); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, image->dx, image->dy, image->width, + image->height); } static const struct fb_ops ssd1307fb_ops = { @@ -495,17 +514,6 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) if (ret < 0) return ret; - /* Set column range */ - ret = ssd1307fb_set_col_range(par, par->col_offset, par->width); - if (ret < 0) - return ret; - - /* Set page range */ - ret = ssd1307fb_set_page_range(par, par->page_offset, - DIV_ROUND_UP(par->height, 8)); - if (ret < 0) - return ret; - /* Clear the screen */ ret = ssd1307fb_update_display(par); if (ret < 0) -- 2.25.1
WARNING: multiple messages have this Message-ID (diff)
From: Geert Uytterhoeven <geert@linux-m68k.org> To: Sam Ravnborg <sam@ravnborg.org>, Maxime Ripard <mripard@kernel.org> Cc: linux-fbdev@vger.kernel.org, Geert Uytterhoeven <geert@linux-m68k.org>, linux-kernel@vger.kernel.org, dri-devel@lists.freedesktop.org Subject: [PATCH v2 4/5] video: fbdev: ssd1307fb: Optimize screen updates Date: Tue, 27 Jul 2021 15:47:29 +0200 [thread overview] Message-ID: <20210727134730.3765898-5-geert@linux-m68k.org> (raw) In-Reply-To: <20210727134730.3765898-1-geert@linux-m68k.org> Currently, each screen update triggers an I2C transfer of all screen data, up to 1 KiB of data for a 128x64 display, which takes at least 20 ms in Fast mode. Reduce the amount of transferred data by only updating the rectangle that changed. Remove the calls to ssd1307fb_set_col_range() and ssd1307fb_set_page_range() during initialization, as ssd1307fb_update_rect() now takes care of that. Note that for now the optimized operation is only used for fillrect, copyarea, and imageblit, which are used by fbcon. Signed-off-by: Geert Uytterhoeven <geert@linux-m68k.org> --- v2: - Reorder operands in DIV_ROUND_UP() to improve readability, - Rebase. --- drivers/video/fbdev/ssd1307fb.c | 50 +++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 21 deletions(-) diff --git a/drivers/video/fbdev/ssd1307fb.c b/drivers/video/fbdev/ssd1307fb.c index 86eb9c99a783f0da..9aed5ee0094f2d95 100644 --- a/drivers/video/fbdev/ssd1307fb.c +++ b/drivers/video/fbdev/ssd1307fb.c @@ -186,16 +186,18 @@ static int ssd1307fb_set_page_range(struct ssd1307fb_par *par, u8 page_start, return ssd1307fb_write_cmd(par->client, page_end); } -static int ssd1307fb_update_display(struct ssd1307fb_par *par) +static int ssd1307fb_update_rect(struct ssd1307fb_par *par, unsigned int x, + unsigned int y, unsigned int width, + unsigned int height) { struct ssd1307fb_array *array; u8 *vmem = par->info->screen_buffer; unsigned int line_length = par->info->fix.line_length; - unsigned int pages = DIV_ROUND_UP(par->height, 8); + unsigned int pages = DIV_ROUND_UP(y % 8 + height, 8); u32 array_idx = 0; int ret, i, j, k; - array = ssd1307fb_alloc_array(par->width * pages, SSD1307FB_DATA); + array = ssd1307fb_alloc_array(width * pages, SSD1307FB_DATA); if (!array) return -ENOMEM; @@ -228,13 +230,21 @@ static int ssd1307fb_update_display(struct ssd1307fb_par *par) * (5) A4 B4 C4 D4 E4 F4 G4 H4 */ - for (i = 0; i < pages; i++) { + ret = ssd1307fb_set_col_range(par, par->col_offset + x, width); + if (ret < 0) + goto out_free; + + ret = ssd1307fb_set_page_range(par, par->page_offset + y / 8, pages); + if (ret < 0) + goto out_free; + + for (i = y / 8; i < y / 8 + pages; i++) { int m = 8; /* Last page may be partial */ - if (i + 1 == pages && par->height % 8) + if (8 * (i + 1) > par->height) m = par->height % 8; - for (j = 0; j < par->width; j++) { + for (j = x; j < x + width; j++) { u8 data = 0; for (k = 0; k < m; k++) { @@ -247,11 +257,17 @@ static int ssd1307fb_update_display(struct ssd1307fb_par *par) } } - ret = ssd1307fb_write_array(par->client, array, par->width * pages); + ret = ssd1307fb_write_array(par->client, array, width * pages); + +out_free: kfree(array); return ret; } +static int ssd1307fb_update_display(struct ssd1307fb_par *par) +{ + return ssd1307fb_update_rect(par, 0, 0, par->width, par->height); +} static ssize_t ssd1307fb_write(struct fb_info *info, const char __user *buf, size_t count, loff_t *ppos) @@ -301,21 +317,24 @@ static void ssd1307fb_fillrect(struct fb_info *info, const struct fb_fillrect *r { struct ssd1307fb_par *par = info->par; sys_fillrect(info, rect); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, rect->dx, rect->dy, rect->width, + rect->height); } static void ssd1307fb_copyarea(struct fb_info *info, const struct fb_copyarea *area) { struct ssd1307fb_par *par = info->par; sys_copyarea(info, area); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, area->dx, area->dy, area->width, + area->height); } static void ssd1307fb_imageblit(struct fb_info *info, const struct fb_image *image) { struct ssd1307fb_par *par = info->par; sys_imageblit(info, image); - ssd1307fb_update_display(par); + ssd1307fb_update_rect(par, image->dx, image->dy, image->width, + image->height); } static const struct fb_ops ssd1307fb_ops = { @@ -495,17 +514,6 @@ static int ssd1307fb_init(struct ssd1307fb_par *par) if (ret < 0) return ret; - /* Set column range */ - ret = ssd1307fb_set_col_range(par, par->col_offset, par->width); - if (ret < 0) - return ret; - - /* Set page range */ - ret = ssd1307fb_set_page_range(par, par->page_offset, - DIV_ROUND_UP(par->height, 8)); - if (ret < 0) - return ret; - /* Clear the screen */ ret = ssd1307fb_update_display(par); if (ret < 0) -- 2.25.1
next prev parent reply other threads:[~2021-07-27 13:49 UTC|newest] Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top 2021-07-27 13:47 [PATCH v2 0/5] video: fbdev: ssd1307fb: Optimizations and improvements Geert Uytterhoeven 2021-07-27 13:47 ` Geert Uytterhoeven 2021-07-27 13:47 ` [PATCH v2 1/5] video: fbdev: ssd1307fb: Propagate errors via ssd1307fb_update_display() Geert Uytterhoeven 2021-07-27 13:47 ` Geert Uytterhoeven 2021-07-27 13:47 ` [PATCH v2 2/5] video: fbdev: ssd1307fb: Simplify ssd1307fb_update_display() Geert Uytterhoeven 2021-07-27 13:47 ` Geert Uytterhoeven 2021-07-27 13:47 ` [PATCH v2 3/5] video: fbdev: ssd1307fb: Extract ssd1307fb_set_{col,page}_range() Geert Uytterhoeven 2021-07-27 13:47 ` [PATCH v2 3/5] video: fbdev: ssd1307fb: Extract ssd1307fb_set_{col, page}_range() Geert Uytterhoeven 2021-07-27 13:47 ` Geert Uytterhoeven [this message] 2021-07-27 13:47 ` [PATCH v2 4/5] video: fbdev: ssd1307fb: Optimize screen updates Geert Uytterhoeven 2021-07-27 13:47 ` [PATCH v2 5/5] video: fbdev: ssd1307fb: Cache address ranges Geert Uytterhoeven 2021-07-27 13:47 ` Geert Uytterhoeven 2021-07-27 15:26 ` [PATCH v2 0/5] video: fbdev: ssd1307fb: Optimizations and improvements Sam Ravnborg
Reply instructions: You may reply publicly to this message via plain-text email using any one of the following methods: * Save the following mbox file, import it into your mail client, and reply-to-all from there: mbox Avoid top-posting and favor interleaved quoting: https://en.wikipedia.org/wiki/Posting_style#Interleaved_style * Reply using the --to, --cc, and --in-reply-to switches of git-send-email(1): git send-email \ --in-reply-to=20210727134730.3765898-5-geert@linux-m68k.org \ --to=geert@linux-m68k.org \ --cc=dri-devel@lists.freedesktop.org \ --cc=linux-fbdev@vger.kernel.org \ --cc=linux-kernel@vger.kernel.org \ --cc=mripard@kernel.org \ --cc=sam@ravnborg.org \ /path/to/YOUR_REPLY https://kernel.org/pub/software/scm/git/docs/git-send-email.html * If your mail client supports setting the In-Reply-To header via mailto: links, try the mailto: linkBe sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes, see mirroring instructions on how to clone and mirror all data and code used by this external index.