diff options
author | Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp> | 2006-10-02 23:19:00 +0900 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2006-10-03 17:59:17 +0100 |
commit | af8b128719f5248e542036ea994610a29d0642a6 (patch) | |
tree | 1330f156553cba8bccc9132c6a64bf766ed9ca8e /sound | |
parent | 08dfcee84c5c747ca1cecbd04c3a7e65cc9ce26b (diff) |
[MIPS] Remove IT8172-based platforms, ITE 8172G and Globespan IVR support.
As per feature-removal-schedule.txt.
Signed-off-by: Yoichi Yuasa <yoichi_yuasa@tripeaks.co.jp>
Acked-by: Alan Cox <alan@redhat.com>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/oss/Kconfig | 4 | ||||
-rw-r--r-- | sound/oss/Makefile | 1 | ||||
-rw-r--r-- | sound/oss/ite8172.c | 2261 |
3 files changed, 0 insertions, 2266 deletions
diff --git a/sound/oss/Kconfig b/sound/oss/Kconfig index 97e38b66558..f3b3530402c 100644 --- a/sound/oss/Kconfig +++ b/sound/oss/Kconfig @@ -115,10 +115,6 @@ config SOUND_HAL2 Say Y or M if you have an SGI Indy or Indigo2 system and want to be able to use its on-board A2 audio system. -config SOUND_IT8172 - tristate "IT8172G Sound" - depends on SOUND_PRIME && (MIPS_ITE8172 || MIPS_IVR) - config SOUND_VRC5477 tristate "NEC Vrc5477 AC97 sound" depends on SOUND_PRIME && DDB5477 diff --git a/sound/oss/Makefile b/sound/oss/Makefile index 9bf3ee544d8..86811792002 100644 --- a/sound/oss/Makefile +++ b/sound/oss/Makefile @@ -77,7 +77,6 @@ obj-$(CONFIG_SOUND_BCM_CS4297A) += swarm_cs4297a.o obj-$(CONFIG_SOUND_RME96XX) += rme96xx.o obj-$(CONFIG_SOUND_BT878) += btaudio.o obj-$(CONFIG_SOUND_ALI5455) += ali5455.o ac97_codec.o -obj-$(CONFIG_SOUND_IT8172) += ite8172.o ac97_codec.o obj-$(CONFIG_SOUND_FORTE) += forte.o ac97_codec.o obj-$(CONFIG_SOUND_AD1980) += ac97_plugin_ad1980.o ac97_codec.o diff --git a/sound/oss/ite8172.c b/sound/oss/ite8172.c deleted file mode 100644 index 68aab3605d7..00000000000 --- a/sound/oss/ite8172.c +++ /dev/null @@ -1,2261 +0,0 @@ -/* - * ite8172.c -- ITE IT8172G Sound Driver. - * - * Copyright 2001 MontaVista Software Inc. - * Author: MontaVista Software, Inc. - * stevel@mvista.com or source@mvista.com - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of the GNU General Public License as published by the - * Free Software Foundation; either version 2 of the License, or (at your - * option) any later version. - * - * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED - * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF - * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN - * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, - * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT - * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF - * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF - * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 675 Mass Ave, Cambridge, MA 02139, USA. - * - * - * Module command line parameters: - * - * Supported devices: - * /dev/dsp standard OSS /dev/dsp device - * /dev/mixer standard OSS /dev/mixer device - * - * Notes: - * - * 1. Much of the OSS buffer allocation, ioctl's, and mmap'ing are - * taken, slightly modified or not at all, from the ES1371 driver, - * so refer to the credits in es1371.c for those. The rest of the - * code (probe, open, read, write, the ISR, etc.) is new. - * 2. The following support is untested: - * * Memory mapping the audio buffers, and the ioctl controls that go - * with it. - * * S/PDIF output. - * * I2S support. - * 3. The following is not supported: - * * legacy audio mode. - * 4. Support for volume button interrupts is implemented but doesn't - * work yet. - * - * Revision history - * 02.08.2001 Initial release - * 06.22.2001 Added I2S support - * 07.30.2003 Removed initialisation to zero for static variables - * (spdif[NR_DEVICE], i2s_fmt[NR_DEVICE], and devindex) - */ -#include <linux/module.h> -#include <linux/string.h> -#include <linux/ioport.h> -#include <linux/sched.h> -#include <linux/delay.h> -#include <linux/sound.h> -#include <linux/slab.h> -#include <linux/soundcard.h> -#include <linux/pci.h> -#include <linux/init.h> -#include <linux/poll.h> -#include <linux/bitops.h> -#include <linux/proc_fs.h> -#include <linux/spinlock.h> -#include <linux/smp_lock.h> -#include <linux/ac97_codec.h> -#include <linux/interrupt.h> -#include <linux/mutex.h> - -#include <asm/io.h> -#include <asm/dma.h> -#include <asm/uaccess.h> -#include <asm/it8172/it8172.h> - -/* --------------------------------------------------------------------- */ - -#undef OSS_DOCUMENTED_MIXER_SEMANTICS -#define IT8172_DEBUG -#undef IT8172_VERBOSE_DEBUG -#define DBG(x) {} - -#define IT8172_MODULE_NAME "IT8172 audio" -#define PFX IT8172_MODULE_NAME - -#ifdef IT8172_DEBUG -#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#endif -#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) - - -#define IT8172_MODULE_NAME "IT8172 audio" -#define PFX IT8172_MODULE_NAME - -#ifdef IT8172_DEBUG -#define dbg(format, arg...) printk(KERN_DEBUG PFX ": " format "\n" , ## arg) -#else -#define dbg(format, arg...) do {} while (0) -#endif -#define err(format, arg...) printk(KERN_ERR PFX ": " format "\n" , ## arg) -#define info(format, arg...) printk(KERN_INFO PFX ": " format "\n" , ## arg) -#define warn(format, arg...) printk(KERN_WARNING PFX ": " format "\n" , ## arg) - - -static const unsigned sample_shift[] = { 0, 1, 1, 2 }; - - -/* - * Audio Controller register bit definitions follow. See - * include/asm/it8172/it8172.h for register offsets. - */ - -/* PCM Out Volume Reg */ -#define PCMOV_PCMOM (1<<15) /* PCM Out Mute default 1: mute */ -#define PCMOV_PCMRCG_BIT 8 /* PCM Right channel Gain */ -#define PCMOV_PCMRCG_MASK (0x1f<<PCMOV_PCMRCG_BIT) -#define PCMOV_PCMLCG_BIT 0 /* PCM Left channel gain */ -#define PCMOV_PCMLCG_MASK 0x1f - -/* FM Out Volume Reg */ -#define FMOV_FMOM (1<<15) /* FM Out Mute default 1: mute */ -#define FMOV_FMRCG_BIT 8 /* FM Right channel Gain */ -#define FMOV_FMRCG_MASK (0x1f<<FMOV_FMRCG_BIT) -#define FMOV_FMLCG_BIT 0 /* FM Left channel gain */ -#define FMOV_FMLCG_MASK 0x1f - -/* I2S Out Volume Reg */ -#define I2SV_I2SOM (1<<15) /* I2S Out Mute default 1: mute */ -#define I2SV_I2SRCG_BIT 8 /* I2S Right channel Gain */ -#define I2SV_I2SRCG_MASK (0x1f<<I2SV_I2SRCG_BIT) -#define I2SV_I2SLCG_BIT 0 /* I2S Left channel gain */ -#define I2SV_I2SLCG_MASK 0x1f - -/* Digital Recording Source Select Reg */ -#define DRSS_BIT 0 -#define DRSS_MASK 0x07 -#define DRSS_AC97_PRIM 0 -#define DRSS_FM 1 -#define DRSS_I2S 2 -#define DRSS_PCM 3 -#define DRSS_AC97_SEC 4 - -/* Playback/Capture Channel Control Registers */ -#define CC_SM (1<<15) /* Stereo, Mone 0: mono 1: stereo */ -#define CC_DF (1<<14) /* Data Format 0: 8 bit 1: 16 bit */ -#define CC_FMT_BIT 14 -#define CC_FMT_MASK (0x03<<CC_FMT_BIT) -#define CC_CF_BIT 12 /* Channel format (Playback only) */ -#define CC_CF_MASK (0x03<<CC_CF_BIT) -#define CC_CF_2 0 -#define CC_CF_4 (1<<CC_CF_BIT) -#define CC_CF_6 (2<<CC_CF_BIT) -#define CC_SR_BIT 8 /* sample Rate */ -#define CC_SR_MASK (0x0f<<CC_SR_BIT) -#define CC_SR_5500 0 -#define CC_SR_8000 (1<<CC_SR_BIT) -#define CC_SR_9600 (2<<CC_SR_BIT) -#define CC_SR_11025 (3<<CC_SR_BIT) -#define CC_SR_16000 (4<<CC_SR_BIT) -#define CC_SR_19200 (5<<CC_SR_BIT) -#define CC_SR_22050 (6<<CC_SR_BIT) -#define CC_SR_32000 (7<<CC_SR_BIT) -#define CC_SR_38400 (8<<CC_SR_BIT) -#define CC_SR_44100 (9<<CC_SR_BIT) -#define CC_SR_48000 (10<<CC_SR_BIT) -#define CC_CSP (1<<7) /* Channel stop - * 0: End of Current buffer - * 1: Immediately stop when rec stop */ -#define CC_CP (1<<6) /* Channel pause 0: normal, 1: pause */ -#define CC_CA (1<<5) /* Channel Action 0: Stop , 1: start */ -#define CC_CB2L (1<<2) /* Cur. buf. 2 xfr is last 0: No, 1: Yes */ -#define CC_CB1L (1<<1) /* Cur. buf. 1 xfr is last 0: No, 1: Yes */ -#define CC_DE 1 /* DFC/DFIFO Data Empty 1: empty, 0: not empty - * (Playback only) - */ - -/* Codec Control Reg */ -#define CODECC_GME (1<<9) /* AC97 GPIO Mode enable */ -#define CODECC_ATM (1<<8) /* AC97 ATE test mode 0: test 1: normal */ -#define CODECC_WR (1<<6) /* AC97 Warn reset 1: warm reset , 0: Normal */ -#define CODECC_CR (1<<5) /* AC97 Cold reset 1: Cold reset , 0: Normal */ - - -/* I2S Control Reg */ -#define I2SMC_SR_BIT 6 /* I2S Sampling rate - * 00: 48KHz, 01: 44.1 KHz, 10: 32 32 KHz */ -#define I2SMC_SR_MASK (0x03<<I2SMC_SR_BIT) -#define I2SMC_SR_48000 0 -#define I2SMC_SR_44100 (1<<I2SMC_SR_BIT) -#define I2SMC_SR_32000 (2<<I2SMC_SR_BIT) -#define I2SMC_SRSS (1<<5) /* Sample Rate Source Select 1:S/W, 0: H/W */ -#define I2SMC_I2SF_BIT 0 /* I2S Format */ -#define I2SMC_I2SF_MASK 0x03 -#define I2SMC_I2SF_DAC 0 -#define I2SMC_I2SF_ADC 2 -#define I2SMC_I2SF_I2S 3 - - -/* Volume up, Down, Mute */ -#define VS_VMP (1<<2) /* Volume mute 1: pushed, 0: not */ -#define VS_VDP (1<<1) /* Volume Down 1: pushed, 0: not */ -#define VS_VUP 1 /* Volime Up 1: pushed, 0: not */ - -/* SRC, Mixer test control/DFC status reg */ -#define SRCS_DPUSC (1<<5) /* DFC Playback underrun Status/clear */ -#define SRCS_DCOSC (1<<4) /* DFC Capture Overrun Status/clear */ -#define SRCS_SIS (1<<3) /* SRC input select 1: Mixer, 0: Codec I/F */ -#define SRCS_CDIS_BIT 0 /* Codec Data Input Select */ -#define SRCS_CDIS_MASK 0x07 -#define SRCS_CDIS_MIXER 0 -#define SRCS_CDIS_PCM 1 -#define SRCS_CDIS_I2S 2 -#define SRCS_CDIS_FM 3 -#define SRCS_CDIS_DFC 4 - - -/* Codec Index Reg command Port */ -#define CIRCP_CID_BIT 10 -#define CIRCP_CID_MASK (0x03<<CIRCP_CID_BIT) -#define CIRCP_CPS (1<<9) /* Command Port Status 0: ready, 1: busy */ -#define CIRCP_DPVF (1<<8) /* Data Port Valid Flag 0: invalis, 1: valid */ -#define CIRCP_RWC (1<<7) /* Read/write command */ -#define CIRCP_CIA_BIT 0 -#define CIRCP_CIA_MASK 0x007F /* Codec Index Address */ - -/* Test Mode Control/Test group Select Control */ - -/* General Control Reg */ -#define GC_VDC_BIT 6 /* Volume Division Control */ -#define GC_VDC_MASK (0x03<<GC_VDC_BIT) -#define GC_VDC_NONE 0 -#define GC_VDC_DIV2 (1<<GC_VDC_BIT) -#define GC_VDC_DIV4 (2<<GC_VDC_BIT) -#define GC_SOE (1<<2) /* S/PDIF Output enable */ -#define GC_SWR 1 /* Software warn reset */ - -/* Interrupt mask Control Reg */ -#define IMC_VCIM (1<<6) /* Volume CNTL interrupt mask */ -#define IMC_CCIM (1<<1) /* Capture Chan. iterrupt mask */ -#define IMC_PCIM 1 /* Playback Chan. interrupt mask */ - -/* Interrupt status/clear reg */ -#define ISC_VCI (1<<6) /* Volume CNTL interrupt 1: clears */ -#define ISC_CCI (1<<1) /* Capture Chan. interrupt 1: clears */ -#define ISC_PCI 1 /* Playback Chan. interrupt 1: clears */ - -/* misc stuff */ -#define POLL_COUNT 0x5000 - - -/* --------------------------------------------------------------------- */ - -/* - * Define DIGITAL1 as the I2S channel, since it is not listed in - * soundcard.h. - */ -#define SOUND_MIXER_I2S SOUND_MIXER_DIGITAL1 -#define SOUND_MASK_I2S SOUND_MASK_DIGITAL1 -#define SOUND_MIXER_READ_I2S MIXER_READ(SOUND_MIXER_I2S) -#define SOUND_MIXER_WRITE_I2S MIXER_WRITE(SOUND_MIXER_I2S) - -/* --------------------------------------------------------------------- */ - -struct it8172_state { - /* list of it8172 devices */ - struct list_head devs; - - /* the corresponding pci_dev structure */ - struct pci_dev *dev; - - /* soundcore stuff */ - int dev_audio; - - /* hardware resources */ - unsigned long io; - unsigned int irq; - - /* PCI ID's */ - u16 vendor; - u16 device; - u8 rev; /* the chip revision */ - - /* options */ - int spdif_volume; /* S/PDIF output is enabled if != -1 */ - int i2s_volume; /* current I2S out volume, in OSS format */ - int i2s_recording;/* 1 = recording from I2S, 0 = not */ - -#ifdef IT8172_DEBUG - /* debug /proc entry */ - struct proc_dir_entry *ps; - struct proc_dir_entry *ac97_ps; -#endif /* IT8172_DEBUG */ - - struct ac97_codec codec; - - unsigned short pcc, capcc; - unsigned dacrate, adcrate; - - spinlock_t lock; - struct mutex open_mutex; - mode_t open_mode; - wait_queue_head_t open_wait; - - struct dmabuf { - void *rawbuf; - dma_addr_t dmaaddr; - unsigned buforder; - unsigned numfrag; - unsigned fragshift; - void* nextIn; - void* nextOut; - int count; - int curBufPtr; - unsigned total_bytes; - unsigned error; /* over/underrun */ - wait_queue_head_t wait; - /* redundant, but makes calculations easier */ - unsigned fragsize; - unsigned dmasize; - unsigned fragsamples; - /* OSS stuff */ - unsigned mapped:1; - unsigned ready:1; - unsigned stopped:1; - unsigned ossfragshift; - int ossmaxfrags; - unsigned subdivision; - } dma_dac, dma_adc; -}; - -/* --------------------------------------------------------------------- */ - -static LIST_HEAD(devs); - -/* --------------------------------------------------------------------- */ - -static inline unsigned ld2(unsigned int x) -{ - unsigned r = 0; - - if (x >= 0x10000) { - x >>= 16; - r += 16; - } - if (x >= 0x100) { - x >>= 8; - r += 8; - } - if (x >= 0x10) { - x >>= 4; - r += 4; - } - if (x >= 4) { - x >>= 2; - r += 2; - } - if (x >= 2) - r++; - return r; -} - -/* --------------------------------------------------------------------- */ - -static void it8172_delay(int msec) -{ - unsigned long tmo; - signed long tmo2; - - if (in_interrupt()) - return; - - tmo = jiffies + (msec*HZ)/1000; - for (;;) { - tmo2 = tmo - jiffies; - if (tmo2 <= 0) - break; - schedule_timeout(tmo2); - } -} - - -static unsigned short -get_compat_rate(unsigned* rate) -{ - unsigned rate_out = *rate; - unsigned short sr; - - if (rate_out >= 46050) { - sr = CC_SR_48000; rate_out = 48000; - } else if (rate_out >= 41250) { - sr = CC_SR_44100; rate_out = 44100; - } else if (rate_out >= 35200) { - sr = CC_SR_38400; rate_out = 38400; - } else if (rate_out >= 27025) { - sr = CC_SR_32000; rate_out = 32000; - } else if (rate_out >= 20625) { - sr = CC_SR_22050; rate_out = 22050; - } else if (rate_out >= 17600) { - sr = CC_SR_19200; rate_out = 19200; - } else if (rate_out >= 13513) { - sr = CC_SR_16000; rate_out = 16000; - } else if (rate_out >= 10313) { - sr = CC_SR_11025; rate_out = 11025; - } else if (rate_out >= 8800) { - sr = CC_SR_9600; rate_out = 9600; - } else if (rate_out >= 6750) { - sr = CC_SR_8000; rate_out = 8000; - } else { - sr = CC_SR_5500; rate_out = 5500; - } - - *rate = rate_out; - return sr; -} - -static void set_adc_rate(struct it8172_state *s, unsigned rate) -{ - unsigned long flags; - unsigned short sr; - - sr = get_compat_rate(&rate); - - spin_lock_irqsave(&s->lock, flags); - s->capcc &= ~CC_SR_MASK; - s->capcc |= sr; - outw(s->capcc, s->io+IT_AC_CAPCC); - spin_unlock_irqrestore(&s->lock, flags); - - s->adcrate = rate; -} - - -static void set_dac_rate(struct it8172_state *s, unsigned rate) -{ - unsigned long flags; - unsigned short sr; - - sr = get_compat_rate(&rate); - - spin_lock_irqsave(&s->lock, flags); - s->pcc &= ~CC_SR_MASK; - s->pcc |= sr; - outw(s->pcc, s->io+IT_AC_PCC); - spin_unlock_irqrestore(&s->lock, flags); - - s->dacrate = rate; -} - - -/* --------------------------------------------------------------------- */ - -static u16 rdcodec(struct ac97_codec *codec, u8 addr) -{ - struct it8172_state *s = (struct it8172_state *)codec->private_data; - unsigned long flags; - unsigned short circp, data; - int i; - - spin_lock_irqsave(&s->lock, flags); - - for (i = 0; i < POLL_COUNT; i++) - if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS)) - break; - if (i == POLL_COUNT) - err("rdcodec: codec ready poll expired!"); - - circp = addr & CIRCP_CIA_MASK; - circp |= (codec->id << CIRCP_CID_BIT); - circp |= CIRCP_RWC; // read command - outw(circp, s->io+IT_AC_CIRCP); - - /* now wait for the data */ - for (i = 0; i < POLL_COUNT; i++) - if (inw(s->io+IT_AC_CIRCP) & CIRCP_DPVF) - break; - if (i == POLL_COUNT) - err("rdcodec: read poll expired!"); - - data = inw(s->io+IT_AC_CIRDP); - spin_unlock_irqrestore(&s->lock, flags); - - return data; -} - - -static void wrcodec(struct ac97_codec *codec, u8 addr, u16 data) -{ - struct it8172_state *s = (struct it8172_state *)codec->private_data; - unsigned long flags; - unsigned short circp; - int i; - - spin_lock_irqsave(&s->lock, flags); - - for (i = 0; i < POLL_COUNT; i++) - if (!(inw(s->io+IT_AC_CIRCP) & CIRCP_CPS)) - break; - if (i == POLL_COUNT) - err("wrcodec: codec ready poll expired!"); - - circp = addr & CIRCP_CIA_MASK; - circp |= (codec->id << CIRCP_CID_BIT); - circp &= ~CIRCP_RWC; // write command - - outw(data, s->io+IT_AC_CIRDP); // send data first - outw(circp, s->io+IT_AC_CIRCP); - - spin_unlock_irqrestore(&s->lock, flags); -} - - -static void waitcodec(struct ac97_codec *codec) -{ - unsigned short temp; - - /* codec_wait is used to wait for a ready state after - an AC97_RESET. */ - it8172_delay(10); - - temp = rdcodec(codec, 0x26); - - // If power down, power up - if (temp & 0x3f00) { - // Power on - wrcodec(codec, 0x26, 0); - it8172_delay(100); - // Reread - temp = rdcodec(codec, 0x26); - } - - // Check if Codec REF,ANL,DAC,ADC ready***/ - if ((temp & 0x3f0f) != 0x000f) { - err("codec reg 26 status (0x%x) not ready!!", temp); - return; - } -} - - -/* --------------------------------------------------------------------- */ - -static inline void stop_adc(struct it8172_state *s) -{ - struct dmabuf* db = &s->dma_adc; - unsigned long flags; - unsigned char imc; - - if (db->stopped) - return; - - spin_lock_irqsave(&s->lock, flags); - - s->capcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L); - s->capcc |= CC_CSP; - outw(s->capcc, s->io+IT_AC_CAPCC); - - // disable capture interrupt - imc = inb(s->io+IT_AC_IMC); - outb(imc | IMC_CCIM, s->io+IT_AC_IMC); - - db->stopped = 1; - - spin_unlock_irqrestore(&s->lock, flags); -} - -static inline void stop_dac(struct it8172_state *s) -{ - struct dmabuf* db = &s->dma_dac; - unsigned long flags; - unsigned char imc; - - if (db->stopped) - return; - - spin_lock_irqsave(&s->lock, flags); - - s->pcc &= ~(CC_CA | CC_CP | CC_CB2L | CC_CB1L); - s->pcc |= CC_CSP; - outw(s->pcc, s->io+IT_AC_PCC); - - // disable playback interrupt - imc = inb(s->io+IT_AC_IMC); - outb(imc | IMC_PCIM, s->io+IT_AC_IMC); - - db->stopped = 1; - - spin_unlock_irqrestore(&s->lock, flags); -} - -static void start_dac(struct it8172_state *s) -{ - struct dmabuf* db = &s->dma_dac; - unsigned long flags; - unsigned char imc; - unsigned long buf1, buf2; - - if (!db->stopped) - return; - - spin_lock_irqsave(&s->lock, flags); - - // reset Buffer 1 and 2 pointers to nextOut and nextOut+fragsize - buf1 = virt_to_bus(db->nextOut); - buf2 = buf1 + db->fragsize; - if (buf2 >= db->dmaaddr + db->dmasize) - buf2 -= db->dmasize; - - outl(buf1, s->io+IT_AC_PCB1STA); - outl(buf2, s->io+IT_AC_PCB2STA); - db->curBufPtr = IT_AC_PCB1STA; - - // enable playback interrupt - imc = inb(s->io+IT_AC_IMC); - outb(imc & ~IMC_PCIM, s->io+IT_AC_IMC); - - s->pcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L); - s->pcc |= CC_CA; - outw(s->pcc, s->io+IT_AC_PCC); - - db->stopped = 0; - - spin_unlock_irqrestore(&s->lock, flags); -} - -static void start_adc(struct it8172_state *s) -{ - struct dmabuf* db = &s->dma_adc; - unsigned long flags; - unsigned char imc; - unsigned long buf1, buf2; - - if (!db->stopped) - return; - - spin_lock_irqsave(&s->lock, flags); - - // reset Buffer 1 and 2 pointers to nextIn and nextIn+fragsize - buf1 = virt_to_bus(db->nextIn); - buf2 = buf1 + db->fragsize; - if (buf2 >= db->dmaaddr + db->dmasize) - buf2 -= db->dmasize; - - outl(buf1, s->io+IT_AC_CAPB1STA); - outl(buf2, s->io+IT_AC_CAPB2STA); - db->curBufPtr = IT_AC_CAPB1STA; - - // enable capture interrupt - imc = inb(s->io+IT_AC_IMC); - outb(imc & ~IMC_CCIM, s->io+IT_AC_IMC); - - s->capcc &= ~(CC_CSP | CC_CP | CC_CB2L | CC_CB1L); - s->capcc |= CC_CA; - outw(s->capcc, s->io+IT_AC_CAPCC); - - db->stopped = 0; - - spin_unlock_irqrestore(&s->lock, flags); -} - -/* --------------------------------------------------------------------- */ - -#define DMABUF_DEFAULTORDER (17-PAGE_SHIFT) -#define DMABUF_MINORDER 1 - -static inline void dealloc_dmabuf(struct it8172_state *s, struct dmabuf *db) -{ - struct page *page, *pend; - - if (db->rawbuf) { - /* undo marking the pages as reserved */ - pend = virt_to_page(db->rawbuf + - (PAGE_SIZE << db->buforder) - 1); - for (page = virt_to_page(db->rawbuf); page <= pend; page++) - ClearPageReserved(page); - pci_free_consistent(s->dev, PAGE_SIZE << db->buforder, - db->rawbuf, db->dmaaddr); - } - db->rawbuf = db->nextIn = db->nextOut = NULL; - db->mapped = db->ready = 0; -} - -static int prog_dmabuf(struct it8172_state *s, struct dmabuf *db, - unsigned rate, unsigned fmt, unsigned reg) -{ - int order; - unsigned bytepersec; - unsigned bufs; - struct page *page, *pend; - - if (!db->rawbuf) { - db->ready = db->mapped = 0; - for (order = DMABUF_DEFAULTORDER; - order >= DMABUF_MINORDER; order--) - if ((db->rawbuf = - pci_alloc_consistent(s->dev, - PAGE_SIZE << order, - &db->dmaaddr))) - break; - if (!db->rawbuf) - return -ENOMEM; - db->buforder = order; - /* now mark the pages as reserved; - otherwise remap_pfn_range doesn't do what we want */ - pend = virt_to_page(db->rawbuf + - (PAGE_SIZE << db->buforder) - 1); - for (page = virt_to_page(db->rawbuf); page <= pend; page++) - SetPageReserved(page); - } - - db->count = 0; - db->nextIn = db->nextOut = db->rawbuf; - - bytepersec = rate << sample_shift[fmt]; - bufs = PAGE_SIZE << db->buforder; - if (db->ossfragshift) { - if ((1000 << db->ossfragshift) < bytepersec) - db->fragshift = ld2(bytepersec/1000); - else - db->fragshift = db->ossfragshift; - } else { - db->fragshift = ld2(bytepersec/100/(db->subdivision ? - db->subdivision : 1)); - if (db->fragshift < 3) - db->fragshift = 3; - } - db->numfrag = bufs >> db->fragshift; - while (db->numfrag < 4 && db->fragshift > 3) { - db->fragshift--; - db->numfrag = bufs >> db->fragshift; - } - db->fragsize = 1 << db->fragshift; - if (db->ossmaxfrags >= 4 && db->ossmaxfrags < db->numfrag) - db->numfrag = db->ossmaxfrags; - db->fragsamples = db->fragsize >> sample_shift[fmt]; - db->dmasize = db->numfrag << db->fragshift; - memset(db->rawbuf, (fmt & (CC_DF>>CC_FMT_BIT)) ? 0 : 0x80, bufs); - -#ifdef IT8172_VERBOSE_DEBUG - dbg("rate=%d, fragsize=%d, numfrag=%d, dmasize=%d", - rate, db->fragsize, db->numfrag, db->dmasize); -#endif - - // set data length register - outw(db->fragsize, s->io+reg+2); - db->ready = 1; - - return 0; -} - -static inline int prog_dmabuf_adc(struct it8172_state *s) -{ - stop_adc(s); - return prog_dmabuf(s, &s->dma_adc, s->adcrate, - (s->capcc & CC_FMT_MASK) >> CC_FMT_BIT, - IT_AC_CAPCC); -} - -static inline int prog_dmabuf_dac(struct it8172_state *s) -{ - stop_dac(s); - return prog_dmabuf(s, &s->dma_dac, s->dacrate, - (s->pcc & CC_FMT_MASK) >> CC_FMT_BIT, - IT_AC_PCC); -} - - -/* hold spinlock for the following! */ - -static irqreturn_t it8172_interrupt(int irq, void *dev_id, struct pt_regs *regs) -{ - struct it8172_state *s = (struct it8172_state *)dev_id; - struct dmabuf* dac = &s->dma_dac; - struct dmabuf* adc = &s->dma_adc; - unsigned char isc, vs; - unsigned short vol, mute; - unsigned long newptr; - - spin_lock(&s->lock); - - isc = inb(s->io+IT_AC_ISC); - - /* fastpath out, to ease interrupt sharing */ - if (!(isc & (ISC_VCI | ISC_CCI | ISC_PCI))) { - spin_unlock(&s->lock); - return IRQ_NONE; - } - - /* clear audio interrupts first */ - outb(isc | ISC_VCI | ISC_CCI | ISC_PCI, s->io+IT_AC_ISC); - - /* handle volume button events (ignore if S/PDIF enabled) */ - if ((isc & ISC_VCI) && s->spdif_volume == -1) { - vs = inb(s->io+IT_AC_VS); - outb(0, s->io+IT_AC_VS); - vol = inw(s->io+IT_AC_PCMOV); - mute = vol & PCMOV_PCMOM; - vol &= PCMOV_PCMLCG_MASK; - if ((vs & VS_VUP) && vol > 0) - vol--; - if ((vs & VS_VDP) && vol < 0x1f) - vol++; - vol |= (vol << PCMOV_PCMRCG_BIT); - if (vs & VS_VMP) - vol |= (mute ^ PCMOV_PCMOM); - outw(vol, s->io+IT_AC_PCMOV); - } - - /* update capture pointers */ - if (isc & ISC_CCI) { - if (adc->count > adc->dmasize - adc->fragsize) { - // Overrun. Stop ADC and log the error - stop_adc(s); - adc->error++; - dbg("adc overrun"); - } else { - newptr = virt_to_bus(adc->nextIn) + 2*adc->fragsize; - if (newptr >= adc->dmaaddr + adc->dmasize) - newptr -= adc->dmasize; - - outl(newptr, s->io+adc->curBufPtr); - adc->curBufPtr = (adc->curBufPtr == IT_AC_CAPB1STA) ? - IT_AC_CAPB2STA : IT_AC_CAPB1STA; - - adc->nextIn += adc->fragsize; - if (adc->nextIn >= adc->rawbuf + adc->dmasize) - adc->nextIn -= adc->dmasize; - - adc->count += adc->fragsize; - adc->total_bytes += adc->fragsize; - - /* wake up anybody listening */ - if (waitqueue_active(&adc->wait)) - wake_up_interruptible(&adc->wait); - } - } - - /* update playback pointers */ - if (isc & ISC_PCI) { - newptr = virt_to_bus(dac->nextOut) + 2*dac->fragsize; - if (newptr >= dac->dmaaddr + dac->dmasize) - newptr -= dac->dmasize; - - outl(newptr, s->io+dac->curBufPtr); - dac->curBufPtr = (dac->curBufPtr == IT_AC_PCB1STA) ? - IT_AC_PCB2STA : IT_AC_PCB1STA; - - dac->nextOut += dac->fragsize; - if (dac->nextOut >= dac->rawbuf + dac->dmasize) - dac->nextOut -= dac->dmasize; - - dac->count -= dac->fragsize; - dac->total_bytes += dac->fragsize; - - /* wake up anybody listening */ - if (waitqueue_active(&dac->wait)) - wake_up_interruptible(&dac->wait); - - if (dac->count <= 0) - stop_dac(s); - } - - spin_unlock(&s->lock); - return IRQ_HANDLED; -} - -/* --------------------------------------------------------------------- */ - -static int it8172_open_mixdev(struct inode *inode, struct file *file) -{ - int minor = iminor(inode); - struct list_head *list; - struct it8172_state *s; - - for (list = devs.next; ; list = list->next) { - if (list == &devs) - return -ENODEV; - s = list_entry(list, struct it8172_state, devs); - if (s->codec.dev_mixer == minor) - break; - } - file->private_data = s; - return nonseekable_open(inode, file); -} - -static int it8172_release_mixdev(struct inode *inode, struct file *file) -{ - return 0; -} - - -static u16 -cvt_ossvol(unsigned int gain) -{ - u16 ret; - - if (gain == 0) - return 0; - - if (gain > 100) - gain = 100; - - ret = (100 - gain + 32) / 4; - ret = ret > 31 ? 31 : ret; - return ret; -} - - -static int mixdev_ioctl(struct ac97_codec *codec, unsigned int cmd, - unsigned long arg) -{ - struct it8172_state *s = (struct it8172_state *)codec->private_data; - unsigned int left, right; - unsigned long flags; - int val; - u16 vol; - - /* - * When we are in S/PDIF mode, we want to disable any analog output so - * we filter the master/PCM channel volume ioctls. - * - * Also filter I2S channel, which AC'97 knows nothing about. - */ - - switch (cmd) { - case SOUND_MIXER_WRITE_VOLUME: - // if not in S/PDIF mode, pass to AC'97 - if (s->spdif_volume == -1) - break; - return 0; - case SOUND_MIXER_WRITE_PCM: - // if not in S/PDIF mode, pass to AC'97 - if (s->spdif_volume == -1) - break; - if (get_user(val, (int *)arg)) - return -EFAULT; - right = ((val >> 8) & 0xff); - left = (val & 0xff); - if (right > 100) - right = 100; - if (left > 100) - left = 100; - s->spdif_volume = (right << 8) | left; - vol = cvt_ossvol(left); - vol |= (cvt_ossvol(right) << PCMOV_PCMRCG_BIT); - if (vol == 0) - vol = PCMOV_PCMOM; // mute - spin_lock_irqsave(&s->lock, flags); - outw(vol, s->io+IT_AC_PCMOV); - spin_unlock_irqrestore(&s->lock, flags); - return put_user(s->spdif_volume, (int *)arg); - case SOUND_MIXER_READ_PCM: - // if not in S/PDIF mode, pass to AC'97 - if (s->spdif_volume == -1) - break; - return put_user(s->spdif_volume, (int *)arg); - case SOUND_MIXER_WRITE_I2S: - if (get_user(val, (int *)arg)) - return -EFAULT; - right = ((val >> 8) & 0xff); - left = (val & 0xff); - if (right > 100) - right = 100; - if (left > 100) - left = 100; - s->i2s_volume = (right << 8) | left; - vol = cvt_ossvol(left); - vol |= (cvt_ossvol(right) << I2SV_I2SRCG_BIT); - if (vol == 0) - vol = I2SV_I2SOM; // mute - outw(vol, s->io+IT_AC_I2SV); - return put_user(s->i2s_volume, (int *)arg); - case SOUND_MIXER_READ_I2S: - return put_user(s->i2s_volume, (int *)arg); - case SOUND_MIXER_WRITE_RECSRC: - if (get_user(val, (int *)arg)) - return -EFAULT; - if (val & SOUND_MASK_I2S) { - s->i2s_recording = 1; - outb(DRSS_I2S, s->io+IT_AC_DRSS); - return 0; - } else { - s->i2s_recording = 0; - outb(DRSS_AC97_PRIM, s->io+IT_AC_DRSS); - // now let AC'97 select record source - break; - } - case SOUND_MIXER_READ_RECSRC: - if (s->i2s_recording) - return put_user(SOUND_MASK_I2S, (int *)arg); - else - // let AC'97 report recording source - break; - } - - return codec->mixer_ioctl(codec, cmd, arg); -} - -static int it8172_ioctl_mixdev(struct inode *inode, struct file *file, - unsigned int cmd, unsigned long arg) -{ - struct it8172_state *s = (struct it8172_state *)file->private_data; - struct ac97_codec *codec = &s->codec; - - return mixdev_ioctl(codec, cmd, arg); -} - -static /*const*/ struct file_operations it8172_mixer_fops = { - .owner = THIS_MODULE, - .llseek = no_llseek, - .ioctl = it8172_ioctl_mixdev, - .open = it8172_open_mixdev, - .release = it8172_release_mixdev, -}; - -/* --------------------------------------------------------------------- */ - -static int drain_dac(struct it8172_state *s, int nonblock) -{ - unsigned long flags; - int count, tmo; - - if (s->dma_dac.mapped || !s->dma_dac.ready || s->dma_dac.stopped) - return 0; - - for (;;) { - spin_lock_irqsave(&s->lock, flags); - count = s->dma_dac.count; - spin_unlock_irqrestore(&s->lock, flags); - if (count <= 0) - break; - if (signal_pending(current)) - break; - //if (nonblock) - //return -EBUSY; - tmo = 1000 * count / s->dacrate; - tmo >>= sample_shift[(s->pcc & CC_FMT_MASK) >> CC_FMT_BIT]; - it8172_delay(tmo); - } - if (signal_pending(current)) - return -ERESTARTSYS; - return 0; -} - -/* --------------------------------------------------------------------- */ - - -/* - * Copy audio data to/from user buffer from/to dma buffer, taking care - * that we wrap when reading/writing the dma buffer. Returns actual byte - * count written to or read from the dma buffer. - */ -static int copy_dmabuf_user(struct dmabuf *db, char* userbuf, - int count, int to_user) -{ - char* bufptr = to_user ? db->nextOut : db->nextIn; - char* bufend = db->rawbuf + db->dmasize; - - if (bufptr + count > bufend) { - int partial = (int)(bufend - bufptr); - if (to_user) { - if (copy_to_user(userbuf, bufptr, partial)) - return -EFAULT; - if (copy_to_user(userbuf + partial, db->rawbuf, - count - partial)) - return -EFAULT; - } else { - if (copy_from_user(bufptr, userbuf, partial)) - return -EFAULT; - if (copy_from_user(db->rawbuf, - userbuf + partial, - count - partial)) - return -EFAULT; - } - } else { - if (to_user) { - if (copy_to_user(userbuf, bufptr, count)) - return -EFAULT; |