2 * s3c-dma-wrapper.c -- S3C DMA Platform Wrapper Driver
4 * Copyright (c) 2010 Samsung Electronics Co. Ltd
5 * Jaswinder Singh <jassi.brar@samsung.com>
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.
13 #include <sound/soc.h>
16 #include "s3c64xx-i2s.h"
18 static struct snd_soc_platform *s3c_wrpdma_get_platform(
19 struct snd_pcm_substream *substream)
21 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
22 #ifdef CONFIG_SND_S5P_RP
23 /* GDMA for Legacy Audio, IDMA for SRP Audio(dedicated codec) */
24 return &s3c24xx_soc_platform;
25 #elif defined CONFIG_S5P_INTERNAL_DMA
26 struct snd_soc_pcm_runtime *rtd = substream->private_data;
28 printk(KERN_ERR "%s, no pcm runtime data\n", __func__);
29 return &s3c24xx_soc_platform;
31 /* Use IDMA for Generic Audio and GDMA for External Audio */
32 if (strcmp(rtd->dai->stream_name, MC1N2_HIFI_STREAM_NAME) != 0)
33 return &s3c24xx_soc_platform;
35 return &idma_soc_platform;
37 /* GDMA for Generic Audio */
38 return &s3c24xx_soc_platform;
41 /* Capture is possible via GDMA only */
42 return &s3c24xx_soc_platform;
46 static int s3c_wrpdma_hw_params(struct snd_pcm_substream *substream,
47 struct snd_pcm_hw_params *params)
49 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
51 if (platform->pcm_ops->hw_params)
52 return platform->pcm_ops->hw_params(substream, params);
57 static int s3c_wrpdma_hw_free(struct snd_pcm_substream *substream)
59 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
61 if (platform->pcm_ops->hw_free)
62 return platform->pcm_ops->hw_free(substream);
67 static int s3c_wrpdma_prepare(struct snd_pcm_substream *substream)
69 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
71 if (platform->pcm_ops->prepare)
72 return platform->pcm_ops->prepare(substream);
77 static int s3c_wrpdma_trigger(struct snd_pcm_substream *substream, int cmd)
79 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
82 case SNDRV_PCM_TRIGGER_START:
83 case SNDRV_PCM_TRIGGER_RESUME:
84 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
85 s5p_i2s_do_resume_stream(substream);
91 if (platform->pcm_ops->trigger)
92 return platform->pcm_ops->trigger(substream, cmd);
97 static snd_pcm_uframes_t s3c_wrpdma_pointer(struct snd_pcm_substream *substream)
99 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
101 if (platform->pcm_ops->pointer)
102 return platform->pcm_ops->pointer(substream);
107 static int s3c_wrpdma_open(struct snd_pcm_substream *substream)
109 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
111 if (platform->pcm_ops->open)
112 return platform->pcm_ops->open(substream);
117 static int s3c_wrpdma_close(struct snd_pcm_substream *substream)
119 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
121 if (platform->pcm_ops->close)
122 return platform->pcm_ops->close(substream);
127 static int s3c_wrpdma_ioctl(struct snd_pcm_substream *substream,
128 unsigned int cmd, void *arg)
130 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
132 if (platform->pcm_ops->ioctl)
133 return platform->pcm_ops->ioctl(substream, cmd, arg);
138 static int s3c_wrpdma_mmap(struct snd_pcm_substream *substream,
139 struct vm_area_struct *vma)
141 struct snd_soc_platform *platform = s3c_wrpdma_get_platform(substream);
143 if (platform->pcm_ops->mmap)
144 return platform->pcm_ops->mmap(substream, vma);
149 static struct snd_pcm_ops s3c_wrpdma_ops = {
150 .open = s3c_wrpdma_open,
151 .close = s3c_wrpdma_close,
152 .ioctl = s3c_wrpdma_ioctl,
153 .hw_params = s3c_wrpdma_hw_params,
154 .hw_free = s3c_wrpdma_hw_free,
155 .prepare = s3c_wrpdma_prepare,
156 .trigger = s3c_wrpdma_trigger,
157 .pointer = s3c_wrpdma_pointer,
158 .mmap = s3c_wrpdma_mmap,
161 static void s3c_wrpdma_pcm_free(struct snd_pcm *pcm)
163 struct snd_soc_platform *gdma_platform;
164 #ifdef CONFIG_S5P_INTERNAL_DMA
165 struct snd_soc_platform *idma_platform;
168 #ifdef CONFIG_S5P_INTERNAL_DMA
169 idma_platform = &idma_soc_platform;
170 if (idma_platform->pcm_free)
171 idma_platform->pcm_free(pcm);
173 gdma_platform = &s3c24xx_soc_platform;
174 if (gdma_platform->pcm_free)
175 gdma_platform->pcm_free(pcm);
178 static int s3c_wrpdma_pcm_new(struct snd_card *card,
179 struct snd_soc_dai *dai, struct snd_pcm *pcm)
181 struct snd_soc_platform *gdma_platform;
182 #ifdef CONFIG_S5P_INTERNAL_DMA
183 struct snd_soc_platform *idma_platform;
186 /* sec_fifo i/f always use internal h/w buffers
187 * irrespective of the xfer method (iDMA or SysDMA) */
189 #ifdef CONFIG_S5P_INTERNAL_DMA
190 idma_platform = &idma_soc_platform;
191 if (idma_platform->pcm_new)
192 idma_platform->pcm_new(card, dai, pcm);
194 gdma_platform = &s3c24xx_soc_platform;
195 if (gdma_platform->pcm_new)
196 gdma_platform->pcm_new(card, dai, pcm);
201 struct snd_soc_platform s3c_dma_wrapper = {
202 .name = "samsung-audio",
203 .pcm_ops = &s3c_wrpdma_ops,
204 .pcm_new = s3c_wrpdma_pcm_new,
205 .pcm_free = s3c_wrpdma_pcm_free,
207 EXPORT_SYMBOL_GPL(s3c_dma_wrapper);
209 static int __init s3c_dma_wrapper_init(void)
211 return snd_soc_register_platform(&s3c_dma_wrapper);
213 module_init(s3c_dma_wrapper_init);
215 static void __exit s3c_dma_wrapper_exit(void)
217 snd_soc_unregister_platform(&s3c_dma_wrapper);
219 module_exit(s3c_dma_wrapper_exit);
221 MODULE_AUTHOR("Jaswinder Singh, <jassi.brar@samsung.com>");
222 MODULE_DESCRIPTION("Audio DMA wrapper module");
223 MODULE_LICENSE("GPL");