18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Driver for Digigram VXpocket V2/440 soundcards 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de> 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci */ 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/init.h> 118c2ecf20Sopenharmony_ci#include <linux/module.h> 128c2ecf20Sopenharmony_ci#include <linux/slab.h> 138c2ecf20Sopenharmony_ci#include <sound/core.h> 148c2ecf20Sopenharmony_ci#include "vxpocket.h" 158c2ecf20Sopenharmony_ci#include <pcmcia/ciscode.h> 168c2ecf20Sopenharmony_ci#include <pcmcia/cisreg.h> 178c2ecf20Sopenharmony_ci#include <sound/initval.h> 188c2ecf20Sopenharmony_ci#include <sound/tlv.h> 198c2ecf20Sopenharmony_ci 208c2ecf20Sopenharmony_ci/* 218c2ecf20Sopenharmony_ci */ 228c2ecf20Sopenharmony_ci 238c2ecf20Sopenharmony_ciMODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>"); 248c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Digigram VXPocket"); 258c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 268c2ecf20Sopenharmony_ciMODULE_SUPPORTED_DEVICE("{{Digigram,VXPocket},{Digigram,VXPocket440}}"); 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ 298c2ecf20Sopenharmony_cistatic char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ 308c2ecf20Sopenharmony_cistatic bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable switches */ 318c2ecf20Sopenharmony_cistatic int ibl[SNDRV_CARDS]; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_cimodule_param_array(index, int, NULL, 0444); 348c2ecf20Sopenharmony_ciMODULE_PARM_DESC(index, "Index value for VXPocket soundcard."); 358c2ecf20Sopenharmony_cimodule_param_array(id, charp, NULL, 0444); 368c2ecf20Sopenharmony_ciMODULE_PARM_DESC(id, "ID string for VXPocket soundcard."); 378c2ecf20Sopenharmony_cimodule_param_array(enable, bool, NULL, 0444); 388c2ecf20Sopenharmony_ciMODULE_PARM_DESC(enable, "Enable VXPocket soundcard."); 398c2ecf20Sopenharmony_cimodule_param_array(ibl, int, NULL, 0444); 408c2ecf20Sopenharmony_ciMODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard."); 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci 438c2ecf20Sopenharmony_ci/* 448c2ecf20Sopenharmony_ci */ 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_cistatic unsigned int card_alloc; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci/* 508c2ecf20Sopenharmony_ci */ 518c2ecf20Sopenharmony_cistatic void vxpocket_release(struct pcmcia_device *link) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci free_irq(link->irq, link->priv); 548c2ecf20Sopenharmony_ci pcmcia_disable_device(link); 558c2ecf20Sopenharmony_ci} 568c2ecf20Sopenharmony_ci 578c2ecf20Sopenharmony_ci/* 588c2ecf20Sopenharmony_ci * destructor, called from snd_card_free_when_closed() 598c2ecf20Sopenharmony_ci */ 608c2ecf20Sopenharmony_cistatic int snd_vxpocket_dev_free(struct snd_device *device) 618c2ecf20Sopenharmony_ci{ 628c2ecf20Sopenharmony_ci struct vx_core *chip = device->device_data; 638c2ecf20Sopenharmony_ci 648c2ecf20Sopenharmony_ci snd_vx_free_firmware(chip); 658c2ecf20Sopenharmony_ci kfree(chip); 668c2ecf20Sopenharmony_ci return 0; 678c2ecf20Sopenharmony_ci} 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci 708c2ecf20Sopenharmony_ci/* 718c2ecf20Sopenharmony_ci * Hardware information 728c2ecf20Sopenharmony_ci */ 738c2ecf20Sopenharmony_ci 748c2ecf20Sopenharmony_ci/* VX-pocket V2 758c2ecf20Sopenharmony_ci * 768c2ecf20Sopenharmony_ci * 1 DSP, 1 sync UER 778c2ecf20Sopenharmony_ci * 1 programmable clock (NIY) 788c2ecf20Sopenharmony_ci * 1 stereo analog input (line/micro) 798c2ecf20Sopenharmony_ci * 1 stereo analog output 808c2ecf20Sopenharmony_ci * Only output levels can be modified 818c2ecf20Sopenharmony_ci */ 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_cistatic const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0); 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic const struct snd_vx_hardware vxpocket_hw = { 868c2ecf20Sopenharmony_ci .name = "VXPocket", 878c2ecf20Sopenharmony_ci .type = VX_TYPE_VXPOCKET, 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci /* hardware specs */ 908c2ecf20Sopenharmony_ci .num_codecs = 1, 918c2ecf20Sopenharmony_ci .num_ins = 1, 928c2ecf20Sopenharmony_ci .num_outs = 1, 938c2ecf20Sopenharmony_ci .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, 948c2ecf20Sopenharmony_ci .output_level_db_scale = db_scale_old_vol, 958c2ecf20Sopenharmony_ci}; 968c2ecf20Sopenharmony_ci 978c2ecf20Sopenharmony_ci/* VX-pocket 440 988c2ecf20Sopenharmony_ci * 998c2ecf20Sopenharmony_ci * 1 DSP, 1 sync UER, 1 sync World Clock (NIY) 1008c2ecf20Sopenharmony_ci * SMPTE (NIY) 1018c2ecf20Sopenharmony_ci * 2 stereo analog input (line/micro) 1028c2ecf20Sopenharmony_ci * 2 stereo analog output 1038c2ecf20Sopenharmony_ci * Only output levels can be modified 1048c2ecf20Sopenharmony_ci * UER, but only for the first two inputs and outputs. 1058c2ecf20Sopenharmony_ci */ 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_cistatic const struct snd_vx_hardware vxp440_hw = { 1088c2ecf20Sopenharmony_ci .name = "VXPocket440", 1098c2ecf20Sopenharmony_ci .type = VX_TYPE_VXP440, 1108c2ecf20Sopenharmony_ci 1118c2ecf20Sopenharmony_ci /* hardware specs */ 1128c2ecf20Sopenharmony_ci .num_codecs = 2, 1138c2ecf20Sopenharmony_ci .num_ins = 2, 1148c2ecf20Sopenharmony_ci .num_outs = 2, 1158c2ecf20Sopenharmony_ci .output_level_max = VX_ANALOG_OUT_LEVEL_MAX, 1168c2ecf20Sopenharmony_ci .output_level_db_scale = db_scale_old_vol, 1178c2ecf20Sopenharmony_ci}; 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci/* 1218c2ecf20Sopenharmony_ci * create vxpocket instance 1228c2ecf20Sopenharmony_ci */ 1238c2ecf20Sopenharmony_cistatic int snd_vxpocket_new(struct snd_card *card, int ibl, 1248c2ecf20Sopenharmony_ci struct pcmcia_device *link, 1258c2ecf20Sopenharmony_ci struct snd_vxpocket **chip_ret) 1268c2ecf20Sopenharmony_ci{ 1278c2ecf20Sopenharmony_ci struct vx_core *chip; 1288c2ecf20Sopenharmony_ci struct snd_vxpocket *vxp; 1298c2ecf20Sopenharmony_ci static const struct snd_device_ops ops = { 1308c2ecf20Sopenharmony_ci .dev_free = snd_vxpocket_dev_free, 1318c2ecf20Sopenharmony_ci }; 1328c2ecf20Sopenharmony_ci int err; 1338c2ecf20Sopenharmony_ci 1348c2ecf20Sopenharmony_ci chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops, 1358c2ecf20Sopenharmony_ci sizeof(struct snd_vxpocket) - sizeof(struct vx_core)); 1368c2ecf20Sopenharmony_ci if (!chip) 1378c2ecf20Sopenharmony_ci return -ENOMEM; 1388c2ecf20Sopenharmony_ci 1398c2ecf20Sopenharmony_ci err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops); 1408c2ecf20Sopenharmony_ci if (err < 0) { 1418c2ecf20Sopenharmony_ci kfree(chip); 1428c2ecf20Sopenharmony_ci return err; 1438c2ecf20Sopenharmony_ci } 1448c2ecf20Sopenharmony_ci chip->ibl.size = ibl; 1458c2ecf20Sopenharmony_ci 1468c2ecf20Sopenharmony_ci vxp = to_vxpocket(chip); 1478c2ecf20Sopenharmony_ci 1488c2ecf20Sopenharmony_ci vxp->p_dev = link; 1498c2ecf20Sopenharmony_ci link->priv = chip; 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_ci link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO; 1528c2ecf20Sopenharmony_ci link->resource[0]->end = 16; 1538c2ecf20Sopenharmony_ci 1548c2ecf20Sopenharmony_ci link->config_flags |= CONF_ENABLE_IRQ; 1558c2ecf20Sopenharmony_ci link->config_index = 1; 1568c2ecf20Sopenharmony_ci link->config_regs = PRESENT_OPTION; 1578c2ecf20Sopenharmony_ci 1588c2ecf20Sopenharmony_ci *chip_ret = vxp; 1598c2ecf20Sopenharmony_ci return 0; 1608c2ecf20Sopenharmony_ci} 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci 1638c2ecf20Sopenharmony_ci/** 1648c2ecf20Sopenharmony_ci * snd_vxpocket_assign_resources - initialize the hardware and card instance. 1658c2ecf20Sopenharmony_ci * @chip: VX core instance 1668c2ecf20Sopenharmony_ci * @port: i/o port for the card 1678c2ecf20Sopenharmony_ci * @irq: irq number for the card 1688c2ecf20Sopenharmony_ci * 1698c2ecf20Sopenharmony_ci * this function assigns the specified port and irq, boot the card, 1708c2ecf20Sopenharmony_ci * create pcm and control instances, and initialize the rest hardware. 1718c2ecf20Sopenharmony_ci * 1728c2ecf20Sopenharmony_ci * returns 0 if successful, or a negative error code. 1738c2ecf20Sopenharmony_ci */ 1748c2ecf20Sopenharmony_cistatic int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci int err; 1778c2ecf20Sopenharmony_ci struct snd_card *card = chip->card; 1788c2ecf20Sopenharmony_ci struct snd_vxpocket *vxp = to_vxpocket(chip); 1798c2ecf20Sopenharmony_ci 1808c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq); 1818c2ecf20Sopenharmony_ci vxp->port = port; 1828c2ecf20Sopenharmony_ci 1838c2ecf20Sopenharmony_ci sprintf(card->shortname, "Digigram %s", card->driver); 1848c2ecf20Sopenharmony_ci sprintf(card->longname, "%s at 0x%x, irq %i", 1858c2ecf20Sopenharmony_ci card->shortname, port, irq); 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci chip->irq = irq; 1888c2ecf20Sopenharmony_ci card->sync_irq = chip->irq; 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci if ((err = snd_vx_setup_firmware(chip)) < 0) 1918c2ecf20Sopenharmony_ci return err; 1928c2ecf20Sopenharmony_ci 1938c2ecf20Sopenharmony_ci return 0; 1948c2ecf20Sopenharmony_ci} 1958c2ecf20Sopenharmony_ci 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci/* 1988c2ecf20Sopenharmony_ci * configuration callback 1998c2ecf20Sopenharmony_ci */ 2008c2ecf20Sopenharmony_ci 2018c2ecf20Sopenharmony_cistatic int vxpocket_config(struct pcmcia_device *link) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci struct vx_core *chip = link->priv; 2048c2ecf20Sopenharmony_ci int ret; 2058c2ecf20Sopenharmony_ci 2068c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "vxpocket_config called\n"); 2078c2ecf20Sopenharmony_ci 2088c2ecf20Sopenharmony_ci /* redefine hardware record according to the VERSION1 string */ 2098c2ecf20Sopenharmony_ci if (!strcmp(link->prod_id[1], "VX-POCKET")) { 2108c2ecf20Sopenharmony_ci snd_printdd("VX-pocket is detected\n"); 2118c2ecf20Sopenharmony_ci } else { 2128c2ecf20Sopenharmony_ci snd_printdd("VX-pocket 440 is detected\n"); 2138c2ecf20Sopenharmony_ci /* overwrite the hardware information */ 2148c2ecf20Sopenharmony_ci chip->hw = &vxp440_hw; 2158c2ecf20Sopenharmony_ci chip->type = vxp440_hw.type; 2168c2ecf20Sopenharmony_ci strcpy(chip->card->driver, vxp440_hw.name); 2178c2ecf20Sopenharmony_ci } 2188c2ecf20Sopenharmony_ci 2198c2ecf20Sopenharmony_ci ret = pcmcia_request_io(link); 2208c2ecf20Sopenharmony_ci if (ret) 2218c2ecf20Sopenharmony_ci goto failed_preirq; 2228c2ecf20Sopenharmony_ci 2238c2ecf20Sopenharmony_ci ret = request_threaded_irq(link->irq, snd_vx_irq_handler, 2248c2ecf20Sopenharmony_ci snd_vx_threaded_irq_handler, 2258c2ecf20Sopenharmony_ci IRQF_SHARED, link->devname, link->priv); 2268c2ecf20Sopenharmony_ci if (ret) 2278c2ecf20Sopenharmony_ci goto failed_preirq; 2288c2ecf20Sopenharmony_ci 2298c2ecf20Sopenharmony_ci ret = pcmcia_enable_device(link); 2308c2ecf20Sopenharmony_ci if (ret) 2318c2ecf20Sopenharmony_ci goto failed; 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci chip->dev = &link->dev; 2348c2ecf20Sopenharmony_ci 2358c2ecf20Sopenharmony_ci if (snd_vxpocket_assign_resources(chip, link->resource[0]->start, 2368c2ecf20Sopenharmony_ci link->irq) < 0) 2378c2ecf20Sopenharmony_ci goto failed; 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_ci return 0; 2408c2ecf20Sopenharmony_ci 2418c2ecf20Sopenharmony_ci failed: 2428c2ecf20Sopenharmony_ci free_irq(link->irq, link->priv); 2438c2ecf20Sopenharmony_cifailed_preirq: 2448c2ecf20Sopenharmony_ci pcmcia_disable_device(link); 2458c2ecf20Sopenharmony_ci return -ENODEV; 2468c2ecf20Sopenharmony_ci} 2478c2ecf20Sopenharmony_ci 2488c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 2498c2ecf20Sopenharmony_ci 2508c2ecf20Sopenharmony_cistatic int vxp_suspend(struct pcmcia_device *link) 2518c2ecf20Sopenharmony_ci{ 2528c2ecf20Sopenharmony_ci struct vx_core *chip = link->priv; 2538c2ecf20Sopenharmony_ci 2548c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "SUSPEND\n"); 2558c2ecf20Sopenharmony_ci if (chip) { 2568c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n"); 2578c2ecf20Sopenharmony_ci snd_vx_suspend(chip); 2588c2ecf20Sopenharmony_ci } 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci return 0; 2618c2ecf20Sopenharmony_ci} 2628c2ecf20Sopenharmony_ci 2638c2ecf20Sopenharmony_cistatic int vxp_resume(struct pcmcia_device *link) 2648c2ecf20Sopenharmony_ci{ 2658c2ecf20Sopenharmony_ci struct vx_core *chip = link->priv; 2668c2ecf20Sopenharmony_ci 2678c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "RESUME\n"); 2688c2ecf20Sopenharmony_ci if (pcmcia_dev_present(link)) { 2698c2ecf20Sopenharmony_ci //struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip; 2708c2ecf20Sopenharmony_ci if (chip) { 2718c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "calling snd_vx_resume\n"); 2728c2ecf20Sopenharmony_ci snd_vx_resume(chip); 2738c2ecf20Sopenharmony_ci } 2748c2ecf20Sopenharmony_ci } 2758c2ecf20Sopenharmony_ci snd_printdd(KERN_DEBUG "resume done!\n"); 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_ci return 0; 2788c2ecf20Sopenharmony_ci} 2798c2ecf20Sopenharmony_ci 2808c2ecf20Sopenharmony_ci#endif 2818c2ecf20Sopenharmony_ci 2828c2ecf20Sopenharmony_ci 2838c2ecf20Sopenharmony_ci/* 2848c2ecf20Sopenharmony_ci */ 2858c2ecf20Sopenharmony_cistatic int vxpocket_probe(struct pcmcia_device *p_dev) 2868c2ecf20Sopenharmony_ci{ 2878c2ecf20Sopenharmony_ci struct snd_card *card; 2888c2ecf20Sopenharmony_ci struct snd_vxpocket *vxp; 2898c2ecf20Sopenharmony_ci int i, err; 2908c2ecf20Sopenharmony_ci 2918c2ecf20Sopenharmony_ci /* find an empty slot from the card list */ 2928c2ecf20Sopenharmony_ci for (i = 0; i < SNDRV_CARDS; i++) { 2938c2ecf20Sopenharmony_ci if (!(card_alloc & (1 << i))) 2948c2ecf20Sopenharmony_ci break; 2958c2ecf20Sopenharmony_ci } 2968c2ecf20Sopenharmony_ci if (i >= SNDRV_CARDS) { 2978c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "vxpocket: too many cards found\n"); 2988c2ecf20Sopenharmony_ci return -EINVAL; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci if (! enable[i]) 3018c2ecf20Sopenharmony_ci return -ENODEV; /* disabled explicitly */ 3028c2ecf20Sopenharmony_ci 3038c2ecf20Sopenharmony_ci /* ok, create a card instance */ 3048c2ecf20Sopenharmony_ci err = snd_card_new(&p_dev->dev, index[i], id[i], THIS_MODULE, 3058c2ecf20Sopenharmony_ci 0, &card); 3068c2ecf20Sopenharmony_ci if (err < 0) { 3078c2ecf20Sopenharmony_ci snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n"); 3088c2ecf20Sopenharmony_ci return err; 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci 3118c2ecf20Sopenharmony_ci err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp); 3128c2ecf20Sopenharmony_ci if (err < 0) { 3138c2ecf20Sopenharmony_ci snd_card_free(card); 3148c2ecf20Sopenharmony_ci return err; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci card->private_data = vxp; 3178c2ecf20Sopenharmony_ci 3188c2ecf20Sopenharmony_ci vxp->index = i; 3198c2ecf20Sopenharmony_ci card_alloc |= 1 << i; 3208c2ecf20Sopenharmony_ci 3218c2ecf20Sopenharmony_ci vxp->p_dev = p_dev; 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci return vxpocket_config(p_dev); 3248c2ecf20Sopenharmony_ci} 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_cistatic void vxpocket_detach(struct pcmcia_device *link) 3278c2ecf20Sopenharmony_ci{ 3288c2ecf20Sopenharmony_ci struct snd_vxpocket *vxp; 3298c2ecf20Sopenharmony_ci struct vx_core *chip; 3308c2ecf20Sopenharmony_ci 3318c2ecf20Sopenharmony_ci if (! link) 3328c2ecf20Sopenharmony_ci return; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci vxp = link->priv; 3358c2ecf20Sopenharmony_ci chip = (struct vx_core *)vxp; 3368c2ecf20Sopenharmony_ci card_alloc &= ~(1 << vxp->index); 3378c2ecf20Sopenharmony_ci 3388c2ecf20Sopenharmony_ci chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */ 3398c2ecf20Sopenharmony_ci snd_card_disconnect(chip->card); 3408c2ecf20Sopenharmony_ci vxpocket_release(link); 3418c2ecf20Sopenharmony_ci snd_card_free_when_closed(chip->card); 3428c2ecf20Sopenharmony_ci} 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci/* 3458c2ecf20Sopenharmony_ci * Module entry points 3468c2ecf20Sopenharmony_ci */ 3478c2ecf20Sopenharmony_ci 3488c2ecf20Sopenharmony_cistatic const struct pcmcia_device_id vxp_ids[] = { 3498c2ecf20Sopenharmony_ci PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100), 3508c2ecf20Sopenharmony_ci PCMCIA_DEVICE_NULL 3518c2ecf20Sopenharmony_ci}; 3528c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(pcmcia, vxp_ids); 3538c2ecf20Sopenharmony_ci 3548c2ecf20Sopenharmony_cistatic struct pcmcia_driver vxp_cs_driver = { 3558c2ecf20Sopenharmony_ci .owner = THIS_MODULE, 3568c2ecf20Sopenharmony_ci .name = "snd-vxpocket", 3578c2ecf20Sopenharmony_ci .probe = vxpocket_probe, 3588c2ecf20Sopenharmony_ci .remove = vxpocket_detach, 3598c2ecf20Sopenharmony_ci .id_table = vxp_ids, 3608c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 3618c2ecf20Sopenharmony_ci .suspend = vxp_suspend, 3628c2ecf20Sopenharmony_ci .resume = vxp_resume, 3638c2ecf20Sopenharmony_ci#endif 3648c2ecf20Sopenharmony_ci}; 3658c2ecf20Sopenharmony_cimodule_pcmcia_driver(vxp_cs_driver); 366