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
;
72 sst_set_stream_status(stream
, SST_PLATFORM_INIT
);
73 runtime
->private_data
= stream
;
80 static int sst_platform_compr_free(struct snd_compr_stream
*cstream
)
82 struct sst_runtime_stream
*stream
;
83 int ret_val
= 0, str_id
;
85 stream
= cstream
->runtime
->private_data
;
89 ret_val
= stream
->compr_ops
->close(str_id
);
90 module_put(sst
->dev
->driver
->owner
);
92 pr_debug("%s: %d\n", __func__
, ret_val
);
96 static int sst_platform_compr_set_params(struct snd_compr_stream
*cstream
,
97 struct snd_compr_params
*params
)
99 struct sst_runtime_stream
*stream
;
101 struct snd_sst_params str_params
;
102 struct sst_compress_cb cb
;
103 struct snd_soc_pcm_runtime
*rtd
= cstream
->private_data
;
104 struct snd_soc_platform
*platform
= rtd
->platform
;
105 struct sst_data
*ctx
= snd_soc_platform_get_drvdata(platform
);
107 stream
= cstream
->runtime
->private_data
;
108 /* construct fw structure for this*/
109 memset(&str_params
, 0, sizeof(str_params
));
111 /* fill the device type and stream id to pass to SST driver */
112 retval
= sst_fill_stream_params(cstream
, ctx
, &str_params
, true);
113 pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval
);
117 switch (params
->codec
.id
) {
118 case SND_AUDIOCODEC_MP3
: {
119 str_params
.codec
= SST_CODEC_TYPE_MP3
;
120 str_params
.sparams
.uc
.mp3_params
.num_chan
= params
->codec
.ch_in
;
121 str_params
.sparams
.uc
.mp3_params
.pcm_wd_sz
= 16;
125 case SND_AUDIOCODEC_AAC
: {
126 str_params
.codec
= SST_CODEC_TYPE_AAC
;
127 str_params
.sparams
.uc
.aac_params
.num_chan
= params
->codec
.ch_in
;
128 str_params
.sparams
.uc
.aac_params
.pcm_wd_sz
= 16;
129 if (params
->codec
.format
== SND_AUDIOSTREAMFORMAT_MP4ADTS
)
130 str_params
.sparams
.uc
.aac_params
.bs_format
=
132 else if (params
->codec
.format
== SND_AUDIOSTREAMFORMAT_RAW
)
133 str_params
.sparams
.uc
.aac_params
.bs_format
=
136 pr_err("Undefined format%d\n", params
->codec
.format
);
139 str_params
.sparams
.uc
.aac_params
.externalsr
=
140 params
->codec
.sample_rate
;
145 pr_err("codec not supported, id =%d\n", params
->codec
.id
);
149 str_params
.aparams
.ring_buf_info
[0].addr
=
150 virt_to_phys(cstream
->runtime
->buffer
);
151 str_params
.aparams
.ring_buf_info
[0].size
=
152 cstream
->runtime
->buffer_size
;
153 str_params
.aparams
.sg_count
= 1;
154 str_params
.aparams
.frag_size
= cstream
->runtime
->fragment_size
;
157 cb
.compr_cb
= sst_compr_fragment_elapsed
;
158 cb
.drain_cb_param
= cstream
;
159 cb
.drain_notify
= sst_drain_notify
;
161 retval
= stream
->compr_ops
->open(&str_params
, &cb
);
163 pr_err("stream allocation failed %d\n", retval
);
171 static int sst_platform_compr_trigger(struct snd_compr_stream
*cstream
, int cmd
)
173 struct sst_runtime_stream
*stream
=
174 cstream
->runtime
->private_data
;
176 return stream
->compr_ops
->control(cmd
, stream
->id
);
179 static int sst_platform_compr_pointer(struct snd_compr_stream
*cstream
,
180 struct snd_compr_tstamp
*tstamp
)
182 struct sst_runtime_stream
*stream
;
184 stream
= cstream
->runtime
->private_data
;
185 stream
->compr_ops
->tstamp(stream
->id
, tstamp
);
186 tstamp
->byte_offset
= tstamp
->copied_total
%
187 (u32
)cstream
->runtime
->buffer_size
;
188 pr_debug("calc bytes offset/copied bytes as %d\n", tstamp
->byte_offset
);
192 static int sst_platform_compr_ack(struct snd_compr_stream
*cstream
,
195 struct sst_runtime_stream
*stream
;
197 stream
= cstream
->runtime
->private_data
;
198 stream
->compr_ops
->ack(stream
->id
, (unsigned long)bytes
);
199 stream
->bytes_written
+= bytes
;
204 static int sst_platform_compr_get_caps(struct snd_compr_stream
*cstream
,
205 struct snd_compr_caps
*caps
)
207 struct sst_runtime_stream
*stream
=
208 cstream
->runtime
->private_data
;
210 return stream
->compr_ops
->get_caps(caps
);
213 static int sst_platform_compr_get_codec_caps(struct snd_compr_stream
*cstream
,
214 struct snd_compr_codec_caps
*codec
)
216 struct sst_runtime_stream
*stream
=
217 cstream
->runtime
->private_data
;
219 return stream
->compr_ops
->get_codec_caps(codec
);
222 static int sst_platform_compr_set_metadata(struct snd_compr_stream
*cstream
,
223 struct snd_compr_metadata
*metadata
)
225 struct sst_runtime_stream
*stream
=
226 cstream
->runtime
->private_data
;
228 return stream
->compr_ops
->set_metadata(stream
->id
, metadata
);
231 struct snd_compr_ops sst_platform_compr_ops
= {
233 .open
= sst_platform_compr_open
,
234 .free
= sst_platform_compr_free
,
235 .set_params
= sst_platform_compr_set_params
,
236 .set_metadata
= sst_platform_compr_set_metadata
,
237 .trigger
= sst_platform_compr_trigger
,
238 .pointer
= sst_platform_compr_pointer
,
239 .ack
= sst_platform_compr_ack
,
240 .get_caps
= sst_platform_compr_get_caps
,
241 .get_codec_caps
= sst_platform_compr_get_codec_caps
,