aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/sound/mt8173-max98090.txt13
-rw-r--r--Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt13
-rw-r--r--Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt45
-rw-r--r--sound/soc/Kconfig1
-rw-r--r--sound/soc/Makefile1
-rw-r--r--sound/soc/codecs/ml26124.c58
-rw-r--r--sound/soc/mediatek/Kconfig30
-rw-r--r--sound/soc/mediatek/Makefile5
-rw-r--r--sound/soc/mediatek/mt8173-max98090.c213
-rw-r--r--sound/soc/mediatek/mt8173-rt5650-rt5676.c278
-rw-r--r--sound/soc/mediatek/mtk-afe-common.h109
-rw-r--r--sound/soc/mediatek/mtk-afe-pcm.c1233
-rw-r--r--sound/soc/omap/rx51.c10
13 files changed, 1955 insertions, 54 deletions
diff --git a/Documentation/devicetree/bindings/sound/mt8173-max98090.txt b/Documentation/devicetree/bindings/sound/mt8173-max98090.txt
new file mode 100644
index 000000000000..829bd26d17f8
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8173-max98090.txt
@@ -0,0 +1,13 @@
1MT8173 with MAX98090 CODEC
2
3Required properties:
4- compatible : "mediatek,mt8173-max98090"
5- mediatek,audio-codec: the phandle of the MAX98090 audio codec
6
7Example:
8
9 sound {
10 compatible = "mediatek,mt8173-max98090";
11 mediatek,audio-codec = <&max98090>;
12 };
13
diff --git a/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
new file mode 100644
index 000000000000..61e98c976bd4
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mt8173-rt5650-rt5676.txt
@@ -0,0 +1,13 @@
1MT8173 with RT5650 RT5676 CODECS
2
3Required properties:
4- compatible : "mediatek,mt8173-rt5650-rt5676"
5- mediatek,audio-codec: the phandles of rt5650 and rt5676 codecs
6
7Example:
8
9 sound {
10 compatible = "mediatek,mt8173-rt5650-rt5676";
11 mediatek,audio-codec = <&rt5650 &rt5676>;
12 };
13
diff --git a/Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt b/Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt
new file mode 100644
index 000000000000..e302c7f43b95
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/mtk-afe-pcm.txt
@@ -0,0 +1,45 @@
1Mediatek AFE PCM controller
2
3Required properties:
4- compatible = "mediatek,mt8173-afe-pcm";
5- reg: register location and size
6- interrupts: Should contain AFE interrupt
7- clock-names: should have these clock names:
8 "infra_sys_audio_clk",
9 "top_pdn_audio",
10 "top_pdn_aud_intbus",
11 "bck0",
12 "bck1",
13 "i2s0_m",
14 "i2s1_m",
15 "i2s2_m",
16 "i2s3_m",
17 "i2s3_b";
18
19Example:
20
21 afe: mt8173-afe-pcm@11220000 {
22 compatible = "mediatek,mt8173-afe-pcm";
23 reg = <0 0x11220000 0 0x1000>;
24 interrupts = <GIC_SPI 134 IRQ_TYPE_EDGE_FALLING>;
25 clocks = <&infracfg INFRA_AUDIO>,
26 <&topckgen TOP_AUDIO_SEL>,
27 <&topckgen TOP_AUD_INTBUS_SEL>,
28 <&topckgen TOP_APLL1_DIV0>,
29 <&topckgen TOP_APLL2_DIV0>,
30 <&topckgen TOP_I2S0_M_CK_SEL>,
31 <&topckgen TOP_I2S1_M_CK_SEL>,
32 <&topckgen TOP_I2S2_M_CK_SEL>,
33 <&topckgen TOP_I2S3_M_CK_SEL>,
34 <&topckgen TOP_I2S3_B_CK_SEL>;
35 clock-names = "infra_sys_audio_clk",
36 "top_pdn_audio",
37 "top_pdn_aud_intbus",
38 "bck0",
39 "bck1",
40 "i2s0_m",
41 "i2s1_m",
42 "i2s2_m",
43 "i2s3_m",
44 "i2s3_b";
45 };
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig
index e2828e101433..2ae9619443d1 100644
--- a/sound/soc/Kconfig
+++ b/sound/soc/Kconfig
@@ -45,6 +45,7 @@ source "sound/soc/nuc900/Kconfig"
45source "sound/soc/omap/Kconfig" 45source "sound/soc/omap/Kconfig"
46source "sound/soc/kirkwood/Kconfig" 46source "sound/soc/kirkwood/Kconfig"
47source "sound/soc/intel/Kconfig" 47source "sound/soc/intel/Kconfig"
48source "sound/soc/mediatek/Kconfig"
48source "sound/soc/mxs/Kconfig" 49source "sound/soc/mxs/Kconfig"
49source "sound/soc/pxa/Kconfig" 50source "sound/soc/pxa/Kconfig"
50source "sound/soc/qcom/Kconfig" 51source "sound/soc/qcom/Kconfig"
diff --git a/sound/soc/Makefile b/sound/soc/Makefile
index a0e1ee6b507d..e189903fabf4 100644
--- a/sound/soc/Makefile
+++ b/sound/soc/Makefile
@@ -24,6 +24,7 @@ obj-$(CONFIG_SND_SOC) += dwc/
24obj-$(CONFIG_SND_SOC) += fsl/ 24obj-$(CONFIG_SND_SOC) += fsl/
25obj-$(CONFIG_SND_SOC) += jz4740/ 25obj-$(CONFIG_SND_SOC) += jz4740/
26obj-$(CONFIG_SND_SOC) += intel/ 26obj-$(CONFIG_SND_SOC) += intel/
27obj-$(CONFIG_SND_SOC) += mediatek/
27obj-$(CONFIG_SND_SOC) += mxs/ 28obj-$(CONFIG_SND_SOC) += mxs/
28obj-$(CONFIG_SND_SOC) += nuc900/ 29obj-$(CONFIG_SND_SOC) += nuc900/
29obj-$(CONFIG_SND_SOC) += omap/ 30obj-$(CONFIG_SND_SOC) += omap/
diff --git a/sound/soc/codecs/ml26124.c b/sound/soc/codecs/ml26124.c
index 62dda2488f14..b74118e019fb 100644
--- a/sound/soc/codecs/ml26124.c
+++ b/sound/soc/codecs/ml26124.c
@@ -341,6 +341,7 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream,
341 struct snd_soc_codec *codec = dai->codec; 341 struct snd_soc_codec *codec = dai->codec;
342 struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec); 342 struct ml26124_priv *priv = snd_soc_codec_get_drvdata(codec);
343 int i = get_coeff(priv->mclk, params_rate(hw_params)); 343 int i = get_coeff(priv->mclk, params_rate(hw_params));
344 int srate;
344 345
345 if (i < 0) 346 if (i < 0)
346 return i; 347 return i;
@@ -370,53 +371,16 @@ static int ml26124_hw_params(struct snd_pcm_substream *substream,
370 BIT(0) | BIT(1), 0); 371 BIT(0) | BIT(1), 0);
371 } 372 }
372 373
373 switch (params_rate(hw_params)) { 374 srate = get_srate(params_rate(hw_params));
374 case 16000: 375 if (srate < 0)
375 snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, 376 return srate;
376 get_srate(params_rate(hw_params))); 377
377 snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, 378 snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf, srate);
378 coeff_div[i].pllnl); 379 snd_soc_update_bits(codec, ML26124_PLLNL, 0xff, coeff_div[i].pllnl);
379 snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, 380 snd_soc_update_bits(codec, ML26124_PLLNH, 0x1, coeff_div[i].pllnh);
380 coeff_div[i].pllnh); 381 snd_soc_update_bits(codec, ML26124_PLLML, 0xff, coeff_div[i].pllml);
381 snd_soc_update_bits(codec, ML26124_PLLML, 0xff, 382 snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f, coeff_div[i].pllmh);
382 coeff_div[i].pllml); 383 snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f, coeff_div[i].plldiv);
383 snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
384 coeff_div[i].pllmh);
385 snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
386 coeff_div[i].plldiv);
387 break;
388 case 32000:
389 snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
390 get_srate(params_rate(hw_params)));
391 snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
392 coeff_div[i].pllnl);
393 snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
394 coeff_div[i].pllnh);
395 snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
396 coeff_div[i].pllml);
397 snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
398 coeff_div[i].pllmh);
399 snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
400 coeff_div[i].plldiv);
401 break;
402 case 48000:
403 snd_soc_update_bits(codec, ML26124_SMPLING_RATE, 0xf,
404 get_srate(params_rate(hw_params)));
405 snd_soc_update_bits(codec, ML26124_PLLNL, 0xff,
406 coeff_div[i].pllnl);
407 snd_soc_update_bits(codec, ML26124_PLLNH, 0x1,
408 coeff_div[i].pllnh);
409 snd_soc_update_bits(codec, ML26124_PLLML, 0xff,
410 coeff_div[i].pllml);
411 snd_soc_update_bits(codec, ML26124_PLLMH, 0x3f,
412 coeff_div[i].pllmh);
413 snd_soc_update_bits(codec, ML26124_PLLDIV, 0x1f,
414 coeff_div[i].plldiv);
415 break;
416 default:
417 pr_err("%s:this rate is no support for ml26124\n", __func__);
418 return -EINVAL;
419 }
420 384
421 return 0; 385 return 0;
422} 386}
diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig
new file mode 100644
index 000000000000..15c04e2eae34
--- /dev/null
+++ b/sound/soc/mediatek/Kconfig
@@ -0,0 +1,30 @@
1config SND_SOC_MEDIATEK
2 tristate "ASoC support for Mediatek chip"
3 depends on ARCH_MEDIATEK
4 help
5 This adds ASoC platform driver support for Mediatek chip
6 that can be used with other codecs.
7 Select Y if you have such device.
8 Ex: MT8173
9
10config SND_SOC_MT8173_MAX98090
11 tristate "ASoC Audio driver for MT8173 with MAX98090 codec"
12 depends on SND_SOC_MEDIATEK
13 select SND_SOC_MAX98090
14 help
15 This adds ASoC driver for Mediatek MT8173 boards
16 with the MAX98090 audio codec.
17 Select Y if you have such device.
18 If unsure select "N".
19
20config SND_SOC_MT8173_RT5650_RT5676
21 tristate "ASoC Audio driver for MT8173 with RT5650 RT5676 codecs"
22 depends on SND_SOC_MEDIATEK
23 select SND_SOC_RT5645
24 select SND_SOC_RT5677
25 help
26 This adds ASoC driver for Mediatek MT8173 boards
27 with the RT5650 and RT5676 codecs.
28 Select Y if you have such device.
29 If unsure select "N".
30
diff --git a/sound/soc/mediatek/Makefile b/sound/soc/mediatek/Makefile
new file mode 100644
index 000000000000..75effbec438d
--- /dev/null
+++ b/sound/soc/mediatek/Makefile
@@ -0,0 +1,5 @@
1# MTK Platform Support
2obj-$(CONFIG_SND_SOC_MEDIATEK) += mtk-afe-pcm.o
3# Machine support
4obj-$(CONFIG_SND_SOC_MT8173_MAX98090) += mt8173-max98090.o
5obj-$(CONFIG_SND_SOC_MT8173_RT5650_RT5676) += mt8173-rt5650-rt5676.o
diff --git a/sound/soc/mediatek/mt8173-max98090.c b/sound/soc/mediatek/mt8173-max98090.c
new file mode 100644
index 000000000000..4d44b5803e55
--- /dev/null
+++ b/sound/soc/mediatek/mt8173-max98090.c
@@ -0,0 +1,213 @@
1/*
2 * mt8173-max98090.c -- MT8173 MAX98090 ALSA SoC machine driver
3 *
4 * Copyright (c) 2015 MediaTek Inc.
5 * Author: Koro Chen <koro.chen@mediatek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 and
9 * only version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/module.h>
18#include <sound/soc.h>
19#include <sound/jack.h>
20#include <linux/gpio.h>
21#include "../codecs/max98090.h"
22
23static struct snd_soc_jack mt8173_max98090_jack;
24
25static struct snd_soc_jack_pin mt8173_max98090_jack_pins[] = {
26 {
27 .pin = "Headphone",
28 .mask = SND_JACK_HEADPHONE,
29 },
30 {
31 .pin = "Headset Mic",
32 .mask = SND_JACK_MICROPHONE,
33 },
34};
35
36static const struct snd_soc_dapm_widget mt8173_max98090_widgets[] = {
37 SND_SOC_DAPM_SPK("Speaker", NULL),
38 SND_SOC_DAPM_MIC("Int Mic", NULL),
39 SND_SOC_DAPM_HP("Headphone", NULL),
40 SND_SOC_DAPM_MIC("Headset Mic", NULL),
41};
42
43static const struct snd_soc_dapm_route mt8173_max98090_routes[] = {
44 {"Speaker", NULL, "SPKL"},
45 {"Speaker", NULL, "SPKR"},
46 {"DMICL", NULL, "Int Mic"},
47 {"Headphone", NULL, "HPL"},
48 {"Headphone", NULL, "HPR"},
49 {"Headset Mic", NULL, "MICBIAS"},
50 {"IN34", NULL, "Headset Mic"},
51};
52
53static const struct snd_kcontrol_new mt8173_max98090_controls[] = {
54 SOC_DAPM_PIN_SWITCH("Speaker"),
55 SOC_DAPM_PIN_SWITCH("Int Mic"),
56 SOC_DAPM_PIN_SWITCH("Headphone"),
57 SOC_DAPM_PIN_SWITCH("Headset Mic"),
58};
59
60static int mt8173_max98090_hw_params(struct snd_pcm_substream *substream,
61 struct snd_pcm_hw_params *params)
62{
63 struct snd_soc_pcm_runtime *rtd = substream->private_data;
64 struct snd_soc_dai *codec_dai = rtd->codec_dai;
65
66 return snd_soc_dai_set_sysclk(codec_dai, 0, params_rate(params) * 256,
67 SND_SOC_CLOCK_IN);
68}
69
70static struct snd_soc_ops mt8173_max98090_ops = {
71 .hw_params = mt8173_max98090_hw_params,
72};
73
74static int mt8173_max98090_init(struct snd_soc_pcm_runtime *runtime)
75{
76 int ret;
77 struct snd_soc_card *card = runtime->card;
78 struct snd_soc_codec *codec = runtime->codec;
79
80 /* enable jack detection */
81 ret = snd_soc_card_jack_new(card, "Headphone", SND_JACK_HEADPHONE,
82 &mt8173_max98090_jack, NULL, 0);
83 if (ret) {
84 dev_err(card->dev, "Can't snd_soc_jack_new %d\n", ret);
85 return ret;
86 }
87
88 ret = snd_soc_jack_add_pins(&mt8173_max98090_jack,
89 ARRAY_SIZE(mt8173_max98090_jack_pins),
90 mt8173_max98090_jack_pins);
91 if (ret) {
92 dev_err(card->dev, "Can't snd_soc_jack_add_pins %d\n", ret);
93 return ret;
94 }
95
96 return max98090_mic_detect(codec, &mt8173_max98090_jack);
97}
98
99/* Digital audio interface glue - connects codec <---> CPU */
100static struct snd_soc_dai_link mt8173_max98090_dais[] = {
101 /* Front End DAI links */
102 {
103 .name = "MAX98090 Playback",
104 .stream_name = "MAX98090 Playback",
105 .cpu_dai_name = "DL1",
106 .platform_name = "11220000.mt8173-afe-pcm",
107 .codec_name = "snd-soc-dummy",
108 .codec_dai_name = "snd-soc-dummy-dai",
109 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
110 .dynamic = 1,
111 .dpcm_playback = 1,
112 },
113 {
114 .name = "MAX98090 Capture",
115 .stream_name = "MAX98090 Capture",
116 .cpu_dai_name = "VUL",
117 .platform_name = "11220000.mt8173-afe-pcm",
118 .codec_name = "snd-soc-dummy",
119 .codec_dai_name = "snd-soc-dummy-dai",
120 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
121 .dynamic = 1,
122 .dpcm_capture = 1,
123 },
124 /* Back End DAI links */
125 {
126 .name = "Codec",
127 .cpu_dai_name = "I2S",
128 .platform_name = "11220000.mt8173-afe-pcm",
129 .no_pcm = 1,
130 .codec_dai_name = "HiFi",
131 .init = mt8173_max98090_init,
132 .ops = &mt8173_max98090_ops,
133 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
134 SND_SOC_DAIFMT_CBS_CFS,
135 .dpcm_playback = 1,
136 .dpcm_capture = 1,
137 },
138};
139
140static struct snd_soc_card mt8173_max98090_card = {
141 .name = "mt8173-max98090",
142 .dai_link = mt8173_max98090_dais,
143 .num_links = ARRAY_SIZE(mt8173_max98090_dais),
144 .controls = mt8173_max98090_controls,
145 .num_controls = ARRAY_SIZE(mt8173_max98090_controls),
146 .dapm_widgets = mt8173_max98090_widgets,
147 .num_dapm_widgets = ARRAY_SIZE(mt8173_max98090_widgets),
148 .dapm_routes = mt8173_max98090_routes,
149 .num_dapm_routes = ARRAY_SIZE(mt8173_max98090_routes),
150};
151
152static int mt8173_max98090_dev_probe(struct platform_device *pdev)
153{
154 struct snd_soc_card *card = &mt8173_max98090_card;
155 struct device_node *codec_node;
156 int ret, i;
157
158 codec_node = of_parse_phandle(pdev->dev.of_node,
159 "mediatek,audio-codec", 0);
160 if (!codec_node) {
161 dev_err(&pdev->dev,
162 "Property 'audio-codec' missing or invalid\n");
163 return -EINVAL;
164 }
165 for (i = 0; i < card->num_links; i++) {
166 if (mt8173_max98090_dais[i].codec_name)
167 continue;
168 mt8173_max98090_dais[i].codec_of_node = codec_node;
169 }
170 card->dev = &pdev->dev;
171
172 ret = snd_soc_register_card(card);
173 if (ret)
174 dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
175 __func__, ret);
176 return ret;
177}
178
179static int mt8173_max98090_dev_remove(struct platform_device *pdev)
180{
181 struct snd_soc_card *card = platform_get_drvdata(pdev);
182
183 snd_soc_unregister_card(card);
184 return 0;
185}
186
187static const struct of_device_id mt8173_max98090_dt_match[] = {
188 { .compatible = "mediatek,mt8173-max98090", },
189 { }
190};
191MODULE_DEVICE_TABLE(of, mt8173_max98090_dt_match);
192
193static struct platform_driver mt8173_max98090_driver = {
194 .driver = {
195 .name = "mt8173-max98090",
196 .owner = THIS_MODULE,
197 .of_match_table = mt8173_max98090_dt_match,
198#ifdef CONFIG_PM
199 .pm = &snd_soc_pm_ops,
200#endif
201 },
202 .probe = mt8173_max98090_dev_probe,
203 .remove = mt8173_max98090_dev_remove,
204};
205
206module_platform_driver(mt8173_max98090_driver);
207
208/* Module information */
209MODULE_DESCRIPTION("MT8173 MAX98090 ALSA SoC machine driver");
210MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
211MODULE_LICENSE("GPL v2");
212MODULE_ALIAS("platform:mt8173-max98090");
213
diff --git a/sound/soc/mediatek/mt8173-rt5650-rt5676.c b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
new file mode 100644
index 000000000000..094055323059
--- /dev/null
+++ b/sound/soc/mediatek/mt8173-rt5650-rt5676.c
@@ -0,0 +1,278 @@
1/*
2 * mt8173-rt5650-rt5676.c -- MT8173 machine driver with RT5650/5676 codecs
3 *
4 * Copyright (c) 2015 MediaTek Inc.
5 * Author: Koro Chen <koro.chen@mediatek.com>
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 and
9 * only version 2 as published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 */
16
17#include <linux/module.h>
18#include <linux/gpio.h>
19#include <linux/of_gpio.h>
20#include <sound/soc.h>
21#include <sound/jack.h>
22#include "../codecs/rt5645.h"
23#include "../codecs/rt5677.h"
24
25#define MCLK_FOR_CODECS 12288000
26
27static const struct snd_soc_dapm_widget mt8173_rt5650_rt5676_widgets[] = {
28 SND_SOC_DAPM_SPK("Speaker", NULL),
29 SND_SOC_DAPM_MIC("Int Mic", NULL),
30 SND_SOC_DAPM_HP("Headphone", NULL),
31 SND_SOC_DAPM_MIC("Headset Mic", NULL),
32};
33
34static const struct snd_soc_dapm_route mt8173_rt5650_rt5676_routes[] = {
35 {"Speaker", NULL, "SPOL"},
36 {"Speaker", NULL, "SPOR"},
37 {"Speaker", NULL, "Sub AIF2TX"}, /* IF2 ADC to 5650 */
38 {"Sub DMIC L1", NULL, "Int Mic"}, /* DMIC from 5676 */
39 {"Sub DMIC R1", NULL, "Int Mic"},
40 {"Headphone", NULL, "HPOL"},
41 {"Headphone", NULL, "HPOR"},
42 {"Headphone", NULL, "Sub AIF2TX"}, /* IF2 ADC to 5650 */
43 {"Headset Mic", NULL, "micbias1"},
44 {"Headset Mic", NULL, "micbias2"},
45 {"IN1P", NULL, "Headset Mic"},
46 {"IN1N", NULL, "Headset Mic"},
47 {"Sub AIF2RX", NULL, "Headset Mic"}, /* IF2 DAC from 5650 */
48};
49
50static const struct snd_kcontrol_new mt8173_rt5650_rt5676_controls[] = {
51 SOC_DAPM_PIN_SWITCH("Speaker"),
52 SOC_DAPM_PIN_SWITCH("Int Mic"),
53 SOC_DAPM_PIN_SWITCH("Headphone"),
54 SOC_DAPM_PIN_SWITCH("Headset Mic"),
55};
56
57static int mt8173_rt5650_rt5676_hw_params(struct snd_pcm_substream *substream,
58 struct snd_pcm_hw_params *params)
59{
60 struct snd_soc_pcm_runtime *rtd = substream->private_data;
61 int i, ret;
62
63 for (i = 0; i < rtd->num_codecs; i++) {
64 struct snd_soc_dai *codec_dai = rtd->codec_dais[i];
65
66 /* pll from mclk 12.288M */
67 ret = snd_soc_dai_set_pll(codec_dai, 0, 0, MCLK_FOR_CODECS,
68 params_rate(params) * 512);
69 if (ret)
70 return ret;
71
72 /* sysclk from pll */
73 ret = snd_soc_dai_set_sysclk(codec_dai, 1,
74 params_rate(params) * 512,
75 SND_SOC_CLOCK_IN);
76 if (ret)
77 return ret;
78 }
79 return 0;
80}
81
82static struct snd_soc_ops mt8173_rt5650_rt5676_ops = {
83 .hw_params = mt8173_rt5650_rt5676_hw_params,
84};
85
86static struct snd_soc_jack mt8173_rt5650_rt5676_jack;
87
88static int mt8173_rt5650_rt5676_init(struct snd_soc_pcm_runtime *runtime)
89{
90 struct snd_soc_card *card = runtime->card;
91 struct snd_soc_codec *codec = runtime->codec_dais[0]->codec;
92 struct snd_soc_codec *codec_sub = runtime->codec_dais[1]->codec;
93 int ret;
94
95 rt5645_sel_asrc_clk_src(codec,
96 RT5645_DA_STEREO_FILTER |
97 RT5645_AD_STEREO_FILTER,
98 RT5645_CLK_SEL_I2S1_ASRC);
99 rt5677_sel_asrc_clk_src(codec_sub,
100 RT5677_DA_STEREO_FILTER |
101 RT5677_AD_STEREO1_FILTER,
102 RT5677_CLK_SEL_I2S1_ASRC);
103 rt5677_sel_asrc_clk_src(codec_sub,
104 RT5677_AD_STEREO2_FILTER |
105 RT5677_I2S2_SOURCE,
106 RT5677_CLK_SEL_I2S2_ASRC);
107
108 /* enable jack detection */
109 ret = snd_soc_card_jack_new(card, "Headset Jack",
110 SND_JACK_HEADPHONE | SND_JACK_MICROPHONE |
111 SND_JACK_BTN_0 | SND_JACK_BTN_1 |
112 SND_JACK_BTN_2 | SND_JACK_BTN_3,
113 &mt8173_rt5650_rt5676_jack, NULL, 0);
114 if (ret) {
115 dev_err(card->dev, "Can't new Headset Jack %d\n", ret);
116 return ret;
117 }
118
119 return rt5645_set_jack_detect(codec,
120 &mt8173_rt5650_rt5676_jack,
121 &mt8173_rt5650_rt5676_jack,
122 &mt8173_rt5650_rt5676_jack);
123}
124
125static struct snd_soc_dai_link_component mt8173_rt5650_rt5676_codecs[] = {
126 {
127 .dai_name = "rt5645-aif1",
128 },
129 {
130 .dai_name = "rt5677-aif1",
131 },
132};
133
134/* Digital audio interface glue - connects codec <---> CPU */
135static struct snd_soc_dai_link mt8173_rt5650_rt5676_dais[] = {
136 /* Front End DAI links */
137 {
138 .name = "rt5650_rt5676 Playback",
139 .stream_name = "rt5650_rt5676 Playback",
140 .cpu_dai_name = "DL1",
141 .platform_name = "11220000.mt8173-afe-pcm",
142 .codec_name = "snd-soc-dummy",
143 .codec_dai_name = "snd-soc-dummy-dai",
144 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
145 .dynamic = 1,
146 .dpcm_playback = 1,
147 },
148 {
149 .name = "rt5650_rt5676 Capture",
150 .stream_name = "rt5650_rt5676 Capture",
151 .cpu_dai_name = "VUL",
152 .platform_name = "11220000.mt8173-afe-pcm",
153 .codec_name = "snd-soc-dummy",
154 .codec_dai_name = "snd-soc-dummy-dai",
155 .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
156 .dynamic = 1,
157 .dpcm_capture = 1,
158 },
159
160 /* Back End DAI links */
161 {
162 .name = "Codec",
163 .cpu_dai_name = "I2S",
164 .platform_name = "11220000.mt8173-afe-pcm",
165 .no_pcm = 1,
166 .codecs = mt8173_rt5650_rt5676_codecs,
167 .num_codecs = 2,
168 .init = mt8173_rt5650_rt5676_init,
169 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
170 SND_SOC_DAIFMT_CBS_CFS,
171 .ops = &mt8173_rt5650_rt5676_ops,
172 .ignore_pmdown_time = 1,
173 .dpcm_playback = 1,
174 .dpcm_capture = 1,
175 },
176 { /* rt5676 <-> rt5650 intercodec link: Sets rt5676 I2S2 as master */
177 .name = "rt5650_rt5676 intercodec",
178 .stream_name = "rt5650_rt5676 intercodec",
179 .cpu_dai_name = "snd-soc-dummy-dai",
180 .platform_name = "snd-soc-dummy",
181 .no_pcm = 1,
182 .codec_dai_name = "rt5677-aif2",
183 .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
184 SND_SOC_DAIFMT_CBM_CFM,
185 },
186
187};
188
189static struct snd_soc_codec_conf mt8173_rt5650_rt5676_codec_conf[] = {
190 {
191 .name_prefix = "Sub",
192 },
193};
194
195static struct snd_soc_card mt8173_rt5650_rt5676_card = {
196 .name = "mtk-rt5650-rt5676",
197 .dai_link = mt8173_rt5650_rt5676_dais,
198 .num_links = ARRAY_SIZE(mt8173_rt5650_rt5676_dais),
199 .codec_conf = mt8173_rt5650_rt5676_codec_conf,
200 .num_configs = ARRAY_SIZE(mt8173_rt5650_rt5676_codec_conf),
201 .controls = mt8173_rt5650_rt5676_controls,
202 .num_controls = ARRAY_SIZE(mt8173_rt5650_rt5676_controls),
203 .dapm_widgets = mt8173_rt5650_rt5676_widgets,
204 .num_dapm_widgets = ARRAY_SIZE(mt8173_rt5650_rt5676_widgets),
205 .dapm_routes = mt8173_rt5650_rt5676_routes,
206 .num_dapm_routes = ARRAY_SIZE(mt8173_rt5650_rt5676_routes),
207};
208
209static int mt8173_rt5650_rt5676_dev_probe(struct platform_device *pdev)
210{
211 struct snd_soc_card *card = &mt8173_rt5650_rt5676_card;
212 int ret;
213
214 mt8173_rt5650_rt5676_codecs[0].of_node =
215 of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 0);
216 if (!mt8173_rt5650_rt5676_codecs[0].of_node) {
217 dev_err(&pdev->dev,
218 "Property 'audio-codec' missing or invalid\n");
219 return -EINVAL;
220 }
221 mt8173_rt5650_rt5676_codecs[1].of_node =
222 of_parse_phandle(pdev->dev.of_node, "mediatek,audio-codec", 1);
223 if (!mt8173_rt5650_rt5676_codecs[1].of_node) {
224 dev_err(&pdev->dev,
225 "Property 'audio-codec' missing or invalid\n");
226 return -EINVAL;
227 }
228 mt8173_rt5650_rt5676_codec_conf[0].of_node =
229 mt8173_rt5650_rt5676_codecs[1].of_node;
230
231 mt8173_rt5650_rt5676_dais[3].codec_of_node =
232 mt8173_rt5650_rt5676_codecs[1].of_node;
233
234 card->dev = &pdev->dev;
235 platform_set_drvdata(pdev, card);
236
237 ret = snd_soc_register_card(card);
238 if (ret)
239 dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
240 __func__, ret);
241 return ret;
242}
243
244static int mt8173_rt5650_rt5676_dev_remove(struct platform_device *pdev)
245{
246 struct snd_soc_card *card = platform_get_drvdata(pdev);
247
248 snd_soc_unregister_card(card);
249 return 0;
250}
251
252static const struct of_device_id mt8173_rt5650_rt5676_dt_match[] = {
253 { .compatible = "mediatek,mt8173-rt5650-rt5676", },
254 { }
255};
256MODULE_DEVICE_TABLE(of, mt8173_rt5650_rt5676_dt_match);
257
258static struct platform_driver mt8173_rt5650_rt5676_driver = {
259 .driver = {
260 .name = "mtk-rt5650-rt5676",
261 .owner = THIS_MODULE,
262 .of_match_table = mt8173_rt5650_rt5676_dt_match,
263#ifdef CONFIG_PM
264 .pm = &snd_soc_pm_ops,
265#endif
266 },
267 .probe = mt8173_rt5650_rt5676_dev_probe,
268 .remove = mt8173_rt5650_rt5676_dev_remove,
269};
270
271module_platform_driver(mt8173_rt5650_rt5676_driver);
272
273/* Module information */
274MODULE_DESCRIPTION("MT8173 RT5650 and RT5676 SoC machine driver");
275MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
276MODULE_LICENSE("GPL v2");
277MODULE_ALIAS("platform:mtk-rt5650-rt5676");
278
diff --git a/sound/soc/mediatek/mtk-afe-common.h b/sound/soc/mediatek/mtk-afe-common.h
new file mode 100644
index 000000000000..a88b17511fdf
--- /dev/null
+++ b/sound/soc/mediatek/mtk-afe-common.h
@@ -0,0 +1,109 @@
1/*
2 * mtk_afe_common.h -- Mediatek audio driver common definitions
3 *
4 * Copyright (c) 2015 MediaTek Inc.
5 * Author: Koro Chen <koro.chen@mediatek.com>
6 * Sascha Hauer <s.hauer@pengutronix.de>
7 * Hidalgo Huang <hidalgo.huang@mediatek.com>
8 * Ir Lian <ir.lian@mediatek.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 and
12 * only version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#ifndef _MTK_AFE_COMMON_H_
21#define _MTK_AFE_COMMON_H_
22
23#include <linux/clk.h>
24#include <linux/regmap.h>
25
26enum {
27 MTK_AFE_MEMIF_DL1,
28 MTK_AFE_MEMIF_DL2,
29 MTK_AFE_MEMIF_VUL,
30 MTK_AFE_MEMIF_DAI,
31 MTK_AFE_MEMIF_AWB,
32 MTK_AFE_MEMIF_MOD_DAI,
33 MTK_AFE_MEMIF_HDMI,
34 MTK_AFE_MEMIF_NUM,
35 MTK_AFE_IO_MOD_PCM1 = MTK_AFE_MEMIF_NUM,
36 MTK_AFE_IO_MOD_PCM2,
37 MTK_AFE_IO_PMIC,
38 MTK_AFE_IO_I2S,
39 MTK_AFE_IO_2ND_I2S,
40 MTK_AFE_IO_HW_GAIN1,
41 MTK_AFE_IO_HW_GAIN2,
42 MTK_AFE_IO_MRG_O,
43 MTK_AFE_IO_MRG_I,
44 MTK_AFE_IO_DAIBT,
45 MTK_AFE_IO_HDMI,
46};
47
48enum {
49 MTK_AFE_IRQ_1,
50 MTK_AFE_IRQ_2,
51 MTK_AFE_IRQ_3,
52 MTK_AFE_IRQ_4,
53 MTK_AFE_IRQ_5,
54 MTK_AFE_IRQ_6,
55 MTK_AFE_IRQ_7,
56 MTK_AFE_IRQ_8,
57 MTK_AFE_IRQ_NUM,
58};
59
60enum {
61 MTK_CLK_INFRASYS_AUD,
62 MTK_CLK_TOP_PDN_AUD,
63 MTK_CLK_TOP_PDN_AUD_BUS,
64 MTK_CLK_I2S0_M,
65 MTK_CLK_I2S1_M,
66 MTK_CLK_I2S2_M,
67 MTK_CLK_I2S3_M,
68 MTK_CLK_I2S3_B,
69 MTK_CLK_BCK0,
70 MTK_CLK_BCK1,
71 MTK_CLK_NUM
72};
73
74struct mtk_afe;
75struct snd_pcm_substream;
76
77struct mtk_afe_memif_data {
78 int id;
79 const char *name;
80 int reg_ofs_base;
81 int reg_ofs_cur;
82 int fs_shift;
83 int mono_shift;
84 int enable_shift;
85 int irq_reg_cnt;
86 int irq_cnt_shift;
87 int irq_en_shift;
88 int irq_fs_shift;
89 int irq_clr_shift;
90};
91
92struct mtk_afe_memif {
93 unsigned int phys_buf_addr;
94 int buffer_size;
95 unsigned int hw_ptr; /* Previous IRQ's HW ptr */
96 struct snd_pcm_substream *substream;
97 const struct mtk_afe_memif_data *data;
98 const struct mtk_afe_irq_data *irqdata;
99};
100
101struct mtk_afe {
102 /* address for ioremap audio hardware register */
103 void __iomem *base_addr;
104 struct device *dev;
105 struct regmap *regmap;
106 struct mtk_afe_memif memif[MTK_AFE_MEMIF_NUM];
107 struct clk *clocks[MTK_CLK_NUM];
108};
109#endif
diff --git a/sound/soc/mediatek/mtk-afe-pcm.c b/sound/soc/mediatek/mtk-afe-pcm.c
new file mode 100644
index 000000000000..cc228db5fb76
--- /dev/null
+++ b/sound/soc/mediatek/mtk-afe-pcm.c
@@ -0,0 +1,1233 @@
1/*
2 * Mediatek ALSA SoC AFE platform driver
3 *
4 * Copyright (c) 2015 MediaTek Inc.
5 * Author: Koro Chen <koro.chen@mediatek.com>
6 * Sascha Hauer <s.hauer@pengutronix.de>
7 * Hidalgo Huang <hidalgo.huang@mediatek.com>
8 * Ir Lian <ir.lian@mediatek.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 and
12 * only version 2 as published by the Free Software Foundation.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 */
19
20#include <linux/delay.h>
21#include <linux/module.h>
22#include <linux/of.h>
23#include <linux/of_address.h>
24#include <linux/pm_runtime.h>
25#include <sound/soc.h>
26#include "mtk-afe-common.h"
27
28/*****************************************************************************
29 * R E G I S T E R D E F I N I T I O N
30 *****************************************************************************/
31#define AUDIO_TOP_CON0 0x0000
32#define AUDIO_TOP_CON1 0x0004
33#define AFE_DAC_CON0 0x0010
34#define AFE_DAC_CON1 0x0014
35#define AFE_I2S_CON1 0x0034
36#define AFE_I2S_CON2 0x0038
37#define AFE_CONN_24BIT 0x006c
38
39#define AFE_CONN1 0x0024
40#define AFE_CONN2 0x0028
41#define AFE_CONN7 0x0460
42#define AFE_CONN8 0x0464
43#define AFE_HDMI_CONN0 0x0390
44
45/* Memory interface */
46#define AFE_DL1_BASE 0x0040
47#define AFE_DL1_CUR 0x0044
48#define AFE_DL2_BASE 0x0050
49#define AFE_DL2_CUR 0x0054
50#define AFE_AWB_BASE 0x0070
51#define AFE_AWB_CUR 0x007c
52#define AFE_VUL_BASE 0x0080
53#define AFE_VUL_CUR 0x008c
54#define AFE_DAI_BASE 0x0090
55#define AFE_DAI_CUR 0x009c
56#define AFE_MOD_PCM_BASE 0x0330
57#define AFE_MOD_PCM_CUR 0x033c
58#define AFE_HDMI_OUT_BASE 0x0374
59#define AFE_HDMI_OUT_CUR 0x0378
60
61#define AFE_ADDA2_TOP_CON0 0x0600
62
63#define AFE_HDMI_OUT_CON0 0x0370
64
65#define AFE_IRQ_MCU_CON 0x03a0
66#define AFE_IRQ_STATUS 0x03a4
67#define AFE_IRQ_CLR 0x03a8
68#define AFE_IRQ_CNT1 0x03ac
69#define AFE_IRQ_CNT2 0x03b0
70#define AFE_IRQ_MCU_EN 0x03b4
71#define AFE_IRQ_CNT5 0x03bc
72#define AFE_IRQ_CNT7 0x03dc
73
74#define AFE_TDM_CON1 0x0548
75#define AFE_TDM_CON2 0x054c
76
77#define AFE_BASE_END_OFFSET 8
78#define AFE_IRQ_STATUS_BITS 0xff
79
80/* AUDIO_TOP_CON0 (0x0000) */
81#define AUD_TCON0_PDN_SPDF (0x1 << 21)
82#define AUD_TCON0_PDN_HDMI (0x1 << 20)
83#define AUD_TCON0_PDN_24M (0x1 << 9)
84#define AUD_TCON0_PDN_22M (0x1 << 8)
85#define AUD_TCON0_PDN_AFE (0x1 << 2)
86
87/* AFE_I2S_CON1 (0x0034) */
88#define AFE_I2S_CON1_LOW_JITTER_CLK (0x1 << 12)
89#define AFE_I2S_CON1_RATE(x) (((x) & 0xf) << 8)
90#define AFE_I2S_CON1_FORMAT_I2S (0x1 << 3)
91#define AFE_I2S_CON1_EN (0x1 << 0)
92
93/* AFE_I2S_CON2 (0x0038) */
94#define AFE_I2S_CON2_LOW_JITTER_CLK (0x1 << 12)
95#define AFE_I2S_CON2_RATE(x) (((x) & 0xf) << 8)
96#define AFE_I2S_CON2_FORMAT_I2S (0x1 << 3)
97#define AFE_I2S_CON2_EN (0x1 << 0)
98
99/* AFE_CONN_24BIT (0x006c) */
100#define AFE_CONN_24BIT_O04 (0x1 << 4)
101#define AFE_CONN_24BIT_O03 (0x1 << 3)
102
103/* AFE_HDMI_CONN0 (0x0390) */
104#define AFE_HDMI_CONN0_O37_I37 (0x7 << 21)
105#define AFE_HDMI_CONN0_O36_I36 (0x6 << 18)
106#define AFE_HDMI_CONN0_O35_I33 (0x3 << 15)
107#define AFE_HDMI_CONN0_O34_I32 (0x2 << 12)
108#define AFE_HDMI_CONN0_O33_I35 (0x5 << 9)
109#define AFE_HDMI_CONN0_O32_I34 (0x4 << 6)
110#define AFE_HDMI_CONN0_O31_I31 (0x1 << 3)
111#define AFE_HDMI_CONN0_O30_I30 (0x0 << 0)
112
113/* AFE_TDM_CON1 (0x0548) */
114#define AFE_TDM_CON1_LRCK_WIDTH(x) (((x) - 1) << 24)
115#define AFE_TDM_CON1_32_BCK_CYCLES (0x2 << 12)
116#define AFE_TDM_CON1_WLEN_32BIT (0x2 << 8)
117#define AFE_TDM_CON1_MSB_ALIGNED (0x1 << 4)
118#define AFE_TDM_CON1_1_BCK_DELAY (0x1 << 3)
119#define AFE_TDM_CON1_BCK_INV (0x1 << 1)
120#define AFE_TDM_CON1_EN (0x1 << 0)
121
122enum afe_tdm_ch_start {
123 AFE_TDM_CH_START_O30_O31 = 0,
124 AFE_TDM_CH_START_O32_O33,
125 AFE_TDM_CH_START_O34_O35,
126 AFE_TDM_CH_START_O36_O37,
127 AFE_TDM_CH_ZERO,
128};
129
130static const struct snd_pcm_hardware mtk_afe_hardware = {
131 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
132 SNDRV_PCM_INFO_MMAP_VALID),
133 .buffer_bytes_max = 256 * 1024,
134 .period_bytes_min = 512,
135 .period_bytes_max = 128 * 1024,
136 .periods_min = 2,
137 .periods_max = 256,
138 .fifo_size = 0,
139};
140
141static snd_pcm_uframes_t mtk_afe_pcm_pointer
142 (struct snd_pcm_substream *substream)
143{
144 struct snd_soc_pcm_runtime *rtd = substream->private_data;
145 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
146 struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
147
148 return bytes_to_frames(substream->runtime, memif->hw_ptr);
149}
150
151static const struct snd_pcm_ops mtk_afe_pcm_ops = {
152 .ioctl = snd_pcm_lib_ioctl,
153 .pointer = mtk_afe_pcm_pointer,
154};
155
156static int mtk_afe_pcm_new(struct snd_soc_pcm_runtime *rtd)
157{
158 size_t size;
159 struct snd_card *card = rtd->card->snd_card;
160 struct snd_pcm *pcm = rtd->pcm;
161
162 size = mtk_afe_hardware.buffer_bytes_max;
163
164 return snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
165 card->dev, size, size);
166}
167
168static void mtk_afe_pcm_free(struct snd_pcm *pcm)
169{
170 snd_pcm_lib_preallocate_free_for_all(pcm);
171}
172
173static const struct snd_soc_platform_driver mtk_afe_pcm_platform = {
174 .ops = &mtk_afe_pcm_ops,
175 .pcm_new = mtk_afe_pcm_new,
176 .pcm_free = mtk_afe_pcm_free,
177};
178
179struct mtk_afe_rate {
180 unsigned int rate;
181 unsigned int regvalue;
182};
183
184static const struct mtk_afe_rate mtk_afe_i2s_rates[] = {
185 { .rate = 8000, .regvalue = 0 },
186 { .rate = 11025, .regvalue = 1 },
187 { .rate = 12000, .regvalue = 2 },
188 { .rate = 16000, .regvalue = 4 },
189 { .rate = 22050, .regvalue = 5 },
190 { .rate = 24000, .regvalue = 6 },
191 { .rate = 32000, .regvalue = 8 },
192 { .rate = 44100, .regvalue = 9 },
193 { .rate = 48000, .regvalue = 10 },
194 { .rate = 88000, .regvalue = 11 },
195 { .rate = 96000, .regvalue = 12 },
196 { .rate = 174000, .regvalue = 13 },
197 { .rate = 192000, .regvalue = 14 },
198};
199
200static int mtk_afe_i2s_fs(unsigned int sample_rate)
201{
202 int i;
203
204 for (i = 0; i < ARRAY_SIZE(mtk_afe_i2s_rates); i++)
205 if (mtk_afe_i2s_rates[i].rate == sample_rate)
206 return mtk_afe_i2s_rates[i].regvalue;
207
208 return -EINVAL;
209}
210
211static int mtk_afe_set_i2s(struct mtk_afe *afe, unsigned int rate)
212{
213 unsigned int val;
214 int fs = mtk_afe_i2s_fs(rate);
215
216 if (fs < 0)
217 return -EINVAL;
218
219 /* from external ADC */
220 regmap_update_bits(afe->regmap, AFE_ADDA2_TOP_CON0, 0x1, 0x1);
221
222 /* set input */
223 val = AFE_I2S_CON2_LOW_JITTER_CLK |
224 AFE_I2S_CON2_RATE(fs) |
225 AFE_I2S_CON2_FORMAT_I2S;
226
227 regmap_update_bits(afe->regmap, AFE_I2S_CON2, ~AFE_I2S_CON2_EN, val);
228
229 /* set output */
230 val = AFE_I2S_CON1_LOW_JITTER_CLK |
231 AFE_I2S_CON1_RATE(fs) |
232 AFE_I2S_CON1_FORMAT_I2S;
233
234 regmap_update_bits(afe->regmap, AFE_I2S_CON1, ~AFE_I2S_CON1_EN, val);
235 return 0;
236}
237
238static void mtk_afe_set_i2s_enable(struct mtk_afe *afe, bool enable)
239{
240 unsigned int val;
241
242 regmap_read(afe->regmap, AFE_I2S_CON2, &val);
243 if (!!(val & AFE_I2S_CON2_EN) == enable)
244 return; /* must skip soft reset */
245
246 /* I2S soft reset begin */
247 regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0x4);
248
249 /* input */
250 regmap_update_bits(afe->regmap, AFE_I2S_CON2, 0x1, enable);
251
252 /* output */
253 regmap_update_bits(afe->regmap, AFE_I2S_CON1, 0x1, enable);
254
255 /* I2S soft reset end */
256 udelay(1);
257 regmap_update_bits(afe->regmap, AUDIO_TOP_CON1, 0x4, 0);
258}
259
260static int mtk_afe_dais_enable_clks(struct mtk_afe *afe,
261 struct clk *m_ck, struct clk *b_ck)
262{
263 int ret;
264
265 if (m_ck) {
266 ret = clk_prepare_enable(m_ck);
267 if (ret) {
268 dev_err(afe->dev, "Failed to enable m_ck\n");
269 return ret;
270 }
271 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
272 AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M, 0);
273 }
274
275 if (b_ck) {
276 ret = clk_prepare_enable(b_ck);
277 if (ret) {
278 dev_err(afe->dev, "Failed to enable b_ck\n");
279 return ret;
280 }
281 }
282 return 0;
283}
284
285static int mtk_afe_dais_set_clks(struct mtk_afe *afe,
286 struct clk *m_ck, unsigned int mck_rate,
287 struct clk *b_ck, unsigned int bck_rate)
288{
289 int ret;
290
291 if (m_ck) {
292 ret = clk_set_rate(m_ck, mck_rate);
293 if (ret) {
294 dev_err(afe->dev, "Failed to set m_ck rate\n");
295 return ret;
296 }
297 }
298
299 if (b_ck) {
300 ret = clk_set_rate(b_ck, bck_rate);
301 if (ret) {
302 dev_err(afe->dev, "Failed to set b_ck rate\n");
303 return ret;
304 }
305 }
306 return 0;
307}
308
309static void mtk_afe_dais_disable_clks(struct mtk_afe *afe,
310 struct clk *m_ck, struct clk *b_ck)
311{
312 if (m_ck) {
313 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
314 AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M,
315 AUD_TCON0_PDN_22M | AUD_TCON0_PDN_24M);
316 clk_disable_unprepare(m_ck);
317 }
318 if (b_ck)
319 clk_disable_unprepare(b_ck);
320}
321
322static int mtk_afe_i2s_startup(struct snd_pcm_substream *substream,
323 struct snd_soc_dai *dai)
324{
325 struct snd_soc_pcm_runtime *rtd = substream->private_data;
326 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
327
328 if (dai->active)
329 return 0;
330
331 mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
332 return 0;
333}
334
335static void mtk_afe_i2s_shutdown(struct snd_pcm_substream *substream,
336 struct snd_soc_dai *dai)
337{
338 struct snd_soc_pcm_runtime *rtd = substream->private_data;
339 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
340
341 if (dai->active)
342 return;
343
344 mtk_afe_set_i2s_enable(afe, false);
345 mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S1_M], NULL);
346
347 /* disable AFE */
348 regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
349}
350
351static int mtk_afe_i2s_prepare(struct snd_pcm_substream *substream,
352 struct snd_soc_dai *dai)
353{
354 struct snd_soc_pcm_runtime *rtd = substream->private_data;
355 struct snd_pcm_runtime * const runtime = substream->runtime;
356 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
357 int ret;
358
359 mtk_afe_dais_set_clks(afe,
360 afe->clocks[MTK_CLK_I2S1_M], runtime->rate * 256,
361 NULL, 0);
362 /* config I2S */
363 ret = mtk_afe_set_i2s(afe, substream->runtime->rate);
364 if (ret)
365 return ret;
366
367 mtk_afe_set_i2s_enable(afe, true);
368
369 return 0;
370}
371
372static int mtk_afe_hdmi_startup(struct snd_pcm_substream *substream,
373 struct snd_soc_dai *dai)
374{
375 struct snd_soc_pcm_runtime *rtd = substream->private_data;
376 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
377
378 if (dai->active)
379 return 0;
380
381 mtk_afe_dais_enable_clks(afe, afe->clocks[MTK_CLK_I2S3_M],
382 afe->clocks[MTK_CLK_I2S3_B]);
383 return 0;
384}
385
386static void mtk_afe_hdmi_shutdown(struct snd_pcm_substream *substream,
387 struct snd_soc_dai *dai)
388{
389 struct snd_soc_pcm_runtime *rtd = substream->private_data;
390 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
391
392 if (dai->active)
393 return;
394
395 mtk_afe_dais_disable_clks(afe, afe->clocks[MTK_CLK_I2S3_M],
396 afe->clocks[MTK_CLK_I2S3_B]);
397
398 /* disable AFE */
399 regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0);
400}
401
402static int mtk_afe_hdmi_prepare(struct snd_pcm_substream *substream,
403 struct snd_soc_dai *dai)
404{
405 struct snd_soc_pcm_runtime *rtd = substream->private_data;
406 struct snd_pcm_runtime * const runtime = substream->runtime;
407 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
408 unsigned int val;
409
410 mtk_afe_dais_set_clks(afe,
411 afe->clocks[MTK_CLK_I2S3_M], runtime->rate * 128,
412 afe->clocks[MTK_CLK_I2S3_B],
413 runtime->rate * runtime->channels * 32);
414
415 val = AFE_TDM_CON1_BCK_INV |
416 AFE_TDM_CON1_1_BCK_DELAY |
417 AFE_TDM_CON1_MSB_ALIGNED | /* I2S mode */
418 AFE_TDM_CON1_WLEN_32BIT |
419 AFE_TDM_CON1_32_BCK_CYCLES |
420 AFE_TDM_CON1_LRCK_WIDTH(32);
421 regmap_update_bits(afe->regmap, AFE_TDM_CON1, ~AFE_TDM_CON1_EN, val);
422
423 /* set tdm2 config */
424 switch (runtime->channels) {
425 case 1:
426 case 2:
427 val = AFE_TDM_CH_START_O30_O31;
428 val |= (AFE_TDM_CH_ZERO << 4);
429 val |= (AFE_TDM_CH_ZERO << 8);
430 val |= (AFE_TDM_CH_ZERO << 12);
431 break;
432 case 3:
433 case 4:
434 val = AFE_TDM_CH_START_O30_O31;
435 val |= (AFE_TDM_CH_START_O32_O33 << 4);
436 val |= (AFE_TDM_CH_ZERO << 8);
437 val |= (AFE_TDM_CH_ZERO << 12);
438 break;
439 case 5:
440 case 6:
441 val = AFE_TDM_CH_START_O30_O31;
442 val |= (AFE_TDM_CH_START_O32_O33 << 4);
443 val |= (AFE_TDM_CH_START_O34_O35 << 8);
444 val |= (AFE_TDM_CH_ZERO << 12);
445 break;
446 case 7:
447 case 8:
448 val = AFE_TDM_CH_START_O30_O31;
449 val |= (AFE_TDM_CH_START_O32_O33 << 4);
450 val |= (AFE_TDM_CH_START_O34_O35 << 8);
451 val |= (AFE_TDM_CH_START_O36_O37 << 12);
452 break;
453 default:
454 val = 0;
455 }
456 regmap_update_bits(afe->regmap, AFE_TDM_CON2, 0x0000ffff, val);
457
458 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0,
459 0x000000f0, runtime->channels << 4);
460 return 0;
461}
462
463static int mtk_afe_hdmi_trigger(struct snd_pcm_substream *substream, int cmd,
464 struct snd_soc_dai *dai)
465{
466 struct snd_soc_pcm_runtime *rtd = substream->private_data;
467 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
468
469 dev_info(afe->dev, "%s cmd=%d %s\n", __func__, cmd, dai->name);
470
471 switch (cmd) {
472 case SNDRV_PCM_TRIGGER_START:
473 case SNDRV_PCM_TRIGGER_RESUME:
474 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
475 AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF, 0);
476
477 /* set connections: O30~O37: L/R/LS/RS/C/LFE/CH7/CH8 */
478 regmap_write(afe->regmap, AFE_HDMI_CONN0,
479 AFE_HDMI_CONN0_O30_I30 | AFE_HDMI_CONN0_O31_I31 |
480 AFE_HDMI_CONN0_O32_I34 | AFE_HDMI_CONN0_O33_I35 |
481 AFE_HDMI_CONN0_O34_I32 | AFE_HDMI_CONN0_O35_I33 |
482 AFE_HDMI_CONN0_O36_I36 | AFE_HDMI_CONN0_O37_I37);
483
484 /* enable Out control */
485 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0x1);
486
487 /* enable tdm */
488 regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0x1);
489
490 return 0;
491 case SNDRV_PCM_TRIGGER_STOP:
492 case SNDRV_PCM_TRIGGER_SUSPEND:
493 /* disable tdm */
494 regmap_update_bits(afe->regmap, AFE_TDM_CON1, 0x1, 0);
495
496 /* disable Out control */
497 regmap_update_bits(afe->regmap, AFE_HDMI_OUT_CON0, 0x1, 0);
498
499 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
500 AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF,
501 AUD_TCON0_PDN_HDMI | AUD_TCON0_PDN_SPDF);
502
503 return 0;
504 default:
505 return -EINVAL;
506 }
507}
508
509static int mtk_afe_dais_startup(struct snd_pcm_substream *substream,
510 struct snd_soc_dai *dai)
511{
512 struct snd_soc_pcm_runtime *rtd = substream->private_data;
513 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
514 struct snd_pcm_runtime *runtime = substream->runtime;
515 struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
516 int ret;
517
518 memif->substream = substream;
519
520 snd_soc_set_runtime_hwparams(substream, &mtk_afe_hardware);
521 ret = snd_pcm_hw_constraint_integer(runtime,
522 SNDRV_PCM_HW_PARAM_PERIODS);
523 if (ret < 0)
524 dev_err(afe->dev, "snd_pcm_hw_constraint_integer failed\n");
525 return ret;
526}
527
528static void mtk_afe_dais_shutdown(struct snd_pcm_substream *substream,
529 struct snd_soc_dai *dai)
530{
531 struct snd_soc_pcm_runtime *rtd = substream->private_data;
532 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
533 struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
534
535 memif->substream = NULL;
536}
537
538static int mtk_afe_dais_hw_params(struct snd_pcm_substream *substream,
539 struct snd_pcm_hw_params *params,
540 struct snd_soc_dai *dai)
541{
542 struct snd_soc_pcm_runtime *rtd = substream->private_data;
543 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
544 struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
545 int ret;
546
547 dev_dbg(afe->dev,
548 "%s period = %u, rate= %u, channels=%u\n",
549 __func__, params_period_size(params), params_rate(params),
550 params_channels(params));
551
552 ret = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
553 if (ret < 0)
554 return ret;
555
556 memif->phys_buf_addr = substream->runtime->dma_addr;
557 memif->buffer_size = substream->runtime->dma_bytes;
558 memif->hw_ptr = 0;
559
560 /* start */
561 regmap_write(afe->regmap,
562 memif->data->reg_ofs_base, memif->phys_buf_addr);
563 /* end */
564 regmap_write(afe->regmap,
565 memif->data->reg_ofs_base + AFE_BASE_END_OFFSET,
566 memif->phys_buf_addr + memif->buffer_size - 1);
567
568 /* set channel */
569 if (memif->data->mono_shift >= 0) {
570 unsigned int mono = (params_channels(params) == 1) ? 1 : 0;
571
572 regmap_update_bits(afe->regmap, AFE_DAC_CON1,
573 1 << memif->data->mono_shift,
574 mono << memif->data->mono_shift);
575 }
576
577 /* set rate */
578 if (memif->data->fs_shift < 0)
579 return 0;
580 if (memif->data->id == MTK_AFE_MEMIF_DAI ||
581 memif->data->id == MTK_AFE_MEMIF_MOD_DAI) {
582 unsigned int val;
583
584 switch (params_rate(params)) {
585 case 8000:
586 val = 0;
587 break;
588 case 16000:
589 val = 1;
590 break;
591 case 32000:
592 val = 2;
593 break;
594 default:
595 return -EINVAL;
596 }
597
598 if (memif->data->id == MTK_AFE_MEMIF_DAI)
599 regmap_update_bits(afe->regmap, AFE_DAC_CON0,
600 0x3 << memif->data->fs_shift,
601 val << memif->data->fs_shift);
602 else
603 regmap_update_bits(afe->regmap, AFE_DAC_CON1,
604 0x3 << memif->data->fs_shift,
605 val << memif->data->fs_shift);
606
607 } else {
608 int fs = mtk_afe_i2s_fs(params_rate(params));
609
610 if (fs < 0)
611 return -EINVAL;
612
613 regmap_update_bits(afe->regmap, AFE_DAC_CON1,
614 0xf << memif->data->fs_shift,
615 fs << memif->data->fs_shift);
616 }
617
618 return 0;
619}
620
621static int mtk_afe_dais_hw_free(struct snd_pcm_substream *substream,
622 struct snd_soc_dai *dai)
623{
624 return snd_pcm_lib_free_pages(substream);
625}
626
627static int mtk_afe_dais_prepare(struct snd_pcm_substream *substream,
628 struct snd_soc_dai *dai)
629{
630 struct snd_soc_pcm_runtime *rtd = substream->private_data;
631 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
632
633 /* enable AFE */
634 regmap_update_bits(afe->regmap, AFE_DAC_CON0, 0x1, 0x1);
635 return 0;
636}
637
638static int mtk_afe_dais_trigger(struct snd_pcm_substream *substream, int cmd,
639 struct snd_soc_dai *dai)
640{
641 struct snd_soc_pcm_runtime *rtd = substream->private_data;
642 struct snd_pcm_runtime * const runtime = substream->runtime;
643 struct mtk_afe *afe = snd_soc_platform_get_drvdata(rtd->platform);
644 struct mtk_afe_memif *memif = &afe->memif[rtd->cpu_dai->id];
645 unsigned int counter = runtime->period_size;
646
647 dev_info(afe->dev, "%s %s cmd=%d\n", __func__, memif->data->name, cmd);
648
649 switch (cmd) {
650 case SNDRV_PCM_TRIGGER_START:
651 case SNDRV_PCM_TRIGGER_RESUME:
652 if (memif->data->enable_shift >= 0)
653 regmap_update_bits(afe->regmap, AFE_DAC_CON0,
654 1 << memif->data->enable_shift,
655 1 << memif->data->enable_shift);
656
657 /* set irq counter */
658 regmap_update_bits(afe->regmap,
659 memif->data->irq_reg_cnt,
660 0x3ffff << memif->data->irq_cnt_shift,
661 counter << memif->data->irq_cnt_shift);
662
663 /* set irq fs */
664 if (memif->data->irq_fs_shift >= 0) {
665 int fs = mtk_afe_i2s_fs(runtime->rate);
666
667 if (fs < 0)
668 return -EINVAL;
669
670 regmap_update_bits(afe->regmap,
671 AFE_IRQ_MCU_CON,
672 0xf << memif->data->irq_fs_shift,
673 fs << memif->data->irq_fs_shift);
674 }
675 /* enable interrupt */
676 regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON,
677 1 << memif->data->irq_en_shift,
678 1 << memif->data->irq_en_shift);
679
680 return 0;
681 case SNDRV_PCM_TRIGGER_STOP:
682 case SNDRV_PCM_TRIGGER_SUSPEND:
683 if (memif->data->enable_shift >= 0)
684 regmap_update_bits(afe->regmap, AFE_DAC_CON0,
685 1 << memif->data->enable_shift, 0);
686 /* disable interrupt */
687 regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CON,
688 1 << memif->data->irq_en_shift,
689 0 << memif->data->irq_en_shift);
690 /* and clear pending IRQ */
691 regmap_write(afe->regmap, AFE_IRQ_CLR,
692 1 << memif->data->irq_clr_shift);
693 memif->hw_ptr = 0;
694 return 0;
695 default:
696 return -EINVAL;
697 }
698}
699
700/* FE DAIs */
701static const struct snd_soc_dai_ops mtk_afe_dai_ops = {
702 .startup = mtk_afe_dais_startup,
703 .shutdown = mtk_afe_dais_shutdown,
704 .hw_params = mtk_afe_dais_hw_params,
705 .hw_free = mtk_afe_dais_hw_free,
706 .prepare = mtk_afe_dais_prepare,
707 .trigger = mtk_afe_dais_trigger,
708};
709
710/* BE DAIs */
711static const struct snd_soc_dai_ops mtk_afe_i2s_ops = {
712 .startup = mtk_afe_i2s_startup,
713 .shutdown = mtk_afe_i2s_shutdown,
714 .prepare = mtk_afe_i2s_prepare,
715};
716
717static const struct snd_soc_dai_ops mtk_afe_hdmi_ops = {
718 .startup = mtk_afe_hdmi_startup,
719 .shutdown = mtk_afe_hdmi_shutdown,
720 .prepare = mtk_afe_hdmi_prepare,
721 .trigger = mtk_afe_hdmi_trigger,
722
723};
724
725static struct snd_soc_dai_driver mtk_afe_pcm_dais[] = {
726 /* FE DAIs: memory intefaces to CPU */
727 {
728 .name = "DL1", /* downlink 1 */
729 .id = MTK_AFE_MEMIF_DL1,
730 .playback = {
731 .stream_name = "DL1",
732 .channels_min = 1,
733 .channels_max = 2,
734 .rates = SNDRV_PCM_RATE_8000_48000,
735 .formats = SNDRV_PCM_FMTBIT_S16_LE,
736 },
737 .ops = &mtk_afe_dai_ops,
738 }, {
739 .name = "VUL", /* voice uplink */
740 .id = MTK_AFE_MEMIF_VUL,
741 .capture = {
742 .stream_name = "VUL",
743 .channels_min = 1,
744 .channels_max = 2,
745 .rates = SNDRV_PCM_RATE_8000_48000,
746 .formats = SNDRV_PCM_FMTBIT_S16_LE,
747 },
748 .ops = &mtk_afe_dai_ops,
749 }, {
750 /* BE DAIs */
751 .name = "I2S",
752 .id = MTK_AFE_IO_I2S,
753 .playback = {
754 .stream_name = "I2S Playback",
755 .channels_min = 1,
756 .channels_max = 2,
757 .rates = SNDRV_PCM_RATE_8000_48000,
758 .formats = SNDRV_PCM_FMTBIT_S16_LE,
759 },
760 .capture = {
761 .stream_name = "I2S Capture",
762 .channels_min = 1,
763 .channels_max = 2,
764 .rates = SNDRV_PCM_RATE_8000_48000,
765 .formats = SNDRV_PCM_FMTBIT_S16_LE,
766 },
767 .ops = &mtk_afe_i2s_ops,
768 .symmetric_rates = 1,
769 },
770};
771
772static struct snd_soc_dai_driver mtk_afe_hdmi_dais[] = {
773 /* FE DAIs */
774 {
775 .name = "HDMI",
776 .id = MTK_AFE_MEMIF_HDMI,
777 .playback = {
778 .stream_name = "HDMI",
779 .channels_min = 2,
780 .channels_max = 8,
781 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
782 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
783 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
784 SNDRV_PCM_RATE_192000,
785 .formats = SNDRV_PCM_FMTBIT_S16_LE,
786 },
787 .ops = &mtk_afe_dai_ops,
788 }, {
789 /* BE DAIs */
790 .name = "HDMIO",
791 .id = MTK_AFE_IO_HDMI,
792 .playback = {
793 .stream_name = "HDMIO Playback",
794 .channels_min = 2,
795 .channels_max = 8,
796 .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |
797 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |
798 SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |
799 SNDRV_PCM_RATE_192000,
800 .formats = SNDRV_PCM_FMTBIT_S16_LE,
801 },
802 .ops = &mtk_afe_hdmi_ops,
803 },
804};
805
806static const struct snd_kcontrol_new mtk_afe_o03_mix[] = {
807 SOC_DAPM_SINGLE_AUTODISABLE("I05 Switch", AFE_CONN1, 21, 1, 0),
808};
809
810static const struct snd_kcontrol_new mtk_afe_o04_mix[] = {
811 SOC_DAPM_SINGLE_AUTODISABLE("I06 Switch", AFE_CONN2, 6, 1, 0),
812};
813
814static const struct snd_kcontrol_new mtk_afe_o09_mix[] = {
815 SOC_DAPM_SINGLE_AUTODISABLE("I17 Switch", AFE_CONN7, 30, 1, 0),
816};
817
818static const struct snd_kcontrol_new mtk_afe_o10_mix[] = {
819 SOC_DAPM_SINGLE_AUTODISABLE("I18 Switch", AFE_CONN8, 0, 1, 0),
820};
821
822static const struct snd_soc_dapm_widget mtk_afe_pcm_widgets[] = {
823 /* Backend DAIs */
824 SND_SOC_DAPM_AIF_IN("I2S Capture", NULL, 0, SND_SOC_NOPM, 0, 0),
825 SND_SOC_DAPM_AIF_OUT("I2S Playback", NULL, 0, SND_SOC_NOPM, 0, 0),
826
827 /* inter-connections */
828 SND_SOC_DAPM_MIXER("I05", SND_SOC_NOPM, 0, 0, NULL, 0),
829 SND_SOC_DAPM_MIXER("I06", SND_SOC_NOPM, 0, 0, NULL, 0),
830 SND_SOC_DAPM_MIXER("I17", SND_SOC_NOPM, 0, 0, NULL, 0),
831 SND_SOC_DAPM_MIXER("I18", SND_SOC_NOPM, 0, 0, NULL, 0),
832
833 SND_SOC_DAPM_MIXER("O03", SND_SOC_NOPM, 0, 0,
834 mtk_afe_o03_mix, ARRAY_SIZE(mtk_afe_o03_mix)),
835 SND_SOC_DAPM_MIXER("O04", SND_SOC_NOPM, 0, 0,
836 mtk_afe_o04_mix, ARRAY_SIZE(mtk_afe_o04_mix)),
837 SND_SOC_DAPM_MIXER("O09", SND_SOC_NOPM, 0, 0,
838 mtk_afe_o09_mix, ARRAY_SIZE(mtk_afe_o09_mix)),
839 SND_SOC_DAPM_MIXER("O10", SND_SOC_NOPM, 0, 0,
840 mtk_afe_o10_mix, ARRAY_SIZE(mtk_afe_o10_mix)),
841};
842
843static const struct snd_soc_dapm_route mtk_afe_pcm_routes[] = {
844 {"I05", NULL, "DL1"},
845 {"I06", NULL, "DL1"},
846 {"I2S Playback", NULL, "O03"},
847 {"I2S Playback", NULL, "O04"},
848 {"VUL", NULL, "O09"},
849 {"VUL", NULL, "O10"},
850 {"I17", NULL, "I2S Capture"},
851 {"I18", NULL, "I2S Capture"},
852 { "O03", "I05 Switch", "I05" },
853 { "O04", "I06 Switch", "I06" },
854 { "O09", "I17 Switch", "I17" },
855 { "O10", "I18 Switch", "I18" },
856};
857
858static const struct snd_soc_dapm_widget mtk_afe_hdmi_widgets[] = {
859 /* Backend DAIs */
860 SND_SOC_DAPM_AIF_OUT("HDMIO Playback", NULL, 0, SND_SOC_NOPM, 0, 0),
861};
862
863static const struct snd_soc_dapm_route mtk_afe_hdmi_routes[] = {
864 {"HDMIO Playback", NULL, "HDMI"},
865};
866
867static const struct snd_soc_component_driver mtk_afe_pcm_dai_component = {
868 .name = "mtk-afe-pcm-dai",
869 .dapm_widgets = mtk_afe_pcm_widgets,
870 .num_dapm_widgets = ARRAY_SIZE(mtk_afe_pcm_widgets),
871 .dapm_routes = mtk_afe_pcm_routes,
872 .num_dapm_routes = ARRAY_SIZE(mtk_afe_pcm_routes),
873};
874
875static const struct snd_soc_component_driver mtk_afe_hdmi_dai_component = {
876 .name = "mtk-afe-hdmi-dai",
877 .dapm_widgets = mtk_afe_hdmi_widgets,
878 .num_dapm_widgets = ARRAY_SIZE(mtk_afe_hdmi_widgets),
879 .dapm_routes = mtk_afe_hdmi_routes,
880 .num_dapm_routes = ARRAY_SIZE(mtk_afe_hdmi_routes),
881};
882
883static const char *aud_clks[MTK_CLK_NUM] = {
884 [MTK_CLK_INFRASYS_AUD] = "infra_sys_audio_clk",
885 [MTK_CLK_TOP_PDN_AUD] = "top_pdn_audio",
886 [MTK_CLK_TOP_PDN_AUD_BUS] = "top_pdn_aud_intbus",
887 [MTK_CLK_I2S0_M] = "i2s0_m",
888 [MTK_CLK_I2S1_M] = "i2s1_m",
889 [MTK_CLK_I2S2_M] = "i2s2_m",
890 [MTK_CLK_I2S3_M] = "i2s3_m",
891 [MTK_CLK_I2S3_B] = "i2s3_b",
892 [MTK_CLK_BCK0] = "bck0",
893 [MTK_CLK_BCK1] = "bck1",
894};
895
896static const struct mtk_afe_memif_data memif_data[MTK_AFE_MEMIF_NUM] = {
897 {
898 .name = "DL1",
899 .id = MTK_AFE_MEMIF_DL1,
900 .reg_ofs_base = AFE_DL1_BASE,
901 .reg_ofs_cur = AFE_DL1_CUR,
902 .fs_shift = 0,
903 .mono_shift = 21,
904 .enable_shift = 1,
905 .irq_reg_cnt = AFE_IRQ_CNT1,
906 .irq_cnt_shift = 0,
907 .irq_en_shift = 0,
908 .irq_fs_shift = 4,
909 .irq_clr_shift = 0,
910 }, {
911 .name = "DL2",
912 .id = MTK_AFE_MEMIF_DL2,
913 .reg_ofs_base = AFE_DL2_BASE,
914 .reg_ofs_cur = AFE_DL2_CUR,
915 .fs_shift = 4,
916 .mono_shift = 22,
917 .enable_shift = 2,
918 .irq_reg_cnt = AFE_IRQ_CNT1,
919 .irq_cnt_shift = 20,
920 .irq_en_shift = 2,
921 .irq_fs_shift = 16,
922 .irq_clr_shift = 2,
923 }, {
924 .name = "VUL",
925 .id = MTK_AFE_MEMIF_VUL,
926 .reg_ofs_base = AFE_VUL_BASE,
927 .reg_ofs_cur = AFE_VUL_CUR,
928 .fs_shift = 16,
929 .mono_shift = 27,
930 .enable_shift = 3,
931 .irq_reg_cnt = AFE_IRQ_CNT2,
932 .irq_cnt_shift = 0,
933 .irq_en_shift = 1,
934 .irq_fs_shift = 8,
935 .irq_clr_shift = 1,
936 }, {
937 .name = "DAI",
938 .id = MTK_AFE_MEMIF_DAI,
939 .reg_ofs_base = AFE_DAI_BASE,
940 .reg_ofs_cur = AFE_DAI_CUR,
941 .fs_shift = 24,
942 .mono_shift = -1,
943 .enable_shift = 4,
944 .irq_reg_cnt = AFE_IRQ_CNT2,
945 .irq_cnt_shift = 20,
946 .irq_en_shift = 3,
947 .irq_fs_shift = 20,
948 .irq_clr_shift = 3,
949 }, {
950 .name = "AWB",
951 .id = MTK_AFE_MEMIF_AWB,
952 .reg_ofs_base = AFE_AWB_BASE,
953 .reg_ofs_cur = AFE_AWB_CUR,
954 .fs_shift = 12,
955 .mono_shift = 24,
956 .enable_shift = 6,
957 .irq_reg_cnt = AFE_IRQ_CNT7,
958 .irq_cnt_shift = 0,
959 .irq_en_shift = 14,
960 .irq_fs_shift = 24,
961 .irq_clr_shift = 6,
962 }, {
963 .name = "MOD_DAI",
964 .id = MTK_AFE_MEMIF_MOD_DAI,
965 .reg_ofs_base = AFE_MOD_PCM_BASE,
966 .reg_ofs_cur = AFE_MOD_PCM_CUR,
967 .fs_shift = 30,
968 .mono_shift = 30,
969 .enable_shift = 7,
970 .irq_reg_cnt = AFE_IRQ_CNT2,
971 .irq_cnt_shift = 20,
972 .irq_en_shift = 3,
973 .irq_fs_shift = 20,
974 .irq_clr_shift = 3,
975 }, {
976 .name = "HDMI",
977 .id = MTK_AFE_MEMIF_HDMI,
978 .reg_ofs_base = AFE_HDMI_OUT_BASE,
979 .reg_ofs_cur = AFE_HDMI_OUT_CUR,
980 .fs_shift = -1,
981 .mono_shift = -1,
982 .enable_shift = -1,
983 .irq_reg_cnt = AFE_IRQ_CNT5,
984 .irq_cnt_shift = 0,
985 .irq_en_shift = 12,
986 .irq_fs_shift = -1,
987 .irq_clr_shift = 4,
988 },
989};
990
991static const struct regmap_config mtk_afe_regmap_config = {
992 .reg_bits = 32,
993 .reg_stride = 4,
994 .val_bits = 32,
995 .max_register = AFE_ADDA2_TOP_CON0,
996 .cache_type = REGCACHE_NONE,
997};
998
999static irqreturn_t mtk_afe_irq_handler(int irq, void *dev_id)
1000{
1001 struct mtk_afe *afe = dev_id;
1002 unsigned int reg_value, hw_ptr;
1003 int i, ret;
1004
1005 ret = regmap_read(afe->regmap, AFE_IRQ_STATUS, &reg_value);
1006 if (ret) {
1007 dev_err(afe->dev, "%s irq status err\n", __func__);
1008 reg_value = AFE_IRQ_STATUS_BITS;
1009 goto err_irq;
1010 }
1011
1012 for (i = 0; i < MTK_AFE_MEMIF_NUM; i++) {
1013 struct mtk_afe_memif *memif = &afe->memif[i];
1014
1015 if (!(reg_value & (1 << memif->data->irq_clr_shift)))
1016 continue;
1017
1018 ret = regmap_read(afe->regmap, memif->data->reg_ofs_cur,
1019 &hw_ptr);
1020 if (ret || hw_ptr == 0) {
1021 dev_err(afe->dev, "%s hw_ptr err\n", __func__);
1022 hw_ptr = memif->phys_buf_addr;
1023 }
1024 memif->hw_ptr = hw_ptr - memif->phys_buf_addr;
1025 snd_pcm_period_elapsed(memif->substream);
1026 }
1027
1028err_irq:
1029 /* clear irq */
1030 regmap_write(afe->regmap, AFE_IRQ_CLR, reg_value & AFE_IRQ_STATUS_BITS);
1031
1032 return IRQ_HANDLED;
1033}
1034
1035static int mtk_afe_runtime_suspend(struct device *dev)
1036{
1037 struct mtk_afe *afe = dev_get_drvdata(dev);
1038
1039 /* disable AFE clk */
1040 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0,
1041 AUD_TCON0_PDN_AFE, AUD_TCON0_PDN_AFE);
1042
1043 clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
1044 clk_disable_unprepare(afe->clocks[MTK_CLK_BCK1]);
1045 clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]);
1046 clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]);
1047 clk_disable_unprepare(afe->clocks[MTK_CLK_INFRASYS_AUD]);
1048 return 0;
1049}
1050
1051static int mtk_afe_runtime_resume(struct device *dev)
1052{
1053 struct mtk_afe *afe = dev_get_drvdata(dev);
1054 int ret;
1055
1056 ret = clk_prepare_enable(afe->clocks[MTK_CLK_INFRASYS_AUD]);
1057 if (ret)
1058 return ret;
1059
1060 ret = clk_prepare_enable(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]);
1061 if (ret)
1062 goto err_infra;
1063
1064 ret = clk_prepare_enable(afe->clocks[MTK_CLK_TOP_PDN_AUD]);
1065 if (ret)
1066 goto err_top_aud_bus;
1067
1068 ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK0]);
1069 if (ret)
1070 goto err_top_aud;
1071
1072 ret = clk_prepare_enable(afe->clocks[MTK_CLK_BCK1]);
1073 if (ret)
1074 goto err_bck0;
1075
1076 /* enable AFE clk */
1077 regmap_update_bits(afe->regmap, AUDIO_TOP_CON0, AUD_TCON0_PDN_AFE, 0);
1078
1079 /* set O3/O4 16bits */
1080 regmap_update_bits(afe->regmap, AFE_CONN_24BIT,
1081 AFE_CONN_24BIT_O03 | AFE_CONN_24BIT_O04, 0);
1082
1083 /* unmask all IRQs */
1084 regmap_update_bits(afe->regmap, AFE_IRQ_MCU_EN, 0xff, 0xff);
1085 return 0;
1086
1087err_bck0:
1088 clk_disable_unprepare(afe->clocks[MTK_CLK_BCK0]);
1089err_top_aud:
1090 clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD]);
1091err_top_aud_bus:
1092 clk_disable_unprepare(afe->clocks[MTK_CLK_TOP_PDN_AUD_BUS]);
1093err_infra:
1094 clk_disable_unprepare(afe->clocks[MTK_CLK_INFRASYS_AUD]);
1095 return ret;
1096}
1097
1098static int mtk_afe_init_audio_clk(struct mtk_afe *afe)
1099{
1100 size_t i;
1101
1102 for (i = 0; i < ARRAY_SIZE(aud_clks); i++) {
1103 afe->clocks[i] = devm_clk_get(afe->dev, aud_clks[i]);
1104 if (IS_ERR(afe->clocks[i])) {
1105 dev_err(afe->dev, "%s devm_clk_get %s fail\n",
1106 __func__, aud_clks[i]);
1107 return PTR_ERR(afe->clocks[i]);
1108 }
1109 }
1110 clk_set_rate(afe->clocks[MTK_CLK_BCK0], 22579200); /* 22M */
1111 clk_set_rate(afe->clocks[MTK_CLK_BCK1], 24576000); /* 24M */
1112 return 0;
1113}
1114
1115static int mtk_afe_pcm_dev_probe(struct platform_device *pdev)
1116{
1117 int ret, i;
1118 unsigned int irq_id;
1119 struct mtk_afe *afe;
1120 struct resource *res;
1121
1122 afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
1123 if (!afe)
1124 return -ENOMEM;
1125
1126 afe->dev = &pdev->dev;
1127
1128 irq_id = platform_get_irq(pdev, 0);
1129 if (!irq_id) {
1130 dev_err(afe->dev, "np %s no irq\n", afe->dev->of_node->name);
1131 return -ENXIO;
1132 }
1133 ret = devm_request_irq(afe->dev, irq_id, mtk_afe_irq_handler,
1134 0, "Afe_ISR_Handle", (void *)afe);
1135 if (ret) {
1136 dev_err(afe->dev, "could not request_irq\n");
1137 return ret;
1138 }
1139
1140 res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
1141 afe->base_addr = devm_ioremap_resource(&pdev->dev, res);
1142 if (IS_ERR(afe->base_addr))
1143 return PTR_ERR(afe->base_addr);
1144
1145 afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
1146 &mtk_afe_regmap_config);
1147 if (IS_ERR(afe->regmap))
1148 return PTR_ERR(afe->regmap);
1149
1150 /* initial audio related clock */
1151 ret = mtk_afe_init_audio_clk(afe);
1152 if (ret) {
1153 dev_err(afe->dev, "mtk_afe_init_audio_clk fail\n");
1154 return ret;
1155 }
1156
1157 for (i = 0; i < MTK_AFE_MEMIF_NUM; i++)
1158 afe->memif[i].data = &memif_data[i];
1159
1160 platform_set_drvdata(pdev, afe);
1161
1162 pm_runtime_enable(&pdev->dev);
1163 if (!pm_runtime_enabled(&pdev->dev)) {
1164 ret = mtk_afe_runtime_resume(&pdev->dev);
1165 if (ret)
1166 goto err_pm_disable;
1167 }
1168
1169 ret = snd_soc_register_platform(&pdev->dev, &mtk_afe_pcm_platform);
1170 if (ret)
1171 goto err_pm_disable;
1172
1173 ret = snd_soc_register_component(&pdev->dev,
1174 &mtk_afe_pcm_dai_component,
1175 mtk_afe_pcm_dais,
1176 ARRAY_SIZE(mtk_afe_pcm_dais));
1177 if (ret)
1178 goto err_platform;
1179
1180 ret = snd_soc_register_component(&pdev->dev,
1181 &mtk_afe_hdmi_dai_component,
1182 mtk_afe_hdmi_dais,
1183 ARRAY_SIZE(mtk_afe_hdmi_dais));
1184 if (ret)
1185 goto err_comp;
1186
1187 dev_info(&pdev->dev, "MTK AFE driver initialized.\n");
1188 return 0;
1189
1190err_comp:
1191 snd_soc_unregister_component(&pdev->dev);
1192err_platform:
1193 snd_soc_unregister_platform(&pdev->dev);
1194err_pm_disable:
1195 pm_runtime_disable(&pdev->dev);
1196 return ret;
1197}
1198
1199static int mtk_afe_pcm_dev_remove(struct platform_device *pdev)
1200{
1201 pm_runtime_disable(&pdev->dev);
1202 snd_soc_unregister_component(&pdev->dev);
1203 snd_soc_unregister_platform(&pdev->dev);
1204 return 0;
1205}
1206
1207static const struct of_device_id mtk_afe_pcm_dt_match[] = {
1208 { .compatible = "mediatek,mt8173-afe-pcm", },
1209 { }
1210};
1211MODULE_DEVICE_TABLE(of, mtk_afe_pcm_dt_match);
1212
1213static const struct dev_pm_ops mtk_afe_pm_ops = {
1214 SET_RUNTIME_PM_OPS(mtk_afe_runtime_suspend, mtk_afe_runtime_resume,
1215 NULL)
1216};
1217
1218static struct platform_driver mtk_afe_pcm_driver = {
1219 .driver = {
1220 .name = "mtk-afe-pcm",
1221 .owner = THIS_MODULE,
1222 .of_match_table = mtk_afe_pcm_dt_match,
1223 .pm = &mtk_afe_pm_ops,
1224 },
1225 .probe = mtk_afe_pcm_dev_probe,
1226 .remove = mtk_afe_pcm_dev_remove,
1227};
1228
1229module_platform_driver(mtk_afe_pcm_driver);
1230
1231MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver");
1232MODULE_AUTHOR("Koro Chen <koro.chen@mediatek.com>");
1233MODULE_LICENSE("GPL v2");
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index fded99362d39..3bebfb1d3a6f 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -245,6 +245,8 @@ static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
245static const struct snd_soc_dapm_route audio_map[] = { 245static const struct snd_soc_dapm_route audio_map[] = {
246 {"Ext Spk", NULL, "HPLOUT"}, 246 {"Ext Spk", NULL, "HPLOUT"},
247 {"Ext Spk", NULL, "HPROUT"}, 247 {"Ext Spk", NULL, "HPROUT"},
248 {"Ext Spk", NULL, "HPLCOM"},
249 {"Ext Spk", NULL, "HPRCOM"},
248 {"Headphone Jack", NULL, "LLOUT"}, 250 {"Headphone Jack", NULL, "LLOUT"},
249 {"Headphone Jack", NULL, "RLOUT"}, 251 {"Headphone Jack", NULL, "RLOUT"},
250 {"FM Transmitter", NULL, "LLOUT"}, 252 {"FM Transmitter", NULL, "LLOUT"},
@@ -288,15 +290,8 @@ static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
288 struct snd_soc_codec *codec = rtd->codec; 290 struct snd_soc_codec *codec = rtd->codec;
289 struct snd_soc_card *card = rtd->card; 291 struct snd_soc_card *card = rtd->card;
290 struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card); 292 struct rx51_audio_pdata *pdata = snd_soc_card_get_drvdata(card);
291
292 struct snd_soc_dapm_context *dapm = &codec->dapm;
293 int err; 293 int err;
294 294
295 /* Set up NC codec pins */
296 snd_soc_dapm_nc_pin(dapm, "MIC3L");
297 snd_soc_dapm_nc_pin(dapm, "MIC3R");
298 snd_soc_dapm_nc_pin(dapm, "LINE1R");
299
300 err = tpa6130a2_add_controls(codec); 295 err = tpa6130a2_add_controls(codec);
301 if (err < 0) { 296 if (err < 0) {
302 dev_err(card->dev, "Failed to add TPA6130A2 controls\n"); 297 dev_err(card->dev, "Failed to add TPA6130A2 controls\n");
@@ -383,6 +378,7 @@ static struct snd_soc_card rx51_sound_card = {
383 .num_aux_devs = ARRAY_SIZE(rx51_aux_dev), 378 .num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
384 .codec_conf = rx51_codec_conf, 379 .codec_conf = rx51_codec_conf,
385 .num_configs = ARRAY_SIZE(rx51_codec_conf), 380 .num_configs = ARRAY_SIZE(rx51_codec_conf),
381 .fully_routed = true,
386 382
387 .controls = aic34_rx51_controls, 383 .controls = aic34_rx51_controls,
388 .num_controls = ARRAY_SIZE(aic34_rx51_controls), 384 .num_controls = ARRAY_SIZE(aic34_rx51_controls),