diff options
Diffstat (limited to 'firmware')
-rw-r--r-- | firmware/drivers/lcd-h300.c | 47 | ||||
-rwxr-xr-x | firmware/drivers/lcd.S | 161 |
2 files changed, 122 insertions, 86 deletions
diff --git a/firmware/drivers/lcd-h300.c b/firmware/drivers/lcd-h300.c index d84edd6b2e..8ee6b1c47e 100644 --- a/firmware/drivers/lcd-h300.c +++ b/firmware/drivers/lcd-h300.c | |||
@@ -77,55 +77,18 @@ static bool display_on=false; /* is the display turned on? */ | |||
77 | 77 | ||
78 | 78 | ||
79 | /* called very frequently - inline! */ | 79 | /* called very frequently - inline! */ |
80 | inline void lcd_write_reg(int reg, int val) | 80 | static inline void lcd_write_reg(int reg, int val) |
81 | { | 81 | { |
82 | *(volatile unsigned short *)0xf0000000 = reg; | 82 | *(volatile unsigned short *)0xf0000000 = reg; |
83 | *(volatile unsigned short *)0xf0000002 = val; | 83 | *(volatile unsigned short *)0xf0000002 = val; |
84 | } | 84 | } |
85 | 85 | ||
86 | /* called very frequently - inline! */ | 86 | /* called very frequently - inline! */ |
87 | inline void lcd_begin_write_gram(void) | 87 | static inline void lcd_begin_write_gram(void) |
88 | { | 88 | { |
89 | *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM; | 89 | *(volatile unsigned short *)0xf0000000 = R_WRITE_DATA_2_GRAM; |
90 | } | 90 | } |
91 | 91 | ||
92 | /* called very frequently - inline! */ | ||
93 | inline void lcd_write_data(const unsigned short* p_bytes, int count) ICODE_ATTR; | ||
94 | inline void lcd_write_data(const unsigned short* p_bytes, int count) | ||
95 | { | ||
96 | int precount = ((-(size_t)p_bytes) & 0xf) / 2; | ||
97 | count -= precount; | ||
98 | while(precount--) | ||
99 | *(volatile unsigned short *)0xf0000002 = *p_bytes++; | ||
100 | while((count -= 8) >= 0) asm ( | ||
101 | "\n\tmovem.l (%[p_bytes]),%%d1-%%d4\ | ||
102 | \n\tswap %%d1\ | ||
103 | \n\tmove.w %%d1,(%[dest])\ | ||
104 | \n\tswap %%d1\ | ||
105 | \n\tmove.w %%d1,(%[dest])\ | ||
106 | \n\tswap %%d2\ | ||
107 | \n\tmove.w %%d2,(%[dest])\ | ||
108 | \n\tswap %%d2\ | ||
109 | \n\tmove.w %%d2,(%[dest])\ | ||
110 | \n\tswap %%d3\ | ||
111 | \n\tmove.w %%d3,(%[dest])\ | ||
112 | \n\tswap %%d3\ | ||
113 | \n\tmove.w %%d3,(%[dest])\ | ||
114 | \n\tswap %%d4\ | ||
115 | \n\tmove.w %%d4,(%[dest])\ | ||
116 | \n\tswap %%d4\ | ||
117 | \n\tmove.w %%d4,(%[dest])\ | ||
118 | \n\tlea.l (16,%[p_bytes]),%[p_bytes]" | ||
119 | : [p_bytes] "+a" (p_bytes) | ||
120 | : [dest] "a" ((volatile unsigned short *)0xf0000002) | ||
121 | : "d1", "d2", "d3", "d4", "memory"); | ||
122 | if (count != 0) { | ||
123 | count += 8; | ||
124 | while(count--) | ||
125 | *(volatile unsigned short *)0xf0000002 = *p_bytes++; | ||
126 | } | ||
127 | } | ||
128 | |||
129 | /*** hardware configuration ***/ | 92 | /*** hardware configuration ***/ |
130 | 93 | ||
131 | void lcd_set_contrast(int val) | 94 | void lcd_set_contrast(int val) |
@@ -406,8 +369,8 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
406 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y); | 369 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, (ymax<<8) | y); |
407 | 370 | ||
408 | /* vert ram addr */ | 371 | /* vert ram addr */ |
409 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x); | 372 | lcd_write_reg(R_VERT_RAM_ADDR_POS,((x+width-1)<<8) | x); |
410 | lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y); | 373 | lcd_write_reg(R_RAM_ADDR_SET, (x<<8) | y); |
411 | lcd_begin_write_gram(); | 374 | lcd_begin_write_gram(); |
412 | 375 | ||
413 | /* Copy specified rectangle bitmap to hardware */ | 376 | /* Copy specified rectangle bitmap to hardware */ |
@@ -421,6 +384,6 @@ void lcd_update_rect(int x, int y, int width, int height) | |||
421 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); | 384 | lcd_write_reg(R_HORIZ_RAM_ADDR_POS, 0xaf00); |
422 | 385 | ||
423 | /* vert ram addr: 0 - 219 */ | 386 | /* vert ram addr: 0 - 219 */ |
424 | lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00); | 387 | lcd_write_reg(R_VERT_RAM_ADDR_POS, 0xdb00); |
425 | } | 388 | } |
426 | } | 389 | } |
diff --git a/firmware/drivers/lcd.S b/firmware/drivers/lcd.S index 79c6e32f33..2b50de5190 100755 --- a/firmware/drivers/lcd.S +++ b/firmware/drivers/lcd.S | |||
@@ -313,62 +313,135 @@ _lcd_write_data: | |||
313 | .type lcd_write_command,@function | 313 | .type lcd_write_command,@function |
314 | 314 | ||
315 | lcd_write_command: | 315 | lcd_write_command: |
316 | move.l (4,%sp),%d0 | 316 | move.l (4,%sp),%d0 |
317 | lea MBAR2,%a1 | 317 | lea MBAR2,%a1 |
318 | move.l #~8,%d1 | 318 | move.l #~8,%d1 |
319 | and.l %d1,(0xb4,%a1) | 319 | and.l %d1,(0xb4,%a1) |
320 | move.w %d0,0xf0000000 | 320 | move.w %d0,0xf0000000 |
321 | rts | 321 | rts |
322 | 322 | ||
323 | .align 2 | 323 | .align 2 |
324 | .global lcd_write_command_ex | 324 | .global lcd_write_command_ex |
325 | .type lcd_write_command_ex,@function | 325 | .type lcd_write_command_ex,@function |
326 | 326 | ||
327 | lcd_write_command_ex: | 327 | lcd_write_command_ex: |
328 | lea MBAR2,%a1 | 328 | lea MBAR2,%a1 |
329 | 329 | ||
330 | move.l (4,%sp),%d0 /* Command */ | 330 | move.l (4,%sp),%d0 /* Command */ |
331 | 331 | ||
332 | move.l #~8,%d1 /* Set A0 = 0 */ | 332 | move.l #~8,%d1 /* Set A0 = 0 */ |
333 | and.l %d1,(0xb4,%a1) | 333 | and.l %d1,(0xb4,%a1) |
334 | move.w %d0,0xf0000000 /* Write to LCD */ | 334 | move.w %d0,0xf0000000 /* Write to LCD */ |
335 | 335 | ||
336 | not.l %d1 /* Set A0 = 1 */ | 336 | not.l %d1 /* Set A0 = 1 */ |
337 | or.l %d1,(0xb4,%a1) | 337 | or.l %d1,(0xb4,%a1) |
338 | 338 | ||
339 | move.l (8,%sp),%d0 /* Data */ | 339 | move.l (8,%sp),%d0 /* Data */ |
340 | cmp.l #0xffffffff,%d0 /* -1? */ | 340 | cmp.l #0xffffffff,%d0 /* -1? */ |
341 | beq.b .last | 341 | beq.b .last |
342 | move.w %d0,0xf0000000 /* Write to LCD */ | 342 | move.w %d0,0xf0000000 /* Write to LCD */ |
343 | 343 | ||
344 | move.l (12,%sp),%d0 /* Data */ | 344 | move.l (12,%sp),%d0 /* Data */ |
345 | cmp.l #0xffffffff,%d0 /* -1? */ | 345 | cmp.l #0xffffffff,%d0 /* -1? */ |
346 | beq.b .last | 346 | beq.b .last |
347 | move.w %d0,0xf0000000 /* Write to LCD */ | 347 | move.w %d0,0xf0000000 /* Write to LCD */ |
348 | 348 | ||
349 | .last: | 349 | .last: |
350 | rts | 350 | rts |
351 | 351 | ||
352 | .align 2 | 352 | .align 2 |
353 | .global lcd_write_data | 353 | .global lcd_write_data |
354 | .type lcd_write_data,@function | 354 | .type lcd_write_data,@function |
355 | 355 | ||
356 | lcd_write_data: | 356 | lcd_write_data: |
357 | move.l (4,%sp),%a0 /* Data pointer */ | 357 | move.l (4,%sp),%a0 /* Data pointer */ |
358 | move.l (8,%sp),%d0 /* Length */ | 358 | move.l (8,%sp),%d0 /* Length */ |
359 | lea MBAR2,%a1 | 359 | lea MBAR2,%a1 |
360 | moveq #8,%d1 | 360 | moveq #8,%d1 |
361 | or.l %d1,(0xb4,%a1) | 361 | or.l %d1,(0xb4,%a1) |
362 | 362 | ||
363 | lea 0xf0000000,%a1 | 363 | lea 0xf0000000,%a1 |
364 | .loop: | 364 | .loop: |
365 | /* When running in IRAM, this loop takes 7 cycles plus the LCD write. | 365 | /* When running in IRAM, this loop takes 7 cycles plus the LCD write. |
366 | The 7 cycles are necessary to follow the LCD timing specs | 366 | The 7 cycles are necessary to follow the LCD timing specs |
367 | at 140MHz */ | 367 | at 140MHz */ |
368 | move.b (%a0)+,%d1 /* 3(1/0) */ | 368 | move.b (%a0)+,%d1 /* 3(1/0) */ |
369 | move.w %d1,(%a1) /* 1(0/1) */ | 369 | move.w %d1,(%a1) /* 1(0/1) */ |
370 | subq.l #1,%d0 /* 1(0/0) */ | 370 | subq.l #1,%d0 /* 1(0/0) */ |
371 | nop /* 1(0/0) */ | 371 | nop /* 1(0/0) */ |
372 | bne .loop /* 2(0/0) */ | 372 | bne .loop /* 2(0/0) */ |
373 | rts | 373 | rts |
374 | #elif defined(IRIVER_H300_SERIES) | ||
375 | .section .icode,"ax",@progbits | ||
376 | |||
377 | .align 2 | ||
378 | .global lcd_write_data | ||
379 | .type lcd_write_data,@function | ||
380 | |||
381 | lcd_write_data: | ||
382 | move.l (4,%sp),%a0 /* data pointer */ | ||
383 | move.l (8,%sp),%d0 /* length in words */ | ||
384 | add.l %d0,%d0 /* words -> bytes */ | ||
385 | add.l %a0,%d0 /* -> end address */ | ||
386 | lea.l 0xf0000002,%a1 /* LCD data port */ | ||
387 | |||
388 | moveq.l #31,%d1 | ||
389 | add.l %a0,%d1 | ||
390 | and.l #0xFFFFFFF0,%d1 /* %d1 = first line bound + 16 */ | ||
391 | cmp.l %d1,%d0 /* at least one full line to send? */ | ||
392 | blo.b .words2_loop /* no: skip to word loop */ | ||
393 | |||
394 | subq.l #8,%d1 | ||
395 | subq.l #8,%d1 /* %d1 = first line bound */ | ||
396 | |||
397 | cmp.l %a0,%d1 /* any leading words? */ | ||
398 | bls.b .words1_end /* no: skip leading word loop */ | ||
399 | |||
400 | .words1_loop: | ||
401 | move.w (%a0)+,(%a1) /* transfer word */ | ||
402 | cmp.l %a0,%d1 /* run %a0 up to first line bound */ | ||
403 | bhi.b .words1_loop | ||
404 | |||
405 | .words1_end: | ||
406 | lea.l (-16,%sp),%sp /* free up some registers */ | ||
407 | movem.l %d2-%d4/%a2,(%sp) | ||
408 | move.l %d0,%a2 | ||
409 | lea.l (-15,%a2),%a2 /* %a2 = end address - 15 (one line/pass) */ | ||
410 | |||
411 | /* burst-optimised line transfers */ | ||
412 | .line_loop: | ||
413 | movem.l (%a0),%d1-%d4 /* burst-read line */ | ||
414 | lea.l (16,%a0),%a0 /* increment address */ | ||
415 | swap %d1 /* send data to LCD in correct order... */ | ||
416 | move.w %d1,(%a1) | ||
417 | swap %d1 | ||
418 | move.w %d1,(%a1) | ||
419 | swap %d2 | ||
420 | move.w %d2,(%a1) | ||
421 | swap %d2 | ||
422 | move.w %d2,(%a1) | ||
423 | swap %d3 | ||
424 | move.w %d3,(%a1) | ||
425 | swap %d3 | ||
426 | move.w %d3,(%a1) | ||
427 | swap %d4 | ||
428 | move.w %d4,(%a1) | ||
429 | swap %d4 | ||
430 | move.w %d4,(%a1) | ||
431 | cmp.l %a0,%a2 /* run %a0 up to last line bound */ | ||
432 | bhi.b .line_loop | ||
433 | |||
434 | movem.l (%sp),%d2-%d4/%a2 | ||
435 | lea.l (16,%sp),%sp /* restore registers */ | ||
436 | |||
437 | cmp.l %a0,%d0 /* any trailing words? */ | ||
438 | bls.b .words2_end /* no: get otta here */ | ||
439 | |||
440 | .words2_loop: | ||
441 | move.w (%a0)+,(%a1) /* transfer word */ | ||
442 | cmp.l %a0,%d0 /* run %a0 up to end address */ | ||
443 | bhi.b .words2_loop | ||
444 | |||
445 | .words2_end: | ||
446 | rts | ||
374 | #endif | 447 | #endif |