Smaller & faster grey blitting on greyscale ipods, based on an idea by Mike Sevakis...
[kugel-rb.git] / firmware / target / arm / ipod / lcd-as-gray.S
blob4579d15f7197de76bf4dcd841332e1608ffc6388
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id$
9  *
10  * Copyright (C) 2008 by Jens Arnold
11  *
12  * This program is free software; you can redistribute it and/or
13  * modify it under the terms of the GNU General Public License
14  * as published by the Free Software Foundation; either version 2
15  * of the License, or (at your option) any later version.
16  *
17  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18  * KIND, either express or implied.
19  *
20  ****************************************************************************/
22 #include "config.h"
23 #include "cpu.h"
25 #if CONFIG_CPU == PP5002
26     .section    .icode,"ax",%progbits
27 #else
28     .text
29 #endif
30     .align      2
33     .global     lcd_write_data
34     .type       lcd_write_data,%function
36 lcd_write_data:
37     ldr     r12, =LCD1_BASE
39 .loop:
40     ldrb    r2, [r0], #1
42 #ifdef IPOD_MINI2G
43     ldrb    r3, [r0], #1
44     orr     r2, r3, r2, lsl #8
45     orr     r2, r2, #0x760000
47     ldr     r3, [r12]
48     tst     r3, #LCD1_BUSY_MASK
49     bne     1b
50     str     r2, [r12, #0x08]
51 #else
53     ldr     r3, [r12]
54     tst     r3, #LCD1_BUSY_MASK
55     bne     1b
56     str     r2, [r12, #0x10]
58     ldrb    r2, [r0], #1
60     ldr     r3, [r12]
61     tst     r3, #LCD1_BUSY_MASK
62     bne     1b
63     str     r2, [r12, #0x10]
64 #endif
66     subs    r1, r1, #1
67     bne     .loop
69     bx      lr
70     .size   lcd_write_data,.-lcd_write_data
71     
73 #ifdef IPOD_MINI2G
75     .global     lcd_write_data_shifted
76     .type       lcd_write_data_shifted,%function
77     
78 lcd_write_data_shifted:
79     stmfd   sp!, {r4, lr}
80     ldr     lr, =LCD1_BASE
81     mov     r12, #0x760000
82     ldrb    r2, [r0], #1
84 .sloop:
85     ldrb    r3, [r0], #1
86     orr     r2, r3, r2, lsl #8
87     ldrb    r3, [r0], #1
88     orr     r2, r3, r2, lsl #8
89     mov     r4, r2, lsl #12
90     orr     r4, r12, r4, lsr #16
92     ldr     r3, [lr]
93     tst     r3, #LCD1_BUSY_MASK
94     bne     1b
95     str     r4, [lr, #0x08]
97     subs    r1, r1, #1
98     bne     .sloop
100     ldmfd   sp!, {r4, pc}
101     .size   lcd_write_data_shifted,.-lcd_write_data_shifted
102     
103 #elif defined IPOD_MINI
105     .global     lcd_write_data_shifted
106     .type       lcd_write_data_shifted,%function
107     
108 lcd_write_data_shifted:
109     str     lr, [sp, #-4]!
110     ldr     lr, =LCD1_BASE
111     ldrb    r2, [r0], #1
113 .sloop:
114     ldrb    r3, [r0], #1
115     orr     r2, r3, r2, lsl #8
116     mov     r12, r2, lsr #4
118     ldr     r3, [lr]
119     tst     r3, #LCD1_BUSY_MASK
120     bne     1b
121     str     r12, [lr, #0x10]
123     ldrb    r3, [r0], #1
124     orr     r2, r3, r2, lsl #8
125     mov     r12, r2, lsr #4
127     ldr     r3, [lr]
128     tst     r3, #LCD1_BUSY_MASK
129     bne     1b
130     str     r12, [lr, #0x10]
132     subs    r1, r1, #1
133     bne     .sloop
135     ldr     pc, [sp], #4
136     .size   lcd_write_data_shifted,.-lcd_write_data_shifted
138 #endif
140     .global     lcd_mono_data
141     .type       lcd_mono_data,%function
142     
143 lcd_mono_data:
144     stmfd   sp!, {r4, lr}
145     ldr     lr, =LCD1_BASE
146     adr     r12, .dibits
148 .mloop:
149     ldrb    r2, [r0], #1
150     mov     r3, r2, lsr #4
151     ldrb    r4, [r12, r3]
153 #ifdef IPOD_MINI2G
154     and     r3, r2, #0x0f
155     ldrb    r3, [r12, r3]
156     orr     r4, r3, r4, lsl #8
157     orr     r4, r4, #0x760000
159     ldr     r3, [lr]
160     tst     r3, #LCD1_BUSY_MASK
161     bne     1b
162     str     r4, [lr, #0x08]
163 #else
165     ldr     r3, [lr]
166     tst     r3, #LCD1_BUSY_MASK
167     bne     1b
168     str     r4, [lr, #0x10]
170     and     r3, r2, #0x0f
171     ldrb    r4, [r12, r3]
173     ldr     r3, [lr]
174     tst     r3, #LCD1_BUSY_MASK
175     bne     1b
176     str     r4, [lr, #0x10]
177 #endif
179     subs    r1, r1, #1
180     bne     .mloop
182     ldmfd   sp!, {r4, pc}
184 .dibits:
185     .byte   0x00, 0x03, 0x0C, 0x0F, 0x30, 0x33, 0x3C, 0x3F
186     .byte   0xC0, 0xC3, 0xCC, 0xCF, 0xF0, 0xF3, 0xFC, 0xFF
188     .size   lcd_mono_data,.-lcd_mono_data
191     .global     lcd_grey_data
192     .type       lcd_grey_data,%function
194 /* A high performance function to write grey phase data to the display,
195  * one or multiple pixels.
197  * Arguments:
198  *   r0 - pixel value data address
199  *   r1 - pixel phase data address
200  *   r2 - pixel block count
202  * Register usage:
203  *   r3/r4 - current block of phases
204  *   r5/r6 - lcd data accumulators
205  *   r6/r7 - current block of values
206  *   r12 - phase signs mask
207  *   lr  - lcd bridge address
208  */
210 lcd_grey_data:
211     stmfd   sp!, {r4-r7, lr}
212     mov     r12, #0x80
213     orr     r12, r12, r12, lsl #8
214     orr     r12, r12, r12, lsl #16
215     ldr     lr, =LCD1_BASE
217 .greyloop:
218     ldmia   r1, {r3-r4}         /* Fetch 8 pixel phases */
220     bic     r5, r12, r3         /* r5 = 0.......1.......2.......3....... */
221     orr     r5, r5, r5, lsr #10 /* r5 = 0.......1.0.....2.1.....3.2..... */
222     orr     r5, r5, r5, lsr #10 /* r5 = 0.......1.0.....2.1.0...3.2.1... */
223     orr     r5, r5, r5, lsr #10 /* r5 = 0.......1.0.....2.1.0...3.2.1.0. */
224     orr     r5, r5, r5, lsr #1  /* r5 = 00......1100....221100..33221100 */
225     bic     r3, r3, r12
227 #ifndef IPOD_MINI2G  /* 8 bit parallel bridge mode */
229     ldr     r6, [lr]
230     tst     r6, #LCD1_BUSY_MASK
231     bne     1b
233     str     r5, [lr, #0x10]
234 #endif
236     ldmia   r0!, {r6-r7}        /* Fetch 8 pixel values */
237     add     r3, r3, r6
239     bic     r6, r12, r4         /* r6 = 4.......5.......6.......7....... */
240     orr     r6, r6, r6, lsr #10 /* r6 = 4.......5.4.....6.5.....7.6..... */
241     orr     r6, r6, r6, lsr #10 /* r6 = 4.......5.4.....6.5.4...7.6.5... */
242     orr     r6, r6, r6, lsr #10 /* r6 = 4.......5.4.....6.5.4...7.6.5.4. */
243     orr     r6, r6, r6, lsr #1  /* r6 = 44......5544....665544..77665544 */
244     bic     r4, r4, r12
246     add     r4, r4, r7
247     stmia   r1!, {r3-r4}
249 #ifdef IPOD_MINI2G   /* 16 bit serial bridge mode */
250     and     r5, r5, #0xff       /* r5 = ........................33221100 */
251     and     r6, r6, #0xff       /* r6 = ........................77665544 */
252     orr     r5, r5, r6, lsl #8  /* r5 = ................7766554433221100 */
253     orr     r5, r5, #0x760000   /* data marker */
254 #endif
257     ldr     r7, [lr]
258     tst     r7, #LCD1_BUSY_MASK
259     bne     1b
261 #ifdef IPOD_MINI2G
262     str     r5, [lr, #0x08]
263 #else
264     str     r6, [lr, #0x10]
265 #endif
267     subs    r2, r2, #1
268     bne     .greyloop
270     ldmfd   sp!, {r4-r7, pc}
271     .size   lcd_grey_data,.-lcd_grey_data