Skip to content

Commit 3c6c84a

Browse files
committed
fbtft: software screen rotation
Signed-off-by: Vincent-FK <vincent.buso@funkey-project.com>
1 parent 02addd9 commit 3c6c84a

5 files changed

Lines changed: 135 additions & 0 deletions

File tree

arch/arm/boot/dts/sun8i-v3s-funkey.dts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@
179179
txbuflen = <115202>;
180180
spi_async_mode = "true";
181181
rotate = <0>;
182+
rotate_soft = <0>;
182183
fps = <100>;
183184
buswidth = <8>;
184185
reset-gpios = <&pio 1 2 GPIO_ACTIVE_HIGH>; //PB2

drivers/staging/fbtft/fbtft-bus.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,9 @@ int fbtft_write_init_cmd_data_transfers(struct fbtft_par *par)
136136

137137
// printk("%s\n", __func__);
138138

139+
/* Post process */
140+
fbtft_post_process_screen(par, 0, par->info->var.yres - 1);
141+
139142
/* Resetting to 0 for incoming cmd init data write */
140143
if (gpio_is_valid(par->gpio.dc))
141144
gpio_set_value(par->gpio.dc, 0);

drivers/staging/fbtft/fbtft-core.c

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -463,6 +463,40 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line,
463463
}
464464
}
465465

466+
/* Soft Matrix Rotation - Works only on 2D square matrices */
467+
void fbtft_rotate_soft(u16 *mat, int size, int rotation)
468+
{
469+
int i, j;
470+
u16 temp;
471+
int N = size;
472+
473+
#define AT(i, j) ((i) * N + (j))
474+
475+
if (rotation == 90) {
476+
/* Rotate screen 90° Clockwise */
477+
for (i = 0; i < N / 2; i++) {
478+
for (j = i; j < N - i - 1; j++) {
479+
temp = mat[AT(i, j)];
480+
mat[AT(i, j)] = mat[AT(N - 1 - j, i)];
481+
mat[AT(N - 1 - j, i)] = mat[AT(N - 1 - i, N - 1 - j)];
482+
mat[AT(N - 1 - i, N - 1 - j)] = mat[AT(j, N - 1 - i)];
483+
mat[AT(j, N - 1 - i)] = temp;
484+
}
485+
}
486+
} else if (rotation == 270) {
487+
/* Rotate screen 270° Clockwise */
488+
for (i = 0; i < N / 2; i++) {
489+
for (j = i; j < N - i - 1; j++) {
490+
temp = mat[AT(i, j)];
491+
mat[AT(i, j)] = mat[AT(j, N - 1 - i)];
492+
mat[AT(j, N-1-i)] = mat[AT(N - 1 - i, N - 1 - j)];
493+
mat[AT(N - 1 - i, N - 1 - j)] = mat[AT(N - 1 - j, i)];
494+
mat[AT(N - 1 - j, i)] = temp;
495+
}
496+
}
497+
}
498+
}
499+
466500
static void fbtft_mkdirty(struct fb_info *info, int y, int height)
467501
{
468502
struct fbtft_par *par = info->par;
@@ -491,6 +525,36 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
491525
schedule_delayed_work(&info->deferred_work, fbdefio->delay);
492526
}
493527

528+
void fbtft_post_process_screen(struct fbtft_par *par, unsigned int dirty_lines_start, unsigned int dirty_lines_end)
529+
{
530+
int x_notif = 0;
531+
int y_notif = 0;
532+
bool screen_post_process = false;
533+
534+
/* Reset default write buffer */
535+
par->vmem_ptr = par->info->screen_buffer;
536+
537+
/* If soft rotation, mark whole screen to update to avoid data non rotated */
538+
if (par->pdata->rotate_soft) {
539+
dirty_lines_start = 0;
540+
dirty_lines_end = par->info->var.yres - 1;
541+
par->vmem_ptr = par->vmem_post_process;
542+
screen_post_process = true;
543+
}
544+
545+
/* Post process */
546+
if (screen_post_process) {
547+
/* Copy buffer */
548+
memcpy(par->vmem_post_process + dirty_lines_start * par->info->fix.line_length,
549+
par->info->screen_buffer + dirty_lines_start * par->info->fix.line_length,
550+
(dirty_lines_end-dirty_lines_start+1) * par->info->fix.line_length);
551+
552+
/* Soft rotation */
553+
if (par->pdata->rotate_soft)
554+
fbtft_rotate_soft((u16*)par->vmem_post_process, par->info->var.yres, par->pdata->rotate_soft);
555+
}
556+
}
557+
494558
static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
495559
{
496560
struct fbtft_par *par = info->par;
@@ -525,6 +589,8 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
525589
dirty_lines_end = y_high;
526590
}
527591

592+
fbtft_post_process_screen(par, dirty_lines_start, dirty_lines_end);
593+
528594
/* Screen upgrade */
529595
par->fbtftops.update_display(par, dirty_lines_start, dirty_lines_end);
530596
}
@@ -1475,6 +1541,7 @@ static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev)
14751541
pdata->display.bpp = fbtft_of_value(node, "bpp");
14761542
pdata->display.debug = fbtft_of_value(node, "debug");
14771543
pdata->rotate = fbtft_of_value(node, "rotate");
1544+
pdata->rotate_soft = fbtft_of_value(node, "rotate_soft");
14781545
pdata->bgr = of_property_read_bool(node, "bgr");
14791546
pdata->spi_async_mode = of_property_read_bool(node, "spi_async_mode");
14801547
pdata->fps = fbtft_of_value(node, "fps");

drivers/staging/fbtft/fbtft-sysfs.c

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,64 @@ static struct device_attribute gamma_device_attrs[] = {
145145
__ATTR(gamma, 0660, show_gamma_curve, store_gamma_curve),
146146
};
147147

148+
void fbtft_expand_rotate_soft_value(unsigned long *rotate_soft)
149+
{
150+
switch (*rotate_soft) {
151+
case 0:
152+
case 90:
153+
case 180:
154+
case 270:
155+
break;
156+
case 1:
157+
*rotate_soft = 90;
158+
break;
159+
case 2:
160+
*rotate_soft = 180;
161+
break;
162+
case 3:
163+
*rotate_soft = 270;
164+
default:
165+
printk("Wrong Rotate soft value: %lu\n", *rotate_soft);
166+
*rotate_soft = 0;
167+
break;
168+
}
169+
}
170+
171+
static ssize_t store_rotate_soft(struct device *device,
172+
struct device_attribute *attr,
173+
const char *buf, size_t count)
174+
{
175+
struct fb_info *fb_info = dev_get_drvdata(device);
176+
struct fbtft_par *par = fb_info->par;
177+
int ret;
178+
179+
ret = kstrtoul(buf, 10, &par->pdata->rotate_soft);
180+
if (ret)
181+
return ret;
182+
fbtft_expand_rotate_soft_value(&par->pdata->rotate_soft);
183+
184+
/* Schedule deferred_io to update display (no-op if already on queue)*/
185+
if (!par->spi_async_mode){
186+
par->dirty_lines_start = 0;
187+
par->dirty_lines_end = par->info->var.yres - 1;
188+
schedule_delayed_work(&par->info->deferred_work, par->info->fbdefio->delay);
189+
}
190+
191+
return count;
192+
}
193+
194+
static ssize_t show_rotate_soft(struct device *device,
195+
struct device_attribute *attr, char *buf)
196+
{
197+
struct fb_info *fb_info = dev_get_drvdata(device);
198+
struct fbtft_par *par = fb_info->par;
199+
200+
return snprintf(buf, PAGE_SIZE, "%lu\n", par->pdata->rotate_soft);
201+
}
202+
203+
static struct device_attribute rotate_soft_device_attr =
204+
__ATTR(rotate_soft, 0660, show_rotate_soft, store_rotate_soft);
205+
148206
void fbtft_expand_debug_value(unsigned long *debug)
149207
{
150208
switch (*debug & 0x7) {
@@ -206,13 +264,15 @@ static struct device_attribute debug_device_attr =
206264
void fbtft_sysfs_init(struct fbtft_par *par)
207265
{
208266
device_create_file(par->info->dev, &debug_device_attr);
267+
device_create_file(par->info->dev, &rotate_soft_device_attr);
209268
if (par->gamma.curves && par->fbtftops.set_gamma)
210269
device_create_file(par->info->dev, &gamma_device_attrs[0]);
211270
}
212271

213272
void fbtft_sysfs_exit(struct fbtft_par *par)
214273
{
215274
device_remove_file(par->info->dev, &debug_device_attr);
275+
device_remove_file(par->info->dev, &rotate_soft_device_attr);
216276
if (par->gamma.curves && par->fbtftops.set_gamma)
217277
device_remove_file(par->info->dev, &gamma_device_attrs[0]);
218278
}

drivers/staging/fbtft/fbtft.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,7 @@ struct fbtft_platform_data {
151151
struct fbtft_display display;
152152
const struct fbtft_gpio *gpios;
153153
unsigned int rotate;
154+
unsigned long rotate_soft;
154155
bool bgr;
155156
bool spi_async_mode;
156157
unsigned int fps;
@@ -273,6 +274,9 @@ int fbtft_init_display(struct fbtft_par *par);
273274
int fbtft_probe_common(struct fbtft_display *display, struct spi_device *sdev,
274275
struct platform_device *pdev);
275276
int fbtft_remove_common(struct device *dev, struct fb_info *info);
277+
void fbtft_rotate_soft(u16 *mat, int size, int rotation);
278+
void fbtft_post_process_screen(struct fbtft_par *par,
279+
unsigned int dirty_lines_start, unsigned int dirty_lines_end);
276280

277281
/* fbtft-io.c */
278282
int fbtft_write_spi(struct fbtft_par *par, void *buf, size_t len);

0 commit comments

Comments
 (0)