summaryrefslogtreecommitdiffstats
path: root/sound/soc/mid-x86/sst_platform.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 07:07:14 +0900
committerLinus Torvalds <torvalds@linux-foundation.org>2012-10-09 07:07:14 +0900
commitf5a246eab9a268f51ba8189ea5b098a1bfff200e (patch)
treea6ff7169e0bcaca498d9aec8b0624de1b74eaecb /sound/soc/mid-x86/sst_platform.c
parentd5bbd43d5f450c3fca058f5b85f3dfb4e8cc88c9 (diff)
parent7ff34ad80b7080fafaac8efa9ef0061708eddd51 (diff)
downloadop-kernel-dev-f5a246eab9a268f51ba8189ea5b098a1bfff200e.zip
op-kernel-dev-f5a246eab9a268f51ba8189ea5b098a1bfff200e.tar.gz
Merge tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound
Pull sound updates from Takashi Iwai: "This contains pretty many small commits covering fairly large range of files in sound/ directory. Partly because of additional API support and partly because of constantly developed ASoC and ARM stuff. Some highlights: - Introduced the helper function and documentation for exposing the channel map via control API, as discussed in Plumbers; most of PCI drivers are covered, will follow more drivers later - Most of drivers have been replaced with the new PM callbacks (if the bus is supported) - HD-audio controller got the support of runtime PM and the support of D3 clock-stop. Also changing the power_save option in sysfs kicks off immediately to enable / disable the power-save mode. - Another significant code change in HD-audio is the rewrite of firmware loading code. Other than that, most of changes in HD-audio are continued cleanups and standardization for the generic auto parser and bug fixes (HBR, device-specific fixups), in addition to the support of channel-map API. - Addition of ASoC bindings for the compressed API, used by the mid-x86 drivers. - Lots of cleanups and API refreshes for ASoC codec drivers and DaVinci. - Conversion of OMAP to dmaengine. - New machine driver for Wolfson Microelectronics Bells. - New CODEC driver for Wolfson Microelectronics WM0010. - Enhancements to the ux500 and wm2000 drivers - A new driver for DA9055 and the support for regulator bypass mode." Fix up various arm soc header file reorg conflicts. * tag 'sound-3.7' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound: (339 commits) ALSA: hda - Add new codec ALC283 ALC290 support ALSA: hda - avoid unneccesary indices on "Headphone Jack" controls ALSA: hda - fix indices on boost volume on Conexant ALSA: aloop - add locking to timer access ALSA: hda - Fix hang caused by race during suspend. sound: Remove unnecessary semicolon ALSA: hda/realtek - Fix detection of ALC271X codec ALSA: hda - Add inverted internal mic quirk for Lenovo IdeaPad U310 ALSA: hda - make Realtek/Sigmatel/Conexant use the generic unsol event ALSA: hda - make a generic unsol event handler ASoC: codecs: Add DA9055 codec driver ASoC: eukrea-tlv320: Convert it to platform driver ALSA: ASoC: add DT bindings for CS4271 ASoC: wm_hubs: Ensure volume updates are handled during class W startup ASoC: wm5110: Adding missing volume update bits ASoC: wm5110: Add OUT3R support ASoC: wm5110: Add AEC loopback support ASoC: wm5110: Rename EPOUT to HPOUT3 ASoC: arizona: Add more clock rates ASoC: arizona: Add more DSP options for mixer input muxes ...
Diffstat (limited to 'sound/soc/mid-x86/sst_platform.c')
-rw-r--r--sound/soc/mid-x86/sst_platform.c204
1 files changed, 203 insertions, 1 deletions
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c
index d34563b..a263cbe 100644
--- a/sound/soc/mid-x86/sst_platform.c
+++ b/sound/soc/mid-x86/sst_platform.c
@@ -1,7 +1,7 @@
/*
* sst_platform.c - Intel MID Platform driver
*
- * Copyright (C) 2010 Intel Corp
+ * Copyright (C) 2010-2012 Intel Corp
* Author: Vinod Koul <vinod.koul@intel.com>
* Author: Harsha Priya <priya.harsha@intel.com>
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -32,6 +32,7 @@
#include <sound/pcm.h>
#include <sound/pcm_params.h>
#include <sound/soc.h>
+#include <sound/compress_driver.h>
#include "sst_platform.h"
static struct sst_device *sst;
@@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = {
.formats = SNDRV_PCM_FMTBIT_S24_LE,
},
},
+{
+ .name = "Compress-cpu-dai",
+ .compress_dai = 1,
+ .playback = {
+ .channels_min = SST_STEREO,
+ .channels_max = SST_STEREO,
+ .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000,
+ .formats = SNDRV_PCM_FMTBIT_S16_LE,
+ },
+},
};
/* helper functions */
@@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd)
}
return retval;
}
+
+/* compress stream operations */
+static void sst_compr_fragment_elapsed(void *arg)
+{
+ struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg;
+
+ pr_debug("fragment elapsed by driver\n");
+ if (cstream)
+ snd_compr_fragment_elapsed(cstream);
+}
+
+static int sst_platform_compr_open(struct snd_compr_stream *cstream)
+{
+
+ int ret_val = 0;
+ struct snd_compr_runtime *runtime = cstream->runtime;
+ struct sst_runtime_stream *stream;
+
+ stream = kzalloc(sizeof(*stream), GFP_KERNEL);
+ if (!stream)
+ return -ENOMEM;
+
+ spin_lock_init(&stream->status_lock);
+
+ /* get the sst ops */
+ if (!sst || !try_module_get(sst->dev->driver->owner)) {
+ pr_err("no device available to run\n");
+ ret_val = -ENODEV;
+ goto out_ops;
+ }
+ stream->compr_ops = sst->compr_ops;
+
+ stream->id = 0;
+ sst_set_stream_status(stream, SST_PLATFORM_INIT);
+ runtime->private_data = stream;
+ return 0;
+out_ops:
+ kfree(stream);
+ return ret_val;
+}
+
+static int sst_platform_compr_free(struct snd_compr_stream *cstream)
+{
+ struct sst_runtime_stream *stream;
+ int ret_val = 0, str_id;
+
+ stream = cstream->runtime->private_data;
+ /*need to check*/
+ str_id = stream->id;
+ if (str_id)
+ ret_val = stream->compr_ops->close(str_id);
+ module_put(sst->dev->driver->owner);
+ kfree(stream);
+ pr_debug("%s: %d\n", __func__, ret_val);
+ return 0;
+}
+
+static int sst_platform_compr_set_params(struct snd_compr_stream *cstream,
+ struct snd_compr_params *params)
+{
+ struct sst_runtime_stream *stream;
+ int retval;
+ struct snd_sst_params str_params;
+ struct sst_compress_cb cb;
+
+ stream = cstream->runtime->private_data;
+ /* construct fw structure for this*/
+ memset(&str_params, 0, sizeof(str_params));
+
+ str_params.ops = STREAM_OPS_PLAYBACK;
+ str_params.stream_type = SST_STREAM_TYPE_MUSIC;
+ str_params.device_type = SND_SST_DEVICE_COMPRESS;
+
+ switch (params->codec.id) {
+ case SND_AUDIOCODEC_MP3: {
+ str_params.codec = SST_CODEC_TYPE_MP3;
+ str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3;
+ str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in;
+ str_params.sparams.uc.mp3_params.pcm_wd_sz = 16;
+ break;
+ }
+
+ case SND_AUDIOCODEC_AAC: {
+ str_params.codec = SST_CODEC_TYPE_AAC;
+ str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC;
+ str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in;
+ str_params.sparams.uc.aac_params.pcm_wd_sz = 16;
+ if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS)
+ str_params.sparams.uc.aac_params.bs_format =
+ AAC_BIT_STREAM_ADTS;
+ else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW)
+ str_params.sparams.uc.aac_params.bs_format =
+ AAC_BIT_STREAM_RAW;
+ else {
+ pr_err("Undefined format%d\n", params->codec.format);
+ return -EINVAL;
+ }
+ str_params.sparams.uc.aac_params.externalsr =
+ params->codec.sample_rate;
+ break;
+ }
+
+ default:
+ pr_err("codec not supported, id =%d\n", params->codec.id);
+ return -EINVAL;
+ }
+
+ str_params.aparams.ring_buf_info[0].addr =
+ virt_to_phys(cstream->runtime->buffer);
+ str_params.aparams.ring_buf_info[0].size =
+ cstream->runtime->buffer_size;
+ str_params.aparams.sg_count = 1;
+ str_params.aparams.frag_size = cstream->runtime->fragment_size;
+
+ cb.param = cstream;
+ cb.compr_cb = sst_compr_fragment_elapsed;
+
+ retval = stream->compr_ops->open(&str_params, &cb);
+ if (retval < 0) {
+ pr_err("stream allocation failed %d\n", retval);
+ return retval;
+ }
+
+ stream->id = retval;
+ return 0;
+}
+
+static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd)
+{
+ struct sst_runtime_stream *stream =
+ cstream->runtime->private_data;
+
+ return stream->compr_ops->control(cmd, stream->id);
+}
+
+static int sst_platform_compr_pointer(struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp)
+{
+ struct sst_runtime_stream *stream;
+
+ stream = cstream->runtime->private_data;
+ stream->compr_ops->tstamp(stream->id, tstamp);
+ tstamp->byte_offset = tstamp->copied_total %
+ (u32)cstream->runtime->buffer_size;
+ pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset);
+ return 0;
+}
+
+static int sst_platform_compr_ack(struct snd_compr_stream *cstream,
+ size_t bytes)
+{
+ struct sst_runtime_stream *stream;
+
+ stream = cstream->runtime->private_data;
+ stream->compr_ops->ack(stream->id, (unsigned long)bytes);
+ stream->bytes_written += bytes;
+
+ return 0;
+}
+
+static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream,
+ struct snd_compr_caps *caps)
+{
+ struct sst_runtime_stream *stream =
+ cstream->runtime->private_data;
+
+ return stream->compr_ops->get_caps(caps);
+}
+
+static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream,
+ struct snd_compr_codec_caps *codec)
+{
+ struct sst_runtime_stream *stream =
+ cstream->runtime->private_data;
+
+ return stream->compr_ops->get_codec_caps(codec);
+}
+
+static struct snd_compr_ops sst_platform_compr_ops = {
+
+ .open = sst_platform_compr_open,
+ .free = sst_platform_compr_free,
+ .set_params = sst_platform_compr_set_params,
+ .trigger = sst_platform_compr_trigger,
+ .pointer = sst_platform_compr_pointer,
+ .ack = sst_platform_compr_ack,
+ .get_caps = sst_platform_compr_get_caps,
+ .get_codec_caps = sst_platform_compr_get_codec_caps,
+};
+
static struct snd_soc_platform_driver sst_soc_platform_drv = {
.ops = &sst_platform_ops,
+ .compr_ops = &sst_platform_compr_ops,
.pcm_new = sst_pcm_new,
.pcm_free = sst_pcm_free,
};
OpenPOWER on IntegriCloud