brintos

brintos / linux-shallow public Read only

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