Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/sound/soc/intel/atom/sst-mfld-platform-compress.c
26493 views
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 <[email protected]>
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
};
272
273