Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit 49d7d58

Browse files
drm/ssd130x: Don't allocate buffers on each plane update
The resolutions for these panels are fixed and defined in the Device Tree, so there's no point to allocate the buffers on each plane update and that can just be done once. Let's do the allocation and free on the encoder enable and disable helpers since that's where others initialization and teardown operations are done. Signed-off-by: Javier Martinez Canillas <[email protected]> Reviewed-by: Thomas Zimmermann <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 179a790 commit 49d7d58

File tree

2 files changed

+56
-35
lines changed

2 files changed

+56
-35
lines changed

drivers/gpu/drm/solomon/ssd130x.c

Lines changed: 53 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,31 @@ static inline struct ssd130x_device *drm_to_ssd130x(struct drm_device *drm)
146146
return container_of(drm, struct ssd130x_device, drm);
147147
}
148148

149+
static int ssd130x_buf_alloc(struct ssd130x_device *ssd130x)
150+
{
151+
unsigned int page_height = ssd130x->device_info->page_height;
152+
unsigned int pages = DIV_ROUND_UP(ssd130x->height, page_height);
153+
154+
ssd130x->buffer = kcalloc(DIV_ROUND_UP(ssd130x->width, 8),
155+
ssd130x->height, GFP_KERNEL);
156+
if (!ssd130x->buffer)
157+
return -ENOMEM;
158+
159+
ssd130x->data_array = kcalloc(ssd130x->width, pages, GFP_KERNEL);
160+
if (!ssd130x->data_array) {
161+
kfree(ssd130x->buffer);
162+
return -ENOMEM;
163+
}
164+
165+
return 0;
166+
}
167+
168+
static void ssd130x_buf_free(struct ssd130x_device *ssd130x)
169+
{
170+
kfree(ssd130x->data_array);
171+
kfree(ssd130x->buffer);
172+
}
173+
149174
/*
150175
* Helper to write data (SSD130X_DATA) to the device.
151176
*/
@@ -434,11 +459,12 @@ static int ssd130x_init(struct ssd130x_device *ssd130x)
434459
SSD130X_SET_ADDRESS_MODE_HORIZONTAL);
435460
}
436461

437-
static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
438-
struct drm_rect *rect)
462+
static int ssd130x_update_rect(struct ssd130x_device *ssd130x, struct drm_rect *rect)
439463
{
440464
unsigned int x = rect->x1;
441465
unsigned int y = rect->y1;
466+
u8 *buf = ssd130x->buffer;
467+
u8 *data_array = ssd130x->data_array;
442468
unsigned int width = drm_rect_width(rect);
443469
unsigned int height = drm_rect_height(rect);
444470
unsigned int line_length = DIV_ROUND_UP(width, 8);
@@ -447,14 +473,9 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
447473
struct drm_device *drm = &ssd130x->drm;
448474
u32 array_idx = 0;
449475
int ret, i, j, k;
450-
u8 *data_array = NULL;
451476

452477
drm_WARN_ONCE(drm, y % 8 != 0, "y must be aligned to screen page\n");
453478

454-
data_array = kcalloc(width, pages, GFP_KERNEL);
455-
if (!data_array)
456-
return -ENOMEM;
457-
458479
/*
459480
* The screen is divided in pages, each having a height of 8
460481
* pixels, and the width of the screen. When sending a byte of
@@ -488,11 +509,11 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
488509
/* Set address range for horizontal addressing mode */
489510
ret = ssd130x_set_col_range(ssd130x, ssd130x->col_offset + x, width);
490511
if (ret < 0)
491-
goto out_free;
512+
return ret;
492513

493514
ret = ssd130x_set_page_range(ssd130x, ssd130x->page_offset + y / 8, pages);
494515
if (ret < 0)
495-
goto out_free;
516+
return ret;
496517
}
497518

498519
for (i = 0; i < pages; i++) {
@@ -522,11 +543,11 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
522543
ssd130x->page_offset + i,
523544
ssd130x->col_offset + x);
524545
if (ret < 0)
525-
goto out_free;
546+
return ret;
526547

527548
ret = ssd130x_write_data(ssd130x, data_array, width);
528549
if (ret < 0)
529-
goto out_free;
550+
return ret;
530551

531552
array_idx = 0;
532553
}
@@ -536,29 +557,19 @@ static int ssd130x_update_rect(struct ssd130x_device *ssd130x, u8 *buf,
536557
if (!ssd130x->page_address_mode)
537558
ret = ssd130x_write_data(ssd130x, data_array, width * pages);
538559

539-
out_free:
540-
kfree(data_array);
541560
return ret;
542561
}
543562

544563
static void ssd130x_clear_screen(struct ssd130x_device *ssd130x)
545564
{
546-
u8 *buf = NULL;
547565
struct drm_rect fullscreen = {
548566
.x1 = 0,
549567
.x2 = ssd130x->width,
550568
.y1 = 0,
551569
.y2 = ssd130x->height,
552570
};
553571

554-
buf = kcalloc(DIV_ROUND_UP(ssd130x->width, 8), ssd130x->height,
555-
GFP_KERNEL);
556-
if (!buf)
557-
return;
558-
559-
ssd130x_update_rect(ssd130x, buf, &fullscreen);
560-
561-
kfree(buf);
572+
ssd130x_update_rect(ssd130x, &fullscreen);
562573
}
563574

564575
static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_map *vmap,
@@ -569,30 +580,27 @@ static int ssd130x_fb_blit_rect(struct drm_framebuffer *fb, const struct iosys_m
569580
struct iosys_map dst;
570581
unsigned int dst_pitch;
571582
int ret = 0;
572-
u8 *buf = NULL;
583+
u8 *buf = ssd130x->buffer;
584+
585+
if (!buf)
586+
return 0;
573587

574588
/* Align y to display page boundaries */
575589
rect->y1 = round_down(rect->y1, page_height);
576590
rect->y2 = min_t(unsigned int, round_up(rect->y2, page_height), ssd130x->height);
577591

578592
dst_pitch = DIV_ROUND_UP(drm_rect_width(rect), page_height);
579-
buf = kcalloc(dst_pitch, drm_rect_height(rect), GFP_KERNEL);
580-
if (!buf)
581-
return -ENOMEM;
582593

583594
ret = drm_gem_fb_begin_cpu_access(fb, DMA_FROM_DEVICE);
584595
if (ret)
585-
goto out_free;
596+
return ret;
586597

587598
iosys_map_set_vaddr(&dst, buf);
588599
drm_fb_xrgb8888_to_mono(&dst, &dst_pitch, vmap, fb, rect);
589600

590601
drm_gem_fb_end_cpu_access(fb, DMA_FROM_DEVICE);
591602

592-
ssd130x_update_rect(ssd130x, buf, rect);
593-
594-
out_free:
595-
kfree(buf);
603+
ssd130x_update_rect(ssd130x, rect);
596604

597605
return ret;
598606
}
@@ -701,14 +709,22 @@ static void ssd130x_encoder_helper_atomic_enable(struct drm_encoder *encoder,
701709
return;
702710

703711
ret = ssd130x_init(ssd130x);
704-
if (ret) {
705-
ssd130x_power_off(ssd130x);
706-
return;
707-
}
712+
if (ret)
713+
goto power_off;
714+
715+
ret = ssd130x_buf_alloc(ssd130x);
716+
if (ret)
717+
goto power_off;
708718

709719
ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_ON);
710720

711721
backlight_enable(ssd130x->bl_dev);
722+
723+
return;
724+
725+
power_off:
726+
ssd130x_power_off(ssd130x);
727+
return;
712728
}
713729

714730
static void ssd130x_encoder_helper_atomic_disable(struct drm_encoder *encoder,
@@ -721,6 +737,8 @@ static void ssd130x_encoder_helper_atomic_disable(struct drm_encoder *encoder,
721737

722738
ssd130x_write_cmd(ssd130x, 1, SSD130X_DISPLAY_OFF);
723739

740+
ssd130x_buf_free(ssd130x);
741+
724742
ssd130x_power_off(ssd130x);
725743
}
726744

drivers/gpu/drm/solomon/ssd130x.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,9 @@ struct ssd130x_device {
8989
u8 col_end;
9090
u8 page_start;
9191
u8 page_end;
92+
93+
u8 *buffer;
94+
u8 *data_array;
9295
};
9396

9497
extern const struct ssd130x_deviceinfo ssd130x_variants[];

0 commit comments

Comments
 (0)