HD200 - use line transfers in lcd_grey_data. This gives ~25% speedup.
[kugel-rb.git] / firmware / target / coldfire / mpio / hd200 / lcd-as-hd200.S
bloba284896af768186e15041f8e7f224fa009b8953f
1 /***************************************************************************
2  *             __________               __   ___.
3  *   Open      \______   \ ____   ____ |  | _\_ |__   _______  ___
4  *   Source     |       _//  _ \_/ ___\|  |/ /| __ \ /  _ \  \/  /
5  *   Jukebox    |    |   (  <_> )  \___|    < | \_\ (  <_> > <  <
6  *   Firmware   |____|_  /\____/ \___  >__|_ \|___  /\____/__/\_ \
7  *                     \/            \/     \/    \/            \/
8  * $Id:$
9  *
10  * Copyright (C) 2010 Marcin Bukat
11  * based on lcd-as-m3.S by Jens Arnold
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
19  * KIND, either express or implied.
20  *
21  ****************************************************************************/
23 #include "config.h" 
24 #include "cpu.h"
27 #define LCD_BASE_ADDRESS 0xf0000000
29     .section    .icode,"ax",@progbits
31     .align      2
32     .global     lcd_write_command
33     .type       lcd_write_command,@function
35 lcd_write_command:
36     move.l  (4, %sp), %d0
37     move.w  %d0, LCD_BASE_ADDRESS       /* data is 1byte but CF uses word
38                                          * transfers only */
39     rts
40 .wc_end:
41     .size   lcd_write_command,.wc_end-lcd_write_command
44     .align      2
45     .global     lcd_write_command_e
46     .type       lcd_write_command_e,@function
48 lcd_write_command_e:
49     lea.l   LCD_BASE_ADDRESS, %a0
51     move.l  (4, %sp), %d0       /* Command */
52     move.w  %d0, (%a0)         
53     move.l  (8, %sp), %d0       /* Data */
54     move.w  %d0, (%a0)          /* Write to LCD */
56     rts
57 .wce_end:
58     .size   lcd_write_command_e,.wce_end-lcd_write_command_e
61     .align      2
62     .global     lcd_write_data
63     .type       lcd_write_data,@function
65 /* PIXELFORMAT = VERTICAL_INTERLEAVED
66  * this means that data is packed verticaly in 8 pixels columns
67  * first byte is lsb of 2bit color in column
68  * second byte is msb of 2bit color in column
69  * so one word of data equals 8 pixels i 2bits color depth packed
70  * verticaly
71  */
72 lcd_write_data:
73     movem.l (4, %sp), %a0            /* Data pointer */
74     move.l  (8, %sp), %d0            /* Length i in words */
75     lea.l   LCD_BASE_ADDRESS+2, %a1  /* LCD data port address */
77     btst    #0, %d0    /* longwords multiply? */
78     jeq    .l_write
80 .w_write:
81     move.w  (%a0)+, %d1  /* load data         3 cycles*/
82     move.w  %d1, (%a1)   /* first byte        1 cycle*/
83     lsr.l   #8, %d1      /* load second byte  1 cycle*/
84     move.w  %d1, (%a1)   /* transfer          1 cycle*/
85     subq.l  #1, %d0      /* decrement counter 1 cycle*/
86     jeq     .write_end   
87     
88 .l_write:
89     move.l  (%a0)+, %d1  /* load data         2 cycles*/
90     swap    %d1          /*                   1 cycle */
91     move.w  %d1, (%a1)   /* first byte        1 cycle*/
92     lsr.l   #8, %d1      /*                   1 cycle */
93     move.w  %d1, (%a1)   /* second byte       1 cycle*/
94     lsr.l   #8, %d1      /*                   1 cycle */
95     move.w  %d1, (%a1)   /* third byte        1 cycle*/
96     lsr.l   #8, %d1      /*                   1 cycle */
97     move.w  %d1, (%a1)   /* forth byte        1 cycle*/
98     subq.l  #2, %d0      /* decrement counter 1 cycle*/
99     bne.s   .l_write
101 .write_end:
102     rts
103 .wd_end:
104     .size   lcd_write_data,.wd_end-lcd_write_data
106     .global lcd_mono_data
107     .type   lcd_mono_data, @function
109 lcd_mono_data:
110     move.l  (4, %sp), %a0       /* p_bytes */
111     move.l  (8, %sp), %d0       /* count */
112     lea.l   LCD_BASE_ADDRESS+2, %a1  /* LCD data port address */
114 .md_loop:
115     move.b  (%a0)+, %d1
116     move.w  %d1, (%a1)    /* byte transfers actually */
117     move.w  %d1, (%a1)
118     subq.l  #1, %d0
119     bne.s   .md_loop
120     rts
121 .md_end:
122     .size   lcd_mono_data,.md_end-lcd_mono_data
124     .global     lcd_grey_data
125     .type       lcd_grey_data,@function
127 lcd_grey_data:
128     lea.l   (-8*4, %sp), %sp
129     movem.l  %d2-%d7/%a2-%a3, (%sp) /* save some registers */
130     movem.l (8*4+4, %sp), %a0-%a2  /* values, phases, length */
131     add.l   %a2, %a2
132     lea.l   (%a1, %a2.l*4), %a2    /* end address */
133     lea.l   LCD_BASE_ADDRESS+2, %a3 /* LCD data port address */
134     moveq.l #24, %d4            /* shift count */
135     move.l  #0x204081, %d5      /* bit shuffle factor */
137     moveq.l #12, %d2
138     add.l   %a1, %d2
139     and.l   #0xfffffff0, %d2    /* first line bound */
140     cmp.l   %d2, %a2            /* end address lower than first line bound? */
141     bhs.s   1f
142     move.l  %a2, %d2            /* -> adjust end address of head loop */
144     cmp.l   %a1, %d2
145     bls.s   .g_head_tail_end
147 .g_head_tail:
148     movem.l (%a1), %d0-%d1      /* fetch 8 pixel phases */
150     move.l  %d0, %d2
151     and.l   #0x80808080, %d2    /* %d2 = 0.......1.......2.......3....... */
152     eor.l   %d2, %d0            
153     add.l   (%a0)+, %d0         /* add values to first 4 phases */
155     move.l  %d1, %d3
156     and.l   #0x80808080, %d3    /* %d3 = 4.......5.......6.......7....... */
157     eor.l   %d3, %d1
158     add.l   (%a0)+, %d1         /* add values to second 4 phases */
160     lsr.l   #4, %d3             /* %d3 = ....4.......5.......6.......7... */
161     or.l    %d3, %d2            /* %d2 = 0...4...1...5...2...6...3...7... */
162     mulu.l  %d5, %d2            /* %d2 = 01234567123.567.23..67..3...7... */
163     not.l   %d2                 /*       negate bits */
164     lsr.l   %d4, %d2            /* %d2 = ........................01234567 */
166     move.w  %d2, (%a3)          /* transfer first LCD byte */
168     movem.l %d0-%d1, (%a1)      /* store 8 new pixel phases */
169     addq.l  #8, %a1
171     move.w  %d2, (%a3)          /* transfer second LCD byte */
173 .g_head_tail_end:
174     cmp.l   %a1, %a2
175     bls.w   .g_end
176     lea.l   (-8, %a2), %a2
177     cmp.l   %a1, %a2
178     bls.s   .g_line_end
180 .g_line_loop:
181     /* loop that utilize line transfers */
182     movem.l (%a1), %d0-%d3      /* fetch 2 * 8 pixels phases */
184     move.l  %d0, %d6
185     and.l   #0x80808080, %d6    /* %d6 = 0.......1.......2.......3....... */
186     eor.l   %d6, %d0
187     add.l   (%a0)+, %d0         /* add values to first 4 phases */
189     move.l  %d1, %d7
190     and.l   #0x80808080, %d7    /* %d7 = 4.......5.......6.......7....... */
191     eor.l   %d7, %d1
192     add.l   (%a0)+, %d1         /* add values to second 4 phases */
194     lsr.l   #4, %d7             /* %d7 = ....4.......5.......6.......7... */
195     or.l    %d7, %d6            /* %d6 = 0...4...1...5...2...6...3...7... */
196     mulu.l  %d5, %d6            /* %d6 = 01234567123.567.23..67..3...7... */
197     not.l   %d6                 /*       negate bits */
198     lsr.l   %d4, %d6            /* %d6 = ........................01234567 */
200     move.w  %d6, (%a3)          /* transfer first LCD byte */
201     move.w  %d6, (%a3)          /* transfer second LCD byte */
203     move.l  %d2, %d6
204     and.l   #0x80808080, %d6    /* %d6 = 0.......1.......2.......3....... */
205     eor.l   %d6, %d2
206     add.l   (%a0)+, %d2         /* add values to first 4 phases */
208     move.l  %d3, %d7
209     and.l   #0x80808080, %d7    /* %d7 = 4.......5.......6.......7....... */
210     eor.l   %d7, %d3
211     add.l   (%a0)+, %d3         /* add values to second 4 phases */
213     lsr.l   #4, %d7             /* %d7 = ....4.......5.......6.......7... */
214     or.l    %d7, %d6            /* %d6 = 0...4...1...5...2...6...3...7... */
215     mulu.l  %d5, %d6            /* %d6 = 01234567123.567.23..67..3...7... */
216     not.l   %d6                 /*       negate bits */
217     lsr.l   %d4, %d6            /* %d6 = ........................01234567 */
219     move.w  %d6, (%a3)          /* transfer first LCD byte */
220     move.w  %d6, (%a3)          /* transfer second LCD byte */
222     movem.l %d0-%d3, (%a1)      /* store 2 * 8 new pixel phases */
223     lea.l   (16, %a1), %a1      /* advance pointer */
225     cmp.l   %a2, %a1
226     bls.s   .g_line_loop
228 .g_line_end:
229     lea.l   (8, %a2), %a2
230     cmp.l   %a1, %a2
231     bls.s   .g_end
232     bra.w   .g_head_tail
234 .g_end:
235     movem.l (%sp), %d2-%d7/%a2-%a3
236     lea.l   (8*4, %sp), %sp
237     rts
238 .grey_end:
239     .size    lcd_grey_data,.grey_end-lcd_grey_data