File Index
Files and directories
Sign in
FILE

fsl_qmc_audio.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/fsl/fsl_qmc_audio.c C
  1// SPDX-License-Identifier: GPL-2.0
  2/*
  3 * ALSA SoC using the QUICC Multichannel Controller (QMC)
  4 *
  5 * Copyright 2022 CS GROUP France
  6 *
  7 * Author: Herve Codina <herve.codina@bootlin.com>
  8 */
  9
 10#include <linux/dma-mapping.h>
 11#include <linux/module.h>
 12#include <linux/of.h>
 13#include <linux/of_platform.h>
 14#include <linux/platform_device.h>
 15#include <linux/slab.h>
 16#include <soc/fsl/qe/qmc.h>
 17#include <sound/pcm_params.h>
 18#include <sound/soc.h>
 19
 20struct qmc_dai {
 21	char *name;
 22	int id;
 23	struct device *dev;
 24	unsigned int nb_tx_ts;
 25	unsigned int nb_rx_ts;
 26
 27	unsigned int nb_chans_avail;
 28	unsigned int nb_chans_used_tx;
 29	unsigned int nb_chans_used_rx;
 30	struct qmc_chan **qmc_chans;
 31};
 32
 33struct qmc_audio {
 34	struct device *dev;
 35	unsigned int num_dais;
 36	struct qmc_dai *dais;
 37	struct snd_soc_dai_driver *dai_drivers;
 38};
 39
 40struct qmc_dai_prtd {
 41	struct qmc_dai *qmc_dai;
 42
 43	snd_pcm_uframes_t buffer_ended;
 44	snd_pcm_uframes_t buffer_size;
 45	snd_pcm_uframes_t period_size;
 46
 47	dma_addr_t ch_dma_addr_start;
 48	dma_addr_t ch_dma_addr_current;
 49	dma_addr_t ch_dma_addr_end;
 50	size_t ch_dma_size;
 51	size_t ch_dma_offset;
 52
 53	unsigned int channels;
 54	struct snd_pcm_substream *substream;
 55};
 56
 57static int qmc_audio_pcm_construct(struct snd_soc_component *component,
 58				   struct snd_soc_pcm_runtime *rtd)
 59{
 60	struct snd_card *card = rtd->card->snd_card;
 61	int ret;
 62
 63	ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32));
 64	if (ret)
 65		return ret;
 66
 67	snd_pcm_set_managed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, card->dev,
 68				       64 * 1024, 64 * 1024);
 69	return 0;
 70}
 71
 72static bool qmc_audio_access_is_interleaved(snd_pcm_access_t access)
 73{
 74	switch (access) {
 75	case SNDRV_PCM_ACCESS_MMAP_INTERLEAVED:
 76	case SNDRV_PCM_ACCESS_RW_INTERLEAVED:
 77		return true;
 78	default:
 79		break;
 80	}
 81	return false;
 82}
 83
 84static int qmc_audio_pcm_hw_params(struct snd_soc_component *component,
 85				   struct snd_pcm_substream *substream,
 86				   struct snd_pcm_hw_params *params)
 87{
 88	struct snd_pcm_runtime *runtime = substream->runtime;
 89	struct qmc_dai_prtd *prtd = substream->runtime->private_data;
 90
 91	/*
 92	 * In interleaved mode, the driver uses one QMC channel for all audio
 93	 * channels whereas in non-interleaved mode, it uses one QMC channel per
 94	 * audio channel.
 95	 */
 96	prtd->channels = qmc_audio_access_is_interleaved(params_access(params)) ?
 97				1 : params_channels(params);
 98
 99	prtd->substream = substream;
100
101	prtd->buffer_ended = 0;
102	prtd->buffer_size = params_buffer_size(params);
103	prtd->period_size = params_period_size(params);
104
105	prtd->ch_dma_addr_start = runtime->dma_addr;
106	prtd->ch_dma_offset = params_buffer_bytes(params) / prtd->channels;
107	prtd->ch_dma_addr_end = runtime->dma_addr + prtd->ch_dma_offset;
108	prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
109	prtd->ch_dma_size = params_period_bytes(params) / prtd->channels;
110
111	return 0;
112}
113
114static void qmc_audio_pcm_write_complete(void *context);
115
116static int qmc_audio_pcm_write_submit(struct qmc_dai_prtd *prtd)
117{
118	unsigned int i;
119	int ret;
120
121	for (i = 0; i < prtd->channels; i++) {
122		ret = qmc_chan_write_submit(prtd->qmc_dai->qmc_chans[i],
123					    prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
124					    prtd->ch_dma_size,
125					    i == prtd->channels - 1 ? qmc_audio_pcm_write_complete :
126								      NULL, prtd);
127		if (ret) {
128			dev_err(prtd->qmc_dai->dev, "write_submit %u failed %d\n",
129				i, ret);
130			return ret;
131		}
132	}
133
134	return 0;
135}
136
137static void qmc_audio_pcm_write_complete(void *context)
138{
139	struct qmc_dai_prtd *prtd = context;
140
141	prtd->buffer_ended += prtd->period_size;
142	if (prtd->buffer_ended >= prtd->buffer_size)
143		prtd->buffer_ended = 0;
144
145	prtd->ch_dma_addr_current += prtd->ch_dma_size;
146	if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
147		prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
148
149	qmc_audio_pcm_write_submit(prtd);
150
151	snd_pcm_period_elapsed(prtd->substream);
152}
153
154static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags);
155
156static int qmc_audio_pcm_read_submit(struct qmc_dai_prtd *prtd)
157{
158	unsigned int i;
159	int ret;
160
161	for (i = 0; i < prtd->channels; i++) {
162		ret = qmc_chan_read_submit(prtd->qmc_dai->qmc_chans[i],
163					   prtd->ch_dma_addr_current + i * prtd->ch_dma_offset,
164					   prtd->ch_dma_size,
165					   i == prtd->channels - 1 ? qmc_audio_pcm_read_complete :
166								     NULL, prtd);
167		if (ret) {
168			dev_err(prtd->qmc_dai->dev, "read_submit %u failed %d\n",
169				i, ret);
170			return ret;
171		}
172	}
173
174	return 0;
175}
176
177static void qmc_audio_pcm_read_complete(void *context, size_t length, unsigned int flags)
178{
179	struct qmc_dai_prtd *prtd = context;
180
181	if (length != prtd->ch_dma_size) {
182		dev_err(prtd->qmc_dai->dev, "read complete length = %zu, exp %zu\n",
183			length, prtd->ch_dma_size);
184	}
185
186	prtd->buffer_ended += prtd->period_size;
187	if (prtd->buffer_ended >= prtd->buffer_size)
188		prtd->buffer_ended = 0;
189
190	prtd->ch_dma_addr_current += prtd->ch_dma_size;
191	if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
192		prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
193
194	qmc_audio_pcm_read_submit(prtd);
195
196	snd_pcm_period_elapsed(prtd->substream);
197}
198
199static int qmc_audio_pcm_trigger(struct snd_soc_component *component,
200				 struct snd_pcm_substream *substream, int cmd)
201{
202	struct qmc_dai_prtd *prtd = substream->runtime->private_data;
203	int ret;
204
205	if (!prtd->qmc_dai) {
206		dev_err(component->dev, "qmc_dai is not set\n");
207		return -EINVAL;
208	}
209
210	switch (cmd) {
211	case SNDRV_PCM_TRIGGER_START:
212		prtd->buffer_ended = 0;
213		prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
214
215		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
216			/* Submit first chunk ... */
217			ret = qmc_audio_pcm_write_submit(prtd);
218			if (ret)
219				return ret;
220
221			/* ... prepare next one ... */
222			prtd->ch_dma_addr_current += prtd->ch_dma_size;
223			if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
224				prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
225
226			/* ... and send it */
227			ret = qmc_audio_pcm_write_submit(prtd);
228			if (ret)
229				return ret;
230		} else {
231			/* Submit first chunk ... */
232			ret = qmc_audio_pcm_read_submit(prtd);
233			if (ret)
234				return ret;
235
236			/* ... prepare next one ... */
237			prtd->ch_dma_addr_current += prtd->ch_dma_size;
238			if (prtd->ch_dma_addr_current >= prtd->ch_dma_addr_end)
239				prtd->ch_dma_addr_current = prtd->ch_dma_addr_start;
240
241			/* ... and send it */
242			ret = qmc_audio_pcm_read_submit(prtd);
243			if (ret)
244				return ret;
245		}
246		break;
247
248	case SNDRV_PCM_TRIGGER_RESUME:
249	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
250		break;
251
252	case SNDRV_PCM_TRIGGER_STOP:
253	case SNDRV_PCM_TRIGGER_SUSPEND:
254	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
255		break;
256
257	default:
258		return -EINVAL;
259	}
260
261	return 0;
262}
263
264static snd_pcm_uframes_t qmc_audio_pcm_pointer(struct snd_soc_component *component,
265					       struct snd_pcm_substream *substream)
266{
267	struct qmc_dai_prtd *prtd = substream->runtime->private_data;
268
269	return prtd->buffer_ended;
270}
271
272static int qmc_audio_of_xlate_dai_name(struct snd_soc_component *component,
273				       const struct of_phandle_args *args,
274				       const char **dai_name)
275{
276	struct qmc_audio *qmc_audio = dev_get_drvdata(component->dev);
277	struct snd_soc_dai_driver *dai_driver;
278	int id = args->args[0];
279	int i;
280
281	for (i = 0; i  < qmc_audio->num_dais; i++) {
282		dai_driver = qmc_audio->dai_drivers + i;
283		if (dai_driver->id == id) {
284			*dai_name = dai_driver->name;
285			return 0;
286		}
287	}
288
289	return -EINVAL;
290}
291
292static const struct snd_pcm_hardware qmc_audio_pcm_hardware = {
293	.info			= SNDRV_PCM_INFO_MMAP |
294				  SNDRV_PCM_INFO_MMAP_VALID |
295				  SNDRV_PCM_INFO_INTERLEAVED |
296				  SNDRV_PCM_INFO_NONINTERLEAVED |
297				  SNDRV_PCM_INFO_PAUSE,
298	.period_bytes_min	= 32,
299	.period_bytes_max	= 64 * 1024,
300	.periods_min		= 2,
301	.periods_max		= 2 * 1024,
302	.buffer_bytes_max	= 64 * 1024,
303};
304
305static int qmc_audio_pcm_open(struct snd_soc_component *component,
306			      struct snd_pcm_substream *substream)
307{
308	struct snd_pcm_runtime *runtime = substream->runtime;
309	struct qmc_dai_prtd *prtd;
310	int ret;
311
312	snd_soc_set_runtime_hwparams(substream, &qmc_audio_pcm_hardware);
313
314	/* ensure that buffer size is a multiple of period size */
315	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
316	if (ret < 0)
317		return ret;
318
319	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
320	if (!prtd)
321		return -ENOMEM;
322
323	runtime->private_data = prtd;
324
325	return 0;
326}
327
328static int qmc_audio_pcm_close(struct snd_soc_component *component,
329			       struct snd_pcm_substream *substream)
330{
331	struct qmc_dai_prtd *prtd = substream->runtime->private_data;
332
333	kfree(prtd);
334	return 0;
335}
336
337static const struct snd_soc_component_driver qmc_audio_soc_platform = {
338	.open			= qmc_audio_pcm_open,
339	.close			= qmc_audio_pcm_close,
340	.hw_params		= qmc_audio_pcm_hw_params,
341	.trigger		= qmc_audio_pcm_trigger,
342	.pointer		= qmc_audio_pcm_pointer,
343	.pcm_construct		= qmc_audio_pcm_construct,
344	.of_xlate_dai_name	= qmc_audio_of_xlate_dai_name,
345};
346
347static unsigned int qmc_dai_get_index(struct snd_soc_dai *dai)
348{
349	struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
350
351	return dai->driver - qmc_audio->dai_drivers;
352}
353
354static struct qmc_dai *qmc_dai_get_data(struct snd_soc_dai *dai)
355{
356	struct qmc_audio *qmc_audio = snd_soc_dai_get_drvdata(dai);
357	unsigned int index;
358
359	index = qmc_dai_get_index(dai);
360	if (index > qmc_audio->num_dais)
361		return NULL;
362
363	return qmc_audio->dais + index;
364}
365
366/*
367 * The constraints for format/channel is to match with the number of 8bit
368 * time-slots available.
369 */
370static int qmc_dai_hw_rule_channels_by_format(struct qmc_dai *qmc_dai,
371					      struct snd_pcm_hw_params *params,
372					      unsigned int nb_ts)
373{
374	struct snd_interval *c = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS);
375	snd_pcm_format_t format = params_format(params);
376	struct snd_interval ch = {0};
377
378	switch (snd_pcm_format_physical_width(format)) {
379	case 8:
380		ch.max = nb_ts;
381		break;
382	case 16:
383		ch.max = nb_ts / 2;
384		break;
385	case 32:
386		ch.max = nb_ts / 4;
387		break;
388	case 64:
389		ch.max = nb_ts / 8;
390		break;
391	default:
392		dev_err(qmc_dai->dev, "format physical width %u not supported\n",
393			snd_pcm_format_physical_width(format));
394		return -EINVAL;
395	}
396
397	ch.min = ch.max ? 1 : 0;
398
399	return snd_interval_refine(c, &ch);
400}
401
402static int qmc_dai_hw_rule_playback_channels_by_format(struct snd_pcm_hw_params *params,
403						       struct snd_pcm_hw_rule *rule)
404{
405	struct qmc_dai *qmc_dai = rule->private;
406
407	return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_tx_ts);
408}
409
410static int qmc_dai_hw_rule_capture_channels_by_format(struct snd_pcm_hw_params *params,
411						      struct snd_pcm_hw_rule *rule)
412{
413	struct qmc_dai *qmc_dai = rule->private;
414
415	return qmc_dai_hw_rule_channels_by_format(qmc_dai, params, qmc_dai->nb_rx_ts);
416}
417
418static int qmc_dai_hw_rule_format_by_channels(struct qmc_dai *qmc_dai,
419					      struct snd_pcm_hw_params *params,
420					      unsigned int nb_ts)
421{
422	struct snd_mask *f_old = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
423	unsigned int channels = params_channels(params);
424	unsigned int slot_width;
425	snd_pcm_format_t format;
426	struct snd_mask f_new;
427
428	if (!channels || channels > nb_ts) {
429		dev_err(qmc_dai->dev, "channels %u not supported\n",
430			nb_ts);
431		return -EINVAL;
432	}
433
434	slot_width = (nb_ts / channels) * 8;
435
436	snd_mask_none(&f_new);
437	pcm_for_each_format(format) {
438		if (snd_mask_test_format(f_old, format)) {
439			if (snd_pcm_format_physical_width(format) <= slot_width)
440				snd_mask_set_format(&f_new, format);
441		}
442	}
443
444	return snd_mask_refine(f_old, &f_new);
445}
446
447static int qmc_dai_hw_rule_playback_format_by_channels(struct snd_pcm_hw_params *params,
448						       struct snd_pcm_hw_rule *rule)
449{
450	struct qmc_dai *qmc_dai = rule->private;
451
452	return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_tx_ts);
453}
454
455static int qmc_dai_hw_rule_capture_format_by_channels(struct snd_pcm_hw_params *params,
456						      struct snd_pcm_hw_rule *rule)
457{
458	struct qmc_dai *qmc_dai = rule->private;
459
460	return qmc_dai_hw_rule_format_by_channels(qmc_dai, params, qmc_dai->nb_rx_ts);
461}
462
463static int qmc_dai_constraints_interleaved(struct snd_pcm_substream *substream,
464					   struct qmc_dai *qmc_dai)
465{
466	snd_pcm_hw_rule_func_t hw_rule_channels_by_format;
467	snd_pcm_hw_rule_func_t hw_rule_format_by_channels;
468	unsigned int frame_bits;
469	u64 access;
470	int ret;
471
472	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
473		hw_rule_channels_by_format = qmc_dai_hw_rule_capture_channels_by_format;
474		hw_rule_format_by_channels = qmc_dai_hw_rule_capture_format_by_channels;
475		frame_bits = qmc_dai->nb_rx_ts * 8;
476	} else {
477		hw_rule_channels_by_format = qmc_dai_hw_rule_playback_channels_by_format;
478		hw_rule_format_by_channels = qmc_dai_hw_rule_playback_format_by_channels;
479		frame_bits = qmc_dai->nb_tx_ts * 8;
480	}
481
482	ret = snd_pcm_hw_rule_add(substream->runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS,
483				  hw_rule_channels_by_format, qmc_dai,
484				  SNDRV_PCM_HW_PARAM_FORMAT, -1);
485	if (ret) {
486		dev_err(qmc_dai->dev, "Failed to add channels rule (%d)\n", ret);
487		return ret;
488	}
489
490	ret = snd_pcm_hw_rule_add(substream->runtime, 0,  SNDRV_PCM_HW_PARAM_FORMAT,
491				  hw_rule_format_by_channels, qmc_dai,
492				  SNDRV_PCM_HW_PARAM_CHANNELS, -1);
493	if (ret) {
494		dev_err(qmc_dai->dev, "Failed to add format rule (%d)\n", ret);
495		return ret;
496	}
497
498	ret = snd_pcm_hw_constraint_single(substream->runtime,
499					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
500					   frame_bits);
501	if (ret < 0) {
502		dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
503		return ret;
504	}
505
506	access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_INTERLEAVED |
507		 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_INTERLEAVED;
508	ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
509					   access);
510	if (ret) {
511		dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
512		return ret;
513	}
514
515	return 0;
516}
517
518static int qmc_dai_constraints_noninterleaved(struct snd_pcm_substream *substream,
519					      struct qmc_dai *qmc_dai)
520{
521	unsigned int frame_bits;
522	u64 access;
523	int ret;
524
525	frame_bits = (substream->stream == SNDRV_PCM_STREAM_CAPTURE) ?
526			qmc_dai->nb_rx_ts * 8 : qmc_dai->nb_tx_ts * 8;
527	ret = snd_pcm_hw_constraint_single(substream->runtime,
528					   SNDRV_PCM_HW_PARAM_FRAME_BITS,
529					   frame_bits);
530	if (ret < 0) {
531		dev_err(qmc_dai->dev, "Failed to add frame_bits constraint (%d)\n", ret);
532		return ret;
533	}
534
535	access = 1ULL << (__force int)SNDRV_PCM_ACCESS_MMAP_NONINTERLEAVED |
536		 1ULL << (__force int)SNDRV_PCM_ACCESS_RW_NONINTERLEAVED;
537	ret = snd_pcm_hw_constraint_mask64(substream->runtime, SNDRV_PCM_HW_PARAM_ACCESS,
538					   access);
539	if (ret) {
540		dev_err(qmc_dai->dev, "Failed to add hw_param_access constraint (%d)\n", ret);
541		return ret;
542	}
543
544	return 0;
545}
546
547static int qmc_dai_startup(struct snd_pcm_substream *substream,
548			   struct snd_soc_dai *dai)
549{
550	struct qmc_dai_prtd *prtd = substream->runtime->private_data;
551	struct qmc_dai *qmc_dai;
552
553	qmc_dai = qmc_dai_get_data(dai);
554	if (!qmc_dai) {
555		dev_err(dai->dev, "Invalid dai\n");
556		return -EINVAL;
557	}
558
559	prtd->qmc_dai = qmc_dai;
560
561	return qmc_dai->nb_chans_avail > 1 ?
562		qmc_dai_constraints_noninterleaved(substream, qmc_dai) :
563		qmc_dai_constraints_interleaved(substream, qmc_dai);
564}
565
566static int qmc_dai_hw_params(struct snd_pcm_substream *substream,
567			     struct snd_pcm_hw_params *params,
568			     struct snd_soc_dai *dai)
569{
570	struct qmc_chan_param chan_param = {0};
571	unsigned int nb_chans_used;
572	struct qmc_dai *qmc_dai;
573	unsigned int i;
574	int ret;
575
576	qmc_dai = qmc_dai_get_data(dai);
577	if (!qmc_dai) {
578		dev_err(dai->dev, "Invalid dai\n");
579		return -EINVAL;
580	}
581
582	/*
583	 * In interleaved mode, the driver uses one QMC channel for all audio
584	 * channels whereas in non-interleaved mode, it uses one QMC channel per
585	 * audio channel.
586	 */
587	nb_chans_used = qmc_audio_access_is_interleaved(params_access(params)) ?
588				1 : params_channels(params);
589
590	if (nb_chans_used > qmc_dai->nb_chans_avail) {
591		dev_err(dai->dev, "Not enough qmc_chans. Need %u, avail %u\n",
592			nb_chans_used, qmc_dai->nb_chans_avail);
593		return -EINVAL;
594	}
595
596	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
597		chan_param.mode = QMC_TRANSPARENT;
598		chan_param.transp.max_rx_buf_size = params_period_bytes(params) / nb_chans_used;
599		for (i = 0; i < nb_chans_used; i++) {
600			ret = qmc_chan_set_param(qmc_dai->qmc_chans[i], &chan_param);
601			if (ret) {
602				dev_err(dai->dev, "qmc_chans[%u], set param failed %d\n",
603					i, ret);
604				return ret;
605			}
606		}
607		qmc_dai->nb_chans_used_rx = nb_chans_used;
608	} else {
609		qmc_dai->nb_chans_used_tx = nb_chans_used;
610	}
611
612	return 0;
613}
614
615static int qmc_dai_trigger(struct snd_pcm_substream *substream, int cmd,
616			   struct snd_soc_dai *dai)
617{
618	unsigned int nb_chans_used;
619	struct qmc_dai *qmc_dai;
620	unsigned int i;
621	int direction;
622	int ret = 0;
623	int ret_tmp;
624
625	qmc_dai = qmc_dai_get_data(dai);
626	if (!qmc_dai) {
627		dev_err(dai->dev, "Invalid dai\n");
628		return -EINVAL;
629	}
630
631	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
632		direction = QMC_CHAN_WRITE;
633		nb_chans_used = qmc_dai->nb_chans_used_tx;
634	} else {
635		direction = QMC_CHAN_READ;
636		nb_chans_used = qmc_dai->nb_chans_used_rx;
637	}
638
639	switch (cmd) {
640	case SNDRV_PCM_TRIGGER_START:
641	case SNDRV_PCM_TRIGGER_RESUME:
642	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
643		for (i = 0; i < nb_chans_used; i++) {
644			ret = qmc_chan_start(qmc_dai->qmc_chans[i], direction);
645			if (ret)
646				goto err_stop;
647		}
648		break;
649
650	case SNDRV_PCM_TRIGGER_STOP:
651		/* Stop and reset all QMC channels and return the first error encountered */
652		for (i = 0; i < nb_chans_used; i++) {
653			ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
654			if (!ret)
655				ret = ret_tmp;
656			if (ret_tmp)
657				continue;
658
659			ret_tmp = qmc_chan_reset(qmc_dai->qmc_chans[i], direction);
660			if (!ret)
661				ret = ret_tmp;
662		}
663		if (ret)
664			return ret;
665		break;
666
667	case SNDRV_PCM_TRIGGER_SUSPEND:
668	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
669		/* Stop all QMC channels and return the first error encountered */
670		for (i = 0; i < nb_chans_used; i++) {
671			ret_tmp = qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
672			if (!ret)
673				ret = ret_tmp;
674		}
675		if (ret)
676			return ret;
677		break;
678
679	default:
680		return -EINVAL;
681	}
682
683	return 0;
684
685err_stop:
686	while (i--) {
687		qmc_chan_stop(qmc_dai->qmc_chans[i], direction);
688		qmc_chan_reset(qmc_dai->qmc_chans[i], direction);
689	}
690	return ret;
691}
692
693static const struct snd_soc_dai_ops qmc_dai_ops = {
694	.startup	= qmc_dai_startup,
695	.trigger	= qmc_dai_trigger,
696	.hw_params	= qmc_dai_hw_params,
697};
698
699static u64 qmc_audio_formats(u8 nb_ts, bool is_noninterleaved)
700{
701	unsigned int format_width;
702	unsigned int chan_width;
703	snd_pcm_format_t format;
704	u64 formats_mask;
705
706	if (!nb_ts)
707		return 0;
708
709	formats_mask = 0;
710	chan_width = nb_ts * 8;
711	pcm_for_each_format(format) {
712		/*
713		 * Support format other than little-endian (ie big-endian or
714		 * without endianness such as 8bit formats)
715		 */
716		if (snd_pcm_format_little_endian(format) == 1)
717			continue;
718
719		/* Support physical width multiple of 8bit */
720		format_width = snd_pcm_format_physical_width(format);
721		if (format_width == 0 || format_width % 8)
722			continue;
723
724		/*
725		 * And support physical width that can fit N times in the
726		 * channel
727		 */
728		if (format_width > chan_width || chan_width % format_width)
729			continue;
730
731		/*
732		 * In non interleaved mode, we can only support formats that
733		 * can fit only 1 time in the channel
734		 */
735		if (is_noninterleaved && format_width != chan_width)
736			continue;
737
738		formats_mask |= pcm_format_to_bits(format);
739	}
740	return formats_mask;
741}
742
743static int qmc_audio_dai_parse(struct qmc_audio *qmc_audio, struct device_node *np,
744			       struct qmc_dai *qmc_dai,
745			       struct snd_soc_dai_driver *qmc_soc_dai_driver)
746{
747	struct qmc_chan_ts_info ts_info;
748	struct qmc_chan_info info;
749	unsigned long rx_fs_rate;
750	unsigned long tx_fs_rate;
751	int prev_last_rx_ts = 0;
752	int prev_last_tx_ts = 0;
753	unsigned int nb_tx_ts;
754	unsigned int nb_rx_ts;
755	unsigned int i;
756	int last_rx_ts;
757	int last_tx_ts;
758	int count;
759	u32 val;
760	int ret;
761
762	qmc_dai->dev = qmc_audio->dev;
763
764	ret = of_property_read_u32(np, "reg", &val);
765	if (ret) {
766		dev_err(qmc_audio->dev, "%pOF: failed to read reg\n", np);
767		return ret;
768	}
769	qmc_dai->id = val;
770
771	qmc_dai->name = devm_kasprintf(qmc_audio->dev, GFP_KERNEL, "%s.%d",
772				       np->parent->name, qmc_dai->id);
773	if (!qmc_dai->name)
774		return -ENOMEM;
775
776	count = qmc_chan_count_phandles(np, "fsl,qmc-chan");
777	if (count < 0)
778		return dev_err_probe(qmc_audio->dev, count,
779				     "dai %d get number of QMC channel failed\n", qmc_dai->id);
780	if (!count)
781		return dev_err_probe(qmc_audio->dev, -EINVAL,
782				     "dai %d no QMC channel defined\n", qmc_dai->id);
783
784	qmc_dai->qmc_chans = devm_kcalloc(qmc_audio->dev, count, sizeof(*qmc_dai->qmc_chans),
785					  GFP_KERNEL);
786	if (!qmc_dai->qmc_chans)
787		return -ENOMEM;
788
789	for (i = 0; i < count; i++) {
790		qmc_dai->qmc_chans[i] = devm_qmc_chan_get_byphandles_index(qmc_audio->dev, np,
791									   "fsl,qmc-chan", i);
792		if (IS_ERR(qmc_dai->qmc_chans[i])) {
793			return dev_err_probe(qmc_audio->dev, PTR_ERR(qmc_dai->qmc_chans[i]),
794					     "dai %d get QMC channel %d failed\n", qmc_dai->id, i);
795		}
796
797		ret = qmc_chan_get_info(qmc_dai->qmc_chans[i], &info);
798		if (ret) {
799			dev_err(qmc_audio->dev, "dai %d get QMC %d channel info failed %d\n",
800				qmc_dai->id, i, ret);
801			return ret;
802		}
803
804		if (info.mode != QMC_TRANSPARENT) {
805			dev_err(qmc_audio->dev, "dai %d QMC chan %d mode %d is not QMC_TRANSPARENT\n",
806				qmc_dai->id, i, info.mode);
807			return -EINVAL;
808		}
809
810		/*
811		 * All channels must have the same number of Tx slots and the
812		 * same numbers of Rx slots.
813		 */
814		if (i == 0) {
815			nb_tx_ts = info.nb_tx_ts;
816			nb_rx_ts = info.nb_rx_ts;
817			tx_fs_rate = info.tx_fs_rate;
818			rx_fs_rate = info.rx_fs_rate;
819		} else {
820			if (nb_tx_ts != info.nb_tx_ts) {
821				dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Tx timeslots (%u instead of %u)\n",
822					qmc_dai->id, i, info.nb_tx_ts, nb_tx_ts);
823				return -EINVAL;
824			}
825			if (nb_rx_ts != info.nb_rx_ts) {
826				dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent number of Rx timeslots (%u instead of %u)\n",
827					qmc_dai->id, i, info.nb_rx_ts, nb_rx_ts);
828				return -EINVAL;
829			}
830			if (tx_fs_rate != info.tx_fs_rate) {
831				dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Tx frame sample rate (%lu instead of %lu)\n",
832					qmc_dai->id, i, info.tx_fs_rate, tx_fs_rate);
833				return -EINVAL;
834			}
835			if (rx_fs_rate != info.rx_fs_rate) {
836				dev_err(qmc_audio->dev, "dai %d QMC chan %d inconsistent Rx frame sample rate (%lu instead of %lu)\n",
837					qmc_dai->id, i, info.rx_fs_rate, rx_fs_rate);
838				return -EINVAL;
839			}
840		}
841
842		ret = qmc_chan_get_ts_info(qmc_dai->qmc_chans[i], &ts_info);
843		if (ret) {
844			dev_err(qmc_audio->dev, "dai %d get QMC %d channel TS info failed %d\n",
845				qmc_dai->id, i, ret);
846			return ret;
847		}
848
849		last_rx_ts = fls64(ts_info.rx_ts_mask);
850		last_tx_ts = fls64(ts_info.tx_ts_mask);
851
852		if (prev_last_rx_ts > last_rx_ts) {
853			dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (RX timeslot %d before %d)\n",
854				qmc_dai->id, i, prev_last_rx_ts, last_rx_ts);
855			return -EINVAL;
856		}
857		if (prev_last_tx_ts > last_tx_ts) {
858			dev_err(qmc_audio->dev, "dai %d QMC chan %d unordered channels (TX timeslot %d before %d)\n",
859				qmc_dai->id, i, prev_last_tx_ts, last_tx_ts);
860			return -EINVAL;
861		}
862
863		prev_last_rx_ts = last_rx_ts;
864		prev_last_tx_ts = last_tx_ts;
865	}
866
867	qmc_dai->nb_chans_avail = count;
868	qmc_dai->nb_tx_ts = nb_tx_ts * count;
869	qmc_dai->nb_rx_ts = nb_rx_ts * count;
870
871	qmc_soc_dai_driver->id = qmc_dai->id;
872	qmc_soc_dai_driver->name = qmc_dai->name;
873
874	qmc_soc_dai_driver->playback.channels_min = 0;
875	qmc_soc_dai_driver->playback.channels_max = 0;
876	if (nb_tx_ts) {
877		qmc_soc_dai_driver->playback.channels_min = 1;
878		qmc_soc_dai_driver->playback.channels_max = count > 1 ? count : nb_tx_ts;
879	}
880	qmc_soc_dai_driver->playback.formats = qmc_audio_formats(nb_tx_ts,
881								 count > 1);
882
883	qmc_soc_dai_driver->capture.channels_min = 0;
884	qmc_soc_dai_driver->capture.channels_max = 0;
885	if (nb_rx_ts) {
886		qmc_soc_dai_driver->capture.channels_min = 1;
887		qmc_soc_dai_driver->capture.channels_max = count > 1 ? count : nb_rx_ts;
888	}
889	qmc_soc_dai_driver->capture.formats = qmc_audio_formats(nb_rx_ts,
890								count > 1);
891
892	qmc_soc_dai_driver->playback.rates = snd_pcm_rate_to_rate_bit(tx_fs_rate);
893	qmc_soc_dai_driver->playback.rate_min = tx_fs_rate;
894	qmc_soc_dai_driver->playback.rate_max = tx_fs_rate;
895	qmc_soc_dai_driver->capture.rates = snd_pcm_rate_to_rate_bit(rx_fs_rate);
896	qmc_soc_dai_driver->capture.rate_min = rx_fs_rate;
897	qmc_soc_dai_driver->capture.rate_max = rx_fs_rate;
898
899	qmc_soc_dai_driver->ops = &qmc_dai_ops;
900
901	return 0;
902}
903
904static int qmc_audio_probe(struct platform_device *pdev)
905{
906	struct device_node *np = pdev->dev.of_node;
907	struct qmc_audio *qmc_audio;
908	struct device_node *child;
909	unsigned int i;
910	int ret;
911
912	qmc_audio = devm_kzalloc(&pdev->dev, sizeof(*qmc_audio), GFP_KERNEL);
913	if (!qmc_audio)
914		return -ENOMEM;
915
916	qmc_audio->dev = &pdev->dev;
917
918	qmc_audio->num_dais = of_get_available_child_count(np);
919	if (qmc_audio->num_dais) {
920		qmc_audio->dais = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
921					       sizeof(*qmc_audio->dais),
922					       GFP_KERNEL);
923		if (!qmc_audio->dais)
924			return -ENOMEM;
925
926		qmc_audio->dai_drivers = devm_kcalloc(&pdev->dev, qmc_audio->num_dais,
927						      sizeof(*qmc_audio->dai_drivers),
928						      GFP_KERNEL);
929		if (!qmc_audio->dai_drivers)
930			return -ENOMEM;
931	}
932
933	i = 0;
934	for_each_available_child_of_node(np, child) {
935		ret = qmc_audio_dai_parse(qmc_audio, child,
936					  qmc_audio->dais + i,
937					  qmc_audio->dai_drivers + i);
938		if (ret) {
939			of_node_put(child);
940			return ret;
941		}
942		i++;
943	}
944
945	platform_set_drvdata(pdev, qmc_audio);
946
947	ret = devm_snd_soc_register_component(qmc_audio->dev,
948					      &qmc_audio_soc_platform,
949					      qmc_audio->dai_drivers,
950					      qmc_audio->num_dais);
951	if (ret)
952		return ret;
953
954	return 0;
955}
956
957static const struct of_device_id qmc_audio_id_table[] = {
958	{ .compatible = "fsl,qmc-audio" },
959	{} /* sentinel */
960};
961MODULE_DEVICE_TABLE(of, qmc_audio_id_table);
962
963static struct platform_driver qmc_audio_driver = {
964	.driver = {
965		.name = "fsl-qmc-audio",
966		.of_match_table = of_match_ptr(qmc_audio_id_table),
967	},
968	.probe = qmc_audio_probe,
969};
970module_platform_driver(qmc_audio_driver);
971
972MODULE_AUTHOR("Herve Codina <herve.codina@bootlin.com>");
973MODULE_DESCRIPTION("CPM/QE QMC audio driver");
974MODULE_LICENSE("GPL");
~/ Read-only file preview.