Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.13.7.
  1/*
  2 *  sst_mfld_platform.c - Intel MID Platform driver
  3 *
  4 *  Copyright (C) 2010-2013 Intel Corp
  5 *  Author: Vinod Koul <vinod.koul@intel.com>
  6 *  Author: Harsha Priya <priya.harsha@intel.com>
  7 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8 *
  9 *  This program is free software; you can redistribute it and/or modify
 10 *  it under the terms of the GNU General Public License as published by
 11 *  the Free Software Foundation; version 2 of the License.
 12 *
 13 *  This program is distributed in the hope that it will be useful, but
 14 *  WITHOUT ANY WARRANTY; without even the implied warranty of
 15 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 16 *  General Public License for more details.
 17 *
 18 *  You should have received a copy of the GNU General Public License along
 19 *  with this program; if not, write to the Free Software Foundation, Inc.,
 20 *  59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
 21 *
 22 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 23 *
 24 *
 25 */
 26#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 27
 28#include <linux/slab.h>
 29#include <linux/io.h>
 30#include <linux/module.h>
 31#include <sound/core.h>
 32#include <sound/pcm.h>
 33#include <sound/pcm_params.h>
 34#include <sound/soc.h>
 35#include <sound/compress_driver.h>
 36#include "sst-mfld-platform.h"
 37
 38static struct sst_device *sst;
 39static DEFINE_MUTEX(sst_lock);
 40
 41int sst_register_dsp(struct sst_device *dev)
 42{
 43	if (WARN_ON(!dev))
 44		return -EINVAL;
 45	if (!try_module_get(dev->dev->driver->owner))
 46		return -ENODEV;
 47	mutex_lock(&sst_lock);
 48	if (sst) {
 49		pr_err("we already have a device %s\n", sst->name);
 50		module_put(dev->dev->driver->owner);
 51		mutex_unlock(&sst_lock);
 52		return -EEXIST;
 53	}
 54	pr_debug("registering device %s\n", dev->name);
 55	sst = dev;
 56	mutex_unlock(&sst_lock);
 57	return 0;
 58}
 59EXPORT_SYMBOL_GPL(sst_register_dsp);
 60
 61int sst_unregister_dsp(struct sst_device *dev)
 62{
 63	if (WARN_ON(!dev))
 64		return -EINVAL;
 65	if (dev != sst)
 66		return -EINVAL;
 67
 68	mutex_lock(&sst_lock);
 69
 70	if (!sst) {
 71		mutex_unlock(&sst_lock);
 72		return -EIO;
 73	}
 74
 75	module_put(sst->dev->driver->owner);
 76	pr_debug("unreg %s\n", sst->name);
 77	sst = NULL;
 78	mutex_unlock(&sst_lock);
 79	return 0;
 80}
 81EXPORT_SYMBOL_GPL(sst_unregister_dsp);
 82
 83static struct snd_pcm_hardware sst_platform_pcm_hw = {
 84	.info =	(SNDRV_PCM_INFO_INTERLEAVED |
 85			SNDRV_PCM_INFO_DOUBLE |
 86			SNDRV_PCM_INFO_PAUSE |
 87			SNDRV_PCM_INFO_RESUME |
 88			SNDRV_PCM_INFO_MMAP|
 89			SNDRV_PCM_INFO_MMAP_VALID |
 90			SNDRV_PCM_INFO_BLOCK_TRANSFER |
 91			SNDRV_PCM_INFO_SYNC_START),
 92	.buffer_bytes_max = SST_MAX_BUFFER,
 93	.period_bytes_min = SST_MIN_PERIOD_BYTES,
 94	.period_bytes_max = SST_MAX_PERIOD_BYTES,
 95	.periods_min = SST_MIN_PERIODS,
 96	.periods_max = SST_MAX_PERIODS,
 97	.fifo_size = SST_FIFO_SIZE,
 98};
 99
100/* MFLD - MSIC */
101static struct snd_soc_dai_driver sst_platform_dai[] = {
102{
103	.name = "Headset-cpu-dai",
104	.id = 0,
105	.playback = {
106		.channels_min = SST_STEREO,
107		.channels_max = SST_STEREO,
108		.rates = SNDRV_PCM_RATE_48000,
109		.formats = SNDRV_PCM_FMTBIT_S24_LE,
110	},
111	.capture = {
112		.channels_min = 1,
113		.channels_max = 5,
114		.rates = SNDRV_PCM_RATE_48000,
115		.formats = SNDRV_PCM_FMTBIT_S24_LE,
116	},
117},
118{
119	.name = "Speaker-cpu-dai",
120	.id = 1,
121	.playback = {
122		.channels_min = SST_MONO,
123		.channels_max = SST_STEREO,
124		.rates = SNDRV_PCM_RATE_48000,
125		.formats = SNDRV_PCM_FMTBIT_S24_LE,
126	},
127},
128{
129	.name = "Vibra1-cpu-dai",
130	.id = 2,
131	.playback = {
132		.channels_min = SST_MONO,
133		.channels_max = SST_MONO,
134		.rates = SNDRV_PCM_RATE_48000,
135		.formats = SNDRV_PCM_FMTBIT_S24_LE,
136	},
137},
138{
139	.name = "Vibra2-cpu-dai",
140	.id = 3,
141	.playback = {
142		.channels_min = SST_MONO,
143		.channels_max = SST_STEREO,
144		.rates = SNDRV_PCM_RATE_48000,
145		.formats = SNDRV_PCM_FMTBIT_S24_LE,
146	},
147},
148{
149	.name = "Compress-cpu-dai",
150	.compress_dai = 1,
151	.playback = {
152		.channels_min = SST_STEREO,
153		.channels_max = SST_STEREO,
154		.rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
155		.formats = SNDRV_PCM_FMTBIT_S16_LE,
156	},
157},
158};
159
160static const struct snd_soc_component_driver sst_component = {
161	.name		= "sst",
162};
163
164/* helper functions */
165static inline void sst_set_stream_status(struct sst_runtime_stream *stream,
166					int state)
167{
168	unsigned long flags;
169	spin_lock_irqsave(&stream->status_lock, flags);
170	stream->stream_status = state;
171	spin_unlock_irqrestore(&stream->status_lock, flags);
172}
173
174static inline int sst_get_stream_status(struct sst_runtime_stream *stream)
175{
176	int state;
177	unsigned long flags;
178
179	spin_lock_irqsave(&stream->status_lock, flags);
180	state = stream->stream_status;
181	spin_unlock_irqrestore(&stream->status_lock, flags);
182	return state;
183}
184
185static void sst_fill_pcm_params(struct snd_pcm_substream *substream,
186				struct sst_pcm_params *param)
187{
188
189	param->codec = SST_CODEC_TYPE_PCM;
190	param->num_chan = (u8) substream->runtime->channels;
191	param->pcm_wd_sz = substream->runtime->sample_bits;
192	param->reserved = 0;
193	param->sfreq = substream->runtime->rate;
194	param->ring_buffer_size = snd_pcm_lib_buffer_bytes(substream);
195	param->period_count = substream->runtime->period_size;
196	param->ring_buffer_addr = virt_to_phys(substream->dma_buffer.area);
197	pr_debug("period_cnt = %d\n", param->period_count);
198	pr_debug("sfreq= %d, wd_sz = %d\n", param->sfreq, param->pcm_wd_sz);
199}
200
201static int sst_platform_alloc_stream(struct snd_pcm_substream *substream)
202{
203	struct sst_runtime_stream *stream =
204			substream->runtime->private_data;
205	struct sst_pcm_params param = {0};
206	struct sst_stream_params str_params = {0};
207	int ret_val;
208
209	/* set codec params and inform SST driver the same */
210	sst_fill_pcm_params(substream, &param);
211	substream->runtime->dma_area = substream->dma_buffer.area;
212	str_params.sparams = param;
213	str_params.codec =  param.codec;
214	if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
215		str_params.ops = STREAM_OPS_PLAYBACK;
216		str_params.device_type = substream->pcm->device + 1;
217		pr_debug("Playbck stream,Device %d\n",
218					substream->pcm->device);
219	} else {
220		str_params.ops = STREAM_OPS_CAPTURE;
221		str_params.device_type = SND_SST_DEVICE_CAPTURE;
222		pr_debug("Capture stream,Device %d\n",
223					substream->pcm->device);
224	}
225	ret_val = stream->ops->open(&str_params);
226	pr_debug("SST_SND_PLAY/CAPTURE ret_val = %x\n", ret_val);
227	if (ret_val < 0)
228		return ret_val;
229
230	stream->stream_info.str_id = ret_val;
231	pr_debug("str id :  %d\n", stream->stream_info.str_id);
232	return ret_val;
233}
234
235static void sst_period_elapsed(void *mad_substream)
236{
237	struct snd_pcm_substream *substream = mad_substream;
238	struct sst_runtime_stream *stream;
239	int status;
240
241	if (!substream || !substream->runtime)
242		return;
243	stream = substream->runtime->private_data;
244	if (!stream)
245		return;
246	status = sst_get_stream_status(stream);
247	if (status != SST_PLATFORM_RUNNING)
248		return;
249	snd_pcm_period_elapsed(substream);
250}
251
252static int sst_platform_init_stream(struct snd_pcm_substream *substream)
253{
254	struct sst_runtime_stream *stream =
255			substream->runtime->private_data;
256	int ret_val;
257
258	pr_debug("setting buffer ptr param\n");
259	sst_set_stream_status(stream, SST_PLATFORM_INIT);
260	stream->stream_info.period_elapsed = sst_period_elapsed;
261	stream->stream_info.mad_substream = substream;
262	stream->stream_info.buffer_ptr = 0;
263	stream->stream_info.sfreq = substream->runtime->rate;
264	ret_val = stream->ops->device_control(
265			SST_SND_STREAM_INIT, &stream->stream_info);
266	if (ret_val)
267		pr_err("control_set ret error %d\n", ret_val);
268	return ret_val;
269
270}
271/* end -- helper functions */
272
273static int sst_platform_open(struct snd_pcm_substream *substream)
274{
275	struct snd_pcm_runtime *runtime = substream->runtime;
276	struct sst_runtime_stream *stream;
277	int ret_val;
278
279	pr_debug("sst_platform_open called\n");
280
281	snd_soc_set_runtime_hwparams(substream, &sst_platform_pcm_hw);
282	ret_val = snd_pcm_hw_constraint_integer(runtime,
283						SNDRV_PCM_HW_PARAM_PERIODS);
284	if (ret_val < 0)
285		return ret_val;
286
287	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
288	if (!stream)
289		return -ENOMEM;
290	spin_lock_init(&stream->status_lock);
291
292	/* get the sst ops */
293	mutex_lock(&sst_lock);
294	if (!sst) {
295		pr_err("no device available to run\n");
296		mutex_unlock(&sst_lock);
297		kfree(stream);
298		return -ENODEV;
299	}
300	if (!try_module_get(sst->dev->driver->owner)) {
301		mutex_unlock(&sst_lock);
302		kfree(stream);
303		return -ENODEV;
304	}
305	stream->ops = sst->ops;
306	mutex_unlock(&sst_lock);
307
308	stream->stream_info.str_id = 0;
309	sst_set_stream_status(stream, SST_PLATFORM_INIT);
310	stream->stream_info.mad_substream = substream;
311	/* allocate memory for SST API set */
312	runtime->private_data = stream;
313
314	return 0;
315}
316
317static int sst_platform_close(struct snd_pcm_substream *substream)
318{
319	struct sst_runtime_stream *stream;
320	int ret_val = 0, str_id;
321
322	pr_debug("sst_platform_close called\n");
323	stream = substream->runtime->private_data;
324	str_id = stream->stream_info.str_id;
325	if (str_id)
326		ret_val = stream->ops->close(str_id);
327	module_put(sst->dev->driver->owner);
328	kfree(stream);
329	return ret_val;
330}
331
332static int sst_platform_pcm_prepare(struct snd_pcm_substream *substream)
333{
334	struct sst_runtime_stream *stream;
335	int ret_val = 0, str_id;
336
337	pr_debug("sst_platform_pcm_prepare called\n");
338	stream = substream->runtime->private_data;
339	str_id = stream->stream_info.str_id;
340	if (stream->stream_info.str_id) {
341		ret_val = stream->ops->device_control(
342				SST_SND_DROP, &str_id);
343		return ret_val;
344	}
345
346	ret_val = sst_platform_alloc_stream(substream);
347	if (ret_val < 0)
348		return ret_val;
349	snprintf(substream->pcm->id, sizeof(substream->pcm->id),
350			"%d", stream->stream_info.str_id);
351
352	ret_val = sst_platform_init_stream(substream);
353	if (ret_val)
354		return ret_val;
355	substream->runtime->hw.info = SNDRV_PCM_INFO_BLOCK_TRANSFER;
356	return ret_val;
357}
358
359static int sst_platform_pcm_trigger(struct snd_pcm_substream *substream,
360					int cmd)
361{
362	int ret_val = 0, str_id;
363	struct sst_runtime_stream *stream;
364	int str_cmd, status;
365
366	pr_debug("sst_platform_pcm_trigger called\n");
367	stream = substream->runtime->private_data;
368	str_id = stream->stream_info.str_id;
369	switch (cmd) {
370	case SNDRV_PCM_TRIGGER_START:
371		pr_debug("sst: Trigger Start\n");
372		str_cmd = SST_SND_START;
373		status = SST_PLATFORM_RUNNING;
374		stream->stream_info.mad_substream = substream;
375		break;
376	case SNDRV_PCM_TRIGGER_STOP:
377		pr_debug("sst: in stop\n");
378		str_cmd = SST_SND_DROP;
379		status = SST_PLATFORM_DROPPED;
380		break;
381	case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
382		pr_debug("sst: in pause\n");
383		str_cmd = SST_SND_PAUSE;
384		status = SST_PLATFORM_PAUSED;
385		break;
386	case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
387		pr_debug("sst: in pause release\n");
388		str_cmd = SST_SND_RESUME;
389		status = SST_PLATFORM_RUNNING;
390		break;
391	default:
392		return -EINVAL;
393	}
394	ret_val = stream->ops->device_control(str_cmd, &str_id);
395	if (!ret_val)
396		sst_set_stream_status(stream, status);
397
398	return ret_val;
399}
400
401
402static snd_pcm_uframes_t sst_platform_pcm_pointer
403			(struct snd_pcm_substream *substream)
404{
405	struct sst_runtime_stream *stream;
406	int ret_val, status;
407	struct pcm_stream_info *str_info;
408
409	stream = substream->runtime->private_data;
410	status = sst_get_stream_status(stream);
411	if (status == SST_PLATFORM_INIT)
412		return 0;
413	str_info = &stream->stream_info;
414	ret_val = stream->ops->device_control(
415				SST_SND_BUFFER_POINTER, str_info);
416	if (ret_val) {
417		pr_err("sst: error code = %d\n", ret_val);
418		return ret_val;
419	}
420	return stream->stream_info.buffer_ptr;
421}
422
423static int sst_platform_pcm_hw_params(struct snd_pcm_substream *substream,
424		struct snd_pcm_hw_params *params)
425{
426	snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
427	memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
428
429	return 0;
430}
431
432static int sst_platform_pcm_hw_free(struct snd_pcm_substream *substream)
433{
434	return snd_pcm_lib_free_pages(substream);
435}
436
437static struct snd_pcm_ops sst_platform_ops = {
438	.open = sst_platform_open,
439	.close = sst_platform_close,
440	.ioctl = snd_pcm_lib_ioctl,
441	.prepare = sst_platform_pcm_prepare,
442	.trigger = sst_platform_pcm_trigger,
443	.pointer = sst_platform_pcm_pointer,
444	.hw_params = sst_platform_pcm_hw_params,
445	.hw_free = sst_platform_pcm_hw_free,
446};
447
448static void sst_pcm_free(struct snd_pcm *pcm)
449{
450	pr_debug("sst_pcm_free called\n");
451	snd_pcm_lib_preallocate_free_for_all(pcm);
452}
453
454static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
455{
456	struct snd_pcm *pcm = rtd->pcm;
457	int retval = 0;
458
459	pr_debug("sst_pcm_new called\n");
460	if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream ||
461			pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
462		retval =  snd_pcm_lib_preallocate_pages_for_all(pcm,
463			SNDRV_DMA_TYPE_CONTINUOUS,
464			snd_dma_continuous_data(GFP_KERNEL),
465			SST_MIN_BUFFER, SST_MAX_BUFFER);
466		if (retval) {
467			pr_err("dma buffer allocationf fail\n");
468			return retval;
469		}
470	}
471	return retval;
472}
473
474/* compress stream operations */
475static void sst_compr_fragment_elapsed(void *arg)
476{
477	struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
478
479	pr_debug("fragment elapsed by driver\n");
480	if (cstream)
481		snd_compr_fragment_elapsed(cstream);
482}
483
484static int sst_platform_compr_open(struct snd_compr_stream *cstream)
485{
486
487	int ret_val = 0;
488	struct snd_compr_runtime *runtime = cstream->runtime;
489	struct sst_runtime_stream *stream;
490
491	stream = kzalloc(sizeof(*stream), GFP_KERNEL);
492	if (!stream)
493		return -ENOMEM;
494
495	spin_lock_init(&stream->status_lock);
496
497	/* get the sst ops */
498	if (!sst || !try_module_get(sst->dev->driver->owner)) {
499		pr_err("no device available to run\n");
500		ret_val = -ENODEV;
501		goto out_ops;
502	}
503	stream->compr_ops = sst->compr_ops;
504
505	stream->id = 0;
506	sst_set_stream_status(stream, SST_PLATFORM_INIT);
507	runtime->private_data = stream;
508	return 0;
509out_ops:
510	kfree(stream);
511	return ret_val;
512}
513
514static int sst_platform_compr_free(struct snd_compr_stream *cstream)
515{
516	struct sst_runtime_stream *stream;
517	int ret_val = 0, str_id;
518
519	stream = cstream->runtime->private_data;
520	/*need to check*/
521	str_id = stream->id;
522	if (str_id)
523		ret_val = stream->compr_ops->close(str_id);
524	module_put(sst->dev->driver->owner);
525	kfree(stream);
526	pr_debug("%s: %d\n", __func__, ret_val);
527	return 0;
528}
529
530static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
531					struct snd_compr_params *params)
532{
533	struct sst_runtime_stream *stream;
534	int retval;
535	struct snd_sst_params str_params;
536	struct sst_compress_cb cb;
537
538	stream = cstream->runtime->private_data;
539	/* construct fw structure for this*/
540	memset(&str_params, 0, sizeof(str_params));
541
542	str_params.ops = STREAM_OPS_PLAYBACK;
543	str_params.stream_type = SST_STREAM_TYPE_MUSIC;
544	str_params.device_type = SND_SST_DEVICE_COMPRESS;
545
546	switch (params->codec.id) {
547	case SND_AUDIOCODEC_MP3: {
548		str_params.codec = SST_CODEC_TYPE_MP3;
549		str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3;
550		str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
551		str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
552		break;
553	}
554
555	case SND_AUDIOCODEC_AAC: {
556		str_params.codec = SST_CODEC_TYPE_AAC;
557		str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC;
558		str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
559		str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
560		if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
561			str_params.sparams.uc.aac_params.bs_format =
562							AAC_BIT_STREAM_ADTS;
563		else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
564			str_params.sparams.uc.aac_params.bs_format =
565							AAC_BIT_STREAM_RAW;
566		else {
567			pr_err("Undefined format%d\n", params->codec.format);
568			return -EINVAL;
569		}
570		str_params.sparams.uc.aac_params.externalsr =
571						params->codec.sample_rate;
572		break;
573	}
574
575	default:
576		pr_err("codec not supported, id =%d\n", params->codec.id);
577		return -EINVAL;
578	}
579
580	str_params.aparams.ring_buf_info[0].addr  =
581					virt_to_phys(cstream->runtime->buffer);
582	str_params.aparams.ring_buf_info[0].size =
583					cstream->runtime->buffer_size;
584	str_params.aparams.sg_count = 1;
585	str_params.aparams.frag_size = cstream->runtime->fragment_size;
586
587	cb.param = cstream;
588	cb.compr_cb = sst_compr_fragment_elapsed;
589
590	retval = stream->compr_ops->open(&str_params, &cb);
591	if (retval < 0) {
592		pr_err("stream allocation failed %d\n", retval);
593		return retval;
594	}
595
596	stream->id = retval;
597	return 0;
598}
599
600static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
601{
602	struct sst_runtime_stream *stream =
603		cstream->runtime->private_data;
604
605	return stream->compr_ops->control(cmd, stream->id);
606}
607
608static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
609					struct snd_compr_tstamp *tstamp)
610{
611	struct sst_runtime_stream *stream;
612
613	stream  = cstream->runtime->private_data;
614	stream->compr_ops->tstamp(stream->id, tstamp);
615	tstamp->byte_offset = tstamp->copied_total %
616				 (u32)cstream->runtime->buffer_size;
617	pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
618	return 0;
619}
620
621static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
622					size_t bytes)
623{
624	struct sst_runtime_stream *stream;
625
626	stream  = cstream->runtime->private_data;
627	stream->compr_ops->ack(stream->id, (unsigned long)bytes);
628	stream->bytes_written += bytes;
629
630	return 0;
631}
632
633static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
634					struct snd_compr_caps *caps)
635{
636	struct sst_runtime_stream *stream =
637		cstream->runtime->private_data;
638
639	return stream->compr_ops->get_caps(caps);
640}
641
642static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
643					struct snd_compr_codec_caps *codec)
644{
645	struct sst_runtime_stream *stream =
646		cstream->runtime->private_data;
647
648	return stream->compr_ops->get_codec_caps(codec);
649}
650
651static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
652					struct snd_compr_metadata *metadata)
653{
654	struct sst_runtime_stream *stream  =
655		 cstream->runtime->private_data;
656
657	return stream->compr_ops->set_metadata(stream->id, metadata);
658}
659
660static struct snd_compr_ops sst_platform_compr_ops = {
661
662	.open = sst_platform_compr_open,
663	.free = sst_platform_compr_free,
664	.set_params = sst_platform_compr_set_params,
665	.set_metadata = sst_platform_compr_set_metadata,
666	.trigger = sst_platform_compr_trigger,
667	.pointer = sst_platform_compr_pointer,
668	.ack = sst_platform_compr_ack,
669	.get_caps = sst_platform_compr_get_caps,
670	.get_codec_caps = sst_platform_compr_get_codec_caps,
671};
672
673static struct snd_soc_platform_driver sst_soc_platform_drv = {
674	.ops		= &sst_platform_ops,
675	.compr_ops	= &sst_platform_compr_ops,
676	.pcm_new	= sst_pcm_new,
677	.pcm_free	= sst_pcm_free,
678};
679
680static int sst_platform_probe(struct platform_device *pdev)
681{
682	int ret;
683
684	pr_debug("sst_platform_probe called\n");
685	sst = NULL;
686	ret = snd_soc_register_platform(&pdev->dev, &sst_soc_platform_drv);
687	if (ret) {
688		pr_err("registering soc platform failed\n");
689		return ret;
690	}
691
692	ret = snd_soc_register_component(&pdev->dev, &sst_component,
693				sst_platform_dai, ARRAY_SIZE(sst_platform_dai));
694	if (ret) {
695		pr_err("registering cpu dais failed\n");
696		snd_soc_unregister_platform(&pdev->dev);
697	}
698	return ret;
699}
700
701static int sst_platform_remove(struct platform_device *pdev)
702{
703
704	snd_soc_unregister_component(&pdev->dev);
705	snd_soc_unregister_platform(&pdev->dev);
706	pr_debug("sst_platform_remove success\n");
707	return 0;
708}
709
710static struct platform_driver sst_platform_driver = {
711	.driver		= {
712		.name		= "sst-mfld-platform",
713		.owner		= THIS_MODULE,
714	},
715	.probe		= sst_platform_probe,
716	.remove		= sst_platform_remove,
717};
718
719module_platform_driver(sst_platform_driver);
720
721MODULE_DESCRIPTION("ASoC Intel(R) MID Platform driver");
722MODULE_AUTHOR("Vinod Koul <vinod.koul@intel.com>");
723MODULE_AUTHOR("Harsha Priya <priya.harsha@intel.com>");
724MODULE_LICENSE("GPL v2");
725MODULE_ALIAS("platform:sst-mfld-platform");