pxa2xx-pcm.c 3.1 KB
Newer Older
L
Liam Girdwood 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * linux/sound/arm/pxa2xx-pcm.c -- ALSA PCM interface for the Intel PXA2xx chip
 *
 * Author:	Nicolas Pitre
 * Created:	Nov 30, 2004
 * Copyright:	(C) 2004 MontaVista Software, Inc.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#include <linux/dma-mapping.h>

#include <sound/core.h>
#include <sound/soc.h>
17
#include <sound/pxa2xx-lib.h>
L
Liam Girdwood 已提交
18 19

#include "pxa2xx-pcm.h"
20
#include "../../arm/pxa2xx-pcm.h"
L
Liam Girdwood 已提交
21 22 23 24 25 26 27

static int pxa2xx_pcm_hw_params(struct snd_pcm_substream *substream,
	struct snd_pcm_hw_params *params)
{
	struct snd_pcm_runtime *runtime = substream->runtime;
	struct pxa2xx_runtime_data *prtd = runtime->private_data;
	struct snd_soc_pcm_runtime *rtd = substream->private_data;
28
	struct pxa2xx_pcm_dma_params *dma = rtd->dai->cpu_dai->dma_data;
L
Liam Girdwood 已提交
29 30
	int ret;

31 32
	/* return if this is a bufferless transfer e.g.
	 * codec <--> BT codec or GSM modem -- lg FIXME */
33 34
	if (!dma)
		return 0;
35

L
Liam Girdwood 已提交
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54
	/* this may get called several times by oss emulation
	 * with different params */
	if (prtd->params == NULL) {
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	} else if (prtd->params != dma) {
		pxa_free_dma(prtd->dma_ch);
		prtd->params = dma;
		ret = pxa_request_dma(prtd->params->name, DMA_PRIO_LOW,
			      pxa2xx_pcm_dma_irq, substream);
		if (ret < 0)
			return ret;
		prtd->dma_ch = ret;
	}

55
	return __pxa2xx_pcm_hw_params(substream, params);
L
Liam Girdwood 已提交
56 57 58 59 60 61
}

static int pxa2xx_pcm_hw_free(struct snd_pcm_substream *substream)
{
	struct pxa2xx_runtime_data *prtd = substream->runtime->private_data;

62
	__pxa2xx_pcm_hw_free(substream);
L
Liam Girdwood 已提交
63 64 65 66 67 68 69 70 71 72

	if (prtd->dma_ch) {
		pxa_free_dma(prtd->dma_ch);
		prtd->dma_ch = 0;
	}

	return 0;
}

struct snd_pcm_ops pxa2xx_pcm_ops = {
73 74
	.open		= __pxa2xx_pcm_open,
	.close		= __pxa2xx_pcm_close,
L
Liam Girdwood 已提交
75 76 77
	.ioctl		= snd_pcm_lib_ioctl,
	.hw_params	= pxa2xx_pcm_hw_params,
	.hw_free	= pxa2xx_pcm_hw_free,
78
	.prepare	= __pxa2xx_pcm_prepare,
L
Liam Girdwood 已提交
79 80 81 82 83 84 85
	.trigger	= pxa2xx_pcm_trigger,
	.pointer	= pxa2xx_pcm_pointer,
	.mmap		= pxa2xx_pcm_mmap,
};

static u64 pxa2xx_pcm_dmamask = DMA_32BIT_MASK;

86
static int pxa2xx_soc_pcm_new(struct snd_card *card, struct snd_soc_dai *dai,
L
Liam Girdwood 已提交
87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
	struct snd_pcm *pcm)
{
	int ret = 0;

	if (!card->dev->dma_mask)
		card->dev->dma_mask = &pxa2xx_pcm_dmamask;
	if (!card->dev->coherent_dma_mask)
		card->dev->coherent_dma_mask = DMA_32BIT_MASK;

	if (dai->playback.channels_min) {
		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
			SNDRV_PCM_STREAM_PLAYBACK);
		if (ret)
			goto out;
	}

	if (dai->capture.channels_min) {
		ret = pxa2xx_pcm_preallocate_dma_buffer(pcm,
			SNDRV_PCM_STREAM_CAPTURE);
		if (ret)
			goto out;
	}
 out:
	return ret;
}

struct snd_soc_platform pxa2xx_soc_platform = {
	.name		= "pxa2xx-audio",
	.pcm_ops 	= &pxa2xx_pcm_ops,
116
	.pcm_new	= pxa2xx_soc_pcm_new,
L
Liam Girdwood 已提交
117 118 119 120 121 122 123
	.pcm_free	= pxa2xx_pcm_free_dma_buffers,
};
EXPORT_SYMBOL_GPL(pxa2xx_soc_platform);

MODULE_AUTHOR("Nicolas Pitre");
MODULE_DESCRIPTION("Intel PXA2xx PCM DMA module");
MODULE_LICENSE("GPL");