~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

TOMOYO Linux Cross Reference
Linux/sound/soc/intel/atom/sst-mfld-platform-compress.c

Version: ~ [ linux-5.2-rc5 ] ~ [ linux-5.1.12 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.53 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.128 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.182 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.182 ] ~ [ linux-4.3.6 ] ~ [ linux-4.2.8 ] ~ [ linux-4.1.52 ] ~ [ linux-4.0.9 ] ~ [ linux-3.19.8 ] ~ [ linux-3.18.140 ] ~ [ linux-3.17.8 ] ~ [ linux-3.16.68 ] ~ [ linux-3.15.10 ] ~ [ linux-3.14.79 ] ~ [ linux-3.13.11 ] ~ [ linux-3.12.74 ] ~ [ linux-3.11.10 ] ~ [ linux-3.10.108 ] ~ [ linux-3.9.11 ] ~ [ linux-3.8.13 ] ~ [ linux-3.7.10 ] ~ [ linux-3.6.11 ] ~ [ linux-3.5.7 ] ~ [ linux-3.4.113 ] ~ [ linux-3.3.8 ] ~ [ linux-3.2.102 ] ~ [ linux-3.1.10 ] ~ [ linux-3.0.101 ] ~ [ linux-2.6.39.4 ] ~ [ linux-2.6.38.8 ] ~ [ linux-2.6.37.6 ] ~ [ linux-2.6.36.4 ] ~ [ linux-2.6.35.14 ] ~ [ linux-2.6.34.15 ] ~ [ linux-2.6.33.20 ] ~ [ linux-2.6.32.71 ] ~ [ linux-2.6.0 ] ~ [ linux-2.4.37.11 ] ~ [ unix-v6-master ] ~ [ ccs-tools-1.8.5 ] ~ [ policy-sample ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  *  sst_mfld_platform.c - Intel MID Platform driver
  3  *
  4  *  Copyright (C) 2010-2014 Intel Corp
  5  *  Author: Vinod Koul <vinod.koul@intel.com>
  6  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  7  *
  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.
 11  *
 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.
 16  *
 17  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 18  */
 19 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 20 
 21 #include <linux/slab.h>
 22 #include <linux/io.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"
 30 
 31 /* compress stream operations */
 32 static void sst_compr_fragment_elapsed(void *arg)
 33 {
 34         struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
 35 
 36         pr_debug("fragment elapsed by driver\n");
 37         if (cstream)
 38                 snd_compr_fragment_elapsed(cstream);
 39 }
 40 
 41 static void sst_drain_notify(void *arg)
 42 {
 43         struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
 44 
 45         pr_debug("drain notify by driver\n");
 46         if (cstream)
 47                 snd_compr_drain_notify(cstream);
 48 }
 49 
 50 static int sst_platform_compr_open(struct snd_compr_stream *cstream)
 51 {
 52 
 53         int ret_val = 0;
 54         struct snd_compr_runtime *runtime = cstream->runtime;
 55         struct sst_runtime_stream *stream;
 56 
 57         stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 58         if (!stream)
 59                 return -ENOMEM;
 60 
 61         spin_lock_init(&stream->status_lock);
 62 
 63         /* get the sst ops */
 64         if (!sst || !try_module_get(sst->dev->driver->owner)) {
 65                 pr_err("no device available to run\n");
 66                 ret_val = -ENODEV;
 67                 goto out_ops;
 68         }
 69         stream->compr_ops = sst->compr_ops;
 70         stream->id = 0;
 71 
 72         /* Turn on LPE */
 73         sst->compr_ops->power(sst->dev, true);
 74 
 75         sst_set_stream_status(stream, SST_PLATFORM_INIT);
 76         runtime->private_data = stream;
 77         return 0;
 78 out_ops:
 79         kfree(stream);
 80         return ret_val;
 81 }
 82 
 83 static int sst_platform_compr_free(struct snd_compr_stream *cstream)
 84 {
 85         struct sst_runtime_stream *stream;
 86         int ret_val = 0, str_id;
 87 
 88         stream = cstream->runtime->private_data;
 89         /* Turn off LPE */
 90         sst->compr_ops->power(sst->dev, false);
 91 
 92         /*need to check*/
 93         str_id = stream->id;
 94         if (str_id)
 95                 ret_val = stream->compr_ops->close(sst->dev, str_id);
 96         module_put(sst->dev->driver->owner);
 97         kfree(stream);
 98         pr_debug("%s: %d\n", __func__, ret_val);
 99         return 0;
100 }
101 
102 static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
103                                         struct snd_compr_params *params)
104 {
105         struct sst_runtime_stream *stream;
106         int retval;
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);
112 
113         stream = cstream->runtime->private_data;
114         /* construct fw structure for this*/
115         memset(&str_params, 0, sizeof(str_params));
116 
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);
120         if (retval < 0)
121                 return retval;
122 
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;
128                 break;
129         }
130 
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 =
137                                                         AAC_BIT_STREAM_ADTS;
138                 else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
139                         str_params.sparams.uc.aac_params.bs_format =
140                                                         AAC_BIT_STREAM_RAW;
141                 else {
142                         pr_err("Undefined format%d\n", params->codec.format);
143                         return -EINVAL;
144                 }
145                 str_params.sparams.uc.aac_params.externalsr =
146                                                 params->codec.sample_rate;
147                 break;
148         }
149 
150         default:
151                 pr_err("codec not supported, id =%d\n", params->codec.id);
152                 return -EINVAL;
153         }
154 
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;
161 
162         cb.param = cstream;
163         cb.compr_cb = sst_compr_fragment_elapsed;
164         cb.drain_cb_param = cstream;
165         cb.drain_notify = sst_drain_notify;
166 
167         retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
168         if (retval < 0) {
169                 pr_err("stream allocation failed %d\n", retval);
170                 return retval;
171         }
172 
173         stream->id = retval;
174         return 0;
175 }
176 
177 static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
178 {
179         struct sst_runtime_stream *stream = cstream->runtime->private_data;
180 
181         switch (cmd) {
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                 break;
186         case SNDRV_PCM_TRIGGER_STOP:
187                 if (stream->compr_ops->stream_drop)
188                         return stream->compr_ops->stream_drop(sst->dev, stream->id);
189                 break;
190         case SND_COMPR_TRIGGER_DRAIN:
191                 if (stream->compr_ops->stream_drain)
192                         return stream->compr_ops->stream_drain(sst->dev, stream->id);
193                 break;
194         case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
195                 if (stream->compr_ops->stream_partial_drain)
196                         return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
197                 break;
198         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
199                 if (stream->compr_ops->stream_pause)
200                         return stream->compr_ops->stream_pause(sst->dev, stream->id);
201                 break;
202         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
203                 if (stream->compr_ops->stream_pause_release)
204                         return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
205                 break;
206         }
207         return -EINVAL;
208 }
209 
210 static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
211                                         struct snd_compr_tstamp *tstamp)
212 {
213         struct sst_runtime_stream *stream;
214 
215         stream  = cstream->runtime->private_data;
216         stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
217         tstamp->byte_offset = tstamp->copied_total %
218                                  (u32)cstream->runtime->buffer_size;
219         pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
220         return 0;
221 }
222 
223 static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
224                                         size_t bytes)
225 {
226         struct sst_runtime_stream *stream;
227 
228         stream  = cstream->runtime->private_data;
229         stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
230         stream->bytes_written += bytes;
231 
232         return 0;
233 }
234 
235 static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
236                                         struct snd_compr_caps *caps)
237 {
238         struct sst_runtime_stream *stream =
239                 cstream->runtime->private_data;
240 
241         return stream->compr_ops->get_caps(caps);
242 }
243 
244 static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
245                                         struct snd_compr_codec_caps *codec)
246 {
247         struct sst_runtime_stream *stream =
248                 cstream->runtime->private_data;
249 
250         return stream->compr_ops->get_codec_caps(codec);
251 }
252 
253 static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
254                                         struct snd_compr_metadata *metadata)
255 {
256         struct sst_runtime_stream *stream  =
257                  cstream->runtime->private_data;
258 
259         return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
260 }
261 
262 struct snd_compr_ops sst_platform_compr_ops = {
263 
264         .open = sst_platform_compr_open,
265         .free = sst_platform_compr_free,
266         .set_params = sst_platform_compr_set_params,
267         .set_metadata = sst_platform_compr_set_metadata,
268         .trigger = sst_platform_compr_trigger,
269         .pointer = sst_platform_compr_pointer,
270         .ack = sst_platform_compr_ack,
271         .get_caps = sst_platform_compr_get_caps,
272         .get_codec_caps = sst_platform_compr_get_codec_caps,
273 };
274 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~

kernel.org | git.kernel.org | LWN.net | Project Home | Wiki (Japanese) | Wiki (English) | SVN repository | Mail admin

Linux® is a registered trademark of Linus Torvalds in the United States and other countries.
TOMOYO® is a registered trademark of NTT DATA CORPORATION.

osdn.jp