root/sound/soc/intel/atom/sst-mfld-platform-compress.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. sst_compr_fragment_elapsed
  2. sst_drain_notify
  3. sst_platform_compr_open
  4. sst_platform_compr_free
  5. sst_platform_compr_set_params
  6. sst_platform_compr_trigger
  7. sst_platform_compr_pointer
  8. sst_platform_compr_ack
  9. sst_platform_compr_get_caps
  10. sst_platform_compr_get_codec_caps
  11. sst_platform_compr_set_metadata

   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 };

/* [<][>][^][v][top][bottom][index][help] */