diff options
author | Aidan MacDonald <amachronic@protonmail.com> | 2021-05-25 23:41:08 +0100 |
---|---|---|
committer | Aidan MacDonald <amachronic@protonmail.com> | 2021-06-03 22:54:59 +0000 |
commit | cec6422ace933fecc02053c0fa6b239f7a6792e5 (patch) | |
tree | 9dd7d69c889831337853e5ab000f515a5d72cb39 /firmware/target | |
parent | a6b5de6a89c82ec8c6d0d7bafb9a377f9035d46b (diff) | |
download | rockbox-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
Diffstat (limited to 'firmware/target')
-rw-r--r-- | firmware/target/mips/ingenic_x1000/lcd-x1000.c | 61 | ||||
-rw-r--r-- | firmware/target/mips/ingenic_x1000/lcd-x1000.h | 23 |
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 */ |
66 | static volatile int fbcopy_done; | 66 | static 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 */ |
69 | static bool lcd_sleeping = false; | 70 | static 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 | ||
275 | static void lcd_dma_start(void) | 277 | static 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 | ||
293 | static 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 | |||
308 | static bool lcd_wait_frame(void) | 297 | static 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 | ||
313 | static 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 | |||
324 | static void lcd_send(uint32_t d) | 333 | static 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 | ||
39 | struct lcd_tgt_config { | 39 | struct 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, |