mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02: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
					
				
					 22 changed files with 0 additions and 11438 deletions
				
			
		| 
						 | 
				
			
			@ -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 a new issue