pcm.c (8c583f526ee9df5c6693f54ac272b7e103b5f1d2) pcm.c (ee1e79b72e3cf5eac42ba9de827536f91d4c04e2)
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9//
10// PCM Layer, interface between ALSA and IPC.
11//
12
13#include <linux/pm_runtime.h>
14#include <sound/pcm_params.h>
15#include <sound/sof.h>
16#include "sof-priv.h"
1// SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause)
2//
3// This file is provided under a dual BSD/GPLv2 license. When using or
4// redistributing this file, you may do so under either license.
5//
6// Copyright(c) 2018 Intel Corporation. All rights reserved.
7//
8// Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9//
10// PCM Layer, interface between ALSA and IPC.
11//
12
13#include <linux/pm_runtime.h>
14#include <sound/pcm_params.h>
15#include <sound/sof.h>
16#include "sof-priv.h"
17#include "sof-audio.h"
17#include "ops.h"
18
18#include "ops.h"
19
19#define DRV_NAME "sof-audio-component"
20
21/* Create DMA buffer page table for DSP */
22static int create_page_table(struct snd_soc_component *component,
23 struct snd_pcm_substream *substream,
24 unsigned char *dma_area, size_t size)
25{
26 struct snd_soc_pcm_runtime *rtd = substream->private_data;
20/* Create DMA buffer page table for DSP */
21static int create_page_table(struct snd_soc_component *component,
22 struct snd_pcm_substream *substream,
23 unsigned char *dma_area, size_t size)
24{
25 struct snd_soc_pcm_runtime *rtd = substream->private_data;
27 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
28 struct snd_sof_pcm *spcm;
29 struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
30 int stream = substream->stream;
31
26 struct snd_sof_pcm *spcm;
27 struct snd_dma_buffer *dmab = snd_pcm_get_dma_buf(substream);
28 int stream = substream->stream;
29
32 spcm = snd_sof_find_spcm_dai(sdev, rtd);
30 spcm = snd_sof_find_spcm_dai(component, rtd);
33 if (!spcm)
34 return -EINVAL;
35
31 if (!spcm)
32 return -EINVAL;
33
36 return snd_sof_create_page_table(sdev->dev, dmab,
34 return snd_sof_create_page_table(component->dev, dmab,
37 spcm->stream[stream].page_table.area, size);
38}
39
40static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream,
41 const struct sof_ipc_pcm_params_reply *reply)
42{
35 spcm->stream[stream].page_table.area, size);
36}
37
38static int sof_pcm_dsp_params(struct snd_sof_pcm *spcm, struct snd_pcm_substream *substream,
39 const struct sof_ipc_pcm_params_reply *reply)
40{
43 struct snd_sof_dev *sdev = spcm->sdev;
41 struct snd_soc_component *scomp = spcm->scomp;
42 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp);
43
44 /* validate offset */
45 int ret = snd_sof_ipc_pcm_params(sdev, substream, reply);
46
47 if (ret < 0)
44 /* validate offset */
45 int ret = snd_sof_ipc_pcm_params(sdev, substream, reply);
46
47 if (ret < 0)
48 dev_err(sdev->dev, "error: got wrong reply for PCM %d\n",
48 dev_err(scomp->dev, "error: got wrong reply for PCM %d\n",
49 spcm->pcm.pcm_id);
50
51 return ret;
52}
53
54/*
55 * sof pcm period elapse work
56 */

--- 8 unchanged lines hidden (view full) ---

65
66/*
67 * sof pcm period elapse, this could be called at irq thread context.
68 */
69void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
70{
71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_component *component =
49 spcm->pcm.pcm_id);
50
51 return ret;
52}
53
54/*
55 * sof pcm period elapse work
56 */

--- 8 unchanged lines hidden (view full) ---

65
66/*
67 * sof pcm period elapse, this could be called at irq thread context.
68 */
69void snd_sof_pcm_period_elapsed(struct snd_pcm_substream *substream)
70{
71 struct snd_soc_pcm_runtime *rtd = substream->private_data;
72 struct snd_soc_component *component =
73 snd_soc_rtdcom_lookup(rtd, DRV_NAME);
74 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
73 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
75 struct snd_sof_pcm *spcm;
76
74 struct snd_sof_pcm *spcm;
75
77 spcm = snd_sof_find_spcm_dai(sdev, rtd);
76 spcm = snd_sof_find_spcm_dai(component, rtd);
78 if (!spcm) {
77 if (!spcm) {
79 dev_err(sdev->dev,
78 dev_err(component->dev,
80 "error: period elapsed for unknown stream!\n");
81 return;
82 }
83
84 /*
85 * snd_pcm_period_elapsed() can be called in interrupt context
86 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
87 * when the PCM is done draining or xrun happened, a STOP IPC will

--- 17 unchanged lines hidden (view full) ---

105 struct sof_ipc_pcm_params pcm;
106 struct sof_ipc_pcm_params_reply ipc_params_reply;
107 int ret;
108
109 /* nothing to do for BE */
110 if (rtd->dai_link->no_pcm)
111 return 0;
112
79 "error: period elapsed for unknown stream!\n");
80 return;
81 }
82
83 /*
84 * snd_pcm_period_elapsed() can be called in interrupt context
85 * before IRQ_HANDLED is returned. Inside snd_pcm_period_elapsed(),
86 * when the PCM is done draining or xrun happened, a STOP IPC will

--- 17 unchanged lines hidden (view full) ---

104 struct sof_ipc_pcm_params pcm;
105 struct sof_ipc_pcm_params_reply ipc_params_reply;
106 int ret;
107
108 /* nothing to do for BE */
109 if (rtd->dai_link->no_pcm)
110 return 0;
111
113 spcm = snd_sof_find_spcm_dai(sdev, rtd);
112 spcm = snd_sof_find_spcm_dai(component, rtd);
114 if (!spcm)
115 return -EINVAL;
116
113 if (!spcm)
114 return -EINVAL;
115
117 dev_dbg(sdev->dev, "pcm: hw params stream %d dir %d\n",
116 dev_dbg(component->dev, "pcm: hw params stream %d dir %d\n",
118 spcm->pcm.pcm_id, substream->stream);
119
120 memset(&pcm, 0, sizeof(pcm));
121
122 /* allocate audio buffer pages */
123 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
124 if (ret < 0) {
117 spcm->pcm.pcm_id, substream->stream);
118
119 memset(&pcm, 0, sizeof(pcm));
120
121 /* allocate audio buffer pages */
122 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
123 if (ret < 0) {
125 dev_err(sdev->dev, "error: could not allocate %d bytes for PCM %d\n",
124 dev_err(component->dev, "error: could not allocate %d bytes for PCM %d\n",
126 params_buffer_bytes(params), spcm->pcm.pcm_id);
127 return ret;
128 }
129 if (ret) {
130 /*
131 * ret == 1 means the buffer is changed
132 * create compressed page table for audio firmware
133 * ret == 0 means the buffer is not changed

--- 48 unchanged lines hidden (view full) ---

182 }
183
184 /* firmware already configured host stream */
185 ret = snd_sof_pcm_platform_hw_params(sdev,
186 substream,
187 params,
188 &pcm.params);
189 if (ret < 0) {
125 params_buffer_bytes(params), spcm->pcm.pcm_id);
126 return ret;
127 }
128 if (ret) {
129 /*
130 * ret == 1 means the buffer is changed
131 * create compressed page table for audio firmware
132 * ret == 0 means the buffer is not changed

--- 48 unchanged lines hidden (view full) ---

181 }
182
183 /* firmware already configured host stream */
184 ret = snd_sof_pcm_platform_hw_params(sdev,
185 substream,
186 params,
187 &pcm.params);
188 if (ret < 0) {
190 dev_err(sdev->dev, "error: platform hw params failed\n");
189 dev_err(component->dev, "error: platform hw params failed\n");
191 return ret;
192 }
193
190 return ret;
191 }
192
194 dev_dbg(sdev->dev, "stream_tag %d", pcm.params.stream_tag);
193 dev_dbg(component->dev, "stream_tag %d", pcm.params.stream_tag);
195
196 /* send IPC to the DSP */
197 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
198 &ipc_params_reply, sizeof(ipc_params_reply));
199 if (ret < 0) {
194
195 /* send IPC to the DSP */
196 ret = sof_ipc_tx_message(sdev->ipc, pcm.hdr.cmd, &pcm, sizeof(pcm),
197 &ipc_params_reply, sizeof(ipc_params_reply));
198 if (ret < 0) {
200 dev_err(sdev->dev, "error: hw params ipc failed for stream %d\n",
199 dev_err(component->dev, "error: hw params ipc failed for stream %d\n",
201 pcm.params.stream_tag);
202 return ret;
203 }
204
205 ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply);
206 if (ret < 0)
207 return ret;
208

--- 33 unchanged lines hidden (view full) ---

242 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
243 struct snd_sof_pcm *spcm;
244 int ret, err = 0;
245
246 /* nothing to do for BE */
247 if (rtd->dai_link->no_pcm)
248 return 0;
249
200 pcm.params.stream_tag);
201 return ret;
202 }
203
204 ret = sof_pcm_dsp_params(spcm, substream, &ipc_params_reply);
205 if (ret < 0)
206 return ret;
207

--- 33 unchanged lines hidden (view full) ---

241 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
242 struct snd_sof_pcm *spcm;
243 int ret, err = 0;
244
245 /* nothing to do for BE */
246 if (rtd->dai_link->no_pcm)
247 return 0;
248
250 spcm = snd_sof_find_spcm_dai(sdev, rtd);
249 spcm = snd_sof_find_spcm_dai(component, rtd);
251 if (!spcm)
252 return -EINVAL;
253
250 if (!spcm)
251 return -EINVAL;
252
254 dev_dbg(sdev->dev, "pcm: free stream %d dir %d\n", spcm->pcm.pcm_id,
255 substream->stream);
253 dev_dbg(component->dev, "pcm: free stream %d dir %d\n",
254 spcm->pcm.pcm_id, substream->stream);
256
257 if (spcm->prepared[substream->stream]) {
258 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
259 if (ret < 0)
260 err = ret;
261 }
262
263 snd_pcm_lib_free_pages(substream);
264
265 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
266
267 ret = snd_sof_pcm_platform_hw_free(sdev, substream);
268 if (ret < 0) {
255
256 if (spcm->prepared[substream->stream]) {
257 ret = sof_pcm_dsp_pcm_free(substream, sdev, spcm);
258 if (ret < 0)
259 err = ret;
260 }
261
262 snd_pcm_lib_free_pages(substream);
263
264 cancel_work_sync(&spcm->stream[substream->stream].period_elapsed_work);
265
266 ret = snd_sof_pcm_platform_hw_free(sdev, substream);
267 if (ret < 0) {
269 dev_err(sdev->dev, "error: platform hw free failed\n");
268 dev_err(component->dev, "error: platform hw free failed\n");
270 err = ret;
271 }
272
273 return err;
274}
275
276static int sof_pcm_prepare(struct snd_soc_component *component,
277 struct snd_pcm_substream *substream)
278{
279 struct snd_soc_pcm_runtime *rtd = substream->private_data;
269 err = ret;
270 }
271
272 return err;
273}
274
275static int sof_pcm_prepare(struct snd_soc_component *component,
276 struct snd_pcm_substream *substream)
277{
278 struct snd_soc_pcm_runtime *rtd = substream->private_data;
280 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
281 struct snd_sof_pcm *spcm;
282 int ret;
283
284 /* nothing to do for BE */
285 if (rtd->dai_link->no_pcm)
286 return 0;
287
279 struct snd_sof_pcm *spcm;
280 int ret;
281
282 /* nothing to do for BE */
283 if (rtd->dai_link->no_pcm)
284 return 0;
285
288 spcm = snd_sof_find_spcm_dai(sdev, rtd);
286 spcm = snd_sof_find_spcm_dai(component, rtd);
289 if (!spcm)
290 return -EINVAL;
291
292 if (spcm->prepared[substream->stream])
293 return 0;
294
287 if (!spcm)
288 return -EINVAL;
289
290 if (spcm->prepared[substream->stream])
291 return 0;
292
295 dev_dbg(sdev->dev, "pcm: prepare stream %d dir %d\n", spcm->pcm.pcm_id,
296 substream->stream);
293 dev_dbg(component->dev, "pcm: prepare stream %d dir %d\n",
294 spcm->pcm.pcm_id, substream->stream);
297
298 /* set hw_params */
299 ret = sof_pcm_hw_params(component,
300 substream, &spcm->params[substream->stream]);
301 if (ret < 0) {
295
296 /* set hw_params */
297 ret = sof_pcm_hw_params(component,
298 substream, &spcm->params[substream->stream]);
299 if (ret < 0) {
302 dev_err(sdev->dev, "error: set pcm hw_params after resume\n");
300 dev_err(component->dev,
301 "error: set pcm hw_params after resume\n");
303 return ret;
304 }
305
306 return 0;
307}
308
309/*
310 * FE dai link trigger actions are always executed in non-atomic context because

--- 10 unchanged lines hidden (view full) ---

321 bool reset_hw_params = false;
322 bool ipc_first = false;
323 int ret;
324
325 /* nothing to do for BE */
326 if (rtd->dai_link->no_pcm)
327 return 0;
328
302 return ret;
303 }
304
305 return 0;
306}
307
308/*
309 * FE dai link trigger actions are always executed in non-atomic context because

--- 10 unchanged lines hidden (view full) ---

320 bool reset_hw_params = false;
321 bool ipc_first = false;
322 int ret;
323
324 /* nothing to do for BE */
325 if (rtd->dai_link->no_pcm)
326 return 0;
327
329 spcm = snd_sof_find_spcm_dai(sdev, rtd);
328 spcm = snd_sof_find_spcm_dai(component, rtd);
330 if (!spcm)
331 return -EINVAL;
332
329 if (!spcm)
330 return -EINVAL;
331
333 dev_dbg(sdev->dev, "pcm: trigger stream %d dir %d cmd %d\n",
332 dev_dbg(component->dev, "pcm: trigger stream %d dir %d cmd %d\n",
334 spcm->pcm.pcm_id, substream->stream, cmd);
335
336 stream.hdr.size = sizeof(stream);
337 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
338 stream.comp_id = spcm->stream[substream->stream].comp_id;
339
340 switch (cmd) {
341 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:

--- 12 unchanged lines hidden (view full) ---

354 */
355 spcm->stream[substream->stream].suspend_ignored = false;
356 return 0;
357 }
358
359 /* set up hw_params */
360 ret = sof_pcm_prepare(component, substream);
361 if (ret < 0) {
333 spcm->pcm.pcm_id, substream->stream, cmd);
334
335 stream.hdr.size = sizeof(stream);
336 stream.hdr.cmd = SOF_IPC_GLB_STREAM_MSG;
337 stream.comp_id = spcm->stream[substream->stream].comp_id;
338
339 switch (cmd) {
340 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:

--- 12 unchanged lines hidden (view full) ---

353 */
354 spcm->stream[substream->stream].suspend_ignored = false;
355 return 0;
356 }
357
358 /* set up hw_params */
359 ret = sof_pcm_prepare(component, substream);
360 if (ret < 0) {
362 dev_err(sdev->dev,
361 dev_err(component->dev,
363 "error: failed to set up hw_params upon resume\n");
364 return ret;
365 }
366
367 /* fallthrough */
368 case SNDRV_PCM_TRIGGER_START:
369 if (spcm->stream[substream->stream].suspend_ignored) {
370 /*

--- 20 unchanged lines hidden (view full) ---

391 }
392 /* fallthrough */
393 case SNDRV_PCM_TRIGGER_STOP:
394 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
395 ipc_first = true;
396 reset_hw_params = true;
397 break;
398 default:
362 "error: failed to set up hw_params upon resume\n");
363 return ret;
364 }
365
366 /* fallthrough */
367 case SNDRV_PCM_TRIGGER_START:
368 if (spcm->stream[substream->stream].suspend_ignored) {
369 /*

--- 20 unchanged lines hidden (view full) ---

390 }
391 /* fallthrough */
392 case SNDRV_PCM_TRIGGER_STOP:
393 stream.hdr.cmd |= SOF_IPC_STREAM_TRIG_STOP;
394 ipc_first = true;
395 reset_hw_params = true;
396 break;
397 default:
399 dev_err(sdev->dev, "error: unhandled trigger cmd %d\n", cmd);
398 dev_err(component->dev, "error: unhandled trigger cmd %d\n",
399 cmd);
400 return -EINVAL;
401 }
402
403 /*
404 * DMA and IPC sequence is different for start and stop. Need to send
405 * STOP IPC before stop DMA
406 */
407 if (!ipc_first)

--- 25 unchanged lines hidden (view full) ---

433 /* nothing to do for BE */
434 if (rtd->dai_link->no_pcm)
435 return 0;
436
437 /* use dsp ops pointer callback directly if set */
438 if (sof_ops(sdev)->pcm_pointer)
439 return sof_ops(sdev)->pcm_pointer(sdev, substream);
440
400 return -EINVAL;
401 }
402
403 /*
404 * DMA and IPC sequence is different for start and stop. Need to send
405 * STOP IPC before stop DMA
406 */
407 if (!ipc_first)

--- 25 unchanged lines hidden (view full) ---

433 /* nothing to do for BE */
434 if (rtd->dai_link->no_pcm)
435 return 0;
436
437 /* use dsp ops pointer callback directly if set */
438 if (sof_ops(sdev)->pcm_pointer)
439 return sof_ops(sdev)->pcm_pointer(sdev, substream);
440
441 spcm = snd_sof_find_spcm_dai(sdev, rtd);
441 spcm = snd_sof_find_spcm_dai(component, rtd);
442 if (!spcm)
443 return -EINVAL;
444
445 /* read position from DSP */
446 host = bytes_to_frames(substream->runtime,
447 spcm->stream[substream->stream].posn.host_posn);
448 dai = bytes_to_frames(substream->runtime,
449 spcm->stream[substream->stream].posn.dai_posn);
450
442 if (!spcm)
443 return -EINVAL;
444
445 /* read position from DSP */
446 host = bytes_to_frames(substream->runtime,
447 spcm->stream[substream->stream].posn.host_posn);
448 dai = bytes_to_frames(substream->runtime,
449 spcm->stream[substream->stream].posn.dai_posn);
450
451 dev_dbg(sdev->dev, "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
451 dev_dbg(component->dev,
452 "PCM: stream %d dir %d DMA position %lu DAI position %lu\n",
452 spcm->pcm.pcm_id, substream->stream, host, dai);
453
454 return host;
455}
456
457static int sof_pcm_open(struct snd_soc_component *component,
458 struct snd_pcm_substream *substream)
459{

--- 4 unchanged lines hidden (view full) ---

464 struct snd_sof_pcm *spcm;
465 struct snd_soc_tplg_stream_caps *caps;
466 int ret;
467
468 /* nothing to do for BE */
469 if (rtd->dai_link->no_pcm)
470 return 0;
471
453 spcm->pcm.pcm_id, substream->stream, host, dai);
454
455 return host;
456}
457
458static int sof_pcm_open(struct snd_soc_component *component,
459 struct snd_pcm_substream *substream)
460{

--- 4 unchanged lines hidden (view full) ---

465 struct snd_sof_pcm *spcm;
466 struct snd_soc_tplg_stream_caps *caps;
467 int ret;
468
469 /* nothing to do for BE */
470 if (rtd->dai_link->no_pcm)
471 return 0;
472
472 spcm = snd_sof_find_spcm_dai(sdev, rtd);
473 spcm = snd_sof_find_spcm_dai(component, rtd);
473 if (!spcm)
474 return -EINVAL;
475
474 if (!spcm)
475 return -EINVAL;
476
476 dev_dbg(sdev->dev, "pcm: open stream %d dir %d\n", spcm->pcm.pcm_id,
477 substream->stream);
477 dev_dbg(component->dev, "pcm: open stream %d dir %d\n",
478 spcm->pcm.pcm_id, substream->stream);
478
479 INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
480 sof_pcm_period_elapsed_work);
481
482 caps = &spcm->pcm.caps[substream->stream];
483
484 /* set any runtime constraints based on topology */
485 snd_pcm_hw_constraint_step(substream->runtime, 0,

--- 13 unchanged lines hidden (view full) ---

499 runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
500
501 /*
502 * caps->buffer_size_min is not used since the
503 * snd_pcm_hardware structure only defines buffer_bytes_max
504 */
505 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
506
479
480 INIT_WORK(&spcm->stream[substream->stream].period_elapsed_work,
481 sof_pcm_period_elapsed_work);
482
483 caps = &spcm->pcm.caps[substream->stream];
484
485 /* set any runtime constraints based on topology */
486 snd_pcm_hw_constraint_step(substream->runtime, 0,

--- 13 unchanged lines hidden (view full) ---

500 runtime->hw.periods_max = le32_to_cpu(caps->periods_max);
501
502 /*
503 * caps->buffer_size_min is not used since the
504 * snd_pcm_hardware structure only defines buffer_bytes_max
505 */
506 runtime->hw.buffer_bytes_max = le32_to_cpu(caps->buffer_size_max);
507
507 dev_dbg(sdev->dev, "period min %zd max %zd bytes\n",
508 dev_dbg(component->dev, "period min %zd max %zd bytes\n",
508 runtime->hw.period_bytes_min,
509 runtime->hw.period_bytes_max);
509 runtime->hw.period_bytes_min,
510 runtime->hw.period_bytes_max);
510 dev_dbg(sdev->dev, "period count %d max %d\n",
511 dev_dbg(component->dev, "period count %d max %d\n",
511 runtime->hw.periods_min,
512 runtime->hw.periods_max);
512 runtime->hw.periods_min,
513 runtime->hw.periods_max);
513 dev_dbg(sdev->dev, "buffer max %zd bytes\n",
514 dev_dbg(component->dev, "buffer max %zd bytes\n",
514 runtime->hw.buffer_bytes_max);
515
516 /* set wait time - TODO: come from topology */
517 substream->wait_time = 500;
518
519 spcm->stream[substream->stream].posn.host_posn = 0;
520 spcm->stream[substream->stream].posn.dai_posn = 0;
521 spcm->stream[substream->stream].substream = substream;
522 spcm->prepared[substream->stream] = false;
523
524 ret = snd_sof_pcm_platform_open(sdev, substream);
525 if (ret < 0)
515 runtime->hw.buffer_bytes_max);
516
517 /* set wait time - TODO: come from topology */
518 substream->wait_time = 500;
519
520 spcm->stream[substream->stream].posn.host_posn = 0;
521 spcm->stream[substream->stream].posn.dai_posn = 0;
522 spcm->stream[substream->stream].substream = substream;
523 spcm->prepared[substream->stream] = false;
524
525 ret = snd_sof_pcm_platform_open(sdev, substream);
526 if (ret < 0)
526 dev_err(sdev->dev, "error: pcm open failed %d\n", ret);
527 dev_err(component->dev, "error: pcm open failed %d\n", ret);
527
528 return ret;
529}
530
531static int sof_pcm_close(struct snd_soc_component *component,
532 struct snd_pcm_substream *substream)
533{
534 struct snd_soc_pcm_runtime *rtd = substream->private_data;
535 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
536 struct snd_sof_pcm *spcm;
537 int err;
538
539 /* nothing to do for BE */
540 if (rtd->dai_link->no_pcm)
541 return 0;
542
528
529 return ret;
530}
531
532static int sof_pcm_close(struct snd_soc_component *component,
533 struct snd_pcm_substream *substream)
534{
535 struct snd_soc_pcm_runtime *rtd = substream->private_data;
536 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
537 struct snd_sof_pcm *spcm;
538 int err;
539
540 /* nothing to do for BE */
541 if (rtd->dai_link->no_pcm)
542 return 0;
543
543 spcm = snd_sof_find_spcm_dai(sdev, rtd);
544 spcm = snd_sof_find_spcm_dai(component, rtd);
544 if (!spcm)
545 return -EINVAL;
546
545 if (!spcm)
546 return -EINVAL;
547
547 dev_dbg(sdev->dev, "pcm: close stream %d dir %d\n", spcm->pcm.pcm_id,
548 substream->stream);
548 dev_dbg(component->dev, "pcm: close stream %d dir %d\n",
549 spcm->pcm.pcm_id, substream->stream);
549
550 err = snd_sof_pcm_platform_close(sdev, substream);
551 if (err < 0) {
550
551 err = snd_sof_pcm_platform_close(sdev, substream);
552 if (err < 0) {
552 dev_err(sdev->dev, "error: pcm close failed %d\n",
553 dev_err(component->dev, "error: pcm close failed %d\n",
553 err);
554 /*
555 * keep going, no point in preventing the close
556 * from happening
557 */
558 }
559
560 return 0;

--- 9 unchanged lines hidden (view full) ---

570{
571 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
572 struct snd_sof_pcm *spcm;
573 struct snd_pcm *pcm = rtd->pcm;
574 struct snd_soc_tplg_stream_caps *caps;
575 int stream = SNDRV_PCM_STREAM_PLAYBACK;
576
577 /* find SOF PCM for this RTD */
554 err);
555 /*
556 * keep going, no point in preventing the close
557 * from happening
558 */
559 }
560
561 return 0;

--- 9 unchanged lines hidden (view full) ---

571{
572 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
573 struct snd_sof_pcm *spcm;
574 struct snd_pcm *pcm = rtd->pcm;
575 struct snd_soc_tplg_stream_caps *caps;
576 int stream = SNDRV_PCM_STREAM_PLAYBACK;
577
578 /* find SOF PCM for this RTD */
578 spcm = snd_sof_find_spcm_dai(sdev, rtd);
579 spcm = snd_sof_find_spcm_dai(component, rtd);
579 if (!spcm) {
580 if (!spcm) {
580 dev_warn(sdev->dev, "warn: can't find PCM with DAI ID %d\n",
581 dev_warn(component->dev, "warn: can't find PCM with DAI ID %d\n",
581 rtd->dai_link->id);
582 return 0;
583 }
584
582 rtd->dai_link->id);
583 return 0;
584 }
585
585 dev_dbg(sdev->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
586 dev_dbg(component->dev, "creating new PCM %s\n", spcm->pcm.pcm_name);
586
587 /* do we need to pre-allocate playback audio buffer pages */
588 if (!spcm->pcm.playback)
589 goto capture;
590
591 caps = &spcm->pcm.caps[stream];
592
593 /* pre-allocate playback audio buffer pages */
587
588 /* do we need to pre-allocate playback audio buffer pages */
589 if (!spcm->pcm.playback)
590 goto capture;
591
592 caps = &spcm->pcm.caps[stream];
593
594 /* pre-allocate playback audio buffer pages */
594 dev_dbg(sdev->dev, "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
595 dev_dbg(component->dev,
596 "spcm: allocate %s playback DMA buffer size 0x%x max 0x%x\n",
595 caps->name, caps->buffer_size_min, caps->buffer_size_max);
596
597 snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
598 SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
599 le32_to_cpu(caps->buffer_size_min),
600 le32_to_cpu(caps->buffer_size_max));
601capture:
602 stream = SNDRV_PCM_STREAM_CAPTURE;
603
604 /* do we need to pre-allocate capture audio buffer pages */
605 if (!spcm->pcm.capture)
606 return 0;
607
608 caps = &spcm->pcm.caps[stream];
609
610 /* pre-allocate capture audio buffer pages */
597 caps->name, caps->buffer_size_min, caps->buffer_size_max);
598
599 snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
600 SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
601 le32_to_cpu(caps->buffer_size_min),
602 le32_to_cpu(caps->buffer_size_max));
603capture:
604 stream = SNDRV_PCM_STREAM_CAPTURE;
605
606 /* do we need to pre-allocate capture audio buffer pages */
607 if (!spcm->pcm.capture)
608 return 0;
609
610 caps = &spcm->pcm.caps[stream];
611
612 /* pre-allocate capture audio buffer pages */
611 dev_dbg(sdev->dev, "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
613 dev_dbg(component->dev,
614 "spcm: allocate %s capture DMA buffer size 0x%x max 0x%x\n",
612 caps->name, caps->buffer_size_min, caps->buffer_size_max);
613
614 snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
615 SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
616 le32_to_cpu(caps->buffer_size_min),
617 le32_to_cpu(caps->buffer_size_max));
618
619 return 0;

--- 4 unchanged lines hidden (view full) ---

624 struct snd_pcm_hw_params *params)
625{
626 struct snd_interval *rate = hw_param_interval(params,
627 SNDRV_PCM_HW_PARAM_RATE);
628 struct snd_interval *channels = hw_param_interval(params,
629 SNDRV_PCM_HW_PARAM_CHANNELS);
630 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
631 struct snd_soc_component *component =
615 caps->name, caps->buffer_size_min, caps->buffer_size_max);
616
617 snd_pcm_lib_preallocate_pages(pcm->streams[stream].substream,
618 SNDRV_DMA_TYPE_DEV_SG, sdev->dev,
619 le32_to_cpu(caps->buffer_size_min),
620 le32_to_cpu(caps->buffer_size_max));
621
622 return 0;

--- 4 unchanged lines hidden (view full) ---

627 struct snd_pcm_hw_params *params)
628{
629 struct snd_interval *rate = hw_param_interval(params,
630 SNDRV_PCM_HW_PARAM_RATE);
631 struct snd_interval *channels = hw_param_interval(params,
632 SNDRV_PCM_HW_PARAM_CHANNELS);
633 struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
634 struct snd_soc_component *component =
632 snd_soc_rtdcom_lookup(rtd, DRV_NAME);
633 struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component);
635 snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME);
634 struct snd_sof_dai *dai =
636 struct snd_sof_dai *dai =
635 snd_sof_find_dai(sdev, (char *)rtd->dai_link->name);
637 snd_sof_find_dai(component, (char *)rtd->dai_link->name);
636
637 /* no topology exists for this BE, try a common configuration */
638 if (!dai) {
638
639 /* no topology exists for this BE, try a common configuration */
640 if (!dai) {
639 dev_warn(sdev->dev, "warning: no topology found for BE DAI %s config\n",
641 dev_warn(component->dev,
642 "warning: no topology found for BE DAI %s config\n",
640 rtd->dai_link->name);
641
642 /* set 48k, stereo, 16bits by default */
643 rate->min = 48000;
644 rate->max = 48000;
645
646 channels->min = 2;
647 channels->max = 2;

--- 13 unchanged lines hidden (view full) ---

661 break;
662 case SOF_IPC_FRAME_S24_4LE:
663 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
664 break;
665 case SOF_IPC_FRAME_S32_LE:
666 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
667 break;
668 default:
643 rtd->dai_link->name);
644
645 /* set 48k, stereo, 16bits by default */
646 rate->min = 48000;
647 rate->max = 48000;
648
649 channels->min = 2;
650 channels->max = 2;

--- 13 unchanged lines hidden (view full) ---

664 break;
665 case SOF_IPC_FRAME_S24_4LE:
666 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S24_LE);
667 break;
668 case SOF_IPC_FRAME_S32_LE:
669 snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S32_LE);
670 break;
671 default:
669 dev_err(sdev->dev, "error: No available DAI format!\n");
672 dev_err(component->dev, "error: No available DAI format!\n");
670 return -EINVAL;
671 }
672
673 /* read rate and channels from topology */
674 switch (dai->dai_config->type) {
675 case SOF_DAI_INTEL_SSP:
676 rate->min = dai->dai_config->ssp.fsync_rate;
677 rate->max = dai->dai_config->ssp.fsync_rate;
678 channels->min = dai->dai_config->ssp.tdm_slots;
679 channels->max = dai->dai_config->ssp.tdm_slots;
680
673 return -EINVAL;
674 }
675
676 /* read rate and channels from topology */
677 switch (dai->dai_config->type) {
678 case SOF_DAI_INTEL_SSP:
679 rate->min = dai->dai_config->ssp.fsync_rate;
680 rate->max = dai->dai_config->ssp.fsync_rate;
681 channels->min = dai->dai_config->ssp.tdm_slots;
682 channels->max = dai->dai_config->ssp.tdm_slots;
683
681 dev_dbg(sdev->dev,
684 dev_dbg(component->dev,
682 "rate_min: %d rate_max: %d\n", rate->min, rate->max);
685 "rate_min: %d rate_max: %d\n", rate->min, rate->max);
683 dev_dbg(sdev->dev,
686 dev_dbg(component->dev,
684 "channels_min: %d channels_max: %d\n",
685 channels->min, channels->max);
686
687 break;
688 case SOF_DAI_INTEL_DMIC:
689 /* DMIC only supports 16 or 32 bit formats */
690 if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
687 "channels_min: %d channels_max: %d\n",
688 channels->min, channels->max);
689
690 break;
691 case SOF_DAI_INTEL_DMIC:
692 /* DMIC only supports 16 or 32 bit formats */
693 if (dai->comp_dai.config.frame_fmt == SOF_IPC_FRAME_S24_4LE) {
691 dev_err(sdev->dev,
694 dev_err(component->dev,
692 "error: invalid fmt %d for DAI type %d\n",
693 dai->comp_dai.config.frame_fmt,
694 dai->dai_config->type);
695 }
696 break;
697 case SOF_DAI_INTEL_HDA:
698 /* do nothing for HDA dai_link */
699 break;
700 case SOF_DAI_INTEL_ALH:
701 /* do nothing for ALH dai_link */
702 break;
703 case SOF_DAI_IMX_ESAI:
704 channels->min = dai->dai_config->esai.tdm_slots;
705 channels->max = dai->dai_config->esai.tdm_slots;
706
695 "error: invalid fmt %d for DAI type %d\n",
696 dai->comp_dai.config.frame_fmt,
697 dai->dai_config->type);
698 }
699 break;
700 case SOF_DAI_INTEL_HDA:
701 /* do nothing for HDA dai_link */
702 break;
703 case SOF_DAI_INTEL_ALH:
704 /* do nothing for ALH dai_link */
705 break;
706 case SOF_DAI_IMX_ESAI:
707 channels->min = dai->dai_config->esai.tdm_slots;
708 channels->max = dai->dai_config->esai.tdm_slots;
709
707 dev_dbg(sdev->dev,
710 dev_dbg(component->dev,
708 "channels_min: %d channels_max: %d\n",
709 channels->min, channels->max);
710 break;
711 default:
711 "channels_min: %d channels_max: %d\n",
712 channels->min, channels->max);
713 break;
714 default:
712 dev_err(sdev->dev, "error: invalid DAI type %d\n",
715 dev_err(component->dev, "error: invalid DAI type %d\n",
713 dai->dai_config->type);
714 break;
715 }
716
717 return 0;
718}
719
720static int sof_pcm_probe(struct snd_soc_component *component)

--- 8 unchanged lines hidden (view full) ---

729
730 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
731 "%s/%s",
732 plat_data->tplg_filename_prefix,
733 plat_data->tplg_filename);
734 if (!tplg_filename)
735 return -ENOMEM;
736
716 dai->dai_config->type);
717 break;
718 }
719
720 return 0;
721}
722
723static int sof_pcm_probe(struct snd_soc_component *component)

--- 8 unchanged lines hidden (view full) ---

732
733 tplg_filename = devm_kasprintf(sdev->dev, GFP_KERNEL,
734 "%s/%s",
735 plat_data->tplg_filename_prefix,
736 plat_data->tplg_filename);
737 if (!tplg_filename)
738 return -ENOMEM;
739
737 ret = snd_sof_load_topology(sdev, tplg_filename);
740 ret = snd_sof_load_topology(component, tplg_filename);
738 if (ret < 0) {
741 if (ret < 0) {
739 dev_err(sdev->dev, "error: failed to load DSP topology %d\n",
742 dev_err(component->dev, "error: failed to load DSP topology %d\n",
740 ret);
741 return ret;
742 }
743
744 return ret;
745}
746
747static void sof_pcm_remove(struct snd_soc_component *component)

--- 38 unchanged lines hidden ---
743 ret);
744 return ret;
745 }
746
747 return ret;
748}
749
750static void sof_pcm_remove(struct snd_soc_component *component)

--- 38 unchanged lines hidden ---