summaryrefslogtreecommitdiff
path: root/firmware/target/arm/imx233/creative-zen
diff options
context:
space:
mode:
authorAmaury Pouly <amaury.pouly@gmail.com>2014-03-08 18:20:08 +0100
committerAmaury Pouly <amaury.pouly@gmail.com>2014-03-08 18:51:54 +0100
commit4b2f59b3db7d378a42dfebd39e4e3b4ccc8280f8 (patch)
tree4cdc80e4c11752ed447a45f0b2b07a6d51010c2f /firmware/target/arm/imx233/creative-zen
parentb0940b1dd388a3d7b8d50da329b84e8f65717b9a (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.c21
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);
}