@@ -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+
466500static 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+
494558static 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" );
0 commit comments