1 // SPDX-License-Identifier: GPL-2.0-only
3 * Intel Baytrail SST PCM Support
4 * Copyright (c) 2014, Intel Corporation.
7 #include <linux/module.h>
8 #include <linux/dma-mapping.h>
9 #include <linux/slab.h>
10 #include <sound/core.h>
11 #include <sound/pcm.h>
12 #include <sound/pcm_params.h>
13 #include <sound/soc.h>
14 #include "sst-baytrail-ipc.h"
15 #include "../common/sst-dsp-priv.h"
16 #include "../common/sst-dsp.h"
18 #define DRV_NAME "byt-dai"
19 #define BYT_PCM_COUNT 2
21 static const struct snd_pcm_hardware sst_byt_pcm_hardware
= {
22 .info
= SNDRV_PCM_INFO_MMAP
|
23 SNDRV_PCM_INFO_MMAP_VALID
|
24 SNDRV_PCM_INFO_INTERLEAVED
|
25 SNDRV_PCM_INFO_PAUSE
|
26 SNDRV_PCM_INFO_RESUME
,
27 .formats
= SNDRV_PCM_FMTBIT_S16_LE
|
28 SNDRV_PCM_FMTBIT_S24_LE
,
29 .period_bytes_min
= 384,
30 .period_bytes_max
= 48000,
33 .buffer_bytes_max
= 96000,
36 /* private data for each PCM DSP stream */
37 struct sst_byt_pcm_data
{
38 struct sst_byt_stream
*stream
;
39 struct snd_pcm_substream
*substream
;
42 /* latest DSP DMA hw pointer */
45 struct work_struct work
;
48 /* private data for the driver */
49 struct sst_byt_priv_data
{
54 struct sst_byt_pcm_data pcm
[BYT_PCM_COUNT
];
56 /* flag indicating is stream context restore needed after suspend */
60 /* this may get called several times by oss emulation */
61 static int sst_byt_pcm_hw_params(struct snd_soc_component
*component
,
62 struct snd_pcm_substream
*substream
,
63 struct snd_pcm_hw_params
*params
)
65 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
66 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
67 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
68 struct sst_byt
*byt
= pdata
->byt
;
71 int ret
, playback
= (substream
->stream
== SNDRV_PCM_STREAM_PLAYBACK
);
73 dev_dbg(rtd
->dev
, "PCM: hw_params, pcm_data %p\n", pcm_data
);
75 ret
= sst_byt_stream_type(byt
, pcm_data
->stream
,
78 dev_err(rtd
->dev
, "failed to set stream format %d\n", ret
);
82 rate
= params_rate(params
);
83 ret
= sst_byt_stream_set_rate(byt
, pcm_data
->stream
, rate
);
85 dev_err(rtd
->dev
, "could not set rate %d\n", rate
);
89 bits
= snd_pcm_format_width(params_format(params
));
90 ret
= sst_byt_stream_set_bits(byt
, pcm_data
->stream
, bits
);
92 dev_err(rtd
->dev
, "could not set formats %d\n",
97 channels
= (u8
)(params_channels(params
) & 0xF);
98 ret
= sst_byt_stream_set_channels(byt
, pcm_data
->stream
, channels
);
100 dev_err(rtd
->dev
, "could not set channels %d\n",
101 params_rate(params
));
105 ret
= sst_byt_stream_buffer(byt
, pcm_data
->stream
,
106 substream
->dma_buffer
.addr
,
107 params_buffer_bytes(params
));
109 dev_err(rtd
->dev
, "PCM: failed to set DMA buffer %d\n", ret
);
113 ret
= sst_byt_stream_commit(byt
, pcm_data
->stream
);
115 dev_err(rtd
->dev
, "PCM: failed stream commit %d\n", ret
);
122 static int sst_byt_pcm_restore_stream_context(struct snd_pcm_substream
*substream
)
124 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
125 struct snd_soc_component
*component
= snd_soc_rtdcom_lookup(rtd
, DRV_NAME
);
126 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
127 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
128 struct sst_byt
*byt
= pdata
->byt
;
131 /* commit stream using existing stream params */
132 ret
= sst_byt_stream_commit(byt
, pcm_data
->stream
);
134 dev_err(rtd
->dev
, "PCM: failed stream commit %d\n", ret
);
138 sst_byt_stream_start(byt
, pcm_data
->stream
, pcm_data
->hw_ptr
);
140 dev_dbg(rtd
->dev
, "stream context restored at offset %d\n",
146 static void sst_byt_pcm_work(struct work_struct
*work
)
148 struct sst_byt_pcm_data
*pcm_data
=
149 container_of(work
, struct sst_byt_pcm_data
, work
);
151 if (snd_pcm_running(pcm_data
->substream
))
152 sst_byt_pcm_restore_stream_context(pcm_data
->substream
);
155 static int sst_byt_pcm_trigger(struct snd_soc_component
*component
,
156 struct snd_pcm_substream
*substream
, int cmd
)
158 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
159 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
160 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
161 struct sst_byt
*byt
= pdata
->byt
;
163 dev_dbg(rtd
->dev
, "PCM: trigger %d\n", cmd
);
166 case SNDRV_PCM_TRIGGER_START
:
167 pcm_data
->hw_ptr
= 0;
168 sst_byt_stream_start(byt
, pcm_data
->stream
, 0);
170 case SNDRV_PCM_TRIGGER_RESUME
:
171 if (pdata
->restore_stream
)
172 schedule_work(&pcm_data
->work
);
174 sst_byt_stream_resume(byt
, pcm_data
->stream
);
176 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
177 sst_byt_stream_resume(byt
, pcm_data
->stream
);
179 case SNDRV_PCM_TRIGGER_STOP
:
180 sst_byt_stream_stop(byt
, pcm_data
->stream
);
182 case SNDRV_PCM_TRIGGER_SUSPEND
:
183 pdata
->restore_stream
= false;
185 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
186 sst_byt_stream_pause(byt
, pcm_data
->stream
);
195 static u32
byt_notify_pointer(struct sst_byt_stream
*stream
, void *data
)
197 struct sst_byt_pcm_data
*pcm_data
= data
;
198 struct snd_pcm_substream
*substream
= pcm_data
->substream
;
199 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
200 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
201 struct snd_soc_component
*component
= snd_soc_rtdcom_lookup(rtd
, DRV_NAME
);
202 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
203 struct sst_byt
*byt
= pdata
->byt
;
206 hw_pos
= sst_byt_get_dsp_position(byt
, pcm_data
->stream
,
207 snd_pcm_lib_buffer_bytes(substream
));
208 pcm_data
->hw_ptr
= hw_pos
;
209 pos
= frames_to_bytes(runtime
,
210 (runtime
->control
->appl_ptr
%
211 runtime
->buffer_size
));
213 dev_dbg(rtd
->dev
, "PCM: App/DMA pointer %u/%u bytes\n", pos
, hw_pos
);
215 snd_pcm_period_elapsed(substream
);
219 static snd_pcm_uframes_t
sst_byt_pcm_pointer(struct snd_soc_component
*component
,
220 struct snd_pcm_substream
*substream
)
222 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
223 struct snd_pcm_runtime
*runtime
= substream
->runtime
;
224 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
225 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
227 dev_dbg(rtd
->dev
, "PCM: DMA pointer %u bytes\n", pcm_data
->hw_ptr
);
229 return bytes_to_frames(runtime
, pcm_data
->hw_ptr
);
232 static int sst_byt_pcm_open(struct snd_soc_component
*component
,
233 struct snd_pcm_substream
*substream
)
235 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
236 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
237 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
238 struct sst_byt
*byt
= pdata
->byt
;
240 dev_dbg(rtd
->dev
, "PCM: open\n");
242 mutex_lock(&pcm_data
->mutex
);
244 pcm_data
->substream
= substream
;
246 snd_soc_set_runtime_hwparams(substream
, &sst_byt_pcm_hardware
);
248 pcm_data
->stream
= sst_byt_stream_new(byt
, substream
->stream
+ 1,
249 byt_notify_pointer
, pcm_data
);
250 if (pcm_data
->stream
== NULL
) {
251 dev_err(rtd
->dev
, "failed to create stream\n");
252 mutex_unlock(&pcm_data
->mutex
);
256 mutex_unlock(&pcm_data
->mutex
);
260 static int sst_byt_pcm_close(struct snd_soc_component
*component
,
261 struct snd_pcm_substream
*substream
)
263 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
264 struct sst_byt_priv_data
*pdata
= snd_soc_component_get_drvdata(component
);
265 struct sst_byt_pcm_data
*pcm_data
= &pdata
->pcm
[substream
->stream
];
266 struct sst_byt
*byt
= pdata
->byt
;
269 dev_dbg(rtd
->dev
, "PCM: close\n");
271 cancel_work_sync(&pcm_data
->work
);
272 mutex_lock(&pcm_data
->mutex
);
273 ret
= sst_byt_stream_free(byt
, pcm_data
->stream
);
275 dev_dbg(rtd
->dev
, "Free stream fail\n");
278 pcm_data
->stream
= NULL
;
281 mutex_unlock(&pcm_data
->mutex
);
285 static int sst_byt_pcm_mmap(struct snd_soc_component
*component
,
286 struct snd_pcm_substream
*substream
,
287 struct vm_area_struct
*vma
)
289 struct snd_soc_pcm_runtime
*rtd
= substream
->private_data
;
291 dev_dbg(rtd
->dev
, "PCM: mmap\n");
292 return snd_pcm_lib_default_mmap(substream
, vma
);
295 static int sst_byt_pcm_new(struct snd_soc_component
*component
,
296 struct snd_soc_pcm_runtime
*rtd
)
298 struct snd_pcm
*pcm
= rtd
->pcm
;
300 struct sst_pdata
*pdata
= dev_get_platdata(component
->dev
);
302 if (pcm
->streams
[SNDRV_PCM_STREAM_PLAYBACK
].substream
||
303 pcm
->streams
[SNDRV_PCM_STREAM_CAPTURE
].substream
) {
304 size
= sst_byt_pcm_hardware
.buffer_bytes_max
;
305 snd_pcm_set_managed_buffer_all(pcm
, SNDRV_DMA_TYPE_DEV
,
306 pdata
->dma_dev
, size
, size
);
312 static struct snd_soc_dai_driver byt_dais
[] = {
314 .name
= "Baytrail PCM",
316 .stream_name
= "System Playback",
319 .rates
= SNDRV_PCM_RATE_48000
,
320 .formats
= SNDRV_PCM_FMTBIT_S24_3LE
|
321 SNDRV_PCM_FMTBIT_S16_LE
,
324 .stream_name
= "Analog Capture",
327 .rates
= SNDRV_PCM_RATE_48000
,
328 .formats
= SNDRV_PCM_FMTBIT_S16_LE
,
333 static int sst_byt_pcm_probe(struct snd_soc_component
*component
)
335 struct sst_pdata
*plat_data
= dev_get_platdata(component
->dev
);
336 struct sst_byt_priv_data
*priv_data
;
342 priv_data
= devm_kzalloc(component
->dev
, sizeof(*priv_data
),
346 priv_data
->byt
= plat_data
->dsp
;
347 snd_soc_component_set_drvdata(component
, priv_data
);
349 for (i
= 0; i
< BYT_PCM_COUNT
; i
++) {
350 mutex_init(&priv_data
->pcm
[i
].mutex
);
351 INIT_WORK(&priv_data
->pcm
[i
].work
, sst_byt_pcm_work
);
357 static const struct snd_soc_component_driver byt_dai_component
= {
359 .probe
= sst_byt_pcm_probe
,
360 .open
= sst_byt_pcm_open
,
361 .close
= sst_byt_pcm_close
,
362 .hw_params
= sst_byt_pcm_hw_params
,
363 .trigger
= sst_byt_pcm_trigger
,
364 .pointer
= sst_byt_pcm_pointer
,
365 .mmap
= sst_byt_pcm_mmap
,
366 .pcm_construct
= sst_byt_pcm_new
,
370 static int sst_byt_pcm_dev_suspend_late(struct device
*dev
)
372 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
373 struct sst_byt_priv_data
*priv_data
= dev_get_drvdata(dev
);
376 dev_dbg(dev
, "suspending late\n");
378 ret
= sst_byt_dsp_suspend_late(dev
, sst_pdata
);
380 dev_err(dev
, "failed to suspend %d\n", ret
);
384 priv_data
->restore_stream
= true;
389 static int sst_byt_pcm_dev_resume_early(struct device
*dev
)
391 struct sst_pdata
*sst_pdata
= dev_get_platdata(dev
);
394 dev_dbg(dev
, "resume early\n");
396 /* load fw and boot DSP */
397 ret
= sst_byt_dsp_boot(dev
, sst_pdata
);
401 /* wait for FW to finish booting */
402 return sst_byt_dsp_wait_for_ready(dev
, sst_pdata
);
405 static const struct dev_pm_ops sst_byt_pm_ops
= {
406 .suspend_late
= sst_byt_pcm_dev_suspend_late
,
407 .resume_early
= sst_byt_pcm_dev_resume_early
,
410 #define SST_BYT_PM_OPS (&sst_byt_pm_ops)
412 #define SST_BYT_PM_OPS NULL
415 static int sst_byt_pcm_dev_probe(struct platform_device
*pdev
)
417 struct sst_pdata
*sst_pdata
= dev_get_platdata(&pdev
->dev
);
420 ret
= sst_byt_dsp_init(&pdev
->dev
, sst_pdata
);
424 ret
= devm_snd_soc_register_component(&pdev
->dev
, &byt_dai_component
,
425 byt_dais
, ARRAY_SIZE(byt_dais
));
432 sst_byt_dsp_free(&pdev
->dev
, sst_pdata
);
436 static int sst_byt_pcm_dev_remove(struct platform_device
*pdev
)
438 struct sst_pdata
*sst_pdata
= dev_get_platdata(&pdev
->dev
);
440 sst_byt_dsp_free(&pdev
->dev
, sst_pdata
);
445 static struct platform_driver sst_byt_pcm_driver
= {
447 .name
= "baytrail-pcm-audio",
448 .pm
= SST_BYT_PM_OPS
,
451 .probe
= sst_byt_pcm_dev_probe
,
452 .remove
= sst_byt_pcm_dev_remove
,
454 module_platform_driver(sst_byt_pcm_driver
);
456 MODULE_AUTHOR("Jarkko Nikula");
457 MODULE_DESCRIPTION("Baytrail PCM");
458 MODULE_LICENSE("GPL v2");
459 MODULE_ALIAS("platform:baytrail-pcm-audio");