xref: /openbmc/linux/sound/soc/qcom/qdsp6/q6apm-dai.c (revision 816ffd28002651a469e86d1118a225862e392ecd)
19b4fe0f1SSrinivas Kandagatla // SPDX-License-Identifier: GPL-2.0
29b4fe0f1SSrinivas Kandagatla // Copyright (c) 2021, Linaro Limited
39b4fe0f1SSrinivas Kandagatla 
49b4fe0f1SSrinivas Kandagatla #include <linux/init.h>
59b4fe0f1SSrinivas Kandagatla #include <linux/err.h>
69b4fe0f1SSrinivas Kandagatla #include <linux/module.h>
79b4fe0f1SSrinivas Kandagatla #include <linux/platform_device.h>
89b4fe0f1SSrinivas Kandagatla #include <linux/slab.h>
99b4fe0f1SSrinivas Kandagatla #include <sound/soc.h>
109b4fe0f1SSrinivas Kandagatla #include <sound/soc-dapm.h>
1184222ef5SSrinivas Kandagatla #include <linux/spinlock.h>
129b4fe0f1SSrinivas Kandagatla #include <sound/pcm.h>
139b4fe0f1SSrinivas Kandagatla #include <asm/dma.h>
149b4fe0f1SSrinivas Kandagatla #include <linux/dma-mapping.h>
159b4fe0f1SSrinivas Kandagatla #include <linux/of_device.h>
169b4fe0f1SSrinivas Kandagatla #include <sound/pcm_params.h>
179b4fe0f1SSrinivas Kandagatla #include "q6apm.h"
189b4fe0f1SSrinivas Kandagatla 
199b4fe0f1SSrinivas Kandagatla #define DRV_NAME "q6apm-dai"
209b4fe0f1SSrinivas Kandagatla 
219b4fe0f1SSrinivas Kandagatla #define PLAYBACK_MIN_NUM_PERIODS	2
229b4fe0f1SSrinivas Kandagatla #define PLAYBACK_MAX_NUM_PERIODS	8
239b4fe0f1SSrinivas Kandagatla #define PLAYBACK_MAX_PERIOD_SIZE	65536
249b4fe0f1SSrinivas Kandagatla #define PLAYBACK_MIN_PERIOD_SIZE	128
259b4fe0f1SSrinivas Kandagatla #define CAPTURE_MIN_NUM_PERIODS		2
269b4fe0f1SSrinivas Kandagatla #define CAPTURE_MAX_NUM_PERIODS		8
279b4fe0f1SSrinivas Kandagatla #define CAPTURE_MAX_PERIOD_SIZE		4096
289b4fe0f1SSrinivas Kandagatla #define CAPTURE_MIN_PERIOD_SIZE		320
299b4fe0f1SSrinivas Kandagatla #define BUFFER_BYTES_MAX (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE)
309b4fe0f1SSrinivas Kandagatla #define BUFFER_BYTES_MIN (PLAYBACK_MIN_NUM_PERIODS * PLAYBACK_MIN_PERIOD_SIZE)
3188b60bf0SSrinivas Kandagatla #define COMPR_PLAYBACK_MAX_FRAGMENT_SIZE (128 * 1024)
3288b60bf0SSrinivas Kandagatla #define COMPR_PLAYBACK_MAX_NUM_FRAGMENTS (16 * 4)
33c0c87738SSrinivas Kandagatla #define COMPR_PLAYBACK_MIN_FRAGMENT_SIZE (8 * 1024)
34c0c87738SSrinivas Kandagatla #define COMPR_PLAYBACK_MIN_NUM_FRAGMENTS (4)
359b4fe0f1SSrinivas Kandagatla #define SID_MASK_DEFAULT	0xF
369b4fe0f1SSrinivas Kandagatla 
37c0c87738SSrinivas Kandagatla static const struct snd_compr_codec_caps q6apm_compr_caps = {
38c0c87738SSrinivas Kandagatla 	.num_descriptors = 1,
39c0c87738SSrinivas Kandagatla 	.descriptor[0].max_ch = 2,
40c0c87738SSrinivas Kandagatla 	.descriptor[0].sample_rates = {	8000, 11025, 12000, 16000, 22050,
41c0c87738SSrinivas Kandagatla 					24000, 32000, 44100, 48000, 88200,
42c0c87738SSrinivas Kandagatla 					96000, 176400, 192000 },
43c0c87738SSrinivas Kandagatla 	.descriptor[0].num_sample_rates = 13,
44c0c87738SSrinivas Kandagatla 	.descriptor[0].bit_rate[0] = 320,
45c0c87738SSrinivas Kandagatla 	.descriptor[0].bit_rate[1] = 128,
46c0c87738SSrinivas Kandagatla 	.descriptor[0].num_bitrates = 2,
47c0c87738SSrinivas Kandagatla 	.descriptor[0].profiles = 0,
48c0c87738SSrinivas Kandagatla 	.descriptor[0].modes = SND_AUDIOCHANMODE_MP3_STEREO,
49c0c87738SSrinivas Kandagatla 	.descriptor[0].formats = 0,
50c0c87738SSrinivas Kandagatla };
51c0c87738SSrinivas Kandagatla 
529b4fe0f1SSrinivas Kandagatla enum stream_state {
539b4fe0f1SSrinivas Kandagatla 	Q6APM_STREAM_IDLE = 0,
549b4fe0f1SSrinivas Kandagatla 	Q6APM_STREAM_STOPPED,
559b4fe0f1SSrinivas Kandagatla 	Q6APM_STREAM_RUNNING,
569b4fe0f1SSrinivas Kandagatla };
579b4fe0f1SSrinivas Kandagatla 
589b4fe0f1SSrinivas Kandagatla struct q6apm_dai_rtd {
599b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_substream *substream;
609b4fe0f1SSrinivas Kandagatla 	struct snd_compr_stream *cstream;
61c0c87738SSrinivas Kandagatla 	struct snd_codec codec;
629b4fe0f1SSrinivas Kandagatla 	struct snd_compr_params codec_param;
639b4fe0f1SSrinivas Kandagatla 	struct snd_dma_buffer dma_buffer;
649b4fe0f1SSrinivas Kandagatla 	phys_addr_t phys;
659b4fe0f1SSrinivas Kandagatla 	unsigned int pcm_size;
669b4fe0f1SSrinivas Kandagatla 	unsigned int pcm_count;
679b4fe0f1SSrinivas Kandagatla 	unsigned int pos;       /* Buffer position */
689b4fe0f1SSrinivas Kandagatla 	unsigned int periods;
699b4fe0f1SSrinivas Kandagatla 	unsigned int bytes_sent;
709b4fe0f1SSrinivas Kandagatla 	unsigned int bytes_received;
719b4fe0f1SSrinivas Kandagatla 	unsigned int copied_total;
729b4fe0f1SSrinivas Kandagatla 	uint16_t bits_per_sample;
739b4fe0f1SSrinivas Kandagatla 	uint16_t source; /* Encoding source bit mask */
749b4fe0f1SSrinivas Kandagatla 	uint16_t session_id;
75c0c87738SSrinivas Kandagatla 	bool next_track;
769b4fe0f1SSrinivas Kandagatla 	enum stream_state state;
779b4fe0f1SSrinivas Kandagatla 	struct q6apm_graph *graph;
7884222ef5SSrinivas Kandagatla 	spinlock_t lock;
79b3f736d1SSrinivas Kandagatla 	uint32_t initial_samples_drop;
80b3f736d1SSrinivas Kandagatla 	uint32_t trailing_samples_drop;
8188b60bf0SSrinivas Kandagatla 	bool notify_on_drain;
829b4fe0f1SSrinivas Kandagatla };
839b4fe0f1SSrinivas Kandagatla 
849b4fe0f1SSrinivas Kandagatla struct q6apm_dai_data {
859b4fe0f1SSrinivas Kandagatla 	long long sid;
869b4fe0f1SSrinivas Kandagatla };
879b4fe0f1SSrinivas Kandagatla 
889b4fe0f1SSrinivas Kandagatla static struct snd_pcm_hardware q6apm_dai_hardware_capture = {
899b4fe0f1SSrinivas Kandagatla 	.info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER |
909b4fe0f1SSrinivas Kandagatla 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED |
91aa759f3fSSrinivas Kandagatla 				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
92aa759f3fSSrinivas Kandagatla 				 SNDRV_PCM_INFO_BATCH),
939b4fe0f1SSrinivas Kandagatla 	.formats =              (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE),
949b4fe0f1SSrinivas Kandagatla 	.rates =                SNDRV_PCM_RATE_8000_48000,
959b4fe0f1SSrinivas Kandagatla 	.rate_min =             8000,
969b4fe0f1SSrinivas Kandagatla 	.rate_max =             48000,
979b4fe0f1SSrinivas Kandagatla 	.channels_min =         2,
989b4fe0f1SSrinivas Kandagatla 	.channels_max =         4,
999b4fe0f1SSrinivas Kandagatla 	.buffer_bytes_max =     CAPTURE_MAX_NUM_PERIODS * CAPTURE_MAX_PERIOD_SIZE,
1009b4fe0f1SSrinivas Kandagatla 	.period_bytes_min =	CAPTURE_MIN_PERIOD_SIZE,
1019b4fe0f1SSrinivas Kandagatla 	.period_bytes_max =     CAPTURE_MAX_PERIOD_SIZE,
1029b4fe0f1SSrinivas Kandagatla 	.periods_min =          CAPTURE_MIN_NUM_PERIODS,
1039b4fe0f1SSrinivas Kandagatla 	.periods_max =          CAPTURE_MAX_NUM_PERIODS,
1049b4fe0f1SSrinivas Kandagatla 	.fifo_size =            0,
1059b4fe0f1SSrinivas Kandagatla };
1069b4fe0f1SSrinivas Kandagatla 
1079b4fe0f1SSrinivas Kandagatla static struct snd_pcm_hardware q6apm_dai_hardware_playback = {
1089b4fe0f1SSrinivas Kandagatla 	.info =                 (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_BLOCK_TRANSFER |
1099b4fe0f1SSrinivas Kandagatla 				 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_INTERLEAVED |
110aa759f3fSSrinivas Kandagatla 				 SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME |
111aa759f3fSSrinivas Kandagatla 				 SNDRV_PCM_INFO_BATCH),
1129b4fe0f1SSrinivas Kandagatla 	.formats =              (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S24_LE),
1139b4fe0f1SSrinivas Kandagatla 	.rates =                SNDRV_PCM_RATE_8000_192000,
1149b4fe0f1SSrinivas Kandagatla 	.rate_min =             8000,
1159b4fe0f1SSrinivas Kandagatla 	.rate_max =             192000,
1169b4fe0f1SSrinivas Kandagatla 	.channels_min =         2,
1179b4fe0f1SSrinivas Kandagatla 	.channels_max =         8,
1189b4fe0f1SSrinivas Kandagatla 	.buffer_bytes_max =     (PLAYBACK_MAX_NUM_PERIODS * PLAYBACK_MAX_PERIOD_SIZE),
1199b4fe0f1SSrinivas Kandagatla 	.period_bytes_min =	PLAYBACK_MIN_PERIOD_SIZE,
1209b4fe0f1SSrinivas Kandagatla 	.period_bytes_max =     PLAYBACK_MAX_PERIOD_SIZE,
1219b4fe0f1SSrinivas Kandagatla 	.periods_min =          PLAYBACK_MIN_NUM_PERIODS,
1229b4fe0f1SSrinivas Kandagatla 	.periods_max =          PLAYBACK_MAX_NUM_PERIODS,
1239b4fe0f1SSrinivas Kandagatla 	.fifo_size =            0,
1249b4fe0f1SSrinivas Kandagatla };
1259b4fe0f1SSrinivas Kandagatla 
event_handler(uint32_t opcode,uint32_t token,uint32_t * payload,void * priv)1269b4fe0f1SSrinivas Kandagatla static void event_handler(uint32_t opcode, uint32_t token, uint32_t *payload, void *priv)
1279b4fe0f1SSrinivas Kandagatla {
1289b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = priv;
1299b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_substream *substream = prtd->substream;
13084222ef5SSrinivas Kandagatla 	unsigned long flags;
1319b4fe0f1SSrinivas Kandagatla 
1329b4fe0f1SSrinivas Kandagatla 	switch (opcode) {
1339b4fe0f1SSrinivas Kandagatla 	case APM_CLIENT_EVENT_CMD_EOS_DONE:
1349b4fe0f1SSrinivas Kandagatla 		prtd->state = Q6APM_STREAM_STOPPED;
1359b4fe0f1SSrinivas Kandagatla 		break;
1369b4fe0f1SSrinivas Kandagatla 	case APM_CLIENT_EVENT_DATA_WRITE_DONE:
13784222ef5SSrinivas Kandagatla 	        spin_lock_irqsave(&prtd->lock, flags);
1389b4fe0f1SSrinivas Kandagatla 		prtd->pos += prtd->pcm_count;
13984222ef5SSrinivas Kandagatla 		spin_unlock_irqrestore(&prtd->lock, flags);
1409b4fe0f1SSrinivas Kandagatla 		snd_pcm_period_elapsed(substream);
1419b4fe0f1SSrinivas Kandagatla 		if (prtd->state == Q6APM_STREAM_RUNNING)
1429b4fe0f1SSrinivas Kandagatla 			q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
1439b4fe0f1SSrinivas Kandagatla 
1449b4fe0f1SSrinivas Kandagatla 		break;
1459b4fe0f1SSrinivas Kandagatla 	case APM_CLIENT_EVENT_DATA_READ_DONE:
14684222ef5SSrinivas Kandagatla 	        spin_lock_irqsave(&prtd->lock, flags);
1479b4fe0f1SSrinivas Kandagatla 		prtd->pos += prtd->pcm_count;
14884222ef5SSrinivas Kandagatla 		spin_unlock_irqrestore(&prtd->lock, flags);
1499b4fe0f1SSrinivas Kandagatla 		snd_pcm_period_elapsed(substream);
1509b4fe0f1SSrinivas Kandagatla 		if (prtd->state == Q6APM_STREAM_RUNNING)
1519b4fe0f1SSrinivas Kandagatla 			q6apm_read(prtd->graph);
1529b4fe0f1SSrinivas Kandagatla 
1539b4fe0f1SSrinivas Kandagatla 		break;
1549b4fe0f1SSrinivas Kandagatla 	default:
1559b4fe0f1SSrinivas Kandagatla 		break;
1569b4fe0f1SSrinivas Kandagatla 	}
1579b4fe0f1SSrinivas Kandagatla }
1589b4fe0f1SSrinivas Kandagatla 
event_handler_compr(uint32_t opcode,uint32_t token,uint32_t * payload,void * priv)15988b60bf0SSrinivas Kandagatla static void event_handler_compr(uint32_t opcode, uint32_t token,
16088b60bf0SSrinivas Kandagatla 				uint32_t *payload, void *priv)
16188b60bf0SSrinivas Kandagatla {
16288b60bf0SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = priv;
16388b60bf0SSrinivas Kandagatla 	struct snd_compr_stream *substream = prtd->cstream;
16488b60bf0SSrinivas Kandagatla 	unsigned long flags;
16588b60bf0SSrinivas Kandagatla 	uint32_t wflags = 0;
16688b60bf0SSrinivas Kandagatla 	uint64_t avail;
16788b60bf0SSrinivas Kandagatla 	uint32_t bytes_written, bytes_to_write;
16888b60bf0SSrinivas Kandagatla 	bool is_last_buffer = false;
16988b60bf0SSrinivas Kandagatla 
17088b60bf0SSrinivas Kandagatla 	switch (opcode) {
17188b60bf0SSrinivas Kandagatla 	case APM_CLIENT_EVENT_CMD_EOS_DONE:
17288b60bf0SSrinivas Kandagatla 		spin_lock_irqsave(&prtd->lock, flags);
17388b60bf0SSrinivas Kandagatla 		if (prtd->notify_on_drain) {
17488b60bf0SSrinivas Kandagatla 			snd_compr_drain_notify(prtd->cstream);
17588b60bf0SSrinivas Kandagatla 			prtd->notify_on_drain = false;
17688b60bf0SSrinivas Kandagatla 		} else {
17788b60bf0SSrinivas Kandagatla 			prtd->state = Q6APM_STREAM_STOPPED;
17888b60bf0SSrinivas Kandagatla 		}
17988b60bf0SSrinivas Kandagatla 		spin_unlock_irqrestore(&prtd->lock, flags);
18088b60bf0SSrinivas Kandagatla 		break;
18188b60bf0SSrinivas Kandagatla 	case APM_CLIENT_EVENT_DATA_WRITE_DONE:
18288b60bf0SSrinivas Kandagatla 		spin_lock_irqsave(&prtd->lock, flags);
18388b60bf0SSrinivas Kandagatla 		bytes_written = token >> APM_WRITE_TOKEN_LEN_SHIFT;
18488b60bf0SSrinivas Kandagatla 		prtd->copied_total += bytes_written;
18588b60bf0SSrinivas Kandagatla 		snd_compr_fragment_elapsed(substream);
18688b60bf0SSrinivas Kandagatla 
18788b60bf0SSrinivas Kandagatla 		if (prtd->state != Q6APM_STREAM_RUNNING) {
18888b60bf0SSrinivas Kandagatla 			spin_unlock_irqrestore(&prtd->lock, flags);
18988b60bf0SSrinivas Kandagatla 			break;
19088b60bf0SSrinivas Kandagatla 		}
19188b60bf0SSrinivas Kandagatla 
19288b60bf0SSrinivas Kandagatla 		avail = prtd->bytes_received - prtd->bytes_sent;
19388b60bf0SSrinivas Kandagatla 
19488b60bf0SSrinivas Kandagatla 		if (avail > prtd->pcm_count) {
19588b60bf0SSrinivas Kandagatla 			bytes_to_write = prtd->pcm_count;
19688b60bf0SSrinivas Kandagatla 		} else {
19788b60bf0SSrinivas Kandagatla 			if (substream->partial_drain || prtd->notify_on_drain)
19888b60bf0SSrinivas Kandagatla 				is_last_buffer = true;
19988b60bf0SSrinivas Kandagatla 			bytes_to_write = avail;
20088b60bf0SSrinivas Kandagatla 		}
20188b60bf0SSrinivas Kandagatla 
20288b60bf0SSrinivas Kandagatla 		if (bytes_to_write) {
20388b60bf0SSrinivas Kandagatla 			if (substream->partial_drain && is_last_buffer)
20488b60bf0SSrinivas Kandagatla 				wflags |= APM_LAST_BUFFER_FLAG;
20588b60bf0SSrinivas Kandagatla 
20688b60bf0SSrinivas Kandagatla 			q6apm_write_async(prtd->graph,
20788b60bf0SSrinivas Kandagatla 						bytes_to_write, 0, 0, wflags);
20888b60bf0SSrinivas Kandagatla 
20988b60bf0SSrinivas Kandagatla 			prtd->bytes_sent += bytes_to_write;
21088b60bf0SSrinivas Kandagatla 
21188b60bf0SSrinivas Kandagatla 			if (prtd->notify_on_drain && is_last_buffer)
21288b60bf0SSrinivas Kandagatla 				audioreach_shared_memory_send_eos(prtd->graph);
21388b60bf0SSrinivas Kandagatla 		}
21488b60bf0SSrinivas Kandagatla 
21588b60bf0SSrinivas Kandagatla 		spin_unlock_irqrestore(&prtd->lock, flags);
21688b60bf0SSrinivas Kandagatla 		break;
21788b60bf0SSrinivas Kandagatla 	default:
21888b60bf0SSrinivas Kandagatla 		break;
21988b60bf0SSrinivas Kandagatla 	}
22088b60bf0SSrinivas Kandagatla }
22188b60bf0SSrinivas Kandagatla 
q6apm_dai_prepare(struct snd_soc_component * component,struct snd_pcm_substream * substream)2229b4fe0f1SSrinivas Kandagatla static int q6apm_dai_prepare(struct snd_soc_component *component,
2239b4fe0f1SSrinivas Kandagatla 			     struct snd_pcm_substream *substream)
2249b4fe0f1SSrinivas Kandagatla {
2259b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
2269b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
2279b4fe0f1SSrinivas Kandagatla 	struct audioreach_module_config cfg;
2289b4fe0f1SSrinivas Kandagatla 	struct device *dev = component->dev;
2299b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_data *pdata;
2309b4fe0f1SSrinivas Kandagatla 	int ret;
2319b4fe0f1SSrinivas Kandagatla 
2329b4fe0f1SSrinivas Kandagatla 	pdata = snd_soc_component_get_drvdata(component);
2339b4fe0f1SSrinivas Kandagatla 	if (!pdata)
2349b4fe0f1SSrinivas Kandagatla 		return -EINVAL;
2359b4fe0f1SSrinivas Kandagatla 
2369b4fe0f1SSrinivas Kandagatla 	if (!prtd || !prtd->graph) {
2379b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "%s: private data null or audio client freed\n", __func__);
2389b4fe0f1SSrinivas Kandagatla 		return -EINVAL;
2399b4fe0f1SSrinivas Kandagatla 	}
2409b4fe0f1SSrinivas Kandagatla 
2419b4fe0f1SSrinivas Kandagatla 	cfg.direction = substream->stream;
2429b4fe0f1SSrinivas Kandagatla 	cfg.sample_rate = runtime->rate;
2439b4fe0f1SSrinivas Kandagatla 	cfg.num_channels = runtime->channels;
2449b4fe0f1SSrinivas Kandagatla 	cfg.bit_width = prtd->bits_per_sample;
245e41521b6SMohammad Rafi Shaik 	cfg.fmt = SND_AUDIOCODEC_PCM;
2469b4fe0f1SSrinivas Kandagatla 
24758136d93SSrinivas Kandagatla 	if (prtd->state) {
24858136d93SSrinivas Kandagatla 		/* clear the previous setup if any  */
24958136d93SSrinivas Kandagatla 		q6apm_graph_stop(prtd->graph);
25058136d93SSrinivas Kandagatla 		q6apm_unmap_memory_regions(prtd->graph, substream->stream);
25158136d93SSrinivas Kandagatla 	}
25258136d93SSrinivas Kandagatla 
2539b4fe0f1SSrinivas Kandagatla 	prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
2549b4fe0f1SSrinivas Kandagatla 	prtd->pos = 0;
2559b4fe0f1SSrinivas Kandagatla 	/* rate and channels are sent to audio driver */
2569b4fe0f1SSrinivas Kandagatla 	ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
2579b4fe0f1SSrinivas Kandagatla 	if (ret < 0) {
2589b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "%s: q6apm_open_write failed\n", __func__);
2599b4fe0f1SSrinivas Kandagatla 		return ret;
2609b4fe0f1SSrinivas Kandagatla 	}
2619b4fe0f1SSrinivas Kandagatla 
2629b4fe0f1SSrinivas Kandagatla 	ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg);
2639b4fe0f1SSrinivas Kandagatla 	if (ret < 0)
2649b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "%s: CMD Format block failed\n", __func__);
2659b4fe0f1SSrinivas Kandagatla 
2669b4fe0f1SSrinivas Kandagatla 	ret = q6apm_map_memory_regions(prtd->graph, substream->stream, prtd->phys,
2679b4fe0f1SSrinivas Kandagatla 				       (prtd->pcm_size / prtd->periods), prtd->periods);
2689b4fe0f1SSrinivas Kandagatla 
2699b4fe0f1SSrinivas Kandagatla 	if (ret < 0) {
2709b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n",	ret);
2719b4fe0f1SSrinivas Kandagatla 		return -ENOMEM;
2729b4fe0f1SSrinivas Kandagatla 	}
2739b4fe0f1SSrinivas Kandagatla 
2749b4fe0f1SSrinivas Kandagatla 	ret = q6apm_graph_prepare(prtd->graph);
2759b4fe0f1SSrinivas Kandagatla 	if (ret) {
2769b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "Failed to prepare Graph %d\n", ret);
2779b4fe0f1SSrinivas Kandagatla 		return ret;
2789b4fe0f1SSrinivas Kandagatla 	}
2799b4fe0f1SSrinivas Kandagatla 
2809b4fe0f1SSrinivas Kandagatla 	ret = q6apm_graph_start(prtd->graph);
2819b4fe0f1SSrinivas Kandagatla 	if (ret) {
2829b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "Failed to Start Graph %d\n", ret);
2839b4fe0f1SSrinivas Kandagatla 		return ret;
2849b4fe0f1SSrinivas Kandagatla 	}
2859b4fe0f1SSrinivas Kandagatla 
2869b4fe0f1SSrinivas Kandagatla 	if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
2879b4fe0f1SSrinivas Kandagatla 		int i;
2889b4fe0f1SSrinivas Kandagatla 		/* Queue the buffers for Capture ONLY after graph is started */
2899b4fe0f1SSrinivas Kandagatla 		for (i = 0; i < runtime->periods; i++)
2909b4fe0f1SSrinivas Kandagatla 			q6apm_read(prtd->graph);
2919b4fe0f1SSrinivas Kandagatla 
2929b4fe0f1SSrinivas Kandagatla 	}
2939b4fe0f1SSrinivas Kandagatla 
2949b4fe0f1SSrinivas Kandagatla 	/* Now that graph as been prepared and started update the internal state accordingly */
2959b4fe0f1SSrinivas Kandagatla 	prtd->state = Q6APM_STREAM_RUNNING;
2969b4fe0f1SSrinivas Kandagatla 
2979b4fe0f1SSrinivas Kandagatla 	return 0;
2989b4fe0f1SSrinivas Kandagatla }
2999b4fe0f1SSrinivas Kandagatla 
q6apm_dai_trigger(struct snd_soc_component * component,struct snd_pcm_substream * substream,int cmd)3009b4fe0f1SSrinivas Kandagatla static int q6apm_dai_trigger(struct snd_soc_component *component,
3019b4fe0f1SSrinivas Kandagatla 			     struct snd_pcm_substream *substream, int cmd)
3029b4fe0f1SSrinivas Kandagatla {
3039b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
3049b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
3059b4fe0f1SSrinivas Kandagatla 	int ret = 0;
3069b4fe0f1SSrinivas Kandagatla 
3079b4fe0f1SSrinivas Kandagatla 	switch (cmd) {
3089b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_START:
3099b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_RESUME:
3109b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
3119b4fe0f1SSrinivas Kandagatla 		 /* start writing buffers for playback only as we already queued capture buffers */
3129b4fe0f1SSrinivas Kandagatla 		if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3139b4fe0f1SSrinivas Kandagatla 			ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, 0);
3149b4fe0f1SSrinivas Kandagatla 		break;
3159b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_STOP:
3169b4fe0f1SSrinivas Kandagatla 		/* TODO support be handled via SoftPause Module */
3179b4fe0f1SSrinivas Kandagatla 		prtd->state = Q6APM_STREAM_STOPPED;
3189b4fe0f1SSrinivas Kandagatla 		break;
3199b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_SUSPEND:
3209b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
3219b4fe0f1SSrinivas Kandagatla 		break;
3229b4fe0f1SSrinivas Kandagatla 	default:
3239b4fe0f1SSrinivas Kandagatla 		ret = -EINVAL;
3249b4fe0f1SSrinivas Kandagatla 		break;
3259b4fe0f1SSrinivas Kandagatla 	}
3269b4fe0f1SSrinivas Kandagatla 
3279b4fe0f1SSrinivas Kandagatla 	return ret;
3289b4fe0f1SSrinivas Kandagatla }
3299b4fe0f1SSrinivas Kandagatla 
q6apm_dai_open(struct snd_soc_component * component,struct snd_pcm_substream * substream)3309b4fe0f1SSrinivas Kandagatla static int q6apm_dai_open(struct snd_soc_component *component,
3319b4fe0f1SSrinivas Kandagatla 			  struct snd_pcm_substream *substream)
3329b4fe0f1SSrinivas Kandagatla {
3339b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
3349b4fe0f1SSrinivas Kandagatla 	struct snd_soc_pcm_runtime *soc_prtd = substream->private_data;
335*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0);
3369b4fe0f1SSrinivas Kandagatla 	struct device *dev = component->dev;
3379b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_data *pdata;
3389b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd;
3399b4fe0f1SSrinivas Kandagatla 	int graph_id, ret;
3409b4fe0f1SSrinivas Kandagatla 
3419b4fe0f1SSrinivas Kandagatla 	graph_id = cpu_dai->driver->id;
3429b4fe0f1SSrinivas Kandagatla 
3439b4fe0f1SSrinivas Kandagatla 	pdata = snd_soc_component_get_drvdata(component);
3449b4fe0f1SSrinivas Kandagatla 	if (!pdata) {
3459b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "Drv data not found ..\n");
3469b4fe0f1SSrinivas Kandagatla 		return -EINVAL;
3479b4fe0f1SSrinivas Kandagatla 	}
3489b4fe0f1SSrinivas Kandagatla 
3499b4fe0f1SSrinivas Kandagatla 	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
3509b4fe0f1SSrinivas Kandagatla 	if (prtd == NULL)
3519b4fe0f1SSrinivas Kandagatla 		return -ENOMEM;
3529b4fe0f1SSrinivas Kandagatla 
35384222ef5SSrinivas Kandagatla 	spin_lock_init(&prtd->lock);
3549b4fe0f1SSrinivas Kandagatla 	prtd->substream = substream;
3559b4fe0f1SSrinivas Kandagatla 	prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler, prtd, graph_id);
3569b4fe0f1SSrinivas Kandagatla 	if (IS_ERR(prtd->graph)) {
3579b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "%s: Could not allocate memory\n", __func__);
3589b4fe0f1SSrinivas Kandagatla 		ret = PTR_ERR(prtd->graph);
3599b4fe0f1SSrinivas Kandagatla 		goto err;
3609b4fe0f1SSrinivas Kandagatla 	}
3619b4fe0f1SSrinivas Kandagatla 
3629b4fe0f1SSrinivas Kandagatla 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK)
3639b4fe0f1SSrinivas Kandagatla 		runtime->hw = q6apm_dai_hardware_playback;
3649b4fe0f1SSrinivas Kandagatla 	else if (substream->stream == SNDRV_PCM_STREAM_CAPTURE)
3659b4fe0f1SSrinivas Kandagatla 		runtime->hw = q6apm_dai_hardware_capture;
3669b4fe0f1SSrinivas Kandagatla 
3679b4fe0f1SSrinivas Kandagatla 	/* Ensure that buffer size is a multiple of period size */
3689b4fe0f1SSrinivas Kandagatla 	ret = snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
3699b4fe0f1SSrinivas Kandagatla 	if (ret < 0) {
3709b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "snd_pcm_hw_constraint_integer failed\n");
3719b4fe0f1SSrinivas Kandagatla 		goto err;
3729b4fe0f1SSrinivas Kandagatla 	}
3739b4fe0f1SSrinivas Kandagatla 
3749b4fe0f1SSrinivas Kandagatla 	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
3759b4fe0f1SSrinivas Kandagatla 		ret = snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_BUFFER_BYTES,
3769b4fe0f1SSrinivas Kandagatla 						   BUFFER_BYTES_MIN, BUFFER_BYTES_MAX);
3779b4fe0f1SSrinivas Kandagatla 		if (ret < 0) {
3789b4fe0f1SSrinivas Kandagatla 			dev_err(dev, "constraint for buffer bytes min max ret = %d\n", ret);
3799b4fe0f1SSrinivas Kandagatla 			goto err;
3809b4fe0f1SSrinivas Kandagatla 		}
3819b4fe0f1SSrinivas Kandagatla 	}
3829b4fe0f1SSrinivas Kandagatla 
3839b4fe0f1SSrinivas Kandagatla 	ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_PERIOD_BYTES, 32);
3849b4fe0f1SSrinivas Kandagatla 	if (ret < 0) {
3859b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "constraint for period bytes step ret = %d\n", ret);
3869b4fe0f1SSrinivas Kandagatla 		goto err;
3879b4fe0f1SSrinivas Kandagatla 	}
3889b4fe0f1SSrinivas Kandagatla 
3899b4fe0f1SSrinivas Kandagatla 	ret = snd_pcm_hw_constraint_step(runtime, 0, SNDRV_PCM_HW_PARAM_BUFFER_BYTES, 32);
3909b4fe0f1SSrinivas Kandagatla 	if (ret < 0) {
3919b4fe0f1SSrinivas Kandagatla 		dev_err(dev, "constraint for buffer bytes step ret = %d\n", ret);
3929b4fe0f1SSrinivas Kandagatla 		goto err;
3939b4fe0f1SSrinivas Kandagatla 	}
3949b4fe0f1SSrinivas Kandagatla 
3959b4fe0f1SSrinivas Kandagatla 	runtime->private_data = prtd;
3969b4fe0f1SSrinivas Kandagatla 	runtime->dma_bytes = BUFFER_BYTES_MAX;
3979b4fe0f1SSrinivas Kandagatla 	if (pdata->sid < 0)
3989b4fe0f1SSrinivas Kandagatla 		prtd->phys = substream->dma_buffer.addr;
3999b4fe0f1SSrinivas Kandagatla 	else
4009b4fe0f1SSrinivas Kandagatla 		prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
4019b4fe0f1SSrinivas Kandagatla 
4029b4fe0f1SSrinivas Kandagatla 	return 0;
4039b4fe0f1SSrinivas Kandagatla err:
4049b4fe0f1SSrinivas Kandagatla 	kfree(prtd);
4059b4fe0f1SSrinivas Kandagatla 
4069b4fe0f1SSrinivas Kandagatla 	return ret;
4079b4fe0f1SSrinivas Kandagatla }
4089b4fe0f1SSrinivas Kandagatla 
q6apm_dai_close(struct snd_soc_component * component,struct snd_pcm_substream * substream)4099b4fe0f1SSrinivas Kandagatla static int q6apm_dai_close(struct snd_soc_component *component,
4109b4fe0f1SSrinivas Kandagatla 			   struct snd_pcm_substream *substream)
4119b4fe0f1SSrinivas Kandagatla {
4129b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
4139b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
4149b4fe0f1SSrinivas Kandagatla 
4158f2e5c65SSrinivas Kandagatla 	if (prtd->state) { /* only stop graph that is started */
4169b4fe0f1SSrinivas Kandagatla 		q6apm_graph_stop(prtd->graph);
4179b4fe0f1SSrinivas Kandagatla 		q6apm_unmap_memory_regions(prtd->graph, substream->stream);
4188f2e5c65SSrinivas Kandagatla 	}
4198f2e5c65SSrinivas Kandagatla 
4209b4fe0f1SSrinivas Kandagatla 	q6apm_graph_close(prtd->graph);
4219b4fe0f1SSrinivas Kandagatla 	prtd->graph = NULL;
4229b4fe0f1SSrinivas Kandagatla 	kfree(prtd);
4239b4fe0f1SSrinivas Kandagatla 	runtime->private_data = NULL;
4249b4fe0f1SSrinivas Kandagatla 
4259b4fe0f1SSrinivas Kandagatla 	return 0;
4269b4fe0f1SSrinivas Kandagatla }
4279b4fe0f1SSrinivas Kandagatla 
q6apm_dai_pointer(struct snd_soc_component * component,struct snd_pcm_substream * substream)4289b4fe0f1SSrinivas Kandagatla static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
4299b4fe0f1SSrinivas Kandagatla 					   struct snd_pcm_substream *substream)
4309b4fe0f1SSrinivas Kandagatla {
4319b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
4329b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
43384222ef5SSrinivas Kandagatla 	snd_pcm_uframes_t ptr;
43484222ef5SSrinivas Kandagatla 	unsigned long flags;
4359b4fe0f1SSrinivas Kandagatla 
43684222ef5SSrinivas Kandagatla 	spin_lock_irqsave(&prtd->lock, flags);
4379b4fe0f1SSrinivas Kandagatla 	if (prtd->pos == prtd->pcm_size)
4389b4fe0f1SSrinivas Kandagatla 		prtd->pos = 0;
4399b4fe0f1SSrinivas Kandagatla 
44084222ef5SSrinivas Kandagatla 	ptr =  bytes_to_frames(runtime, prtd->pos);
44184222ef5SSrinivas Kandagatla 	spin_unlock_irqrestore(&prtd->lock, flags);
44284222ef5SSrinivas Kandagatla 
44384222ef5SSrinivas Kandagatla 	return ptr;
4449b4fe0f1SSrinivas Kandagatla }
4459b4fe0f1SSrinivas Kandagatla 
q6apm_dai_hw_params(struct snd_soc_component * component,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params)4469b4fe0f1SSrinivas Kandagatla static int q6apm_dai_hw_params(struct snd_soc_component *component,
4479b4fe0f1SSrinivas Kandagatla 			       struct snd_pcm_substream *substream,
4489b4fe0f1SSrinivas Kandagatla 			       struct snd_pcm_hw_params *params)
4499b4fe0f1SSrinivas Kandagatla {
4509b4fe0f1SSrinivas Kandagatla 	struct snd_pcm_runtime *runtime = substream->runtime;
4519b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
4529b4fe0f1SSrinivas Kandagatla 
4539b4fe0f1SSrinivas Kandagatla 	prtd->pcm_size = params_buffer_bytes(params);
4549b4fe0f1SSrinivas Kandagatla 	prtd->periods = params_periods(params);
4559b4fe0f1SSrinivas Kandagatla 
4569b4fe0f1SSrinivas Kandagatla 	switch (params_format(params)) {
4579b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_FORMAT_S16_LE:
4589b4fe0f1SSrinivas Kandagatla 		prtd->bits_per_sample = 16;
4599b4fe0f1SSrinivas Kandagatla 		break;
4609b4fe0f1SSrinivas Kandagatla 	case SNDRV_PCM_FORMAT_S24_LE:
4619b4fe0f1SSrinivas Kandagatla 		prtd->bits_per_sample = 24;
4629b4fe0f1SSrinivas Kandagatla 		break;
4639b4fe0f1SSrinivas Kandagatla 	default:
4649b4fe0f1SSrinivas Kandagatla 		return -EINVAL;
4659b4fe0f1SSrinivas Kandagatla 	}
4669b4fe0f1SSrinivas Kandagatla 
4679b4fe0f1SSrinivas Kandagatla 	return 0;
4689b4fe0f1SSrinivas Kandagatla }
4699b4fe0f1SSrinivas Kandagatla 
q6apm_dai_pcm_new(struct snd_soc_component * component,struct snd_soc_pcm_runtime * rtd)4709b4fe0f1SSrinivas Kandagatla static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
4719b4fe0f1SSrinivas Kandagatla {
4729b4fe0f1SSrinivas Kandagatla 	int size = BUFFER_BYTES_MAX;
4739b4fe0f1SSrinivas Kandagatla 
4749b4fe0f1SSrinivas Kandagatla 	return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
4759b4fe0f1SSrinivas Kandagatla }
4769b4fe0f1SSrinivas Kandagatla 
q6apm_dai_compr_open(struct snd_soc_component * component,struct snd_compr_stream * stream)47788b60bf0SSrinivas Kandagatla static int q6apm_dai_compr_open(struct snd_soc_component *component,
47888b60bf0SSrinivas Kandagatla 				struct snd_compr_stream *stream)
47988b60bf0SSrinivas Kandagatla {
48088b60bf0SSrinivas Kandagatla 	struct snd_soc_pcm_runtime *rtd = stream->private_data;
481*841361d8SKuninori Morimoto 	struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
48288b60bf0SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
48388b60bf0SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd;
48488b60bf0SSrinivas Kandagatla 	struct q6apm_dai_data *pdata;
48588b60bf0SSrinivas Kandagatla 	struct device *dev = component->dev;
48688b60bf0SSrinivas Kandagatla 	int ret, size;
48788b60bf0SSrinivas Kandagatla 	int graph_id;
48888b60bf0SSrinivas Kandagatla 
48988b60bf0SSrinivas Kandagatla 	graph_id = cpu_dai->driver->id;
49088b60bf0SSrinivas Kandagatla 	pdata = snd_soc_component_get_drvdata(component);
49188b60bf0SSrinivas Kandagatla 	if (!pdata)
49288b60bf0SSrinivas Kandagatla 		return -EINVAL;
49388b60bf0SSrinivas Kandagatla 
49488b60bf0SSrinivas Kandagatla 	prtd = kzalloc(sizeof(*prtd), GFP_KERNEL);
49588b60bf0SSrinivas Kandagatla 	if (prtd == NULL)
49688b60bf0SSrinivas Kandagatla 		return -ENOMEM;
49788b60bf0SSrinivas Kandagatla 
49888b60bf0SSrinivas Kandagatla 	prtd->cstream = stream;
49988b60bf0SSrinivas Kandagatla 	prtd->graph = q6apm_graph_open(dev, (q6apm_cb)event_handler_compr, prtd, graph_id);
50088b60bf0SSrinivas Kandagatla 	if (IS_ERR(prtd->graph)) {
50188b60bf0SSrinivas Kandagatla 		ret = PTR_ERR(prtd->graph);
50288b60bf0SSrinivas Kandagatla 		kfree(prtd);
50388b60bf0SSrinivas Kandagatla 		return ret;
50488b60bf0SSrinivas Kandagatla 	}
50588b60bf0SSrinivas Kandagatla 
50688b60bf0SSrinivas Kandagatla 	runtime->private_data = prtd;
50788b60bf0SSrinivas Kandagatla 	runtime->dma_bytes = BUFFER_BYTES_MAX;
50888b60bf0SSrinivas Kandagatla 	size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE * COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
50988b60bf0SSrinivas Kandagatla 	ret = snd_dma_alloc_pages(SNDRV_DMA_TYPE_DEV, dev, size, &prtd->dma_buffer);
51088b60bf0SSrinivas Kandagatla 	if (ret)
51188b60bf0SSrinivas Kandagatla 		return ret;
51288b60bf0SSrinivas Kandagatla 
51388b60bf0SSrinivas Kandagatla 	if (pdata->sid < 0)
51488b60bf0SSrinivas Kandagatla 		prtd->phys = prtd->dma_buffer.addr;
51588b60bf0SSrinivas Kandagatla 	else
51688b60bf0SSrinivas Kandagatla 		prtd->phys = prtd->dma_buffer.addr | (pdata->sid << 32);
51788b60bf0SSrinivas Kandagatla 
51888b60bf0SSrinivas Kandagatla 	snd_compr_set_runtime_buffer(stream, &prtd->dma_buffer);
51988b60bf0SSrinivas Kandagatla 	spin_lock_init(&prtd->lock);
52088b60bf0SSrinivas Kandagatla 
52188b60bf0SSrinivas Kandagatla 	q6apm_enable_compress_module(dev, prtd->graph, true);
52288b60bf0SSrinivas Kandagatla 	return 0;
52388b60bf0SSrinivas Kandagatla }
52488b60bf0SSrinivas Kandagatla 
q6apm_dai_compr_free(struct snd_soc_component * component,struct snd_compr_stream * stream)52588b60bf0SSrinivas Kandagatla static int q6apm_dai_compr_free(struct snd_soc_component *component,
52688b60bf0SSrinivas Kandagatla 				struct snd_compr_stream *stream)
52788b60bf0SSrinivas Kandagatla {
52888b60bf0SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
52988b60bf0SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
53088b60bf0SSrinivas Kandagatla 
53188b60bf0SSrinivas Kandagatla 	q6apm_graph_stop(prtd->graph);
53288b60bf0SSrinivas Kandagatla 	q6apm_unmap_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK);
53388b60bf0SSrinivas Kandagatla 	q6apm_graph_close(prtd->graph);
53488b60bf0SSrinivas Kandagatla 	snd_dma_free_pages(&prtd->dma_buffer);
53588b60bf0SSrinivas Kandagatla 	prtd->graph = NULL;
53688b60bf0SSrinivas Kandagatla 	kfree(prtd);
53788b60bf0SSrinivas Kandagatla 	runtime->private_data = NULL;
53888b60bf0SSrinivas Kandagatla 
53988b60bf0SSrinivas Kandagatla 	return 0;
54088b60bf0SSrinivas Kandagatla }
541c0c87738SSrinivas Kandagatla 
q6apm_dai_compr_get_caps(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_caps * caps)542c0c87738SSrinivas Kandagatla static int q6apm_dai_compr_get_caps(struct snd_soc_component *component,
543c0c87738SSrinivas Kandagatla 				    struct snd_compr_stream *stream,
544c0c87738SSrinivas Kandagatla 				    struct snd_compr_caps *caps)
545c0c87738SSrinivas Kandagatla {
546c0c87738SSrinivas Kandagatla 	caps->direction = SND_COMPRESS_PLAYBACK;
547c0c87738SSrinivas Kandagatla 	caps->min_fragment_size = COMPR_PLAYBACK_MIN_FRAGMENT_SIZE;
548c0c87738SSrinivas Kandagatla 	caps->max_fragment_size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE;
549c0c87738SSrinivas Kandagatla 	caps->min_fragments = COMPR_PLAYBACK_MIN_NUM_FRAGMENTS;
550c0c87738SSrinivas Kandagatla 	caps->max_fragments = COMPR_PLAYBACK_MAX_NUM_FRAGMENTS;
551c0c87738SSrinivas Kandagatla 	caps->num_codecs = 3;
552c0c87738SSrinivas Kandagatla 	caps->codecs[0] = SND_AUDIOCODEC_MP3;
553c0c87738SSrinivas Kandagatla 	caps->codecs[1] = SND_AUDIOCODEC_AAC;
554c0c87738SSrinivas Kandagatla 	caps->codecs[2] = SND_AUDIOCODEC_FLAC;
555c0c87738SSrinivas Kandagatla 
556c0c87738SSrinivas Kandagatla 	return 0;
557c0c87738SSrinivas Kandagatla }
558c0c87738SSrinivas Kandagatla 
q6apm_dai_compr_get_codec_caps(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_codec_caps * codec)559c0c87738SSrinivas Kandagatla static int q6apm_dai_compr_get_codec_caps(struct snd_soc_component *component,
560c0c87738SSrinivas Kandagatla 					  struct snd_compr_stream *stream,
561c0c87738SSrinivas Kandagatla 					  struct snd_compr_codec_caps *codec)
562c0c87738SSrinivas Kandagatla {
563c0c87738SSrinivas Kandagatla 	switch (codec->codec) {
564c0c87738SSrinivas Kandagatla 	case SND_AUDIOCODEC_MP3:
565c0c87738SSrinivas Kandagatla 		*codec = q6apm_compr_caps;
566c0c87738SSrinivas Kandagatla 		break;
567c0c87738SSrinivas Kandagatla 	default:
568c0c87738SSrinivas Kandagatla 		break;
569c0c87738SSrinivas Kandagatla 	}
570c0c87738SSrinivas Kandagatla 
571c0c87738SSrinivas Kandagatla 	return 0;
572c0c87738SSrinivas Kandagatla }
573c337bf33SSrinivas Kandagatla 
q6apm_dai_compr_pointer(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_tstamp * tstamp)574c337bf33SSrinivas Kandagatla static int q6apm_dai_compr_pointer(struct snd_soc_component *component,
575c337bf33SSrinivas Kandagatla 				   struct snd_compr_stream *stream,
576c337bf33SSrinivas Kandagatla 				   struct snd_compr_tstamp *tstamp)
577c337bf33SSrinivas Kandagatla {
578c337bf33SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
579c337bf33SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
580c337bf33SSrinivas Kandagatla 	unsigned long flags;
581c337bf33SSrinivas Kandagatla 
582c337bf33SSrinivas Kandagatla 	spin_lock_irqsave(&prtd->lock, flags);
583c337bf33SSrinivas Kandagatla 	tstamp->copied_total = prtd->copied_total;
584c337bf33SSrinivas Kandagatla 	tstamp->byte_offset = prtd->copied_total % prtd->pcm_size;
585c337bf33SSrinivas Kandagatla 	spin_unlock_irqrestore(&prtd->lock, flags);
586c337bf33SSrinivas Kandagatla 
587c337bf33SSrinivas Kandagatla 	return 0;
588c337bf33SSrinivas Kandagatla }
589c337bf33SSrinivas Kandagatla 
q6apm_dai_compr_trigger(struct snd_soc_component * component,struct snd_compr_stream * stream,int cmd)590c337bf33SSrinivas Kandagatla static int q6apm_dai_compr_trigger(struct snd_soc_component *component,
591c337bf33SSrinivas Kandagatla 			    struct snd_compr_stream *stream, int cmd)
592c337bf33SSrinivas Kandagatla {
593c337bf33SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
594c337bf33SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
595c337bf33SSrinivas Kandagatla 	int ret = 0;
596c337bf33SSrinivas Kandagatla 
597c337bf33SSrinivas Kandagatla 	switch (cmd) {
598c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_START:
599c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_RESUME:
600c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
601c337bf33SSrinivas Kandagatla 		ret = q6apm_write_async(prtd->graph, prtd->pcm_count, 0, 0, NO_TIMESTAMP);
602c337bf33SSrinivas Kandagatla 		break;
603c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_STOP:
604c337bf33SSrinivas Kandagatla 		break;
605c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_SUSPEND:
606c337bf33SSrinivas Kandagatla 	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
607c337bf33SSrinivas Kandagatla 		break;
608c337bf33SSrinivas Kandagatla 	case SND_COMPR_TRIGGER_NEXT_TRACK:
609c337bf33SSrinivas Kandagatla 		prtd->next_track = true;
610c337bf33SSrinivas Kandagatla 		break;
611c337bf33SSrinivas Kandagatla 	case SND_COMPR_TRIGGER_DRAIN:
612c337bf33SSrinivas Kandagatla 	case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
613c337bf33SSrinivas Kandagatla 		prtd->notify_on_drain = true;
614c337bf33SSrinivas Kandagatla 		break;
615c337bf33SSrinivas Kandagatla 	default:
616c337bf33SSrinivas Kandagatla 		ret = -EINVAL;
617c337bf33SSrinivas Kandagatla 		break;
618c337bf33SSrinivas Kandagatla 	}
619c337bf33SSrinivas Kandagatla 
620c337bf33SSrinivas Kandagatla 	return ret;
621c337bf33SSrinivas Kandagatla }
622c337bf33SSrinivas Kandagatla 
q6apm_dai_compr_ack(struct snd_soc_component * component,struct snd_compr_stream * stream,size_t count)623c337bf33SSrinivas Kandagatla static int q6apm_dai_compr_ack(struct snd_soc_component *component, struct snd_compr_stream *stream,
624c337bf33SSrinivas Kandagatla 			size_t count)
625c337bf33SSrinivas Kandagatla {
626c337bf33SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
627c337bf33SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
628c337bf33SSrinivas Kandagatla 	unsigned long flags;
629c337bf33SSrinivas Kandagatla 
630c337bf33SSrinivas Kandagatla 	spin_lock_irqsave(&prtd->lock, flags);
631c337bf33SSrinivas Kandagatla 	prtd->bytes_received += count;
632c337bf33SSrinivas Kandagatla 	spin_unlock_irqrestore(&prtd->lock, flags);
633c337bf33SSrinivas Kandagatla 
634c337bf33SSrinivas Kandagatla 	return count;
635c337bf33SSrinivas Kandagatla }
636c337bf33SSrinivas Kandagatla 
q6apm_dai_compr_set_params(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_params * params)637b3f736d1SSrinivas Kandagatla static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
638b3f736d1SSrinivas Kandagatla 				      struct snd_compr_stream *stream,
639b3f736d1SSrinivas Kandagatla 				      struct snd_compr_params *params)
640b3f736d1SSrinivas Kandagatla {
641b3f736d1SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
642b3f736d1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
643b3f736d1SSrinivas Kandagatla 	struct q6apm_dai_data *pdata;
644b3f736d1SSrinivas Kandagatla 	struct audioreach_module_config cfg;
645b3f736d1SSrinivas Kandagatla 	struct snd_codec *codec = &params->codec;
646b3f736d1SSrinivas Kandagatla 	int dir = stream->direction;
647b3f736d1SSrinivas Kandagatla 	int ret;
648b3f736d1SSrinivas Kandagatla 
649b3f736d1SSrinivas Kandagatla 	pdata = snd_soc_component_get_drvdata(component);
650b3f736d1SSrinivas Kandagatla 	if (!pdata)
651b3f736d1SSrinivas Kandagatla 		return -EINVAL;
652b3f736d1SSrinivas Kandagatla 
653b3f736d1SSrinivas Kandagatla 	prtd->periods = runtime->fragments;
654b3f736d1SSrinivas Kandagatla 	prtd->pcm_count = runtime->fragment_size;
655b3f736d1SSrinivas Kandagatla 	prtd->pcm_size = runtime->fragments * runtime->fragment_size;
656b3f736d1SSrinivas Kandagatla 	prtd->bits_per_sample = 16;
657b3f736d1SSrinivas Kandagatla 
658b3f736d1SSrinivas Kandagatla 	prtd->pos = 0;
659b3f736d1SSrinivas Kandagatla 
660b3f736d1SSrinivas Kandagatla 	if (prtd->next_track != true) {
661b3f736d1SSrinivas Kandagatla 		memcpy(&prtd->codec, codec, sizeof(*codec));
662b3f736d1SSrinivas Kandagatla 
663b3f736d1SSrinivas Kandagatla 		ret = q6apm_set_real_module_id(component->dev, prtd->graph, codec->id);
664b3f736d1SSrinivas Kandagatla 		if (ret)
665b3f736d1SSrinivas Kandagatla 			return ret;
666b3f736d1SSrinivas Kandagatla 
667b3f736d1SSrinivas Kandagatla 		cfg.direction = dir;
668b3f736d1SSrinivas Kandagatla 		cfg.sample_rate = codec->sample_rate;
669b3f736d1SSrinivas Kandagatla 		cfg.num_channels = 2;
670b3f736d1SSrinivas Kandagatla 		cfg.bit_width = prtd->bits_per_sample;
671b3f736d1SSrinivas Kandagatla 		cfg.fmt = codec->id;
672b3f736d1SSrinivas Kandagatla 		memcpy(&cfg.codec, codec, sizeof(*codec));
673b3f736d1SSrinivas Kandagatla 
674b3f736d1SSrinivas Kandagatla 		ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
675b3f736d1SSrinivas Kandagatla 		if (ret < 0)
676b3f736d1SSrinivas Kandagatla 			return ret;
677b3f736d1SSrinivas Kandagatla 
678b3f736d1SSrinivas Kandagatla 		ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg);
679b3f736d1SSrinivas Kandagatla 		if (ret)
680b3f736d1SSrinivas Kandagatla 			return ret;
681b3f736d1SSrinivas Kandagatla 
682b3f736d1SSrinivas Kandagatla 		ret = q6apm_map_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
683b3f736d1SSrinivas Kandagatla 					       prtd->phys, (prtd->pcm_size / prtd->periods),
684b3f736d1SSrinivas Kandagatla 					       prtd->periods);
685b3f736d1SSrinivas Kandagatla 		if (ret < 0)
686b3f736d1SSrinivas Kandagatla 			return -ENOMEM;
687b3f736d1SSrinivas Kandagatla 
688b3f736d1SSrinivas Kandagatla 		ret = q6apm_graph_prepare(prtd->graph);
689b3f736d1SSrinivas Kandagatla 		if (ret)
690b3f736d1SSrinivas Kandagatla 			return ret;
691b3f736d1SSrinivas Kandagatla 
692b3f736d1SSrinivas Kandagatla 		ret = q6apm_graph_start(prtd->graph);
693b3f736d1SSrinivas Kandagatla 		if (ret)
694b3f736d1SSrinivas Kandagatla 			return ret;
695b3f736d1SSrinivas Kandagatla 
696b3f736d1SSrinivas Kandagatla 	} else {
697b3f736d1SSrinivas Kandagatla 		cfg.direction = dir;
698b3f736d1SSrinivas Kandagatla 		cfg.sample_rate = codec->sample_rate;
699b3f736d1SSrinivas Kandagatla 		cfg.num_channels = 2;
700b3f736d1SSrinivas Kandagatla 		cfg.bit_width = prtd->bits_per_sample;
701b3f736d1SSrinivas Kandagatla 		cfg.fmt = codec->id;
702b3f736d1SSrinivas Kandagatla 		memcpy(&cfg.codec, codec, sizeof(*codec));
703b3f736d1SSrinivas Kandagatla 
704b3f736d1SSrinivas Kandagatla 		ret = audioreach_compr_set_param(prtd->graph,  &cfg);
705b3f736d1SSrinivas Kandagatla 		if (ret < 0)
706b3f736d1SSrinivas Kandagatla 			return ret;
707b3f736d1SSrinivas Kandagatla 	}
708b3f736d1SSrinivas Kandagatla 	prtd->state = Q6APM_STREAM_RUNNING;
709b3f736d1SSrinivas Kandagatla 
710b3f736d1SSrinivas Kandagatla 	return 0;
711b3f736d1SSrinivas Kandagatla }
712b3f736d1SSrinivas Kandagatla 
q6apm_dai_compr_set_metadata(struct snd_soc_component * component,struct snd_compr_stream * stream,struct snd_compr_metadata * metadata)713b3f736d1SSrinivas Kandagatla static int q6apm_dai_compr_set_metadata(struct snd_soc_component *component,
714b3f736d1SSrinivas Kandagatla 					struct snd_compr_stream *stream,
715b3f736d1SSrinivas Kandagatla 					struct snd_compr_metadata *metadata)
716b3f736d1SSrinivas Kandagatla {
717b3f736d1SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
718b3f736d1SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
719b3f736d1SSrinivas Kandagatla 	int ret = 0;
720b3f736d1SSrinivas Kandagatla 
721b3f736d1SSrinivas Kandagatla 	switch (metadata->key) {
722b3f736d1SSrinivas Kandagatla 	case SNDRV_COMPRESS_ENCODER_PADDING:
723b3f736d1SSrinivas Kandagatla 		prtd->trailing_samples_drop = metadata->value[0];
724b3f736d1SSrinivas Kandagatla 		q6apm_remove_trailing_silence(component->dev, prtd->graph,
725b3f736d1SSrinivas Kandagatla 					      prtd->trailing_samples_drop);
726b3f736d1SSrinivas Kandagatla 		break;
727b3f736d1SSrinivas Kandagatla 	case SNDRV_COMPRESS_ENCODER_DELAY:
728b3f736d1SSrinivas Kandagatla 		prtd->initial_samples_drop = metadata->value[0];
729b3f736d1SSrinivas Kandagatla 		q6apm_remove_initial_silence(component->dev, prtd->graph,
730b3f736d1SSrinivas Kandagatla 					     prtd->initial_samples_drop);
731b3f736d1SSrinivas Kandagatla 		break;
732b3f736d1SSrinivas Kandagatla 	default:
733b3f736d1SSrinivas Kandagatla 		ret = -EINVAL;
734b3f736d1SSrinivas Kandagatla 		break;
735b3f736d1SSrinivas Kandagatla 	}
736b3f736d1SSrinivas Kandagatla 
737b3f736d1SSrinivas Kandagatla 	return ret;
738b3f736d1SSrinivas Kandagatla }
739b3f736d1SSrinivas Kandagatla 
q6apm_dai_compr_mmap(struct snd_soc_component * component,struct snd_compr_stream * stream,struct vm_area_struct * vma)740c317d148SSrinivas Kandagatla static int q6apm_dai_compr_mmap(struct snd_soc_component *component,
741c317d148SSrinivas Kandagatla 				struct snd_compr_stream *stream,
742c317d148SSrinivas Kandagatla 				struct vm_area_struct *vma)
743c317d148SSrinivas Kandagatla {
744c317d148SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
745c317d148SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
746c317d148SSrinivas Kandagatla 	struct device *dev = component->dev;
747c317d148SSrinivas Kandagatla 
748c317d148SSrinivas Kandagatla 	return dma_mmap_coherent(dev, vma, prtd->dma_buffer.area, prtd->dma_buffer.addr,
749c317d148SSrinivas Kandagatla 				 prtd->dma_buffer.bytes);
750c317d148SSrinivas Kandagatla }
751c317d148SSrinivas Kandagatla 
q6apm_compr_copy(struct snd_soc_component * component,struct snd_compr_stream * stream,char __user * buf,size_t count)752c317d148SSrinivas Kandagatla static int q6apm_compr_copy(struct snd_soc_component *component,
753c317d148SSrinivas Kandagatla 			    struct snd_compr_stream *stream, char __user *buf,
754c317d148SSrinivas Kandagatla 			    size_t count)
755c317d148SSrinivas Kandagatla {
756c317d148SSrinivas Kandagatla 	struct snd_compr_runtime *runtime = stream->runtime;
757c317d148SSrinivas Kandagatla 	struct q6apm_dai_rtd *prtd = runtime->private_data;
758c317d148SSrinivas Kandagatla 	void *dstn;
759c317d148SSrinivas Kandagatla 	unsigned long flags;
760c317d148SSrinivas Kandagatla 	size_t copy;
761c317d148SSrinivas Kandagatla 	u32 wflags = 0;
762c317d148SSrinivas Kandagatla 	u32 app_pointer;
763c317d148SSrinivas Kandagatla 	u32 bytes_received;
764c317d148SSrinivas Kandagatla 	uint32_t bytes_to_write;
765c317d148SSrinivas Kandagatla 	int avail, bytes_in_flight = 0;
766c317d148SSrinivas Kandagatla 
767c317d148SSrinivas Kandagatla 	bytes_received = prtd->bytes_received;
768c317d148SSrinivas Kandagatla 
769c317d148SSrinivas Kandagatla 	/**
770c317d148SSrinivas Kandagatla 	 * Make sure that next track data pointer is aligned at 32 bit boundary
771c317d148SSrinivas Kandagatla 	 * This is a Mandatory requirement from DSP data buffers alignment
772c317d148SSrinivas Kandagatla 	 */
773c317d148SSrinivas Kandagatla 	if (prtd->next_track)
774c317d148SSrinivas Kandagatla 		bytes_received = ALIGN(prtd->bytes_received, prtd->pcm_count);
775c317d148SSrinivas Kandagatla 
776c317d148SSrinivas Kandagatla 	app_pointer = bytes_received/prtd->pcm_size;
777c317d148SSrinivas Kandagatla 	app_pointer = bytes_received -  (app_pointer * prtd->pcm_size);
778c317d148SSrinivas Kandagatla 	dstn = prtd->dma_buffer.area + app_pointer;
779c317d148SSrinivas Kandagatla 
780c317d148SSrinivas Kandagatla 	if (count < prtd->pcm_size - app_pointer) {
781c317d148SSrinivas Kandagatla 		if (copy_from_user(dstn, buf, count))
782c317d148SSrinivas Kandagatla 			return -EFAULT;
783c317d148SSrinivas Kandagatla 	} else {
784c317d148SSrinivas Kandagatla 		copy = prtd->pcm_size - app_pointer;
785c317d148SSrinivas Kandagatla 		if (copy_from_user(dstn, buf, copy))
786c317d148SSrinivas Kandagatla 			return -EFAULT;
787c317d148SSrinivas Kandagatla 		if (copy_from_user(prtd->dma_buffer.area, buf + copy, count - copy))
788c317d148SSrinivas Kandagatla 			return -EFAULT;
789c317d148SSrinivas Kandagatla 	}
790c317d148SSrinivas Kandagatla 
791c317d148SSrinivas Kandagatla 	spin_lock_irqsave(&prtd->lock, flags);
792c317d148SSrinivas Kandagatla 	bytes_in_flight = prtd->bytes_received - prtd->copied_total;
793c317d148SSrinivas Kandagatla 
794c317d148SSrinivas Kandagatla 	if (prtd->next_track) {
795c317d148SSrinivas Kandagatla 		prtd->next_track = false;
796c317d148SSrinivas Kandagatla 		prtd->copied_total = ALIGN(prtd->copied_total, prtd->pcm_count);
797c317d148SSrinivas Kandagatla 		prtd->bytes_sent = ALIGN(prtd->bytes_sent, prtd->pcm_count);
798c317d148SSrinivas Kandagatla 	}
799c317d148SSrinivas Kandagatla 
800c317d148SSrinivas Kandagatla 	prtd->bytes_received = bytes_received + count;
801c317d148SSrinivas Kandagatla 
802c317d148SSrinivas Kandagatla 	/* Kick off the data to dsp if its starving!! */
803c317d148SSrinivas Kandagatla 	if (prtd->state == Q6APM_STREAM_RUNNING && (bytes_in_flight == 0)) {
804c317d148SSrinivas Kandagatla 		bytes_to_write = prtd->pcm_count;
805c317d148SSrinivas Kandagatla 		avail = prtd->bytes_received - prtd->bytes_sent;
806c317d148SSrinivas Kandagatla 
807c317d148SSrinivas Kandagatla 		if (avail < prtd->pcm_count)
808c317d148SSrinivas Kandagatla 			bytes_to_write = avail;
809c317d148SSrinivas Kandagatla 
810c317d148SSrinivas Kandagatla 		q6apm_write_async(prtd->graph, bytes_to_write, 0, 0, wflags);
811c317d148SSrinivas Kandagatla 		prtd->bytes_sent += bytes_to_write;
812c317d148SSrinivas Kandagatla 	}
813c317d148SSrinivas Kandagatla 
814c317d148SSrinivas Kandagatla 	spin_unlock_irqrestore(&prtd->lock, flags);
815c317d148SSrinivas Kandagatla 
816c317d148SSrinivas Kandagatla 	return count;
817c317d148SSrinivas Kandagatla }
818c317d148SSrinivas Kandagatla 
81988b60bf0SSrinivas Kandagatla static const struct snd_compress_ops q6apm_dai_compress_ops = {
82088b60bf0SSrinivas Kandagatla 	.open		= q6apm_dai_compr_open,
82188b60bf0SSrinivas Kandagatla 	.free		= q6apm_dai_compr_free,
822c0c87738SSrinivas Kandagatla 	.get_caps	= q6apm_dai_compr_get_caps,
823c0c87738SSrinivas Kandagatla 	.get_codec_caps	= q6apm_dai_compr_get_codec_caps,
824c337bf33SSrinivas Kandagatla 	.pointer	= q6apm_dai_compr_pointer,
825c337bf33SSrinivas Kandagatla 	.trigger	= q6apm_dai_compr_trigger,
826c337bf33SSrinivas Kandagatla 	.ack		= q6apm_dai_compr_ack,
827b3f736d1SSrinivas Kandagatla 	.set_params	= q6apm_dai_compr_set_params,
828b3f736d1SSrinivas Kandagatla 	.set_metadata	= q6apm_dai_compr_set_metadata,
829c317d148SSrinivas Kandagatla 	.mmap		= q6apm_dai_compr_mmap,
830c317d148SSrinivas Kandagatla 	.copy		= q6apm_compr_copy,
83188b60bf0SSrinivas Kandagatla };
83288b60bf0SSrinivas Kandagatla 
8339b4fe0f1SSrinivas Kandagatla static const struct snd_soc_component_driver q6apm_fe_dai_component = {
8349b4fe0f1SSrinivas Kandagatla 	.name		= DRV_NAME,
8359b4fe0f1SSrinivas Kandagatla 	.open		= q6apm_dai_open,
8369b4fe0f1SSrinivas Kandagatla 	.close		= q6apm_dai_close,
8379b4fe0f1SSrinivas Kandagatla 	.prepare	= q6apm_dai_prepare,
8389b4fe0f1SSrinivas Kandagatla 	.pcm_construct	= q6apm_dai_pcm_new,
8399b4fe0f1SSrinivas Kandagatla 	.hw_params	= q6apm_dai_hw_params,
8409b4fe0f1SSrinivas Kandagatla 	.pointer	= q6apm_dai_pointer,
8419b4fe0f1SSrinivas Kandagatla 	.trigger	= q6apm_dai_trigger,
84288b60bf0SSrinivas Kandagatla 	.compress_ops	= &q6apm_dai_compress_ops,
843ac192c1aSSrinivas Kandagatla 	.use_dai_pcm_id = true,
8449b4fe0f1SSrinivas Kandagatla };
8459b4fe0f1SSrinivas Kandagatla 
q6apm_dai_probe(struct platform_device * pdev)8469b4fe0f1SSrinivas Kandagatla static int q6apm_dai_probe(struct platform_device *pdev)
8479b4fe0f1SSrinivas Kandagatla {
8489b4fe0f1SSrinivas Kandagatla 	struct device *dev = &pdev->dev;
8499b4fe0f1SSrinivas Kandagatla 	struct device_node *node = dev->of_node;
8509b4fe0f1SSrinivas Kandagatla 	struct q6apm_dai_data *pdata;
8519b4fe0f1SSrinivas Kandagatla 	struct of_phandle_args args;
8529b4fe0f1SSrinivas Kandagatla 	int rc;
8539b4fe0f1SSrinivas Kandagatla 
8549b4fe0f1SSrinivas Kandagatla 	pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
8559b4fe0f1SSrinivas Kandagatla 	if (!pdata)
8569b4fe0f1SSrinivas Kandagatla 		return -ENOMEM;
8579b4fe0f1SSrinivas Kandagatla 
8589b4fe0f1SSrinivas Kandagatla 	rc = of_parse_phandle_with_fixed_args(node, "iommus", 1, 0, &args);
8599b4fe0f1SSrinivas Kandagatla 	if (rc < 0)
8609b4fe0f1SSrinivas Kandagatla 		pdata->sid = -1;
8619b4fe0f1SSrinivas Kandagatla 	else
8629b4fe0f1SSrinivas Kandagatla 		pdata->sid = args.args[0] & SID_MASK_DEFAULT;
8639b4fe0f1SSrinivas Kandagatla 
8649b4fe0f1SSrinivas Kandagatla 	dev_set_drvdata(dev, pdata);
8659b4fe0f1SSrinivas Kandagatla 
8669b4fe0f1SSrinivas Kandagatla 	return devm_snd_soc_register_component(dev, &q6apm_fe_dai_component, NULL, 0);
8679b4fe0f1SSrinivas Kandagatla }
8689b4fe0f1SSrinivas Kandagatla 
8699b4fe0f1SSrinivas Kandagatla #ifdef CONFIG_OF
8709b4fe0f1SSrinivas Kandagatla static const struct of_device_id q6apm_dai_device_id[] = {
8719b4fe0f1SSrinivas Kandagatla 	{ .compatible = "qcom,q6apm-dais" },
8729b4fe0f1SSrinivas Kandagatla 	{},
8739b4fe0f1SSrinivas Kandagatla };
8749b4fe0f1SSrinivas Kandagatla MODULE_DEVICE_TABLE(of, q6apm_dai_device_id);
8759b4fe0f1SSrinivas Kandagatla #endif
8769b4fe0f1SSrinivas Kandagatla 
8779b4fe0f1SSrinivas Kandagatla static struct platform_driver q6apm_dai_platform_driver = {
8789b4fe0f1SSrinivas Kandagatla 	.driver = {
8799b4fe0f1SSrinivas Kandagatla 		.name = "q6apm-dai",
8809b4fe0f1SSrinivas Kandagatla 		.of_match_table = of_match_ptr(q6apm_dai_device_id),
8819b4fe0f1SSrinivas Kandagatla 	},
8829b4fe0f1SSrinivas Kandagatla 	.probe = q6apm_dai_probe,
8839b4fe0f1SSrinivas Kandagatla };
8849b4fe0f1SSrinivas Kandagatla module_platform_driver(q6apm_dai_platform_driver);
8859b4fe0f1SSrinivas Kandagatla 
8869b4fe0f1SSrinivas Kandagatla MODULE_DESCRIPTION("Q6APM dai driver");
8879b4fe0f1SSrinivas Kandagatla MODULE_LICENSE("GPL");
888