[alsa-devel] [PATCH 6/6] ASoC: add Component level struct snd_pcm_ops
Kuninori Morimoto
kuninori.morimoto.gx at renesas.com
Mon Dec 19 08:38:36 CET 2016
From: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
In current ALSA SoC, Platform has struct snd_pcm_ops feature,
but it should be supported on Component level. This patch adds it.
If component level has it, many snd_pcm_ops can be called,
but, 1st ops function only will be used now. It should/will be
fixed in the future.
Signed-off-by: Kuninori Morimoto <kuninori.morimoto.gx at renesas.com>
---
include/sound/soc.h | 2 +
sound/soc/soc-core.c | 2 +
sound/soc/soc-pcm.c | 235 ++++++++++++++++++++++++++++++++++++++++-----------
3 files changed, 192 insertions(+), 47 deletions(-)
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 225e9b6..f3a3601 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -777,6 +777,7 @@ struct snd_soc_component_driver {
const struct snd_soc_dapm_route *dapm_routes;
unsigned int num_dapm_routes;
+ const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;
int (*probe)(struct snd_soc_component *);
@@ -857,6 +858,7 @@ struct snd_soc_component {
unsigned int num_dapm_routes;
struct snd_soc_codec *codec;
+ const struct snd_pcm_ops *ops;
const struct snd_compr_ops *compr_ops;
int (*probe)(struct snd_soc_component *);
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index ecadebe..ffa51ab 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3202,6 +3202,8 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform,
platform->component.pcm_free = snd_soc_platform_drv_pcm_free;
if (platform_drv->compr_ops)
platform->component.compr_ops = platform_drv->compr_ops;
+ if (platform_drv->ops)
+ platform->component.ops = platform_drv->ops;
#ifdef CONFIG_DEBUG_FS
platform->component.debugfs_prefix = "platform";
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index ff31bf5..82a3c73 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -450,6 +450,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
const char *codec_dai_name = "multicodec";
@@ -475,14 +476,22 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
}
}
- if (platform->driver->ops && platform->driver->ops->open) {
- ret = platform->driver->ops->open(substream);
- if (ret < 0) {
- dev_err(platform->dev, "ASoC: can't open platform"
- " %s: %d\n", platform->component.name, ret);
- goto platform_err;
+ ret = 0;
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->open) {
+ int _ret = ops->open(substream);
+
+ if (_ret < 0)
+ dev_err(component->dev,
+ "ASoC: can't open component %s: %d\n",
+ component->name, ret);
+ ret |= _ret;
}
}
+ if (ret < 0)
+ goto component_err;
for (i = 0; i < rtd->num_codecs; i++) {
codec_dai = rtd->codec_dais[i];
@@ -590,10 +599,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream)
codec_dai->driver->ops->shutdown(substream, codec_dai);
}
- if (platform->driver->ops && platform->driver->ops->close)
- platform->driver->ops->close(substream);
+component_err:
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->close)
+ ops->close(substream);
+ }
-platform_err:
if (cpu_dai->driver->ops->shutdown)
cpu_dai->driver->ops->shutdown(substream, cpu_dai);
out:
@@ -655,6 +668,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
int i;
@@ -687,8 +701,12 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
if (rtd->dai_link->ops && rtd->dai_link->ops->shutdown)
rtd->dai_link->ops->shutdown(substream);
- if (platform->driver->ops && platform->driver->ops->close)
- platform->driver->ops->close(substream);
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->close)
+ ops->close(substream);
+ }
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
if (snd_soc_runtime_ignore_pmdown_time(rtd)) {
@@ -740,7 +758,7 @@ static int soc_pcm_close(struct snd_pcm_substream *substream)
static int soc_pcm_prepare(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
int i, ret = 0;
@@ -756,12 +774,17 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream)
}
}
- if (platform->driver->ops && platform->driver->ops->prepare) {
- ret = platform->driver->ops->prepare(substream);
- if (ret < 0) {
- dev_err(platform->dev, "ASoC: platform prepare error:"
- " %d\n", ret);
- goto out;
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->prepare) {
+ ret = ops->prepare(substream);
+ if (ret < 0) {
+ dev_err(component->dev,
+ "ASoC: component prepare error: %d\n",
+ ret);
+ goto out;
+ }
}
}
@@ -846,7 +869,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
struct snd_pcm_hw_params *params)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
int i, ret = 0;
@@ -911,12 +934,16 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
if (ret < 0)
goto interface_err;
- if (platform->driver->ops && platform->driver->ops->hw_params) {
- ret = platform->driver->ops->hw_params(substream, params);
- if (ret < 0) {
- dev_err(platform->dev, "ASoC: %s hw params failed: %d\n",
- platform->component.name, ret);
- goto platform_err;
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->hw_params) {
+ ret = ops->hw_params(substream, params);
+ if (ret < 0) {
+ dev_err(component->dev, "ASoC: %s hw params failed: %d\n",
+ component->name, ret);
+ goto component_err;
+ }
}
}
@@ -930,7 +957,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
mutex_unlock(&rtd->pcm_mutex);
return ret;
-platform_err:
+component_err:
if (cpu_dai->driver->ops && cpu_dai->driver->ops->hw_free)
cpu_dai->driver->ops->hw_free(substream, cpu_dai);
@@ -958,7 +985,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream,
static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
bool playback = substream->stream == SNDRV_PCM_STREAM_PLAYBACK;
@@ -995,8 +1022,12 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
rtd->dai_link->ops->hw_free(substream);
/* free any DMA resources */
- if (platform->driver->ops && platform->driver->ops->hw_free)
- platform->driver->ops->hw_free(substream);
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->hw_free)
+ ops->hw_free(substream);
+ }
/* now free hw params for the DAIs */
for (i = 0; i < rtd->num_codecs; i++) {
@@ -1015,7 +1046,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream)
static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
int i, ret;
@@ -1030,10 +1061,14 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
}
}
- if (platform->driver->ops && platform->driver->ops->trigger) {
- ret = platform->driver->ops->trigger(substream, cmd);
- if (ret < 0)
- return ret;
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops && ops->trigger) {
+ ret = ops->trigger(substream, cmd);
+ if (ret < 0)
+ return ret;
+ }
}
if (cpu_dai->driver->ops && cpu_dai->driver->ops->trigger) {
@@ -1085,7 +1120,7 @@ static int soc_pcm_bespoke_trigger(struct snd_pcm_substream *substream,
static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai;
struct snd_pcm_runtime *runtime = substream->runtime;
@@ -1094,8 +1129,15 @@ static snd_pcm_uframes_t soc_pcm_pointer(struct snd_pcm_substream *substream)
snd_pcm_sframes_t codec_delay = 0;
int i;
- if (platform->driver->ops && platform->driver->ops->pointer)
- offset = platform->driver->ops->pointer(substream);
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->pointer) {
+ offset = ops->pointer(substream);
+ break;
+ }
+ }
if (cpu_dai->driver->ops && cpu_dai->driver->ops->delay)
delay += cpu_dai->driver->ops->delay(substream, cpu_dai);
@@ -2278,10 +2320,16 @@ static int soc_pcm_ioctl(struct snd_pcm_substream *substream,
unsigned int cmd, void *arg)
{
struct snd_soc_pcm_runtime *rtd = substream->private_data;
- struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->ioctl)
+ return ops->ioctl(substream, cmd, arg);
+ }
- if (platform->driver->ops && platform->driver->ops->ioctl)
- return platform->driver->ops->ioctl(substream, cmd, arg);
return snd_pcm_lib_ioctl(substream, cmd, arg);
}
@@ -2637,10 +2685,94 @@ static void soc_pcm_free(struct snd_pcm *pcm)
}
}
+static int soc_pcm_copy(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos,
+ void __user *buf, snd_pcm_uframes_t count)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->copy)
+ return ops->copy(substream, channel, pos, buf, count);
+ }
+
+ return -EIO;
+}
+
+static int soc_pcm_silence(struct snd_pcm_substream *substream, int channel,
+ snd_pcm_uframes_t pos, snd_pcm_uframes_t count)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->silence)
+ return ops->silence(substream, channel, pos, count);
+ }
+
+ return -EIO;
+}
+
+static struct page *soc_pcm_page(struct snd_pcm_substream *substream,
+ unsigned long offset)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->page)
+ return ops->page(substream, offset);
+ }
+
+ return ERR_PTR(-EIO);
+}
+
+static int soc_pcm_mmap(struct snd_pcm_substream *substream,
+ struct vm_area_struct *vma)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->mmap)
+ return ops->mmap(substream, vma);
+ }
+
+ return -EIO;
+}
+
+static int soc_pcm_ack(struct snd_pcm_substream *substream)
+{
+ struct snd_soc_pcm_runtime *rtd = substream->private_data;
+ struct snd_soc_component *component;
+
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ /* FIXME: It uses 1st function only now */
+ if (ops && ops->ack)
+ return ops->ack(substream);
+ }
+
+ return -EIO;
+}
+
/* create a new pcm */
int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
{
- struct snd_soc_platform *platform = rtd->platform;
struct snd_soc_dai *codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_component *component;
@@ -2738,12 +2870,21 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num)
rtd->ops.ioctl = soc_pcm_ioctl;
}
- if (platform->driver->ops) {
- rtd->ops.ack = platform->driver->ops->ack;
- rtd->ops.copy = platform->driver->ops->copy;
- rtd->ops.silence = platform->driver->ops->silence;
- rtd->ops.page = platform->driver->ops->page;
- rtd->ops.mmap = platform->driver->ops->mmap;
+ for_each_component(component, rtd->card) {
+ const struct snd_pcm_ops *ops = component->ops;
+
+ if (ops) {
+ if (ops->ack)
+ rtd->ops.ack = soc_pcm_ack;
+ if (ops->copy)
+ rtd->ops.copy = soc_pcm_copy;
+ if (ops->silence)
+ rtd->ops.silence = soc_pcm_silence;
+ if (ops->page)
+ rtd->ops.page = soc_pcm_page;
+ if (ops->mmap)
+ rtd->ops.mmap = soc_pcm_mmap;
+ }
}
if (playback)
--
1.9.1
More information about the Alsa-devel
mailing list