Commit bce93a16 authored by AngeloGioacchino Del Regno's avatar AngeloGioacchino Del Regno Committed by Mark Brown

ASoC: mediatek: Add common machine soundcard driver probe mechanism

Add a common machine soundcard driver probe function that supports both
DSP and AFE-direct usecases and also provides a hook for legacy machine
soundcard driver probe mechanisms.

Note that the hook is there because, even for legacy probe, a lot of the
actual code can still be commonized, hence still reducing duplication
for the legacy devicetree retrocompatibility cases.

This common probe function deprecates all of the inconsistent previous
probe mechanisms and aims to settle all of the MediaTek card drivers on
consistent and common devicetree properties describing wanted DAIs,
device specific DAI configuration and DAI links to codecs found on
each device/board.
Reviewed-by: default avatarAlexandre Mergnat <amergnat@baylibre.com>
Signed-off-by: default avatarAngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
Link: https://lore.kernel.org/r/20240416071410.75620-2-angelogioacchino.delregno@collabora.comSigned-off-by: default avatarMark Brown <broonie@kernel.org>
parent 62c48dd3
...@@ -9,9 +9,14 @@ ...@@ -9,9 +9,14 @@
#ifndef _MTK_SOC_CARD_H_ #ifndef _MTK_SOC_CARD_H_
#define _MTK_SOC_CARD_H_ #define _MTK_SOC_CARD_H_
struct mtk_platform_card_data;
struct mtk_sof_priv;
struct mtk_soc_card_data { struct mtk_soc_card_data {
struct mtk_sof_priv *sof_priv;
struct list_head sof_dai_link_list;
struct mtk_platform_card_data *card_data;
void *mach_priv; void *mach_priv;
void *sof_priv;
}; };
#endif #endif
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <linux/of.h> #include <linux/of.h>
#include <sound/soc.h> #include <sound/soc.h>
#include "mtk-dsp-sof-common.h"
#include "mtk-soc-card.h"
#include "mtk-soundcard-driver.h" #include "mtk-soundcard-driver.h"
static int set_card_codec_info(struct snd_soc_card *card, static int set_card_codec_info(struct snd_soc_card *card,
...@@ -136,3 +138,149 @@ void clean_card_reference(struct snd_soc_card *card) ...@@ -136,3 +138,149 @@ void clean_card_reference(struct snd_soc_card *card)
snd_soc_of_put_dai_link_codecs(dai_link); snd_soc_of_put_dai_link_codecs(dai_link);
} }
EXPORT_SYMBOL_GPL(clean_card_reference); EXPORT_SYMBOL_GPL(clean_card_reference);
int mtk_soundcard_common_probe(struct platform_device *pdev)
{
struct device_node *platform_node, *adsp_node;
const struct mtk_soundcard_pdata *pdata;
struct mtk_soc_card_data *soc_card_data;
struct snd_soc_dai_link *orig_dai_link, *dai_link;
struct snd_soc_jack *jacks;
struct snd_soc_card *card;
int i, orig_num_links, ret;
bool needs_legacy_probe;
pdata = device_get_match_data(&pdev->dev);
if (!pdata)
return -EINVAL;
card = pdata->card_data->card;
card->dev = &pdev->dev;
orig_dai_link = card->dai_link;
orig_num_links = card->num_links;
ret = snd_soc_of_parse_card_name(card, "model");
if (ret)
return ret;
if (!card->name) {
if (!pdata->card_name)
return -EINVAL;
card->name = pdata->card_name;
}
needs_legacy_probe = !of_property_read_bool(pdev->dev.of_node, "audio-routing");
if (needs_legacy_probe) {
/*
* If we have no .soc_probe() callback there's no way of using
* any legacy probe mechanism, as that cannot not be generic.
*/
if (!pdata->soc_probe)
return -EINVAL;
dev_info_once(&pdev->dev, "audio-routing not found: using legacy probe\n");
} else {
ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
if (ret)
return ret;
}
soc_card_data = devm_kzalloc(&pdev->dev, sizeof(*soc_card_data), GFP_KERNEL);
if (!soc_card_data)
return -ENOMEM;
soc_card_data->card_data = pdata->card_data;
jacks = devm_kcalloc(card->dev, soc_card_data->card_data->num_jacks,
sizeof(*jacks), GFP_KERNEL);
if (!jacks)
return -ENOMEM;
soc_card_data->card_data->jacks = jacks;
platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0);
if (!platform_node)
return dev_err_probe(&pdev->dev, -EINVAL,
"Property mediatek,platform missing or invalid\n");
/* Check if this SoC has an Audio DSP */
if (pdata->sof_priv)
adsp_node = of_parse_phandle(pdev->dev.of_node, "mediatek,adsp", 0);
else
adsp_node = NULL;
if (adsp_node) {
if (of_property_read_bool(pdev->dev.of_node, "mediatek,dai-link")) {
ret = mtk_sof_dailink_parse_of(card, pdev->dev.of_node,
"mediatek,dai-link",
card->dai_link, card->num_links);
if (ret) {
of_node_put(adsp_node);
of_node_put(platform_node);
return dev_err_probe(&pdev->dev, ret,
"Cannot parse mediatek,dai-link\n");
}
}
soc_card_data->sof_priv = pdata->sof_priv;
card->probe = mtk_sof_card_probe;
card->late_probe = mtk_sof_card_late_probe;
if (!card->topology_shortname_created) {
snprintf(card->topology_shortname, 32, "sof-%s", card->name);
card->topology_shortname_created = true;
}
card->name = card->topology_shortname;
}
/*
* Regardless of whether the ADSP is wanted and/or present in a machine
* specific device tree or not and regardless of whether any AFE_SOF
* link is present, we have to make sure that the platforms->of_node
* is not NULL, and set to either ADSP (adsp_node) or AFE (platform_node).
*/
for_each_card_prelinks(card, i, dai_link) {
if (adsp_node && !strncmp(dai_link->name, "AFE_SOF", strlen("AFE_SOF")))
dai_link->platforms->of_node = adsp_node;
else if (!dai_link->platforms->name && !dai_link->platforms->of_node)
dai_link->platforms->of_node = platform_node;
}
if (!needs_legacy_probe) {
ret = parse_dai_link_info(card);
if (ret)
goto err_restore_dais;
} else {
if (adsp_node)
of_node_put(adsp_node);
of_node_put(platform_node);
}
if (pdata->soc_probe) {
ret = pdata->soc_probe(soc_card_data, needs_legacy_probe);
if (ret) {
if (!needs_legacy_probe)
clean_card_reference(card);
goto err_restore_dais;
}
}
snd_soc_card_set_drvdata(card, soc_card_data);
ret = devm_snd_soc_register_card(&pdev->dev, card);
if (!needs_legacy_probe)
clean_card_reference(card);
if (ret) {
dev_err_probe(&pdev->dev, ret, "Cannot register card\n");
goto err_restore_dais;
}
return 0;
err_restore_dais:
card->dai_link = orig_dai_link;
card->num_links = orig_num_links;
return ret;
}
EXPORT_SYMBOL_GPL(mtk_soundcard_common_probe);
...@@ -9,6 +9,24 @@ ...@@ -9,6 +9,24 @@
#ifndef _MTK_SOUNDCARD_DRIVER_H_ #ifndef _MTK_SOUNDCARD_DRIVER_H_
#define _MTK_SOUNDCARD_DRIVER_H_ #define _MTK_SOUNDCARD_DRIVER_H_
struct mtk_sof_priv;
struct mtk_soc_card_data;
struct mtk_platform_card_data {
struct snd_soc_card *card;
struct snd_soc_jack *jacks;
u8 num_jacks;
u8 flags;
};
struct mtk_soundcard_pdata {
const char *card_name;
struct mtk_platform_card_data *card_data;
struct mtk_sof_priv *sof_priv;
int (*soc_probe)(struct mtk_soc_card_data *card_data, bool legacy);
};
int parse_dai_link_info(struct snd_soc_card *card); int parse_dai_link_info(struct snd_soc_card *card);
void clean_card_reference(struct snd_soc_card *card); void clean_card_reference(struct snd_soc_card *card);
int mtk_soundcard_common_probe(struct platform_device *pdev);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment