3737#include <video/mipi_display.h>
3838#include <linux/hrtimer.h>
3939#include <linux/list.h>
40+ #include <linux/interrupt.h>
4041
4142/* to support deferred IO */
4243#include <linux/rmap.h>
@@ -425,7 +426,11 @@ static void fbtft_update_display(struct fbtft_par *par, unsigned int start_line,
425426
426427 fbtft_par_dbg (DEBUG_UPDATE_DISPLAY , par , "%s(start_line=%u, end_line=%u)\n" ,
427428 __func__ , start_line , end_line );
428- par -> fbtftops .set_addr_win (par , 0 , start_line ,
429+ if (par -> pdata -> rotate == 90 )
430+ par -> fbtftops .set_addr_win (par , 80 , start_line ,
431+ 320 - 1 , end_line );
432+ else
433+ par -> fbtftops .set_addr_win (par , 0 , start_line ,
429434 par -> info -> var .xres - 1 , end_line );
430435 }
431436
@@ -510,7 +515,7 @@ static void fbtft_mkdirty(struct fb_info *info, int y, int height)
510515 struct fbtft_par * par = info -> par ;
511516 struct fb_deferred_io * fbdefio = info -> fbdefio ;
512517
513- /* This disables fbtft's defered io, useful in spi_asyn mode or
518+ /* This disables fbtft's defered io, useful in spi_async mode or
514519 if any other driver handles screens updates instead of fbtft */
515520 if (par -> spi_async_mode )
516521 return ;
@@ -540,9 +545,12 @@ void fbtft_post_process_screen(struct fbtft_par *par)
540545 bool screen_post_process = false;
541546
542547 /* bypass */
548+ //#define FORCE_POSTPROCESS
549+ #ifdef FORCE_POSTPROCESS
543550 screen_post_process = true;
544551 par -> write_line_start = 0 ;
545552 par -> write_line_end = par -> info -> var .yres - 1 ;
553+ #endif //FORCE_POSTPROCESS
546554
547555 /* If soft rotation, mark whole screen to update to avoid data
548556 non rotated */
@@ -573,6 +581,22 @@ void fbtft_post_process_screen(struct fbtft_par *par)
573581 par -> vmem_ptr = par -> vmem_post_process ;
574582
575583 /* Copy buffer */
584+
585+ /* This should be handled using a double buffer (or
586+ triple depending on game fps vs screen fps) pointed
587+ by par->info->screen_buffer. The buffer pointed
588+ (the one being written) should change using the
589+ FBIOPAN_DISPLAY ioctl called by SDL_Flip() (in
590+ FB_FlipHWSurface). This is a dirty but very
591+ efficient alternative for now: we make a quick
592+ memcpy of the screen_buffer in another one. It goes
593+ so fast that the "applicative" tearing that could
594+ happen if this function were to launch in the
595+ middle of a user space SDL_BlitSurface(sw_surface,
596+ NULL, hw_surface, NULL) call is so unbelievably
597+ rare that completey unnoticeable and it takes up so
598+ little CPU that really, it's worth the compromise
599+ for now */
576600 memcpy (par -> vmem_post_process + par -> write_line_start * par -> info -> fix .line_length ,
577601 par -> info -> screen_buffer + par -> write_line_start * par -> info -> fix .line_length ,
578602 (par -> write_line_end - par -> write_line_start + 1 ) * par -> info -> fix .line_length );
@@ -598,7 +622,8 @@ void fbtft_post_process_screen(struct fbtft_par *par)
598622 /* Soft rotation */
599623 if (par -> pdata -> rotate_soft )
600624 fbtft_rotate_soft ((u16 * )par -> vmem_post_process , par -> info -> var .yres , par -> pdata -> rotate_soft );
601- }
625+ } else
626+ par -> vmem_ptr = par -> info -> screen_buffer ;
602627}
603628
604629static void fbtft_deferred_io (struct fb_info * info , struct list_head * pagelist )
@@ -666,26 +691,14 @@ static void fbtft_deferred_io(struct fb_info *info, struct list_head *pagelist)
666691 }
667692
668693 /* Copy buffer */
669- if (dirty_lines_start != 0 || dirty_lines_end != par -> info -> var .yres - 1 )
670- printk ("dirty_lines_start = %d, dirty_lines_end = %d\n" , dirty_lines_start , dirty_lines_end );
671694 par -> write_line_start = dirty_lines_start ;
672695 par -> write_line_end = dirty_lines_end ;
673- memcpy (par -> vmem_post_process + dirty_lines_start * par -> info -> fix .line_length ,
674- par -> info -> screen_buffer + dirty_lines_start * par -> info -> fix .line_length ,
675- (dirty_lines_end - dirty_lines_start + 1 ) * par -> info -> fix .line_length );
676- par -> vmem_ptr = par -> vmem_post_process ;
677696
678- /* Exit in SPI async mode, otherwise update screen now */
679- if (par -> spi_async_mode ) {
680- fbtft_start_new_screen_transfer_async (par );
681- return ;
682- } else {
683- /* Post process screen for doufle buf cpy, notifs, rotation soft... */
684- fbtft_post_process_screen (par );
697+ /* Post process screen for doufle buf cpy, notifs, rotation soft... */
698+ fbtft_post_process_screen (par );
685699
686- /* Screen upgrade */
687- par -> fbtftops .update_display (par , dirty_lines_start , dirty_lines_end );
688- }
700+ /* Screen upgrade */
701+ par -> fbtftops .update_display (par , dirty_lines_start , dirty_lines_end );
689702}
690703
691704static void fbtft_fb_fillrect (struct fb_info * info ,
@@ -1150,11 +1163,13 @@ struct fb_info *fbtft_framebuffer_alloc(struct fbtft_display *display,
11501163 par -> vmem_post_process = vmem_post_process ;
11511164 par -> vmem_ptr = par -> info -> screen_buffer ;
11521165 par -> pdata = pdata ;
1166+ pdata -> par = par ;
11531167 par -> debug = display -> debug ;
11541168 par -> buf = buf ;
11551169 spin_lock_init (& par -> dirty_lock );
11561170 par -> bgr = pdata -> bgr ;
11571171 par -> spi_async_mode = pdata -> spi_async_mode ;
1172+ par -> ready_for_spi_async = false;
11581173 par -> interlacing = pdata -> interlacing ;
11591174 par -> startbyte = pdata -> startbyte ;
11601175 par -> init_sequence = init_sequence ;
@@ -1615,10 +1630,40 @@ static u32 fbtft_of_value(struct device_node *node, const char *propname)
16151630 return val ;
16161631}
16171632
1633+
1634+ static irqreturn_t irq_TE_handler (int irq_no , void * dev_id )
1635+ {
1636+ struct fbtft_platform_data * pdata = (struct fbtft_platform_data * ) dev_id ;
1637+
1638+ //#define DEBUG_TE_IRQ_COUNT
1639+ #ifdef DEBUG_TE_IRQ_COUNT
1640+ static ktime_t prev_ts = 0 ;
1641+ static int te_count = 0 ;
1642+ static int nb_sec = 5 ;
1643+ te_count ++ ;
1644+
1645+ ktime_t ts_now = ktime_get ();
1646+ if (ktime_us_delta (ts_now , prev_ts ) > nb_sec * 1000000 ){
1647+ prev_ts = ts_now ;
1648+ printk ("TE irq: %d times/sec\n" , te_count /nb_sec );
1649+ te_count = 0 ;
1650+ }
1651+ #endif //DEBUG_TE_IRQ_COUNT
1652+
1653+ fbtft_start_new_screen_transfer_async (pdata -> par );
1654+
1655+ return IRQ_HANDLED ;
1656+ }
1657+
1658+
1659+
16181660static struct fbtft_platform_data * fbtft_probe_dt (struct device * dev )
16191661{
16201662 struct device_node * node = dev -> of_node ;
16211663 struct fbtft_platform_data * pdata ;
1664+ int gpio , irq_id , err ;
1665+ enum of_gpio_flags of_flags ;
1666+ char * te_irq_name ;
16221667
16231668 if (!node ) {
16241669 dev_err (dev , "Missing platform data or DT\n" );
@@ -1652,6 +1697,37 @@ static struct fbtft_platform_data *fbtft_probe_dt(struct device *dev)
16521697 pdata -> display .fbtftops .init_display = fbtft_init_display_dt ;
16531698 pdata -> display .fbtftops .request_gpios = fbtft_request_gpios_dt ;
16541699
1700+ /* TE signal for Vsync */
1701+ pdata -> te_irq = false;
1702+ te_irq_name = "te-irq" ;
1703+ if (of_find_property (node , te_irq_name , NULL )) {
1704+ gpio = of_get_named_gpio_flags (node , te_irq_name , 0 , & of_flags );
1705+ if (gpio == - ENOENT || gpio == - EPROBE_DEFER || gpio < 0 ) {
1706+ dev_err (dev ,
1707+ "failed to get '%s' from DT\n" , te_irq_name );
1708+ }
1709+ else {
1710+ pr_info ("%s: '%s' = GPIO%d\n" , __func__ , te_irq_name , gpio );
1711+
1712+ irq_id = gpio_to_irq (gpio );
1713+ if (irq_id < 0 ) {
1714+ dev_err (dev ,"%s - Unable to request IRQ: %d\n" , __func__ , irq_id );
1715+ }
1716+ else {
1717+ pr_info ("TE GPIO%d, IRQ id = %d\n" , gpio , irq_id );
1718+
1719+ err = request_irq (irq_id , irq_TE_handler , IRQF_SHARED | IRQF_TRIGGER_RISING ,
1720+ "TE" , pdata );
1721+ if (err < 0 ) {
1722+ dev_err (dev ,"ERROR initializing TE signal irq\n" );
1723+ }
1724+ else {
1725+ pdata -> te_irq = true;
1726+ }
1727+ }
1728+ }
1729+ }
1730+
16551731 return pdata ;
16561732}
16571733#else
@@ -1783,7 +1859,10 @@ int fbtft_probe_common(struct fbtft_display *display,
17831859 /* Start constant Display update using spi async */
17841860 par -> write_line_start = 0 ;
17851861 par -> write_line_end = par -> info -> var .yres - 1 ;
1786- fbtft_start_new_screen_transfer_async (par );
1862+ if (par -> pdata -> te_irq )
1863+ par -> ready_for_spi_async = true;
1864+ else
1865+ fbtft_start_new_screen_transfer_async (par );
17871866 }
17881867 return 0 ;
17891868
0 commit comments