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:
Adrian Bunk 2007-10-18 03:06:12 -07:00 committed by Linus Torvalds
parent 5b4db0c2f2
commit fc37449f79
22 changed files with 0 additions and 11438 deletions

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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_ */

View File

@ -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);
}

View File

@ -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

View File

@ -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);

View File

@ -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
};

View File

@ -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_ */

View File

@ -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

View File

@ -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_ */

View File

@ -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
};

View File

@ -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);
}

View File

@ -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:
*/

View File

@ -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:
*/

View File

@ -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

View File

@ -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,
};

File diff suppressed because it is too large Load Diff