diff --git a/target/linux/ramips/modules.mk b/target/linux/ramips/modules.mk index b604110b1..1bdde9c6d 100644 --- a/target/linux/ramips/modules.mk +++ b/target/linux/ramips/modules.mk @@ -136,3 +136,18 @@ define KernelPackage/sound-mt7620/description endef $(eval $(call KernelPackage,sound-mt7620)) + +define KernelPackage/sound-mt76x8-wm8960 + TITLE:=MT76x8 WM8960 ALSA SoC Machine Driver + DEPENDS:=@TARGET_ramips +kmod-sound-mt7620 +kmod-i2c-mt7628 @!TARGET_ramips_rt288x + KCONFIG:=CONFIG_SND_SOC_MT76X8_WM8960 + FILES:=$(LINUX_DIR)/sound/soc/ralink/snd-soc-mt76x8-wm8960.ko + AUTOLOAD:=$(call AutoLoad,91,snd-soc-mt76x8-wm8960) + $(call AddDepends/sound) +endef + +define KernelPackage/sound-mt76x8-wm8960/description + ASoC Audio driver for Ralink SoC with WM8960 codec. +endef + +$(eval $(call KernelPackage,sound-mt76x8-wm8960)) diff --git a/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch b/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch index 5f105c69e..ffbe78263 100644 --- a/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch +++ b/target/linux/ramips/patches-4.14/0048-asoc-add-mt7620-support.patch @@ -58,7 +58,7 @@ Signed-off-by: John Crispin obj-$(CONFIG_SND_SOC) += sirf/ --- /dev/null +++ b/sound/soc/ralink/Kconfig -@@ -0,0 +1,8 @@ +@@ -0,0 +1,15 @@ +config SND_RALINK_SOC_I2S + depends on RALINK && SND_SOC && !SOC_RT288X + select SND_SOC_GENERIC_DMAENGINE_PCM @@ -67,15 +67,26 @@ Signed-off-by: John Crispin + help + Say Y if you want to use I2S protocol and I2S codec on Ralink/MediaTek + based boards. ++ ++config SND_SOC_MT76X8_WM8960 ++ tristate "ASoC Audio driver for Ralink SoC with WM8960 codec" ++ depends on SND_RALINK_SOC_I2S && I2C ++ select SND_SOC_WM8960 ++ help ++ Say Y if you want to use WM8960 codec on Ralink/MediaTek based boards. --- /dev/null +++ b/sound/soc/ralink/Makefile -@@ -0,0 +1,6 @@ +@@ -0,0 +1,10 @@ +# +# Ralink/MediaTek Platform Support +# +snd-soc-ralink-i2s-objs := ralink-i2s.o + +obj-$(CONFIG_SND_RALINK_SOC_I2S) += snd-soc-ralink-i2s.o ++ ++snd-soc-mt76x8-wm8960-objs := mt76x8-wm8960.o ++ ++obj-$(CONFIG_SND_SOC_MT76X8_WM8960) += snd-soc-mt76x8-wm8960.o --- /dev/null +++ b/sound/soc/ralink/ralink-i2s.c @@ -0,0 +1,965 @@ @@ -1044,3 +1055,169 @@ Signed-off-by: John Crispin +MODULE_DESCRIPTION("Ralink/MediaTek I2S driver"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS("platform:" DRV_NAME); +--- /dev/null ++++ b/sound/soc/ralink/mt76x8-wm8960.c +@@ -0,0 +1,163 @@ ++/* ++ * mt76x8-wm8960.c -- MT76x8 WM8960 ALSA SoC machine driver ++ * ++ * Copyright 2018 Jack Chen ++ * ++ * Based on mt2701-wm8960.c ++ * Copyright (c) 2017 MediaTek Inc. ++ * Author: Ryder Lee ++ * ++ * The code contained herein is licensed under the GNU General Public ++ * License. You may obtain a copy of the GNU General Public License ++ * Version 2 or later at the following locations: ++ * ++ * http://www.opensource.org/licenses/gpl-license.html ++ * http://www.gnu.org/copyleft/gpl.html ++ */ ++ ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++#include ++ ++#include "../codecs/wm8960.h" ++ ++static const struct snd_soc_dapm_widget mt76x8_wm8960_dapm_widgets[] = { ++ SND_SOC_DAPM_HP("Headphone", NULL), ++ SND_SOC_DAPM_SPK("Ext Spk", NULL), ++ SND_SOC_DAPM_LINE("Line In", NULL), ++ SND_SOC_DAPM_MIC("Mic", NULL), ++}; ++ ++static int mt76x8_wm8960_ops_hw_params(struct snd_pcm_substream *substream, ++ struct snd_pcm_hw_params *params) ++{ ++ struct snd_soc_pcm_runtime *rtd = substream->private_data; ++ struct snd_soc_dai *codec_dai = rtd->codec_dai; ++ struct snd_soc_dai *cpu_dai = rtd->cpu_dai; ++ unsigned int mclk_rate; ++ unsigned int rate = params_rate(params); ++ unsigned int div_mclk_over_bck = rate > 192000 ? 2 : 4; ++ unsigned int div_bck_over_lrck = 64; ++ ++ mclk_rate = rate * div_bck_over_lrck * div_mclk_over_bck; ++ ++ snd_soc_dai_set_sysclk(cpu_dai, 0, mclk_rate, SND_SOC_CLOCK_OUT); ++ snd_soc_dai_set_sysclk(codec_dai, 0, mclk_rate, SND_SOC_CLOCK_IN); ++ ++ return 0; ++} ++ ++static struct snd_soc_ops mt76x8_wm8960_ops = { ++ .hw_params = mt76x8_wm8960_ops_hw_params, ++}; ++ ++static struct snd_soc_dai_link mt76x8_wm8960_dai_links[] = { ++ { ++ .name = "wm8960-codec", ++ .stream_name = "wm8960-hifi", ++ .cpu_dai_name = "ralink-i2s", ++ .codec_dai_name = "wm8960-hifi", ++ .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS, ++ .ops = &mt76x8_wm8960_ops, ++ .dpcm_playback = 1, ++ .dpcm_capture = 1, ++ }, ++}; ++ ++static struct snd_soc_card mt76x8_wm8960_card = { ++ .name = "MT76x8 WM8960 ASoC Card", ++ .owner = THIS_MODULE, ++ .dai_link = mt76x8_wm8960_dai_links, ++ .num_links = ARRAY_SIZE(mt76x8_wm8960_dai_links), ++ .dapm_widgets = mt76x8_wm8960_dapm_widgets, ++ .num_dapm_widgets = ARRAY_SIZE(mt76x8_wm8960_dapm_widgets), ++}; ++ ++static int mt76x8_wm8960_machine_probe(struct platform_device *pdev) ++{ ++ struct snd_soc_card *card = &mt76x8_wm8960_card; ++ struct device_node *platform_node, *codec_node; ++ struct platform_device *platform_dev; ++ struct i2c_client *codec_dev; ++ int ret, i; ++ ++ platform_node = of_parse_phandle(pdev->dev.of_node, "mediatek,platform", 0); ++ if (!platform_node) { ++ dev_err(&pdev->dev, "property 'platform' missing or invalid\n"); ++ return -EINVAL; ++ } ++ platform_dev = of_find_device_by_node(platform_node); ++ if (!platform_dev) { ++ dev_err(&pdev->dev, "failed to find platform device\n"); ++ return -EINVAL; ++ } ++ for (i=0; inum_links; i++) { ++ if (mt76x8_wm8960_dai_links[i].platform_name) { ++ continue; ++ } ++ mt76x8_wm8960_dai_links[i].platform_of_node = platform_node; ++ } ++ ++ card->dev = &pdev->dev; ++ ++ codec_node = of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0); ++ if (!codec_node) { ++ dev_err(&pdev->dev, "property 'audio-codec' missing or invalid\n"); ++ return -EINVAL; ++ } ++ codec_dev = of_find_i2c_device_by_node(codec_node); ++ if (!codec_dev || !codec_dev->dev.driver) { ++ dev_err(&pdev->dev, "failed to find audio codec device\n"); ++ return -EINVAL; ++ } ++ for (i=0; inum_links; i++) { ++ if (mt76x8_wm8960_dai_links[i].codec_name) { ++ continue; ++ } ++ mt76x8_wm8960_dai_links[i].codec_of_node = 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); ++ return ret; ++ } ++ ++ 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); ++ } ++ ++ return ret; ++} ++ ++#ifdef CONFIG_OF ++static const struct of_device_id mt76x8_wm8960_machine_dt_match[] = { ++ {.compatible = "mediatek,mt76x8-wm8960-machine"}, ++ {} ++}; ++#endif ++ ++static struct platform_driver mt76x8_wm8960_machine = { ++ .driver = { ++ .name = "mt76x8-wm8960", ++ .owner = THIS_MODULE, ++#ifdef CONFIG_OF ++ .of_match_table = mt76x8_wm8960_machine_dt_match, ++#endif ++ }, ++ .probe = mt76x8_wm8960_machine_probe, ++}; ++ ++module_platform_driver(mt76x8_wm8960_machine); ++ ++/* Module information */ ++MODULE_DESCRIPTION("MT76x8 WM8960 ALSA SoC machine driver"); ++MODULE_AUTHOR("Jack Chen "); ++MODULE_LICENSE("GPL v2"); ++MODULE_ALIAS("MT76x8 WM8960 ASoC driver");