Path: blob/master/sound/soc/intel/atom/sst-mfld-platform-compress.c
26493 views
// SPDX-License-Identifier: GPL-2.0-only1/*2* sst_mfld_platform.c - Intel MID Platform driver3*4* Copyright (C) 2010-2014 Intel Corp5* Author: Vinod Koul <[email protected]>6* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~7*8* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~9*/10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt1112#include <linux/slab.h>13#include <linux/io.h>14#include <linux/module.h>15#include <sound/core.h>16#include <sound/pcm.h>17#include <sound/pcm_params.h>18#include <sound/soc.h>19#include <sound/compress_driver.h>20#include "sst-mfld-platform.h"2122/* compress stream operations */23static void sst_compr_fragment_elapsed(void *arg)24{25struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;2627pr_debug("fragment elapsed by driver\n");28if (cstream)29snd_compr_fragment_elapsed(cstream);30}3132static void sst_drain_notify(void *arg)33{34struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;3536pr_debug("drain notify by driver\n");37if (cstream)38snd_compr_drain_notify(cstream);39}4041static int sst_platform_compr_open(struct snd_soc_component *component,42struct snd_compr_stream *cstream)43{44int ret_val;45struct snd_compr_runtime *runtime = cstream->runtime;46struct sst_runtime_stream *stream;4748stream = kzalloc(sizeof(*stream), GFP_KERNEL);49if (!stream)50return -ENOMEM;5152spin_lock_init(&stream->status_lock);5354/* get the sst ops */55if (!sst || !try_module_get(sst->dev->driver->owner)) {56pr_err("no device available to run\n");57ret_val = -ENODEV;58goto out_ops;59}60stream->compr_ops = sst->compr_ops;61stream->id = 0;6263/* Turn on LPE */64sst->compr_ops->power(sst->dev, true);6566sst_set_stream_status(stream, SST_PLATFORM_INIT);67runtime->private_data = stream;68return 0;69out_ops:70kfree(stream);71return ret_val;72}7374static int sst_platform_compr_free(struct snd_soc_component *component,75struct snd_compr_stream *cstream)76{77struct sst_runtime_stream *stream;78int ret_val = 0, str_id;7980stream = cstream->runtime->private_data;81/* Turn off LPE */82sst->compr_ops->power(sst->dev, false);8384/*need to check*/85str_id = stream->id;86if (str_id)87ret_val = stream->compr_ops->close(sst->dev, str_id);88module_put(sst->dev->driver->owner);89kfree(stream);90pr_debug("%s: %d\n", __func__, ret_val);91return 0;92}9394static int sst_platform_compr_set_params(struct snd_soc_component *component,95struct snd_compr_stream *cstream,96struct snd_compr_params *params)97{98struct sst_runtime_stream *stream;99int retval;100struct snd_sst_params str_params;101struct sst_compress_cb cb;102struct sst_data *ctx = snd_soc_component_get_drvdata(component);103104stream = cstream->runtime->private_data;105/* construct fw structure for this*/106memset(&str_params, 0, sizeof(str_params));107108/* fill the device type and stream id to pass to SST driver */109retval = sst_fill_stream_params(cstream, ctx, &str_params, true);110pr_debug("compr_set_params: fill stream params ret_val = 0x%x\n", retval);111if (retval < 0)112return retval;113114switch (params->codec.id) {115case SND_AUDIOCODEC_MP3: {116str_params.codec = SST_CODEC_TYPE_MP3;117str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;118str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;119break;120}121122case SND_AUDIOCODEC_AAC: {123str_params.codec = SST_CODEC_TYPE_AAC;124str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;125str_params.sparams.uc.aac_params.pcm_wd_sz = 16;126if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)127str_params.sparams.uc.aac_params.bs_format =128AAC_BIT_STREAM_ADTS;129else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)130str_params.sparams.uc.aac_params.bs_format =131AAC_BIT_STREAM_RAW;132else {133pr_err("Undefined format%d\n", params->codec.format);134return -EINVAL;135}136str_params.sparams.uc.aac_params.externalsr =137params->codec.sample_rate;138break;139}140141default:142pr_err("codec not supported, id =%d\n", params->codec.id);143return -EINVAL;144}145146str_params.aparams.ring_buf_info[0].addr =147virt_to_phys(cstream->runtime->buffer);148str_params.aparams.ring_buf_info[0].size =149cstream->runtime->buffer_size;150str_params.aparams.sg_count = 1;151str_params.aparams.frag_size = cstream->runtime->fragment_size;152153cb.param = cstream;154cb.compr_cb = sst_compr_fragment_elapsed;155cb.drain_cb_param = cstream;156cb.drain_notify = sst_drain_notify;157158retval = stream->compr_ops->open(sst->dev, &str_params, &cb);159if (retval < 0) {160pr_err("stream allocation failed %d\n", retval);161return retval;162}163164stream->id = retval;165return 0;166}167168static int sst_platform_compr_trigger(struct snd_soc_component *component,169struct snd_compr_stream *cstream, int cmd)170{171struct sst_runtime_stream *stream = cstream->runtime->private_data;172173switch (cmd) {174case SNDRV_PCM_TRIGGER_START:175if (stream->compr_ops->stream_start)176return stream->compr_ops->stream_start(sst->dev, stream->id);177break;178case SNDRV_PCM_TRIGGER_STOP:179if (stream->compr_ops->stream_drop)180return stream->compr_ops->stream_drop(sst->dev, stream->id);181break;182case SND_COMPR_TRIGGER_DRAIN:183if (stream->compr_ops->stream_drain)184return stream->compr_ops->stream_drain(sst->dev, stream->id);185break;186case SND_COMPR_TRIGGER_PARTIAL_DRAIN:187if (stream->compr_ops->stream_partial_drain)188return stream->compr_ops->stream_partial_drain(sst->dev, stream->id);189break;190case SNDRV_PCM_TRIGGER_PAUSE_PUSH:191if (stream->compr_ops->stream_pause)192return stream->compr_ops->stream_pause(sst->dev, stream->id);193break;194case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:195if (stream->compr_ops->stream_pause_release)196return stream->compr_ops->stream_pause_release(sst->dev, stream->id);197break;198}199return -EINVAL;200}201202static int sst_platform_compr_pointer(struct snd_soc_component *component,203struct snd_compr_stream *cstream,204struct snd_compr_tstamp *tstamp)205{206struct sst_runtime_stream *stream;207208stream = cstream->runtime->private_data;209stream->compr_ops->tstamp(sst->dev, stream->id, tstamp);210tstamp->byte_offset = tstamp->copied_total %211(u32)cstream->runtime->buffer_size;212pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);213return 0;214}215216static int sst_platform_compr_ack(struct snd_soc_component *component,217struct snd_compr_stream *cstream,218size_t bytes)219{220struct sst_runtime_stream *stream;221222stream = cstream->runtime->private_data;223stream->compr_ops->ack(sst->dev, stream->id, (unsigned long)bytes);224stream->bytes_written += bytes;225226return 0;227}228229static int sst_platform_compr_get_caps(struct snd_soc_component *component,230struct snd_compr_stream *cstream,231struct snd_compr_caps *caps)232{233struct sst_runtime_stream *stream =234cstream->runtime->private_data;235236return stream->compr_ops->get_caps(caps);237}238239static int sst_platform_compr_get_codec_caps(struct snd_soc_component *component,240struct snd_compr_stream *cstream,241struct snd_compr_codec_caps *codec)242{243struct sst_runtime_stream *stream =244cstream->runtime->private_data;245246return stream->compr_ops->get_codec_caps(codec);247}248249static int sst_platform_compr_set_metadata(struct snd_soc_component *component,250struct snd_compr_stream *cstream,251struct snd_compr_metadata *metadata)252{253struct sst_runtime_stream *stream =254cstream->runtime->private_data;255256return stream->compr_ops->set_metadata(sst->dev, stream->id, metadata);257}258259const struct snd_compress_ops sst_platform_compress_ops = {260261.open = sst_platform_compr_open,262.free = sst_platform_compr_free,263.set_params = sst_platform_compr_set_params,264.set_metadata = sst_platform_compr_set_metadata,265.trigger = sst_platform_compr_trigger,266.pointer = sst_platform_compr_pointer,267.ack = sst_platform_compr_ack,268.get_caps = sst_platform_compr_get_caps,269.get_codec_caps = sst_platform_compr_get_codec_caps,270};271272273