Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
imx-pcm.c
Go to the documentation of this file.
1 /*
2  * Copyright 2009 Sascha Hauer <[email protected]>
3  *
4  * This code is based on code copyrighted by Freescale,
5  * Liam Girdwood, Javier Martin and probably others.
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU General Public License as published by the
9  * Free Software Foundation; either version 2 of the License, or (at your
10  * option) any later version.
11  */
12 
13 #include <linux/dma-mapping.h>
14 #include <linux/module.h>
15 #include <sound/pcm.h>
16 #include <sound/soc.h>
17 #include "imx-pcm.h"
18 
19 int snd_imx_pcm_mmap(struct snd_pcm_substream *substream,
20  struct vm_area_struct *vma)
21 {
22  struct snd_pcm_runtime *runtime = substream->runtime;
23  int ret;
24 
25  ret = dma_mmap_writecombine(substream->pcm->card->dev, vma,
26  runtime->dma_area, runtime->dma_addr, runtime->dma_bytes);
27 
28  pr_debug("%s: ret: %d %p 0x%08x 0x%08x\n", __func__, ret,
29  runtime->dma_area,
30  runtime->dma_addr,
31  runtime->dma_bytes);
32  return ret;
33 }
35 
36 static int imx_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
37 {
38  struct snd_pcm_substream *substream = pcm->streams[stream].substream;
39  struct snd_dma_buffer *buf = &substream->dma_buffer;
40  size_t size = IMX_SSI_DMABUF_SIZE;
41 
42  buf->dev.type = SNDRV_DMA_TYPE_DEV;
43  buf->dev.dev = pcm->card->dev;
44  buf->private_data = NULL;
45  buf->area = dma_alloc_writecombine(pcm->card->dev, size,
46  &buf->addr, GFP_KERNEL);
47  if (!buf->area)
48  return -ENOMEM;
49  buf->bytes = size;
50 
51  return 0;
52 }
53 
54 static u64 imx_pcm_dmamask = DMA_BIT_MASK(32);
55 
57 {
58  struct snd_card *card = rtd->card->snd_card;
59  struct snd_pcm *pcm = rtd->pcm;
60  int ret = 0;
61 
62  if (!card->dev->dma_mask)
63  card->dev->dma_mask = &imx_pcm_dmamask;
64  if (!card->dev->coherent_dma_mask)
65  card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
66  if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
67  ret = imx_pcm_preallocate_dma_buffer(pcm,
69  if (ret)
70  goto out;
71  }
72 
73  if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
74  ret = imx_pcm_preallocate_dma_buffer(pcm,
76  if (ret)
77  goto out;
78  }
79 
80 out:
81  return ret;
82 }
84 
85 void imx_pcm_free(struct snd_pcm *pcm)
86 {
87  struct snd_pcm_substream *substream;
88  struct snd_dma_buffer *buf;
89  int stream;
90 
91  for (stream = 0; stream < 2; stream++) {
92  substream = pcm->streams[stream].substream;
93  if (!substream)
94  continue;
95 
96  buf = &substream->dma_buffer;
97  if (!buf->area)
98  continue;
99 
100  dma_free_writecombine(pcm->card->dev, buf->bytes,
101  buf->area, buf->addr);
102  buf->area = NULL;
103  }
104 }