blob: d652710bf30873bb0d972d6eb0b715bdc575076b [file] [log] [blame]
Jens Arnold9737fc72008-04-06 23:57:37 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2008 by Jens Arnold
11 *
Daniel Stenberg2acc0ac2008-06-28 18:10:04 +000012 * 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.
Jens Arnold9737fc72008-04-06 23:57:37 +000016 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23
24#define RS_MASK 0x00010000
25#define CLOCK_MASK 0x10000000
26#define GPIO_OUT_ADDR 0x80000004
27
28#define CS_MASK 0x00000004 /* used in moveq.l */
29#define DATA_MASK 0x00040000
30#define GPIO1_OUT_ADDR 0x800000b4
31
32#define CS_TIMEOUT 10 /* HZ/10 */
33
34 .extern cpu_frequency /* Global variable from system.c */
35 .extern remote_byte_delay /* Global variable from lcd-remote-iriver.c */
36 .extern remote_cs_countdown /* Global variable from lcd-remote-iriver.c */
37
38 .section .icode,"ax",@progbits
39
40 /* Output 8 bits to the LCD. Instruction order is devised to maximize the
41 * delay between changing the data line and the CLK L->H transition, which
42 * makes the LCD controller sample DATA.
43 * Requires CLK = 0 on entry.
44 *
45 * Custom calling convention:
46 * %a0 - GPIO_OUT_ADDR
47 * %a1 - GPIO1_OUT_ADDR
48 * %d4 - data byte
49 * %d6 - DATA_MASK
50 * Clobbers:
51 * %d0..%d4
52 */
53#ifdef HAVE_REMOTE_LCD_TICKING
54.write_byte_delayed:
55 move.l remote_byte_delay, %d0
561:
57 subq.l #1, %d0
58 bne.s 1b
59#endif
60
61.write_byte:
62 move.w %sr, %d3 /* Get current interrupt level */
63 move.w #0x2700, %sr /* Disable interrupts */
64
65 move.l (%a1), %d0 /* Get current state of data port */
66 move.l %d0, %d1
67 and.l %d6, %d1 /* Check current state of data line */
68 beq.s 1f /* and set it as previous-state bit */
69 bset #8, %d4
701:
71 move.l %d4, %d1 /* Compute the 'bit derivative', i.e. a value */
72 lsr.l #1, %d1 /* with 1's where the data changes from the */
73 eor.l %d1, %d4 /* previous state, and 0's where it doesn't */
74 swap %d4 /* Shift data to upper byte */
75 lsl.l #8, %d4
76
77 move.l (%a0),%d1 /* Get current state of clock port */
78 move.l %d1, %d2 /* Precalculate opposite state of clock line */
79 eor.l #CLOCK_MASK, %d2
80
81 lsl.l #1, %d4 /* Invert data line for bit7 ? */
82 bcc.s 1f /* no: skip */
83 eor.l %d6, %d0 /* invert data bit */
84 move.l %d0, (%a1) /* output data bit7 */
85 nop
Jens Arnoldd52bea82008-05-29 21:41:47 +000086 nop
Jens Arnold9737fc72008-04-06 23:57:37 +0000871:
88
89.macro bit_out
Jens Arnoldd52bea82008-05-29 21:41:47 +000090 move.l %d2, (%a0) /* Bit7: set CLK = 1 */
91 nop
Jens Arnold9737fc72008-04-06 23:57:37 +000092 lsl.l #1, %d4 /* Invert data line for bit6 ? */
93 bcc.s 1f /* no: skip */
94 eor.l %d6, %d0 /* Invert data bit */
Jens Arnold9737fc72008-04-06 23:57:37 +000095 move.l %d1, (%a0) /* set CLK = 0 */
96 move.l %d0, (%a1) /* Output data bit6 */
Jens Arnoldd52bea82008-05-29 21:41:47 +000097 .word 0x51fa /* trapf.w - shadow next insn */
981:
Jens Arnold9737fc72008-04-06 23:57:37 +000099 move.l %d1, (%a0) /* set CLK = 0 */
Jens Arnold9737fc72008-04-06 23:57:37 +0000100.endm
Jens Arnold9737fc72008-04-06 23:57:37 +0000101
Jens Arnoldd52bea82008-05-29 21:41:47 +0000102 bit_out
103 nop
104 nop
105 bit_out
106 nop
107 nop
108 bit_out
109 nop
110 nop
111 bit_out
112 nop
113 nop
114 bit_out
115 nop
116 nop
117 bit_out
118 nop
119 nop
120 bit_out
121 nop
122 nop
123
Jens Arnold9737fc72008-04-06 23:57:37 +0000124 move.l %d2, (%a0) /* Bit0: Set CLK = 1 */
Jens Arnoldd52bea82008-05-29 21:41:47 +0000125 nop
126 nop
Jens Arnold9737fc72008-04-06 23:57:37 +0000127 move.l %d1, (%a0) /* Set CLK = 0 */
128
129 move.w %d3, %sr /* Restore interrupt level */
130 rts
131
132 /* Output 8 bits to the LCD as fast as possible. Use only at < 60MHz.
133 *
134 * Custom calling convention:
135 * %a0 - GPIO_OUT_ADDR
136 * %a1 - GPIO1_OUT_ADDR
137 * %d4 - data word
138 * %d6 - DATA_MASK
139 * Clobbers:
140 * %d0..%d4
141 */
142#ifdef HAVE_REMOTE_LCD_TICKING
143.write_byte_fast_delayed:
144 move.l remote_byte_delay, %d0
1451:
146 subq.l #1, %d0
147 bne.s 1b
148#endif
149
150.write_byte_fast:
151 move.w %sr, %d3 /* Get current interrupt level */
152 move.w #0x2700,%sr /* Disable interrupts */
153
154 move.l (%a1), %d0 /* Get current state of data port */
155 move.l %d0, %d1
156 and.l %d6, %d1 /* Check current state of data line */
157 beq.s 1f /* and set it as previous-state bit */
158 bset #8, %d4
1591:
160 move.l %d4, %d1 /* Compute the 'bit derivative', i.e. a value */
161 lsr.l #1, %d1 /* with 1's where the data changes from the */
162 eor.l %d1, %d4 /* previous state, and 0's where it doesn't */
163 swap %d4 /* Shift data to upper byte */
164 lsl.l #8, %d4
165
166 move.l (%a0), %d1 /* Get current state of clock port */
167 move.l %d1, %d2 /* Precalculate opposite state of clock line */
168 eor.l #CLOCK_MASK, %d2
169
170.macro bit_out_fast
171 lsl.l #1,%d4 /* Shift out MSB */
172 bcc.s 1f
173 eor.l %d6, %d0 /* 1: flip data bit */
174 move.l %d0, (%a1) /* and output new DATA state */
1751:
176 move.l %d2, (%a0) /* Set CLK */
177 move.l %d1, (%a0) /* Reset CLK */
178.endm
179 bit_out_fast
180 bit_out_fast
181 bit_out_fast
182 bit_out_fast
183 bit_out_fast
184 bit_out_fast
185 bit_out_fast
186 bit_out_fast
187
188 move.w %d3, %sr /* Restore interrupt level */
189 rts
190
191
192 .global lcd_remote_write_command
193 .type lcd_remote_write_command, @function
194
195lcd_remote_write_command:
196 lea.l (-4*4, %sp), %sp
197 movem.l %d2-%d4/%d6, (%sp)
198
199 move.l (4*4+4, %sp), %d4 /* cmd */
200
201 lea.l GPIO_OUT_ADDR, %a0
202 lea.l GPIO1_OUT_ADDR, %a1
203 move.l #DATA_MASK, %d6
204
205 clr.l remote_cs_countdown
206
207 move.l #~RS_MASK, %d0
208 and.l %d0, (%a0)
209 moveq.l #~CS_MASK, %d0
210 and.l %d0, (%a1)
211
212#ifdef HAVE_REMOTE_LCD_TICKING
213 tst.l remote_byte_delay
214 ble.s 1f
215 bsr.w .write_byte_delayed
216 bra.s 2f
2171:
218#endif
219 bsr.w .write_byte
2202:
221
222 moveq.l #CS_TIMEOUT, %d0
223 move.l %d0, remote_cs_countdown
224
225 movem.l (%sp), %d2-%d4/%d6
226 lea.l (4*4, %sp), %sp
227 rts
228
229
230 .global lcd_remote_write_command_ex
231 .type lcd_remote_write_command_ex, @function
232
233lcd_remote_write_command_ex:
234 lea.l (-4*4, %sp), %sp
235 movem.l %d2-%d4/%d6, (%sp)
236
237 lea.l GPIO_OUT_ADDR, %a0
238 lea.l GPIO1_OUT_ADDR, %a1
239 move.l #DATA_MASK, %d6
240
241 clr.l remote_cs_countdown
242
243 move.l #~RS_MASK, %d0
244 and.l %d0, (%a0)
245 moveq.l #~CS_MASK, %d0
246 and.l %d0, (%a1)
247
248 move.l (4*4+4, %sp), %d4
249
250#ifdef HAVE_REMOTE_LCD_TICKING
251 tst.l remote_byte_delay
252 ble.s 1f
253 bsr.w .write_byte_delayed
254 move.l (4*4+8, %sp), %d4
255 bsr.w .write_byte_delayed
256 bra.s 2f
2571:
258#endif
259 bsr.w .write_byte
260 move.l (4*4+8, %sp), %d4
261 bsr.w .write_byte
2622:
263
264 moveq.l #CS_TIMEOUT, %d0
265 move.l %d0, remote_cs_countdown
266
267 movem.l (%sp), %d2-%d4/%d6
268 lea.l (4*4, %sp), %sp
269 rts
270
271
272 .global lcd_remote_write_data
273 .type lcd_remote_write_data, @function
274
275lcd_remote_write_data:
276 lea.l (-7*4, %sp), %sp
277 movem.l %d2-%d6/%a2-%a3, (%sp)
278
279 move.l (7*4+4, %sp), %a2 /* p_bytes */
280 move.l (7*4+8, %sp), %d5 /* count */
281
282 lea.l GPIO_OUT_ADDR, %a0
283 lea.l GPIO1_OUT_ADDR, %a1
284 move.l #DATA_MASK, %d6
285
286 lea.l .write_byte, %a3
287 move.l cpu_frequency, %d0
288 cmp.l #60000000, %d0
289 bhi.b 1f
290 lea.l .write_byte_fast, %a3
2911:
292
293#ifdef HAVE_REMOTE_LCD_TICKING
294 tst.l remote_byte_delay
295 ble.s 1f
296 moveq.l #(.write_byte_delayed - .write_byte), %d0
297 add.l %d0, %a3
2981:
299#endif
300
301 clr.l remote_cs_countdown
302
303 move.l #RS_MASK, %d0
304 or.l %d0, (%a0)
305 moveq.l #~CS_MASK, %d0
306 and.l %d0, (%a1)
307
308.wd_loop:
309 clr.l %d4
310 move.b (%a2)+, %d4
311 jsr (%a3)
312 subq.l #1, %d5
313 bne.s .wd_loop
314
315 moveq.l #CS_TIMEOUT, %d0
316 move.l %d0, remote_cs_countdown
317
318 movem.l (%sp), %d2-%d6/%a2-%a3
319 lea.l (7*4, %sp), %sp
320 rts