Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- x1000: LCD DMA fix 'revisited' for cd91c238de and newer
- And in long Experiments and Player usages the (seldom)
- Display hang when Wake from Sleep could be fixed by this
- Don't complete deactivate the Controller in Sleep,
- only controlled Stop the LCD_DMA_TX
- Testet on fiiom3ks / Hifi Walkers 1.5, 1.8 and Surfans F20 2.7, 3.2
- in its original incarnation since 16 Jul 2024, and this anti-crufted Ver. since 7 Aug 2024
- (And no x1000 Display Hang since 16 Jul...)
- NEW: Move the complete Timing count Loop & case Logic to the
- LCD Timing Debug x1000_LCD_DMA_Debug3.diff where it belongs.
- Leave only the DMA Start/Stop differences of Sleep/Wake in
- Anti-Cruft lcd_active / lcd_on
- (And leave the Bootloader Logic largely unmodified)
- Credit ZappBranigan2972 on forums / F. Jacobsen on the Theme Site
- ---
- --- a/firmware/target/mips/ingenic_x1000/lcd-x1000.c.orig 2024-07-10 09:00:17.175641885 +0200
- +++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.c 2024-07-10 09:06:46.482963434 +0200
- @@ -69,6 +69,7 @@
- /* True if we're in sleep mode */
- static bool lcd_sleeping = false;
- #endif
- +static bool lcd_on = false;
- /* Check if running with interrupts disabled (eg: panic screen) */
- #define lcd_panic_mode \
- @@ -125,7 +126,7 @@
- /* DMA settings */
- jz_writef(LCD_CTRL, ENABLE(0), BURST_V(64WORD),
- - EOFM(1), SOFM(0), IFUM(0), QDM(0),
- + EOFM(0), SOFM(0), IFUM(0), QDM(0),
- BEDN(cfg->big_endian), PEDN(0));
- jz_write(LCD_DAH, LCD_WIDTH);
- jz_write(LCD_DAV, LCD_HEIGHT);
- @@ -274,7 +275,14 @@
- # define lcd_fbcopy_dma_partial lcd_fbcopy_dma_partial1
- #endif
- -static void lcd_dma_start(void)
- +typedef enum {
- + MODE_INIT,
- + MODE_SLEEP
- +} DMA_Mode;
- +
- +/* lcd_dma_start/stop It doesn't follow the 'chinese' Datasheet, but no Display *
- + * Hang on my x1000 Devices since the first Test from 16Jul24 with this */
- +static void lcd_dma_start(DMA_Mode mode)
- {
- /* Set format conversion bit, seems necessary for DMA mode.
- * Must set DTIMES here if we use an 8-bit bus type. */
- @@ -286,44 +294,49 @@
- TE_INV(lcd_tgt_config.te_polarity ? 0 : 1),
- NOT_USE_TE(lcd_tgt_config.te_enable ? 0 : 1));
- + if (mode == MODE_INIT) { // INIT: Enable DMA Controller only once on Startup
- + jz_write(LCD_DA, PHYSADDR(&lcd_dma_desc[0]));
- + jz_writef(LCD_CTRL, ENABLE(1));
- + }
- + jz_write(LCD_STATE, 0);
- /* Begin DMA transfer. Need to start a dummy frame or else we will
- * not be able to pass lcd_wait_frame() at the first lcd_update(). */
- - jz_write(LCD_STATE, 0);
- - jz_write(LCD_DA, PHYSADDR(&lcd_dma_desc[0]));
- jz_writef(LCD_MCTRL, DMA_MODE(1), DMA_START(1), DMA_TX_EN(1));
- - jz_writef(LCD_CTRL, ENABLE(1));
- +
- + lcd_on = true;
- }
- -static bool lcd_wait_frame(void)
- +static void lcd_wait_frame(void)
- {
- - /* Bail out if DMA is not enabled */
- - int irq = disable_irq_save();
- - int bit = jz_readf(LCD_CTRL, ENABLE);
- - restore_irq(irq);
- - if(!bit)
- - return false;
- -
- /* Usual case -- wait for EOF, wait for FIFO to drain, clear EOF */
- while(jz_readf(LCD_STATE, EOF) == 0);
- while(jz_readf(LCD_MSTATE, BUSY));
- jz_writef(LCD_STATE, EOF(0));
- - return true;
- }
- -static void lcd_dma_stop(void)
- +static void lcd_dma_stop(DMA_Mode mode)
- {
- + lcd_on = false;
- +
- + if (mode == MODE_INIT) { // INIT: Disable DMA Controller only once when ending
- #ifdef LCD_X1000_DMA_WAIT_FOR_FRAME
- - /* Wait for frame to finish to avoid misaligning the write pointer */
- - lcd_wait_frame();
- + /* Wait for frame to finish to avoid misaligning the write pointer */
- + lcd_wait_frame();
- #endif
- + /* Stop the DMA transfer */
- + jz_writef(LCD_CTRL, ENABLE(0));
- + jz_writef(LCD_MCTRL, DMA_TX_EN(0));
- +
- + /* Wait for disable to take effect */
- + while(jz_readf(LCD_STATE, QD) == 0);
- + } else { // SLEEP: only controlled Stop DMA_TX_EN
- + /* Usual case -- wait for EOF, wait for FIFO to drain */
- + lcd_wait_frame();
- - /* Stop the DMA transfer */
- - jz_writef(LCD_CTRL, ENABLE(0));
- - jz_writef(LCD_MCTRL, DMA_TX_EN(0));
- -
- - /* Wait for disable to take effect */
- - while(jz_readf(LCD_STATE, QD) == 0);
- - jz_writef(LCD_STATE, QD(0));
- + /* Stop the DMA transfer */
- + jz_writef(LCD_MCTRL, DMA_TX_EN(0));
- + }
- + jz_write(LCD_STATE, 0); // clear State
- /* Clear format conversion bit, disable vsync */
- jz_writef(LCD_MCFG_NEW, FMT_CONV(0), DTIMES(0));
- @@ -370,6 +383,7 @@
- break;
- }
- }
- + udelay(1); // Debug-Timings: 0.1-0.5µS could it be busy, be safe....
- }
- void lcd_init_device(void)
- @@ -381,7 +395,7 @@
- lcd_tgt_enable(true);
- - lcd_dma_start();
- + lcd_dma_start(MODE_INIT);
- }
- #ifdef HAVE_LCD_SHUTDOWN
- @@ -389,8 +403,8 @@
- {
- if(lcd_sleeping)
- lcd_tgt_sleep(false);
- - else if(jz_readf(LCD_CTRL, ENABLE))
- - lcd_dma_stop();
- + else if(lcd_active())
- + lcd_dma_stop(MODE_INIT);
- lcd_tgt_enable(false);
- jz_writef(CPM_CLKGR, LCD(1));
- @@ -400,37 +414,41 @@
- #if defined(HAVE_LCD_ENABLE) || defined(HAVE_LCD_SLEEP)
- bool lcd_active(void)
- {
- - return jz_readf(LCD_CTRL, ENABLE);
- + return lcd_on;
- }
- void lcd_enable(bool en)
- {
- - /* Must disable IRQs to turn off the running LCD */
- - int irq = disable_irq_save();
- - int bit = jz_readf(LCD_CTRL, ENABLE);
- - if(bit && !en)
- - lcd_dma_stop();
- - restore_irq(irq);
- -
- + bool state = lcd_active();
- + if(state && !en)
- +#ifdef BOOTLOADER
- + lcd_dma_stop(MODE_INIT);
- +#else
- + lcd_dma_stop(MODE_SLEEP);
- +#endif
- /* Deal with sleep mode */
- #if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
- #if defined(LCD_X1000_FASTSLEEP)
- - if(bit && !en) {
- + if(state && !en) {
- lcd_tgt_sleep(true);
- lcd_sleeping = true;
- } else
- #endif
- - if(!bit && en && lcd_sleeping) {
- + if(!state && en && lcd_sleeping) {
- lcd_tgt_sleep(false);
- lcd_sleeping = false;
- }
- #endif
- /* Handle turning the LCD back on */
- - if(!bit && en)
- + if(!state && en)
- {
- send_event(LCD_EVENT_ACTIVATION, NULL);
- - lcd_dma_start();
- +#ifdef BOOTLOADER
- + lcd_dma_start(MODE_INIT);
- +#else
- + lcd_dma_start(MODE_SLEEP);
- +#endif
- }
- }
- #endif
- @@ -452,9 +470,10 @@
- void lcd_update(void)
- {
- - if(!lcd_wait_frame())
- + if (!lcd_active())
- return;
- + lcd_wait_frame();
- commit_dcache();
- lcd_fbcopy_dma_full();
- jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1));
- @@ -466,6 +485,9 @@
- * its entirety to the LCD through a different DMA process. */
- void lcd_update_rect(int x, int y, int width, int height)
- {
- + if (!lcd_active())
- + return;
- +
- /* Clamp the coordinates */
- if(x < 0) {
- width += x;
- @@ -486,9 +508,7 @@
- if(width < 0 || height < 0)
- return;
- - if(!lcd_wait_frame())
- - return;
- -
- + lcd_wait_frame();
- commit_dcache();
- lcd_fbcopy_dma_partial(x, y, width, height);
- jz_writef(LCD_MCTRL, DMA_START(1), DMA_MODE(1));
Advertisement
Add Comment
Please, Sign In to add comment