summaryrefslogtreecommitdiff
path: root/firmware
diff options
context:
space:
mode:
Diffstat (limited to 'firmware')
-rw-r--r--firmware/drivers/lcd-ipodvideo.c164
-rw-r--r--firmware/export/lcd.h2
2 files changed, 163 insertions, 3 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
121static int finishup_needed = 0;
122
121/* Update a fraction of the display. */ 123/* Update a fraction of the display. */
122void lcd_update_rect(int x, int y, int width, int height) ICODE_ATTR; 124void lcd_update_rect(int x, int y, int width, int height) ICODE_ATTR;
123void lcd_update_rect(int x, int y, int width, int height) 125void 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 */
222void 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}
diff --git a/firmware/export/lcd.h b/firmware/export/lcd.h
index 7551a1ab23..c3ad4f97d9 100644
--- a/firmware/export/lcd.h
+++ b/firmware/export/lcd.h
@@ -72,7 +72,7 @@ extern void lcd_puts_scroll_style(int x, int y, const unsigned char* string,
72extern void lcd_icon(int icon, bool enable); 72extern void lcd_icon(int icon, bool enable);
73 73
74#if CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \ 74#if CONFIG_LCD == LCD_IPODCOLOR || CONFIG_LCD == LCD_IPODNANO \
75 || CONFIG_LCD == LCD_H300 75 || CONFIG_LCD == LCD_H300 || CONFIG_LCD == LCD_IPODVIDEO
76void lcd_yuv_blit(unsigned char * const src[3], 76void lcd_yuv_blit(unsigned char * const src[3],
77 int src_x, int src_y, int stride, 77 int src_x, int src_y, int stride,
78 int x, int y, int width, int height); 78 int x, int y, int width, int height);