219 lines
4.3 KiB
ArmAsm
219 lines
4.3 KiB
ArmAsm
/*
|
|
* 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
|