From 4b2f59b3db7d378a42dfebd39e4e3b4ccc8280f8 Mon Sep 17 00:00:00 2001 From: Amaury Pouly Date: Sat, 8 Mar 2014 18:20:08 +0100 Subject: 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 --- firmware/target/arm/imx233/creative-zen/lcd-zen.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'firmware/target') 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); } -- cgit v1.2.3