📄 vwsnd.c
字号:
/* * Sound driver for Silicon Graphics 320 and 540 Visual Workstations' * onboard audio. See notes in ../../Documentation/sound/vwsnd . * * Copyright 1999 Silicon Graphics, Inc. All rights reserved. * * 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. */#undef VWSND_DEBUG /* define for debugging *//* * XXX to do - * * External sync. * Rename swbuf, hwbuf, u&i, hwptr&swptr to something rational. * Bug - if select() called before read(), pcm_setup() not called. * Bug - output doesn't stop soon enough if process killed. *//* * Things to test - * * Will readv/writev work? Write a test. * * insmod/rmmod 100 million times. * * Run I/O until int ptrs wrap around (roughly 6.2 hours @ DAT * rate). * * Concurrent threads banging on mixer simultaneously, both UP * and SMP kernels. Especially, watch for thread A changing * OUTSRC while thread B changes gain -- both write to the same * ad1843 register. * * What happens if a client opens /dev/audio then forks? * Do two procs have /dev/audio open? Test. * * Pump audio through the CD, MIC and line inputs and verify that * they mix/mute into the output. * * Apps: * amp * mpg123 * x11amp * mxv * kmedia * esound * need more input apps * * Run tests while bombarding with signals. setitimer(2) will do it... *//* * This driver is organized in nine sections. * The nine sections are: * * debug stuff * low level lithium access * high level lithium access * AD1843 access * PCM I/O * audio driver * mixer driver * probe/attach/unload * initialization and loadable kernel module interface * * That is roughly the order of increasing abstraction, so forward * dependencies are minimal. *//* * Locking Notes * * INC_USE_COUNT and DEC_USE_COUNT keep track of the number of * open descriptors to this driver. They store it in vwsnd_use_count. * The global device list, vwsnd_dev_list, is immutable when the IN_USE * is true. * * devc->open_lock is a semaphore that is used to enforce the * single reader/single writer rule for /dev/audio. The rule is * that each device may have at most one reader and one writer. * Open will block until the previous client has closed the * device, unless O_NONBLOCK is specified. * * The semaphore devc->io_sema serializes PCM I/O syscalls. This * is unnecessary in Linux 2.2, because the kernel lock * serializes read, write, and ioctl globally, but it's there, * ready for the brave, new post-kernel-lock world. * * Locking between interrupt and baselevel is handled by the * "lock" spinlock in vwsnd_port (one lock each for read and * write). Each half holds the lock just long enough to see what * area it owns and update its pointers. See pcm_output() and * pcm_input() for most of the gory stuff. * * devc->mix_sema serializes all mixer ioctls. This is also * redundant because of the kernel lock. * * The lowest level lock is lith->lithium_lock. It is a * spinlock which is held during the two-register tango of * reading/writing an AD1843 register. See * li_{read,write}_ad1843_reg(). *//* * Sample Format Notes * * Lithium's DMA engine has two formats: 16-bit 2's complement * and 8-bit unsigned . 16-bit transfers the data unmodified, 2 * bytes per sample. 8-bit unsigned transfers 1 byte per sample * and XORs each byte with 0x80. Lithium can input or output * either mono or stereo in either format. * * The AD1843 has four formats: 16-bit 2's complement, 8-bit * unsigned, 8-bit mu-Law and 8-bit A-Law. * * This driver supports five formats: AFMT_S8, AFMT_U8, * AFMT_MU_LAW, AFMT_A_LAW, and AFMT_S16_LE. * * For AFMT_U8 output, we keep the AD1843 in 16-bit mode, and * rely on Lithium's XOR to translate between U8 and S8. * * For AFMT_S8, AFMT_MU_LAW and AFMT_A_LAW output, we have to XOR * the 0x80 bit in software to compensate for Lithium's XOR. * This happens in pcm_copy_{in,out}(). * * Changes: * 11-10-2000 Bartlomiej Zolnierkiewicz <bkz@linux-ide.org> * Added some __init/__exit */#include <linux/module.h>#include <linux/init.h>#include <linux/sched.h>#include <linux/semaphore.h>#include <linux/stddef.h>#include <linux/spinlock.h>#include <linux/smp_lock.h>#include <asm/fixmap.h>#include <asm/cobalt.h>#include <asm/semaphore.h>#include "sound_config.h"/*****************************************************************************//* debug stuff */#ifdef VWSND_DEBUG#include <linux/interrupt.h> /* for in_interrupt() */static int shut_up = 1;/* * dbgassert - called when an assertion fails. */static void dbgassert(const char *fcn, int line, const char *expr){ if (in_interrupt()) panic("ASSERTION FAILED IN INTERRUPT, %s:%s:%d %s\n", __FILE__, fcn, line, expr); else { int x; printk(KERN_ERR "ASSERTION FAILED, %s:%s:%d %s\n", __FILE__, fcn, line, expr); x = * (volatile int *) 0; /* force proc to exit */ }}/* * Bunch of useful debug macros: * * ASSERT - print unless e nonzero (panic if in interrupt) * DBGDO - include arbitrary code if debugging * DBGX - debug print raw (w/o function name) * DBGP - debug print w/ function name * DBGE - debug print function entry * DBGC - debug print function call * DBGR - debug print function return * DBGXV - debug print raw when verbose * DBGPV - debug print when verbose * DBGEV - debug print function entry when verbose * DBGRV - debug print function return when verbose */#define ASSERT(e) ((e) ? (void) 0 : dbgassert(__FUNCTION__, __LINE__, #e))#define DBGDO(x) x#define DBGX(fmt, args...) (in_interrupt() ? 0 : printk(KERN_ERR fmt, ##args))#define DBGP(fmt, args...) (DBGX(__FUNCTION__ ": " fmt, ##args))#define DBGE(fmt, args...) (DBGX(__FUNCTION__ fmt, ##args))#define DBGC(rtn) (DBGP("calling %s\n", rtn))#define DBGR() (DBGP("returning\n"))#define DBGXV(fmt, args...) (shut_up ? 0 : DBGX(fmt, ##args))#define DBGPV(fmt, args...) (shut_up ? 0 : DBGP(fmt, ##args))#define DBGEV(fmt, args...) (shut_up ? 0 : DBGE(fmt, ##args))#define DBGCV(rtn) (shut_up ? 0 : DBGC(rtn))#define DBGRV() (shut_up ? 0 : DBGR())#else /* !VWSND_DEBUG */#define ASSERT(e) ((void) 0)#define DBGDO(x) /* don't */#define DBGX(fmt, args...) ((void) 0)#define DBGP(fmt, args...) ((void) 0)#define DBGE(fmt, args...) ((void) 0)#define DBGC(rtn) ((void) 0)#define DBGR() ((void) 0)#define DBGPV(fmt, args...) ((void) 0)#define DBGXV(fmt, args...) ((void) 0)#define DBGEV(fmt, args...) ((void) 0)#define DBGCV(rtn) ((void) 0)#define DBGRV() ((void) 0)#endif /* !VWSND_DEBUG *//*****************************************************************************//* low level lithium access *//* * We need to talk to Lithium registers on three pages. Here are * the pages' offsets from the base address (0xFF001000). */enum { LI_PAGE0_OFFSET = 0x01000 - 0x1000, /* FF001000 */ LI_PAGE1_OFFSET = 0x0F000 - 0x1000, /* FF00F000 */ LI_PAGE2_OFFSET = 0x10000 - 0x1000, /* FF010000 */};/* low-level lithium data */typedef struct lithium { caddr_t page0; /* virtual addresses */ caddr_t page1; caddr_t page2; spinlock_t lock; /* protects codec and UST/MSC access */} lithium_t;/* * li_create initializes the lithium_t structure and sets up vm mappings * to access the registers. * Returns 0 on success, -errno on failure. */static int li_create(lithium_t *lith, unsigned long baseaddr){ static void li_destroy(lithium_t *); lith->lock = SPIN_LOCK_UNLOCKED; lith->page0 = ioremap_nocache(baseaddr + LI_PAGE0_OFFSET, PAGE_SIZE); lith->page1 = ioremap_nocache(baseaddr + LI_PAGE1_OFFSET, PAGE_SIZE); lith->page2 = ioremap_nocache(baseaddr + LI_PAGE2_OFFSET, PAGE_SIZE); if (!lith->page0 || !lith->page1 || !lith->page2) { li_destroy(lith); return -ENOMEM; } return 0;}/* * li_destroy destroys the lithium_t structure and vm mappings. */static void li_destroy(lithium_t *lith){ if (lith->page0) { iounmap(lith->page0); lith->page0 = NULL; } if (lith->page1) { iounmap(lith->page1); lith->page1 = NULL; } if (lith->page2) { iounmap(lith->page2); lith->page2 = NULL; }}/* * basic register accessors - read/write long/byte */static __inline__ unsigned long li_readl(lithium_t *lith, int off){ return * (volatile unsigned long *) (lith->page0 + off);}static __inline__ unsigned char li_readb(lithium_t *lith, int off){ return * (volatile unsigned char *) (lith->page0 + off);}static __inline__ void li_writel(lithium_t *lith, int off, unsigned long val){ * (volatile unsigned long *) (lith->page0 + off) = val;}static __inline__ void li_writeb(lithium_t *lith, int off, unsigned char val){ * (volatile unsigned char *) (lith->page0 + off) = val;}/*****************************************************************************//* High Level Lithium Access *//* * Lithium DMA Notes * * Lithium has two dedicated DMA channels for audio. They are known * as comm1 and comm2 (communication areas 1 and 2). Comm1 is for * input, and comm2 is for output. Each is controlled by three * registers: BASE (base address), CFG (config) and CCTL * (config/control). * * Each DMA channel points to a physically contiguous ring buffer in * main memory of up to 8 Kbytes. (This driver always uses 8 Kb.) * There are three pointers into the ring buffer: read, write, and * trigger. The pointers are 8 bits each. Each pointer points to * 32-byte "chunks" of data. The DMA engine moves 32 bytes at a time, * so there is no finer-granularity control. * * In comm1, the hardware updates the write ptr, and software updates * the read ptr. In comm2, it's the opposite: hardware updates the * read ptr, and software updates the write ptr. I designate the * hardware-updated ptr as the hwptr, and the software-updated ptr as * the swptr. * * The trigger ptr and trigger mask are used to trigger interrupts. * From the Lithium spec, section 5.6.8, revision of 12/15/1998: * * Trigger Mask Value * * A three bit wide field that represents a power of two mask * that is used whenever the trigger pointer is compared to its * respective read or write pointer. A value of zero here * implies a mask of 0xFF and a value of seven implies a mask * 0x01. This value can be used to sub-divide the ring buffer * into pie sections so that interrupts monitor the progress of * hardware from section to section. * * My interpretation of that is, whenever the hw ptr is updated, it is * compared with the trigger ptr, and the result is masked by the * trigger mask. (Actually, by the complement of the trigger mask.) * If the result is zero, an interrupt is triggered. I.e., interrupt * if ((hwptr & ~mask) == (trptr & ~mask)). The mask is formed from * the trigger register value as mask = (1 << (8 - tmreg)) - 1. * * In yet different words, setting tmreg to 0 causes an interrupt after * every 256 DMA chunks (8192 bytes) or once per traversal of the * ring buffer. Setting it to 7 caues an interrupt every 2 DMA chunks * (64 bytes) or 128 times per traversal of the ring buffer. *//* Lithium register offsets and bit definitions */#define LI_HOST_CONTROLLER 0x000# define LI_HC_RESET 0x00008000# define LI_HC_LINK_ENABLE 0x00004000# define LI_HC_LINK_FAILURE 0x00000004# define LI_HC_LINK_CODEC 0x00000002# define LI_HC_LINK_READY 0x00000001#define LI_INTR_STATUS 0x010#define LI_INTR_MASK 0x014# define LI_INTR_LINK_ERR 0x00008000# define LI_INTR_COMM2_TRIG 0x00000008# define LI_INTR_COMM2_UNDERFLOW 0x00000004# define LI_INTR_COMM1_TRIG 0x00000002# define LI_INTR_COMM1_OVERFLOW 0x00000001#define LI_CODEC_COMMAND 0x018# define LI_CC_BUSY 0x00008000# define LI_CC_DIR 0x00000080# define LI_CC_DIR_RD LI_CC_DIR# define LI_CC_DIR_WR (!LI_CC_DIR)# define LI_CC_ADDR_MASK 0x0000007F#define LI_CODEC_DATA 0x01C#define LI_COMM1_BASE 0x100#define LI_COMM1_CTL 0x104# define LI_CCTL_RESET 0x80000000# define LI_CCTL_SIZE 0x70000000# define LI_CCTL_DMA_ENABLE 0x08000000# define LI_CCTL_TMASK 0x07000000 /* trigger mask */# define LI_CCTL_TPTR 0x00FF0000 /* trigger pointer */# define LI_CCTL_RPTR 0x0000FF00# define LI_CCTL_WPTR 0x000000FF#define LI_COMM1_CFG 0x108# define LI_CCFG_LOCK 0x00008000# define LI_CCFG_SLOT 0x00000070# define LI_CCFG_DIRECTION 0x00000008# define LI_CCFG_DIR_IN (!LI_CCFG_DIRECTION)# define LI_CCFG_DIR_OUT LI_CCFG_DIRECTION# define LI_CCFG_MODE 0x00000004# define LI_CCFG_MODE_MONO (!LI_CCFG_MODE)# define LI_CCFG_MODE_STEREO LI_CCFG_MODE# define LI_CCFG_FORMAT 0x00000003# define LI_CCFG_FMT_8BIT 0x00000000# define LI_CCFG_FMT_16BIT 0x00000001#define LI_COMM2_BASE 0x10C#define LI_COMM2_CTL 0x110 /* bit definitions are the same as LI_COMM1_CTL */#define LI_COMM2_CFG 0x114 /* bit definitions are the same as LI_COMM1_CFG */#define LI_UST_LOW 0x200 /* 64-bit Unadjusted System Time is */#define LI_UST_HIGH 0x204 /* microseconds since boot */#define LI_AUDIO1_UST 0x300 /* UST-MSC pairs */#define LI_AUDIO1_MSC 0x304 /* MSC (Media Stream Counter) */#define LI_AUDIO2_UST 0x308 /* counts samples actually */#define LI_AUDIO2_MSC 0x30C /* processed as of time UST *//* * Lithium's DMA engine operates on chunks of 32 bytes. We call that * a DMACHUNK. */#define DMACHUNK_SHIFT 5#define DMACHUNK_SIZE (1 << DMACHUNK_SHIFT)#define BYTES_TO_CHUNKS(bytes) ((bytes) >> DMACHUNK_SHIFT)#define CHUNKS_TO_BYTES(chunks) ((chunks) << DMACHUNK_SHIFT)/* * Two convenient macros to shift bitfields into/out of position. * * Observe that (mask & -mask) is (1 << low_set_bit_of(mask)). * As long as mask is constant, we trust the compiler will change the * multipy and divide into shifts. */#define SHIFT_FIELD(val, mask) (((val) * ((mask) & -(mask))) & (mask))#define UNSHIFT_FIELD(val, mask) (((val) & (mask)) / ((mask) & -(mask)))/*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -