summaryrefslogtreecommitdiffstats
path: root/firmware/target/arm/ipod/lcd-color_nano.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/ipod/lcd-color_nano.c')
-rw-r--r--firmware/target/arm/ipod/lcd-color_nano.c56
1 files changed, 56 insertions, 0 deletions
diff --git a/firmware/target/arm/ipod/lcd-color_nano.c b/firmware/target/arm/ipod/lcd-color_nano.c
index 71ae22cb23..67d26aa862 100644
--- a/firmware/target/arm/ipod/lcd-color_nano.c
+++ b/firmware/target/arm/ipod/lcd-color_nano.c
@@ -202,6 +202,62 @@ static void lcd_setup_drawing_region(int x, int y, int width, int height)
}
}
+/* Line write helper function for lcd_yuv_blit. Writes two lines of yuv420. */
+extern void lcd_write_yuv420_lines(unsigned char const * const src[3],
+ const unsigned int lcd_baseadress,
+ int width,
+ int stride);
+
+/* Performance function to blit a YUV bitmap directly to the LCD */
+void lcd_blit_yuv(unsigned char * const src[3],
+ int src_x, int src_y, int stride,
+ int x, int y, int width, int height)
+{
+ int z;
+ unsigned char const * yuv_src[3];
+
+ width = (width + 1) & ~1; /* ensure width is even */
+ height = (height + 1) & ~1; /* ensure height is even */
+
+ lcd_setup_drawing_region(x, y, width, height);
+
+ z = stride * src_y;
+ yuv_src[0] = src[0] + z + src_x;
+ yuv_src[1] = src[1] + (z >> 2) + (src_x >> 1);
+ yuv_src[2] = src[2] + (yuv_src[1] - src[1]);
+
+ while (height > 0) {
+ int r, h, pixels_to_write;
+
+ pixels_to_write = (width * height) * 2;
+ h = height;
+
+ /* calculate how much we can do in one go */
+ if (pixels_to_write > 0x10000) {
+ h = ((0x10000/2) / width) & ~1; /* ensure h is even */
+ pixels_to_write = (width * h) * 2;
+ }
+
+ LCD2_BLOCK_CTRL = 0x10000080;
+ LCD2_BLOCK_CONFIG = 0xc0010000 | (pixels_to_write - 1);
+ LCD2_BLOCK_CTRL = 0x34000000;
+
+ r = h>>1; /* lcd_write_yuv420_lines writes two lines at once */
+ do {
+ lcd_write_yuv420_lines(yuv_src, LCD2_BASE, width, stride);
+ yuv_src[0] += stride << 1;
+ yuv_src[1] += stride >> 1;
+ yuv_src[2] += stride >> 1;
+ } while (--r > 0);
+
+ /* transfer of pixels_to_write bytes finished */
+ while (!(LCD2_BLOCK_CTRL & LCD2_BLOCK_READY));
+ LCD2_BLOCK_CONFIG = 0;
+
+ height -= h;
+ }
+}
+
/* Helper function writes 'count' consecutive pixels from src to LCD IF */
static void lcd_write_line(int count, unsigned long *src)
{