diff options
Diffstat (limited to 'sound/oss/vidc_fill.S')
-rw-r--r-- | sound/oss/vidc_fill.S | 218 |
1 files changed, 218 insertions, 0 deletions
diff --git a/sound/oss/vidc_fill.S b/sound/oss/vidc_fill.S new file mode 100644 index 0000000..01ccc07 --- /dev/null +++ b/sound/oss/vidc_fill.S @@ -0,0 +1,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 |