0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0012
0013 #include <linux/slab.h>
0014 #include <linux/io.h>
0015 #include <linux/module.h>
0016 #include <sound/core.h>
0017 #include <sound/pcm.h>
0018 #include <sound/pcm_params.h>
0019 #include <sound/soc.h>
0020 #include <sound/compress_driver.h>
0021 #include "sst-mfld-platform.h"
0022
0023
0024 static void sst_compr_fragment_elapsed(void *arg)
0025 {
0026 struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
0027
0028 pr_debug("fragment elapsed by driver\n");
0029 if (cstream)
0030 snd_compr_fragment_elapsed(cstream);
0031 }
0032
0033 static void sst_drain_notify(void *arg)
0034 {
0035 struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
0036
0037 pr_debug("drain notify by driver\n");
0038 if (cstream)
0039 snd_compr_drain_notify(cstream);
0040 }
0041
0042 static int sst_platform_compr_open(struct snd_soc_component *component,
0043 struct snd_compr_stream *cstream)
0044 {
0045 int ret_val;
0046 struct snd_compr_runtime *runtime = cstream->runtime;
0047 struct sst_runtime_stream *stream;
0048
0049 stream = kzalloc(sizeof(*stream), GFP_KERNEL);
0050 if (!stream)
0051 return -ENOMEM;
0052
0053 spin_lock_init(&stream->status_lock);
0054
0055
0056 if (!sst || !try_module_get(sst->dev->driver->owner)) {
0057 pr_err("no device available to run\n");
0058 ret_val = -ENODEV;
0059 goto out_ops;
0060 }
0061 stream->compr_ops = sst->compr_ops;
0062 stream->id = 0;
0063
0064
0065 sst->compr_ops->power(sst->dev, true);
0066
0067 sst_set_stream_status(stream, SST_PLATFORM_INIT);
0068 runtime->private_data = stream;
0069 return 0;
0070 out_ops:
0071 kfree(stream);
0072 return ret_val;
0073 }
0074
0075 static int sst_platform_compr_free(struct snd_soc_component *component,
0076 struct snd_compr_stream *cstream)
0077 {
0078 struct sst_runtime_stream *stream;
0079 int ret_val = 0, str_id;
0080
0081 stream = cstream->runtime->private_data;
0082
0083 sst->compr_ops->power(sst->dev, false);
0084
0085
0086 str_id = stream->id;
0087 if (str_id)
0088 ret_val = stream->compr_ops->close(sst->dev, str_id);
0089 module_put(sst->dev->driver->owner);
0090 kfree(stream);
0091 pr_debug("%s: %d\n", __func__, ret_val);
0092 return 0;
0093 }
0094
0095 static int sst_platform_compr_set_params(struct snd_soc_component *component,
0096 struct snd_compr_stream *cstream,
0097 struct snd_compr_params *params)
0098 {
0099 struct sst_runtime_stream *stream;
0100 int retval;
0101 struct snd_sst_params str_params;
0102 struct sst_compress_cb cb;
0103 struct sst_data *ctx = snd_soc_component_get_drvdata(component);
0104
0105 stream = cstream->runtime->private_data;
0106
0107 memset(&str_params, 0, sizeof(str_params));
0108
0109
0110 retval = sst_fill_stream_params(cstream, ctx, &str_params, true);
0111 pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);
0112 if (retval < 0)
0113 return retval;
0114
0115 switch (params->codec.id) {
0116 case SND_AUDIOCODEC_MP3: {
0117 str_params.codec = SST_CODEC_TYPE_MP3;
0118 str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
0119 str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
0120 break;
0121 }
0122
0123 case SND_AUDIOCODEC_AAC: {
0124 str_params.codec = SST_CODEC_TYPE_AAC;
0125 str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
0126 str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
0127 if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
0128 str_params.sparams.uc.aac_params.bs_format =
0129 AAC_BIT_STREAM_ADTS;
0130 else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
0131 str_params.sparams.uc.aac_params.bs_format =
0132 AAC_BIT_STREAM_RAW;
0133 else {
0134 pr_err("Undefined format%d\n", params->codec.format);
0135 return -EINVAL;
0136 }
0137 str_params.sparams.uc.aac_params.externalsr =
0138 params->codec.sample_rate;
0139 break;
0140 }
0141
0142 default:
0143 pr_err("codec not supported, id =%d\n", params->codec.id);
0144 return -EINVAL;
0145 }
0146
0147 str_params.aparams.ring_buf_info[0].addr =
0148 virt_to_phys(cstream->runtime->buffer);
0149 str_params.aparams.ring_buf_info[0].size =
0150 cstream->runtime->buffer_size;
0151 str_params.aparams.sg_count = 1;
0152 str_params.aparams.frag_size = cstream->runtime->fragment_size;
0153
0154 cb.param = cstream;
0155 cb.compr_cb = sst_compr_fragment_elapsed;
0156 cb.drain_cb_param = cstream;
0157 cb.drain_notify = sst_drain_notify;
0158
0159 retval = stream->compr_ops->open(sst->dev, &str_params, &cb);
0160 if (retval < 0) {
0161 pr_err("stream allocation failed %d\n", retval);
0162 return retval;
0163 }
0164
0165 stream->id = retval;
0166 return 0;
0167 }
0168
0169 static int sst_platform_compr_trigger(struct snd_soc_component *component,
0170 struct snd_compr_stream *cstream, int cmd)
0171 {
0172 struct sst_runtime_stream *stream = cstream->runtime->private_data;
0173
0174 switch (cmd) {
0175 case SNDRV_PCM_TRIGGER_START:
0176 if (stream->compr_ops->stream_start)
0177 return stream->compr_ops->stream_start(sst->dev, stream->id);
0178 break;
0179 case SNDRV_PCM_TRIGGER_STOP:
0180 if (stream->compr_ops->stream_drop)
0181 return stream->compr_ops->stream_drop(sst->dev, stream->id);
0182 break;
0183 case SND_COMPR_TRIGGER_DRAIN:
0184 if (stream->compr_ops->stream_drain)
0185 return stream->compr_ops->stream_drain(sst->dev, stream->id);
0186 break;
0187 case SND_COMPR_TRIGGER_PARTIAL_DRAIN:
0188 if (stream->compr_ops->stream_partial_drain)
0189 return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);
0190 break;
0191 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
0192 if (stream->compr_ops->stream_pause)
0193 return stream->compr_ops->stream_pause(sst->dev, stream->id);
0194 break;
0195 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
0196 if (stream->compr_ops->stream_pause_release)
0197 return stream->compr_ops->stream_pause_release(sst->dev, stream->id);
0198 break;
0199 }
0200 return -EINVAL;
0201 }
0202
0203 static int sst_platform_compr_pointer(struct snd_soc_component *component,
0204 struct snd_compr_stream *cstream,
0205 struct snd_compr_tstamp *tstamp)
0206 {
0207 struct sst_runtime_stream *stream;
0208
0209 stream = cstream->runtime->private_data;
0210 stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);
0211 tstamp->byte_offset = tstamp->copied_total %
0212 (u32)cstream->runtime->buffer_size;
0213 pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
0214 return 0;
0215 }
0216
0217 static int sst_platform_compr_ack(struct snd_soc_component *component,
0218 struct snd_compr_stream *cstream,
0219 size_t bytes)
0220 {
0221 struct sst_runtime_stream *stream;
0222
0223 stream = cstream->runtime->private_data;
0224 stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);
0225 stream->bytes_written += bytes;
0226
0227 return 0;
0228 }
0229
0230 static int sst_platform_compr_get_caps(struct snd_soc_component *component,
0231 struct snd_compr_stream *cstream,
0232 struct snd_compr_caps *caps)
0233 {
0234 struct sst_runtime_stream *stream =
0235 cstream->runtime->private_data;
0236
0237 return stream->compr_ops->get_caps(caps);
0238 }
0239
0240 static int sst_platform_compr_get_codec_caps(struct snd_soc_component *component,
0241 struct snd_compr_stream *cstream,
0242 struct snd_compr_codec_caps *codec)
0243 {
0244 struct sst_runtime_stream *stream =
0245 cstream->runtime->private_data;
0246
0247 return stream->compr_ops->get_codec_caps(codec);
0248 }
0249
0250 static int sst_platform_compr_set_metadata(struct snd_soc_component *component,
0251 struct snd_compr_stream *cstream,
0252 struct snd_compr_metadata *metadata)
0253 {
0254 struct sst_runtime_stream *stream =
0255 cstream->runtime->private_data;
0256
0257 return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);
0258 }
0259
0260 const struct snd_compress_ops sst_platform_compress_ops = {
0261
0262 .open = sst_platform_compr_open,
0263 .free = sst_platform_compr_free,
0264 .set_params = sst_platform_compr_set_params,
0265 .set_metadata = sst_platform_compr_set_metadata,
0266 .trigger = sst_platform_compr_trigger,
0267 .pointer = sst_platform_compr_pointer,
0268 .ack = sst_platform_compr_ack,
0269 .get_caps = sst_platform_compr_get_caps,
0270 .get_codec_caps = sst_platform_compr_get_codec_caps,
0271 };