ASoC: tegra: register 'platform' from DAIs, get rid of pdev
[firefly-linux-kernel-4.4.55.git] / sound / soc / tegra / tegra_pcm.c
1 /*
2  * tegra_pcm.c - Tegra PCM driver
3  *
4  * Author: Stephen Warren <swarren@nvidia.com>
5  * Copyright (C) 2010,2012 - NVIDIA, Inc.
6  *
7  * Based on code copyright/by:
8  *
9  * Copyright (c) 2009-2010, NVIDIA Corporation.
10  * Scott Peterson <speterson@nvidia.com>
11  * Vijay Mali <vmali@nvidia.com>
12  *
13  * Copyright (C) 2010 Google, Inc.
14  * Iliyan Malchev <malchev@google.com>
15  *
16  * This program is free software; you can redistribute it and/or
17  * modify it under the terms of the GNU General Public License
18  * version 2 as published by the Free Software Foundation.
19  *
20  * This program is distributed in the hope that it will be useful, but
21  * WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
28  * 02110-1301 USA
29  *
30  */
31
32 #include <linux/module.h>
33 #include <linux/dma-mapping.h>
34 #include <linux/slab.h>
35 #include <sound/core.h>
36 #include <sound/pcm.h>
37 #include <sound/pcm_params.h>
38 #include <sound/soc.h>
39
40 #include "tegra_pcm.h"
41
42 static const struct snd_pcm_hardware tegra_pcm_hardware = {
43         .info                   = SNDRV_PCM_INFO_MMAP |
44                                   SNDRV_PCM_INFO_MMAP_VALID |
45                                   SNDRV_PCM_INFO_PAUSE |
46                                   SNDRV_PCM_INFO_RESUME |
47                                   SNDRV_PCM_INFO_INTERLEAVED,
48         .formats                = SNDRV_PCM_FMTBIT_S16_LE,
49         .channels_min           = 2,
50         .channels_max           = 2,
51         .period_bytes_min       = 1024,
52         .period_bytes_max       = PAGE_SIZE,
53         .periods_min            = 2,
54         .periods_max            = 8,
55         .buffer_bytes_max       = PAGE_SIZE * 8,
56         .fifo_size              = 4,
57 };
58
59 static void tegra_pcm_queue_dma(struct tegra_runtime_data *prtd)
60 {
61         struct snd_pcm_substream *substream = prtd->substream;
62         struct snd_dma_buffer *buf = &substream->dma_buffer;
63         struct tegra_dma_req *dma_req;
64         unsigned long addr;
65
66         dma_req = &prtd->dma_req[prtd->dma_req_idx];
67         prtd->dma_req_idx = 1 - prtd->dma_req_idx;
68
69         addr = buf->addr + prtd->dma_pos;
70         prtd->dma_pos += dma_req->size;
71         if (prtd->dma_pos >= prtd->dma_pos_end)
72                 prtd->dma_pos = 0;
73
74         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
75                 dma_req->source_addr = addr;
76         else
77                 dma_req->dest_addr = addr;
78
79         tegra_dma_enqueue_req(prtd->dma_chan, dma_req);
80 }
81
82 static void dma_complete_callback(struct tegra_dma_req *req)
83 {
84         struct tegra_runtime_data *prtd = (struct tegra_runtime_data *)req->dev;
85         struct snd_pcm_substream *substream = prtd->substream;
86         struct snd_pcm_runtime *runtime = substream->runtime;
87
88         spin_lock(&prtd->lock);
89
90         if (!prtd->running) {
91                 spin_unlock(&prtd->lock);
92                 return;
93         }
94
95         if (++prtd->period_index >= runtime->periods)
96                 prtd->period_index = 0;
97
98         tegra_pcm_queue_dma(prtd);
99
100         spin_unlock(&prtd->lock);
101
102         snd_pcm_period_elapsed(substream);
103 }
104
105 static void setup_dma_tx_request(struct tegra_dma_req *req,
106                                         struct tegra_pcm_dma_params * dmap)
107 {
108         req->complete = dma_complete_callback;
109         req->to_memory = false;
110         req->dest_addr = dmap->addr;
111         req->dest_wrap = dmap->wrap;
112         req->source_bus_width = 32;
113         req->source_wrap = 0;
114         req->dest_bus_width = dmap->width;
115         req->req_sel = dmap->req_sel;
116 }
117
118 static void setup_dma_rx_request(struct tegra_dma_req *req,
119                                         struct tegra_pcm_dma_params * dmap)
120 {
121         req->complete = dma_complete_callback;
122         req->to_memory = true;
123         req->source_addr = dmap->addr;
124         req->dest_wrap = 0;
125         req->source_bus_width = dmap->width;
126         req->source_wrap = dmap->wrap;
127         req->dest_bus_width = 32;
128         req->req_sel = dmap->req_sel;
129 }
130
131 static int tegra_pcm_open(struct snd_pcm_substream *substream)
132 {
133         struct snd_pcm_runtime *runtime = substream->runtime;
134         struct tegra_runtime_data *prtd;
135         struct snd_soc_pcm_runtime *rtd = substream->private_data;
136         struct tegra_pcm_dma_params * dmap;
137         int ret = 0;
138
139         prtd = kzalloc(sizeof(struct tegra_runtime_data), GFP_KERNEL);
140         if (prtd == NULL)
141                 return -ENOMEM;
142
143         runtime->private_data = prtd;
144         prtd->substream = substream;
145
146         spin_lock_init(&prtd->lock);
147
148         if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
149                 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
150                 setup_dma_tx_request(&prtd->dma_req[0], dmap);
151                 setup_dma_tx_request(&prtd->dma_req[1], dmap);
152         } else {
153                 dmap = snd_soc_dai_get_dma_data(rtd->cpu_dai, substream);
154                 setup_dma_rx_request(&prtd->dma_req[0], dmap);
155                 setup_dma_rx_request(&prtd->dma_req[1], dmap);
156         }
157
158         prtd->dma_req[0].dev = prtd;
159         prtd->dma_req[1].dev = prtd;
160
161         prtd->dma_chan = tegra_dma_allocate_channel(TEGRA_DMA_MODE_ONESHOT);
162         if (prtd->dma_chan == NULL) {
163                 ret = -ENOMEM;
164                 goto err;
165         }
166
167         /* Set HW params now that initialization is complete */
168         snd_soc_set_runtime_hwparams(substream, &tegra_pcm_hardware);
169
170         /* Ensure that buffer size is a multiple of period size */
171         ret = snd_pcm_hw_constraint_integer(runtime,
172                                                 SNDRV_PCM_HW_PARAM_PERIODS);
173         if (ret < 0)
174                 goto err;
175
176         return 0;
177
178 err:
179         if (prtd->dma_chan) {
180                 tegra_dma_free_channel(prtd->dma_chan);
181         }
182
183         kfree(prtd);
184
185         return ret;
186 }
187
188 static int tegra_pcm_close(struct snd_pcm_substream *substream)
189 {
190         struct snd_pcm_runtime *runtime = substream->runtime;
191         struct tegra_runtime_data *prtd = runtime->private_data;
192
193         tegra_dma_free_channel(prtd->dma_chan);
194
195         kfree(prtd);
196
197         return 0;
198 }
199
200 static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
201                                 struct snd_pcm_hw_params *params)
202 {
203         struct snd_pcm_runtime *runtime = substream->runtime;
204         struct tegra_runtime_data *prtd = runtime->private_data;
205
206         snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer);
207
208         prtd->dma_req[0].size = params_period_bytes(params);
209         prtd->dma_req[1].size = prtd->dma_req[0].size;
210
211         return 0;
212 }
213
214 static int tegra_pcm_hw_free(struct snd_pcm_substream *substream)
215 {
216         snd_pcm_set_runtime_buffer(substream, NULL);
217
218         return 0;
219 }
220
221 static int tegra_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
222 {
223         struct snd_pcm_runtime *runtime = substream->runtime;
224         struct tegra_runtime_data *prtd = runtime->private_data;
225         unsigned long flags;
226
227         switch (cmd) {
228         case SNDRV_PCM_TRIGGER_START:
229                 prtd->dma_pos = 0;
230                 prtd->dma_pos_end = frames_to_bytes(runtime, runtime->periods * runtime->period_size);
231                 prtd->period_index = 0;
232                 prtd->dma_req_idx = 0;
233                 /* Fall-through */
234         case SNDRV_PCM_TRIGGER_RESUME:
235         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
236                 spin_lock_irqsave(&prtd->lock, flags);
237                 prtd->running = 1;
238                 spin_unlock_irqrestore(&prtd->lock, flags);
239                 tegra_pcm_queue_dma(prtd);
240                 tegra_pcm_queue_dma(prtd);
241                 break;
242         case SNDRV_PCM_TRIGGER_STOP:
243         case SNDRV_PCM_TRIGGER_SUSPEND:
244         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
245                 spin_lock_irqsave(&prtd->lock, flags);
246                 prtd->running = 0;
247                 spin_unlock_irqrestore(&prtd->lock, flags);
248                 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[0]);
249                 tegra_dma_dequeue_req(prtd->dma_chan, &prtd->dma_req[1]);
250                 break;
251         default:
252                 return -EINVAL;
253         }
254
255         return 0;
256 }
257
258 static snd_pcm_uframes_t tegra_pcm_pointer(struct snd_pcm_substream *substream)
259 {
260         struct snd_pcm_runtime *runtime = substream->runtime;
261         struct tegra_runtime_data *prtd = runtime->private_data;
262
263         return prtd->period_index * runtime->period_size;
264 }
265
266
267 static int tegra_pcm_mmap(struct snd_pcm_substream *substream,
268                                 struct vm_area_struct *vma)
269 {
270         struct snd_pcm_runtime *runtime = substream->runtime;
271
272         return dma_mmap_writecombine(substream->pcm->card->dev, vma,
273                                         runtime->dma_area,
274                                         runtime->dma_addr,
275                                         runtime->dma_bytes);
276 }
277
278 static struct snd_pcm_ops tegra_pcm_ops = {
279         .open           = tegra_pcm_open,
280         .close          = tegra_pcm_close,
281         .ioctl          = snd_pcm_lib_ioctl,
282         .hw_params      = tegra_pcm_hw_params,
283         .hw_free        = tegra_pcm_hw_free,
284         .trigger        = tegra_pcm_trigger,
285         .pointer        = tegra_pcm_pointer,
286         .mmap           = tegra_pcm_mmap,
287 };
288
289 static int tegra_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, int stream)
290 {
291         struct snd_pcm_substream *substream = pcm->streams[stream].substream;
292         struct snd_dma_buffer *buf = &substream->dma_buffer;
293         size_t size = tegra_pcm_hardware.buffer_bytes_max;
294
295         buf->area = dma_alloc_writecombine(pcm->card->dev, size,
296                                                 &buf->addr, GFP_KERNEL);
297         if (!buf->area)
298                 return -ENOMEM;
299
300         buf->dev.type = SNDRV_DMA_TYPE_DEV;
301         buf->dev.dev = pcm->card->dev;
302         buf->private_data = NULL;
303         buf->bytes = size;
304
305         return 0;
306 }
307
308 static void tegra_pcm_deallocate_dma_buffer(struct snd_pcm *pcm, int stream)
309 {
310         struct snd_pcm_substream *substream;
311         struct snd_dma_buffer *buf;
312
313         substream = pcm->streams[stream].substream;
314         if (!substream)
315                 return;
316
317         buf = &substream->dma_buffer;
318         if (!buf->area)
319                 return;
320
321         dma_free_writecombine(pcm->card->dev, buf->bytes,
322                                 buf->area, buf->addr);
323         buf->area = NULL;
324 }
325
326 static u64 tegra_dma_mask = DMA_BIT_MASK(32);
327
328 static int tegra_pcm_new(struct snd_soc_pcm_runtime *rtd)
329 {
330         struct snd_card *card = rtd->card->snd_card;
331         struct snd_pcm *pcm = rtd->pcm;
332         int ret = 0;
333
334         if (!card->dev->dma_mask)
335                 card->dev->dma_mask = &tegra_dma_mask;
336         if (!card->dev->coherent_dma_mask)
337                 card->dev->coherent_dma_mask = DMA_BIT_MASK(32);
338
339         if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
340                 ret = tegra_pcm_preallocate_dma_buffer(pcm,
341                                                 SNDRV_PCM_STREAM_PLAYBACK);
342                 if (ret)
343                         goto err;
344         }
345
346         if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
347                 ret = tegra_pcm_preallocate_dma_buffer(pcm,
348                                                 SNDRV_PCM_STREAM_CAPTURE);
349                 if (ret)
350                         goto err_free_play;
351         }
352
353         return 0;
354
355 err_free_play:
356         tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
357 err:
358         return ret;
359 }
360
361 static void tegra_pcm_free(struct snd_pcm *pcm)
362 {
363         tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE);
364         tegra_pcm_deallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK);
365 }
366
367 static struct snd_soc_platform_driver tegra_pcm_platform = {
368         .ops            = &tegra_pcm_ops,
369         .pcm_new        = tegra_pcm_new,
370         .pcm_free       = tegra_pcm_free,
371 };
372
373 int __devinit tegra_pcm_platform_register(struct device *dev)
374 {
375         return snd_soc_register_platform(dev, &tegra_pcm_platform);
376 }
377 EXPORT_SYMBOL_GPL(tegra_pcm_platform_register);
378
379 void __devexit tegra_pcm_platform_unregister(struct device *dev)
380 {
381         snd_soc_unregister_platform(dev);
382 }
383 EXPORT_SYMBOL_GPL(tegra_pcm_platform_unregister);
384
385 MODULE_AUTHOR("Stephen Warren <swarren@nvidia.com>");
386 MODULE_DESCRIPTION("Tegra PCM ASoC driver");
387 MODULE_LICENSE("GPL");