| /* |
| * 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/arch/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 |