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

als100.c (9215B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2
      3/*
      4    card-als100.c - driver for Avance Logic ALS100 based soundcards.
      5    Copyright (C) 1999-2000 by Massimo Piccioni <dafastidio@libero.it>
      6    Copyright (C) 1999-2002 by Massimo Piccioni <dafastidio@libero.it>
      7
      8    Thanks to Pierfrancesco 'qM2' Passerini.
      9
     10    Generalised for soundcards based on DT-0196 and ALS-007 chips
     11    by Jonathan Woithe <jwoithe@just42.net>: June 2002.
     12
     13*/
     14
     15#include <linux/init.h>
     16#include <linux/wait.h>
     17#include <linux/time.h>
     18#include <linux/pnp.h>
     19#include <linux/module.h>
     20#include <sound/core.h>
     21#include <sound/initval.h>
     22#include <sound/mpu401.h>
     23#include <sound/opl3.h>
     24#include <sound/sb.h>
     25
     26#define PFX "als100: "
     27
     28MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0");
     29MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
     30MODULE_LICENSE("GPL");
     31
     32static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
     33static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
     34static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;	/* Enable this card */
     35static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
     36static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
     37static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;	/* PnP setup */
     38static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* PnP setup */
     39static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;	/* PnP setup */
     40static int dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
     41static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;	/* PnP setup */
     42
     43module_param_array(index, int, NULL, 0444);
     44MODULE_PARM_DESC(index, "Index value for Avance Logic based soundcard.");
     45module_param_array(id, charp, NULL, 0444);
     46MODULE_PARM_DESC(id, "ID string for Avance Logic based soundcard.");
     47module_param_array(enable, bool, NULL, 0444);
     48MODULE_PARM_DESC(enable, "Enable Avance Logic based soundcard.");
     49
     50MODULE_ALIAS("snd-dt019x");
     51
     52struct snd_card_als100 {
     53	struct pnp_dev *dev;
     54	struct pnp_dev *devmpu;
     55	struct pnp_dev *devopl;
     56	struct snd_sb *chip;
     57};
     58
     59static const struct pnp_card_device_id snd_als100_pnpids[] = {
     60	/* DT197A30 */
     61	{ .id = "RWB1688",
     62	  .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
     63	  .driver_data = SB_HW_DT019X },
     64	/* DT0196 / ALS-007 */
     65	{ .id = "ALS0007",
     66	  .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
     67	  .driver_data = SB_HW_DT019X },
     68	/* ALS100 - PRO16PNP */
     69	{ .id = "ALS0001",
     70	  .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
     71	  .driver_data = SB_HW_ALS100 },
     72	/* ALS110 - MF1000 - Digimate 3D Sound */
     73	{ .id = "ALS0110",
     74	  .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } },
     75	  .driver_data = SB_HW_ALS100 },
     76	/* ALS120 */
     77	{ .id = "ALS0120",
     78	  .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
     79	  .driver_data = SB_HW_ALS100 },
     80	/* ALS200 */
     81	{ .id = "ALS0200",
     82	  .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } },
     83	  .driver_data = SB_HW_ALS100 },
     84	/* ALS200 OEM */
     85	{ .id = "ALS0200",
     86	  .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } },
     87	  .driver_data = SB_HW_ALS100 },
     88	/* RTL3000 */
     89	{ .id = "RTL3000",
     90	  .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
     91	  .driver_data = SB_HW_ALS100 },
     92	{ .id = "" } /* end */
     93};
     94
     95MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
     96
     97static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
     98			       struct pnp_card_link *card,
     99			       const struct pnp_card_device_id *id)
    100{
    101	struct pnp_dev *pdev;
    102	int err;
    103
    104	acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
    105	if (acard->dev == NULL)
    106		return -ENODEV;
    107
    108	acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
    109	acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
    110
    111	pdev = acard->dev;
    112
    113	err = pnp_activate_dev(pdev);
    114	if (err < 0) {
    115		snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
    116		return err;
    117	}
    118	port[dev] = pnp_port_start(pdev, 0);
    119	if (id->driver_data == SB_HW_DT019X)
    120		dma8[dev] = pnp_dma(pdev, 0);
    121	else {
    122		dma8[dev] = pnp_dma(pdev, 1);
    123		dma16[dev] = pnp_dma(pdev, 0);
    124	}
    125	irq[dev] = pnp_irq(pdev, 0);
    126
    127	pdev = acard->devmpu;
    128	if (pdev != NULL) {
    129		err = pnp_activate_dev(pdev);
    130		if (err < 0)
    131			goto __mpu_error;
    132		mpu_port[dev] = pnp_port_start(pdev, 0);
    133		mpu_irq[dev] = pnp_irq(pdev, 0);
    134	} else {
    135	     __mpu_error:
    136	     	if (pdev) {
    137		     	pnp_release_card_device(pdev);
    138	     		snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
    139	     	}
    140	     	acard->devmpu = NULL;
    141	     	mpu_port[dev] = -1;
    142	}
    143
    144	pdev = acard->devopl;
    145	if (pdev != NULL) {
    146		err = pnp_activate_dev(pdev);
    147		if (err < 0)
    148			goto __fm_error;
    149		fm_port[dev] = pnp_port_start(pdev, 0);
    150	} else {
    151	      __fm_error:
    152	     	if (pdev) {
    153		     	pnp_release_card_device(pdev);
    154	     		snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
    155	     	}
    156	     	acard->devopl = NULL;
    157	     	fm_port[dev] = -1;
    158	}
    159
    160	return 0;
    161}
    162
    163static int snd_card_als100_probe(int dev,
    164				 struct pnp_card_link *pcard,
    165				 const struct pnp_card_device_id *pid)
    166{
    167	int error;
    168	struct snd_sb *chip;
    169	struct snd_card *card;
    170	struct snd_card_als100 *acard;
    171	struct snd_opl3 *opl3;
    172
    173	error = snd_devm_card_new(&pcard->card->dev,
    174				  index[dev], id[dev], THIS_MODULE,
    175				  sizeof(struct snd_card_als100), &card);
    176	if (error < 0)
    177		return error;
    178	acard = card->private_data;
    179
    180	error = snd_card_als100_pnp(dev, acard, pcard, pid);
    181	if (error)
    182		return error;
    183
    184	if (pid->driver_data == SB_HW_DT019X)
    185		dma16[dev] = -1;
    186
    187	error = snd_sbdsp_create(card, port[dev], irq[dev],
    188				  snd_sb16dsp_interrupt,
    189				  dma8[dev], dma16[dev],
    190				  pid->driver_data,
    191				  &chip);
    192	if (error < 0)
    193		return error;
    194	acard->chip = chip;
    195
    196	if (pid->driver_data == SB_HW_DT019X) {
    197		strcpy(card->driver, "DT-019X");
    198		strcpy(card->shortname, "Diamond Tech. DT-019X");
    199		snprintf(card->longname, sizeof(card->longname),
    200			 "Diamond Tech. DT-019X, %s at 0x%lx, irq %d, dma %d",
    201			 chip->name, chip->port, irq[dev], dma8[dev]);
    202	} else {
    203		strcpy(card->driver, "ALS100");
    204		strcpy(card->shortname, "Avance Logic ALS100");
    205		snprintf(card->longname, sizeof(card->longname),
    206			 "Avance Logic ALS100, %s at 0x%lx, irq %d, dma %d&%d",
    207			 chip->name, chip->port, irq[dev], dma8[dev],
    208			 dma16[dev]);
    209	}
    210
    211	error = snd_sb16dsp_pcm(chip, 0);
    212	if (error < 0)
    213		return error;
    214
    215	error = snd_sbmixer_new(chip);
    216	if (error < 0)
    217		return error;
    218
    219	if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
    220		int mpu_type = MPU401_HW_ALS100;
    221
    222		if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
    223			mpu_irq[dev] = -1;
    224
    225		if (pid->driver_data == SB_HW_DT019X)
    226			mpu_type = MPU401_HW_MPU401;
    227
    228		if (snd_mpu401_uart_new(card, 0,
    229					mpu_type,
    230					mpu_port[dev], 0, 
    231					mpu_irq[dev],
    232					NULL) < 0)
    233			snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
    234	}
    235
    236	if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
    237		if (snd_opl3_create(card,
    238				    fm_port[dev], fm_port[dev] + 2,
    239				    OPL3_HW_AUTO, 0, &opl3) < 0) {
    240			snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
    241				   fm_port[dev], fm_port[dev] + 2);
    242		} else {
    243			error = snd_opl3_timer_new(opl3, 0, 1);
    244			if (error < 0)
    245				return error;
    246			error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
    247			if (error < 0)
    248				return error;
    249		}
    250	}
    251
    252	error = snd_card_register(card);
    253	if (error < 0)
    254		return error;
    255	pnp_set_card_drvdata(pcard, card);
    256	return 0;
    257}
    258
    259static unsigned int als100_devices;
    260
    261static int snd_als100_pnp_detect(struct pnp_card_link *card,
    262				 const struct pnp_card_device_id *id)
    263{
    264	static int dev;
    265	int res;
    266
    267	for ( ; dev < SNDRV_CARDS; dev++) {
    268		if (!enable[dev])
    269			continue;
    270		res = snd_card_als100_probe(dev, card, id);
    271		if (res < 0)
    272			return res;
    273		dev++;
    274		als100_devices++;
    275		return 0;
    276	}
    277	return -ENODEV;
    278}
    279
    280#ifdef CONFIG_PM
    281static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
    282{
    283	struct snd_card *card = pnp_get_card_drvdata(pcard);
    284	struct snd_card_als100 *acard = card->private_data;
    285	struct snd_sb *chip = acard->chip;
    286
    287	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
    288	snd_sbmixer_suspend(chip);
    289	return 0;
    290}
    291
    292static int snd_als100_pnp_resume(struct pnp_card_link *pcard)
    293{
    294	struct snd_card *card = pnp_get_card_drvdata(pcard);
    295	struct snd_card_als100 *acard = card->private_data;
    296	struct snd_sb *chip = acard->chip;
    297
    298	snd_sbdsp_reset(chip);
    299	snd_sbmixer_resume(chip);
    300	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
    301	return 0;
    302}
    303#endif
    304
    305static struct pnp_card_driver als100_pnpc_driver = {
    306	.flags          = PNP_DRIVER_RES_DISABLE,
    307	.name		= "als100",
    308        .id_table       = snd_als100_pnpids,
    309        .probe          = snd_als100_pnp_detect,
    310#ifdef CONFIG_PM
    311	.suspend	= snd_als100_pnp_suspend,
    312	.resume		= snd_als100_pnp_resume,
    313#endif
    314};
    315
    316static int __init alsa_card_als100_init(void)
    317{
    318	int err;
    319
    320	err = pnp_register_card_driver(&als100_pnpc_driver);
    321	if (err)
    322		return err;
    323
    324	if (!als100_devices) {
    325		pnp_unregister_card_driver(&als100_pnpc_driver);
    326#ifdef MODULE
    327		snd_printk(KERN_ERR "no Avance Logic based soundcards found\n");
    328#endif
    329		return -ENODEV;
    330	}
    331	return 0;
    332}
    333
    334static void __exit alsa_card_als100_exit(void)
    335{
    336	pnp_unregister_card_driver(&als100_pnpc_driver);
    337}
    338
    339module_init(alsa_card_als100_init)
    340module_exit(alsa_card_als100_exit)