summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAidan MacDonald <amachronic@protonmail.com>2021-05-25 23:41:08 +0100
committerAidan MacDonald <amachronic@protonmail.com>2021-06-03 22:54:59 +0000
commitcec6422ace933fecc02053c0fa6b239f7a6792e5 (patch)
tree9dd7d69c889831337853e5ab000f515a5d72cb39
parenta6b5de6a89c82ec8c6d0d7bafb9a377f9035d46b (diff)
downloadrockbox-cec6422ace933fecc02053c0fa6b239f7a6792e5.tar.gz
rockbox-cec6422ace933fecc02053c0fa6b239f7a6792e5.zip
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
-rw-r--r--firmware/target/mips/ingenic_x1000/lcd-x1000.c61
-rw-r--r--firmware/target/mips/ingenic_x1000/lcd-x1000.h23
2 files changed, 49 insertions, 35 deletions
diff --git a/firmware/target/mips/ingenic_x1000/lcd-x1000.c b/firmware/target/mips/ingenic_x1000/lcd-x1000.c
index aadf93c8ff..193ff082e0 100644
--- a/firmware/target/mips/ingenic_x1000/lcd-x1000.c
+++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.c
@@ -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)
diff --git a/firmware/target/mips/ingenic_x1000/lcd-x1000.h b/firmware/target/mips/ingenic_x1000/lcd-x1000.h
index 96085ac207..749fac8240 100644
--- a/firmware/target/mips/ingenic_x1000/lcd-x1000.h
+++ b/firmware/target/mips/ingenic_x1000/lcd-x1000.h
@@ -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,