⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 maestro.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 5 页
字号:
/***************************************************************************** * *      ESS Maestro/Maestro-2/Maestro-2E driver for Linux 2.[23].x * *      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. * *	(c) Copyright 1999	 Alan Cox <alan.cox@linux.org> * *	Based heavily on SonicVibes.c: *      Copyright (C) 1998-1999  Thomas Sailer (sailer@ife.ee.ethz.ch) * *	Heavily modified by Zach Brown <zab@zabbo.net> based on lunch *	with ESS engineers.  Many thanks to Howard Kim for providing  *	contacts and hardware.  Honorable mention goes to Eric  *	Brombaugh for all sorts of things.  Best regards to the  *	proprietors of Hack Central for fine lodging. * *  Supported devices: *  /dev/dsp0-3    standard /dev/dsp device, (mostly) OSS compatible *  /dev/mixer  standard /dev/mixer device, (mostly) OSS compatible * *  Hardware Description * *	A working Maestro setup contains the Maestro chip wired to a  *	codec or 2.  In the Maestro we have the APUs, the ASSP, and the *	Wavecache.  The APUs can be though of as virtual audio routing *	channels.  They can take data from a number of sources and perform *	basic encodings of the data.  The wavecache is a storehouse for *	PCM data.  Typically it deals with PCI and interracts with the *	APUs.  The ASSP is a wacky DSP like device that ESS is loth *	to release docs on.  Thankfully it isn't required on the Maestro *	until you start doing insane things like FM emulation and surround *	encoding.  The codecs are almost always AC-97 compliant codecs,  *	but it appears that early Maestros may have had PT101 (an ESS *	part?) wired to them.  The only real difference in the Maestro *	families is external goop like docking capability, memory for *	the ASSP, and initialization differences. * *  Driver Operation * *	We only drive the APU/Wavecache as typical DACs and drive the *	mixers in the codecs.  There are 64 APUs.  We assign 6 to each *	/dev/dsp? device.  2 channels for output, and 4 channels for *	input. * *	Each APU can do a number of things, but we only really use *	3 basic functions.  For playback we use them to convert PCM *	data fetched over PCI by the wavecahche into analog data that *	is handed to the codec.  One APU for mono, and a pair for stereo. *	When in stereo, the combination of smarts in the APU and Wavecache *	decide which wavecache gets the left or right channel. * *	For record we still use the old overly mono system.  For each in *	coming channel the data comes in from the codec, through a 'input' *	APU, through another rate converter APU, and then into memory via *	the wavecache and PCI.  If its stereo, we mash it back into LRLR in *	software.  The pass between the 2 APUs is supposedly what requires us *	to have a 512 byte buffer sitting around in wavecache/memory. * *	The wavecache makes our life even more fun.  First off, it can *	only address the first 28 bits of PCI address space, making it *	useless on quite a few architectures.  Secondly, its insane. *	It claims to fetch from 4 regions of PCI space, each 4 meg in length. *	But that doesn't really work.  You can only use 1 region.  So all our *	allocations have to be in 4meg of each other.  Booo.  Hiss. *	So we have a module parameter, dsps_order, that is the order of *	the number of dsps to provide.  All their buffer space is allocated *	on open time.  The sonicvibes OSS routines we inherited really want *	power of 2 buffers, so we have all those next to each other, then *	512 byte regions for the recording wavecaches.  This ends up *	wasting quite a bit of memory.  The only fixes I can see would be  *	getting a kernel allocator that could work in zones, or figuring out *	just how to coerce the WP into doing what we want. * *	The indirection of the various registers means we have to spinlock *	nearly all register accesses.  We have the main register indirection *	like the wave cache, maestro registers, etc.  Then we have beasts *	like the APU interface that is indirect registers gotten at through *	the main maestro indirection.  Ouch.  We spinlock around the actual *	ports on a per card basis.  This means spinlock activity at each IO *	operation, but the only IO operation clusters are in non critical  *	paths and it makes the code far easier to follow.  Interrupts are *	blocked while holding the locks because the int handler has to *	get at some of them :(.  The mixer interface doesn't, however. *	We also have an OSS state lock that is thrown around in a few *	places. * *	This driver has brute force APM suspend support.  We catch suspend *	notifications and stop all work being done on the chip.  Any people *	that try between this shutdown and the real suspend operation will *	be put to sleep.  When we resume we restore our software state on *	the chip and wake up the people that were using it.  The code thats *	being used now is quite dirty and assumes we're on a uni-processor *	machine.  Much of it will need to be cleaned up for SMP ACPI or  *	similar. * *	We also pay attention to PCI power management now.  The driver *	will power down units of the chip that it knows aren't needed. *	The WaveProcessor and company are only powered on when people *	have /dev/dsp*s open.  On removal the driver will *	power down the maestro entirely.  There could still be *	trouble with BIOSen that magically change power states  *	themselves, but we'll see.   *	 * History *  v0.15 - May 21 2001 - Marcus Meissner <mm@caldera.de> *      Ported to Linux 2.4 PCI API. Some clean ups, global devs list *      removed (now using pci device driver data). *      PM needs to be polished still. Bumped version. *  (still kind of v0.14) May 13 2001 - Ben Pfaff <pfaffben@msu.edu> *      Add support for 978 docking and basic hardware volume control *  (still kind of v0.14) Nov 23 - Alan Cox <alan@redhat.com> *	Add clocking= for people with seriously warped hardware *  (still v0.14) Nov 10 2000 - Bartlomiej Zolnierkiewicz <bkz@linux-ide.org> *	add __init to maestro_ac97_init() and maestro_install() *  (still based on v0.14) Mar 29 2000 - Zach Brown <zab@redhat.com> *	move to 2.3 power management interface, which *		required hacking some suspend/resume/check paths  *	make static compilation work *  v0.14 - Jan 28 2000 - Zach Brown <zab@redhat.com> *	add PCI power management through ACPI regs. *	we now shut down on machine reboot/halt *	leave scary PCI config items alone (isa stuff, mostly) *	enable 1921s, it seems only mine was broke. *	fix swapped left/right pcm dac.  har har. *	up bob freq, increase buffers, fix pointers at underflow *	silly compilation problems *  v0.13 - Nov 18 1999 - Zach Brown <zab@redhat.com> *	fix nec Versas?  man would that be cool. *  v0.12 - Nov 12 1999 - Zach Brown <zab@redhat.com> *	brown bag volume max fix.. *  v0.11 - Nov 11 1999 - Zach Brown <zab@redhat.com> *	use proper stereo apu decoding, mmap/write should work. *	make volume sliders more useful, tweak rate calculation. *	fix lame 8bit format reporting bug.  duh. apm apu saving buglet also *	fix maestro 1 clock freq "bug", remove pt101 support *  v0.10 - Oct 28 1999 - Zach Brown <zab@redhat.com> *	aha, so, sometimes the WP writes a status word to offset 0 *	  from one of the PCMBARs.  rearrange allocation accordingly.. *	  cheers again to Eric for being a good hacker in investigating this. *	Jeroen Hoogervorst submits 7500 fix out of nowhere.  yay.  :) *  v0.09 - Oct 23 1999 - Zach Brown <zab@redhat.com> *	added APM support. *	re-order something such that some 2Es now work.  Magic! *	new codec reset routine.  made some codecs come to life. *	fix clear_advance, sync some control with ESS. *	now write to all base regs to be paranoid. *  v0.08 - Oct 20 1999 - Zach Brown <zab@redhat.com> *	Fix initial buflen bug.  I am so smart.  also smp compiling.. *	I owe Eric yet another beer: fixed recmask, igain,  *	  muting, and adc sync consistency.  Go Team. *  v0.07 - Oct 4 1999 - Zach Brown <zab@redhat.com> *	tweak adc/dac, formating, and stuff to allow full duplex *	allocate dsps memory at open() so we can fit in the wavecache window *	fix wavecache braindamage.  again.  no more scribbling? *	fix ess 1921 codec bug on some laptops. *	fix dumb pci scanning bug *	started 2.3 cleanup, redid spinlocks, little cleanups *  v0.06 - Sep 20 1999 - Zach Brown <zab@redhat.com> *	fix wavecache thinkos.  limit to 1 /dev/dsp. *	eric is wearing his thinking toque this week. *		spotted apu mode bugs and gain ramping problem *	don't touch weird mixer regs, make recmask optional *	fixed igain inversion, defaults for mixers, clean up rec_start *	make mono recording work. *	report subsystem stuff, please send reports. *	littles: parallel out, amp now *  v0.05 - Sep 17 1999 - Zach Brown <zab@redhat.com> *	merged and fixed up Eric's initial recording code *	munged format handling to catch misuse, needs rewrite. *	revert ring bus init, fixup shared int, add pci busmaster setting *	fix mixer oss interface, fix mic mute and recmask *	mask off unsupported mixers, reset with all 1s, modularize defaults *	make sure bob is running while we need it *	got rid of device limit, initial minimal apm hooks *	pull out dead code/includes, only allow multimedia/audio maestros *  v0.04 - Sep 01 1999 - Zach Brown <zab@redhat.com> *	copied memory leak fix from sonicvibes driver *	different ac97 reset, play with 2.0 ac97, simplify ring bus setup *	bob freq code, region sanity, jitter sync fix; all from Eric  * * TODO *	fix bob frequency *	endianness *	do smart things with ac97 2.0 bits. *	dual codecs *	leave 54->61 open * *	it also would be fun to have a mode that would not use pci dma at all *	but would copy into the wavecache on board memory and use that  *	on architectures that don't like the maestro's pci dma ickiness. *//*****************************************************************************/#include <linux/version.h>#include <linux/module.h>#include <linux/sched.h>#include <linux/smp_lock.h>#include <linux/wrapper.h>#include <linux/string.h>#include <linux/ctype.h>#include <linux/ioport.h>#include <linux/delay.h>#include <linux/sound.h>#include <linux/slab.h>#include <linux/soundcard.h>#include <linux/pci.h>#include <linux/spinlock.h>#include <asm/io.h>#include <asm/dma.h>#include <linux/init.h>#include <linux/poll.h>#include <linux/reboot.h>#include <asm/uaccess.h>#include <asm/hardirq.h>#include <linux/bitops.h>#include <linux/pm.h>static int maestro_pm_callback(struct pm_dev *dev, pm_request_t rqst, void *d);#include "maestro.h"static struct pci_driver maestro_pci_driver;/* --------------------------------------------------------------------- */#define M_DEBUG 1#ifdef M_DEBUGstatic int debug=0;#define M_printk(args...) {if (debug) printk(args);}#else#define M_printk(x)#endif/* we try to setup 2^(dsps_order) /dev/dsp devices */static int dsps_order=0;/* wether or not we mess around with power management */static int use_pm=2; /* set to 1 for force *//* clocking for broken hardware - a few laptops seem to use a 50Khz clock	ie insmod with clocking=50000 or so */	static int clocking=48000;MODULE_AUTHOR("Zach Brown <zab@zabbo.net>, Alan Cox <alan@redhat.com>");MODULE_DESCRIPTION("ESS Maestro Driver");MODULE_LICENSE("GPL");#ifdef M_DEBUGMODULE_PARM(debug,"i");#endifMODULE_PARM(dsps_order,"i");MODULE_PARM(use_pm,"i");MODULE_PARM(clocking, "i");/* --------------------------------------------------------------------- */#define DRIVER_VERSION "0.15"#ifndef PCI_VENDOR_ESS#define PCI_VENDOR_ESS			0x125D#define PCI_DEVICE_ID_ESS_ESS1968	0x1968		/* Maestro 2	*/#define PCI_DEVICE_ID_ESS_ESS1978      	0x1978		/* Maestro 2E	*/#define PCI_VENDOR_ESS_OLD		0x1285		/* Platform Tech, 						the people the maestro 						was bought from */#define PCI_DEVICE_ID_ESS_ESS0100	0x0100		/* maestro 1 */#endif /* PCI_VENDOR_ESS */#define ESS_CHAN_HARD		0x100/* NEC Versas ? */#define NEC_VERSA_SUBID1	0x80581033#define NEC_VERSA_SUBID2	0x803c1033/* changed so that I could actually find all the	references and fix them up.  its a little more readable now. */#define ESS_FMT_STEREO	0x01#define ESS_FMT_16BIT	0x02#define ESS_FMT_MASK	0x03#define ESS_DAC_SHIFT	0   #define ESS_ADC_SHIFT	4#define ESS_STATE_MAGIC		0x125D1968#define ESS_CARD_MAGIC		0x19283746#define DAC_RUNNING		1#define ADC_RUNNING		2#define MAX_DSP_ORDER	2#define MAX_DSPS	(1<<MAX_DSP_ORDER)#define NR_DSPS		(1<<dsps_order)#define NR_IDRS		32#define NR_APUS		64#define NR_APU_REGS	16/* acpi states */enum {	ACPI_D0=0,	ACPI_D1,	ACPI_D2,	ACPI_D3};/* bits in the acpi masks */#define ACPI_12MHZ	( 1 << 15)#define ACPI_24MHZ	( 1 << 14)#define ACPI_978	( 1 << 13)#define ACPI_SPDIF	( 1 << 12)#define ACPI_GLUE	( 1 << 11)#define ACPI__10	( 1 << 10) /* reserved */#define ACPI_PCIINT	( 1 << 9)#define ACPI_HV		( 1 << 8) /* hardware volume */#define ACPI_GPIO	( 1 << 7)#define ACPI_ASSP	( 1 << 6)#define ACPI_SB		( 1 << 5) /* sb emul */#define ACPI_FM		( 1 << 4) /* fm emul */#define ACPI_RB		( 1 << 3) /* ringbus / aclink */#define ACPI_MIDI	( 1 << 2) #define ACPI_GP		( 1 << 1) /* game port */#define ACPI_WP		( 1 << 0) /* wave processor */#define ACPI_ALL	(0xffff)#define ACPI_SLEEP	(~(ACPI_SPDIF|ACPI_ASSP|ACPI_SB|ACPI_FM| \			ACPI_MIDI|ACPI_GP|ACPI_WP))#define ACPI_NONE	(ACPI__10)/* these masks indicate which units we care about at	which states */u16 acpi_state_mask[] = {	[ACPI_D0] = ACPI_ALL,	[ACPI_D1] = ACPI_SLEEP,	[ACPI_D2] = ACPI_SLEEP,	[ACPI_D3] = ACPI_NONE};static char version[] __devinitdata =KERN_INFO "maestro: version " DRIVER_VERSION " time " __TIME__ " " __DATE__ "\n";static const unsigned sample_size[] = { 1, 2, 2, 4 };static const unsigned sample_shift[] = { 0, 1, 1, 2 };enum card_types_t {	TYPE_MAESTRO,	TYPE_MAESTRO2,	TYPE_MAESTRO2E};static const char *card_names[]={	[TYPE_MAESTRO] = "ESS Maestro",	[TYPE_MAESTRO2] = "ESS Maestro 2",	[TYPE_MAESTRO2E] = "ESS Maestro 2E"};static int clock_freq[]={	[TYPE_MAESTRO] = (49152000L / 1024L),	[TYPE_MAESTRO2] = (50000000L / 1024L),	[TYPE_MAESTRO2E] = (50000000L / 1024L)};static int maestro_notifier(struct notifier_block *nb, unsigned long event, void *buf);static struct notifier_block maestro_nb = {maestro_notifier, NULL, 0};/* --------------------------------------------------------------------- */struct ess_state {	unsigned int magic;	/* FIXME: we probably want submixers in here, but only one record pair */	u8 apu[6];		/* l/r output, l/r intput converters, l/r input apus */	u8 apu_mode[6];		/* Running mode for this APU */	u8 apu_pan[6];		/* Panning setup for this APU */	u32 apu_base[6];	/* base address for this apu */	struct ess_card *card;	/* Card info */	/* wave stuff */	unsigned int rateadc, ratedac;	unsigned char fmt, enable;	int index;	/* this locks around the oss state in the driver */	spinlock_t lock;	/* only let 1 be opening at a time */	struct semaphore open_sem;	wait_queue_head_t open_wait;	mode_t open_mode;	/* soundcore stuff */	int dev_audio;	struct dmabuf {		void *rawbuf;		unsigned buforder;		unsigned numfrag;		unsigned fragshift;		/* XXX zab - swptr only in here so that it can be referenced by			clear_advance, as far as I can tell :( */		unsigned hwptr, swptr;		unsigned total_bytes;		int count;		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;	/* our oss buffers are ready to go */		unsigned endcleared:1;		unsigned ossfragshift;		int ossmaxfrags;		unsigned subdivision;		u16 base;		/* Offset for ptr */	} dma_dac, dma_adc;	/* pointer to each dsp?s piece of the apu->src buffer page */	void *mixbuf;};	struct ess_card {	unsigned int magic;	/* We keep maestro cards in a linked list */	struct ess_card *next;	int dev_mixer;	int card_type;	/* as most of this is static,		perhaps it should be a pointer to a global struct */	struct mixer_goo {		int modcnt;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -