blob: 6a455958baacc0f28be631191230bfb6d8a3c23a [file] [log] [blame]
developerbe797a32021-12-16 16:56:09 +08001// SPDX-License-Identifier: GPL-2.0
2/*
3 * mt79xx-si3218x.c -- MT79xx WM8960 ALSA SoC machine driver
4 *
5 * Copyright (c) 2021 MediaTek Inc.
6 * Author: Vic Wu <vic.wu@mediatek.com>
7 */
8
9#include <linux/module.h>
10#include <sound/soc.h>
11
12#include "mt79xx-afe-clk.h"
13#include "mt79xx-afe-common.h"
14#include "mt79xx-reg.h"
15#include "../common/mtk-afe-platform-driver.h"
16
17enum {
18 HOPPING_CLK = 0,
19 APLL_CLK = 1,
20};
21
22enum {
23 I2S = 0,
24 PCMA = 4,
25 PCMB,
26};
27
28enum {
29 ETDM_IN5 = 2,
30 ETDM_OUT5 = 10,
31};
32
33enum {
34 AFE_FS_8K = 0,
35 AFE_FS_11K = 1,
36 AFE_FS_12K = 2,
37 AFE_FS_16K = 4,
38 AFE_FS_22K = 5,
39 AFE_FS_24K = 6,
40 AFE_FS_32K = 8,
41 AFE_FS_44K = 9,
42 AFE_FS_48K = 10,
43 AFE_FS_88K = 13,
44 AFE_FS_96K = 14,
45 AFE_FS_176K = 17,
46 AFE_FS_192K = 18,
47};
48
49enum {
50 ETDM_FS_8K = 0,
51 ETDM_FS_12K = 1,
52 ETDM_FS_16K = 2,
53 ETDM_FS_24K = 3,
54 ETDM_FS_32K = 4,
55 ETDM_FS_48K = 5,
56 ETDM_FS_96K = 7,
57 ETDM_FS_192K = 9,
58 ETDM_FS_11K = 16,
59 ETDM_FS_22K = 17,
60 ETDM_FS_44K = 18,
61 ETDM_FS_88K = 19,
62 ETDM_FS_176K = 20,
63};
64
65struct mt79xx_si3218x_priv {
66 struct device_node *platform_node;
67 struct device_node *codec_node;
68};
69
70static int mt79xx_si3218x_init(struct snd_soc_pcm_runtime *rtd)
71{
72 struct snd_soc_component *component =
73 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
74 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
75
76 /* enable clk */
77 mt79xx_afe_enable_clock(afe);
78 regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_OUT5_PDN_MASK,
79 0);
80 regmap_update_bits(afe->regmap, AUDIO_TOP_CON2, CLK_IN5_PDN_MASK,
81 0);
82 regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0);
83 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK,
84 AUD_APLL2_EN);
85 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK,
86 AUD_26M_EN);
87
88 /* set ETDM_IN5_CON0 */
89 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_SYNC_MASK,
90 ETDM_SYNC);
91 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_FMT_MASK,
92 ETDM_FMT(PCMA));
93 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_BIT_LEN_MASK,
94 ETDM_BIT_LEN(16));
95 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_WRD_LEN_MASK,
96 ETDM_WRD_LEN(16));
97 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_CH_NUM_MASK,
98 ETDM_CH_NUM(4));
99 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, RELATCH_SRC_MASK,
100 RELATCH_SRC(APLL_CLK));
101
102 /* set ETDM_IN5_CON2 */
103 regmap_update_bits(afe->regmap, ETDM_IN5_CON2, IN_CLK_SRC_MASK,
104 IN_CLK_SRC(APLL_CLK));
105
106 /* set ETDM_IN5_CON3 */
107 regmap_update_bits(afe->regmap, ETDM_IN5_CON3, IN_SEL_FS_MASK,
108 IN_SEL_FS(ETDM_FS_16K));
109
110 /* set ETDM_IN5_CON4 */
111 regmap_update_bits(afe->regmap, ETDM_IN5_CON4, IN_CLK_INV_MASK,
112 IN_CLK_INV);
113 regmap_update_bits(afe->regmap, ETDM_IN5_CON4, IN_RELATCH_MASK,
114 IN_RELATCH(AFE_FS_16K));
115
116 /* set ETDM_OUT5_CON0 */
117 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_FMT_MASK,
118 ETDM_FMT(PCMA));
119 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_BIT_LEN_MASK,
120 ETDM_BIT_LEN(16));
121 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_WRD_LEN_MASK,
122 ETDM_WRD_LEN(16));
123 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_CH_NUM_MASK,
124 ETDM_CH_NUM(4));
125 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, RELATCH_SRC_MASK,
126 RELATCH_SRC(APLL_CLK));
127
128 /* set ETDM_OUT5_CON4 */
129 regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, OUT_SEL_FS_MASK,
130 OUT_SEL_FS(ETDM_FS_16K));
131 regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, OUT_CLK_SRC_MASK,
132 OUT_CLK_SRC(APLL_CLK));
133 regmap_update_bits(afe->regmap, ETDM_OUT5_CON4, OUT_RELATCH_MASK,
134 OUT_RELATCH(AFE_FS_16K));
135
136 /* set ETDM_OUT5_CON5 */
137 regmap_update_bits(afe->regmap, ETDM_OUT5_CON5, OUT_CLK_INV_MASK,
138 OUT_CLK_INV);
139 regmap_update_bits(afe->regmap, ETDM_OUT5_CON5, ETDM_CLK_DIV_MASK,
140 ETDM_CLK_DIV);
141
142 /* set external loopback */
143 regmap_update_bits(afe->regmap, ETDM_4_7_COWORK_CON0, OUT_SEL_MASK,
144 OUT_SEL(ETDM_IN5));
145
146 /* enable ETDM */
147 regmap_update_bits(afe->regmap, ETDM_IN5_CON0, ETDM_EN_MASK,
148 ETDM_EN);
149 regmap_update_bits(afe->regmap, ETDM_OUT5_CON0, ETDM_EN_MASK,
150 ETDM_EN);
151
152 return 0;
153}
154
155SND_SOC_DAILINK_DEFS(playback,
156 DAILINK_COMP_ARRAY(COMP_CPU("DL1")),
157 DAILINK_COMP_ARRAY(COMP_DUMMY()),
158 DAILINK_COMP_ARRAY(COMP_EMPTY()));
159
160SND_SOC_DAILINK_DEFS(capture,
161 DAILINK_COMP_ARRAY(COMP_CPU("UL1")),
162 DAILINK_COMP_ARRAY(COMP_DUMMY()),
163 DAILINK_COMP_ARRAY(COMP_EMPTY()));
164
165SND_SOC_DAILINK_DEFS(codec,
166 DAILINK_COMP_ARRAY(COMP_CPU("ETDM")),
167 DAILINK_COMP_ARRAY(COMP_CODEC(NULL, "proslic_spi-aif")),
168 DAILINK_COMP_ARRAY(COMP_EMPTY()));
169
170static struct snd_soc_dai_link mt79xx_si3218x_dai_links[] = {
171 /* FE */
172 {
173 .name = "si3218x-playback",
174 .stream_name = "si3218x-playback",
175 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
176 SND_SOC_DPCM_TRIGGER_POST},
177 .dynamic = 1,
178 .dpcm_playback = 1,
179 SND_SOC_DAILINK_REG(playback),
180 },
181 {
182 .name = "si3218x-capture",
183 .stream_name = "si3218x-capture",
184 .trigger = {SND_SOC_DPCM_TRIGGER_POST,
185 SND_SOC_DPCM_TRIGGER_POST},
186 .dynamic = 1,
187 .dpcm_capture = 1,
188 SND_SOC_DAILINK_REG(capture),
189 },
190 /* BE */
191 {
192 .name = "si3218x-codec",
193 .no_pcm = 1,
194 .dai_fmt = SND_SOC_DAIFMT_DSP_A |
195 SND_SOC_DAIFMT_IB_NF |
196 SND_SOC_DAIFMT_CBS_CFS,
197 .init = mt79xx_si3218x_init,
198 .dpcm_playback = 1,
199 .dpcm_capture = 1,
200 SND_SOC_DAILINK_REG(codec),
201 },
202};
203
204static struct snd_soc_card mt79xx_si3218x_card = {
205 .name = "mt79xx-si3218x",
206 .owner = THIS_MODULE,
207 .dai_link = mt79xx_si3218x_dai_links,
208 .num_links = ARRAY_SIZE(mt79xx_si3218x_dai_links),
209};
210
211static int mt79xx_si3218x_machine_probe(struct platform_device *pdev)
212{
213 struct snd_soc_card *card = &mt79xx_si3218x_card;
214 struct snd_soc_dai_link *dai_link;
215 struct mt79xx_si3218x_priv *priv;
216 int ret, i;
217
218 priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
219 if (!priv)
220 return -ENOMEM;
221
222 priv->platform_node = of_parse_phandle(pdev->dev.of_node,
223 "mediatek,platform", 0);
224 if (!priv->platform_node) {
225 dev_err(&pdev->dev, "Property 'platform' missing or invalid\n");
226 return -EINVAL;
227 }
228
229 for_each_card_prelinks(card, i, dai_link) {
230 if (dai_link->platforms->name)
231 continue;
232 dai_link->platforms->of_node = priv->platform_node;
233 }
234
235 card->dev = &pdev->dev;
236
237 priv->codec_node = of_parse_phandle(pdev->dev.of_node,
238 "mediatek,ext-codec", 0);
239 if (!priv->codec_node) {
240 dev_err(&pdev->dev,
241 "Property 'audio-codec' missing or invalid\n");
242 of_node_put(priv->platform_node);
243 return -EINVAL;
244 }
245
246 for_each_card_prelinks(card, i, dai_link) {
247 if (dai_link->codecs->name)
248 continue;
249 dai_link->codecs->of_node = priv->codec_node;
250 }
251
252 ret = devm_snd_soc_register_card(&pdev->dev, card);
253 if (ret) {
254 dev_err(&pdev->dev, "%s snd_soc_register_card fail %d\n",
255 __func__, ret);
256 of_node_put(priv->codec_node);
257 of_node_put(priv->platform_node);
258 }
259
260 return ret;
261}
262
263static int mt79xx_si3218x_machine_remove(struct platform_device *pdev)
264{
265 struct snd_soc_card *card = platform_get_drvdata(pdev);
266 struct mt79xx_si3218x_priv *priv = snd_soc_card_get_drvdata(card);
267
268 of_node_put(priv->codec_node);
269 of_node_put(priv->platform_node);
270
271 return 0;
272}
273
274#ifdef CONFIG_OF
275static const struct of_device_id mt79xx_si3218x_machine_dt_match[] = {
276 {.compatible = "mediatek,mt79xx-si3218x-machine",},
277 {}
278};
279#endif
280
281static struct platform_driver mt79xx_si3218x_machine = {
282 .driver = {
283 .name = "mt79xx-si3218x",
284#ifdef CONFIG_OF
285 .of_match_table = mt79xx_si3218x_machine_dt_match,
286#endif
287 },
288 .probe = mt79xx_si3218x_machine_probe,
289 .remove = mt79xx_si3218x_machine_remove,
290};
291
292module_platform_driver(mt79xx_si3218x_machine);
293
294/* Module information */
295MODULE_DESCRIPTION("MT79xx SI3218x ALSA SoC machine driver");
296MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
297MODULE_LICENSE("GPL");
298MODULE_ALIAS("mt79xx si3218x soc card");