2
0

860-v6.6-04-ASoC-mediatek-mt7986-add-machine-driver-with-wm8960.patch 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. From ddf6abc1c78072f8ccad59166be95f0ca5af8ca4 Mon Sep 17 00:00:00 2001
  2. From: Maso Huang <[email protected]>
  3. Date: Thu, 17 Aug 2023 18:13:36 +0800
  4. Subject: [PATCH 4/9] ASoC: mediatek: mt7986: add machine driver with wm8960
  5. Add support for mt7986 board with wm8960.
  6. Signed-off-by: Maso Huang <[email protected]>
  7. Reviewed-by: AngeloGioacchino Del Regno <[email protected]>
  8. Link: https://lore.kernel.org/r/[email protected]
  9. Signed-off-by: Mark Brown <[email protected]>
  10. ---
  11. sound/soc/mediatek/Kconfig | 10 ++
  12. sound/soc/mediatek/mt7986/Makefile | 1 +
  13. sound/soc/mediatek/mt7986/mt7986-wm8960.c | 196 ++++++++++++++++++++++
  14. 3 files changed, 207 insertions(+)
  15. create mode 100644 sound/soc/mediatek/mt7986/mt7986-wm8960.c
  16. --- a/sound/soc/mediatek/Kconfig
  17. +++ b/sound/soc/mediatek/Kconfig
  18. @@ -64,6 +64,16 @@ config SND_SOC_MT7986
  19. Select Y if you have such device.
  20. If unsure select "N".
  21. +config SND_SOC_MT7986_WM8960
  22. + tristate "ASoc Audio driver for MT7986 with WM8960 codec"
  23. + depends on SND_SOC_MT7986 && I2C
  24. + select SND_SOC_WM8960
  25. + help
  26. + This adds support for ASoC machine driver for MediaTek MT7986
  27. + boards with the WM8960 codecs.
  28. + Select Y if you have such device.
  29. + If unsure select "N".
  30. +
  31. config SND_SOC_MT8173
  32. tristate "ASoC support for Mediatek MT8173 chip"
  33. depends on ARCH_MEDIATEK
  34. --- a/sound/soc/mediatek/mt7986/Makefile
  35. +++ b/sound/soc/mediatek/mt7986/Makefile
  36. @@ -6,3 +6,4 @@ snd-soc-mt7986-afe-objs := \
  37. mt7986-dai-etdm.o
  38. obj-$(CONFIG_SND_SOC_MT7986) += snd-soc-mt7986-afe.o
  39. +obj-$(CONFIG_SND_SOC_MT7986_WM8960) += mt7986-wm8960.o
  40. --- /dev/null
  41. +++ b/sound/soc/mediatek/mt7986/mt7986-wm8960.c
  42. @@ -0,0 +1,196 @@
  43. +// SPDX-License-Identifier: GPL-2.0
  44. +/*
  45. + * mt7986-wm8960.c -- MT7986-WM8960 ALSA SoC machine driver
  46. + *
  47. + * Copyright (c) 2023 MediaTek Inc.
  48. + * Authors: Vic Wu <[email protected]>
  49. + * Maso Huang <[email protected]>
  50. + */
  51. +
  52. +#include <linux/module.h>
  53. +#include <sound/soc.h>
  54. +
  55. +#include "mt7986-afe-common.h"
  56. +
  57. +struct mt7986_wm8960_priv {
  58. + struct device_node *platform_node;
  59. + struct device_node *codec_node;
  60. +};
  61. +
  62. +static const struct snd_soc_dapm_widget mt7986_wm8960_widgets[] = {
  63. + SND_SOC_DAPM_HP("Headphone", NULL),
  64. + SND_SOC_DAPM_MIC("AMIC", NULL),
  65. +};
  66. +
  67. +static const struct snd_kcontrol_new mt7986_wm8960_controls[] = {
  68. + SOC_DAPM_PIN_SWITCH("Headphone"),
  69. + SOC_DAPM_PIN_SWITCH("AMIC"),
  70. +};
  71. +
  72. +SND_SOC_DAILINK_DEFS(playback,
  73. + DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
  74. + DAILINK_COMP_ARRAY(COMP_DUMMY()),
  75. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  76. +
  77. +SND_SOC_DAILINK_DEFS(capture,
  78. + DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
  79. + DAILINK_COMP_ARRAY(COMP_DUMMY()),
  80. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  81. +
  82. +SND_SOC_DAILINK_DEFS(codec,
  83. + DAILINK_COMP_ARRAY(COMP_CPU("ETDM")),
  84. + DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "wm8960-hifi")),
  85. + DAILINK_COMP_ARRAY(COMP_EMPTY()));
  86. +
  87. +static struct snd_soc_dai_link mt7986_wm8960_dai_links[] = {
  88. + /* FE */
  89. + {
  90. + .name = "wm8960-playback",
  91. + .stream_name = "wm8960-playback",
  92. + .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  93. + SND_SOC_DPCM_TRIGGER_POST},
  94. + .dynamic = 1,
  95. + .dpcm_playback = 1,
  96. + SND_SOC_DAILINK_REG(playback),
  97. + },
  98. + {
  99. + .name = "wm8960-capture",
  100. + .stream_name = "wm8960-capture",
  101. + .trigger = {SND_SOC_DPCM_TRIGGER_POST,
  102. + SND_SOC_DPCM_TRIGGER_POST},
  103. + .dynamic = 1,
  104. + .dpcm_capture = 1,
  105. + SND_SOC_DAILINK_REG(capture),
  106. + },
  107. + /* BE */
  108. + {
  109. + .name = "wm8960-codec",
  110. + .no_pcm = 1,
  111. + .dai_fmt = SND_SOC_DAIFMT_I2S |
  112. + SND_SOC_DAIFMT_NB_NF |
  113. + SND_SOC_DAIFMT_CBS_CFS |
  114. + SND_SOC_DAIFMT_GATED,
  115. + .dpcm_playback = 1,
  116. + .dpcm_capture = 1,
  117. + SND_SOC_DAILINK_REG(codec),
  118. + },
  119. +};
  120. +
  121. +static struct snd_soc_card mt7986_wm8960_card = {
  122. + .name = "mt7986-wm8960",
  123. + .owner = THIS_MODULE,
  124. + .dai_link = mt7986_wm8960_dai_links,
  125. + .num_links = ARRAY_SIZE(mt7986_wm8960_dai_links),
  126. + .controls = mt7986_wm8960_controls,
  127. + .num_controls = ARRAY_SIZE(mt7986_wm8960_controls),
  128. + .dapm_widgets = mt7986_wm8960_widgets,
  129. + .num_dapm_widgets = ARRAY_SIZE(mt7986_wm8960_widgets),
  130. +};
  131. +
  132. +static int mt7986_wm8960_machine_probe(struct platform_device *pdev)
  133. +{
  134. + struct snd_soc_card *card = &mt7986_wm8960_card;
  135. + struct snd_soc_dai_link *dai_link;
  136. + struct device_node *platform, *codec;
  137. + struct mt7986_wm8960_priv *priv;
  138. + int ret, i;
  139. +
  140. + priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
  141. + if (!priv)
  142. + return -ENOMEM;
  143. +
  144. + platform = of_get_child_by_name(pdev->dev.of_node, "platform");
  145. +
  146. + if (platform) {
  147. + priv->platform_node = of_parse_phandle(platform, "sound-dai", 0);
  148. + of_node_put(platform);
  149. +
  150. + if (!priv->platform_node) {
  151. + dev_err(&pdev->dev, "Failed to parse platform/sound-dai property\n");
  152. + return -EINVAL;
  153. + }
  154. + } else {
  155. + dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
  156. + return -EINVAL;
  157. + }
  158. +
  159. + for_each_card_prelinks(card, i, dai_link) {
  160. + if (dai_link->platforms->name)
  161. + continue;
  162. + dai_link->platforms->of_node = priv->platform_node;
  163. + }
  164. +
  165. + card->dev = &pdev->dev;
  166. +
  167. + codec = of_get_child_by_name(pdev->dev.of_node, "codec");
  168. +
  169. + if (codec) {
  170. + priv->codec_node = of_parse_phandle(codec, "sound-dai", 0);
  171. + of_node_put(codec);
  172. +
  173. + if (!priv->codec_node) {
  174. + of_node_put(priv->platform_node);
  175. + dev_err(&pdev->dev, "Failed to parse codec/sound-dai property\n");
  176. + return -EINVAL;
  177. + }
  178. + } else {
  179. + of_node_put(priv->platform_node);
  180. + dev_err(&pdev->dev, "Property 'codec' missing or invalid\n");
  181. + return -EINVAL;
  182. + }
  183. +
  184. + for_each_card_prelinks(card, i, dai_link) {
  185. + if (dai_link->codecs->name)
  186. + continue;
  187. + dai_link->codecs->of_node = priv->codec_node;
  188. + }
  189. +
  190. + ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
  191. + if (ret) {
  192. + dev_err(&pdev->dev, "Failed to parse audio-routing: %d\n", ret);
  193. + goto err_of_node_put;
  194. + }
  195. +
  196. + ret = devm_snd_soc_register_card(&pdev->dev, card);
  197. + if (ret) {
  198. + dev_err(&pdev->dev, "%s snd_soc_register_card fail: %d\n", __func__, ret);
  199. + goto err_of_node_put;
  200. + }
  201. +
  202. +err_of_node_put:
  203. + of_node_put(priv->codec_node);
  204. + of_node_put(priv->platform_node);
  205. + return ret;
  206. +}
  207. +
  208. +static void mt7986_wm8960_machine_remove(struct platform_device *pdev)
  209. +{
  210. + struct snd_soc_card *card = platform_get_drvdata(pdev);
  211. + struct mt7986_wm8960_priv *priv = snd_soc_card_get_drvdata(card);
  212. +
  213. + of_node_put(priv->codec_node);
  214. + of_node_put(priv->platform_node);
  215. +}
  216. +
  217. +static const struct of_device_id mt7986_wm8960_machine_dt_match[] = {
  218. + {.compatible = "mediatek,mt7986-wm8960-sound"},
  219. + { /* sentinel */ }
  220. +};
  221. +MODULE_DEVICE_TABLE(of, mt7986_wm8960_machine_dt_match);
  222. +
  223. +static struct platform_driver mt7986_wm8960_machine = {
  224. + .driver = {
  225. + .name = "mt7986-wm8960",
  226. + .of_match_table = mt7986_wm8960_machine_dt_match,
  227. + },
  228. + .probe = mt7986_wm8960_machine_probe,
  229. + .remove_new = mt7986_wm8960_machine_remove,
  230. +};
  231. +
  232. +module_platform_driver(mt7986_wm8960_machine);
  233. +
  234. +/* Module information */
  235. +MODULE_DESCRIPTION("MT7986 WM8960 ALSA SoC machine driver");
  236. +MODULE_AUTHOR("Vic Wu <[email protected]>");
  237. +MODULE_LICENSE("GPL");
  238. +MODULE_ALIAS("mt7986 wm8960 soc card");