2 * Intel Baytrail SST PCM Support
3 * Copyright (c) 2014, Intel Corporation.
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.
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
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"
26 #define BYT_PCM_COUNT 2
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_FMTBIT_S24_LE
,
36 .period_bytes_min
= 384,
37 .period_bytes_max
= 48000,
40 .buffer_bytes_max
= 96000,
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
;
49 /* latest DSP DMA hw pointer */
52 struct work_struct work
;
55 /* private data for the driver */
56 struct sst_byt_priv_data
{
61 struct sst_byt_pcm_data pcm
[BYT_PCM_COUNT
];
64 /* this may get called several times by oss emulation */
65 static int sst_byt_pcm_hw_params(struct snd_pcm_substream
*substream
,
66 struct snd_pcm_hw_params
*params
)
68 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
69 struct sst_byt_priv_data
*pdata
=
70 snd_soc_platform_get_drvdata(rtd
->platform
);
71 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
72 struct sst_byt
*byt
= pdata
->byt
;
75 int ret
, playback
= (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
);
77 dev_dbg(rtd
->dev
, "PCM: hw_params, pcm_data %p\n", pcm_data
);
79 ret
= sst_byt_stream_type(byt
, pcm_data
->stream
,
82 dev_err(rtd
->dev
, "failed to set stream format %d\n", ret
);
86 rate
= params_rate(params
);
87 ret
= sst_byt_stream_set_rate(byt
, pcm_data
->stream
, rate
);
89 dev_err(rtd
->dev
, "could not set rate %d\n", rate
);
93 bits
= snd_pcm_format_width(params_format(params
));
94 ret
= sst_byt_stream_set_bits(byt
, pcm_data
->stream
, bits
);
96 dev_err(rtd
->dev
, "could not set formats %d\n",
101 channels
= (u8
)(params_channels(params
) & 0xF);
102 ret
= sst_byt_stream_set_channels(byt
, pcm_data
->stream
, channels
);
104 dev_err(rtd
->dev
, "could not set channels %d\n",
105 params_rate(params
));
109 snd_pcm_lib_malloc_pages(substream
, params_buffer_bytes(params
));
111 ret
= sst_byt_stream_buffer(byt
, pcm_data
->stream
,
112 substream
->dma_buffer
.addr
,
113 params_buffer_bytes(params
));
115 dev_err(rtd
->dev
, "PCM: failed to set DMA buffer %d\n", ret
);
119 ret
= sst_byt_stream_commit(byt
, pcm_data
->stream
);
121 dev_err(rtd
->dev
, "PCM: failed stream commit %d\n", ret
);
128 static int sst_byt_pcm_hw_free(struct snd_pcm_substream
*substream
)
130 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
132 dev_dbg(rtd
->dev
, "PCM: hw_free\n");
133 snd_pcm_lib_free_pages(substream
);
138 static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream
*substream
)
140 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
141 struct sst_byt_priv_data
*pdata
=
142 snd_soc_platform_get_drvdata(rtd
->platform
);
143 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
144 struct sst_byt
*byt
= pdata
->byt
;
147 /* commit stream using existing stream params */
148 ret
= sst_byt_stream_commit(byt
, pcm_data
->stream
);
150 dev_err(rtd
->dev
, "PCM: failed stream commit %d\n", ret
);
154 sst_byt_stream_start(byt
, pcm_data
->stream
, pcm_data
->hw_ptr
);
156 dev_dbg(rtd
->dev
, "stream context restored at offset %d\n",
162 static void sst_byt_pcm_work(struct work_struct
*work
)
164 struct sst_byt_pcm_data
*pcm_data
=
165 container_of(work
, struct sst_byt_pcm_data
, work
);
167 if (snd_pcm_running(pcm_data
->substream
))
168 sst_byt_pcm_restore_stream_context(pcm_data
->substream
);
171 static int sst_byt_pcm_trigger(struct snd_pcm_substream
*substream
, int cmd
)
173 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
174 struct sst_byt_priv_data
*pdata
=
175 snd_soc_platform_get_drvdata(rtd
->platform
);
176 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
177 struct sst_byt
*byt
= pdata
->byt
;
179 dev_dbg(rtd
->dev
, "PCM: trigger %d\n", cmd
);
182 case SNDRV_PCM_TRIGGER_START
:
183 pcm_data
->hw_ptr
= 0;
184 sst_byt_stream_start(byt
, pcm_data
->stream
, 0);
186 case SNDRV_PCM_TRIGGER_RESUME
:
187 schedule_work(&pcm_data
->work
);
189 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
190 sst_byt_stream_resume(byt
, pcm_data
->stream
);
192 case SNDRV_PCM_TRIGGER_STOP
:
193 sst_byt_stream_stop(byt
, pcm_data
->stream
);
195 case SNDRV_PCM_TRIGGER_SUSPEND
:
196 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
197 sst_byt_stream_pause(byt
, pcm_data
->stream
);
206 static u32
byt_notify_pointer(struct sst_byt_stream
*stream
, void *data
)
208 struct sst_byt_pcm_data
*pcm_data
= data
;
209 struct snd_pcm_substream
*substream
= pcm_data
->substream
;
210 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
211 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
212 struct sst_byt_priv_data
*pdata
=
213 snd_soc_platform_get_drvdata(rtd
->platform
);
214 struct sst_byt
*byt
= pdata
->byt
;
217 hw_pos
= sst_byt_get_dsp_position(byt
, pcm_data
->stream
,
218 snd_pcm_lib_buffer_bytes(substream
));
219 pcm_data
->hw_ptr
= hw_pos
;
220 pos
= frames_to_bytes(runtime
,
221 (runtime
->control
->appl_ptr
%
222 runtime
->buffer_size
));
224 dev_dbg(rtd
->dev
, "PCM: App/DMA pointer %u/%u bytes\n", pos
, hw_pos
);
226 snd_pcm_period_elapsed(substream
);
230 static snd_pcm_uframes_t
sst_byt_pcm_pointer(struct snd_pcm_substream
*substream
)
232 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
233 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
234 struct sst_byt_priv_data
*pdata
=
235 snd_soc_platform_get_drvdata(rtd
->platform
);
236 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
238 dev_dbg(rtd
->dev
, "PCM: DMA pointer %u bytes\n", pcm_data
->hw_ptr
);
240 return bytes_to_frames(runtime
, pcm_data
->hw_ptr
);
243 static int sst_byt_pcm_open(struct snd_pcm_substream
*substream
)
245 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
246 struct sst_byt_priv_data
*pdata
=
247 snd_soc_platform_get_drvdata(rtd
->platform
);
248 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
249 struct sst_byt
*byt
= pdata
->byt
;
251 dev_dbg(rtd
->dev
, "PCM: open\n");
253 mutex_lock(&pcm_data
->mutex
);
255 pcm_data
->substream
= substream
;
257 snd_soc_set_runtime_hwparams(substream
, &sst_byt_pcm_hardware
);
259 pcm_data
->stream
= sst_byt_stream_new(byt
, substream
->stream
+ 1,
260 byt_notify_pointer
, pcm_data
);
261 if (pcm_data
->stream
== NULL
) {
262 dev_err(rtd
->dev
, "failed to create stream\n");
263 mutex_unlock(&pcm_data
->mutex
);
267 mutex_unlock(&pcm_data
->mutex
);
271 static int sst_byt_pcm_close(struct snd_pcm_substream
*substream
)
273 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
274 struct sst_byt_priv_data
*pdata
=
275 snd_soc_platform_get_drvdata(rtd
->platform
);
276 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
277 struct sst_byt
*byt
= pdata
->byt
;
280 dev_dbg(rtd
->dev
, "PCM: close\n");
282 cancel_work_sync(&pcm_data
->work
);
283 mutex_lock(&pcm_data
->mutex
);
284 ret
= sst_byt_stream_free(byt
, pcm_data
->stream
);
286 dev_dbg(rtd
->dev
, "Free stream fail\n");
289 pcm_data
->stream
= NULL
;
292 mutex_unlock(&pcm_data
->mutex
);
296 static int sst_byt_pcm_mmap(struct snd_pcm_substream
*substream
,
297 struct vm_area_struct
*vma
)
299 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
301 dev_dbg(rtd
->dev
, "PCM: mmap\n");
302 return snd_pcm_lib_default_mmap(substream
, vma
);
305 static struct snd_pcm_ops sst_byt_pcm_ops
= {
306 .open
= sst_byt_pcm_open
,
307 .close
= sst_byt_pcm_close
,
308 .ioctl
= snd_pcm_lib_ioctl
,
309 .hw_params
= sst_byt_pcm_hw_params
,
310 .hw_free
= sst_byt_pcm_hw_free
,
311 .trigger
= sst_byt_pcm_trigger
,
312 .pointer
= sst_byt_pcm_pointer
,
313 .mmap
= sst_byt_pcm_mmap
,
316 static void sst_byt_pcm_free(struct snd_pcm
*pcm
)
318 snd_pcm_lib_preallocate_free_for_all(pcm
);
321 static int sst_byt_pcm_new(struct snd_soc_pcm_runtime
*rtd
)
323 struct snd_pcm
*pcm
= rtd
->pcm
;
325 struct snd_soc_platform
*platform
= rtd
->platform
;
326 struct sst_pdata
*pdata
= dev_get_platdata(platform
->dev
);
329 if (pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
||
330 pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
) {
331 size
= sst_byt_pcm_hardware
.buffer_bytes_max
;
332 ret
= snd_pcm_lib_preallocate_pages_for_all(pcm
,
337 dev_err(rtd
->dev
, "dma buffer allocation failed %d\n",
346 static struct snd_soc_dai_driver byt_dais
[] = {
348 .name
= "Baytrail PCM",
350 .stream_name
= "System Playback",
353 .rates
= SNDRV_PCM_RATE_48000
,
354 .formats
= SNDRV_PCM_FMTBIT_S24_3LE
|
355 SNDRV_PCM_FMTBIT_S16_LE
,
358 .stream_name
= "Analog Capture",
361 .rates
= SNDRV_PCM_RATE_48000
,
362 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
367 static int sst_byt_pcm_probe(struct snd_soc_platform
*platform
)
369 struct sst_pdata
*plat_data
= dev_get_platdata(platform
->dev
);
370 struct sst_byt_priv_data
*priv_data
;
376 priv_data
= devm_kzalloc(platform
->dev
, sizeof(*priv_data
),
378 priv_data
->byt
= plat_data
->dsp
;
379 snd_soc_platform_set_drvdata(platform
, priv_data
);
381 for (i
= 0; i
< BYT_PCM_COUNT
; i
++) {
382 mutex_init(&priv_data
->pcm
[i
].mutex
);
383 INIT_WORK(&priv_data
->pcm
[i
].work
, sst_byt_pcm_work
);
389 static int sst_byt_pcm_remove(struct snd_soc_platform
*platform
)
394 static struct snd_soc_platform_driver byt_soc_platform
= {
395 .probe
= sst_byt_pcm_probe
,
396 .remove
= sst_byt_pcm_remove
,
397 .ops
= &sst_byt_pcm_ops
,
398 .pcm_new
= sst_byt_pcm_new
,
399 .pcm_free
= sst_byt_pcm_free
,
402 static const struct snd_soc_component_driver byt_dai_component
= {
407 static int sst_byt_pcm_dev_suspend_noirq(struct device
*dev
)
409 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
412 dev_dbg(dev
, "suspending noirq\n");
414 /* at this point all streams will be stopped and context saved */
415 ret
= sst_byt_dsp_suspend_noirq(dev
, sst_pdata
);
417 dev_err(dev
, "failed to suspend %d\n", ret
);
424 static int sst_byt_pcm_dev_suspend_late(struct device
*dev
)
426 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
429 dev_dbg(dev
, "suspending late\n");
431 ret
= sst_byt_dsp_suspend_late(dev
, sst_pdata
);
433 dev_err(dev
, "failed to suspend %d\n", ret
);
440 static int sst_byt_pcm_dev_resume_early(struct device
*dev
)
442 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
444 dev_dbg(dev
, "resume early\n");
446 /* load fw and boot DSP */
447 return sst_byt_dsp_boot(dev
, sst_pdata
);
450 static int sst_byt_pcm_dev_resume(struct device
*dev
)
452 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
454 dev_dbg(dev
, "resume\n");
456 /* wait for FW to finish booting */
457 return sst_byt_dsp_wait_for_ready(dev
, sst_pdata
);
460 static const struct dev_pm_ops sst_byt_pm_ops
= {
461 .suspend_noirq
= sst_byt_pcm_dev_suspend_noirq
,
462 .suspend_late
= sst_byt_pcm_dev_suspend_late
,
463 .resume_early
= sst_byt_pcm_dev_resume_early
,
464 .resume
= sst_byt_pcm_dev_resume
,
467 #define SST_BYT_PM_OPS (&sst_byt_pm_ops)
469 #define SST_BYT_PM_OPS NULL
472 static int sst_byt_pcm_dev_probe(struct platform_device
*pdev
)
474 struct sst_pdata
*sst_pdata
= dev_get_platdata(&pdev
->dev
);
477 ret
= sst_byt_dsp_init(&pdev
->dev
, sst_pdata
);
481 ret
= snd_soc_register_platform(&pdev
->dev
, &byt_soc_platform
);
485 ret
= snd_soc_register_component(&pdev
->dev
, &byt_dai_component
,
486 byt_dais
, ARRAY_SIZE(byt_dais
));
493 snd_soc_unregister_platform(&pdev
->dev
);
495 sst_byt_dsp_free(&pdev
->dev
, sst_pdata
);
499 static int sst_byt_pcm_dev_remove(struct platform_device
*pdev
)
501 struct sst_pdata
*sst_pdata
= dev_get_platdata(&pdev
->dev
);
503 snd_soc_unregister_platform(&pdev
->dev
);
504 snd_soc_unregister_component(&pdev
->dev
);
505 sst_byt_dsp_free(&pdev
->dev
, sst_pdata
);
510 static struct platform_driver sst_byt_pcm_driver
= {
512 .name
= "baytrail-pcm-audio",
513 .owner
= THIS_MODULE
,
514 .pm
= SST_BYT_PM_OPS
,
517 .probe
= sst_byt_pcm_dev_probe
,
518 .remove
= sst_byt_pcm_dev_remove
,
520 module_platform_driver(sst_byt_pcm_driver
);
522 MODULE_AUTHOR("Jarkko Nikula");
523 MODULE_DESCRIPTION("Baytrail PCM");
524 MODULE_LICENSE("GPL v2");
525 MODULE_ALIAS("platform:baytrail-pcm-audio");