summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/sound/soc.h94
-rw-r--r--sound/soc/soc-compress.c461
-rw-r--r--sound/soc/soc-core.c192
-rw-r--r--sound/soc/soc-dapm.c8
-rw-r--r--sound/soc/soc-io.c14
-rw-r--r--sound/soc/soc-pcm.c459
6 files changed, 1090 insertions, 138 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h
index 580da1e4f141..0668cbd9f0b5 100644
--- a/include/sound/soc.h
+++ b/include/sound/soc.h
@@ -480,6 +480,8 @@ int devm_snd_soc_register_component(struct device *dev,
const struct snd_soc_component_driver *component_driver,
struct snd_soc_dai_driver *dai_drv, int num_dai);
void snd_soc_unregister_component(struct device *dev);
+struct snd_soc_component *snd_soc_lookup_component(struct device *dev,
+ const char *driver_name);
int snd_soc_cache_init(struct snd_soc_codec *codec);
int snd_soc_cache_exit(struct snd_soc_codec *codec);
@@ -800,6 +802,10 @@ struct snd_soc_component_driver {
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
+ /* pcm creation and destruction */
+ int (*pcm_new)(struct snd_soc_pcm_runtime *);
+ void (*pcm_free)(struct snd_pcm *);
+
/* component wide operations */
int (*set_sysclk)(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir);
@@ -817,10 +823,22 @@ struct snd_soc_component_driver {
void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type,
int subseq);
int (*stream_event)(struct snd_soc_component *, int event);
+ int (*set_bias_level)(struct snd_soc_component *component,
+ enum snd_soc_bias_level level);
+
+ const struct snd_pcm_ops *ops;
+ const struct snd_compr_ops *compr_ops;
/* probe ordering - for components with runtime dependencies */
int probe_order;
int remove_order;
+
+ /* bits */
+ unsigned int idle_bias_on:1;
+ unsigned int suspend_bias_off:1;
+ unsigned int pmdown_time:1; /* care pmdown_time at stop */
+ unsigned int endianness:1;
+ unsigned int non_legacy_dai_naming:1;
};
struct snd_soc_component {
@@ -877,6 +895,8 @@ struct snd_soc_component {
void (*remove)(struct snd_soc_component *);
int (*suspend)(struct snd_soc_component *);
int (*resume)(struct snd_soc_component *);
+ int (*pcm_new)(struct snd_soc_component *, struct snd_soc_pcm_runtime *);
+ void (*pcm_free)(struct snd_soc_component *, struct snd_pcm *);
int (*set_sysclk)(struct snd_soc_component *component,
int clk_id, int source, unsigned int freq, int dir);
@@ -884,6 +904,8 @@ struct snd_soc_component {
int source, unsigned int freq_in, unsigned int freq_out);
int (*set_jack)(struct snd_soc_component *component,
struct snd_soc_jack *jack, void *data);
+ int (*set_bias_level)(struct snd_soc_component *component,
+ enum snd_soc_bias_level level);
/* machine specific init */
int (*init)(struct snd_soc_component *component);
@@ -1418,6 +1440,21 @@ static inline void snd_soc_codec_init_bias_level(struct snd_soc_codec *codec,
}
/**
+ * snd_soc_component_init_bias_level() - Initialize COMPONENT DAPM bias level
+ * @component: The COMPONENT for which to initialize the DAPM bias level
+ * @level: The DAPM level to initialize to
+ *
+ * Initializes the COMPONENT DAPM bias level. See snd_soc_dapm_init_bias_level().
+ */
+static inline void
+snd_soc_component_init_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+{
+ snd_soc_dapm_init_bias_level(
+ snd_soc_component_get_dapm(component), level);
+}
+
+/**
* snd_soc_dapm_get_bias_level() - Get current CODEC DAPM bias level
* @codec: The CODEC for which to get the DAPM bias level
*
@@ -1430,6 +1467,19 @@ static inline enum snd_soc_bias_level snd_soc_codec_get_bias_level(
}
/**
+ * snd_soc_component_get_bias_level() - Get current COMPONENT DAPM bias level
+ * @component: The COMPONENT for which to get the DAPM bias level
+ *
+ * Returns: The current DAPM bias level of the COMPONENT.
+ */
+static inline enum snd_soc_bias_level
+snd_soc_component_get_bias_level(struct snd_soc_component *component)
+{
+ return snd_soc_dapm_get_bias_level(
+ snd_soc_component_get_dapm(component));
+}
+
+/**
* snd_soc_codec_force_bias_level() - Set the CODEC DAPM bias level
* @codec: The CODEC for which to set the level
* @level: The level to set to
@@ -1445,6 +1495,23 @@ static inline int snd_soc_codec_force_bias_level(struct snd_soc_codec *codec,
}
/**
+ * snd_soc_component_force_bias_level() - Set the COMPONENT DAPM bias level
+ * @component: The COMPONENT for which to set the level
+ * @level: The level to set to
+ *
+ * Forces the COMPONENT bias level to a specific state. See
+ * snd_soc_dapm_force_bias_level().
+ */
+static inline int
+snd_soc_component_force_bias_level(struct snd_soc_component *component,
+ enum snd_soc_bias_level level)
+{
+ return snd_soc_dapm_force_bias_level(
+ snd_soc_component_get_dapm(component),
+ level);
+}
+
+/**
* snd_soc_dapm_kcontrol_codec() - Returns the codec associated to a kcontrol
* @kcontrol: The kcontrol
*
@@ -1457,6 +1524,19 @@ static inline struct snd_soc_codec *snd_soc_dapm_kcontrol_codec(
return snd_soc_dapm_to_codec(snd_soc_dapm_kcontrol_dapm(kcontrol));
}
+/**
+ * snd_soc_dapm_kcontrol_component() - Returns the component associated to a kcontrol
+ * @kcontrol: The kcontrol
+ *
+ * This function must only be used on DAPM contexts that are known to be part of
+ * a COMPONENT (e.g. in a COMPONENT driver). Otherwise the behavior is undefined.
+ */
+static inline struct snd_soc_component *snd_soc_dapm_kcontrol_component(
+ struct snd_kcontrol *kcontrol)
+{
+ return snd_soc_dapm_to_component(snd_soc_dapm_kcontrol_dapm(kcontrol));
+}
+
/* codec IO */
unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg);
int snd_soc_write(struct snd_soc_codec *codec, unsigned int reg,
@@ -1473,9 +1553,23 @@ static inline int snd_soc_cache_sync(struct snd_soc_codec *codec)
return regcache_sync(codec->component.regmap);
}
+/**
+ * snd_soc_component_cache_sync() - Sync the register cache with the hardware
+ * @component: COMPONENT to sync
+ *
+ * Note: This function will call regcache_sync()
+ */
+static inline int snd_soc_component_cache_sync(
+ struct snd_soc_component *component)
+{
+ return regcache_sync(component->regmap);
+}
+
/* component IO */
int snd_soc_component_read(struct snd_soc_component *component,
unsigned int reg, unsigned int *val);
+unsigned int snd_soc_component_read32(struct snd_soc_component *component,
+ unsigned int reg);
int snd_soc_component_write(struct snd_soc_component *component,
unsigned int reg, unsigned int val);
int snd_soc_component_update_bits(struct snd_soc_component *component,
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c
index 2cb8d3b55fbc..d9b1e6417fb9 100644
--- a/sound/soc/soc-compress.c
+++ b/sound/soc/soc-compress.c
@@ -30,8 +30,10 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -44,7 +46,7 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
}
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
ret = platform->driver->compr_ops->open(cstream);
if (ret < 0) {
pr_err("compress asoc: can't open platform %s\n",
@@ -53,6 +55,27 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
}
}
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->open)
+ continue;
+
+ __ret = component->driver->compr_ops->open(cstream);
+ if (__ret < 0) {
+ pr_err("compress asoc: can't open platform %s\n",
+ component->name);
+ ret = __ret;
+ }
+ }
+ if (ret < 0)
+ goto machine_err;
+
if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) {
ret = rtd->dai_link->compr_ops->startup(cstream);
if (ret < 0) {
@@ -68,7 +91,21 @@ static int soc_compr_open(struct snd_compr_stream *cstream)
return 0;
machine_err:
- if (platform->driver->compr_ops && platform->driver->compr_ops->free)
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->free)
+ continue;
+
+ component->driver->compr_ops->free(cstream);
+ }
+
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
platform->driver->compr_ops->free(cstream);
plat_err:
if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
@@ -84,11 +121,13 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
struct snd_pcm_substream *fe_substream =
fe->pcm->streams[cstream->direction].substream;
struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
struct snd_soc_dpcm *dpcm;
struct snd_soc_dapm_widget_list *list;
int stream;
- int ret = 0;
+ int ret = 0, __ret;
if (cstream->direction == SND_COMPRESS_PLAYBACK)
stream = SNDRV_PCM_STREAM_PLAYBACK;
@@ -107,7 +146,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->open) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->open) {
ret = platform->driver->compr_ops->open(cstream);
if (ret < 0) {
pr_err("compress asoc: can't open platform %s\n",
@@ -116,6 +155,27 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream)
}
}
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->open)
+ continue;
+
+ __ret = component->driver->compr_ops->open(cstream);
+ if (__ret < 0) {
+ pr_err("compress asoc: can't open platform %s\n",
+ component->name);
+ ret = __ret;
+ }
+ }
+ if (ret < 0)
+ goto machine_err;
+
if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->startup) {
ret = fe->dai_link->compr_ops->startup(cstream);
if (ret < 0) {
@@ -167,7 +227,21 @@ fe_err:
if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
fe->dai_link->compr_ops->shutdown(cstream);
machine_err:
- if (platform->driver->compr_ops && platform->driver->compr_ops->free)
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->free)
+ continue;
+
+ component->driver->compr_ops->free(cstream);
+ }
+
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
platform->driver->compr_ops->free(cstream);
plat_err:
if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
@@ -210,6 +284,8 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
int stream;
@@ -235,7 +311,21 @@ static int soc_compr_free(struct snd_compr_stream *cstream)
if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown)
rtd->dai_link->compr_ops->shutdown(cstream);
- if (platform->driver->compr_ops && platform->driver->compr_ops->free)
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->free)
+ continue;
+
+ component->driver->compr_ops->free(cstream);
+ }
+
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
platform->driver->compr_ops->free(cstream);
if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
@@ -267,6 +357,8 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
{
struct snd_soc_pcm_runtime *fe = cstream->private_data;
struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
struct snd_soc_dpcm *dpcm;
int stream, ret;
@@ -304,9 +396,23 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream)
if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->shutdown)
fe->dai_link->compr_ops->shutdown(cstream);
- if (platform->driver->compr_ops && platform->driver->compr_ops->free)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->free)
platform->driver->compr_ops->free(cstream);
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->free)
+ continue;
+
+ component->driver->compr_ops->free(cstream);
+ }
+
if (cpu_dai->driver->cops && cpu_dai->driver->cops->shutdown)
cpu_dai->driver->cops->shutdown(cstream, cpu_dai);
@@ -319,18 +425,38 @@ static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd)
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
- if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
ret = platform->driver->compr_ops->trigger(cstream, cmd);
if (ret < 0)
goto out;
}
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->trigger)
+ continue;
+
+ __ret = component->driver->compr_ops->trigger(cstream, cmd);
+ if (__ret < 0)
+ ret = __ret;
+ }
+ if (ret < 0)
+ goto out;
+
if (cpu_dai->driver->cops && cpu_dai->driver->cops->trigger)
cpu_dai->driver->cops->trigger(cstream, cmd, cpu_dai);
@@ -353,16 +479,36 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
{
struct snd_soc_pcm_runtime *fe = cstream->private_data;
struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
- int ret = 0, stream;
+ int ret = 0, __ret, stream;
if (cmd == SND_COMPR_TRIGGER_PARTIAL_DRAIN ||
cmd == SND_COMPR_TRIGGER_DRAIN) {
- if (platform->driver->compr_ops &&
+ if (platform &&
+ platform->driver->compr_ops &&
platform->driver->compr_ops->trigger)
return platform->driver->compr_ops->trigger(cstream,
cmd);
+
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->trigger)
+ continue;
+
+ __ret = component->driver->compr_ops->trigger(cstream, cmd);
+ if (__ret < 0)
+ ret = __ret;
+ }
+ return ret;
}
if (cstream->direction == SND_COMPRESS_PLAYBACK)
@@ -379,12 +525,30 @@ static int soc_compr_trigger_fe(struct snd_compr_stream *cstream, int cmd)
goto out;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->trigger) {
ret = platform->driver->compr_ops->trigger(cstream, cmd);
if (ret < 0)
goto out;
}
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->trigger)
+ continue;
+
+ __ret = component->driver->compr_ops->trigger(cstream, cmd);
+ if (__ret < 0)
+ ret = __ret;
+ }
+ if (ret < 0)
+ goto out;
+
fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE;
ret = dpcm_be_dai_trigger(fe, stream, cmd);
@@ -415,8 +579,10 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -432,12 +598,30 @@ static int soc_compr_set_params(struct snd_compr_stream *cstream,
goto err;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
ret = platform->driver->compr_ops->set_params(cstream, params);
if (ret < 0)
goto err;
}
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->set_params)
+ continue;
+
+ __ret = component->driver->compr_ops->set_params(cstream, params);
+ if (__ret < 0)
+ ret = __ret;
+ }
+ if (ret < 0)
+ goto err;
+
if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) {
ret = rtd->dai_link->compr_ops->set_params(cstream);
if (ret < 0)
@@ -471,8 +655,10 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
struct snd_pcm_substream *fe_substream =
fe->pcm->streams[cstream->direction].substream;
struct snd_soc_platform *platform = fe->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = fe->cpu_dai;
- int ret = 0, stream;
+ int ret = 0, __ret, stream;
if (cstream->direction == SND_COMPRESS_PLAYBACK)
stream = SNDRV_PCM_STREAM_PLAYBACK;
@@ -487,12 +673,30 @@ static int soc_compr_set_params_fe(struct snd_compr_stream *cstream,
goto out;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_params) {
ret = platform->driver->compr_ops->set_params(cstream, params);
if (ret < 0)
goto out;
}
+ for_each_rtdcom(fe, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->set_params)
+ continue;
+
+ __ret = component->driver->compr_ops->set_params(cstream, params);
+ if (__ret < 0)
+ ret = __ret;
+ }
+ if (ret < 0)
+ goto out;
+
if (fe->dai_link->compr_ops && fe->dai_link->compr_ops->set_params) {
ret = fe->dai_link->compr_ops->set_params(cstream);
if (ret < 0)
@@ -531,8 +735,10 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -542,8 +748,27 @@ static int soc_compr_get_params(struct snd_compr_stream *cstream,
goto err;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->get_params)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_params) {
ret = platform->driver->compr_ops->get_params(cstream, params);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->get_params)
+ continue;
+
+ __ret = component->driver->compr_ops->get_params(cstream, params);
+ if (__ret < 0)
+ ret = __ret;
+ }
err:
mutex_unlock(&rtd->pcm_mutex);
@@ -555,13 +780,35 @@ static int soc_compr_get_caps(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
- int ret = 0;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
- if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_caps) {
ret = platform->driver->compr_ops->get_caps(cstream, caps);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->get_caps)
+ continue;
+
+ __ret = component->driver->compr_ops->get_caps(cstream, caps);
+ if (__ret < 0)
+ ret = __ret;
+ }
+
+err:
mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -571,13 +818,35 @@ static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
- int ret = 0;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
- if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) {
ret = platform->driver->compr_ops->get_codec_caps(cstream, codec);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->get_codec_caps)
+ continue;
+
+ __ret = component->driver->compr_ops->get_codec_caps(cstream, codec);
+ if (__ret < 0)
+ ret = __ret;
+ }
+
+err:
mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -586,8 +855,10 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -597,8 +868,27 @@ static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes)
goto err;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->ack)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->ack) {
ret = platform->driver->compr_ops->ack(cstream, bytes);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->ack)
+ continue;
+
+ __ret = component->driver->compr_ops->ack(cstream, bytes);
+ if (__ret < 0)
+ ret = __ret;
+ }
err:
mutex_unlock(&rtd->pcm_mutex);
@@ -610,7 +900,9 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
- int ret = 0;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
+ int ret = 0, __ret;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
@@ -618,9 +910,29 @@ static int soc_compr_pointer(struct snd_compr_stream *cstream,
if (cpu_dai->driver->cops && cpu_dai->driver->cops->pointer)
cpu_dai->driver->cops->pointer(cstream, tstamp, cpu_dai);
- if (platform->driver->compr_ops && platform->driver->compr_ops->pointer)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->pointer) {
ret = platform->driver->compr_ops->pointer(cstream, tstamp);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->pointer)
+ continue;
+ __ret = component->driver->compr_ops->pointer(cstream, tstamp);
+ if (__ret < 0)
+ ret = __ret;
+ }
+
+err:
mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -630,13 +942,34 @@ static int soc_compr_copy(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
- int ret = 0;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
+ int ret = 0, __ret;
mutex_lock_nested(&rtd->pcm_mutex, rtd->pcm_subclass);
- if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy) {
ret = platform->driver->compr_ops->copy(cstream, buf, count);
+ if (ret < 0)
+ goto err;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->copy)
+ continue;
+ __ret = component->driver->compr_ops->copy(cstream, buf, count);
+ if (__ret < 0)
+ ret = __ret;
+ }
+err:
mutex_unlock(&rtd->pcm_mutex);
return ret;
}
@@ -646,8 +979,10 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
if (cpu_dai->driver->cops && cpu_dai->driver->cops->set_metadata) {
ret = cpu_dai->driver->cops->set_metadata(cstream, metadata, cpu_dai);
@@ -655,8 +990,27 @@ static int soc_compr_set_metadata(struct snd_compr_stream *cstream,
return ret;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->set_metadata)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->set_metadata) {
ret = platform->driver->compr_ops->set_metadata(cstream, metadata);
+ if (ret < 0)
+ return ret;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->set_metadata)
+ continue;
+
+ __ret = component->driver->compr_ops->set_metadata(cstream, metadata);
+ if (__ret < 0)
+ ret = __ret;
+ }
return ret;
}
@@ -666,8 +1020,10 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
{
struct snd_soc_pcm_runtime *rtd = cstream->private_data;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
- int ret = 0;
+ int ret = 0, __ret;
if (cpu_dai->driver->cops && cpu_dai->driver->cops->get_metadata) {
ret = cpu_dai->driver->cops->get_metadata(cstream, metadata, cpu_dai);
@@ -675,8 +1031,27 @@ static int soc_compr_get_metadata(struct snd_compr_stream *cstream,
return ret;
}
- if (platform->driver->compr_ops && platform->driver->compr_ops->get_metadata)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->get_metadata) {
ret = platform->driver->compr_ops->get_metadata(cstream, metadata);
+ if (ret < 0)
+ return ret;
+ }
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->get_metadata)
+ continue;
+
+ __ret = component->driver->compr_ops->get_metadata(cstream, metadata);
+ if (__ret < 0)
+ ret = __ret;
+ }
return ret;
}
@@ -723,6 +1098,8 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
{
struct snd_soc_codec *codec = rtd->codec;
struct snd_soc_platform *platform = rtd->platform;
+ struct snd_soc_component *component;
+ struct snd_soc_rtdcom_list *rtdcom;
struct snd_soc_dai *codec_dai = rtd->codec_dai;
struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
struct snd_compr *compr;
@@ -798,9 +1175,25 @@ int snd_soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num)
memcpy(compr->ops, &soc_compr_ops, sizeof(soc_compr_ops));
}
+
/* Add copy callback for not memory mapped DSPs */
- if (platform->driver->compr_ops && platform->driver->compr_ops->copy)
+ if (platform && platform->driver->compr_ops && platform->driver->compr_ops->copy)
+ compr->ops->copy = soc_compr_copy;
+
+ for_each_rtdcom(rtd, rtdcom) {
+ component = rtdcom->component;
+
+ /* ignore duplication for now */
+ if (platform && (component == &platform->component))
+ continue;
+
+ if (!component->driver->compr_ops ||
+ !component->driver->compr_ops->copy)
+ continue;
+
compr->ops->copy = soc_compr_copy;
+ }
+
mutex_init(&compr->lock);
ret = snd_compress_new(rtd->card->snd_card, num, direction,
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 3a1c3b44de5e..533c822ca6e6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -614,6 +614,8 @@ struct snd_pcm_substream *snd_soc_get_dai_substream(struct snd_soc_card *card,
}
EXPORT_SYMBOL_GPL(snd_soc_get_dai_substream);
+static const struct snd_soc_ops null_snd_soc_ops;
+
static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
struct snd_soc_card *card, struct snd_soc_dai_link *dai_link)
{
@@ -626,6 +628,9 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
INIT_LIST_HEAD(&rtd->component_list);
rtd->card = card;
rtd->dai_link = dai_link;
+ if (!rtd->dai_link->ops)
+ rtd->dai_link->ops = &null_snd_soc_ops;
+
rtd->codec_dais = kzalloc(sizeof(struct snd_soc_dai *) *
dai_link->num_codecs,
GFP_KERNEL);
@@ -639,8 +644,7 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime(
static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd)
{
- if (rtd && rtd->codec_dais)
- kfree(rtd->codec_dais);
+ kfree(rtd->codec_dais);
snd_soc_rtdcom_del_all(rtd);
kfree(rtd);
}
@@ -2632,7 +2636,7 @@ EXPORT_SYMBOL_GPL(snd_soc_add_dai_controls);
int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id,
unsigned int freq, int dir)
{
- if (dai->driver && dai->driver->ops->set_sysclk)
+ if (dai->driver->ops->set_sysclk)
return dai->driver->ops->set_sysclk(dai, clk_id, freq, dir);
return snd_soc_component_set_sysclk(dai->component, clk_id, 0,
@@ -2700,7 +2704,7 @@ EXPORT_SYMBOL_GPL(snd_soc_component_set_sysclk);
int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai,
int div_id, int div)
{
- if (dai->driver && dai->driver->ops->set_clkdiv)
+ if (dai->driver->ops->set_clkdiv)
return dai->driver->ops->set_clkdiv(dai, div_id, div);
else
return -EINVAL;
@@ -2720,7 +2724,7 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv);
int snd_soc_dai_set_pll(struct snd_soc_da