]> git.karo-electronics.de Git - karo-tx-linux.git/blob - sound/soc/intel/sst-baytrail-pcm.c
Merge tag 'md/3.15' of git://neil.brown.name/md
[karo-tx-linux.git] / sound / soc / intel / sst-baytrail-pcm.c
1 /*
2  * Intel Baytrail SST PCM Support
3  * Copyright (c) 2014, Intel Corporation.
4  *
5  * This program is free software; you can redistribute it and/or modify it
6  * under the terms and conditions of the GNU General Public License,
7  * version 2, as published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
12  * more details.
13  */
14
15 #include <linux/module.h>
16 #include <linux/dma-mapping.h>
17 #include <linux/slab.h>
18 #include <sound/core.h>
19 #include <sound/pcm.h>
20 #include <sound/pcm_params.h>
21 #include <sound/soc.h>
22 #include "sst-baytrail-ipc.h"
23 #include "sst-dsp-priv.h"
24 #include "sst-dsp.h"
25
26 #define BYT_PCM_COUNT           2
27
28 static const struct snd_pcm_hardware sst_byt_pcm_hardware = {
29         .info                   = SNDRV_PCM_INFO_MMAP |
30                                   SNDRV_PCM_INFO_MMAP_VALID |
31                                   SNDRV_PCM_INFO_INTERLEAVED |
32                                   SNDRV_PCM_INFO_PAUSE |
33                                   SNDRV_PCM_INFO_RESUME,
34         .formats                = SNDRV_PCM_FMTBIT_S16_LE |
35                                   SNDRV_PCM_FORMAT_S24_LE,
36         .period_bytes_min       = 384,
37         .period_bytes_max       = 48000,
38         .periods_min            = 2,
39         .periods_max            = 250,
40         .buffer_bytes_max       = 96000,
41 };
42
43 /* private data for each PCM DSP stream */
44 struct sst_byt_pcm_data {
45         struct sst_byt_stream *stream;
46         struct snd_pcm_substream *substream;
47         struct mutex mutex;
48 };
49
50 /* private data for the driver */
51 struct sst_byt_priv_data {
52         /* runtime DSP */
53         struct sst_byt *byt;
54
55         /* DAI data */
56         struct sst_byt_pcm_data pcm[BYT_PCM_COUNT];
57 };
58
59 /* this may get called several times by oss emulation */
60 static int sst_byt_pcm_hw_params(struct snd_pcm_substream *substream,
61                                  struct snd_pcm_hw_params *params)
62 {
63         struct snd_soc_pcm_runtime *rtd = substream->private_data;
64         struct sst_byt_priv_data *pdata =
65                 snd_soc_platform_get_drvdata(rtd->platform);
66         struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
67         struct sst_byt *byt = pdata->byt;
68         u32 rate, bits;
69         u8 channels;
70         int ret, playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK);
71
72         dev_dbg(rtd->dev, "PCM: hw_params, pcm_data %p\n", pcm_data);
73
74         ret = sst_byt_stream_type(byt, pcm_data->stream,
75                                   1, 1, !playback);
76         if (ret < 0) {
77                 dev_err(rtd->dev, "failed to set stream format %d\n", ret);
78                 return ret;
79         }
80
81         rate = params_rate(params);
82         ret = sst_byt_stream_set_rate(byt, pcm_data->stream, rate);
83         if (ret < 0) {
84                 dev_err(rtd->dev, "could not set rate %d\n", rate);
85                 return ret;
86         }
87
88         bits = snd_pcm_format_width(params_format(params));
89         ret = sst_byt_stream_set_bits(byt, pcm_data->stream, bits);
90         if (ret < 0) {
91                 dev_err(rtd->dev, "could not set formats %d\n",
92                         params_rate(params));
93                 return ret;
94         }
95
96         channels = (u8)(params_channels(params) & 0xF);
97         ret = sst_byt_stream_set_channels(byt, pcm_data->stream, channels);
98         if (ret < 0) {
99                 dev_err(rtd->dev, "could not set channels %d\n",
100                         params_rate(params));
101                 return ret;
102         }
103
104         snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
105
106         ret = sst_byt_stream_buffer(byt, pcm_data->stream,
107                                     substream->dma_buffer.addr,
108                                     params_buffer_bytes(params));
109         if (ret < 0) {
110                 dev_err(rtd->dev, "PCM: failed to set DMA buffer %d\n", ret);
111                 return ret;
112         }
113
114         ret = sst_byt_stream_commit(byt, pcm_data->stream);
115         if (ret < 0) {
116                 dev_err(rtd->dev, "PCM: failed stream commit %d\n", ret);
117                 return ret;
118         }
119
120         return 0;
121 }
122
123 static int sst_byt_pcm_hw_free(struct snd_pcm_substream *substream)
124 {
125         struct snd_soc_pcm_runtime *rtd = substream->private_data;
126
127         dev_dbg(rtd->dev, "PCM: hw_free\n");
128         snd_pcm_lib_free_pages(substream);
129
130         return 0;
131 }
132
133 static int sst_byt_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
134 {
135         struct snd_soc_pcm_runtime *rtd = substream->private_data;
136         struct sst_byt_priv_data *pdata =
137                 snd_soc_platform_get_drvdata(rtd->platform);
138         struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
139         struct sst_byt *byt = pdata->byt;
140
141         dev_dbg(rtd->dev, "PCM: trigger %d\n", cmd);
142
143         switch (cmd) {
144         case SNDRV_PCM_TRIGGER_START:
145                 sst_byt_stream_start(byt, pcm_data->stream);
146                 break;
147         case SNDRV_PCM_TRIGGER_RESUME:
148         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
149                 sst_byt_stream_resume(byt, pcm_data->stream);
150                 break;
151         case SNDRV_PCM_TRIGGER_STOP:
152                 sst_byt_stream_stop(byt, pcm_data->stream);
153                 break;
154         case SNDRV_PCM_TRIGGER_SUSPEND:
155         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
156                 sst_byt_stream_pause(byt, pcm_data->stream);
157                 break;
158         default:
159                 break;
160         }
161
162         return 0;
163 }
164
165 static u32 byt_notify_pointer(struct sst_byt_stream *stream, void *data)
166 {
167         struct sst_byt_pcm_data *pcm_data = data;
168         struct snd_pcm_substream *substream = pcm_data->substream;
169         struct snd_pcm_runtime *runtime = substream->runtime;
170         struct snd_soc_pcm_runtime *rtd = substream->private_data;
171         u32 pos;
172
173         pos = frames_to_bytes(runtime,
174                               (runtime->control->appl_ptr %
175                                runtime->buffer_size));
176
177         dev_dbg(rtd->dev, "PCM: App pointer %d bytes\n", pos);
178
179         snd_pcm_period_elapsed(substream);
180         return pos;
181 }
182
183 static snd_pcm_uframes_t sst_byt_pcm_pointer(struct snd_pcm_substream *substream)
184 {
185         struct snd_soc_pcm_runtime *rtd = substream->private_data;
186         struct snd_pcm_runtime *runtime = substream->runtime;
187         struct sst_byt_priv_data *pdata =
188                 snd_soc_platform_get_drvdata(rtd->platform);
189         struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
190         struct sst_byt *byt = pdata->byt;
191         snd_pcm_uframes_t offset;
192         int pos;
193
194         pos = sst_byt_get_dsp_position(byt, pcm_data->stream,
195                                        snd_pcm_lib_buffer_bytes(substream));
196         offset = bytes_to_frames(runtime, pos);
197
198         dev_dbg(rtd->dev, "PCM: DMA pointer %zu bytes\n",
199                 frames_to_bytes(runtime, (u32)offset));
200         return offset;
201 }
202
203 static int sst_byt_pcm_open(struct snd_pcm_substream *substream)
204 {
205         struct snd_soc_pcm_runtime *rtd = substream->private_data;
206         struct sst_byt_priv_data *pdata =
207                 snd_soc_platform_get_drvdata(rtd->platform);
208         struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
209         struct sst_byt *byt = pdata->byt;
210
211         dev_dbg(rtd->dev, "PCM: open\n");
212
213         pcm_data = &pdata->pcm[rtd->cpu_dai->id];
214         mutex_lock(&pcm_data->mutex);
215
216         snd_soc_pcm_set_drvdata(rtd, pcm_data);
217         pcm_data->substream = substream;
218
219         snd_soc_set_runtime_hwparams(substream, &sst_byt_pcm_hardware);
220
221         pcm_data->stream = sst_byt_stream_new(byt, rtd->cpu_dai->id + 1,
222                                               byt_notify_pointer, pcm_data);
223         if (pcm_data->stream == NULL) {
224                 dev_err(rtd->dev, "failed to create stream\n");
225                 mutex_unlock(&pcm_data->mutex);
226                 return -EINVAL;
227         }
228
229         mutex_unlock(&pcm_data->mutex);
230         return 0;
231 }
232
233 static int sst_byt_pcm_close(struct snd_pcm_substream *substream)
234 {
235         struct snd_soc_pcm_runtime *rtd = substream->private_data;
236         struct sst_byt_priv_data *pdata =
237                 snd_soc_platform_get_drvdata(rtd->platform);
238         struct sst_byt_pcm_data *pcm_data = snd_soc_pcm_get_drvdata(rtd);
239         struct sst_byt *byt = pdata->byt;
240         int ret;
241
242         dev_dbg(rtd->dev, "PCM: close\n");
243
244         mutex_lock(&pcm_data->mutex);
245         ret = sst_byt_stream_free(byt, pcm_data->stream);
246         if (ret < 0) {
247                 dev_dbg(rtd->dev, "Free stream fail\n");
248                 goto out;
249         }
250         pcm_data->stream = NULL;
251
252 out:
253         mutex_unlock(&pcm_data->mutex);
254         return ret;
255 }
256
257 static int sst_byt_pcm_mmap(struct snd_pcm_substream *substream,
258                             struct vm_area_struct *vma)
259 {
260         struct snd_soc_pcm_runtime *rtd = substream->private_data;
261
262         dev_dbg(rtd->dev, "PCM: mmap\n");
263         return snd_pcm_lib_default_mmap(substream, vma);
264 }
265
266 static struct snd_pcm_ops sst_byt_pcm_ops = {
267         .open           = sst_byt_pcm_open,
268         .close          = sst_byt_pcm_close,
269         .ioctl          = snd_pcm_lib_ioctl,
270         .hw_params      = sst_byt_pcm_hw_params,
271         .hw_free        = sst_byt_pcm_hw_free,
272         .trigger        = sst_byt_pcm_trigger,
273         .pointer        = sst_byt_pcm_pointer,
274         .mmap           = sst_byt_pcm_mmap,
275 };
276
277 static void sst_byt_pcm_free(struct snd_pcm *pcm)
278 {
279         snd_pcm_lib_preallocate_free_for_all(pcm);
280 }
281
282 static int sst_byt_pcm_new(struct snd_soc_pcm_runtime *rtd)
283 {
284         struct snd_pcm *pcm = rtd->pcm;
285         size_t size;
286         int ret = 0;
287
288         ret = dma_coerce_mask_and_coherent(rtd->card->dev, DMA_BIT_MASK(32));
289         if (ret)
290                 return ret;
291
292         if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
293             pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
294                 size = sst_byt_pcm_hardware.buffer_bytes_max;
295                 ret = snd_pcm_lib_preallocate_pages_for_all(pcm,
296                                                             SNDRV_DMA_TYPE_DEV,
297                                                             rtd->card->dev,
298                                                             size, size);
299                 if (ret) {
300                         dev_err(rtd->dev, "dma buffer allocation failed %d\n",
301                                 ret);
302                         return ret;
303                 }
304         }
305
306         return ret;
307 }
308
309 static struct snd_soc_dai_driver byt_dais[] = {
310         {
311                 .name  = "Front-cpu-dai",
312                 .playback = {
313                         .stream_name = "System Playback",
314                         .channels_min = 2,
315                         .channels_max = 2,
316                         .rates = SNDRV_PCM_RATE_48000,
317                         .formats = SNDRV_PCM_FMTBIT_S24_3LE |
318                                    SNDRV_PCM_FMTBIT_S16_LE,
319                 },
320         },
321         {
322                 .name  = "Mic1-cpu-dai",
323                 .capture = {
324                         .stream_name = "Analog Capture",
325                         .channels_min = 2,
326                         .channels_max = 2,
327                         .rates = SNDRV_PCM_RATE_48000,
328                         .formats = SNDRV_PCM_FMTBIT_S16_LE,
329                 },
330         },
331 };
332
333 static int sst_byt_pcm_probe(struct snd_soc_platform *platform)
334 {
335         struct sst_pdata *plat_data = dev_get_platdata(platform->dev);
336         struct sst_byt_priv_data *priv_data;
337         int i;
338
339         if (!plat_data)
340                 return -ENODEV;
341
342         priv_data = devm_kzalloc(platform->dev, sizeof(*priv_data),
343                                  GFP_KERNEL);
344         priv_data->byt = plat_data->dsp;
345         snd_soc_platform_set_drvdata(platform, priv_data);
346
347         for (i = 0; i < ARRAY_SIZE(byt_dais); i++)
348                 mutex_init(&priv_data->pcm[i].mutex);
349
350         return 0;
351 }
352
353 static int sst_byt_pcm_remove(struct snd_soc_platform *platform)
354 {
355         return 0;
356 }
357
358 static struct snd_soc_platform_driver byt_soc_platform = {
359         .probe          = sst_byt_pcm_probe,
360         .remove         = sst_byt_pcm_remove,
361         .ops            = &sst_byt_pcm_ops,
362         .pcm_new        = sst_byt_pcm_new,
363         .pcm_free       = sst_byt_pcm_free,
364 };
365
366 static const struct snd_soc_component_driver byt_dai_component = {
367         .name           = "byt-dai",
368 };
369
370 static int sst_byt_pcm_dev_probe(struct platform_device *pdev)
371 {
372         struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev);
373         int ret;
374
375         ret = sst_byt_dsp_init(&pdev->dev, sst_pdata);
376         if (ret < 0)
377                 return -ENODEV;
378
379         ret = snd_soc_register_platform(&pdev->dev, &byt_soc_platform);
380         if (ret < 0)
381                 goto err_plat;
382
383         ret = snd_soc_register_component(&pdev->dev, &byt_dai_component,
384                                          byt_dais, ARRAY_SIZE(byt_dais));
385         if (ret < 0)
386                 goto err_comp;
387
388         return 0;
389
390 err_comp:
391         snd_soc_unregister_platform(&pdev->dev);
392 err_plat:
393         sst_byt_dsp_free(&pdev->dev, sst_pdata);
394         return ret;
395 }
396
397 static int sst_byt_pcm_dev_remove(struct platform_device *pdev)
398 {
399         struct sst_pdata *sst_pdata = dev_get_platdata(&pdev->dev);
400
401         snd_soc_unregister_platform(&pdev->dev);
402         snd_soc_unregister_component(&pdev->dev);
403         sst_byt_dsp_free(&pdev->dev, sst_pdata);
404
405         return 0;
406 }
407
408 static struct platform_driver sst_byt_pcm_driver = {
409         .driver = {
410                 .name = "baytrail-pcm-audio",
411                 .owner = THIS_MODULE,
412         },
413
414         .probe = sst_byt_pcm_dev_probe,
415         .remove = sst_byt_pcm_dev_remove,
416 };
417 module_platform_driver(sst_byt_pcm_driver);
418
419 MODULE_AUTHOR("Jarkko Nikula");
420 MODULE_DESCRIPTION("Baytrail PCM");
421 MODULE_LICENSE("GPL v2");
422 MODULE_ALIAS("platform:baytrail-pcm-audio");