arm64: dts: qcom: sm8550: add TRNG node
[linux-modified.git] / sound / soc / intel / atom / sst-mfld-platform-compress.c
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_soc_component *component,
43                                    struct snd_compr_stream *cstream)
44 {
45         int ret_val;
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_soc_component *component,
76                                    struct snd_compr_stream *cstream)
77 {
78         struct sst_runtime_stream *stream;
79         int ret_val = 0, str_id;
80
81         stream = cstream->runtime->private_data;
82         /* Turn off LPE */
83         sst->compr_ops->power(sst->dev, false);
84
85         /*need to check*/
86         str_id = stream->id;
87         if (str_id)
88                 ret_val = stream->compr_ops->close(sst->dev, str_id);
89         module_put(sst->dev->driver->owner);
90         kfree(stream);
91         pr_debug("%s: %d\n", __func__, ret_val);
92         return 0;
93 }
94
95 static int sst_platform_compr_set_params(struct snd_soc_component *component,
96                                          struct snd_compr_stream *cstream,
97                                          struct snd_compr_params *params)
98 {
99         struct sst_runtime_stream *stream;
100         int retval;
101         struct snd_sst_params str_params;
102         struct sst_compress_cb cb;
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_soc_component *component,
170                                       struct snd_compr_stream *cstream, int cmd)
171 {
172         struct sst_runtime_stream *stream = cstream->runtime->private_data;
173
174         switch (cmd) {
175         case SNDRV_PCM_TRIGGER_START:
176                 if (stream->compr_ops->stream_start)
177                         return stream->compr_ops->stream_start(sst->dev, stream->id);
178                 break;
179         case SNDRV_PCM_TRIGGER_STOP:
180                 if (stream->compr_ops->stream_drop)
181                         return stream->compr_ops->stream_drop(sst->dev, stream->id);
182                 break;
183         case SND_COMPR_TRIGGER_DRAIN:
184                 if (stream->compr_ops->stream_drain)
185                         return stream->compr_ops->stream_drain(sst->dev, stream->id);
186                 break;
187         case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
188                 if (stream->compr_ops->stream_partial_drain)
189                         return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
190                 break;
191         case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
192                 if (stream->compr_ops->stream_pause)
193                         return stream->compr_ops->stream_pause(sst->dev, stream->id);
194                 break;
195         case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
196                 if (stream->compr_ops->stream_pause_release)
197                         return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
198                 break;
199         }
200         return -EINVAL;
201 }
202
203 static int sst_platform_compr_pointer(struct snd_soc_component *component,
204                                       struct snd_compr_stream *cstream,
205                                       struct snd_compr_tstamp *tstamp)
206 {
207         struct sst_runtime_stream *stream;
208
209         stream  = cstream->runtime->private_data;
210         stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
211         tstamp->byte_offset = tstamp->copied_total %
212                                  (u32)cstream->runtime->buffer_size;
213         pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
214         return 0;
215 }
216
217 static int sst_platform_compr_ack(struct snd_soc_component *component,
218                                   struct snd_compr_stream *cstream,
219                                   size_t bytes)
220 {
221         struct sst_runtime_stream *stream;
222
223         stream  = cstream->runtime->private_data;
224         stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
225         stream->bytes_written += bytes;
226
227         return 0;
228 }
229
230 static int sst_platform_compr_get_caps(struct snd_soc_component *component,
231                                        struct snd_compr_stream *cstream,
232                                        struct snd_compr_caps *caps)
233 {
234         struct sst_runtime_stream *stream =
235                 cstream->runtime->private_data;
236
237         return stream->compr_ops->get_caps(caps);
238 }
239
240 static int sst_platform_compr_get_codec_caps(struct snd_soc_component *component,
241                                              struct snd_compr_stream *cstream,
242                                              struct snd_compr_codec_caps *codec)
243 {
244         struct sst_runtime_stream *stream =
245                 cstream->runtime->private_data;
246
247         return stream->compr_ops->get_codec_caps(codec);
248 }
249
250 static int sst_platform_compr_set_metadata(struct snd_soc_component *component,
251                                            struct snd_compr_stream *cstream,
252                                            struct snd_compr_metadata *metadata)
253 {
254         struct sst_runtime_stream *stream  =
255                  cstream->runtime->private_data;
256
257         return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
258 }
259
260 const struct snd_compress_ops sst_platform_compress_ops = {
261
262         .open = sst_platform_compr_open,
263         .free = sst_platform_compr_free,
264         .set_params = sst_platform_compr_set_params,
265         .set_metadata = sst_platform_compr_set_metadata,
266         .trigger = sst_platform_compr_trigger,
267         .pointer = sst_platform_compr_pointer,
268         .ack = sst_platform_compr_ack,
269         .get_caps = sst_platform_compr_get_caps,
270         .get_codec_caps = sst_platform_compr_get_codec_caps,
271 };