linux/sound/core/isadma.c
<<
>>
Prefs
   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 */
  27void snd_dma_program(unsigned long dma,
  28                     unsigned long addr, unsigned int size,
  29                     unsigned short mode)
  30{
  31        unsigned long flags;
  32
  33        flags = claim_dma_lock();
  34        disable_dma(dma);
  35        clear_dma_ff(dma);
  36        set_dma_mode(dma, mode);
  37        set_dma_addr(dma, addr);
  38        set_dma_count(dma, size);
  39        if (!(mode & DMA_MODE_NO_ENABLE))
  40                enable_dma(dma);
  41        release_dma_lock(flags);
  42}
  43EXPORT_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 */
  51void snd_dma_disable(unsigned long dma)
  52{
  53        unsigned long flags;
  54
  55        flags = claim_dma_lock();
  56        clear_dma_ff(dma);
  57        disable_dma(dma);
  58        release_dma_lock(flags);
  59}
  60EXPORT_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 */
  69unsigned int snd_dma_pointer(unsigned long dma, unsigned int size)
  70{
  71        unsigned long flags;
  72        unsigned int result, result1;
  73
  74        flags = claim_dma_lock();
  75        clear_dma_ff(dma);
  76        if (!isa_dma_bridge_buggy)
  77                disable_dma(dma);
  78        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        result1 = get_dma_residue(dma);
  85        if (!isa_dma_bridge_buggy)
  86                enable_dma(dma);
  87        release_dma_lock(flags);
  88        if (unlikely(result < result1))
  89                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        if (result >= size || result == 0)
  95                return 0;
  96        else
  97                return size - result;
  98}
  99EXPORT_SYMBOL(snd_dma_pointer);
 100