diff options
author | Dave Chapman <dave@dchapman.com> | 2006-08-08 21:28:08 +0000 |
---|---|---|
committer | Dave Chapman <dave@dchapman.com> | 2006-08-08 21:28:08 +0000 |
commit | 13b23fbcdb38dc2865d550ae5cc5bdaa8e444264 (patch) | |
tree | 460022828d88e5c60335b0e06ecc4ec339cd7c4c /firmware/drivers | |
parent | c4c56a3da7a3ef868b853fb8f434198d6b9f9ee9 (diff) | |
download | rockbox-13b23fbcdb38dc2865d550ae5cc5bdaa8e444264.tar.gz rockbox-13b23fbcdb38dc2865d550ae5cc5bdaa8e444264.zip |
Implementation of lcd_yuv_blit() for the ipod 5g.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@10487 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware/drivers')
-rw-r--r-- | firmware/drivers/lcd-ipodvideo.c | 164 |
1 files changed, 162 insertions, 2 deletions
diff --git a/firmware/drivers/lcd-ipodvideo.c b/firmware/drivers/lcd-ipodvideo.c index b94ab0b992..25ae235c0a 100644 --- a/firmware/drivers/lcd-ipodvideo.c +++ b/firmware/drivers/lcd-ipodvideo.c | |||
@@ -118,12 +118,12 @@ static unsigned lcd_bcm_read32(unsigned address) { | |||
118 | return inw(0x30000000) | inw(0x30000000) << 16; | 118 | return inw(0x30000000) | inw(0x30000000) << 16; |
119 | } | 119 | } |
120 | 120 | ||
121 | static int finishup_needed = 0; | ||
122 | |||
121 | /* Update a fraction of the display. */ | 123 | /* Update a fraction of the display. */ |
122 | void lcd_update_rect(int x, int y, int width, int height) ICODE_ATTR; | 124 | void lcd_update_rect(int x, int y, int width, int height) ICODE_ATTR; |
123 | void lcd_update_rect(int x, int y, int width, int height) | 125 | void lcd_update_rect(int x, int y, int width, int height) |
124 | { | 126 | { |
125 | static int finishup_needed = 0; | ||
126 | |||
127 | { | 127 | { |
128 | int endy = x + width; | 128 | int endy = x + width; |
129 | /* Ensure x and width are both even - so we can read 32-bit aligned | 129 | /* Ensure x and width are both even - so we can read 32-bit aligned |
@@ -204,3 +204,163 @@ void lcd_update(void) | |||
204 | { | 204 | { |
205 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); | 205 | lcd_update_rect(0, 0, LCD_WIDTH, LCD_HEIGHT); |
206 | } | 206 | } |
207 | |||
208 | #define CSUB_X 2 | ||
209 | #define CSUB_Y 2 | ||
210 | |||
211 | #define RYFAC (31*257) | ||
212 | #define GYFAC (63*257) | ||
213 | #define BYFAC (31*257) | ||
214 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
215 | #define GVFAC (-11563) /* 63 * 257 * -0.714136 */ | ||
216 | #define GUFAC (-5572) /* 63 * 257 * -0.344136 */ | ||
217 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
218 | |||
219 | #define ROUNDOFFS (127*257) | ||
220 | |||
221 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
222 | void lcd_yuv_blit(unsigned char * const src[3], | ||
223 | int src_x, int src_y, int stride, | ||
224 | int x, int y, int width, int height) | ||
225 | { | ||
226 | int ymax; | ||
227 | |||
228 | width = (width + 1) & ~1; | ||
229 | |||
230 | if (finishup_needed) { | ||
231 | unsigned int data; | ||
232 | /* Bottom-half of original lcd_bcm_finishup() function */ | ||
233 | do { | ||
234 | /* This function takes about 14ms to execute - so we yield() */ | ||
235 | yield(); | ||
236 | data = lcd_bcm_read32(0x1F8); | ||
237 | } while (data == 0xFFFA0005 || data == 0xFFFF); | ||
238 | } | ||
239 | |||
240 | lcd_bcm_read32(0x1FC); | ||
241 | |||
242 | { | ||
243 | int rect1, rect2, rect3, rect4; | ||
244 | int count = (width * height) << 1; | ||
245 | /* calculate the drawing region */ | ||
246 | rect1 = x; /* start horiz */ | ||
247 | rect2 = y; /* start vert */ | ||
248 | rect3 = (x + width) - 1; /* max horiz */ | ||
249 | rect4 = (y + height) - 1; /* max vert */ | ||
250 | |||
251 | /* setup the drawing region */ | ||
252 | lcd_bcm_setup_rect(0x34, rect1, rect2, rect3, rect4, count); | ||
253 | } | ||
254 | |||
255 | /* write out destination address as two 16bit values */ | ||
256 | outw((0xE0020 & 0xffff), 0x30010000); | ||
257 | outw((0xE0020 >> 16), 0x30010000); | ||
258 | |||
259 | /* wait for it to be write ready */ | ||
260 | while ((inw(0x30030000) & 0x2) == 0); | ||
261 | |||
262 | ymax = y + height - 1 ; | ||
263 | |||
264 | for (; y <= ymax ; y++) | ||
265 | { | ||
266 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
267 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
268 | const unsigned char *usrc = src[1] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
269 | + (src_x/CSUB_X); | ||
270 | const unsigned char *vsrc = src[2] + (stride/CSUB_X) * (src_y/CSUB_Y) | ||
271 | + (src_x/CSUB_X); | ||
272 | const unsigned char *row_end = ysrc + width; | ||
273 | |||
274 | int y, u, v; | ||
275 | int red, green, blue; | ||
276 | unsigned rbits, gbits, bbits; | ||
277 | unsigned short pixel; | ||
278 | |||
279 | int rc, gc, bc; | ||
280 | |||
281 | do | ||
282 | { | ||
283 | u = *usrc++ - 128; | ||
284 | v = *vsrc++ - 128; | ||
285 | rc = RVFAC * v + ROUNDOFFS; | ||
286 | gc = GVFAC * v + GUFAC * u + ROUNDOFFS; | ||
287 | bc = BUFAC * u + ROUNDOFFS; | ||
288 | |||
289 | /* Pixel 1 */ | ||
290 | y = *ysrc++; | ||
291 | red = RYFAC * y + rc; | ||
292 | green = GYFAC * y + gc; | ||
293 | blue = BYFAC * y + bc; | ||
294 | |||
295 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
296 | { | ||
297 | if (red < 0) | ||
298 | red = 0; | ||
299 | else | ||
300 | red = (RYFAC*255+ROUNDOFFS); | ||
301 | } | ||
302 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
303 | { | ||
304 | if (green < 0) | ||
305 | green = 0; | ||
306 | else | ||
307 | green = (GYFAC*255+ROUNDOFFS); | ||
308 | } | ||
309 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
310 | { | ||
311 | if (blue < 0) | ||
312 | blue = 0; | ||
313 | else | ||
314 | blue = (BYFAC*255+ROUNDOFFS); | ||
315 | } | ||
316 | rbits = ((unsigned)red) >> 16 ; | ||
317 | gbits = ((unsigned)green) >> 16 ; | ||
318 | bbits = ((unsigned)blue) >> 16 ; | ||
319 | |||
320 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | ||
321 | |||
322 | /* Pixel 2 */ | ||
323 | y = *ysrc++; | ||
324 | red = RYFAC * y + rc; | ||
325 | green = GYFAC * y + gc; | ||
326 | blue = BYFAC * y + bc; | ||
327 | |||
328 | if ((unsigned)red > (RYFAC*255+ROUNDOFFS)) | ||
329 | { | ||
330 | if (red < 0) | ||
331 | red = 0; | ||
332 | else | ||
333 | red = (RYFAC*255+ROUNDOFFS); | ||
334 | } | ||
335 | if ((unsigned)green > (GYFAC*255+ROUNDOFFS)) | ||
336 | { | ||
337 | if (green < 0) | ||
338 | green = 0; | ||
339 | else | ||
340 | green = (GYFAC*255+ROUNDOFFS); | ||
341 | } | ||
342 | if ((unsigned)blue > (BYFAC*255+ROUNDOFFS)) | ||
343 | { | ||
344 | if (blue < 0) | ||
345 | blue = 0; | ||
346 | else | ||
347 | blue = (BYFAC*255+ROUNDOFFS); | ||
348 | } | ||
349 | rbits = ((unsigned)red) >> 16 ; | ||
350 | gbits = ((unsigned)green) >> 16 ; | ||
351 | bbits = ((unsigned)blue) >> 16 ; | ||
352 | |||
353 | outw((rbits << 11) | (gbits << 5) | bbits, 0x30000000); | ||
354 | } | ||
355 | while (ysrc < row_end); | ||
356 | |||
357 | src_y++; | ||
358 | } | ||
359 | |||
360 | /* Top-half of original lcd_bcm_finishup() function */ | ||
361 | outw(0x31, 0x30030000); | ||
362 | |||
363 | lcd_bcm_read32(0x1FC); | ||
364 | |||
365 | finishup_needed = 1; | ||
366 | } | ||