cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vxpocket.c (7497B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Digigram VXpocket V2/440 soundcards
      4 *
      5 * Copyright (c) 2002 by Takashi Iwai <tiwai@suse.de>
      6
      7 */
      8
      9
     10#include <linux/init.h>
     11#include <linux/module.h>
     12#include <linux/slab.h>
     13#include <sound/core.h>
     14#include "vxpocket.h"
     15#include <pcmcia/ciscode.h>
     16#include <pcmcia/cisreg.h>
     17#include <sound/initval.h>
     18#include <sound/tlv.h>
     19
     20MODULE_AUTHOR("Takashi Iwai <tiwai@suse.de>");
     21MODULE_DESCRIPTION("Digigram VXPocket");
     22MODULE_LICENSE("GPL");
     23
     24static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
     25static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
     26static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable switches */
     27static int ibl[SNDRV_CARDS];
     28
     29module_param_array(index, int, NULL, 0444);
     30MODULE_PARM_DESC(index, "Index value for VXPocket soundcard.");
     31module_param_array(id, charp, NULL, 0444);
     32MODULE_PARM_DESC(id, "ID string for VXPocket soundcard.");
     33module_param_array(enable, bool, NULL, 0444);
     34MODULE_PARM_DESC(enable, "Enable VXPocket soundcard.");
     35module_param_array(ibl, int, NULL, 0444);
     36MODULE_PARM_DESC(ibl, "Capture IBL size for VXPocket soundcard.");
     37 
     38
     39/*
     40 */
     41
     42static unsigned int card_alloc;
     43
     44
     45/*
     46 */
     47static void vxpocket_release(struct pcmcia_device *link)
     48{
     49	free_irq(link->irq, link->priv);
     50	pcmcia_disable_device(link);
     51}
     52
     53/*
     54 * Hardware information
     55 */
     56
     57/* VX-pocket V2
     58 *
     59 * 1 DSP, 1 sync UER
     60 * 1 programmable clock (NIY)
     61 * 1 stereo analog input (line/micro)
     62 * 1 stereo analog output
     63 * Only output levels can be modified
     64 */
     65
     66static const DECLARE_TLV_DB_SCALE(db_scale_old_vol, -11350, 50, 0);
     67
     68static const struct snd_vx_hardware vxpocket_hw = {
     69	.name = "VXPocket",
     70	.type = VX_TYPE_VXPOCKET,
     71
     72	/* hardware specs */
     73	.num_codecs = 1,
     74	.num_ins = 1,
     75	.num_outs = 1,
     76	.output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
     77	.output_level_db_scale = db_scale_old_vol,
     78};	
     79
     80/* VX-pocket 440
     81 *
     82 * 1 DSP, 1 sync UER, 1 sync World Clock (NIY)
     83 * SMPTE (NIY)
     84 * 2 stereo analog input (line/micro)
     85 * 2 stereo analog output
     86 * Only output levels can be modified
     87 * UER, but only for the first two inputs and outputs.
     88 */
     89
     90static const struct snd_vx_hardware vxp440_hw = {
     91	.name = "VXPocket440",
     92	.type = VX_TYPE_VXP440,
     93
     94	/* hardware specs */
     95	.num_codecs = 2,
     96	.num_ins = 2,
     97	.num_outs = 2,
     98	.output_level_max = VX_ANALOG_OUT_LEVEL_MAX,
     99	.output_level_db_scale = db_scale_old_vol,
    100};	
    101
    102
    103/*
    104 * create vxpocket instance
    105 */
    106static int snd_vxpocket_new(struct snd_card *card, int ibl,
    107			    struct pcmcia_device *link,
    108			    struct snd_vxpocket **chip_ret)
    109{
    110	struct vx_core *chip;
    111	struct snd_vxpocket *vxp;
    112
    113	chip = snd_vx_create(card, &vxpocket_hw, &snd_vxpocket_ops,
    114			     sizeof(struct snd_vxpocket) - sizeof(struct vx_core));
    115	if (!chip)
    116		return -ENOMEM;
    117
    118	chip->ibl.size = ibl;
    119
    120	vxp = to_vxpocket(chip);
    121
    122	vxp->p_dev = link;
    123	link->priv = chip;
    124
    125	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
    126	link->resource[0]->end = 16;
    127
    128	link->config_flags |= CONF_ENABLE_IRQ;
    129	link->config_index = 1;
    130	link->config_regs = PRESENT_OPTION;
    131
    132	*chip_ret = vxp;
    133	return 0;
    134}
    135
    136
    137/**
    138 * snd_vxpocket_assign_resources - initialize the hardware and card instance.
    139 * @chip: VX core instance
    140 * @port: i/o port for the card
    141 * @irq: irq number for the card
    142 *
    143 * this function assigns the specified port and irq, boot the card,
    144 * create pcm and control instances, and initialize the rest hardware.
    145 *
    146 * returns 0 if successful, or a negative error code.
    147 */
    148static int snd_vxpocket_assign_resources(struct vx_core *chip, int port, int irq)
    149{
    150	int err;
    151	struct snd_card *card = chip->card;
    152	struct snd_vxpocket *vxp = to_vxpocket(chip);
    153
    154	snd_printdd(KERN_DEBUG "vxpocket assign resources: port = 0x%x, irq = %d\n", port, irq);
    155	vxp->port = port;
    156
    157	sprintf(card->shortname, "Digigram %s", card->driver);
    158	sprintf(card->longname, "%s at 0x%x, irq %i",
    159		card->shortname, port, irq);
    160
    161	chip->irq = irq;
    162	card->sync_irq = chip->irq;
    163
    164	err = snd_vx_setup_firmware(chip);
    165	if (err < 0)
    166		return err;
    167
    168	return 0;
    169}
    170
    171
    172/*
    173 * configuration callback
    174 */
    175
    176static int vxpocket_config(struct pcmcia_device *link)
    177{
    178	struct vx_core *chip = link->priv;
    179	int ret;
    180
    181	snd_printdd(KERN_DEBUG "vxpocket_config called\n");
    182
    183	/* redefine hardware record according to the VERSION1 string */
    184	if (!strcmp(link->prod_id[1], "VX-POCKET")) {
    185		snd_printdd("VX-pocket is detected\n");
    186	} else {
    187		snd_printdd("VX-pocket 440 is detected\n");
    188		/* overwrite the hardware information */
    189		chip->hw = &vxp440_hw;
    190		chip->type = vxp440_hw.type;
    191		strcpy(chip->card->driver, vxp440_hw.name);
    192	}
    193
    194	ret = pcmcia_request_io(link);
    195	if (ret)
    196		goto failed_preirq;
    197
    198	ret = request_threaded_irq(link->irq, snd_vx_irq_handler,
    199				   snd_vx_threaded_irq_handler,
    200				   IRQF_SHARED, link->devname, link->priv);
    201	if (ret)
    202		goto failed_preirq;
    203
    204	ret = pcmcia_enable_device(link);
    205	if (ret)
    206		goto failed;
    207
    208	chip->dev = &link->dev;
    209
    210	if (snd_vxpocket_assign_resources(chip, link->resource[0]->start,
    211						link->irq) < 0)
    212		goto failed;
    213
    214	return 0;
    215
    216 failed:
    217	free_irq(link->irq, link->priv);
    218failed_preirq:
    219	pcmcia_disable_device(link);
    220	return -ENODEV;
    221}
    222
    223#ifdef CONFIG_PM
    224
    225static int vxp_suspend(struct pcmcia_device *link)
    226{
    227	struct vx_core *chip = link->priv;
    228
    229	snd_printdd(KERN_DEBUG "SUSPEND\n");
    230	if (chip) {
    231		snd_printdd(KERN_DEBUG "snd_vx_suspend calling\n");
    232		snd_vx_suspend(chip);
    233	}
    234
    235	return 0;
    236}
    237
    238static int vxp_resume(struct pcmcia_device *link)
    239{
    240	struct vx_core *chip = link->priv;
    241
    242	snd_printdd(KERN_DEBUG "RESUME\n");
    243	if (pcmcia_dev_present(link)) {
    244		//struct snd_vxpocket *vxp = (struct snd_vxpocket *)chip;
    245		if (chip) {
    246			snd_printdd(KERN_DEBUG "calling snd_vx_resume\n");
    247			snd_vx_resume(chip);
    248		}
    249	}
    250	snd_printdd(KERN_DEBUG "resume done!\n");
    251
    252	return 0;
    253}
    254
    255#endif
    256
    257
    258/*
    259 */
    260static int vxpocket_probe(struct pcmcia_device *p_dev)
    261{
    262	struct snd_card *card;
    263	struct snd_vxpocket *vxp;
    264	int i, err;
    265
    266	/* find an empty slot from the card list */
    267	for (i = 0; i < SNDRV_CARDS; i++) {
    268		if (!(card_alloc & (1 << i)))
    269			break;
    270	}
    271	if (i >= SNDRV_CARDS) {
    272		snd_printk(KERN_ERR "vxpocket: too many cards found\n");
    273		return -EINVAL;
    274	}
    275	if (! enable[i])
    276		return -ENODEV; /* disabled explicitly */
    277
    278	/* ok, create a card instance */
    279	err = snd_card_new(&p_dev->dev, index[i], id[i], THIS_MODULE,
    280			   0, &card);
    281	if (err < 0) {
    282		snd_printk(KERN_ERR "vxpocket: cannot create a card instance\n");
    283		return err;
    284	}
    285
    286	err = snd_vxpocket_new(card, ibl[i], p_dev, &vxp);
    287	if (err < 0) {
    288		snd_card_free(card);
    289		return err;
    290	}
    291	card->private_data = vxp;
    292
    293	vxp->index = i;
    294	card_alloc |= 1 << i;
    295
    296	vxp->p_dev = p_dev;
    297
    298	return vxpocket_config(p_dev);
    299}
    300
    301static void vxpocket_detach(struct pcmcia_device *link)
    302{
    303	struct snd_vxpocket *vxp;
    304	struct vx_core *chip;
    305
    306	if (! link)
    307		return;
    308
    309	vxp = link->priv;
    310	chip = (struct vx_core *)vxp;
    311	card_alloc &= ~(1 << vxp->index);
    312
    313	chip->chip_status |= VX_STAT_IS_STALE; /* to be sure */
    314	snd_card_disconnect(chip->card);
    315	vxpocket_release(link);
    316	snd_card_free_when_closed(chip->card);
    317}
    318
    319/*
    320 * Module entry points
    321 */
    322
    323static const struct pcmcia_device_id vxp_ids[] = {
    324	PCMCIA_DEVICE_MANF_CARD(0x01f1, 0x0100),
    325	PCMCIA_DEVICE_NULL
    326};
    327MODULE_DEVICE_TABLE(pcmcia, vxp_ids);
    328
    329static struct pcmcia_driver vxp_cs_driver = {
    330	.owner		= THIS_MODULE,
    331	.name		= "snd-vxpocket",
    332	.probe		= vxpocket_probe,
    333	.remove		= vxpocket_detach,
    334	.id_table	= vxp_ids,
    335#ifdef CONFIG_PM
    336	.suspend	= vxp_suspend,
    337	.resume		= vxp_resume,
    338#endif
    339};
    340module_pcmcia_driver(vxp_cs_driver);