Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0-or-later 2 : : /* 3 : : * ISA DMA support functions 4 : : * Copyright (c) by Jaroslav Kysela <perex@perex.cz> 5 : : */ 6 : : 7 : : /* 8 : : * Defining following add some delay. Maybe this helps for some broken 9 : : * ISA DMA controllers. 10 : : */ 11 : : 12 : : #undef HAVE_REALLY_SLOW_DMA_CONTROLLER 13 : : 14 : : #include <linux/export.h> 15 : : #include <sound/core.h> 16 : : #include <asm/dma.h> 17 : : 18 : : /** 19 : : * snd_dma_program - program an ISA DMA transfer 20 : : * @dma: the dma number 21 : : * @addr: the physical address of the buffer 22 : : * @size: the DMA transfer size 23 : : * @mode: the DMA transfer mode, DMA_MODE_XXX 24 : : * 25 : : * Programs an ISA DMA transfer for the given buffer. 26 : : */ 27 : 0 : void snd_dma_program(unsigned long dma, 28 : : unsigned long addr, unsigned int size, 29 : : unsigned short mode) 30 : : { 31 : 0 : unsigned long flags; 32 : : 33 : 0 : flags = claim_dma_lock(); 34 [ # # ]: 0 : disable_dma(dma); 35 [ # # ]: 0 : clear_dma_ff(dma); 36 [ # # ]: 0 : set_dma_mode(dma, mode); 37 : 0 : set_dma_addr(dma, addr); 38 [ # # ]: 0 : set_dma_count(dma, size); 39 [ # # ]: 0 : if (!(mode & DMA_MODE_NO_ENABLE)) 40 [ # # ]: 0 : enable_dma(dma); 41 : 0 : release_dma_lock(flags); 42 : 0 : } 43 : : EXPORT_SYMBOL(snd_dma_program); 44 : : 45 : : /** 46 : : * snd_dma_disable - stop the ISA DMA transfer 47 : : * @dma: the dma number 48 : : * 49 : : * Stops the ISA DMA transfer. 50 : : */ 51 : 0 : void snd_dma_disable(unsigned long dma) 52 : : { 53 : 0 : unsigned long flags; 54 : : 55 : 0 : flags = claim_dma_lock(); 56 [ # # ]: 0 : clear_dma_ff(dma); 57 [ # # ]: 0 : disable_dma(dma); 58 : 0 : release_dma_lock(flags); 59 : 0 : } 60 : : EXPORT_SYMBOL(snd_dma_disable); 61 : : 62 : : /** 63 : : * snd_dma_pointer - return the current pointer to DMA transfer buffer in bytes 64 : : * @dma: the dma number 65 : : * @size: the dma transfer size 66 : : * 67 : : * Return: The current pointer in DMA transfer buffer in bytes. 68 : : */ 69 : 0 : unsigned int snd_dma_pointer(unsigned long dma, unsigned int size) 70 : : { 71 : 0 : unsigned long flags; 72 : 0 : unsigned int result, result1; 73 : : 74 : 0 : flags = claim_dma_lock(); 75 [ # # ]: 0 : clear_dma_ff(dma); 76 [ # # ]: 0 : if (!isa_dma_bridge_buggy) 77 [ # # ]: 0 : disable_dma(dma); 78 [ # # ]: 0 : result = get_dma_residue(dma); 79 : : /* 80 : : * HACK - read the counter again and choose higher value in order to 81 : : * avoid reading during counter lower byte roll over if the 82 : : * isa_dma_bridge_buggy is set. 83 : : */ 84 : 0 : result1 = get_dma_residue(dma); 85 [ # # ]: 0 : if (!isa_dma_bridge_buggy) 86 [ # # ]: 0 : enable_dma(dma); 87 : 0 : release_dma_lock(flags); 88 [ # # ]: 0 : if (unlikely(result < result1)) 89 : 0 : result = result1; 90 : : #ifdef CONFIG_SND_DEBUG 91 : : if (result > size) 92 : : pr_err("ALSA: pointer (0x%x) for DMA #%ld is greater than transfer size (0x%x)\n", result, dma, size); 93 : : #endif 94 [ # # ]: 0 : if (result >= size || result == 0) 95 : : return 0; 96 : : else 97 : 0 : return size - result; 98 : : } 99 : : EXPORT_SYMBOL(snd_dma_pointer);