Guest User

454_x1000_LCD_DMA_Fix.diff

a guest
Sep 1st, 2024
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 7.22 KB | Source Code | 0 0
  1. x1000: LCD DMA fix 'revisited' for cd91c238de and newer
  2.  
  3. And in long Experiments and Player usages the (seldom)
  4. Display hang when Wake from Sleep could be fixed by this
  5.  
  6. Don't complete deactivate the Controller in Sleep,
  7. only controlled Stop the LCD_DMA_TX
  8.  
  9. Testet on fiiom3ks / Hifi Walkers 1.5, 1.8 and Surfans F20 2.7, 3.2
  10. in its original incarnation since 16 Jul 2024, and this anti-crufted Ver. since 7 Aug 2024
  11. (And no x1000 Display Hang since 16 Jul...)
  12.  
  13. NEW: Move the complete Timing count Loop & case Logic to the
  14.     LCD Timing Debug x1000_LCD_DMA_Debug3.diff where it belongs.
  15.  
  16.     Leave only the DMA Start/Stop differences of Sleep/Wake in
  17.     Anti-Cruft lcd_active / lcd_on
  18.     (And leave the Bootloader Logic largely unmodified)
  19.  
  20. Credit ZappBranigan2972 on forums / F. Jacobsen on the Theme Site
  21.  
  22. ---
  23.  
  24. --- a/firmware/target/mips/ingenic_x1000/lcd-x1000.c.orig   2024-07-10 09:00:17.175641885 +0200
  25. +++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.c    2024-07-10 09:06:46.482963434 +0200
  26. @@ -69,6 +69,7 @@
  27. /* True if we're in sleep mode */
  28.  static bool lcd_sleeping = false;
  29.  #endif
  30. +static bool lcd_on = false;
  31.  
  32.  /* Check if running with interrupts disabled (eg: panic screen) */
  33.  #define lcd_panic_mode \
  34. @@ -125,7 +126,7 @@
  35.  
  36.      /* DMA settings */
  37.      jz_writef(LCD_CTRL, ENABLE(0), BURST_V(64WORD),
  38. -              EOFM(1), SOFM(0), IFUM(0), QDM(0),
  39. +              EOFM(0), SOFM(0), IFUM(0), QDM(0),
  40.                BEDN(cfg->big_endian), PEDN(0));
  41.      jz_write(LCD_DAH, LCD_WIDTH);
  42.      jz_write(LCD_DAV, LCD_HEIGHT);
  43. @@ -274,7 +275,14 @@
  44.  # define lcd_fbcopy_dma_partial lcd_fbcopy_dma_partial1
  45.  #endif
  46.  
  47. -static void lcd_dma_start(void)
  48. +typedef enum {
  49. +    MODE_INIT,
  50. +    MODE_SLEEP
  51. +} DMA_Mode;
  52. +
  53. +/* lcd_dma_start/stop It doesn't follow the 'chinese' Datasheet, but no Display *
  54. + * Hang on my x1000 Devices since the first Test from 16Jul24 with this         */
  55. +static void lcd_dma_start(DMA_Mode mode)
  56.  {
  57.      /* Set format conversion bit, seems necessary for DMA mode.
  58.       * Must set DTIMES here if we use an 8-bit bus type. */
  59. @@ -286,44 +294,49 @@
  60.                TE_INV(lcd_tgt_config.te_polarity ? 0 : 1),
  61.                NOT_USE_TE(lcd_tgt_config.te_enable ? 0 : 1));
  62.  
  63. +    if (mode == MODE_INIT) { // INIT: Enable DMA Controller only once on Startup
  64. +        jz_write(LCD_DA, PHYSADDR(&lcd_dma_desc[0]));
  65. +        jz_writef(LCD_CTRL, ENABLE(1));
  66. +    }
  67. +    jz_write(LCD_STATE, 0);
  68.      /* Begin DMA transfer. Need to start a dummy frame or else we will
  69.       * not be able to pass lcd_wait_frame() at the first lcd_update(). */
  70. -    jz_write(LCD_STATE, 0);
  71. -    jz_write(LCD_DA, PHYSADDR(&lcd_dma_desc[0]));
  72.      jz_writef(LCD_MCTRL, DMA_MODE(1), DMA_START(1), DMA_TX_EN(1));
  73. -    jz_writef(LCD_CTRL, ENABLE(1));
  74. +
  75. +    lcd_on = true;
  76.  }
  77.  
  78. -static bool lcd_wait_frame(void)
  79. +static void lcd_wait_frame(void)
  80.  {
  81. -    /* Bail out if DMA is not enabled */
  82. -    int irq = disable_irq_save();
  83. -    int bit = jz_readf(LCD_CTRL, ENABLE);
  84. -    restore_irq(irq);
  85. -    if(!bit)
  86. -        return false;
  87. -
  88.      /* Usual case -- wait for EOF, wait for FIFO to drain, clear EOF */
  89.      while(jz_readf(LCD_STATE, EOF) == 0);
  90.      while(jz_readf(LCD_MSTATE, BUSY));
  91.      jz_writef(LCD_STATE, EOF(0));
  92. -    return true;
  93.  }
  94.  
  95. -static void lcd_dma_stop(void)
  96. +static void lcd_dma_stop(DMA_Mode mode)
  97.  {
  98. +    lcd_on = false;
  99. +
  100. +    if (mode == MODE_INIT) { // INIT: Disable DMA Controller only once when ending
  101.  #ifdef LCD_X1000_DMA_WAIT_FOR_FRAME
  102. -    /* Wait for frame to finish to avoid misaligning the write pointer */
  103. -    lcd_wait_frame();
  104. +        /* Wait for frame to finish to avoid misaligning the write pointer */
  105. +        lcd_wait_frame();
  106.  #endif
  107. +        /* Stop the DMA transfer */
  108. +        jz_writef(LCD_CTRL, ENABLE(0));
  109. +        jz_writef(LCD_MCTRL, DMA_TX_EN(0));
  110. +
  111. +        /* Wait for disable to take effect */
  112. +        while(jz_readf(LCD_STATE, QD) == 0);
  113. +    } else { // SLEEP: only controlled Stop DMA_TX_EN
  114. +        /* Usual case -- wait for EOF, wait for FIFO to drain */
  115. +        lcd_wait_frame();
  116.  
  117. -    /* Stop the DMA transfer */
  118. -    jz_writef(LCD_CTRL, ENABLE(0));
  119. -    jz_writef(LCD_MCTRL, DMA_TX_EN(0));
  120. -
  121. -    /* Wait for disable to take effect */
  122. -    while(jz_readf(LCD_STATE, QD) == 0);
  123. -    jz_writef(LCD_STATE, QD(0));
  124. +        /* Stop the DMA transfer */
  125. +        jz_writef(LCD_MCTRL, DMA_TX_EN(0));
  126. +    }
  127. +    jz_write(LCD_STATE, 0); // clear State
  128.  
  129.      /* Clear format conversion bit, disable vsync */
  130.      jz_writef(LCD_MCFG_NEW, FMT_CONV(0), DTIMES(0));
  131. @@ -370,6 +383,7 @@
  132.              break;
  133.          }
  134.      }
  135. +    udelay(1); // Debug-Timings: 0.1-0.5µS could it be busy, be safe....
  136.  }
  137.  
  138.  void lcd_init_device(void)
  139. @@ -381,7 +395,7 @@
  140.  
  141.      lcd_tgt_enable(true);
  142.  
  143. -    lcd_dma_start();
  144. +    lcd_dma_start(MODE_INIT);
  145.  }
  146.  
  147.  #ifdef HAVE_LCD_SHUTDOWN
  148. @@ -389,8 +403,8 @@
  149.  {
  150.      if(lcd_sleeping)
  151.          lcd_tgt_sleep(false);
  152. -    else if(jz_readf(LCD_CTRL, ENABLE))
  153. -        lcd_dma_stop();
  154. +    else if(lcd_active())
  155. +        lcd_dma_stop(MODE_INIT);
  156.  
  157.      lcd_tgt_enable(false);
  158.      jz_writef(CPM_CLKGR, LCD(1));
  159. @@ -400,37 +414,41 @@
  160.  #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
  161.  bool lcd_active(void)
  162.  {
  163. -    return jz_readf(LCD_CTRL, ENABLE);
  164. +    return lcd_on;
  165.  }
  166.  
  167.  void lcd_enable(bool en)
  168.  {
  169. -    /* Must disable IRQs to turn off the running LCD */
  170. -    int irq = disable_irq_save();
  171. -    int bit = jz_readf(LCD_CTRL, ENABLE);
  172. -    if(bit && !en)
  173. -        lcd_dma_stop();
  174. -    restore_irq(irq);
  175. -
  176. +    bool state = lcd_active();
  177. +    if(state && !en)
  178. +#ifdef BOOTLOADER
  179. +        lcd_dma_stop(MODE_INIT);
  180. +#else
  181. +        lcd_dma_stop(MODE_SLEEP);
  182. +#endif
  183.      /* Deal with sleep mode */
  184.  #if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
  185.  #if defined(LCD_X1000_FASTSLEEP)
  186. -    if(bit && !en) {
  187. +    if(state && !en) {
  188.          lcd_tgt_sleep(true);
  189.          lcd_sleeping = true;
  190.      } else
  191.  #endif
  192. -    if(!bit && en && lcd_sleeping) {
  193. +    if(!state && en && lcd_sleeping) {
  194.          lcd_tgt_sleep(false);
  195.          lcd_sleeping = false;
  196.      }
  197.  #endif
  198.  
  199.      /* Handle turning the LCD back on */
  200. -    if(!bit && en)
  201. +    if(!state && en)
  202.      {
  203.          send_event(LCD_EVENT_ACTIVATION, NULL);
  204. -        lcd_dma_start();
  205. +#ifdef BOOTLOADER
  206. +        lcd_dma_start(MODE_INIT);
  207. +#else
  208. +        lcd_dma_start(MODE_SLEEP);
  209. +#endif
  210.      }
  211.  }
  212.  #endif
  213. @@ -452,9 +470,10 @@
  214.  
  215.  void lcd_update(void)
  216.  {
  217. -    if(!lcd_wait_frame())
  218. +    if (!lcd_active())
  219.          return;
  220.  
  221. +    lcd_wait_frame();
  222.      commit_dcache();
  223.      lcd_fbcopy_dma_full();
  224.      jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1));
  225. @@ -466,6 +485,9 @@
  226.   * its entirety to the LCD through a different DMA process.                      */
  227.  void lcd_update_rect(int x, int y, int width, int height)
  228.  {
  229. +    if (!lcd_active())
  230. +        return;
  231. +
  232.      /* Clamp the coordinates */
  233.      if(x < 0) {
  234.          width += x;
  235. @@ -486,9 +508,7 @@
  236.      if(width < 0 || height < 0)
  237.          return;
  238.  
  239. -    if(!lcd_wait_frame())
  240. -        return;
  241. -
  242. +    lcd_wait_frame();
  243.      commit_dcache();
  244.      lcd_fbcopy_dma_partial(x, y, width, height);
  245.      jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1));
  246.  
Advertisement
Add Comment
Please, Sign In to add comment