Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  *  sst_mfld_platform.c - Intel MID Platform driver
0004  *
0005  *  Copyright (C) 2010-2014 Intel Corp
0006  *  Author: Vinod Koul <vinod.koul@intel.com>
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 /* compress stream operations */
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     /* get the sst ops */
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     /* Turn on LPE */
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     /* Turn off LPE */
0083     sst->compr_ops->power(sst->dev, false);
0084 
0085     /*need to check*/
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     /* construct fw structure for this*/
0107     memset(&str_params, 0, sizeof(str_params));
0108 
0109     /* fill the device type and stream id to pass to SST driver */
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 };