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

pdaudiocf.c (6627B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 * Driver for Sound Core PDAudioCF soundcard
      4 *
      5 * Copyright (c) 2003 by Jaroslav Kysela <perex@perex.cz>
      6 */
      7
      8#include <sound/core.h>
      9#include <linux/slab.h>
     10#include <linux/module.h>
     11#include <pcmcia/ciscode.h>
     12#include <pcmcia/cisreg.h>
     13#include "pdaudiocf.h"
     14#include <sound/initval.h>
     15#include <linux/init.h>
     16
     17/*
     18 */
     19
     20#define CARD_NAME	"PDAudio-CF"
     21
     22MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
     23MODULE_DESCRIPTION("Sound Core " CARD_NAME);
     24MODULE_LICENSE("GPL");
     25
     26static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
     27static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
     28static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;	/* Enable switches */
     29
     30module_param_array(index, int, NULL, 0444);
     31MODULE_PARM_DESC(index, "Index value for " CARD_NAME " soundcard.");
     32module_param_array(id, charp, NULL, 0444);
     33MODULE_PARM_DESC(id, "ID string for " CARD_NAME " soundcard.");
     34module_param_array(enable, bool, NULL, 0444);
     35MODULE_PARM_DESC(enable, "Enable " CARD_NAME " soundcard.");
     36
     37/*
     38 */
     39
     40static struct snd_card *card_list[SNDRV_CARDS];
     41
     42/*
     43 * prototypes
     44 */
     45static int pdacf_config(struct pcmcia_device *link);
     46static void snd_pdacf_detach(struct pcmcia_device *p_dev);
     47
     48static void pdacf_release(struct pcmcia_device *link)
     49{
     50	free_irq(link->irq, link->priv);
     51	pcmcia_disable_device(link);
     52}
     53
     54/*
     55 * destructor
     56 */
     57static int snd_pdacf_free(struct snd_pdacf *pdacf)
     58{
     59	struct pcmcia_device *link = pdacf->p_dev;
     60
     61	pdacf_release(link);
     62
     63	card_list[pdacf->index] = NULL;
     64	pdacf->card = NULL;
     65
     66	kfree(pdacf);
     67	return 0;
     68}
     69
     70static int snd_pdacf_dev_free(struct snd_device *device)
     71{
     72	struct snd_pdacf *chip = device->device_data;
     73	return snd_pdacf_free(chip);
     74}
     75
     76/*
     77 * snd_pdacf_attach - attach callback for cs
     78 */
     79static int snd_pdacf_probe(struct pcmcia_device *link)
     80{
     81	int i, err;
     82	struct snd_pdacf *pdacf;
     83	struct snd_card *card;
     84	static const struct snd_device_ops ops = {
     85		.dev_free =	snd_pdacf_dev_free,
     86	};
     87
     88	snd_printdd(KERN_DEBUG "pdacf_attach called\n");
     89	/* find an empty slot from the card list */
     90	for (i = 0; i < SNDRV_CARDS; i++) {
     91		if (! card_list[i])
     92			break;
     93	}
     94	if (i >= SNDRV_CARDS) {
     95		snd_printk(KERN_ERR "pdacf: too many cards found\n");
     96		return -EINVAL;
     97	}
     98	if (! enable[i])
     99		return -ENODEV; /* disabled explicitly */
    100
    101	/* ok, create a card instance */
    102	err = snd_card_new(&link->dev, index[i], id[i], THIS_MODULE,
    103			   0, &card);
    104	if (err < 0) {
    105		snd_printk(KERN_ERR "pdacf: cannot create a card instance\n");
    106		return err;
    107	}
    108
    109	pdacf = snd_pdacf_create(card);
    110	if (!pdacf) {
    111		snd_card_free(card);
    112		return -ENOMEM;
    113	}
    114
    115	err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, pdacf, &ops);
    116	if (err < 0) {
    117		kfree(pdacf);
    118		snd_card_free(card);
    119		return err;
    120	}
    121
    122	pdacf->index = i;
    123	card_list[i] = card;
    124
    125	pdacf->p_dev = link;
    126	link->priv = pdacf;
    127
    128	link->resource[0]->flags |= IO_DATA_PATH_WIDTH_AUTO;
    129	link->resource[0]->end = 16;
    130
    131	link->config_flags = CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
    132	link->config_index = 1;
    133	link->config_regs = PRESENT_OPTION;
    134
    135	return pdacf_config(link);
    136}
    137
    138
    139/**
    140 * snd_pdacf_assign_resources - initialize the hardware and card instance.
    141 * @pdacf: context
    142 * @port: i/o port for the card
    143 * @irq: irq number for the card
    144 *
    145 * this function assigns the specified port and irq, boot the card,
    146 * create pcm and control instances, and initialize the rest hardware.
    147 *
    148 * returns 0 if successful, or a negative error code.
    149 */
    150static int snd_pdacf_assign_resources(struct snd_pdacf *pdacf, int port, int irq)
    151{
    152	int err;
    153	struct snd_card *card = pdacf->card;
    154
    155	snd_printdd(KERN_DEBUG "pdacf assign resources: port = 0x%x, irq = %d\n", port, irq);
    156	pdacf->port = port;
    157	pdacf->irq = irq;
    158	pdacf->chip_status |= PDAUDIOCF_STAT_IS_CONFIGURED;
    159
    160	err = snd_pdacf_ak4117_create(pdacf);
    161	if (err < 0)
    162		return err;	
    163
    164	strcpy(card->driver, "PDAudio-CF");
    165	sprintf(card->shortname, "Core Sound %s", card->driver);
    166	sprintf(card->longname, "%s at 0x%x, irq %i",
    167		card->shortname, port, irq);
    168
    169	err = snd_pdacf_pcm_new(pdacf);
    170	if (err < 0)
    171		return err;
    172
    173	err = snd_card_register(card);
    174	if (err < 0)
    175		return err;
    176
    177	return 0;
    178}
    179
    180
    181/*
    182 * snd_pdacf_detach - detach callback for cs
    183 */
    184static void snd_pdacf_detach(struct pcmcia_device *link)
    185{
    186	struct snd_pdacf *chip = link->priv;
    187
    188	snd_printdd(KERN_DEBUG "pdacf_detach called\n");
    189
    190	if (chip->chip_status & PDAUDIOCF_STAT_IS_CONFIGURED)
    191		snd_pdacf_powerdown(chip);
    192	chip->chip_status |= PDAUDIOCF_STAT_IS_STALE; /* to be sure */
    193	snd_card_disconnect(chip->card);
    194	snd_card_free_when_closed(chip->card);
    195}
    196
    197/*
    198 * configuration callback
    199 */
    200
    201static int pdacf_config(struct pcmcia_device *link)
    202{
    203	struct snd_pdacf *pdacf = link->priv;
    204	int ret;
    205
    206	snd_printdd(KERN_DEBUG "pdacf_config called\n");
    207	link->config_index = 0x5;
    208	link->config_flags |= CONF_ENABLE_IRQ | CONF_ENABLE_PULSE_IRQ;
    209
    210	ret = pcmcia_request_io(link);
    211	if (ret)
    212		goto failed_preirq;
    213
    214	ret = request_threaded_irq(link->irq, pdacf_interrupt,
    215				   pdacf_threaded_irq,
    216				   IRQF_SHARED, link->devname, link->priv);
    217	if (ret)
    218		goto failed_preirq;
    219
    220	ret = pcmcia_enable_device(link);
    221	if (ret)
    222		goto failed;
    223
    224	if (snd_pdacf_assign_resources(pdacf, link->resource[0]->start,
    225					link->irq) < 0)
    226		goto failed;
    227
    228	pdacf->card->sync_irq = link->irq;
    229	return 0;
    230
    231 failed:
    232	free_irq(link->irq, link->priv);
    233failed_preirq:
    234	pcmcia_disable_device(link);
    235	return -ENODEV;
    236}
    237
    238#ifdef CONFIG_PM
    239
    240static int pdacf_suspend(struct pcmcia_device *link)
    241{
    242	struct snd_pdacf *chip = link->priv;
    243
    244	snd_printdd(KERN_DEBUG "SUSPEND\n");
    245	if (chip) {
    246		snd_printdd(KERN_DEBUG "snd_pdacf_suspend calling\n");
    247		snd_pdacf_suspend(chip);
    248	}
    249
    250	return 0;
    251}
    252
    253static int pdacf_resume(struct pcmcia_device *link)
    254{
    255	struct snd_pdacf *chip = link->priv;
    256
    257	snd_printdd(KERN_DEBUG "RESUME\n");
    258	if (pcmcia_dev_present(link)) {
    259		if (chip) {
    260			snd_printdd(KERN_DEBUG "calling snd_pdacf_resume\n");
    261			snd_pdacf_resume(chip);
    262		}
    263	}
    264	snd_printdd(KERN_DEBUG "resume done!\n");
    265
    266	return 0;
    267}
    268
    269#endif
    270
    271/*
    272 * Module entry points
    273 */
    274static const struct pcmcia_device_id snd_pdacf_ids[] = {
    275	/* this is too general PCMCIA_DEVICE_MANF_CARD(0x015d, 0x4c45), */
    276	PCMCIA_DEVICE_PROD_ID12("Core Sound","PDAudio-CF",0x396d19d2,0x71717b49),
    277	PCMCIA_DEVICE_NULL
    278};
    279MODULE_DEVICE_TABLE(pcmcia, snd_pdacf_ids);
    280
    281static struct pcmcia_driver pdacf_cs_driver = {
    282	.owner		= THIS_MODULE,
    283	.name		= "snd-pdaudiocf",
    284	.probe		= snd_pdacf_probe,
    285	.remove		= snd_pdacf_detach,
    286	.id_table	= snd_pdacf_ids,
    287#ifdef CONFIG_PM
    288	.suspend	= pdacf_suspend,
    289	.resume		= pdacf_resume,
    290#endif
    291};
    292module_pcmcia_driver(pdacf_cs_driver);