blob: 63162c76acd1c5c35b9265f1b256f8387902e7c8 [file] [log] [blame]
developerbe797a32021-12-16 16:56:09 +08001// SPDX-License-Identifier: GPL-2.0
2//
3// Mediatek ALSA SoC AFE platform driver for 79xx
4//
5// Copyright (c) 2021 MediaTek Inc.
6// Author: Vic Wu <vic.wu@mediatek.com>
7
8#include <linux/delay.h>
9#include <linux/module.h>
10#include <linux/of.h>
11#include <linux/of_address.h>
12#include <linux/pm_runtime.h>
13
14#include "mt79xx-afe-common.h"
15#include "mt79xx-afe-clk.h"
16#include "mt79xx-reg.h"
17#include "../common/mtk-afe-platform-driver.h"
18#include "../common/mtk-afe-fe-dai.h"
19
20enum {
21 MTK_AFE_RATE_8K = 0,
22 MTK_AFE_RATE_11K = 1,
23 MTK_AFE_RATE_12K = 2,
24 MTK_AFE_RATE_16K = 4,
25 MTK_AFE_RATE_22K = 5,
26 MTK_AFE_RATE_24K = 6,
27 MTK_AFE_RATE_32K = 8,
28 MTK_AFE_RATE_44K = 9,
29 MTK_AFE_RATE_48K = 10,
30 MTK_AFE_RATE_88K = 13,
31 MTK_AFE_RATE_96K = 14,
32 MTK_AFE_RATE_176K = 17,
33 MTK_AFE_RATE_192K = 18,
34};
35
36unsigned int mt79xx_afe_rate_transform(struct device *dev,
37 unsigned int rate)
38{
39 switch (rate) {
40 case 8000:
41 return MTK_AFE_RATE_8K;
42 case 11025:
43 return MTK_AFE_RATE_11K;
44 case 12000:
45 return MTK_AFE_RATE_12K;
46 case 16000:
47 return MTK_AFE_RATE_16K;
48 case 22050:
49 return MTK_AFE_RATE_22K;
50 case 24000:
51 return MTK_AFE_RATE_24K;
52 case 32000:
53 return MTK_AFE_RATE_32K;
54 case 44100:
55 return MTK_AFE_RATE_44K;
56 case 48000:
57 return MTK_AFE_RATE_48K;
58 case 88200:
59 return MTK_AFE_RATE_88K;
60 case 96000:
61 return MTK_AFE_RATE_96K;
62 case 176400:
63 return MTK_AFE_RATE_176K;
64 case 192000:
65 return MTK_AFE_RATE_192K;
66 default:
67 dev_warn(dev, "%s(), rate %u invalid, use %d!!!\n",
68 __func__, rate, MTK_AFE_RATE_48K);
69 return MTK_AFE_RATE_48K;
70 }
71}
72
73static const struct snd_pcm_hardware mt79xx_afe_hardware = {
74 .info = SNDRV_PCM_INFO_MMAP |
75 SNDRV_PCM_INFO_INTERLEAVED |
76 SNDRV_PCM_INFO_MMAP_VALID,
77 .formats = SNDRV_PCM_FMTBIT_S16_LE |
78 SNDRV_PCM_FMTBIT_S24_LE |
79 SNDRV_PCM_FMTBIT_S32_LE,
80 .period_bytes_min = 256,
81 .period_bytes_max = 4 * 48 * 1024,
82 .periods_min = 2,
83 .periods_max = 256,
84 .buffer_bytes_max = 8 * 48 * 1024,
85 .fifo_size = 0,
86};
87
88static int mt79xx_memif_fs(struct snd_pcm_substream *substream,
89 unsigned int rate)
90{
91 struct snd_soc_pcm_runtime *rtd = substream->private_data;
92 struct snd_soc_component *component =
93 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
94 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
95
96 return mt79xx_afe_rate_transform(afe->dev, rate);
97}
98
99static int mt79xx_irq_fs(struct snd_pcm_substream *substream,
100 unsigned int rate)
101{
102 struct snd_soc_pcm_runtime *rtd = substream->private_data;
103 struct snd_soc_component *component =
104 snd_soc_rtdcom_lookup(rtd, AFE_PCM_NAME);
105 struct mtk_base_afe *afe = snd_soc_component_get_drvdata(component);
106
107 return mt79xx_afe_rate_transform(afe->dev, rate);
108}
109
110#define MTK_PCM_RATES (SNDRV_PCM_RATE_8000_48000 |\
111 SNDRV_PCM_RATE_88200 |\
112 SNDRV_PCM_RATE_96000 |\
113 SNDRV_PCM_RATE_176400 |\
114 SNDRV_PCM_RATE_192000)
115
116#define MTK_PCM_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\
117 SNDRV_PCM_FMTBIT_S24_LE |\
118 SNDRV_PCM_FMTBIT_S32_LE)
119
120static struct snd_soc_dai_driver mt79xx_memif_dai_driver[] = {
121 /* FE DAIs: memory intefaces to CPU */
122 {
123 .name = "DL1",
124 .id = MT79XX_MEMIF_DL1,
125 .playback = {
126 .stream_name = "DL1",
127 .channels_min = 1,
128 .channels_max = 2,
129 .rates = MTK_PCM_RATES,
130 .formats = MTK_PCM_FORMATS,
131 },
132 .ops = &mtk_afe_fe_ops,
133 },
134 {
135 .name = "UL1",
136 .id = MT79XX_MEMIF_VUL12,
137 .capture = {
138 .stream_name = "UL1",
139 .channels_min = 1,
140 .channels_max = 2,
141 .rates = MTK_PCM_RATES,
142 .formats = MTK_PCM_FORMATS,
143 },
144 .ops = &mtk_afe_fe_ops,
145 },
146};
147
148static const struct snd_kcontrol_new o018_mix[] = {
149 SOC_DAPM_SINGLE_AUTODISABLE("I150_Switch", AFE_CONN018_4, 22, 1, 0),
150};
151
152static const struct snd_kcontrol_new o019_mix[] = {
153 SOC_DAPM_SINGLE_AUTODISABLE("I151_Switch", AFE_CONN019_4, 23, 1, 0),
154};
155
156static const struct snd_soc_dapm_widget mt79xx_memif_widgets[] = {
157 /* DL */
158 SND_SOC_DAPM_MIXER("I032", SND_SOC_NOPM, 0, 0, NULL, 0),
159 SND_SOC_DAPM_MIXER("I033", SND_SOC_NOPM, 0, 0, NULL, 0),
160
161 /* UL */
162 SND_SOC_DAPM_MIXER("O018", SND_SOC_NOPM, 0, 0,
163 o018_mix, ARRAY_SIZE(o018_mix)),
164 SND_SOC_DAPM_MIXER("O019", SND_SOC_NOPM, 0, 0,
165 o019_mix, ARRAY_SIZE(o019_mix)),
166};
167
168static const struct snd_soc_dapm_route mt79xx_memif_routes[] = {
169 {"I032", NULL, "DL1"},
170 {"I033", NULL, "DL1"},
171 {"UL1", NULL, "O018"},
172 {"UL1", NULL, "O019"},
173 {"O018", "I150_Switch", "I150"},
174 {"O019", "I151_Switch", "I151"},
175};
176
177static const struct snd_soc_component_driver mt79xx_afe_pcm_dai_component = {
178 .name = "mt79xx-afe-pcm-dai",
179};
180
181static const struct mtk_base_memif_data memif_data[MT79XX_MEMIF_NUM] = {
182 [MT79XX_MEMIF_DL1] = {
183 .name = "DL1",
184 .id = MT79XX_MEMIF_DL1,
185 .reg_ofs_base = AFE_DL0_BASE,
186 .reg_ofs_cur = AFE_DL0_CUR,
187 .reg_ofs_end = AFE_DL0_END,
188 .reg_ofs_base_msb = AFE_DL0_BASE_MSB,
189 .reg_ofs_cur_msb = AFE_DL0_CUR_MSB,
190 .reg_ofs_end_msb = AFE_DL0_END_MSB,
191 .fs_reg = AFE_DL0_CON0,
192 .fs_shift = DL0_MODE_SFT,
193 .fs_maskbit = DL0_MODE_MASK,
194 .mono_reg = AFE_DL0_CON0,
195 .mono_shift = DL0_MONO_SFT,
196 .enable_reg = AFE_DL0_CON0,
197 .enable_shift = DL0_ON_SFT,
198 .hd_reg = AFE_DL0_CON0,
199 .hd_shift = DL0_HD_MODE_SFT,
200 .hd_align_reg = AFE_DL0_CON0,
201 .hd_align_mshift = DL0_HALIGN_SFT,
202 .pbuf_reg = AFE_DL0_CON0,
203 .pbuf_shift = DL0_PBUF_SIZE_SFT,
204 .minlen_reg = AFE_DL0_CON0,
205 .minlen_shift = DL0_MINLEN_SFT,
206 },
207 [MT79XX_MEMIF_VUL12] = {
208 .name = "VUL12",
209 .id = MT79XX_MEMIF_VUL12,
210 .reg_ofs_base = AFE_VUL0_BASE,
211 .reg_ofs_cur = AFE_VUL0_CUR,
212 .reg_ofs_end = AFE_VUL0_END,
213 .reg_ofs_base_msb = AFE_VUL0_BASE_MSB,
214 .reg_ofs_cur_msb = AFE_VUL0_CUR_MSB,
215 .reg_ofs_end_msb = AFE_VUL0_END_MSB,
216 .fs_reg = AFE_VUL0_CON0,
217 .fs_shift = VUL0_MODE_SFT,
218 .fs_maskbit = VUL0_MODE_MASK,
219 .mono_reg = AFE_VUL0_CON0,
220 .mono_shift = VUL0_MONO_SFT,
221 .enable_reg = AFE_VUL0_CON0,
222 .enable_shift = VUL0_ON_SFT,
223 .hd_reg = AFE_VUL0_CON0,
224 .hd_shift = VUL0_HD_MODE_SFT,
225 .hd_align_reg = AFE_VUL0_CON0,
226 .hd_align_mshift = VUL0_HALIGN_SFT,
227 },
228};
229
230static const struct mtk_base_irq_data irq_data[MT79XX_IRQ_NUM] = {
231 [MT79XX_IRQ_0] = {
232 .id = MT79XX_IRQ_0,
233 .irq_cnt_reg = AFE_IRQ0_MCU_CFG1,
234 .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
235 .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
236 .irq_fs_reg = AFE_IRQ0_MCU_CFG0,
237 .irq_fs_shift = IRQ_MCU_MODE_SFT,
238 .irq_fs_maskbit = IRQ_MCU_MODE_MASK,
239 .irq_en_reg = AFE_IRQ0_MCU_CFG0,
240 .irq_en_shift = IRQ_MCU_ON_SFT,
241 .irq_clr_reg = AFE_IRQ_MCU_CLR,
developer0426ed22022-01-07 10:49:03 +0800242 .irq_clr_shift = IRQ0_MCU_CLR_SFT,
developerbe797a32021-12-16 16:56:09 +0800243 },
244 [MT79XX_IRQ_1] = {
245 .id = MT79XX_IRQ_1,
246 .irq_cnt_reg = AFE_IRQ1_MCU_CFG1,
247 .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
248 .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
249 .irq_fs_reg = AFE_IRQ1_MCU_CFG0,
250 .irq_fs_shift = IRQ_MCU_MODE_SFT,
251 .irq_fs_maskbit = IRQ_MCU_MODE_MASK,
252 .irq_en_reg = AFE_IRQ1_MCU_CFG0,
253 .irq_en_shift = IRQ_MCU_ON_SFT,
254 .irq_clr_reg = AFE_IRQ_MCU_CLR,
developer0426ed22022-01-07 10:49:03 +0800255 .irq_clr_shift = IRQ1_MCU_CLR_SFT,
256 },
257 [MT79XX_IRQ_2] = {
258 .id = MT79XX_IRQ_2,
259 .irq_cnt_reg = AFE_IRQ2_MCU_CFG1,
260 .irq_cnt_shift = AFE_IRQ_CNT_SHIFT,
261 .irq_cnt_maskbit = AFE_IRQ_CNT_MASK,
262 .irq_fs_reg = AFE_IRQ2_MCU_CFG0,
263 .irq_fs_shift = IRQ_MCU_MODE_SFT,
264 .irq_fs_maskbit = IRQ_MCU_MODE_MASK,
265 .irq_en_reg = AFE_IRQ2_MCU_CFG0,
266 .irq_en_shift = IRQ_MCU_ON_SFT,
267 .irq_clr_reg = AFE_IRQ_MCU_CLR,
268 .irq_clr_shift = IRQ2_MCU_CLR_SFT,
developerbe797a32021-12-16 16:56:09 +0800269 },
270};
271
272static bool mt79xx_is_volatile_reg(struct device *dev, unsigned int reg)
273{
274 /* these auto-gen reg has read-only bit, so put it as volatile */
275 /* volatile reg cannot be cached, so cannot be set when power off */
276 switch (reg) {
277 case AFE_DL0_CUR_MSB:
278 case AFE_DL0_CUR:
279 case AFE_DL0_RCH_MON:
280 case AFE_DL0_LCH_MON:
281 case AFE_VUL0_CUR_MSB:
282 case AFE_VUL0_CUR:
283 case AFE_IRQ_MCU_STATUS:
284 case AFE_MEMIF_RD_MON:
285 case AFE_MEMIF_WR_MON:
286 return true;
287 default:
288 return false;
289 };
290}
291
292static const struct regmap_config mt79xx_afe_regmap_config = {
293 .reg_bits = 32,
294 .reg_stride = 4,
295 .val_bits = 32,
296 .volatile_reg = mt79xx_is_volatile_reg,
297 .max_register = AFE_MAX_REGISTER,
298 .num_reg_defaults_raw = ((AFE_MAX_REGISTER / 4) + 1),
299};
300
301static irqreturn_t mt79xx_afe_irq_handler(int irq_id, void *dev)
302{
303 struct mtk_base_afe *afe = dev;
304 struct mtk_base_afe_irq *irq;
305 unsigned int status;
306 unsigned int status_mcu;
307 unsigned int mcu_en;
308 int ret;
309 int i;
310 irqreturn_t irq_ret = IRQ_HANDLED;
311
312 /* get irq that is sent to MCU */
313 regmap_read(afe->regmap, AFE_IRQ_MCU_EN, &mcu_en);
314
315 ret = regmap_read(afe->regmap, AFE_IRQ_MCU_STATUS, &status);
316 /* only care IRQ which is sent to MCU */
317 status_mcu = status & mcu_en & AFE_IRQ_STATUS_BITS;
318
319 if (ret || status_mcu == 0) {
320 dev_err(afe->dev, "%s(), irq status err, ret %d, status 0x%x,\
321 mcu_en 0x%x\n", __func__, ret, status, mcu_en);
322
323 irq_ret = IRQ_NONE;
324 goto err_irq;
325 }
326
327 for (i = 0; i < MT79XX_MEMIF_NUM; i++) {
328 struct mtk_base_afe_memif *memif = &afe->memif[i];
329
330 if (!memif->substream)
331 continue;
332
333 if (memif->irq_usage < 0)
334 continue;
335
336 irq = &afe->irqs[memif->irq_usage];
337
338 if (status_mcu & (1 << irq->irq_data->irq_en_shift))
339 snd_pcm_period_elapsed(memif->substream);
340 }
341
342err_irq:
343 /* clear irq */
344 regmap_write(afe->regmap, AFE_IRQ_MCU_CLR, status_mcu);
345
346 return irq_ret;
347}
348
349static int mt79xx_afe_runtime_suspend(struct device *dev)
350{
351 struct mtk_base_afe *afe = dev_get_drvdata(dev);
352 struct mt79xx_afe_private *afe_priv = afe->platform_priv;
353
354 if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
355 goto skip_regmap;
356
357 /* disable clk*/
358 regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0x3fff);
359 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK,
360 0);
361 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK,
362 0);
363
364 /* make sure all irq status are cleared, twice intended */
365 regmap_update_bits(afe->regmap, AFE_IRQ_MCU_CLR, 0xffff, 0xffff);
366
367skip_regmap:
368 return mt79xx_afe_disable_clock(afe);
369}
370
371static int mt79xx_afe_runtime_resume(struct device *dev)
372{
373 struct mtk_base_afe *afe = dev_get_drvdata(dev);
374 struct mt79xx_afe_private *afe_priv = afe->platform_priv;
375 int ret;
376
377 ret = mt79xx_afe_enable_clock(afe);
378 if (ret)
379 return ret;
380
381 if (!afe->regmap || afe_priv->pm_runtime_bypass_reg_ctl)
382 goto skip_regmap;
383
384 /* enable clk*/
385 regmap_update_bits(afe->regmap, AUDIO_TOP_CON4, 0x3fff, 0);
386 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_APLL2_EN_MASK,
387 AUD_APLL2_EN);
388 regmap_update_bits(afe->regmap, AUDIO_ENGEN_CON0, AUD_26M_EN_MASK,
389 AUD_26M_EN);
390
391skip_regmap:
392 return 0;
393}
394
395static int mt79xx_afe_component_probe(struct snd_soc_component *component)
396{
397 return mtk_afe_add_sub_dai_control(component);
398}
399
400static const struct snd_soc_component_driver mt79xx_afe_component = {
401 .name = AFE_PCM_NAME,
402 .ops = &mtk_afe_pcm_ops,
403 .pcm_new = mtk_afe_pcm_new,
404 .pcm_free = mtk_afe_pcm_free,
405 .probe = mt79xx_afe_component_probe,
406};
407
408static int mt79xx_dai_memif_register(struct mtk_base_afe *afe)
409{
410 struct mtk_base_afe_dai *dai;
411
412 dai = devm_kzalloc(afe->dev, sizeof(*dai), GFP_KERNEL);
413 if (!dai)
414 return -ENOMEM;
415
416 list_add(&dai->list, &afe->sub_dais);
417
418 dai->dai_drivers = mt79xx_memif_dai_driver;
419 dai->num_dai_drivers = ARRAY_SIZE(mt79xx_memif_dai_driver);
420
421 dai->dapm_widgets = mt79xx_memif_widgets;
422 dai->num_dapm_widgets = ARRAY_SIZE(mt79xx_memif_widgets);
423 dai->dapm_routes = mt79xx_memif_routes;
424 dai->num_dapm_routes = ARRAY_SIZE(mt79xx_memif_routes);
425
426 return 0;
427}
428
429typedef int (*dai_register_cb)(struct mtk_base_afe *);
430static const dai_register_cb dai_register_cbs[] = {
431 mt79xx_dai_etdm_register,
432 mt79xx_dai_memif_register,
433};
434
435static int mt79xx_afe_pcm_dev_probe(struct platform_device *pdev)
436{
437 struct mtk_base_afe *afe;
438 struct mt79xx_afe_private *afe_priv;
439 struct device *dev;
440 int i, irq_id, ret;
441
442 afe = devm_kzalloc(&pdev->dev, sizeof(*afe), GFP_KERNEL);
443 if (!afe)
444 return -ENOMEM;
445 platform_set_drvdata(pdev, afe);
446
447 afe->platform_priv = devm_kzalloc(&pdev->dev, sizeof(*afe_priv),
448 GFP_KERNEL);
449 if (!afe->platform_priv)
450 return -ENOMEM;
451
452 afe_priv = afe->platform_priv;
453 afe->dev = &pdev->dev;
454 dev = afe->dev;
455
456 afe->base_addr = devm_platform_ioremap_resource(pdev, 0);
457 if (IS_ERR(afe->base_addr))
458 return PTR_ERR(afe->base_addr);
459
460 /* initial audio related clock */
461 ret = mt79xx_init_clock(afe);
462 if (ret) {
463 dev_err(dev, "init clock error\n");
464 return ret;
465 }
466
467 pm_runtime_enable(dev);
468
469 /* enable clock for regcache get default value from hw */
470 afe_priv->pm_runtime_bypass_reg_ctl = true;
471 pm_runtime_get_sync(&pdev->dev);
472
473 afe->regmap = devm_regmap_init_mmio(&pdev->dev, afe->base_addr,
474 &mt79xx_afe_regmap_config);
475 if (IS_ERR(afe->regmap)) {
476 ret = PTR_ERR(afe->regmap);
477 goto err_pm_disable;
478 }
479
480 pm_runtime_put_sync(&pdev->dev);
481 afe_priv->pm_runtime_bypass_reg_ctl = false;
482
483 /* init memif */
484 afe->memif_size = MT79XX_MEMIF_NUM;
485 afe->memif = devm_kcalloc(dev, afe->memif_size, sizeof(*afe->memif),
486 GFP_KERNEL);
487 if (!afe->memif)
488 goto err_pm_disable;
489
490 for (i = 0; i < afe->memif_size; i++) {
491 afe->memif[i].data = &memif_data[i];
492 afe->memif[i].irq_usage = -1;
493 }
494
495 mutex_init(&afe->irq_alloc_lock);
496
497 /* irq initialize */
498 afe->irqs_size = MT79XX_IRQ_NUM;
499 afe->irqs = devm_kcalloc(dev, afe->irqs_size, sizeof(*afe->irqs),
500 GFP_KERNEL);
501 if (!afe->irqs)
502 goto err_pm_disable;
503
504 for (i = 0; i < afe->irqs_size; i++)
505 afe->irqs[i].irq_data = &irq_data[i];
506
507 /* request irq */
508 irq_id = platform_get_irq(pdev, 0);
509 if (!irq_id) {
510 dev_err(dev, "%pOFn no irq found\n", dev->of_node);
511 goto err_pm_disable;
512 }
513 ret = devm_request_irq(dev, irq_id, mt79xx_afe_irq_handler,
514 IRQF_TRIGGER_NONE, "asys-isr", (void *)afe);
515 if (ret) {
516 dev_err(dev, "could not request_irq for asys-isr\n");
517 goto err_pm_disable;
518 }
519
520 /* init sub_dais */
521 INIT_LIST_HEAD(&afe->sub_dais);
522
523 for (i = 0; i < ARRAY_SIZE(dai_register_cbs); i++) {
524 ret = dai_register_cbs[i](afe);
525 if (ret) {
526 dev_warn(afe->dev, "dai register i %d fail, ret %d\n",
527 i, ret);
528 goto err_pm_disable;
529 }
530 }
531
532 /* init dai_driver and component_driver */
533 ret = mtk_afe_combine_sub_dai(afe);
534 if (ret) {
535 dev_warn(afe->dev, "mtk_afe_combine_sub_dai fail, ret %d\n",
536 ret);
537 goto err_pm_disable;
538 }
539
540 afe->mtk_afe_hardware = &mt79xx_afe_hardware;
541 afe->memif_fs = mt79xx_memif_fs;
542 afe->irq_fs = mt79xx_irq_fs;
543
544 afe->runtime_resume = mt79xx_afe_runtime_resume;
545 afe->runtime_suspend = mt79xx_afe_runtime_suspend;
546
547 /* register component */
548 ret = devm_snd_soc_register_component(&pdev->dev,
549 &mt79xx_afe_component,
550 NULL, 0);
551 if (ret) {
552 dev_warn(dev, "err_platform\n");
553 goto err_pm_disable;
554 }
555
556 ret = devm_snd_soc_register_component(afe->dev,
557 &mt79xx_afe_pcm_dai_component,
558 afe->dai_drivers,
559 afe->num_dai_drivers);
560 if (ret) {
561 dev_warn(dev, "err_dai_component\n");
562 goto err_pm_disable;
563 }
564
565 return ret;
566
567err_pm_disable:
568 pm_runtime_put_sync(&pdev->dev);
569 pm_runtime_disable(&pdev->dev);
570 return ret;
571}
572
573static int mt79xx_afe_pcm_dev_remove(struct platform_device *pdev)
574{
575 pm_runtime_disable(&pdev->dev);
576 if (!pm_runtime_status_suspended(&pdev->dev))
577 mt79xx_afe_runtime_suspend(&pdev->dev);
578
579 return 0;
580}
581
582static const struct of_device_id mt79xx_afe_pcm_dt_match[] = {
583 { .compatible = "mediatek,mt79xx-audio", },
584 {},
585};
586MODULE_DEVICE_TABLE(of, mt79xx_afe_pcm_dt_match);
587
588static const struct dev_pm_ops mt79xx_afe_pm_ops = {
589 SET_RUNTIME_PM_OPS(mt79xx_afe_runtime_suspend,
590 mt79xx_afe_runtime_resume, NULL)
591};
592
593static struct platform_driver mt79xx_afe_pcm_driver = {
594 .driver = {
595 .name = "mt79xx-audio",
596 .of_match_table = mt79xx_afe_pcm_dt_match,
597 .pm = &mt79xx_afe_pm_ops,
598 },
599 .probe = mt79xx_afe_pcm_dev_probe,
600 .remove = mt79xx_afe_pcm_dev_remove,
601};
602
603module_platform_driver(mt79xx_afe_pcm_driver);
604
605MODULE_DESCRIPTION("Mediatek ALSA SoC AFE platform driver for 79xx");
606MODULE_AUTHOR("Vic Wu <vic.wu@mediatek.com>");
607MODULE_LICENSE("GPL");