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

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

Version: ~ [ linux-5.8-rc3 ] ~ [ linux-5.7.5 ] ~ [ linux-5.6.19 ] ~ [ linux-5.5.19 ] ~ [ linux-5.4.48 ] ~ [ linux-5.3.18 ] ~ [ linux-5.2.21 ] ~ [ linux-5.1.21 ] ~ [ linux-5.0.21 ] ~ [ linux-4.20.17 ] ~ [ linux-4.19.129 ] ~ [ linux-4.18.20 ] ~ [ linux-4.17.19 ] ~ [ linux-4.16.18 ] ~ [ linux-4.15.18 ] ~ [ linux-4.14.185 ] ~ [ linux-4.13.16 ] ~ [ linux-4.12.14 ] ~ [ linux-4.11.12 ] ~ [ linux-4.10.17 ] ~ [ linux-4.9.228 ] ~ [ linux-4.8.17 ] ~ [ linux-4.7.10 ] ~ [ linux-4.6.7 ] ~ [ linux-4.5.7 ] ~ [ linux-4.4.228 ] ~ [ 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.85 ] ~ [ 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-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 // SPDX-License-Identifier: GPL-2.0-only
  2 /*
  3  *  sst_mfld_platform.c - Intel MID Platform driver
  4  *
  5  *  Copyright (C) 2010-2014 Intel Corp
  6  *  Author: Vinod Koul <vinod.koul@intel.com>
  7  *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  8  *
  9  * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 10  */
 11 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 12 
 13 #include <linux/slab.h>
 14 #include <linux/io.h>
 15 #include <linux/module.h>
 16 #include <sound/core.h>
 17 #include <sound/pcm.h>
 18 #include <sound/pcm_params.h>
 19 #include <sound/soc.h>
 20 #include <sound/compress_driver.h>
 21 #include "sst-mfld-platform.h"
 22 
 23 /* compress stream operations */
 24 static void sst_compr_fragment_elapsed(void *arg)
 25 {
 26         struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
 27 
 28         pr_debug("fragment elapsed by driver\n");
 29         if (cstream)
 30                 snd_compr_fragment_elapsed(cstream);
 31 }
 32 
 33 static void sst_drain_notify(void *arg)
 34 {
 35         struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
 36 
 37         pr_debug("drain notify by driver\n");
 38         if (cstream)
 39                 snd_compr_drain_notify(cstream);
 40 }
 41 
 42 static int sst_platform_compr_open(struct snd_compr_stream *cstream)
 43 {
 44 
 45         int ret_val = 0;
 46         struct snd_compr_runtime *runtime = cstream->runtime;
 47         struct sst_runtime_stream *stream;
 48 
 49         stream = kzalloc(sizeof(*stream), GFP_KERNEL);
 50         if (!stream)
 51                 return -ENOMEM;
 52 
 53         spin_lock_init(&stream->status_lock);
 54 
 55         /* get the sst ops */
 56         if (!sst || !try_module_get(sst->dev->driver->owner)) {
 57                 pr_err("no device available to run\n");
 58                 ret_val = -ENODEV;
 59                 goto out_ops;
 60         }
 61         stream->compr_ops = sst->compr_ops;
 62         stream->id = 0;
 63 
 64         /* Turn on LPE */
 65         sst->compr_ops->power(sst->dev, true);
 66 
 67         sst_set_stream_status(stream, SST_PLATFORM_INIT);
 68         runtime->private_data = stream;
 69         return 0;
 70 out_ops:
 71         kfree(stream);
 72         return ret_val;
 73 }
 74 
 75 static int sst_platform_compr_free(struct snd_compr_stream *cstream)
 76 {
 77         struct sst_runtime_stream *stream;
 78         int ret_val = 0, str_id;
 79 
 80         stream = cstream->runtime->private_data;
 81         /* Turn off LPE */
 82         sst->compr_ops->power(sst->dev, false);
 83 
 84         /*need to check*/
 85         str_id = stream->id;
 86         if (str_id)
 87                 ret_val = stream->compr_ops->close(sst->dev, str_id);
 88         module_put(sst->dev->driver->owner);
 89         kfree(stream);
 90         pr_debug("%s: %d\n", __func__, ret_val);
 91         return 0;
 92 }
 93 
 94 static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
 95                                         struct snd_compr_params *params)
 96 {
 97         struct sst_runtime_stream *stream;
 98         int retval;
 99         struct snd_sst_params str_params;
100         struct sst_compress_cb cb;
101         struct snd_soc_pcm_runtime *rtd = cstream->private_data;
102         struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, DRV_NAME);
103         struct sst_data *ctx = snd_soc_component_get_drvdata(component);
104 
105         stream = cstream->runtime->private_data;
106         /* construct fw structure for this*/
107         memset(&str_params, 0, sizeof(str_params));
108 
109         /* fill the device type and stream id to pass to SST driver */
110         retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
111         pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
112         if (retval < 0)
113                 return retval;
114 
115         switch (params->codec.id) {
116         case SND_AUDIOCODEC_MP3: {
117                 str_params.codec = SST_CODEC_TYPE_MP3;
118                 str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
119                 str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
120                 break;
121         }
122 
123         case SND_AUDIOCODEC_AAC: {
124                 str_params.codec = SST_CODEC_TYPE_AAC;
125                 str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
126                 str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
127                 if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
128                         str_params.sparams.uc.aac_params.bs_format =
129                                                         AAC_BIT_STREAM_ADTS;
130                 else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
131                         str_params.sparams.uc.aac_params.bs_format =
132                                                         AAC_BIT_STREAM_RAW;
133                 else {
134                         pr_err("Undefined format%d\n", params->codec.format);
135                         return -EINVAL;
136                 }
137                 str_params.sparams.uc.aac_params.externalsr =
138                                                 params->codec.sample_rate;
139                 break;
140         }
141 
142         default:
143                 pr_err("codec not supported, id =%d\n", params->codec.id);
144                 return -EINVAL;
145         }
146 
147         str_params.aparams.ring_buf_info[0].addr  =
148                                         virt_to_phys(cstream->runtime->buffer);
149         str_params.aparams.ring_buf_info[0].size =
150                                         cstream->runtime->buffer_size;
151         str_params.aparams.sg_count = 1;
152         str_params.aparams.frag_size = cstream->runtime->fragment_size;
153 
154         cb.param = cstream;
155         cb.compr_cb = sst_compr_fragment_elapsed;
156         cb.drain_cb_param = cstream;
157         cb.drain_notify = sst_drain_notify;
158 
159         retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
160         if (retval < 0) {
161                 pr_err("stream allocation failed %d\n", retval);
162                 return retval;
163         }
164 
165         stream->id = retval;
166         return 0;
167 }
168 
169 static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
170 {
171         struct sst_runtime_stream *stream = cstream->runtime->private_data;
172 
173         switch (cmd) {
174         case SNDRV_PCM_TRIGGER_START:
175                 if (stream->compr_ops->stream_start)
176                         return stream->compr_ops->stream_start(sst->dev, stream->id);
177                 break;
178         case SNDRV_PCM_TRIGGER_STOP:
179                 if (stream->compr_ops->stream_drop)
180                         return stream->compr_ops->stream_drop(sst->dev, stream->id);
181                 break;
182         case SND_COMPR_TRIGGER_DRAIN:
183                 if (stream->compr_ops->stream_drain)
184                         return stream->compr_ops->stream_drain(sst->dev, stream->id);
185                 break;
186         case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
187                 if (stream->compr_ops->stream_partial_drain)
188                         return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
189                 break;
190         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
191                 if (stream->compr_ops->stream_pause)
192                         return stream->compr_ops->stream_pause(sst->dev, stream->id);
193                 break;
194         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
195                 if (stream->compr_ops->stream_pause_release)
196                         return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
197                 break;
198         }
199         return -EINVAL;
200 }
201 
202 static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
203                                         struct snd_compr_tstamp *tstamp)
204 {
205         struct sst_runtime_stream *stream;
206 
207         stream  = cstream->runtime->private_data;
208         stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
209         tstamp->byte_offset = tstamp->copied_total %
210                                  (u32)cstream->runtime->buffer_size;
211         pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
212         return 0;
213 }
214 
215 static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
216                                         size_t bytes)
217 {
218         struct sst_runtime_stream *stream;
219 
220         stream  = cstream->runtime->private_data;
221         stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
222         stream->bytes_written += bytes;
223 
224         return 0;
225 }
226 
227 static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
228                                         struct snd_compr_caps *caps)
229 {
230         struct sst_runtime_stream *stream =
231                 cstream->runtime->private_data;
232 
233         return stream->compr_ops->get_caps(caps);
234 }
235 
236 static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
237                                         struct snd_compr_codec_caps *codec)
238 {
239         struct sst_runtime_stream *stream =
240                 cstream->runtime->private_data;
241 
242         return stream->compr_ops->get_codec_caps(codec);
243 }
244 
245 static int sst_platform_compr_set_metadata(struct snd_compr_stream *cstream,
246                                         struct snd_compr_metadata *metadata)
247 {
248         struct sst_runtime_stream *stream  =
249                  cstream->runtime->private_data;
250 
251         return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
252 }
253 
254 const struct snd_compr_ops sst_platform_compr_ops = {
255 
256         .open = sst_platform_compr_open,
257         .free = sst_platform_compr_free,
258         .set_params = sst_platform_compr_set_params,
259         .set_metadata = sst_platform_compr_set_metadata,
260         .trigger = sst_platform_compr_trigger,
261         .pointer = sst_platform_compr_pointer,
262         .ack = sst_platform_compr_ack,
263         .get_caps = sst_platform_compr_get_caps,
264         .get_codec_caps = sst_platform_compr_get_codec_caps,
265 };
266 

~ [ 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