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

opti92x-ad1848.c (29689B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3    card-opti92x-ad1848.c - driver for OPTi 82c92x based soundcards.
      4    Copyright (C) 1998-2000 by Massimo Piccioni <dafastidio@libero.it>
      5
      6    Part of this code was developed at the Italian Ministry of Air Defence,
      7    Sixth Division (oh, che pace ...), Rome.
      8
      9    Thanks to Maria Grazia Pollarini, Salvatore Vassallo.
     10
     11*/
     12
     13
     14#include <linux/init.h>
     15#include <linux/err.h>
     16#include <linux/isa.h>
     17#include <linux/delay.h>
     18#include <linux/pnp.h>
     19#include <linux/module.h>
     20#include <linux/io.h>
     21#include <asm/dma.h>
     22#include <sound/core.h>
     23#include <sound/tlv.h>
     24#include <sound/wss.h>
     25#include <sound/mpu401.h>
     26#include <sound/opl3.h>
     27#ifndef OPTi93X
     28#include <sound/opl4.h>
     29#endif
     30#define SNDRV_LEGACY_FIND_FREE_IOPORT
     31#define SNDRV_LEGACY_FIND_FREE_IRQ
     32#define SNDRV_LEGACY_FIND_FREE_DMA
     33#include <sound/initval.h>
     34
     35MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
     36MODULE_LICENSE("GPL");
     37#ifdef OPTi93X
     38MODULE_DESCRIPTION("OPTi93X");
     39#else	/* OPTi93X */
     40#ifdef CS4231
     41MODULE_DESCRIPTION("OPTi92X - CS4231");
     42#else	/* CS4231 */
     43MODULE_DESCRIPTION("OPTi92X - AD1848");
     44#endif	/* CS4231 */
     45#endif	/* OPTi93X */
     46
     47static int index = SNDRV_DEFAULT_IDX1;	/* Index 0-MAX */
     48static char *id = SNDRV_DEFAULT_STR1;		/* ID for this card */
     49//static bool enable = SNDRV_DEFAULT_ENABLE1;	/* Enable this card */
     50#ifdef CONFIG_PNP
     51static bool isapnp = true;			/* Enable ISA PnP detection */
     52#endif
     53static long port = SNDRV_DEFAULT_PORT1; 	/* 0x530,0xe80,0xf40,0x604 */
     54static long mpu_port = SNDRV_DEFAULT_PORT1;	/* 0x300,0x310,0x320,0x330 */
     55static long fm_port = SNDRV_DEFAULT_PORT1;	/* 0x388 */
     56static int irq = SNDRV_DEFAULT_IRQ1;		/* 5,7,9,10,11 */
     57static int mpu_irq = SNDRV_DEFAULT_IRQ1;	/* 5,7,9,10 */
     58static int dma1 = SNDRV_DEFAULT_DMA1;		/* 0,1,3 */
     59#if defined(CS4231) || defined(OPTi93X)
     60static int dma2 = SNDRV_DEFAULT_DMA1;		/* 0,1,3 */
     61#endif	/* CS4231 || OPTi93X */
     62
     63module_param(index, int, 0444);
     64MODULE_PARM_DESC(index, "Index value for opti9xx based soundcard.");
     65module_param(id, charp, 0444);
     66MODULE_PARM_DESC(id, "ID string for opti9xx based soundcard.");
     67//module_param(enable, bool, 0444);
     68//MODULE_PARM_DESC(enable, "Enable opti9xx soundcard.");
     69#ifdef CONFIG_PNP
     70module_param(isapnp, bool, 0444);
     71MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard.");
     72#endif
     73module_param_hw(port, long, ioport, 0444);
     74MODULE_PARM_DESC(port, "WSS port # for opti9xx driver.");
     75module_param_hw(mpu_port, long, ioport, 0444);
     76MODULE_PARM_DESC(mpu_port, "MPU-401 port # for opti9xx driver.");
     77module_param_hw(fm_port, long, ioport, 0444);
     78MODULE_PARM_DESC(fm_port, "FM port # for opti9xx driver.");
     79module_param_hw(irq, int, irq, 0444);
     80MODULE_PARM_DESC(irq, "WSS irq # for opti9xx driver.");
     81module_param_hw(mpu_irq, int, irq, 0444);
     82MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for opti9xx driver.");
     83module_param_hw(dma1, int, dma, 0444);
     84MODULE_PARM_DESC(dma1, "1st dma # for opti9xx driver.");
     85#if defined(CS4231) || defined(OPTi93X)
     86module_param_hw(dma2, int, dma, 0444);
     87MODULE_PARM_DESC(dma2, "2nd dma # for opti9xx driver.");
     88#endif	/* CS4231 || OPTi93X */
     89
     90#define OPTi9XX_HW_82C928	1
     91#define OPTi9XX_HW_82C929	2
     92#define OPTi9XX_HW_82C924	3
     93#define OPTi9XX_HW_82C925	4
     94#define OPTi9XX_HW_82C930	5
     95#define OPTi9XX_HW_82C931	6
     96#define OPTi9XX_HW_82C933	7
     97#define OPTi9XX_HW_LAST		OPTi9XX_HW_82C933
     98
     99#define OPTi9XX_MC_REG(n)	n
    100
    101#ifdef OPTi93X
    102
    103#define OPTi93X_STATUS			0x02
    104#define OPTi93X_PORT(chip, r)		((chip)->port + OPTi93X_##r)
    105
    106#define OPTi93X_IRQ_PLAYBACK		0x04
    107#define OPTi93X_IRQ_CAPTURE		0x08
    108
    109#endif /* OPTi93X */
    110
    111struct snd_opti9xx {
    112	unsigned short hardware;
    113	unsigned char password;
    114	char name[7];
    115
    116	unsigned long mc_base;
    117	struct resource *res_mc_base;
    118	unsigned long mc_base_size;
    119#ifdef OPTi93X
    120	unsigned long mc_indir_index;
    121	struct resource *res_mc_indir;
    122#endif	/* OPTi93X */
    123	struct snd_wss *codec;
    124	unsigned long pwd_reg;
    125
    126	spinlock_t lock;
    127
    128	long wss_base;
    129	int irq;
    130};
    131
    132static int snd_opti9xx_pnp_is_probed;
    133
    134#ifdef CONFIG_PNP
    135
    136static const struct pnp_card_device_id snd_opti9xx_pnpids[] = {
    137#ifndef OPTi93X
    138	/* OPTi 82C924 */
    139	{ .id = "OPT0924",
    140	  .devs = { { "OPT0000" }, { "OPT0002" }, { "OPT0005" } },
    141	  .driver_data = 0x0924 },
    142	/* OPTi 82C925 */
    143	{ .id = "OPT0925",
    144	  .devs = { { "OPT9250" }, { "OPT0002" }, { "OPT0005" } },
    145	  .driver_data = 0x0925 },
    146#else
    147	/* OPTi 82C931/3 */
    148	{ .id = "OPT0931", .devs = { { "OPT9310" }, { "OPT0002" } },
    149	  .driver_data = 0x0931 },
    150#endif	/* OPTi93X */
    151	{ .id = "" }
    152};
    153
    154MODULE_DEVICE_TABLE(pnp_card, snd_opti9xx_pnpids);
    155
    156#endif	/* CONFIG_PNP */
    157
    158#define DEV_NAME KBUILD_MODNAME
    159
    160static const char * const snd_opti9xx_names[] = {
    161	"unknown",
    162	"82C928",	"82C929",
    163	"82C924",	"82C925",
    164	"82C930",	"82C931",	"82C933"
    165};
    166
    167static int snd_opti9xx_init(struct snd_opti9xx *chip,
    168			    unsigned short hardware)
    169{
    170	static const int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
    171
    172	chip->hardware = hardware;
    173	strcpy(chip->name, snd_opti9xx_names[hardware]);
    174
    175	spin_lock_init(&chip->lock);
    176
    177	chip->irq = -1;
    178
    179#ifndef OPTi93X
    180#ifdef CONFIG_PNP
    181	if (isapnp && chip->mc_base)
    182		/* PnP resource gives the least 10 bits */
    183		chip->mc_base |= 0xc00;
    184	else
    185#endif	/* CONFIG_PNP */
    186	{
    187		chip->mc_base = 0xf8c;
    188		chip->mc_base_size = opti9xx_mc_size[hardware];
    189	}
    190#else
    191		chip->mc_base_size = opti9xx_mc_size[hardware];
    192#endif
    193
    194	switch (hardware) {
    195#ifndef OPTi93X
    196	case OPTi9XX_HW_82C928:
    197	case OPTi9XX_HW_82C929:
    198		chip->password = (hardware == OPTi9XX_HW_82C928) ? 0xe2 : 0xe3;
    199		chip->pwd_reg = 3;
    200		break;
    201
    202	case OPTi9XX_HW_82C924:
    203	case OPTi9XX_HW_82C925:
    204		chip->password = 0xe5;
    205		chip->pwd_reg = 3;
    206		break;
    207#else	/* OPTi93X */
    208
    209	case OPTi9XX_HW_82C930:
    210	case OPTi9XX_HW_82C931:
    211	case OPTi9XX_HW_82C933:
    212		chip->mc_base = (hardware == OPTi9XX_HW_82C930) ? 0xf8f : 0xf8d;
    213		if (!chip->mc_indir_index)
    214			chip->mc_indir_index = 0xe0e;
    215		chip->password = 0xe4;
    216		chip->pwd_reg = 0;
    217		break;
    218#endif	/* OPTi93X */
    219
    220	default:
    221		snd_printk(KERN_ERR "chip %d not supported\n", hardware);
    222		return -ENODEV;
    223	}
    224	return 0;
    225}
    226
    227static unsigned char snd_opti9xx_read(struct snd_opti9xx *chip,
    228				      unsigned char reg)
    229{
    230	unsigned long flags;
    231	unsigned char retval = 0xff;
    232
    233	spin_lock_irqsave(&chip->lock, flags);
    234	outb(chip->password, chip->mc_base + chip->pwd_reg);
    235
    236	switch (chip->hardware) {
    237#ifndef OPTi93X
    238	case OPTi9XX_HW_82C924:
    239	case OPTi9XX_HW_82C925:
    240		if (reg > 7) {
    241			outb(reg, chip->mc_base + 8);
    242			outb(chip->password, chip->mc_base + chip->pwd_reg);
    243			retval = inb(chip->mc_base + 9);
    244			break;
    245		}
    246		fallthrough;
    247
    248	case OPTi9XX_HW_82C928:
    249	case OPTi9XX_HW_82C929:
    250		retval = inb(chip->mc_base + reg);
    251		break;
    252#else	/* OPTi93X */
    253
    254	case OPTi9XX_HW_82C930:
    255	case OPTi9XX_HW_82C931:
    256	case OPTi9XX_HW_82C933:
    257		outb(reg, chip->mc_indir_index);
    258		outb(chip->password, chip->mc_base + chip->pwd_reg);
    259		retval = inb(chip->mc_indir_index + 1);
    260		break;
    261#endif	/* OPTi93X */
    262
    263	default:
    264		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
    265	}
    266
    267	spin_unlock_irqrestore(&chip->lock, flags);
    268	return retval;
    269}
    270
    271static void snd_opti9xx_write(struct snd_opti9xx *chip, unsigned char reg,
    272			      unsigned char value)
    273{
    274	unsigned long flags;
    275
    276	spin_lock_irqsave(&chip->lock, flags);
    277	outb(chip->password, chip->mc_base + chip->pwd_reg);
    278
    279	switch (chip->hardware) {
    280#ifndef OPTi93X
    281	case OPTi9XX_HW_82C924:
    282	case OPTi9XX_HW_82C925:
    283		if (reg > 7) {
    284			outb(reg, chip->mc_base + 8);
    285			outb(chip->password, chip->mc_base + chip->pwd_reg);
    286			outb(value, chip->mc_base + 9);
    287			break;
    288		}
    289		fallthrough;
    290
    291	case OPTi9XX_HW_82C928:
    292	case OPTi9XX_HW_82C929:
    293		outb(value, chip->mc_base + reg);
    294		break;
    295#else	/* OPTi93X */
    296
    297	case OPTi9XX_HW_82C930:
    298	case OPTi9XX_HW_82C931:
    299	case OPTi9XX_HW_82C933:
    300		outb(reg, chip->mc_indir_index);
    301		outb(chip->password, chip->mc_base + chip->pwd_reg);
    302		outb(value, chip->mc_indir_index + 1);
    303		break;
    304#endif	/* OPTi93X */
    305
    306	default:
    307		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
    308	}
    309
    310	spin_unlock_irqrestore(&chip->lock, flags);
    311}
    312
    313
    314static inline void snd_opti9xx_write_mask(struct snd_opti9xx *chip,
    315		unsigned char reg, unsigned char value, unsigned char mask)
    316{
    317	unsigned char oldval = snd_opti9xx_read(chip, reg);
    318
    319	snd_opti9xx_write(chip, reg, (oldval & ~mask) | (value & mask));
    320}
    321
    322static int snd_opti9xx_configure(struct snd_opti9xx *chip,
    323					   long port,
    324					   int irq, int dma1, int dma2,
    325					   long mpu_port, int mpu_irq)
    326{
    327	unsigned char wss_base_bits;
    328	unsigned char irq_bits;
    329	unsigned char dma_bits;
    330	unsigned char mpu_port_bits = 0;
    331	unsigned char mpu_irq_bits;
    332
    333	switch (chip->hardware) {
    334#ifndef OPTi93X
    335	case OPTi9XX_HW_82C924:
    336		/* opti 929 mode (?), OPL3 clock output, audio enable */
    337		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0xf0, 0xfc);
    338		/* enable wave audio */
    339		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
    340		fallthrough;
    341
    342	case OPTi9XX_HW_82C925:
    343		/* enable WSS mode */
    344		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
    345		/* OPL3 FM synthesis */
    346		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
    347		/* disable Sound Blaster IRQ and DMA */
    348		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
    349#ifdef CS4231
    350		/* cs4231/4248 fix enabled */
    351		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
    352#else
    353		/* cs4231/4248 fix disabled */
    354		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
    355#endif	/* CS4231 */
    356		break;
    357
    358	case OPTi9XX_HW_82C928:
    359	case OPTi9XX_HW_82C929:
    360		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
    361		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2), 0x00, 0x20);
    362		/*
    363		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0xa2, 0xae);
    364		*/
    365		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
    366#ifdef CS4231
    367		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
    368#else
    369		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x00, 0x02);
    370#endif	/* CS4231 */
    371		break;
    372
    373#else	/* OPTi93X */
    374	case OPTi9XX_HW_82C931:
    375		/* disable 3D sound (set GPIO1 as output, low) */
    376		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(20), 0x04, 0x0c);
    377		fallthrough;
    378
    379	case OPTi9XX_HW_82C933:
    380		/*
    381		 * The BTC 1817DW has QS1000 wavetable which is connected
    382		 * to the serial digital input of the OPTI931.
    383		 */
    384		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(21), 0x82, 0xff);
    385		/* 
    386		 * This bit sets OPTI931 to automaticaly select FM
    387		 * or digital input signal.
    388		 */
    389		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(26), 0x01, 0x01);
    390		fallthrough;
    391
    392	case OPTi9XX_HW_82C930:
    393		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x03);
    394		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(3), 0x00, 0xff);
    395		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(4), 0x10 |
    396			(chip->hardware == OPTi9XX_HW_82C930 ? 0x00 : 0x04),
    397			0x34);
    398		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(5), 0x20, 0xbf);
    399		break;
    400#endif	/* OPTi93X */
    401
    402	default:
    403		snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
    404		return -EINVAL;
    405	}
    406
    407	/* PnP resource says it decodes only 10 bits of address */
    408	switch (port & 0x3ff) {
    409	case 0x130:
    410		chip->wss_base = 0x530;
    411		wss_base_bits = 0x00;
    412		break;
    413	case 0x204:
    414		chip->wss_base = 0x604;
    415		wss_base_bits = 0x03;
    416		break;
    417	case 0x280:
    418		chip->wss_base = 0xe80;
    419		wss_base_bits = 0x01;
    420		break;
    421	case 0x340:
    422		chip->wss_base = 0xf40;
    423		wss_base_bits = 0x02;
    424		break;
    425	default:
    426		snd_printk(KERN_WARNING "WSS port 0x%lx not valid\n", port);
    427		goto __skip_base;
    428	}
    429	snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
    430
    431__skip_base:
    432	switch (irq) {
    433//#ifdef OPTi93X
    434	case 5:
    435		irq_bits = 0x05;
    436		break;
    437//#endif	/* OPTi93X */
    438	case 7:
    439		irq_bits = 0x01;
    440		break;
    441	case 9:
    442		irq_bits = 0x02;
    443		break;
    444	case 10:
    445		irq_bits = 0x03;
    446		break;
    447	case 11:
    448		irq_bits = 0x04;
    449		break;
    450	default:
    451		snd_printk(KERN_WARNING "WSS irq # %d not valid\n", irq);
    452		goto __skip_resources;
    453	}
    454
    455	switch (dma1) {
    456	case 0:
    457		dma_bits = 0x01;
    458		break;
    459	case 1:
    460		dma_bits = 0x02;
    461		break;
    462	case 3:
    463		dma_bits = 0x03;
    464		break;
    465	default:
    466		snd_printk(KERN_WARNING "WSS dma1 # %d not valid\n", dma1);
    467		goto __skip_resources;
    468	}
    469
    470#if defined(CS4231) || defined(OPTi93X)
    471	if (dma1 == dma2) {
    472		snd_printk(KERN_ERR "don't want to share dmas\n");
    473		return -EBUSY;
    474	}
    475
    476	switch (dma2) {
    477	case 0:
    478	case 1:
    479		break;
    480	default:
    481		snd_printk(KERN_WARNING "WSS dma2 # %d not valid\n", dma2);
    482		goto __skip_resources;
    483	}
    484	dma_bits |= 0x04;
    485#endif	/* CS4231 || OPTi93X */
    486
    487#ifndef OPTi93X
    488	 outb(irq_bits << 3 | dma_bits, chip->wss_base);
    489#else /* OPTi93X */
    490	snd_opti9xx_write(chip, OPTi9XX_MC_REG(3), (irq_bits << 3 | dma_bits));
    491#endif /* OPTi93X */
    492
    493__skip_resources:
    494	if (chip->hardware > OPTi9XX_HW_82C928) {
    495		switch (mpu_port) {
    496		case 0:
    497		case -1:
    498			break;
    499		case 0x300:
    500			mpu_port_bits = 0x03;
    501			break;
    502		case 0x310:
    503			mpu_port_bits = 0x02;
    504			break;
    505		case 0x320:
    506			mpu_port_bits = 0x01;
    507			break;
    508		case 0x330:
    509			mpu_port_bits = 0x00;
    510			break;
    511		default:
    512			snd_printk(KERN_WARNING
    513				   "MPU-401 port 0x%lx not valid\n", mpu_port);
    514			goto __skip_mpu;
    515		}
    516
    517		switch (mpu_irq) {
    518		case 5:
    519			mpu_irq_bits = 0x02;
    520			break;
    521		case 7:
    522			mpu_irq_bits = 0x03;
    523			break;
    524		case 9:
    525			mpu_irq_bits = 0x00;
    526			break;
    527		case 10:
    528			mpu_irq_bits = 0x01;
    529			break;
    530		default:
    531			snd_printk(KERN_WARNING "MPU-401 irq # %d not valid\n",
    532				mpu_irq);
    533			goto __skip_mpu;
    534		}
    535
    536		snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(6),
    537			(mpu_port <= 0) ? 0x00 :
    538				0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
    539			0xf8);
    540	}
    541__skip_mpu:
    542
    543	return 0;
    544}
    545
    546#ifdef OPTi93X
    547
    548static const DECLARE_TLV_DB_SCALE(db_scale_5bit_3db_step, -9300, 300, 0);
    549static const DECLARE_TLV_DB_SCALE(db_scale_5bit, -4650, 150, 0);
    550static const DECLARE_TLV_DB_SCALE(db_scale_4bit_12db_max, -3300, 300, 0);
    551
    552static const struct snd_kcontrol_new snd_opti93x_controls[] = {
    553WSS_DOUBLE("Master Playback Switch", 0,
    554		OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 7, 7, 1, 1),
    555WSS_DOUBLE_TLV("Master Playback Volume", 0,
    556		OPTi93X_OUT_LEFT, OPTi93X_OUT_RIGHT, 1, 1, 31, 1,
    557		db_scale_5bit_3db_step),
    558WSS_DOUBLE_TLV("PCM Playback Volume", 0,
    559		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 31, 1,
    560		db_scale_5bit),
    561WSS_DOUBLE_TLV("FM Playback Volume", 0,
    562		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 1, 1, 15, 1,
    563		db_scale_4bit_12db_max),
    564WSS_DOUBLE("Line Playback Switch", 0,
    565		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
    566WSS_DOUBLE_TLV("Line Playback Volume", 0,
    567		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 15, 1,
    568		db_scale_4bit_12db_max),
    569WSS_DOUBLE("Mic Playback Switch", 0,
    570		OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 7, 7, 1, 1),
    571WSS_DOUBLE_TLV("Mic Playback Volume", 0,
    572		OPTi93X_MIC_LEFT_INPUT, OPTi93X_MIC_RIGHT_INPUT, 1, 1, 15, 1,
    573		db_scale_4bit_12db_max),
    574WSS_DOUBLE_TLV("CD Playback Volume", 0,
    575		CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 1, 1, 15, 1,
    576		db_scale_4bit_12db_max),
    577WSS_DOUBLE("Aux Playback Switch", 0,
    578		OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 7, 7, 1, 1),
    579WSS_DOUBLE_TLV("Aux Playback Volume", 0,
    580		OPTi931_AUX_LEFT_INPUT, OPTi931_AUX_RIGHT_INPUT, 1, 1, 15, 1,
    581		db_scale_4bit_12db_max),
    582};
    583
    584static int snd_opti93x_mixer(struct snd_wss *chip)
    585{
    586	struct snd_card *card;
    587	unsigned int idx;
    588	struct snd_ctl_elem_id id1, id2;
    589	int err;
    590
    591	if (snd_BUG_ON(!chip || !chip->pcm))
    592		return -EINVAL;
    593
    594	card = chip->card;
    595
    596	strcpy(card->mixername, chip->pcm->name);
    597
    598	memset(&id1, 0, sizeof(id1));
    599	memset(&id2, 0, sizeof(id2));
    600	id1.iface = id2.iface = SNDRV_CTL_ELEM_IFACE_MIXER;
    601	/* reassign AUX0 switch to CD */
    602	strcpy(id1.name, "Aux Playback Switch");
    603	strcpy(id2.name, "CD Playback Switch");
    604	err = snd_ctl_rename_id(card, &id1, &id2);
    605	if (err < 0) {
    606		snd_printk(KERN_ERR "Cannot rename opti93x control\n");
    607		return err;
    608	}
    609	/* reassign AUX1 switch to FM */
    610	strcpy(id1.name, "Aux Playback Switch"); id1.index = 1;
    611	strcpy(id2.name, "FM Playback Switch");
    612	err = snd_ctl_rename_id(card, &id1, &id2);
    613	if (err < 0) {
    614		snd_printk(KERN_ERR "Cannot rename opti93x control\n");
    615		return err;
    616	}
    617	/* remove AUX1 volume */
    618	strcpy(id1.name, "Aux Playback Volume"); id1.index = 1;
    619	snd_ctl_remove_id(card, &id1);
    620
    621	/* Replace WSS volume controls with OPTi93x volume controls */
    622	id1.index = 0;
    623	for (idx = 0; idx < ARRAY_SIZE(snd_opti93x_controls); idx++) {
    624		strcpy(id1.name, snd_opti93x_controls[idx].name);
    625		snd_ctl_remove_id(card, &id1);
    626
    627		err = snd_ctl_add(card,
    628				snd_ctl_new1(&snd_opti93x_controls[idx], chip));
    629		if (err < 0)
    630			return err;
    631	}
    632	return 0;
    633}
    634
    635static irqreturn_t snd_opti93x_interrupt(int irq, void *dev_id)
    636{
    637	struct snd_opti9xx *chip = dev_id;
    638	struct snd_wss *codec = chip->codec;
    639	unsigned char status;
    640
    641	if (!codec)
    642		return IRQ_HANDLED;
    643
    644	status = snd_opti9xx_read(chip, OPTi9XX_MC_REG(11));
    645	if ((status & OPTi93X_IRQ_PLAYBACK) && codec->playback_substream)
    646		snd_pcm_period_elapsed(codec->playback_substream);
    647	if ((status & OPTi93X_IRQ_CAPTURE) && codec->capture_substream) {
    648		snd_wss_overrange(codec);
    649		snd_pcm_period_elapsed(codec->capture_substream);
    650	}
    651	outb(0x00, OPTi93X_PORT(codec, STATUS));
    652	return IRQ_HANDLED;
    653}
    654
    655#endif /* OPTi93X */
    656
    657static int snd_opti9xx_read_check(struct snd_card *card,
    658				  struct snd_opti9xx *chip)
    659{
    660	unsigned char value;
    661#ifdef OPTi93X
    662	unsigned long flags;
    663#endif
    664
    665	chip->res_mc_base =
    666		devm_request_region(card->dev, chip->mc_base,
    667				    chip->mc_base_size, "OPTi9xx MC");
    668	if (!chip->res_mc_base)
    669		return -EBUSY;
    670#ifndef OPTi93X
    671	value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(1));
    672	if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1)))
    673		if (value == snd_opti9xx_read(chip, OPTi9XX_MC_REG(1)))
    674			return 0;
    675#else	/* OPTi93X */
    676	chip->res_mc_indir =
    677		devm_request_region(card->dev, chip->mc_indir_index, 2,
    678				    "OPTi93x MC");
    679	if (!chip->res_mc_indir)
    680		return -EBUSY;
    681
    682	spin_lock_irqsave(&chip->lock, flags);
    683	outb(chip->password, chip->mc_base + chip->pwd_reg);
    684	outb(((chip->mc_indir_index & 0x1f0) >> 4), chip->mc_base);
    685	spin_unlock_irqrestore(&chip->lock, flags);
    686
    687	value = snd_opti9xx_read(chip, OPTi9XX_MC_REG(7));
    688	snd_opti9xx_write(chip, OPTi9XX_MC_REG(7), 0xff - value);
    689	if (snd_opti9xx_read(chip, OPTi9XX_MC_REG(7)) == 0xff - value)
    690		return 0;
    691
    692	devm_release_resource(card->dev, chip->res_mc_indir);
    693	chip->res_mc_indir = NULL;
    694#endif	/* OPTi93X */
    695	devm_release_resource(card->dev, chip->res_mc_base);
    696	chip->res_mc_base = NULL;
    697
    698	return -ENODEV;
    699}
    700
    701static int snd_card_opti9xx_detect(struct snd_card *card,
    702				   struct snd_opti9xx *chip)
    703{
    704	int i, err;
    705
    706#ifndef OPTi93X
    707	for (i = OPTi9XX_HW_82C928; i < OPTi9XX_HW_82C930; i++) {
    708#else
    709	for (i = OPTi9XX_HW_82C931; i >= OPTi9XX_HW_82C930; i--) {
    710#endif
    711		err = snd_opti9xx_init(chip, i);
    712		if (err < 0)
    713			return err;
    714
    715		err = snd_opti9xx_read_check(card, chip);
    716		if (err == 0)
    717			return 1;
    718#ifdef OPTi93X
    719		chip->mc_indir_index = 0;
    720#endif
    721	}
    722	return -ENODEV;
    723}
    724
    725#ifdef CONFIG_PNP
    726static int snd_card_opti9xx_pnp(struct snd_opti9xx *chip,
    727				struct pnp_card_link *card,
    728				const struct pnp_card_device_id *pid)
    729{
    730	struct pnp_dev *pdev;
    731	int err;
    732	struct pnp_dev *devmpu;
    733#ifndef OPTi93X
    734	struct pnp_dev *devmc;
    735#endif
    736
    737	pdev = pnp_request_card_device(card, pid->devs[0].id, NULL);
    738	if (pdev == NULL)
    739		return -EBUSY;
    740
    741	err = pnp_activate_dev(pdev);
    742	if (err < 0) {
    743		snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n", err);
    744		return err;
    745	}
    746
    747#ifdef OPTi93X
    748	port = pnp_port_start(pdev, 0) - 4;
    749	fm_port = pnp_port_start(pdev, 1) + 8;
    750	/* adjust mc_indir_index - some cards report it at 0xe?d,
    751	   other at 0xe?c but it really is always at 0xe?e */
    752	chip->mc_indir_index = (pnp_port_start(pdev, 3) & ~0xf) | 0xe;
    753#else
    754	devmc = pnp_request_card_device(card, pid->devs[2].id, NULL);
    755	if (devmc == NULL)
    756		return -EBUSY;
    757
    758	err = pnp_activate_dev(devmc);
    759	if (err < 0) {
    760		snd_printk(KERN_ERR "MC pnp configure failure: %d\n", err);
    761		return err;
    762	}
    763
    764	port = pnp_port_start(pdev, 1);
    765	fm_port = pnp_port_start(pdev, 2) + 8;
    766	/*
    767	 * The MC(0) is never accessed and card does not
    768	 * include it in the PnP resource range. OPTI93x include it.
    769	 */
    770	chip->mc_base = pnp_port_start(devmc, 0) - 1;
    771	chip->mc_base_size = pnp_port_len(devmc, 0) + 1;
    772#endif	/* OPTi93X */
    773	irq = pnp_irq(pdev, 0);
    774	dma1 = pnp_dma(pdev, 0);
    775#if defined(CS4231) || defined(OPTi93X)
    776	dma2 = pnp_dma(pdev, 1);
    777#endif	/* CS4231 || OPTi93X */
    778
    779	devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
    780
    781	if (devmpu && mpu_port > 0) {
    782		err = pnp_activate_dev(devmpu);
    783		if (err < 0) {
    784			snd_printk(KERN_ERR "MPU401 pnp configure failure\n");
    785			mpu_port = -1;
    786		} else {
    787			mpu_port = pnp_port_start(devmpu, 0);
    788			mpu_irq = pnp_irq(devmpu, 0);
    789		}
    790	}
    791	return pid->driver_data;
    792}
    793#endif	/* CONFIG_PNP */
    794
    795static int snd_opti9xx_probe(struct snd_card *card)
    796{
    797	static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
    798	int error;
    799	int xdma2;
    800	struct snd_opti9xx *chip = card->private_data;
    801	struct snd_wss *codec;
    802	struct snd_rawmidi *rmidi;
    803	struct snd_hwdep *synth;
    804
    805#if defined(CS4231) || defined(OPTi93X)
    806	xdma2 = dma2;
    807#else
    808	xdma2 = -1;
    809#endif
    810
    811	if (port == SNDRV_AUTO_PORT) {
    812		port = snd_legacy_find_free_ioport(possible_ports, 4);
    813		if (port < 0) {
    814			snd_printk(KERN_ERR "unable to find a free WSS port\n");
    815			return -EBUSY;
    816		}
    817	}
    818	error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
    819				      mpu_port, mpu_irq);
    820	if (error)
    821		return error;
    822
    823	error = snd_wss_create(card, chip->wss_base + 4, -1, irq, dma1, xdma2,
    824#ifdef OPTi93X
    825			       WSS_HW_OPTI93X, WSS_HWSHARE_IRQ,
    826#else
    827			       WSS_HW_DETECT, 0,
    828#endif
    829			       &codec);
    830	if (error < 0)
    831		return error;
    832	chip->codec = codec;
    833	error = snd_wss_pcm(codec, 0);
    834	if (error < 0)
    835		return error;
    836	error = snd_wss_mixer(codec);
    837	if (error < 0)
    838		return error;
    839#ifdef OPTi93X
    840	error = snd_opti93x_mixer(codec);
    841	if (error < 0)
    842		return error;
    843#endif
    844#ifdef CS4231
    845	error = snd_wss_timer(codec, 0);
    846	if (error < 0)
    847		return error;
    848#endif
    849#ifdef OPTi93X
    850	error = devm_request_irq(card->dev, irq, snd_opti93x_interrupt,
    851				 0, DEV_NAME" - WSS", chip);
    852	if (error < 0) {
    853		snd_printk(KERN_ERR "opti9xx: can't grab IRQ %d\n", irq);
    854		return error;
    855	}
    856#endif
    857	chip->irq = irq;
    858	card->sync_irq = chip->irq;
    859	strcpy(card->driver, chip->name);
    860	sprintf(card->shortname, "OPTi %s", card->driver);
    861#if defined(CS4231) || defined(OPTi93X)
    862	snprintf(card->longname, sizeof(card->longname),
    863		 "%s, %s at 0x%lx, irq %d, dma %d&%d",
    864		 card->shortname, codec->pcm->name,
    865		 chip->wss_base + 4, irq, dma1, xdma2);
    866#else
    867	snprintf(card->longname, sizeof(card->longname),
    868		 "%s, %s at 0x%lx, irq %d, dma %d",
    869		 card->shortname, codec->pcm->name, chip->wss_base + 4, irq,
    870		 dma1);
    871#endif	/* CS4231 || OPTi93X */
    872
    873	if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT)
    874		rmidi = NULL;
    875	else {
    876		error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
    877				mpu_port, 0, mpu_irq, &rmidi);
    878		if (error)
    879			snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n",
    880				   mpu_port);
    881	}
    882
    883	if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) {
    884		struct snd_opl3 *opl3 = NULL;
    885#ifndef OPTi93X
    886		if (chip->hardware == OPTi9XX_HW_82C928 ||
    887		    chip->hardware == OPTi9XX_HW_82C929 ||
    888		    chip->hardware == OPTi9XX_HW_82C924) {
    889			struct snd_opl4 *opl4;
    890			/* assume we have an OPL4 */
    891			snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
    892					       0x20, 0x20);
    893			if (snd_opl4_create(card, fm_port, fm_port - 8,
    894					    2, &opl3, &opl4) < 0) {
    895				/* no luck, use OPL3 instead */
    896				snd_opti9xx_write_mask(chip, OPTi9XX_MC_REG(2),
    897						       0x00, 0x20);
    898			}
    899		}
    900#endif	/* !OPTi93X */
    901		if (!opl3 && snd_opl3_create(card, fm_port, fm_port + 2,
    902					     OPL3_HW_AUTO, 0, &opl3) < 0) {
    903			snd_printk(KERN_WARNING "no OPL device at 0x%lx-0x%lx\n",
    904				   fm_port, fm_port + 4 - 1);
    905		}
    906		if (opl3) {
    907			error = snd_opl3_hwdep_new(opl3, 0, 1, &synth);
    908			if (error < 0)
    909				return error;
    910		}
    911	}
    912
    913	return snd_card_register(card);
    914}
    915
    916static int snd_opti9xx_card_new(struct device *pdev, struct snd_card **cardp)
    917{
    918	struct snd_card *card;
    919	int err;
    920
    921	err = snd_devm_card_new(pdev, index, id, THIS_MODULE,
    922				sizeof(struct snd_opti9xx), &card);
    923	if (err < 0)
    924		return err;
    925	*cardp = card;
    926	return 0;
    927}
    928
    929static int snd_opti9xx_isa_match(struct device *devptr,
    930				 unsigned int dev)
    931{
    932#ifdef CONFIG_PNP
    933	if (snd_opti9xx_pnp_is_probed)
    934		return 0;
    935	if (isapnp)
    936		return 0;
    937#endif
    938	return 1;
    939}
    940
    941static int snd_opti9xx_isa_probe(struct device *devptr,
    942				 unsigned int dev)
    943{
    944	struct snd_card *card;
    945	int error;
    946	static const long possible_mpu_ports[] = {0x300, 0x310, 0x320, 0x330, -1};
    947#ifdef OPTi93X
    948	static const int possible_irqs[] = {5, 9, 10, 11, 7, -1};
    949#else
    950	static const int possible_irqs[] = {9, 10, 11, 7, -1};
    951#endif	/* OPTi93X */
    952	static const int possible_mpu_irqs[] = {5, 9, 10, 7, -1};
    953	static const int possible_dma1s[] = {3, 1, 0, -1};
    954#if defined(CS4231) || defined(OPTi93X)
    955	static const int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
    956#endif	/* CS4231 || OPTi93X */
    957
    958	if (mpu_port == SNDRV_AUTO_PORT) {
    959		mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2);
    960		if (mpu_port < 0) {
    961			snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
    962			return -EBUSY;
    963		}
    964	}
    965	if (irq == SNDRV_AUTO_IRQ) {
    966		irq = snd_legacy_find_free_irq(possible_irqs);
    967		if (irq < 0) {
    968			snd_printk(KERN_ERR "unable to find a free IRQ\n");
    969			return -EBUSY;
    970		}
    971	}
    972	if (mpu_irq == SNDRV_AUTO_IRQ) {
    973		mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs);
    974		if (mpu_irq < 0) {
    975			snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
    976			return -EBUSY;
    977		}
    978	}
    979	if (dma1 == SNDRV_AUTO_DMA) {
    980		dma1 = snd_legacy_find_free_dma(possible_dma1s);
    981		if (dma1 < 0) {
    982			snd_printk(KERN_ERR "unable to find a free DMA1\n");
    983			return -EBUSY;
    984		}
    985	}
    986#if defined(CS4231) || defined(OPTi93X)
    987	if (dma2 == SNDRV_AUTO_DMA) {
    988		dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]);
    989		if (dma2 < 0) {
    990			snd_printk(KERN_ERR "unable to find a free DMA2\n");
    991			return -EBUSY;
    992		}
    993	}
    994#endif
    995
    996	error = snd_opti9xx_card_new(devptr, &card);
    997	if (error < 0)
    998		return error;
    999
   1000	error = snd_card_opti9xx_detect(card, card->private_data);
   1001	if (error < 0)
   1002		return error;
   1003	error = snd_opti9xx_probe(card);
   1004	if (error < 0)
   1005		return error;
   1006	dev_set_drvdata(devptr, card);
   1007	return 0;
   1008}
   1009
   1010#ifdef CONFIG_PM
   1011static int snd_opti9xx_suspend(struct snd_card *card)
   1012{
   1013	struct snd_opti9xx *chip = card->private_data;
   1014
   1015	snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
   1016	chip->codec->suspend(chip->codec);
   1017	return 0;
   1018}
   1019
   1020static int snd_opti9xx_resume(struct snd_card *card)
   1021{
   1022	struct snd_opti9xx *chip = card->private_data;
   1023	int error, xdma2;
   1024#if defined(CS4231) || defined(OPTi93X)
   1025	xdma2 = dma2;
   1026#else
   1027	xdma2 = -1;
   1028#endif
   1029
   1030	error = snd_opti9xx_configure(chip, port, irq, dma1, xdma2,
   1031				      mpu_port, mpu_irq);
   1032	if (error)
   1033		return error;
   1034	chip->codec->resume(chip->codec);
   1035	snd_power_change_state(card, SNDRV_CTL_POWER_D0);
   1036	return 0;
   1037}
   1038
   1039static int snd_opti9xx_isa_suspend(struct device *dev, unsigned int n,
   1040				   pm_message_t state)
   1041{
   1042	return snd_opti9xx_suspend(dev_get_drvdata(dev));
   1043}
   1044
   1045static int snd_opti9xx_isa_resume(struct device *dev, unsigned int n)
   1046{
   1047	return snd_opti9xx_resume(dev_get_drvdata(dev));
   1048}
   1049#endif
   1050
   1051static struct isa_driver snd_opti9xx_driver = {
   1052	.match		= snd_opti9xx_isa_match,
   1053	.probe		= snd_opti9xx_isa_probe,
   1054#ifdef CONFIG_PM
   1055	.suspend	= snd_opti9xx_isa_suspend,
   1056	.resume		= snd_opti9xx_isa_resume,
   1057#endif
   1058	.driver		= {
   1059		.name	= DEV_NAME
   1060	},
   1061};
   1062
   1063#ifdef CONFIG_PNP
   1064static int snd_opti9xx_pnp_probe(struct pnp_card_link *pcard,
   1065				 const struct pnp_card_device_id *pid)
   1066{
   1067	struct snd_card *card;
   1068	int error, hw;
   1069	struct snd_opti9xx *chip;
   1070
   1071	if (snd_opti9xx_pnp_is_probed)
   1072		return -EBUSY;
   1073	if (! isapnp)
   1074		return -ENODEV;
   1075	error = snd_opti9xx_card_new(&pcard->card->dev, &card);
   1076	if (error < 0)
   1077		return error;
   1078	chip = card->private_data;
   1079
   1080	hw = snd_card_opti9xx_pnp(chip, pcard, pid);
   1081	switch (hw) {
   1082	case 0x0924:
   1083		hw = OPTi9XX_HW_82C924;
   1084		break;
   1085	case 0x0925:
   1086		hw = OPTi9XX_HW_82C925;
   1087		break;
   1088	case 0x0931:
   1089		hw = OPTi9XX_HW_82C931;
   1090		break;
   1091	default:
   1092		return -ENODEV;
   1093	}
   1094
   1095	error = snd_opti9xx_init(chip, hw);
   1096	if (error)
   1097		return error;
   1098	error = snd_opti9xx_read_check(card, chip);
   1099	if (error) {
   1100		snd_printk(KERN_ERR "OPTI chip not found\n");
   1101		return error;
   1102	}
   1103	error = snd_opti9xx_probe(card);
   1104	if (error < 0)
   1105		return error;
   1106	pnp_set_card_drvdata(pcard, card);
   1107	snd_opti9xx_pnp_is_probed = 1;
   1108	return 0;
   1109}
   1110
   1111static void snd_opti9xx_pnp_remove(struct pnp_card_link *pcard)
   1112{
   1113	snd_opti9xx_pnp_is_probed = 0;
   1114}
   1115
   1116#ifdef CONFIG_PM
   1117static int snd_opti9xx_pnp_suspend(struct pnp_card_link *pcard,
   1118				   pm_message_t state)
   1119{
   1120	return snd_opti9xx_suspend(pnp_get_card_drvdata(pcard));
   1121}
   1122
   1123static int snd_opti9xx_pnp_resume(struct pnp_card_link *pcard)
   1124{
   1125	return snd_opti9xx_resume(pnp_get_card_drvdata(pcard));
   1126}
   1127#endif
   1128
   1129static struct pnp_card_driver opti9xx_pnpc_driver = {
   1130	.flags		= PNP_DRIVER_RES_DISABLE,
   1131	.name		= DEV_NAME,
   1132	.id_table	= snd_opti9xx_pnpids,
   1133	.probe		= snd_opti9xx_pnp_probe,
   1134	.remove		= snd_opti9xx_pnp_remove,
   1135#ifdef CONFIG_PM
   1136	.suspend	= snd_opti9xx_pnp_suspend,
   1137	.resume		= snd_opti9xx_pnp_resume,
   1138#endif
   1139};
   1140#endif
   1141
   1142#ifdef OPTi93X
   1143#define CHIP_NAME	"82C93x"
   1144#else
   1145#define CHIP_NAME	"82C92x"
   1146#endif
   1147
   1148static int __init alsa_card_opti9xx_init(void)
   1149{
   1150#ifdef CONFIG_PNP
   1151	pnp_register_card_driver(&opti9xx_pnpc_driver);
   1152	if (snd_opti9xx_pnp_is_probed)
   1153		return 0;
   1154	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
   1155#endif
   1156	return isa_register_driver(&snd_opti9xx_driver, 1);
   1157}
   1158
   1159static void __exit alsa_card_opti9xx_exit(void)
   1160{
   1161	if (!snd_opti9xx_pnp_is_probed) {
   1162		isa_unregister_driver(&snd_opti9xx_driver);
   1163		return;
   1164	}
   1165#ifdef CONFIG_PNP
   1166	pnp_unregister_card_driver(&opti9xx_pnpc_driver);
   1167#endif
   1168}
   1169
   1170module_init(alsa_card_opti9xx_init)
   1171module_exit(alsa_card_opti9xx_exit)