diff options
Diffstat (limited to 'firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c')
-rw-r--r-- | firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | 121 |
1 files changed, 89 insertions, 32 deletions
diff --git a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c index 3e08ba4dff..141b890861 100644 --- a/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c +++ b/firmware/target/arm/as3525/sansa-fuze/lcd-fuze.c | |||
@@ -37,7 +37,9 @@ | |||
37 | #define R_WRITE_DATA_2_GRAM 0x22 | 37 | #define R_WRITE_DATA_2_GRAM 0x22 |
38 | 38 | ||
39 | #define R_ENTRY_MODE_HORZ 0x7030 | 39 | #define R_ENTRY_MODE_HORZ 0x7030 |
40 | #define R_ENTRY_MODE_VERT 0x7038 | ||
40 | 41 | ||
42 | static unsigned lcd_yuv_options SHAREDBSS_ATTR = 0; | ||
41 | static bool display_on = false; /* is the display turned on? */ | 43 | static bool display_on = false; /* is the display turned on? */ |
42 | static bool display_flipped = false; | 44 | static bool display_flipped = false; |
43 | static int xoffset = 20; /* needed for flip */ | 45 | static int xoffset = 20; /* needed for flip */ |
@@ -189,7 +191,7 @@ void lcd_enable(bool on) | |||
189 | * avoid irritating flash on backlight on */ | 191 | * avoid irritating flash on backlight on */ |
190 | while(delay--); | 192 | while(delay--); |
191 | lcd_activation_call_hook(); | 193 | lcd_activation_call_hook(); |
192 | 194 | ||
193 | } | 195 | } |
194 | else | 196 | else |
195 | { | 197 | { |
@@ -210,22 +212,94 @@ bool lcd_active(void) | |||
210 | 212 | ||
211 | /*** update functions ***/ | 213 | /*** update functions ***/ |
212 | 214 | ||
213 | /* Performance function to blit a YUV bitmap directly to the LCD | 215 | /* Set horizontal window addresses */ |
214 | * src_x, src_y, width and height should be even | 216 | static void lcd_window_x(int xmin, int xmax) |
215 | * x, y, width and height have to be within LCD bounds | 217 | { |
216 | */ | 218 | xmin += xoffset; |
219 | xmax += xoffset; | ||
220 | lcd_write_reg(0x46, (xmax << 8) | xmin); | ||
221 | lcd_write_reg(0x20, xmin); | ||
222 | } | ||
223 | |||
224 | /* Set vertical window addresses */ | ||
225 | static void lcd_window_y(int ymin, int ymax) | ||
226 | { | ||
227 | lcd_write_reg(0x47, ymax); | ||
228 | lcd_write_reg(0x48, ymin); | ||
229 | lcd_write_reg(0x21, ymin); | ||
230 | } | ||
231 | |||
232 | void lcd_yuv_set_options(unsigned options) | ||
233 | { | ||
234 | lcd_yuv_options = options; | ||
235 | } | ||
236 | |||
237 | /* Line write helper function for lcd_yuv_blit. Write two lines of yuv420. */ | ||
238 | extern void lcd_write_yuv420_lines(unsigned char const * const src[3], | ||
239 | int width, | ||
240 | int stride); | ||
241 | extern void lcd_write_yuv420_lines_odither(unsigned char const * const src[3], | ||
242 | int width, | ||
243 | int stride, | ||
244 | int x_screen, /* To align dither pattern */ | ||
245 | int y_screen); | ||
246 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
217 | void lcd_blit_yuv(unsigned char * const src[3], | 247 | void lcd_blit_yuv(unsigned char * const src[3], |
218 | int src_x, int src_y, int stride, | 248 | int src_x, int src_y, int stride, |
219 | int x, int y, int width, int height) | 249 | int x, int y, int width, int height) |
220 | { | 250 | { |
221 | (void)src; | 251 | unsigned char const * yuv_src[3]; |
222 | (void)src_x; | 252 | off_t z; |
223 | (void)src_y; | 253 | |
224 | (void)stride; | 254 | lcd_busy = true; |
225 | (void)x; | 255 | |
226 | (void)y; | 256 | lcd_write_reg(R_ENTRY_MODE, R_ENTRY_MODE_VERT); |
227 | (void)width; | 257 | |
228 | (void)height; | 258 | /* Sorry, but width and height must be >= 2 or else */ |
259 | width &= ~1; | ||
260 | height >>= 1; | ||
261 | |||
262 | z = stride*src_y; | ||
263 | yuv_src[0] = src[0] + z + src_x; | ||
264 | yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1); | ||
265 | yuv_src[2] = src[2] + (yuv_src[1] - src[1]); | ||
266 | |||
267 | lcd_window_x(x, x + width - 1); | ||
268 | |||
269 | if (lcd_yuv_options & LCD_YUV_DITHER) | ||
270 | { | ||
271 | do | ||
272 | { | ||
273 | lcd_window_y(y, y + 1); | ||
274 | /* Start write to GRAM */ | ||
275 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
276 | |||
277 | lcd_write_yuv420_lines_odither(yuv_src, width, stride, x, y); | ||
278 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
279 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
280 | yuv_src[2] += stride >> 1; | ||
281 | y += 2; | ||
282 | } | ||
283 | while (--height > 0); | ||
284 | } | ||
285 | else | ||
286 | { | ||
287 | do | ||
288 | { | ||
289 | lcd_window_y(y, y + 1); | ||
290 | /* Start write to GRAM */ | ||
291 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | ||
292 | |||
293 | lcd_write_yuv420_lines(yuv_src, width, stride); | ||
294 | yuv_src[0] += stride << 1; /* Skip down two luma lines */ | ||
295 | yuv_src[1] += stride >> 1; /* Skip down one chroma line */ | ||
296 | yuv_src[2] += stride >> 1; | ||
297 | y += 2; | ||
298 | } | ||
299 | while (--height > 0); | ||
300 | } | ||
301 | |||
302 | lcd_busy = false; | ||
229 | } | 303 | } |
230 | 304 | ||
231 | void lcd_init_device() | 305 | void lcd_init_device() |
@@ -242,23 +316,6 @@ void lcd_init_device() | |||
242 | _display_on(); | 316 | _display_on(); |
243 | } | 317 | } |
244 | 318 | ||
245 | /* Set horizontal window addresses */ | ||
246 | void lcd_window_x(int xmin, int xmax) | ||
247 | { | ||
248 | xmin += xoffset; | ||
249 | xmax += xoffset; | ||
250 | lcd_write_reg(0x46, (xmax << 8) | xmin); | ||
251 | lcd_write_reg(0x20, xmin); | ||
252 | } | ||
253 | |||
254 | /* Set vertical window addresses */ | ||
255 | void lcd_window_y(int ymin, int ymax) | ||
256 | { | ||
257 | lcd_write_reg(0x47, ymax); | ||
258 | lcd_write_reg(0x48, ymin); | ||
259 | lcd_write_reg(0x21, ymin); | ||
260 | } | ||
261 | |||
262 | /* Update the display. | 319 | /* Update the display. |
263 | This must be called after all other LCD functions that change the display. */ | 320 | This must be called after all other LCD functions that change the display. */ |
264 | void lcd_update(void) | 321 | void lcd_update(void) |
@@ -272,7 +329,7 @@ void lcd_update(void) | |||
272 | lcd_window_x(0, LCD_WIDTH - 1); | 329 | lcd_window_x(0, LCD_WIDTH - 1); |
273 | lcd_window_y(0, LCD_HEIGHT - 1); | 330 | lcd_window_y(0, LCD_HEIGHT - 1); |
274 | 331 | ||
275 | /* Start write to GRAM */ | 332 | /* Start write to GRAM */ |
276 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 333 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
277 | 334 | ||
278 | /* Write data */ | 335 | /* Write data */ |
@@ -313,7 +370,7 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
313 | lcd_window_x(x, xmax); | 370 | lcd_window_x(x, xmax); |
314 | lcd_window_y(y, ymax); | 371 | lcd_window_y(y, ymax); |
315 | 372 | ||
316 | /* Start write to GRAM */ | 373 | /* Start write to GRAM */ |
317 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); | 374 | lcd_write_cmd(R_WRITE_DATA_2_GRAM); |
318 | 375 | ||
319 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; | 376 | ptr = (unsigned short *)&lcd_framebuffer[y][x]; |