diff options
author | Amaury Pouly <amaury.pouly@gmail.com> | 2014-03-08 18:20:08 +0100 |
---|---|---|
committer | Amaury Pouly <amaury.pouly@gmail.com> | 2014-03-08 18:51:54 +0100 |
commit | 4b2f59b3db7d378a42dfebd39e4e3b4ccc8280f8 (patch) | |
tree | 4cdc80e4c11752ed447a45f0b2b07a6d51010c2f /firmware/target/arm/imx233/creative-zen | |
parent | b0940b1dd388a3d7b8d50da329b84e8f65717b9a (diff) |
zen: handle lcd underflow by hand
Contrary to the imx233, the stmp37xx lcdif doesn't know how to properly
recover from underflow and things are worse because of the errata which
makes the lcdif not clear the fifo. Workaround this by detecting underflow
and taking action: stop dotclk mode (will clear fifo) and schedule next frame.
The dma transfers now write the ctrl register as part of the PIO writes,
making the code simpler.
Change-Id: I15abc24567f322cd03bf2ef7903094f7f0178427
Diffstat (limited to 'firmware/target/arm/imx233/creative-zen')
-rw-r--r-- | firmware/target/arm/imx233/creative-zen/lcd-zen.c | 21 |
1 files changed, 17 insertions, 4 deletions
diff --git a/firmware/target/arm/imx233/creative-zen/lcd-zen.c b/firmware/target/arm/imx233/creative-zen/lcd-zen.c index e9644278f1..6482c58787 100644 --- a/firmware/target/arm/imx233/creative-zen/lcd-zen.c +++ b/firmware/target/arm/imx233/creative-zen/lcd-zen.c @@ -48,7 +48,7 @@ static bool lcd_on; struct lcdif_dma_command_t { struct apb_dma_command_t dma; - uint32_t pad; + uint32_t ctrl; } __attribute__((packed)) CACHEALIGN_ATTR; __ENSURE_STRUCT_CACHE_FRIENDLY(struct lcdif_dma_command_t) @@ -249,15 +249,12 @@ void lcd_enable(bool enable) // "power" on lcd_power(true); // setup registers - imx233_lcdif_enable_sync_signals(true); // we need frame signals during init lcd_power_seq(); lcd_init_seq(); lcd_display_on_seq(); imx233_dma_reset_channel(APB_LCDIF); imx233_dma_start_command(APB_LCDIF, &lcdif_dma[0].dma); - BF_SET(LCDIF_CTRL, DOTCLK_MODE); - BF_SET(LCDIF_CTRL, RUN); } else { @@ -275,6 +272,15 @@ void lcd_enable(bool enable) } } +static void lcd_underflow(void) +{ + /* on underflow, current frame is dead so stop lcdif and prepare for next frame + * don't bother with the errata, fifo is empty since we are underflowing ! */ + BF_CLR(LCDIF_CTRL, DOTCLK_MODE); + imx233_dma_reset_channel(APB_LCDIF); + imx233_dma_start_command(APB_LCDIF, &lcdif_dma[0].dma); +} + void lcd_init_device(void) { semaphore_init(&g_wait_sema, 1, 0); @@ -297,6 +303,8 @@ void lcd_init_device(void) imx233_lcdif_init(); imx233_lcdif_setup_dotclk_pins(8, false); imx233_lcdif_set_word_length(8); + imx233_lcdif_set_underflow_cb(&lcd_underflow); + imx233_lcdif_enable_underflow_irq(true); imx233_dma_clkgate_channel(APB_LCDIF, true); imx233_dma_reset_channel(APB_LCDIF); /** Datasheet states: @@ -312,6 +320,7 @@ void lcd_init_device(void) /*h_front_porch*/4, LCD_WIDTH, LCD_HEIGHT, /*clk_per_pix*/3, /*enable_present*/false); imx233_lcdif_set_byte_packing_format(0xf); + imx233_lcdif_enable_sync_signals(true); // we need frame signals during init // setup dma unsigned size = IMX233_FRAMEBUFFER_SIZE; uint8_t *frame_p = FRAME; @@ -325,6 +334,10 @@ void lcd_init_device(void) size -= xfer; frame_p += xfer; } + // first transfer: enable run, dotclk and so on + lcdif_dma[0].dma.cmd |= BF_OR1(APB_CHx_CMD, CMDWORDS(1)); + lcdif_dma[0].ctrl = BF_OR4(LCDIF_CTRL, BYPASS_COUNT(1), DOTCLK_MODE(1), + RUN(1), WORD_LENGTH(1)); // enable lcd_enable(true); } |