summaryrefslogtreecommitdiff
path: root/sound/oss/vidc_fill.S
blob: 01ccc074cc11c8db479e6efdd8fe2a7fc9ec4b0d (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
/*
 *  linux/drivers/sound/vidc_fill.S
 *
 *  Copyright (C) 1997 Russell King
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 *  Filler routines for DMA buffers
 */
#include <linux/linkage.h>
#include <asm/assembler.h>
#include <asm/hardware.h>
#include <asm/hardware/iomd.h>

		.text

ENTRY(vidc_fill_1x8_u)
		mov	ip, #0xff00
1:		cmp	r0, r1
		bge	vidc_clear
		ldrb	r4, [r0], #1
		eor	r4, r4, #0x80
		and	r4, ip, r4, lsl #8
		orr	r4, r4, r4, lsl #16
		str	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_2x8_u)
		mov	ip, #0xff00
1:		cmp	r0, r1
		bge	vidc_clear
		ldr	r4, [r0], #2
		and	r5, r4, ip
		and	r4, ip, r4, lsl #8
		orr	r4, r4, r5, lsl #16
		orr	r4, r4, r4, lsr #8
		str	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_1x8_s)
		mov	ip, #0xff00
1:		cmp	r0, r1
		bge	vidc_clear
		ldrb	r4, [r0], #1
		and	r4, ip, r4, lsl #8
		orr	r4, r4, r4, lsl #16
		str	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_2x8_s)
		mov	ip, #0xff00
1:		cmp	r0, r1
		bge	vidc_clear
		ldr	r4, [r0], #2
		and	r5, r4, ip
		and	r4, ip, r4, lsl #8
		orr	r4, r4, r5, lsl #16
		orr	r4, r4, r4, lsr #8
		str	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_1x16_s)
		mov	ip, #0xff00
		orr	ip, ip, ip, lsr #8
1:		cmp	r0, r1
		bge	vidc_clear
		ldr	r5, [r0], #2
		and	r4, r5, ip
		orr	r4, r4, r4, lsl #16
		str	r4, [r2], #4
		cmp	r0, r1
		addlt	r0, r0, #2
		andlt	r4, r5, ip, lsl #16
		orrlt	r4, r4, r4, lsr #16
		strlt	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_2x16_s)
		mov	ip, #0xff00
		orr	ip, ip, ip, lsr #8
1:		cmp	r0, r1
		bge	vidc_clear
		ldr	r4, [r0], #4
		str	r4, [r2], #4
		cmp	r0, r1
		ldrlt	r4, [r0], #4
		strlt	r4, [r2], #4
		cmp	r2, r3
		blt	1b
		mov	pc, lr

ENTRY(vidc_fill_noaudio)
		mov	r0, #0
		mov	r1, #0
2:		mov	r4, #0
		mov	r5, #0
1:		cmp	r2, r3
		stmltia	r2!, {r0, r1, r4, r5}
		blt	1b
		mov	pc, lr

ENTRY(vidc_clear)
		mov	r0, #0
		mov	r1, #0
		tst	r2, #4
		str	r0, [r2], #4
		tst	r2, #8
		stmia	r2!, {r0, r1}
		b	2b

/*
 * Call filler routines with:
 *  r0 = phys address
 *  r1 = phys end
 *  r2 = buffer
 * Returns:
 *  r0 = new buffer address
 *  r2 = new buffer finish
 *  r4 = corrupted
 *  r5 = corrupted
 *  ip = corrupted
 */

ENTRY(vidc_sound_dma_irq)
		stmfd	sp!, {r4 - r8, lr}
		ldr	r8, =dma_start
		ldmia	r8, {r0, r1, r2, r3, r4, r5}
		teq	r1, #0
		adreq	r4, vidc_fill_noaudio
		moveq	r7, #1 << 31
		movne	r7, #0
		mov	ip, #IOMD_BASE & 0xff000000
		orr	ip, ip, #IOMD_BASE & 0x00ff0000
		ldrb	r6, [ip, #IOMD_SD0ST]
		tst	r6, #DMA_ST_OFL			@ Check for overrun
		eorne	r6, r6, #DMA_ST_AB
		tst	r6, #DMA_ST_AB
		moveq	r2, r3				@ DMAing A, update B
		add	r3, r2, r5			@ End of DMA buffer
		add	r1, r1, r0			@ End of virtual DMA buffer
		mov	lr, pc
		mov	pc, r4				@ Call fill routine (uses r4, ip)
		sub	r1, r1, r0			@ Remaining length
		stmia	r8, {r0, r1}
		mov	r0, #0
		tst	r2, #4				@ Round buffer up to 4 words
		strne	r0, [r2], #4
		tst	r2, #8
		strne	r0, [r2], #4
		strne	r0, [r2], #4
		sub	r2, r2, #16
		mov	r2, r2, lsl #20
		movs	r2, r2, lsr #20
		orreq	r2, r2, #1 << 30		@ Set L bit
		orr	r2, r2, r7
		ldmdb	r8, {r3, r4, r5}
		tst	r6, #DMA_ST_AB
		mov	ip, #IOMD_BASE & 0xff000000
		orr	ip, ip, #IOMD_BASE & 0x00ff0000
		streq	r4, [ip, #IOMD_SD0CURB]
		strne	r5, [ip, #IOMD_SD0CURA]
		streq	r2, [ip, #IOMD_SD0ENDB]
		strne	r2, [ip, #IOMD_SD0ENDA]
		ldr	lr, [ip, #IOMD_SD0ST]
		tst	lr, #DMA_ST_OFL
		bne	1f
		tst	r6, #DMA_ST_AB
		strne	r4, [ip, #IOMD_SD0CURB]
		streq	r5, [ip, #IOMD_SD0CURA]
		strne	r2, [ip, #IOMD_SD0ENDB]
		streq	r2, [ip, #IOMD_SD0ENDA]
1:		teq	r7, #0
		mov	r0, #0x10
		strneb	r0, [ip, #IOMD_SD0CR]
		ldmfd	sp!, {r4 - r8, lr}
		mov	r0, #1				@ IRQ_HANDLED
		teq	r1, #0				@ If we have no more
		movne	pc, lr
		teq	r3, #0
		movne	pc, r3				@ Call interrupt routine
		mov	pc, lr

		.data
		.globl	dma_interrupt
dma_interrupt:
		.long	0				@ r3
		.globl	dma_pbuf
dma_pbuf:
		.long	0				@ r4
		.long	0				@ r5
		.globl	dma_start
dma_start:
		.long	0				@ r0
		.globl	dma_count
dma_count:
		.long	0				@ r1
		.globl	dma_buf
dma_buf:
		.long	0				@ r2
		.long	0				@ r3
		.globl	vidc_filler
vidc_filler:
		.long	vidc_fill_noaudio		@ r4
		.globl	dma_bufsize
dma_bufsize:
		.long	0x1000				@ r5