brintos

brintos / linux-shallow public Read only

0
0
Text · 7.7 KiB · 89c9c5a Raw
272 lines · c
1// SPDX-License-Identifier: GPL-2.0-only2/*3 *  sst_mfld_platform.c - Intel MID Platform driver4 *5 *  Copyright (C) 2010-2014 Intel Corp6 *  Author: Vinod Koul <vinod.koul@intel.com>7 *  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~8 *9 * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~10 */11#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt12 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 */24static 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 33static 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 42static 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;70out_ops:71	kfree(stream);72	return ret_val;73}74 75static 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 95static 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 169static 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 203static 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 217static 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 230static 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 240static 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 250static 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 260const 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