summaryrefslogtreecommitdiff
path: root/sound/soc/soc-component.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2020-12-14 17:57:14 +0300
committerTakashi Iwai <tiwai@suse.de>2020-12-14 17:57:14 +0300
commit598100be3053fef628adf3ad6ee4f828ad308f64 (patch)
tree78069fd27e04f19fb14043ce16122ed1a6df1886 /sound/soc/soc-component.c
parent175b8d89fe292796811fdee87fa39799a5b6b87a (diff)
parent460aa020f56c974a3e7e5b5378b2355fec6a2c11 (diff)
downloadlinux-598100be3053fef628adf3ad6ee4f828ad308f64.tar.xz
Merge tag 'asoc-v5.11' of https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v5.11 There's a lot of changes here but mostly cleanups and driver specific things, the most user visible change is the support for boot time selection of Intel DSP firmware which will make it easier for people to move over to the preferred modern implementations in distros and other large scale deployments. This also includes a merge of the new auxillary bus which was done in anticipation of use by the Intel DSP drivers which didn't quite make it. - Lots more cleanups and simplifications from Morimoto-san. - Support for some basic DPCM systems in the audio graph card from Sameer Pujar. - Remove some old pre-DT Freescale drivers for platforms that are now DT only. - Move selection of which Intel DSP implementation to use to boot time rather than requiring it to be selected at build time. - Support for Allwinner H6 I2S, Analog Devices ADAU1372, Intel Alderlake-S, GMediatek MT8192, NXP i.MX HDMI and XCVR, Realtek RT715, Qualcomm SM8250 and simple GPIO based muxes.
Diffstat (limited to 'sound/soc/soc-component.c')
-rw-r--r--sound/soc/soc-component.c318
1 files changed, 301 insertions, 17 deletions
diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c
index 728e93f35ffb..760523382f3c 100644
--- a/sound/soc/soc-component.c
+++ b/sound/soc/soc-component.c
@@ -421,6 +421,260 @@ EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap);
#endif
+int snd_soc_component_compr_open(struct snd_compr_stream *cstream)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->open) {
+ ret = component->driver->compress_ops->open(component, cstream);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ soc_component_mark_push(component, cstream, compr_open);
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_open);
+
+void snd_soc_component_compr_free(struct snd_compr_stream *cstream,
+ int rollback)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (rollback && !soc_component_mark_match(component, cstream, compr_open))
+ continue;
+
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->free)
+ component->driver->compress_ops->free(component, cstream);
+
+ soc_component_mark_pop(component, cstream, compr_open);
+ }
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_free);
+
+int snd_soc_component_compr_trigger(struct snd_compr_stream *cstream, int cmd)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->trigger) {
+ ret = component->driver->compress_ops->trigger(
+ component, cstream, cmd);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_trigger);
+
+int snd_soc_component_compr_set_params(struct snd_compr_stream *cstream,
+ struct snd_compr_params *params)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->set_params) {
+ ret = component->driver->compress_ops->set_params(
+ component, cstream, params);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_params);
+
+int snd_soc_component_compr_get_params(struct snd_compr_stream *cstream,
+ struct snd_codec *params)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->get_params) {
+ ret = component->driver->compress_ops->get_params(
+ component, cstream, params);
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_params);
+
+int snd_soc_component_compr_get_caps(struct snd_compr_stream *cstream,
+ struct snd_compr_caps *caps)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret = 0;
+
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->get_caps) {
+ ret = component->driver->compress_ops->get_caps(
+ component, cstream, caps);
+ break;
+ }
+ }
+
+ mutex_unlock(&rtd->card->pcm_mutex);
+
+ return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_caps);
+
+int snd_soc_component_compr_get_codec_caps(struct snd_compr_stream *cstream,
+ struct snd_compr_codec_caps *codec)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret = 0;
+
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->get_codec_caps) {
+ ret = component->driver->compress_ops->get_codec_caps(
+ component, cstream, codec);
+ break;
+ }
+ }
+
+ mutex_unlock(&rtd->card->pcm_mutex);
+
+ return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_codec_caps);
+
+int snd_soc_component_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->ack) {
+ ret = component->driver->compress_ops->ack(
+ component, cstream, bytes);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_ack);
+
+int snd_soc_component_compr_pointer(struct snd_compr_stream *cstream,
+ struct snd_compr_tstamp *tstamp)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->pointer) {
+ ret = component->driver->compress_ops->pointer(
+ component, cstream, tstamp);
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_pointer);
+
+int snd_soc_component_compr_copy(struct snd_compr_stream *cstream,
+ char __user *buf, size_t count)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret = 0;
+
+ mutex_lock_nested(&rtd->card->pcm_mutex, rtd->card->pcm_subclass);
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->copy) {
+ ret = component->driver->compress_ops->copy(
+ component, cstream, buf, count);
+ break;
+ }
+ }
+
+ mutex_unlock(&rtd->card->pcm_mutex);
+
+ return soc_component_ret(component, ret);
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_copy);
+
+int snd_soc_component_compr_set_metadata(struct snd_compr_stream *cstream,
+ struct snd_compr_metadata *metadata)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->set_metadata) {
+ ret = component->driver->compress_ops->set_metadata(
+ component, cstream, metadata);
+ if (ret < 0)
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_set_metadata);
+
+int snd_soc_component_compr_get_metadata(struct snd_compr_stream *cstream,
+ struct snd_compr_metadata *metadata)
+{
+ struct snd_soc_pcm_runtime *rtd = cstream->private_data;
+ struct snd_soc_component *component;
+ int i, ret;
+
+ for_each_rtd_components(rtd, i, component) {
+ if (component->driver->compress_ops &&
+ component->driver->compress_ops->get_metadata) {
+ ret = component->driver->compress_ops->get_metadata(
+ component, cstream, metadata);
+ return soc_component_ret(component, ret);
+ }
+ }
+
+ return 0;
+}
+EXPORT_SYMBOL_GPL(snd_soc_component_compr_get_metadata);
+
static unsigned int soc_component_read_no_lock(
struct snd_soc_component *component,
unsigned int reg)
@@ -779,8 +1033,7 @@ int snd_soc_pcm_component_prepare(struct snd_pcm_substream *substream)
}
int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
- struct snd_pcm_hw_params *params,
- struct snd_soc_component **last)
+ struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component;
@@ -790,52 +1043,83 @@ int snd_soc_pcm_component_hw_params(struct snd_pcm_substream *substream,
if (component->driver->hw_params) {
ret = component->driver->hw_params(component,
substream, params);
- if (ret < 0) {
- *last = component;
+ if (ret < 0)
return soc_component_ret(component, ret);
- }
}
+ /* mark substream if succeeded */
+ soc_component_mark_push(component, substream, hw_params);
}
- *last = NULL;
return 0;
}
void snd_soc_pcm_component_hw_free(struct snd_pcm_substream *substream,
- struct snd_soc_component *last)
+ int rollback)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component;
int i, ret;
for_each_rtd_components(rtd, i, component) {
- if (component == last)
- break;
+ if (rollback && !soc_component_mark_match(component, substream, hw_params))
+ continue;
if (component->driver->hw_free) {
ret = component->driver->hw_free(component, substream);
if (ret < 0)
soc_component_ret(component, ret);
}
+
+ /* remove marked substream */
+ soc_component_mark_pop(component, substream, hw_params);
}
}
+static int soc_component_trigger(struct snd_soc_component *component,
+ struct snd_pcm_substream *substream,
+ int cmd)
+{
+ int ret = 0;
+
+ if (component->driver->trigger)
+ ret = component->driver->trigger(component, substream, cmd);
+
+ return soc_component_ret(component, ret);
+}
+
int snd_soc_pcm_component_trigger(struct snd_pcm_substream *substream,
- int cmd)
+ int cmd, int rollback)
{
struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream);
struct snd_soc_component *component;
- int i, ret;
-
- for_each_rtd_components(rtd, i, component) {
- if (component->driver->trigger) {
- ret = component->driver->trigger(component, substream, cmd);
+ int i, r, ret = 0;
+
+ switch (cmd) {
+ case SNDRV_PCM_TRIGGER_START:
+ case SNDRV_PCM_TRIGGER_RESUME:
+ case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
+ for_each_rtd_components(rtd, i, component) {
+ ret = soc_component_trigger(component, substream, cmd);
if (ret < 0)
- return soc_component_ret(component, ret);
+ break;
+ soc_component_mark_push(component, substream, trigger);
+ }
+ break;
+ case SNDRV_PCM_TRIGGER_STOP:
+ case SNDRV_PCM_TRIGGER_SUSPEND:
+ case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
+ for_each_rtd_components(rtd, i, component) {
+ if (rollback && !soc_component_mark_match(component, substream, trigger))
+ continue;
+
+ r = soc_component_trigger(component, substream, cmd);
+ if (r < 0)
+ ret = r; /* use last ret */
+ soc_component_mark_pop(component, substream, trigger);
}
}
- return 0;
+ return ret;
}
int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd,