diff options
Diffstat (limited to 'firmware/target/arm')
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | 124 | ||||
-rw-r--r-- | firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h | 8 |
2 files changed, 132 insertions, 0 deletions
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c index ad417663fe..d4d5b97ca7 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c +++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-sansaconnect.c | |||
@@ -153,6 +153,130 @@ void lcd_init_device(void) | |||
153 | lcd_on = true; | 153 | lcd_on = true; |
154 | } | 154 | } |
155 | 155 | ||
156 | #ifdef LCD_USE_DMA | ||
157 | static void dma_lcd_copy_buffer_rect(int x, int y, int width, int height) | ||
158 | { | ||
159 | char *dst, *src; | ||
160 | |||
161 | /* Image buffer A is 4KW, every pixel is one Word */ | ||
162 | /* lines is maximum number of lines we can transfer in single run */ | ||
163 | int lines = 4096/width; | ||
164 | if (lines > height) | ||
165 | lines = height; | ||
166 | |||
167 | /* Set source and destination addresses */ | ||
168 | dst = (char*)(FRAME + LCD_WIDTH*y + x); | ||
169 | src = (char*)(&lcd_framebuffer[y][x]); | ||
170 | |||
171 | /* Flush cache to memory */ | ||
172 | commit_dcache(); | ||
173 | |||
174 | /* Addresses are relative to start of SDRAM */ | ||
175 | src -= CONFIG_SDRAM_START; | ||
176 | dst -= CONFIG_SDRAM_START; | ||
177 | |||
178 | /* Enable Image Buffer clock */ | ||
179 | bitset16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF); | ||
180 | |||
181 | /* Use Image Buffer A for DMA */ | ||
182 | COP_BUF_MUX0 = (COP_BUF_MUX0 & 0xFFF0) | 0x0003; | ||
183 | |||
184 | /* Setup buffer offsets and transfer width/height */ | ||
185 | COP_BUF_LOFST = width; | ||
186 | COP_DMA_XNUM = width; | ||
187 | COP_DMA_YNUM = lines; | ||
188 | |||
189 | /* DMA: No byte SWAP, no transformation, data bus shift down 0 bit */ | ||
190 | COP_IMG_MODE &= 0xC0; | ||
191 | |||
192 | /* Set the start address of buffer */ | ||
193 | COP_BUF_ADDR = 0x0000; | ||
194 | |||
195 | /* Setup SDRAM stride */ | ||
196 | COP_SDEM_LOFST = LCD_WIDTH; | ||
197 | |||
198 | do { | ||
199 | int addr; | ||
200 | |||
201 | addr = (int)src; | ||
202 | addr >>= 1; /* Addresses are in 16-bit words */ | ||
203 | |||
204 | /* Setup the registers to initiate the read from SDRAM */ | ||
205 | COP_SDEM_ADDRH = addr >> 16; | ||
206 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
207 | |||
208 | /* Set direction and start */ | ||
209 | COP_DMA_CTRL = 0x0001; | ||
210 | COP_DMA_CTRL |= 0x0002; | ||
211 | |||
212 | /* Wait for read to finish */ | ||
213 | while (COP_DMA_CTRL & 0x02) {}; | ||
214 | |||
215 | addr = (int)dst; | ||
216 | addr >>= 1; | ||
217 | |||
218 | COP_SDEM_ADDRH = addr >> 16; | ||
219 | COP_SDEM_ADDRL = addr & 0xFFFF; | ||
220 | |||
221 | /* Set direction and start transfer */ | ||
222 | COP_DMA_CTRL = 0x0000; | ||
223 | COP_DMA_CTRL |= 0x0002; | ||
224 | |||
225 | /* Wait for the transfer to complete */ | ||
226 | while (COP_DMA_CTRL & 0x02) {}; | ||
227 | |||
228 | /* Decrease height, update pointers */ | ||
229 | src += (LCD_WIDTH << 1)*lines; | ||
230 | dst += (LCD_WIDTH << 1)*lines; | ||
231 | |||
232 | height -= lines; | ||
233 | if (height < lines) | ||
234 | { | ||
235 | lines = height; | ||
236 | COP_DMA_YNUM = height; | ||
237 | } | ||
238 | } while (height > 0); | ||
239 | |||
240 | /* Disable Image Buffer clock */ | ||
241 | bitclr16(&IO_CLK_MOD1, CLK_MOD1_IMGBUF); | ||
242 | } | ||
243 | |||
244 | /* Update a fraction of the display. */ | ||
245 | void lcd_update_rect(int x, int y, int width, int height) | ||
246 | __attribute__ ((section(".icode"))); | ||
247 | void lcd_update_rect(int x, int y, int width, int height) | ||
248 | { | ||
249 | if (!lcd_on) | ||
250 | return; | ||
251 | |||
252 | if ((width | height) < 0) | ||
253 | return; /* Nothing left to do */ | ||
254 | |||
255 | if (x + width > LCD_WIDTH) | ||
256 | width = LCD_WIDTH - x; /* Clip right */ | ||
257 | if (x < 0) | ||
258 | width += x, x = 0; /* Clip left */ | ||
259 | |||
260 | if (y + height > LCD_HEIGHT) | ||
261 | height = LCD_HEIGHT - y; /* Clip bottom */ | ||
262 | if (y < 0) | ||
263 | height += y, y = 0; /* Clip top */ | ||
264 | |||
265 | dma_lcd_copy_buffer_rect(x, y, width, height); | ||
266 | } | ||
267 | |||
268 | /* Update the display. | ||
269 | This must be called after all other LCD functions that change the display. */ | ||
270 | void lcd_update(void) __attribute__ ((section(".icode"))); | ||
271 | void lcd_update(void) | ||
272 | { | ||
273 | if (!lcd_on) | ||
274 | return; | ||
275 | |||
276 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | ||
277 | } | ||
278 | #endif | ||
279 | |||
156 | void lcd_set_contrast(int val) { | 280 | void lcd_set_contrast(int val) { |
157 | (void) val; | 281 | (void) val; |
158 | // TODO: | 282 | // TODO: |
diff --git a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h index 60d5df69c8..6a62140b27 100644 --- a/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h +++ b/firmware/target/arm/tms320dm320/sansa-connect/lcd-target.h | |||
@@ -24,6 +24,14 @@ | |||
24 | 24 | ||
25 | #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) | 25 | #define LCD_FRAMEBUF_ADDR(col, row) ((fb_data *)FRAME + (row)*LCD_WIDTH + (col)) |
26 | 26 | ||
27 | /* Comment this to remove Image Buffer DMA usage */ | ||
28 | #define LCD_USE_DMA | ||
29 | |||
30 | #ifdef LCD_USE_DMA | ||
31 | #define LCD_OPTIMIZED_UPDATE | ||
32 | #define LCD_OPTIMIZED_UPDATE_RECT | ||
33 | #endif | ||
34 | |||
27 | void lcd_awake(void); | 35 | void lcd_awake(void); |
28 | 36 | ||
29 | #endif /* LCD_TARGET_H */ | 37 | #endif /* LCD_TARGET_H */ |