2 * sst_mfld_platform.c - Intel MID Platform driver
4 * Copyright (C) 2010-2014 Intel Corp
5 * Author: Vinod Koul <vinod.koul@intel.com>
6 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; version 2 of the License.
12 * This program is distributed in the hope that it will be useful, but
13 * WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * General Public License for more details.
17 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
21 #include <linux/slab.h>
23 #include <linux/module.h>
24 #include <sound/core.h>
25 #include <sound/pcm.h>
26 #include <sound/pcm_params.h>
27 #include <sound/soc.h>
28 #include <sound/compress_driver.h>
29 #include "sst-mfld-platform.h"
31 /* compress stream operations */
32 static void sst_compr_fragment_elapsed(void *arg
)
34 struct snd_compr_stream
*cstream
= (struct snd_compr_stream
*)arg
;
36 pr_debug("fragment elapsed by driver\n");
38 snd_compr_fragment_elapsed(cstream
);
41 static void sst_drain_notify(void *arg
)
43 struct snd_compr_stream
*cstream
= (struct snd_compr_stream
*)arg
;
45 pr_debug("drain notify by driver\n");
47 snd_compr_drain_notify(cstream
);
50 static int sst_platform_compr_open(struct snd_compr_stream
*cstream
)
54 struct snd_compr_runtime
*runtime
= cstream
->runtime
;
55 struct sst_runtime_stream
*stream
;
57 stream
= kzalloc(sizeof(*stream
), GFP_KERNEL
);
61 spin_lock_init(&stream
->status_lock
);
64 if (!sst
|| !try_module_get(sst
->dev
->driver
->owner
)) {
65 pr_err("no device available to run\n");
69 stream
->compr_ops
= sst
->compr_ops
;
73 sst
->compr_ops
->power(sst
->dev
, true);
75 sst_set_stream_status(stream
, SST_PLATFORM_INIT
);
76 runtime
->private_data
= stream
;
83 static int sst_platform_compr_free(struct snd_compr_stream
*cstream
)
85 struct sst_runtime_stream
*stream
;
86 int ret_val
= 0, str_id
;
88 stream
= cstream
->runtime
->private_data
;
90 sst
->compr_ops
->power(sst
->dev
, false);
95 ret_val
= stream
->compr_ops
->close(sst
->dev
, str_id
);
96 module_put(sst
->dev
->driver
->owner
);
98 pr_debug("%s: %d\n", __func__
, ret_val
);
102 static int sst_platform_compr_set_params(struct snd_compr_stream
*cstream
,
103 struct snd_compr_params
*params
)
105 struct sst_runtime_stream
*stream
;
107 struct snd_sst_params str_params
;
108 struct sst_compress_cb cb
;
109 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
110 struct snd_soc_platform
*platform
= rtd
->platform
;
111 struct sst_data
*ctx
= snd_soc_platform_get_drvdata(platform
);
113 stream
= cstream
->runtime
->private_data
;
114 /* construct fw structure for this*/
115 memset(&str_params
, 0, sizeof(str_params
));
117 /* fill the device type and stream id to pass to SST driver */
118 retval
= sst_fill_stream_params(cstream
, ctx
, &str_params
, true);
119 pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval
);
123 switch (params
->codec
.id
) {
124 case SND_AUDIOCODEC_MP3
: {
125 str_params
.codec
= SST_CODEC_TYPE_MP3
;
126 str_params
.sparams
.uc
.mp3_params
.num_chan
= params
->codec
.ch_in
;
127 str_params
.sparams
.uc
.mp3_params
.pcm_wd_sz
= 16;
131 case SND_AUDIOCODEC_AAC
: {
132 str_params
.codec
= SST_CODEC_TYPE_AAC
;
133 str_params
.sparams
.uc
.aac_params
.num_chan
= params
->codec
.ch_in
;
134 str_params
.sparams
.uc
.aac_params
.pcm_wd_sz
= 16;
135 if (params
->codec
.format
== SND_AUDIOSTREAMFORMAT_MP4ADTS
)
136 str_params
.sparams
.uc
.aac_params
.bs_format
=
138 else if (params
->codec
.format
== SND_AUDIOSTREAMFORMAT_RAW
)
139 str_params
.sparams
.uc
.aac_params
.bs_format
=
142 pr_err("Undefined format%d\n", params
->codec
.format
);
145 str_params
.sparams
.uc
.aac_params
.externalsr
=
146 params
->codec
.sample_rate
;
151 pr_err("codec not supported, id =%d\n", params
->codec
.id
);
155 str_params
.aparams
.ring_buf_info
[0].addr
=
156 virt_to_phys(cstream
->runtime
->buffer
);
157 str_params
.aparams
.ring_buf_info
[0].size
=
158 cstream
->runtime
->buffer_size
;
159 str_params
.aparams
.sg_count
= 1;
160 str_params
.aparams
.frag_size
= cstream
->runtime
->fragment_size
;
163 cb
.compr_cb
= sst_compr_fragment_elapsed
;
164 cb
.drain_cb_param
= cstream
;
165 cb
.drain_notify
= sst_drain_notify
;
167 retval
= stream
->compr_ops
->open(sst
->dev
, &str_params
, &cb
);
169 pr_err("stream allocation failed %d\n", retval
);
177 static int sst_platform_compr_trigger(struct snd_compr_stream
*cstream
, int cmd
)
179 struct sst_runtime_stream
*stream
= cstream
->runtime
->private_data
;
182 case SNDRV_PCM_TRIGGER_START
:
183 if (stream
->compr_ops
->stream_start
)
184 return stream
->compr_ops
->stream_start(sst
->dev
, stream
->id
);
185 case SNDRV_PCM_TRIGGER_STOP
:
186 if (stream
->compr_ops
->stream_drop
)
187 return stream
->compr_ops
->stream_drop(sst
->dev
, stream
->id
);
188 case SND_COMPR_TRIGGER_DRAIN
:
189 if (stream
->compr_ops
->stream_drain
)
190 return stream
->compr_ops
->stream_drain(sst
->dev
, stream
->id
);
191 case SND_COMPR_TRIGGER_PARTIAL_DRAIN
:
192 if (stream
->compr_ops
->stream_partial_drain
)
193 return stream
->compr_ops
->stream_partial_drain(sst
->dev
, stream
->id
);
194 case SNDRV_PCM_TRIGGER_PAUSE_PUSH
:
195 if (stream
->compr_ops
->stream_pause
)
196 return stream
->compr_ops
->stream_pause(sst
->dev
, stream
->id
);
197 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE
:
198 if (stream
->compr_ops
->stream_pause_release
)
199 return stream
->compr_ops
->stream_pause_release(sst
->dev
, stream
->id
);
205 static int sst_platform_compr_pointer(struct snd_compr_stream
*cstream
,
206 struct snd_compr_tstamp
*tstamp
)
208 struct sst_runtime_stream
*stream
;
210 stream
= cstream
->runtime
->private_data
;
211 stream
->compr_ops
->tstamp(sst
->dev
, stream
->id
, tstamp
);
212 tstamp
->byte_offset
= tstamp
->copied_total
%
213 (u32
)cstream
->runtime
->buffer_size
;
214 pr_debug("calc bytes offset/copied bytes as %d\n", tstamp
->byte_offset
);
218 static int sst_platform_compr_ack(struct snd_compr_stream
*cstream
,
221 struct sst_runtime_stream
*stream
;
223 stream
= cstream
->runtime
->private_data
;
224 stream
->compr_ops
->ack(sst
->dev
, stream
->id
, (unsigned long)bytes
);
225 stream
->bytes_written
+= bytes
;
230 static int sst_platform_compr_get_caps(struct snd_compr_stream
*cstream
,
231 struct snd_compr_caps
*caps
)
233 struct sst_runtime_stream
*stream
=
234 cstream
->runtime
->private_data
;
236 return stream
->compr_ops
->get_caps(caps
);
239 static int sst_platform_compr_get_codec_caps(struct snd_compr_stream
*cstream
,
240 struct snd_compr_codec_caps
*codec
)
242 struct sst_runtime_stream
*stream
=
243 cstream
->runtime
->private_data
;
245 return stream
->compr_ops
->get_codec_caps(codec
);
248 static int sst_platform_compr_set_metadata(struct snd_compr_stream
*cstream
,
249 struct snd_compr_metadata
*metadata
)
251 struct sst_runtime_stream
*stream
=
252 cstream
->runtime
->private_data
;
254 return stream
->compr_ops
->set_metadata(sst
->dev
, stream
->id
, metadata
);
257 struct snd_compr_ops sst_platform_compr_ops
= {
259 .open
= sst_platform_compr_open
,
260 .free
= sst_platform_compr_free
,
261 .set_params
= sst_platform_compr_set_params
,
262 .set_metadata
= sst_platform_compr_set_metadata
,
263 .trigger
= sst_platform_compr_trigger
,
264 .pointer
= sst_platform_compr_pointer
,
265 .ack
= sst_platform_compr_ack
,
266 .get_caps
= sst_platform_compr_get_caps
,
267 .get_codec_caps
= sst_platform_compr_get_codec_caps
,