summaryrefslogtreecommitdiff
path: root/firmware/target/arm/iriver
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/iriver')
-rw-r--r--firmware/target/arm/iriver/h10/lcd-h10.c174
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
112static void lcd_wait_write(void) 112static 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 */
124static void lcd_send_cmd(int v) 124static 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 */
132static void lcd_send_data(int v) 132static 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 */
140static void lcd_send_data2(int v) 140static 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 */
192void lcd_yuv_blit(unsigned char * const src[3], 207void 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