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

wss_lib.c (63230B)


      1// SPDX-License-Identifier: GPL-2.0-or-later
      2/*
      3 *  Copyright (c) by Jaroslav Kysela <perex@perex.cz>
      4 *  Routines for control of CS4231(A)/CS4232/InterWave & compatible chips
      5 *
      6 *  Bugs:
      7 *     - sometimes record brokes playback with WSS portion of
      8 *       Yamaha OPL3-SA3 chip
      9 *     - CS4231 (GUS MAX) - still trouble with occasional noises
     10 *			  - broken initialization?
     11 */
     12
     13#include <linux/delay.h>
     14#include <linux/pm.h>
     15#include <linux/init.h>
     16#include <linux/interrupt.h>
     17#include <linux/slab.h>
     18#include <linux/ioport.h>
     19#include <linux/module.h>
     20#include <linux/io.h>
     21#include <sound/core.h>
     22#include <sound/wss.h>
     23#include <sound/pcm_params.h>
     24#include <sound/tlv.h>
     25
     26#include <asm/dma.h>
     27#include <asm/irq.h>
     28
     29MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
     30MODULE_DESCRIPTION("Routines for control of CS4231(A)/CS4232/InterWave & compatible chips");
     31MODULE_LICENSE("GPL");
     32
     33#if 0
     34#define SNDRV_DEBUG_MCE
     35#endif
     36
     37/*
     38 *  Some variables
     39 */
     40
     41static const unsigned char freq_bits[14] = {
     42	/* 5510 */	0x00 | CS4231_XTAL2,
     43	/* 6620 */	0x0E | CS4231_XTAL2,
     44	/* 8000 */	0x00 | CS4231_XTAL1,
     45	/* 9600 */	0x0E | CS4231_XTAL1,
     46	/* 11025 */	0x02 | CS4231_XTAL2,
     47	/* 16000 */	0x02 | CS4231_XTAL1,
     48	/* 18900 */	0x04 | CS4231_XTAL2,
     49	/* 22050 */	0x06 | CS4231_XTAL2,
     50	/* 27042 */	0x04 | CS4231_XTAL1,
     51	/* 32000 */	0x06 | CS4231_XTAL1,
     52	/* 33075 */	0x0C | CS4231_XTAL2,
     53	/* 37800 */	0x08 | CS4231_XTAL2,
     54	/* 44100 */	0x0A | CS4231_XTAL2,
     55	/* 48000 */	0x0C | CS4231_XTAL1
     56};
     57
     58static const unsigned int rates[14] = {
     59	5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
     60	27042, 32000, 33075, 37800, 44100, 48000
     61};
     62
     63static const struct snd_pcm_hw_constraint_list hw_constraints_rates = {
     64	.count = ARRAY_SIZE(rates),
     65	.list = rates,
     66	.mask = 0,
     67};
     68
     69static int snd_wss_xrate(struct snd_pcm_runtime *runtime)
     70{
     71	return snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
     72					  &hw_constraints_rates);
     73}
     74
     75static const unsigned char snd_wss_original_image[32] =
     76{
     77	0x00,			/* 00/00 - lic */
     78	0x00,			/* 01/01 - ric */
     79	0x9f,			/* 02/02 - la1ic */
     80	0x9f,			/* 03/03 - ra1ic */
     81	0x9f,			/* 04/04 - la2ic */
     82	0x9f,			/* 05/05 - ra2ic */
     83	0xbf,			/* 06/06 - loc */
     84	0xbf,			/* 07/07 - roc */
     85	0x20,			/* 08/08 - pdfr */
     86	CS4231_AUTOCALIB,	/* 09/09 - ic */
     87	0x00,			/* 0a/10 - pc */
     88	0x00,			/* 0b/11 - ti */
     89	CS4231_MODE2,		/* 0c/12 - mi */
     90	0xfc,			/* 0d/13 - lbc */
     91	0x00,			/* 0e/14 - pbru */
     92	0x00,			/* 0f/15 - pbrl */
     93	0x80,			/* 10/16 - afei */
     94	0x01,			/* 11/17 - afeii */
     95	0x9f,			/* 12/18 - llic */
     96	0x9f,			/* 13/19 - rlic */
     97	0x00,			/* 14/20 - tlb */
     98	0x00,			/* 15/21 - thb */
     99	0x00,			/* 16/22 - la3mic/reserved */
    100	0x00,			/* 17/23 - ra3mic/reserved */
    101	0x00,			/* 18/24 - afs */
    102	0x00,			/* 19/25 - lamoc/version */
    103	0xcf,			/* 1a/26 - mioc */
    104	0x00,			/* 1b/27 - ramoc/reserved */
    105	0x20,			/* 1c/28 - cdfr */
    106	0x00,			/* 1d/29 - res4 */
    107	0x00,			/* 1e/30 - cbru */
    108	0x00,			/* 1f/31 - cbrl */
    109};
    110
    111static const unsigned char snd_opti93x_original_image[32] =
    112{
    113	0x00,		/* 00/00 - l_mixout_outctrl */
    114	0x00,		/* 01/01 - r_mixout_outctrl */
    115	0x88,		/* 02/02 - l_cd_inctrl */
    116	0x88,		/* 03/03 - r_cd_inctrl */
    117	0x88,		/* 04/04 - l_a1/fm_inctrl */
    118	0x88,		/* 05/05 - r_a1/fm_inctrl */
    119	0x80,		/* 06/06 - l_dac_inctrl */
    120	0x80,		/* 07/07 - r_dac_inctrl */
    121	0x00,		/* 08/08 - ply_dataform_reg */
    122	0x00,		/* 09/09 - if_conf */
    123	0x00,		/* 0a/10 - pin_ctrl */
    124	0x00,		/* 0b/11 - err_init_reg */
    125	0x0a,		/* 0c/12 - id_reg */
    126	0x00,		/* 0d/13 - reserved */
    127	0x00,		/* 0e/14 - ply_upcount_reg */
    128	0x00,		/* 0f/15 - ply_lowcount_reg */
    129	0x88,		/* 10/16 - reserved/l_a1_inctrl */
    130	0x88,		/* 11/17 - reserved/r_a1_inctrl */
    131	0x88,		/* 12/18 - l_line_inctrl */
    132	0x88,		/* 13/19 - r_line_inctrl */
    133	0x88,		/* 14/20 - l_mic_inctrl */
    134	0x88,		/* 15/21 - r_mic_inctrl */
    135	0x80,		/* 16/22 - l_out_outctrl */
    136	0x80,		/* 17/23 - r_out_outctrl */
    137	0x00,		/* 18/24 - reserved */
    138	0x00,		/* 19/25 - reserved */
    139	0x00,		/* 1a/26 - reserved */
    140	0x00,		/* 1b/27 - reserved */
    141	0x00,		/* 1c/28 - cap_dataform_reg */
    142	0x00,		/* 1d/29 - reserved */
    143	0x00,		/* 1e/30 - cap_upcount_reg */
    144	0x00		/* 1f/31 - cap_lowcount_reg */
    145};
    146
    147/*
    148 *  Basic I/O functions
    149 */
    150
    151static inline void wss_outb(struct snd_wss *chip, u8 offset, u8 val)
    152{
    153	outb(val, chip->port + offset);
    154}
    155
    156static inline u8 wss_inb(struct snd_wss *chip, u8 offset)
    157{
    158	return inb(chip->port + offset);
    159}
    160
    161static void snd_wss_wait(struct snd_wss *chip)
    162{
    163	int timeout;
    164
    165	for (timeout = 250;
    166	     timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
    167	     timeout--)
    168		udelay(100);
    169}
    170
    171static void snd_wss_dout(struct snd_wss *chip, unsigned char reg,
    172			 unsigned char value)
    173{
    174	int timeout;
    175
    176	for (timeout = 250;
    177	     timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
    178	     timeout--)
    179		udelay(10);
    180	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
    181	wss_outb(chip, CS4231P(REG), value);
    182	mb();
    183}
    184
    185void snd_wss_out(struct snd_wss *chip, unsigned char reg, unsigned char value)
    186{
    187	snd_wss_wait(chip);
    188#ifdef CONFIG_SND_DEBUG
    189	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
    190		snd_printk(KERN_DEBUG "out: auto calibration time out "
    191			   "- reg = 0x%x, value = 0x%x\n", reg, value);
    192#endif
    193	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
    194	wss_outb(chip, CS4231P(REG), value);
    195	chip->image[reg] = value;
    196	mb();
    197	snd_printdd("codec out - reg 0x%x = 0x%x\n",
    198			chip->mce_bit | reg, value);
    199}
    200EXPORT_SYMBOL(snd_wss_out);
    201
    202unsigned char snd_wss_in(struct snd_wss *chip, unsigned char reg)
    203{
    204	snd_wss_wait(chip);
    205#ifdef CONFIG_SND_DEBUG
    206	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
    207		snd_printk(KERN_DEBUG "in: auto calibration time out "
    208			   "- reg = 0x%x\n", reg);
    209#endif
    210	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | reg);
    211	mb();
    212	return wss_inb(chip, CS4231P(REG));
    213}
    214EXPORT_SYMBOL(snd_wss_in);
    215
    216void snd_cs4236_ext_out(struct snd_wss *chip, unsigned char reg,
    217			unsigned char val)
    218{
    219	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
    220	wss_outb(chip, CS4231P(REG),
    221		 reg | (chip->image[CS4236_EXT_REG] & 0x01));
    222	wss_outb(chip, CS4231P(REG), val);
    223	chip->eimage[CS4236_REG(reg)] = val;
    224#if 0
    225	printk(KERN_DEBUG "ext out : reg = 0x%x, val = 0x%x\n", reg, val);
    226#endif
    227}
    228EXPORT_SYMBOL(snd_cs4236_ext_out);
    229
    230unsigned char snd_cs4236_ext_in(struct snd_wss *chip, unsigned char reg)
    231{
    232	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | 0x17);
    233	wss_outb(chip, CS4231P(REG),
    234		 reg | (chip->image[CS4236_EXT_REG] & 0x01));
    235#if 1
    236	return wss_inb(chip, CS4231P(REG));
    237#else
    238	{
    239		unsigned char res;
    240		res = wss_inb(chip, CS4231P(REG));
    241		printk(KERN_DEBUG "ext in : reg = 0x%x, val = 0x%x\n",
    242		       reg, res);
    243		return res;
    244	}
    245#endif
    246}
    247EXPORT_SYMBOL(snd_cs4236_ext_in);
    248
    249#if 0
    250
    251static void snd_wss_debug(struct snd_wss *chip)
    252{
    253	printk(KERN_DEBUG
    254		"CS4231 REGS:      INDEX = 0x%02x  "
    255		"                 STATUS = 0x%02x\n",
    256					wss_inb(chip, CS4231P(REGSEL)),
    257					wss_inb(chip, CS4231P(STATUS)));
    258	printk(KERN_DEBUG
    259		"  0x00: left input      = 0x%02x  "
    260		"  0x10: alt 1 (CFIG 2)  = 0x%02x\n",
    261					snd_wss_in(chip, 0x00),
    262					snd_wss_in(chip, 0x10));
    263	printk(KERN_DEBUG
    264		"  0x01: right input     = 0x%02x  "
    265		"  0x11: alt 2 (CFIG 3)  = 0x%02x\n",
    266					snd_wss_in(chip, 0x01),
    267					snd_wss_in(chip, 0x11));
    268	printk(KERN_DEBUG
    269		"  0x02: GF1 left input  = 0x%02x  "
    270		"  0x12: left line in    = 0x%02x\n",
    271					snd_wss_in(chip, 0x02),
    272					snd_wss_in(chip, 0x12));
    273	printk(KERN_DEBUG
    274		"  0x03: GF1 right input = 0x%02x  "
    275		"  0x13: right line in   = 0x%02x\n",
    276					snd_wss_in(chip, 0x03),
    277					snd_wss_in(chip, 0x13));
    278	printk(KERN_DEBUG
    279		"  0x04: CD left input   = 0x%02x  "
    280		"  0x14: timer low       = 0x%02x\n",
    281					snd_wss_in(chip, 0x04),
    282					snd_wss_in(chip, 0x14));
    283	printk(KERN_DEBUG
    284		"  0x05: CD right input  = 0x%02x  "
    285		"  0x15: timer high      = 0x%02x\n",
    286					snd_wss_in(chip, 0x05),
    287					snd_wss_in(chip, 0x15));
    288	printk(KERN_DEBUG
    289		"  0x06: left output     = 0x%02x  "
    290		"  0x16: left MIC (PnP)  = 0x%02x\n",
    291					snd_wss_in(chip, 0x06),
    292					snd_wss_in(chip, 0x16));
    293	printk(KERN_DEBUG
    294		"  0x07: right output    = 0x%02x  "
    295		"  0x17: right MIC (PnP) = 0x%02x\n",
    296					snd_wss_in(chip, 0x07),
    297					snd_wss_in(chip, 0x17));
    298	printk(KERN_DEBUG
    299		"  0x08: playback format = 0x%02x  "
    300		"  0x18: IRQ status      = 0x%02x\n",
    301					snd_wss_in(chip, 0x08),
    302					snd_wss_in(chip, 0x18));
    303	printk(KERN_DEBUG
    304		"  0x09: iface (CFIG 1)  = 0x%02x  "
    305		"  0x19: left line out   = 0x%02x\n",
    306					snd_wss_in(chip, 0x09),
    307					snd_wss_in(chip, 0x19));
    308	printk(KERN_DEBUG
    309		"  0x0a: pin control     = 0x%02x  "
    310		"  0x1a: mono control    = 0x%02x\n",
    311					snd_wss_in(chip, 0x0a),
    312					snd_wss_in(chip, 0x1a));
    313	printk(KERN_DEBUG
    314		"  0x0b: init & status   = 0x%02x  "
    315		"  0x1b: right line out  = 0x%02x\n",
    316					snd_wss_in(chip, 0x0b),
    317					snd_wss_in(chip, 0x1b));
    318	printk(KERN_DEBUG
    319		"  0x0c: revision & mode = 0x%02x  "
    320		"  0x1c: record format   = 0x%02x\n",
    321					snd_wss_in(chip, 0x0c),
    322					snd_wss_in(chip, 0x1c));
    323	printk(KERN_DEBUG
    324		"  0x0d: loopback        = 0x%02x  "
    325		"  0x1d: var freq (PnP)  = 0x%02x\n",
    326					snd_wss_in(chip, 0x0d),
    327					snd_wss_in(chip, 0x1d));
    328	printk(KERN_DEBUG
    329		"  0x0e: ply upr count   = 0x%02x  "
    330		"  0x1e: ply lwr count   = 0x%02x\n",
    331					snd_wss_in(chip, 0x0e),
    332					snd_wss_in(chip, 0x1e));
    333	printk(KERN_DEBUG
    334		"  0x0f: rec upr count   = 0x%02x  "
    335		"  0x1f: rec lwr count   = 0x%02x\n",
    336					snd_wss_in(chip, 0x0f),
    337					snd_wss_in(chip, 0x1f));
    338}
    339
    340#endif
    341
    342/*
    343 *  CS4231 detection / MCE routines
    344 */
    345
    346static void snd_wss_busy_wait(struct snd_wss *chip)
    347{
    348	int timeout;
    349
    350	/* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
    351	for (timeout = 5; timeout > 0; timeout--)
    352		wss_inb(chip, CS4231P(REGSEL));
    353	/* end of cleanup sequence */
    354	for (timeout = 25000;
    355	     timeout > 0 && (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT);
    356	     timeout--)
    357		udelay(10);
    358}
    359
    360void snd_wss_mce_up(struct snd_wss *chip)
    361{
    362	unsigned long flags;
    363	int timeout;
    364
    365	snd_wss_wait(chip);
    366#ifdef CONFIG_SND_DEBUG
    367	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
    368		snd_printk(KERN_DEBUG
    369			   "mce_up - auto calibration time out (0)\n");
    370#endif
    371	spin_lock_irqsave(&chip->reg_lock, flags);
    372	chip->mce_bit |= CS4231_MCE;
    373	timeout = wss_inb(chip, CS4231P(REGSEL));
    374	if (timeout == 0x80)
    375		snd_printk(KERN_DEBUG "mce_up [0x%lx]: "
    376			   "serious init problem - codec still busy\n",
    377			   chip->port);
    378	if (!(timeout & CS4231_MCE))
    379		wss_outb(chip, CS4231P(REGSEL),
    380			 chip->mce_bit | (timeout & 0x1f));
    381	spin_unlock_irqrestore(&chip->reg_lock, flags);
    382}
    383EXPORT_SYMBOL(snd_wss_mce_up);
    384
    385void snd_wss_mce_down(struct snd_wss *chip)
    386{
    387	unsigned long flags;
    388	unsigned long end_time;
    389	int timeout;
    390	int hw_mask = WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK | WSS_HW_AD1848;
    391
    392	snd_wss_busy_wait(chip);
    393
    394#ifdef CONFIG_SND_DEBUG
    395	if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
    396		snd_printk(KERN_DEBUG "mce_down [0x%lx] - "
    397			   "auto calibration time out (0)\n",
    398			   (long)CS4231P(REGSEL));
    399#endif
    400	spin_lock_irqsave(&chip->reg_lock, flags);
    401	chip->mce_bit &= ~CS4231_MCE;
    402	timeout = wss_inb(chip, CS4231P(REGSEL));
    403	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
    404	spin_unlock_irqrestore(&chip->reg_lock, flags);
    405	if (timeout == 0x80)
    406		snd_printk(KERN_DEBUG "mce_down [0x%lx]: "
    407			   "serious init problem - codec still busy\n",
    408			   chip->port);
    409	if ((timeout & CS4231_MCE) == 0 || !(chip->hardware & hw_mask))
    410		return;
    411
    412	/*
    413	 * Wait for (possible -- during init auto-calibration may not be set)
    414	 * calibration process to start. Needs up to 5 sample periods on AD1848
    415	 * which at the slowest possible rate of 5.5125 kHz means 907 us.
    416	 */
    417	msleep(1);
    418
    419	snd_printdd("(1) jiffies = %lu\n", jiffies);
    420
    421	/* check condition up to 250 ms */
    422	end_time = jiffies + msecs_to_jiffies(250);
    423	while (snd_wss_in(chip, CS4231_TEST_INIT) &
    424		CS4231_CALIB_IN_PROGRESS) {
    425
    426		if (time_after(jiffies, end_time)) {
    427			snd_printk(KERN_ERR "mce_down - "
    428					"auto calibration time out (2)\n");
    429			return;
    430		}
    431		msleep(1);
    432	}
    433
    434	snd_printdd("(2) jiffies = %lu\n", jiffies);
    435
    436	/* check condition up to 100 ms */
    437	end_time = jiffies + msecs_to_jiffies(100);
    438	while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
    439		if (time_after(jiffies, end_time)) {
    440			snd_printk(KERN_ERR "mce_down - auto calibration time out (3)\n");
    441			return;
    442		}
    443		msleep(1);
    444	}
    445
    446	snd_printdd("(3) jiffies = %lu\n", jiffies);
    447	snd_printd("mce_down - exit = 0x%x\n", wss_inb(chip, CS4231P(REGSEL)));
    448}
    449EXPORT_SYMBOL(snd_wss_mce_down);
    450
    451static unsigned int snd_wss_get_count(unsigned char format, unsigned int size)
    452{
    453	switch (format & 0xe0) {
    454	case CS4231_LINEAR_16:
    455	case CS4231_LINEAR_16_BIG:
    456		size >>= 1;
    457		break;
    458	case CS4231_ADPCM_16:
    459		return size >> 2;
    460	}
    461	if (format & CS4231_STEREO)
    462		size >>= 1;
    463	return size;
    464}
    465
    466static int snd_wss_trigger(struct snd_pcm_substream *substream,
    467			   int cmd)
    468{
    469	struct snd_wss *chip = snd_pcm_substream_chip(substream);
    470	int result = 0;
    471	unsigned int what;
    472	struct snd_pcm_substream *s;
    473	int do_start;
    474
    475	switch (cmd) {
    476	case SNDRV_PCM_TRIGGER_START:
    477	case SNDRV_PCM_TRIGGER_RESUME:
    478		do_start = 1; break;
    479	case SNDRV_PCM_TRIGGER_STOP:
    480	case SNDRV_PCM_TRIGGER_SUSPEND:
    481		do_start = 0; break;
    482	default:
    483		return -EINVAL;
    484	}
    485
    486	what = 0;
    487	snd_pcm_group_for_each_entry(s, substream) {
    488		if (s == chip->playback_substream) {
    489			what |= CS4231_PLAYBACK_ENABLE;
    490			snd_pcm_trigger_done(s, substream);
    491		} else if (s == chip->capture_substream) {
    492			what |= CS4231_RECORD_ENABLE;
    493			snd_pcm_trigger_done(s, substream);
    494		}
    495	}
    496	spin_lock(&chip->reg_lock);
    497	if (do_start) {
    498		chip->image[CS4231_IFACE_CTRL] |= what;
    499		if (chip->trigger)
    500			chip->trigger(chip, what, 1);
    501	} else {
    502		chip->image[CS4231_IFACE_CTRL] &= ~what;
    503		if (chip->trigger)
    504			chip->trigger(chip, what, 0);
    505	}
    506	snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
    507	spin_unlock(&chip->reg_lock);
    508#if 0
    509	snd_wss_debug(chip);
    510#endif
    511	return result;
    512}
    513
    514/*
    515 *  CODEC I/O
    516 */
    517
    518static unsigned char snd_wss_get_rate(unsigned int rate)
    519{
    520	int i;
    521
    522	for (i = 0; i < ARRAY_SIZE(rates); i++)
    523		if (rate == rates[i])
    524			return freq_bits[i];
    525	// snd_BUG();
    526	return freq_bits[ARRAY_SIZE(rates) - 1];
    527}
    528
    529static unsigned char snd_wss_get_format(struct snd_wss *chip,
    530					snd_pcm_format_t format,
    531					int channels)
    532{
    533	unsigned char rformat;
    534
    535	rformat = CS4231_LINEAR_8;
    536	switch (format) {
    537	case SNDRV_PCM_FORMAT_MU_LAW:	rformat = CS4231_ULAW_8; break;
    538	case SNDRV_PCM_FORMAT_A_LAW:	rformat = CS4231_ALAW_8; break;
    539	case SNDRV_PCM_FORMAT_S16_LE:	rformat = CS4231_LINEAR_16; break;
    540	case SNDRV_PCM_FORMAT_S16_BE:	rformat = CS4231_LINEAR_16_BIG; break;
    541	case SNDRV_PCM_FORMAT_IMA_ADPCM:	rformat = CS4231_ADPCM_16; break;
    542	}
    543	if (channels > 1)
    544		rformat |= CS4231_STEREO;
    545#if 0
    546	snd_printk(KERN_DEBUG "get_format: 0x%x (mode=0x%x)\n", format, mode);
    547#endif
    548	return rformat;
    549}
    550
    551static void snd_wss_calibrate_mute(struct snd_wss *chip, int mute)
    552{
    553	unsigned long flags;
    554
    555	mute = mute ? 0x80 : 0;
    556	spin_lock_irqsave(&chip->reg_lock, flags);
    557	if (chip->calibrate_mute == mute) {
    558		spin_unlock_irqrestore(&chip->reg_lock, flags);
    559		return;
    560	}
    561	if (!mute) {
    562		snd_wss_dout(chip, CS4231_LEFT_INPUT,
    563			     chip->image[CS4231_LEFT_INPUT]);
    564		snd_wss_dout(chip, CS4231_RIGHT_INPUT,
    565			     chip->image[CS4231_RIGHT_INPUT]);
    566		snd_wss_dout(chip, CS4231_LOOPBACK,
    567			     chip->image[CS4231_LOOPBACK]);
    568	} else {
    569		snd_wss_dout(chip, CS4231_LEFT_INPUT,
    570			     0);
    571		snd_wss_dout(chip, CS4231_RIGHT_INPUT,
    572			     0);
    573		snd_wss_dout(chip, CS4231_LOOPBACK,
    574			     0xfd);
    575	}
    576
    577	snd_wss_dout(chip, CS4231_AUX1_LEFT_INPUT,
    578		     mute | chip->image[CS4231_AUX1_LEFT_INPUT]);
    579	snd_wss_dout(chip, CS4231_AUX1_RIGHT_INPUT,
    580		     mute | chip->image[CS4231_AUX1_RIGHT_INPUT]);
    581	snd_wss_dout(chip, CS4231_AUX2_LEFT_INPUT,
    582		     mute | chip->image[CS4231_AUX2_LEFT_INPUT]);
    583	snd_wss_dout(chip, CS4231_AUX2_RIGHT_INPUT,
    584		     mute | chip->image[CS4231_AUX2_RIGHT_INPUT]);
    585	snd_wss_dout(chip, CS4231_LEFT_OUTPUT,
    586		     mute | chip->image[CS4231_LEFT_OUTPUT]);
    587	snd_wss_dout(chip, CS4231_RIGHT_OUTPUT,
    588		     mute | chip->image[CS4231_RIGHT_OUTPUT]);
    589	if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
    590		snd_wss_dout(chip, CS4231_LEFT_LINE_IN,
    591			     mute | chip->image[CS4231_LEFT_LINE_IN]);
    592		snd_wss_dout(chip, CS4231_RIGHT_LINE_IN,
    593			     mute | chip->image[CS4231_RIGHT_LINE_IN]);
    594		snd_wss_dout(chip, CS4231_MONO_CTRL,
    595			     mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
    596	}
    597	if (chip->hardware == WSS_HW_INTERWAVE) {
    598		snd_wss_dout(chip, CS4231_LEFT_MIC_INPUT,
    599			     mute | chip->image[CS4231_LEFT_MIC_INPUT]);
    600		snd_wss_dout(chip, CS4231_RIGHT_MIC_INPUT,
    601			     mute | chip->image[CS4231_RIGHT_MIC_INPUT]);
    602		snd_wss_dout(chip, CS4231_LINE_LEFT_OUTPUT,
    603			     mute | chip->image[CS4231_LINE_LEFT_OUTPUT]);
    604		snd_wss_dout(chip, CS4231_LINE_RIGHT_OUTPUT,
    605			     mute | chip->image[CS4231_LINE_RIGHT_OUTPUT]);
    606	}
    607	chip->calibrate_mute = mute;
    608	spin_unlock_irqrestore(&chip->reg_lock, flags);
    609}
    610
    611static void snd_wss_playback_format(struct snd_wss *chip,
    612				       struct snd_pcm_hw_params *params,
    613				       unsigned char pdfr)
    614{
    615	unsigned long flags;
    616	int full_calib = 1;
    617
    618	mutex_lock(&chip->mce_mutex);
    619	if (chip->hardware == WSS_HW_CS4231A ||
    620	    (chip->hardware & WSS_HW_CS4232_MASK)) {
    621		spin_lock_irqsave(&chip->reg_lock, flags);
    622		if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (pdfr & 0x0f)) {	/* rate is same? */
    623			snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    624				    chip->image[CS4231_ALT_FEATURE_1] | 0x10);
    625			chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
    626			snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
    627				    chip->image[CS4231_PLAYBK_FORMAT]);
    628			snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    629				    chip->image[CS4231_ALT_FEATURE_1] &= ~0x10);
    630			udelay(100); /* Fixes audible clicks at least on GUS MAX */
    631			full_calib = 0;
    632		}
    633		spin_unlock_irqrestore(&chip->reg_lock, flags);
    634	} else if (chip->hardware == WSS_HW_AD1845) {
    635		unsigned rate = params_rate(params);
    636
    637		/*
    638		 * Program the AD1845 correctly for the playback stream.
    639		 * Note that we do NOT need to toggle the MCE bit because
    640		 * the PLAYBACK_ENABLE bit of the Interface Configuration
    641		 * register is set.
    642		 *
    643		 * NOTE: We seem to need to write to the MSB before the LSB
    644		 *       to get the correct sample frequency.
    645		 */
    646		spin_lock_irqsave(&chip->reg_lock, flags);
    647		snd_wss_out(chip, CS4231_PLAYBK_FORMAT, (pdfr & 0xf0));
    648		snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
    649		snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
    650		full_calib = 0;
    651		spin_unlock_irqrestore(&chip->reg_lock, flags);
    652	}
    653	if (full_calib) {
    654		snd_wss_mce_up(chip);
    655		spin_lock_irqsave(&chip->reg_lock, flags);
    656		if (chip->hardware != WSS_HW_INTERWAVE && !chip->single_dma) {
    657			if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)
    658				pdfr = (pdfr & 0xf0) |
    659				       (chip->image[CS4231_REC_FORMAT] & 0x0f);
    660		} else {
    661			chip->image[CS4231_PLAYBK_FORMAT] = pdfr;
    662		}
    663		snd_wss_out(chip, CS4231_PLAYBK_FORMAT, pdfr);
    664		spin_unlock_irqrestore(&chip->reg_lock, flags);
    665		if (chip->hardware == WSS_HW_OPL3SA2)
    666			udelay(100);	/* this seems to help */
    667		snd_wss_mce_down(chip);
    668	}
    669	mutex_unlock(&chip->mce_mutex);
    670}
    671
    672static void snd_wss_capture_format(struct snd_wss *chip,
    673				   struct snd_pcm_hw_params *params,
    674				   unsigned char cdfr)
    675{
    676	unsigned long flags;
    677	int full_calib = 1;
    678
    679	mutex_lock(&chip->mce_mutex);
    680	if (chip->hardware == WSS_HW_CS4231A ||
    681	    (chip->hardware & WSS_HW_CS4232_MASK)) {
    682		spin_lock_irqsave(&chip->reg_lock, flags);
    683		if ((chip->image[CS4231_PLAYBK_FORMAT] & 0x0f) == (cdfr & 0x0f) ||	/* rate is same? */
    684		    (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
    685			snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    686				chip->image[CS4231_ALT_FEATURE_1] | 0x20);
    687			snd_wss_out(chip, CS4231_REC_FORMAT,
    688				chip->image[CS4231_REC_FORMAT] = cdfr);
    689			snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    690				chip->image[CS4231_ALT_FEATURE_1] &= ~0x20);
    691			full_calib = 0;
    692		}
    693		spin_unlock_irqrestore(&chip->reg_lock, flags);
    694	} else if (chip->hardware == WSS_HW_AD1845) {
    695		unsigned rate = params_rate(params);
    696
    697		/*
    698		 * Program the AD1845 correctly for the capture stream.
    699		 * Note that we do NOT need to toggle the MCE bit because
    700		 * the PLAYBACK_ENABLE bit of the Interface Configuration
    701		 * register is set.
    702		 *
    703		 * NOTE: We seem to need to write to the MSB before the LSB
    704		 *       to get the correct sample frequency.
    705		 */
    706		spin_lock_irqsave(&chip->reg_lock, flags);
    707		snd_wss_out(chip, CS4231_REC_FORMAT, (cdfr & 0xf0));
    708		snd_wss_out(chip, AD1845_UPR_FREQ_SEL, (rate >> 8) & 0xff);
    709		snd_wss_out(chip, AD1845_LWR_FREQ_SEL, rate & 0xff);
    710		full_calib = 0;
    711		spin_unlock_irqrestore(&chip->reg_lock, flags);
    712	}
    713	if (full_calib) {
    714		snd_wss_mce_up(chip);
    715		spin_lock_irqsave(&chip->reg_lock, flags);
    716		if (chip->hardware != WSS_HW_INTERWAVE &&
    717		    !(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
    718			if (chip->single_dma)
    719				snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
    720			else
    721				snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
    722				   (chip->image[CS4231_PLAYBK_FORMAT] & 0xf0) |
    723				   (cdfr & 0x0f));
    724			spin_unlock_irqrestore(&chip->reg_lock, flags);
    725			snd_wss_mce_down(chip);
    726			snd_wss_mce_up(chip);
    727			spin_lock_irqsave(&chip->reg_lock, flags);
    728		}
    729		if (chip->hardware & WSS_HW_AD1848_MASK)
    730			snd_wss_out(chip, CS4231_PLAYBK_FORMAT, cdfr);
    731		else
    732			snd_wss_out(chip, CS4231_REC_FORMAT, cdfr);
    733		spin_unlock_irqrestore(&chip->reg_lock, flags);
    734		snd_wss_mce_down(chip);
    735	}
    736	mutex_unlock(&chip->mce_mutex);
    737}
    738
    739/*
    740 *  Timer interface
    741 */
    742
    743static unsigned long snd_wss_timer_resolution(struct snd_timer *timer)
    744{
    745	struct snd_wss *chip = snd_timer_chip(timer);
    746	if (chip->hardware & WSS_HW_CS4236B_MASK)
    747		return 14467;
    748	else
    749		return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
    750}
    751
    752static int snd_wss_timer_start(struct snd_timer *timer)
    753{
    754	unsigned long flags;
    755	unsigned int ticks;
    756	struct snd_wss *chip = snd_timer_chip(timer);
    757	spin_lock_irqsave(&chip->reg_lock, flags);
    758	ticks = timer->sticks;
    759	if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
    760	    (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
    761	    (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
    762		chip->image[CS4231_TIMER_HIGH] = (unsigned char) (ticks >> 8);
    763		snd_wss_out(chip, CS4231_TIMER_HIGH,
    764			    chip->image[CS4231_TIMER_HIGH]);
    765		chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks;
    766		snd_wss_out(chip, CS4231_TIMER_LOW,
    767			    chip->image[CS4231_TIMER_LOW]);
    768		snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    769			    chip->image[CS4231_ALT_FEATURE_1] |
    770			    CS4231_TIMER_ENABLE);
    771	}
    772	spin_unlock_irqrestore(&chip->reg_lock, flags);
    773	return 0;
    774}
    775
    776static int snd_wss_timer_stop(struct snd_timer *timer)
    777{
    778	unsigned long flags;
    779	struct snd_wss *chip = snd_timer_chip(timer);
    780	spin_lock_irqsave(&chip->reg_lock, flags);
    781	chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE;
    782	snd_wss_out(chip, CS4231_ALT_FEATURE_1,
    783		    chip->image[CS4231_ALT_FEATURE_1]);
    784	spin_unlock_irqrestore(&chip->reg_lock, flags);
    785	return 0;
    786}
    787
    788static void snd_wss_init(struct snd_wss *chip)
    789{
    790	unsigned long flags;
    791
    792	snd_wss_calibrate_mute(chip, 1);
    793	snd_wss_mce_down(chip);
    794
    795#ifdef SNDRV_DEBUG_MCE
    796	snd_printk(KERN_DEBUG "init: (1)\n");
    797#endif
    798	snd_wss_mce_up(chip);
    799	spin_lock_irqsave(&chip->reg_lock, flags);
    800	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
    801					    CS4231_PLAYBACK_PIO |
    802					    CS4231_RECORD_ENABLE |
    803					    CS4231_RECORD_PIO |
    804					    CS4231_CALIB_MODE);
    805	chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
    806	snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
    807	spin_unlock_irqrestore(&chip->reg_lock, flags);
    808	snd_wss_mce_down(chip);
    809
    810#ifdef SNDRV_DEBUG_MCE
    811	snd_printk(KERN_DEBUG "init: (2)\n");
    812#endif
    813
    814	snd_wss_mce_up(chip);
    815	spin_lock_irqsave(&chip->reg_lock, flags);
    816	chip->image[CS4231_IFACE_CTRL] &= ~CS4231_AUTOCALIB;
    817	snd_wss_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
    818	snd_wss_out(chip,
    819		    CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
    820	spin_unlock_irqrestore(&chip->reg_lock, flags);
    821	snd_wss_mce_down(chip);
    822
    823#ifdef SNDRV_DEBUG_MCE
    824	snd_printk(KERN_DEBUG "init: (3) - afei = 0x%x\n",
    825		   chip->image[CS4231_ALT_FEATURE_1]);
    826#endif
    827
    828	spin_lock_irqsave(&chip->reg_lock, flags);
    829	snd_wss_out(chip, CS4231_ALT_FEATURE_2,
    830		    chip->image[CS4231_ALT_FEATURE_2]);
    831	spin_unlock_irqrestore(&chip->reg_lock, flags);
    832
    833	snd_wss_mce_up(chip);
    834	spin_lock_irqsave(&chip->reg_lock, flags);
    835	snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
    836		    chip->image[CS4231_PLAYBK_FORMAT]);
    837	spin_unlock_irqrestore(&chip->reg_lock, flags);
    838	snd_wss_mce_down(chip);
    839
    840#ifdef SNDRV_DEBUG_MCE
    841	snd_printk(KERN_DEBUG "init: (4)\n");
    842#endif
    843
    844	snd_wss_mce_up(chip);
    845	spin_lock_irqsave(&chip->reg_lock, flags);
    846	if (!(chip->hardware & WSS_HW_AD1848_MASK))
    847		snd_wss_out(chip, CS4231_REC_FORMAT,
    848			    chip->image[CS4231_REC_FORMAT]);
    849	spin_unlock_irqrestore(&chip->reg_lock, flags);
    850	snd_wss_mce_down(chip);
    851	snd_wss_calibrate_mute(chip, 0);
    852
    853#ifdef SNDRV_DEBUG_MCE
    854	snd_printk(KERN_DEBUG "init: (5)\n");
    855#endif
    856}
    857
    858static int snd_wss_open(struct snd_wss *chip, unsigned int mode)
    859{
    860	unsigned long flags;
    861
    862	mutex_lock(&chip->open_mutex);
    863	if ((chip->mode & mode) ||
    864	    ((chip->mode & WSS_MODE_OPEN) && chip->single_dma)) {
    865		mutex_unlock(&chip->open_mutex);
    866		return -EAGAIN;
    867	}
    868	if (chip->mode & WSS_MODE_OPEN) {
    869		chip->mode |= mode;
    870		mutex_unlock(&chip->open_mutex);
    871		return 0;
    872	}
    873	/* ok. now enable and ack CODEC IRQ */
    874	spin_lock_irqsave(&chip->reg_lock, flags);
    875	if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
    876		snd_wss_out(chip, CS4231_IRQ_STATUS,
    877			    CS4231_PLAYBACK_IRQ |
    878			    CS4231_RECORD_IRQ |
    879			    CS4231_TIMER_IRQ);
    880		snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
    881	}
    882	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    883	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    884	chip->image[CS4231_PIN_CTRL] |= CS4231_IRQ_ENABLE;
    885	snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
    886	if (!(chip->hardware & WSS_HW_AD1848_MASK)) {
    887		snd_wss_out(chip, CS4231_IRQ_STATUS,
    888			    CS4231_PLAYBACK_IRQ |
    889			    CS4231_RECORD_IRQ |
    890			    CS4231_TIMER_IRQ);
    891		snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
    892	}
    893	spin_unlock_irqrestore(&chip->reg_lock, flags);
    894
    895	chip->mode = mode;
    896	mutex_unlock(&chip->open_mutex);
    897	return 0;
    898}
    899
    900static void snd_wss_close(struct snd_wss *chip, unsigned int mode)
    901{
    902	unsigned long flags;
    903
    904	mutex_lock(&chip->open_mutex);
    905	chip->mode &= ~mode;
    906	if (chip->mode & WSS_MODE_OPEN) {
    907		mutex_unlock(&chip->open_mutex);
    908		return;
    909	}
    910	/* disable IRQ */
    911	spin_lock_irqsave(&chip->reg_lock, flags);
    912	if (!(chip->hardware & WSS_HW_AD1848_MASK))
    913		snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
    914	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    915	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    916	chip->image[CS4231_PIN_CTRL] &= ~CS4231_IRQ_ENABLE;
    917	snd_wss_out(chip, CS4231_PIN_CTRL, chip->image[CS4231_PIN_CTRL]);
    918
    919	/* now disable record & playback */
    920
    921	if (chip->image[CS4231_IFACE_CTRL] & (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
    922					       CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
    923		spin_unlock_irqrestore(&chip->reg_lock, flags);
    924		snd_wss_mce_up(chip);
    925		spin_lock_irqsave(&chip->reg_lock, flags);
    926		chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
    927						     CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
    928		snd_wss_out(chip, CS4231_IFACE_CTRL,
    929			    chip->image[CS4231_IFACE_CTRL]);
    930		spin_unlock_irqrestore(&chip->reg_lock, flags);
    931		snd_wss_mce_down(chip);
    932		spin_lock_irqsave(&chip->reg_lock, flags);
    933	}
    934
    935	/* clear IRQ again */
    936	if (!(chip->hardware & WSS_HW_AD1848_MASK))
    937		snd_wss_out(chip, CS4231_IRQ_STATUS, 0);
    938	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    939	wss_outb(chip, CS4231P(STATUS), 0);	/* clear IRQ */
    940	spin_unlock_irqrestore(&chip->reg_lock, flags);
    941
    942	chip->mode = 0;
    943	mutex_unlock(&chip->open_mutex);
    944}
    945
    946/*
    947 *  timer open/close
    948 */
    949
    950static int snd_wss_timer_open(struct snd_timer *timer)
    951{
    952	struct snd_wss *chip = snd_timer_chip(timer);
    953	snd_wss_open(chip, WSS_MODE_TIMER);
    954	return 0;
    955}
    956
    957static int snd_wss_timer_close(struct snd_timer *timer)
    958{
    959	struct snd_wss *chip = snd_timer_chip(timer);
    960	snd_wss_close(chip, WSS_MODE_TIMER);
    961	return 0;
    962}
    963
    964static const struct snd_timer_hardware snd_wss_timer_table =
    965{
    966	.flags =	SNDRV_TIMER_HW_AUTO,
    967	.resolution =	9945,
    968	.ticks =	65535,
    969	.open =		snd_wss_timer_open,
    970	.close =	snd_wss_timer_close,
    971	.c_resolution = snd_wss_timer_resolution,
    972	.start =	snd_wss_timer_start,
    973	.stop =		snd_wss_timer_stop,
    974};
    975
    976/*
    977 *  ok.. exported functions..
    978 */
    979
    980static int snd_wss_playback_hw_params(struct snd_pcm_substream *substream,
    981					 struct snd_pcm_hw_params *hw_params)
    982{
    983	struct snd_wss *chip = snd_pcm_substream_chip(substream);
    984	unsigned char new_pdfr;
    985
    986	new_pdfr = snd_wss_get_format(chip, params_format(hw_params),
    987				params_channels(hw_params)) |
    988				snd_wss_get_rate(params_rate(hw_params));
    989	chip->set_playback_format(chip, hw_params, new_pdfr);
    990	return 0;
    991}
    992
    993static int snd_wss_playback_prepare(struct snd_pcm_substream *substream)
    994{
    995	struct snd_wss *chip = snd_pcm_substream_chip(substream);
    996	struct snd_pcm_runtime *runtime = substream->runtime;
    997	unsigned long flags;
    998	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
    999	unsigned int count = snd_pcm_lib_period_bytes(substream);
   1000
   1001	spin_lock_irqsave(&chip->reg_lock, flags);
   1002	chip->p_dma_size = size;
   1003	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO);
   1004	snd_dma_program(chip->dma1, runtime->dma_addr, size, DMA_MODE_WRITE | DMA_AUTOINIT);
   1005	count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT], count) - 1;
   1006	snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
   1007	snd_wss_out(chip, CS4231_PLY_UPR_CNT, (unsigned char) (count >> 8));
   1008	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1009#if 0
   1010	snd_wss_debug(chip);
   1011#endif
   1012	return 0;
   1013}
   1014
   1015static int snd_wss_capture_hw_params(struct snd_pcm_substream *substream,
   1016					struct snd_pcm_hw_params *hw_params)
   1017{
   1018	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1019	unsigned char new_cdfr;
   1020
   1021	new_cdfr = snd_wss_get_format(chip, params_format(hw_params),
   1022			   params_channels(hw_params)) |
   1023			   snd_wss_get_rate(params_rate(hw_params));
   1024	chip->set_capture_format(chip, hw_params, new_cdfr);
   1025	return 0;
   1026}
   1027
   1028static int snd_wss_capture_prepare(struct snd_pcm_substream *substream)
   1029{
   1030	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1031	struct snd_pcm_runtime *runtime = substream->runtime;
   1032	unsigned long flags;
   1033	unsigned int size = snd_pcm_lib_buffer_bytes(substream);
   1034	unsigned int count = snd_pcm_lib_period_bytes(substream);
   1035
   1036	spin_lock_irqsave(&chip->reg_lock, flags);
   1037	chip->c_dma_size = size;
   1038	chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
   1039	snd_dma_program(chip->dma2, runtime->dma_addr, size, DMA_MODE_READ | DMA_AUTOINIT);
   1040	if (chip->hardware & WSS_HW_AD1848_MASK)
   1041		count = snd_wss_get_count(chip->image[CS4231_PLAYBK_FORMAT],
   1042					  count);
   1043	else
   1044		count = snd_wss_get_count(chip->image[CS4231_REC_FORMAT],
   1045					  count);
   1046	count--;
   1047	if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
   1048		snd_wss_out(chip, CS4231_PLY_LWR_CNT, (unsigned char) count);
   1049		snd_wss_out(chip, CS4231_PLY_UPR_CNT,
   1050			    (unsigned char) (count >> 8));
   1051	} else {
   1052		snd_wss_out(chip, CS4231_REC_LWR_CNT, (unsigned char) count);
   1053		snd_wss_out(chip, CS4231_REC_UPR_CNT,
   1054			    (unsigned char) (count >> 8));
   1055	}
   1056	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1057	return 0;
   1058}
   1059
   1060void snd_wss_overrange(struct snd_wss *chip)
   1061{
   1062	unsigned long flags;
   1063	unsigned char res;
   1064
   1065	spin_lock_irqsave(&chip->reg_lock, flags);
   1066	res = snd_wss_in(chip, CS4231_TEST_INIT);
   1067	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1068	if (res & (0x08 | 0x02))	/* detect overrange only above 0dB; may be user selectable? */
   1069		chip->capture_substream->runtime->overrange++;
   1070}
   1071EXPORT_SYMBOL(snd_wss_overrange);
   1072
   1073irqreturn_t snd_wss_interrupt(int irq, void *dev_id)
   1074{
   1075	struct snd_wss *chip = dev_id;
   1076	unsigned char status;
   1077
   1078	if (chip->hardware & WSS_HW_AD1848_MASK)
   1079		/* pretend it was the only possible irq for AD1848 */
   1080		status = CS4231_PLAYBACK_IRQ;
   1081	else
   1082		status = snd_wss_in(chip, CS4231_IRQ_STATUS);
   1083	if (status & CS4231_TIMER_IRQ) {
   1084		if (chip->timer)
   1085			snd_timer_interrupt(chip->timer, chip->timer->sticks);
   1086	}
   1087	if (chip->single_dma && chip->hardware != WSS_HW_INTERWAVE) {
   1088		if (status & CS4231_PLAYBACK_IRQ) {
   1089			if (chip->mode & WSS_MODE_PLAY) {
   1090				if (chip->playback_substream)
   1091					snd_pcm_period_elapsed(chip->playback_substream);
   1092			}
   1093			if (chip->mode & WSS_MODE_RECORD) {
   1094				if (chip->capture_substream) {
   1095					snd_wss_overrange(chip);
   1096					snd_pcm_period_elapsed(chip->capture_substream);
   1097				}
   1098			}
   1099		}
   1100	} else {
   1101		if (status & CS4231_PLAYBACK_IRQ) {
   1102			if (chip->playback_substream)
   1103				snd_pcm_period_elapsed(chip->playback_substream);
   1104		}
   1105		if (status & CS4231_RECORD_IRQ) {
   1106			if (chip->capture_substream) {
   1107				snd_wss_overrange(chip);
   1108				snd_pcm_period_elapsed(chip->capture_substream);
   1109			}
   1110		}
   1111	}
   1112
   1113	spin_lock(&chip->reg_lock);
   1114	status = ~CS4231_ALL_IRQS | ~status;
   1115	if (chip->hardware & WSS_HW_AD1848_MASK)
   1116		wss_outb(chip, CS4231P(STATUS), 0);
   1117	else
   1118		snd_wss_out(chip, CS4231_IRQ_STATUS, status);
   1119	spin_unlock(&chip->reg_lock);
   1120	return IRQ_HANDLED;
   1121}
   1122EXPORT_SYMBOL(snd_wss_interrupt);
   1123
   1124static snd_pcm_uframes_t snd_wss_playback_pointer(struct snd_pcm_substream *substream)
   1125{
   1126	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1127	size_t ptr;
   1128
   1129	if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
   1130		return 0;
   1131	ptr = snd_dma_pointer(chip->dma1, chip->p_dma_size);
   1132	return bytes_to_frames(substream->runtime, ptr);
   1133}
   1134
   1135static snd_pcm_uframes_t snd_wss_capture_pointer(struct snd_pcm_substream *substream)
   1136{
   1137	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1138	size_t ptr;
   1139
   1140	if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
   1141		return 0;
   1142	ptr = snd_dma_pointer(chip->dma2, chip->c_dma_size);
   1143	return bytes_to_frames(substream->runtime, ptr);
   1144}
   1145
   1146/*
   1147
   1148 */
   1149
   1150static int snd_ad1848_probe(struct snd_wss *chip)
   1151{
   1152	unsigned long timeout = jiffies + msecs_to_jiffies(1000);
   1153	unsigned long flags;
   1154	unsigned char r;
   1155	unsigned short hardware = 0;
   1156	int err = 0;
   1157	int i;
   1158
   1159	while (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT) {
   1160		if (time_after(jiffies, timeout))
   1161			return -ENODEV;
   1162		cond_resched();
   1163	}
   1164	spin_lock_irqsave(&chip->reg_lock, flags);
   1165
   1166	/* set CS423x MODE 1 */
   1167	snd_wss_dout(chip, CS4231_MISC_INFO, 0);
   1168
   1169	snd_wss_dout(chip, CS4231_RIGHT_INPUT, 0x45); /* 0x55 & ~0x10 */
   1170	r = snd_wss_in(chip, CS4231_RIGHT_INPUT);
   1171	if (r != 0x45) {
   1172		/* RMGE always high on AD1847 */
   1173		if ((r & ~CS4231_ENABLE_MIC_GAIN) != 0x45) {
   1174			err = -ENODEV;
   1175			goto out;
   1176		}
   1177		hardware = WSS_HW_AD1847;
   1178	} else {
   1179		snd_wss_dout(chip, CS4231_LEFT_INPUT,  0xaa);
   1180		r = snd_wss_in(chip, CS4231_LEFT_INPUT);
   1181		/* L/RMGE always low on AT2320 */
   1182		if ((r | CS4231_ENABLE_MIC_GAIN) != 0xaa) {
   1183			err = -ENODEV;
   1184			goto out;
   1185		}
   1186	}
   1187
   1188	/* clear pending IRQ */
   1189	wss_inb(chip, CS4231P(STATUS));
   1190	wss_outb(chip, CS4231P(STATUS), 0);
   1191	mb();
   1192
   1193	if ((chip->hardware & WSS_HW_TYPE_MASK) != WSS_HW_DETECT)
   1194		goto out;
   1195
   1196	if (hardware) {
   1197		chip->hardware = hardware;
   1198		goto out;
   1199	}
   1200
   1201	r = snd_wss_in(chip, CS4231_MISC_INFO);
   1202
   1203	/* set CS423x MODE 2 */
   1204	snd_wss_dout(chip, CS4231_MISC_INFO, CS4231_MODE2);
   1205	for (i = 0; i < 16; i++) {
   1206		if (snd_wss_in(chip, i) != snd_wss_in(chip, 16 + i)) {
   1207			/* we have more than 16 registers: check ID */
   1208			if ((r & 0xf) != 0xa)
   1209				goto out_mode;
   1210			/*
   1211			 * on CMI8330, CS4231_VERSION is volume control and
   1212			 * can be set to 0
   1213			 */
   1214			snd_wss_dout(chip, CS4231_VERSION, 0);
   1215			r = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
   1216			if (!r)
   1217				chip->hardware = WSS_HW_CMI8330;
   1218			goto out_mode;
   1219		}
   1220	}
   1221	if (r & 0x80)
   1222		chip->hardware = WSS_HW_CS4248;
   1223	else
   1224		chip->hardware = WSS_HW_AD1848;
   1225out_mode:
   1226	snd_wss_dout(chip, CS4231_MISC_INFO, 0);
   1227out:
   1228	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1229	return err;
   1230}
   1231
   1232static int snd_wss_probe(struct snd_wss *chip)
   1233{
   1234	unsigned long flags;
   1235	int i, id, rev, regnum;
   1236	unsigned char *ptr;
   1237	unsigned int hw;
   1238
   1239	id = snd_ad1848_probe(chip);
   1240	if (id < 0)
   1241		return id;
   1242
   1243	hw = chip->hardware;
   1244	if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
   1245		for (i = 0; i < 50; i++) {
   1246			mb();
   1247			if (wss_inb(chip, CS4231P(REGSEL)) & CS4231_INIT)
   1248				msleep(2);
   1249			else {
   1250				spin_lock_irqsave(&chip->reg_lock, flags);
   1251				snd_wss_out(chip, CS4231_MISC_INFO,
   1252					    CS4231_MODE2);
   1253				id = snd_wss_in(chip, CS4231_MISC_INFO) & 0x0f;
   1254				spin_unlock_irqrestore(&chip->reg_lock, flags);
   1255				if (id == 0x0a)
   1256					break;	/* this is valid value */
   1257			}
   1258		}
   1259		snd_printdd("wss: port = 0x%lx, id = 0x%x\n", chip->port, id);
   1260		if (id != 0x0a)
   1261			return -ENODEV;	/* no valid device found */
   1262
   1263		rev = snd_wss_in(chip, CS4231_VERSION) & 0xe7;
   1264		snd_printdd("CS4231: VERSION (I25) = 0x%x\n", rev);
   1265		if (rev == 0x80) {
   1266			unsigned char tmp = snd_wss_in(chip, 23);
   1267			snd_wss_out(chip, 23, ~tmp);
   1268			if (snd_wss_in(chip, 23) != tmp)
   1269				chip->hardware = WSS_HW_AD1845;
   1270			else
   1271				chip->hardware = WSS_HW_CS4231;
   1272		} else if (rev == 0xa0) {
   1273			chip->hardware = WSS_HW_CS4231A;
   1274		} else if (rev == 0xa2) {
   1275			chip->hardware = WSS_HW_CS4232;
   1276		} else if (rev == 0xb2) {
   1277			chip->hardware = WSS_HW_CS4232A;
   1278		} else if (rev == 0x83) {
   1279			chip->hardware = WSS_HW_CS4236;
   1280		} else if (rev == 0x03) {
   1281			chip->hardware = WSS_HW_CS4236B;
   1282		} else {
   1283			snd_printk(KERN_ERR
   1284				   "unknown CS chip with version 0x%x\n", rev);
   1285			return -ENODEV;		/* unknown CS4231 chip? */
   1286		}
   1287	}
   1288	spin_lock_irqsave(&chip->reg_lock, flags);
   1289	wss_inb(chip, CS4231P(STATUS));	/* clear any pendings IRQ */
   1290	wss_outb(chip, CS4231P(STATUS), 0);
   1291	mb();
   1292	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1293
   1294	if (!(chip->hardware & WSS_HW_AD1848_MASK))
   1295		chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
   1296	switch (chip->hardware) {
   1297	case WSS_HW_INTERWAVE:
   1298		chip->image[CS4231_MISC_INFO] = CS4231_IW_MODE3;
   1299		break;
   1300	case WSS_HW_CS4235:
   1301	case WSS_HW_CS4236B:
   1302	case WSS_HW_CS4237B:
   1303	case WSS_HW_CS4238B:
   1304	case WSS_HW_CS4239:
   1305		if (hw == WSS_HW_DETECT3)
   1306			chip->image[CS4231_MISC_INFO] = CS4231_4236_MODE3;
   1307		else
   1308			chip->hardware = WSS_HW_CS4236;
   1309		break;
   1310	}
   1311
   1312	chip->image[CS4231_IFACE_CTRL] =
   1313	    (chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA) |
   1314	    (chip->single_dma ? CS4231_SINGLE_DMA : 0);
   1315	if (chip->hardware != WSS_HW_OPTI93X) {
   1316		chip->image[CS4231_ALT_FEATURE_1] = 0x80;
   1317		chip->image[CS4231_ALT_FEATURE_2] =
   1318			chip->hardware == WSS_HW_INTERWAVE ? 0xc2 : 0x01;
   1319	}
   1320	/* enable fine grained frequency selection */
   1321	if (chip->hardware == WSS_HW_AD1845)
   1322		chip->image[AD1845_PWR_DOWN] = 8;
   1323
   1324	ptr = (unsigned char *) &chip->image;
   1325	regnum = (chip->hardware & WSS_HW_AD1848_MASK) ? 16 : 32;
   1326	snd_wss_mce_down(chip);
   1327	spin_lock_irqsave(&chip->reg_lock, flags);
   1328	for (i = 0; i < regnum; i++)	/* ok.. fill all registers */
   1329		snd_wss_out(chip, i, *ptr++);
   1330	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1331	snd_wss_mce_up(chip);
   1332	snd_wss_mce_down(chip);
   1333
   1334	mdelay(2);
   1335
   1336	/* ok.. try check hardware version for CS4236+ chips */
   1337	if ((hw & WSS_HW_TYPE_MASK) == WSS_HW_DETECT) {
   1338		if (chip->hardware == WSS_HW_CS4236B) {
   1339			rev = snd_cs4236_ext_in(chip, CS4236_VERSION);
   1340			snd_cs4236_ext_out(chip, CS4236_VERSION, 0xff);
   1341			id = snd_cs4236_ext_in(chip, CS4236_VERSION);
   1342			snd_cs4236_ext_out(chip, CS4236_VERSION, rev);
   1343			snd_printdd("CS4231: ext version; rev = 0x%x, id = 0x%x\n", rev, id);
   1344			if ((id & 0x1f) == 0x1d) {	/* CS4235 */
   1345				chip->hardware = WSS_HW_CS4235;
   1346				switch (id >> 5) {
   1347				case 4:
   1348				case 5:
   1349				case 6:
   1350					break;
   1351				default:
   1352					snd_printk(KERN_WARNING
   1353						"unknown CS4235 chip "
   1354						"(enhanced version = 0x%x)\n",
   1355						id);
   1356				}
   1357			} else if ((id & 0x1f) == 0x0b) {	/* CS4236/B */
   1358				switch (id >> 5) {
   1359				case 4:
   1360				case 5:
   1361				case 6:
   1362				case 7:
   1363					chip->hardware = WSS_HW_CS4236B;
   1364					break;
   1365				default:
   1366					snd_printk(KERN_WARNING
   1367						"unknown CS4236 chip "
   1368						"(enhanced version = 0x%x)\n",
   1369						id);
   1370				}
   1371			} else if ((id & 0x1f) == 0x08) {	/* CS4237B */
   1372				chip->hardware = WSS_HW_CS4237B;
   1373				switch (id >> 5) {
   1374				case 4:
   1375				case 5:
   1376				case 6:
   1377				case 7:
   1378					break;
   1379				default:
   1380					snd_printk(KERN_WARNING
   1381						"unknown CS4237B chip "
   1382						"(enhanced version = 0x%x)\n",
   1383						id);
   1384				}
   1385			} else if ((id & 0x1f) == 0x09) {	/* CS4238B */
   1386				chip->hardware = WSS_HW_CS4238B;
   1387				switch (id >> 5) {
   1388				case 5:
   1389				case 6:
   1390				case 7:
   1391					break;
   1392				default:
   1393					snd_printk(KERN_WARNING
   1394						"unknown CS4238B chip "
   1395						"(enhanced version = 0x%x)\n",
   1396						id);
   1397				}
   1398			} else if ((id & 0x1f) == 0x1e) {	/* CS4239 */
   1399				chip->hardware = WSS_HW_CS4239;
   1400				switch (id >> 5) {
   1401				case 4:
   1402				case 5:
   1403				case 6:
   1404					break;
   1405				default:
   1406					snd_printk(KERN_WARNING
   1407						"unknown CS4239 chip "
   1408						"(enhanced version = 0x%x)\n",
   1409						id);
   1410				}
   1411			} else {
   1412				snd_printk(KERN_WARNING
   1413					   "unknown CS4236/CS423xB chip "
   1414					   "(enhanced version = 0x%x)\n", id);
   1415			}
   1416		}
   1417	}
   1418	return 0;		/* all things are ok.. */
   1419}
   1420
   1421/*
   1422
   1423 */
   1424
   1425static const struct snd_pcm_hardware snd_wss_playback =
   1426{
   1427	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
   1428				 SNDRV_PCM_INFO_MMAP_VALID |
   1429				 SNDRV_PCM_INFO_SYNC_START),
   1430	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
   1431				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
   1432	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
   1433	.rate_min =		5510,
   1434	.rate_max =		48000,
   1435	.channels_min =		1,
   1436	.channels_max =		2,
   1437	.buffer_bytes_max =	(128*1024),
   1438	.period_bytes_min =	64,
   1439	.period_bytes_max =	(128*1024),
   1440	.periods_min =		1,
   1441	.periods_max =		1024,
   1442	.fifo_size =		0,
   1443};
   1444
   1445static const struct snd_pcm_hardware snd_wss_capture =
   1446{
   1447	.info =			(SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
   1448				 SNDRV_PCM_INFO_MMAP_VALID |
   1449				 SNDRV_PCM_INFO_RESUME |
   1450				 SNDRV_PCM_INFO_SYNC_START),
   1451	.formats =		(SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | SNDRV_PCM_FMTBIT_IMA_ADPCM |
   1452				 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S16_BE),
   1453	.rates =		SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
   1454	.rate_min =		5510,
   1455	.rate_max =		48000,
   1456	.channels_min =		1,
   1457	.channels_max =		2,
   1458	.buffer_bytes_max =	(128*1024),
   1459	.period_bytes_min =	64,
   1460	.period_bytes_max =	(128*1024),
   1461	.periods_min =		1,
   1462	.periods_max =		1024,
   1463	.fifo_size =		0,
   1464};
   1465
   1466/*
   1467
   1468 */
   1469
   1470static int snd_wss_playback_open(struct snd_pcm_substream *substream)
   1471{
   1472	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1473	struct snd_pcm_runtime *runtime = substream->runtime;
   1474	int err;
   1475
   1476	runtime->hw = snd_wss_playback;
   1477
   1478	/* hardware limitation of older chipsets */
   1479	if (chip->hardware & WSS_HW_AD1848_MASK)
   1480		runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
   1481					 SNDRV_PCM_FMTBIT_S16_BE);
   1482
   1483	/* hardware bug in InterWave chipset */
   1484	if (chip->hardware == WSS_HW_INTERWAVE && chip->dma1 > 3)
   1485		runtime->hw.formats &= ~SNDRV_PCM_FMTBIT_MU_LAW;
   1486
   1487	/* hardware limitation of cheap chips */
   1488	if (chip->hardware == WSS_HW_CS4235 ||
   1489	    chip->hardware == WSS_HW_CS4239)
   1490		runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE;
   1491
   1492	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.buffer_bytes_max);
   1493	snd_pcm_limit_isa_dma_size(chip->dma1, &runtime->hw.period_bytes_max);
   1494
   1495	if (chip->claim_dma) {
   1496		err = chip->claim_dma(chip, chip->dma_private_data, chip->dma1);
   1497		if (err < 0)
   1498			return err;
   1499	}
   1500
   1501	err = snd_wss_open(chip, WSS_MODE_PLAY);
   1502	if (err < 0) {
   1503		if (chip->release_dma)
   1504			chip->release_dma(chip, chip->dma_private_data, chip->dma1);
   1505		return err;
   1506	}
   1507	chip->playback_substream = substream;
   1508	snd_pcm_set_sync(substream);
   1509	chip->rate_constraint(runtime);
   1510	return 0;
   1511}
   1512
   1513static int snd_wss_capture_open(struct snd_pcm_substream *substream)
   1514{
   1515	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1516	struct snd_pcm_runtime *runtime = substream->runtime;
   1517	int err;
   1518
   1519	runtime->hw = snd_wss_capture;
   1520
   1521	/* hardware limitation of older chipsets */
   1522	if (chip->hardware & WSS_HW_AD1848_MASK)
   1523		runtime->hw.formats &= ~(SNDRV_PCM_FMTBIT_IMA_ADPCM |
   1524					 SNDRV_PCM_FMTBIT_S16_BE);
   1525
   1526	/* hardware limitation of cheap chips */
   1527	if (chip->hardware == WSS_HW_CS4235 ||
   1528	    chip->hardware == WSS_HW_CS4239 ||
   1529	    chip->hardware == WSS_HW_OPTI93X)
   1530		runtime->hw.formats = SNDRV_PCM_FMTBIT_U8 |
   1531				      SNDRV_PCM_FMTBIT_S16_LE;
   1532
   1533	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.buffer_bytes_max);
   1534	snd_pcm_limit_isa_dma_size(chip->dma2, &runtime->hw.period_bytes_max);
   1535
   1536	if (chip->claim_dma) {
   1537		err = chip->claim_dma(chip, chip->dma_private_data, chip->dma2);
   1538		if (err < 0)
   1539			return err;
   1540	}
   1541
   1542	err = snd_wss_open(chip, WSS_MODE_RECORD);
   1543	if (err < 0) {
   1544		if (chip->release_dma)
   1545			chip->release_dma(chip, chip->dma_private_data, chip->dma2);
   1546		return err;
   1547	}
   1548	chip->capture_substream = substream;
   1549	snd_pcm_set_sync(substream);
   1550	chip->rate_constraint(runtime);
   1551	return 0;
   1552}
   1553
   1554static int snd_wss_playback_close(struct snd_pcm_substream *substream)
   1555{
   1556	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1557
   1558	chip->playback_substream = NULL;
   1559	snd_wss_close(chip, WSS_MODE_PLAY);
   1560	return 0;
   1561}
   1562
   1563static int snd_wss_capture_close(struct snd_pcm_substream *substream)
   1564{
   1565	struct snd_wss *chip = snd_pcm_substream_chip(substream);
   1566
   1567	chip->capture_substream = NULL;
   1568	snd_wss_close(chip, WSS_MODE_RECORD);
   1569	return 0;
   1570}
   1571
   1572static void snd_wss_thinkpad_twiddle(struct snd_wss *chip, int on)
   1573{
   1574	int tmp;
   1575
   1576	if (!chip->thinkpad_flag)
   1577		return;
   1578
   1579	outb(0x1c, AD1848_THINKPAD_CTL_PORT1);
   1580	tmp = inb(AD1848_THINKPAD_CTL_PORT2);
   1581
   1582	if (on)
   1583		/* turn it on */
   1584		tmp |= AD1848_THINKPAD_CS4248_ENABLE_BIT;
   1585	else
   1586		/* turn it off */
   1587		tmp &= ~AD1848_THINKPAD_CS4248_ENABLE_BIT;
   1588
   1589	outb(tmp, AD1848_THINKPAD_CTL_PORT2);
   1590}
   1591
   1592#ifdef CONFIG_PM
   1593
   1594/* lowlevel suspend callback for CS4231 */
   1595static void snd_wss_suspend(struct snd_wss *chip)
   1596{
   1597	int reg;
   1598	unsigned long flags;
   1599
   1600	spin_lock_irqsave(&chip->reg_lock, flags);
   1601	for (reg = 0; reg < 32; reg++)
   1602		chip->image[reg] = snd_wss_in(chip, reg);
   1603	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1604	if (chip->thinkpad_flag)
   1605		snd_wss_thinkpad_twiddle(chip, 0);
   1606}
   1607
   1608/* lowlevel resume callback for CS4231 */
   1609static void snd_wss_resume(struct snd_wss *chip)
   1610{
   1611	int reg;
   1612	unsigned long flags;
   1613	/* int timeout; */
   1614
   1615	if (chip->thinkpad_flag)
   1616		snd_wss_thinkpad_twiddle(chip, 1);
   1617	snd_wss_mce_up(chip);
   1618	spin_lock_irqsave(&chip->reg_lock, flags);
   1619	for (reg = 0; reg < 32; reg++) {
   1620		switch (reg) {
   1621		case CS4231_VERSION:
   1622			break;
   1623		default:
   1624			snd_wss_out(chip, reg, chip->image[reg]);
   1625			break;
   1626		}
   1627	}
   1628	/* Yamaha needs this to resume properly */
   1629	if (chip->hardware == WSS_HW_OPL3SA2)
   1630		snd_wss_out(chip, CS4231_PLAYBK_FORMAT,
   1631			    chip->image[CS4231_PLAYBK_FORMAT]);
   1632	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1633#if 1
   1634	snd_wss_mce_down(chip);
   1635#else
   1636	/* The following is a workaround to avoid freeze after resume on TP600E.
   1637	   This is the first half of copy of snd_wss_mce_down(), but doesn't
   1638	   include rescheduling.  -- iwai
   1639	   */
   1640	snd_wss_busy_wait(chip);
   1641	spin_lock_irqsave(&chip->reg_lock, flags);
   1642	chip->mce_bit &= ~CS4231_MCE;
   1643	timeout = wss_inb(chip, CS4231P(REGSEL));
   1644	wss_outb(chip, CS4231P(REGSEL), chip->mce_bit | (timeout & 0x1f));
   1645	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1646	if (timeout == 0x80)
   1647		snd_printk(KERN_ERR "down [0x%lx]: serious init problem "
   1648			   "- codec still busy\n", chip->port);
   1649	if ((timeout & CS4231_MCE) == 0 ||
   1650	    !(chip->hardware & (WSS_HW_CS4231_MASK | WSS_HW_CS4232_MASK))) {
   1651		return;
   1652	}
   1653	snd_wss_busy_wait(chip);
   1654#endif
   1655}
   1656#endif /* CONFIG_PM */
   1657
   1658const char *snd_wss_chip_id(struct snd_wss *chip)
   1659{
   1660	switch (chip->hardware) {
   1661	case WSS_HW_CS4231:
   1662		return "CS4231";
   1663	case WSS_HW_CS4231A:
   1664		return "CS4231A";
   1665	case WSS_HW_CS4232:
   1666		return "CS4232";
   1667	case WSS_HW_CS4232A:
   1668		return "CS4232A";
   1669	case WSS_HW_CS4235:
   1670		return "CS4235";
   1671	case WSS_HW_CS4236:
   1672		return "CS4236";
   1673	case WSS_HW_CS4236B:
   1674		return "CS4236B";
   1675	case WSS_HW_CS4237B:
   1676		return "CS4237B";
   1677	case WSS_HW_CS4238B:
   1678		return "CS4238B";
   1679	case WSS_HW_CS4239:
   1680		return "CS4239";
   1681	case WSS_HW_INTERWAVE:
   1682		return "AMD InterWave";
   1683	case WSS_HW_OPL3SA2:
   1684		return chip->card->shortname;
   1685	case WSS_HW_AD1845:
   1686		return "AD1845";
   1687	case WSS_HW_OPTI93X:
   1688		return "OPTi 93x";
   1689	case WSS_HW_AD1847:
   1690		return "AD1847";
   1691	case WSS_HW_AD1848:
   1692		return "AD1848";
   1693	case WSS_HW_CS4248:
   1694		return "CS4248";
   1695	case WSS_HW_CMI8330:
   1696		return "CMI8330/C3D";
   1697	default:
   1698		return "???";
   1699	}
   1700}
   1701EXPORT_SYMBOL(snd_wss_chip_id);
   1702
   1703static int snd_wss_new(struct snd_card *card,
   1704			  unsigned short hardware,
   1705			  unsigned short hwshare,
   1706			  struct snd_wss **rchip)
   1707{
   1708	struct snd_wss *chip;
   1709
   1710	*rchip = NULL;
   1711	chip = devm_kzalloc(card->dev, sizeof(*chip), GFP_KERNEL);
   1712	if (chip == NULL)
   1713		return -ENOMEM;
   1714	chip->hardware = hardware;
   1715	chip->hwshare = hwshare;
   1716
   1717	spin_lock_init(&chip->reg_lock);
   1718	mutex_init(&chip->mce_mutex);
   1719	mutex_init(&chip->open_mutex);
   1720	chip->card = card;
   1721	chip->rate_constraint = snd_wss_xrate;
   1722	chip->set_playback_format = snd_wss_playback_format;
   1723	chip->set_capture_format = snd_wss_capture_format;
   1724	if (chip->hardware == WSS_HW_OPTI93X)
   1725		memcpy(&chip->image, &snd_opti93x_original_image,
   1726		       sizeof(snd_opti93x_original_image));
   1727	else
   1728		memcpy(&chip->image, &snd_wss_original_image,
   1729		       sizeof(snd_wss_original_image));
   1730	if (chip->hardware & WSS_HW_AD1848_MASK) {
   1731		chip->image[CS4231_PIN_CTRL] = 0;
   1732		chip->image[CS4231_TEST_INIT] = 0;
   1733	}
   1734
   1735	*rchip = chip;
   1736	return 0;
   1737}
   1738
   1739int snd_wss_create(struct snd_card *card,
   1740		      unsigned long port,
   1741		      unsigned long cport,
   1742		      int irq, int dma1, int dma2,
   1743		      unsigned short hardware,
   1744		      unsigned short hwshare,
   1745		      struct snd_wss **rchip)
   1746{
   1747	struct snd_wss *chip;
   1748	int err;
   1749
   1750	err = snd_wss_new(card, hardware, hwshare, &chip);
   1751	if (err < 0)
   1752		return err;
   1753
   1754	chip->irq = -1;
   1755	chip->dma1 = -1;
   1756	chip->dma2 = -1;
   1757
   1758	chip->res_port = devm_request_region(card->dev, port, 4, "WSS");
   1759	if (!chip->res_port) {
   1760		snd_printk(KERN_ERR "wss: can't grab port 0x%lx\n", port);
   1761		return -EBUSY;
   1762	}
   1763	chip->port = port;
   1764	if ((long)cport >= 0) {
   1765		chip->res_cport = devm_request_region(card->dev, cport, 8,
   1766						      "CS4232 Control");
   1767		if (!chip->res_cport) {
   1768			snd_printk(KERN_ERR
   1769				"wss: can't grab control port 0x%lx\n", cport);
   1770			return -ENODEV;
   1771		}
   1772	}
   1773	chip->cport = cport;
   1774	if (!(hwshare & WSS_HWSHARE_IRQ))
   1775		if (devm_request_irq(card->dev, irq, snd_wss_interrupt, 0,
   1776				     "WSS", (void *) chip)) {
   1777			snd_printk(KERN_ERR "wss: can't grab IRQ %d\n", irq);
   1778			return -EBUSY;
   1779		}
   1780	chip->irq = irq;
   1781	card->sync_irq = chip->irq;
   1782	if (!(hwshare & WSS_HWSHARE_DMA1) &&
   1783	    snd_devm_request_dma(card->dev, dma1, "WSS - 1")) {
   1784		snd_printk(KERN_ERR "wss: can't grab DMA1 %d\n", dma1);
   1785		return -EBUSY;
   1786	}
   1787	chip->dma1 = dma1;
   1788	if (!(hwshare & WSS_HWSHARE_DMA2) && dma1 != dma2 && dma2 >= 0 &&
   1789	    snd_devm_request_dma(card->dev, dma2, "WSS - 2")) {
   1790		snd_printk(KERN_ERR "wss: can't grab DMA2 %d\n", dma2);
   1791		return -EBUSY;
   1792	}
   1793	if (dma1 == dma2 || dma2 < 0) {
   1794		chip->single_dma = 1;
   1795		chip->dma2 = chip->dma1;
   1796	} else
   1797		chip->dma2 = dma2;
   1798
   1799	if (hardware == WSS_HW_THINKPAD) {
   1800		chip->thinkpad_flag = 1;
   1801		chip->hardware = WSS_HW_DETECT; /* reset */
   1802		snd_wss_thinkpad_twiddle(chip, 1);
   1803	}
   1804
   1805	/* global setup */
   1806	if (snd_wss_probe(chip) < 0)
   1807		return -ENODEV;
   1808	snd_wss_init(chip);
   1809
   1810#if 0
   1811	if (chip->hardware & WSS_HW_CS4232_MASK) {
   1812		if (chip->res_cport == NULL)
   1813			snd_printk(KERN_ERR "CS4232 control port features are "
   1814				   "not accessible\n");
   1815	}
   1816#endif
   1817
   1818#ifdef CONFIG_PM
   1819	/* Power Management */
   1820	chip->suspend = snd_wss_suspend;
   1821	chip->resume = snd_wss_resume;
   1822#endif
   1823
   1824	*rchip = chip;
   1825	return 0;
   1826}
   1827EXPORT_SYMBOL(snd_wss_create);
   1828
   1829static const struct snd_pcm_ops snd_wss_playback_ops = {
   1830	.open =		snd_wss_playback_open,
   1831	.close =	snd_wss_playback_close,
   1832	.hw_params =	snd_wss_playback_hw_params,
   1833	.prepare =	snd_wss_playback_prepare,
   1834	.trigger =	snd_wss_trigger,
   1835	.pointer =	snd_wss_playback_pointer,
   1836};
   1837
   1838static const struct snd_pcm_ops snd_wss_capture_ops = {
   1839	.open =		snd_wss_capture_open,
   1840	.close =	snd_wss_capture_close,
   1841	.hw_params =	snd_wss_capture_hw_params,
   1842	.prepare =	snd_wss_capture_prepare,
   1843	.trigger =	snd_wss_trigger,
   1844	.pointer =	snd_wss_capture_pointer,
   1845};
   1846
   1847int snd_wss_pcm(struct snd_wss *chip, int device)
   1848{
   1849	struct snd_pcm *pcm;
   1850	int err;
   1851
   1852	err = snd_pcm_new(chip->card, "WSS", device, 1, 1, &pcm);
   1853	if (err < 0)
   1854		return err;
   1855
   1856	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_wss_playback_ops);
   1857	snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_wss_capture_ops);
   1858
   1859	/* global setup */
   1860	pcm->private_data = chip;
   1861	pcm->info_flags = 0;
   1862	if (chip->single_dma)
   1863		pcm->info_flags |= SNDRV_PCM_INFO_HALF_DUPLEX;
   1864	if (chip->hardware != WSS_HW_INTERWAVE)
   1865		pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
   1866	strcpy(pcm->name, snd_wss_chip_id(chip));
   1867
   1868	snd_pcm_set_managed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, chip->card->dev,
   1869				       64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024);
   1870
   1871	chip->pcm = pcm;
   1872	return 0;
   1873}
   1874EXPORT_SYMBOL(snd_wss_pcm);
   1875
   1876static void snd_wss_timer_free(struct snd_timer *timer)
   1877{
   1878	struct snd_wss *chip = timer->private_data;
   1879	chip->timer = NULL;
   1880}
   1881
   1882int snd_wss_timer(struct snd_wss *chip, int device)
   1883{
   1884	struct snd_timer *timer;
   1885	struct snd_timer_id tid;
   1886	int err;
   1887
   1888	/* Timer initialization */
   1889	tid.dev_class = SNDRV_TIMER_CLASS_CARD;
   1890	tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
   1891	tid.card = chip->card->number;
   1892	tid.device = device;
   1893	tid.subdevice = 0;
   1894	err = snd_timer_new(chip->card, "CS4231", &tid, &timer);
   1895	if (err < 0)
   1896		return err;
   1897	strcpy(timer->name, snd_wss_chip_id(chip));
   1898	timer->private_data = chip;
   1899	timer->private_free = snd_wss_timer_free;
   1900	timer->hw = snd_wss_timer_table;
   1901	chip->timer = timer;
   1902	return 0;
   1903}
   1904EXPORT_SYMBOL(snd_wss_timer);
   1905
   1906/*
   1907 *  MIXER part
   1908 */
   1909
   1910static int snd_wss_info_mux(struct snd_kcontrol *kcontrol,
   1911			    struct snd_ctl_elem_info *uinfo)
   1912{
   1913	static const char * const texts[4] = {
   1914		"Line", "Aux", "Mic", "Mix"
   1915	};
   1916	static const char * const opl3sa_texts[4] = {
   1917		"Line", "CD", "Mic", "Mix"
   1918	};
   1919	static const char * const gusmax_texts[4] = {
   1920		"Line", "Synth", "Mic", "Mix"
   1921	};
   1922	const char * const *ptexts = texts;
   1923	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   1924
   1925	if (snd_BUG_ON(!chip->card))
   1926		return -EINVAL;
   1927	if (!strcmp(chip->card->driver, "GUS MAX"))
   1928		ptexts = gusmax_texts;
   1929	switch (chip->hardware) {
   1930	case WSS_HW_INTERWAVE:
   1931		ptexts = gusmax_texts;
   1932		break;
   1933	case WSS_HW_OPTI93X:
   1934	case WSS_HW_OPL3SA2:
   1935		ptexts = opl3sa_texts;
   1936		break;
   1937	}
   1938	return snd_ctl_enum_info(uinfo, 2, 4, ptexts);
   1939}
   1940
   1941static int snd_wss_get_mux(struct snd_kcontrol *kcontrol,
   1942			   struct snd_ctl_elem_value *ucontrol)
   1943{
   1944	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   1945	unsigned long flags;
   1946
   1947	spin_lock_irqsave(&chip->reg_lock, flags);
   1948	ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
   1949	ucontrol->value.enumerated.item[1] = (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
   1950	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1951	return 0;
   1952}
   1953
   1954static int snd_wss_put_mux(struct snd_kcontrol *kcontrol,
   1955			   struct snd_ctl_elem_value *ucontrol)
   1956{
   1957	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   1958	unsigned long flags;
   1959	unsigned short left, right;
   1960	int change;
   1961
   1962	if (ucontrol->value.enumerated.item[0] > 3 ||
   1963	    ucontrol->value.enumerated.item[1] > 3)
   1964		return -EINVAL;
   1965	left = ucontrol->value.enumerated.item[0] << 6;
   1966	right = ucontrol->value.enumerated.item[1] << 6;
   1967	spin_lock_irqsave(&chip->reg_lock, flags);
   1968	left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
   1969	right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
   1970	change = left != chip->image[CS4231_LEFT_INPUT] ||
   1971		 right != chip->image[CS4231_RIGHT_INPUT];
   1972	snd_wss_out(chip, CS4231_LEFT_INPUT, left);
   1973	snd_wss_out(chip, CS4231_RIGHT_INPUT, right);
   1974	spin_unlock_irqrestore(&chip->reg_lock, flags);
   1975	return change;
   1976}
   1977
   1978int snd_wss_info_single(struct snd_kcontrol *kcontrol,
   1979			struct snd_ctl_elem_info *uinfo)
   1980{
   1981	int mask = (kcontrol->private_value >> 16) & 0xff;
   1982
   1983	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
   1984	uinfo->count = 1;
   1985	uinfo->value.integer.min = 0;
   1986	uinfo->value.integer.max = mask;
   1987	return 0;
   1988}
   1989EXPORT_SYMBOL(snd_wss_info_single);
   1990
   1991int snd_wss_get_single(struct snd_kcontrol *kcontrol,
   1992		       struct snd_ctl_elem_value *ucontrol)
   1993{
   1994	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   1995	unsigned long flags;
   1996	int reg = kcontrol->private_value & 0xff;
   1997	int shift = (kcontrol->private_value >> 8) & 0xff;
   1998	int mask = (kcontrol->private_value >> 16) & 0xff;
   1999	int invert = (kcontrol->private_value >> 24) & 0xff;
   2000
   2001	spin_lock_irqsave(&chip->reg_lock, flags);
   2002	ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
   2003	spin_unlock_irqrestore(&chip->reg_lock, flags);
   2004	if (invert)
   2005		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
   2006	return 0;
   2007}
   2008EXPORT_SYMBOL(snd_wss_get_single);
   2009
   2010int snd_wss_put_single(struct snd_kcontrol *kcontrol,
   2011		       struct snd_ctl_elem_value *ucontrol)
   2012{
   2013	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   2014	unsigned long flags;
   2015	int reg = kcontrol->private_value & 0xff;
   2016	int shift = (kcontrol->private_value >> 8) & 0xff;
   2017	int mask = (kcontrol->private_value >> 16) & 0xff;
   2018	int invert = (kcontrol->private_value >> 24) & 0xff;
   2019	int change;
   2020	unsigned short val;
   2021
   2022	val = (ucontrol->value.integer.value[0] & mask);
   2023	if (invert)
   2024		val = mask - val;
   2025	val <<= shift;
   2026	spin_lock_irqsave(&chip->reg_lock, flags);
   2027	val = (chip->image[reg] & ~(mask << shift)) | val;
   2028	change = val != chip->image[reg];
   2029	snd_wss_out(chip, reg, val);
   2030	spin_unlock_irqrestore(&chip->reg_lock, flags);
   2031	return change;
   2032}
   2033EXPORT_SYMBOL(snd_wss_put_single);
   2034
   2035int snd_wss_info_double(struct snd_kcontrol *kcontrol,
   2036			struct snd_ctl_elem_info *uinfo)
   2037{
   2038	int mask = (kcontrol->private_value >> 24) & 0xff;
   2039
   2040	uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
   2041	uinfo->count = 2;
   2042	uinfo->value.integer.min = 0;
   2043	uinfo->value.integer.max = mask;
   2044	return 0;
   2045}
   2046EXPORT_SYMBOL(snd_wss_info_double);
   2047
   2048int snd_wss_get_double(struct snd_kcontrol *kcontrol,
   2049		       struct snd_ctl_elem_value *ucontrol)
   2050{
   2051	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   2052	unsigned long flags;
   2053	int left_reg = kcontrol->private_value & 0xff;
   2054	int right_reg = (kcontrol->private_value >> 8) & 0xff;
   2055	int shift_left = (kcontrol->private_value >> 16) & 0x07;
   2056	int shift_right = (kcontrol->private_value >> 19) & 0x07;
   2057	int mask = (kcontrol->private_value >> 24) & 0xff;
   2058	int invert = (kcontrol->private_value >> 22) & 1;
   2059
   2060	spin_lock_irqsave(&chip->reg_lock, flags);
   2061	ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
   2062	ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
   2063	spin_unlock_irqrestore(&chip->reg_lock, flags);
   2064	if (invert) {
   2065		ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
   2066		ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
   2067	}
   2068	return 0;
   2069}
   2070EXPORT_SYMBOL(snd_wss_get_double);
   2071
   2072int snd_wss_put_double(struct snd_kcontrol *kcontrol,
   2073		       struct snd_ctl_elem_value *ucontrol)
   2074{
   2075	struct snd_wss *chip = snd_kcontrol_chip(kcontrol);
   2076	unsigned long flags;
   2077	int left_reg = kcontrol->private_value & 0xff;
   2078	int right_reg = (kcontrol->private_value >> 8) & 0xff;
   2079	int shift_left = (kcontrol->private_value >> 16) & 0x07;
   2080	int shift_right = (kcontrol->private_value >> 19) & 0x07;
   2081	int mask = (kcontrol->private_value >> 24) & 0xff;
   2082	int invert = (kcontrol->private_value >> 22) & 1;
   2083	int change;
   2084	unsigned short val1, val2;
   2085
   2086	val1 = ucontrol->value.integer.value[0] & mask;
   2087	val2 = ucontrol->value.integer.value[1] & mask;
   2088	if (invert) {
   2089		val1 = mask - val1;
   2090		val2 = mask - val2;
   2091	}
   2092	val1 <<= shift_left;
   2093	val2 <<= shift_right;
   2094	spin_lock_irqsave(&chip->reg_lock, flags);
   2095	if (left_reg != right_reg) {
   2096		val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
   2097		val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
   2098		change = val1 != chip->image[left_reg] ||
   2099			 val2 != chip->image[right_reg];
   2100		snd_wss_out(chip, left_reg, val1);
   2101		snd_wss_out(chip, right_reg, val2);
   2102	} else {
   2103		mask = (mask << shift_left) | (mask << shift_right);
   2104		val1 = (chip->image[left_reg] & ~mask) | val1 | val2;
   2105		change = val1 != chip->image[left_reg];
   2106		snd_wss_out(chip, left_reg, val1);
   2107	}
   2108	spin_unlock_irqrestore(&chip->reg_lock, flags);
   2109	return change;
   2110}
   2111EXPORT_SYMBOL(snd_wss_put_double);
   2112
   2113static const DECLARE_TLV_DB_SCALE(db_scale_6bit, -9450, 150, 0);
   2114static const DECLARE_TLV_DB_SCALE(db_scale_5bit_12db_max, -3450, 150, 0);
   2115static const DECLARE_TLV_DB_SCALE(db_scale_rec_gain, 0, 150, 0);
   2116static const DECLARE_TLV_DB_SCALE(db_scale_4bit, -4500, 300, 0);
   2117
   2118static const struct snd_kcontrol_new snd_wss_controls[] = {
   2119WSS_DOUBLE("PCM Playback Switch", 0,
   2120		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
   2121WSS_DOUBLE_TLV("PCM Playback Volume", 0,
   2122		CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1,
   2123		db_scale_6bit),
   2124WSS_DOUBLE("Aux Playback Switch", 0,
   2125		CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
   2126WSS_DOUBLE_TLV("Aux Playback Volume", 0,
   2127		CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1,
   2128		db_scale_5bit_12db_max),
   2129WSS_DOUBLE("Aux Playback Switch", 1,
   2130		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
   2131WSS_DOUBLE_TLV("Aux Playback Volume", 1,
   2132		CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1,
   2133		db_scale_5bit_12db_max),
   2134WSS_DOUBLE_TLV("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT,
   2135		0, 0, 15, 0, db_scale_rec_gain),
   2136{
   2137	.iface = SNDRV_CTL_ELEM_IFACE_MIXER,
   2138	.name = "Capture Source",
   2139	.info = snd_wss_info_mux,
   2140	.get = snd_wss_get_mux,
   2141	.put = snd_wss_put_mux,
   2142},
   2143WSS_DOUBLE("Mic Boost (+20dB)", 0,
   2144		CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
   2145WSS_SINGLE("Loopback Capture Switch", 0,
   2146		CS4231_LOOPBACK, 0, 1, 0),
   2147WSS_SINGLE_TLV("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1,
   2148		db_scale_6bit),
   2149WSS_DOUBLE("Line Playback Switch", 0,
   2150		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
   2151WSS_DOUBLE_TLV("Line Playback Volume", 0,
   2152		CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1,
   2153		db_scale_5bit_12db_max),
   2154WSS_SINGLE("Beep Playback Switch", 0,
   2155		CS4231_MONO_CTRL, 7, 1, 1),
   2156WSS_SINGLE_TLV("Beep Playback Volume", 0,
   2157		CS4231_MONO_CTRL, 0, 15, 1,
   2158		db_scale_4bit),
   2159WSS_SINGLE("Mono Output Playback Switch", 0,
   2160		CS4231_MONO_CTRL, 6, 1, 1),
   2161WSS_SINGLE("Beep Bypass Playback Switch", 0,
   2162		CS4231_MONO_CTRL, 5, 1, 0),
   2163};
   2164
   2165int snd_wss_mixer(struct snd_wss *chip)
   2166{
   2167	struct snd_card *card;
   2168	unsigned int idx;
   2169	int err;
   2170	int count = ARRAY_SIZE(snd_wss_controls);
   2171
   2172	if (snd_BUG_ON(!chip || !chip->pcm))
   2173		return -EINVAL;
   2174
   2175	card = chip->card;
   2176
   2177	strcpy(card->mixername, chip->pcm->name);
   2178
   2179	/* Use only the first 11 entries on AD1848 */
   2180	if (chip->hardware & WSS_HW_AD1848_MASK)
   2181		count = 11;
   2182	/* There is no loopback on OPTI93X */
   2183	else if (chip->hardware == WSS_HW_OPTI93X)
   2184		count = 9;
   2185
   2186	for (idx = 0; idx < count; idx++) {
   2187		err = snd_ctl_add(card,
   2188				snd_ctl_new1(&snd_wss_controls[idx],
   2189					     chip));
   2190		if (err < 0)
   2191			return err;
   2192	}
   2193	return 0;
   2194}
   2195EXPORT_SYMBOL(snd_wss_mixer);
   2196
   2197const struct snd_pcm_ops *snd_wss_get_pcm_ops(int direction)
   2198{
   2199	return direction == SNDRV_PCM_STREAM_PLAYBACK ?
   2200		&snd_wss_playback_ops : &snd_wss_capture_ops;
   2201}
   2202EXPORT_SYMBOL(snd_wss_get_pcm_ops);