Linux Audio

Check our new training course

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