1
0
Fork 0
forked from len0rd/rockbox

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
This commit is contained in:
Amaury Pouly 2014-03-08 18:20:08 +01:00
parent b0940b1dd3
commit 4b2f59b3db

View file

@ -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);
}