atmel-pcm.c 3.4 KB
Newer Older
1 2
/*
 * atmel-pcm.c  --  ALSA PCM interface for the Atmel atmel SoC.
G
Geoffrey Wossum 已提交
3
 *
4 5 6 7 8 9 10 11 12 13 14 15 16 17
 *  Copyright (C) 2005 SAN People
 *  Copyright (C) 2008 Atmel
 *
 * Authors: Sedji Gaouaou <sedji.gaouaou@atmel.com>
 *
 * Based on at91-pcm. by:
 * Frank Mandarino <fmandarino@endrelia.com>
 * Copyright 2006 Endrelia Technologies Inc.
 *
 * Based on pxa2xx-pcm.c by:
 *
 * Author:	Nicolas Pitre
 * Created:	Nov 30, 2004
 * Copyright:	(C) 2004 MontaVista Software, Inc.
G
Geoffrey Wossum 已提交
18 19
 *
 * This program is free software; you can redistribute it and/or modify
20 21 22
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
G
Geoffrey Wossum 已提交
23
 *
24 25 26 27 28 29 30 31
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
G
Geoffrey Wossum 已提交
32 33 34 35 36 37
 */

#include <linux/module.h>
#include <linux/dma-mapping.h>
#include <sound/pcm.h>
#include <sound/soc.h>
38
#include "atmel-pcm.h"
G
Geoffrey Wossum 已提交
39

40 41
static int atmel_pcm_preallocate_dma_buffer(struct snd_pcm *pcm,
	int stream)
G
Geoffrey Wossum 已提交
42 43
{
	struct snd_pcm_substream *substream = pcm->streams[stream].substream;
44
	struct snd_dma_buffer *buf = &substream->dma_buffer;
B
Bo Shen 已提交
45
	size_t size = ATMEL_SSC_DMABUF_SIZE;
46 47 48 49 50

	buf->dev.type = SNDRV_DMA_TYPE_DEV;
	buf->dev.dev = pcm->card->dev;
	buf->private_data = NULL;
	buf->area = dma_alloc_coherent(pcm->card->dev, size,
B
Bo Shen 已提交
51 52 53
			&buf->addr, GFP_KERNEL);
	pr_debug("atmel-pcm: alloc dma buffer: area=%p, addr=%p, size=%d\n",
			(void *)buf->area, (void *)buf->addr, size);
54 55

	if (!buf->area)
G
Geoffrey Wossum 已提交
56 57
		return -ENOMEM;

58
	buf->bytes = size;
G
Geoffrey Wossum 已提交
59 60 61
	return 0;
}

B
Bo Shen 已提交
62
int atmel_pcm_mmap(struct snd_pcm_substream *substream,
63
	struct vm_area_struct *vma)
G
Geoffrey Wossum 已提交
64 65
{
	return remap_pfn_range(vma, vma->vm_start,
66 67
		       substream->dma_buffer.addr >> PAGE_SHIFT,
		       vma->vm_end - vma->vm_start, vma->vm_page_prot);
G
Geoffrey Wossum 已提交
68
}
B
Bo Shen 已提交
69
EXPORT_SYMBOL_GPL(atmel_pcm_mmap);
G
Geoffrey Wossum 已提交
70

71
static u64 atmel_pcm_dmamask = DMA_BIT_MASK(32);
G
Geoffrey Wossum 已提交
72

B
Bo Shen 已提交
73
int atmel_pcm_new(struct snd_soc_pcm_runtime *rtd)
G
Geoffrey Wossum 已提交
74
{
75 76
	struct snd_card *card = rtd->card->snd_card;
	struct snd_pcm *pcm = rtd->pcm;
G
Geoffrey Wossum 已提交
77 78 79
	int ret = 0;

	if (!card->dev->dma_mask)
80
		card->dev->dma_mask = &atmel_pcm_dmamask;
G
Geoffrey Wossum 已提交
81
	if (!card->dev->coherent_dma_mask)
82
		card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
G
Geoffrey Wossum 已提交
83

84
	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
B
Bo Shen 已提交
85
		pr_debug("atmel-pcm: allocating PCM playback DMA buffer\n");
86 87
		ret = atmel_pcm_preallocate_dma_buffer(pcm,
			SNDRV_PCM_STREAM_PLAYBACK);
G
Geoffrey Wossum 已提交
88 89 90 91
		if (ret)
			goto out;
	}

92
	if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
B
Bo Shen 已提交
93
		pr_debug("atmel-pcm: allocating PCM capture DMA buffer\n");
94 95
		ret = atmel_pcm_preallocate_dma_buffer(pcm,
			SNDRV_PCM_STREAM_CAPTURE);
G
Geoffrey Wossum 已提交
96 97 98
		if (ret)
			goto out;
	}
99
 out:
G
Geoffrey Wossum 已提交
100 101
	return ret;
}
B
Bo Shen 已提交
102
EXPORT_SYMBOL_GPL(atmel_pcm_new);
G
Geoffrey Wossum 已提交
103

B
Bo Shen 已提交
104
void atmel_pcm_free(struct snd_pcm *pcm)
G
Geoffrey Wossum 已提交
105 106 107 108 109 110 111
{
	struct snd_pcm_substream *substream;
	struct snd_dma_buffer *buf;
	int stream;

	for (stream = 0; stream < 2; stream++) {
		substream = pcm->streams[stream].substream;
112
		if (!substream)
G
Geoffrey Wossum 已提交
113 114 115 116 117 118 119 120 121 122
			continue;

		buf = &substream->dma_buffer;
		if (!buf->area)
			continue;
		dma_free_coherent(pcm->card->dev, buf->bytes,
				  buf->area, buf->addr);
		buf->area = NULL;
	}
}
B
Bo Shen 已提交
123
EXPORT_SYMBOL_GPL(atmel_pcm_free);
G
Geoffrey Wossum 已提交
124