SOC_VALUE_ENUM_DOUBLE_DECL(name, xreg, xshift, xshift, xmask, xtexts, xvalues)
/*
+ * Component probe and remove ordering levels for components with runtime
+ * dependencies.
+ */
+#define SND_SOC_COMP_ORDER_FIRST -2
+#define SND_SOC_COMP_ORDER_EARLY -1
+#define SND_SOC_COMP_ORDER_NORMAL 0
+#define SND_SOC_COMP_ORDER_LATE 1
+#define SND_SOC_COMP_ORDER_LAST 2
+
+/*
* Bias levels
*
* @ON: Bias is fully on for audio playback and capture operations.
void (*seq_notifier)(struct snd_soc_dapm_context *,
enum snd_soc_dapm_type, int);
+
+ /* probe ordering - for components with runtime dependencies */
+ int probe_order;
+ int remove_order;
};
/* SoC platform interface */
/* platform stream ops */
struct snd_pcm_ops *ops;
+
+ /* probe ordering - for components with runtime dependencies */
+ int probe_order;
+ int remove_order;
};
struct snd_soc_platform {
module_put(codec->dev->driver->owner);
}
-static void soc_remove_dai_link(struct snd_soc_card *card, int num)
+static void soc_remove_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_codec *codec = rtd->codec;
}
/* remove the CODEC DAI */
- if (codec_dai && codec_dai->probed) {
+ if (codec_dai && codec_dai->probed &&
+ codec_dai->driver->remove_order == order) {
if (codec_dai->driver->remove) {
err = codec_dai->driver->remove(codec_dai);
if (err < 0)
}
/* remove the platform */
- if (platform && platform->probed) {
+ if (platform && platform->probed &&
+ platform->driver->remove_order == order) {
if (platform->driver->remove) {
err = platform->driver->remove(platform);
if (err < 0)
}
/* remove the CODEC */
- if (codec && codec->probed)
+ if (codec && codec->probed &&
+ codec->driver->remove_order == order)
soc_remove_codec(codec);
/* remove the cpu_dai */
- if (cpu_dai && cpu_dai->probed) {
+ if (cpu_dai && cpu_dai->probed &&
+ cpu_dai->driver->remove_order == order) {
if (cpu_dai->driver->remove) {
err = cpu_dai->driver->remove(cpu_dai);
if (err < 0)
static void soc_remove_dai_links(struct snd_soc_card *card)
{
- int i;
-
- for (i = 0; i < card->num_rtd; i++)
- soc_remove_dai_link(card, i);
+ int dai, order;
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ for (dai = 0; dai < card->num_rtd; dai++)
+ soc_remove_dai_link(card, dai, order);
+ }
card->num_rtd = 0;
}
return 0;
}
-static int soc_probe_dai_link(struct snd_soc_card *card, int num)
+static int soc_probe_dai_link(struct snd_soc_card *card, int num, int order)
{
struct snd_soc_dai_link *dai_link = &card->dai_link[num];
struct snd_soc_pcm_runtime *rtd = &card->rtd[num];
struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai;
int ret;
- dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num);
+ dev_dbg(card->dev, "probe %s dai link %d late %d\n",
+ card->name, num, order);
/* config components */
codec_dai->codec = codec;
rtd->pmdown_time = pmdown_time;
/* probe the cpu_dai */
- if (!cpu_dai->probed) {
+ if (!cpu_dai->probed &&
+ cpu_dai->driver->probe_order == order) {
if (!try_module_get(cpu_dai->dev->driver->owner))
return -ENODEV;
}
/* probe the CODEC */
- if (!codec->probed) {
+ if (!codec->probed &&
+ codec->driver->probe_order == order) {
ret = soc_probe_codec(card, codec);
if (ret < 0)
return ret;
}
/* probe the platform */
- if (!platform->probed) {
+ if (!platform->probed &&
+ platform->driver->probe_order == order) {
if (!try_module_get(platform->dev->driver->owner))
return -ENODEV;
}
/* probe the CODEC DAI */
- if (!codec_dai->probed) {
+ if (!codec_dai->probed && codec_dai->driver->probe_order == order) {
if (codec_dai->driver->probe) {
ret = codec_dai->driver->probe(codec_dai);
if (ret < 0) {
list_add(&codec_dai->card_list, &card->dai_dev_list);
}
+ /* complete DAI probe during last probe */
+ if (order != SND_SOC_COMP_ORDER_LAST)
+ return 0;
+
/* DAPM dai link stream work */
INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work);
struct snd_soc_codec *codec;
struct snd_soc_codec_conf *codec_conf;
enum snd_soc_compress_type compress_type;
- int ret, i;
+ int ret, i, order;
mutex_lock(&card->mutex);
goto card_probe_error;
}
- for (i = 0; i < card->num_links; i++) {
- ret = soc_probe_dai_link(card, i);
- if (ret < 0) {
- pr_err("asoc: failed to instantiate card %s: %d\n",
+ /* early DAI link probe */
+ for (order = SND_SOC_COMP_ORDER_FIRST; order <= SND_SOC_COMP_ORDER_LAST;
+ order++) {
+ for (i = 0; i < card->num_links; i++) {
+ ret = soc_probe_dai_link(card, i, order);
+ if (ret < 0) {
+ pr_err("asoc: failed to instantiate card %s: %d\n",
card->name, ret);
- goto probe_dai_err;
+ goto probe_dai_err;
+ }
}
}