summaryrefslogtreecommitdiff
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)));
65/* Signals DMA copy to shadow FB is done */ 65/* Signals DMA copy to shadow FB is done */
66static volatile int fbcopy_done; 66static volatile int fbcopy_done;
67 67
68#if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
68/* True if we're in sleep mode */ 69/* True if we're in sleep mode */
69static bool lcd_sleeping = false; 70static bool lcd_sleeping = false;
71#endif
70 72
71/* Check if running with interrupts disabled (eg: panic screen) */ 73/* Check if running with interrupts disabled (eg: panic screen) */
72#define lcd_panic_mode \ 74#define lcd_panic_mode \
@@ -98,16 +100,16 @@ static void lcd_init_controller(const struct lcd_tgt_config* cfg)
98 default: break; 100 default: break;
99 } 101 }
100 102
101 if(lcd_tgt_config.use_serial) 103 if(cfg->use_serial)
102 mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(SERIAL), CTYPE_V(SERIAL)); 104 mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(SERIAL), CTYPE_V(SERIAL));
103 else 105 else
104 mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL)); 106 mcfg_new |= jz_orf(LCD_MCFG_NEW, DTYPE_V(PARALLEL), CTYPE_V(PARALLEL));
105 107
106 jz_vwritef(mcfg_new, LCD_MCFG_NEW, 108 jz_vwritef(mcfg_new, LCD_MCFG_NEW,
107 6800_MODE(lcd_tgt_config.use_6800_mode), 109 6800_MODE(cfg->use_6800_mode),
108 CSPLY(lcd_tgt_config.wr_polarity ? 0 : 1), 110 CSPLY(cfg->wr_polarity ? 0 : 1),
109 RSPLY(lcd_tgt_config.dc_polarity), 111 RSPLY(cfg->dc_polarity),
110 CLKPLY(lcd_tgt_config.clk_polarity)); 112 CLKPLY(cfg->clk_polarity));
111 113
112 /* Program the configuration. Note we cannot enable TE signal at 114 /* Program the configuration. Note we cannot enable TE signal at
113 * this stage, because the panel will need to be configured first. 115 * 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)
122 jz_write(LCD_SMWT, 0); 124 jz_write(LCD_SMWT, 0);
123 125
124 /* DMA settings */ 126 /* DMA settings */
125 jz_writef(LCD_CTRL, BURST_V(64WORD), 127 jz_writef(LCD_CTRL, ENABLE(0), BURST_V(64WORD),
126 EOFM(1), SOFM(0), IFUM(0), QDM(0), 128 EOFM(1), SOFM(0), IFUM(0), QDM(0),
127 BEDN(0), PEDN(0), ENABLE(0)); 129 BEDN(cfg->big_endian), PEDN(0));
128 jz_write(LCD_DAH, LCD_WIDTH); 130 jz_write(LCD_DAH, LCD_WIDTH);
129 jz_write(LCD_DAV, LCD_HEIGHT); 131 jz_write(LCD_DAV, LCD_HEIGHT);
130} 132}
@@ -274,8 +276,10 @@ static void lcd_fbcopy_dma_partial(int x, int y, int width, int height)
274 276
275static void lcd_dma_start(void) 277static void lcd_dma_start(void)
276{ 278{
277 /* Set format conversion bit, seems necessary for DMA mode */ 279 /* Set format conversion bit, seems necessary for DMA mode.
278 jz_writef(LCD_MCFG_NEW, FMT_CONV(1)); 280 * Must set DTIMES here if we use an 8-bit bus type. */
281 int dtimes = lcd_tgt_config.bus_width == 8 ? (LCD_DEPTH/8 - 1) : 0;
282 jz_writef(LCD_MCFG_NEW, FMT_CONV(1), DTIMES(dtimes));
279 283
280 /* Program vsync configuration */ 284 /* Program vsync configuration */
281 jz_writef(LCD_MCTRL, NARROW_TE(lcd_tgt_config.te_narrow), 285 jz_writef(LCD_MCTRL, NARROW_TE(lcd_tgt_config.te_narrow),
@@ -290,21 +294,6 @@ static void lcd_dma_start(void)
290 jz_writef(LCD_CTRL, ENABLE(1)); 294 jz_writef(LCD_CTRL, ENABLE(1));
291} 295}
292 296
293static void lcd_dma_stop(void)
294{
295 /* Stop the DMA transfer */
296 jz_writef(LCD_CTRL, ENABLE(0));
297 jz_writef(LCD_MCTRL, DMA_TX_EN(0));
298
299 /* Wait for disable to take effect */
300 while(jz_readf(LCD_STATE, QD) == 0);
301 jz_writef(LCD_STATE, QD(0));
302
303 /* Clear format conversion bit, disable vsync */
304 jz_writef(LCD_MCFG_NEW, FMT_CONV(0));
305 jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1));
306}
307
308static bool lcd_wait_frame(void) 297static bool lcd_wait_frame(void)
309{ 298{
310 /* Bail out if DMA is not enabled */ 299 /* Bail out if DMA is not enabled */
@@ -321,6 +310,26 @@ static bool lcd_wait_frame(void)
321 return true; 310 return true;
322} 311}
323 312
313static void lcd_dma_stop(void)
314{
315#ifdef LCD_X1000_DMA_WAIT_FOR_FRAME
316 /* Wait for frame to finish to avoid misaligning the write pointer */
317 lcd_wait_frame();
318#endif
319
320 /* Stop the DMA transfer */
321 jz_writef(LCD_CTRL, ENABLE(0));
322 jz_writef(LCD_MCTRL, DMA_TX_EN(0));
323
324 /* Wait for disable to take effect */
325 while(jz_readf(LCD_STATE, QD) == 0);
326 jz_writef(LCD_STATE, QD(0));
327
328 /* Clear format conversion bit, disable vsync */
329 jz_writef(LCD_MCFG_NEW, FMT_CONV(0), DTIMES(0));
330 jz_writef(LCD_MCTRL, NARROW_TE(0), TE_INV(0), NOT_USE_TE(1));
331}
332
324static void lcd_send(uint32_t d) 333static void lcd_send(uint32_t d)
325{ 334{
326 while(jz_readf(LCD_MSTATE, BUSY)); 335 while(jz_readf(LCD_MSTATE, BUSY));
@@ -404,7 +413,8 @@ void lcd_enable(bool en)
404 restore_irq(irq); 413 restore_irq(irq);
405 414
406 /* Deal with sleep mode */ 415 /* Deal with sleep mode */
407#ifdef LCD_X1000_FASTSLEEP 416#if defined(HAVE_LCD_SLEEP) || defined(LCD_X1000_FASTSLEEP)
417#if defined(LCD_X1000_FASTSLEEP)
408 if(bit && !en) { 418 if(bit && !en) {
409 lcd_tgt_sleep(true); 419 lcd_tgt_sleep(true);
410 lcd_sleeping = true; 420 lcd_sleeping = true;
@@ -414,6 +424,7 @@ void lcd_enable(bool en)
414 lcd_tgt_sleep(false); 424 lcd_tgt_sleep(false);
415 lcd_sleeping = false; 425 lcd_sleeping = false;
416 } 426 }
427#endif
417 428
418 /* Handle turning the LCD back on */ 429 /* Handle turning the LCD back on */
419 if(!bit && en) 430 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 @@
38 38
39struct lcd_tgt_config { 39struct lcd_tgt_config {
40 /* Data bus width, in bits */ 40 /* Data bus width, in bits */
41 int bus_width: 8; 41 unsigned bus_width: 8;
42 42
43 /* Command bus width, in bits */ 43 /* Command bus width, in bits */
44 int cmd_width: 8; 44 unsigned cmd_width: 8;
45 45
46 /* 1 = use 6800 timings, 0 = use 8080 timings */ 46 /* 1 = use 6800 timings, 0 = use 8080 timings */
47 int use_6800_mode: 1; 47 unsigned use_6800_mode: 1;
48 48
49 /* 1 = serial interface, 0 = parallel interface */ 49 /* 1 = serial interface, 0 = parallel interface */
50 int use_serial: 1; 50 unsigned use_serial: 1;
51 51
52 /* Clock active edge: 0 = falling edge, 1 = rising edge */ 52 /* Clock active edge: 0 = falling edge, 1 = rising edge */
53 int clk_polarity: 1; 53 unsigned clk_polarity: 1;
54 54
55 /* DC pin levels: 1 = data high, command low; 0 = data low, command high */ 55 /* DC pin levels: 1 = data high, command low; 0 = data low, command high */
56 int dc_polarity: 1; 56 unsigned dc_polarity: 1;
57 57
58 /* WR pin level during idle: 1 = keep high; 0 = keep low */ 58 /* WR pin level during idle: 1 = keep high; 0 = keep low */
59 int wr_polarity: 1; 59 unsigned wr_polarity: 1;
60 60
61 /* 1 to enable vsync, so DMA transfer is synchronized with TE signal */ 61 /* 1 to enable vsync, so DMA transfer is synchronized with TE signal */
62 int te_enable: 1; 62 unsigned te_enable: 1;
63 63
64 /* Active level of TE signal: 1 = high, 0 = low */ 64 /* Active level of TE signal: 1 = high, 0 = low */
65 int te_polarity: 1; 65 unsigned te_polarity: 1;
66 66
67 /* 1 = support narrow TE signal (<=3 pixel clocks); 0 = don't support */ 67 /* 1 = support narrow TE signal (<=3 pixel clocks); 0 = don't support */
68 int te_narrow: 1; 68 unsigned te_narrow: 1;
69
70 /* 1 = big endian mode, 0 = little endian mode */
71 unsigned big_endian: 1;
69 72
70 /* Commands used to initiate a framebuffer write. Buffer must be 73 /* Commands used to initiate a framebuffer write. Buffer must be
71 * aligned to 64-byte boundary and size must be a multiple of 4, 74 * aligned to 64-byte boundary and size must be a multiple of 4,