diff options
Diffstat (limited to 'sound/sparc')
-rw-r--r-- | sound/sparc/cs4231.c | 805 | ||||
-rw-r--r-- | sound/sparc/dbri.c | 581 |
2 files changed, 651 insertions, 735 deletions
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c index f2950cab74a..9785382a5f3 100644 --- a/sound/sparc/cs4231.c +++ b/sound/sparc/cs4231.c @@ -3,9 +3,9 @@ * Copyright (C) 2002 David S. Miller <davem@redhat.com> * * Based entirely upon drivers/sbus/audio/cs4231.c which is: - * Copyright (C) 1996, 1997, 1998, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) + * Copyright (C) 1996, 1997, 1998 Derrick J Brashear (shadow@andrew.cmu.edu) * and also sound/isa/cs423x/cs4231_lib.c which is: - * Copyright (c) by Jaroslav Kysela <perex@suse.cz> + * Copyright (c) by Jaroslav Kysela <perex@perex.cz> */ #include <linux/module.h> @@ -15,6 +15,9 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/moduleparam.h> +#include <linux/irq.h> +#include <linux/io.h> + #include <sound/driver.h> #include <sound/core.h> @@ -25,29 +28,21 @@ #include <sound/initval.h> #include <sound/pcm_params.h> -#include <asm/io.h> -#include <asm/irq.h> - #ifdef CONFIG_SBUS #define SBUS_SUPPORT -#endif - -#ifdef SBUS_SUPPORT #include <asm/sbus.h> #endif #if defined(CONFIG_PCI) && defined(CONFIG_SPARC64) #define EBUS_SUPPORT -#endif - -#ifdef EBUS_SUPPORT #include <linux/pci.h> #include <asm/ebus.h> #endif static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +/* Enable this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard."); @@ -62,19 +57,22 @@ MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}"); #ifdef SBUS_SUPPORT struct sbus_dma_info { - spinlock_t lock; - int dir; - void __iomem *regs; + spinlock_t lock; /* DMA access lock */ + int dir; + void __iomem *regs; }; #endif struct snd_cs4231; struct cs4231_dma_control { - void (*prepare)(struct cs4231_dma_control *dma_cont, int dir); - void (*enable)(struct cs4231_dma_control *dma_cont, int on); - int (*request)(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len); - unsigned int (*address)(struct cs4231_dma_control *dma_cont); - void (*preallocate)(struct snd_cs4231 *chip, struct snd_pcm *pcm); + void (*prepare)(struct cs4231_dma_control *dma_cont, + int dir); + void (*enable)(struct cs4231_dma_control *dma_cont, int on); + int (*request)(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len); + unsigned int (*address)(struct cs4231_dma_control *dma_cont); + void (*preallocate)(struct snd_cs4231 *chip, + struct snd_pcm *pcm); #ifdef EBUS_SUPPORT struct ebus_dma_info ebus_info; #endif @@ -84,7 +82,7 @@ struct cs4231_dma_control { }; struct snd_cs4231 { - spinlock_t lock; + spinlock_t lock; /* registers access lock */ void __iomem *port; struct cs4231_dma_control p_dma; @@ -108,13 +106,14 @@ struct snd_cs4231 { #define CS4231_MODE_PLAY 0x0001 #define CS4231_MODE_RECORD 0x0002 #define CS4231_MODE_TIMER 0x0004 -#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER) +#define CS4231_MODE_OPEN (CS4231_MODE_PLAY | CS4231_MODE_RECORD | \ + CS4231_MODE_TIMER) unsigned char image[32]; /* registers image */ int mce_bit; int calibrate_mute; - struct mutex mce_mutex; - struct mutex open_mutex; + struct mutex mce_mutex; /* mutex for mce register */ + struct mutex open_mutex; /* mutex for ALSA open/close */ union { #ifdef SBUS_SUPPORT @@ -136,129 +135,10 @@ static struct snd_cs4231 *cs4231_list; */ /* IO ports */ - -#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x) +#include <sound/cs4231-regs.h> /* XXX offsets are different than PC ISA chips... */ -#define c_d_c_CS4231REGSEL 0x0 -#define c_d_c_CS4231REG 0x4 -#define c_d_c_CS4231STATUS 0x8 -#define c_d_c_CS4231PIO 0xc - -/* codec registers */ - -#define CS4231_LEFT_INPUT 0x00 /* left input control */ -#define CS4231_RIGHT_INPUT 0x01 /* right input control */ -#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */ -#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */ -#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */ -#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */ -#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */ -#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */ -#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */ -#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */ -#define CS4231_PIN_CTRL 0x0a /* pin control */ -#define CS4231_TEST_INIT 0x0b /* test and initialization */ -#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */ -#define CS4231_LOOPBACK 0x0d /* loopback control */ -#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */ -#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */ -#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */ -#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */ -#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */ -#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */ -#define CS4231_TIMER_LOW 0x14 /* timer low byte */ -#define CS4231_TIMER_HIGH 0x15 /* timer high byte */ -#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */ -#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */ -#define CS4236_EXT_REG 0x17 /* extended register access */ -#define CS4231_IRQ_STATUS 0x18 /* irq status register */ -#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */ -#define CS4231_VERSION 0x19 /* CS4231(A) - version values */ -#define CS4231_MONO_CTRL 0x1a /* mono input/output control */ -#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */ -#define CS4235_LEFT_MASTER 0x1b /* left master output control */ -#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */ -#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */ -#define CS4235_RIGHT_MASTER 0x1d /* right master output control */ -#define CS4231_REC_UPR_CNT 0x1e /* record upper count */ -#define CS4231_REC_LWR_CNT 0x1f /* record lower count */ - -/* definitions for codec register select port - CODECP( REGSEL ) */ - -#define CS4231_INIT 0x80 /* CODEC is initializing */ -#define CS4231_MCE 0x40 /* mode change enable */ -#define CS4231_TRD 0x20 /* transfer request disable */ - -/* definitions for codec status register - CODECP( STATUS ) */ - -#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */ - -/* definitions for codec irq status - CS4231_IRQ_STATUS */ - -#define CS4231_PLAYBACK_IRQ 0x10 -#define CS4231_RECORD_IRQ 0x20 -#define CS4231_TIMER_IRQ 0x40 -#define CS4231_ALL_IRQS 0x70 -#define CS4231_REC_UNDERRUN 0x08 -#define CS4231_REC_OVERRUN 0x04 -#define CS4231_PLY_OVERRUN 0x02 -#define CS4231_PLY_UNDERRUN 0x01 - -/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */ - -#define CS4231_ENABLE_MIC_GAIN 0x20 - -#define CS4231_MIXS_LINE 0x00 -#define CS4231_MIXS_AUX1 0x40 -#define CS4231_MIXS_MIC 0x80 -#define CS4231_MIXS_ALL 0xc0 - -/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */ - -#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */ -#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */ -#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */ -#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */ -#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */ -#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */ -#define CS4231_STEREO 0x10 /* stereo mode */ -/* bits 3-1 define frequency divisor */ -#define CS4231_XTAL1 0x00 /* 24.576 crystal */ -#define CS4231_XTAL2 0x01 /* 16.9344 crystal */ - -/* definitions for interface control register - CS4231_IFACE_CTRL */ - -#define CS4231_RECORD_PIO 0x80 /* record PIO enable */ -#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */ -#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */ -#define CS4231_AUTOCALIB 0x08 /* auto calibrate */ -#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */ -#define CS4231_RECORD_ENABLE 0x02 /* record enable */ -#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */ - -/* definitions for pin control register - CS4231_PIN_CTRL */ - -#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */ -#define CS4231_XCTL1 0x40 /* external control #1 */ -#define CS4231_XCTL0 0x80 /* external control #0 */ - -/* definitions for test and init register - CS4231_TEST_INIT */ - -#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */ -#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */ - -/* definitions for misc control register - CS4231_MISC_INFO */ - -#define CS4231_MODE2 0x40 /* MODE 2 */ -#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */ -#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */ - -/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */ - -#define CS4231_DACZ 0x01 /* zero DAC when underrun */ -#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */ -#define CS4231_OLB 0x80 /* output level bit */ +#define CS4231U(chip, x) ((chip)->port + ((c_d_c_CS4231##x) << 2)) /* SBUS DMA register defines. */ @@ -339,7 +219,7 @@ static unsigned int rates[14] = { }; static struct snd_pcm_hw_constraint_list hw_constraints_rates = { - .count = 14, + .count = ARRAY_SIZE(rates), .list = rates, }; @@ -389,116 +269,89 @@ static unsigned char snd_cs4231_original_image[32] = static u8 __cs4231_readb(struct snd_cs4231 *cp, void __iomem *reg_addr) { #ifdef EBUS_SUPPORT - if (cp->flags & CS4231_FLAG_EBUS) { + if (cp->flags & CS4231_FLAG_EBUS) return readb(reg_addr); - } else { + else #endif #ifdef SBUS_SUPPORT return sbus_readb(reg_addr); #endif -#ifdef EBUS_SUPPORT - } -#endif } -static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, void __iomem *reg_addr) +static void __cs4231_writeb(struct snd_cs4231 *cp, u8 val, + void __iomem *reg_addr) { #ifdef EBUS_SUPPORT - if (cp->flags & CS4231_FLAG_EBUS) { + if (cp->flags & CS4231_FLAG_EBUS) return writeb(val, reg_addr); - } else { + else #endif #ifdef SBUS_SUPPORT return sbus_writeb(val, reg_addr); #endif -#ifdef EBUS_SUPPORT - } -#endif } /* * Basic I/O functions */ -static void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, - unsigned char mask, unsigned char value) +static void snd_cs4231_ready(struct snd_cs4231 *chip) { int timeout; - unsigned char tmp; - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -#ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); -#endif - if (chip->calibrate_mute) { - chip->image[reg] &= mask; - chip->image[reg] |= value; - } else { - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - mb(); - tmp = (chip->image[reg] & mask) | value; - __cs4231_writeb(chip, tmp, CS4231P(chip, REG)); - chip->image[reg] = tmp; - mb(); + for (timeout = 250; timeout > 0; timeout--) { + int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + if ((val & CS4231_INIT) == 0) + break; + udelay(100); } } -static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +static void snd_cs4231_dout(struct snd_cs4231 *chip, unsigned char reg, + unsigned char value) { - int timeout; - - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("out: auto calibration time out - reg = 0x%x, " + "value = 0x%x\n", + reg, value); #endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, value, CS4231P(chip, REG)); + __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); + wmb(); + __cs4231_writeb(chip, value, CS4231U(chip, REG)); mb(); } -static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, unsigned char value) +static inline void snd_cs4231_outm(struct snd_cs4231 *chip, unsigned char reg, + unsigned char mask, unsigned char value) { - int timeout; + unsigned char tmp = (chip->image[reg] & mask) | value; - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); -#ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value); -#endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, value, CS4231P(chip, REG)); + chip->image[reg] = tmp; + if (!chip->calibrate_mute) + snd_cs4231_dout(chip, reg, tmp); +} + +static void snd_cs4231_out(struct snd_cs4231 *chip, unsigned char reg, + unsigned char value) +{ + snd_cs4231_dout(chip, reg, value); chip->image[reg] = value; mb(); } static unsigned char snd_cs4231_in(struct snd_cs4231 *chip, unsigned char reg) { - int timeout; - unsigned char ret; - - for (timeout = 250; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("in: auto calibration time out - reg = 0x%x\n", reg); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("in: auto calibration time out - reg = 0x%x\n", + reg); #endif - __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | reg, CS4231U(chip, REGSEL)); mb(); - ret = __cs4231_readb(chip, CS4231P(chip, REG)); - return ret; + return __cs4231_readb(chip, CS4231U(chip, REG)); } /* @@ -509,15 +362,17 @@ static void snd_cs4231_busy_wait(struct snd_cs4231 *chip) { int timeout; - /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */ + /* looks like this sequence is proper for CS4231A chip (GUS MAX) */ for (timeout = 5; timeout > 0; timeout--) - __cs4231_readb(chip, CS4231P(chip, REGSEL)); + __cs4231_readb(chip, CS4231U(chip, REGSEL)); /* end of cleanup sequence */ - for (timeout = 500; - timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); - timeout--) - udelay(1000); + for (timeout = 500; timeout > 0; timeout--) { + int val = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + if ((val & CS4231_INIT) == 0) + break; + msleep(1); + } } static void snd_cs4231_mce_up(struct snd_cs4231 *chip) @@ -526,74 +381,81 @@ static void snd_cs4231_mce_up(struct snd_cs4231 *chip) int timeout; spin_lock_irqsave(&chip->lock, flags); - for (timeout = 250; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--) - udelay(100); + snd_cs4231_ready(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) snd_printdd("mce_up - auto calibration time out (0)\n"); #endif chip->mce_bit |= CS4231_MCE; - timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); + timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); if (timeout == 0x80) - snd_printdd("mce_up [%p]: serious init problem - codec still busy\n", chip->port); + snd_printdd("mce_up [%p]: serious init problem - " + "codec still busy\n", + chip->port); if (!(timeout & CS4231_MCE)) - __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), + CS4231U(chip, REGSEL)); spin_unlock_irqrestore(&chip->lock, flags); } static void snd_cs4231_mce_down(struct snd_cs4231 *chip) { unsigned long flags; + unsigned long end_time; int timeout; spin_lock_irqsave(&chip->lock, flags); snd_cs4231_busy_wait(chip); #ifdef CONFIG_SND_DEBUG - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - snd_printdd("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL)); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + snd_printdd("mce_down [%p] - auto calibration time out (0)\n", + CS4231U(chip, REGSEL)); #endif chip->mce_bit &= ~CS4231_MCE; - timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL)); - __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL)); + timeout = __cs4231_readb(chip, CS4231U(chip, REGSEL)); + __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), + CS4231U(chip, REGSEL)); if (timeout == 0x80) - snd_printdd("mce_down [%p]: serious init problem - codec still busy\n", chip->port); + snd_printdd("mce_down [%p]: serious init problem - " + "codec still busy\n", + chip->port); if ((timeout & CS4231_MCE) == 0) { spin_unlock_irqrestore(&chip->lock, flags); return; } - snd_cs4231_busy_wait(chip); - /* calibration process */ + /* + * Wait for (possible -- during init auto-calibration may not be set) + * calibration process to start. Needs upto 5 sample periods on AD1848 + * which at the slowest possible rate of 5.5125 kHz means 907 us. + */ + msleep(1); - for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--) - udelay(100); - if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) { - snd_printd("cs4231_mce_down - auto calibration time out (1)\n"); - spin_unlock_irqrestore(&chip->lock, flags); - return; - } + /* check condition up to 250ms */ + end_time = jiffies + msecs_to_jiffies(250); + while (snd_cs4231_in(chip, CS4231_TEST_INIT) & + CS4231_CALIB_IN_PROGRESS) { - /* in 10ms increments, check condition, up to 250ms */ - timeout = 25; - while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) { spin_unlock_irqrestore(&chip->lock, flags); - if (--timeout < 0) { - snd_printk("mce_down - auto calibration time out (2)\n"); + if (time_after(jiffies, end_time)) { + snd_printk("mce_down - " + "auto calibration time out (2)\n"); return; } - msleep(10); + msleep(1); spin_lock_irqsave(&chip->lock, flags); } - /* in 10ms increments, check condition, up to 100ms */ - timeout = 10; - while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) { + /* check condition up to 100ms */ + end_time = jiffies + msecs_to_jiffies(100); + while (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) { spin_unlock_irqrestore(&chip->lock, flags); - if (--timeout < 0) { - snd_printk("mce_down - auto calibration time out (3)\n"); + if (time_after(jiffies, end_time)) { + snd_printk("mce_down - " + "auto calibration time out (3)\n"); return; } - msleep(10); + msleep(1); spin_lock_irqsave(&chip->lock, flags); } spin_unlock_irqrestore(&chip->lock, flags); @@ -611,7 +473,8 @@ static void snd_cs4231_advance_dma(struct cs4231_dma_control *dma_cont, BUG_ON(period_size >= (1 << 24)); - if (dma_cont->request(dma_cont, runtime->dma_addr + offset, period_size)) + if (dma_cont->request(dma_cont, + runtime->dma_addr + offset, period_size)) return; (*periods_sent) = ((*periods_sent) + 1) % runtime->periods; } @@ -704,21 +567,32 @@ static unsigned char snd_cs4231_get_rate(unsigned int rate) for (i = 0; i < 14; i++) if (rate == rates[i]) return freq_bits[i]; - // snd_BUG(); + return freq_bits[13]; } -static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, int channels) +static unsigned char snd_cs4231_get_format(struct snd_cs4231 *chip, int format, + int channels) { unsigned char rformat; rformat = CS4231_LINEAR_8; switch (format) { - case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break; - case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break; - case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break; - case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break; - case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break; + case SNDRV_PCM_FORMAT_MU_LAW: + rformat = CS4231_ULAW_8; + break; + case SNDRV_PCM_FORMAT_A_LAW: + rformat = CS4231_ALAW_8; + break; + case SNDRV_PCM_FORMAT_S16_LE: + rformat = CS4231_LINEAR_16; + break; + case SNDRV_PCM_FORMAT_S16_BE: + rformat = CS4231_LINEAR_16_BIG; + break; + case SNDRV_PCM_FORMAT_IMA_ADPCM: + rformat = CS4231_ADPCM_16; + break; } if (channels > 1) rformat |= CS4231_STEREO; @@ -765,7 +639,8 @@ static void snd_cs4231_calibrate_mute(struct snd_cs4231 *chip, int mute) spin_unlock_irqrestore(&chip->lock, flags); } -static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, +static void snd_cs4231_playback_format(struct snd_cs4231 *chip, + struct snd_pcm_hw_params *params, unsigned char pdfr) { unsigned long flags; @@ -788,8 +663,9 @@ static void snd_cs4231_playback_format(struct snd_cs4231 *chip, struct snd_pcm_h mutex_unlock(&chip->mce_mutex); } -static void snd_cs4231_capture_format(struct snd_cs4231 *chip, struct snd_pcm_hw_params *params, - unsigned char cdfr) +static void snd_cs4231_capture_format(struct snd_cs4231 *chip, + struct snd_pcm_hw_params *params, + unsigned char cdfr) { unsigned long flags; @@ -846,7 +722,8 @@ static int snd_cs4231_timer_start(struct snd_timer *timer) chip->image[CS4231_TIMER_LOW] = (unsigned char) ticks); snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE); + chip->image[CS4231_ALT_FEATURE_1] | + CS4231_TIMER_ENABLE); } spin_unlock_irqrestore(&chip->lock, flags); @@ -859,8 +736,9 @@ static int snd_cs4231_timer_stop(struct snd_timer *timer) struct snd_cs4231 *chip = snd_timer_chip(timer); spin_lock_irqsave(&chip->lock, flags); + chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE; snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, - chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE); + chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->lock, flags); return 0; @@ -877,8 +755,10 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) #endif snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | - CS4231_RECORD_ENABLE | CS4231_RECORD_PIO | + chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | + CS4231_PLAYBACK_PIO | + CS4231_RECORD_ENABLE | + CS4231_RECORD_PIO | CS4231_CALIB_MODE); chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB; snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); @@ -891,21 +771,25 @@ static void __init snd_cs4231_init(struct snd_cs4231 *chip) snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]); + snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, + chip->image[CS4231_ALT_FEATURE_1]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); #ifdef SNDRV_DEBUG_MCE - snd_printdd("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]); + snd_printdd("init: (3) - afei = 0x%x\n", + chip->image[CS4231_ALT_FEATURE_1]); #endif spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]); + snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, + chip->image[CS4231_ALT_FEATURE_2]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_up(chip); spin_lock_irqsave(&chip->lock, flags); - snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]); + snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, + chip->image[CS4231_PLAYBK_FORMAT]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); @@ -944,8 +828,8 @@ static int snd_cs4231_open(struct snd_cs4231 *chip, unsigned int mode) CS4231_RECORD_IRQ | CS4231_TIMER_IRQ); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ | CS4231_RECORD_IRQ | @@ -974,8 +858,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) /* disable IRQ */ spin_lock_irqsave(&chip->lock, flags); snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ /* now disable record & playback */ @@ -988,7 +872,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO | CS4231_RECORD_ENABLE | CS4231_RECORD_PIO); - snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]); + snd_cs4231_out(chip, CS4231_IFACE_CTRL, + chip->image[CS4231_IFACE_CTRL]); spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_mce_down(chip); spin_lock_irqsave(&chip->lock, flags); @@ -996,8 +881,8 @@ static void snd_cs4231_close(struct snd_cs4231 *chip, unsigned int mode) /* clear IRQ again */ snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0); - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); /* clear IRQ */ spin_unlock_irqrestore(&chip->lock, flags); snd_cs4231_calibrate_mute(chip, 0); @@ -1017,15 +902,14 @@ static int snd_cs4231_timer_open(struct snd_timer *timer) return 0; } -static int snd_cs4231_timer_close(struct snd_timer * timer) +static int snd_cs4231_timer_close(struct snd_timer *timer) { struct snd_cs4231 *chip = snd_timer_chip(timer); snd_cs4231_close(chip, CS4231_MODE_TIMER); return 0; } -static struct snd_timer_hardware snd_cs4231_timer_table = -{ +static struct snd_timer_hardware snd_cs4231_timer_table = { .flags = SNDRV_TIMER_HW_AUTO, .resolution = 9945, .ticks = 65535, @@ -1047,8 +931,9 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, unsigned char new_pdfr; int err; - if ((err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params))) < 0) + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) return err; new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | @@ -1058,11 +943,6 @@ static int snd_cs4231_playback_hw_params(struct snd_pcm_substream *substream, return 0; } -static int snd_cs4231_playback_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_cs4231_playback_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); @@ -1089,8 +969,9 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, unsigned char new_cdfr; int err; - if ((err = snd_pcm_lib_malloc_pages(substream, - params_buffer_bytes(hw_params))) < 0) + err = snd_pcm_lib_malloc_pages(substream, + params_buffer_bytes(hw_params)); + if (err < 0) return err; new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params), params_channels(hw_params)) | @@ -1100,11 +981,6 @@ static int snd_cs4231_capture_hw_params(struct snd_pcm_substream *substream, return 0; } -static int snd_cs4231_capture_hw_free(struct snd_pcm_substream *substream) -{ - return snd_pcm_lib_free_pages(substream); -} - static int snd_cs4231_capture_prepare(struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); @@ -1130,7 +1006,8 @@ static void snd_cs4231_overrange(struct snd_cs4231 *chip) res = snd_cs4231_in(chip, CS4231_TEST_INIT); spin_unlock_irqrestore(&chip->lock, flags); - if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */ + /* detect overrange only above 0dB; may be user selectable? */ + if (res & (0x08 | 0x02)) chip->capture_substream->runtime->overrange++; } @@ -1152,51 +1029,50 @@ static void snd_cs4231_capture_callback(struct snd_cs4231 *chip) } } -static snd_pcm_uframes_t snd_cs4231_playback_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_cs4231_playback_pointer( + struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct cs4231_dma_control *dma_cont = &chip->p_dma; size_t ptr; - + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) return 0; ptr = dma_cont->address(dma_cont); if (ptr != 0) ptr -= substream->runtime->dma_addr; - + return bytes_to_frames(substream->runtime, ptr); } -static snd_pcm_uframes_t snd_cs4231_capture_pointer(struct snd_pcm_substream *substream) +static snd_pcm_uframes_t snd_cs4231_capture_pointer( + struct snd_pcm_substream *substream) { struct snd_cs4231 *chip = snd_pcm_substream_chip(substream); struct cs4231_dma_control *dma_cont = &chip->c_dma; size_t ptr; - + if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE)) return 0; ptr = dma_cont->address(dma_cont); if (ptr != 0) ptr -= substream->runtime->dma_addr; - + return bytes_to_frames(substream->runtime, ptr); } -/* - - */ - static int __init snd_cs4231_probe(struct snd_cs4231 *chip) { unsigned long flags; - int i, id, vers; + int i; + int id = 0; + int vers = 0; unsigned char *ptr; - id = vers = 0; for (i = 0; i < 50; i++) { mb(); - if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) - udelay(2000); + if (__cs4231_readb(chip, CS4231U(chip, REGSEL)) & CS4231_INIT) + msleep(2); else { spin_lock_irqsave(&chip->lock, flags); snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2); @@ -1213,8 +1089,9 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) spin_lock_irqsave(&chip->lock, flags); - __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */ - __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); + /* clear any pendings IRQ */ + __cs4231_readb(chip, CS4231U(chip, STATUS)); + __cs4231_writeb(chip, 0, CS4231U(chip, STATUS)); mb(); spin_unlock_irqrestore(&chip->lock, flags); @@ -1247,42 +1124,50 @@ static int __init snd_cs4231_probe(struct snd_cs4231 *chip) return 0; /* all things are ok.. */ } -static struct snd_pcm_hardware snd_cs4231_playback = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, +static struct snd_pcm_hardware snd_cs4231_playback = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_8000_48000, .rate_min = 5510, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (32*1024), + .buffer_bytes_max = 32 * 1024, .period_bytes_min = 64, - .period_bytes_max = (32*1024), + .period_bytes_max = 32 * 1024, .periods_min = 1, .periods_max = 1024, }; -static struct snd_pcm_hardware snd_cs4231_capture = -{ - .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START), - .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_IMA_ADPCM | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE | - SNDRV_PCM_FMTBIT_S16_BE), - .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000, +static struct snd_pcm_hardware snd_cs4231_capture = { + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_SYNC_START, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_IMA_ADPCM | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_LE | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_KNOT | + SNDRV_PCM_RATE_8000_48000, .rate_min = 5510, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (32*1024), + .buffer_bytes_max = 32 * 1024, .period_bytes_min = 64, - .period_bytes_max = (32*1024), + .period_bytes_max = 32 * 1024, .periods_min = 1, .periods_max = 1024, }; @@ -1295,7 +1180,8 @@ static int snd_cs4231_playback_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_playback; - if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) { + err = snd_cs4231_open(chip, CS4231_MODE_PLAY); + if (err < 0) { snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } @@ -1315,7 +1201,8 @@ static int snd_cs4231_capture_open(struct snd_pcm_substream *substream) runtime->hw = snd_cs4231_capture; - if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) { + err = snd_cs4231_open(chip, CS4231_MODE_RECORD); + if (err < 0) { snd_free_pages(runtime->dma_area, runtime->dma_bytes); return err; } @@ -1356,7 +1243,7 @@ static struct snd_pcm_ops snd_cs4231_playback_ops = { .close = snd_cs4231_playback_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs4231_playback_hw_params, - .hw_free = snd_cs4231_playback_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = snd_cs4231_playback_prepare, .trigger = snd_cs4231_trigger, .pointer = snd_cs4231_playback_pointer, @@ -1367,23 +1254,27 @@ static struct snd_pcm_ops snd_cs4231_capture_ops = { .close = snd_cs4231_capture_close, .ioctl = snd_pcm_lib_ioctl, .hw_params = snd_cs4231_capture_hw_params, - .hw_free = snd_cs4231_capture_hw_free, + .hw_free = snd_pcm_lib_free_pages, .prepare = snd_cs4231_capture_prepare, .trigger = snd_cs4231_trigger, .pointer = snd_cs4231_capture_pointer, }; -static int __init snd_cs4231_pcm(struct snd_cs4231 *chip) +static int __init snd_cs4231_pcm(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0) + err = snd_pcm_new(card, "CS4231", 0, 1, 1, &pcm); + if (err < 0) return err; - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops); - snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops); - + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, + &snd_cs4231_playback_ops); + snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, + &snd_cs4231_capture_ops); + /* global setup */ pcm->private_data = chip; pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX; @@ -1396,8 +1287,9 @@ static int __init snd_cs4231_pcm(struct snd_cs4231 *chip) return 0; } -static int __init snd_cs4231_timer(struct snd_cs4231 *chip) +static int __init snd_cs4231_timer(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; struct snd_timer *timer; struct snd_timer_id tid; int err; @@ -1405,10 +1297,11 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) /* Timer initialization */ tid.dev_class = SNDRV_TIMER_CLASS_CARD; tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE; - tid.card = chip->card->number; + tid.card = card->number; tid.device = 0; tid.subdevice = 0; - if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0) + err = snd_timer_new(card, "CS4231", &tid, &timer); + if (err < 0) return err; strcpy(timer->name, "CS4231"); timer->private_data = chip; @@ -1417,7 +1310,7 @@ static int __init snd_cs4231_timer(struct snd_cs4231 *chip) return 0; } - + /* * MIXER part */ @@ -1428,15 +1321,14 @@ static int snd_cs4231_info_mux(struct snd_kcontrol *kcontrol, static char *texts[4] = { "Line", "CD", "Mic", "Mix" }; - struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); - snd_assert(chip->card != NULL, return -EINVAL); uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; uinfo->count = 2; uinfo->value.enumerated.items = 4; if (uinfo->value.enumerated.item > 3) uinfo->value.enumerated.item = 3; - strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]); + strcpy(uinfo->value.enumerated.name, + texts[uinfo->value.enumerated.item]); return 0; } @@ -1446,7 +1338,7 @@ static int snd_cs4231_get_mux(struct snd_kcontrol *kcontrol, { struct snd_cs4231 *chip = snd_kcontrol_chip(kcontrol); unsigned long flags; - + spin_lock_irqsave(&chip->lock, flags); ucontrol->value.enumerated.item[0] = (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6; @@ -1464,7 +1356,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, unsigned long flags; unsigned short left, right; int change; - + if (ucontrol->value.enumerated.item[0] > 3 || ucontrol->value.enumerated.item[1] > 3) return -EINVAL; @@ -1476,7 +1368,7 @@ static int snd_cs4231_put_mux(struct snd_kcontrol *kcontrol, left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left; right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right; change = left != chip->image[CS4231_LEFT_INPUT] || - right != chip->image[CS4231_RIGHT_INPUT]; + right != chip->image[CS4231_RIGHT_INPUT]; snd_cs4231_out(chip, CS4231_LEFT_INPUT, left); snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right); @@ -1508,7 +1400,7 @@ static int snd_cs4231_get_single(struct snd_kcontrol *kcontrol, int shift = (kcontrol->private_value >> 8) & 0xff; int mask = (kcontrol->private_value >> 16) & 0xff; int invert = (kcontrol->private_value >> 24) & 0xff; - + spin_lock_irqsave(&chip->lock, flags); ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask; @@ -1533,7 +1425,7 @@ static int snd_cs4231_put_single(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 0xff; int change; unsigned short val; - + val = (ucontrol->value.integer.value[0] & mask); if (invert) val = mask - val; @@ -1575,11 +1467,13 @@ static int snd_cs4231_get_double(struct snd_kcontrol *kcontrol, int shift_right = (kcontrol->private_value >> 19) & 0x07; int mask = (kcontrol->private_value >> 24) & 0xff; int invert = (kcontrol->private_value >> 22) & 1; - + spin_lock_irqsave(&chip->lock, flags); - ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask; - ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask; + ucontrol->value.integer.value[0] = + (chip->image[left_reg] >> shift_left) & mask; + ucontrol->value.integer.value[1] = + (chip->image[right_reg] >> shift_right) & mask; spin_unlock_irqrestore(&chip->lock, flags); @@ -1606,7 +1500,7 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 22) & 1; int change; unsigned short val1, val2; - + val1 = ucontrol->value.integer.value[0] & mask; val2 = ucontrol->value.integer.value[1] & mask; if (invert) { @@ -1620,7 +1514,8 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1; val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2; - change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg]; + change = val1 != chip->image[left_reg]; + change |= val2 != chip->image[right_reg]; snd_cs4231_out(chip, left_reg, val1); snd_cs4231_out(chip, right_reg, val2); @@ -1630,31 +1525,42 @@ static int snd_cs4231_put_double(struct snd_kcontrol *kcontrol, } #define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_single, \ - .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ - .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) } - -#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \ - .info = snd_cs4231_info_double, \ - .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ - .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) } +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ + .info = snd_cs4231_info_single, \ + .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \ + .private_value = (reg) | ((shift) << 8) | ((mask) << 16) | ((invert) << 24) } + +#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, \ + shift_right, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), .index = (xindex), \ + .info = snd_cs4231_info_double, \ + .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \ + .private_value = (left_reg) | ((right_reg) << 8) | ((shift_left) << 16) | \ + ((shift_right) << 19) | ((mask) << 24) | ((invert) << 22) } static struct snd_kcontrol_new snd_cs4231_controls[] __initdata = { -CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), -CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), -CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), -CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), -CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), -CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), +CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, + CS4231_RIGHT_OUTPUT, 7, 7, 1, 1), +CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, + CS4231_RIGHT_OUTPUT, 0, 0, 63, 1), +CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, + CS4231_RIGHT_LINE_IN, 7, 7, 1, 1), +CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, + CS4231_RIGHT_LINE_IN, 0, 0, 31, 1), +CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, + CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, + CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1), +CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, + CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1), +CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, + CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1), CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1), CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1), CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1), CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0), -CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0), +CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, + 15, 0), { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "Capture Source", @@ -1662,29 +1568,28 @@ CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, .get = snd_cs4231_get_mux, .put = snd_cs4231_put_mux, }, -CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0), +CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, + 1, 0), CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0), CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1), /* SPARC specific uses of XCTL{0,1} general purpose outputs. */ CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1), CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1) }; - -static int __init snd_cs4231_mixer(struct snd_cs4231 *chip) + +static int __init snd_cs4231_mixer(struct snd_card *card) { - struct snd_card *card; + struct snd_cs4231 *chip = card->private_data; int err, idx; snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL); - card = chip->card; - strcpy(card->mixername, chip->pcm->name); for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) { - if ((err = snd_ctl_add(card, - snd_ctl_new1(&snd_cs4231_controls[idx], - chip))) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&snd_cs4231_controls[idx], chip)); + if (err < 0) return err; } return 0; @@ -1695,6 +1600,7 @@ static int dev; static int __init cs4231_attach_begin(struct snd_card **rcard) { struct snd_card *card; + struct snd_cs4231 *chip; *rcard = NULL; @@ -1706,31 +1612,40 @@ static int __init cs4231_attach_begin(struct snd_card **rcard) return -ENOENT; } - card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0); + card = snd_card_new(index[dev], id[dev], THIS_MODULE, + sizeof(struct snd_cs4231)); if (card == NULL) return -ENOMEM; strcpy(card->driver, "CS4231"); strcpy(card->shortname, "Sun CS4231"); + chip = card->private_data; + chip->card = card; + *rcard = card; return 0; } -static int __init cs4231_attach_finish(struct snd_card *card, struct snd_cs4231 *chip) +static int __init cs4231_attach_finish(struct snd_card *card) { + struct snd_cs4231 *chip = card->private_data; int err; - if ((err = snd_cs4231_pcm(chip)) < 0) + err = snd_cs4231_pcm(card); + if (err < 0) goto out_err; - if ((err = snd_cs4231_mixer(chip)) < 0) + err = snd_cs4231_mixer(card); + if (err < 0) goto out_err; - if ((err = snd_cs4231_timer(chip)) < 0) + err = snd_cs4231_timer(card); + if (err < 0) goto out_err; - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto out_err; chip->next = cs4231_list; @@ -1754,7 +1669,7 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) struct snd_cs4231 *chip = dev_id; /*This is IRQ is not raised by the cs4231*/ - if (!(__cs4231_readb(chip, CS4231P(chip, STATUS)) & CS4231_GLOBALIRQ)) + if (!(__cs4231_readb(chip, CS4231U(chip, STATUS)) & CS4231_GLOBALIRQ)) return IRQ_NONE; /* ACK the APC interrupt. */ @@ -1762,24 +1677,24 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) sbus_writel(csr, chip->port + APCCSR); - if ((csr & APC_PDMA_READY) && - (csr & APC_PLAY_INT) && + if ((csr & APC_PDMA_READY) && + (csr & APC_PLAY_INT) && (csr & APC_XINT_PNVA) && !(csr & APC_XINT_EMPT)) snd_cs4231_play_callback(chip); - if ((csr & APC_CDMA_READY) && - (csr & APC_CAPT_INT) && + if ((csr & APC_CDMA_READY) && + (csr & APC_CAPT_INT) && (csr & APC_XINT_CNVA) && !(csr & APC_XINT_EMPT)) snd_cs4231_capture_callback(chip); - + status = snd_cs4231_in(chip, CS4231_IRQ_STATUS); if (status & CS4231_TIMER_IRQ) { if (chip->timer) snd_timer_interrupt(chip->timer, chip->timer->sticks); - } + } if ((status & CS4231_RECORD_IRQ) && (csr & APC_CDMA_READY)) snd_cs4231_overrange(chip); @@ -1796,26 +1711,27 @@ static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id) * SBUS DMA routines */ -static int sbus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +static int sbus_dma_request(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len) { unsigned long flags; u32 test, csr; int err; struct sbus_dma_info *base = &dma_cont->sbus_info; - + if (len >= (1 << 24)) return -EINVAL; spin_lock_irqsave(&base->lock, flags); csr = sbus_readl(base->regs + APCCSR); err = -EINVAL; test = APC_CDMA_READY; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) test = APC_PDMA_READY; if (!(csr & test)) goto out; err = -EBUSY; test = APC_XINT_CNVA; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) test = APC_XINT_PNVA; if (!(csr & test)) goto out; @@ -1838,7 +1754,7 @@ static void sbus_dma_prepare(struct cs4231_dma_control *dma_cont, int d) test = APC_GENL_INT | APC_PLAY_INT | APC_XINT_ENA | APC_XINT_PLAY | APC_XINT_PEMP | APC_XINT_GENL | APC_XINT_PENA; - if ( base->dir == APC_RECORD ) + if (base->dir == APC_RECORD) test = APC_GENL_INT | APC_CAPT_INT | APC_XINT_ENA | APC_XINT_CAPT | APC_XINT_CEMP | APC_XINT_GENL; csr |= test; @@ -1856,28 +1772,28 @@ static void sbus_dma_enable(struct cs4231_dma_control *dma_cont, int on) if (!on) { sbus_writel(0, base->regs + base->dir + APCNC); sbus_writel(0, base->regs + base->dir + APCNVA); - if ( base->dir == APC_PLAY ) { + if (base->dir == APC_PLAY) { sbus_writel(0, base->regs + base->dir + APCC); sbus_writel(0, base->regs + base->dir + APCVA); } udelay(1200); - } + } csr = sbus_readl(base->regs + APCCSR); shift = 0; - if ( base->dir == APC_PLAY ) + if (base->dir == APC_PLAY) shift = 1; if (on) csr &= ~(APC_CPAUSE << shift); else - csr |= (APC_CPAUSE << shift); + csr |= (APC_CPAUSE << shift); sbus_writel(csr, base->regs + APCCSR); if (on) csr |= (APC_CDMA_READY << shift); else csr &= ~(APC_CDMA_READY << shift); sbus_writel(csr, base->regs + APCCSR); - + spin_unlock_irqrestore(&base->lock, flags); } @@ -1885,14 +1801,14 @@ static unsigned int sbus_dma_addr(struct cs4231_dma_control *dma_cont) { struct sbus_dma_info *base = &dma_cont->sbus_info; - return sbus_readl(base->regs + base->dir + APCVA); + return sbus_readl(base->regs + base->dir + APCVA); } static void sbus_dma_preallocate(struct snd_cs4231 *chip, struct snd_pcm *pcm) { snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS, - snd_dma_sbus_data(chip->dev_u.sdev), - 64*1024, 128*1024); + snd_dma_sbus_data(chip->dev_u.sdev), + 64 * 1024, 128 * 1024); } /* @@ -1907,8 +1823,6 @@ static int snd_cs4231_sbus_free(struct snd_cs4231 *chip) if (chip->port) sbus_iounmap(chip->port, chip->regs_size); - kfree(chip); - return 0; } @@ -1925,23 +1839,16 @@ static struct snd_device_ops snd_cs4231_sbus_dev_ops = { static int __init snd_cs4231_sbus_create(struct snd_card *card, struct sbus_dev *sdev, - int dev, - struct snd_cs4231 **rchip) + int dev) { - struct snd_cs4231 *chip; + struct snd_cs4231 *chip = card->private_data; int err; - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); spin_lock_init(&chip->c_dma.sbus_info.lock); spin_lock_init(&chip->p_dma.sbus_info.lock); mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); - chip->card = card; chip->dev_u.sdev = sdev; chip->regs_size = sdev->reg_addrs[0].reg_size; memcpy(&chip->image, &snd_cs4231_original_image, @@ -1992,14 +1899,12 @@ static int __init snd_cs4231_sbus_create(struct snd_card *card, return err; } - *rchip = chip; return 0; } static int __init cs4231_sbus_attach(struct sbus_dev *sdev) { struct resource *rp = &sdev->resource[0]; - struct snd_cs4231 *cp; struct snd_card *card; int err; @@ -2013,25 +1918,28 @@ static int __init cs4231_sbus_attach(struct sbus_dev *sdev) (unsigned long long)rp->start, sdev->irqs[0]); - if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) { + err = snd_cs4231_sbus_create(card, sdev, dev); + if (err < 0) { snd_card_free(card); return err; } - return cs4231_attach_finish(card, cp); + return cs4231_attach_finish(card); } #endif #ifdef EBUS_SUPPORT -static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, + void *cookie) { struct snd_cs4231 *chip = cookie; - + snd_cs4231_play_callback(chip); } -static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie) +static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, + int event, void *cookie) { struct snd_cs4231 *chip = cookie; @@ -2042,7 +1950,8 @@ static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, * EBUS DMA wrappers */ -static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, dma_addr_t bus_addr, size_t len) +static int _ebus_dma_request(struct cs4231_dma_control *dma_cont, + dma_addr_t bus_addr, size_t len) { return ebus_dma_request(&dma_cont->ebus_info, bus_addr, len); } @@ -2087,8 +1996,6 @@ static int snd_cs4231_ebus_free(struct snd_cs4231 *chip) if (chip->port) iounmap(chip->port); - kfree(chip); - return 0; } @@ -2105,24 +2012,17 @@ static struct snd_device_ops snd_cs4231_ebus_dev_ops = { static int __init snd_cs4231_ebus_create(struct snd_card *card, struct linux_ebus_device *edev, - int dev, - struct snd_cs4231 **rchip) + int dev) { - struct snd_cs4231 *chip; + struct snd_cs4231 *chip = card->private_data; int err; - *rchip = NULL; - chip = kzalloc(sizeof(*chip), GFP_KERNEL); - if (chip == NULL) - return -ENOMEM; - spin_lock_init(&chip->lock); spin_lock_init(&chip->c_dma.ebus_info.lock); spin_lock_init(&chip->p_dma.ebus_info.lock); mutex_init(&chip->mce_mutex); mutex_init(&chip->open_mutex); chip->flags |= CS4231_FLAG_EBUS; - chip->card = card; chip->dev_u.pdev = edev->bus->self; memcpy(&chip->image, &snd_cs4231_original_image, sizeof(snd_cs4231_original_image)); @@ -2152,7 +2052,8 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, chip->port = ioremap(edev->resource[0].start, 0x10); chip->p_dma.ebus_info.regs = ioremap(edev->resource[1].start, 0x10); chip->c_dma.ebus_info.regs = ioremap(edev->resource[2].start, 0x10); - if (!chip->port || !chip->p_dma.ebus_info.regs || !chip->c_dma.ebus_info.regs) { + if (!chip->port || !chip->p_dma.ebus_info.regs || + !chip->c_dma.ebus_info.regs) { snd_cs4231_ebus_free(chip); snd_printdd("cs4231-%d: Unable to map chip registers.\n", dev); return -EIO; @@ -2160,18 +2061,21 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, if (ebus_dma_register(&chip->c_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS capture DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->c_dma.ebus_info, 1)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev); + snd_printdd("cs4231-%d: Unable to enable EBUS capture IRQ\n", + dev); return -EBUSY; } if (ebus_dma_register(&chip->p_dma.ebus_info)) { snd_cs4231_ebus_free(chip); - snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", dev); + snd_printdd("cs4231-%d: Unable to register EBUS play DMA\n", + dev); return -EBUSY; } if (ebus_dma_irq_enable(&chip->p_dma.ebus_info, 1)) { @@ -2192,14 +2096,12 @@ static int __init snd_cs4231_ebus_create(struct snd_card *card, return err; } - *rchip = chip; return 0; } static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) { struct snd_card *card; - struct snd_cs4231 *chip; int err; err = cs4231_attach_begin(&card); @@ -2211,12 +2113,13 @@ static int __init cs4231_ebus_attach(struct linux_ebus_device *edev) edev->resource[0].start, edev->irqs[0]); - if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) { + err = snd_cs4231_ebus_create(card, edev, dev); + if (err < 0) { snd_card_free(card); return err; } - return cs4231_attach_finish(card, chip); + return cs4231_attach_finish(card); } #endif diff --git a/sound/sparc/dbri.c b/sound/sparc/dbri.c index e07085a7cfc..376b98691c9 100644 --- a/sound/sparc/dbri.c +++ b/sound/sparc/dbri.c @@ -8,18 +8,18 @@ * Copyright (C) 1997 Rudolf Koenig (rfkoenig@immd4.informatik.uni-erlangen.de) * Copyright (C) 1998, 1999 Brent Baccala (baccala@freesoft.org) * - * This is the lowlevel driver for the DBRI & MMCODEC duo used for ISDN & AUDIO - * on Sun SPARCstation 10, 20, LX and Voyager models. + * This is the low level driver for the DBRI & MMCODEC duo used for ISDN & AUDIO + * on Sun SPARCStation 10, 20, LX and Voyager models. * * - DBRI: AT&T T5900FX Dual Basic Rates ISDN Interface. It is a 32 channel * data time multiplexer with ISDN support (aka T7259) * Interfaces: SBus,ISDN NT & TE, CHI, 4 bits parallel. * CHI: (spelled ki) Concentration Highway Interface (AT&T or Intel bus ?). * Documentation: - * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Tranceiver" from + * - "STP 4000SBus Dual Basic Rate ISDN (DBRI) Transceiver" from * Sparc Technology Business (courtesy of Sun Support) * - Data sheet of the T7903, a newer but very similar ISA bus equivalent - * available from the Lucent (formarly AT&T microelectronics) home + * available from the Lucent (formerly AT&T microelectronics) home * page. * - http://www.freesoft.org/Linux/DBRI/ * - MMCODEC: Crystal Semiconductor CS4215 16 bit Multimedia Audio Codec @@ -27,21 +27,21 @@ * Documentation: from the Crystal Semiconductor home page. * * The DBRI is a 32 pipe machine, each pipe can transfer some bits between - * memory and a serial device (long pipes, nr 0-15) or between two serial - * devices (short pipes, nr 16-31), or simply send a fixed data to a serial + * memory and a serial device (long pipes, no. 0-15) or between two serial + * devices (short pipes, no. 16-31), or simply send a fixed data to a serial * device (short pipes). - * A timeslot defines the bit-offset and nr of bits read from a serial device. + * A timeslot defines the bit-offset and no. of bits read from a serial device. * The timeslots are linked to 6 circular lists, one for each direction for * each serial device (NT,TE,CHI). A timeslot is associated to 1 or 2 pipes * (the second one is a monitor/tee pipe, valid only for serial input). * * The mmcodec is connected via the CHI bus and needs the data & some - * parameters (volume, output selection) timemultiplexed in 8 byte + * parameters (volume, output selection) time multiplexed in 8 byte * chunks. It also has a control mode, which serves for audio format setting. * * Looking at the CS4215 data sheet it is easy to set up 2 or 4 codecs on - * the same CHI bus, so I thought perhaps it is possible to use the onboard - * & the speakerbox codec simultanously, giving 2 (not very independent :-) + * the same CHI bus, so I thought perhaps it is possible to use the on-board + * & the speakerbox codec simultaneously, giving 2 (not very independent :-) * audio devices. But the SUN HW group decided against it, at least on my * LX the speakerbox connector has at least 1 pin missing and 1 wrongly * connected. @@ -56,6 +56,8 @@ #include <sound/driver.h> #include <linux/interrupt.h> #include <linux/delay.h> +#include <linux/irq.h> +#include <linux/io.h> #include <sound/core.h> #include <sound/pcm.h> @@ -64,8 +66,7 @@ #include <sound/control.h> #include <sound/initval.h> -#include <asm/irq.h> -#include <asm/io.h> +#include <linux/of.h> #include <asm/sbus.h> #include <asm/atomic.h> @@ -76,7 +77,8 @@ MODULE_SUPPORTED_DEVICE("{{Sun,DBRI}}"); static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */ static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */ -static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */ +/* Enable this card */ +static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for Sun DBRI soundcard."); @@ -104,7 +106,7 @@ static char *cmds[] = { "SSP", "CHI", "NT", "TE", "CDEC", "TEST", "CDM", "RESRV" }; -#define dprintk(a, x...) if(dbri_debug & a) printk(KERN_DEBUG x) +#define dprintk(a, x...) if (dbri_debug & a) printk(KERN_DEBUG x) #else #define dprintk(a, x...) do { } while (0) @@ -131,7 +133,7 @@ struct cs4215 { }; /* - * Control mode first + * Control mode first */ /* Time Slot 1, Status register */ @@ -219,7 +221,7 @@ static struct { /* Time Slot 7, Input Setting */ #define CS4215_LG(v) v /* Left Gain Setting 0xf: 22.5 dB */ #define CS4215_IS (1<<4) /* Input Select: 1=Microphone, 0=Line */ -#define CS4215_OVR (1<<5) /* 1: Overrange condition occurred */ +#define CS4215_OVR (1<<5) /* 1: Over range condition occurred */ #define CS4215_PIO0 (1<<6) /* Parallel I/O 0 */ #define CS4215_PIO1 (1<<7) @@ -232,12 +234,12 @@ static struct { ****************************************************************************/ /* DBRI main registers */ -#define REG0 0x00UL /* Status and Control */ -#define REG1 0x04UL /* Mode and Interrupt */ -#define REG2 0x08UL /* Parallel IO */ -#define REG3 0x0cUL /* Test */ -#define REG8 0x20UL /* Command Queue Pointer */ -#define REG9 0x24UL /* Interrupt Queue Pointer */ +#define REG0 0x00 /* Status and Control */ +#define REG1 0x04 /* Mode and Interrupt */ +#define REG2 0x08 /* Parallel IO */ +#define REG3 0x0c /* Test */ +#define REG8 0x20 /* Command Queue Pointer */ +#define REG9 0x24 /* Interrupt Queue Pointer */ #define DBRI_NO_CMDS 64 #define DBRI_INT_BLK 64 @@ -285,7 +287,7 @@ struct dbri_pipe { /* Per stream (playback or record) information */ struct dbri_streaminfo { struct snd_pcm_substream *substream; - u32 dvma_buffer; /* Device view of Alsa DMA buffer */ + u32 dvma_buffer; /* Device view of ALSA DMA buffer */ int size; /* Size of DMA buffer */ size_t offset; /* offset in user buffer */ int pipe; /* Data pipe used */ @@ -295,8 +297,6 @@ struct dbri_streaminfo { /* This structure holds the information for both chips (DBRI & CS4215) */ struct snd_dbri { - struct snd_card *card; /* ALSA card */ - int regs_size, irq; /* Needed for unload */ struct sbus_dev *sdev; /* SBUS device info */ spinlock_t lock; @@ -317,8 +317,6 @@ struct snd_dbri { struct cs4215 mm; /* mmcodec special info */ /* per stream (playback/record) info */ struct dbri_streaminfo stream_info[DBRI_NO_STREAMS]; - - struct snd_dbri *next; }; #define DBRI_MAX_VOLUME 63 /* Output volume */ @@ -341,11 +339,11 @@ struct snd_dbri { /* DBRI Reg1 - Mode and Interrupt Register - defines. (Page 18) */ #define D_LITTLE_END (1<<8) /* Byte Order */ #define D_BIG_END (0<<8) /* Byte Order */ -#define D_MRR (1<<4) /* Multiple Error Ack on SBus (readonly) */ -#define D_MLE (1<<3) /* Multiple Late Error on SBus (readonly) */ -#define D_LBG (1<<2) /* Lost Bus Grant on SBus (readonly) */ -#define D_MBE (1<<1) /* Burst Error on SBus (readonly) */ -#define D_IR (1<<0) /* Interrupt Indicator (readonly) */ +#define D_MRR (1<<4) /* Multiple Error Ack on SBus (read only) */ +#define D_MLE (1<<3) /* Multiple Late Error on SBus (read only) */ +#define D_LBG (1<<2) /* Lost Bus Grant on SBus (read only) */ +#define D_MBE (1<<1) /* Burst Error on SBus (read only) */ +#define D_IR (1<<0) /* Interrupt Indicator (read only) */ /* DBRI Reg2 - Parallel IO Register - defines. (Page 18) */ #define D_ENPIO3 (1<<7) /* Enable Pin 3 */ @@ -376,11 +374,11 @@ struct snd_dbri { #define D_CDM 0xe /* CHI Data mode command */ /* Special bits for some commands */ -#define D_PIPE(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ +#define D_PIPE(v) ((v)<<0) /* Pipe No.: 0-15 long, 16-21 short */ /* Setup Data Pipe */ /* IRM */ -#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value rcvd */ +#define D_SDP_2SAME (1<<18) /* Report 2nd time in a row value received */ #define D_SDP_CHANGE (2<<18) /* Report any changes */ #define D_SDP_EVERY (3<<18) /* Report any changes */ #define D_SDP_EOL (1<<17) /* EOL interrupt enable */ @@ -419,7 +417,7 @@ struct snd_dbri { #define D_TS_NONCONTIG (3<<10) /* Non contiguous mode */ #define D_TS_ANCHOR (7<<10) /* Starting short pipes */ #define D_TS_MON(v) ((v)<<5) /* Monitor Pipe */ -#define D_TS_NEXT(v) ((v)<<0) /* Pipe Nr: 0-15 long, 16-21 short */ +#define D_TS_NEXT(v) ((v)<<0) /* Pipe no.: 0-15 long, 16-21 short */ /* Concentration Highway Interface Modes */ #define D_CHI_CHICM(v) ((v)<<16) /* Clock mode */ @@ -435,7 +433,7 @@ struct snd_dbri { #define D_NT_NBF (1<<16) /* Number of bad frames to loose framing */ #define D_NT_IRM_IMM (1<<15) /* Interrupt Report & Mask: Immediate */ #define D_NT_IRM_EN (1<<14) /* Interrupt Report & Mask: Enable */ -#define D_NT_ISNT (1<<13) /* Configfure interface as NT */ +#define D_NT_ISNT (1<<13) /* Configure interface as NT */ #define D_NT_FT (1<<12) /* Fixed Timing */ #define D_NT_EZ (1<<11) /* Echo Channel is Zeros */ #define D_NT_IFA (1<<10) /* Inhibit Final Activation */ @@ -455,7 +453,7 @@ struct snd_dbri { #define D_TEST_RAM(v) ((v)<<16) /* RAM Pointer */ #define D_TEST_SIZE(v) ((v)<<11) /* */ #define D_TEST_ROMONOFF 0x5 /* Toggle ROM opcode monitor on/off */ -#define D_TEST_PROC 0x6 /* MicroProcessor test */ +#define D_TEST_PROC 0x6 /* Microprocessor test */ #define D_TEST_SER 0x7 /* Serial-Controller test */ #define D_TEST_RAMREAD 0x8 /* Copy from Ram to system memory */ #define D_TEST_RAMWRITE 0x9 /* Copy into Ram from system memory */ @@ -464,12 +462,12 @@ struct snd_dbri { #define D_TEST_DUMP 0xe /* ROM Dump */ /* CHI Data Mode */ -#define D_CDM_THI (1<<8) /* Transmit Data on CHIDR Pin */ -#define D_CDM_RHI (1<<7) /* Receive Data on CHIDX Pin */ -#define D_CDM_RCE (1<<6) /* Receive on Rising Edge of CHICK */ -#define D_CDM_XCE (1<<2) /* Transmit Data on Rising Edge of CHICK */ -#define D_CDM_XEN (1<<1) /* Transmit Highway Enable */ -#define D_CDM_REN (1<<0) /* Receive Highway Enable */ +#define D_CDM_THI (1 << 8) /* Transmit Data on CHIDR Pin */ +#define D_CDM_RHI (1 << 7) /* Receive Data on CHIDX Pin */ +#define D_CDM_RCE (1 << 6) /* Receive on Rising Edge of CHICK */ +#define D_CDM_XCE (1 << 2) /* Transmit Data on Rising Edge of CHICK */ +#define D_CDM_XEN (1 << 1) /* Transmit Highway Enable */ +#define D_CDM_REN (1 << 0) /* Receive Highway Enable */ /* The Interrupts */ #define D_INTR_BRDY 1 /* Buffer Ready for processing */ @@ -493,9 +491,9 @@ struct snd_dbri { #define D_INTR_CHI 36 #define D_INTR_CMD 38 -#define D_INTR_GETCHAN(v) (((v)>>24) & 0x3f) -#define D_INTR_GETCODE(v) (((v)>>20) & 0xf) -#define D_INTR_GETCMD(v) (((v)>>16) & 0xf) +#define D_INTR_GETCHAN(v) (((v) >> 24) & 0x3f) +#define D_INTR_GETCODE(v) (((v) >> 20) & 0xf) +#define D_INTR_GETCMD(v) (((v) >> 16) & 0xf) #define D_INTR_GETVAL(v) ((v) & 0xffff) #define D_INTR_GETRVAL(v) ((v) & 0xfffff) @@ -533,43 +531,42 @@ struct snd_dbri { #define D_P_31 31 /* */ /* Transmit descriptor defines */ -#define DBRI_TD_F (1<<31) /* End of Frame */ -#define DBRI_TD_D (1<<30) /* Do not append CRC */ -#define DBRI_TD_CNT(v) ((v)<<16) /* Number of valid bytes in the buffer */ -#define DBRI_TD_B (1<<15) /* Final interrupt */ -#define DBRI_TD_M (1<<14) /* Marker interrupt */ -#define DBRI_TD_I (1<<13) /* Transmit Idle Characters */ -#define DBRI_TD_FCNT(v) (v) /* Flag Count */ -#define DBRI_TD_UNR (1<<3) /* Underrun: transmitter is out of data */ -#define DBRI_TD_ABT (1<<2) /* Abort: frame aborted */ -#define DBRI_TD_TBC (1<<0) /* Transmit buffer Complete */ -#define DBRI_TD_STATUS(v) ((v)&0xff) /* Transmit status */ - /* Maximum buffer size per TD: almost 8Kb */ +#define DBRI_TD_F (1 << 31) /* End of Frame */ +#define DBRI_TD_D (1 << 30) /* Do not append CRC */ +#define DBRI_TD_CNT(v) ((v) << 16) /* Number of valid bytes in the buffer */ +#define DBRI_TD_B (1 << 15) /* Final interrupt */ +#define DBRI_TD_M (1 << 14) /* Marker interrupt */ +#define DBRI_TD_I (1 << 13) /* Transmit Idle Characters */ +#define DBRI_TD_FCNT(v) (v) /* Flag Count */ +#define DBRI_TD_UNR (1 << 3) /* Underrun: transmitter is out of data */ +#define DBRI_TD_ABT (1 << 2) /* Abort: frame aborted */ +#define DBRI_TD_TBC (1 << 0) /* Transmit buffer Complete */ +#define DBRI_TD_STATUS(v) ((v) & 0xff) /* Transmit status */ + /* Maximum buffer size per TD: almost 8KB */ #define DBRI_TD_MAXCNT ((1 << 13) - 4) /* Receive descriptor defines */ -#define DBRI_RD_F (1<<31) /* End of Frame */ -#define DBRI_RD_C (1<<30) /* Completed buffer */ -#define DBRI_RD_B (1<<15) /* Final interrupt */ -#define DBRI_RD_M (1<<14) /* Marker interrupt */ -#define DBRI_RD_BCNT(v) (v) /* Buffer size */ -#define DBRI_RD_CRC (1<<7) /* 0: CRC is correct */ -#define DBRI_RD_BBC (1<<6) /* 1: Bad Byte received */ -#define DBRI_RD_ABT (1<<5) /* Abort: frame aborted */ -#define DBRI_RD_OVRN (1<<3) /* Overrun: data lost */ -#define DBRI_RD_STATUS(v) ((v)&0xff) /* Receive status */ -#define DBRI_RD_CNT(v) (((v)>>16)&0x1fff) /* Valid bytes in the buffer */ +#define DBRI_RD_F (1 << 31) /* End of Frame */ +#define DBRI_RD_C (1 << 30) /* Completed buffer */ +#define DBRI_RD_B (1 << 15) /* Final interrupt */ +#define DBRI_RD_M (1 << 14) /* Marker interrupt */ +#define DBRI_RD_BCNT(v) (v) /* Buffer size */ +#define DBRI_RD_CRC (1 << 7) /* 0: CRC is correct */ +#define DBRI_RD_BBC (1 << 6) /* 1: Bad Byte received */ +#define DBRI_RD_ABT (1 << 5) /* Abort: frame aborted */ +#define DBRI_RD_OVRN (1 << 3) /* Overrun: data lost */ +#define DBRI_RD_STATUS(v) ((v) & 0xff) /* Receive status */ +#define DBRI_RD_CNT(v) (((v) >> 16) & 0x1fff) /* Valid bytes in the buffer */ /* stream_info[] access */ /* Translate the ALSA direction into the array index */ #define DBRI_STREAMNO(substream) \ - (substream->stream == \ - SNDRV_PCM_STREAM_PLAYBACK? DBRI_PLAY: DBRI_REC) + (substream->stream == \ + SNDRV_PCM_STREAM_PLAYBACK ? DBRI_PLAY: DBRI_REC) /* Return a pointer to dbri_streaminfo */ -#define DBRI_STREAM(dbri, substream) &dbri->stream_info[DBRI_STREAMNO(substream)] - -static struct snd_dbri *dbri_list; /* All DBRI devices */ +#define DBRI_STREAM(dbri, substream) \ + &dbri->stream_info[DBRI_STREAMNO(substream)] /* * Short data pipes transmit LSB first. The CS4215 receives MSB first. Grrr. @@ -609,21 +606,21 @@ The list is terminated with a WAIT command, which generates a CPU interrupt to signal completion. Since the DBRI can run in parallel with the CPU, several means of -synchronization present themselves. The method implemented here is only -use of the dbri_cmdwait() to wait for execution of batch of sent commands. +synchronization present themselves. The method implemented here uses +the dbri_cmdwait() to wait for execution of batch of sent commands. -A circular command buffer is used here. A new command is being added +A circular command buffer is used here. A new command is being added while another can be executed. The scheme works by adding two WAIT commands after each sent batch of commands. When the next batch is prepared it is added after the WAIT commands then the WAITs are replaced with single JUMP -command to the new batch. The the DBRI is forced to reread the last WAIT -command (replaced by the JUMP by then). If the DBRI is still executing +command to the new batch. The the DBRI is forced to reread the last WAIT +command (replaced by the JUMP by then). If the DBRI is still executing previous commands the request to reread the WAIT command is ignored. Every time a routine wants to write commands to the DBRI, it must -first call dbri_cmdlock() and get pointer to a free space in -dbri->dma->cmd buffer. After this, the commands can be written to -the buffer, and dbri_cmdsend() is called with the final pointer value +first call dbri_cmdlock() and get pointer to a free space in +dbri->dma->cmd buffer. After this, the commands can be written to +the buffer, and dbri_cmdsend() is called with the final pointer value to send them to the DBRI. */ @@ -646,18 +643,17 @@ static void dbri_cmdwait(struct snd_dbri *dbri) } spin_unlock_irqrestore(&dbri->lock, flags); - if (maxloops == 0) { + if (maxloops == 0) printk(KERN_ERR "DBRI: Chip never completed command buffer\n"); - } else { + else dprintk(D_CMD, "Chip completed command buffer (%d)\n", MAXLOOPS - maxloops - 1); - } } /* - * Lock the command queue and returns pointer to a space for len cmd words + * Lock the command queue and return pointer to space for len cmd words * It locks the cmdlock spinlock. */ -static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) +static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len) { /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */ len += 2; @@ -680,7 +676,7 @@ static s32 *dbri_cmdlock(struct snd_dbri * dbri, int len) * * Lock must be held before calling this. */ -static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) +static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len) { s32 tmp, addr; static int wait_id = 0; @@ -700,16 +696,17 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) s32 *ptr; for (ptr = dbri->cmdptr; ptr < cmd+2; ptr++) - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); + dprintk(D_CMD, "cmd: %lx:%08x\n", + (unsigned long)ptr, *ptr); } else { s32 *ptr = dbri->cmdptr; dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); ptr++; dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) { - dprintk(D_CMD, "cmd: %lx:%08x\n", (unsigned long)ptr, *ptr); - } + for (ptr = dbri->dma->cmd; ptr < cmd+2; ptr++) + dprintk(D_CMD, "cmd: %lx:%08x\n", + (unsigned long)ptr, *ptr); } #endif @@ -723,7 +720,7 @@ static void dbri_cmdsend(struct snd_dbri * dbri, s32 * cmd,int len) } /* Lock must be held when calling this */ -static void dbri_reset(struct snd_dbri * dbri) +static void dbri_reset(struct snd_dbri *dbri) { int i; u32 tmp; @@ -746,7 +743,7 @@ static void dbri_reset(struct snd_dbri * dbri) } /* Lock must not be held before calling this */ -static void dbri_initialize(struct snd_dbri * dbri) +static void __devinit dbri_initialize(struct snd_dbri *dbri) { s32 *cmd; u32 dma_addr; @@ -763,7 +760,7 @@ static void dbri_initialize(struct snd_dbri * dbri) spin_lock_init(&dbri->cmdlock); /* - * Initialize the interrupt ringbuffer. + * Initialize the interrupt ring buffer. */ dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0); dbri->dma->intr[0] = dma_addr; @@ -801,7 +798,7 @@ list ordering, among other things. The transmit and receive functions here interface closely with the transmit and receive interrupt code. */ -static int pipe_active(struct snd_dbri * dbri, int pipe) +static inline int pipe_active(struct snd_dbri *dbri, int pipe) { return ((pipe >= 0) && (dbri->pipes[pipe].desc != -1)); } @@ -811,20 +808,22 @@ static int pipe_active(struct snd_dbri * dbri, int pipe) * Called on an in-use pipe to clear anything being transmitted or received * Lock must be held before calling this. */ -static void reset_pipe(struct snd_dbri * dbri, int pipe) +static void reset_pipe(struct snd_dbri *dbri, int pipe) { int sdp; int desc; s32 *cmd; if (pipe < 0 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: reset_pipe called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: reset_pipe called with " + "illegal pipe number\n"); return; } sdp = dbri->pipes[pipe].sdp; if (sdp == 0) { - printk(KERN_ERR "DBRI: reset_pipe called on uninitialized pipe\n"); + printk(KERN_ERR "DBRI: reset_pipe called " + "on uninitialized pipe\n"); return; } @@ -835,9 +834,10 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) dbri_cmdsend(dbri, cmd, 3); desc = dbri->pipes[pipe].first_desc; - if ( desc >= 0) + if (desc >= 0) do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].nda = 0; desc = dbri->next_desc[desc]; } while (desc != -1 && desc != dbri->pipes[pipe].first_desc); @@ -848,15 +848,17 @@ static void reset_pipe(struct snd_dbri * dbri, int pipe) /* * Lock must be held before calling this. */ -static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) +static void setup_pipe(struct snd_dbri *dbri, int pipe, int sdp) { if (pipe < 0 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: setup_pipe called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: setup_pipe called " + "with illegal pipe number\n"); return; } if ((sdp & 0xf800) != sdp) { - printk(KERN_ERR "DBRI: setup_pipe called with strange SDP value\n"); + printk(KERN_ERR "DBRI: setup_pipe called " + "with strange SDP value\n"); /* sdp &= 0xf800; */ } @@ -877,25 +879,26 @@ static void setup_pipe(struct snd_dbri * dbri, int pipe, int sdp) /* * Lock must be held before calling this. */ -static void link_time_slot(struct snd_dbri * dbri, int pipe, +static void link_time_slot(struct snd_dbri *dbri, int pipe, int prevpipe, int nextpipe, int length, int cycle) { s32 *cmd; int val; - if (pipe < 0 || pipe > DBRI_MAX_PIPE + if (pipe < 0 || pipe > DBRI_MAX_PIPE || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: link_time_slot called with illegal pipe number\n"); return; } - if (dbri->pipes[pipe].sdp == 0 + if (dbri->pipes[pipe].sdp == 0 || dbri->pipes[prevpipe].sdp == 0 || dbri->pipes[nextpipe].sdp == 0) { - printk(KERN_ERR "DBRI: link_time_slot called on uninitialized pipe\n"); + printk(KERN_ERR "DBRI: link_time_slot called " + "on uninitialized pipe\n"); return; } @@ -935,17 +938,17 @@ static void link_time_slot(struct snd_dbri * dbri, int pipe, /* * Lock must be held before calling this. */ -static void unlink_time_slot(struct snd_dbri * dbri, int pipe, +static void unlink_time_slot(struct snd_dbri *dbri, int pipe, enum in_or_out direction, int prevpipe, int nextpipe) { s32 *cmd; int val; - if (pipe < 0 || pipe > DBRI_MAX_PIPE + if (pipe < 0 || pipe > DBRI_MAX_PIPE || prevpipe < 0 || prevpipe > DBRI_MAX_PIPE || nextpipe < 0 || nextpipe > DBRI_MAX_PIPE) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: unlink_time_slot called with illegal pipe number\n"); return; } @@ -985,7 +988,7 @@ static void unlink_time_slot(struct snd_dbri * dbri, int pipe, * * Lock must not be held before calling it. */ -static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) +static void xmit_fixed(struct snd_dbri *dbri, int pipe, unsigned int data) { s32 *cmd; unsigned long flags; @@ -996,7 +999,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } if (D_SDP_MODE(dbri->pipes[pipe].sdp) == 0) { - printk(KERN_ERR "DBRI: xmit_fixed: Uninitialized pipe %d\n", pipe); + printk(KERN_ERR "DBRI: xmit_fixed: " + "Uninitialized pipe %d\n", pipe); return; } @@ -1006,7 +1010,8 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } if (!(dbri->pipes[pipe].sdp & D_SDP_TO_SER)) { - printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", pipe); + printk(KERN_ERR "DBRI: xmit_fixed: Called on receive pipe %d\n", + pipe); return; } @@ -1028,20 +1033,23 @@ static void xmit_fixed(struct snd_dbri * dbri, int pipe, unsigned int data) } -static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) +static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr) { if (pipe < 16 || pipe > DBRI_MAX_PIPE) { - printk(KERN_ERR "DBRI: recv_fixed called with illegal pipe number\n"); + printk(KERN_ERR "DBRI: recv_fixed called with " + "illegal pipe number\n"); return; } if (D_SDP_MODE(dbri->pipes[pipe].sdp) != D_SDP_FIXED) { - printk(KERN_ERR "DBRI: recv_fixed called on non-fixed pipe %d\n", pipe); + printk(KERN_ERR "DBRI: recv_fixed called on " + "non-fixed pipe %d\n", pipe); return; } if (dbri->pipes[pipe].sdp & D_SDP_TO_SER) { - printk(KERN_ERR "DBRI: recv_fixed called on transmit pipe %d\n", pipe); + printk(KERN_ERR "DBRI: recv_fixed called on " + "transmit pipe %d\n", pipe); return; } @@ -1064,7 +1072,7 @@ static void recv_fixed(struct snd_dbri * dbri, int pipe, volatile __u32 * ptr) * * Lock must be held before calling this. */ -static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period) +static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period) { struct dbri_streaminfo *info = &dbri->stream_info[streamno]; __u32 dvma_buffer; @@ -1089,21 +1097,23 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (streamno == DBRI_PLAY) { if (!(dbri->pipes[info->pipe].sdp & D_SDP_TO_SER)) { - printk(KERN_ERR "DBRI: setup_descs: Called on receive pipe %d\n", - info->pipe); + printk(KERN_ERR "DBRI: setup_descs: " + "Called on receive pipe %d\n", info->pipe); return -2; } } else { if (dbri->pipes[info->pipe].sdp & D_SDP_TO_SER) { - printk(KERN_ERR + printk(KERN_ERR "DBRI: setup_descs: Called on transmit pipe %d\n", info->pipe); return -2; } - /* Should be able to queue multiple buffers to receive on a pipe */ + /* Should be able to queue multiple buffers + * to receive on a pipe + */ if (pipe_active(dbri, info->pipe)) { - printk(KERN_ERR "DBRI: recv_on_pipe: Called on active pipe %d\n", - info->pipe); + printk(KERN_ERR "DBRI: recv_on_pipe: " + "Called on active pipe %d\n", info->pipe); return -2; } @@ -1113,11 +1123,13 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period /* Free descriptors if pipe has any */ desc = dbri->pipes[info->pipe].first_desc; - if ( desc >= 0) + if (desc >= 0) do { - dbri->dma->desc[desc].nda = dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].ba = 0; + dbri->dma->desc[desc].nda = 0; desc = dbri->next_desc[desc]; - } while (desc != -1 && desc != dbri->pipes[info->pipe].first_desc); + } while (desc != -1 && + desc != dbri->pipes[info->pipe].first_desc); dbri->pipes[info->pipe].desc = -1; dbri->pipes[info->pipe].first_desc = -1; @@ -1130,6 +1142,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (!dbri->dma->desc[desc].ba) break; } + if (desc == DBRI_NO_DESCS) { printk(KERN_ERR "DBRI: setup_descs: No descriptors\n"); return -1; @@ -1150,8 +1163,7 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period if (streamno == DBRI_PLAY) { dbri->dma->desc[desc].word1 = DBRI_TD_CNT(mylen); dbri->dma->desc[desc].word4 = 0; - dbri->dma->desc[desc].word1 |= - DBRI_TD_F | DBRI_TD_B; + dbri->dma->desc[desc].word1 |= DBRI_TD_F | DBRI_TD_B; } else { dbri->dma->desc[desc].word1 = 0; dbri->dma->desc[desc].word4 = @@ -1172,7 +1184,8 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period } if (first_desc == -1 || last_desc == -1) { - printk(KERN_ERR "DBRI: setup_descs: Not enough descriptors available\n"); + printk(KERN_ERR "DBRI: setup_descs: " + " Not enough descriptors available\n"); return -1; } @@ -1183,14 +1196,14 @@ static int setup_descs(struct snd_dbri * dbri, int streamno, unsigned int period dbri->pipes[info->pipe].desc = first_desc; #ifdef DBRI_DEBUG - for (desc = first_desc; desc != -1; ) { + for (desc = first_desc; desc != -1;) { dprintk(D_DESC, "DESC %d: %08x %08x %08x %08x\n", desc, dbri->dma->desc[desc].word1, dbri->dma->desc[desc].ba, dbri->dma->desc[desc].nda, dbri->dma->desc[desc].word4); desc = dbri->next_desc[desc]; - if ( desc == first_desc ) + if (desc == first_desc) break; } #endif @@ -1213,7 +1226,8 @@ enum master_or_slave { CHImaster, CHIslave }; /* * Lock must not be held before calling it. */ -static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_slave, +static void reset_chi(struct snd_dbri *dbri, + enum master_or_slave master_or_slave, int bits_per_frame) { s32 *cmd; @@ -1222,7 +1236,7 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla /* Set CHI Anchor: Pipe 16 */ cmd = dbri_cmdlock(dbri, 4); - val = D_DTS_VO | D_DTS_VI | D_DTS_INS + val = D_DTS_VO | D_DTS_VI | D_DTS_INS | D_DTS_PRVIN(16) | D_PIPE(16) | D_DTS_PRVOUT(16); *(cmd++) = DBRI_CMD(D_DTS, 0, val); *(cmd++) = D_TS_ANCHOR | D_TS_NEXT(16); @@ -1246,15 +1260,16 @@ static void reset_chi(struct snd_dbri * dbri, enum master_or_slave master_or_sla } else { /* Setup DBRI for CHI Master - generate clock, FS * - * BPF = bits per 8 kHz frame - * 12.288 MHz / CHICM_divisor = clock rate - * FD = 1 - drive CHIFS on rising edge of CHICK + * BPF = bits per 8 kHz frame + * 12.288 MHz / CHICM_divisor = clock rate + * FD = 1 - drive CHIFS on rising edge of CHICK */ int clockrate = bits_per_frame * 8; int divisor = 12288 / clockrate; if (divisor > 255 || divisor * clockrate != 12288) - printk(KERN_ERR "DBRI: illegal bits_per_frame in setup_chi\n"); + printk(KERN_ERR "DBRI: illegal bits_per_frame " + "in setup_chi\n"); *(cmd++) = DBRI_CMD(D_CHI, 0, D_CHI_CHICM(divisor) | D_CHI_FD | D_CHI_BPF(bits_per_frame)); @@ -1288,7 +1303,7 @@ to the DBRI via the CHI interface and few of the DBRI's PIO pins. * Lock must not be held before calling it. */ -static void cs4215_setup_pipes(struct snd_dbri * dbri) +static __devinit void cs4215_setup_pipes(struct snd_dbri *dbri) { unsigned long flags; @@ -1303,9 +1318,9 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) * not relevant for us (only for doublechecking). * * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). + * Pipe 19: Receive timeslot 7 (version). */ setup_pipe(dbri, 4, D_SDP_MEM | D_SDP_TO_SER | D_SDP_MSB); @@ -1321,7 +1336,7 @@ static void cs4215_setup_pipes(struct snd_dbri * dbri) dbri_cmdwait(dbri); } -static int cs4215_init_data(struct cs4215 *mm) +static __devinit int cs4215_init_data(struct cs4215 *mm) { /* * No action, memory resetting only. @@ -1355,7 +1370,7 @@ static int cs4215_init_data(struct cs4215 *mm) return 0; } -static void cs4215_setdata(struct snd_dbri * dbri, int muted) +static void cs4215_setdata(struct snd_dbri *dbri, int muted) { if (muted) { dbri->mm.data[0] |= 63; @@ -1387,7 +1402,7 @@ static void cs4215_setdata(struct snd_dbri * dbri, int muted) /* * Set the CS4215 to data mode. */ -static void cs4215_open(struct snd_dbri * dbri) +static void cs4215_open(struct snd_dbri *dbri) { int data_width; u32 tmp; @@ -1452,7 +1467,7 @@ static void cs4215_open(struct snd_dbri * dbri) /* * Send the control information (i.e. audio format) */ -static int cs4215_setctrl(struct snd_dbri * dbri) +static int cs4215_setctrl(struct snd_dbri *dbri) { int i, val; u32 tmp; @@ -1502,9 +1517,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) /* * Control mode: - * Pipe 17: Send timeslots 1-4 (slots 5-8 are readonly) + * Pipe 17: Send timeslots 1-4 (slots 5-8 are read only) * Pipe 18: Receive timeslot 1 (clb). - * Pipe 19: Receive timeslot 7 (version). + * Pipe 19: Receive timeslot 7 (version). */ link_time_slot(dbri, 17, 16, 16, 32, dbri->mm.offset); @@ -1522,9 +1537,9 @@ static int cs4215_setctrl(struct snd_dbri * dbri) sbus_writel(tmp, dbri->regs + REG0); spin_unlock_irqrestore(&dbri->lock, flags); - for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) { + for (i = 10; ((dbri->mm.status & 0xe4) != 0x20); --i) msleep_interruptible(1); - } + if (i == 0) { dprintk(D_MM, "CS4215 didn't respond to CLB (0x%02x)\n", dbri->mm.status); @@ -1556,7 +1571,7 @@ static int cs4215_setctrl(struct snd_dbri * dbri) * As part of the process we resend the settings for the data * timeslots as well. */ -static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, +static int cs4215_prepare(struct snd_dbri *dbri, unsigned int rate, snd_pcm_format_t format, unsigned int channels) { int freq_idx; @@ -1613,7 +1628,7 @@ static int cs4215_prepare(struct snd_dbri * dbri, unsigned int rate, /* * */ -static int cs4215_init(struct snd_dbri * dbri) +static __devinit int cs4215_init(struct snd_dbri *dbri) { u32 reg2 = sbus_readl(dbri->regs + REG2); dprintk(D_MM, "cs4215_init: reg2=0x%x\n", reg2); @@ -1674,7 +1689,7 @@ interrupts are disabled. /* xmit_descs() * - * Starts transmiting the current TD's for recording/playing. + * Starts transmitting the current TD's for recording/playing. * For playback, ALSA has filled the DMA memory with new data (we hope). */ static void xmit_descs(struct snd_dbri *dbri) @@ -1701,7 +1716,8 @@ static void xmit_descs(struct snd_dbri *dbri) *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[info->pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + *(cmd++) = dbri->dma_dvma + + dbri_dma_off(desc, first_td); dbri_cmdsend(dbri, cmd, 2); /* Reset our admin of the pipe. */ @@ -1722,7 +1738,8 @@ static void xmit_descs(struct snd_dbri *dbri) *(cmd++) = DBRI_CMD(D_SDP, 0, dbri->pipes[info->pipe].sdp | D_SDP_P | D_SDP_EVERY | D_SDP_C); - *(cmd++) = dbri->dma_dvma + dbri_dma_off(desc, first_td); + *(cmd++) = dbri->dma_dvma + + dbri_dma_off(desc, first_td); dbri_cmdsend(dbri, cmd, 2); /* Reset our admin of the pipe. */ @@ -1747,15 +1764,12 @@ static void xmit_descs(struct snd_dbri *dbri) * */ -static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) +static void transmission_complete_intr(struct snd_dbri *dbri, int pipe) { - struct dbri_streaminfo *info; - int td; + struct dbri_streaminfo *info = &dbri->stream_info[DBRI_PLAY]; + int td = dbri->pipes[pipe].desc; int status; - info = &dbri->stream_info[DBRI_PLAY]; - - td = dbri->pipes[pipe].desc; while (td >= 0) { if (td >= DBRI_NO_DESCS) { printk(KERN_ERR "DBRI: invalid td on pipe %d\n", pipe); @@ -1763,9 +1777,8 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) } status = DBRI_TD_STATUS(dbri->dma->desc[td].word4); - if (!(status & DBRI_TD_TBC)) { + if (!(status & DBRI_TD_TBC)) break; - } dprintk(D_INT, "TD %d, status 0x%02x\n", td, status); @@ -1777,15 +1790,12 @@ static void transmission_complete_intr(struct snd_dbri * dbri, int pipe) } /* Notify ALSA */ - if (spin_is_locked(&dbri->lock)) { - spin_unlock(&dbri->lock); - snd_pcm_period_elapsed(info->substream); - spin_lock(&dbri->lock); - } else - snd_pcm_period_elapsed(info->substream); + spin_unlock(&dbri->lock); + snd_pcm_period_elapsed(info->substream); + spin_lock(&dbri->lock); } -static void reception_complete_intr(struct snd_dbri * dbri, int pipe) +static void reception_complete_intr(struct snd_dbri *dbri, int pipe) { struct dbri_streaminfo *info; int rd = dbri->pipes[pipe].desc; @@ -1809,15 +1819,12 @@ static void reception_complete_intr(struct snd_dbri * dbri, int pipe) rd, DBRI_RD_STATUS(status), DBRI_RD_CNT(status)); /* Notify ALSA */ - if (spin_is_locked(&dbri->lock)) { - spin_unlock(&dbri->lock); - snd_pcm_period_elapsed(info->substream); - spin_lock(&dbri->lock); - } else - snd_pcm_period_elapsed(info->substream); + spin_unlock(&dbri->lock); + snd_pcm_period_elapsed(info->substream); + spin_lock(&dbri->lock); } -static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) +static void dbri_process_one_interrupt(struct snd_dbri *dbri, int x) { int val = D_INTR_GETVAL(x); int channel = D_INTR_GETCHAN(x); @@ -1889,7 +1896,7 @@ static void dbri_process_one_interrupt(struct snd_dbri * dbri, int x) * right now). Non-zero words require processing and are handed off * to dbri_process_one_interrupt AFTER advancing the pointer. */ -static void dbri_process_interrupt_buffer(struct snd_dbri * dbri) +static void dbri_process_interrupt_buffer(struct snd_dbri *dbri) { s32 x; @@ -1965,20 +1972,20 @@ static irqreturn_t snd_dbri_interrupt(int irq, void *dev_id) PCM Interface ****************************************************************************/ static struct snd_pcm_hardware snd_dbri_pcm_hw = { - .info = (SNDRV_PCM_INFO_MMAP | - SNDRV_PCM_INFO_INTERLEAVED | - SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_MMAP_VALID), - .formats = SNDRV_PCM_FMTBIT_MU_LAW | - SNDRV_PCM_FMTBIT_A_LAW | - SNDRV_PCM_FMTBIT_U8 | - SNDRV_PCM_FMTBIT_S16_BE, - .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, + .info = SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP_VALID, + .formats = SNDRV_PCM_FMTBIT_MU_LAW | + SNDRV_PCM_FMTBIT_A_LAW | + SNDRV_PCM_FMTBIT_U8 | + SNDRV_PCM_FMTBIT_S16_BE, + .rates = SNDRV_PCM_RATE_8000_48000 | SNDRV_PCM_RATE_5512, .rate_min = 5512, .rate_max = 48000, .channels_min = 1, .channels_max = 2, - .buffer_bytes_max = (64 * 1024), + .buffer_bytes_max = 64 * 1024, .period_bytes_min = 1, .period_bytes_max = DBRI_TD_MAXCNT, .periods_min = 1, @@ -2011,7 +2018,8 @@ static int snd_hw_rule_channels(struct snd_pcm_hw_params *params, snd_interval_any(&ch); if (!(f->bits[0] & SNDRV_PCM_FMTBIT_S16_BE)) { - ch.min = ch.max = 1; + ch.min = 1; + ch.max = 1; ch.integer = 1; return snd_interval_refine(c, &ch); } @@ -2035,14 +2043,14 @@ static int snd_dbri_open(struct snd_pcm_substream *substream) info->pipe = -1; spin_unlock_irqrestore(&dbri->lock, flags); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_CHANNELS, + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, snd_hw_rule_format, NULL, SNDRV_PCM_HW_PARAM_FORMAT, -1); - snd_pcm_hw_rule_add(runtime,0,SNDRV_PCM_HW_PARAM_FORMAT, - snd_hw_rule_channels, NULL, + snd_pcm_hw_rule_add(runtime, 0, SNDRV_PCM_HW_PARAM_FORMAT, + snd_hw_rule_channels, NULL, SNDRV_PCM_HW_PARAM_CHANNELS, -1); - + cs4215_open(dbri); return 0; @@ -2145,7 +2153,7 @@ static int snd_dbri_prepare(struct snd_pcm_substream *substream) spin_lock_irq(&dbri->lock); info->offset = 0; - /* Setup the all the transmit/receive desciptors to cover the + /* Setup the all the transmit/receive descriptors to cover the * whole DMA buffer. */ ret = setup_descs(dbri, DBRI_STREAMNO(substream), @@ -2205,12 +2213,12 @@ static struct snd_pcm_ops snd_dbri_ops = { .pointer = snd_dbri_pointer, }; -static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) +static int __devinit snd_dbri_pcm(struct snd_card *card) { struct snd_pcm *pcm; int err; - if ((err = snd_pcm_new(dbri->card, + if ((err = snd_pcm_new(card, /* ID */ "sun_dbri", /* device */ 0, /* playback count */ 1, @@ -2221,16 +2229,15 @@ static int __devinit snd_dbri_pcm(struct snd_dbri * dbri) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_dbri_ops); snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_dbri_ops); - pcm->private_data = dbri; + pcm->private_data = card->private_data; pcm->info_flags = 0; - strcpy(pcm->name, dbri->card->shortname); + strcpy(pcm->name, card->shortname); if ((err = snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS, snd_dma_continuous_data(GFP_KERNEL), - 64 * 1024, 64 * 1024)) < 0) { + 64 * 1024, 64 * 1024)) < 0) return err; - } return 0; } @@ -2245,11 +2252,10 @@ static int snd_cs4215_info_volume(struct snd_kcontrol *kcontrol, uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; uinfo->count = 2; uinfo->value.integer.min = 0; - if (kcontrol->private_value == DBRI_PLAY) { + if (kcontrol->private_value == DBRI_PLAY) uinfo->value.integer.max = DBRI_MAX_VOLUME; - } else { + else uinfo->value.integer.max = DBRI_MAX_GAIN; - } return 0; } @@ -2271,7 +2277,8 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_dbri *dbri = snd_kcontrol_chip(kcontrol); - struct dbri_streaminfo *info = &dbri->stream_info[kcontrol->private_value]; + struct dbri_streaminfo *info = + &dbri->stream_info[kcontrol->private_value]; int changed = 0; if (info->left_gain != ucontrol->value.integer.value[0]) { @@ -2282,7 +2289,7 @@ static int snd_cs4215_put_volume(struct snd_kcontrol *kcontrol, info->right_gain = ucontrol->value.integer.value[1]; changed = 1; } - if (changed == 1) { + if (changed) { /* First mute outputs, and wait 1/8000 sec (125 us) * to make sure this takes. This avoids clicking noises. */ @@ -2316,18 +2323,16 @@ static int snd_cs4215_get_single(struct snd_kcontrol *kcontrol, int invert = (kcontrol->private_value >> 24) & 1; snd_assert(dbri != NULL, return -EINVAL); - if (elem < 4) { + if (elem < 4) ucontrol->value.integer.value[0] = (dbri->mm.data[elem] >> shift) & mask; - } else { + else ucontrol->value.integer.value[0] = (dbri->mm.ctrl[elem - 4] >> shift) & mask; - } - if (invert == 1) { + if (invert == 1) ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0]; - } return 0; } @@ -2378,11 +2383,12 @@ static int snd_cs4215_put_single(struct snd_kcontrol *kcontrol, timeslots. Shift is the bit offset in the timeslot, mask defines the number of bits. invert is a boolean for use with attenuation. */ -#define CS4215_SINGLE(xname, entry, shift, mask, invert) \ -{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ - .info = snd_cs4215_info_single, \ - .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ - .private_value = entry | (shift << 8) | (mask << 16) | (invert << 24) }, +#define CS4215_SINGLE(xname, entry, shift, mask, invert) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = snd_cs4215_info_single, \ + .get = snd_cs4215_get_single, .put = snd_cs4215_put_single, \ + .private_value = (entry) | ((shift) << 8) | ((mask) << 16) | \ + ((invert) << 24) }, static struct snd_kcontrol_new dbri_controls[] __devinitdata = { { @@ -2411,19 +2417,20 @@ static struct snd_kcontrol_new dbri_controls[] __devinitdata = { CS4215_SINGLE("Mic boost", 4, 4, 1, 1) }; -static int __init snd_dbri_mixer(struct snd_dbri * dbri) +static int __devinit snd_dbri_mixer(struct snd_card *card) { - struct snd_card *card; int idx, err; + struct snd_dbri *dbri; - snd_assert(dbri != NULL && dbri->card != NULL, return -EINVAL); + snd_assert(card != NULL && card->private_data != NULL, return -EINVAL); + dbri = card->private_data; - card = dbri->card; strcpy(card->mixername, card->shortname); for (idx = 0; idx < ARRAY_SIZE(dbri_controls); idx++) { - if ((err = snd_ctl_add(card, - snd_ctl_new1(&dbri_controls[idx], dbri))) < 0) + err = snd_ctl_add(card, + snd_ctl_new1(&dbri_controls[idx], dbri)); + if (err < 0) return err; } @@ -2438,7 +2445,8 @@ static int __init snd_dbri_mixer(struct snd_dbri * dbri) /**************************************************************************** /proc interface ****************************************************************************/ -static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer *buffer) +static void dbri_regs_read(struct snd_info_entry *entry, + struct snd_info_buffer *buffer) { struct snd_dbri *dbri = entry->private_data; @@ -2449,7 +2457,7 @@ static void dbri_regs_read(struct snd_info_entry * entry, struct snd_info_buffer } #ifdef DBRI_DEBUG -static void dbri_debug_read(struct snd_info_entry * entry, +static void dbri_debug_read(struct snd_info_entry *entry, struct snd_info_buffer *buffer) { struct snd_dbri *dbri = entry->private_data; @@ -2463,7 +2471,8 @@ static void dbri_debug_read(struct snd_info_entry * entry, "Pipe %d: %s SDP=0x%x desc=%d, " "len=%d next %d\n", pipe, - ((pptr->sdp & D_SDP_TO_SER) ? "output" : "input"), + (pptr->sdp & D_SDP_TO_SER) ? "output" : + "input", pptr->sdp, pptr->desc, pptr->length, pptr->nextpipe); } @@ -2471,15 +2480,16 @@ static void dbri_debug_read(struct snd_info_entry * entry, } #endif -void snd_dbri_proc(struct snd_dbri * dbri) +void __devinit snd_dbri_proc(struct snd_card *card) { + struct snd_dbri *dbri = card->private_data; struct snd_info_entry *entry; - if (! snd_card_proc_new(dbri->card, "regs", &entry)) + if (!snd_card_proc_new(card, "regs", &entry)) snd_info_set_text_ops(entry, dbri, dbri_regs_read); #ifdef DBRI_DEBUG - if (! snd_card_proc_new(dbri->card, "debug", &entry)) { + if (!snd_card_proc_new(card, "debug", &entry)) { snd_info_set_text_ops(entry, dbri, dbri_debug_read); entry->mode = S_IFREG | S_IRUGO; /* Readable only. */ } @@ -2491,19 +2501,18 @@ void snd_dbri_proc(struct snd_dbri * dbri) **************************** Initialization ******************************** **************************************************************************** */ -static void snd_dbri_free(struct snd_dbri * dbri); +static void snd_dbri_free(struct snd_dbri *dbri); -static int __init snd_dbri_create(struct snd_card *card, +static int __devinit snd_dbri_create(struct snd_card *card, struct sbus_dev *sdev, - struct linux_prom_irqs *irq, int dev) + int irq, int dev) { struct snd_dbri *dbri = card->private_data; int err; spin_lock_init(&dbri->lock); - dbri->card = card; dbri->sdev = sdev; - dbri->irq = irq->pri; + dbri->irq = irq; dbri->dma = sbus_alloc_consistent(sdev, sizeof(struct dbri_dma), &dbri->dma_dvma); @@ -2541,13 +2550,10 @@ static int __init snd_dbri_create(struct snd_card *card, return err; } - dbri->next = dbri_list; - dbri_list = dbri; - return 0; } -static void snd_dbri_free(struct snd_dbri * dbri) +static void snd_dbri_free(struct snd_dbri *dbri) { dprintk(D_GEN, "snd_dbri_free\n"); dbri_reset(dbri); @@ -2563,20 +2569,19 @@ static void snd_dbri_free(struct snd_dbri * dbri) (void *)dbri->dma, dbri->dma_dvma); } -static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) +static int __devinit dbri_probe(struct of_device *of_dev, + const struct of_device_id *match) { + struct sbus_dev *sdev = to_sbus_device(&of_dev->dev); struct snd_dbri *dbri; - struct linux_prom_irqs irq; + int irq; struct resource *rp; struct snd_card *card; static int dev = 0; int err; - if (sdev->prom_name[9] < 'e') { - printk(KERN_ERR "DBRI: unsupported chip version %c found.\n", - sdev->prom_name[9]); - return -EIO; - } + dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", + sdev->prom_name, sdev->slot); if (dev >= SNDRV_CARDS) return -ENODEV; @@ -2585,9 +2590,9 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) return -ENOENT; } - err = prom_getproperty(prom_node, "intr", (char *)&irq, sizeof(irq)); - if (err < 0) { - printk(KERN_ERR "DBRI-%d: Firmware node lacks IRQ property.\n", dev); + irq = sdev->irqs[0]; + if (irq <= 0) { + printk(KERN_ERR "DBRI-%d: No IRQ.\n", dev); return -ENODEV; } @@ -2601,24 +2606,29 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) rp = &sdev->resource[0]; sprintf(card->longname, "%s at 0x%02lx:0x%016Lx, irq %d", card->shortname, - rp->flags & 0xffL, (unsigned long long)rp->start, irq.pri); + rp->flags & 0xffL, (unsigned long long)rp->start, irq); - if ((err = snd_dbri_create(card, sdev, &irq, dev)) < 0) { + err = snd_dbri_create(card, sdev, irq, dev); + if (err < 0) { snd_card_free(card); return err; } dbri = card->private_data; - if ((err = snd_dbri_pcm(dbri)) < 0) + err = snd_dbri_pcm(card); + if (err < 0) goto _err; - if ((err = snd_dbri_mixer(dbri)) < 0) + err = snd_dbri_mixer(card); + if (err < 0) goto _err; /* /proc file handling */ - snd_dbri_proc(dbri); + snd_dbri_proc(card); + dev_set_drvdata(&of_dev->dev, card); - if ((err = snd_card_register(card)) < 0) + err = snd_card_register(card); + if (err < 0) goto _err; printk(KERN_INFO "audio%d at %p (irq %d) is DBRI(%c)+CS4215(%d)\n", @@ -2628,49 +2638,52 @@ static int __init dbri_attach(int prom_node, struct sbus_dev *sdev) return 0; - _err: +_err: snd_dbri_free(dbri); snd_card_free(card); return err; } -/* Probe for the dbri chip and then attach the driver. */ -static int __init dbri_init(void) +static int __devexit dbri_remove(struct of_device *dev) { - struct sbus_bus *sbus; - struct sbus_dev *sdev; - int found = 0; - - /* Probe each SBUS for the DBRI chip(s). */ - for_all_sbusdev(sdev, sbus) { - /* - * The version is coded in the last character - */ - if (!strncmp(sdev->prom_name, "SUNW,DBRI", 9)) { - dprintk(D_GEN, "DBRI: Found %s in SBUS slot %d\n", - sdev->prom_name, sdev->slot); + struct snd_card *card = dev_get_drvdata(&dev->dev); - if (dbri_attach(sdev->prom_node, sdev) == 0) - found++; - } - } + snd_dbri_free(card->private_data); + snd_card_free(card); + + dev_set_drvdata(&dev->dev, NULL); + + return 0; +} + +static struct of_device_id dbri_match[] = { + { + .name = "SUNW,DBRIe", + }, + { + .name = "SUNW,DBRIf", + }, + {}, +}; + +MODULE_DEVICE_TABLE(of, dbri_match); + +static struct of_platform_driver dbri_sbus_driver = { + .name = "dbri", + .match_table = dbri_match, + .probe = dbri_probe, + .remove = __devexit_p(dbri_remove), +}; - return (found > 0) ? 0 : -EIO; +/* Probe for the dbri chip and then attach the driver. */ +static int __init dbri_init(void) +{ + return of_register_driver(&dbri_sbus_driver, &sbus_bus_type); } static void __exit dbri_exit(void) { - struct snd_dbri *this = dbri_list; - - while (this != NULL) { - struct snd_dbri *next = this->next; - struct snd_card *card = this->card; - - snd_dbri_free(this); - snd_card_free(card); - this = next; - } - dbri_list = NULL; + of_unregister_driver(&dbri_sbus_driver); } module_init(dbri_init); |