mirror of
				git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
				synced 2025-09-04 20:19:47 +08:00 
			
		
		
		
	The next round of scheduled OSS code removal
This patch contains the next round of scheduled OSS code removal. Signed-off-by: Adrian Bunk <bunk@stusta.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									5b4db0c2f2
								
							
						
					
					
						commit
						fc37449f79
					
				| @ -219,13 +219,6 @@ Who:	Jean Delvare <khali@linux-fr.org>, | ||||
| 
 | ||||
| --------------------------- | ||||
| 
 | ||||
| What:  drivers depending on OBSOLETE_OSS | ||||
| When:  options in 2.6.22, code in 2.6.24 | ||||
| Why:   OSS drivers with ALSA replacements | ||||
| Who:   Adrian Bunk <bunk@stusta.de> | ||||
| 
 | ||||
| --------------------------- | ||||
| 
 | ||||
| What:	ACPI procfs interface | ||||
| When:	July 2008 | ||||
| Why:	ACPI sysfs conversion should be finished by January 2008. | ||||
|  | ||||
| @ -1,64 +0,0 @@ | ||||
| /proc/sound, /dev/sndstat | ||||
| ------------------------- | ||||
| 
 | ||||
| /proc/sound and /dev/sndstat is not supported by the | ||||
| driver. To find out whether the driver succeeded loading, | ||||
| check the kernel log (dmesg). | ||||
| 
 | ||||
| 
 | ||||
| ALaw/uLaw sample formats | ||||
| ------------------------ | ||||
| 
 | ||||
| This driver does not support the ALaw/uLaw sample formats. | ||||
| ALaw is the default mode when opening a sound device | ||||
| using OSS/Free. The reason for the lack of support is | ||||
| that the hardware does not support these formats, and adding | ||||
| conversion routines to the kernel would lead to very ugly | ||||
| code in the presence of the mmap interface to the driver. | ||||
| And since xquake uses mmap, mmap is considered important :-) | ||||
| and no sane application uses ALaw/uLaw these days anyway. | ||||
| In short, playing a Sun .au file as follows: | ||||
| 
 | ||||
| cat my_file.au > /dev/dsp | ||||
| 
 | ||||
| does not work. Instead, you may use the play script from | ||||
| Chris Bagwell's sox-12.14 package (available from the URL | ||||
| below) to play many different audio file formats. | ||||
| The script automatically determines the audio format | ||||
| and does do audio conversions if necessary. | ||||
| http://home.sprynet.com/sprynet/cbagwell/projects.html | ||||
| 
 | ||||
| 
 | ||||
| Blocking vs. nonblocking IO | ||||
| --------------------------- | ||||
| 
 | ||||
| Unlike OSS/Free this driver honours the O_NONBLOCK file flag | ||||
| not only during open, but also during read and write. | ||||
| This is an effort to make the sound driver interface more | ||||
| regular. Timidity has problems with this; a patch | ||||
| is available from http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html. | ||||
| (Timidity patched will also run on OSS/Free). | ||||
| 
 | ||||
| 
 | ||||
| MIDI UART | ||||
| --------- | ||||
| 
 | ||||
| The driver supports a simple MIDI UART interface, with | ||||
| no ioctl's supported. | ||||
| 
 | ||||
| 
 | ||||
| MIDI synthesizer | ||||
| ---------------- | ||||
| 
 | ||||
| This soundcard does not have any hardware MIDI synthesizer; | ||||
| MIDI synthesis has to be done in software. To allow this | ||||
| the driver/soundcard supports two PCM (/dev/dsp) interfaces. | ||||
| 
 | ||||
| There is a freely available software package that allows | ||||
| MIDI file playback on this soundcard called Timidity. | ||||
| See http://www.cgs.fi/~tt/timidity/. | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| Thomas Sailer | ||||
| t.sailer@alumni.ethz.ch | ||||
| @ -2940,13 +2940,6 @@ L:	linux-kernel@vger.kernel.org | ||||
| L:	linux-pci@atrey.karlin.mff.cuni.cz | ||||
| S:	Supported | ||||
| 
 | ||||
| PCI SOUND DRIVERS (ES1370, ES1371 and SONICVIBES) | ||||
| P:	Thomas Sailer | ||||
| M:	sailer@ife.ee.ethz.ch | ||||
| L:	linux-sound@vger.kernel.org | ||||
| W:	http://www.ife.ee.ethz.ch/~sailer/linux/pciaudio.html | ||||
| S:	Maintained | ||||
| 
 | ||||
| PCI SUBSYSTEM | ||||
| P:	Greg Kroah-Hartman | ||||
| M:	gregkh@suse.de | ||||
|  | ||||
| @ -36,7 +36,6 @@ obj-$(CONFIG_SOUND_MSNDCLAS)	+= msnd.o msnd_classic.o | ||||
| obj-$(CONFIG_SOUND_MSNDPIN)	+= msnd.o msnd_pinnacle.o | ||||
| obj-$(CONFIG_SOUND_VWSND)	+= vwsnd.o | ||||
| obj-$(CONFIG_SOUND_ICH)		+= i810_audio.o ac97_codec.o | ||||
| obj-$(CONFIG_SOUND_ES1371)	+= es1371.o ac97_codec.o | ||||
| obj-$(CONFIG_SOUND_AU1550_AC97)	+= au1550_ac97.o ac97_codec.o | ||||
| obj-$(CONFIG_SOUND_TRIDENT)	+= trident.o ac97_codec.o | ||||
| obj-$(CONFIG_SOUND_BCM_CS4297A)	+= swarm_cs4297a.o | ||||
|  | ||||
| @ -2,12 +2,6 @@ | ||||
| # Makefile for the DMA sound driver
 | ||||
| #
 | ||||
| 
 | ||||
| dmasound_pmac-y			+= dmasound_awacs.o \
 | ||||
| 				   trans_16.o dac3550a.o tas_common.o \
 | ||||
| 				   tas3001c.o tas3001c_tables.o \
 | ||||
| 				   tas3004.o tas3004_tables.o | ||||
| 
 | ||||
| obj-$(CONFIG_DMASOUND_ATARI)	+= dmasound_core.o dmasound_atari.o | ||||
| obj-$(CONFIG_DMASOUND_PMAC)	+= dmasound_core.o dmasound_pmac.o | ||||
| obj-$(CONFIG_DMASOUND_PAULA)	+= dmasound_core.o dmasound_paula.o | ||||
| obj-$(CONFIG_DMASOUND_Q40)	+= dmasound_core.o dmasound_q40.o | ||||
|  | ||||
| @ -1,251 +0,0 @@ | ||||
| /*********************************************************/ | ||||
| /* This file was written by someone, somewhere, sometime */ | ||||
| /* And is released into the Public Domain                */ | ||||
| /*********************************************************/ | ||||
| 
 | ||||
| #ifndef _AWACS_DEFS_H_ | ||||
| #define _AWACS_DEFS_H_ | ||||
| 
 | ||||
| /*******************************/ | ||||
| /* AWACs Audio Register Layout */ | ||||
| /*******************************/ | ||||
| 
 | ||||
| struct awacs_regs { | ||||
|     unsigned	control;	/* Audio control register */ | ||||
|     unsigned	pad0[3]; | ||||
|     unsigned	codec_ctrl;	/* Codec control register */ | ||||
|     unsigned	pad1[3]; | ||||
|     unsigned	codec_stat;	/* Codec status register */ | ||||
|     unsigned	pad2[3]; | ||||
|     unsigned	clip_count;	/* Clipping count register */ | ||||
|     unsigned	pad3[3]; | ||||
|     unsigned	byteswap;	/* Data is little-endian if 1 */ | ||||
| }; | ||||
| 
 | ||||
| /*******************/ | ||||
| /* Audio Bit Masks */ | ||||
| /*******************/ | ||||
| 
 | ||||
| /* Audio Control Reg Bit Masks */ | ||||
| /* ----- ------- --- --- ----- */ | ||||
| #define MASK_ISFSEL	(0xf)		/* Input SubFrame Select */ | ||||
| #define MASK_OSFSEL	(0xf << 4)	/* Output SubFrame Select */ | ||||
| #define MASK_RATE	(0x7 << 8)	/* Sound Rate */ | ||||
| #define MASK_CNTLERR	(0x1 << 11)	/* Error */ | ||||
| #define MASK_PORTCHG	(0x1 << 12)	/* Port Change */ | ||||
| #define MASK_IEE	(0x1 << 13)	/* Enable Interrupt on Error */ | ||||
| #define MASK_IEPC	(0x1 << 14)	/* Enable Interrupt on Port Change */ | ||||
| #define MASK_SSFSEL	(0x3 << 15)	/* Status SubFrame Select */ | ||||
| 
 | ||||
| /* Audio Codec Control Reg Bit Masks */ | ||||
| /* ----- ----- ------- --- --- ----- */ | ||||
| #define MASK_NEWECMD	(0x1 << 24)	/* Lock: don't write to reg when 1 */ | ||||
| #define MASK_EMODESEL	(0x3 << 22)	/* Send info out on which frame? */ | ||||
| #define MASK_EXMODEADDR	(0x3ff << 12)	/* Extended Mode Address -- 10 bits */ | ||||
| #define MASK_EXMODEDATA	(0xfff)		/* Extended Mode Data -- 12 bits */ | ||||
| 
 | ||||
| /* Audio Codec Control Address Values / Masks */ | ||||
| /* ----- ----- ------- ------- ------ - ----- */ | ||||
| #define MASK_ADDR0	(0x0 << 12)	/* Expanded Data Mode Address 0 */ | ||||
| #define MASK_ADDR_MUX	MASK_ADDR0	/* Mux Control */ | ||||
| #define MASK_ADDR_GAIN	MASK_ADDR0 | ||||
| 
 | ||||
| #define MASK_ADDR1	(0x1 << 12)	/* Expanded Data Mode Address 1 */ | ||||
| #define MASK_ADDR_MUTE	MASK_ADDR1 | ||||
| #define MASK_ADDR_RATE	MASK_ADDR1 | ||||
| 
 | ||||
| #define MASK_ADDR2	(0x2 << 12)	/* Expanded Data Mode Address 2 */ | ||||
| #define MASK_ADDR_VOLA	MASK_ADDR2	/* Volume Control A -- Headphones */ | ||||
| #define MASK_ADDR_VOLHD MASK_ADDR2 | ||||
| 
 | ||||
| #define MASK_ADDR4	(0x4 << 12)	/* Expanded Data Mode Address 4 */ | ||||
| #define MASK_ADDR_VOLC	MASK_ADDR4	/* Volume Control C -- Speaker */ | ||||
| #define MASK_ADDR_VOLSPK MASK_ADDR4 | ||||
| 
 | ||||
| /* additional registers of screamer */ | ||||
| #define MASK_ADDR5	(0x5 << 12)	/* Expanded Data Mode Address 5 */ | ||||
| #define MASK_ADDR6	(0x6 << 12)	/* Expanded Data Mode Address 6 */ | ||||
| #define MASK_ADDR7	(0x7 << 12)	/* Expanded Data Mode Address 7 */ | ||||
| 
 | ||||
| /* Address 0 Bit Masks & Macros */ | ||||
| /* ------- - --- ----- - ------ */ | ||||
| #define MASK_GAINRIGHT	(0xf)		/* Gain Right Mask */ | ||||
| #define MASK_GAINLEFT	(0xf << 4)	/* Gain Left Mask */ | ||||
| #define MASK_GAINLINE	(0x1 << 8)	/* Disable Mic preamp */ | ||||
| #define MASK_GAINMIC	(0x0 << 8)	/* Enable Mic preamp */ | ||||
| 
 | ||||
| #define MASK_MUX_CD	(0x1 << 9)	/* Select CD in MUX */ | ||||
| #define MASK_MUX_MIC	(0x1 << 10)	/* Select Mic in MUX */ | ||||
| #define MASK_MUX_AUDIN	(0x1 << 11)	/* Select Audio In in MUX */ | ||||
| #define MASK_MUX_LINE	MASK_MUX_AUDIN | ||||
| 
 | ||||
| #define GAINRIGHT(x)	((x) & MASK_GAINRIGHT) | ||||
| #define GAINLEFT(x)	(((x) << 4) & MASK_GAINLEFT) | ||||
| 
 | ||||
| #define DEF_CD_GAIN 0x00bb | ||||
| #define DEF_MIC_GAIN 0x00cc | ||||
| 
 | ||||
| /* Address 1 Bit Masks */ | ||||
| /* ------- - --- ----- */ | ||||
| #define MASK_ADDR1RES1	(0x3)		/* Reserved */ | ||||
| #define MASK_RECALIBRATE (0x1 << 2)	/* Recalibrate */ | ||||
| #define MASK_SAMPLERATE	(0x7 << 3)	/* Sample Rate: */ | ||||
| #define MASK_LOOPTHRU	(0x1 << 6)	/* Loopthrough Enable */ | ||||
| #define MASK_CMUTE	(0x1 << 7)	/* Output C (Speaker) Mute when 1 */ | ||||
| #define MASK_SPKMUTE	MASK_CMUTE | ||||
| #define MASK_ADDR1RES2	(0x1 << 8)	/* Reserved */ | ||||
| #define MASK_AMUTE	(0x1 << 9)	/* Output A (Headphone) Mute when 1 */ | ||||
| #define MASK_HDMUTE	MASK_AMUTE | ||||
| #define MASK_PAROUT0	(0x1 << 10)	/* Parallel Output 0 */ | ||||
| #define MASK_PAROUT1	(0x2 << 10)	/* Parallel Output 1 */ | ||||
| 
 | ||||
| #define MASK_MIC_BOOST  (0x4)           /* screamer mic boost */ | ||||
| 
 | ||||
| #define SAMPLERATE_48000	(0x0 << 3)	/* 48 or 44.1 kHz */ | ||||
| #define SAMPLERATE_32000	(0x1 << 3)	/* 32 or 29.4 kHz */ | ||||
| #define SAMPLERATE_24000	(0x2 << 3)	/* 24 or 22.05 kHz */ | ||||
| #define SAMPLERATE_19200	(0x3 << 3)	/* 19.2 or 17.64 kHz */ | ||||
| #define SAMPLERATE_16000	(0x4 << 3)	/* 16 or 14.7 kHz */ | ||||
| #define SAMPLERATE_12000	(0x5 << 3)	/* 12 or 11.025 kHz */ | ||||
| #define SAMPLERATE_9600		(0x6 << 3)	/* 9.6 or 8.82 kHz */ | ||||
| #define SAMPLERATE_8000		(0x7 << 3)	/* 8 or 7.35 kHz */ | ||||
| 
 | ||||
| /* Address 2 & 4 Bit Masks & Macros */ | ||||
| /* ------- - - - --- ----- - ------ */ | ||||
| #define MASK_OUTVOLRIGHT (0xf)		/* Output Right Volume */ | ||||
| #define MASK_ADDR2RES1	(0x2 << 4)	/* Reserved */ | ||||
| #define MASK_ADDR4RES1	MASK_ADDR2RES1 | ||||
| #define MASK_OUTVOLLEFT	(0xf << 6)	/* Output Left Volume */ | ||||
| #define MASK_ADDR2RES2	(0x2 << 10)	/* Reserved */ | ||||
| #define MASK_ADDR4RES2	MASK_ADDR2RES2 | ||||
| 
 | ||||
| #define VOLRIGHT(x)	(((~(x)) & MASK_OUTVOLRIGHT)) | ||||
| #define VOLLEFT(x)	(((~(x)) << 6) & MASK_OUTVOLLEFT) | ||||
| 
 | ||||
| /* Audio Codec Status Reg Bit Masks */ | ||||
| /* ----- ----- ------ --- --- ----- */ | ||||
| #define MASK_EXTEND	(0x1 << 23)	/* Extend */ | ||||
| #define MASK_VALID	(0x1 << 22)	/* Valid Data? */ | ||||
| #define MASK_OFLEFT	(0x1 << 21)	/* Overflow Left */ | ||||
| #define MASK_OFRIGHT	(0x1 << 20)	/* Overflow Right */ | ||||
| #define MASK_ERRCODE	(0xf << 16)	/* Error Code */ | ||||
| #define MASK_REVISION	(0xf << 12)	/* Revision Number */ | ||||
| #define MASK_MFGID	(0xf << 8)	/* Mfg. ID */ | ||||
| #define MASK_CODSTATRES	(0xf << 4)	/* bits 4 - 7 reserved */ | ||||
| #define MASK_INPPORT	(0xf)		/* Input Port */ | ||||
| #define MASK_HDPCONN	8		/* headphone plugged in */ | ||||
| 
 | ||||
| /* Clipping Count Reg Bit Masks */ | ||||
| /* -------- ----- --- --- ----- */ | ||||
| #define MASK_CLIPLEFT	(0xff << 7)	/* Clipping Count, Left Channel */ | ||||
| #define MASK_CLIPRIGHT	(0xff)		/* Clipping Count, Right Channel */ | ||||
| 
 | ||||
| /* DBDMA ChannelStatus Bit Masks */ | ||||
| /* ----- ------------- --- ----- */ | ||||
| #define MASK_CSERR	(0x1 << 7)	/* Error */ | ||||
| #define MASK_EOI	(0x1 << 6)	/* End of Input -- only for Input Channel */ | ||||
| #define MASK_CSUNUSED	(0x1f << 1)	/* bits 1-5 not used */ | ||||
| #define MASK_WAIT	(0x1)		/* Wait */ | ||||
| 
 | ||||
| /* Various Rates */ | ||||
| /* ------- ----- */ | ||||
| #define RATE_48000	(0x0 << 8)	/* 48 kHz */ | ||||
| #define RATE_44100	(0x0 << 8)	/* 44.1 kHz */ | ||||
| #define RATE_32000	(0x1 << 8)	/* 32 kHz */ | ||||
| #define RATE_29400	(0x1 << 8)	/* 29.4 kHz */ | ||||
| #define RATE_24000	(0x2 << 8)	/* 24 kHz */ | ||||
| #define RATE_22050	(0x2 << 8)	/* 22.05 kHz */ | ||||
| #define RATE_19200	(0x3 << 8)	/* 19.2 kHz */ | ||||
| #define RATE_17640	(0x3 << 8)	/* 17.64 kHz */ | ||||
| #define RATE_16000	(0x4 << 8)	/* 16 kHz */ | ||||
| #define RATE_14700	(0x4 << 8)	/* 14.7 kHz */ | ||||
| #define RATE_12000	(0x5 << 8)	/* 12 kHz */ | ||||
| #define RATE_11025	(0x5 << 8)	/* 11.025 kHz */ | ||||
| #define RATE_9600	(0x6 << 8)	/* 9.6 kHz */ | ||||
| #define RATE_8820	(0x6 << 8)	/* 8.82 kHz */ | ||||
| #define RATE_8000	(0x7 << 8)	/* 8 kHz */ | ||||
| #define RATE_7350	(0x7 << 8)	/* 7.35 kHz */ | ||||
| 
 | ||||
| #define RATE_LOW	1	/* HIGH = 48kHz, etc;  LOW = 44.1kHz, etc. */ | ||||
| 
 | ||||
| /*******************/ | ||||
| /* Burgundy values */ | ||||
| /*******************/ | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12) | ||||
| #define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12) | ||||
| #define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1) | ||||
| #define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2) | ||||
| #define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3) | ||||
| #define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4) | ||||
| 
 | ||||
| #define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1) | ||||
| #define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2) | ||||
| #define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3) | ||||
| #define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4) | ||||
| 
 | ||||
| 
 | ||||
| /* These are all default values for the burgundy */ | ||||
| #define DEF_BURGUNDY_INPSEL21 (0xAA) | ||||
| #define DEF_BURGUNDY_INPSEL3 (0x0A) | ||||
| 
 | ||||
| #define DEF_BURGUNDY_GAINCD (0x33) | ||||
| #define DEF_BURGUNDY_GAINLINE (0x44) | ||||
| #define DEF_BURGUNDY_GAINMIC (0x44) | ||||
| #define DEF_BURGUNDY_GAINMODEM (0x06) | ||||
| 
 | ||||
| /* Remember: lowest volume here is 0x9b */ | ||||
| #define DEF_BURGUNDY_VOLCD (0xCCCCCCCC) | ||||
| #define DEF_BURGUNDY_VOLLINE (0x00000000) | ||||
| #define DEF_BURGUNDY_VOLMIC (0x00000000) | ||||
| #define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC) | ||||
| 
 | ||||
| #define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f) | ||||
| #define DEF_BURGUNDY_OUTPUTENABLES (0x0A) | ||||
| 
 | ||||
| #define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF) | ||||
| 
 | ||||
| #define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E) | ||||
| 
 | ||||
| #define DEF_BURGUNDY_ATTENSPEAKER (0x44) | ||||
| #define DEF_BURGUNDY_ATTENLINEOUT (0xCC) | ||||
| #define DEF_BURGUNDY_ATTENHP (0xCC) | ||||
| 
 | ||||
| /*********************/ | ||||
| /* i2s layout values */ | ||||
| /*********************/ | ||||
| 
 | ||||
| #define I2S_REG_INT_CTL			0x00 | ||||
| #define I2S_REG_SERIAL_FORMAT		0x10 | ||||
| #define I2S_REG_CODEC_MSG_OUT		0x20 | ||||
| #define I2S_REG_CODEC_MSG_IN		0x30 | ||||
| #define I2S_REG_FRAME_COUNT		0x40 | ||||
| #define I2S_REG_FRAME_MATCH		0x50 | ||||
| #define I2S_REG_DATAWORD_SIZES		0x60 | ||||
| #define I2S_REG_PEAKLEVEL_SEL		0x70 | ||||
| #define I2S_REG_PEAKLEVEL_IN0		0x80 | ||||
| #define I2S_REG_PEAKLEVEL_IN1		0x90 | ||||
| 
 | ||||
| #endif /* _AWACS_DEFS_H_ */ | ||||
| @ -1,209 +0,0 @@ | ||||
| /*
 | ||||
|  * Driver for the i2c/i2s based DAC3550a sound chip used | ||||
|  * on some Apple iBooks. Also known as "DACA". | ||||
|  * | ||||
|  *  This file is subject to the terms and conditions of the GNU General Public | ||||
|  *  License.  See the file COPYING in the main directory of this archive | ||||
|  *  for more details. | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/delay.h> | ||||
| #include <linux/proc_fs.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/sysctl.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/init.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/errno.h> | ||||
| #include <asm/io.h> | ||||
| 
 | ||||
| #include "dmasound.h" | ||||
| 
 | ||||
| /* FYI: This code was derived from the tas3001c.c Texas/Tumbler mixer
 | ||||
|  * control code, as well as info derived from the AppleDACAAudio driver | ||||
|  * from Darwin CVS (main thing I derived being register numbers and  | ||||
|  * values, as well as when to make the calls). */ | ||||
| 
 | ||||
| #define I2C_DRIVERID_DACA (0xFDCB) | ||||
| 
 | ||||
| #define DACA_VERSION	"0.1" | ||||
| #define DACA_DATE "20010930" | ||||
| 
 | ||||
| static int cur_left_vol; | ||||
| static int cur_right_vol; | ||||
| static struct i2c_client *daca_client; | ||||
| 
 | ||||
| static int daca_attach_adapter(struct i2c_adapter *adapter); | ||||
| static int daca_detect_client(struct i2c_adapter *adapter, int address); | ||||
| static int daca_detach_client(struct i2c_client *client); | ||||
| 
 | ||||
| struct i2c_driver daca_driver = {   | ||||
| 	.driver = { | ||||
| 		.name		= "DAC3550A driver  V " DACA_VERSION, | ||||
| 	}, | ||||
| 	.id			= I2C_DRIVERID_DACA, | ||||
| 	.attach_adapter		= daca_attach_adapter, | ||||
| 	.detach_client		= daca_detach_client, | ||||
| }; | ||||
| 
 | ||||
| #define VOL_MAX ((1<<20) - 1) | ||||
| 
 | ||||
| void daca_get_volume(uint * left_vol, uint  *right_vol) | ||||
| { | ||||
| 	*left_vol = cur_left_vol >> 5; | ||||
| 	*right_vol = cur_right_vol >> 5; | ||||
| } | ||||
| 
 | ||||
| int daca_set_volume(uint left_vol, uint right_vol) | ||||
| { | ||||
| 	unsigned short voldata; | ||||
|    | ||||
| 	if (!daca_client) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	/* Derived from experience, not from any specific values */ | ||||
| 	left_vol <<= 5; | ||||
| 	right_vol <<= 5; | ||||
| 
 | ||||
| 	if (left_vol > VOL_MAX) | ||||
| 		left_vol = VOL_MAX; | ||||
| 	if (right_vol > VOL_MAX) | ||||
| 		right_vol = VOL_MAX; | ||||
| 
 | ||||
| 	voldata = ((left_vol >> 14)  & 0x3f) << 8; | ||||
| 	voldata |= (right_vol >> 14)  & 0x3f; | ||||
|    | ||||
| 	if (i2c_smbus_write_word_data(daca_client, 2, voldata) < 0) { | ||||
| 		printk("daca: failed to set volume \n"); | ||||
| 		return -1;  | ||||
| 	} | ||||
| 
 | ||||
| 	cur_left_vol = left_vol; | ||||
| 	cur_right_vol = right_vol; | ||||
|    | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int daca_leave_sleep(void) | ||||
| { | ||||
| 	if (!daca_client) | ||||
| 		return -1; | ||||
|    | ||||
| 	/* Do a short sleep, just to make sure I2C bus is awake and paying
 | ||||
| 	 * attention to us | ||||
| 	 */ | ||||
| 	msleep(20); | ||||
| 	/* Write the sample rate reg the value it needs */ | ||||
| 	i2c_smbus_write_byte_data(daca_client, 1, 8); | ||||
| 	daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5); | ||||
| 	/* Another short delay, just to make sure the other I2C bus writes
 | ||||
| 	 * have taken... | ||||
| 	 */ | ||||
| 	msleep(20); | ||||
| 	/* Write the global config reg - invert right power amp,
 | ||||
| 	 * DAC on, use 5-volt mode */ | ||||
| 	i2c_smbus_write_byte_data(daca_client, 3, 0x45); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int daca_enter_sleep(void) | ||||
| { | ||||
| 	if (!daca_client) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	i2c_smbus_write_byte_data(daca_client, 1, 8); | ||||
| 	daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5); | ||||
| 
 | ||||
| 	/* Write the global config reg - invert right power amp,
 | ||||
| 	 * DAC on, enter low-power mode, use 5-volt mode | ||||
| 	 */ | ||||
| 	i2c_smbus_write_byte_data(daca_client, 3, 0x65); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int daca_attach_adapter(struct i2c_adapter *adapter) | ||||
| { | ||||
| 	if (!strncmp(adapter->name, "mac-io", 6)) | ||||
| 		daca_detect_client(adapter, 0x4d); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int daca_init_client(struct i2c_client * new_client) | ||||
| { | ||||
| 	/* 
 | ||||
| 	 * Probe is not working with the current i2c-keywest | ||||
| 	 * driver. We try to use addr 0x4d on each adapters | ||||
| 	 * instead, by setting the format register. | ||||
| 	 *  | ||||
| 	 * FIXME: I'm sure that can be obtained from the | ||||
| 	 * device-tree. --BenH. | ||||
| 	 */ | ||||
|    | ||||
| 	/* Write the global config reg - invert right power amp,
 | ||||
| 	 * DAC on, use 5-volt mode | ||||
| 	 */ | ||||
| 	if (i2c_smbus_write_byte_data(new_client, 3, 0x45)) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	i2c_smbus_write_byte_data(new_client, 1, 8); | ||||
| 	daca_client = new_client; | ||||
| 	daca_set_volume(15000, 15000); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int daca_detect_client(struct i2c_adapter *adapter, int address) | ||||
| { | ||||
| 	const char *client_name = "DAC 3550A Digital Equalizer"; | ||||
| 	struct i2c_client *new_client; | ||||
| 	int rc = -ENODEV; | ||||
| 
 | ||||
| 	new_client = kzalloc(sizeof(*new_client), GFP_KERNEL); | ||||
| 	if (!new_client) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	new_client->addr = address; | ||||
| 	new_client->adapter = adapter; | ||||
| 	new_client->driver = &daca_driver; | ||||
| 	new_client->flags = 0; | ||||
| 	strcpy(new_client->name, client_name); | ||||
| 
 | ||||
| 	if (daca_init_client(new_client)) | ||||
| 		goto bail; | ||||
| 
 | ||||
| 	/* Tell the i2c layer a new client has arrived */ | ||||
| 	if (i2c_attach_client(new_client)) | ||||
| 		goto bail; | ||||
| 
 | ||||
| 	return 0; | ||||
|  bail: | ||||
| 	kfree(new_client); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static int daca_detach_client(struct i2c_client *client) | ||||
| { | ||||
| 	if (client == daca_client) | ||||
| 		daca_client = NULL; | ||||
| 
 | ||||
|   	i2c_detach_client(client); | ||||
| 	kfree(client); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void daca_cleanup(void) | ||||
| { | ||||
| 	i2c_del_driver(&daca_driver); | ||||
| } | ||||
| 
 | ||||
| int daca_init(void) | ||||
| { | ||||
| 	printk("dac3550a driver version %s (%s)\n",DACA_VERSION,DACA_DATE); | ||||
| 	return i2c_add_driver(&daca_driver); | ||||
| } | ||||
| @ -59,7 +59,6 @@ static inline int ioctl_return(int __user *addr, int value) | ||||
|      */ | ||||
| 
 | ||||
| #undef HAS_8BIT_TABLES | ||||
| #undef HAS_RECORD | ||||
| 
 | ||||
| #if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\ | ||||
|     defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\ | ||||
| @ -83,10 +82,6 @@ static inline int ioctl_return(int __user *addr, int value) | ||||
| #define DEFAULT_N_BUFFERS 4 | ||||
| #define DEFAULT_BUFF_SIZE (1<<15) | ||||
| 
 | ||||
| #if defined(CONFIG_DMASOUND_PMAC) || defined(CONFIG_DMASOUND_PMAC_MODULE) | ||||
| #define HAS_RECORD | ||||
| #endif | ||||
| 
 | ||||
|     /*
 | ||||
|      *  Initialization | ||||
|      */ | ||||
| @ -168,9 +163,6 @@ struct sound_settings { | ||||
|     SETTINGS soft;	/* software settings */ | ||||
|     SETTINGS dsp;	/* /dev/dsp default settings */ | ||||
|     TRANS *trans_write;	/* supported translations */ | ||||
| #ifdef HAS_RECORD | ||||
|     TRANS *trans_read;	/* supported translations */ | ||||
| #endif | ||||
|     int volume_left;	/* volume (range is machine dependent) */ | ||||
|     int volume_right; | ||||
|     int bass;		/* tone (range is machine dependent) */ | ||||
| @ -253,11 +245,6 @@ struct sound_queue { | ||||
| extern struct sound_queue dmasound_write_sq; | ||||
| #define write_sq	dmasound_write_sq | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| extern struct sound_queue dmasound_read_sq; | ||||
| #define read_sq		dmasound_read_sq | ||||
| #endif | ||||
| 
 | ||||
| extern int dmasound_catchRadius; | ||||
| #define catchRadius	dmasound_catchRadius | ||||
| 
 | ||||
|  | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -202,13 +202,6 @@ module_param(numWriteBufs, int, 0); | ||||
| static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ;	/* in bytes */ | ||||
| module_param(writeBufSize, int, 0); | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| static unsigned int numReadBufs = DEFAULT_N_BUFFERS; | ||||
| module_param(numReadBufs, int, 0); | ||||
| static unsigned int readBufSize = DEFAULT_BUFF_SIZE;	/* in bytes */ | ||||
| module_param(readBufSize, int, 0); | ||||
| #endif | ||||
| 
 | ||||
| MODULE_LICENSE("GPL"); | ||||
| 
 | ||||
| #ifdef MODULE | ||||
| @ -403,10 +396,6 @@ static void mixer_init(void) | ||||
| 
 | ||||
| struct sound_queue dmasound_write_sq; | ||||
| static void sq_reset_output(void) ; | ||||
| #ifdef HAS_RECORD | ||||
| struct sound_queue dmasound_read_sq; | ||||
| static void sq_reset_input(void) ; | ||||
| #endif | ||||
| 
 | ||||
| static int sq_allocate_buffers(struct sound_queue *sq, int num, int size) | ||||
| { | ||||
| @ -530,12 +519,6 @@ printk("dmasound_core: invalid frag count (user set %d)\n", sq->user_frags) ; | ||||
| 	    sq->rear = -1; | ||||
| 	    setup_func = dmasound.mach.write_sq_setup; | ||||
| 	} | ||||
| #ifdef HAS_RECORD | ||||
| 	else { | ||||
| 	    sq->rear = 0; | ||||
| 	    setup_func = dmasound.mach.read_sq_setup; | ||||
| 	} | ||||
| #endif | ||||
| 	if (setup_func) | ||||
| 	    return setup_func(); | ||||
| 	return 0 ; | ||||
| @ -672,13 +655,6 @@ static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait) | ||||
| 	} | ||||
| 	if (file->f_mode & FMODE_WRITE ) | ||||
| 		poll_wait(file, &write_sq.action_queue, wait); | ||||
| #ifdef HAS_RECORD | ||||
| 	if (file->f_mode & FMODE_READ) | ||||
| 		poll_wait(file, &read_sq.action_queue, wait); | ||||
| 	if (file->f_mode & FMODE_READ) | ||||
| 		if (read_sq.block_size - read_sq.rear_size > 0) | ||||
| 			mask |= POLLIN | POLLRDNORM; | ||||
| #endif | ||||
| 	if (file->f_mode & FMODE_WRITE) | ||||
| 		if (write_sq.count < write_sq.max_active || write_sq.block_size - write_sq.rear_size > 0) | ||||
| 			mask |= POLLOUT | POLLWRNORM; | ||||
| @ -686,101 +662,6 @@ static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait) | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
|     /*
 | ||||
|      *  Here is how the values are used for reading. | ||||
|      *  The value 'active' simply indicates the DMA is running.  This is done | ||||
|      *  so the driver semantics are DMA starts when the first read is posted. | ||||
|      *  The value 'front' indicates the buffer we should next send to the user. | ||||
|      *  The value 'rear' indicates the buffer the DMA is currently filling. | ||||
|      *  When 'front' == 'rear' the buffer "ring" is empty (we always have an | ||||
|      *  empty available).  The 'rear_size' is used to track partial offsets | ||||
|      *  into the buffer we are currently returning to the user. | ||||
| 
 | ||||
|      *  This level (> [1.5]) doesn't care what strategy the LL driver uses with | ||||
|      *  DMA on over-run.  It can leave it running (and keep active == 1) or it | ||||
|      *  can kill it and set active == 0 in which case this routine will spot | ||||
|      *  it and restart the DMA. | ||||
|      */ | ||||
| 
 | ||||
| static ssize_t sq_read(struct file *file, char __user *dst, size_t uLeft, | ||||
| 		       loff_t *ppos) | ||||
| { | ||||
| 
 | ||||
| 	ssize_t	uRead, bLeft, bUsed, uUsed; | ||||
| 
 | ||||
| 	if (uLeft == 0) | ||||
| 		return 0; | ||||
| 
 | ||||
| 	/* cater for the compatibility mode - record compiled in but no LL */ | ||||
| 	if (dmasound.mach.record == NULL) | ||||
| 		return -EINVAL ; | ||||
| 
 | ||||
| 	/* see comment in sq_write()
 | ||||
| 	*/ | ||||
| 
 | ||||
| 	if( shared_resources_initialised == 0) { | ||||
| 		dmasound.mach.init() ; | ||||
| 		shared_resources_initialised = 1 ; | ||||
| 	} | ||||
| 
 | ||||
| 	/* set up the sq if it is not already done. see comments in sq_write().
 | ||||
| 	*/ | ||||
| 
 | ||||
| 	if (read_sq.locked == 0) { | ||||
| 		if ((uRead = sq_setup(&read_sq)) < 0) | ||||
| 			return uRead ; | ||||
| 	} | ||||
| 
 | ||||
| 	uRead = 0; | ||||
| 
 | ||||
| 	/* Move what the user requests, depending upon other options.
 | ||||
| 	*/ | ||||
| 	while (uLeft > 0) { | ||||
| 
 | ||||
| 		/* we happened to get behind and the LL driver killed DMA
 | ||||
| 		   then we should set it going again.  This also sets it | ||||
| 		   going the first time through. | ||||
| 		*/ | ||||
| 		if ( !read_sq.active ) | ||||
| 			dmasound.mach.record(); | ||||
| 
 | ||||
| 		/* When front == rear, the DMA is not done yet.
 | ||||
| 		*/ | ||||
| 		while (read_sq.front == read_sq.rear) { | ||||
| 			if (read_sq.open_mode & O_NONBLOCK) { | ||||
| 			       return uRead > 0 ? uRead : -EAGAIN; | ||||
| 			} | ||||
| 			SLEEP(read_sq.action_queue); | ||||
| 			if (signal_pending(current)) | ||||
| 				return uRead > 0 ? uRead : -EINTR; | ||||
| 		} | ||||
| 
 | ||||
| 		/* The amount we move is either what is left in the
 | ||||
| 		 * current buffer or what the user wants. | ||||
| 		 */ | ||||
| 		bLeft = read_sq.block_size - read_sq.rear_size; | ||||
| 		bUsed = read_sq.rear_size; | ||||
| 		uUsed = sound_copy_translate(dmasound.trans_read, dst, uLeft, | ||||
| 					     read_sq.buffers[read_sq.front], | ||||
| 					     &bUsed, bLeft); | ||||
| 		if (uUsed <= 0) | ||||
| 			return uUsed; | ||||
| 		dst += uUsed; | ||||
| 		uRead += uUsed; | ||||
| 		uLeft -= uUsed; | ||||
| 		read_sq.rear_size += bUsed; | ||||
| 		if (read_sq.rear_size >= read_sq.block_size) { | ||||
| 			read_sq.rear_size = 0; | ||||
| 			read_sq.front++; | ||||
| 			if (read_sq.front >= read_sq.max_active) | ||||
| 				read_sq.front = 0; | ||||
| 		} | ||||
| 	} | ||||
| 	return uRead; | ||||
| } | ||||
| #endif /* HAS_RECORD */ | ||||
| 
 | ||||
| static inline void sq_init_waitqueue(struct sound_queue *sq) | ||||
| { | ||||
| 	init_waitqueue_head(&sq->action_queue); | ||||
| @ -854,23 +735,6 @@ static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode, | ||||
| #define write_sq_open(file)	\ | ||||
| 	sq_open2(&write_sq, file, FMODE_WRITE, numWriteBufs, writeBufSize ) | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| #define read_sq_init_waitqueue()	sq_init_waitqueue(&read_sq) | ||||
| #if 0 /* blocking open() */
 | ||||
| #define read_sq_wake_up(file)		sq_wake_up(&read_sq, file, FMODE_READ) | ||||
| #endif | ||||
| #define read_sq_release_buffers()	sq_release_buffers(&read_sq) | ||||
| #define read_sq_open(file)	\ | ||||
| 	sq_open2(&read_sq, file, FMODE_READ, numReadBufs, readBufSize ) | ||||
| #else | ||||
| #define read_sq_init_waitqueue()	do {} while (0) | ||||
| #if 0 /* blocking open() */
 | ||||
| #define read_sq_wake_up(file)		do {} while (0) | ||||
| #endif | ||||
| #define read_sq_release_buffers()	do {} while (0) | ||||
| #define sq_reset_input()		do {} while (0) | ||||
| #endif | ||||
| 
 | ||||
| static int sq_open(struct inode *inode, struct file *file) | ||||
| { | ||||
| 	int rc; | ||||
| @ -881,25 +745,11 @@ static int sq_open(struct inode *inode, struct file *file) | ||||
| 	rc = write_sq_open(file); /* checks the f_mode */ | ||||
| 	if (rc) | ||||
| 		goto out; | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) { | ||||
| 		rc = read_sq_open(file); /* checks the f_mode */ | ||||
| 		if (rc) | ||||
| 			goto out; | ||||
| 	} else { /* no record function installed; in compat mode */ | ||||
| 		if (file->f_mode & FMODE_READ) { | ||||
| 			/* TODO: if O_RDWR, release any resources grabbed by write part */ | ||||
| 			rc = -ENXIO; | ||||
| 			goto out; | ||||
| 		} | ||||
| 	} | ||||
| #else /* !HAS_RECORD */ | ||||
| 	if (file->f_mode & FMODE_READ) { | ||||
| 		/* TODO: if O_RDWR, release any resources grabbed by write part */ | ||||
| 		rc = -ENXIO ; /* I think this is what is required by open(2) */ | ||||
| 		goto out; | ||||
| 	} | ||||
| #endif /* HAS_RECORD */ | ||||
| 
 | ||||
| 	if (dmasound.mach.sq_open) | ||||
| 	    dmasound.mach.sq_open(file->f_mode); | ||||
| @ -956,43 +806,9 @@ static void sq_reset_output(void) | ||||
| 	write_sq.user_frag_size = 0 ; | ||||
| } | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| 
 | ||||
| static void sq_reset_input(void) | ||||
| { | ||||
| 	if (dmasound.mach.record && read_sq.active) { | ||||
| 		if (dmasound.mach.abort_read) { /* this routine must really be present */ | ||||
| 			read_sq.syncing = 1 ; | ||||
| 			/* this can use the read_sq.sync_queue to sleep if
 | ||||
| 			   necessary - it should not return until DMA | ||||
| 			   is really stopped - because we might deallocate | ||||
| 			   the buffers as the next action... | ||||
| 			*/ | ||||
| 			dmasound.mach.abort_read() ; | ||||
| 		} else { | ||||
| 			printk(KERN_ERR | ||||
| 			"dmasound_core: %s has no abort_read()!! all bets are off\n", | ||||
| 				dmasound.mach.name) ; | ||||
| 		} | ||||
| 	} | ||||
| 	read_sq.syncing = | ||||
| 	read_sq.active = | ||||
| 	read_sq.front = | ||||
| 	read_sq.count = | ||||
| 	read_sq.rear = 0 ; | ||||
| 
 | ||||
| 	/* OK - we can unlock the parameters and fragment settings */ | ||||
| 	read_sq.locked = 0 ; | ||||
| 	read_sq.user_frags = 0 ; | ||||
| 	read_sq.user_frag_size = 0 ; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| static void sq_reset(void) | ||||
| { | ||||
| 	sq_reset_output() ; | ||||
| 	sq_reset_input() ; | ||||
| 	/* we could consider resetting the shared_resources_owner here... but I
 | ||||
| 	   think it is probably still rather non-obvious to application writer | ||||
| 	*/ | ||||
| @ -1038,17 +854,6 @@ static int sq_release(struct inode *inode, struct file *file) | ||||
| 
 | ||||
| 	lock_kernel(); | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| 	/* probably best to do the read side first - so that time taken to do it
 | ||||
| 	   overlaps with playing any remaining output samples. | ||||
| 	*/ | ||||
| 	if (file->f_mode & FMODE_READ) { | ||||
| 		sq_reset_input() ; /* make sure dma is stopped and all is quiet */ | ||||
| 		read_sq_release_buffers(); | ||||
| 		read_sq.busy = 0; | ||||
| 	} | ||||
| #endif | ||||
| 
 | ||||
| 	if (file->f_mode & FMODE_WRITE) { | ||||
| 		if (write_sq.busy) | ||||
| 			rc = sq_fsync(file, file->f_path.dentry); | ||||
| @ -1105,11 +910,6 @@ static int shared_resources_are_mine(mode_t md) | ||||
| 
 | ||||
| static int queues_are_quiescent(void) | ||||
| { | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) | ||||
| 		if (read_sq.locked) | ||||
| 			return 0 ; | ||||
| #endif | ||||
| 	if (write_sq.locked) | ||||
| 		return 0 ; | ||||
| 	return 1 ; | ||||
| @ -1185,13 +985,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||||
| 		   the read_sq ones. | ||||
| 		*/ | ||||
| 		size = 0 ; | ||||
| #ifdef HAS_RECORD | ||||
| 		if (dmasound.mach.record && (file->f_mode & FMODE_READ)) { | ||||
| 			if ( !read_sq.locked ) | ||||
| 				sq_setup(&read_sq) ; /* set params */ | ||||
| 			size = read_sq.user_frag_size ; | ||||
| 		} | ||||
| #endif | ||||
| 		if (file->f_mode & FMODE_WRITE) { | ||||
| 			if ( !write_sq.locked ) | ||||
| 				sq_setup(&write_sq) ; | ||||
| @ -1214,8 +1007,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||||
| 		   everything - read, however, is killed imediately. | ||||
| 		*/ | ||||
| 		result = 0 ; | ||||
| 		if ((file->f_mode & FMODE_READ) && dmasound.mach.record) | ||||
| 			sq_reset_input() ; | ||||
| 		if (file->f_mode & FMODE_WRITE) { | ||||
| 			result = sq_fsync(file, file->f_path.dentry); | ||||
| 			sq_reset_output() ; | ||||
| @ -1294,13 +1085,6 @@ static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd, | ||||
| 		result = 0 ; | ||||
| 		nbufs = (data >> 16) & 0x7fff ; /* 0x7fff is 'use maximum' */ | ||||
| 		size = data & 0xffff; | ||||
| #ifdef HAS_RECORD | ||||
| 		if ((file->f_mode & FMODE_READ) && dmasound.mach.record) { | ||||
| 			result = set_queue_frags(&read_sq, nbufs, size) ; | ||||
| 			if (result) | ||||
| 				return result ; | ||||
| 		} | ||||
| #endif | ||||
| 		if (file->f_mode & FMODE_WRITE) { | ||||
| 			result = set_queue_frags(&write_sq, nbufs, size) ; | ||||
| 			if (result) | ||||
| @ -1348,20 +1132,6 @@ static const struct file_operations sq_fops = | ||||
| 	.release	= sq_release, | ||||
| }; | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| static const struct file_operations sq_fops_record = | ||||
| { | ||||
| 	.owner		= THIS_MODULE, | ||||
| 	.llseek		= no_llseek, | ||||
| 	.write		= sq_write, | ||||
| 	.poll		= sq_poll, | ||||
| 	.ioctl		= sq_ioctl, | ||||
| 	.open		= sq_open, | ||||
| 	.release	= sq_release, | ||||
| 	.read		= sq_read, | ||||
| }; | ||||
| #endif | ||||
| 
 | ||||
| static int sq_init(void) | ||||
| { | ||||
| 	const struct file_operations *fops = &sq_fops; | ||||
| @ -1369,10 +1139,6 @@ static int sq_init(void) | ||||
| 	int sq_unit; | ||||
| #endif | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) | ||||
| 		fops = &sq_fops_record; | ||||
| #endif | ||||
| 	sq_unit = register_sound_dsp(fops, -1); | ||||
| 	if (sq_unit < 0) { | ||||
| 		printk(KERN_ERR "dmasound_core: couldn't register fops\n") ; | ||||
| @ -1380,7 +1146,6 @@ static int sq_init(void) | ||||
| 	} | ||||
| 
 | ||||
| 	write_sq_init_waitqueue(); | ||||
| 	read_sq_init_waitqueue(); | ||||
| 
 | ||||
| 	/* These parameters will be restored for every clean open()
 | ||||
| 	 * in the case of multiple open()s (e.g. dsp0 & dsp1) they | ||||
| @ -1406,11 +1171,7 @@ static int sq_init(void) | ||||
|    driver. | ||||
| */ | ||||
| 
 | ||||
| #ifdef HAS_RECORD | ||||
| #define STAT_BUFF_LEN 1024 | ||||
| #else | ||||
| #define STAT_BUFF_LEN 768 | ||||
| #endif | ||||
| 
 | ||||
| /* this is how much space we will allow the low-level driver to use
 | ||||
|    in the stat buffer.  Currently, 2 * (80 character line + <NL>). | ||||
| @ -1518,11 +1279,6 @@ static int state_open(struct inode *inode, struct file *file) | ||||
| 	len += sprintf(buffer+len,"Allocated:%8s%6s\n","Buffers","Size") ; | ||||
| 	len += sprintf(buffer+len,"%9s:%8d%6d\n", | ||||
| 		"write", write_sq.numBufs, write_sq.bufSize) ; | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) | ||||
| 		len += sprintf(buffer+len,"%9s:%8d%6d\n", | ||||
| 			"read", read_sq.numBufs, read_sq.bufSize) ; | ||||
| #endif | ||||
| 	len += sprintf(buffer+len, | ||||
| 		"Current  : MaxFrg FragSiz MaxAct Frnt Rear " | ||||
| 		"Cnt RrSize A B S L  xruns\n") ; | ||||
| @ -1531,14 +1287,6 @@ static int state_open(struct inode *inode, struct file *file) | ||||
| 		write_sq.max_active, write_sq.front, write_sq.rear, | ||||
| 		write_sq.count, write_sq.rear_size, write_sq.active, | ||||
| 		write_sq.busy, write_sq.syncing, write_sq.locked, write_sq.xruns) ; | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) | ||||
| 		len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n", | ||||
| 			"read", read_sq.max_count, read_sq.block_size, | ||||
| 			read_sq.max_active, read_sq.front, read_sq.rear, | ||||
| 			read_sq.count, read_sq.rear_size, read_sq.active, | ||||
| 			read_sq.busy, read_sq.syncing, read_sq.locked, read_sq.xruns) ; | ||||
| #endif | ||||
| #ifdef DEBUG_DMASOUND | ||||
| printk("dmasound: stat buffer used %d bytes\n", len) ; | ||||
| #endif | ||||
| @ -1638,13 +1386,6 @@ int dmasound_init(void) | ||||
| 		(dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ; | ||||
| 	printk(KERN_INFO "Write will use %4d fragments of %7d bytes as default\n", | ||||
| 		numWriteBufs, writeBufSize) ; | ||||
| #ifdef HAS_RECORD | ||||
| 	if (dmasound.mach.record) | ||||
| 		printk(KERN_INFO | ||||
| 			"Read  will use %4d fragments of %7d bytes as default\n", | ||||
| 			numReadBufs, readBufSize) ; | ||||
| #endif | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| @ -1659,7 +1400,6 @@ void dmasound_deinit(void) | ||||
| 	} | ||||
| 
 | ||||
| 	write_sq_release_buffers(); | ||||
| 	read_sq_release_buffers(); | ||||
| 
 | ||||
| 	if (mixer_unit >= 0) | ||||
| 		unregister_sound_mixer(mixer_unit); | ||||
| @ -1684,36 +1424,12 @@ static int dmasound_setup(char *str) | ||||
| 	 */ | ||||
| 
 | ||||
| 	switch (ints[0]) { | ||||
| #ifdef HAS_RECORD | ||||
|         case 5: | ||||
|                 if ((ints[5] < 0) || (ints[5] > MAX_CATCH_RADIUS)) | ||||
|                         printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); | ||||
|                 else | ||||
|                         catchRadius = ints[5]; | ||||
|                 /* fall through */ | ||||
|         case 4: | ||||
|                 if (ints[4] < MIN_BUFFERS) | ||||
|                         printk("dmasound_setup: invalid number of read buffers, using default = %d\n", | ||||
|                                  numReadBufs); | ||||
|                 else | ||||
|                         numReadBufs = ints[4]; | ||||
|                 /* fall through */ | ||||
|         case 3: | ||||
| 		if ((size = ints[3]) < 256)  /* check for small buffer specs */ | ||||
| 			size <<= 10 ; | ||||
|                 if (size < MIN_BUFSIZE || size > MAX_BUFSIZE) | ||||
|                         printk("dmasound_setup: invalid read buffer size, using default = %d\n", readBufSize); | ||||
|                 else | ||||
|                         readBufSize = size; | ||||
|                 /* fall through */ | ||||
| #else | ||||
| 	case 3: | ||||
| 		if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS)) | ||||
| 			printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius); | ||||
| 		else | ||||
| 			catchRadius = ints[3]; | ||||
| 		/* fall through */ | ||||
| #endif | ||||
| 	case 2: | ||||
| 		if (ints[1] < MIN_BUFFERS) | ||||
| 			printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs); | ||||
| @ -1830,9 +1546,6 @@ EXPORT_SYMBOL(dmasound_init); | ||||
| EXPORT_SYMBOL(dmasound_deinit); | ||||
| #endif | ||||
| EXPORT_SYMBOL(dmasound_write_sq); | ||||
| #ifdef HAS_RECORD | ||||
| EXPORT_SYMBOL(dmasound_read_sq); | ||||
| #endif | ||||
| EXPORT_SYMBOL(dmasound_catchRadius); | ||||
| #ifdef HAS_8BIT_TABLES | ||||
| EXPORT_SYMBOL(dmasound_ulaw2dma8); | ||||
|  | ||||
| @ -1,849 +0,0 @@ | ||||
| /*
 | ||||
|  * Driver for the i2c/i2s based TA3004 sound chip used | ||||
|  * on some Apple hardware. Also known as "snapper". | ||||
|  * | ||||
|  * Tobias Sargeant <tobias.sargeant@bigpond.com> | ||||
|  * Based upon, tas3001c.c by Christopher C. Chimelis <chris@debian.org>: | ||||
|  * | ||||
|  *   TODO: | ||||
|  *   ----- | ||||
|  *   * Enable control over input line 2 (is this connected?) | ||||
|  *   * Implement sleep support (at least mute everything and | ||||
|  *   * set gains to minimum during sleep) | ||||
|  *   * Look into some of Darwin's tweaks regarding the mute | ||||
|  *   * lines (delays & different behaviour on some HW) | ||||
|  * | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/module.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/proc_fs.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/sysctl.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/soundcard.h> | ||||
| #include <linux/workqueue.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/errno.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/prom.h> | ||||
| 
 | ||||
| #include "dmasound.h" | ||||
| #include "tas_common.h" | ||||
| #include "tas3001c.h" | ||||
| 
 | ||||
| #include "tas_ioctl.h" | ||||
| 
 | ||||
| #define TAS3001C_BIQUAD_FILTER_COUNT  6 | ||||
| #define TAS3001C_BIQUAD_CHANNEL_COUNT 2 | ||||
| 
 | ||||
| #define VOL_DEFAULT	(100 * 4 / 5) | ||||
| #define INPUT_DEFAULT	(100 * 4 / 5) | ||||
| #define BASS_DEFAULT	(100 / 2) | ||||
| #define TREBLE_DEFAULT	(100 / 2) | ||||
| 
 | ||||
| struct tas3001c_data_t { | ||||
| 	struct tas_data_t super; | ||||
| 	int device_id; | ||||
| 	int output_id; | ||||
| 	int speaker_id; | ||||
| 	struct tas_drce_t drce_state; | ||||
| 	struct work_struct change; | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static const union tas_biquad_t | ||||
| tas3001c_eq_unity={ | ||||
| 	.buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } | ||||
| }; | ||||
| 
 | ||||
| 
 | ||||
| static inline unsigned char db_to_regval(short db) { | ||||
| 	int r=0; | ||||
| 
 | ||||
| 	r=(db+0x59a0) / 0x60; | ||||
| 
 | ||||
| 	if (r < 0x91) return 0x91; | ||||
| 	if (r > 0xef) return 0xef; | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| static inline short quantize_db(short db) { | ||||
| 	return db_to_regval(db) * 0x60 - 0x59a0; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static inline int | ||||
| register_width(enum tas3001c_reg_t r) | ||||
| { | ||||
| 	switch(r) { | ||||
| 	case TAS3001C_REG_MCR: | ||||
|  	case TAS3001C_REG_TREBLE: | ||||
| 	case TAS3001C_REG_BASS: | ||||
| 		return 1; | ||||
| 
 | ||||
| 	case TAS3001C_REG_DRC: | ||||
| 		return 2; | ||||
| 
 | ||||
| 	case TAS3001C_REG_MIXER1: | ||||
| 	case TAS3001C_REG_MIXER2: | ||||
| 		return 3; | ||||
| 
 | ||||
| 	case TAS3001C_REG_VOLUME: | ||||
| 		return 6; | ||||
| 
 | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD0: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD1: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD2: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD3: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD4: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD5: | ||||
| 	case TAS3001C_REG_LEFT_BIQUAD6: | ||||
| 
 | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD0: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD1: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD2: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD3: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD4: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD5: | ||||
| 	case TAS3001C_REG_RIGHT_BIQUAD6: | ||||
| 		return 15; | ||||
| 
 | ||||
| 	default: | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_write_register(	struct tas3001c_data_t *self, | ||||
| 				enum tas3001c_reg_t reg_num, | ||||
| 				char *data, | ||||
| 				uint write_mode) | ||||
| { | ||||
| 	if (reg_num==TAS3001C_REG_MCR || | ||||
| 	    reg_num==TAS3001C_REG_BASS || | ||||
| 	    reg_num==TAS3001C_REG_TREBLE) { | ||||
| 		return tas_write_byte_register(&self->super, | ||||
| 					       (uint)reg_num, | ||||
| 					       *data, | ||||
| 					       write_mode); | ||||
| 	} else { | ||||
| 		return tas_write_register(&self->super, | ||||
| 					  (uint)reg_num, | ||||
| 					  register_width(reg_num), | ||||
| 					  data, | ||||
| 					  write_mode); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_sync_register(	struct tas3001c_data_t *self, | ||||
| 			enum tas3001c_reg_t reg_num) | ||||
| { | ||||
| 	if (reg_num==TAS3001C_REG_MCR || | ||||
| 	    reg_num==TAS3001C_REG_BASS || | ||||
| 	    reg_num==TAS3001C_REG_TREBLE) { | ||||
| 		return tas_sync_byte_register(&self->super, | ||||
| 					      (uint)reg_num, | ||||
| 					      register_width(reg_num)); | ||||
| 	} else { | ||||
| 		return tas_sync_register(&self->super, | ||||
| 					 (uint)reg_num, | ||||
| 					 register_width(reg_num)); | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_read_register(	struct tas3001c_data_t *self, | ||||
| 			enum tas3001c_reg_t reg_num, | ||||
| 			char *data, | ||||
| 			uint write_mode) | ||||
| { | ||||
| 	return tas_read_register(&self->super, | ||||
| 				 (uint)reg_num, | ||||
| 				 register_width(reg_num), | ||||
| 				 data); | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tas3001c_fast_load(struct tas3001c_data_t *self, int fast) | ||||
| { | ||||
| 	if (fast) | ||||
| 		self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80; | ||||
| 	else | ||||
| 		self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f; | ||||
| 	return tas3001c_sync_register(self,TAS3001C_REG_MCR); | ||||
| } | ||||
| 
 | ||||
| static uint | ||||
| tas3001c_supported_mixers(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	return SOUND_MASK_VOLUME | | ||||
| 		SOUND_MASK_PCM | | ||||
| 		SOUND_MASK_ALTPCM | | ||||
| 		SOUND_MASK_TREBLE | | ||||
| 		SOUND_MASK_BASS; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer) | ||||
| { | ||||
| 	switch(mixer) { | ||||
| 	case SOUND_MIXER_VOLUME: | ||||
| 		return 1; | ||||
| 	default: | ||||
| 		return 0; | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static uint | ||||
| tas3001c_stereo_mixers(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	uint r=tas3001c_supported_mixers(self); | ||||
| 	uint i; | ||||
| 	 | ||||
| 	for (i=1; i<SOUND_MIXER_NRDEVICES; i++) | ||||
| 		if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i)) | ||||
| 			r &= ~(1<<i); | ||||
| 	return r; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level) | ||||
| { | ||||
| 	if (!self) | ||||
| 		return -1; | ||||
| 		 | ||||
| 	*level=self->super.mixer[mixer]; | ||||
| 	 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level) | ||||
| { | ||||
| 	int rc; | ||||
| 	tas_shadow_t *shadow; | ||||
| 
 | ||||
| 	uint temp; | ||||
| 	uint offset=0; | ||||
| 
 | ||||
| 	if (!self) | ||||
| 		return -1; | ||||
| 		 | ||||
| 	shadow=self->super.shadow; | ||||
| 
 | ||||
| 	if (!tas3001c_mixer_is_stereo(self,mixer)) | ||||
| 		level = tas_mono_to_stereo(level); | ||||
| 
 | ||||
| 	switch(mixer) { | ||||
| 	case SOUND_MIXER_VOLUME: | ||||
| 		temp = tas3001c_gain.master[level&0xff]; | ||||
| 		shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff; | ||||
| 		shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8)  & 0xff; | ||||
| 		shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0)  & 0xff; | ||||
| 		temp = tas3001c_gain.master[(level>>8)&0xff]; | ||||
| 		shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff; | ||||
| 		shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8)  & 0xff; | ||||
| 		shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0)  & 0xff; | ||||
| 		rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME); | ||||
| 		break; | ||||
| 	case SOUND_MIXER_ALTPCM: | ||||
| 		/* tas3001c_fast_load(self, 1); */ | ||||
| 		level = tas_mono_to_stereo(level); | ||||
| 		temp = tas3001c_gain.mixer[level&0xff]; | ||||
| 		shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff; | ||||
| 		shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8)  & 0xff; | ||||
| 		shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0)  & 0xff; | ||||
| 		rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2); | ||||
| 		/* tas3001c_fast_load(self, 0); */ | ||||
| 		break; | ||||
| 	case SOUND_MIXER_PCM: | ||||
| 		/* tas3001c_fast_load(self, 1); */ | ||||
| 		level = tas_mono_to_stereo(level); | ||||
| 		temp = tas3001c_gain.mixer[level&0xff]; | ||||
| 		shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff; | ||||
| 		shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8)  & 0xff; | ||||
| 		shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0)  & 0xff; | ||||
| 		rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1); | ||||
| 		/* tas3001c_fast_load(self, 0); */ | ||||
| 		break; | ||||
| 	case SOUND_MIXER_TREBLE: | ||||
| 		temp = tas3001c_gain.treble[level&0xff]; | ||||
| 		shadow[TAS3001C_REG_TREBLE][0]=temp&0xff; | ||||
| 		rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE); | ||||
| 		break; | ||||
| 	case SOUND_MIXER_BASS: | ||||
| 		temp = tas3001c_gain.bass[level&0xff]; | ||||
| 		shadow[TAS3001C_REG_BASS][0]=temp&0xff; | ||||
| 		rc = tas3001c_sync_register(self,TAS3001C_REG_BASS); | ||||
| 		break; | ||||
| 	default: | ||||
| 		rc = -1; | ||||
| 		break; | ||||
| 	} | ||||
| 	if (rc < 0) | ||||
| 		return rc; | ||||
| 	self->super.mixer[mixer]=level; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_leave_sleep(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	unsigned char mcr = (1<<6)+(2<<4)+(2<<2); | ||||
| 
 | ||||
| 	if (!self) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	/* Make sure something answers on the i2c bus */ | ||||
| 	if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, | ||||
| 	    WRITE_NORMAL|FORCE_WRITE) < 0) | ||||
| 	    	return -1; | ||||
| 
 | ||||
| 	tas3001c_fast_load(self, 1); | ||||
| 
 | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); | ||||
| 
 | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); | ||||
| 
 | ||||
| 	tas3001c_fast_load(self, 0); | ||||
| 
 | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_BASS); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_enter_sleep(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	/* Stub for now, but I have the details on low-power mode */ | ||||
| 	if (!self) | ||||
| 		return -1;  | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_sync_biquad(	struct tas3001c_data_t *self, | ||||
| 			u_int channel, | ||||
| 			u_int filter) | ||||
| { | ||||
| 	enum tas3001c_reg_t reg; | ||||
| 
 | ||||
| 	if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || | ||||
| 	    filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; | ||||
| 
 | ||||
| 	reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; | ||||
| 
 | ||||
| 	return tas3001c_sync_register(self,reg); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_write_biquad_shadow(	struct tas3001c_data_t *self, | ||||
| 				u_int channel, | ||||
| 				u_int filter, | ||||
| 				const union tas_biquad_t *biquad) | ||||
| { | ||||
| 	tas_shadow_t *shadow=self->super.shadow; | ||||
| 	enum tas3001c_reg_t reg; | ||||
| 
 | ||||
| 	if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || | ||||
| 	    filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; | ||||
| 
 | ||||
| 	reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; | ||||
| 
 | ||||
| 	SET_4_20(shadow[reg], 0,biquad->coeff.b0); | ||||
| 	SET_4_20(shadow[reg], 3,biquad->coeff.b1); | ||||
| 	SET_4_20(shadow[reg], 6,biquad->coeff.b2); | ||||
| 	SET_4_20(shadow[reg], 9,biquad->coeff.a1); | ||||
| 	SET_4_20(shadow[reg],12,biquad->coeff.a2); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_write_biquad(	struct tas3001c_data_t *self, | ||||
| 			u_int channel, | ||||
| 			u_int filter, | ||||
| 			const union tas_biquad_t *biquad) | ||||
| { | ||||
| 	int rc; | ||||
| 
 | ||||
| 	rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad); | ||||
| 	if (rc < 0) return rc; | ||||
| 
 | ||||
| 	return tas3001c_sync_biquad(self, channel, filter); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_write_biquad_list(	struct tas3001c_data_t *self, | ||||
| 				u_int filter_count, | ||||
| 				u_int flags, | ||||
| 				struct tas_biquad_ctrl_t *biquads) | ||||
| { | ||||
| 	int i; | ||||
| 	int rc; | ||||
| 
 | ||||
| 	if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); | ||||
| 
 | ||||
| 	for (i=0; i<filter_count; i++) { | ||||
| 		rc=tas3001c_write_biquad(self, | ||||
| 					 biquads[i].channel, | ||||
| 					 biquads[i].filter, | ||||
| 					 &biquads[i].data); | ||||
| 		if (rc < 0) break; | ||||
| 	} | ||||
| 
 | ||||
| 	if (flags & TAS_BIQUAD_FAST_LOAD) { | ||||
| 		tas3001c_fast_load(self,0); | ||||
| 
 | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_BASS); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); | ||||
| 	} | ||||
| 
 | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_read_biquad(	struct tas3001c_data_t *self, | ||||
| 			u_int channel, | ||||
| 			u_int filter, | ||||
| 			union tas_biquad_t *biquad) | ||||
| { | ||||
| 	tas_shadow_t *shadow=self->super.shadow; | ||||
| 	enum tas3001c_reg_t reg; | ||||
| 
 | ||||
| 	if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT || | ||||
| 	    filter  >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL; | ||||
| 
 | ||||
| 	reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter; | ||||
| 
 | ||||
| 	biquad->coeff.b0=GET_4_20(shadow[reg], 0); | ||||
| 	biquad->coeff.b1=GET_4_20(shadow[reg], 3); | ||||
| 	biquad->coeff.b2=GET_4_20(shadow[reg], 6); | ||||
| 	biquad->coeff.a1=GET_4_20(shadow[reg], 9); | ||||
| 	biquad->coeff.a2=GET_4_20(shadow[reg],12); | ||||
| 	 | ||||
| 	return 0;	 | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_eq_rw(	struct tas3001c_data_t *self, | ||||
| 		u_int cmd, | ||||
| 		u_long arg) | ||||
| { | ||||
| 	int rc; | ||||
| 	struct tas_biquad_ctrl_t biquad; | ||||
| 	void __user *argp = (void __user *)arg; | ||||
| 
 | ||||
| 	if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) { | ||||
| 		return -EFAULT; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cmd & SIOC_IN) { | ||||
| 		rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data); | ||||
| 		if (rc != 0) return rc; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cmd & SIOC_OUT) { | ||||
| 		rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); | ||||
| 		if (rc != 0) return rc; | ||||
| 
 | ||||
| 		if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 
 | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_eq_list_rw(	struct tas3001c_data_t *self, | ||||
| 			u_int cmd, | ||||
| 			u_long arg) | ||||
| { | ||||
| 	int rc; | ||||
| 	int filter_count; | ||||
| 	int flags; | ||||
| 	int i,j; | ||||
| 	char sync_required[2][6]; | ||||
| 	struct tas_biquad_ctrl_t biquad; | ||||
| 	struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg; | ||||
| 
 | ||||
| 	memset(sync_required,0,sizeof(sync_required)); | ||||
| 
 | ||||
| 	if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	if (copy_from_user(&flags, &argp->flags, sizeof(int))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| 	if (cmd & SIOC_IN) { | ||||
| 	} | ||||
| 
 | ||||
| 	for (i=0; i < filter_count; i++) { | ||||
| 		if (copy_from_user(&biquad, &argp->biquads[i], | ||||
| 				   sizeof(struct tas_biquad_ctrl_t))) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cmd & SIOC_IN) { | ||||
| 			sync_required[biquad.channel][biquad.filter]=1; | ||||
| 			rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data); | ||||
| 			if (rc != 0) return rc; | ||||
| 		} | ||||
| 
 | ||||
| 		if (cmd & SIOC_OUT) { | ||||
| 			rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data); | ||||
| 			if (rc != 0) return rc; | ||||
| 
 | ||||
| 			if (copy_to_user(&argp->biquads[i], &biquad, | ||||
| 					 sizeof(struct tas_biquad_ctrl_t))) { | ||||
| 				return -EFAULT; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if (cmd & SIOC_IN) { | ||||
| 		if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1); | ||||
| 		for (i=0; i<2; i++) { | ||||
| 			for (j=0; j<6; j++) { | ||||
| 				if (sync_required[i][j]) { | ||||
| 					rc=tas3001c_sync_biquad(self, i, j); | ||||
| 					if (rc < 0) return rc; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 		if (flags & TAS_BIQUAD_FAST_LOAD) { | ||||
| 			tas3001c_fast_load(self,0); | ||||
| 			/* now we need to set up the mixers again,
 | ||||
| 			   because leaving fast mode resets them. */ | ||||
| 			(void)tas3001c_sync_register(self,TAS3001C_REG_BASS); | ||||
| 			(void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); | ||||
| 			(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); | ||||
| 			(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); | ||||
| 			(void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_update_drce(	struct tas3001c_data_t *self, | ||||
| 			int flags, | ||||
| 			struct tas_drce_t *drce) | ||||
| { | ||||
| 	tas_shadow_t *shadow; | ||||
| 	shadow=self->super.shadow; | ||||
| 
 | ||||
| 	shadow[TAS3001C_REG_DRC][1] = 0xc1; | ||||
| 
 | ||||
| 	if (flags & TAS_DRCE_THRESHOLD) { | ||||
| 		self->drce_state.threshold=quantize_db(drce->threshold); | ||||
| 		shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold); | ||||
| 	} | ||||
| 
 | ||||
| 	if (flags & TAS_DRCE_ENABLE) { | ||||
| 		self->drce_state.enable = drce->enable; | ||||
| 	} | ||||
| 
 | ||||
| 	if (!self->drce_state.enable) { | ||||
| 		shadow[TAS3001C_REG_DRC][0] = 0xf0; | ||||
| 	} | ||||
| 
 | ||||
| #ifdef DEBUG_DRCE | ||||
| 	printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n", | ||||
| 	       self->drce_state.enable, | ||||
| 	       self->drce_state.threshold); | ||||
| 
 | ||||
| 	printk("DRCE IOCTL: reg [ %02x %02x ]\n", | ||||
| 	       (unsigned char)shadow[TAS3001C_REG_DRC][0], | ||||
| 	       (unsigned char)shadow[TAS3001C_REG_DRC][1]); | ||||
| #endif | ||||
| 
 | ||||
| 	return tas3001c_sync_register(self, TAS3001C_REG_DRC); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_drce_rw(	struct tas3001c_data_t *self, | ||||
| 			u_int cmd, | ||||
| 			u_long arg) | ||||
| { | ||||
| 	int rc; | ||||
| 	struct tas_drce_ctrl_t drce_ctrl; | ||||
| 	void __user *argp = (void __user *)arg; | ||||
| 
 | ||||
| 	if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t))) | ||||
| 		return -EFAULT; | ||||
| 
 | ||||
| #ifdef DEBUG_DRCE | ||||
| 	printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n", | ||||
| 	       drce_ctrl.flags, | ||||
| 	       drce_ctrl.data.enable, | ||||
| 	       drce_ctrl.data.threshold); | ||||
| #endif | ||||
| 
 | ||||
| 	if (cmd & SIOC_IN) { | ||||
| 		rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data); | ||||
| 		if (rc < 0) | ||||
| 			return rc; | ||||
| 	} | ||||
| 
 | ||||
| 	if (cmd & SIOC_OUT) { | ||||
| 		if (drce_ctrl.flags & TAS_DRCE_ENABLE) | ||||
| 			drce_ctrl.data.enable = self->drce_state.enable; | ||||
| 
 | ||||
| 		if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) | ||||
| 			drce_ctrl.data.threshold = self->drce_state.threshold; | ||||
| 
 | ||||
| 		if (copy_to_user(argp, &drce_ctrl, | ||||
| 				 sizeof(struct tas_drce_ctrl_t))) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| tas3001c_update_device_parameters(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	int i,j; | ||||
| 
 | ||||
| 	if (!self) return; | ||||
| 
 | ||||
| 	if (self->output_id == TAS_OUTPUT_HEADPHONES) { | ||||
| 		tas3001c_fast_load(self, 1); | ||||
| 
 | ||||
| 		for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) { | ||||
| 			for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) { | ||||
| 				tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity); | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		tas3001c_fast_load(self, 0); | ||||
| 
 | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_BASS); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2); | ||||
| 		(void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME); | ||||
| 
 | ||||
| 		return; | ||||
| 	} | ||||
| 
 | ||||
| 	for (i=0; tas3001c_eq_prefs[i]; i++) { | ||||
| 		struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i]; | ||||
| 
 | ||||
| 		if (eq->device_id == self->device_id && | ||||
| 		    (eq->output_id == 0 || eq->output_id == self->output_id) && | ||||
| 		    (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) { | ||||
| 
 | ||||
| 			tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce); | ||||
| 			tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads); | ||||
| 
 | ||||
| 			break; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| tas3001c_device_change_handler(struct work_struct *work) | ||||
| { | ||||
| 	struct tas3001c_data_t *self; | ||||
| 	self = container_of(work, struct tas3001c_data_t, change); | ||||
| 	tas3001c_update_device_parameters(self); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_output_device_change(	struct tas3001c_data_t *self, | ||||
| 				int device_id, | ||||
| 				int output_id, | ||||
| 				int speaker_id) | ||||
| { | ||||
| 	self->device_id=device_id; | ||||
| 	self->output_id=output_id; | ||||
| 	self->speaker_id=speaker_id; | ||||
| 
 | ||||
| 	schedule_work(&self->change); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_device_ioctl(	struct tas3001c_data_t *self, | ||||
| 			u_int cmd, | ||||
| 			u_long arg) | ||||
| { | ||||
| 	uint __user *argp = (void __user *)arg; | ||||
| 	switch (cmd) { | ||||
| 	case TAS_READ_EQ: | ||||
| 	case TAS_WRITE_EQ: | ||||
| 		return tas3001c_eq_rw(self, cmd, arg); | ||||
| 
 | ||||
| 	case TAS_READ_EQ_LIST: | ||||
| 	case TAS_WRITE_EQ_LIST: | ||||
| 		return tas3001c_eq_list_rw(self, cmd, arg); | ||||
| 
 | ||||
| 	case TAS_READ_EQ_FILTER_COUNT: | ||||
| 		put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp); | ||||
| 		return 0; | ||||
| 
 | ||||
| 	case TAS_READ_EQ_CHANNEL_COUNT: | ||||
| 		put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp); | ||||
| 		return 0; | ||||
| 
 | ||||
| 	case TAS_READ_DRCE: | ||||
| 	case TAS_WRITE_DRCE: | ||||
| 		return tas3001c_drce_rw(self, cmd, arg); | ||||
| 
 | ||||
| 	case TAS_READ_DRCE_CAPS: | ||||
| 		put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp); | ||||
| 		return 0; | ||||
| 
 | ||||
| 	case TAS_READ_DRCE_MIN: | ||||
| 	case TAS_READ_DRCE_MAX: { | ||||
| 		struct tas_drce_ctrl_t drce_ctrl; | ||||
| 
 | ||||
| 		if (copy_from_user(&drce_ctrl, argp, | ||||
| 				   sizeof(struct tas_drce_ctrl_t))) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 
 | ||||
| 		if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) { | ||||
| 			if (cmd == TAS_READ_DRCE_MIN) { | ||||
| 				drce_ctrl.data.threshold=-36<<8; | ||||
| 			} else { | ||||
| 				drce_ctrl.data.threshold=-6<<8; | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if (copy_to_user(argp, &drce_ctrl, | ||||
| 				 sizeof(struct tas_drce_ctrl_t))) { | ||||
| 			return -EFAULT; | ||||
| 		} | ||||
| 	} | ||||
| 	} | ||||
| 
 | ||||
| 	return -EINVAL; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_init_mixer(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	unsigned char mcr = (1<<6)+(2<<4)+(2<<2); | ||||
| 
 | ||||
| 	/* Make sure something answers on the i2c bus */ | ||||
| 	if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr, | ||||
| 	    WRITE_NORMAL|FORCE_WRITE) < 0) | ||||
| 		return -1; | ||||
| 
 | ||||
| 	tas3001c_fast_load(self, 1); | ||||
| 
 | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6); | ||||
| 
 | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5); | ||||
| 	(void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6); | ||||
| 
 | ||||
| 	tas3001c_fast_load(self, 0); | ||||
| 
 | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); | ||||
| 
 | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_uninit_mixer(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_PCM,    0); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0); | ||||
| 
 | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_BASS,   0); | ||||
| 	tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0); | ||||
| 
 | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas3001c_init(struct i2c_client *client) | ||||
| { | ||||
| 	struct tas3001c_data_t *self; | ||||
| 	size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t)); | ||||
| 	int i, j; | ||||
| 
 | ||||
| 	self = kzalloc(sz, GFP_KERNEL); | ||||
| 	if (!self) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	self->super.client = client; | ||||
| 	self->super.shadow = (tas_shadow_t *)(self+1); | ||||
| 	self->output_id = TAS_OUTPUT_HEADPHONES; | ||||
| 
 | ||||
| 	dev_set_drvdata(&client->dev, self); | ||||
| 
 | ||||
| 	for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++) | ||||
| 		for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++) | ||||
| 			tas3001c_write_biquad_shadow(self, i, j, | ||||
| 				&tas3001c_eq_unity); | ||||
| 
 | ||||
| 	INIT_WORK(&self->change, tas3001c_device_change_handler); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static void | ||||
| tas3001c_uninit(struct tas3001c_data_t *self) | ||||
| { | ||||
| 	tas3001c_uninit_mixer(self); | ||||
| 	kfree(self); | ||||
| } | ||||
| 
 | ||||
| struct tas_driver_hooks_t tas3001c_hooks = { | ||||
| 	.init			= (tas_hook_init_t)tas3001c_init, | ||||
| 	.post_init		= (tas_hook_post_init_t)tas3001c_init_mixer, | ||||
| 	.uninit			= (tas_hook_uninit_t)tas3001c_uninit, | ||||
| 	.get_mixer_level	= (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level, | ||||
| 	.set_mixer_level	= (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level, | ||||
| 	.enter_sleep		= (tas_hook_enter_sleep_t)tas3001c_enter_sleep, | ||||
| 	.leave_sleep		= (tas_hook_leave_sleep_t)tas3001c_leave_sleep, | ||||
| 	.supported_mixers	= (tas_hook_supported_mixers_t)tas3001c_supported_mixers, | ||||
| 	.mixer_is_stereo	= (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo, | ||||
| 	.stereo_mixers		= (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers, | ||||
| 	.output_device_change	= (tas_hook_output_device_change_t)tas3001c_output_device_change, | ||||
| 	.device_ioctl		= (tas_hook_device_ioctl_t)tas3001c_device_ioctl | ||||
| }; | ||||
| @ -1,64 +0,0 @@ | ||||
| /*
 | ||||
|  * Header file for the i2c/i2s based TA3001c sound chip used | ||||
|  * on some Apple hardware. Also known as "tumbler". | ||||
|  * | ||||
|  *  This file is subject to the terms and conditions of the GNU General Public | ||||
|  *  License.  See the file COPYING in the main directory of this archive | ||||
|  *  for more details. | ||||
|  * | ||||
|  * Written by Christopher C. Chimelis <chris@debian.org> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _TAS3001C_H_ | ||||
| #define _TAS3001C_H_ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #include "tas_common.h" | ||||
| #include "tas_eq_prefs.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Macros that correspond to the registers that we write to | ||||
|  * when setting the various values. | ||||
|  */ | ||||
| 
 | ||||
| #define TAS3001C_VERSION	"0.3" | ||||
| #define TAS3001C_DATE	        "20011214" | ||||
| 
 | ||||
| #define I2C_DRIVERNAME_TAS3001C "TAS3001c driver V " TAS3001C_VERSION | ||||
| #define I2C_DRIVERID_TAS3001C   (I2C_DRIVERID_TAS_BASE+0) | ||||
| 
 | ||||
| extern  struct tas_driver_hooks_t tas3001c_hooks; | ||||
| extern struct tas_gain_t tas3001c_gain; | ||||
| extern struct tas_eq_pref_t *tas3001c_eq_prefs[]; | ||||
| 
 | ||||
| enum tas3001c_reg_t { | ||||
|   TAS3001C_REG_MCR                    = 0x01, | ||||
|   TAS3001C_REG_DRC                    = 0x02, | ||||
| 
 | ||||
|   TAS3001C_REG_VOLUME                 = 0x04, | ||||
|   TAS3001C_REG_TREBLE                 = 0x05, | ||||
|   TAS3001C_REG_BASS                   = 0x06, | ||||
|   TAS3001C_REG_MIXER1                 = 0x07, | ||||
|   TAS3001C_REG_MIXER2                 = 0x08, | ||||
| 
 | ||||
|   TAS3001C_REG_LEFT_BIQUAD0           = 0x0a, | ||||
|   TAS3001C_REG_LEFT_BIQUAD1           = 0x0b, | ||||
|   TAS3001C_REG_LEFT_BIQUAD2           = 0x0c, | ||||
|   TAS3001C_REG_LEFT_BIQUAD3           = 0x0d, | ||||
|   TAS3001C_REG_LEFT_BIQUAD4           = 0x0e, | ||||
|   TAS3001C_REG_LEFT_BIQUAD5           = 0x0f, | ||||
|   TAS3001C_REG_LEFT_BIQUAD6           = 0x10, | ||||
|    | ||||
|   TAS3001C_REG_RIGHT_BIQUAD0          = 0x13, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD1          = 0x14, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD2          = 0x15, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD3          = 0x16, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD4          = 0x17, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD5          = 0x18, | ||||
|   TAS3001C_REG_RIGHT_BIQUAD6          = 0x19, | ||||
| 
 | ||||
|   TAS3001C_REG_MAX                    = 0x20 | ||||
| }; | ||||
| 
 | ||||
| #endif /* _TAS3001C_H_ */ | ||||
| @ -1,375 +0,0 @@ | ||||
| #include "tas_common.h" | ||||
| #include "tas_eq_prefs.h" | ||||
| 
 | ||||
| static struct tas_drce_t eqp_0e_2_1_drce = { | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -15.33  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_0e_2_1_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_0e_2_1 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x0e, | ||||
|   .output_id     = TAS_OUTPUT_EXTERNAL_SPKR, | ||||
|   .speaker_id    = 0x01, | ||||
| 
 | ||||
|   .drce          = &eqp_0e_2_1_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_0e_2_1_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_10_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -12.46  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_10_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_10_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x10, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_10_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_10_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_15_2_1_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -15.33  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_15_2_1_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_15_2_1 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x15, | ||||
|   .output_id     = TAS_OUTPUT_EXTERNAL_SPKR, | ||||
|   .speaker_id    = 0x01, | ||||
| 
 | ||||
|   .drce          = &eqp_15_2_1_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_15_2_1_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_15_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = 0.0     * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_15_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_15_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x15, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_15_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_15_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_0f_2_1_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -15.33  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_0f_2_1_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_0f_2_1 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x0f, | ||||
|   .output_id     = TAS_OUTPUT_EXTERNAL_SPKR, | ||||
|   .speaker_id    = 0x01, | ||||
| 
 | ||||
|   .drce          = &eqp_0f_2_1_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_0f_2_1_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_0f_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -15.33  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_0f_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } }, | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_0f_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x0f, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_0f_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 12, | ||||
|   .biquads       = eqp_0f_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static uint tas3001c_master_tab[]={ | ||||
| 	       0x0,       0x75,       0x9c,       0xbb, | ||||
| 	      0xdb,       0xfb,      0x11e,      0x143, | ||||
| 	     0x16b,      0x196,      0x1c3,      0x1f5, | ||||
| 	     0x229,      0x263,      0x29f,      0x2e1, | ||||
| 	     0x328,      0x373,      0x3c5,      0x41b, | ||||
| 	     0x478,      0x4dc,      0x547,      0x5b8, | ||||
| 	     0x633,      0x6b5,      0x740,      0x7d5, | ||||
| 	     0x873,      0x91c,      0x9d2,      0xa92, | ||||
| 	     0xb5e,      0xc39,      0xd22,      0xe19, | ||||
| 	     0xf20,     0x1037,     0x1161,     0x129e, | ||||
| 	    0x13ed,     0x1551,     0x16ca,     0x185d, | ||||
| 	    0x1a08,     0x1bcc,     0x1dac,     0x1fa7, | ||||
| 	    0x21c1,     0x23fa,     0x2655,     0x28d6, | ||||
| 	    0x2b7c,     0x2e4a,     0x3141,     0x3464, | ||||
| 	    0x37b4,     0x3b35,     0x3ee9,     0x42d3, | ||||
| 	    0x46f6,     0x4b53,     0x4ff0,     0x54ce, | ||||
| 	    0x59f2,     0x5f5f,     0x6519,     0x6b24, | ||||
| 	    0x7183,     0x783c,     0x7f53,     0x86cc, | ||||
| 	    0x8ead,     0x96fa,     0x9fba,     0xa8f2, | ||||
| 	    0xb2a7,     0xbce1,     0xc7a5,     0xd2fa, | ||||
| 	    0xdee8,     0xeb75,     0xf8aa,    0x1068e, | ||||
| 	   0x1152a,    0x12487,    0x134ad,    0x145a5, | ||||
| 	   0x1577b,    0x16a37,    0x17df5,    0x192bd, | ||||
| 	   0x1a890,    0x1bf7b,    0x1d78d,    0x1f0d1, | ||||
| 	   0x20b55,    0x22727,    0x24456,    0x262f2, | ||||
| 	   0x2830b | ||||
| }; | ||||
| 
 | ||||
| static uint tas3001c_mixer_tab[]={ | ||||
| 	       0x0,      0x748,      0x9be,      0xbaf, | ||||
| 	     0xda4,      0xfb1,     0x11de,     0x1431, | ||||
| 	    0x16ad,     0x1959,     0x1c37,     0x1f4b, | ||||
| 	    0x2298,     0x2628,     0x29fb,     0x2e12, | ||||
| 	    0x327d,     0x3734,     0x3c47,     0x41b4, | ||||
| 	    0x4787,     0x4dbe,     0x546d,     0x5b86, | ||||
| 	    0x632e,     0x6b52,     0x7400,     0x7d54, | ||||
| 	    0x873b,     0x91c6,     0x9d1a,     0xa920, | ||||
| 	    0xb5e5,     0xc38c,     0xd21b,     0xe18f, | ||||
| 	    0xf1f5,    0x1036a,    0x1160f,    0x129d6, | ||||
| 	   0x13ed0,    0x1550c,    0x16ca0,    0x185c9, | ||||
| 	   0x1a07b,    0x1bcc3,    0x1dab9,    0x1fa75, | ||||
| 	   0x21c0f,    0x23fa3,    0x26552,    0x28d64, | ||||
| 	   0x2b7c9,    0x2e4a2,    0x31411,    0x3463b, | ||||
| 	   0x37b44,    0x3b353,    0x3ee94,    0x42d30, | ||||
| 	   0x46f55,    0x4b533,    0x4fefc,    0x54ce5, | ||||
| 	   0x59f25,    0x5f5f6,    0x65193,    0x6b23c, | ||||
| 	   0x71835,    0x783c3,    0x7f52c,    0x86cc0, | ||||
| 	   0x8eacc,    0x96fa5,    0x9fba0,    0xa8f1a, | ||||
| 	   0xb2a71,    0xbce0a,    0xc7a4a,    0xd2fa0, | ||||
| 	   0xdee7b,    0xeb752,    0xf8a9f,   0x1068e4, | ||||
| 	  0x1152a3,   0x12486a,   0x134ac8,   0x145a55, | ||||
| 	  0x1577ac,   0x16a370,   0x17df51,   0x192bc2, | ||||
| 	  0x1a88f8,   0x1bf7b7,   0x1d78c9,   0x1f0d04, | ||||
| 	  0x20b542,   0x227268,   0x244564,   0x262f26, | ||||
| 	  0x2830af | ||||
| }; | ||||
| 
 | ||||
| static uint tas3001c_treble_tab[]={ | ||||
| 	      0x96,       0x95,       0x95,       0x94, | ||||
| 	      0x93,       0x92,       0x92,       0x91, | ||||
| 	      0x90,       0x90,       0x8f,       0x8e, | ||||
| 	      0x8d,       0x8d,       0x8c,       0x8b, | ||||
| 	      0x8a,       0x8a,       0x89,       0x88, | ||||
| 	      0x88,       0x87,       0x86,       0x85, | ||||
| 	      0x85,       0x84,       0x83,       0x83, | ||||
| 	      0x82,       0x81,       0x80,       0x80, | ||||
| 	      0x7f,       0x7e,       0x7e,       0x7d, | ||||
| 	      0x7c,       0x7b,       0x7b,       0x7a, | ||||
| 	      0x79,       0x78,       0x78,       0x77, | ||||
| 	      0x76,       0x76,       0x75,       0x74, | ||||
| 	      0x73,       0x73,       0x72,       0x71, | ||||
| 	      0x71,       0x70,       0x6e,       0x6d, | ||||
| 	      0x6d,       0x6c,       0x6b,       0x6a, | ||||
| 	      0x69,       0x68,       0x67,       0x66, | ||||
| 	      0x65,       0x63,       0x62,       0x62, | ||||
| 	      0x60,       0x5f,       0x5d,       0x5c, | ||||
| 	      0x5a,       0x58,       0x56,       0x55, | ||||
| 	      0x53,       0x51,       0x4f,       0x4c, | ||||
| 	      0x4a,       0x48,       0x45,       0x43, | ||||
| 	      0x40,       0x3d,       0x3a,       0x37, | ||||
| 	      0x35,       0x32,       0x2e,       0x2a, | ||||
| 	      0x27,       0x22,       0x1e,       0x1a, | ||||
| 	      0x15,       0x11,        0xc,        0x7, | ||||
| 	       0x1 | ||||
| }; | ||||
| 
 | ||||
| static uint tas3001c_bass_tab[]={ | ||||
| 	      0x86,       0x83,       0x81,       0x7f, | ||||
| 	      0x7d,       0x7b,       0x79,       0x78, | ||||
| 	      0x76,       0x75,       0x74,       0x72, | ||||
| 	      0x71,       0x6f,       0x6e,       0x6d, | ||||
| 	      0x6c,       0x6b,       0x69,       0x67, | ||||
| 	      0x65,       0x64,       0x61,       0x60, | ||||
| 	      0x5e,       0x5d,       0x5c,       0x5b, | ||||
| 	      0x5a,       0x59,       0x58,       0x57, | ||||
| 	      0x56,       0x55,       0x55,       0x54, | ||||
| 	      0x53,       0x52,       0x50,       0x4f, | ||||
| 	      0x4d,       0x4c,       0x4b,       0x49, | ||||
| 	      0x47,       0x45,       0x44,       0x42, | ||||
| 	      0x41,       0x3f,       0x3e,       0x3d, | ||||
| 	      0x3c,       0x3b,       0x39,       0x38, | ||||
| 	      0x37,       0x36,       0x35,       0x34, | ||||
| 	      0x33,       0x31,       0x30,       0x2f, | ||||
| 	      0x2e,       0x2c,       0x2b,       0x2b, | ||||
| 	      0x29,       0x28,       0x27,       0x26, | ||||
| 	      0x25,       0x24,       0x22,       0x21, | ||||
| 	      0x20,       0x1e,       0x1c,       0x19, | ||||
| 	      0x18,       0x18,       0x17,       0x16, | ||||
| 	      0x15,       0x14,       0x13,       0x12, | ||||
| 	      0x11,       0x10,        0xf,        0xe, | ||||
| 	       0xd,        0xb,        0xa,        0x9, | ||||
| 	       0x8,        0x6,        0x4,        0x2, | ||||
| 	       0x1 | ||||
| }; | ||||
| 
 | ||||
| struct tas_gain_t tas3001c_gain = { | ||||
|   .master  = tas3001c_master_tab, | ||||
|   .treble  = tas3001c_treble_tab, | ||||
|   .bass    = tas3001c_bass_tab, | ||||
|   .mixer   = tas3001c_mixer_tab | ||||
| }; | ||||
| 
 | ||||
| struct tas_eq_pref_t *tas3001c_eq_prefs[]={ | ||||
|   &eqp_0e_2_1, | ||||
|   &eqp_10_1_0, | ||||
|   &eqp_15_2_1, | ||||
|   &eqp_15_1_0, | ||||
|   &eqp_0f_2_1, | ||||
|   &eqp_0f_1_0, | ||||
|   NULL | ||||
| }; | ||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @ -1,77 +0,0 @@ | ||||
| /*
 | ||||
|  * Header file for the i2c/i2s based TA3004 sound chip used | ||||
|  * on some Apple hardware. Also known as "tumbler". | ||||
|  * | ||||
|  *  This file is subject to the terms and conditions of the GNU General Public | ||||
|  *  License.  See the file COPYING in the main directory of this archive | ||||
|  *  for more details. | ||||
|  * | ||||
|  * Written by Christopher C. Chimelis <chris@debian.org> | ||||
|  */ | ||||
| 
 | ||||
| #ifndef _TAS3004_H_ | ||||
| #define _TAS3004_H_ | ||||
| 
 | ||||
| #include <linux/types.h> | ||||
| 
 | ||||
| #include "tas_common.h" | ||||
| #include "tas_eq_prefs.h" | ||||
| 
 | ||||
| /*
 | ||||
|  * Macros that correspond to the registers that we write to | ||||
|  * when setting the various values. | ||||
|  */ | ||||
| 
 | ||||
| #define TAS3004_VERSION	        "0.3" | ||||
| #define TAS3004_DATE	        "20011214" | ||||
| 
 | ||||
| #define I2C_DRIVERNAME_TAS3004 "TAS3004 driver V " TAS3004_VERSION | ||||
| #define I2C_DRIVERID_TAS3004    (I2C_DRIVERID_TAS_BASE+1) | ||||
| 
 | ||||
| extern  struct tas_driver_hooks_t tas3004_hooks; | ||||
| extern struct tas_gain_t tas3004_gain; | ||||
| extern struct tas_eq_pref_t *tas3004_eq_prefs[]; | ||||
| 
 | ||||
| enum tas3004_reg_t { | ||||
|   TAS3004_REG_MCR                    = 0x01, | ||||
|   TAS3004_REG_DRC                    = 0x02, | ||||
| 
 | ||||
|   TAS3004_REG_VOLUME                 = 0x04, | ||||
|   TAS3004_REG_TREBLE                 = 0x05, | ||||
|   TAS3004_REG_BASS                   = 0x06, | ||||
|   TAS3004_REG_LEFT_MIXER             = 0x07, | ||||
|   TAS3004_REG_RIGHT_MIXER            = 0x08, | ||||
| 
 | ||||
|   TAS3004_REG_LEFT_BIQUAD0           = 0x0a, | ||||
|   TAS3004_REG_LEFT_BIQUAD1           = 0x0b, | ||||
|   TAS3004_REG_LEFT_BIQUAD2           = 0x0c, | ||||
|   TAS3004_REG_LEFT_BIQUAD3           = 0x0d, | ||||
|   TAS3004_REG_LEFT_BIQUAD4           = 0x0e, | ||||
|   TAS3004_REG_LEFT_BIQUAD5           = 0x0f, | ||||
|   TAS3004_REG_LEFT_BIQUAD6           = 0x10, | ||||
|    | ||||
|   TAS3004_REG_RIGHT_BIQUAD0          = 0x13, | ||||
|   TAS3004_REG_RIGHT_BIQUAD1          = 0x14, | ||||
|   TAS3004_REG_RIGHT_BIQUAD2          = 0x15, | ||||
|   TAS3004_REG_RIGHT_BIQUAD3          = 0x16, | ||||
|   TAS3004_REG_RIGHT_BIQUAD4          = 0x17, | ||||
|   TAS3004_REG_RIGHT_BIQUAD5          = 0x18, | ||||
|   TAS3004_REG_RIGHT_BIQUAD6          = 0x19, | ||||
| 
 | ||||
|   TAS3004_REG_LEFT_LOUD_BIQUAD       = 0x21, | ||||
|   TAS3004_REG_RIGHT_LOUD_BIQUAD      = 0x22, | ||||
| 
 | ||||
|   TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN  = 0x23, | ||||
|   TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN = 0x24, | ||||
| 
 | ||||
|   TAS3004_REG_TEST                   = 0x29, | ||||
| 
 | ||||
|   TAS3004_REG_ANALOG_CTRL            = 0x40, | ||||
|   TAS3004_REG_TEST1                  = 0x41, | ||||
|   TAS3004_REG_TEST2                  = 0x42, | ||||
|   TAS3004_REG_MCR2                   = 0x43, | ||||
| 
 | ||||
|   TAS3004_REG_MAX                    = 0x44 | ||||
| }; | ||||
| 
 | ||||
| #endif /* _TAS3004_H_ */ | ||||
| @ -1,301 +0,0 @@ | ||||
| #include "tas3004.h" | ||||
| #include "tas_eq_prefs.h" | ||||
| 
 | ||||
| static struct tas_drce_t eqp_17_1_0_drce={ | ||||
|     .enable     = 1, | ||||
|     .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|     .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|     .threshold  = -19.12  * (1<<8), | ||||
|     .energy     = 2.4     * (1<<12), | ||||
|     .attack     = 0.013   * (1<<12), | ||||
|     .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_17_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, | ||||
|   { .channel = 0, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } }, | ||||
|   { .channel = 1, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } } | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_17_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x17, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_17_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 14, | ||||
|   .biquads       = eqp_17_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_18_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -13.14  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_18_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, | ||||
|   { .channel = 0, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } }, | ||||
|   { .channel = 1, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } } | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_18_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x18, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_18_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 14, | ||||
|   .biquads       = eqp_18_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_1a_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -10.75  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_1a_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, | ||||
|   { .channel = 0, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } }, | ||||
|   { .channel = 1, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } } | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_1a_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x1a, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_1a_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 14, | ||||
|   .biquads       = eqp_1a_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static struct tas_drce_t eqp_1c_1_0_drce={ | ||||
|   .enable     = 1, | ||||
|   .above      = { .val = 3.0 * (1<<8), .expand = 0 }, | ||||
|   .below      = { .val = 1.0 * (1<<8), .expand = 0 }, | ||||
|   .threshold  = -14.34  * (1<<8), | ||||
|   .energy     = 2.4     * (1<<12), | ||||
|   .attack     = 0.013   * (1<<12), | ||||
|   .decay      = 0.212   * (1<<12), | ||||
| }; | ||||
| 
 | ||||
| static struct tas_biquad_ctrl_t eqp_1c_1_0_biquads[]={ | ||||
|   { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, | ||||
|   { .channel = 0, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, | ||||
|   { .channel = 0, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, | ||||
|   { .channel = 0, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, | ||||
|   { .channel = 0, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, | ||||
|   { .channel = 0, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, | ||||
|   { .channel = 0, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } }, | ||||
| 
 | ||||
|   { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } }, | ||||
|   { .channel = 1, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } }, | ||||
|   { .channel = 1, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } }, | ||||
|   { .channel = 1, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } }, | ||||
|   { .channel = 1, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } }, | ||||
|   { .channel = 1, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } }, | ||||
|   { .channel = 1, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } } | ||||
| }; | ||||
| 
 | ||||
| static struct tas_eq_pref_t eqp_1c_1_0 = { | ||||
|   .sample_rate   = 44100, | ||||
|   .device_id     = 0x1c, | ||||
|   .output_id     = TAS_OUTPUT_INTERNAL_SPKR, | ||||
|   .speaker_id    = 0x00, | ||||
| 
 | ||||
|   .drce          = &eqp_1c_1_0_drce, | ||||
| 
 | ||||
|   .filter_count  = 14, | ||||
|   .biquads       = eqp_1c_1_0_biquads | ||||
| }; | ||||
| 
 | ||||
| /* ======================================================================== */ | ||||
| 
 | ||||
| static uint tas3004_master_tab[]={ | ||||
| 	       0x0,       0x75,       0x9c,       0xbb, | ||||
| 	      0xdb,       0xfb,      0x11e,      0x143, | ||||
| 	     0x16b,      0x196,      0x1c3,      0x1f5, | ||||
| 	     0x229,      0x263,      0x29f,      0x2e1, | ||||
| 	     0x328,      0x373,      0x3c5,      0x41b, | ||||
| 	     0x478,      0x4dc,      0x547,      0x5b8, | ||||
| 	     0x633,      0x6b5,      0x740,      0x7d5, | ||||
| 	     0x873,      0x91c,      0x9d2,      0xa92, | ||||
| 	     0xb5e,      0xc39,      0xd22,      0xe19, | ||||
| 	     0xf20,     0x1037,     0x1161,     0x129e, | ||||
| 	    0x13ed,     0x1551,     0x16ca,     0x185d, | ||||
| 	    0x1a08,     0x1bcc,     0x1dac,     0x1fa7, | ||||
| 	    0x21c1,     0x23fa,     0x2655,     0x28d6, | ||||
| 	    0x2b7c,     0x2e4a,     0x3141,     0x3464, | ||||
| 	    0x37b4,     0x3b35,     0x3ee9,     0x42d3, | ||||
| 	    0x46f6,     0x4b53,     0x4ff0,     0x54ce, | ||||
| 	    0x59f2,     0x5f5f,     0x6519,     0x6b24, | ||||
| 	    0x7183,     0x783c,     0x7f53,     0x86cc, | ||||
| 	    0x8ead,     0x96fa,     0x9fba,     0xa8f2, | ||||
| 	    0xb2a7,     0xbce1,     0xc7a5,     0xd2fa, | ||||
| 	    0xdee8,     0xeb75,     0xf8aa,    0x1068e, | ||||
| 	   0x1152a,    0x12487,    0x134ad,    0x145a5, | ||||
| 	   0x1577b,    0x16a37,    0x17df5,    0x192bd, | ||||
| 	   0x1a890,    0x1bf7b,    0x1d78d,    0x1f0d1, | ||||
| 	   0x20b55,    0x22727,    0x24456,    0x262f2, | ||||
| 	   0x2830b | ||||
| }; | ||||
| 
 | ||||
| static uint tas3004_mixer_tab[]={ | ||||
| 	       0x0,      0x748,      0x9be,      0xbaf, | ||||
| 	     0xda4,      0xfb1,     0x11de,     0x1431, | ||||
| 	    0x16ad,     0x1959,     0x1c37,     0x1f4b, | ||||
| 	    0x2298,     0x2628,     0x29fb,     0x2e12, | ||||
| 	    0x327d,     0x3734,     0x3c47,     0x41b4, | ||||
| 	    0x4787,     0x4dbe,     0x546d,     0x5b86, | ||||
| 	    0x632e,     0x6b52,     0x7400,     0x7d54, | ||||
| 	    0x873b,     0x91c6,     0x9d1a,     0xa920, | ||||
| 	    0xb5e5,     0xc38c,     0xd21b,     0xe18f, | ||||
| 	    0xf1f5,    0x1036a,    0x1160f,    0x129d6, | ||||
| 	   0x13ed0,    0x1550c,    0x16ca0,    0x185c9, | ||||
| 	   0x1a07b,    0x1bcc3,    0x1dab9,    0x1fa75, | ||||
| 	   0x21c0f,    0x23fa3,    0x26552,    0x28d64, | ||||
| 	   0x2b7c9,    0x2e4a2,    0x31411,    0x3463b, | ||||
| 	   0x37b44,    0x3b353,    0x3ee94,    0x42d30, | ||||
| 	   0x46f55,    0x4b533,    0x4fefc,    0x54ce5, | ||||
| 	   0x59f25,    0x5f5f6,    0x65193,    0x6b23c, | ||||
| 	   0x71835,    0x783c3,    0x7f52c,    0x86cc0, | ||||
| 	   0x8eacc,    0x96fa5,    0x9fba0,    0xa8f1a, | ||||
| 	   0xb2a71,    0xbce0a,    0xc7a4a,    0xd2fa0, | ||||
| 	   0xdee7b,    0xeb752,    0xf8a9f,   0x1068e4, | ||||
| 	  0x1152a3,   0x12486a,   0x134ac8,   0x145a55, | ||||
| 	  0x1577ac,   0x16a370,   0x17df51,   0x192bc2, | ||||
| 	  0x1a88f8,   0x1bf7b7,   0x1d78c9,   0x1f0d04, | ||||
| 	  0x20b542,   0x227268,   0x244564,   0x262f26, | ||||
| 	  0x2830af | ||||
| }; | ||||
| 
 | ||||
| static uint tas3004_treble_tab[]={ | ||||
| 	      0x96,       0x95,       0x95,       0x94, | ||||
| 	      0x93,       0x92,       0x92,       0x91, | ||||
| 	      0x90,       0x90,       0x8f,       0x8e, | ||||
| 	      0x8d,       0x8d,       0x8c,       0x8b, | ||||
| 	      0x8a,       0x8a,       0x89,       0x88, | ||||
| 	      0x88,       0x87,       0x86,       0x85, | ||||
| 	      0x85,       0x84,       0x83,       0x83, | ||||
| 	      0x82,       0x81,       0x80,       0x80, | ||||
| 	      0x7f,       0x7e,       0x7e,       0x7d, | ||||
| 	      0x7c,       0x7b,       0x7b,       0x7a, | ||||
| 	      0x79,       0x78,       0x78,       0x77, | ||||
| 	      0x76,       0x76,       0x75,       0x74, | ||||
| 	      0x73,       0x73,       0x72,       0x71, | ||||
| 	      0x71,       0x68,       0x45,       0x5b, | ||||
| 	      0x6d,       0x6c,       0x6b,       0x6a, | ||||
| 	      0x69,       0x68,       0x67,       0x66, | ||||
| 	      0x65,       0x63,       0x62,       0x62, | ||||
| 	      0x60,       0x5e,       0x5c,       0x5b, | ||||
| 	      0x59,       0x57,       0x55,       0x53, | ||||
| 	      0x52,       0x4f,       0x4d,       0x4a, | ||||
| 	      0x48,       0x46,       0x43,       0x40, | ||||
| 	      0x3d,       0x3a,       0x36,       0x33, | ||||
| 	      0x2f,       0x2c,       0x27,       0x23, | ||||
| 	      0x1f,       0x1a,       0x15,        0xf, | ||||
| 	       0x8,        0x5,        0x2,        0x1, | ||||
| 	       0x1 | ||||
| }; | ||||
| 
 | ||||
| static uint tas3004_bass_tab[]={ | ||||
| 	      0x96,       0x95,       0x95,       0x94, | ||||
| 	      0x93,       0x92,       0x92,       0x91, | ||||
| 	      0x90,       0x90,       0x8f,       0x8e, | ||||
| 	      0x8d,       0x8d,       0x8c,       0x8b, | ||||
| 	      0x8a,       0x8a,       0x89,       0x88, | ||||
| 	      0x88,       0x87,       0x86,       0x85, | ||||
| 	      0x85,       0x84,       0x83,       0x83, | ||||
| 	      0x82,       0x81,       0x80,       0x80, | ||||
| 	      0x7f,       0x7e,       0x7e,       0x7d, | ||||
| 	      0x7c,       0x7b,       0x7b,       0x7a, | ||||
| 	      0x79,       0x78,       0x78,       0x77, | ||||
| 	      0x76,       0x76,       0x75,       0x74, | ||||
| 	      0x73,       0x73,       0x72,       0x71, | ||||
| 	      0x70,       0x6f,       0x6e,       0x6d, | ||||
| 	      0x6c,       0x6b,       0x6a,       0x6a, | ||||
| 	      0x69,       0x67,       0x66,       0x66, | ||||
| 	      0x65,       0x63,       0x62,       0x62, | ||||
| 	      0x61,       0x60,       0x5e,       0x5d, | ||||
| 	      0x5b,       0x59,       0x57,       0x55, | ||||
| 	      0x53,       0x51,       0x4f,       0x4c, | ||||
| 	      0x4a,       0x48,       0x46,       0x44, | ||||
| 	      0x41,       0x3e,       0x3b,       0x38, | ||||
| 	      0x36,       0x33,       0x2f,       0x2b, | ||||
| 	      0x28,       0x24,       0x20,       0x1c, | ||||
| 	      0x17,       0x12,        0xd,        0x7, | ||||
| 	       0x1 | ||||
| }; | ||||
| 
 | ||||
| struct tas_gain_t tas3004_gain={ | ||||
|   .master  = tas3004_master_tab, | ||||
|   .treble  = tas3004_treble_tab, | ||||
|   .bass    = tas3004_bass_tab, | ||||
|   .mixer   = tas3004_mixer_tab | ||||
| }; | ||||
| 
 | ||||
| struct tas_eq_pref_t *tas3004_eq_prefs[]={ | ||||
|   &eqp_17_1_0, | ||||
|   &eqp_18_1_0, | ||||
|   &eqp_1a_1_0, | ||||
|   &eqp_1c_1_0, | ||||
|   NULL | ||||
| }; | ||||
| @ -1,214 +0,0 @@ | ||||
| #include <linux/module.h> | ||||
| #include <linux/slab.h> | ||||
| #include <linux/proc_fs.h> | ||||
| #include <linux/ioport.h> | ||||
| #include <linux/sysctl.h> | ||||
| #include <linux/types.h> | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/init.h> | ||||
| #include <linux/soundcard.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include <asm/errno.h> | ||||
| #include <asm/io.h> | ||||
| #include <asm/prom.h> | ||||
| 
 | ||||
| #include "tas_common.h" | ||||
| 
 | ||||
| #define CALL0(proc)								\ | ||||
| 	do {									\ | ||||
| 		struct tas_data_t *self;					\ | ||||
| 		if (!tas_client || driver_hooks == NULL)			\ | ||||
| 			return -1;						\ | ||||
| 		self = dev_get_drvdata(&tas_client->dev);			\ | ||||
| 		if (driver_hooks->proc)						\ | ||||
| 			return driver_hooks->proc(self);			\ | ||||
| 		else								\ | ||||
| 			return -EINVAL;						\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define CALL(proc,arg...)							\ | ||||
| 	do {									\ | ||||
| 		struct tas_data_t *self;					\ | ||||
| 		if (!tas_client || driver_hooks == NULL)			\ | ||||
| 			return -1;						\ | ||||
| 		self = dev_get_drvdata(&tas_client->dev);			\ | ||||
| 		if (driver_hooks->proc)						\ | ||||
| 			return driver_hooks->proc(self, ## arg);		\ | ||||
| 		else								\ | ||||
| 			return -EINVAL;						\ | ||||
| 	} while (0) | ||||
| 
 | ||||
| 
 | ||||
| static u8 tas_i2c_address = 0x34; | ||||
| static struct i2c_client *tas_client; | ||||
| 
 | ||||
| static int tas_attach_adapter(struct i2c_adapter *); | ||||
| static int tas_detach_client(struct i2c_client *); | ||||
| 
 | ||||
| struct i2c_driver tas_driver = { | ||||
| 	.driver = { | ||||
| 		.name	= "tas", | ||||
| 	}, | ||||
| 	.attach_adapter	= tas_attach_adapter, | ||||
| 	.detach_client	= tas_detach_client, | ||||
| }; | ||||
| 
 | ||||
| struct tas_driver_hooks_t *driver_hooks; | ||||
| 
 | ||||
| int | ||||
| tas_register_driver(struct tas_driver_hooks_t *hooks) | ||||
| { | ||||
| 	driver_hooks = hooks; | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_get_mixer_level(int mixer, uint *level) | ||||
| { | ||||
| 	CALL(get_mixer_level,mixer,level); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_set_mixer_level(int mixer,uint level) | ||||
| { | ||||
| 	CALL(set_mixer_level,mixer,level); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_enter_sleep(void) | ||||
| { | ||||
| 	CALL0(enter_sleep); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_leave_sleep(void) | ||||
| { | ||||
| 	CALL0(leave_sleep); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_supported_mixers(void) | ||||
| { | ||||
| 	CALL0(supported_mixers); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_mixer_is_stereo(int mixer) | ||||
| { | ||||
| 	CALL(mixer_is_stereo,mixer); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_stereo_mixers(void) | ||||
| { | ||||
| 	CALL0(stereo_mixers); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_output_device_change(int device_id,int layout_id,int speaker_id) | ||||
| { | ||||
| 	CALL(output_device_change,device_id,layout_id,speaker_id); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_device_ioctl(u_int cmd, u_long arg) | ||||
| { | ||||
| 	CALL(device_ioctl,cmd,arg); | ||||
| } | ||||
| 
 | ||||
| int | ||||
| tas_post_init(void) | ||||
| { | ||||
| 	CALL0(post_init); | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas_detect_client(struct i2c_adapter *adapter, int address) | ||||
| { | ||||
| 	static const char *client_name = "tas Digital Equalizer"; | ||||
| 	struct i2c_client *new_client; | ||||
| 	int rc = -ENODEV; | ||||
| 
 | ||||
| 	if (!driver_hooks) { | ||||
| 		printk(KERN_ERR "tas_detect_client called with no hooks !\n"); | ||||
| 		return -ENODEV; | ||||
| 	} | ||||
| 	 | ||||
| 	new_client = kzalloc(sizeof(*new_client), GFP_KERNEL); | ||||
| 	if (!new_client) | ||||
| 		return -ENOMEM; | ||||
| 
 | ||||
| 	new_client->addr = address; | ||||
| 	new_client->adapter = adapter; | ||||
| 	new_client->driver = &tas_driver; | ||||
| 	strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE); | ||||
| 
 | ||||
|         if (driver_hooks->init(new_client)) | ||||
| 		goto bail; | ||||
| 
 | ||||
| 	/* Tell the i2c layer a new client has arrived */ | ||||
| 	if (i2c_attach_client(new_client)) { | ||||
| 		driver_hooks->uninit(dev_get_drvdata(&new_client->dev)); | ||||
| 		goto bail; | ||||
| 	} | ||||
| 
 | ||||
| 	tas_client = new_client; | ||||
| 	return 0; | ||||
|  bail: | ||||
| 	tas_client = NULL; | ||||
| 	kfree(new_client); | ||||
| 	return rc; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas_attach_adapter(struct i2c_adapter *adapter) | ||||
| { | ||||
| 	if (!strncmp(adapter->name, "mac-io", 6)) | ||||
| 		return tas_detect_client(adapter, tas_i2c_address); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static int | ||||
| tas_detach_client(struct i2c_client *client) | ||||
| { | ||||
| 	if (client == tas_client) { | ||||
| 		driver_hooks->uninit(dev_get_drvdata(&client->dev)); | ||||
| 
 | ||||
| 		i2c_detach_client(client); | ||||
| 		kfree(client); | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| void | ||||
| tas_cleanup(void) | ||||
| { | ||||
| 	i2c_del_driver(&tas_driver); | ||||
| } | ||||
| 
 | ||||
| int __init | ||||
| tas_init(int driver_id, const char *driver_name) | ||||
| { | ||||
| 	const u32* paddr; | ||||
| 	struct device_node *tas_node; | ||||
| 
 | ||||
| 	printk(KERN_INFO "tas driver [%s])\n", driver_name); | ||||
| 
 | ||||
| #ifndef CONFIG_I2C_POWERMAC | ||||
| 	request_module("i2c-powermac"); | ||||
| #endif | ||||
| 	tas_node = of_find_node_by_name("deq"); | ||||
| 	if (tas_node == NULL) | ||||
| 		return -ENODEV; | ||||
| 	paddr = of_get_property(tas_node, "i2c-address", NULL); | ||||
| 	if (paddr) { | ||||
| 		tas_i2c_address = (*paddr) >> 1; | ||||
| 		printk(KERN_INFO "using i2c address: 0x%x from device-tree\n", | ||||
| 				tas_i2c_address); | ||||
| 	} else     | ||||
| 		printk(KERN_INFO "using i2c address: 0x%x (default)\n", | ||||
| 				tas_i2c_address); | ||||
| 	of_node_put(tas_node); | ||||
| 
 | ||||
| 	return i2c_add_driver(&tas_driver); | ||||
| } | ||||
| @ -1,284 +0,0 @@ | ||||
| #ifndef _TAS_COMMON_H_ | ||||
| #define _TAS_COMMON_H_ | ||||
| 
 | ||||
| #include <linux/i2c.h> | ||||
| #include <linux/soundcard.h> | ||||
| #include <asm/string.h> | ||||
| 
 | ||||
| #define I2C_DRIVERID_TAS_BASE   (0xFEBA) | ||||
| 
 | ||||
| #define SET_4_20(shadow, offset, val)                        \ | ||||
| 	do {                                                 \ | ||||
| 		(shadow)[(offset)+0] = ((val) >> 16) & 0xff; \ | ||||
| 		(shadow)[(offset)+1] = ((val) >> 8)  & 0xff; \ | ||||
| 		(shadow)[(offset)+2] = ((val) >> 0)  & 0xff; \ | ||||
| 	} while (0) | ||||
| 
 | ||||
| #define GET_4_20(shadow, offset)                             \ | ||||
| 	(((u_int)((shadow)[(offset)+0]) << 16) |             \ | ||||
| 	 ((u_int)((shadow)[(offset)+1]) <<  8) |             \ | ||||
| 	 ((u_int)((shadow)[(offset)+2]) <<  0)) | ||||
| 
 | ||||
| 
 | ||||
| #define TAS_BIQUAD_FAST_LOAD 0x01 | ||||
| 
 | ||||
| #define TAS_DRCE_ENABLE           0x01 | ||||
| #define TAS_DRCE_ABOVE_RATIO      0x02 | ||||
| #define TAS_DRCE_BELOW_RATIO      0x04 | ||||
| #define TAS_DRCE_THRESHOLD        0x08 | ||||
| #define TAS_DRCE_ENERGY           0x10 | ||||
| #define TAS_DRCE_ATTACK           0x20 | ||||
| #define TAS_DRCE_DECAY            0x40 | ||||
| 
 | ||||
| #define TAS_DRCE_ALL              0x7f | ||||
| 
 | ||||
| 
 | ||||
| #define TAS_OUTPUT_HEADPHONES     0x00 | ||||
| #define TAS_OUTPUT_INTERNAL_SPKR  0x01 | ||||
| #define TAS_OUTPUT_EXTERNAL_SPKR  0x02 | ||||
| 
 | ||||
| 
 | ||||
| union tas_biquad_t { | ||||
| 	struct { | ||||
| 		int b0,b1,b2,a1,a2; | ||||
| 	} coeff; | ||||
| 	int buf[5]; | ||||
| }; | ||||
| 
 | ||||
| struct tas_biquad_ctrl_t { | ||||
| 	u_int channel:4; | ||||
| 	u_int filter:4; | ||||
| 
 | ||||
| 	union tas_biquad_t data; | ||||
| }; | ||||
| 
 | ||||
| struct tas_biquad_ctrl_list_t { | ||||
| 	int flags; | ||||
| 	int filter_count; | ||||
| 	struct tas_biquad_ctrl_t biquads[0]; | ||||
| }; | ||||
| 
 | ||||
| struct tas_ratio_t { | ||||
| 	unsigned short val;    /* 8.8                        */ | ||||
| 	unsigned short expand; /* 0 = compress, !0 = expand. */ | ||||
| }; | ||||
| 
 | ||||
| struct tas_drce_t { | ||||
| 	unsigned short enable; | ||||
| 	struct tas_ratio_t above; | ||||
| 	struct tas_ratio_t below; | ||||
| 	short threshold;       /* dB,       8.8 signed    */ | ||||
| 	unsigned short energy; /* seconds,  4.12 unsigned */ | ||||
| 	unsigned short attack; /* seconds,  4.12 unsigned */ | ||||
| 	unsigned short decay;  /* seconds,  4.12 unsigned */ | ||||
| }; | ||||
| 
 | ||||
| struct tas_drce_ctrl_t { | ||||
| 	uint flags; | ||||
| 
 | ||||
| 	struct tas_drce_t data; | ||||
| }; | ||||
| 
 | ||||
| struct tas_gain_t | ||||
| { | ||||
|   unsigned int *master; | ||||
|   unsigned int *treble; | ||||
|   unsigned int *bass; | ||||
|   unsigned int *mixer; | ||||
| }; | ||||
| 
 | ||||
| typedef char tas_shadow_t[0x45]; | ||||
| 
 | ||||
| struct tas_data_t | ||||
| { | ||||
| 	struct i2c_client *client; | ||||
| 	tas_shadow_t *shadow; | ||||
| 	uint mixer[SOUND_MIXER_NRDEVICES]; | ||||
| }; | ||||
| 
 | ||||
| typedef int (*tas_hook_init_t)(struct i2c_client *); | ||||
| typedef int (*tas_hook_post_init_t)(struct tas_data_t *); | ||||
| typedef void (*tas_hook_uninit_t)(struct tas_data_t *); | ||||
| 
 | ||||
| typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *); | ||||
| typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint); | ||||
| 
 | ||||
| typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *); | ||||
| typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *); | ||||
| 
 | ||||
| typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *); | ||||
| typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int); | ||||
| typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *); | ||||
| 
 | ||||
| typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int); | ||||
| typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long); | ||||
| 
 | ||||
| struct tas_driver_hooks_t { | ||||
| 	/*
 | ||||
| 	 * All hardware initialisation must be performed in | ||||
| 	 * post_init(), as tas_dmasound_init() does a hardware reset. | ||||
| 	 * | ||||
| 	 * init() is called before tas_dmasound_init() so that | ||||
| 	 * ouput_device_change() is always called after i2c driver | ||||
| 	 * initialisation. The implication is that | ||||
| 	 * output_device_change() must cope with the fact that it | ||||
| 	 * may be called before post_init(). | ||||
| 	 */ | ||||
| 
 | ||||
| 	tas_hook_init_t                   init; | ||||
| 	tas_hook_post_init_t              post_init; | ||||
| 	tas_hook_uninit_t                 uninit; | ||||
| 
 | ||||
| 	tas_hook_get_mixer_level_t        get_mixer_level; | ||||
| 	tas_hook_set_mixer_level_t        set_mixer_level; | ||||
| 
 | ||||
| 	tas_hook_enter_sleep_t            enter_sleep; | ||||
| 	tas_hook_leave_sleep_t            leave_sleep; | ||||
| 
 | ||||
| 	tas_hook_supported_mixers_t       supported_mixers; | ||||
| 	tas_hook_mixer_is_stereo_t        mixer_is_stereo; | ||||
| 	tas_hook_stereo_mixers_t          stereo_mixers; | ||||
| 
 | ||||
| 	tas_hook_output_device_change_t   output_device_change; | ||||
| 	tas_hook_device_ioctl_t           device_ioctl; | ||||
| }; | ||||
| 
 | ||||
| enum tas_write_mode_t { | ||||
| 	WRITE_HW     = 0x01, | ||||
| 	WRITE_SHADOW = 0x02, | ||||
| 	WRITE_NORMAL = 0x03, | ||||
| 	FORCE_WRITE  = 0x04 | ||||
| }; | ||||
| 
 | ||||
| static inline uint | ||||
| tas_mono_to_stereo(uint mono) | ||||
| { | ||||
| 	mono &=0xff; | ||||
| 	return mono | (mono<<8); | ||||
| } | ||||
| 
 | ||||
| /*
 | ||||
|  * Todo: make these functions a bit more efficient ! | ||||
|  */ | ||||
| static inline int | ||||
| tas_write_register(	struct tas_data_t *self, | ||||
| 			uint reg_num, | ||||
| 			uint reg_width, | ||||
| 			char *data, | ||||
| 			uint write_mode) | ||||
| { | ||||
| 	int rc; | ||||
| 
 | ||||
| 	if (reg_width==0 || data==NULL || self==NULL) | ||||
| 		return -EINVAL; | ||||
| 	if (!(write_mode & FORCE_WRITE) && | ||||
| 	    !memcmp(data,self->shadow[reg_num],reg_width)) | ||||
| 	    	return 0; | ||||
| 
 | ||||
| 	if (write_mode & WRITE_SHADOW) | ||||
| 		memcpy(self->shadow[reg_num],data,reg_width); | ||||
| 	if (write_mode & WRITE_HW) { | ||||
| 		rc=i2c_smbus_write_i2c_block_data(self->client, | ||||
| 						  reg_num, | ||||
| 						  reg_width, | ||||
| 						  data); | ||||
| 		if (rc < 0) { | ||||
| 			printk("tas: I2C block write failed \n");   | ||||
| 			return rc;  | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tas_sync_register(	struct tas_data_t *self, | ||||
| 			uint reg_num, | ||||
| 			uint reg_width) | ||||
| { | ||||
| 	int rc; | ||||
| 
 | ||||
| 	if (reg_width==0 || self==NULL) | ||||
| 		return -EINVAL; | ||||
| 	rc=i2c_smbus_write_i2c_block_data(self->client, | ||||
| 					  reg_num, | ||||
| 					  reg_width, | ||||
| 					  self->shadow[reg_num]); | ||||
| 	if (rc < 0) { | ||||
| 		printk("tas: I2C block write failed \n"); | ||||
| 		return rc; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tas_write_byte_register(	struct tas_data_t *self, | ||||
| 				uint reg_num, | ||||
| 				char data, | ||||
| 				uint write_mode) | ||||
| { | ||||
| 	if (self==NULL) | ||||
| 		return -1; | ||||
| 	if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0]) | ||||
| 		return 0; | ||||
| 	if (write_mode & WRITE_SHADOW) | ||||
| 		self->shadow[reg_num][0]=data; | ||||
| 	if (write_mode & WRITE_HW) { | ||||
| 		if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) { | ||||
| 			printk("tas: I2C byte write failed \n");   | ||||
| 			return -1;  | ||||
| 		} | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tas_sync_byte_register(	struct tas_data_t *self, | ||||
| 			uint reg_num, | ||||
| 			uint reg_width) | ||||
| { | ||||
| 	if (reg_width==0 || self==NULL) | ||||
| 		return -1; | ||||
| 	if (i2c_smbus_write_byte_data( | ||||
| 	    self->client, reg_num, self->shadow[reg_num][0]) < 0) { | ||||
| 		printk("tas: I2C byte write failed \n"); | ||||
| 		return -1; | ||||
| 	} | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| static inline int | ||||
| tas_read_register(	struct tas_data_t *self, | ||||
| 			uint reg_num, | ||||
| 			uint reg_width, | ||||
| 			char *data) | ||||
| { | ||||
| 	if (reg_width==0 || data==NULL || self==NULL) | ||||
| 		return -1; | ||||
| 	memcpy(data,self->shadow[reg_num],reg_width); | ||||
| 	return 0; | ||||
| } | ||||
| 
 | ||||
| extern int tas_register_driver(struct tas_driver_hooks_t *hooks); | ||||
| 
 | ||||
| extern int tas_get_mixer_level(int mixer,uint *level); | ||||
| extern int tas_set_mixer_level(int mixer,uint level); | ||||
| extern int tas_enter_sleep(void); | ||||
| extern int tas_leave_sleep(void); | ||||
| extern int tas_supported_mixers(void); | ||||
| extern int tas_mixer_is_stereo(int mixer); | ||||
| extern int tas_stereo_mixers(void); | ||||
| extern int tas_output_device_change(int,int,int); | ||||
| extern int tas_device_ioctl(u_int, u_long); | ||||
| 
 | ||||
| extern void tas_cleanup(void); | ||||
| extern int tas_init(int driver_id,const char *driver_name); | ||||
| extern int tas_post_init(void); | ||||
| 
 | ||||
| #endif /* _TAS_COMMON_H_ */ | ||||
| /*
 | ||||
|  * Local Variables: | ||||
|  * tab-width: 8 | ||||
|  * indent-tabs-mode: t | ||||
|  * c-basic-offset: 8 | ||||
|  * End: | ||||
|  */ | ||||
| @ -1,24 +0,0 @@ | ||||
| #ifndef _TAS_EQ_PREFS_H_ | ||||
| #define _TAS_EQ_PREFS_H_ | ||||
| 
 | ||||
| struct tas_eq_pref_t { | ||||
| 	u_int sample_rate; | ||||
| 	u_int device_id; | ||||
| 	u_int output_id; | ||||
| 	u_int speaker_id; | ||||
| 
 | ||||
| 	struct tas_drce_t *drce; | ||||
| 
 | ||||
| 	u_int filter_count; | ||||
| 	struct tas_biquad_ctrl_t *biquads; | ||||
| }; | ||||
| 
 | ||||
| #endif /* _TAS_EQ_PREFS_H_ */ | ||||
| 
 | ||||
| /*
 | ||||
|  * Local Variables: | ||||
|  * tab-width: 8 | ||||
|  * indent-tabs-mode: t | ||||
|  * c-basic-offset: 8 | ||||
|  * End: | ||||
|  */ | ||||
| @ -1,23 +0,0 @@ | ||||
| #ifndef _TAS_IOCTL_H_ | ||||
| #define _TAS_IOCTL_H_ | ||||
| 
 | ||||
| #include <linux/soundcard.h> | ||||
| 
 | ||||
| 
 | ||||
| #define TAS_READ_EQ              _SIOR('t',0,struct tas_biquad_ctrl_t) | ||||
| #define TAS_WRITE_EQ             _SIOW('t',0,struct tas_biquad_ctrl_t) | ||||
| 
 | ||||
| #define TAS_READ_EQ_LIST         _SIOR('t',1,struct tas_biquad_ctrl_t) | ||||
| #define TAS_WRITE_EQ_LIST        _SIOW('t',1,struct tas_biquad_ctrl_t) | ||||
| 
 | ||||
| #define TAS_READ_EQ_FILTER_COUNT  _SIOR('t',2,int) | ||||
| #define TAS_READ_EQ_CHANNEL_COUNT _SIOR('t',3,int) | ||||
| 
 | ||||
| #define TAS_READ_DRCE            _SIOR('t',4,struct tas_drce_ctrl_t) | ||||
| #define TAS_WRITE_DRCE           _SIOW('t',4,struct tas_drce_ctrl_t) | ||||
| 
 | ||||
| #define TAS_READ_DRCE_CAPS       _SIOR('t',5,int) | ||||
| #define TAS_READ_DRCE_MIN        _SIOR('t',6,int) | ||||
| #define TAS_READ_DRCE_MAX        _SIOR('t',7,int) | ||||
| 
 | ||||
| #endif | ||||
| @ -1,898 +0,0 @@ | ||||
| /*
 | ||||
|  *  linux/sound/oss/dmasound/trans_16.c | ||||
|  * | ||||
|  *  16 bit translation routines.  Only used by Power mac at present. | ||||
|  * | ||||
|  *  See linux/sound/oss/dmasound/dmasound_core.c for copyright and | ||||
|  *  history prior to 08/02/2001. | ||||
|  * | ||||
|  *  08/02/2001 Iain Sandoe | ||||
|  *		split from dmasound_awacs.c | ||||
|  *  11/29/2003 Renzo Davoli (King Enzo) | ||||
|  *  	- input resampling (for soft rate < hard rate) | ||||
|  *  	- software line in gain control | ||||
|  */ | ||||
| 
 | ||||
| #include <linux/soundcard.h> | ||||
| #include <asm/uaccess.h> | ||||
| #include "dmasound.h" | ||||
| 
 | ||||
| extern int expand_bal;	/* Balance factor for expanding (not volume!) */ | ||||
| static short dmasound_alaw2dma16[] ; | ||||
| static short dmasound_ulaw2dma16[] ; | ||||
| 
 | ||||
| static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft); | ||||
| static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft); | ||||
| static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| 
 | ||||
| static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft); | ||||
| static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft); | ||||
| static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft); | ||||
| 
 | ||||
| static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft); | ||||
| 
 | ||||
| /*** Translations ************************************************************/ | ||||
| 
 | ||||
| static int expand_data;	/* Data for expanding */ | ||||
| 
 | ||||
| static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	short *table = dmasound.soft.format == AFMT_MU_LAW | ||||
| 		? dmasound_ulaw2dma16 : dmasound_alaw2dma16; | ||||
| 	ssize_t count, used; | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int val, stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		u_char data; | ||||
| 		if (get_user(data, userPtr++)) | ||||
| 			return -EFAULT; | ||||
| 		val = table[data]; | ||||
| 		*p++ = val; | ||||
| 		if (stereo) { | ||||
| 			if (get_user(data, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			val = table[data]; | ||||
| 		} | ||||
| 		*p++ = val; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 2: used; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int val, stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		u_char data; | ||||
| 		if (get_user(data, userPtr++)) | ||||
| 			return -EFAULT; | ||||
| 		val = data << 8; | ||||
| 		*p++ = val; | ||||
| 		if (stereo) { | ||||
| 			if (get_user(data, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			val = data << 8; | ||||
| 		} | ||||
| 		*p++ = val; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 2: used; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int val, stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		u_char data; | ||||
| 		if (get_user(data, userPtr++)) | ||||
| 			return -EFAULT; | ||||
| 		val = (data ^ 0x80) << 8; | ||||
| 		*p++ = val; | ||||
| 		if (stereo) { | ||||
| 			if (get_user(data, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			val = (data ^ 0x80) << 8; | ||||
| 		} | ||||
| 		*p++ = val; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 2: used; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	if (!stereo) { | ||||
| 		short __user *up = (short __user *) userPtr; | ||||
| 		while (count > 0) { | ||||
| 			short data; | ||||
| 			if (get_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 			*fp++ = data; | ||||
| 			*fp++ = data; | ||||
| 			count--; | ||||
| 		} | ||||
| 	} else { | ||||
| 		if (copy_from_user(fp, userPtr, count * 4)) | ||||
| 			return -EFAULT; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 4: used * 2; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 	short __user *up = (short __user *) userPtr; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		short data; | ||||
| 		if (get_user(data, up++)) | ||||
| 			return -EFAULT; | ||||
| 		data ^= mask; | ||||
| 		*fp++ = data; | ||||
| 		if (stereo) { | ||||
| 			if (get_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 			data ^= mask; | ||||
| 		} | ||||
| 		*fp++ = data; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 4: used * 2; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft) | ||||
| { | ||||
| 	unsigned short *table = (unsigned short *) | ||||
| 		(dmasound.soft.format == AFMT_MU_LAW | ||||
| 		 ? dmasound_ulaw2dma16 : dmasound_alaw2dma16); | ||||
| 	unsigned int data = expand_data; | ||||
| 	unsigned int *p = (unsigned int *) &frame[*frameUsed]; | ||||
| 	int bal = expand_bal; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int utotal, ftotal; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		u_char c; | ||||
| 		if (bal < 0) { | ||||
| 			if (userCount == 0) | ||||
| 				break; | ||||
| 			if (get_user(c, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			data = table[c]; | ||||
| 			if (stereo) { | ||||
| 				if (get_user(c, userPtr++)) | ||||
| 					return -EFAULT; | ||||
| 				data = (data << 16) + table[c]; | ||||
| 			} else | ||||
| 				data = (data << 16) + data; | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		*p++ = data; | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_bal = bal; | ||||
| 	expand_data = data; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 2: utotal; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	unsigned int *p = (unsigned int *) &frame[*frameUsed]; | ||||
| 	unsigned int data = expand_data; | ||||
| 	int bal = expand_bal; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		u_char c; | ||||
| 		if (bal < 0) { | ||||
| 			if (userCount == 0) | ||||
| 				break; | ||||
| 			if (get_user(c, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			data = c << 8; | ||||
| 			if (stereo) { | ||||
| 				if (get_user(c, userPtr++)) | ||||
| 					return -EFAULT; | ||||
| 				data = (data << 16) + (c << 8); | ||||
| 			} else | ||||
| 				data = (data << 16) + data; | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		*p++ = data; | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_bal = bal; | ||||
| 	expand_data = data; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 2: utotal; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	unsigned int *p = (unsigned int *) &frame[*frameUsed]; | ||||
| 	unsigned int data = expand_data; | ||||
| 	int bal = expand_bal; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		u_char c; | ||||
| 		if (bal < 0) { | ||||
| 			if (userCount == 0) | ||||
| 				break; | ||||
| 			if (get_user(c, userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			data = (c ^ 0x80) << 8; | ||||
| 			if (stereo) { | ||||
| 				if (get_user(c, userPtr++)) | ||||
| 					return -EFAULT; | ||||
| 				data = (data << 16) + ((c ^ 0x80) << 8); | ||||
| 			} else | ||||
| 				data = (data << 16) + data; | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		*p++ = data; | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_bal = bal; | ||||
| 	expand_data = data; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 2: utotal; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft) | ||||
| { | ||||
| 	unsigned int *p = (unsigned int *) &frame[*frameUsed]; | ||||
| 	unsigned int data = expand_data; | ||||
| 	unsigned short __user *up = (unsigned short __user *) userPtr; | ||||
| 	int bal = expand_bal; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		unsigned short c; | ||||
| 		if (bal < 0) { | ||||
| 			if (userCount == 0) | ||||
| 				break; | ||||
| 			if (get_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 			if (stereo) { | ||||
| 				if (get_user(c, up++)) | ||||
| 					return -EFAULT; | ||||
| 				data = (data << 16) + c; | ||||
| 			} else | ||||
| 				data = (data << 16) + data; | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		*p++ = data; | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_bal = bal; | ||||
| 	expand_data = data; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 4: utotal * 2; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount, | ||||
| 			    u_char frame[], ssize_t *frameUsed, | ||||
| 			    ssize_t frameLeft) | ||||
| { | ||||
| 	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | ||||
| 	unsigned int *p = (unsigned int *) &frame[*frameUsed]; | ||||
| 	unsigned int data = expand_data; | ||||
| 	unsigned short __user *up = (unsigned short __user *) userPtr; | ||||
| 	int bal = expand_bal; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		unsigned short c; | ||||
| 		if (bal < 0) { | ||||
| 			if (userCount == 0) | ||||
| 				break; | ||||
| 			if (get_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 			data ^= mask; | ||||
| 			if (stereo) { | ||||
| 				if (get_user(c, up++)) | ||||
| 					return -EFAULT; | ||||
| 				data = (data << 16) + (c ^ mask); | ||||
| 			} else | ||||
| 				data = (data << 16) + data; | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		*p++ = data; | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_bal = bal; | ||||
| 	expand_data = data; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 4: utotal * 2; | ||||
| } | ||||
| 
 | ||||
| /* data in routines... */ | ||||
| 
 | ||||
| static ssize_t pmac_ct_s8_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int val, stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		u_char data; | ||||
| 
 | ||||
| 		val = *p++; | ||||
| 		val = (val * software_input_volume) >> 7; | ||||
| 		data = val >> 8; | ||||
| 		if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 			return -EFAULT; | ||||
| 		if (stereo) { | ||||
| 			val = *p; | ||||
| 			val = (val * software_input_volume) >> 7; | ||||
| 			data = val >> 8; | ||||
| 			if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 		} | ||||
| 		p++; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 2: used; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ct_u8_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int val, stereo = dmasound.soft.stereo; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		u_char data; | ||||
| 
 | ||||
| 		val = *p++; | ||||
| 		val = (val * software_input_volume) >> 7; | ||||
| 		data = (val >> 8) ^ 0x80; | ||||
| 		if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 			return -EFAULT; | ||||
| 		if (stereo) { | ||||
| 			val = *p; | ||||
| 			val = (val * software_input_volume) >> 7; | ||||
| 			data = (val >> 8) ^ 0x80; | ||||
| 			if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 		} | ||||
| 		p++; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 2: used; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 	short __user *up = (short __user *) userPtr; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		short data; | ||||
| 
 | ||||
| 		data = *fp++; | ||||
| 		data = (data * software_input_volume) >> 7; | ||||
| 		if (put_user(data, up++)) | ||||
| 			return -EFAULT; | ||||
| 		if (stereo) { | ||||
| 			data = *fp; | ||||
| 			data = (data * software_input_volume) >> 7; | ||||
| 			if (put_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 		} | ||||
| 		fp++; | ||||
| 		count--; | ||||
|  	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 4: used * 2; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	ssize_t count, used; | ||||
| 	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 	short __user *up = (short __user *) userPtr; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	used = count = min_t(unsigned long, userCount, frameLeft); | ||||
| 	while (count > 0) { | ||||
| 		int data; | ||||
| 
 | ||||
| 		data = *fp++; | ||||
| 		data = (data * software_input_volume) >> 7; | ||||
| 		data ^= mask; | ||||
| 		if (put_user(data, up++)) | ||||
| 			return -EFAULT; | ||||
| 		if (stereo) { | ||||
| 			data = *fp; | ||||
| 			data = (data * software_input_volume) >> 7; | ||||
| 			data ^= mask; | ||||
| 			if (put_user(data, up++)) | ||||
| 				return -EFAULT; | ||||
| 		} | ||||
| 		fp++; | ||||
| 		count--; | ||||
| 	} | ||||
| 	*frameUsed += used * 4; | ||||
| 	return stereo? used * 4: used * 2; | ||||
| } | ||||
| 
 | ||||
| /* data in routines (reducing speed)... */ | ||||
| 
 | ||||
| static ssize_t pmac_ctx_s8_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int bal = expand_read_bal; | ||||
| 	int vall,valr, stereo = dmasound.soft.stereo; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		u_char data; | ||||
| 
 | ||||
| 		if (bal<0 && userCount == 0) | ||||
| 			break; | ||||
| 		vall = *p++; | ||||
| 		vall = (vall * software_input_volume) >> 7; | ||||
| 		if (stereo) { | ||||
| 			valr = *p; | ||||
| 			valr = (valr * software_input_volume) >> 7; | ||||
| 		} | ||||
| 		p++; | ||||
| 		if (bal < 0) { | ||||
| 			data = vall >> 8; | ||||
| 			if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			if (stereo) { | ||||
| 				data = valr >> 8; | ||||
| 				if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 					return -EFAULT; | ||||
| 			} | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_read_bal=bal; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 2: utotal; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| static ssize_t pmac_ctx_u8_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			  u_char frame[], ssize_t *frameUsed, | ||||
| 			  ssize_t frameLeft) | ||||
| { | ||||
| 	short *p = (short *) &frame[*frameUsed]; | ||||
| 	int bal = expand_read_bal; | ||||
| 	int vall,valr, stereo = dmasound.soft.stereo; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	if (stereo) | ||||
| 		userCount >>= 1; | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		u_char data; | ||||
| 
 | ||||
| 		if (bal<0 && userCount == 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		vall = *p++; | ||||
| 		vall = (vall * software_input_volume) >> 7; | ||||
| 		if (stereo) { | ||||
| 			valr = *p; | ||||
| 			valr = (valr * software_input_volume) >> 7; | ||||
| 		} | ||||
| 		p++; | ||||
| 		if (bal < 0) { | ||||
| 			data = (vall >> 8) ^ 0x80; | ||||
| 			if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 				return -EFAULT; | ||||
| 			if (stereo) { | ||||
| 				data = (valr >> 8) ^ 0x80; | ||||
| 				if (put_user(data, (u_char __user *)userPtr++)) | ||||
| 					return -EFAULT; | ||||
| 			} | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_read_bal=bal; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 2: utotal; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ctx_s16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	int bal = expand_read_bal; | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 	short __user *up = (short __user *) userPtr; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		int datal,datar; | ||||
| 
 | ||||
| 		if (bal<0 && userCount == 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		datal = *fp++; | ||||
| 		datal = (datal * software_input_volume) >> 7; | ||||
| 		if (stereo) { | ||||
| 			datar = *fp; | ||||
| 			datar = (datar * software_input_volume) >> 7; | ||||
| 		} | ||||
| 		fp++; | ||||
| 		if (bal < 0) { | ||||
| 			if (put_user(datal, up++)) | ||||
| 				return -EFAULT; | ||||
| 			if (stereo) { | ||||
| 				if (put_user(datar, up++)) | ||||
| 					return -EFAULT; | ||||
| 			} | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_read_bal=bal; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 4: utotal * 2; | ||||
| } | ||||
| 
 | ||||
| static ssize_t pmac_ctx_u16_read(const u_char __user *userPtr, size_t userCount, | ||||
| 			   u_char frame[], ssize_t *frameUsed, | ||||
| 			   ssize_t frameLeft) | ||||
| { | ||||
| 	int bal = expand_read_bal; | ||||
| 	int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000); | ||||
| 	short *fp = (short *) &frame[*frameUsed]; | ||||
| 	short __user *up = (short __user *) userPtr; | ||||
| 	int stereo = dmasound.soft.stereo; | ||||
| 	int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed; | ||||
| 	int utotal, ftotal; | ||||
| 
 | ||||
| 	frameLeft >>= 2; | ||||
| 	userCount >>= (stereo? 2: 1); | ||||
| 	ftotal = frameLeft; | ||||
| 	utotal = userCount; | ||||
| 	while (frameLeft) { | ||||
| 		int datal,datar; | ||||
| 
 | ||||
| 		if (bal<0 && userCount == 0) | ||||
| 			break; | ||||
| 
 | ||||
| 		datal = *fp++; | ||||
| 		datal = (datal * software_input_volume) >> 7; | ||||
| 		datal ^= mask; | ||||
| 		if (stereo) { | ||||
| 			datar = *fp; | ||||
| 			datar = (datar * software_input_volume) >> 7; | ||||
| 			datar ^= mask; | ||||
| 		} | ||||
| 		fp++; | ||||
| 		if (bal < 0) { | ||||
| 			if (put_user(datal, up++)) | ||||
| 				return -EFAULT; | ||||
| 			if (stereo) { | ||||
| 				if (put_user(datar, up++)) | ||||
| 					return -EFAULT; | ||||
| 			} | ||||
| 			userCount--; | ||||
| 			bal += hSpeed; | ||||
| 		} | ||||
| 		frameLeft--; | ||||
| 		bal -= sSpeed; | ||||
| 	} | ||||
| 	expand_read_bal=bal; | ||||
| 	*frameUsed += (ftotal - frameLeft) * 4; | ||||
| 	utotal -= userCount; | ||||
| 	return stereo? utotal * 4: utotal * 2; | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| TRANS transAwacsNormal = { | ||||
| 	.ct_ulaw=	pmac_ct_law, | ||||
| 	.ct_alaw=	pmac_ct_law, | ||||
| 	.ct_s8=		pmac_ct_s8, | ||||
| 	.ct_u8=		pmac_ct_u8, | ||||
| 	.ct_s16be=	pmac_ct_s16, | ||||
| 	.ct_u16be=	pmac_ct_u16, | ||||
| 	.ct_s16le=	pmac_ct_s16, | ||||
| 	.ct_u16le=	pmac_ct_u16, | ||||
| }; | ||||
| 
 | ||||
| TRANS transAwacsExpand = { | ||||
| 	.ct_ulaw=	pmac_ctx_law, | ||||
| 	.ct_alaw=	pmac_ctx_law, | ||||
| 	.ct_s8=		pmac_ctx_s8, | ||||
| 	.ct_u8=		pmac_ctx_u8, | ||||
| 	.ct_s16be=	pmac_ctx_s16, | ||||
| 	.ct_u16be=	pmac_ctx_u16, | ||||
| 	.ct_s16le=	pmac_ctx_s16, | ||||
| 	.ct_u16le=	pmac_ctx_u16, | ||||
| }; | ||||
| 
 | ||||
| TRANS transAwacsNormalRead = { | ||||
| 	.ct_s8=		pmac_ct_s8_read, | ||||
| 	.ct_u8=		pmac_ct_u8_read, | ||||
| 	.ct_s16be=	pmac_ct_s16_read, | ||||
| 	.ct_u16be=	pmac_ct_u16_read, | ||||
| 	.ct_s16le=	pmac_ct_s16_read, | ||||
| 	.ct_u16le=	pmac_ct_u16_read, | ||||
| }; | ||||
| 
 | ||||
| TRANS transAwacsExpandRead = { | ||||
| 	.ct_s8=		pmac_ctx_s8_read, | ||||
| 	.ct_u8=		pmac_ctx_u8_read, | ||||
| 	.ct_s16be=	pmac_ctx_s16_read, | ||||
| 	.ct_u16be=	pmac_ctx_u16_read, | ||||
| 	.ct_s16le=	pmac_ctx_s16_read, | ||||
| 	.ct_u16le=	pmac_ctx_u16_read, | ||||
| }; | ||||
| 
 | ||||
| /* translation tables */ | ||||
| /* 16 bit mu-law */ | ||||
| 
 | ||||
| static short dmasound_ulaw2dma16[] = { | ||||
| 	-32124,	-31100,	-30076,	-29052,	-28028,	-27004,	-25980,	-24956, | ||||
| 	-23932,	-22908,	-21884,	-20860,	-19836,	-18812,	-17788,	-16764, | ||||
| 	-15996,	-15484,	-14972,	-14460,	-13948,	-13436,	-12924,	-12412, | ||||
| 	-11900,	-11388,	-10876,	-10364,	-9852,	-9340,	-8828,	-8316, | ||||
| 	-7932,	-7676,	-7420,	-7164,	-6908,	-6652,	-6396,	-6140, | ||||
| 	-5884,	-5628,	-5372,	-5116,	-4860,	-4604,	-4348,	-4092, | ||||
| 	-3900,	-3772,	-3644,	-3516,	-3388,	-3260,	-3132,	-3004, | ||||
| 	-2876,	-2748,	-2620,	-2492,	-2364,	-2236,	-2108,	-1980, | ||||
| 	-1884,	-1820,	-1756,	-1692,	-1628,	-1564,	-1500,	-1436, | ||||
| 	-1372,	-1308,	-1244,	-1180,	-1116,	-1052,	-988,	-924, | ||||
| 	-876,	-844,	-812,	-780,	-748,	-716,	-684,	-652, | ||||
| 	-620,	-588,	-556,	-524,	-492,	-460,	-428,	-396, | ||||
| 	-372,	-356,	-340,	-324,	-308,	-292,	-276,	-260, | ||||
| 	-244,	-228,	-212,	-196,	-180,	-164,	-148,	-132, | ||||
| 	-120,	-112,	-104,	-96,	-88,	-80,	-72,	-64, | ||||
| 	-56,	-48,	-40,	-32,	-24,	-16,	-8,	0, | ||||
| 	32124,	31100,	30076,	29052,	28028,	27004,	25980,	24956, | ||||
| 	23932,	22908,	21884,	20860,	19836,	18812,	17788,	16764, | ||||
| 	15996,	15484,	14972,	14460,	13948,	13436,	12924,	12412, | ||||
| 	11900,	11388,	10876,	10364,	9852,	9340,	8828,	8316, | ||||
| 	7932,	7676,	7420,	7164,	6908,	6652,	6396,	6140, | ||||
| 	5884,	5628,	5372,	5116,	4860,	4604,	4348,	4092, | ||||
| 	3900,	3772,	3644,	3516,	3388,	3260,	3132,	3004, | ||||
| 	2876,	2748,	2620,	2492,	2364,	2236,	2108,	1980, | ||||
| 	1884,	1820,	1756,	1692,	1628,	1564,	1500,	1436, | ||||
| 	1372,	1308,	1244,	1180,	1116,	1052,	988,	924, | ||||
| 	876,	844,	812,	780,	748,	716,	684,	652, | ||||
| 	620,	588,	556,	524,	492,	460,	428,	396, | ||||
| 	372,	356,	340,	324,	308,	292,	276,	260, | ||||
| 	244,	228,	212,	196,	180,	164,	148,	132, | ||||
| 	120,	112,	104,	96,	88,	80,	72,	64, | ||||
| 	56,	48,	40,	32,	24,	16,	8,	0, | ||||
| }; | ||||
| 
 | ||||
| /* 16 bit A-law */ | ||||
| 
 | ||||
| static short dmasound_alaw2dma16[] = { | ||||
| 	-5504,	-5248,	-6016,	-5760,	-4480,	-4224,	-4992,	-4736, | ||||
| 	-7552,	-7296,	-8064,	-7808,	-6528,	-6272,	-7040,	-6784, | ||||
| 	-2752,	-2624,	-3008,	-2880,	-2240,	-2112,	-2496,	-2368, | ||||
| 	-3776,	-3648,	-4032,	-3904,	-3264,	-3136,	-3520,	-3392, | ||||
| 	-22016,	-20992,	-24064,	-23040,	-17920,	-16896,	-19968,	-18944, | ||||
| 	-30208,	-29184,	-32256,	-31232,	-26112,	-25088,	-28160,	-27136, | ||||
| 	-11008,	-10496,	-12032,	-11520,	-8960,	-8448,	-9984,	-9472, | ||||
| 	-15104,	-14592,	-16128,	-15616,	-13056,	-12544,	-14080,	-13568, | ||||
| 	-344,	-328,	-376,	-360,	-280,	-264,	-312,	-296, | ||||
| 	-472,	-456,	-504,	-488,	-408,	-392,	-440,	-424, | ||||
| 	-88,	-72,	-120,	-104,	-24,	-8,	-56,	-40, | ||||
| 	-216,	-200,	-248,	-232,	-152,	-136,	-184,	-168, | ||||
| 	-1376,	-1312,	-1504,	-1440,	-1120,	-1056,	-1248,	-1184, | ||||
| 	-1888,	-1824,	-2016,	-1952,	-1632,	-1568,	-1760,	-1696, | ||||
| 	-688,	-656,	-752,	-720,	-560,	-528,	-624,	-592, | ||||
| 	-944,	-912,	-1008,	-976,	-816,	-784,	-880,	-848, | ||||
| 	5504,	5248,	6016,	5760,	4480,	4224,	4992,	4736, | ||||
| 	7552,	7296,	8064,	7808,	6528,	6272,	7040,	6784, | ||||
| 	2752,	2624,	3008,	2880,	2240,	2112,	2496,	2368, | ||||
| 	3776,	3648,	4032,	3904,	3264,	3136,	3520,	3392, | ||||
| 	22016,	20992,	24064,	23040,	17920,	16896,	19968,	18944, | ||||
| 	30208,	29184,	32256,	31232,	26112,	25088,	28160,	27136, | ||||
| 	11008,	10496,	12032,	11520,	8960,	8448,	9984,	9472, | ||||
| 	15104,	14592,	16128,	15616,	13056,	12544,	14080,	13568, | ||||
| 	344,	328,	376,	360,	280,	264,	312,	296, | ||||
| 	472,	456,	504,	488,	408,	392,	440,	424, | ||||
| 	88,	72,	120,	104,	24,	8,	56,	40, | ||||
| 	216,	200,	248,	232,	152,	136,	184,	168, | ||||
| 	1376,	1312,	1504,	1440,	1120,	1056,	1248,	1184, | ||||
| 	1888,	1824,	2016,	1952,	1632,	1568,	1760,	1696, | ||||
| 	688,	656,	752,	720,	560,	528,	624,	592, | ||||
| 	944,	912,	1008,	976,	816,	784,	880,	848, | ||||
| }; | ||||
							
								
								
									
										3131
									
								
								sound/oss/es1371.c
									
									
									
									
									
								
							
							
						
						
									
										3131
									
								
								sound/oss/es1371.c
									
									
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user
	 Adrian Bunk
						Adrian Bunk