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

msnd_pinnacle.c (29062B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*********************************************************************
      3 *
      4 * Linux multisound pinnacle/fiji driver for ALSA.
      5 *
      6 * 2002/06/30 Karsten Wiese:
      7 *	for now this is only used to build a pinnacle / fiji driver.
      8 *	the OSS parent of this code is designed to also support
      9 *	the multisound classic via the file msnd_classic.c.
     10 *	to make it easier for some brave heart to implemt classic
     11 *	support in alsa, i left all the MSND_CLASSIC tokens in this file.
     12 *	but for now this untested & undone.
     13 *
     14 * ripped from linux kernel 2.4.18 by Karsten Wiese.
     15 *
     16 * the following is a copy of the 2.4.18 OSS FREE file-heading comment:
     17 *
     18 * Turtle Beach MultiSound Sound Card Driver for Linux
     19 * msnd_pinnacle.c / msnd_classic.c
     20 *
     21 * -- If MSND_CLASSIC is defined:
     22 *
     23 *     -> driver for Turtle Beach Classic/Monterey/Tahiti
     24 *
     25 * -- Else
     26 *
     27 *     -> driver for Turtle Beach Pinnacle/Fiji
     28 *
     29 * 12-3-2000  Modified IO port validation  Steve Sycamore
     30 *
     31 * Copyright (C) 1998 Andrew Veliath
     32 *
     33 ********************************************************************/
     34
     35#include <linux/kernel.h>
     36#include <linux/module.h>
     37#include <linux/interrupt.h>
     38#include <linux/types.h>
     39#include <linux/delay.h>
     40#include <linux/ioport.h>
     41#include <linux/firmware.h>
     42#include <linux/isa.h>
     43#include <linux/isapnp.h>
     44#include <linux/irq.h>
     45#include <linux/io.h>
     46
     47#include <sound/core.h>
     48#include <sound/initval.h>
     49#include <sound/asound.h>
     50#include <sound/pcm.h>
     51#include <sound/mpu401.h>
     52
     53#ifdef MSND_CLASSIC
     54# ifndef __alpha__
     55#  define SLOWIO
     56# endif
     57#endif
     58#include "msnd.h"
     59#ifdef MSND_CLASSIC
     60#  include "msnd_classic.h"
     61#  define LOGNAME			"msnd_classic"
     62#  define DEV_NAME			"msnd-classic"
     63#else
     64#  include "msnd_pinnacle.h"
     65#  define LOGNAME			"snd_msnd_pinnacle"
     66#  define DEV_NAME			"msnd-pinnacle"
     67#endif
     68
     69static void set_default_audio_parameters(struct snd_msnd *chip)
     70{
     71	chip->play_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
     72	chip->play_sample_rate = DEFSAMPLERATE;
     73	chip->play_channels = DEFCHANNELS;
     74	chip->capture_sample_size = snd_pcm_format_width(DEFSAMPLESIZE);
     75	chip->capture_sample_rate = DEFSAMPLERATE;
     76	chip->capture_channels = DEFCHANNELS;
     77}
     78
     79static void snd_msnd_eval_dsp_msg(struct snd_msnd *chip, u16 wMessage)
     80{
     81	switch (HIBYTE(wMessage)) {
     82	case HIMT_PLAY_DONE: {
     83		if (chip->banksPlayed < 3)
     84			snd_printdd("%08X: HIMT_PLAY_DONE: %i\n",
     85				(unsigned)jiffies, LOBYTE(wMessage));
     86
     87		if (chip->last_playbank == LOBYTE(wMessage)) {
     88			snd_printdd("chip.last_playbank == LOBYTE(wMessage)\n");
     89			break;
     90		}
     91		chip->banksPlayed++;
     92
     93		if (test_bit(F_WRITING, &chip->flags))
     94			snd_msnd_DAPQ(chip, 0);
     95
     96		chip->last_playbank = LOBYTE(wMessage);
     97		chip->playDMAPos += chip->play_period_bytes;
     98		if (chip->playDMAPos > chip->playLimit)
     99			chip->playDMAPos = 0;
    100		snd_pcm_period_elapsed(chip->playback_substream);
    101
    102		break;
    103	}
    104	case HIMT_RECORD_DONE:
    105		if (chip->last_recbank == LOBYTE(wMessage))
    106			break;
    107		chip->last_recbank = LOBYTE(wMessage);
    108		chip->captureDMAPos += chip->capturePeriodBytes;
    109		if (chip->captureDMAPos > (chip->captureLimit))
    110			chip->captureDMAPos = 0;
    111
    112		if (test_bit(F_READING, &chip->flags))
    113			snd_msnd_DARQ(chip, chip->last_recbank);
    114
    115		snd_pcm_period_elapsed(chip->capture_substream);
    116		break;
    117
    118	case HIMT_DSP:
    119		switch (LOBYTE(wMessage)) {
    120#ifndef MSND_CLASSIC
    121		case HIDSP_PLAY_UNDER:
    122#endif
    123		case HIDSP_INT_PLAY_UNDER:
    124			snd_printd(KERN_WARNING LOGNAME ": Play underflow %i\n",
    125				chip->banksPlayed);
    126			if (chip->banksPlayed > 2)
    127				clear_bit(F_WRITING, &chip->flags);
    128			break;
    129
    130		case HIDSP_INT_RECORD_OVER:
    131			snd_printd(KERN_WARNING LOGNAME ": Record overflow\n");
    132			clear_bit(F_READING, &chip->flags);
    133			break;
    134
    135		default:
    136			snd_printd(KERN_WARNING LOGNAME
    137				   ": DSP message %d 0x%02x\n",
    138				   LOBYTE(wMessage), LOBYTE(wMessage));
    139			break;
    140		}
    141		break;
    142
    143	case HIMT_MIDI_IN_UCHAR:
    144		if (chip->msndmidi_mpu)
    145			snd_msndmidi_input_read(chip->msndmidi_mpu);
    146		break;
    147
    148	default:
    149		snd_printd(KERN_WARNING LOGNAME ": HIMT message %d 0x%02x\n",
    150			   HIBYTE(wMessage), HIBYTE(wMessage));
    151		break;
    152	}
    153}
    154
    155static irqreturn_t snd_msnd_interrupt(int irq, void *dev_id)
    156{
    157	struct snd_msnd *chip = dev_id;
    158	void __iomem *pwDSPQData = chip->mappedbase + DSPQ_DATA_BUFF;
    159	u16 head, tail, size;
    160
    161	/* Send ack to DSP */
    162	/* inb(chip->io + HP_RXL); */
    163
    164	/* Evaluate queued DSP messages */
    165	head = readw(chip->DSPQ + JQS_wHead);
    166	tail = readw(chip->DSPQ + JQS_wTail);
    167	size = readw(chip->DSPQ + JQS_wSize);
    168	if (head > size || tail > size)
    169		goto out;
    170	while (head != tail) {
    171		snd_msnd_eval_dsp_msg(chip, readw(pwDSPQData + 2 * head));
    172		if (++head > size)
    173			head = 0;
    174		writew(head, chip->DSPQ + JQS_wHead);
    175	}
    176 out:
    177	/* Send ack to DSP */
    178	inb(chip->io + HP_RXL);
    179	return IRQ_HANDLED;
    180}
    181
    182
    183static int snd_msnd_reset_dsp(long io, unsigned char *info)
    184{
    185	int timeout = 100;
    186
    187	outb(HPDSPRESET_ON, io + HP_DSPR);
    188	msleep(1);
    189#ifndef MSND_CLASSIC
    190	if (info)
    191		*info = inb(io + HP_INFO);
    192#endif
    193	outb(HPDSPRESET_OFF, io + HP_DSPR);
    194	msleep(1);
    195	while (timeout-- > 0) {
    196		if (inb(io + HP_CVR) == HP_CVR_DEF)
    197			return 0;
    198		msleep(1);
    199	}
    200	snd_printk(KERN_ERR LOGNAME ": Cannot reset DSP\n");
    201
    202	return -EIO;
    203}
    204
    205static int snd_msnd_probe(struct snd_card *card)
    206{
    207	struct snd_msnd *chip = card->private_data;
    208	unsigned char info;
    209#ifndef MSND_CLASSIC
    210	char *xv, *rev = NULL;
    211	char *pin = "TB Pinnacle", *fiji = "TB Fiji";
    212	char *pinfiji = "TB Pinnacle/Fiji";
    213#endif
    214
    215	if (!request_region(chip->io, DSP_NUMIO, "probing")) {
    216		snd_printk(KERN_ERR LOGNAME ": I/O port conflict\n");
    217		return -ENODEV;
    218	}
    219
    220	if (snd_msnd_reset_dsp(chip->io, &info) < 0) {
    221		release_region(chip->io, DSP_NUMIO);
    222		return -ENODEV;
    223	}
    224
    225#ifdef MSND_CLASSIC
    226	strcpy(card->shortname, "Classic/Tahiti/Monterey");
    227	strcpy(card->longname, "Turtle Beach Multisound");
    228	printk(KERN_INFO LOGNAME ": %s, "
    229	       "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
    230	       card->shortname,
    231	       chip->io, chip->io + DSP_NUMIO - 1,
    232	       chip->irq,
    233	       chip->base, chip->base + 0x7fff);
    234#else
    235	switch (info >> 4) {
    236	case 0xf:
    237		xv = "<= 1.15";
    238		break;
    239	case 0x1:
    240		xv = "1.18/1.2";
    241		break;
    242	case 0x2:
    243		xv = "1.3";
    244		break;
    245	case 0x3:
    246		xv = "1.4";
    247		break;
    248	default:
    249		xv = "unknown";
    250		break;
    251	}
    252
    253	switch (info & 0x7) {
    254	case 0x0:
    255		rev = "I";
    256		strcpy(card->shortname, pin);
    257		break;
    258	case 0x1:
    259		rev = "F";
    260		strcpy(card->shortname, pin);
    261		break;
    262	case 0x2:
    263		rev = "G";
    264		strcpy(card->shortname, pin);
    265		break;
    266	case 0x3:
    267		rev = "H";
    268		strcpy(card->shortname, pin);
    269		break;
    270	case 0x4:
    271		rev = "E";
    272		strcpy(card->shortname, fiji);
    273		break;
    274	case 0x5:
    275		rev = "C";
    276		strcpy(card->shortname, fiji);
    277		break;
    278	case 0x6:
    279		rev = "D";
    280		strcpy(card->shortname, fiji);
    281		break;
    282	case 0x7:
    283		rev = "A-B (Fiji) or A-E (Pinnacle)";
    284		strcpy(card->shortname, pinfiji);
    285		break;
    286	}
    287	strcpy(card->longname, "Turtle Beach Multisound Pinnacle");
    288	printk(KERN_INFO LOGNAME ": %s revision %s, Xilinx version %s, "
    289	       "I/O 0x%lx-0x%lx, IRQ %d, memory mapped to 0x%lX-0x%lX\n",
    290	       card->shortname,
    291	       rev, xv,
    292	       chip->io, chip->io + DSP_NUMIO - 1,
    293	       chip->irq,
    294	       chip->base, chip->base + 0x7fff);
    295#endif
    296
    297	release_region(chip->io, DSP_NUMIO);
    298	return 0;
    299}
    300
    301static int snd_msnd_init_sma(struct snd_msnd *chip)
    302{
    303	static int initted;
    304	u16 mastVolLeft, mastVolRight;
    305	unsigned long flags;
    306
    307#ifdef MSND_CLASSIC
    308	outb(chip->memid, chip->io + HP_MEMM);
    309#endif
    310	outb(HPBLKSEL_0, chip->io + HP_BLKS);
    311	/* Motorola 56k shared memory base */
    312	chip->SMA = chip->mappedbase + SMA_STRUCT_START;
    313
    314	if (initted) {
    315		mastVolLeft = readw(chip->SMA + SMA_wCurrMastVolLeft);
    316		mastVolRight = readw(chip->SMA + SMA_wCurrMastVolRight);
    317	} else
    318		mastVolLeft = mastVolRight = 0;
    319	memset_io(chip->mappedbase, 0, 0x8000);
    320
    321	/* Critical section: bank 1 access */
    322	spin_lock_irqsave(&chip->lock, flags);
    323	outb(HPBLKSEL_1, chip->io + HP_BLKS);
    324	memset_io(chip->mappedbase, 0, 0x8000);
    325	outb(HPBLKSEL_0, chip->io + HP_BLKS);
    326	spin_unlock_irqrestore(&chip->lock, flags);
    327
    328	/* Digital audio play queue */
    329	chip->DAPQ = chip->mappedbase + DAPQ_OFFSET;
    330	snd_msnd_init_queue(chip->DAPQ, DAPQ_DATA_BUFF, DAPQ_BUFF_SIZE);
    331
    332	/* Digital audio record queue */
    333	chip->DARQ = chip->mappedbase + DARQ_OFFSET;
    334	snd_msnd_init_queue(chip->DARQ, DARQ_DATA_BUFF, DARQ_BUFF_SIZE);
    335
    336	/* MIDI out queue */
    337	chip->MODQ = chip->mappedbase + MODQ_OFFSET;
    338	snd_msnd_init_queue(chip->MODQ, MODQ_DATA_BUFF, MODQ_BUFF_SIZE);
    339
    340	/* MIDI in queue */
    341	chip->MIDQ = chip->mappedbase + MIDQ_OFFSET;
    342	snd_msnd_init_queue(chip->MIDQ, MIDQ_DATA_BUFF, MIDQ_BUFF_SIZE);
    343
    344	/* DSP -> host message queue */
    345	chip->DSPQ = chip->mappedbase + DSPQ_OFFSET;
    346	snd_msnd_init_queue(chip->DSPQ, DSPQ_DATA_BUFF, DSPQ_BUFF_SIZE);
    347
    348	/* Setup some DSP values */
    349#ifndef MSND_CLASSIC
    350	writew(1, chip->SMA + SMA_wCurrPlayFormat);
    351	writew(chip->play_sample_size, chip->SMA + SMA_wCurrPlaySampleSize);
    352	writew(chip->play_channels, chip->SMA + SMA_wCurrPlayChannels);
    353	writew(chip->play_sample_rate, chip->SMA + SMA_wCurrPlaySampleRate);
    354#endif
    355	writew(chip->play_sample_rate, chip->SMA + SMA_wCalFreqAtoD);
    356	writew(mastVolLeft, chip->SMA + SMA_wCurrMastVolLeft);
    357	writew(mastVolRight, chip->SMA + SMA_wCurrMastVolRight);
    358#ifndef MSND_CLASSIC
    359	writel(0x00010000, chip->SMA + SMA_dwCurrPlayPitch);
    360	writel(0x00000001, chip->SMA + SMA_dwCurrPlayRate);
    361#endif
    362	writew(0x303, chip->SMA + SMA_wCurrInputTagBits);
    363
    364	initted = 1;
    365
    366	return 0;
    367}
    368
    369
    370static int upload_dsp_code(struct snd_card *card)
    371{
    372	struct snd_msnd *chip = card->private_data;
    373	const struct firmware *init_fw = NULL, *perm_fw = NULL;
    374	int err;
    375
    376	outb(HPBLKSEL_0, chip->io + HP_BLKS);
    377
    378	err = request_firmware(&init_fw, INITCODEFILE, card->dev);
    379	if (err < 0) {
    380		printk(KERN_ERR LOGNAME ": Error loading " INITCODEFILE);
    381		goto cleanup1;
    382	}
    383	err = request_firmware(&perm_fw, PERMCODEFILE, card->dev);
    384	if (err < 0) {
    385		printk(KERN_ERR LOGNAME ": Error loading " PERMCODEFILE);
    386		goto cleanup;
    387	}
    388
    389	memcpy_toio(chip->mappedbase, perm_fw->data, perm_fw->size);
    390	if (snd_msnd_upload_host(chip, init_fw->data, init_fw->size) < 0) {
    391		printk(KERN_WARNING LOGNAME ": Error uploading to DSP\n");
    392		err = -ENODEV;
    393		goto cleanup;
    394	}
    395	printk(KERN_INFO LOGNAME ": DSP firmware uploaded\n");
    396	err = 0;
    397
    398cleanup:
    399	release_firmware(perm_fw);
    400cleanup1:
    401	release_firmware(init_fw);
    402	return err;
    403}
    404
    405#ifdef MSND_CLASSIC
    406static void reset_proteus(struct snd_msnd *chip)
    407{
    408	outb(HPPRORESET_ON, chip->io + HP_PROR);
    409	msleep(TIME_PRO_RESET);
    410	outb(HPPRORESET_OFF, chip->io + HP_PROR);
    411	msleep(TIME_PRO_RESET_DONE);
    412}
    413#endif
    414
    415static int snd_msnd_initialize(struct snd_card *card)
    416{
    417	struct snd_msnd *chip = card->private_data;
    418	int err, timeout;
    419
    420#ifdef MSND_CLASSIC
    421	outb(HPWAITSTATE_0, chip->io + HP_WAIT);
    422	outb(HPBITMODE_16, chip->io + HP_BITM);
    423
    424	reset_proteus(chip);
    425#endif
    426	err = snd_msnd_init_sma(chip);
    427	if (err < 0) {
    428		printk(KERN_WARNING LOGNAME ": Cannot initialize SMA\n");
    429		return err;
    430	}
    431
    432	err = snd_msnd_reset_dsp(chip->io, NULL);
    433	if (err < 0)
    434		return err;
    435
    436	err = upload_dsp_code(card);
    437	if (err < 0) {
    438		printk(KERN_WARNING LOGNAME ": Cannot upload DSP code\n");
    439		return err;
    440	}
    441
    442	timeout = 200;
    443
    444	while (readw(chip->mappedbase)) {
    445		msleep(1);
    446		if (!timeout--) {
    447			snd_printd(KERN_ERR LOGNAME ": DSP reset timeout\n");
    448			return -EIO;
    449		}
    450	}
    451
    452	snd_msndmix_setup(chip);
    453	return 0;
    454}
    455
    456static int snd_msnd_dsp_full_reset(struct snd_card *card)
    457{
    458	struct snd_msnd *chip = card->private_data;
    459	int rv;
    460
    461	if (test_bit(F_RESETTING, &chip->flags) || ++chip->nresets > 10)
    462		return 0;
    463
    464	set_bit(F_RESETTING, &chip->flags);
    465	snd_msnd_dsp_halt(chip, NULL);	/* Unconditionally halt */
    466
    467	rv = snd_msnd_initialize(card);
    468	if (rv)
    469		printk(KERN_WARNING LOGNAME ": DSP reset failed\n");
    470	snd_msndmix_force_recsrc(chip, 0);
    471	clear_bit(F_RESETTING, &chip->flags);
    472	return rv;
    473}
    474
    475
    476static int snd_msnd_send_dsp_cmd_chk(struct snd_msnd *chip, u8 cmd)
    477{
    478	if (snd_msnd_send_dsp_cmd(chip, cmd) == 0)
    479		return 0;
    480	snd_msnd_dsp_full_reset(chip->card);
    481	return snd_msnd_send_dsp_cmd(chip, cmd);
    482}
    483
    484static int snd_msnd_calibrate_adc(struct snd_msnd *chip, u16 srate)
    485{
    486	snd_printdd("snd_msnd_calibrate_adc(%i)\n", srate);
    487	writew(srate, chip->SMA + SMA_wCalFreqAtoD);
    488	if (chip->calibrate_signal == 0)
    489		writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
    490		       | 0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
    491	else
    492		writew(readw(chip->SMA + SMA_wCurrHostStatusFlags)
    493		       & ~0x0001, chip->SMA + SMA_wCurrHostStatusFlags);
    494	if (snd_msnd_send_word(chip, 0, 0, HDEXAR_CAL_A_TO_D) == 0 &&
    495	    snd_msnd_send_dsp_cmd_chk(chip, HDEX_AUX_REQ) == 0) {
    496		schedule_timeout_interruptible(msecs_to_jiffies(333));
    497		return 0;
    498	}
    499	printk(KERN_WARNING LOGNAME ": ADC calibration failed\n");
    500	return -EIO;
    501}
    502
    503/*
    504 * ALSA callback function, called when attempting to open the MIDI device.
    505 */
    506static int snd_msnd_mpu401_open(struct snd_mpu401 *mpu)
    507{
    508	snd_msnd_enable_irq(mpu->private_data);
    509	snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_START);
    510	return 0;
    511}
    512
    513static void snd_msnd_mpu401_close(struct snd_mpu401 *mpu)
    514{
    515	snd_msnd_send_dsp_cmd(mpu->private_data, HDEX_MIDI_IN_STOP);
    516	snd_msnd_disable_irq(mpu->private_data);
    517}
    518
    519static long mpu_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    520static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
    521
    522static int snd_msnd_attach(struct snd_card *card)
    523{
    524	struct snd_msnd *chip = card->private_data;
    525	int err;
    526
    527	err = devm_request_irq(card->dev, chip->irq, snd_msnd_interrupt, 0,
    528			       card->shortname, chip);
    529	if (err < 0) {
    530		printk(KERN_ERR LOGNAME ": Couldn't grab IRQ %d\n", chip->irq);
    531		return err;
    532	}
    533	card->sync_irq = chip->irq;
    534	if (!devm_request_region(card->dev, chip->io, DSP_NUMIO,
    535				 card->shortname))
    536		return -EBUSY;
    537
    538	if (!devm_request_mem_region(card->dev, chip->base, BUFFSIZE,
    539				     card->shortname)) {
    540		printk(KERN_ERR LOGNAME
    541			": unable to grab memory region 0x%lx-0x%lx\n",
    542			chip->base, chip->base + BUFFSIZE - 1);
    543		return -EBUSY;
    544	}
    545	chip->mappedbase = devm_ioremap(card->dev, chip->base, 0x8000);
    546	if (!chip->mappedbase) {
    547		printk(KERN_ERR LOGNAME
    548			": unable to map memory region 0x%lx-0x%lx\n",
    549			chip->base, chip->base + BUFFSIZE - 1);
    550		return -EIO;
    551	}
    552
    553	err = snd_msnd_dsp_full_reset(card);
    554	if (err < 0)
    555		return err;
    556
    557	err = snd_msnd_pcm(card, 0);
    558	if (err < 0) {
    559		printk(KERN_ERR LOGNAME ": error creating new PCM device\n");
    560		return err;
    561	}
    562
    563	err = snd_msndmix_new(card);
    564	if (err < 0) {
    565		printk(KERN_ERR LOGNAME ": error creating new Mixer device\n");
    566		return err;
    567	}
    568
    569
    570	if (mpu_io[0] != SNDRV_AUTO_PORT) {
    571		struct snd_mpu401 *mpu;
    572
    573		err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
    574					  mpu_io[0],
    575					  MPU401_MODE_INPUT |
    576					  MPU401_MODE_OUTPUT,
    577					  mpu_irq[0],
    578					  &chip->rmidi);
    579		if (err < 0) {
    580			printk(KERN_ERR LOGNAME
    581				": error creating new Midi device\n");
    582			return err;
    583		}
    584		mpu = chip->rmidi->private_data;
    585
    586		mpu->open_input = snd_msnd_mpu401_open;
    587		mpu->close_input = snd_msnd_mpu401_close;
    588		mpu->private_data = chip;
    589	}
    590
    591	disable_irq(chip->irq);
    592	snd_msnd_calibrate_adc(chip, chip->play_sample_rate);
    593	snd_msndmix_force_recsrc(chip, 0);
    594
    595	err = snd_card_register(card);
    596	if (err < 0)
    597		return err;
    598
    599	return 0;
    600}
    601
    602
    603#ifndef MSND_CLASSIC
    604
    605/* Pinnacle/Fiji Logical Device Configuration */
    606
    607static int snd_msnd_write_cfg(int cfg, int reg, int value)
    608{
    609	outb(reg, cfg);
    610	outb(value, cfg + 1);
    611	if (value != inb(cfg + 1)) {
    612		printk(KERN_ERR LOGNAME ": snd_msnd_write_cfg: I/O error\n");
    613		return -EIO;
    614	}
    615	return 0;
    616}
    617
    618static int snd_msnd_write_cfg_io0(int cfg, int num, u16 io)
    619{
    620	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    621		return -EIO;
    622	if (snd_msnd_write_cfg(cfg, IREG_IO0_BASEHI, HIBYTE(io)))
    623		return -EIO;
    624	if (snd_msnd_write_cfg(cfg, IREG_IO0_BASELO, LOBYTE(io)))
    625		return -EIO;
    626	return 0;
    627}
    628
    629static int snd_msnd_write_cfg_io1(int cfg, int num, u16 io)
    630{
    631	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    632		return -EIO;
    633	if (snd_msnd_write_cfg(cfg, IREG_IO1_BASEHI, HIBYTE(io)))
    634		return -EIO;
    635	if (snd_msnd_write_cfg(cfg, IREG_IO1_BASELO, LOBYTE(io)))
    636		return -EIO;
    637	return 0;
    638}
    639
    640static int snd_msnd_write_cfg_irq(int cfg, int num, u16 irq)
    641{
    642	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    643		return -EIO;
    644	if (snd_msnd_write_cfg(cfg, IREG_IRQ_NUMBER, LOBYTE(irq)))
    645		return -EIO;
    646	if (snd_msnd_write_cfg(cfg, IREG_IRQ_TYPE, IRQTYPE_EDGE))
    647		return -EIO;
    648	return 0;
    649}
    650
    651static int snd_msnd_write_cfg_mem(int cfg, int num, int mem)
    652{
    653	u16 wmem;
    654
    655	mem >>= 8;
    656	wmem = (u16)(mem & 0xfff);
    657	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    658		return -EIO;
    659	if (snd_msnd_write_cfg(cfg, IREG_MEMBASEHI, HIBYTE(wmem)))
    660		return -EIO;
    661	if (snd_msnd_write_cfg(cfg, IREG_MEMBASELO, LOBYTE(wmem)))
    662		return -EIO;
    663	if (wmem && snd_msnd_write_cfg(cfg, IREG_MEMCONTROL,
    664				       MEMTYPE_HIADDR | MEMTYPE_16BIT))
    665		return -EIO;
    666	return 0;
    667}
    668
    669static int snd_msnd_activate_logical(int cfg, int num)
    670{
    671	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    672		return -EIO;
    673	if (snd_msnd_write_cfg(cfg, IREG_ACTIVATE, LD_ACTIVATE))
    674		return -EIO;
    675	return 0;
    676}
    677
    678static int snd_msnd_write_cfg_logical(int cfg, int num, u16 io0,
    679				      u16 io1, u16 irq, int mem)
    680{
    681	if (snd_msnd_write_cfg(cfg, IREG_LOGDEVICE, num))
    682		return -EIO;
    683	if (snd_msnd_write_cfg_io0(cfg, num, io0))
    684		return -EIO;
    685	if (snd_msnd_write_cfg_io1(cfg, num, io1))
    686		return -EIO;
    687	if (snd_msnd_write_cfg_irq(cfg, num, irq))
    688		return -EIO;
    689	if (snd_msnd_write_cfg_mem(cfg, num, mem))
    690		return -EIO;
    691	if (snd_msnd_activate_logical(cfg, num))
    692		return -EIO;
    693	return 0;
    694}
    695
    696static int snd_msnd_pinnacle_cfg_reset(int cfg)
    697{
    698	int i;
    699
    700	/* Reset devices if told to */
    701	printk(KERN_INFO LOGNAME ": Resetting all devices\n");
    702	for (i = 0; i < 4; ++i)
    703		if (snd_msnd_write_cfg_logical(cfg, i, 0, 0, 0, 0))
    704			return -EIO;
    705
    706	return 0;
    707}
    708#endif
    709
    710static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;	/* Index 0-MAX */
    711static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;	/* ID for this card */
    712
    713module_param_array(index, int, NULL, 0444);
    714MODULE_PARM_DESC(index, "Index value for msnd_pinnacle soundcard.");
    715module_param_array(id, charp, NULL, 0444);
    716MODULE_PARM_DESC(id, "ID string for msnd_pinnacle soundcard.");
    717
    718static long io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    719static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
    720static long mem[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    721
    722#ifndef MSND_CLASSIC
    723static long cfg[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    724
    725/* Extra Peripheral Configuration (Default: Disable) */
    726static long ide_io0[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    727static long ide_io1[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    728static int ide_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
    729
    730static long joystick_io[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
    731/* If we have the digital daugherboard... */
    732static int digital[SNDRV_CARDS];
    733
    734/* Extra Peripheral Configuration */
    735static int reset[SNDRV_CARDS];
    736#endif
    737
    738static int write_ndelay[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = 1 };
    739
    740static int calibrate_signal;
    741
    742#ifdef CONFIG_PNP
    743static bool isapnp[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP;
    744module_param_array(isapnp, bool, NULL, 0444);
    745MODULE_PARM_DESC(isapnp, "ISA PnP detection for specified soundcard.");
    746#define has_isapnp(x) isapnp[x]
    747#else
    748#define has_isapnp(x) 0
    749#endif
    750
    751MODULE_AUTHOR("Karsten Wiese <annabellesgarden@yahoo.de>");
    752MODULE_DESCRIPTION("Turtle Beach " LONGNAME " Linux Driver");
    753MODULE_LICENSE("GPL");
    754MODULE_FIRMWARE(INITCODEFILE);
    755MODULE_FIRMWARE(PERMCODEFILE);
    756
    757module_param_hw_array(io, long, ioport, NULL, 0444);
    758MODULE_PARM_DESC(io, "IO port #");
    759module_param_hw_array(irq, int, irq, NULL, 0444);
    760module_param_hw_array(mem, long, iomem, NULL, 0444);
    761module_param_array(write_ndelay, int, NULL, 0444);
    762module_param(calibrate_signal, int, 0444);
    763#ifndef MSND_CLASSIC
    764module_param_array(digital, int, NULL, 0444);
    765module_param_hw_array(cfg, long, ioport, NULL, 0444);
    766module_param_array(reset, int, NULL, 0444);
    767module_param_hw_array(mpu_io, long, ioport, NULL, 0444);
    768module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
    769module_param_hw_array(ide_io0, long, ioport, NULL, 0444);
    770module_param_hw_array(ide_io1, long, ioport, NULL, 0444);
    771module_param_hw_array(ide_irq, int, irq, NULL, 0444);
    772module_param_hw_array(joystick_io, long, ioport, NULL, 0444);
    773#endif
    774
    775
    776static int snd_msnd_isa_match(struct device *pdev, unsigned int i)
    777{
    778	if (io[i] == SNDRV_AUTO_PORT)
    779		return 0;
    780
    781	if (irq[i] == SNDRV_AUTO_PORT || mem[i] == SNDRV_AUTO_PORT) {
    782		printk(KERN_WARNING LOGNAME ": io, irq and mem must be set\n");
    783		return 0;
    784	}
    785
    786#ifdef MSND_CLASSIC
    787	if (!(io[i] == 0x290 ||
    788	      io[i] == 0x260 ||
    789	      io[i] == 0x250 ||
    790	      io[i] == 0x240 ||
    791	      io[i] == 0x230 ||
    792	      io[i] == 0x220 ||
    793	      io[i] == 0x210 ||
    794	      io[i] == 0x3e0)) {
    795		printk(KERN_ERR LOGNAME ": \"io\" - DSP I/O base must be set "
    796			" to 0x210, 0x220, 0x230, 0x240, 0x250, 0x260, 0x290, "
    797			"or 0x3E0\n");
    798		return 0;
    799	}
    800#else
    801	if (io[i] < 0x100 || io[i] > 0x3e0 || (io[i] % 0x10) != 0) {
    802		printk(KERN_ERR LOGNAME
    803			": \"io\" - DSP I/O base must within the range 0x100 "
    804			"to 0x3E0 and must be evenly divisible by 0x10\n");
    805		return 0;
    806	}
    807#endif /* MSND_CLASSIC */
    808
    809	if (!(irq[i] == 5 ||
    810	      irq[i] == 7 ||
    811	      irq[i] == 9 ||
    812	      irq[i] == 10 ||
    813	      irq[i] == 11 ||
    814	      irq[i] == 12)) {
    815		printk(KERN_ERR LOGNAME
    816			": \"irq\" - must be set to 5, 7, 9, 10, 11 or 12\n");
    817		return 0;
    818	}
    819
    820	if (!(mem[i] == 0xb0000 ||
    821	      mem[i] == 0xc8000 ||
    822	      mem[i] == 0xd0000 ||
    823	      mem[i] == 0xd8000 ||
    824	      mem[i] == 0xe0000 ||
    825	      mem[i] == 0xe8000)) {
    826		printk(KERN_ERR LOGNAME ": \"mem\" - must be set to "
    827		       "0xb0000, 0xc8000, 0xd0000, 0xd8000, 0xe0000 or "
    828		       "0xe8000\n");
    829		return 0;
    830	}
    831
    832#ifndef MSND_CLASSIC
    833	if (cfg[i] == SNDRV_AUTO_PORT) {
    834		printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
    835	} else if (cfg[i] != 0x250 && cfg[i] != 0x260 && cfg[i] != 0x270) {
    836		printk(KERN_INFO LOGNAME
    837			": Config port must be 0x250, 0x260 or 0x270 "
    838			"(or unspecified for PnP mode)\n");
    839		return 0;
    840	}
    841#endif /* MSND_CLASSIC */
    842
    843	return 1;
    844}
    845
    846static int snd_msnd_isa_probe(struct device *pdev, unsigned int idx)
    847{
    848	int err;
    849	struct snd_card *card;
    850	struct snd_msnd *chip;
    851
    852	if (has_isapnp(idx)
    853#ifndef MSND_CLASSIC
    854	    || cfg[idx] == SNDRV_AUTO_PORT
    855#endif
    856	    ) {
    857		printk(KERN_INFO LOGNAME ": Assuming PnP mode\n");
    858		return -ENODEV;
    859	}
    860
    861	err = snd_devm_card_new(pdev, index[idx], id[idx], THIS_MODULE,
    862				sizeof(struct snd_msnd), &card);
    863	if (err < 0)
    864		return err;
    865
    866	chip = card->private_data;
    867	chip->card = card;
    868
    869#ifdef MSND_CLASSIC
    870	switch (irq[idx]) {
    871	case 5:
    872		chip->irqid = HPIRQ_5; break;
    873	case 7:
    874		chip->irqid = HPIRQ_7; break;
    875	case 9:
    876		chip->irqid = HPIRQ_9; break;
    877	case 10:
    878		chip->irqid = HPIRQ_10; break;
    879	case 11:
    880		chip->irqid = HPIRQ_11; break;
    881	case 12:
    882		chip->irqid = HPIRQ_12; break;
    883	}
    884
    885	switch (mem[idx]) {
    886	case 0xb0000:
    887		chip->memid = HPMEM_B000; break;
    888	case 0xc8000:
    889		chip->memid = HPMEM_C800; break;
    890	case 0xd0000:
    891		chip->memid = HPMEM_D000; break;
    892	case 0xd8000:
    893		chip->memid = HPMEM_D800; break;
    894	case 0xe0000:
    895		chip->memid = HPMEM_E000; break;
    896	case 0xe8000:
    897		chip->memid = HPMEM_E800; break;
    898	}
    899#else
    900	printk(KERN_INFO LOGNAME ": Non-PnP mode: configuring at port 0x%lx\n",
    901			cfg[idx]);
    902
    903	if (!devm_request_region(card->dev, cfg[idx], 2,
    904				 "Pinnacle/Fiji Config")) {
    905		printk(KERN_ERR LOGNAME ": Config port 0x%lx conflict\n",
    906			   cfg[idx]);
    907		return -EIO;
    908	}
    909	if (reset[idx])
    910		if (snd_msnd_pinnacle_cfg_reset(cfg[idx]))
    911			return -EIO;
    912
    913	/* DSP */
    914	err = snd_msnd_write_cfg_logical(cfg[idx], 0,
    915					 io[idx], 0,
    916					 irq[idx], mem[idx]);
    917
    918	if (err)
    919		return err;
    920
    921	/* The following are Pinnacle specific */
    922
    923	/* MPU */
    924	if (mpu_io[idx] != SNDRV_AUTO_PORT
    925	    && mpu_irq[idx] != SNDRV_AUTO_IRQ) {
    926		printk(KERN_INFO LOGNAME
    927		       ": Configuring MPU to I/O 0x%lx IRQ %d\n",
    928		       mpu_io[idx], mpu_irq[idx]);
    929		err = snd_msnd_write_cfg_logical(cfg[idx], 1,
    930						 mpu_io[idx], 0,
    931						 mpu_irq[idx], 0);
    932
    933		if (err)
    934			return err;
    935	}
    936
    937	/* IDE */
    938	if (ide_io0[idx] != SNDRV_AUTO_PORT
    939	    && ide_io1[idx] != SNDRV_AUTO_PORT
    940	    && ide_irq[idx] != SNDRV_AUTO_IRQ) {
    941		printk(KERN_INFO LOGNAME
    942		       ": Configuring IDE to I/O 0x%lx, 0x%lx IRQ %d\n",
    943		       ide_io0[idx], ide_io1[idx], ide_irq[idx]);
    944		err = snd_msnd_write_cfg_logical(cfg[idx], 2,
    945						 ide_io0[idx], ide_io1[idx],
    946						 ide_irq[idx], 0);
    947
    948		if (err)
    949			return err;
    950	}
    951
    952	/* Joystick */
    953	if (joystick_io[idx] != SNDRV_AUTO_PORT) {
    954		printk(KERN_INFO LOGNAME
    955		       ": Configuring joystick to I/O 0x%lx\n",
    956		       joystick_io[idx]);
    957		err = snd_msnd_write_cfg_logical(cfg[idx], 3,
    958						 joystick_io[idx], 0,
    959						 0, 0);
    960
    961		if (err)
    962			return err;
    963	}
    964
    965#endif /* MSND_CLASSIC */
    966
    967	set_default_audio_parameters(chip);
    968#ifdef MSND_CLASSIC
    969	chip->type = msndClassic;
    970#else
    971	chip->type = msndPinnacle;
    972#endif
    973	chip->io = io[idx];
    974	chip->irq = irq[idx];
    975	chip->base = mem[idx];
    976
    977	chip->calibrate_signal = calibrate_signal ? 1 : 0;
    978	chip->recsrc = 0;
    979	chip->dspq_data_buff = DSPQ_DATA_BUFF;
    980	chip->dspq_buff_size = DSPQ_BUFF_SIZE;
    981	if (write_ndelay[idx])
    982		clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
    983	else
    984		set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
    985#ifndef MSND_CLASSIC
    986	if (digital[idx])
    987		set_bit(F_HAVEDIGITAL, &chip->flags);
    988#endif
    989	spin_lock_init(&chip->lock);
    990	err = snd_msnd_probe(card);
    991	if (err < 0) {
    992		printk(KERN_ERR LOGNAME ": Probe failed\n");
    993		return err;
    994	}
    995
    996	err = snd_msnd_attach(card);
    997	if (err < 0) {
    998		printk(KERN_ERR LOGNAME ": Attach failed\n");
    999		return err;
   1000	}
   1001	dev_set_drvdata(pdev, card);
   1002
   1003	return 0;
   1004}
   1005
   1006static struct isa_driver snd_msnd_driver = {
   1007	.match		= snd_msnd_isa_match,
   1008	.probe		= snd_msnd_isa_probe,
   1009	/* FIXME: suspend, resume */
   1010	.driver		= {
   1011		.name	= DEV_NAME
   1012	},
   1013};
   1014
   1015#ifdef CONFIG_PNP
   1016static int snd_msnd_pnp_detect(struct pnp_card_link *pcard,
   1017			       const struct pnp_card_device_id *pid)
   1018{
   1019	static int idx;
   1020	struct pnp_dev *pnp_dev;
   1021	struct pnp_dev *mpu_dev;
   1022	struct snd_card *card;
   1023	struct snd_msnd *chip;
   1024	int ret;
   1025
   1026	for ( ; idx < SNDRV_CARDS; idx++) {
   1027		if (has_isapnp(idx))
   1028			break;
   1029	}
   1030	if (idx >= SNDRV_CARDS)
   1031		return -ENODEV;
   1032
   1033	/*
   1034	 * Check that we still have room for another sound card ...
   1035	 */
   1036	pnp_dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
   1037	if (!pnp_dev)
   1038		return -ENODEV;
   1039
   1040	mpu_dev = pnp_request_card_device(pcard, pid->devs[1].id, NULL);
   1041	if (!mpu_dev)
   1042		return -ENODEV;
   1043
   1044	if (!pnp_is_active(pnp_dev) && pnp_activate_dev(pnp_dev) < 0) {
   1045		printk(KERN_INFO "msnd_pinnacle: device is inactive\n");
   1046		return -EBUSY;
   1047	}
   1048
   1049	if (!pnp_is_active(mpu_dev) && pnp_activate_dev(mpu_dev) < 0) {
   1050		printk(KERN_INFO "msnd_pinnacle: MPU device is inactive\n");
   1051		return -EBUSY;
   1052	}
   1053
   1054	/*
   1055	 * Create a new ALSA sound card entry, in anticipation
   1056	 * of detecting our hardware ...
   1057	 */
   1058	ret = snd_devm_card_new(&pcard->card->dev,
   1059				index[idx], id[idx], THIS_MODULE,
   1060				sizeof(struct snd_msnd), &card);
   1061	if (ret < 0)
   1062		return ret;
   1063
   1064	chip = card->private_data;
   1065	chip->card = card;
   1066
   1067	/*
   1068	 * Read the correct parameters off the ISA PnP bus ...
   1069	 */
   1070	io[idx] = pnp_port_start(pnp_dev, 0);
   1071	irq[idx] = pnp_irq(pnp_dev, 0);
   1072	mem[idx] = pnp_mem_start(pnp_dev, 0);
   1073	mpu_io[idx] = pnp_port_start(mpu_dev, 0);
   1074	mpu_irq[idx] = pnp_irq(mpu_dev, 0);
   1075
   1076	set_default_audio_parameters(chip);
   1077#ifdef MSND_CLASSIC
   1078	chip->type = msndClassic;
   1079#else
   1080	chip->type = msndPinnacle;
   1081#endif
   1082	chip->io = io[idx];
   1083	chip->irq = irq[idx];
   1084	chip->base = mem[idx];
   1085
   1086	chip->calibrate_signal = calibrate_signal ? 1 : 0;
   1087	chip->recsrc = 0;
   1088	chip->dspq_data_buff = DSPQ_DATA_BUFF;
   1089	chip->dspq_buff_size = DSPQ_BUFF_SIZE;
   1090	if (write_ndelay[idx])
   1091		clear_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
   1092	else
   1093		set_bit(F_DISABLE_WRITE_NDELAY, &chip->flags);
   1094#ifndef MSND_CLASSIC
   1095	if (digital[idx])
   1096		set_bit(F_HAVEDIGITAL, &chip->flags);
   1097#endif
   1098	spin_lock_init(&chip->lock);
   1099	ret = snd_msnd_probe(card);
   1100	if (ret < 0) {
   1101		printk(KERN_ERR LOGNAME ": Probe failed\n");
   1102		return ret;
   1103	}
   1104
   1105	ret = snd_msnd_attach(card);
   1106	if (ret < 0) {
   1107		printk(KERN_ERR LOGNAME ": Attach failed\n");
   1108		return ret;
   1109	}
   1110
   1111	pnp_set_card_drvdata(pcard, card);
   1112	++idx;
   1113	return 0;
   1114}
   1115
   1116static int isa_registered;
   1117static int pnp_registered;
   1118
   1119static const struct pnp_card_device_id msnd_pnpids[] = {
   1120	/* Pinnacle PnP */
   1121	{ .id = "BVJ0440", .devs = { { "TBS0000" }, { "TBS0001" } } },
   1122	{ .id = "" }	/* end */
   1123};
   1124
   1125MODULE_DEVICE_TABLE(pnp_card, msnd_pnpids);
   1126
   1127static struct pnp_card_driver msnd_pnpc_driver = {
   1128	.flags = PNP_DRIVER_RES_DO_NOT_CHANGE,
   1129	.name = "msnd_pinnacle",
   1130	.id_table = msnd_pnpids,
   1131	.probe = snd_msnd_pnp_detect,
   1132};
   1133#endif /* CONFIG_PNP */
   1134
   1135static int __init snd_msnd_init(void)
   1136{
   1137	int err;
   1138
   1139	err = isa_register_driver(&snd_msnd_driver, SNDRV_CARDS);
   1140#ifdef CONFIG_PNP
   1141	if (!err)
   1142		isa_registered = 1;
   1143
   1144	err = pnp_register_card_driver(&msnd_pnpc_driver);
   1145	if (!err)
   1146		pnp_registered = 1;
   1147
   1148	if (isa_registered)
   1149		err = 0;
   1150#endif
   1151	return err;
   1152}
   1153
   1154static void __exit snd_msnd_exit(void)
   1155{
   1156#ifdef CONFIG_PNP
   1157	if (pnp_registered)
   1158		pnp_unregister_card_driver(&msnd_pnpc_driver);
   1159	if (isa_registered)
   1160#endif
   1161		isa_unregister_driver(&snd_msnd_driver);
   1162}
   1163
   1164module_init(snd_msnd_init);
   1165module_exit(snd_msnd_exit);
   1166