diff options
Diffstat (limited to 'firmware/target/arm/iriver/h10/lcd-h10.c')
-rw-r--r-- | firmware/target/arm/iriver/h10/lcd-h10.c | 174 |
1 files changed, 162 insertions, 12 deletions
diff --git a/firmware/target/arm/iriver/h10/lcd-h10.c b/firmware/target/arm/iriver/h10/lcd-h10.c index e1532bd5a7..a791009b33 100644 --- a/firmware/target/arm/iriver/h10/lcd-h10.c +++ b/firmware/target/arm/iriver/h10/lcd-h10.c | |||
@@ -109,7 +109,7 @@ static inline bool timer_check(int clock_start, int usecs) | |||
109 | 109 | ||
110 | #endif | 110 | #endif |
111 | 111 | ||
112 | static void lcd_wait_write(void) | 112 | static inline void lcd_wait_write(void) |
113 | { | 113 | { |
114 | if ((LCD_BASE & LCD_BUSY_MASK) != 0) { | 114 | if ((LCD_BASE & LCD_BUSY_MASK) != 0) { |
115 | int start = USEC_TIMER; | 115 | int start = USEC_TIMER; |
@@ -121,7 +121,7 @@ static void lcd_wait_write(void) | |||
121 | } | 121 | } |
122 | 122 | ||
123 | /* Send command */ | 123 | /* Send command */ |
124 | static void lcd_send_cmd(int v) | 124 | static inline void lcd_send_cmd(int v) |
125 | { | 125 | { |
126 | lcd_wait_write(); | 126 | lcd_wait_write(); |
127 | LCD_BASE = 0x00000000 | LCD_CMD; | 127 | LCD_BASE = 0x00000000 | LCD_CMD; |
@@ -129,7 +129,7 @@ static void lcd_send_cmd(int v) | |||
129 | } | 129 | } |
130 | 130 | ||
131 | /* Send 16-bit data */ | 131 | /* Send 16-bit data */ |
132 | static void lcd_send_data(int v) | 132 | static inline void lcd_send_data(int v) |
133 | { | 133 | { |
134 | lcd_wait_write(); | 134 | lcd_wait_write(); |
135 | LCD_BASE = ( v & 0xff) | LCD_DATA; /* Send MSB first */ | 135 | LCD_BASE = ( v & 0xff) | LCD_DATA; /* Send MSB first */ |
@@ -137,7 +137,7 @@ static void lcd_send_data(int v) | |||
137 | } | 137 | } |
138 | 138 | ||
139 | /* Send two 16-bit data */ | 139 | /* Send two 16-bit data */ |
140 | static void lcd_send_data2(int v) | 140 | static inline void lcd_send_data2(int v) |
141 | { | 141 | { |
142 | unsigned int vsr = v; | 142 | unsigned int vsr = v; |
143 | lcd_send_data(vsr); | 143 | lcd_send_data(vsr); |
@@ -189,18 +189,168 @@ void lcd_blit(const fb_data* data, int x, int by, int width, | |||
189 | (void)stride; | 189 | (void)stride; |
190 | } | 190 | } |
191 | 191 | ||
192 | #define CSUB_X 2 | ||
193 | #define CSUB_Y 2 | ||
194 | |||
195 | #define RYFAC (31*257) | ||
196 | #define GYFAC (31*257) | ||
197 | #define BYFAC (31*257) | ||
198 | #define RVFAC 11170 /* 31 * 257 * 1.402 */ | ||
199 | #define GVFAC (-5690) /* 31 * 257 * -0.714136 */ | ||
200 | #define GUFAC (-2742) /* 31 * 257 * -0.344136 */ | ||
201 | #define BUFAC 14118 /* 31 * 257 * 1.772 */ | ||
202 | |||
203 | #define ROUNDOFFS (127*257) | ||
204 | #define ROUNDOFFSG (63*257) | ||
205 | |||
206 | /* Performance function to blit a YUV bitmap directly to the LCD */ | ||
192 | void lcd_yuv_blit(unsigned char * const src[3], | 207 | void lcd_yuv_blit(unsigned char * const src[3], |
193 | int src_x, int src_y, int stride, | 208 | int src_x, int src_y, int stride, |
194 | int x, int y, int width, int height) | 209 | int x, int y, int width, int height) |
195 | { | 210 | { |
196 | (void)src; | 211 | int y0, x0, y1, x1; |
197 | (void)src_x; | 212 | int ymax; |
198 | (void)src_y; | 213 | |
199 | (void)stride; | 214 | width = (width + 1) & ~1; |
200 | (void)x; | 215 | |
201 | (void)y; | 216 | /* calculate the drawing region */ |
202 | (void)width; | 217 | x0 = x; |
203 | (void)height; | 218 | x1 = x + width - 1; |
219 | y0 = y; | ||
220 | y1 = y + height - 1; | ||
221 | |||
222 | /* max horiz << 8 | start horiz */ | ||
223 | lcd_send_cmd(R_HORIZ_RAM_ADDR_POS); | ||
224 | lcd_send_data((y0 << 8) | y1); | ||
225 | /* max vert << 8 | start vert */ | ||
226 | lcd_send_cmd(R_VERT_RAM_ADDR_POS); | ||
227 | lcd_send_data((x0 << 8) | x1); | ||
228 | |||
229 | /* position cursor (set AD0-AD15) */ | ||
230 | /* start vert << 8 | start horiz */ | ||
231 | lcd_send_cmd(R_RAM_ADDR_SET); | ||
232 | lcd_send_data(((y0 << 8) | x0)); | ||
233 | |||
234 | /* start drawing */ | ||
235 | lcd_send_cmd(R_WRITE_DATA_2_GRAM); | ||
236 | |||
237 | ymax = y + height - 1 ; | ||
238 | |||
239 | const int stride_div_csub_x = stride/CSUB_X; | ||
240 | |||
241 | for (; y <= ymax ; y++) | ||
242 | { | ||
243 | /* upsampling, YUV->RGB conversion and reduction to RGB565 in one go */ | ||
244 | const unsigned char *ysrc = src[0] + stride * src_y + src_x; | ||
245 | |||
246 | const int uvoffset = stride_div_csub_x * (src_y/CSUB_Y) + | ||
247 | (src_x/CSUB_X); | ||
248 | |||
249 | const unsigned char *usrc = src[1] + uvoffset; | ||
250 | const unsigned char *vsrc = src[2] + uvoffset; | ||
251 | const unsigned char *row_end = ysrc + width; | ||
252 | |||
253 | int y, u, v; | ||
254 | int red1, green1, blue1; | ||
255 | int red2, green2, blue2; | ||
256 | unsigned rbits, gbits, bbits; | ||
257 | |||
258 | int rc, gc, bc; | ||
259 | |||
260 | do | ||
261 | { | ||
262 | u = *usrc++ - 128; | ||
263 | v = *vsrc++ - 128; | ||
264 | rc = RVFAC * v + ROUNDOFFS; | ||
265 | gc = GVFAC * v + GUFAC * u + ROUNDOFFSG; | ||
266 | bc = BUFAC * u + ROUNDOFFS; | ||
267 | |||
268 | /* Pixel 1 */ | ||
269 | y = *ysrc++; | ||
270 | |||
271 | red1 = RYFAC * y + rc; | ||
272 | green1 = GYFAC * y + gc; | ||
273 | blue1 = BYFAC * y + bc; | ||
274 | |||
275 | /* Pixel 2 */ | ||
276 | y = *ysrc++; | ||
277 | red2 = RYFAC * y + rc; | ||
278 | green2 = GYFAC * y + gc; | ||
279 | blue2 = BYFAC * y + bc; | ||
280 | |||
281 | /* Since out of bounds errors are relatively rare, we check two | ||
282 | pixels at once to see if any components are out of bounds, and | ||
283 | then fix whichever is broken. This works due to high values and | ||
284 | negative values both becoming larger than the cutoff when | ||
285 | casted to unsigned. And ORing them together checks all of them | ||
286 | simultaneously. */ | ||
287 | if (((unsigned)(red1 | green1 | blue1 | | ||
288 | red2 | green2 | blue2)) > (RYFAC*255+ROUNDOFFS)) { | ||
289 | if (((unsigned)(red1 | green1 | blue1)) > | ||
290 | (RYFAC*255+ROUNDOFFS)) { | ||
291 | if ((unsigned)red1 > (RYFAC*255+ROUNDOFFS)) | ||
292 | { | ||
293 | if (red1 < 0) | ||
294 | red1 = 0; | ||
295 | else | ||
296 | red1 = (RYFAC*255+ROUNDOFFS); | ||
297 | } | ||
298 | if ((unsigned)green1 > (GYFAC*255+ROUNDOFFSG)) | ||
299 | { | ||
300 | if (green1 < 0) | ||
301 | green1 = 0; | ||
302 | else | ||
303 | green1 = (GYFAC*255+ROUNDOFFSG); | ||
304 | } | ||
305 | if ((unsigned)blue1 > (BYFAC*255+ROUNDOFFS)) | ||
306 | { | ||
307 | if (blue1 < 0) | ||
308 | blue1 = 0; | ||
309 | else | ||
310 | blue1 = (BYFAC*255+ROUNDOFFS); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | if (((unsigned)(red2 | green2 | blue2)) > | ||
315 | (RYFAC*255+ROUNDOFFS)) { | ||
316 | if ((unsigned)red2 > (RYFAC*255+ROUNDOFFS)) | ||
317 | { | ||
318 | if (red2 < 0) | ||
319 | red2 = 0; | ||
320 | else | ||
321 | red2 = (RYFAC*255+ROUNDOFFS); | ||
322 | } | ||
323 | if ((unsigned)green2 > (GYFAC*255+ROUNDOFFSG)) | ||
324 | { | ||
325 | if (green2 < 0) | ||
326 | green2 = 0; | ||
327 | else | ||
328 | green2 = (GYFAC*255+ROUNDOFFSG); | ||
329 | } | ||
330 | if ((unsigned)blue2 > (BYFAC*255+ROUNDOFFS)) | ||
331 | { | ||
332 | if (blue2 < 0) | ||
333 | blue2 = 0; | ||
334 | else | ||
335 | blue2 = (BYFAC*255+ROUNDOFFS); | ||
336 | } | ||
337 | } | ||
338 | } | ||
339 | |||
340 | rbits = red1 >> 16 ; | ||
341 | gbits = green1 >> 15 ; | ||
342 | bbits = blue1 >> 16 ; | ||
343 | lcd_send_data(swap16((rbits << 11) | (gbits << 5) | bbits)); | ||
344 | |||
345 | rbits = red2 >> 16 ; | ||
346 | gbits = green2 >> 15 ; | ||
347 | bbits = blue2 >> 16 ; | ||
348 | lcd_send_data(swap16((rbits << 11) | (gbits << 5) | bbits)); | ||
349 | } | ||
350 | while (ysrc < row_end); | ||
351 | |||
352 | src_y++; | ||
353 | } | ||
204 | } | 354 | } |
205 | 355 | ||
206 | 356 | ||