18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci// 38c2ecf20Sopenharmony_ci// Copyright(c) 2020 Intel Corporation. All rights reserved. 48c2ecf20Sopenharmony_ci// 58c2ecf20Sopenharmony_ci// Author: Cezary Rojewski <cezary.rojewski@intel.com> 68c2ecf20Sopenharmony_ci// 78c2ecf20Sopenharmony_ci// Special thanks to: 88c2ecf20Sopenharmony_ci// Marcin Barlik <marcin.barlik@intel.com> 98c2ecf20Sopenharmony_ci// Piotr Papierkowski <piotr.papierkowski@intel.com> 108c2ecf20Sopenharmony_ci// 118c2ecf20Sopenharmony_ci// for sharing LPT-LP and WTP-LP AudioDSP architecture expertise and 128c2ecf20Sopenharmony_ci// helping backtrack its historical background 138c2ecf20Sopenharmony_ci// 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/acpi.h> 168c2ecf20Sopenharmony_ci#include <linux/dma-mapping.h> 178c2ecf20Sopenharmony_ci#include <linux/interrupt.h> 188c2ecf20Sopenharmony_ci#include <linux/module.h> 198c2ecf20Sopenharmony_ci#include <linux/pci.h> 208c2ecf20Sopenharmony_ci#include <linux/platform_device.h> 218c2ecf20Sopenharmony_ci#include <linux/pm_runtime.h> 228c2ecf20Sopenharmony_ci#include <sound/soc.h> 238c2ecf20Sopenharmony_ci#include <sound/soc-acpi.h> 248c2ecf20Sopenharmony_ci#include <sound/soc-acpi-intel-match.h> 258c2ecf20Sopenharmony_ci#include "core.h" 268c2ecf20Sopenharmony_ci#include "registers.h" 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_ci#define CREATE_TRACE_POINTS 298c2ecf20Sopenharmony_ci#include "trace.h" 308c2ecf20Sopenharmony_ci 318c2ecf20Sopenharmony_cistatic int __maybe_unused catpt_suspend(struct device *dev) 328c2ecf20Sopenharmony_ci{ 338c2ecf20Sopenharmony_ci struct catpt_dev *cdev = dev_get_drvdata(dev); 348c2ecf20Sopenharmony_ci struct dma_chan *chan; 358c2ecf20Sopenharmony_ci int ret; 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_ci chan = catpt_dma_request_config_chan(cdev); 388c2ecf20Sopenharmony_ci if (IS_ERR(chan)) 398c2ecf20Sopenharmony_ci return PTR_ERR(chan); 408c2ecf20Sopenharmony_ci 418c2ecf20Sopenharmony_ci memset(&cdev->dx_ctx, 0, sizeof(cdev->dx_ctx)); 428c2ecf20Sopenharmony_ci ret = catpt_ipc_enter_dxstate(cdev, CATPT_DX_STATE_D3, &cdev->dx_ctx); 438c2ecf20Sopenharmony_ci if (ret) { 448c2ecf20Sopenharmony_ci ret = CATPT_IPC_ERROR(ret); 458c2ecf20Sopenharmony_ci goto release_dma_chan; 468c2ecf20Sopenharmony_ci } 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci ret = catpt_dsp_stall(cdev, true); 498c2ecf20Sopenharmony_ci if (ret) 508c2ecf20Sopenharmony_ci goto release_dma_chan; 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci ret = catpt_store_memdumps(cdev, chan); 538c2ecf20Sopenharmony_ci if (ret) { 548c2ecf20Sopenharmony_ci dev_err(cdev->dev, "store memdumps failed: %d\n", ret); 558c2ecf20Sopenharmony_ci goto release_dma_chan; 568c2ecf20Sopenharmony_ci } 578c2ecf20Sopenharmony_ci 588c2ecf20Sopenharmony_ci ret = catpt_store_module_states(cdev, chan); 598c2ecf20Sopenharmony_ci if (ret) { 608c2ecf20Sopenharmony_ci dev_err(cdev->dev, "store module states failed: %d\n", ret); 618c2ecf20Sopenharmony_ci goto release_dma_chan; 628c2ecf20Sopenharmony_ci } 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci ret = catpt_store_streams_context(cdev, chan); 658c2ecf20Sopenharmony_ci if (ret) 668c2ecf20Sopenharmony_ci dev_err(cdev->dev, "store streams ctx failed: %d\n", ret); 678c2ecf20Sopenharmony_ci 688c2ecf20Sopenharmony_cirelease_dma_chan: 698c2ecf20Sopenharmony_ci dma_release_channel(chan); 708c2ecf20Sopenharmony_ci if (ret) 718c2ecf20Sopenharmony_ci return ret; 728c2ecf20Sopenharmony_ci return cdev->spec->power_down(cdev); 738c2ecf20Sopenharmony_ci} 748c2ecf20Sopenharmony_ci 758c2ecf20Sopenharmony_cistatic int __maybe_unused catpt_resume(struct device *dev) 768c2ecf20Sopenharmony_ci{ 778c2ecf20Sopenharmony_ci struct catpt_dev *cdev = dev_get_drvdata(dev); 788c2ecf20Sopenharmony_ci int ret, i; 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci ret = cdev->spec->power_up(cdev); 818c2ecf20Sopenharmony_ci if (ret) 828c2ecf20Sopenharmony_ci return ret; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci if (!try_module_get(dev->driver->owner)) { 858c2ecf20Sopenharmony_ci dev_info(dev, "module unloading, skipping fw boot\n"); 868c2ecf20Sopenharmony_ci return 0; 878c2ecf20Sopenharmony_ci } 888c2ecf20Sopenharmony_ci module_put(dev->driver->owner); 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci ret = catpt_boot_firmware(cdev, true); 918c2ecf20Sopenharmony_ci if (ret) { 928c2ecf20Sopenharmony_ci dev_err(cdev->dev, "boot firmware failed: %d\n", ret); 938c2ecf20Sopenharmony_ci return ret; 948c2ecf20Sopenharmony_ci } 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci /* reconfigure SSP devices after Dx transition */ 978c2ecf20Sopenharmony_ci for (i = 0; i < CATPT_SSP_COUNT; i++) { 988c2ecf20Sopenharmony_ci if (cdev->devfmt[i].iface == UINT_MAX) 998c2ecf20Sopenharmony_ci continue; 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci ret = catpt_ipc_set_device_format(cdev, &cdev->devfmt[i]); 1028c2ecf20Sopenharmony_ci if (ret) 1038c2ecf20Sopenharmony_ci return CATPT_IPC_ERROR(ret); 1048c2ecf20Sopenharmony_ci } 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci return 0; 1078c2ecf20Sopenharmony_ci} 1088c2ecf20Sopenharmony_ci 1098c2ecf20Sopenharmony_cistatic int __maybe_unused catpt_runtime_suspend(struct device *dev) 1108c2ecf20Sopenharmony_ci{ 1118c2ecf20Sopenharmony_ci if (!try_module_get(dev->driver->owner)) { 1128c2ecf20Sopenharmony_ci dev_info(dev, "module unloading, skipping suspend\n"); 1138c2ecf20Sopenharmony_ci return 0; 1148c2ecf20Sopenharmony_ci } 1158c2ecf20Sopenharmony_ci module_put(dev->driver->owner); 1168c2ecf20Sopenharmony_ci 1178c2ecf20Sopenharmony_ci return catpt_suspend(dev); 1188c2ecf20Sopenharmony_ci} 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_cistatic int __maybe_unused catpt_runtime_resume(struct device *dev) 1218c2ecf20Sopenharmony_ci{ 1228c2ecf20Sopenharmony_ci return catpt_resume(dev); 1238c2ecf20Sopenharmony_ci} 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_cistatic const struct dev_pm_ops catpt_dev_pm = { 1268c2ecf20Sopenharmony_ci SET_SYSTEM_SLEEP_PM_OPS(catpt_suspend, catpt_resume) 1278c2ecf20Sopenharmony_ci SET_RUNTIME_PM_OPS(catpt_runtime_suspend, catpt_runtime_resume, NULL) 1288c2ecf20Sopenharmony_ci}; 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* machine board owned by CATPT is removed with this hook */ 1318c2ecf20Sopenharmony_cistatic void board_pdev_unregister(void *data) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci platform_device_unregister(data); 1348c2ecf20Sopenharmony_ci} 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic int catpt_register_board(struct catpt_dev *cdev) 1378c2ecf20Sopenharmony_ci{ 1388c2ecf20Sopenharmony_ci const struct catpt_spec *spec = cdev->spec; 1398c2ecf20Sopenharmony_ci struct snd_soc_acpi_mach *mach; 1408c2ecf20Sopenharmony_ci struct platform_device *board; 1418c2ecf20Sopenharmony_ci 1428c2ecf20Sopenharmony_ci mach = snd_soc_acpi_find_machine(spec->machines); 1438c2ecf20Sopenharmony_ci if (!mach) { 1448c2ecf20Sopenharmony_ci dev_info(cdev->dev, "no machines present\n"); 1458c2ecf20Sopenharmony_ci return 0; 1468c2ecf20Sopenharmony_ci } 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci mach->mach_params.platform = "catpt-platform"; 1498c2ecf20Sopenharmony_ci board = platform_device_register_data(NULL, mach->drv_name, 1508c2ecf20Sopenharmony_ci PLATFORM_DEVID_NONE, 1518c2ecf20Sopenharmony_ci (const void *)mach, sizeof(*mach)); 1528c2ecf20Sopenharmony_ci if (IS_ERR(board)) { 1538c2ecf20Sopenharmony_ci dev_err(cdev->dev, "board register failed\n"); 1548c2ecf20Sopenharmony_ci return PTR_ERR(board); 1558c2ecf20Sopenharmony_ci } 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_ci return devm_add_action_or_reset(cdev->dev, board_pdev_unregister, 1588c2ecf20Sopenharmony_ci board); 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int catpt_probe_components(struct catpt_dev *cdev) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci int ret; 1648c2ecf20Sopenharmony_ci 1658c2ecf20Sopenharmony_ci ret = cdev->spec->power_up(cdev); 1668c2ecf20Sopenharmony_ci if (ret) 1678c2ecf20Sopenharmony_ci return ret; 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci ret = catpt_dmac_probe(cdev); 1708c2ecf20Sopenharmony_ci if (ret) { 1718c2ecf20Sopenharmony_ci dev_err(cdev->dev, "DMAC probe failed: %d\n", ret); 1728c2ecf20Sopenharmony_ci goto err_dmac_probe; 1738c2ecf20Sopenharmony_ci } 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci ret = catpt_first_boot_firmware(cdev); 1768c2ecf20Sopenharmony_ci if (ret) { 1778c2ecf20Sopenharmony_ci dev_err(cdev->dev, "first fw boot failed: %d\n", ret); 1788c2ecf20Sopenharmony_ci goto err_boot_fw; 1798c2ecf20Sopenharmony_ci } 1808c2ecf20Sopenharmony_ci 1818c2ecf20Sopenharmony_ci ret = catpt_register_plat_component(cdev); 1828c2ecf20Sopenharmony_ci if (ret) { 1838c2ecf20Sopenharmony_ci dev_err(cdev->dev, "register plat comp failed: %d\n", ret); 1848c2ecf20Sopenharmony_ci goto err_boot_fw; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci ret = catpt_register_board(cdev); 1888c2ecf20Sopenharmony_ci if (ret) { 1898c2ecf20Sopenharmony_ci dev_err(cdev->dev, "register board failed: %d\n", ret); 1908c2ecf20Sopenharmony_ci goto err_reg_board; 1918c2ecf20Sopenharmony_ci } 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci /* reflect actual ADSP state in pm_runtime */ 1948c2ecf20Sopenharmony_ci pm_runtime_set_active(cdev->dev); 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci pm_runtime_set_autosuspend_delay(cdev->dev, 2000); 1978c2ecf20Sopenharmony_ci pm_runtime_use_autosuspend(cdev->dev); 1988c2ecf20Sopenharmony_ci pm_runtime_mark_last_busy(cdev->dev); 1998c2ecf20Sopenharmony_ci pm_runtime_enable(cdev->dev); 2008c2ecf20Sopenharmony_ci return 0; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_cierr_reg_board: 2038c2ecf20Sopenharmony_ci snd_soc_unregister_component(cdev->dev); 2048c2ecf20Sopenharmony_cierr_boot_fw: 2058c2ecf20Sopenharmony_ci catpt_dmac_remove(cdev); 2068c2ecf20Sopenharmony_cierr_dmac_probe: 2078c2ecf20Sopenharmony_ci cdev->spec->power_down(cdev); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci return ret; 2108c2ecf20Sopenharmony_ci} 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_cistatic void catpt_dev_init(struct catpt_dev *cdev, struct device *dev, 2138c2ecf20Sopenharmony_ci const struct catpt_spec *spec) 2148c2ecf20Sopenharmony_ci{ 2158c2ecf20Sopenharmony_ci cdev->dev = dev; 2168c2ecf20Sopenharmony_ci cdev->spec = spec; 2178c2ecf20Sopenharmony_ci init_completion(&cdev->fw_ready); 2188c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cdev->stream_list); 2198c2ecf20Sopenharmony_ci spin_lock_init(&cdev->list_lock); 2208c2ecf20Sopenharmony_ci mutex_init(&cdev->clk_mutex); 2218c2ecf20Sopenharmony_ci 2228c2ecf20Sopenharmony_ci /* 2238c2ecf20Sopenharmony_ci * Mark both device formats as uninitialized. Once corresponding 2248c2ecf20Sopenharmony_ci * cpu_dai's pcm is created, proper values are assigned. 2258c2ecf20Sopenharmony_ci */ 2268c2ecf20Sopenharmony_ci cdev->devfmt[CATPT_SSP_IFACE_0].iface = UINT_MAX; 2278c2ecf20Sopenharmony_ci cdev->devfmt[CATPT_SSP_IFACE_1].iface = UINT_MAX; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci catpt_ipc_init(&cdev->ipc, dev); 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci catpt_sram_init(&cdev->dram, spec->host_dram_offset, 2328c2ecf20Sopenharmony_ci catpt_dram_size(cdev)); 2338c2ecf20Sopenharmony_ci catpt_sram_init(&cdev->iram, spec->host_iram_offset, 2348c2ecf20Sopenharmony_ci catpt_iram_size(cdev)); 2358c2ecf20Sopenharmony_ci} 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_cistatic int catpt_acpi_probe(struct platform_device *pdev) 2388c2ecf20Sopenharmony_ci{ 2398c2ecf20Sopenharmony_ci const struct catpt_spec *spec; 2408c2ecf20Sopenharmony_ci struct catpt_dev *cdev; 2418c2ecf20Sopenharmony_ci struct device *dev = &pdev->dev; 2428c2ecf20Sopenharmony_ci struct resource *res; 2438c2ecf20Sopenharmony_ci int ret; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci spec = device_get_match_data(dev); 2468c2ecf20Sopenharmony_ci if (!spec) 2478c2ecf20Sopenharmony_ci return -ENODEV; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci cdev = devm_kzalloc(dev, sizeof(*cdev), GFP_KERNEL); 2508c2ecf20Sopenharmony_ci if (!cdev) 2518c2ecf20Sopenharmony_ci return -ENOMEM; 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci catpt_dev_init(cdev, dev, spec); 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* map DSP bar address */ 2568c2ecf20Sopenharmony_ci cdev->lpe_ba = devm_platform_get_and_ioremap_resource(pdev, 0, &res); 2578c2ecf20Sopenharmony_ci if (IS_ERR(cdev->lpe_ba)) 2588c2ecf20Sopenharmony_ci return PTR_ERR(cdev->lpe_ba); 2598c2ecf20Sopenharmony_ci cdev->lpe_base = res->start; 2608c2ecf20Sopenharmony_ci 2618c2ecf20Sopenharmony_ci /* map PCI bar address */ 2628c2ecf20Sopenharmony_ci cdev->pci_ba = devm_platform_ioremap_resource(pdev, 1); 2638c2ecf20Sopenharmony_ci if (IS_ERR(cdev->pci_ba)) 2648c2ecf20Sopenharmony_ci return PTR_ERR(cdev->pci_ba); 2658c2ecf20Sopenharmony_ci 2668c2ecf20Sopenharmony_ci /* alloc buffer for storing DRAM context during dx transitions */ 2678c2ecf20Sopenharmony_ci cdev->dxbuf_vaddr = dmam_alloc_coherent(dev, catpt_dram_size(cdev), 2688c2ecf20Sopenharmony_ci &cdev->dxbuf_paddr, GFP_KERNEL); 2698c2ecf20Sopenharmony_ci if (!cdev->dxbuf_vaddr) 2708c2ecf20Sopenharmony_ci return -ENOMEM; 2718c2ecf20Sopenharmony_ci 2728c2ecf20Sopenharmony_ci ret = platform_get_irq(pdev, 0); 2738c2ecf20Sopenharmony_ci if (ret < 0) 2748c2ecf20Sopenharmony_ci return ret; 2758c2ecf20Sopenharmony_ci cdev->irq = ret; 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci platform_set_drvdata(pdev, cdev); 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci ret = devm_request_threaded_irq(dev, cdev->irq, catpt_dsp_irq_handler, 2808c2ecf20Sopenharmony_ci catpt_dsp_irq_thread, 2818c2ecf20Sopenharmony_ci IRQF_SHARED, "AudioDSP", cdev); 2828c2ecf20Sopenharmony_ci if (ret) 2838c2ecf20Sopenharmony_ci return ret; 2848c2ecf20Sopenharmony_ci 2858c2ecf20Sopenharmony_ci return catpt_probe_components(cdev); 2868c2ecf20Sopenharmony_ci} 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_cistatic int catpt_acpi_remove(struct platform_device *pdev) 2898c2ecf20Sopenharmony_ci{ 2908c2ecf20Sopenharmony_ci struct catpt_dev *cdev = platform_get_drvdata(pdev); 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_ci pm_runtime_disable(cdev->dev); 2938c2ecf20Sopenharmony_ci 2948c2ecf20Sopenharmony_ci snd_soc_unregister_component(cdev->dev); 2958c2ecf20Sopenharmony_ci catpt_dmac_remove(cdev); 2968c2ecf20Sopenharmony_ci cdev->spec->power_down(cdev); 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_ci catpt_sram_free(&cdev->iram); 2998c2ecf20Sopenharmony_ci catpt_sram_free(&cdev->dram); 3008c2ecf20Sopenharmony_ci 3018c2ecf20Sopenharmony_ci return 0; 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_cistatic struct catpt_spec lpt_desc = { 3058c2ecf20Sopenharmony_ci .machines = snd_soc_acpi_intel_haswell_machines, 3068c2ecf20Sopenharmony_ci .core_id = 0x01, 3078c2ecf20Sopenharmony_ci .host_dram_offset = 0x000000, 3088c2ecf20Sopenharmony_ci .host_iram_offset = 0x080000, 3098c2ecf20Sopenharmony_ci .host_shim_offset = 0x0E7000, 3108c2ecf20Sopenharmony_ci .host_dma_offset = { 0x0F0000, 0x0F8000 }, 3118c2ecf20Sopenharmony_ci .host_ssp_offset = { 0x0E8000, 0x0E9000 }, 3128c2ecf20Sopenharmony_ci .dram_mask = LPT_VDRTCTL0_DSRAMPGE_MASK, 3138c2ecf20Sopenharmony_ci .iram_mask = LPT_VDRTCTL0_ISRAMPGE_MASK, 3148c2ecf20Sopenharmony_ci .pll_shutdown = lpt_dsp_pll_shutdown, 3158c2ecf20Sopenharmony_ci .power_up = lpt_dsp_power_up, 3168c2ecf20Sopenharmony_ci .power_down = lpt_dsp_power_down, 3178c2ecf20Sopenharmony_ci}; 3188c2ecf20Sopenharmony_ci 3198c2ecf20Sopenharmony_cistatic struct catpt_spec wpt_desc = { 3208c2ecf20Sopenharmony_ci .machines = snd_soc_acpi_intel_broadwell_machines, 3218c2ecf20Sopenharmony_ci .core_id = 0x02, 3228c2ecf20Sopenharmony_ci .host_dram_offset = 0x000000, 3238c2ecf20Sopenharmony_ci .host_iram_offset = 0x0A0000, 3248c2ecf20Sopenharmony_ci .host_shim_offset = 0x0FB000, 3258c2ecf20Sopenharmony_ci .host_dma_offset = { 0x0FE000, 0x0FF000 }, 3268c2ecf20Sopenharmony_ci .host_ssp_offset = { 0x0FC000, 0x0FD000 }, 3278c2ecf20Sopenharmony_ci .dram_mask = WPT_VDRTCTL0_DSRAMPGE_MASK, 3288c2ecf20Sopenharmony_ci .iram_mask = WPT_VDRTCTL0_ISRAMPGE_MASK, 3298c2ecf20Sopenharmony_ci .pll_shutdown = wpt_dsp_pll_shutdown, 3308c2ecf20Sopenharmony_ci .power_up = wpt_dsp_power_up, 3318c2ecf20Sopenharmony_ci .power_down = wpt_dsp_power_down, 3328c2ecf20Sopenharmony_ci}; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_cistatic const struct acpi_device_id catpt_ids[] = { 3358c2ecf20Sopenharmony_ci { "INT33C8", (unsigned long)&lpt_desc }, 3368c2ecf20Sopenharmony_ci { "INT3438", (unsigned long)&wpt_desc }, 3378c2ecf20Sopenharmony_ci { } 3388c2ecf20Sopenharmony_ci}; 3398c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(acpi, catpt_ids); 3408c2ecf20Sopenharmony_ci 3418c2ecf20Sopenharmony_cistatic struct platform_driver catpt_acpi_driver = { 3428c2ecf20Sopenharmony_ci .probe = catpt_acpi_probe, 3438c2ecf20Sopenharmony_ci .remove = catpt_acpi_remove, 3448c2ecf20Sopenharmony_ci .driver = { 3458c2ecf20Sopenharmony_ci .name = "intel_catpt", 3468c2ecf20Sopenharmony_ci .acpi_match_table = catpt_ids, 3478c2ecf20Sopenharmony_ci .pm = &catpt_dev_pm, 3488c2ecf20Sopenharmony_ci .dev_groups = catpt_attr_groups, 3498c2ecf20Sopenharmony_ci }, 3508c2ecf20Sopenharmony_ci}; 3518c2ecf20Sopenharmony_cimodule_platform_driver(catpt_acpi_driver); 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ciMODULE_AUTHOR("Cezary Rojewski <cezary.rojewski@intel.com>"); 3548c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Intel LPT/WPT AudioDSP driver"); 3558c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2"); 356