18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (c) 2010-2011,2013-2015 The Linux Foundation. All rights reserved. 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * lpass-apq8016.c -- ALSA SoC CPU DAI driver for APQ8016 LPASS 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/clk.h> 108c2ecf20Sopenharmony_ci#include <linux/device.h> 118c2ecf20Sopenharmony_ci#include <linux/err.h> 128c2ecf20Sopenharmony_ci#include <linux/kernel.h> 138c2ecf20Sopenharmony_ci#include <linux/module.h> 148c2ecf20Sopenharmony_ci#include <linux/of.h> 158c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 168c2ecf20Sopenharmony_ci#include <sound/pcm.h> 178c2ecf20Sopenharmony_ci#include <sound/pcm_params.h> 188c2ecf20Sopenharmony_ci#include <sound/soc.h> 198c2ecf20Sopenharmony_ci#include <sound/soc-dai.h> 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_ci#include <dt-bindings/sound/apq8016-lpass.h> 228c2ecf20Sopenharmony_ci#include "lpass-lpaif-reg.h" 238c2ecf20Sopenharmony_ci#include "lpass.h" 248c2ecf20Sopenharmony_ci 258c2ecf20Sopenharmony_cistatic struct snd_soc_dai_driver apq8016_lpass_cpu_dai_driver[] = { 268c2ecf20Sopenharmony_ci [MI2S_PRIMARY] = { 278c2ecf20Sopenharmony_ci .id = MI2S_PRIMARY, 288c2ecf20Sopenharmony_ci .name = "Primary MI2S", 298c2ecf20Sopenharmony_ci .playback = { 308c2ecf20Sopenharmony_ci .stream_name = "Primary Playback", 318c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16 | 328c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24 | 338c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32, 348c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000 | 358c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | 368c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | 378c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 388c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000, 398c2ecf20Sopenharmony_ci .rate_min = 8000, 408c2ecf20Sopenharmony_ci .rate_max = 96000, 418c2ecf20Sopenharmony_ci .channels_min = 1, 428c2ecf20Sopenharmony_ci .channels_max = 8, 438c2ecf20Sopenharmony_ci }, 448c2ecf20Sopenharmony_ci .probe = &asoc_qcom_lpass_cpu_dai_probe, 458c2ecf20Sopenharmony_ci .ops = &asoc_qcom_lpass_cpu_dai_ops, 468c2ecf20Sopenharmony_ci }, 478c2ecf20Sopenharmony_ci [MI2S_SECONDARY] = { 488c2ecf20Sopenharmony_ci .id = MI2S_SECONDARY, 498c2ecf20Sopenharmony_ci .name = "Secondary MI2S", 508c2ecf20Sopenharmony_ci .playback = { 518c2ecf20Sopenharmony_ci .stream_name = "Secondary Playback", 528c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16 | 538c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24 | 548c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32, 558c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000 | 568c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | 578c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | 588c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 598c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000, 608c2ecf20Sopenharmony_ci .rate_min = 8000, 618c2ecf20Sopenharmony_ci .rate_max = 96000, 628c2ecf20Sopenharmony_ci .channels_min = 1, 638c2ecf20Sopenharmony_ci .channels_max = 8, 648c2ecf20Sopenharmony_ci }, 658c2ecf20Sopenharmony_ci .probe = &asoc_qcom_lpass_cpu_dai_probe, 668c2ecf20Sopenharmony_ci .ops = &asoc_qcom_lpass_cpu_dai_ops, 678c2ecf20Sopenharmony_ci }, 688c2ecf20Sopenharmony_ci [MI2S_TERTIARY] = { 698c2ecf20Sopenharmony_ci .id = MI2S_TERTIARY, 708c2ecf20Sopenharmony_ci .name = "Tertiary MI2S", 718c2ecf20Sopenharmony_ci .capture = { 728c2ecf20Sopenharmony_ci .stream_name = "Tertiary Capture", 738c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16 | 748c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24 | 758c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32, 768c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000 | 778c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | 788c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | 798c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 808c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000, 818c2ecf20Sopenharmony_ci .rate_min = 8000, 828c2ecf20Sopenharmony_ci .rate_max = 96000, 838c2ecf20Sopenharmony_ci .channels_min = 1, 848c2ecf20Sopenharmony_ci .channels_max = 8, 858c2ecf20Sopenharmony_ci }, 868c2ecf20Sopenharmony_ci .probe = &asoc_qcom_lpass_cpu_dai_probe, 878c2ecf20Sopenharmony_ci .ops = &asoc_qcom_lpass_cpu_dai_ops, 888c2ecf20Sopenharmony_ci }, 898c2ecf20Sopenharmony_ci [MI2S_QUATERNARY] = { 908c2ecf20Sopenharmony_ci .id = MI2S_QUATERNARY, 918c2ecf20Sopenharmony_ci .name = "Quatenary MI2S", 928c2ecf20Sopenharmony_ci .playback = { 938c2ecf20Sopenharmony_ci .stream_name = "Quatenary Playback", 948c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16 | 958c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24 | 968c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32, 978c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000 | 988c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | 998c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | 1008c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 1018c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000, 1028c2ecf20Sopenharmony_ci .rate_min = 8000, 1038c2ecf20Sopenharmony_ci .rate_max = 96000, 1048c2ecf20Sopenharmony_ci .channels_min = 1, 1058c2ecf20Sopenharmony_ci .channels_max = 8, 1068c2ecf20Sopenharmony_ci }, 1078c2ecf20Sopenharmony_ci .capture = { 1088c2ecf20Sopenharmony_ci .stream_name = "Quatenary Capture", 1098c2ecf20Sopenharmony_ci .formats = SNDRV_PCM_FMTBIT_S16 | 1108c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S24 | 1118c2ecf20Sopenharmony_ci SNDRV_PCM_FMTBIT_S32, 1128c2ecf20Sopenharmony_ci .rates = SNDRV_PCM_RATE_8000 | 1138c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_16000 | 1148c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_32000 | 1158c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_48000 | 1168c2ecf20Sopenharmony_ci SNDRV_PCM_RATE_96000, 1178c2ecf20Sopenharmony_ci .rate_min = 8000, 1188c2ecf20Sopenharmony_ci .rate_max = 96000, 1198c2ecf20Sopenharmony_ci .channels_min = 1, 1208c2ecf20Sopenharmony_ci .channels_max = 8, 1218c2ecf20Sopenharmony_ci }, 1228c2ecf20Sopenharmony_ci .probe = &asoc_qcom_lpass_cpu_dai_probe, 1238c2ecf20Sopenharmony_ci .ops = &asoc_qcom_lpass_cpu_dai_ops, 1248c2ecf20Sopenharmony_ci }, 1258c2ecf20Sopenharmony_ci}; 1268c2ecf20Sopenharmony_ci 1278c2ecf20Sopenharmony_cistatic int apq8016_lpass_alloc_dma_channel(struct lpass_data *drvdata, 1288c2ecf20Sopenharmony_ci int direction, unsigned int dai_id) 1298c2ecf20Sopenharmony_ci{ 1308c2ecf20Sopenharmony_ci struct lpass_variant *v = drvdata->variant; 1318c2ecf20Sopenharmony_ci int chan = 0; 1328c2ecf20Sopenharmony_ci 1338c2ecf20Sopenharmony_ci if (direction == SNDRV_PCM_STREAM_PLAYBACK) { 1348c2ecf20Sopenharmony_ci chan = find_first_zero_bit(&drvdata->dma_ch_bit_map, 1358c2ecf20Sopenharmony_ci v->rdma_channels); 1368c2ecf20Sopenharmony_ci 1378c2ecf20Sopenharmony_ci if (chan >= v->rdma_channels) 1388c2ecf20Sopenharmony_ci return -EBUSY; 1398c2ecf20Sopenharmony_ci } else { 1408c2ecf20Sopenharmony_ci chan = find_next_zero_bit(&drvdata->dma_ch_bit_map, 1418c2ecf20Sopenharmony_ci v->wrdma_channel_start + 1428c2ecf20Sopenharmony_ci v->wrdma_channels, 1438c2ecf20Sopenharmony_ci v->wrdma_channel_start); 1448c2ecf20Sopenharmony_ci 1458c2ecf20Sopenharmony_ci if (chan >= v->wrdma_channel_start + v->wrdma_channels) 1468c2ecf20Sopenharmony_ci return -EBUSY; 1478c2ecf20Sopenharmony_ci } 1488c2ecf20Sopenharmony_ci 1498c2ecf20Sopenharmony_ci set_bit(chan, &drvdata->dma_ch_bit_map); 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci return chan; 1528c2ecf20Sopenharmony_ci} 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_cistatic int apq8016_lpass_free_dma_channel(struct lpass_data *drvdata, int chan, unsigned int dai_id) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci clear_bit(chan, &drvdata->dma_ch_bit_map); 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int apq8016_lpass_init(struct platform_device *pdev) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci struct lpass_data *drvdata = platform_get_drvdata(pdev); 1648c2ecf20Sopenharmony_ci struct lpass_variant *variant = drvdata->variant; 1658c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 1668c2ecf20Sopenharmony_ci int ret, i; 1678c2ecf20Sopenharmony_ci 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci drvdata->clks = devm_kcalloc(dev, variant->num_clks, 1708c2ecf20Sopenharmony_ci sizeof(*drvdata->clks), GFP_KERNEL); 1718c2ecf20Sopenharmony_ci if (!drvdata->clks) 1728c2ecf20Sopenharmony_ci return -ENOMEM; 1738c2ecf20Sopenharmony_ci drvdata->num_clks = variant->num_clks; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci for (i = 0; i < drvdata->num_clks; i++) 1768c2ecf20Sopenharmony_ci drvdata->clks[i].id = variant->clk_name[i]; 1778c2ecf20Sopenharmony_ci 1788c2ecf20Sopenharmony_ci ret = devm_clk_bulk_get(dev, drvdata->num_clks, drvdata->clks); 1798c2ecf20Sopenharmony_ci if (ret) { 1808c2ecf20Sopenharmony_ci dev_err(dev, "Failed to get clocks %d\n", ret); 1818c2ecf20Sopenharmony_ci return ret; 1828c2ecf20Sopenharmony_ci } 1838c2ecf20Sopenharmony_ci 1848c2ecf20Sopenharmony_ci ret = clk_bulk_prepare_enable(drvdata->num_clks, drvdata->clks); 1858c2ecf20Sopenharmony_ci if (ret) { 1868c2ecf20Sopenharmony_ci dev_err(dev, "apq8016 clk_enable failed\n"); 1878c2ecf20Sopenharmony_ci return ret; 1888c2ecf20Sopenharmony_ci } 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci drvdata->ahbix_clk = devm_clk_get(dev, "ahbix-clk"); 1918c2ecf20Sopenharmony_ci if (IS_ERR(drvdata->ahbix_clk)) { 1928c2ecf20Sopenharmony_ci dev_err(dev, "error getting ahbix-clk: %ld\n", 1938c2ecf20Sopenharmony_ci PTR_ERR(drvdata->ahbix_clk)); 1948c2ecf20Sopenharmony_ci ret = PTR_ERR(drvdata->ahbix_clk); 1958c2ecf20Sopenharmony_ci goto err_ahbix_clk; 1968c2ecf20Sopenharmony_ci } 1978c2ecf20Sopenharmony_ci 1988c2ecf20Sopenharmony_ci ret = clk_set_rate(drvdata->ahbix_clk, LPASS_AHBIX_CLOCK_FREQUENCY); 1998c2ecf20Sopenharmony_ci if (ret) { 2008c2ecf20Sopenharmony_ci dev_err(dev, "error setting rate on ahbix_clk: %d\n", ret); 2018c2ecf20Sopenharmony_ci goto err_ahbix_clk; 2028c2ecf20Sopenharmony_ci } 2038c2ecf20Sopenharmony_ci dev_dbg(dev, "set ahbix_clk rate to %lu\n", 2048c2ecf20Sopenharmony_ci clk_get_rate(drvdata->ahbix_clk)); 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci ret = clk_prepare_enable(drvdata->ahbix_clk); 2078c2ecf20Sopenharmony_ci if (ret) { 2088c2ecf20Sopenharmony_ci dev_err(dev, "error enabling ahbix_clk: %d\n", ret); 2098c2ecf20Sopenharmony_ci goto err_ahbix_clk; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci return 0; 2138c2ecf20Sopenharmony_ci 2148c2ecf20Sopenharmony_cierr_ahbix_clk: 2158c2ecf20Sopenharmony_ci clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); 2168c2ecf20Sopenharmony_ci return ret; 2178c2ecf20Sopenharmony_ci} 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_cistatic int apq8016_lpass_exit(struct platform_device *pdev) 2208c2ecf20Sopenharmony_ci{ 2218c2ecf20Sopenharmony_ci struct lpass_data *drvdata = platform_get_drvdata(pdev); 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci clk_bulk_disable_unprepare(drvdata->num_clks, drvdata->clks); 2248c2ecf20Sopenharmony_ci clk_disable_unprepare(drvdata->ahbix_clk); 2258c2ecf20Sopenharmony_ci 2268c2ecf20Sopenharmony_ci return 0; 2278c2ecf20Sopenharmony_ci} 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci 2308c2ecf20Sopenharmony_cistatic struct lpass_variant apq8016_data = { 2318c2ecf20Sopenharmony_ci .i2sctrl_reg_base = 0x1000, 2328c2ecf20Sopenharmony_ci .i2sctrl_reg_stride = 0x1000, 2338c2ecf20Sopenharmony_ci .i2s_ports = 4, 2348c2ecf20Sopenharmony_ci .irq_reg_base = 0x6000, 2358c2ecf20Sopenharmony_ci .irq_reg_stride = 0x1000, 2368c2ecf20Sopenharmony_ci .irq_ports = 3, 2378c2ecf20Sopenharmony_ci .rdma_reg_base = 0x8400, 2388c2ecf20Sopenharmony_ci .rdma_reg_stride = 0x1000, 2398c2ecf20Sopenharmony_ci .rdma_channels = 2, 2408c2ecf20Sopenharmony_ci .dmactl_audif_start = 1, 2418c2ecf20Sopenharmony_ci .wrdma_reg_base = 0xB000, 2428c2ecf20Sopenharmony_ci .wrdma_reg_stride = 0x1000, 2438c2ecf20Sopenharmony_ci .wrdma_channel_start = 5, 2448c2ecf20Sopenharmony_ci .wrdma_channels = 2, 2458c2ecf20Sopenharmony_ci .loopback = REG_FIELD_ID(0x1000, 15, 15, 4, 0x1000), 2468c2ecf20Sopenharmony_ci .spken = REG_FIELD_ID(0x1000, 14, 14, 4, 0x1000), 2478c2ecf20Sopenharmony_ci .spkmode = REG_FIELD_ID(0x1000, 10, 13, 4, 0x1000), 2488c2ecf20Sopenharmony_ci .spkmono = REG_FIELD_ID(0x1000, 9, 9, 4, 0x1000), 2498c2ecf20Sopenharmony_ci .micen = REG_FIELD_ID(0x1000, 8, 8, 4, 0x1000), 2508c2ecf20Sopenharmony_ci .micmode = REG_FIELD_ID(0x1000, 4, 7, 4, 0x1000), 2518c2ecf20Sopenharmony_ci .micmono = REG_FIELD_ID(0x1000, 3, 3, 4, 0x1000), 2528c2ecf20Sopenharmony_ci .wssrc = REG_FIELD_ID(0x1000, 2, 2, 4, 0x1000), 2538c2ecf20Sopenharmony_ci .bitwidth = REG_FIELD_ID(0x1000, 0, 1, 4, 0x1000), 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci .rdma_dyncclk = REG_FIELD_ID(0x8400, 12, 12, 2, 0x1000), 2568c2ecf20Sopenharmony_ci .rdma_bursten = REG_FIELD_ID(0x8400, 11, 11, 2, 0x1000), 2578c2ecf20Sopenharmony_ci .rdma_wpscnt = REG_FIELD_ID(0x8400, 8, 10, 2, 0x1000), 2588c2ecf20Sopenharmony_ci .rdma_intf = REG_FIELD_ID(0x8400, 4, 7, 2, 0x1000), 2598c2ecf20Sopenharmony_ci .rdma_fifowm = REG_FIELD_ID(0x8400, 1, 3, 2, 0x1000), 2608c2ecf20Sopenharmony_ci .rdma_enable = REG_FIELD_ID(0x8400, 0, 0, 2, 0x1000), 2618c2ecf20Sopenharmony_ci 2628c2ecf20Sopenharmony_ci .wrdma_dyncclk = REG_FIELD_ID(0xB000, 12, 12, 2, 0x1000), 2638c2ecf20Sopenharmony_ci .wrdma_bursten = REG_FIELD_ID(0xB000, 11, 11, 2, 0x1000), 2648c2ecf20Sopenharmony_ci .wrdma_wpscnt = REG_FIELD_ID(0xB000, 8, 10, 2, 0x1000), 2658c2ecf20Sopenharmony_ci .wrdma_intf = REG_FIELD_ID(0xB000, 4, 7, 2, 0x1000), 2668c2ecf20Sopenharmony_ci .wrdma_fifowm = REG_FIELD_ID(0xB000, 1, 3, 2, 0x1000), 2678c2ecf20Sopenharmony_ci .wrdma_enable = REG_FIELD_ID(0xB000, 0, 0, 2, 0x1000), 2688c2ecf20Sopenharmony_ci 2698c2ecf20Sopenharmony_ci .clk_name = (const char*[]) { 2708c2ecf20Sopenharmony_ci "pcnoc-mport-clk", 2718c2ecf20Sopenharmony_ci "pcnoc-sway-clk", 2728c2ecf20Sopenharmony_ci }, 2738c2ecf20Sopenharmony_ci .num_clks = 2, 2748c2ecf20Sopenharmony_ci .dai_driver = apq8016_lpass_cpu_dai_driver, 2758c2ecf20Sopenharmony_ci .num_dai = ARRAY_SIZE(apq8016_lpass_cpu_dai_driver), 2768c2ecf20Sopenharmony_ci .dai_osr_clk_names = (const char *[]) { 2778c2ecf20Sopenharmony_ci "mi2s-osr-clk0", 2788c2ecf20Sopenharmony_ci "mi2s-osr-clk1", 2798c2ecf20Sopenharmony_ci "mi2s-osr-clk2", 2808c2ecf20Sopenharmony_ci "mi2s-osr-clk3", 2818c2ecf20Sopenharmony_ci }, 2828c2ecf20Sopenharmony_ci .dai_bit_clk_names = (const char *[]) { 2838c2ecf20Sopenharmony_ci "mi2s-bit-clk0", 2848c2ecf20Sopenharmony_ci "mi2s-bit-clk1", 2858c2ecf20Sopenharmony_ci "mi2s-bit-clk2", 2868c2ecf20Sopenharmony_ci "mi2s-bit-clk3", 2878c2ecf20Sopenharmony_ci }, 2888c2ecf20Sopenharmony_ci .init = apq8016_lpass_init, 2898c2ecf20Sopenharmony_ci .exit = apq8016_lpass_exit, 2908c2ecf20Sopenharmony_ci .alloc_dma_channel = apq8016_lpass_alloc_dma_channel, 2918c2ecf20Sopenharmony_ci .free_dma_channel = apq8016_lpass_free_dma_channel, 2928c2ecf20Sopenharmony_ci}; 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_cistatic const struct of_device_id apq8016_lpass_cpu_device_id[] = { 2958c2ecf20Sopenharmony_ci { .compatible = "qcom,lpass-cpu-apq8016", .data = &apq8016_data }, 2968c2ecf20Sopenharmony_ci {} 2978c2ecf20Sopenharmony_ci}; 2988c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(of, apq8016_lpass_cpu_device_id); 2998c2ecf20Sopenharmony_ci 3008c2ecf20Sopenharmony_cistatic struct platform_driver apq8016_lpass_cpu_platform_driver = { 3018c2ecf20Sopenharmony_ci .driver = { 3028c2ecf20Sopenharmony_ci .name = "apq8016-lpass-cpu", 3038c2ecf20Sopenharmony_ci .of_match_table = of_match_ptr(apq8016_lpass_cpu_device_id), 3048c2ecf20Sopenharmony_ci }, 3058c2ecf20Sopenharmony_ci .probe = asoc_qcom_lpass_cpu_platform_probe, 3068c2ecf20Sopenharmony_ci .remove = asoc_qcom_lpass_cpu_platform_remove, 3078c2ecf20Sopenharmony_ci}; 3088c2ecf20Sopenharmony_cimodule_platform_driver(apq8016_lpass_cpu_platform_driver); 3098c2ecf20Sopenharmony_ci 3108c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("APQ8016 LPASS CPU Driver"); 3118c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 3128c2ecf20Sopenharmony_ci 313