Lines Matching +full:audio +full:- +full:graph
1 // SPDX-License-Identifier: GPL-2.0
10 #include <sound/soc-dapm.h>
13 #include <linux/dma-mapping.h>
18 #define DRV_NAME "q6apm-dai"
55 struct q6apm_graph *graph; member
101 struct snd_pcm_substream *substream = prtd->substream; in event_handler()
105 prtd->state = Q6APM_STREAM_STOPPED; in event_handler()
108 prtd->pos += prtd->pcm_count; in event_handler()
110 if (prtd->state == Q6APM_STREAM_RUNNING) in event_handler()
111 q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); in event_handler()
115 prtd->pos += prtd->pcm_count; in event_handler()
117 if (prtd->state == Q6APM_STREAM_RUNNING) in event_handler()
118 q6apm_read(prtd->graph); in event_handler()
129 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_prepare()
130 struct q6apm_dai_rtd *prtd = runtime->private_data; in q6apm_dai_prepare()
132 struct device *dev = component->dev; in q6apm_dai_prepare()
138 return -EINVAL; in q6apm_dai_prepare()
140 if (!prtd || !prtd->graph) { in q6apm_dai_prepare()
141 dev_err(dev, "%s: private data null or audio client freed\n", __func__); in q6apm_dai_prepare()
142 return -EINVAL; in q6apm_dai_prepare()
145 cfg.direction = substream->stream; in q6apm_dai_prepare()
146 cfg.sample_rate = runtime->rate; in q6apm_dai_prepare()
147 cfg.num_channels = runtime->channels; in q6apm_dai_prepare()
148 cfg.bit_width = prtd->bits_per_sample; in q6apm_dai_prepare()
150 if (prtd->state) { in q6apm_dai_prepare()
152 q6apm_graph_stop(prtd->graph); in q6apm_dai_prepare()
153 q6apm_unmap_memory_regions(prtd->graph, substream->stream); in q6apm_dai_prepare()
156 prtd->pcm_count = snd_pcm_lib_period_bytes(substream); in q6apm_dai_prepare()
157 prtd->pos = 0; in q6apm_dai_prepare()
158 /* rate and channels are sent to audio driver */ in q6apm_dai_prepare()
159 ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg); in q6apm_dai_prepare()
165 ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg); in q6apm_dai_prepare()
169 ret = q6apm_map_memory_regions(prtd->graph, substream->stream, prtd->phys, in q6apm_dai_prepare()
170 (prtd->pcm_size / prtd->periods), prtd->periods); in q6apm_dai_prepare()
173 dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret); in q6apm_dai_prepare()
174 return -ENOMEM; in q6apm_dai_prepare()
177 ret = q6apm_graph_prepare(prtd->graph); in q6apm_dai_prepare()
179 dev_err(dev, "Failed to prepare Graph %d\n", ret); in q6apm_dai_prepare()
183 ret = q6apm_graph_start(prtd->graph); in q6apm_dai_prepare()
185 dev_err(dev, "Failed to Start Graph %d\n", ret); in q6apm_dai_prepare()
189 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { in q6apm_dai_prepare()
191 /* Queue the buffers for Capture ONLY after graph is started */ in q6apm_dai_prepare()
192 for (i = 0; i < runtime->periods; i++) in q6apm_dai_prepare()
193 q6apm_read(prtd->graph); in q6apm_dai_prepare()
197 /* Now that graph as been prepared and started update the internal state accordingly */ in q6apm_dai_prepare()
198 prtd->state = Q6APM_STREAM_RUNNING; in q6apm_dai_prepare()
206 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_trigger()
207 struct q6apm_dai_rtd *prtd = runtime->private_data; in q6apm_dai_trigger()
215 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in q6apm_dai_trigger()
216 ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0); in q6apm_dai_trigger()
220 prtd->state = Q6APM_STREAM_STOPPED; in q6apm_dai_trigger()
226 ret = -EINVAL; in q6apm_dai_trigger()
236 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_open()
237 struct snd_soc_pcm_runtime *soc_prtd = substream->private_data; in q6apm_dai_open()
239 struct device *dev = component->dev; in q6apm_dai_open()
244 graph_id = cpu_dai->driver->id; in q6apm_dai_open()
249 return -EINVAL; in q6apm_dai_open()
254 return -ENOMEM; in q6apm_dai_open()
256 prtd->substream = substream; in q6apm_dai_open()
257 prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler, prtd, graph_id); in q6apm_dai_open()
258 if (IS_ERR(prtd->graph)) { in q6apm_dai_open()
260 ret = PTR_ERR(prtd->graph); in q6apm_dai_open()
264 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) in q6apm_dai_open()
265 runtime->hw = q6apm_dai_hardware_playback; in q6apm_dai_open()
266 else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) in q6apm_dai_open()
267 runtime->hw = q6apm_dai_hardware_capture; in q6apm_dai_open()
276 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { in q6apm_dai_open()
297 runtime->private_data = prtd; in q6apm_dai_open()
298 runtime->dma_bytes = BUFFER_BYTES_MAX; in q6apm_dai_open()
299 if (pdata->sid < 0) in q6apm_dai_open()
300 prtd->phys = substream->dma_buffer.addr; in q6apm_dai_open()
302 prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32); in q6apm_dai_open()
314 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_close()
315 struct q6apm_dai_rtd *prtd = runtime->private_data; in q6apm_dai_close()
317 if (prtd->state) { /* only stop graph that is started */ in q6apm_dai_close()
318 q6apm_graph_stop(prtd->graph); in q6apm_dai_close()
319 q6apm_unmap_memory_regions(prtd->graph, substream->stream); in q6apm_dai_close()
322 q6apm_graph_close(prtd->graph); in q6apm_dai_close()
323 prtd->graph = NULL; in q6apm_dai_close()
325 runtime->private_data = NULL; in q6apm_dai_close()
333 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_pointer()
334 struct q6apm_dai_rtd *prtd = runtime->private_data; in q6apm_dai_pointer()
336 if (prtd->pos == prtd->pcm_size) in q6apm_dai_pointer()
337 prtd->pos = 0; in q6apm_dai_pointer()
339 return bytes_to_frames(runtime, prtd->pos); in q6apm_dai_pointer()
346 struct snd_pcm_runtime *runtime = substream->runtime; in q6apm_dai_hw_params()
347 struct q6apm_dai_rtd *prtd = runtime->private_data; in q6apm_dai_hw_params()
349 prtd->pcm_size = params_buffer_bytes(params); in q6apm_dai_hw_params()
350 prtd->periods = params_periods(params); in q6apm_dai_hw_params()
354 prtd->bits_per_sample = 16; in q6apm_dai_hw_params()
357 prtd->bits_per_sample = 24; in q6apm_dai_hw_params()
360 return -EINVAL; in q6apm_dai_hw_params()
370 return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size); in q6apm_dai_pcm_new()
386 struct device *dev = &pdev->dev; in q6apm_dai_probe()
387 struct device_node *node = dev->of_node; in q6apm_dai_probe()
394 return -ENOMEM; in q6apm_dai_probe()
398 pdata->sid = -1; in q6apm_dai_probe()
400 pdata->sid = args.args[0] & SID_MASK_DEFAULT; in q6apm_dai_probe()
409 { .compatible = "qcom,q6apm-dais" },
417 .name = "q6apm-dai",