linux/sound/arm/pxa2xx-pcm.c
<<
>>
Prefs
   1/*
   2 * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
   3 *
   4 * Author:      Nicolas Pitre
   5 * Created:     Nov 30, 2004
   6 * Copyright:   (C) 2004 MontaVista Software, Inc.
   7 *
   8 * This program is free software; you can redistribute it and/or modify
   9 * it under the terms of the GNU General Public License version 2 as
  10 * published by the Free Software Foundation.
  11 */
  12
  13#include <linux/module.h>
  14#include <sound/core.h>
  15#include <sound/pxa2xx-lib.h>
  16
  17#include "pxa2xx-pcm.h"
  18
  19static int pxa2xx_pcm_prepare(struct snd_pcm_substream *substream)
  20{
  21        struct pxa2xx_pcm_client *client = substream->private_data;
  22
  23        __pxa2xx_pcm_prepare(substream);
  24
  25        return client->prepare(substream);
  26}
  27
  28static int pxa2xx_pcm_open(struct snd_pcm_substream *substream)
  29{
  30        struct pxa2xx_pcm_client *client = substream->private_data;
  31        struct snd_pcm_runtime *runtime = substream->runtime;
  32        struct pxa2xx_runtime_data *rtd;
  33        int ret;
  34
  35        ret = __pxa2xx_pcm_open(substream);
  36        if (ret)
  37                goto out;
  38
  39        rtd = runtime->private_data;
  40
  41        rtd->params = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ?
  42                      client->playback_params : client->capture_params;
  43        ret = pxa_request_dma(rtd->params->name, DMA_PRIO_LOW,
  44                              pxa2xx_pcm_dma_irq, substream);
  45        if (ret < 0)
  46                goto err2;
  47        rtd->dma_ch = ret;
  48
  49        ret = client->startup(substream);
  50        if (!ret)
  51                goto out;
  52
  53        pxa_free_dma(rtd->dma_ch);
  54 err2:
  55        __pxa2xx_pcm_close(substream);
  56 out:
  57        return ret;
  58}
  59
  60static int pxa2xx_pcm_close(struct snd_pcm_substream *substream)
  61{
  62        struct pxa2xx_pcm_client *client = substream->private_data;
  63        struct pxa2xx_runtime_data *rtd = substream->runtime->private_data;
  64
  65        pxa_free_dma(rtd->dma_ch);
  66        client->shutdown(substream);
  67
  68        return __pxa2xx_pcm_close(substream);
  69}
  70
  71static struct snd_pcm_ops pxa2xx_pcm_ops = {
  72        .open           = pxa2xx_pcm_open,
  73        .close          = pxa2xx_pcm_close,
  74        .ioctl          = snd_pcm_lib_ioctl,
  75        .hw_params      = __pxa2xx_pcm_hw_params,
  76        .hw_free        = __pxa2xx_pcm_hw_free,
  77        .prepare        = pxa2xx_pcm_prepare,
  78        .trigger        = pxa2xx_pcm_trigger,
  79        .pointer        = pxa2xx_pcm_pointer,
  80        .mmap           = pxa2xx_pcm_mmap,
  81};
  82
  83static u64 pxa2xx_pcm_dmamask = 0xffffffff;
  84
  85int pxa2xx_pcm_new(struct snd_card *card, struct pxa2xx_pcm_client *client,
  86                   struct snd_pcm **rpcm)
  87{
  88        struct snd_pcm *pcm;
  89        int play = client->playback_params ? 1 : 0;
  90        int capt = client->capture_params ? 1 : 0;
  91        int ret;
  92
  93        ret = snd_pcm_new(card, "PXA2xx-PCM", 0, play, capt, &pcm);
  94        if (ret)
  95                goto out;
  96
  97        pcm->private_data = client;
  98        pcm->private_free = pxa2xx_pcm_free_dma_buffers;
  99
 100        if (!card->dev->dma_mask)
 101                card->dev->dma_mask = &pxa2xx_pcm_dmamask;
 102        if (!card->dev->coherent_dma_mask)
 103                card->dev->coherent_dma_mask = 0xffffffff;
 104
 105        if (play) {
 106                int stream = SNDRV_PCM_STREAM_PLAYBACK;
 107                snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
 108                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
 109                if (ret)
 110                        goto out;
 111        }
 112        if (capt) {
 113                int stream = SNDRV_PCM_STREAM_CAPTURE;
 114                snd_pcm_set_ops(pcm, stream, &pxa2xx_pcm_ops);
 115                ret = pxa2xx_pcm_preallocate_dma_buffer(pcm, stream);
 116                if (ret)
 117                        goto out;
 118        }
 119
 120        if (rpcm)
 121                *rpcm = pcm;
 122        ret = 0;
 123
 124 out:
 125        return ret;
 126}
 127
 128EXPORT_SYMBOL(pxa2xx_pcm_new);
 129
 130MODULE_AUTHOR("Nicolas Pitre");
 131MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
 132MODULE_LICENSE("GPL");
 133