trident.c
来自「Linux Kernel 2.6.9 for OMAP1710」· C语言 代码 · 共 2,286 行 · 第 1/5 页
C
2,286 行
/* * OSS driver for Linux 2.[46].x for * * Trident 4D-Wave * SiS 7018 * ALi 5451 * Tvia/IGST CyberPro 5050 * * Driver: Alan Cox <alan@redhat.com> * * Built from: * Low level code: <audio@tridentmicro.com> from ALSA * Framework: Thomas Sailer <sailer@ife.ee.ethz.ch> * Extended by: Zach Brown <zab@redhat.com> * * Hacked up by: * Aaron Holtzman <aholtzma@ess.engr.uvic.ca> * Ollie Lho <ollie@sis.com.tw> SiS 7018 Audio Core Support * Ching-Ling Lee <cling-li@ali.com.tw> ALi 5451 Audio Core Support * Matt Wu <mattwu@acersoftech.com.cn> ALi 5451 Audio Core Support * Peter W鋍htler <pwaechtler@loewe-komp.de> CyberPro5050 support * Muli Ben-Yehuda <mulix@mulix.org> * * * 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 program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * 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. * * History * v0.14.10j * January 3 2004 Eugene Teo <eugeneteo@eugeneteo.net> * minor cleanup to use pr_debug instead of TRDBG since it is already * defined in linux/kernel.h. * v0.14.10i * December 29 2003 Muli Ben-Yehuda <mulix@mulix.org> * major cleanup for 2.6, fix a few error patch buglets * with returning without properly cleaning up first, * get rid of lock_kernel(). * v0.14.10h * Sept 10 2002 Pascal Schmidt <der.eremit@email.de> * added support for ALi 5451 joystick port * v0.14.10g * Sept 05 2002 Alan Cox <alan@redhat.com> * adapt to new pci joystick attachment interface * v0.14.10f * July 24 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * patch from Eric Lemar (via Ian Soboroff): in suspend and resume, * fix wrong cast from pci_dev* to struct trident_card*. * v0.14.10e * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * rewrite the DMA buffer allocation/deallcoation functions, to make it * modular and fix a bug where we would call free_pages on memory * obtained with pci_alloc_consistent. Also remove unnecessary #ifdef * CONFIG_PROC_FS and various other cleanups. * v0.14.10d * July 19 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * made several printk(KERN_NOTICE...) into TRDBG(...), to avoid spamming * my syslog with hundreds of messages. * v0.14.10c * July 16 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * Cleaned up Lei Hu's 0.4.10 driver to conform to Documentation/CodingStyle * and the coding style used in the rest of the file. * v0.14.10b * June 23 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * add a missing unlock_set_fmt, remove a superflous lock/unlock pair * with nothing in between. * v0.14.10a * June 21 2002 Muli Ben-Yehuda <mulix@actcom.co.il> * use a debug macro instead of #ifdef CONFIG_DEBUG, trim to 80 columns * per line, use 'do {} while (0)' in statement macros. * v0.14.10 * June 6 2002 Lei Hu <Lei_hu@ali.com.tw> * rewrite the part to read/write registers of audio codec for Ali5451 * v0.14.9e * January 2 2002 Vojtech Pavlik <vojtech@ucw.cz> added gameport * support to avoid resource conflict with pcigame.c * v0.14.9d * October 8 2001 Arnaldo Carvalho de Melo <acme@conectiva.com.br> * use set_current_state, properly release resources on failure in * trident_probe, get rid of check_region * v0.14.9c * August 10 2001 Peter W鋍htler <pwaechtler@loewe-komp.de> * added support for Tvia (formerly Integraphics/IGST) CyberPro5050 * this chip is often found in settop boxes (combined video+audio) * v0.14.9b * Switch to static inline not extern inline (gcc 3) * v0.14.9a * Aug 6 2001 Alan Cox * 0.14.9 crashed on rmmod due to a timer/bh left running. Simplified * the existing logic (the BH doesn't help as ac97 is lock_irqsave) * and used del_timer_sync to clean up * Fixed a problem where the ALi change broke my generic card * v0.14.9 * Jul 10 2001 Matt Wu * Add H/W Volume Control * v0.14.8a * July 7 2001 Alan Cox * Moved Matt Wu's ac97 register cache into the card structure * v0.14.8 * Apr 30 2001 Matt Wu * Set EBUF1 and EBUF2 to still mode * Add dc97/ac97 reset function * Fix power management: ali_restore_regs * unreleased * Mar 09 2001 Matt Wu * Add cache for ac97 access * v0.14.7 * Feb 06 2001 Matt Wu * Fix ac97 initialization * Fix bug: an extra tail will be played when playing * Jan 05 2001 Matt Wu * Implement multi-channels and S/PDIF in support for ALi 1535+ * v0.14.6 * Nov 1 2000 Ching-Ling Lee * Fix the bug of memory leak when switching 5.1-channels to 2 channels. * Add lock protection into dynamic changing format of data. * Oct 18 2000 Ching-Ling Lee * 5.1-channels support for ALi * June 28 2000 Ching-Ling Lee * S/PDIF out/in(playback/record) support for ALi 1535+, using /proc to be selected by user * Simple Power Management support for ALi * v0.14.5 May 23 2000 Ollie Lho * Misc bug fix from the Net * v0.14.4 May 20 2000 Aaron Holtzman * Fix kfree'd memory access in release * Fix race in open while looking for a free virtual channel slot * remove open_wait wq (which appears to be unused) * v0.14.3 May 10 2000 Ollie Lho * fixed a small bug in trident_update_ptr, xmms 1.0.1 no longer uses 100% CPU * v0.14.2 Mar 29 2000 Ching-Ling Lee * Add clear to silence advance in trident_update_ptr * fix invalid data of the end of the sound * v0.14.1 Mar 24 2000 Ching-Ling Lee * ALi 5451 support added, playback and recording O.K. * ALi 5451 originally developed and structured based on sonicvibes, and * suggested to merge into this file by Alan Cox. * v0.14 Mar 15 2000 Ollie Lho * 5.1 channel output support with channel binding. What's the Matrix ? * v0.13.1 Mar 10 2000 Ollie Lho * few minor bugs on dual codec support, needs more testing * v0.13 Mar 03 2000 Ollie Lho * new pci_* for 2.4 kernel, back ported to 2.2 * v0.12 Feb 23 2000 Ollie Lho * Preliminary Recording support * v0.11.2 Feb 19 2000 Ollie Lho * removed incomplete full-dulplex support * v0.11.1 Jan 28 2000 Ollie Lho * small bug in setting sample rate for 4d-nx (reported by Aaron) * v0.11 Jan 27 2000 Ollie Lho * DMA bug, scheduler latency, second try * v0.10 Jan 24 2000 Ollie Lho * DMA bug fixed, found kernel scheduling problem * v0.09 Jan 20 2000 Ollie Lho * Clean up of channel register access routine (prepare for channel binding) * v0.08 Jan 14 2000 Ollie Lho * Isolation of AC97 codec code * v0.07 Jan 13 2000 Ollie Lho * Get rid of ugly old low level access routines (e.g. CHRegs.lp****) * v0.06 Jan 11 2000 Ollie Lho * Preliminary support for dual (more ?) AC97 codecs * v0.05 Jan 08 2000 Luca Montecchiani <m.luca@iname.com> * adapt to 2.3.x new __setup/__init call * v0.04 Dec 31 1999 Ollie Lho * Multiple Open, using Middle Loop Interrupt to smooth playback * v0.03 Dec 24 1999 Ollie Lho * mem leak in prog_dmabuf and dealloc_dmabuf removed * v0.02 Dec 15 1999 Ollie Lho * SiS 7018 support added, playback O.K. * v0.01 Alan Cox et. al. * Initial Release in kernel 2.3.30, does not work * * ToDo * Clean up of low level channel register access code. (done) * Fix the bug on dma buffer management in update_ptr, read/write, drain_dac (done) * Dual AC97 codecs support (done) * Recording support (done) * Mmap support * "Channel Binding" ioctl extension (done) * new pci device driver interface for 2.4 kernel (done) * * Lock order (high->low) * lock - hardware lock * open_sem - guard opens * sem - guard dmabuf, write re-entry etc */#include <linux/config.h>#include <linux/module.h>#include <linux/string.h>#include <linux/ctype.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/spinlock.h>#include <linux/smp_lock.h>#include <linux/ac97_codec.h>#include <linux/bitops.h>#include <linux/proc_fs.h>#include <linux/interrupt.h>#include <linux/pm.h>#include <linux/gameport.h>#include <linux/kernel.h>#include <asm/uaccess.h>#include <asm/io.h>#include <asm/dma.h>#if defined(CONFIG_ALPHA_NAUTILUS) || defined(CONFIG_ALPHA_GENERIC)#include <asm/hwrpb.h>#endif#include "trident.h"#define DRIVER_VERSION "0.14.10j-2.6"/* magic numbers to protect our data structures */#define TRIDENT_CARD_MAGIC 0x5072696E /* "Prin" */#define TRIDENT_STATE_MAGIC 0x63657373 /* "cess" */#define TRIDENT_DMA_MASK 0x3fffffff /* DMA buffer mask for pci_alloc_consist */#define ALI_DMA_MASK 0x7fffffff /* ALI Tridents have 31-bit DMA. Wow. */#define NR_HW_CH 32/* maximum number of AC97 codecs connected, AC97 2.0 defined 4, but 7018 and 4D-NX only have 2 SDATA_IN lines (currently) */#define NR_AC97 2/* minor number of /dev/swmodem (temporary, experimental) */#define SND_DEV_SWMODEM 7static const unsigned ali_multi_channels_5_1[] = { /*ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL, */ ALI_CENTER_CHANNEL, ALI_LEF_CHANNEL, ALI_SURR_LEFT_CHANNEL, ALI_SURR_RIGHT_CHANNEL};static const unsigned sample_size[] = { 1, 2, 2, 4 };static const unsigned sample_shift[] = { 0, 1, 1, 2 };static const char invalid_magic[] = KERN_CRIT "trident: invalid magic value in %s\n";enum { TRIDENT_4D_DX = 0, TRIDENT_4D_NX, SIS_7018, ALI_5451, CYBER5050};static char *card_names[] = { "Trident 4DWave DX", "Trident 4DWave NX", "SiS 7018 PCI Audio", "ALi Audio Accelerator", "Tvia/IGST CyberPro 5050"};static struct pci_device_id trident_pci_tbl[] = { {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_DX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_DX}, {PCI_VENDOR_ID_TRIDENT, PCI_DEVICE_ID_TRIDENT_4DWAVE_NX, PCI_ANY_ID, PCI_ANY_ID, 0, 0, TRIDENT_4D_NX}, {PCI_VENDOR_ID_SI, PCI_DEVICE_ID_SI_7018, PCI_ANY_ID, PCI_ANY_ID, 0, 0, SIS_7018}, {PCI_VENDOR_ID_ALI, PCI_DEVICE_ID_ALI_5451, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ALI_5451}, {PCI_VENDOR_ID_INTERG, PCI_DEVICE_ID_INTERG_5050, PCI_ANY_ID, PCI_ANY_ID, 0, 0, CYBER5050}, {0,}};MODULE_DEVICE_TABLE(pci, trident_pci_tbl);/* "software" or virtual channel, an instance of opened /dev/dsp */struct trident_state { unsigned int magic; struct trident_card *card; /* Card info */ /* file mode */ mode_t open_mode; /* virtual channel number */ int virt; struct dmabuf { /* wave sample stuff */ unsigned int rate; unsigned char fmt, enable; /* hardware channel */ struct trident_channel *channel; /* OSS buffer management stuff */ void *rawbuf; dma_addr_t dma_handle; unsigned buforder; unsigned numfrag; unsigned fragshift; /* our buffer acts like a circular ring */ unsigned hwptr; /* where dma last started, updated by update_ptr */ unsigned swptr; /* where driver last clear/filled, updated by read/write */ int count; /* bytes to be comsumed or been generated by dma machine */ unsigned total_bytes; /* total bytes dmaed by hardware */ unsigned error; /* number of over/underruns */ /* put process on wait queue when no more space in buffer */ 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 endcleared:1; unsigned update_flag; unsigned ossfragshift; int ossmaxfrags; unsigned subdivision; } dmabuf; /* 5.1 channels */ struct trident_state *other_states[4]; int multi_channels_adjust_count; unsigned chans_num; unsigned long fmt_flag; /* Guard against mmap/write/read races */ struct semaphore sem;};/* hardware channels */struct trident_channel { int num; /* channel number */ u32 lba; /* Loop Begine Address, where dma buffer starts */ u32 eso; /* End Sample Offset, wehre dma buffer ends */ /* (in the unit of samples) */ u32 delta; /* delta value, sample rate / 48k for playback, */ /* 48k/sample rate for recording */ u16 attribute; /* control where PCM data go and come */ u16 fm_vol; u32 control; /* signed/unsigned, 8/16 bits, mono/stereo */};struct trident_pcm_bank_address { u32 start; u32 stop; u32 aint; u32 aint_en;};static struct trident_pcm_bank_address bank_a_addrs = { T4D_START_A, T4D_STOP_A, T4D_AINT_A, T4D_AINTEN_A};static struct trident_pcm_bank_address bank_b_addrs = { T4D_START_B, T4D_STOP_B, T4D_AINT_B, T4D_AINTEN_B};struct trident_pcm_bank { /* register addresses to control bank operations */ struct trident_pcm_bank_address *addresses; /* each bank has 32 channels */ u32 bitmap; /* channel allocation bitmap */ struct trident_channel channels[32];};struct trident_card { unsigned int magic; /* We keep trident cards in a linked list */ struct trident_card *next; /* single open lock mechanism, only used for recording */ struct semaphore open_sem; /* The trident has a certain amount of cross channel interaction so we use a single per card lock */ spinlock_t lock; /* PCI device stuff */ struct pci_dev *pci_dev; u16 pci_id; u8 revision; /* soundcore stuff */ int dev_audio; /* structures for abstraction of hardware facilities, codecs, */ /* banks and channels */ struct ac97_codec *ac97_codec[NR_AC97]; struct trident_pcm_bank banks[NR_BANKS]; struct trident_state *states[NR_HW_CH]; /* hardware resources */ unsigned long iobase; u32 irq; /* Function support */ struct trident_channel *(*alloc_pcm_channel) (struct trident_card *); struct trident_channel *(*alloc_rec_pcm_channel) (struct trident_card *); void (*free_pcm_channel) (struct trident_card *, unsigned int chan); void (*address_interrupt) (struct trident_card *); /* Added by Matt Wu 01-05-2001 for spdif in */ int multi_channel_use_count; int rec_channel_use_count; u16 mixer_regs[64][NR_AC97]; /* Made card local by Alan */ int mixer_regs_ready; /* Added for hardware volume control */ int hwvolctl; struct timer_list timer; /* Game port support */ struct gameport gameport;};enum dmabuf_mode { DM_PLAYBACK = 0, DM_RECORD};/* table to map from CHANNELMASK to channel attribute for SiS 7018 */static u16 mask2attr[] = { PCM_LR, PCM_LR, SURR_LR, CENTER_LFE, HSET, MIC, MODEM_LINE1, MODEM_LINE2, I2S_LR, SPDIF_LR};
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?