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 */
|
/* Signals DMA copy to shadow FB is done */
|
||||||
static volatile int fbcopy_done;
|
static volatile int fbcopy_done;
|
||||||
|
|
||||||
|
#if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
|
||||||
/* True if we're in sleep mode */
|
/* True if we're in sleep mode */
|
||||||
static bool lcd_sleeping = false;
|
static bool lcd_sleeping = false;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Check if running with interrupts disabled (eg: panic screen) */
|
/* Check if running with interrupts disabled (eg: panic screen) */
|
||||||
#define lcd_panic_mode \
|
#define lcd_panic_mode \
|
||||||
|
|
@ -98,16 +100,16 @@ static void lcd_init_controller(const struct lcd_tgt_config* cfg)
|
||||||
default: break;
|
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));
|
mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(SERIAL), CTYPE_V(SERIAL));
|
||||||
else
|
else
|
||||||
mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL));
|
mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL));
|
||||||
|
|
||||||
jz_vwritef(mcfg_new, LCD_MCFG_NEW,
|
jz_vwritef(mcfg_new, LCD_MCFG_NEW,
|
||||||
6800_MODE(lcd_tgt_config.use_6800_mode),
|
6800_MODE(cfg->use_6800_mode),
|
||||||
CSPLY(lcd_tgt_config.wr_polarity ? 0 : 1),
|
CSPLY(cfg->wr_polarity ? 0 : 1),
|
||||||
RSPLY(lcd_tgt_config.dc_polarity),
|
RSPLY(cfg->dc_polarity),
|
||||||
CLKPLY(lcd_tgt_config.clk_polarity));
|
CLKPLY(cfg->clk_polarity));
|
||||||
|
|
||||||
/* Program the configuration. Note we cannot enable TE signal at
|
/* Program the configuration. Note we cannot enable TE signal at
|
||||||
* this stage, because the panel will need to be configured first.
|
* 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);
|
jz_write(LCD_SMWT, 0);
|
||||||
|
|
||||||
/* DMA settings */
|
/* 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),
|
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_DAH, LCD_WIDTH);
|
||||||
jz_write(LCD_DAV, LCD_HEIGHT);
|
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)
|
static void lcd_dma_start(void)
|
||||||
{
|
{
|
||||||
/* Set format conversion bit, seems necessary for DMA mode */
|
/* Set format conversion bit, seems necessary for DMA mode.
|
||||||
jz_writef(LCD_MCFG_NEW, FMT_CONV(1));
|
* 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 */
|
/* Program vsync configuration */
|
||||||
jz_writef(LCD_MCTRL, NARROW_TE(lcd_tgt_config.te_narrow),
|
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));
|
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)
|
static bool lcd_wait_frame(void)
|
||||||
{
|
{
|
||||||
/* Bail out if DMA is not enabled */
|
/* Bail out if DMA is not enabled */
|
||||||
|
|
@ -321,6 +310,26 @@ static bool lcd_wait_frame(void)
|
||||||
return true;
|
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)
|
static void lcd_send(uint32_t d)
|
||||||
{
|
{
|
||||||
while(jz_readf(LCD_MSTATE, BUSY));
|
while(jz_readf(LCD_MSTATE, BUSY));
|
||||||
|
|
@ -404,7 +413,8 @@ void lcd_enable(bool en)
|
||||||
restore_irq(irq);
|
restore_irq(irq);
|
||||||
|
|
||||||
/* Deal with sleep mode */
|
/* 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) {
|
if(bit && !en) {
|
||||||
lcd_tgt_sleep(true);
|
lcd_tgt_sleep(true);
|
||||||
lcd_sleeping = true;
|
lcd_sleeping = true;
|
||||||
|
|
@ -414,6 +424,7 @@ void lcd_enable(bool en)
|
||||||
lcd_tgt_sleep(false);
|
lcd_tgt_sleep(false);
|
||||||
lcd_sleeping = false;
|
lcd_sleeping = false;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Handle turning the LCD back on */
|
/* Handle turning the LCD back on */
|
||||||
if(!bit && en)
|
if(!bit && en)
|
||||||
|
|
|
||||||
|
|
@ -38,34 +38,37 @@
|
||||||
|
|
||||||
struct lcd_tgt_config {
|
struct lcd_tgt_config {
|
||||||
/* Data bus width, in bits */
|
/* Data bus width, in bits */
|
||||||
int bus_width: 8;
|
unsigned bus_width: 8;
|
||||||
|
|
||||||
/* Command bus width, in bits */
|
/* Command bus width, in bits */
|
||||||
int cmd_width: 8;
|
unsigned cmd_width: 8;
|
||||||
|
|
||||||
/* 1 = use 6800 timings, 0 = use 8080 timings */
|
/* 1 = use 6800 timings, 0 = use 8080 timings */
|
||||||
int use_6800_mode: 1;
|
unsigned use_6800_mode: 1;
|
||||||
|
|
||||||
/* 1 = serial interface, 0 = parallel interface */
|
/* 1 = serial interface, 0 = parallel interface */
|
||||||
int use_serial: 1;
|
unsigned use_serial: 1;
|
||||||
|
|
||||||
/* Clock active edge: 0 = falling edge, 1 = rising edge */
|
/* 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 */
|
/* 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 */
|
/* 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 */
|
/* 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 */
|
/* 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 */
|
/* 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
|
/* Commands used to initiate a framebuffer write. Buffer must be
|
||||||
* aligned to 64-byte boundary and size must be a multiple of 4,
|
* aligned to 64-byte boundary and size must be a multiple of 4,
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue