123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243 |
- From ddf6abc1c78072f8ccad59166be95f0ca5af8ca4 Mon Sep 17 00:00:00 2001
- From: Maso Huang <[email protected]>
- Date: Thu, 17 Aug 2023 18:13:36 +0800
- Subject: [PATCH 4/9] ASoC: mediatek: mt7986: add machine driver with wm8960
- Add support for mt7986 board with wm8960.
- Signed-off-by: Maso Huang <[email protected]>
- Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
- Link: https://lore.kernel.org/r/[email protected]
- Signed-off-by: Mark Brown <[email protected]>
- ---
- sound/soc/mediatek/Kconfig | 10 ++
- sound/soc/mediatek/mt7986/Makefile | 1 +
- sound/soc/mediatek/mt7986/mt7986-wm8960.c | 196 ++++++++++++++++++++++
- 3 files changed, 207 insertions(+)
- create mode 100644 sound/soc/mediatek/mt7986/mt7986-wm8960.c
- --- a/sound/soc/mediatek/Kconfig
- +++ b/sound/soc/mediatek/Kconfig
- @@ -64,6 +64,16 @@ config SND_SOC_MT7986
- Select Y if you have such device.
- If unsure select "N".
-
- +config SND_SOC_MT7986_WM8960
- + tristate "ASoc Audio driver for MT7986 with WM8960 codec"
- + depends on SND_SOC_MT7986 && I2C
- + select SND_SOC_WM8960
- + help
- + This adds support for ASoC machine driver for MediaTek MT7986
- + boards with the WM8960 codecs.
- + Select Y if you have such device.
- + If unsure select "N".
- +
- config SND_SOC_MT8173
- tristate "ASoC support for Mediatek MT8173 chip"
- depends on ARCH_MEDIATEK
- --- a/sound/soc/mediatek/mt7986/Makefile
- +++ b/sound/soc/mediatek/mt7986/Makefile
- @@ -6,3 +6,4 @@ snd-soc-mt7986-afe-objs := \
- mt7986-dai-etdm.o
-
- obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o
- +obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o
- --- /dev/null
- +++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
- @@ -0,0 +1,196 @@
- +// SPDX-License-Identifier: GPL-2.0
- +/*
- + * mt7986-wm8960.c -- MT7986-WM8960 ALSA SoC machine driver
- + *
- + * Copyright (c) 2023 MediaTek Inc.
- + * Authors: Vic Wu <[email protected]>
- + * Maso Huang <[email protected]>
- + */
- +
- +#include <linux/module.h>
- +#include <sound/soc.h>
- +
- +#include "mt7986-afe-common.h"
- +
- +struct mt7986_wm8960_priv {
- + struct device_node *platform_node;
- + struct device_node *codec_node;
- +};
- +
- +static const struct snd_soc_dapm_widget mt7986_wm8960_widgets[] = {
- + SND_SOC_DAPM_HP("Headphone", NULL),
- + SND_SOC_DAPM_MIC("AMIC", NULL),
- +};
- +
- +static const struct snd_kcontrol_new mt7986_wm8960_controls[] = {
- + SOC_DAPM_PIN_SWITCH("Headphone"),
- + SOC_DAPM_PIN_SWITCH("AMIC"),
- +};
- +
- +SND_SOC_DAILINK_DEFS(playback,
- + DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
- + DAILINK_COMP_ARRAY(COMP_DUMMY()),
- + DAILINK_COMP_ARRAY(COMP_EMPTY()));
- +
- +SND_SOC_DAILINK_DEFS(capture,
- + DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
- + DAILINK_COMP_ARRAY(COMP_DUMMY()),
- + DAILINK_COMP_ARRAY(COMP_EMPTY()));
- +
- +SND_SOC_DAILINK_DEFS(codec,
- + DAILINK_COMP_ARRAY(COMP_CPU("ETDM")),
- + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")),
- + DAILINK_COMP_ARRAY(COMP_EMPTY()));
- +
- +static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = {
- + /* FE */
- + {
- + .name = "wm8960-playback",
- + .stream_name = "wm8960-playback",
- + .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- + SND_SOC_DPCM_TRIGGER_POST},
- + .dynamic = 1,
- + .dpcm_playback = 1,
- + SND_SOC_DAILINK_REG(playback),
- + },
- + {
- + .name = "wm8960-capture",
- + .stream_name = "wm8960-capture",
- + .trigger = {SND_SOC_DPCM_TRIGGER_POST,
- + SND_SOC_DPCM_TRIGGER_POST},
- + .dynamic = 1,
- + .dpcm_capture = 1,
- + SND_SOC_DAILINK_REG(capture),
- + },
- + /* BE */
- + {
- + .name = "wm8960-codec",
- + .no_pcm = 1,
- + .dai_fmt = SND_SOC_DAIFMT_I2S |
- + SND_SOC_DAIFMT_NB_NF |
- + SND_SOC_DAIFMT_CBS_CFS |
- + SND_SOC_DAIFMT_GATED,
- + .dpcm_playback = 1,
- + .dpcm_capture = 1,
- + SND_SOC_DAILINK_REG(codec),
- + },
- +};
- +
- +static struct snd_soc_card mt7986_wm8960_card = {
- + .name = "mt7986-wm8960",
- + .owner = THIS_MODULE,
- + .dai_link = mt7986_wm8960_dai_links,
- + .num_links = ARRAY_SIZE(mt7986_wm8960_dai_links),
- + .controls = mt7986_wm8960_controls,
- + .num_controls = ARRAY_SIZE(mt7986_wm8960_controls),
- + .dapm_widgets = mt7986_wm8960_widgets,
- + .num_dapm_widgets = ARRAY_SIZE(mt7986_wm8960_widgets),
- +};
- +
- +static int mt7986_wm8960_machine_probe(struct platform_device *pdev)
- +{
- + struct snd_soc_card *card = &mt7986_wm8960_card;
- + struct snd_soc_dai_link *dai_link;
- + struct device_node *platform, *codec;
- + struct mt7986_wm8960_priv *priv;
- + int ret, i;
- +
- + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
- + if (!priv)
- + return -ENOMEM;
- +
- + platform = of_get_child_by_name(pdev->dev.of_node, "platform");
- +
- + if (platform) {
- + priv->platform_node = of_parse_phandle(platform, "sound-dai", 0);
- + of_node_put(platform);
- +
- + if (!priv->platform_node) {
- + dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n");
- + return -EINVAL;
- + }
- + } else {
- + dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
- + return -EINVAL;
- + }
- +
- + for_each_card_prelinks(card, i, dai_link) {
- + if (dai_link->platforms->name)
- + continue;
- + dai_link->platforms->of_node = priv->platform_node;
- + }
- +
- + card->dev = &pdev->dev;
- +
- + codec = of_get_child_by_name(pdev->dev.of_node, "codec");
- +
- + if (codec) {
- + priv->codec_node = of_parse_phandle(codec, "sound-dai", 0);
- + of_node_put(codec);
- +
- + if (!priv->codec_node) {
- + of_node_put(priv->platform_node);
- + dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n");
- + return -EINVAL;
- + }
- + } else {
- + of_node_put(priv->platform_node);
- + dev_err(&pdev->dev, "Property 'codec' missing or invalid\n");
- + return -EINVAL;
- + }
- +
- + for_each_card_prelinks(card, i, dai_link) {
- + if (dai_link->codecs->name)
- + continue;
- + dai_link->codecs->of_node = priv->codec_node;
- + }
- +
- + ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
- + if (ret) {
- + dev_err(&pdev->dev, "Failed to parse audio-routing: %d\n", ret);
- + goto err_of_node_put;
- + }
- +
- + ret = devm_snd_soc_register_card(&pdev->dev, card);
- + if (ret) {
- + dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret);
- + goto err_of_node_put;
- + }
- +
- +err_of_node_put:
- + of_node_put(priv->codec_node);
- + of_node_put(priv->platform_node);
- + return ret;
- +}
- +
- +static void mt7986_wm8960_machine_remove(struct platform_device *pdev)
- +{
- + struct snd_soc_card *card = platform_get_drvdata(pdev);
- + struct mt7986_wm8960_priv *priv = snd_soc_card_get_drvdata(card);
- +
- + of_node_put(priv->codec_node);
- + of_node_put(priv->platform_node);
- +}
- +
- +static const struct of_device_id mt7986_wm8960_machine_dt_match[] = {
- + {.compatible = "mediatek,mt7986-wm8960-sound"},
- + { /* sentinel */ }
- +};
- +MODULE_DEVICE_TABLE(of, mt7986_wm8960_machine_dt_match);
- +
- +static struct platform_driver mt7986_wm8960_machine = {
- + .driver = {
- + .name = "mt7986-wm8960",
- + .of_match_table = mt7986_wm8960_machine_dt_match,
- + },
- + .probe = mt7986_wm8960_machine_probe,
- + .remove_new = mt7986_wm8960_machine_remove,
- +};
- +
- +module_platform_driver(mt7986_wm8960_machine);
- +
- +/* Module information */
- +MODULE_DESCRIPTION("MT7986 WM8960 ALSA SoC machine driver");
- +MODULE_AUTHOR("Vic Wu <[email protected]>");
- +MODULE_LICENSE("GPL");
- +MODULE_ALIAS("mt7986 wm8960 soc card");
|