forked from len0rd/rockbox
x1000: LCD driver minor fixes & improvements
- Use unsigned bitfields in 'lcd_tgt_config' - Set DTIMES when using an 8-bit bus width - Allow using DMA big-endian mode - Provide an #ifdef to avoid stopping DMA in the middle of a frame - Correctly #ifdef LCD sleep code when target does not implement it Change-Id: I327c6b05223638b876d5ab62cb6e48f82e6d5fa5
This commit is contained in:
parent
a6b5de6a89
commit
cec6422ace
2 changed files with 49 additions and 35 deletions
|
|
@ -65,8 +65,10 @@ static fb_data shadowfb[LCD_HEIGHT*LCD_WIDTH] __attribute__((aligned(64)));
|
|||
/* Signals DMA copy to shadow FB is done */
|
||||
static volatile int fbcopy_done;
|
||||
|
||||
#if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
|
||||
/* True if we're in sleep mode */
|
||||
static bool lcd_sleeping = false;
|
||||
#endif
|
||||
|
||||
/* Check if running with interrupts disabled (eg: panic screen) */
|
||||
#define lcd_panic_mode \
|
||||
|
|
@ -98,16 +100,16 @@ static void lcd_init_controller(const struct lcd_tgt_config* cfg)
|
|||
default: break;
|
||||
}
|
||||
|
||||
if(lcd_tgt_config.use_serial)
|
||||
if(cfg->use_serial)
|
||||
mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(SERIAL), CTYPE_V(SERIAL));
|
||||
else
|
||||
mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL));
|
||||
|
||||
jz_vwritef(mcfg_new, LCD_MCFG_NEW,
|
||||
6800_MODE(lcd_tgt_config.use_6800_mode),
|
||||
CSPLY(lcd_tgt_config.wr_polarity ? 0 : 1),
|
||||
RSPLY(lcd_tgt_config.dc_polarity),
|
||||
CLKPLY(lcd_tgt_config.clk_polarity));
|
||||
6800_MODE(cfg->use_6800_mode),
|
||||
CSPLY(cfg->wr_polarity ? 0 : 1),
|
||||
RSPLY(cfg->dc_polarity),
|
||||
CLKPLY(cfg->clk_polarity));
|
||||
|
||||
/* Program the configuration. Note we cannot enable TE signal at
|
||||
* this stage, because the panel will need to be configured first.
|
||||
|
|
@ -122,9 +124,9 @@ static void lcd_init_controller(const struct lcd_tgt_config* cfg)
|
|||
jz_write(LCD_SMWT, 0);
|
||||
|
||||
/* DMA settings */
|
||||
jz_writef(LCD_CTRL, BURST_V(64WORD),
|
||||
jz_writef(LCD_CTRL, ENABLE(0), BURST_V(64WORD),
|
||||
EOFM(1), SOFM(0), IFUM(0), QDM(0),
|
||||
BEDN(0), PEDN(0), ENABLE(0));
|
||||
BEDN(cfg->big_endian), PEDN(0));
|
||||
jz_write(LCD_DAH, LCD_WIDTH);
|
||||
jz_write(LCD_DAV, LCD_HEIGHT);
|
||||
}
|
||||
|
|
@ -274,8 +276,10 @@ static void lcd_fbcopy_dma_partial(int x, int y, int width, int height)
|
|||
|
||||
static void lcd_dma_start(void)
|
||||
{
|
||||
/* Set format conversion bit, seems necessary for DMA mode */
|
||||
jz_writef(LCD_MCFG_NEW, FMT_CONV(1));
|
||||
/* Set format conversion bit, seems necessary for DMA mode.
|
||||
* Must set DTIMES here if we use an 8-bit bus type. */
|
||||
int dtimes = lcd_tgt_config.bus_width == 8 ? (LCD_DEPTH/8 - 1) : 0;
|
||||
jz_writef(LCD_MCFG_NEW, FMT_CONV(1), DTIMES(dtimes));
|
||||
|
||||
/* Program vsync configuration */
|
||||
jz_writef(LCD_MCTRL, NARROW_TE(lcd_tgt_config.te_narrow),
|
||||
|
|
@ -290,21 +294,6 @@ static void lcd_dma_start(void)
|
|||
jz_writef(LCD_CTRL, ENABLE(1));
|
||||
}
|
||||
|
||||
static void lcd_dma_stop(void)
|
||||
{
|
||||
/* 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));
|
||||
|
||||
/* Clear format conversion bit, disable vsync */
|
||||
jz_writef(LCD_MCFG_NEW, FMT_CONV(0));
|
||||
jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1));
|
||||
}
|
||||
|
||||
static bool lcd_wait_frame(void)
|
||||
{
|
||||
/* Bail out if DMA is not enabled */
|
||||
|
|
@ -321,6 +310,26 @@ static bool lcd_wait_frame(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
static void lcd_dma_stop(void)
|
||||
{
|
||||
#ifdef LCD_X1000_DMA_WAIT_FOR_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);
|
||||
jz_writef(LCD_STATE, QD(0));
|
||||
|
||||
/* Clear format conversion bit, disable vsync */
|
||||
jz_writef(LCD_MCFG_NEW, FMT_CONV(0), DTIMES(0));
|
||||
jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1));
|
||||
}
|
||||
|
||||
static void lcd_send(uint32_t d)
|
||||
{
|
||||
while(jz_readf(LCD_MSTATE, BUSY));
|
||||
|
|
@ -404,7 +413,8 @@ void lcd_enable(bool en)
|
|||
restore_irq(irq);
|
||||
|
||||
/* Deal with sleep mode */
|
||||
#ifdef LCD_X1000_FASTSLEEP
|
||||
#if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
|
||||
#if defined(LCD_X1000_FASTSLEEP)
|
||||
if(bit && !en) {
|
||||
lcd_tgt_sleep(true);
|
||||
lcd_sleeping = true;
|
||||
|
|
@ -414,6 +424,7 @@ void lcd_enable(bool en)
|
|||
lcd_tgt_sleep(false);
|
||||
lcd_sleeping = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Handle turning the LCD back on */
|
||||
if(!bit && en)
|
||||
|
|
|
|||
|
|
@ -38,34 +38,37 @@
|
|||
|
||||
struct lcd_tgt_config {
|
||||
/* Data bus width, in bits */
|
||||
int bus_width: 8;
|
||||
unsigned bus_width: 8;
|
||||
|
||||
/* Command bus width, in bits */
|
||||
int cmd_width: 8;
|
||||
unsigned cmd_width: 8;
|
||||
|
||||
/* 1 = use 6800 timings, 0 = use 8080 timings */
|
||||
int use_6800_mode: 1;
|
||||
unsigned use_6800_mode: 1;
|
||||
|
||||
/* 1 = serial interface, 0 = parallel interface */
|
||||
int use_serial: 1;
|
||||
unsigned use_serial: 1;
|
||||
|
||||
/* Clock active edge: 0 = falling edge, 1 = rising edge */
|
||||
int clk_polarity: 1;
|
||||
unsigned clk_polarity: 1;
|
||||
|
||||
/* DC pin levels: 1 = data high, command low; 0 = data low, command high */
|
||||
int dc_polarity: 1;
|
||||
unsigned dc_polarity: 1;
|
||||
|
||||
/* WR pin level during idle: 1 = keep high; 0 = keep low */
|
||||
int wr_polarity: 1;
|
||||
unsigned wr_polarity: 1;
|
||||
|
||||
/* 1 to enable vsync, so DMA transfer is synchronized with TE signal */
|
||||
int te_enable: 1;
|
||||
unsigned te_enable: 1;
|
||||
|
||||
/* Active level of TE signal: 1 = high, 0 = low */
|
||||
int te_polarity: 1;
|
||||
unsigned te_polarity: 1;
|
||||
|
||||
/* 1 = support narrow TE signal (<=3 pixel clocks); 0 = don't support */
|
||||
int te_narrow: 1;
|
||||
unsigned te_narrow: 1;
|
||||
|
||||
/* 1 = big endian mode, 0 = little endian mode */
|
||||
unsigned big_endian: 1;
|
||||
|
||||
/* Commands used to initiate a framebuffer write. Buffer must be
|
||||
* aligned to 64-byte boundary and size must be a multiple of 4,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue