aboutsummaryrefslogtreecommitdiffstats
path: root/sound/oss/dmasound
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /sound/oss/dmasound
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'sound/oss/dmasound')
-rw-r--r--sound/oss/dmasound/Kconfig58
-rw-r--r--sound/oss/dmasound/Makefile13
-rw-r--r--sound/oss/dmasound/awacs_defs.h251
-rw-r--r--sound/oss/dmasound/dac3550a.c210
-rw-r--r--sound/oss/dmasound/dmasound.h277
-rw-r--r--sound/oss/dmasound/dmasound_atari.c1600
-rw-r--r--sound/oss/dmasound/dmasound_awacs.c3176
-rw-r--r--sound/oss/dmasound/dmasound_core.c1829
-rw-r--r--sound/oss/dmasound/dmasound_paula.c743
-rw-r--r--sound/oss/dmasound/dmasound_q40.c634
-rw-r--r--sound/oss/dmasound/tas3001c.c850
-rw-r--r--sound/oss/dmasound/tas3001c.h64
-rw-r--r--sound/oss/dmasound/tas3001c_tables.c375
-rw-r--r--sound/oss/dmasound/tas3004.c1140
-rw-r--r--sound/oss/dmasound/tas3004.h77
-rw-r--r--sound/oss/dmasound/tas3004_tables.c301
-rw-r--r--sound/oss/dmasound/tas_common.c214
-rw-r--r--sound/oss/dmasound/tas_common.h284
-rw-r--r--sound/oss/dmasound/tas_eq_prefs.h24
-rw-r--r--sound/oss/dmasound/tas_ioctl.h24
-rw-r--r--sound/oss/dmasound/trans_16.c897
21 files changed, 13041 insertions, 0 deletions
diff --git a/sound/oss/dmasound/Kconfig b/sound/oss/dmasound/Kconfig
new file mode 100644
index 000000000000..cb845580fe03
--- /dev/null
+++ b/sound/oss/dmasound/Kconfig
@@ -0,0 +1,58 @@
1config DMASOUND_ATARI
2 tristate "Atari DMA sound support"
3 depends on ATARI && SOUND
4 select DMASOUND
5 help
6 If you want to use the internal audio of your Atari in Linux, answer
7 Y to this question. This will provide a Sun-like /dev/audio,
8 compatible with the Linux/i386 sound system. Otherwise, say N.
9
10 This driver is also available as a module ( = code which can be
11 inserted in and removed from the running kernel whenever you
12 want). If you want to compile it as a module, say M here and read
13 <file:Documentation/kbuild/modules.txt>.
14
15config DMASOUND_PMAC
16 tristate "PowerMac DMA sound support"
17 depends on PPC32 && PPC_PMAC && SOUND && I2C
18 select DMASOUND
19 help
20 If you want to use the internal audio of your PowerMac in Linux,
21 answer Y to this question. This will provide a Sun-like /dev/audio,
22 compatible with the Linux/i386 sound system. Otherwise, say N.
23
24 This driver is also available as a module ( = code which can be
25 inserted in and removed from the running kernel whenever you
26 want). If you want to compile it as a module, say M here and read
27 <file:Documentation/kbuild/modules.txt>.
28
29config DMASOUND_PAULA
30 tristate "Amiga DMA sound support"
31 depends on (AMIGA || APUS) && SOUND
32 select DMASOUND
33 help
34 If you want to use the internal audio of your Amiga in Linux, answer
35 Y to this question. This will provide a Sun-like /dev/audio,
36 compatible with the Linux/i386 sound system. Otherwise, say N.
37
38 This driver is also available as a module ( = code which can be
39 inserted in and removed from the running kernel whenever you
40 want). If you want to compile it as a module, say M here and read
41 <file:Documentation/kbuild/modules.txt>.
42
43config DMASOUND_Q40
44 tristate "Q40 sound support"
45 depends on Q40 && SOUND
46 select DMASOUND
47 help
48 If you want to use the internal audio of your Q40 in Linux, answer
49 Y to this question. This will provide a Sun-like /dev/audio,
50 compatible with the Linux/i386 sound system. Otherwise, say N.
51
52 This driver is also available as a module ( = code which can be
53 inserted in and removed from the running kernel whenever you
54 want). If you want to compile it as a module, say M here and read
55 <file:Documentation/kbuild/modules.txt>.
56
57config DMASOUND
58 tristate
diff --git a/sound/oss/dmasound/Makefile b/sound/oss/dmasound/Makefile
new file mode 100644
index 000000000000..4611636b1a81
--- /dev/null
+++ b/sound/oss/dmasound/Makefile
@@ -0,0 +1,13 @@
1#
2# Makefile for the DMA sound driver
3#
4
5dmasound_pmac-y += dmasound_awacs.o \
6 trans_16.o dac3550a.o tas_common.o \
7 tas3001c.o tas3001c_tables.o \
8 tas3004.o tas3004_tables.o
9
10obj-$(CONFIG_DMASOUND_ATARI) += dmasound_core.o dmasound_atari.o
11obj-$(CONFIG_DMASOUND_PMAC) += dmasound_core.o dmasound_pmac.o
12obj-$(CONFIG_DMASOUND_PAULA) += dmasound_core.o dmasound_paula.o
13obj-$(CONFIG_DMASOUND_Q40) += dmasound_core.o dmasound_q40.o
diff --git a/sound/oss/dmasound/awacs_defs.h b/sound/oss/dmasound/awacs_defs.h
new file mode 100644
index 000000000000..2194f46b046c
--- /dev/null
+++ b/sound/oss/dmasound/awacs_defs.h
@@ -0,0 +1,251 @@
1/*********************************************************/
2/* This file was written by someone, somewhere, sometime */
3/* And is released into the Public Domain */
4/*********************************************************/
5
6#ifndef _AWACS_DEFS_H_
7#define _AWACS_DEFS_H_
8
9/*******************************/
10/* AWACs Audio Register Layout */
11/*******************************/
12
13struct awacs_regs {
14 unsigned control; /* Audio control register */
15 unsigned pad0[3];
16 unsigned codec_ctrl; /* Codec control register */
17 unsigned pad1[3];
18 unsigned codec_stat; /* Codec status register */
19 unsigned pad2[3];
20 unsigned clip_count; /* Clipping count register */
21 unsigned pad3[3];
22 unsigned byteswap; /* Data is little-endian if 1 */
23};
24
25/*******************/
26/* Audio Bit Masks */
27/*******************/
28
29/* Audio Control Reg Bit Masks */
30/* ----- ------- --- --- ----- */
31#define MASK_ISFSEL (0xf) /* Input SubFrame Select */
32#define MASK_OSFSEL (0xf << 4) /* Output SubFrame Select */
33#define MASK_RATE (0x7 << 8) /* Sound Rate */
34#define MASK_CNTLERR (0x1 << 11) /* Error */
35#define MASK_PORTCHG (0x1 << 12) /* Port Change */
36#define MASK_IEE (0x1 << 13) /* Enable Interrupt on Error */
37#define MASK_IEPC (0x1 << 14) /* Enable Interrupt on Port Change */
38#define MASK_SSFSEL (0x3 << 15) /* Status SubFrame Select */
39
40/* Audio Codec Control Reg Bit Masks */
41/* ----- ----- ------- --- --- ----- */
42#define MASK_NEWECMD (0x1 << 24) /* Lock: don't write to reg when 1 */
43#define MASK_EMODESEL (0x3 << 22) /* Send info out on which frame? */
44#define MASK_EXMODEADDR (0x3ff << 12) /* Extended Mode Address -- 10 bits */
45#define MASK_EXMODEDATA (0xfff) /* Extended Mode Data -- 12 bits */
46
47/* Audio Codec Control Address Values / Masks */
48/* ----- ----- ------- ------- ------ - ----- */
49#define MASK_ADDR0 (0x0 << 12) /* Expanded Data Mode Address 0 */
50#define MASK_ADDR_MUX MASK_ADDR0 /* Mux Control */
51#define MASK_ADDR_GAIN MASK_ADDR0
52
53#define MASK_ADDR1 (0x1 << 12) /* Expanded Data Mode Address 1 */
54#define MASK_ADDR_MUTE MASK_ADDR1
55#define MASK_ADDR_RATE MASK_ADDR1
56
57#define MASK_ADDR2 (0x2 << 12) /* Expanded Data Mode Address 2 */
58#define MASK_ADDR_VOLA MASK_ADDR2 /* Volume Control A -- Headphones */
59#define MASK_ADDR_VOLHD MASK_ADDR2
60
61#define MASK_ADDR4 (0x4 << 12) /* Expanded Data Mode Address 4 */
62#define MASK_ADDR_VOLC MASK_ADDR4 /* Volume Control C -- Speaker */
63#define MASK_ADDR_VOLSPK MASK_ADDR4
64
65/* additional registers of screamer */
66#define MASK_ADDR5 (0x5 << 12) /* Expanded Data Mode Address 5 */
67#define MASK_ADDR6 (0x6 << 12) /* Expanded Data Mode Address 6 */
68#define MASK_ADDR7 (0x7 << 12) /* Expanded Data Mode Address 7 */
69
70/* Address 0 Bit Masks & Macros */
71/* ------- - --- ----- - ------ */
72#define MASK_GAINRIGHT (0xf) /* Gain Right Mask */
73#define MASK_GAINLEFT (0xf << 4) /* Gain Left Mask */
74#define MASK_GAINLINE (0x1 << 8) /* Disable Mic preamp */
75#define MASK_GAINMIC (0x0 << 8) /* Enable Mic preamp */
76
77#define MASK_MUX_CD (0x1 << 9) /* Select CD in MUX */
78#define MASK_MUX_MIC (0x1 << 10) /* Select Mic in MUX */
79#define MASK_MUX_AUDIN (0x1 << 11) /* Select Audio In in MUX */
80#define MASK_MUX_LINE MASK_MUX_AUDIN
81
82#define GAINRIGHT(x) ((x) & MASK_GAINRIGHT)
83#define GAINLEFT(x) (((x) << 4) & MASK_GAINLEFT)
84
85#define DEF_CD_GAIN 0x00bb
86#define DEF_MIC_GAIN 0x00cc
87
88/* Address 1 Bit Masks */
89/* ------- - --- ----- */
90#define MASK_ADDR1RES1 (0x3) /* Reserved */
91#define MASK_RECALIBRATE (0x1 << 2) /* Recalibrate */
92#define MASK_SAMPLERATE (0x7 << 3) /* Sample Rate: */
93#define MASK_LOOPTHRU (0x1 << 6) /* Loopthrough Enable */
94#define MASK_CMUTE (0x1 << 7) /* Output C (Speaker) Mute when 1 */
95#define MASK_SPKMUTE MASK_CMUTE
96#define MASK_ADDR1RES2 (0x1 << 8) /* Reserved */
97#define MASK_AMUTE (0x1 << 9) /* Output A (Headphone) Mute when 1 */
98#define MASK_HDMUTE MASK_AMUTE
99#define MASK_PAROUT0 (0x1 << 10) /* Parallel Output 0 */
100#define MASK_PAROUT1 (0x2 << 10) /* Parallel Output 1 */
101
102#define MASK_MIC_BOOST (0x4) /* screamer mic boost */
103
104#define SAMPLERATE_48000 (0x0 << 3) /* 48 or 44.1 kHz */
105#define SAMPLERATE_32000 (0x1 << 3) /* 32 or 29.4 kHz */
106#define SAMPLERATE_24000 (0x2 << 3) /* 24 or 22.05 kHz */
107#define SAMPLERATE_19200 (0x3 << 3) /* 19.2 or 17.64 kHz */
108#define SAMPLERATE_16000 (0x4 << 3) /* 16 or 14.7 kHz */
109#define SAMPLERATE_12000 (0x5 << 3) /* 12 or 11.025 kHz */
110#define SAMPLERATE_9600 (0x6 << 3) /* 9.6 or 8.82 kHz */
111#define SAMPLERATE_8000 (0x7 << 3) /* 8 or 7.35 kHz */
112
113/* Address 2 & 4 Bit Masks & Macros */
114/* ------- - - - --- ----- - ------ */
115#define MASK_OUTVOLRIGHT (0xf) /* Output Right Volume */
116#define MASK_ADDR2RES1 (0x2 << 4) /* Reserved */
117#define MASK_ADDR4RES1 MASK_ADDR2RES1
118#define MASK_OUTVOLLEFT (0xf << 6) /* Output Left Volume */
119#define MASK_ADDR2RES2 (0x2 << 10) /* Reserved */
120#define MASK_ADDR4RES2 MASK_ADDR2RES2
121
122#define VOLRIGHT(x) (((~(x)) & MASK_OUTVOLRIGHT))
123#define VOLLEFT(x) (((~(x)) << 6) & MASK_OUTVOLLEFT)
124
125/* Audio Codec Status Reg Bit Masks */
126/* ----- ----- ------ --- --- ----- */
127#define MASK_EXTEND (0x1 << 23) /* Extend */
128#define MASK_VALID (0x1 << 22) /* Valid Data? */
129#define MASK_OFLEFT (0x1 << 21) /* Overflow Left */
130#define MASK_OFRIGHT (0x1 << 20) /* Overflow Right */
131#define MASK_ERRCODE (0xf << 16) /* Error Code */
132#define MASK_REVISION (0xf << 12) /* Revision Number */
133#define MASK_MFGID (0xf << 8) /* Mfg. ID */
134#define MASK_CODSTATRES (0xf << 4) /* bits 4 - 7 reserved */
135#define MASK_INPPORT (0xf) /* Input Port */
136#define MASK_HDPCONN 8 /* headphone plugged in */
137
138/* Clipping Count Reg Bit Masks */
139/* -------- ----- --- --- ----- */
140#define MASK_CLIPLEFT (0xff << 7) /* Clipping Count, Left Channel */
141#define MASK_CLIPRIGHT (0xff) /* Clipping Count, Right Channel */
142
143/* DBDMA ChannelStatus Bit Masks */
144/* ----- ------------- --- ----- */
145#define MASK_CSERR (0x1 << 7) /* Error */
146#define MASK_EOI (0x1 << 6) /* End of Input -- only for Input Channel */
147#define MASK_CSUNUSED (0x1f << 1) /* bits 1-5 not used */
148#define MASK_WAIT (0x1) /* Wait */
149
150/* Various Rates */
151/* ------- ----- */
152#define RATE_48000 (0x0 << 8) /* 48 kHz */
153#define RATE_44100 (0x0 << 8) /* 44.1 kHz */
154#define RATE_32000 (0x1 << 8) /* 32 kHz */
155#define RATE_29400 (0x1 << 8) /* 29.4 kHz */
156#define RATE_24000 (0x2 << 8) /* 24 kHz */
157#define RATE_22050 (0x2 << 8) /* 22.05 kHz */
158#define RATE_19200 (0x3 << 8) /* 19.2 kHz */
159#define RATE_17640 (0x3 << 8) /* 17.64 kHz */
160#define RATE_16000 (0x4 << 8) /* 16 kHz */
161#define RATE_14700 (0x4 << 8) /* 14.7 kHz */
162#define RATE_12000 (0x5 << 8) /* 12 kHz */
163#define RATE_11025 (0x5 << 8) /* 11.025 kHz */
164#define RATE_9600 (0x6 << 8) /* 9.6 kHz */
165#define RATE_8820 (0x6 << 8) /* 8.82 kHz */
166#define RATE_8000 (0x7 << 8) /* 8 kHz */
167#define RATE_7350 (0x7 << 8) /* 7.35 kHz */
168
169#define RATE_LOW 1 /* HIGH = 48kHz, etc; LOW = 44.1kHz, etc. */
170
171/*******************/
172/* Burgundy values */
173/*******************/
174
175#define MASK_ADDR_BURGUNDY_INPSEL21 (0x11 << 12)
176#define MASK_ADDR_BURGUNDY_INPSEL3 (0x12 << 12)
177
178#define MASK_ADDR_BURGUNDY_GAINCH1 (0x13 << 12)
179#define MASK_ADDR_BURGUNDY_GAINCH2 (0x14 << 12)
180#define MASK_ADDR_BURGUNDY_GAINCH3 (0x15 << 12)
181#define MASK_ADDR_BURGUNDY_GAINCH4 (0x16 << 12)
182
183#define MASK_ADDR_BURGUNDY_VOLCH1 (0x20 << 12)
184#define MASK_ADDR_BURGUNDY_VOLCH2 (0x21 << 12)
185#define MASK_ADDR_BURGUNDY_VOLCH3 (0x22 << 12)
186#define MASK_ADDR_BURGUNDY_VOLCH4 (0x23 << 12)
187
188#define MASK_ADDR_BURGUNDY_OUTPUTSELECTS (0x2B << 12)
189#define MASK_ADDR_BURGUNDY_OUTPUTENABLES (0x2F << 12)
190
191#define MASK_ADDR_BURGUNDY_MASTER_VOLUME (0x30 << 12)
192
193#define MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES (0x60 << 12)
194
195#define MASK_ADDR_BURGUNDY_ATTENSPEAKER (0x62 << 12)
196#define MASK_ADDR_BURGUNDY_ATTENLINEOUT (0x63 << 12)
197#define MASK_ADDR_BURGUNDY_ATTENHP (0x64 << 12)
198
199#define MASK_ADDR_BURGUNDY_VOLCD (MASK_ADDR_BURGUNDY_VOLCH1)
200#define MASK_ADDR_BURGUNDY_VOLLINE (MASK_ADDR_BURGUNDY_VOLCH2)
201#define MASK_ADDR_BURGUNDY_VOLMIC (MASK_ADDR_BURGUNDY_VOLCH3)
202#define MASK_ADDR_BURGUNDY_VOLMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
203
204#define MASK_ADDR_BURGUNDY_GAINCD (MASK_ADDR_BURGUNDY_GAINCH1)
205#define MASK_ADDR_BURGUNDY_GAINLINE (MASK_ADDR_BURGUNDY_GAINCH2)
206#define MASK_ADDR_BURGUNDY_GAINMIC (MASK_ADDR_BURGUNDY_GAINCH3)
207#define MASK_ADDR_BURGUNDY_GAINMODEM (MASK_ADDR_BURGUNDY_VOLCH4)
208
209
210/* These are all default values for the burgundy */
211#define DEF_BURGUNDY_INPSEL21 (0xAA)
212#define DEF_BURGUNDY_INPSEL3 (0x0A)
213
214#define DEF_BURGUNDY_GAINCD (0x33)
215#define DEF_BURGUNDY_GAINLINE (0x44)
216#define DEF_BURGUNDY_GAINMIC (0x44)
217#define DEF_BURGUNDY_GAINMODEM (0x06)
218
219/* Remember: lowest volume here is 0x9b */
220#define DEF_BURGUNDY_VOLCD (0xCCCCCCCC)
221#define DEF_BURGUNDY_VOLLINE (0x00000000)
222#define DEF_BURGUNDY_VOLMIC (0x00000000)
223#define DEF_BURGUNDY_VOLMODEM (0xCCCCCCCC)
224
225#define DEF_BURGUNDY_OUTPUTSELECTS (0x010f010f)
226#define DEF_BURGUNDY_OUTPUTENABLES (0x0A)
227
228#define DEF_BURGUNDY_MASTER_VOLUME (0xFFFFFFFF)
229
230#define DEF_BURGUNDY_MORE_OUTPUTENABLES (0x7E)
231
232#define DEF_BURGUNDY_ATTENSPEAKER (0x44)
233#define DEF_BURGUNDY_ATTENLINEOUT (0xCC)
234#define DEF_BURGUNDY_ATTENHP (0xCC)
235
236/*********************/
237/* i2s layout values */
238/*********************/
239
240#define I2S_REG_INT_CTL 0x00
241#define I2S_REG_SERIAL_FORMAT 0x10
242#define I2S_REG_CODEC_MSG_OUT 0x20
243#define I2S_REG_CODEC_MSG_IN 0x30
244#define I2S_REG_FRAME_COUNT 0x40
245#define I2S_REG_FRAME_MATCH 0x50
246#define I2S_REG_DATAWORD_SIZES 0x60
247#define I2S_REG_PEAKLEVEL_SEL 0x70
248#define I2S_REG_PEAKLEVEL_IN0 0x80
249#define I2S_REG_PEAKLEVEL_IN1 0x90
250
251#endif /* _AWACS_DEFS_H_ */
diff --git a/sound/oss/dmasound/dac3550a.c b/sound/oss/dmasound/dac3550a.c
new file mode 100644
index 000000000000..533895eba0eb
--- /dev/null
+++ b/sound/oss/dmasound/dac3550a.c
@@ -0,0 +1,210 @@
1/*
2 * Driver for the i2c/i2s based DAC3550a sound chip used
3 * on some Apple iBooks. Also known as "DACA".
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file COPYING in the main directory of this archive
7 * for more details.
8 */
9
10#include <linux/module.h>
11#include <linux/slab.h>
12#include <linux/delay.h>
13#include <linux/proc_fs.h>
14#include <linux/ioport.h>
15#include <linux/sysctl.h>
16#include <linux/types.h>
17#include <linux/i2c.h>
18#include <linux/init.h>
19#include <asm/uaccess.h>
20#include <asm/errno.h>
21#include <asm/io.h>
22
23#include "dmasound.h"
24
25/* FYI: This code was derived from the tas3001c.c Texas/Tumbler mixer
26 * control code, as well as info derived from the AppleDACAAudio driver
27 * from Darwin CVS (main thing I derived being register numbers and
28 * values, as well as when to make the calls). */
29
30#define I2C_DRIVERID_DACA (0xFDCB)
31
32#define DACA_VERSION "0.1"
33#define DACA_DATE "20010930"
34
35static int cur_left_vol;
36static int cur_right_vol;
37static struct i2c_client *daca_client;
38
39static int daca_attach_adapter(struct i2c_adapter *adapter);
40static int daca_detect_client(struct i2c_adapter *adapter, int address);
41static int daca_detach_client(struct i2c_client *client);
42
43struct i2c_driver daca_driver = {
44 .owner = THIS_MODULE,
45 .name = "DAC3550A driver V " DACA_VERSION,
46 .id = I2C_DRIVERID_DACA,
47 .flags = I2C_DF_NOTIFY,
48 .attach_adapter = daca_attach_adapter,
49 .detach_client = daca_detach_client,
50};
51
52#define VOL_MAX ((1<<20) - 1)
53
54void daca_get_volume(uint * left_vol, uint *right_vol)
55{
56 *left_vol = cur_left_vol >> 5;
57 *right_vol = cur_right_vol >> 5;
58}
59
60int daca_set_volume(uint left_vol, uint right_vol)
61{
62 unsigned short voldata;
63
64 if (!daca_client)
65 return -1;
66
67 /* Derived from experience, not from any specific values */
68 left_vol <<= 5;
69 right_vol <<= 5;
70
71 if (left_vol > VOL_MAX)
72 left_vol = VOL_MAX;
73 if (right_vol > VOL_MAX)
74 right_vol = VOL_MAX;
75
76 voldata = ((left_vol >> 14) & 0x3f) << 8;
77 voldata |= (right_vol >> 14) & 0x3f;
78
79 if (i2c_smbus_write_word_data(daca_client, 2, voldata) < 0) {
80 printk("daca: failed to set volume \n");
81 return -1;
82 }
83
84 cur_left_vol = left_vol;
85 cur_right_vol = right_vol;
86
87 return 0;
88}
89
90int daca_leave_sleep(void)
91{
92 if (!daca_client)
93 return -1;
94
95 /* Do a short sleep, just to make sure I2C bus is awake and paying
96 * attention to us
97 */
98 msleep(20);
99 /* Write the sample rate reg the value it needs */
100 i2c_smbus_write_byte_data(daca_client, 1, 8);
101 daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5);
102 /* Another short delay, just to make sure the other I2C bus writes
103 * have taken...
104 */
105 msleep(20);
106 /* Write the global config reg - invert right power amp,
107 * DAC on, use 5-volt mode */
108 i2c_smbus_write_byte_data(daca_client, 3, 0x45);
109
110 return 0;
111}
112
113int daca_enter_sleep(void)
114{
115 if (!daca_client)
116 return -1;
117
118 i2c_smbus_write_byte_data(daca_client, 1, 8);
119 daca_set_volume(cur_left_vol >> 5, cur_right_vol >> 5);
120
121 /* Write the global config reg - invert right power amp,
122 * DAC on, enter low-power mode, use 5-volt mode
123 */
124 i2c_smbus_write_byte_data(daca_client, 3, 0x65);
125
126 return 0;
127}
128
129static int daca_attach_adapter(struct i2c_adapter *adapter)
130{
131 if (!strncmp(adapter->name, "mac-io", 6))
132 daca_detect_client(adapter, 0x4d);
133 return 0;
134}
135
136static int daca_init_client(struct i2c_client * new_client)
137{
138 /*
139 * Probe is not working with the current i2c-keywest
140 * driver. We try to use addr 0x4d on each adapters
141 * instead, by setting the format register.
142 *
143 * FIXME: I'm sure that can be obtained from the
144 * device-tree. --BenH.
145 */
146
147 /* Write the global config reg - invert right power amp,
148 * DAC on, use 5-volt mode
149 */
150 if (i2c_smbus_write_byte_data(new_client, 3, 0x45))
151 return -1;
152
153 i2c_smbus_write_byte_data(new_client, 1, 8);
154 daca_client = new_client;
155 daca_set_volume(15000, 15000);
156
157 return 0;
158}
159
160static int daca_detect_client(struct i2c_adapter *adapter, int address)
161{
162 const char *client_name = "DAC 3550A Digital Equalizer";
163 struct i2c_client *new_client;
164 int rc = -ENODEV;
165
166 new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
167 if (!new_client)
168 return -ENOMEM;
169 memset(new_client, 0, sizeof(*new_client));
170
171 new_client->addr = address;
172 new_client->adapter = adapter;
173 new_client->driver = &daca_driver;
174 new_client->flags = 0;
175 strcpy(new_client->name, client_name);
176
177 if (daca_init_client(new_client))
178 goto bail;
179
180 /* Tell the i2c layer a new client has arrived */
181 if (i2c_attach_client(new_client))
182 goto bail;
183
184 return 0;
185 bail:
186 kfree(new_client);
187 return rc;
188}
189
190
191static int daca_detach_client(struct i2c_client *client)
192{
193 if (client == daca_client)
194 daca_client = NULL;
195
196 i2c_detach_client(client);
197 kfree(client);
198 return 0;
199}
200
201void daca_cleanup(void)
202{
203 i2c_del_driver(&daca_driver);
204}
205
206int daca_init(void)
207{
208 printk("dac3550a driver version %s (%s)\n",DACA_VERSION,DACA_DATE);
209 return i2c_add_driver(&daca_driver);
210}
diff --git a/sound/oss/dmasound/dmasound.h b/sound/oss/dmasound/dmasound.h
new file mode 100644
index 000000000000..9a2f50f0b184
--- /dev/null
+++ b/sound/oss/dmasound/dmasound.h
@@ -0,0 +1,277 @@
1#ifndef _dmasound_h_
2/*
3 * linux/sound/oss/dmasound/dmasound.h
4 *
5 *
6 * Minor numbers for the sound driver.
7 *
8 * Unfortunately Creative called the codec chip of SB as a DSP. For this
9 * reason the /dev/dsp is reserved for digitized audio use. There is a
10 * device for true DSP processors but it will be called something else.
11 * In v3.0 it's /dev/sndproc but this could be a temporary solution.
12 */
13#define _dmasound_h_
14
15#include <linux/types.h>
16#include <linux/config.h>
17
18#define SND_NDEVS 256 /* Number of supported devices */
19#define SND_DEV_CTL 0 /* Control port /dev/mixer */
20#define SND_DEV_SEQ 1 /* Sequencer output /dev/sequencer (FM
21 synthesizer and MIDI output) */
22#define SND_DEV_MIDIN 2 /* Raw midi access */
23#define SND_DEV_DSP 3 /* Digitized voice /dev/dsp */
24#define SND_DEV_AUDIO 4 /* Sparc compatible /dev/audio */
25#define SND_DEV_DSP16 5 /* Like /dev/dsp but 16 bits/sample */
26#define SND_DEV_STATUS 6 /* /dev/sndstat */
27/* #7 not in use now. Was in 2.4. Free for use after v3.0. */
28#define SND_DEV_SEQ2 8 /* /dev/sequencer, level 2 interface */
29#define SND_DEV_SNDPROC 9 /* /dev/sndproc for programmable devices */
30#define SND_DEV_PSS SND_DEV_SNDPROC
31
32/* switch on various prinks */
33#define DEBUG_DMASOUND 1
34
35#define MAX_AUDIO_DEV 5
36#define MAX_MIXER_DEV 4
37#define MAX_SYNTH_DEV 3
38#define MAX_MIDI_DEV 6
39#define MAX_TIMER_DEV 3
40
41#define MAX_CATCH_RADIUS 10
42
43#define le2be16(x) (((x)<<8 & 0xff00) | ((x)>>8 & 0x00ff))
44#define le2be16dbl(x) (((x)<<8 & 0xff00ff00) | ((x)>>8 & 0x00ff00ff))
45
46#define IOCTL_IN(arg, ret) \
47 do { int error = get_user(ret, (int __user *)(arg)); \
48 if (error) return error; \
49 } while (0)
50#define IOCTL_OUT(arg, ret) ioctl_return((int __user *)(arg), ret)
51
52static inline int ioctl_return(int __user *addr, int value)
53{
54 return value < 0 ? value : put_user(value, addr);
55}
56
57
58 /*
59 * Configuration
60 */
61
62#undef HAS_8BIT_TABLES
63#undef HAS_RECORD
64
65#if defined(CONFIG_DMASOUND_ATARI) || defined(CONFIG_DMASOUND_ATARI_MODULE) ||\
66 defined(CONFIG_DMASOUND_PAULA) || defined(CONFIG_DMASOUND_PAULA_MODULE) ||\
67 defined(CONFIG_DMASOUND_Q40) || defined(CONFIG_DMASOUND_Q40_MODULE)
68#define HAS_8BIT_TABLES
69#define MIN_BUFFERS 4
70#define MIN_BUFSIZE (1<<12) /* in bytes (- where does this come from ?) */
71#define MIN_FRAG_SIZE 8 /* not 100% sure about this */
72#define MAX_BUFSIZE (1<<17) /* Limit for Amiga is 128 kb */
73#define MAX_FRAG_SIZE 15 /* allow *4 for mono-8 => stereo-16 (for multi) */
74
75#else /* is pmac and multi is off */
76
77#define MIN_BUFFERS 2
78#define MIN_BUFSIZE (1<<8) /* in bytes */
79#define MIN_FRAG_SIZE 8
80#define MAX_BUFSIZE (1<<18) /* this is somewhat arbitrary for pmac */
81#define MAX_FRAG_SIZE 16 /* need to allow *4 for mono-8 => stereo-16 */
82#endif
83
84#define DEFAULT_N_BUFFERS 4
85#define DEFAULT_BUFF_SIZE (1<<15)
86
87#if defined(CONFIG_DMASOUND_PMAC) || defined(CONFIG_DMASOUND_PMAC_MODULE)
88#define HAS_RECORD
89#endif
90
91 /*
92 * Initialization
93 */
94
95extern int dmasound_init(void);
96#ifdef MODULE
97extern void dmasound_deinit(void);
98#else
99#define dmasound_deinit() do { } while (0)
100#endif
101
102/* description of the set-up applies to either hard or soft settings */
103
104typedef struct {
105 int format; /* AFMT_* */
106 int stereo; /* 0 = mono, 1 = stereo */
107 int size; /* 8/16 bit*/
108 int speed; /* speed */
109} SETTINGS;
110
111 /*
112 * Machine definitions
113 */
114
115typedef struct {
116 const char *name;
117 const char *name2;
118 struct module *owner;
119 void *(*dma_alloc)(unsigned int, int);
120 void (*dma_free)(void *, unsigned int);
121 int (*irqinit)(void);
122#ifdef MODULE
123 void (*irqcleanup)(void);
124#endif
125 void (*init)(void);
126 void (*silence)(void);
127 int (*setFormat)(int);
128 int (*setVolume)(int);
129 int (*setBass)(int);
130 int (*setTreble)(int);
131 int (*setGain)(int);
132 void (*play)(void);
133 void (*record)(void); /* optional */
134 void (*mixer_init)(void); /* optional */
135 int (*mixer_ioctl)(u_int, u_long); /* optional */
136 int (*write_sq_setup)(void); /* optional */
137 int (*read_sq_setup)(void); /* optional */
138 int (*sq_open)(mode_t); /* optional */
139 int (*state_info)(char *, size_t); /* optional */
140 void (*abort_read)(void); /* optional */
141 int min_dsp_speed;
142 int max_dsp_speed;
143 int version ;
144 int hardware_afmts ; /* OSS says we only return h'ware info */
145 /* when queried via SNDCTL_DSP_GETFMTS */
146 int capabilities ; /* low-level reply to SNDCTL_DSP_GETCAPS */
147 SETTINGS default_hard ; /* open() or init() should set something valid */
148 SETTINGS default_soft ; /* you can make it look like old OSS, if you want to */
149} MACHINE;
150
151 /*
152 * Low level stuff
153 */
154
155typedef struct {
156 ssize_t (*ct_ulaw)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
157 ssize_t (*ct_alaw)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
158 ssize_t (*ct_s8)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
159 ssize_t (*ct_u8)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
160 ssize_t (*ct_s16be)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
161 ssize_t (*ct_u16be)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
162 ssize_t (*ct_s16le)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
163 ssize_t (*ct_u16le)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
164} TRANS;
165
166struct sound_settings {
167 MACHINE mach; /* machine dependent things */
168 SETTINGS hard; /* hardware settings */
169 SETTINGS soft; /* software settings */
170 SETTINGS dsp; /* /dev/dsp default settings */
171 TRANS *trans_write; /* supported translations */
172#ifdef HAS_RECORD
173 TRANS *trans_read; /* supported translations */
174#endif
175 int volume_left; /* volume (range is machine dependent) */
176 int volume_right;
177 int bass; /* tone (range is machine dependent) */
178 int treble;
179 int gain;
180 int minDev; /* minor device number currently open */
181 spinlock_t lock;
182};
183
184extern struct sound_settings dmasound;
185
186#ifdef HAS_8BIT_TABLES
187extern char dmasound_ulaw2dma8[];
188extern char dmasound_alaw2dma8[];
189#endif
190
191 /*
192 * Mid level stuff
193 */
194
195static inline int dmasound_set_volume(int volume)
196{
197 return dmasound.mach.setVolume(volume);
198}
199
200static inline int dmasound_set_bass(int bass)
201{
202 return dmasound.mach.setBass ? dmasound.mach.setBass(bass) : 50;
203}
204
205static inline int dmasound_set_treble(int treble)
206{
207 return dmasound.mach.setTreble ? dmasound.mach.setTreble(treble) : 50;
208}
209
210static inline int dmasound_set_gain(int gain)
211{
212 return dmasound.mach.setGain ? dmasound.mach.setGain(gain) : 100;
213}
214
215
216 /*
217 * Sound queue stuff, the heart of the driver
218 */
219
220struct sound_queue {
221 /* buffers allocated for this queue */
222 int numBufs; /* real limits on what the user can have */
223 int bufSize; /* in bytes */
224 char **buffers;
225
226 /* current parameters */
227 int locked ; /* params cannot be modified when != 0 */
228 int user_frags ; /* user requests this many */
229 int user_frag_size ; /* of this size */
230 int max_count; /* actual # fragments <= numBufs */
231 int block_size; /* internal block size in bytes */
232 int max_active; /* in-use fragments <= max_count */
233
234 /* it shouldn't be necessary to declare any of these volatile */
235 int front, rear, count;
236 int rear_size;
237 /*
238 * The use of the playing field depends on the hardware
239 *
240 * Atari, PMac: The number of frames that are loaded/playing
241 *
242 * Amiga: Bit 0 is set: a frame is loaded
243 * Bit 1 is set: a frame is playing
244 */
245 int active;
246 wait_queue_head_t action_queue, open_queue, sync_queue;
247 int open_mode;
248 int busy, syncing, xruns, died;
249};
250
251#define SLEEP(queue) interruptible_sleep_on_timeout(&queue, HZ)
252#define WAKE_UP(queue) (wake_up_interruptible(&queue))
253
254extern struct sound_queue dmasound_write_sq;
255#define write_sq dmasound_write_sq
256
257#ifdef HAS_RECORD
258extern struct sound_queue dmasound_read_sq;
259#define read_sq dmasound_read_sq
260#endif
261
262extern int dmasound_catchRadius;
263#define catchRadius dmasound_catchRadius
264
265/* define the value to be put in the byte-swap reg in mac-io
266 when we want it to swap for us.
267*/
268#define BS_VAL 1
269
270#define SW_INPUT_VOLUME_SCALE 4
271#define SW_INPUT_VOLUME_DEFAULT (128 / SW_INPUT_VOLUME_SCALE)
272
273extern int expand_bal; /* Balance factor for expanding (not volume!) */
274extern int expand_read_bal; /* Balance factor for reading */
275extern uint software_input_volume; /* software implemented recording volume! */
276
277#endif /* _dmasound_h_ */
diff --git a/sound/oss/dmasound/dmasound_atari.c b/sound/oss/dmasound/dmasound_atari.c
new file mode 100644
index 000000000000..8daaf87664ba
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_atari.c
@@ -0,0 +1,1600 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_atari.c
3 *
4 * Atari TT and Falcon DMA Sound Driver
5 *
6 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
7 * prior to 28/01/2001
8 *
9 * 28/01/2001 [0.1] Iain Sandoe
10 * - added versioning
11 * - put in and populated the hardware_afmts field.
12 * [0.2] - put in SNDCTL_DSP_GETCAPS value.
13 * 01/02/2001 [0.3] - put in default hard/soft settings.
14 */
15
16
17#include <linux/module.h>
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/soundcard.h>
21#include <linux/mm.h>
22#include <linux/spinlock.h>
23#include <linux/interrupt.h>
24
25#include <asm/uaccess.h>
26#include <asm/atariints.h>
27#include <asm/atari_stram.h>
28
29#include "dmasound.h"
30
31#define DMASOUND_ATARI_REVISION 0
32#define DMASOUND_ATARI_EDITION 3
33
34extern void atari_microwire_cmd(int cmd);
35
36static int is_falcon;
37static int write_sq_ignore_int; /* ++TeSche: used for Falcon */
38
39static int expand_bal; /* Balance factor for expanding (not volume!) */
40static int expand_data; /* Data for expanding */
41
42
43/*** Translations ************************************************************/
44
45
46/* ++TeSche: radically changed for new expanding purposes...
47 *
48 * These two routines now deal with copying/expanding/translating the samples
49 * from user space into our buffer at the right frequency. They take care about
50 * how much data there's actually to read, how much buffer space there is and
51 * to convert samples into the right frequency/encoding. They will only work on
52 * complete samples so it may happen they leave some bytes in the input stream
53 * if the user didn't write a multiple of the current sample size. They both
54 * return the number of bytes they've used from both streams so you may detect
55 * such a situation. Luckily all programs should be able to cope with that.
56 *
57 * I think I've optimized anything as far as one can do in plain C, all
58 * variables should fit in registers and the loops are really short. There's
59 * one loop for every possible situation. Writing a more generalized and thus
60 * parameterized loop would only produce slower code. Feel free to optimize
61 * this in assembler if you like. :)
62 *
63 * I think these routines belong here because they're not yet really hardware
64 * independent, especially the fact that the Falcon can play 16bit samples
65 * only in stereo is hardcoded in both of them!
66 *
67 * ++geert: split in even more functions (one per format)
68 */
69
70static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
71 u_char frame[], ssize_t *frameUsed,
72 ssize_t frameLeft);
73static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
74 u_char frame[], ssize_t *frameUsed,
75 ssize_t frameLeft);
76static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
77 u_char frame[], ssize_t *frameUsed,
78 ssize_t frameLeft);
79static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
80 u_char frame[], ssize_t *frameUsed,
81 ssize_t frameLeft);
82static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
83 u_char frame[], ssize_t *frameUsed,
84 ssize_t frameLeft);
85static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
86 u_char frame[], ssize_t *frameUsed,
87 ssize_t frameLeft);
88static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
89 u_char frame[], ssize_t *frameUsed,
90 ssize_t frameLeft);
91static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
92 u_char frame[], ssize_t *frameUsed,
93 ssize_t frameLeft);
94static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
95 u_char frame[], ssize_t *frameUsed,
96 ssize_t frameLeft);
97static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
98 u_char frame[], ssize_t *frameUsed,
99 ssize_t frameLeft);
100static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
101 u_char frame[], ssize_t *frameUsed,
102 ssize_t frameLeft);
103static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
104 u_char frame[], ssize_t *frameUsed,
105 ssize_t frameLeft);
106static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
107 u_char frame[], ssize_t *frameUsed,
108 ssize_t frameLeft);
109static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
110 u_char frame[], ssize_t *frameUsed,
111 ssize_t frameLeft);
112
113
114/*** Low level stuff *********************************************************/
115
116
117static void *AtaAlloc(unsigned int size, int flags);
118static void AtaFree(void *, unsigned int size);
119static int AtaIrqInit(void);
120#ifdef MODULE
121static void AtaIrqCleanUp(void);
122#endif /* MODULE */
123static int AtaSetBass(int bass);
124static int AtaSetTreble(int treble);
125static void TTSilence(void);
126static void TTInit(void);
127static int TTSetFormat(int format);
128static int TTSetVolume(int volume);
129static int TTSetGain(int gain);
130static void FalconSilence(void);
131static void FalconInit(void);
132static int FalconSetFormat(int format);
133static int FalconSetVolume(int volume);
134static void AtaPlayNextFrame(int index);
135static void AtaPlay(void);
136static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp);
137
138/*** Mid level stuff *********************************************************/
139
140static void TTMixerInit(void);
141static void FalconMixerInit(void);
142static int AtaMixerIoctl(u_int cmd, u_long arg);
143static int TTMixerIoctl(u_int cmd, u_long arg);
144static int FalconMixerIoctl(u_int cmd, u_long arg);
145static int AtaWriteSqSetup(void);
146static int AtaSqOpen(mode_t mode);
147static int TTStateInfo(char *buffer, size_t space);
148static int FalconStateInfo(char *buffer, size_t space);
149
150
151/*** Translations ************************************************************/
152
153
154static ssize_t ata_ct_law(const u_char *userPtr, size_t userCount,
155 u_char frame[], ssize_t *frameUsed,
156 ssize_t frameLeft)
157{
158 char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
159 : dmasound_alaw2dma8;
160 ssize_t count, used;
161 u_char *p = &frame[*frameUsed];
162
163 count = min_t(unsigned long, userCount, frameLeft);
164 if (dmasound.soft.stereo)
165 count &= ~1;
166 used = count;
167 while (count > 0) {
168 u_char data;
169 if (get_user(data, userPtr++))
170 return -EFAULT;
171 *p++ = table[data];
172 count--;
173 }
174 *frameUsed += used;
175 return used;
176}
177
178
179static ssize_t ata_ct_s8(const u_char *userPtr, size_t userCount,
180 u_char frame[], ssize_t *frameUsed,
181 ssize_t frameLeft)
182{
183 ssize_t count, used;
184 void *p = &frame[*frameUsed];
185
186 count = min_t(unsigned long, userCount, frameLeft);
187 if (dmasound.soft.stereo)
188 count &= ~1;
189 used = count;
190 if (copy_from_user(p, userPtr, count))
191 return -EFAULT;
192 *frameUsed += used;
193 return used;
194}
195
196
197static ssize_t ata_ct_u8(const u_char *userPtr, size_t userCount,
198 u_char frame[], ssize_t *frameUsed,
199 ssize_t frameLeft)
200{
201 ssize_t count, used;
202
203 if (!dmasound.soft.stereo) {
204 u_char *p = &frame[*frameUsed];
205 count = min_t(unsigned long, userCount, frameLeft);
206 used = count;
207 while (count > 0) {
208 u_char data;
209 if (get_user(data, userPtr++))
210 return -EFAULT;
211 *p++ = data ^ 0x80;
212 count--;
213 }
214 } else {
215 u_short *p = (u_short *)&frame[*frameUsed];
216 count = min_t(unsigned long, userCount, frameLeft)>>1;
217 used = count*2;
218 while (count > 0) {
219 u_short data;
220 if (get_user(data, ((u_short *)userPtr)++))
221 return -EFAULT;
222 *p++ = data ^ 0x8080;
223 count--;
224 }
225 }
226 *frameUsed += used;
227 return used;
228}
229
230
231static ssize_t ata_ct_s16be(const u_char *userPtr, size_t userCount,
232 u_char frame[], ssize_t *frameUsed,
233 ssize_t frameLeft)
234{
235 ssize_t count, used;
236
237 if (!dmasound.soft.stereo) {
238 u_short *p = (u_short *)&frame[*frameUsed];
239 count = min_t(unsigned long, userCount, frameLeft)>>1;
240 used = count*2;
241 while (count > 0) {
242 u_short data;
243 if (get_user(data, ((u_short *)userPtr)++))
244 return -EFAULT;
245 *p++ = data;
246 *p++ = data;
247 count--;
248 }
249 *frameUsed += used*2;
250 } else {
251 void *p = (u_short *)&frame[*frameUsed];
252 count = min_t(unsigned long, userCount, frameLeft) & ~3;
253 used = count;
254 if (copy_from_user(p, userPtr, count))
255 return -EFAULT;
256 *frameUsed += used;
257 }
258 return used;
259}
260
261
262static ssize_t ata_ct_u16be(const u_char *userPtr, size_t userCount,
263 u_char frame[], ssize_t *frameUsed,
264 ssize_t frameLeft)
265{
266 ssize_t count, used;
267
268 if (!dmasound.soft.stereo) {
269 u_short *p = (u_short *)&frame[*frameUsed];
270 count = min_t(unsigned long, userCount, frameLeft)>>1;
271 used = count*2;
272 while (count > 0) {
273 u_short data;
274 if (get_user(data, ((u_short *)userPtr)++))
275 return -EFAULT;
276 data ^= 0x8000;
277 *p++ = data;
278 *p++ = data;
279 count--;
280 }
281 *frameUsed += used*2;
282 } else {
283 u_long *p = (u_long *)&frame[*frameUsed];
284 count = min_t(unsigned long, userCount, frameLeft)>>2;
285 used = count*4;
286 while (count > 0) {
287 u_long data;
288 if (get_user(data, ((u_int *)userPtr)++))
289 return -EFAULT;
290 *p++ = data ^ 0x80008000;
291 count--;
292 }
293 *frameUsed += used;
294 }
295 return used;
296}
297
298
299static ssize_t ata_ct_s16le(const u_char *userPtr, size_t userCount,
300 u_char frame[], ssize_t *frameUsed,
301 ssize_t frameLeft)
302{
303 ssize_t count, used;
304
305 count = frameLeft;
306 if (!dmasound.soft.stereo) {
307 u_short *p = (u_short *)&frame[*frameUsed];
308 count = min_t(unsigned long, userCount, frameLeft)>>1;
309 used = count*2;
310 while (count > 0) {
311 u_short data;
312 if (get_user(data, ((u_short *)userPtr)++))
313 return -EFAULT;
314 data = le2be16(data);
315 *p++ = data;
316 *p++ = data;
317 count--;
318 }
319 *frameUsed += used*2;
320 } else {
321 u_long *p = (u_long *)&frame[*frameUsed];
322 count = min_t(unsigned long, userCount, frameLeft)>>2;
323 used = count*4;
324 while (count > 0) {
325 u_long data;
326 if (get_user(data, ((u_int *)userPtr)++))
327 return -EFAULT;
328 data = le2be16dbl(data);
329 *p++ = data;
330 count--;
331 }
332 *frameUsed += used;
333 }
334 return used;
335}
336
337
338static ssize_t ata_ct_u16le(const u_char *userPtr, size_t userCount,
339 u_char frame[], ssize_t *frameUsed,
340 ssize_t frameLeft)
341{
342 ssize_t count, used;
343
344 count = frameLeft;
345 if (!dmasound.soft.stereo) {
346 u_short *p = (u_short *)&frame[*frameUsed];
347 count = min_t(unsigned long, userCount, frameLeft)>>1;
348 used = count*2;
349 while (count > 0) {
350 u_short data;
351 if (get_user(data, ((u_short *)userPtr)++))
352 return -EFAULT;
353 data = le2be16(data) ^ 0x8000;
354 *p++ = data;
355 *p++ = data;
356 }
357 *frameUsed += used*2;
358 } else {
359 u_long *p = (u_long *)&frame[*frameUsed];
360 count = min_t(unsigned long, userCount, frameLeft)>>2;
361 used = count;
362 while (count > 0) {
363 u_long data;
364 if (get_user(data, ((u_int *)userPtr)++))
365 return -EFAULT;
366 data = le2be16dbl(data) ^ 0x80008000;
367 *p++ = data;
368 count--;
369 }
370 *frameUsed += used;
371 }
372 return used;
373}
374
375
376static ssize_t ata_ctx_law(const u_char *userPtr, size_t userCount,
377 u_char frame[], ssize_t *frameUsed,
378 ssize_t frameLeft)
379{
380 char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8
381 : dmasound_alaw2dma8;
382 /* this should help gcc to stuff everything into registers */
383 long bal = expand_bal;
384 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
385 ssize_t used, usedf;
386
387 used = userCount;
388 usedf = frameLeft;
389 if (!dmasound.soft.stereo) {
390 u_char *p = &frame[*frameUsed];
391 u_char data = expand_data;
392 while (frameLeft) {
393 u_char c;
394 if (bal < 0) {
395 if (!userCount)
396 break;
397 if (get_user(c, userPtr++))
398 return -EFAULT;
399 data = table[c];
400 userCount--;
401 bal += hSpeed;
402 }
403 *p++ = data;
404 frameLeft--;
405 bal -= sSpeed;
406 }
407 expand_data = data;
408 } else {
409 u_short *p = (u_short *)&frame[*frameUsed];
410 u_short data = expand_data;
411 while (frameLeft >= 2) {
412 u_char c;
413 if (bal < 0) {
414 if (userCount < 2)
415 break;
416 if (get_user(c, userPtr++))
417 return -EFAULT;
418 data = table[c] << 8;
419 if (get_user(c, userPtr++))
420 return -EFAULT;
421 data |= table[c];
422 userCount -= 2;
423 bal += hSpeed;
424 }
425 *p++ = data;
426 frameLeft -= 2;
427 bal -= sSpeed;
428 }
429 expand_data = data;
430 }
431 expand_bal = bal;
432 used -= userCount;
433 *frameUsed += usedf-frameLeft;
434 return used;
435}
436
437
438static ssize_t ata_ctx_s8(const u_char *userPtr, size_t userCount,
439 u_char frame[], ssize_t *frameUsed,
440 ssize_t frameLeft)
441{
442 /* this should help gcc to stuff everything into registers */
443 long bal = expand_bal;
444 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
445 ssize_t used, usedf;
446
447 used = userCount;
448 usedf = frameLeft;
449 if (!dmasound.soft.stereo) {
450 u_char *p = &frame[*frameUsed];
451 u_char data = expand_data;
452 while (frameLeft) {
453 if (bal < 0) {
454 if (!userCount)
455 break;
456 if (get_user(data, userPtr++))
457 return -EFAULT;
458 userCount--;
459 bal += hSpeed;
460 }
461 *p++ = data;
462 frameLeft--;
463 bal -= sSpeed;
464 }
465 expand_data = data;
466 } else {
467 u_short *p = (u_short *)&frame[*frameUsed];
468 u_short data = expand_data;
469 while (frameLeft >= 2) {
470 if (bal < 0) {
471 if (userCount < 2)
472 break;
473 if (get_user(data, ((u_short *)userPtr)++))
474 return -EFAULT;
475 userCount -= 2;
476 bal += hSpeed;
477 }
478 *p++ = data;
479 frameLeft -= 2;
480 bal -= sSpeed;
481 }
482 expand_data = data;
483 }
484 expand_bal = bal;
485 used -= userCount;
486 *frameUsed += usedf-frameLeft;
487 return used;
488}
489
490
491static ssize_t ata_ctx_u8(const u_char *userPtr, size_t userCount,
492 u_char frame[], ssize_t *frameUsed,
493 ssize_t frameLeft)
494{
495 /* this should help gcc to stuff everything into registers */
496 long bal = expand_bal;
497 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
498 ssize_t used, usedf;
499
500 used = userCount;
501 usedf = frameLeft;
502 if (!dmasound.soft.stereo) {
503 u_char *p = &frame[*frameUsed];
504 u_char data = expand_data;
505 while (frameLeft) {
506 if (bal < 0) {
507 if (!userCount)
508 break;
509 if (get_user(data, userPtr++))
510 return -EFAULT;
511 data ^= 0x80;
512 userCount--;
513 bal += hSpeed;
514 }
515 *p++ = data;
516 frameLeft--;
517 bal -= sSpeed;
518 }
519 expand_data = data;
520 } else {
521 u_short *p = (u_short *)&frame[*frameUsed];
522 u_short data = expand_data;
523 while (frameLeft >= 2) {
524 if (bal < 0) {
525 if (userCount < 2)
526 break;
527 if (get_user(data, ((u_short *)userPtr)++))
528 return -EFAULT;
529 data ^= 0x8080;
530 userCount -= 2;
531 bal += hSpeed;
532 }
533 *p++ = data;
534 frameLeft -= 2;
535 bal -= sSpeed;
536 }
537 expand_data = data;
538 }
539 expand_bal = bal;
540 used -= userCount;
541 *frameUsed += usedf-frameLeft;
542 return used;
543}
544
545
546static ssize_t ata_ctx_s16be(const u_char *userPtr, size_t userCount,
547 u_char frame[], ssize_t *frameUsed,
548 ssize_t frameLeft)
549{
550 /* this should help gcc to stuff everything into registers */
551 long bal = expand_bal;
552 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
553 ssize_t used, usedf;
554
555 used = userCount;
556 usedf = frameLeft;
557 if (!dmasound.soft.stereo) {
558 u_short *p = (u_short *)&frame[*frameUsed];
559 u_short data = expand_data;
560 while (frameLeft >= 4) {
561 if (bal < 0) {
562 if (userCount < 2)
563 break;
564 if (get_user(data, ((u_short *)userPtr)++))
565 return -EFAULT;
566 userCount -= 2;
567 bal += hSpeed;
568 }
569 *p++ = data;
570 *p++ = data;
571 frameLeft -= 4;
572 bal -= sSpeed;
573 }
574 expand_data = data;
575 } else {
576 u_long *p = (u_long *)&frame[*frameUsed];
577 u_long data = expand_data;
578 while (frameLeft >= 4) {
579 if (bal < 0) {
580 if (userCount < 4)
581 break;
582 if (get_user(data, ((u_int *)userPtr)++))
583 return -EFAULT;
584 userCount -= 4;
585 bal += hSpeed;
586 }
587 *p++ = data;
588 frameLeft -= 4;
589 bal -= sSpeed;
590 }
591 expand_data = data;
592 }
593 expand_bal = bal;
594 used -= userCount;
595 *frameUsed += usedf-frameLeft;
596 return used;
597}
598
599
600static ssize_t ata_ctx_u16be(const u_char *userPtr, size_t userCount,
601 u_char frame[], ssize_t *frameUsed,
602 ssize_t frameLeft)
603{
604 /* this should help gcc to stuff everything into registers */
605 long bal = expand_bal;
606 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
607 ssize_t used, usedf;
608
609 used = userCount;
610 usedf = frameLeft;
611 if (!dmasound.soft.stereo) {
612 u_short *p = (u_short *)&frame[*frameUsed];
613 u_short data = expand_data;
614 while (frameLeft >= 4) {
615 if (bal < 0) {
616 if (userCount < 2)
617 break;
618 if (get_user(data, ((u_short *)userPtr)++))
619 return -EFAULT;
620 data ^= 0x8000;
621 userCount -= 2;
622 bal += hSpeed;
623 }
624 *p++ = data;
625 *p++ = data;
626 frameLeft -= 4;
627 bal -= sSpeed;
628 }
629 expand_data = data;
630 } else {
631 u_long *p = (u_long *)&frame[*frameUsed];
632 u_long data = expand_data;
633 while (frameLeft >= 4) {
634 if (bal < 0) {
635 if (userCount < 4)
636 break;
637 if (get_user(data, ((u_int *)userPtr)++))
638 return -EFAULT;
639 data ^= 0x80008000;
640 userCount -= 4;
641 bal += hSpeed;
642 }
643 *p++ = data;
644 frameLeft -= 4;
645 bal -= sSpeed;
646 }
647 expand_data = data;
648 }
649 expand_bal = bal;
650 used -= userCount;
651 *frameUsed += usedf-frameLeft;
652 return used;
653}
654
655
656static ssize_t ata_ctx_s16le(const u_char *userPtr, size_t userCount,
657 u_char frame[], ssize_t *frameUsed,
658 ssize_t frameLeft)
659{
660 /* this should help gcc to stuff everything into registers */
661 long bal = expand_bal;
662 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
663 ssize_t used, usedf;
664
665 used = userCount;
666 usedf = frameLeft;
667 if (!dmasound.soft.stereo) {
668 u_short *p = (u_short *)&frame[*frameUsed];
669 u_short data = expand_data;
670 while (frameLeft >= 4) {
671 if (bal < 0) {
672 if (userCount < 2)
673 break;
674 if (get_user(data, ((u_short *)userPtr)++))
675 return -EFAULT;
676 data = le2be16(data);
677 userCount -= 2;
678 bal += hSpeed;
679 }
680 *p++ = data;
681 *p++ = data;
682 frameLeft -= 4;
683 bal -= sSpeed;
684 }
685 expand_data = data;
686 } else {
687 u_long *p = (u_long *)&frame[*frameUsed];
688 u_long data = expand_data;
689 while (frameLeft >= 4) {
690 if (bal < 0) {
691 if (userCount < 4)
692 break;
693 if (get_user(data, ((u_int *)userPtr)++))
694 return -EFAULT;
695 data = le2be16dbl(data);
696 userCount -= 4;
697 bal += hSpeed;
698 }
699 *p++ = data;
700 frameLeft -= 4;
701 bal -= sSpeed;
702 }
703 expand_data = data;
704 }
705 expand_bal = bal;
706 used -= userCount;
707 *frameUsed += usedf-frameLeft;
708 return used;
709}
710
711
712static ssize_t ata_ctx_u16le(const u_char *userPtr, size_t userCount,
713 u_char frame[], ssize_t *frameUsed,
714 ssize_t frameLeft)
715{
716 /* this should help gcc to stuff everything into registers */
717 long bal = expand_bal;
718 long hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
719 ssize_t used, usedf;
720
721 used = userCount;
722 usedf = frameLeft;
723 if (!dmasound.soft.stereo) {
724 u_short *p = (u_short *)&frame[*frameUsed];
725 u_short data = expand_data;
726 while (frameLeft >= 4) {
727 if (bal < 0) {
728 if (userCount < 2)
729 break;
730 if (get_user(data, ((u_short *)userPtr)++))
731 return -EFAULT;
732 data = le2be16(data) ^ 0x8000;
733 userCount -= 2;
734 bal += hSpeed;
735 }
736 *p++ = data;
737 *p++ = data;
738 frameLeft -= 4;
739 bal -= sSpeed;
740 }
741 expand_data = data;
742 } else {
743 u_long *p = (u_long *)&frame[*frameUsed];
744 u_long data = expand_data;
745 while (frameLeft >= 4) {
746 if (bal < 0) {
747 if (userCount < 4)
748 break;
749 if (get_user(data, ((u_int *)userPtr)++))
750 return -EFAULT;
751 data = le2be16dbl(data) ^ 0x80008000;
752 userCount -= 4;
753 bal += hSpeed;
754 }
755 *p++ = data;
756 frameLeft -= 4;
757 bal -= sSpeed;
758 }
759 expand_data = data;
760 }
761 expand_bal = bal;
762 used -= userCount;
763 *frameUsed += usedf-frameLeft;
764 return used;
765}
766
767
768static TRANS transTTNormal = {
769 .ct_ulaw = ata_ct_law,
770 .ct_alaw = ata_ct_law,
771 .ct_s8 = ata_ct_s8,
772 .ct_u8 = ata_ct_u8,
773};
774
775static TRANS transTTExpanding = {
776 .ct_ulaw = ata_ctx_law,
777 .ct_alaw = ata_ctx_law,
778 .ct_s8 = ata_ctx_s8,
779 .ct_u8 = ata_ctx_u8,
780};
781
782static TRANS transFalconNormal = {
783 .ct_ulaw = ata_ct_law,
784 .ct_alaw = ata_ct_law,
785 .ct_s8 = ata_ct_s8,
786 .ct_u8 = ata_ct_u8,
787 .ct_s16be = ata_ct_s16be,
788 .ct_u16be = ata_ct_u16be,
789 .ct_s16le = ata_ct_s16le,
790 .ct_u16le = ata_ct_u16le
791};
792
793static TRANS transFalconExpanding = {
794 .ct_ulaw = ata_ctx_law,
795 .ct_alaw = ata_ctx_law,
796 .ct_s8 = ata_ctx_s8,
797 .ct_u8 = ata_ctx_u8,
798 .ct_s16be = ata_ctx_s16be,
799 .ct_u16be = ata_ctx_u16be,
800 .ct_s16le = ata_ctx_s16le,
801 .ct_u16le = ata_ctx_u16le,
802};
803
804
805/*** Low level stuff *********************************************************/
806
807
808
809/*
810 * Atari (TT/Falcon)
811 */
812
813static void *AtaAlloc(unsigned int size, int flags)
814{
815 return atari_stram_alloc(size, "dmasound");
816}
817
818static void AtaFree(void *obj, unsigned int size)
819{
820 atari_stram_free( obj );
821}
822
823static int __init AtaIrqInit(void)
824{
825 /* Set up timer A. Timer A
826 will receive a signal upon end of playing from the sound
827 hardware. Furthermore Timer A is able to count events
828 and will cause an interrupt after a programmed number
829 of events. So all we need to keep the music playing is
830 to provide the sound hardware with new data upon
831 an interrupt from timer A. */
832 mfp.tim_ct_a = 0; /* ++roman: Stop timer before programming! */
833 mfp.tim_dt_a = 1; /* Cause interrupt after first event. */
834 mfp.tim_ct_a = 8; /* Turn on event counting. */
835 /* Register interrupt handler. */
836 request_irq(IRQ_MFP_TIMA, AtaInterrupt, IRQ_TYPE_SLOW, "DMA sound",
837 AtaInterrupt);
838 mfp.int_en_a |= 0x20; /* Turn interrupt on. */
839 mfp.int_mk_a |= 0x20;
840 return 1;
841}
842
843#ifdef MODULE
844static void AtaIrqCleanUp(void)
845{
846 mfp.tim_ct_a = 0; /* stop timer */
847 mfp.int_en_a &= ~0x20; /* turn interrupt off */
848 free_irq(IRQ_MFP_TIMA, AtaInterrupt);
849}
850#endif /* MODULE */
851
852
853#define TONE_VOXWARE_TO_DB(v) \
854 (((v) < 0) ? -12 : ((v) > 100) ? 12 : ((v) - 50) * 6 / 25)
855#define TONE_DB_TO_VOXWARE(v) (((v) * 25 + ((v) > 0 ? 5 : -5)) / 6 + 50)
856
857
858static int AtaSetBass(int bass)
859{
860 dmasound.bass = TONE_VOXWARE_TO_DB(bass);
861 atari_microwire_cmd(MW_LM1992_BASS(dmasound.bass));
862 return TONE_DB_TO_VOXWARE(dmasound.bass);
863}
864
865
866static int AtaSetTreble(int treble)
867{
868 dmasound.treble = TONE_VOXWARE_TO_DB(treble);
869 atari_microwire_cmd(MW_LM1992_TREBLE(dmasound.treble));
870 return TONE_DB_TO_VOXWARE(dmasound.treble);
871}
872
873
874
875/*
876 * TT
877 */
878
879
880static void TTSilence(void)
881{
882 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
883 atari_microwire_cmd(MW_LM1992_PSG_HIGH); /* mix in PSG signal 1:1 */
884}
885
886
887static void TTInit(void)
888{
889 int mode, i, idx;
890 const int freq[4] = {50066, 25033, 12517, 6258};
891
892 /* search a frequency that fits into the allowed error range */
893
894 idx = -1;
895 for (i = 0; i < ARRAY_SIZE(freq); i++)
896 /* this isn't as much useful for a TT than for a Falcon, but
897 * then it doesn't hurt very much to implement it for a TT too.
898 */
899 if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
900 idx = i;
901 if (idx > -1) {
902 dmasound.soft.speed = freq[idx];
903 dmasound.trans_write = &transTTNormal;
904 } else
905 dmasound.trans_write = &transTTExpanding;
906
907 TTSilence();
908 dmasound.hard = dmasound.soft;
909
910 if (dmasound.hard.speed > 50066) {
911 /* we would need to squeeze the sound, but we won't do that */
912 dmasound.hard.speed = 50066;
913 mode = DMASND_MODE_50KHZ;
914 dmasound.trans_write = &transTTNormal;
915 } else if (dmasound.hard.speed > 25033) {
916 dmasound.hard.speed = 50066;
917 mode = DMASND_MODE_50KHZ;
918 } else if (dmasound.hard.speed > 12517) {
919 dmasound.hard.speed = 25033;
920 mode = DMASND_MODE_25KHZ;
921 } else if (dmasound.hard.speed > 6258) {
922 dmasound.hard.speed = 12517;
923 mode = DMASND_MODE_12KHZ;
924 } else {
925 dmasound.hard.speed = 6258;
926 mode = DMASND_MODE_6KHZ;
927 }
928
929 tt_dmasnd.mode = (dmasound.hard.stereo ?
930 DMASND_MODE_STEREO : DMASND_MODE_MONO) |
931 DMASND_MODE_8BIT | mode;
932
933 expand_bal = -dmasound.soft.speed;
934}
935
936
937static int TTSetFormat(int format)
938{
939 /* TT sound DMA supports only 8bit modes */
940
941 switch (format) {
942 case AFMT_QUERY:
943 return dmasound.soft.format;
944 case AFMT_MU_LAW:
945 case AFMT_A_LAW:
946 case AFMT_S8:
947 case AFMT_U8:
948 break;
949 default:
950 format = AFMT_S8;
951 }
952
953 dmasound.soft.format = format;
954 dmasound.soft.size = 8;
955 if (dmasound.minDev == SND_DEV_DSP) {
956 dmasound.dsp.format = format;
957 dmasound.dsp.size = 8;
958 }
959 TTInit();
960
961 return format;
962}
963
964
965#define VOLUME_VOXWARE_TO_DB(v) \
966 (((v) < 0) ? -40 : ((v) > 100) ? 0 : ((v) * 2) / 5 - 40)
967#define VOLUME_DB_TO_VOXWARE(v) ((((v) + 40) * 5 + 1) / 2)
968
969
970static int TTSetVolume(int volume)
971{
972 dmasound.volume_left = VOLUME_VOXWARE_TO_DB(volume & 0xff);
973 atari_microwire_cmd(MW_LM1992_BALLEFT(dmasound.volume_left));
974 dmasound.volume_right = VOLUME_VOXWARE_TO_DB((volume & 0xff00) >> 8);
975 atari_microwire_cmd(MW_LM1992_BALRIGHT(dmasound.volume_right));
976 return VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
977 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8);
978}
979
980
981#define GAIN_VOXWARE_TO_DB(v) \
982 (((v) < 0) ? -80 : ((v) > 100) ? 0 : ((v) * 4) / 5 - 80)
983#define GAIN_DB_TO_VOXWARE(v) ((((v) + 80) * 5 + 1) / 4)
984
985static int TTSetGain(int gain)
986{
987 dmasound.gain = GAIN_VOXWARE_TO_DB(gain);
988 atari_microwire_cmd(MW_LM1992_VOLUME(dmasound.gain));
989 return GAIN_DB_TO_VOXWARE(dmasound.gain);
990}
991
992
993
994/*
995 * Falcon
996 */
997
998
999static void FalconSilence(void)
1000{
1001 /* stop playback, set sample rate 50kHz for PSG sound */
1002 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1003 tt_dmasnd.mode = DMASND_MODE_50KHZ | DMASND_MODE_STEREO | DMASND_MODE_8BIT;
1004 tt_dmasnd.int_div = 0; /* STE compatible divider */
1005 tt_dmasnd.int_ctrl = 0x0;
1006 tt_dmasnd.cbar_src = 0x0000; /* no matrix inputs */
1007 tt_dmasnd.cbar_dst = 0x0000; /* no matrix outputs */
1008 tt_dmasnd.dac_src = 1; /* connect ADC to DAC, disconnect matrix */
1009 tt_dmasnd.adc_src = 3; /* ADC Input = PSG */
1010}
1011
1012
1013static void FalconInit(void)
1014{
1015 int divider, i, idx;
1016 const int freq[8] = {49170, 32780, 24585, 19668, 16390, 12292, 9834, 8195};
1017
1018 /* search a frequency that fits into the allowed error range */
1019
1020 idx = -1;
1021 for (i = 0; i < ARRAY_SIZE(freq); i++)
1022 /* if we will tolerate 3% error 8000Hz->8195Hz (2.38%) would
1023 * be playable without expanding, but that now a kernel runtime
1024 * option
1025 */
1026 if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) < catchRadius)
1027 idx = i;
1028 if (idx > -1) {
1029 dmasound.soft.speed = freq[idx];
1030 dmasound.trans_write = &transFalconNormal;
1031 } else
1032 dmasound.trans_write = &transFalconExpanding;
1033
1034 FalconSilence();
1035 dmasound.hard = dmasound.soft;
1036
1037 if (dmasound.hard.size == 16) {
1038 /* the Falcon can play 16bit samples only in stereo */
1039 dmasound.hard.stereo = 1;
1040 }
1041
1042 if (dmasound.hard.speed > 49170) {
1043 /* we would need to squeeze the sound, but we won't do that */
1044 dmasound.hard.speed = 49170;
1045 divider = 1;
1046 dmasound.trans_write = &transFalconNormal;
1047 } else if (dmasound.hard.speed > 32780) {
1048 dmasound.hard.speed = 49170;
1049 divider = 1;
1050 } else if (dmasound.hard.speed > 24585) {
1051 dmasound.hard.speed = 32780;
1052 divider = 2;
1053 } else if (dmasound.hard.speed > 19668) {
1054 dmasound.hard.speed = 24585;
1055 divider = 3;
1056 } else if (dmasound.hard.speed > 16390) {
1057 dmasound.hard.speed = 19668;
1058 divider = 4;
1059 } else if (dmasound.hard.speed > 12292) {
1060 dmasound.hard.speed = 16390;
1061 divider = 5;
1062 } else if (dmasound.hard.speed > 9834) {
1063 dmasound.hard.speed = 12292;
1064 divider = 7;
1065 } else if (dmasound.hard.speed > 8195) {
1066 dmasound.hard.speed = 9834;
1067 divider = 9;
1068 } else {
1069 dmasound.hard.speed = 8195;
1070 divider = 11;
1071 }
1072 tt_dmasnd.int_div = divider;
1073
1074 /* Setup Falcon sound DMA for playback */
1075 tt_dmasnd.int_ctrl = 0x4; /* Timer A int at play end */
1076 tt_dmasnd.track_select = 0x0; /* play 1 track, track 1 */
1077 tt_dmasnd.cbar_src = 0x0001; /* DMA(25MHz) --> DAC */
1078 tt_dmasnd.cbar_dst = 0x0000;
1079 tt_dmasnd.rec_track_select = 0;
1080 tt_dmasnd.dac_src = 2; /* connect matrix to DAC */
1081 tt_dmasnd.adc_src = 0; /* ADC Input = Mic */
1082
1083 tt_dmasnd.mode = (dmasound.hard.stereo ?
1084 DMASND_MODE_STEREO : DMASND_MODE_MONO) |
1085 ((dmasound.hard.size == 8) ?
1086 DMASND_MODE_8BIT : DMASND_MODE_16BIT) |
1087 DMASND_MODE_6KHZ;
1088
1089 expand_bal = -dmasound.soft.speed;
1090}
1091
1092
1093static int FalconSetFormat(int format)
1094{
1095 int size;
1096 /* Falcon sound DMA supports 8bit and 16bit modes */
1097
1098 switch (format) {
1099 case AFMT_QUERY:
1100 return dmasound.soft.format;
1101 case AFMT_MU_LAW:
1102 case AFMT_A_LAW:
1103 case AFMT_U8:
1104 case AFMT_S8:
1105 size = 8;
1106 break;
1107 case AFMT_S16_BE:
1108 case AFMT_U16_BE:
1109 case AFMT_S16_LE:
1110 case AFMT_U16_LE:
1111 size = 16;
1112 break;
1113 default: /* :-) */
1114 size = 8;
1115 format = AFMT_S8;
1116 }
1117
1118 dmasound.soft.format = format;
1119 dmasound.soft.size = size;
1120 if (dmasound.minDev == SND_DEV_DSP) {
1121 dmasound.dsp.format = format;
1122 dmasound.dsp.size = dmasound.soft.size;
1123 }
1124
1125 FalconInit();
1126
1127 return format;
1128}
1129
1130
1131/* This is for the Falcon output *attenuation* in 1.5dB steps,
1132 * i.e. output level from 0 to -22.5dB in -1.5dB steps.
1133 */
1134#define VOLUME_VOXWARE_TO_ATT(v) \
1135 ((v) < 0 ? 15 : (v) > 100 ? 0 : 15 - (v) * 3 / 20)
1136#define VOLUME_ATT_TO_VOXWARE(v) (100 - (v) * 20 / 3)
1137
1138
1139static int FalconSetVolume(int volume)
1140{
1141 dmasound.volume_left = VOLUME_VOXWARE_TO_ATT(volume & 0xff);
1142 dmasound.volume_right = VOLUME_VOXWARE_TO_ATT((volume & 0xff00) >> 8);
1143 tt_dmasnd.output_atten = dmasound.volume_left << 8 | dmasound.volume_right << 4;
1144 return VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1145 VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8;
1146}
1147
1148
1149static void AtaPlayNextFrame(int index)
1150{
1151 char *start, *end;
1152
1153 /* used by AtaPlay() if all doubts whether there really is something
1154 * to be played are already wiped out.
1155 */
1156 start = write_sq.buffers[write_sq.front];
1157 end = start+((write_sq.count == index) ? write_sq.rear_size
1158 : write_sq.block_size);
1159 /* end might not be a legal virtual address. */
1160 DMASNDSetEnd(virt_to_phys(end - 1) + 1);
1161 DMASNDSetBase(virt_to_phys(start));
1162 /* Since only an even number of samples per frame can
1163 be played, we might lose one byte here. (TO DO) */
1164 write_sq.front = (write_sq.front+1) % write_sq.max_count;
1165 write_sq.active++;
1166 tt_dmasnd.ctrl = DMASND_CTRL_ON | DMASND_CTRL_REPEAT;
1167}
1168
1169
1170static void AtaPlay(void)
1171{
1172 /* ++TeSche: Note that write_sq.active is no longer just a flag but
1173 * holds the number of frames the DMA is currently programmed for
1174 * instead, may be 0, 1 (currently being played) or 2 (pre-programmed).
1175 *
1176 * Changes done to write_sq.count and write_sq.active are a bit more
1177 * subtle again so now I must admit I also prefer disabling the irq
1178 * here rather than considering all possible situations. But the point
1179 * is that disabling the irq doesn't have any bad influence on this
1180 * version of the driver as we benefit from having pre-programmed the
1181 * DMA wherever possible: There's no need to reload the DMA at the
1182 * exact time of an interrupt but only at some time while the
1183 * pre-programmed frame is playing!
1184 */
1185 atari_disable_irq(IRQ_MFP_TIMA);
1186
1187 if (write_sq.active == 2 || /* DMA is 'full' */
1188 write_sq.count <= 0) { /* nothing to do */
1189 atari_enable_irq(IRQ_MFP_TIMA);
1190 return;
1191 }
1192
1193 if (write_sq.active == 0) {
1194 /* looks like there's nothing 'in' the DMA yet, so try
1195 * to put two frames into it (at least one is available).
1196 */
1197 if (write_sq.count == 1 &&
1198 write_sq.rear_size < write_sq.block_size &&
1199 !write_sq.syncing) {
1200 /* hmmm, the only existing frame is not
1201 * yet filled and we're not syncing?
1202 */
1203 atari_enable_irq(IRQ_MFP_TIMA);
1204 return;
1205 }
1206 AtaPlayNextFrame(1);
1207 if (write_sq.count == 1) {
1208 /* no more frames */
1209 atari_enable_irq(IRQ_MFP_TIMA);
1210 return;
1211 }
1212 if (write_sq.count == 2 &&
1213 write_sq.rear_size < write_sq.block_size &&
1214 !write_sq.syncing) {
1215 /* hmmm, there were two frames, but the second
1216 * one is not yet filled and we're not syncing?
1217 */
1218 atari_enable_irq(IRQ_MFP_TIMA);
1219 return;
1220 }
1221 AtaPlayNextFrame(2);
1222 } else {
1223 /* there's already a frame being played so we may only stuff
1224 * one new into the DMA, but even if this may be the last
1225 * frame existing the previous one is still on write_sq.count.
1226 */
1227 if (write_sq.count == 2 &&
1228 write_sq.rear_size < write_sq.block_size &&
1229 !write_sq.syncing) {
1230 /* hmmm, the only existing frame is not
1231 * yet filled and we're not syncing?
1232 */
1233 atari_enable_irq(IRQ_MFP_TIMA);
1234 return;
1235 }
1236 AtaPlayNextFrame(2);
1237 }
1238 atari_enable_irq(IRQ_MFP_TIMA);
1239}
1240
1241
1242static irqreturn_t AtaInterrupt(int irq, void *dummy, struct pt_regs *fp)
1243{
1244#if 0
1245 /* ++TeSche: if you should want to test this... */
1246 static int cnt;
1247 if (write_sq.active == 2)
1248 if (++cnt == 10) {
1249 /* simulate losing an interrupt */
1250 cnt = 0;
1251 return IRQ_HANDLED;
1252 }
1253#endif
1254 spin_lock(&dmasound.lock);
1255 if (write_sq_ignore_int && is_falcon) {
1256 /* ++TeSche: Falcon only: ignore first irq because it comes
1257 * immediately after starting a frame. after that, irqs come
1258 * (almost) like on the TT.
1259 */
1260 write_sq_ignore_int = 0;
1261 return IRQ_HANDLED;
1262 }
1263
1264 if (!write_sq.active) {
1265 /* playing was interrupted and sq_reset() has already cleared
1266 * the sq variables, so better don't do anything here.
1267 */
1268 WAKE_UP(write_sq.sync_queue);
1269 return IRQ_HANDLED;
1270 }
1271
1272 /* Probably ;) one frame is finished. Well, in fact it may be that a
1273 * pre-programmed one is also finished because there has been a long
1274 * delay in interrupt delivery and we've completely lost one, but
1275 * there's no way to detect such a situation. In such a case the last
1276 * frame will be played more than once and the situation will recover
1277 * as soon as the irq gets through.
1278 */
1279 write_sq.count--;
1280 write_sq.active--;
1281
1282 if (!write_sq.active) {
1283 tt_dmasnd.ctrl = DMASND_CTRL_OFF;
1284 write_sq_ignore_int = 1;
1285 }
1286
1287 WAKE_UP(write_sq.action_queue);
1288 /* At least one block of the queue is free now
1289 so wake up a writing process blocked because
1290 of a full queue. */
1291
1292 if ((write_sq.active != 1) || (write_sq.count != 1))
1293 /* We must be a bit carefully here: write_sq.count indicates the
1294 * number of buffers used and not the number of frames to be
1295 * played. If write_sq.count==1 and write_sq.active==1 that
1296 * means the only remaining frame was already programmed
1297 * earlier (and is currently running) so we mustn't call
1298 * AtaPlay() here, otherwise we'll play one frame too much.
1299 */
1300 AtaPlay();
1301
1302 if (!write_sq.active) WAKE_UP(write_sq.sync_queue);
1303 /* We are not playing after AtaPlay(), so there
1304 is nothing to play any more. Wake up a process
1305 waiting for audio output to drain. */
1306 spin_unlock(&dmasound.lock);
1307 return IRQ_HANDLED;
1308}
1309
1310
1311/*** Mid level stuff *********************************************************/
1312
1313
1314/*
1315 * /dev/mixer abstraction
1316 */
1317
1318#define RECLEVEL_VOXWARE_TO_GAIN(v) \
1319 ((v) < 0 ? 0 : (v) > 100 ? 15 : (v) * 3 / 20)
1320#define RECLEVEL_GAIN_TO_VOXWARE(v) (((v) * 20 + 2) / 3)
1321
1322
1323static void __init TTMixerInit(void)
1324{
1325 atari_microwire_cmd(MW_LM1992_VOLUME(0));
1326 dmasound.volume_left = 0;
1327 atari_microwire_cmd(MW_LM1992_BALLEFT(0));
1328 dmasound.volume_right = 0;
1329 atari_microwire_cmd(MW_LM1992_BALRIGHT(0));
1330 atari_microwire_cmd(MW_LM1992_TREBLE(0));
1331 atari_microwire_cmd(MW_LM1992_BASS(0));
1332}
1333
1334static void __init FalconMixerInit(void)
1335{
1336 dmasound.volume_left = (tt_dmasnd.output_atten & 0xf00) >> 8;
1337 dmasound.volume_right = (tt_dmasnd.output_atten & 0xf0) >> 4;
1338}
1339
1340static int AtaMixerIoctl(u_int cmd, u_long arg)
1341{
1342 int data;
1343 unsigned long flags;
1344 switch (cmd) {
1345 case SOUND_MIXER_READ_SPEAKER:
1346 if (is_falcon || MACH_IS_TT) {
1347 int porta;
1348 spin_lock_irqsave(&dmasound.lock, flags);
1349 sound_ym.rd_data_reg_sel = 14;
1350 porta = sound_ym.rd_data_reg_sel;
1351 spin_unlock_irqrestore(&dmasound.lock, flags);
1352 return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1353 }
1354 break;
1355 case SOUND_MIXER_WRITE_VOLUME:
1356 IOCTL_IN(arg, data);
1357 return IOCTL_OUT(arg, dmasound_set_volume(data));
1358 case SOUND_MIXER_WRITE_SPEAKER:
1359 if (is_falcon || MACH_IS_TT) {
1360 int porta;
1361 IOCTL_IN(arg, data);
1362 spin_lock_irqsave(&dmasound.lock, flags);
1363 sound_ym.rd_data_reg_sel = 14;
1364 porta = (sound_ym.rd_data_reg_sel & ~0x40) |
1365 (data < 50 ? 0x40 : 0);
1366 sound_ym.wd_data = porta;
1367 spin_unlock_irqrestore(&dmasound.lock, flags);
1368 return IOCTL_OUT(arg, porta & 0x40 ? 0 : 100);
1369 }
1370 }
1371 return -EINVAL;
1372}
1373
1374
1375static int TTMixerIoctl(u_int cmd, u_long arg)
1376{
1377 int data;
1378 switch (cmd) {
1379 case SOUND_MIXER_READ_RECMASK:
1380 return IOCTL_OUT(arg, 0);
1381 case SOUND_MIXER_READ_DEVMASK:
1382 return IOCTL_OUT(arg,
1383 SOUND_MASK_VOLUME | SOUND_MASK_TREBLE | SOUND_MASK_BASS |
1384 (MACH_IS_TT ? SOUND_MASK_SPEAKER : 0));
1385 case SOUND_MIXER_READ_STEREODEVS:
1386 return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
1387 case SOUND_MIXER_READ_VOLUME:
1388 return IOCTL_OUT(arg,
1389 VOLUME_DB_TO_VOXWARE(dmasound.volume_left) |
1390 (VOLUME_DB_TO_VOXWARE(dmasound.volume_right) << 8));
1391 case SOUND_MIXER_READ_BASS:
1392 return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.bass));
1393 case SOUND_MIXER_READ_TREBLE:
1394 return IOCTL_OUT(arg, TONE_DB_TO_VOXWARE(dmasound.treble));
1395 case SOUND_MIXER_READ_OGAIN:
1396 return IOCTL_OUT(arg, GAIN_DB_TO_VOXWARE(dmasound.gain));
1397 case SOUND_MIXER_WRITE_BASS:
1398 IOCTL_IN(arg, data);
1399 return IOCTL_OUT(arg, dmasound_set_bass(data));
1400 case SOUND_MIXER_WRITE_TREBLE:
1401 IOCTL_IN(arg, data);
1402 return IOCTL_OUT(arg, dmasound_set_treble(data));
1403 case SOUND_MIXER_WRITE_OGAIN:
1404 IOCTL_IN(arg, data);
1405 return IOCTL_OUT(arg, dmasound_set_gain(data));
1406 }
1407 return AtaMixerIoctl(cmd, arg);
1408}
1409
1410static int FalconMixerIoctl(u_int cmd, u_long arg)
1411{
1412 int data;
1413 switch (cmd) {
1414 case SOUND_MIXER_READ_RECMASK:
1415 return IOCTL_OUT(arg, SOUND_MASK_MIC);
1416 case SOUND_MIXER_READ_DEVMASK:
1417 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC | SOUND_MASK_SPEAKER);
1418 case SOUND_MIXER_READ_STEREODEVS:
1419 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_MIC);
1420 case SOUND_MIXER_READ_VOLUME:
1421 return IOCTL_OUT(arg,
1422 VOLUME_ATT_TO_VOXWARE(dmasound.volume_left) |
1423 VOLUME_ATT_TO_VOXWARE(dmasound.volume_right) << 8);
1424 case SOUND_MIXER_READ_CAPS:
1425 return IOCTL_OUT(arg, SOUND_CAP_EXCL_INPUT);
1426 case SOUND_MIXER_WRITE_MIC:
1427 IOCTL_IN(arg, data);
1428 tt_dmasnd.input_gain =
1429 RECLEVEL_VOXWARE_TO_GAIN(data & 0xff) << 4 |
1430 RECLEVEL_VOXWARE_TO_GAIN(data >> 8 & 0xff);
1431 /* fall thru, return set value */
1432 case SOUND_MIXER_READ_MIC:
1433 return IOCTL_OUT(arg,
1434 RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain >> 4 & 0xf) |
1435 RECLEVEL_GAIN_TO_VOXWARE(tt_dmasnd.input_gain & 0xf) << 8);
1436 }
1437 return AtaMixerIoctl(cmd, arg);
1438}
1439
1440static int AtaWriteSqSetup(void)
1441{
1442 write_sq_ignore_int = 0;
1443 return 0 ;
1444}
1445
1446static int AtaSqOpen(mode_t mode)
1447{
1448 write_sq_ignore_int = 1;
1449 return 0 ;
1450}
1451
1452static int TTStateInfo(char *buffer, size_t space)
1453{
1454 int len = 0;
1455 len += sprintf(buffer+len, "\tvol left %ddB [-40... 0]\n",
1456 dmasound.volume_left);
1457 len += sprintf(buffer+len, "\tvol right %ddB [-40... 0]\n",
1458 dmasound.volume_right);
1459 len += sprintf(buffer+len, "\tbass %ddB [-12...+12]\n",
1460 dmasound.bass);
1461 len += sprintf(buffer+len, "\ttreble %ddB [-12...+12]\n",
1462 dmasound.treble);
1463 if (len >= space) {
1464 printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1465 len = space ;
1466 }
1467 return len;
1468}
1469
1470static int FalconStateInfo(char *buffer, size_t space)
1471{
1472 int len = 0;
1473 len += sprintf(buffer+len, "\tvol left %ddB [-22.5 ... 0]\n",
1474 dmasound.volume_left);
1475 len += sprintf(buffer+len, "\tvol right %ddB [-22.5 ... 0]\n",
1476 dmasound.volume_right);
1477 if (len >= space) {
1478 printk(KERN_ERR "dmasound_atari: overflowed state buffer alloc.\n") ;
1479 len = space ;
1480 }
1481 return len;
1482}
1483
1484
1485/*** Machine definitions *****************************************************/
1486
1487static SETTINGS def_hard_falcon = {
1488 .format = AFMT_S8,
1489 .stereo = 0,
1490 .size = 8,
1491 .speed = 8195
1492} ;
1493
1494static SETTINGS def_hard_tt = {
1495 .format = AFMT_S8,
1496 .stereo = 0,
1497 .size = 8,
1498 .speed = 12517
1499} ;
1500
1501static SETTINGS def_soft = {
1502 .format = AFMT_U8,
1503 .stereo = 0,
1504 .size = 8,
1505 .speed = 8000
1506} ;
1507
1508static MACHINE machTT = {
1509 .name = "Atari",
1510 .name2 = "TT",
1511 .owner = THIS_MODULE,
1512 .dma_alloc = AtaAlloc,
1513 .dma_free = AtaFree,
1514 .irqinit = AtaIrqInit,
1515#ifdef MODULE
1516 .irqcleanup = AtaIrqCleanUp,
1517#endif /* MODULE */
1518 .init = TTInit,
1519 .silence = TTSilence,
1520 .setFormat = TTSetFormat,
1521 .setVolume = TTSetVolume,
1522 .setBass = AtaSetBass,
1523 .setTreble = AtaSetTreble,
1524 .setGain = TTSetGain,
1525 .play = AtaPlay,
1526 .mixer_init = TTMixerInit,
1527 .mixer_ioctl = TTMixerIoctl,
1528 .write_sq_setup = AtaWriteSqSetup,
1529 .sq_open = AtaSqOpen,
1530 .state_info = TTStateInfo,
1531 .min_dsp_speed = 6258,
1532 .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1533 .hardware_afmts = AFMT_S8, /* h'ware-supported formats *only* here */
1534 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
1535};
1536
1537static MACHINE machFalcon = {
1538 .name = "Atari",
1539 .name2 = "FALCON",
1540 .dma_alloc = AtaAlloc,
1541 .dma_free = AtaFree,
1542 .irqinit = AtaIrqInit,
1543#ifdef MODULE
1544 .irqcleanup = AtaIrqCleanUp,
1545#endif /* MODULE */
1546 .init = FalconInit,
1547 .silence = FalconSilence,
1548 .setFormat = FalconSetFormat,
1549 .setVolume = FalconSetVolume,
1550 .setBass = AtaSetBass,
1551 .setTreble = AtaSetTreble,
1552 .play = AtaPlay,
1553 .mixer_init = FalconMixerInit,
1554 .mixer_ioctl = FalconMixerIoctl,
1555 .write_sq_setup = AtaWriteSqSetup,
1556 .sq_open = AtaSqOpen,
1557 .state_info = FalconStateInfo,
1558 .min_dsp_speed = 8195,
1559 .version = ((DMASOUND_ATARI_REVISION<<8) | DMASOUND_ATARI_EDITION),
1560 .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
1561 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
1562};
1563
1564
1565/*** Config & Setup **********************************************************/
1566
1567
1568static int __init dmasound_atari_init(void)
1569{
1570 if (MACH_IS_ATARI && ATARIHW_PRESENT(PCM_8BIT)) {
1571 if (ATARIHW_PRESENT(CODEC)) {
1572 dmasound.mach = machFalcon;
1573 dmasound.mach.default_soft = def_soft ;
1574 dmasound.mach.default_hard = def_hard_falcon ;
1575 is_falcon = 1;
1576 } else if (ATARIHW_PRESENT(MICROWIRE)) {
1577 dmasound.mach = machTT;
1578 dmasound.mach.default_soft = def_soft ;
1579 dmasound.mach.default_hard = def_hard_tt ;
1580 is_falcon = 0;
1581 } else
1582 return -ENODEV;
1583 if ((mfp.int_en_a & mfp.int_mk_a & 0x20) == 0)
1584 return dmasound_init();
1585 else {
1586 printk("DMA sound driver: Timer A interrupt already in use\n");
1587 return -EBUSY;
1588 }
1589 }
1590 return -ENODEV;
1591}
1592
1593static void __exit dmasound_atari_cleanup(void)
1594{
1595 dmasound_deinit();
1596}
1597
1598module_init(dmasound_atari_init);
1599module_exit(dmasound_atari_cleanup);
1600MODULE_LICENSE("GPL");
diff --git a/sound/oss/dmasound/dmasound_awacs.c b/sound/oss/dmasound/dmasound_awacs.c
new file mode 100644
index 000000000000..5281b88987f3
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_awacs.c
@@ -0,0 +1,3176 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_awacs.c
3 *
4 * PowerMac `AWACS' and `Burgundy' DMA Sound Driver
5 * with some limited support for DACA & Tumbler
6 *
7 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and
8 * history prior to 2001/01/26.
9 *
10 * 26/01/2001 ed 0.1 Iain Sandoe
11 * - added version info.
12 * - moved dbdma command buffer allocation to PMacXXXSqSetup()
13 * - fixed up beep dbdma cmd buffers
14 *
15 * 08/02/2001 [0.2]
16 * - make SNDCTL_DSP_GETFMTS return the correct info for the h/w
17 * - move soft format translations to a separate file
18 * - [0.3] make SNDCTL_DSP_GETCAPS return correct info.
19 * - [0.4] more informative machine name strings.
20 * - [0.5]
21 * - record changes.
22 * - made the default_hard/soft entries.
23 * 04/04/2001 [0.6]
24 * - minor correction to bit assignments in awacs_defs.h
25 * - incorporate mixer changes from 2.2.x back-port.
26 * - take out passthru as a rec input (it isn't).
27 * - make Input Gain slider work the 'right way up'.
28 * - try to make the mixer sliders more logical - so now the
29 * input selectors are just two-state (>50% == ON) and the
30 * Input Gain slider handles the rest of the gain issues.
31 * - try to pick slider representations that most closely match
32 * the actual use - e.g. IGain for input gain...
33 * - first stab at over/under-run detection.
34 * - minor cosmetic changes to IRQ identification.
35 * - fix bug where rates > max would be reported as supported.
36 * - first stab at over/under-run detection.
37 * - make use of i2c for mixer settings conditional on perch
38 * rather than cuda (some machines without perch have cuda).
39 * - fix bug where TX stops when dbdma status comes up "DEAD"
40 * so far only reported on PowerComputing clones ... but.
41 * - put in AWACS/Screamer register write timeouts.
42 * - part way to partitioning the init() stuff
43 * - first pass at 'tumbler' stuff (not support - just an attempt
44 * to allow the driver to load on new G4s).
45 * 01/02/2002 [0.7] - BenH
46 * - all sort of minor bits went in since the latest update, I
47 * bumped the version number for that reason
48 *
49 * 07/26/2002 [0.8] - BenH
50 * - More minor bits since last changelog (I should be more careful
51 * with those)
52 * - Support for snapper & better tumbler integration by Toby Sargeant
53 * - Headphone detect for scremer by Julien Blache
54 * - More tumbler fixed by Andreas Schwab
55 * 11/29/2003 [0.8.1] - Renzo Davoli (King Enzo)
56 * - Support for Snapper line in
57 * - snapper input resampling (for rates < 44100)
58 * - software line gain control
59 */
60
61/* GENERAL FIXME/TODO: check that the assumptions about what is written to
62 mac-io is valid for DACA & Tumbler.
63
64 This driver is in bad need of a rewrite. The dbdma code has to be split,
65 some proper device-tree parsing code has to be written, etc...
66*/
67
68#include <linux/types.h>
69#include <linux/module.h>
70#include <linux/config.h>
71#include <linux/slab.h>
72#include <linux/init.h>
73#include <linux/delay.h>
74#include <linux/soundcard.h>
75#include <linux/adb.h>
76#include <linux/nvram.h>
77#include <linux/tty.h>
78#include <linux/vt_kern.h>
79#include <linux/spinlock.h>
80#include <linux/kmod.h>
81#include <linux/interrupt.h>
82#include <linux/input.h>
83#include <asm/semaphore.h>
84#ifdef CONFIG_ADB_CUDA
85#include <linux/cuda.h>
86#endif
87#ifdef CONFIG_ADB_PMU
88#include <linux/pmu.h>
89#endif
90
91#include <linux/i2c-dev.h>
92
93#include <asm/uaccess.h>
94#include <asm/prom.h>
95#include <asm/machdep.h>
96#include <asm/io.h>
97#include <asm/dbdma.h>
98#include <asm/pmac_feature.h>
99#include <asm/irq.h>
100#include <asm/nvram.h>
101
102#include "awacs_defs.h"
103#include "dmasound.h"
104#include "tas3001c.h"
105#include "tas3004.h"
106#include "tas_common.h"
107
108#define DMASOUND_AWACS_REVISION 0
109#define DMASOUND_AWACS_EDITION 7
110
111#define AWACS_SNAPPER 110 /* fake revision # for snapper */
112#define AWACS_BURGUNDY 100 /* fake revision # for burgundy */
113#define AWACS_TUMBLER 90 /* fake revision # for tumbler */
114#define AWACS_DACA 80 /* fake revision # for daca (ibook) */
115#define AWACS_AWACS 2 /* holding revision for AWACS */
116#define AWACS_SCREAMER 3 /* holding revision for Screamer */
117/*
118 * Interrupt numbers and addresses, & info obtained from the device tree.
119 */
120static int awacs_irq, awacs_tx_irq, awacs_rx_irq;
121static volatile struct awacs_regs __iomem *awacs;
122static volatile u32 __iomem *i2s;
123static volatile struct dbdma_regs __iomem *awacs_txdma, *awacs_rxdma;
124static int awacs_rate_index;
125static int awacs_subframe;
126static struct device_node* awacs_node;
127static struct device_node* i2s_node;
128
129static char awacs_name[64];
130static int awacs_revision;
131static int awacs_sleeping;
132static DECLARE_MUTEX(dmasound_sem);
133
134static int sound_device_id; /* exists after iMac revA */
135static int hw_can_byteswap = 1 ; /* most pmac sound h/w can */
136
137/* model info */
138/* To be replaced with better interaction with pmac_feature.c */
139static int is_pbook_3X00;
140static int is_pbook_g3;
141
142/* expansion info */
143static int has_perch;
144static int has_ziva;
145
146/* for earlier powerbooks which need fiddling with mac-io to enable
147 * cd etc.
148*/
149static unsigned char __iomem *latch_base;
150static unsigned char __iomem *macio_base;
151
152/*
153 * Space for the DBDMA command blocks.
154 */
155static void *awacs_tx_cmd_space;
156static volatile struct dbdma_cmd *awacs_tx_cmds;
157static int number_of_tx_cmd_buffers;
158
159static void *awacs_rx_cmd_space;
160static volatile struct dbdma_cmd *awacs_rx_cmds;
161static int number_of_rx_cmd_buffers;
162
163/*
164 * Cached values of AWACS registers (we can't read them).
165 * Except on the burgundy (and screamer). XXX
166 */
167
168int awacs_reg[8];
169int awacs_reg1_save;
170
171/* tracking values for the mixer contents
172*/
173
174static int spk_vol;
175static int line_vol;
176static int passthru_vol;
177
178static int ip_gain; /* mic preamp settings */
179static int rec_lev = 0x4545 ; /* default CD gain 69 % */
180static int mic_lev;
181static int cd_lev = 0x6363 ; /* 99 % */
182static int line_lev;
183
184static int hdp_connected;
185
186/*
187 * Stuff for outputting a beep. The values range from -327 to +327
188 * so we can multiply by an amplitude in the range 0..100 to get a
189 * signed short value to put in the output buffer.
190 */
191static short beep_wform[256] = {
192 0, 40, 79, 117, 153, 187, 218, 245,
193 269, 288, 304, 316, 323, 327, 327, 324,
194 318, 310, 299, 288, 275, 262, 249, 236,
195 224, 213, 204, 196, 190, 186, 183, 182,
196 182, 183, 186, 189, 192, 196, 200, 203,
197 206, 208, 209, 209, 209, 207, 204, 201,
198 197, 193, 188, 183, 179, 174, 170, 166,
199 163, 161, 160, 159, 159, 160, 161, 162,
200 164, 166, 168, 169, 171, 171, 171, 170,
201 169, 167, 163, 159, 155, 150, 144, 139,
202 133, 128, 122, 117, 113, 110, 107, 105,
203 103, 103, 103, 103, 104, 104, 105, 105,
204 105, 103, 101, 97, 92, 86, 78, 68,
205 58, 45, 32, 18, 3, -11, -26, -41,
206 -55, -68, -79, -88, -95, -100, -102, -102,
207 -99, -93, -85, -75, -62, -48, -33, -16,
208 0, 16, 33, 48, 62, 75, 85, 93,
209 99, 102, 102, 100, 95, 88, 79, 68,
210 55, 41, 26, 11, -3, -18, -32, -45,
211 -58, -68, -78, -86, -92, -97, -101, -103,
212 -105, -105, -105, -104, -104, -103, -103, -103,
213 -103, -105, -107, -110, -113, -117, -122, -128,
214 -133, -139, -144, -150, -155, -159, -163, -167,
215 -169, -170, -171, -171, -171, -169, -168, -166,
216 -164, -162, -161, -160, -159, -159, -160, -161,
217 -163, -166, -170, -174, -179, -183, -188, -193,
218 -197, -201, -204, -207, -209, -209, -209, -208,
219 -206, -203, -200, -196, -192, -189, -186, -183,
220 -182, -182, -183, -186, -190, -196, -204, -213,
221 -224, -236, -249, -262, -275, -288, -299, -310,
222 -318, -324, -327, -327, -323, -316, -304, -288,
223 -269, -245, -218, -187, -153, -117, -79, -40,
224};
225
226/* beep support */
227#define BEEP_SRATE 22050 /* 22050 Hz sample rate */
228#define BEEP_BUFLEN 512
229#define BEEP_VOLUME 15 /* 0 - 100 */
230
231static int beep_vol = BEEP_VOLUME;
232static int beep_playing;
233static int awacs_beep_state;
234static short *beep_buf;
235static void *beep_dbdma_cmd_space;
236static volatile struct dbdma_cmd *beep_dbdma_cmd;
237
238/* Burgundy functions */
239static void awacs_burgundy_wcw(unsigned addr,unsigned newval);
240static unsigned awacs_burgundy_rcw(unsigned addr);
241static void awacs_burgundy_write_volume(unsigned address, int volume);
242static int awacs_burgundy_read_volume(unsigned address);
243static void awacs_burgundy_write_mvolume(unsigned address, int volume);
244static int awacs_burgundy_read_mvolume(unsigned address);
245
246/* we will allocate a single 'emergency' dbdma cmd block to use if the
247 tx status comes up "DEAD". This happens on some PowerComputing Pmac
248 clones, either owing to a bug in dbdma or some interaction between
249 IDE and sound. However, this measure would deal with DEAD status if
250 if appeared elsewhere.
251
252 for the sake of memory efficiency we'll allocate this cmd as part of
253 the beep cmd stuff.
254*/
255
256static volatile struct dbdma_cmd *emergency_dbdma_cmd;
257
258#ifdef CONFIG_PMAC_PBOOK
259/*
260 * Stuff for restoring after a sleep.
261 */
262static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when);
263struct pmu_sleep_notifier awacs_sleep_notifier = {
264 awacs_sleep_notify, SLEEP_LEVEL_SOUND,
265};
266#endif /* CONFIG_PMAC_PBOOK */
267
268/* for (soft) sample rate translations */
269int expand_bal; /* Balance factor for expanding (not volume!) */
270int expand_read_bal; /* Balance factor for expanding reads (not volume!) */
271
272/*** Low level stuff *********************************************************/
273
274static void *PMacAlloc(unsigned int size, int flags);
275static void PMacFree(void *ptr, unsigned int size);
276static int PMacIrqInit(void);
277#ifdef MODULE
278static void PMacIrqCleanup(void);
279#endif
280static void PMacSilence(void);
281static void PMacInit(void);
282static int PMacSetFormat(int format);
283static int PMacSetVolume(int volume);
284static void PMacPlay(void);
285static void PMacRecord(void);
286static irqreturn_t pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs);
287static irqreturn_t pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs);
288static irqreturn_t pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs);
289static void awacs_write(int val);
290static int awacs_get_volume(int reg, int lshift);
291static int awacs_volume_setter(int volume, int n, int mute, int lshift);
292
293
294/*** Mid level stuff **********************************************************/
295
296static int PMacMixerIoctl(u_int cmd, u_long arg);
297static int PMacWriteSqSetup(void);
298static int PMacReadSqSetup(void);
299static void PMacAbortRead(void);
300
301extern TRANS transAwacsNormal ;
302extern TRANS transAwacsExpand ;
303extern TRANS transAwacsNormalRead ;
304extern TRANS transAwacsExpandRead ;
305
306extern int daca_init(void);
307extern void daca_cleanup(void);
308extern int daca_set_volume(uint left_vol, uint right_vol);
309extern void daca_get_volume(uint * left_vol, uint *right_vol);
310extern int daca_enter_sleep(void);
311extern int daca_leave_sleep(void);
312
313#define TRY_LOCK() \
314 if ((rc = down_interruptible(&dmasound_sem)) != 0) \
315 return rc;
316#define LOCK() down(&dmasound_sem);
317
318#define UNLOCK() up(&dmasound_sem);
319
320/* We use different versions that the ones provided in dmasound.h
321 *
322 * FIXME: Use different names ;)
323 */
324#undef IOCTL_IN
325#undef IOCTL_OUT
326
327#define IOCTL_IN(arg, ret) \
328 rc = get_user(ret, (int __user *)(arg)); \
329 if (rc) break;
330#define IOCTL_OUT(arg, ret) \
331 ioctl_return2((int __user *)(arg), ret)
332
333static inline int ioctl_return2(int __user *addr, int value)
334{
335 return value < 0 ? value : put_user(value, addr);
336}
337
338
339/*** AE - TUMBLER / SNAPPER START ************************************************/
340
341
342int gpio_audio_reset, gpio_audio_reset_pol;
343int gpio_amp_mute, gpio_amp_mute_pol;
344int gpio_headphone_mute, gpio_headphone_mute_pol;
345int gpio_headphone_detect, gpio_headphone_detect_pol;
346int gpio_headphone_irq;
347
348int
349setup_audio_gpio(const char *name, const char* compatible, int *gpio_addr, int* gpio_pol)
350{
351 struct device_node *np;
352 u32* pp;
353
354 np = find_devices("gpio");
355 if (!np)
356 return -ENODEV;
357
358 np = np->child;
359 while(np != 0) {
360 if (name) {
361 char *property = get_property(np,"audio-gpio",NULL);
362 if (property != 0 && strcmp(property,name) == 0)
363 break;
364 } else if (compatible && device_is_compatible(np, compatible))
365 break;
366 np = np->sibling;
367 }
368 if (!np)
369 return -ENODEV;
370 pp = (u32 *)get_property(np, "AAPL,address", NULL);
371 if (!pp)
372 return -ENODEV;
373 *gpio_addr = (*pp) & 0x0000ffff;
374 pp = (u32 *)get_property(np, "audio-gpio-active-state", NULL);
375 if (pp)
376 *gpio_pol = *pp;
377 else
378 *gpio_pol = 1;
379 if (np->n_intrs > 0)
380 return np->intrs[0].line;
381
382 return 0;
383}
384
385static inline void
386write_audio_gpio(int gpio_addr, int data)
387{
388 if (!gpio_addr)
389 return;
390 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_addr, data ? 0x05 : 0x04);
391}
392
393static inline int
394read_audio_gpio(int gpio_addr)
395{
396 if (!gpio_addr)
397 return 0;
398 return ((pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_addr, 0) & 0x02) !=0);
399}
400
401/*
402 * Headphone interrupt via GPIO (Tumbler, Snapper, DACA)
403 */
404static irqreturn_t
405headphone_intr(int irq, void *devid, struct pt_regs *regs)
406{
407 unsigned long flags;
408
409 spin_lock_irqsave(&dmasound.lock, flags);
410 if (read_audio_gpio(gpio_headphone_detect) == gpio_headphone_detect_pol) {
411 printk(KERN_INFO "Audio jack plugged, muting speakers.\n");
412 write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol);
413 write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
414 tas_output_device_change(sound_device_id,TAS_OUTPUT_HEADPHONES,0);
415 } else {
416 printk(KERN_INFO "Audio jack unplugged, enabling speakers.\n");
417 write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol);
418 write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
419 tas_output_device_change(sound_device_id,TAS_OUTPUT_INTERNAL_SPKR,0);
420 }
421 spin_unlock_irqrestore(&dmasound.lock, flags);
422 return IRQ_HANDLED;
423}
424
425
426/* Initialize tumbler */
427
428static int
429tas_dmasound_init(void)
430{
431 setup_audio_gpio(
432 "audio-hw-reset",
433 NULL,
434 &gpio_audio_reset,
435 &gpio_audio_reset_pol);
436 setup_audio_gpio(
437 "amp-mute",
438 NULL,
439 &gpio_amp_mute,
440 &gpio_amp_mute_pol);
441 setup_audio_gpio("headphone-mute",
442 NULL,
443 &gpio_headphone_mute,
444 &gpio_headphone_mute_pol);
445 gpio_headphone_irq = setup_audio_gpio(
446 "headphone-detect",
447 NULL,
448 &gpio_headphone_detect,
449 &gpio_headphone_detect_pol);
450 /* Fix some broken OF entries in desktop machines */
451 if (!gpio_headphone_irq)
452 gpio_headphone_irq = setup_audio_gpio(
453 NULL,
454 "keywest-gpio15",
455 &gpio_headphone_detect,
456 &gpio_headphone_detect_pol);
457
458 write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
459 msleep(100);
460 write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);
461 msleep(100);
462 if (gpio_headphone_irq) {
463 if (request_irq(gpio_headphone_irq,headphone_intr,0,"Headphone detect",NULL) < 0) {
464 printk(KERN_ERR "tumbler: Can't request headphone interrupt\n");
465 gpio_headphone_irq = 0;
466 } else {
467 u8 val;
468 /* Activate headphone status interrupts */
469 val = pmac_call_feature(PMAC_FTR_READ_GPIO, NULL, gpio_headphone_detect, 0);
470 pmac_call_feature(PMAC_FTR_WRITE_GPIO, NULL, gpio_headphone_detect, val | 0x80);
471 /* Trigger it */
472 headphone_intr(0,NULL,NULL);
473 }
474 }
475 if (!gpio_headphone_irq) {
476 /* Some machine enter this case ? */
477 printk(KERN_WARNING "tumbler: Headphone detect IRQ not found, enabling all outputs !\n");
478 write_audio_gpio(gpio_amp_mute, !gpio_amp_mute_pol);
479 write_audio_gpio(gpio_headphone_mute, !gpio_headphone_mute_pol);
480 }
481 return 0;
482}
483
484
485static int
486tas_dmasound_cleanup(void)
487{
488 if (gpio_headphone_irq)
489 free_irq(gpio_headphone_irq, NULL);
490 return 0;
491}
492
493/* We don't support 48k yet */
494static int tas_freqs[1] = { 44100 } ;
495static int tas_freqs_ok[1] = { 1 } ;
496
497/* don't know what to do really - just have to leave it where
498 * OF left things
499*/
500
501static int
502tas_set_frame_rate(void)
503{
504 if (i2s) {
505 out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);
506 out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);
507 }
508 dmasound.hard.speed = 44100 ;
509 awacs_rate_index = 0 ;
510 return 44100 ;
511}
512
513static int
514tas_mixer_ioctl(u_int cmd, u_long arg)
515{
516 int __user *argp = (int __user *)arg;
517 int data;
518 int rc;
519
520 rc=tas_device_ioctl(cmd, arg);
521 if (rc != -EINVAL) {
522 return rc;
523 }
524
525 if ((cmd & ~0xff) == MIXER_WRITE(0) &&
526 tas_supported_mixers() & (1<<(cmd & 0xff))) {
527 rc = get_user(data, argp);
528 if (rc<0) return rc;
529 tas_set_mixer_level(cmd & 0xff, data);
530 tas_get_mixer_level(cmd & 0xff, &data);
531 return ioctl_return2(argp, data);
532 }
533 if ((cmd & ~0xff) == MIXER_READ(0) &&
534 tas_supported_mixers() & (1<<(cmd & 0xff))) {
535 tas_get_mixer_level(cmd & 0xff, &data);
536 return ioctl_return2(argp, data);
537 }
538
539 switch(cmd) {
540 case SOUND_MIXER_READ_DEVMASK:
541 data = tas_supported_mixers() | SOUND_MASK_SPEAKER;
542 rc = IOCTL_OUT(arg, data);
543 break;
544 case SOUND_MIXER_READ_STEREODEVS:
545 data = tas_stereo_mixers();
546 rc = IOCTL_OUT(arg, data);
547 break;
548 case SOUND_MIXER_READ_CAPS:
549 rc = IOCTL_OUT(arg, 0);
550 break;
551 case SOUND_MIXER_READ_RECMASK:
552 // XXX FIXME: find a way to check what is really available */
553 data = SOUND_MASK_LINE | SOUND_MASK_MIC;
554 rc = IOCTL_OUT(arg, data);
555 break;
556 case SOUND_MIXER_READ_RECSRC:
557 if (awacs_reg[0] & MASK_MUX_AUDIN)
558 data |= SOUND_MASK_LINE;
559 if (awacs_reg[0] & MASK_MUX_MIC)
560 data |= SOUND_MASK_MIC;
561 rc = IOCTL_OUT(arg, data);
562 break;
563 case SOUND_MIXER_WRITE_RECSRC:
564 IOCTL_IN(arg, data);
565 data =0;
566 rc = IOCTL_OUT(arg, data);
567 break;
568 case SOUND_MIXER_WRITE_SPEAKER: /* really bell volume */
569 IOCTL_IN(arg, data);
570 beep_vol = data & 0xff;
571 /* fall through */
572 case SOUND_MIXER_READ_SPEAKER:
573 rc = IOCTL_OUT(arg, (beep_vol<<8) | beep_vol);
574 break;
575 case SOUND_MIXER_OUTMASK:
576 case SOUND_MIXER_OUTSRC:
577 default:
578 rc = -EINVAL;
579 }
580
581 return rc;
582}
583
584static void __init
585tas_init_frame_rates(unsigned int *prop, unsigned int l)
586{
587 int i ;
588 if (prop) {
589 for (i=0; i<1; i++)
590 tas_freqs_ok[i] = 0;
591 for (l /= sizeof(int); l > 0; --l) {
592 unsigned int r = *prop++;
593 /* Apple 'Fixed' format */
594 if (r >= 0x10000)
595 r >>= 16;
596 for (i = 0; i < 1; ++i) {
597 if (r == tas_freqs[i]) {
598 tas_freqs_ok[i] = 1;
599 break;
600 }
601 }
602 }
603 }
604 /* else we assume that all the rates are available */
605}
606
607
608/*** AE - TUMBLER / SNAPPER END ************************************************/
609
610
611
612/*** Low level stuff *********************************************************/
613
614/*
615 * PCI PowerMac, with AWACS, Screamer, Burgundy, DACA or Tumbler and DBDMA.
616 */
617static void *PMacAlloc(unsigned int size, int flags)
618{
619 return kmalloc(size, flags);
620}
621
622static void PMacFree(void *ptr, unsigned int size)
623{
624 kfree(ptr);
625}
626
627static int __init PMacIrqInit(void)
628{
629 if (awacs)
630 if (request_irq(awacs_irq, pmac_awacs_intr, 0, "Built-in Sound misc", NULL))
631 return 0;
632 if (request_irq(awacs_tx_irq, pmac_awacs_tx_intr, 0, "Built-in Sound out", NULL)
633 || request_irq(awacs_rx_irq, pmac_awacs_rx_intr, 0, "Built-in Sound in", NULL))
634 return 0;
635 return 1;
636}
637
638#ifdef MODULE
639static void PMacIrqCleanup(void)
640{
641 /* turn off input & output dma */
642 DBDMA_DO_STOP(awacs_txdma);
643 DBDMA_DO_STOP(awacs_rxdma);
644
645 if (awacs)
646 /* disable interrupts from awacs interface */
647 out_le32(&awacs->control, in_le32(&awacs->control) & 0xfff);
648
649 /* Switch off the sound clock */
650 pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);
651 /* Make sure proper bits are set on pismo & tipb */
652 if ((machine_is_compatible("PowerBook3,1") ||
653 machine_is_compatible("PowerBook3,2")) && awacs) {
654 awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
655 awacs_write(MASK_ADDR1 | awacs_reg[1]);
656 msleep(200);
657 }
658 if (awacs)
659 free_irq(awacs_irq, NULL);
660 free_irq(awacs_tx_irq, NULL);
661 free_irq(awacs_rx_irq, NULL);
662
663 if (awacs)
664 iounmap(awacs);
665 if (i2s)
666 iounmap(i2s);
667 iounmap(awacs_txdma);
668 iounmap(awacs_rxdma);
669
670 release_OF_resource(awacs_node, 0);
671 release_OF_resource(awacs_node, 1);
672 release_OF_resource(awacs_node, 2);
673
674 if (awacs_tx_cmd_space)
675 kfree(awacs_tx_cmd_space);
676 if (awacs_rx_cmd_space)
677 kfree(awacs_rx_cmd_space);
678 if (beep_dbdma_cmd_space)
679 kfree(beep_dbdma_cmd_space);
680 if (beep_buf)
681 kfree(beep_buf);
682#ifdef CONFIG_PMAC_PBOOK
683 pmu_unregister_sleep_notifier(&awacs_sleep_notifier);
684#endif
685}
686#endif /* MODULE */
687
688static void PMacSilence(void)
689{
690 /* turn off output dma */
691 DBDMA_DO_STOP(awacs_txdma);
692}
693
694/* don't know what to do really - just have to leave it where
695 * OF left things
696*/
697
698static int daca_set_frame_rate(void)
699{
700 if (i2s) {
701 out_le32(i2s + (I2S_REG_SERIAL_FORMAT >> 2), 0x41190000);
702 out_le32(i2s + (I2S_REG_DATAWORD_SIZES >> 2), 0x02000200);
703 }
704 dmasound.hard.speed = 44100 ;
705 awacs_rate_index = 0 ;
706 return 44100 ;
707}
708
709static int awacs_freqs[8] = {
710 44100, 29400, 22050, 17640, 14700, 11025, 8820, 7350
711};
712static int awacs_freqs_ok[8] = { 1, 1, 1, 1, 1, 1, 1, 1 };
713
714static int
715awacs_set_frame_rate(int desired, int catch_r)
716{
717 int tolerance, i = 8 ;
718 /*
719 * If we have a sample rate which is within catchRadius percent
720 * of the requested value, we don't have to expand the samples.
721 * Otherwise choose the next higher rate.
722 * N.B.: burgundy awacs only works at 44100 Hz.
723 */
724 do {
725 tolerance = catch_r * awacs_freqs[--i] / 100;
726 if (awacs_freqs_ok[i]
727 && dmasound.soft.speed <= awacs_freqs[i] + tolerance)
728 break;
729 } while (i > 0);
730 dmasound.hard.speed = awacs_freqs[i];
731 awacs_rate_index = i;
732
733 out_le32(&awacs->control, MASK_IEPC | (i << 8) | 0x11 );
734 awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) | (i << 3);
735 awacs_write(awacs_reg[1] | MASK_ADDR1);
736 return dmasound.hard.speed;
737}
738
739static int
740burgundy_set_frame_rate(void)
741{
742 awacs_rate_index = 0 ;
743 awacs_reg[1] = (awacs_reg[1] & ~MASK_SAMPLERATE) ;
744 /* XXX disable error interrupt on burgundy for now */
745 out_le32(&awacs->control, MASK_IEPC | 0 | 0x11 | MASK_IEE);
746 return 44100 ;
747}
748
749static int
750set_frame_rate(int desired, int catch_r)
751{
752 switch (awacs_revision) {
753 case AWACS_BURGUNDY:
754 dmasound.hard.speed = burgundy_set_frame_rate();
755 break ;
756 case AWACS_TUMBLER:
757 case AWACS_SNAPPER:
758 dmasound.hard.speed = tas_set_frame_rate();
759 break ;
760 case AWACS_DACA:
761 dmasound.hard.speed =
762 daca_set_frame_rate();
763 break ;
764 default:
765 dmasound.hard.speed = awacs_set_frame_rate(desired,
766 catch_r);
767 break ;
768 }
769 return dmasound.hard.speed ;
770}
771
772static void
773awacs_recalibrate(void)
774{
775 /* Sorry for the horrible delays... I hope to get that improved
776 * by making the whole PM process asynchronous in a future version
777 */
778 msleep(750);
779 awacs_reg[1] |= MASK_CMUTE | MASK_AMUTE;
780 awacs_write(awacs_reg[1] | MASK_RECALIBRATE | MASK_ADDR1);
781 msleep(1000);
782 awacs_write(awacs_reg[1] | MASK_ADDR1);
783}
784
785static void PMacInit(void)
786{
787 int tolerance;
788
789 switch (dmasound.soft.format) {
790 case AFMT_S16_LE:
791 case AFMT_U16_LE:
792 if (hw_can_byteswap)
793 dmasound.hard.format = AFMT_S16_LE;
794 else
795 dmasound.hard.format = AFMT_S16_BE;
796 break;
797 default:
798 dmasound.hard.format = AFMT_S16_BE;
799 break;
800 }
801 dmasound.hard.stereo = 1;
802 dmasound.hard.size = 16;
803
804 /* set dmasound.hard.speed - on the basis of what we want (soft)
805 * and the tolerance we'll allow.
806 */
807 set_frame_rate(dmasound.soft.speed, catchRadius) ;
808
809 tolerance = (catchRadius * dmasound.hard.speed) / 100;
810 if (dmasound.soft.speed >= dmasound.hard.speed - tolerance) {
811 dmasound.trans_write = &transAwacsNormal;
812 dmasound.trans_read = &transAwacsNormalRead;
813 } else {
814 dmasound.trans_write = &transAwacsExpand;
815 dmasound.trans_read = &transAwacsExpandRead;
816 }
817
818 if (awacs) {
819 if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))
820 out_le32(&awacs->byteswap, BS_VAL);
821 else
822 out_le32(&awacs->byteswap, 0);
823 }
824
825 expand_bal = -dmasound.soft.speed;
826 expand_read_bal = -dmasound.soft.speed;
827}
828
829static int PMacSetFormat(int format)
830{
831 int size;
832 int req_format = format;
833
834 switch (format) {
835 case AFMT_QUERY:
836 return dmasound.soft.format;
837 case AFMT_MU_LAW:
838 case AFMT_A_LAW:
839 case AFMT_U8:
840 case AFMT_S8:
841 size = 8;
842 break;
843 case AFMT_S16_LE:
844 if(!hw_can_byteswap)
845 format = AFMT_S16_BE;
846 case AFMT_S16_BE:
847 size = 16;
848 break;
849 case AFMT_U16_LE:
850 if(!hw_can_byteswap)
851 format = AFMT_U16_BE;
852 case AFMT_U16_BE:
853 size = 16;
854 break;
855 default: /* :-) */
856 printk(KERN_ERR "dmasound: unknown format 0x%x, using AFMT_U8\n",
857 format);
858 size = 8;
859 format = AFMT_U8;
860 }
861
862 if (req_format == format) {
863 dmasound.soft.format = format;
864 dmasound.soft.size = size;
865 if (dmasound.minDev == SND_DEV_DSP) {
866 dmasound.dsp.format = format;
867 dmasound.dsp.size = size;
868 }
869 }
870
871 return format;
872}
873
874#define AWACS_VOLUME_TO_MASK(x) (15 - ((((x) - 1) * 15) / 99))
875#define AWACS_MASK_TO_VOLUME(y) (100 - ((y) * 99 / 15))
876
877static int awacs_get_volume(int reg, int lshift)
878{
879 int volume;
880
881 volume = AWACS_MASK_TO_VOLUME((reg >> lshift) & 0xf);
882 volume |= AWACS_MASK_TO_VOLUME(reg & 0xf) << 8;
883 return volume;
884}
885
886static int awacs_volume_setter(int volume, int n, int mute, int lshift)
887{
888 int r1, rn;
889
890 if (mute && volume == 0) {
891 r1 = awacs_reg[1] | mute;
892 } else {
893 r1 = awacs_reg[1] & ~mute;
894 rn = awacs_reg[n] & ~(0xf | (0xf << lshift));
895 rn |= ((AWACS_VOLUME_TO_MASK(volume & 0xff) & 0xf) << lshift);
896 rn |= AWACS_VOLUME_TO_MASK((volume >> 8) & 0xff) & 0xf;
897 awacs_reg[n] = rn;
898 awacs_write((n << 12) | rn);
899 volume = awacs_get_volume(rn, lshift);
900 }
901 if (r1 != awacs_reg[1]) {
902 awacs_reg[1] = r1;
903 awacs_write(r1 | MASK_ADDR1);
904 }
905 return volume;
906}
907
908static int PMacSetVolume(int volume)
909{
910 printk(KERN_WARNING "Bogus call to PMacSetVolume !\n");
911 return 0;
912}
913
914static void awacs_setup_for_beep(int speed)
915{
916 out_le32(&awacs->control,
917 (in_le32(&awacs->control) & ~0x1f00)
918 | ((speed > 0 ? speed : awacs_rate_index) << 8));
919
920 if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE) && speed == -1)
921 out_le32(&awacs->byteswap, BS_VAL);
922 else
923 out_le32(&awacs->byteswap, 0);
924}
925
926/* CHECK: how much of this *really* needs IRQs masked? */
927static void __PMacPlay(void)
928{
929 volatile struct dbdma_cmd *cp;
930 int next_frg, count;
931
932 count = 300 ; /* > two cycles at the lowest sample rate */
933
934 /* what we want to send next */
935 next_frg = (write_sq.front + write_sq.active) % write_sq.max_count;
936
937 if (awacs_beep_state) {
938 /* sound takes precedence over beeps */
939 /* stop the dma channel */
940 out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
941 while ( (in_le32(&awacs_txdma->status) & RUN) && count--)
942 udelay(1);
943 if (awacs)
944 awacs_setup_for_beep(-1);
945 out_le32(&awacs_txdma->cmdptr,
946 virt_to_bus(&(awacs_tx_cmds[next_frg])));
947
948 beep_playing = 0;
949 awacs_beep_state = 0;
950 }
951 /* this won't allow more than two frags to be in the output queue at
952 once. (or one, if the max frags is 2 - because count can't exceed
953 2 in that case)
954 */
955 while (write_sq.active < 2 && write_sq.active < write_sq.count) {
956 count = (write_sq.count == write_sq.active + 1) ?
957 write_sq.rear_size:write_sq.block_size ;
958 if (count < write_sq.block_size) {
959 if (!write_sq.syncing) /* last block not yet filled,*/
960 break; /* and we're not syncing or POST-ed */
961 else {
962 /* pretend the block is full to force a new
963 block to be started on the next write */
964 write_sq.rear_size = write_sq.block_size ;
965 write_sq.syncing &= ~2 ; /* clear POST */
966 }
967 }
968 cp = &awacs_tx_cmds[next_frg];
969 st_le16(&cp->req_count, count);
970 st_le16(&cp->xfer_status, 0);
971 st_le16(&cp->command, OUTPUT_MORE + INTR_ALWAYS);
972 /* put a STOP at the end of the queue - but only if we have
973 space for it. This means that, if we under-run and we only
974 have two fragments, we might re-play sound from an existing
975 queued frag. I guess the solution to that is not to set two
976 frags if you are likely to under-run...
977 */
978 if (write_sq.count < write_sq.max_count) {
979 if (++next_frg >= write_sq.max_count)
980 next_frg = 0 ; /* wrap */
981 /* if we get here then we've underrun so we will stop*/
982 st_le16(&awacs_tx_cmds[next_frg].command, DBDMA_STOP);
983 }
984 /* set the dbdma controller going, if it is not already */
985 if (write_sq.active == 0)
986 out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp));
987 (void)in_le32(&awacs_txdma->status);
988 out_le32(&awacs_txdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
989 ++write_sq.active;
990 }
991}
992
993static void PMacPlay(void)
994{
995 LOCK();
996 if (!awacs_sleeping) {
997 unsigned long flags;
998
999 spin_lock_irqsave(&dmasound.lock, flags);
1000 __PMacPlay();
1001 spin_unlock_irqrestore(&dmasound.lock, flags);
1002 }
1003 UNLOCK();
1004}
1005
1006static void PMacRecord(void)
1007{
1008 unsigned long flags;
1009
1010 if (read_sq.active)
1011 return;
1012
1013 spin_lock_irqsave(&dmasound.lock, flags);
1014
1015 /* This is all we have to do......Just start it up.
1016 */
1017 out_le32(&awacs_rxdma->control, ((RUN|WAKE) << 16) + (RUN|WAKE));
1018 read_sq.active = 1;
1019
1020 spin_unlock_irqrestore(&dmasound.lock, flags);
1021}
1022
1023/* if the TX status comes up "DEAD" - reported on some Power Computing machines
1024 we need to re-start the dbdma - but from a different physical start address
1025 and with a different transfer length. It would get very messy to do this
1026 with the normal dbdma_cmd blocks - we would have to re-write the buffer start
1027 addresses each time. So, we will keep a single dbdma_cmd block which can be
1028 fiddled with.
1029 When DEAD status is first reported the content of the faulted dbdma block is
1030 copied into the emergency buffer and we note that the buffer is in use.
1031 we then bump the start physical address by the amount that was successfully
1032 output before it died.
1033 On any subsequent DEAD result we just do the bump-ups (we know that we are
1034 already using the emergency dbdma_cmd).
1035 CHECK: this just tries to "do it". It is possible that we should abandon
1036 xfers when the number of residual bytes gets below a certain value - I can
1037 see that this might cause a loop-forever if too small a transfer causes
1038 DEAD status. However this is a TODO for now - we'll see what gets reported.
1039 When we get a successful transfer result with the emergency buffer we just
1040 pretend that it completed using the original dmdma_cmd and carry on. The
1041 'next_cmd' field will already point back to the original loop of blocks.
1042*/
1043
1044static irqreturn_t
1045pmac_awacs_tx_intr(int irq, void *devid, struct pt_regs *regs)
1046{
1047 int i = write_sq.front;
1048 int stat;
1049 int i_nowrap = write_sq.front;
1050 volatile struct dbdma_cmd *cp;
1051 /* != 0 when we are dealing with a DEAD xfer */
1052 static int emergency_in_use;
1053
1054 spin_lock(&dmasound.lock);
1055 while (write_sq.active > 0) { /* we expect to have done something*/
1056 if (emergency_in_use) /* we are dealing with DEAD xfer */
1057 cp = emergency_dbdma_cmd ;
1058 else
1059 cp = &awacs_tx_cmds[i];
1060 stat = ld_le16(&cp->xfer_status);
1061 if (stat & DEAD) {
1062 unsigned short req, res ;
1063 unsigned int phy ;
1064#ifdef DEBUG_DMASOUND
1065printk("dmasound_pmac: tx-irq: xfer died - patching it up...\n") ;
1066#endif
1067 /* to clear DEAD status we must first clear RUN
1068 set it to quiescent to be on the safe side */
1069 (void)in_le32(&awacs_txdma->status);
1070 out_le32(&awacs_txdma->control,
1071 (RUN|PAUSE|FLUSH|WAKE) << 16);
1072 write_sq.died++ ;
1073 if (!emergency_in_use) { /* new problem */
1074 memcpy((void *)emergency_dbdma_cmd, (void *)cp,
1075 sizeof(struct dbdma_cmd));
1076 emergency_in_use = 1;
1077 cp = emergency_dbdma_cmd;
1078 }
1079 /* now bump the values to reflect the amount
1080 we haven't yet shifted */
1081 req = ld_le16(&cp->req_count);
1082 res = ld_le16(&cp->res_count);
1083 phy = ld_le32(&cp->phy_addr);
1084 phy += (req - res);
1085 st_le16(&cp->req_count, res);
1086 st_le16(&cp->res_count, 0);
1087 st_le16(&cp->xfer_status, 0);
1088 st_le32(&cp->phy_addr, phy);
1089 st_le32(&cp->cmd_dep, virt_to_bus(&awacs_tx_cmds[(i+1)%write_sq.max_count]));
1090 st_le16(&cp->command, OUTPUT_MORE | BR_ALWAYS | INTR_ALWAYS);
1091
1092 /* point at our patched up command block */
1093 out_le32(&awacs_txdma->cmdptr, virt_to_bus(cp));
1094 /* we must re-start the controller */
1095 (void)in_le32(&awacs_txdma->status);
1096 /* should complete clearing the DEAD status */
1097 out_le32(&awacs_txdma->control,
1098 ((RUN|WAKE) << 16) + (RUN|WAKE));
1099 break; /* this block is still going */
1100 }
1101 if ((stat & ACTIVE) == 0)
1102 break; /* this frame is still going */
1103 if (emergency_in_use)
1104 emergency_in_use = 0 ; /* done that */
1105 --write_sq.count;
1106 --write_sq.active;
1107 i_nowrap++;
1108 if (++i >= write_sq.max_count)
1109 i = 0;
1110 }
1111
1112 /* if we stopped and we were not sync-ing - then we under-ran */
1113 if( write_sq.syncing == 0 ){
1114 stat = in_le32(&awacs_txdma->status) ;
1115 /* we hit the dbdma_stop */
1116 if( (stat & ACTIVE) == 0 ) write_sq.xruns++ ;
1117 }
1118
1119 /* if we used some data up then wake the writer to supply some more*/
1120 if (i_nowrap != write_sq.front)
1121 WAKE_UP(write_sq.action_queue);
1122 write_sq.front = i;
1123
1124 /* but make sure we funnel what we've already got */\
1125 if (!awacs_sleeping)
1126 __PMacPlay();
1127
1128 /* make the wake-on-empty conditional on syncing */
1129 if (!write_sq.active && (write_sq.syncing & 1))
1130 WAKE_UP(write_sq.sync_queue); /* any time we're empty */
1131 spin_unlock(&dmasound.lock);
1132 return IRQ_HANDLED;
1133}
1134
1135
1136static irqreturn_t
1137pmac_awacs_rx_intr(int irq, void *devid, struct pt_regs *regs)
1138{
1139 int stat ;
1140 /* For some reason on my PowerBook G3, I get one interrupt
1141 * when the interrupt vector is installed (like something is
1142 * pending). This happens before the dbdma is initialized by
1143 * us, so I just check the command pointer and if it is zero,
1144 * just blow it off.
1145 */
1146 if (in_le32(&awacs_rxdma->cmdptr) == 0)
1147 return IRQ_HANDLED;
1148
1149 /* We also want to blow 'em off when shutting down.
1150 */
1151 if (read_sq.active == 0)
1152 return IRQ_HANDLED;
1153
1154 spin_lock(&dmasound.lock);
1155 /* Check multiple buffers in case we were held off from
1156 * interrupt processing for a long time. Geeze, I really hope
1157 * this doesn't happen.
1158 */
1159 while ((stat=awacs_rx_cmds[read_sq.rear].xfer_status)) {
1160
1161 /* if we got a "DEAD" status then just log it for now.
1162 and try to restart dma.
1163 TODO: figure out how best to fix it up
1164 */
1165 if (stat & DEAD){
1166#ifdef DEBUG_DMASOUND
1167printk("dmasound_pmac: rx-irq: DIED - attempting resurection\n");
1168#endif
1169 /* to clear DEAD status we must first clear RUN
1170 set it to quiescent to be on the safe side */
1171 (void)in_le32(&awacs_txdma->status);
1172 out_le32(&awacs_txdma->control,
1173 (RUN|PAUSE|FLUSH|WAKE) << 16);
1174 awacs_rx_cmds[read_sq.rear].xfer_status = 0;
1175 awacs_rx_cmds[read_sq.rear].res_count = 0;
1176 read_sq.died++ ;
1177 (void)in_le32(&awacs_txdma->status);
1178 /* re-start the same block */
1179 out_le32(&awacs_rxdma->cmdptr,
1180 virt_to_bus(&awacs_rx_cmds[read_sq.rear]));
1181 /* we must re-start the controller */
1182 (void)in_le32(&awacs_rxdma->status);
1183 /* should complete clearing the DEAD status */
1184 out_le32(&awacs_rxdma->control,
1185 ((RUN|WAKE) << 16) + (RUN|WAKE));
1186 spin_unlock(&dmasound.lock);
1187 return IRQ_HANDLED; /* try this block again */
1188 }
1189 /* Clear status and move on to next buffer.
1190 */
1191 awacs_rx_cmds[read_sq.rear].xfer_status = 0;
1192 read_sq.rear++;
1193
1194 /* Wrap the buffer ring.
1195 */
1196 if (read_sq.rear >= read_sq.max_active)
1197 read_sq.rear = 0;
1198
1199 /* If we have caught up to the front buffer, bump it.
1200 * This will cause weird (but not fatal) results if the
1201 * read loop is currently using this buffer. The user is
1202 * behind in this case anyway, so weird things are going
1203 * to happen.
1204 */
1205 if (read_sq.rear == read_sq.front) {
1206 read_sq.front++;
1207 read_sq.xruns++ ; /* we overan */
1208 if (read_sq.front >= read_sq.max_active)
1209 read_sq.front = 0;
1210 }
1211 }
1212
1213 WAKE_UP(read_sq.action_queue);
1214 spin_unlock(&dmasound.lock);
1215 return IRQ_HANDLED;
1216}
1217
1218
1219static irqreturn_t
1220pmac_awacs_intr(int irq, void *devid, struct pt_regs *regs)
1221{
1222 int ctrl;
1223 int status;
1224 int r1;
1225
1226 spin_lock(&dmasound.lock);
1227 ctrl = in_le32(&awacs->control);
1228 status = in_le32(&awacs->codec_stat);
1229
1230 if (ctrl & MASK_PORTCHG) {
1231 /* tested on Screamer, should work on others too */
1232 if (awacs_revision == AWACS_SCREAMER) {
1233 if (((status & MASK_HDPCONN) >> 3) && (hdp_connected == 0)) {
1234 hdp_connected = 1;
1235
1236 r1 = awacs_reg[1] | MASK_SPKMUTE;
1237 awacs_reg[1] = r1;
1238 awacs_write(r1 | MASK_ADDR_MUTE);
1239 } else if (((status & MASK_HDPCONN) >> 3 == 0) && (hdp_connected == 1)) {
1240 hdp_connected = 0;
1241
1242 r1 = awacs_reg[1] & ~MASK_SPKMUTE;
1243 awacs_reg[1] = r1;
1244 awacs_write(r1 | MASK_ADDR_MUTE);
1245 }
1246 }
1247 }
1248 if (ctrl & MASK_CNTLERR) {
1249 int err = (in_le32(&awacs->codec_stat) & MASK_ERRCODE) >> 16;
1250 /* CHECK: we just swallow burgundy errors at the moment..*/
1251 if (err != 0 && awacs_revision != AWACS_BURGUNDY)
1252 printk(KERN_ERR "dmasound_pmac: error %x\n", err);
1253 }
1254 /* Writing 1s to the CNTLERR and PORTCHG bits clears them... */
1255 out_le32(&awacs->control, ctrl);
1256 spin_unlock(&dmasound.lock);
1257 return IRQ_HANDLED;
1258}
1259
1260static void
1261awacs_write(int val)
1262{
1263 int count = 300 ;
1264 if (awacs_revision >= AWACS_DACA || !awacs)
1265 return ;
1266
1267 while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--)
1268 udelay(1) ; /* timeout is > 2 samples at lowest rate */
1269 out_le32(&awacs->codec_ctrl, val | (awacs_subframe << 22));
1270 (void)in_le32(&awacs->byteswap);
1271}
1272
1273/* this is called when the beep timer expires... it will be called even
1274 if the beep has been overidden by other sound output.
1275*/
1276static void awacs_nosound(unsigned long xx)
1277{
1278 unsigned long flags;
1279 int count = 600 ; /* > four samples at lowest rate */
1280
1281 spin_lock_irqsave(&dmasound.lock, flags);
1282 if (beep_playing) {
1283 st_le16(&beep_dbdma_cmd->command, DBDMA_STOP);
1284 out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
1285 while ((in_le32(&awacs_txdma->status) & RUN) && count--)
1286 udelay(1);
1287 if (awacs)
1288 awacs_setup_for_beep(-1);
1289 beep_playing = 0;
1290 }
1291 spin_unlock_irqrestore(&dmasound.lock, flags);
1292}
1293
1294/*
1295 * We generate the beep with a single dbdma command that loops a buffer
1296 * forever - without generating interrupts.
1297 *
1298 * So, to stop it you have to stop dma output as per awacs_nosound.
1299 */
1300static int awacs_beep_event(struct input_dev *dev, unsigned int type,
1301 unsigned int code, int hz)
1302{
1303 unsigned long flags;
1304 int beep_speed = 0;
1305 int srate;
1306 int period, ncycles, nsamples;
1307 int i, j, f;
1308 short *p;
1309 static int beep_hz_cache;
1310 static int beep_nsamples_cache;
1311 static int beep_volume_cache;
1312
1313 if (type != EV_SND)
1314 return -1;
1315 switch (code) {
1316 case SND_BELL:
1317 if (hz)
1318 hz = 1000;
1319 break;
1320 case SND_TONE:
1321 break;
1322 default:
1323 return -1;
1324 }
1325
1326 if (beep_buf == NULL)
1327 return -1;
1328
1329 /* quick-hack fix for DACA, Burgundy & Tumbler */
1330
1331 if (awacs_revision >= AWACS_DACA){
1332 srate = 44100 ;
1333 } else {
1334 for (i = 0; i < 8 && awacs_freqs[i] >= BEEP_SRATE; ++i)
1335 if (awacs_freqs_ok[i])
1336 beep_speed = i;
1337 srate = awacs_freqs[beep_speed];
1338 }
1339
1340 if (hz <= srate / BEEP_BUFLEN || hz > srate / 2) {
1341 /* cancel beep currently playing */
1342 awacs_nosound(0);
1343 return 0;
1344 }
1345
1346 spin_lock_irqsave(&dmasound.lock, flags);
1347 if (beep_playing || write_sq.active || beep_buf == NULL) {
1348 spin_unlock_irqrestore(&dmasound.lock, flags);
1349 return -1; /* too hard, sorry :-( */
1350 }
1351 beep_playing = 1;
1352 st_le16(&beep_dbdma_cmd->command, OUTPUT_MORE + BR_ALWAYS);
1353 spin_unlock_irqrestore(&dmasound.lock, flags);
1354
1355 if (hz == beep_hz_cache && beep_vol == beep_volume_cache) {
1356 nsamples = beep_nsamples_cache;
1357 } else {
1358 period = srate * 256 / hz; /* fixed point */
1359 ncycles = BEEP_BUFLEN * 256 / period;
1360 nsamples = (period * ncycles) >> 8;
1361 f = ncycles * 65536 / nsamples;
1362 j = 0;
1363 p = beep_buf;
1364 for (i = 0; i < nsamples; ++i, p += 2) {
1365 p[0] = p[1] = beep_wform[j >> 8] * beep_vol;
1366 j = (j + f) & 0xffff;
1367 }
1368 beep_hz_cache = hz;
1369 beep_volume_cache = beep_vol;
1370 beep_nsamples_cache = nsamples;
1371 }
1372
1373 st_le16(&beep_dbdma_cmd->req_count, nsamples*4);
1374 st_le16(&beep_dbdma_cmd->xfer_status, 0);
1375 st_le32(&beep_dbdma_cmd->cmd_dep, virt_to_bus(beep_dbdma_cmd));
1376 st_le32(&beep_dbdma_cmd->phy_addr, virt_to_bus(beep_buf));
1377 awacs_beep_state = 1;
1378
1379 spin_lock_irqsave(&dmasound.lock, flags);
1380 if (beep_playing) { /* i.e. haven't been terminated already */
1381 int count = 300 ;
1382 out_le32(&awacs_txdma->control, (RUN|WAKE|FLUSH|PAUSE) << 16);
1383 while ((in_le32(&awacs_txdma->status) & RUN) && count--)
1384 udelay(1); /* timeout > 2 samples at lowest rate*/
1385 if (awacs)
1386 awacs_setup_for_beep(beep_speed);
1387 out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
1388 (void)in_le32(&awacs_txdma->status);
1389 out_le32(&awacs_txdma->control, RUN | (RUN << 16));
1390 }
1391 spin_unlock_irqrestore(&dmasound.lock, flags);
1392
1393 return 0;
1394}
1395
1396/* used in init and for wake-up */
1397
1398static void
1399load_awacs(void)
1400{
1401 awacs_write(awacs_reg[0] + MASK_ADDR0);
1402 awacs_write(awacs_reg[1] + MASK_ADDR1);
1403 awacs_write(awacs_reg[2] + MASK_ADDR2);
1404 awacs_write(awacs_reg[4] + MASK_ADDR4);
1405
1406 if (awacs_revision == AWACS_SCREAMER) {
1407 awacs_write(awacs_reg[5] + MASK_ADDR5);
1408 msleep(100);
1409 awacs_write(awacs_reg[6] + MASK_ADDR6);
1410 msleep(2);
1411 awacs_write(awacs_reg[1] + MASK_ADDR1);
1412 awacs_write(awacs_reg[7] + MASK_ADDR7);
1413 }
1414 if (awacs) {
1415 if (hw_can_byteswap && (dmasound.hard.format == AFMT_S16_LE))
1416 out_le32(&awacs->byteswap, BS_VAL);
1417 else
1418 out_le32(&awacs->byteswap, 0);
1419 }
1420}
1421
1422#ifdef CONFIG_PMAC_PBOOK
1423/*
1424 * Save state when going to sleep, restore it afterwards.
1425 */
1426/* FIXME: sort out disabling/re-enabling of read stuff as well */
1427static int awacs_sleep_notify(struct pmu_sleep_notifier *self, int when)
1428{
1429 unsigned long flags;
1430
1431 switch (when) {
1432 case PBOOK_SLEEP_NOW:
1433 LOCK();
1434 awacs_sleeping = 1;
1435 /* Tell the rest of the driver we are now going to sleep */
1436 mb();
1437 if (awacs_revision == AWACS_SCREAMER ||
1438 awacs_revision == AWACS_AWACS) {
1439 awacs_reg1_save = awacs_reg[1];
1440 awacs_reg[1] |= MASK_AMUTE | MASK_CMUTE;
1441 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1442 }
1443
1444 PMacSilence();
1445 /* stop rx - if going - a bit of a daft user... but */
1446 out_le32(&awacs_rxdma->control, (RUN|WAKE|FLUSH << 16));
1447 /* deny interrupts */
1448 if (awacs)
1449 disable_irq(awacs_irq);
1450 disable_irq(awacs_tx_irq);
1451 disable_irq(awacs_rx_irq);
1452 /* Chip specific sleep code */
1453 switch (awacs_revision) {
1454 case AWACS_TUMBLER:
1455 case AWACS_SNAPPER:
1456 write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
1457 write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
1458 tas_enter_sleep();
1459 write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
1460 break ;
1461 case AWACS_DACA:
1462 daca_enter_sleep();
1463 break ;
1464 case AWACS_BURGUNDY:
1465 break ;
1466 case AWACS_SCREAMER:
1467 case AWACS_AWACS:
1468 default:
1469 out_le32(&awacs->control, 0x11) ;
1470 break ;
1471 }
1472 /* Disable sound clock */
1473 pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 0);
1474 /* According to Darwin, we do that after turning off the sound
1475 * chip clock. All this will have to be cleaned up once we properly
1476 * parse the OF sound-objects
1477 */
1478 if ((machine_is_compatible("PowerBook3,1") ||
1479 machine_is_compatible("PowerBook3,2")) && awacs) {
1480 awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
1481 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1482 msleep(200);
1483 }
1484 break;
1485 case PBOOK_WAKE:
1486 /* Enable sound clock */
1487 pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, awacs_node, 0, 1);
1488 if ((machine_is_compatible("PowerBook3,1") ||
1489 machine_is_compatible("PowerBook3,2")) && awacs) {
1490 msleep(100);
1491 awacs_reg[1] &= ~(MASK_PAROUT0 | MASK_PAROUT1);
1492 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1493 msleep(300);
1494 } else
1495 msleep(1000);
1496 /* restore settings */
1497 switch (awacs_revision) {
1498 case AWACS_TUMBLER:
1499 case AWACS_SNAPPER:
1500 write_audio_gpio(gpio_headphone_mute, gpio_headphone_mute_pol);
1501 write_audio_gpio(gpio_amp_mute, gpio_amp_mute_pol);
1502 write_audio_gpio(gpio_audio_reset, gpio_audio_reset_pol);
1503 msleep(100);
1504 write_audio_gpio(gpio_audio_reset, !gpio_audio_reset_pol);
1505 msleep(150);
1506 tas_leave_sleep(); /* Stub for now */
1507 headphone_intr(0,NULL,NULL);
1508 break;
1509 case AWACS_DACA:
1510 msleep(10); /* Check this !!! */
1511 daca_leave_sleep();
1512 break ; /* dont know how yet */
1513 case AWACS_BURGUNDY:
1514 break ;
1515 case AWACS_SCREAMER:
1516 case AWACS_AWACS:
1517 default:
1518 load_awacs() ;
1519 break ;
1520 }
1521 /* Recalibrate chip */
1522 if (awacs_revision == AWACS_SCREAMER && awacs)
1523 awacs_recalibrate();
1524 /* Make sure dma is stopped */
1525 PMacSilence();
1526 if (awacs)
1527 enable_irq(awacs_irq);
1528 enable_irq(awacs_tx_irq);
1529 enable_irq(awacs_rx_irq);
1530 if (awacs) {
1531 /* OK, allow ints back again */
1532 out_le32(&awacs->control, MASK_IEPC
1533 | (awacs_rate_index << 8) | 0x11
1534 | (awacs_revision < AWACS_DACA ? MASK_IEE: 0));
1535 }
1536 if (macio_base && is_pbook_g3) {
1537 /* FIXME: should restore the setup we had...*/
1538 out_8(macio_base + 0x37, 3);
1539 } else if (is_pbook_3X00) {
1540 in_8(latch_base + 0x190);
1541 }
1542 /* Remove mute */
1543 if (awacs_revision == AWACS_SCREAMER ||
1544 awacs_revision == AWACS_AWACS) {
1545 awacs_reg[1] = awacs_reg1_save;
1546 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1547 }
1548 awacs_sleeping = 0;
1549 /* Resume pending sounds. */
1550 /* we don't try to restart input... */
1551 spin_lock_irqsave(&dmasound.lock, flags);
1552 __PMacPlay();
1553 spin_unlock_irqrestore(&dmasound.lock, flags);
1554 UNLOCK();
1555 }
1556 return PBOOK_SLEEP_OK;
1557}
1558#endif /* CONFIG_PMAC_PBOOK */
1559
1560
1561/* All the burgundy functions: */
1562
1563/* Waits for busy flag to clear */
1564inline static void
1565awacs_burgundy_busy_wait(void)
1566{
1567 int count = 50; /* > 2 samples at 44k1 */
1568 while ((in_le32(&awacs->codec_ctrl) & MASK_NEWECMD) && count--)
1569 udelay(1) ;
1570}
1571
1572inline static void
1573awacs_burgundy_extend_wait(void)
1574{
1575 int count = 50 ; /* > 2 samples at 44k1 */
1576 while ((!(in_le32(&awacs->codec_stat) & MASK_EXTEND)) && count--)
1577 udelay(1) ;
1578 count = 50;
1579 while ((in_le32(&awacs->codec_stat) & MASK_EXTEND) && count--)
1580 udelay(1);
1581}
1582
1583static void
1584awacs_burgundy_wcw(unsigned addr, unsigned val)
1585{
1586 out_le32(&awacs->codec_ctrl, addr + 0x200c00 + (val & 0xff));
1587 awacs_burgundy_busy_wait();
1588 out_le32(&awacs->codec_ctrl, addr + 0x200d00 +((val>>8) & 0xff));
1589 awacs_burgundy_busy_wait();
1590 out_le32(&awacs->codec_ctrl, addr + 0x200e00 +((val>>16) & 0xff));
1591 awacs_burgundy_busy_wait();
1592 out_le32(&awacs->codec_ctrl, addr + 0x200f00 +((val>>24) & 0xff));
1593 awacs_burgundy_busy_wait();
1594}
1595
1596static unsigned
1597awacs_burgundy_rcw(unsigned addr)
1598{
1599 unsigned val = 0;
1600 unsigned long flags;
1601
1602 /* should have timeouts here */
1603 spin_lock_irqsave(&dmasound.lock, flags);
1604
1605 out_le32(&awacs->codec_ctrl, addr + 0x100000);
1606 awacs_burgundy_busy_wait();
1607 awacs_burgundy_extend_wait();
1608 val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
1609
1610 out_le32(&awacs->codec_ctrl, addr + 0x100100);
1611 awacs_burgundy_busy_wait();
1612 awacs_burgundy_extend_wait();
1613 val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<8;
1614
1615 out_le32(&awacs->codec_ctrl, addr + 0x100200);
1616 awacs_burgundy_busy_wait();
1617 awacs_burgundy_extend_wait();
1618 val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<16;
1619
1620 out_le32(&awacs->codec_ctrl, addr + 0x100300);
1621 awacs_burgundy_busy_wait();
1622 awacs_burgundy_extend_wait();
1623 val += ((in_le32(&awacs->codec_stat)>>4) & 0xff) <<24;
1624
1625 spin_unlock_irqrestore(&dmasound.lock, flags);
1626
1627 return val;
1628}
1629
1630
1631static void
1632awacs_burgundy_wcb(unsigned addr, unsigned val)
1633{
1634 out_le32(&awacs->codec_ctrl, addr + 0x300000 + (val & 0xff));
1635 awacs_burgundy_busy_wait();
1636}
1637
1638static unsigned
1639awacs_burgundy_rcb(unsigned addr)
1640{
1641 unsigned val = 0;
1642 unsigned long flags;
1643
1644 /* should have timeouts here */
1645 spin_lock_irqsave(&dmasound.lock, flags);
1646
1647 out_le32(&awacs->codec_ctrl, addr + 0x100000);
1648 awacs_burgundy_busy_wait();
1649 awacs_burgundy_extend_wait();
1650 val += (in_le32(&awacs->codec_stat) >> 4) & 0xff;
1651
1652 spin_unlock_irqrestore(&dmasound.lock, flags);
1653
1654 return val;
1655}
1656
1657static int
1658awacs_burgundy_check(void)
1659{
1660 /* Checks to see the chip is alive and kicking */
1661 int error = in_le32(&awacs->codec_ctrl) & MASK_ERRCODE;
1662
1663 return error == 0xf0000;
1664}
1665
1666static int
1667awacs_burgundy_init(void)
1668{
1669 if (awacs_burgundy_check()) {
1670 printk(KERN_WARNING "dmasound_pmac: burgundy not working :-(\n");
1671 return 1;
1672 }
1673
1674 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_OUTPUTENABLES,
1675 DEF_BURGUNDY_OUTPUTENABLES);
1676 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
1677 DEF_BURGUNDY_MORE_OUTPUTENABLES);
1678 awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_OUTPUTSELECTS,
1679 DEF_BURGUNDY_OUTPUTSELECTS);
1680
1681 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL21,
1682 DEF_BURGUNDY_INPSEL21);
1683 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_INPSEL3,
1684 DEF_BURGUNDY_INPSEL3);
1685 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINCD,
1686 DEF_BURGUNDY_GAINCD);
1687 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINLINE,
1688 DEF_BURGUNDY_GAINLINE);
1689 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMIC,
1690 DEF_BURGUNDY_GAINMIC);
1691 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_GAINMODEM,
1692 DEF_BURGUNDY_GAINMODEM);
1693
1694 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER,
1695 DEF_BURGUNDY_ATTENSPEAKER);
1696 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENLINEOUT,
1697 DEF_BURGUNDY_ATTENLINEOUT);
1698 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENHP,
1699 DEF_BURGUNDY_ATTENHP);
1700
1701 awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_MASTER_VOLUME,
1702 DEF_BURGUNDY_MASTER_VOLUME);
1703 awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLCD,
1704 DEF_BURGUNDY_VOLCD);
1705 awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLLINE,
1706 DEF_BURGUNDY_VOLLINE);
1707 awacs_burgundy_wcw(MASK_ADDR_BURGUNDY_VOLMIC,
1708 DEF_BURGUNDY_VOLMIC);
1709 return 0;
1710}
1711
1712static void
1713awacs_burgundy_write_volume(unsigned address, int volume)
1714{
1715 int hardvolume,lvolume,rvolume;
1716
1717 lvolume = (volume & 0xff) ? (volume & 0xff) + 155 : 0;
1718 rvolume = ((volume >>8)&0xff) ? ((volume >> 8)&0xff ) + 155 : 0;
1719
1720 hardvolume = lvolume + (rvolume << 16);
1721
1722 awacs_burgundy_wcw(address, hardvolume);
1723}
1724
1725static int
1726awacs_burgundy_read_volume(unsigned address)
1727{
1728 int softvolume,wvolume;
1729
1730 wvolume = awacs_burgundy_rcw(address);
1731
1732 softvolume = (wvolume & 0xff) - 155;
1733 softvolume += (((wvolume >> 16) & 0xff) - 155)<<8;
1734
1735 return softvolume > 0 ? softvolume : 0;
1736}
1737
1738static int
1739awacs_burgundy_read_mvolume(unsigned address)
1740{
1741 int lvolume,rvolume,wvolume;
1742
1743 wvolume = awacs_burgundy_rcw(address);
1744
1745 wvolume &= 0xffff;
1746
1747 rvolume = (wvolume & 0xff) - 155;
1748 lvolume = ((wvolume & 0xff00)>>8) - 155;
1749
1750 return lvolume + (rvolume << 8);
1751}
1752
1753static void
1754awacs_burgundy_write_mvolume(unsigned address, int volume)
1755{
1756 int lvolume,rvolume,hardvolume;
1757
1758 lvolume = (volume &0xff) ? (volume & 0xff) + 155 :0;
1759 rvolume = ((volume >>8) & 0xff) ? (volume >> 8) + 155 :0;
1760
1761 hardvolume = lvolume + (rvolume << 8);
1762 hardvolume += (hardvolume << 16);
1763
1764 awacs_burgundy_wcw(address, hardvolume);
1765}
1766
1767/* End burgundy functions */
1768
1769/* Set up output volumes on machines with the 'perch/whisper' extension card.
1770 * this has an SGS i2c chip (7433) which is accessed using the cuda.
1771 *
1772 * TODO: split this out and make use of the other parts of the SGS chip to
1773 * do Bass, Treble etc.
1774 */
1775
1776static void
1777awacs_enable_amp(int spkr_vol)
1778{
1779#ifdef CONFIG_ADB_CUDA
1780 struct adb_request req;
1781
1782 if (sys_ctrler != SYS_CTRLER_CUDA)
1783 return;
1784
1785 /* turn on headphones */
1786 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
1787 0x8a, 4, 0);
1788 while (!req.complete) cuda_poll();
1789 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
1790 0x8a, 6, 0);
1791 while (!req.complete) cuda_poll();
1792
1793 /* turn on speaker */
1794 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
1795 0x8a, 3, (100 - (spkr_vol & 0xff)) * 32 / 100);
1796 while (!req.complete) cuda_poll();
1797 cuda_request(&req, NULL, 5, CUDA_PACKET, CUDA_GET_SET_IIC,
1798 0x8a, 5, (100 - ((spkr_vol >> 8) & 0xff)) * 32 / 100);
1799 while (!req.complete) cuda_poll();
1800
1801 cuda_request(&req, NULL, 5, CUDA_PACKET,
1802 CUDA_GET_SET_IIC, 0x8a, 1, 0x29);
1803 while (!req.complete) cuda_poll();
1804#endif /* CONFIG_ADB_CUDA */
1805}
1806
1807
1808/*** Mid level stuff *********************************************************/
1809
1810
1811/*
1812 * /dev/mixer abstraction
1813 */
1814
1815static void do_line_lev(int data)
1816{
1817 line_lev = data ;
1818 awacs_reg[0] &= ~MASK_MUX_AUDIN;
1819 if ((data & 0xff) >= 50)
1820 awacs_reg[0] |= MASK_MUX_AUDIN;
1821 awacs_write(MASK_ADDR0 | awacs_reg[0]);
1822}
1823
1824static void do_ip_gain(int data)
1825{
1826 ip_gain = data ;
1827 data &= 0xff;
1828 awacs_reg[0] &= ~MASK_GAINLINE;
1829 if (awacs_revision == AWACS_SCREAMER) {
1830 awacs_reg[6] &= ~MASK_MIC_BOOST ;
1831 if (data >= 33) {
1832 awacs_reg[0] |= MASK_GAINLINE;
1833 if( data >= 66)
1834 awacs_reg[6] |= MASK_MIC_BOOST ;
1835 }
1836 awacs_write(MASK_ADDR6 | awacs_reg[6]) ;
1837 } else {
1838 if (data >= 50)
1839 awacs_reg[0] |= MASK_GAINLINE;
1840 }
1841 awacs_write(MASK_ADDR0 | awacs_reg[0]);
1842}
1843
1844static void do_mic_lev(int data)
1845{
1846 mic_lev = data ;
1847 data &= 0xff;
1848 awacs_reg[0] &= ~MASK_MUX_MIC;
1849 if (data >= 50)
1850 awacs_reg[0] |= MASK_MUX_MIC;
1851 awacs_write(MASK_ADDR0 | awacs_reg[0]);
1852}
1853
1854static void do_cd_lev(int data)
1855{
1856 cd_lev = data ;
1857 awacs_reg[0] &= ~MASK_MUX_CD;
1858 if ((data & 0xff) >= 50)
1859 awacs_reg[0] |= MASK_MUX_CD;
1860 awacs_write(MASK_ADDR0 | awacs_reg[0]);
1861}
1862
1863static void do_rec_lev(int data)
1864{
1865 int left, right ;
1866 rec_lev = data ;
1867 /* need to fudge this to use the volume setter routine */
1868 left = 100 - (data & 0xff) ; if( left < 0 ) left = 0 ;
1869 right = 100 - ((data >> 8) & 0xff) ; if( right < 0 ) right = 0 ;
1870 left |= (right << 8 );
1871 left = awacs_volume_setter(left, 0, 0, 4);
1872}
1873
1874static void do_passthru_vol(int data)
1875{
1876 passthru_vol = data ;
1877 awacs_reg[1] &= ~MASK_LOOPTHRU;
1878 if (awacs_revision == AWACS_SCREAMER) {
1879 if( data ) { /* switch it on for non-zero */
1880 awacs_reg[1] |= MASK_LOOPTHRU;
1881 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1882 }
1883 data = awacs_volume_setter(data, 5, 0, 6) ;
1884 } else {
1885 if ((data & 0xff) >= 50)
1886 awacs_reg[1] |= MASK_LOOPTHRU;
1887 awacs_write(MASK_ADDR1 | awacs_reg[1]);
1888 data = (awacs_reg[1] & MASK_LOOPTHRU)? 100: 0;
1889 }
1890}
1891
1892static int awacs_mixer_ioctl(u_int cmd, u_long arg)
1893{
1894 int data;
1895 int rc;
1896
1897 switch (cmd) {
1898 case SOUND_MIXER_READ_CAPS:
1899 /* say we will allow multiple inputs? prob. wrong
1900 so I'm switching it to single */
1901 return IOCTL_OUT(arg, 1);
1902 case SOUND_MIXER_READ_DEVMASK:
1903 data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
1904 | SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD
1905 | SOUND_MASK_IGAIN | SOUND_MASK_RECLEV
1906 | SOUND_MASK_ALTPCM
1907 | SOUND_MASK_MONITOR;
1908 rc = IOCTL_OUT(arg, data);
1909 break;
1910 case SOUND_MIXER_READ_RECMASK:
1911 data = SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD;
1912 rc = IOCTL_OUT(arg, data);
1913 break;
1914 case SOUND_MIXER_READ_RECSRC:
1915 data = 0;
1916 if (awacs_reg[0] & MASK_MUX_AUDIN)
1917 data |= SOUND_MASK_LINE;
1918 if (awacs_reg[0] & MASK_MUX_MIC)
1919 data |= SOUND_MASK_MIC;
1920 if (awacs_reg[0] & MASK_MUX_CD)
1921 data |= SOUND_MASK_CD;
1922 rc = IOCTL_OUT(arg, data);
1923 break;
1924 case SOUND_MIXER_WRITE_RECSRC:
1925 IOCTL_IN(arg, data);
1926 data &= (SOUND_MASK_LINE | SOUND_MASK_MIC | SOUND_MASK_CD);
1927 awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
1928 | MASK_MUX_AUDIN);
1929 if (data & SOUND_MASK_LINE)
1930 awacs_reg[0] |= MASK_MUX_AUDIN;
1931 if (data & SOUND_MASK_MIC)
1932 awacs_reg[0] |= MASK_MUX_MIC;
1933 if (data & SOUND_MASK_CD)
1934 awacs_reg[0] |= MASK_MUX_CD;
1935 awacs_write(awacs_reg[0] | MASK_ADDR0);
1936 rc = IOCTL_OUT(arg, data);
1937 break;
1938 case SOUND_MIXER_READ_STEREODEVS:
1939 data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER| SOUND_MASK_RECLEV ;
1940 if (awacs_revision == AWACS_SCREAMER)
1941 data |= SOUND_MASK_MONITOR ;
1942 rc = IOCTL_OUT(arg, data);
1943 break;
1944 case SOUND_MIXER_WRITE_VOLUME:
1945 IOCTL_IN(arg, data);
1946 line_vol = data ;
1947 awacs_volume_setter(data, 2, 0, 6);
1948 /* fall through */
1949 case SOUND_MIXER_READ_VOLUME:
1950 rc = IOCTL_OUT(arg, line_vol);
1951 break;
1952 case SOUND_MIXER_WRITE_SPEAKER:
1953 IOCTL_IN(arg, data);
1954 spk_vol = data ;
1955 if (has_perch)
1956 awacs_enable_amp(data);
1957 else
1958 (void)awacs_volume_setter(data, 4, MASK_CMUTE, 6);
1959 /* fall though */
1960 case SOUND_MIXER_READ_SPEAKER:
1961 rc = IOCTL_OUT(arg, spk_vol);
1962 break;
1963 case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
1964 IOCTL_IN(arg, data);
1965 beep_vol = data & 0xff;
1966 /* fall through */
1967 case SOUND_MIXER_READ_ALTPCM:
1968 rc = IOCTL_OUT(arg, beep_vol);
1969 break;
1970 case SOUND_MIXER_WRITE_LINE:
1971 IOCTL_IN(arg, data);
1972 do_line_lev(data) ;
1973 /* fall through */
1974 case SOUND_MIXER_READ_LINE:
1975 rc = IOCTL_OUT(arg, line_lev);
1976 break;
1977 case SOUND_MIXER_WRITE_IGAIN:
1978 IOCTL_IN(arg, data);
1979 do_ip_gain(data) ;
1980 /* fall through */
1981 case SOUND_MIXER_READ_IGAIN:
1982 rc = IOCTL_OUT(arg, ip_gain);
1983 break;
1984 case SOUND_MIXER_WRITE_MIC:
1985 IOCTL_IN(arg, data);
1986 do_mic_lev(data);
1987 /* fall through */
1988 case SOUND_MIXER_READ_MIC:
1989 rc = IOCTL_OUT(arg, mic_lev);
1990 break;
1991 case SOUND_MIXER_WRITE_CD:
1992 IOCTL_IN(arg, data);
1993 do_cd_lev(data);
1994 /* fall through */
1995 case SOUND_MIXER_READ_CD:
1996 rc = IOCTL_OUT(arg, cd_lev);
1997 break;
1998 case SOUND_MIXER_WRITE_RECLEV:
1999 IOCTL_IN(arg, data);
2000 do_rec_lev(data) ;
2001 /* fall through */
2002 case SOUND_MIXER_READ_RECLEV:
2003 rc = IOCTL_OUT(arg, rec_lev);
2004 break;
2005 case MIXER_WRITE(SOUND_MIXER_MONITOR):
2006 IOCTL_IN(arg, data);
2007 do_passthru_vol(data) ;
2008 /* fall through */
2009 case MIXER_READ(SOUND_MIXER_MONITOR):
2010 rc = IOCTL_OUT(arg, passthru_vol);
2011 break;
2012 default:
2013 rc = -EINVAL;
2014 }
2015
2016 return rc;
2017}
2018
2019static void awacs_mixer_init(void)
2020{
2021 awacs_volume_setter(line_vol, 2, 0, 6);
2022 if (has_perch)
2023 awacs_enable_amp(spk_vol);
2024 else
2025 (void)awacs_volume_setter(spk_vol, 4, MASK_CMUTE, 6);
2026 do_line_lev(line_lev) ;
2027 do_ip_gain(ip_gain) ;
2028 do_mic_lev(mic_lev) ;
2029 do_cd_lev(cd_lev) ;
2030 do_rec_lev(rec_lev) ;
2031 do_passthru_vol(passthru_vol) ;
2032}
2033
2034static int burgundy_mixer_ioctl(u_int cmd, u_long arg)
2035{
2036 int data;
2037 int rc;
2038
2039 /* We are, we are, we are... Burgundy or better */
2040 switch(cmd) {
2041 case SOUND_MIXER_READ_DEVMASK:
2042 data = SOUND_MASK_VOLUME | SOUND_MASK_CD |
2043 SOUND_MASK_LINE | SOUND_MASK_MIC |
2044 SOUND_MASK_SPEAKER | SOUND_MASK_ALTPCM;
2045 rc = IOCTL_OUT(arg, data);
2046 break;
2047 case SOUND_MIXER_READ_RECMASK:
2048 data = SOUND_MASK_LINE | SOUND_MASK_MIC
2049 | SOUND_MASK_CD;
2050 rc = IOCTL_OUT(arg, data);
2051 break;
2052 case SOUND_MIXER_READ_RECSRC:
2053 data = 0;
2054 if (awacs_reg[0] & MASK_MUX_AUDIN)
2055 data |= SOUND_MASK_LINE;
2056 if (awacs_reg[0] & MASK_MUX_MIC)
2057 data |= SOUND_MASK_MIC;
2058 if (awacs_reg[0] & MASK_MUX_CD)
2059 data |= SOUND_MASK_CD;
2060 rc = IOCTL_OUT(arg, data);
2061 break;
2062 case SOUND_MIXER_WRITE_RECSRC:
2063 IOCTL_IN(arg, data);
2064 data &= (SOUND_MASK_LINE
2065 | SOUND_MASK_MIC | SOUND_MASK_CD);
2066 awacs_reg[0] &= ~(MASK_MUX_CD | MASK_MUX_MIC
2067 | MASK_MUX_AUDIN);
2068 if (data & SOUND_MASK_LINE)
2069 awacs_reg[0] |= MASK_MUX_AUDIN;
2070 if (data & SOUND_MASK_MIC)
2071 awacs_reg[0] |= MASK_MUX_MIC;
2072 if (data & SOUND_MASK_CD)
2073 awacs_reg[0] |= MASK_MUX_CD;
2074 awacs_write(awacs_reg[0] | MASK_ADDR0);
2075 rc = IOCTL_OUT(arg, data);
2076 break;
2077 case SOUND_MIXER_READ_STEREODEVS:
2078 data = SOUND_MASK_VOLUME | SOUND_MASK_SPEAKER
2079 | SOUND_MASK_RECLEV | SOUND_MASK_CD
2080 | SOUND_MASK_LINE;
2081 rc = IOCTL_OUT(arg, data);
2082 break;
2083 case SOUND_MIXER_READ_CAPS:
2084 rc = IOCTL_OUT(arg, 0);
2085 break;
2086 case SOUND_MIXER_WRITE_VOLUME:
2087 IOCTL_IN(arg, data);
2088 awacs_burgundy_write_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME, data);
2089 /* Fall through */
2090 case SOUND_MIXER_READ_VOLUME:
2091 rc = IOCTL_OUT(arg, awacs_burgundy_read_mvolume(MASK_ADDR_BURGUNDY_MASTER_VOLUME));
2092 break;
2093 case SOUND_MIXER_WRITE_SPEAKER:
2094 IOCTL_IN(arg, data);
2095 if (!(data & 0xff)) {
2096 /* Mute the left speaker */
2097 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
2098 awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x2);
2099 } else {
2100 /* Unmute the left speaker */
2101 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
2102 awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x2);
2103 }
2104 if (!(data & 0xff00)) {
2105 /* Mute the right speaker */
2106 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
2107 awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) & ~0x4);
2108 } else {
2109 /* Unmute the right speaker */
2110 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES,
2111 awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_MORE_OUTPUTENABLES) | 0x4);
2112 }
2113
2114 data = (((data&0xff)*16)/100 > 0xf ? 0xf :
2115 (((data&0xff)*16)/100)) +
2116 ((((data>>8)*16)/100 > 0xf ? 0xf :
2117 ((((data>>8)*16)/100)))<<4);
2118
2119 awacs_burgundy_wcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER, ~data);
2120 /* Fall through */
2121 case SOUND_MIXER_READ_SPEAKER:
2122 data = awacs_burgundy_rcb(MASK_ADDR_BURGUNDY_ATTENSPEAKER);
2123 data = (((data & 0xf)*100)/16) + ((((data>>4)*100)/16)<<8);
2124 rc = IOCTL_OUT(arg, (~data) & 0x0000ffff);
2125 break;
2126 case SOUND_MIXER_WRITE_ALTPCM: /* really bell volume */
2127 IOCTL_IN(arg, data);
2128 beep_vol = data & 0xff;
2129 /* fall through */
2130 case SOUND_MIXER_READ_ALTPCM:
2131 rc = IOCTL_OUT(arg, beep_vol);
2132 break;
2133 case SOUND_MIXER_WRITE_LINE:
2134 IOCTL_IN(arg, data);
2135 awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLLINE, data);
2136
2137 /* fall through */
2138 case SOUND_MIXER_READ_LINE:
2139 data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLLINE);
2140 rc = IOCTL_OUT(arg, data);
2141 break;
2142 case SOUND_MIXER_WRITE_MIC:
2143 IOCTL_IN(arg, data);
2144 /* Mic is mono device */
2145 data = (data << 8) + (data << 24);
2146 awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLMIC, data);
2147 /* fall through */
2148 case SOUND_MIXER_READ_MIC:
2149 data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLMIC);
2150 data <<= 24;
2151 rc = IOCTL_OUT(arg, data);
2152 break;
2153 case SOUND_MIXER_WRITE_CD:
2154 IOCTL_IN(arg, data);
2155 awacs_burgundy_write_volume(MASK_ADDR_BURGUNDY_VOLCD, data);
2156 /* fall through */
2157 case SOUND_MIXER_READ_CD:
2158 data = awacs_burgundy_read_volume(MASK_ADDR_BURGUNDY_VOLCD);
2159 rc = IOCTL_OUT(arg, data);
2160 break;
2161 case SOUND_MIXER_WRITE_RECLEV:
2162 IOCTL_IN(arg, data);
2163 data = awacs_volume_setter(data, 0, 0, 4);
2164 rc = IOCTL_OUT(arg, data);
2165 break;
2166 case SOUND_MIXER_READ_RECLEV:
2167 data = awacs_get_volume(awacs_reg[0], 4);
2168 rc = IOCTL_OUT(arg, data);
2169 break;
2170 case SOUND_MIXER_OUTMASK:
2171 case SOUND_MIXER_OUTSRC:
2172 default:
2173 rc = -EINVAL;
2174 }
2175
2176 return rc;
2177}
2178
2179static int daca_mixer_ioctl(u_int cmd, u_long arg)
2180{
2181 int data;
2182 int rc;
2183
2184 /* And the DACA's no genius either! */
2185
2186 switch(cmd) {
2187 case SOUND_MIXER_READ_DEVMASK:
2188 data = SOUND_MASK_VOLUME;
2189 rc = IOCTL_OUT(arg, data);
2190 break;
2191 case SOUND_MIXER_READ_RECMASK:
2192 data = 0;
2193 rc = IOCTL_OUT(arg, data);
2194 break;
2195 case SOUND_MIXER_READ_RECSRC:
2196 data = 0;
2197 rc = IOCTL_OUT(arg, data);
2198 break;
2199 case SOUND_MIXER_WRITE_RECSRC:
2200 IOCTL_IN(arg, data);
2201 data =0;
2202 rc = IOCTL_OUT(arg, data);
2203 break;
2204 case SOUND_MIXER_READ_STEREODEVS:
2205 data = SOUND_MASK_VOLUME;
2206 rc = IOCTL_OUT(arg, data);
2207 break;
2208 case SOUND_MIXER_READ_CAPS:
2209 rc = IOCTL_OUT(arg, 0);
2210 break;
2211 case SOUND_MIXER_WRITE_VOLUME:
2212 IOCTL_IN(arg, data);
2213 daca_set_volume(data, data);
2214 /* Fall through */
2215 case SOUND_MIXER_READ_VOLUME:
2216 daca_get_volume(& data, &data);
2217 rc = IOCTL_OUT(arg, data);
2218 break;
2219 case SOUND_MIXER_OUTMASK:
2220 case SOUND_MIXER_OUTSRC:
2221 default:
2222 rc = -EINVAL;
2223 }
2224 return rc;
2225}
2226
2227static int PMacMixerIoctl(u_int cmd, u_long arg)
2228{
2229 int rc;
2230
2231 /* Different IOCTLS for burgundy and, eventually, DACA & Tumbler */
2232
2233 TRY_LOCK();
2234
2235 switch (awacs_revision){
2236 case AWACS_BURGUNDY:
2237 rc = burgundy_mixer_ioctl(cmd, arg);
2238 break ;
2239 case AWACS_DACA:
2240 rc = daca_mixer_ioctl(cmd, arg);
2241 break;
2242 case AWACS_TUMBLER:
2243 case AWACS_SNAPPER:
2244 rc = tas_mixer_ioctl(cmd, arg);
2245 break ;
2246 default: /* ;-)) */
2247 rc = awacs_mixer_ioctl(cmd, arg);
2248 }
2249
2250 UNLOCK();
2251
2252 return rc;
2253}
2254
2255static void PMacMixerInit(void)
2256{
2257 switch (awacs_revision) {
2258 case AWACS_TUMBLER:
2259 printk("AE-Init tumbler mixer\n");
2260 break ;
2261 case AWACS_SNAPPER:
2262 printk("AE-Init snapper mixer\n");
2263 break ;
2264 case AWACS_DACA:
2265 case AWACS_BURGUNDY:
2266 break ; /* don't know yet */
2267 case AWACS_AWACS:
2268 case AWACS_SCREAMER:
2269 default:
2270 awacs_mixer_init() ;
2271 break ;
2272 }
2273}
2274
2275/* Write/Read sq setup functions:
2276 Check to see if we have enough (or any) dbdma cmd buffers for the
2277 user's fragment settings. If not, allocate some. If this fails we will
2278 point at the beep buffer - as an emergency provision - to stop dma tromping
2279 on some random bit of memory (if someone lets it go anyway).
2280 The command buffers are then set up to point to the fragment buffers
2281 (allocated elsewhere). We need n+1 commands the last of which holds
2282 a NOP + loop to start.
2283*/
2284
2285static int PMacWriteSqSetup(void)
2286{
2287 int i, count = 600 ;
2288 volatile struct dbdma_cmd *cp;
2289
2290 LOCK();
2291
2292 /* stop the controller from doing any output - if it isn't already.
2293 it _should_ be before this is called anyway */
2294
2295 out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
2296 while ((in_le32(&awacs_txdma->status) & RUN) && count--)
2297 udelay(1);
2298#ifdef DEBUG_DMASOUND
2299if (count <= 0)
2300 printk("dmasound_pmac: write sq setup: timeout waiting for dma to stop\n");
2301#endif
2302
2303 if ((write_sq.max_count + 1) > number_of_tx_cmd_buffers) {
2304 if (awacs_tx_cmd_space)
2305 kfree(awacs_tx_cmd_space);
2306 number_of_tx_cmd_buffers = 0;
2307
2308 /* we need nbufs + 1 (for the loop) and we should request + 1
2309 again because the DBDMA_ALIGN might pull the start up by up
2310 to sizeof(struct dbdma_cmd) - 4.
2311 */
2312
2313 awacs_tx_cmd_space = kmalloc
2314 ((write_sq.max_count + 1 + 1) * sizeof(struct dbdma_cmd),
2315 GFP_KERNEL);
2316 if (awacs_tx_cmd_space == NULL) {
2317 /* don't leave it dangling - nasty but better than a
2318 random address */
2319 out_le32(&awacs_txdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
2320 printk(KERN_ERR
2321 "dmasound_pmac: can't allocate dbdma cmd buffers"
2322 ", driver disabled\n");
2323 UNLOCK();
2324 return -ENOMEM;
2325 }
2326 awacs_tx_cmds = (volatile struct dbdma_cmd *)
2327 DBDMA_ALIGN(awacs_tx_cmd_space);
2328 number_of_tx_cmd_buffers = write_sq.max_count + 1;
2329 }
2330
2331 cp = awacs_tx_cmds;
2332 memset((void *)cp, 0, (write_sq.max_count+1) * sizeof(struct dbdma_cmd));
2333 for (i = 0; i < write_sq.max_count; ++i, ++cp) {
2334 st_le32(&cp->phy_addr, virt_to_bus(write_sq.buffers[i]));
2335 }
2336 st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
2337 st_le32(&cp->cmd_dep, virt_to_bus(awacs_tx_cmds));
2338 /* point the controller at the command stack - ready to go */
2339 out_le32(&awacs_txdma->cmdptr, virt_to_bus(awacs_tx_cmds));
2340 UNLOCK();
2341 return 0;
2342}
2343
2344static int PMacReadSqSetup(void)
2345{
2346 int i, count = 600;
2347 volatile struct dbdma_cmd *cp;
2348
2349 LOCK();
2350
2351 /* stop the controller from doing any input - if it isn't already.
2352 it _should_ be before this is called anyway */
2353
2354 out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
2355 while ((in_le32(&awacs_rxdma->status) & RUN) && count--)
2356 udelay(1);
2357#ifdef DEBUG_DMASOUND
2358if (count <= 0)
2359 printk("dmasound_pmac: read sq setup: timeout waiting for dma to stop\n");
2360#endif
2361
2362 if ((read_sq.max_count+1) > number_of_rx_cmd_buffers ) {
2363 if (awacs_rx_cmd_space)
2364 kfree(awacs_rx_cmd_space);
2365 number_of_rx_cmd_buffers = 0;
2366
2367 /* we need nbufs + 1 (for the loop) and we should request + 1 again
2368 because the DBDMA_ALIGN might pull the start up by up to
2369 sizeof(struct dbdma_cmd) - 4 (assuming kmalloc aligns 32 bits).
2370 */
2371
2372 awacs_rx_cmd_space = kmalloc
2373 ((read_sq.max_count + 1 + 1) * sizeof(struct dbdma_cmd),
2374 GFP_KERNEL);
2375 if (awacs_rx_cmd_space == NULL) {
2376 /* don't leave it dangling - nasty but better than a
2377 random address */
2378 out_le32(&awacs_rxdma->cmdptr, virt_to_bus(beep_dbdma_cmd));
2379 printk(KERN_ERR
2380 "dmasound_pmac: can't allocate dbdma cmd buffers"
2381 ", driver disabled\n");
2382 UNLOCK();
2383 return -ENOMEM;
2384 }
2385 awacs_rx_cmds = (volatile struct dbdma_cmd *)
2386 DBDMA_ALIGN(awacs_rx_cmd_space);
2387 number_of_rx_cmd_buffers = read_sq.max_count + 1 ;
2388 }
2389 cp = awacs_rx_cmds;
2390 memset((void *)cp, 0, (read_sq.max_count+1) * sizeof(struct dbdma_cmd));
2391
2392 /* Set dma buffers up in a loop */
2393 for (i = 0; i < read_sq.max_count; i++,cp++) {
2394 st_le32(&cp->phy_addr, virt_to_bus(read_sq.buffers[i]));
2395 st_le16(&cp->command, INPUT_MORE + INTR_ALWAYS);
2396 st_le16(&cp->req_count, read_sq.block_size);
2397 st_le16(&cp->xfer_status, 0);
2398 }
2399
2400 /* The next two lines make the thing loop around.
2401 */
2402 st_le16(&cp->command, DBDMA_NOP + BR_ALWAYS);
2403 st_le32(&cp->cmd_dep, virt_to_bus(awacs_rx_cmds));
2404 /* point the controller at the command stack - ready to go */
2405 out_le32(&awacs_rxdma->cmdptr, virt_to_bus(awacs_rx_cmds));
2406
2407 UNLOCK();
2408 return 0;
2409}
2410
2411/* TODO: this needs work to guarantee that when it returns DMA has stopped
2412 but in a more elegant way than is done here....
2413*/
2414
2415static void PMacAbortRead(void)
2416{
2417 int i;
2418 volatile struct dbdma_cmd *cp;
2419
2420 LOCK();
2421 /* give it a chance to update the output and provide the IRQ
2422 that is expected.
2423 */
2424
2425 out_le32(&awacs_rxdma->control, ((FLUSH) << 16) + FLUSH );
2426
2427 cp = awacs_rx_cmds;
2428 for (i = 0; i < read_sq.max_count; i++,cp++)
2429 st_le16(&cp->command, DBDMA_STOP);
2430 /*
2431 * We should probably wait for the thing to stop before we
2432 * release the memory.
2433 */
2434
2435 msleep(100) ; /* give it a (small) chance to act */
2436
2437 /* apply the sledgehammer approach - just stop it now */
2438
2439 out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE) << 16);
2440 UNLOCK();
2441}
2442
2443extern char *get_afmt_string(int);
2444static int PMacStateInfo(char *b, size_t sp)
2445{
2446 int i, len = 0;
2447 len = sprintf(b,"HW rates: ");
2448 switch (awacs_revision){
2449 case AWACS_DACA:
2450 case AWACS_BURGUNDY:
2451 len += sprintf(b,"44100 ") ;
2452 break ;
2453 case AWACS_TUMBLER:
2454 case AWACS_SNAPPER:
2455 for (i=0; i<1; i++){
2456 if (tas_freqs_ok[i])
2457 len += sprintf(b+len,"%d ", tas_freqs[i]) ;
2458 }
2459 break ;
2460 case AWACS_AWACS:
2461 case AWACS_SCREAMER:
2462 default:
2463 for (i=0; i<8; i++){
2464 if (awacs_freqs_ok[i])
2465 len += sprintf(b+len,"%d ", awacs_freqs[i]) ;
2466 }
2467 break ;
2468 }
2469 len += sprintf(b+len,"s/sec\n") ;
2470 if (len < sp) {
2471 len += sprintf(b+len,"HW AFMTS: ");
2472 i = AFMT_U16_BE ;
2473 while (i) {
2474 if (i & dmasound.mach.hardware_afmts)
2475 len += sprintf(b+len,"%s ",
2476 get_afmt_string(i & dmasound.mach.hardware_afmts));
2477 i >>= 1 ;
2478 }
2479 len += sprintf(b+len,"\n") ;
2480 }
2481 return len ;
2482}
2483
2484/*** Machine definitions *****************************************************/
2485
2486static SETTINGS def_hard = {
2487 .format = AFMT_S16_BE,
2488 .stereo = 1,
2489 .size = 16,
2490 .speed = 44100
2491} ;
2492
2493static SETTINGS def_soft = {
2494 .format = AFMT_S16_BE,
2495 .stereo = 1,
2496 .size = 16,
2497 .speed = 44100
2498} ;
2499
2500static MACHINE machPMac = {
2501 .name = awacs_name,
2502 .name2 = "PowerMac Built-in Sound",
2503 .owner = THIS_MODULE,
2504 .dma_alloc = PMacAlloc,
2505 .dma_free = PMacFree,
2506 .irqinit = PMacIrqInit,
2507#ifdef MODULE
2508 .irqcleanup = PMacIrqCleanup,
2509#endif /* MODULE */
2510 .init = PMacInit,
2511 .silence = PMacSilence,
2512 .setFormat = PMacSetFormat,
2513 .setVolume = PMacSetVolume,
2514 .play = PMacPlay,
2515 .record = NULL, /* default to no record */
2516 .mixer_init = PMacMixerInit,
2517 .mixer_ioctl = PMacMixerIoctl,
2518 .write_sq_setup = PMacWriteSqSetup,
2519 .read_sq_setup = PMacReadSqSetup,
2520 .state_info = PMacStateInfo,
2521 .abort_read = PMacAbortRead,
2522 .min_dsp_speed = 7350,
2523 .max_dsp_speed = 44100,
2524 .version = ((DMASOUND_AWACS_REVISION<<8) + DMASOUND_AWACS_EDITION)
2525};
2526
2527
2528/*** Config & Setup **********************************************************/
2529
2530/* Check for pmac models that we care about in terms of special actions.
2531*/
2532
2533void __init
2534set_model(void)
2535{
2536 /* portables/lap-tops */
2537
2538 if (machine_is_compatible("AAPL,3400/2400") ||
2539 machine_is_compatible("AAPL,3500")) {
2540 is_pbook_3X00 = 1 ;
2541 }
2542 if (machine_is_compatible("PowerBook1,1") || /* lombard */
2543 machine_is_compatible("AAPL,PowerBook1998")){ /* wallstreet */
2544 is_pbook_g3 = 1 ;
2545 return ;
2546 }
2547}
2548
2549/* Get the OF node that tells us about the registers, interrupts etc. to use
2550 for sound IO.
2551
2552 On most machines the sound IO OF node is the 'davbus' node. On newer pmacs
2553 with DACA (& Tumbler) the node to use is i2s-a. On much older machines i.e.
2554 before 9500 there is no davbus node and we have to use the 'awacs' property.
2555
2556 In the latter case we signal this by setting the codec value - so that the
2557 code that looks for chip properties knows how to go about it.
2558*/
2559
2560static struct device_node* __init
2561get_snd_io_node(void)
2562{
2563 struct device_node *np = NULL;
2564
2565 /* set up awacs_node for early OF which doesn't have a full set of
2566 * properties on davbus
2567 */
2568
2569 awacs_node = find_devices("awacs");
2570 if (awacs_node)
2571 awacs_revision = AWACS_AWACS;
2572
2573 /* powermac models after 9500 (other than those which use DACA or
2574 * Tumbler) have a node called "davbus".
2575 */
2576 np = find_devices("davbus");
2577 /*
2578 * if we didn't find a davbus device, try 'i2s-a' since
2579 * this seems to be what iBooks (& Tumbler) have.
2580 */
2581 if (np == NULL)
2582 np = i2s_node = find_devices("i2s-a");
2583
2584 /* if we didn't find this - perhaps we are on an early model
2585 * which _only_ has an 'awacs' node
2586 */
2587 if (np == NULL && awacs_node)
2588 np = awacs_node ;
2589
2590 /* if we failed all these return null - this will cause the
2591 * driver to give up...
2592 */
2593 return np ;
2594}
2595
2596/* Get the OF node that contains the info about the sound chip, inputs s-rates
2597 etc.
2598 This node does not exist (or contains much reduced info) on earlier machines
2599 we have to deduce the info other ways for these.
2600*/
2601
2602static struct device_node* __init
2603get_snd_info_node(struct device_node *io)
2604{
2605 struct device_node *info;
2606
2607 info = find_devices("sound");
2608 while (info && info->parent != io)
2609 info = info->next;
2610 return info;
2611}
2612
2613/* Find out what type of codec we have.
2614*/
2615
2616static int __init
2617get_codec_type(struct device_node *info)
2618{
2619 /* already set if pre-davbus model and info will be NULL */
2620 int codec = awacs_revision ;
2621
2622 if (info) {
2623 /* must do awacs first to allow screamer to overide it */
2624 if (device_is_compatible(info, "awacs"))
2625 codec = AWACS_AWACS ;
2626 if (device_is_compatible(info, "screamer"))
2627 codec = AWACS_SCREAMER;
2628 if (device_is_compatible(info, "burgundy"))
2629 codec = AWACS_BURGUNDY ;
2630 if (device_is_compatible(info, "daca"))
2631 codec = AWACS_DACA;
2632 if (device_is_compatible(info, "tumbler"))
2633 codec = AWACS_TUMBLER;
2634 if (device_is_compatible(info, "snapper"))
2635 codec = AWACS_SNAPPER;
2636 }
2637 return codec ;
2638}
2639
2640/* find out what type, if any, of expansion card we have
2641*/
2642static void __init
2643get_expansion_type(void)
2644{
2645 if (find_devices("perch") != NULL)
2646 has_perch = 1;
2647
2648 if (find_devices("pb-ziva-pc") != NULL)
2649 has_ziva = 1;
2650 /* need to work out how we deal with iMac SRS module */
2651}
2652
2653/* set up frame rates.
2654 * I suspect that these routines don't quite go about it the right way:
2655 * - where there is more than one rate - I think that the first property
2656 * value is the number of rates.
2657 * TODO: check some more device trees and modify accordingly
2658 * Set dmasound.mach.max_dsp_rate on the basis of these routines.
2659*/
2660
2661static void __init
2662awacs_init_frame_rates(unsigned int *prop, unsigned int l)
2663{
2664 int i ;
2665 if (prop) {
2666 for (i=0; i<8; i++)
2667 awacs_freqs_ok[i] = 0 ;
2668 for (l /= sizeof(int); l > 0; --l) {
2669 unsigned int r = *prop++;
2670 /* Apple 'Fixed' format */
2671 if (r >= 0x10000)
2672 r >>= 16;
2673 for (i = 0; i < 8; ++i) {
2674 if (r == awacs_freqs[i]) {
2675 awacs_freqs_ok[i] = 1;
2676 break;
2677 }
2678 }
2679 }
2680 }
2681 /* else we assume that all the rates are available */
2682}
2683
2684static void __init
2685burgundy_init_frame_rates(unsigned int *prop, unsigned int l)
2686{
2687 int temp[9] ;
2688 int i = 0 ;
2689 if (prop) {
2690 for (l /= sizeof(int); l > 0; --l) {
2691 unsigned int r = *prop++;
2692 /* Apple 'Fixed' format */
2693 if (r >= 0x10000)
2694 r >>= 16;
2695 temp[i] = r ;
2696 i++ ; if(i>=9) i=8;
2697 }
2698 }
2699#ifdef DEBUG_DMASOUND
2700if (i > 1){
2701 int j;
2702 printk("dmasound_pmac: burgundy with multiple frame rates\n");
2703 for(j=0; j<i; j++)
2704 printk("%d ", temp[j]) ;
2705 printk("\n") ;
2706}
2707#endif
2708}
2709
2710static void __init
2711daca_init_frame_rates(unsigned int *prop, unsigned int l)
2712{
2713 int temp[9] ;
2714 int i = 0 ;
2715 if (prop) {
2716 for (l /= sizeof(int); l > 0; --l) {
2717 unsigned int r = *prop++;
2718 /* Apple 'Fixed' format */
2719 if (r >= 0x10000)
2720 r >>= 16;
2721 temp[i] = r ;
2722 i++ ; if(i>=9) i=8;
2723
2724 }
2725 }
2726#ifdef DEBUG_DMASOUND
2727if (i > 1){
2728 int j;
2729 printk("dmasound_pmac: DACA with multiple frame rates\n");
2730 for(j=0; j<i; j++)
2731 printk("%d ", temp[j]) ;
2732 printk("\n") ;
2733}
2734#endif
2735}
2736
2737static void __init
2738init_frame_rates(unsigned int *prop, unsigned int l)
2739{
2740 switch (awacs_revision) {
2741 case AWACS_TUMBLER:
2742 case AWACS_SNAPPER:
2743 tas_init_frame_rates(prop, l);
2744 break ;
2745 case AWACS_DACA:
2746 daca_init_frame_rates(prop, l);
2747 break ;
2748 case AWACS_BURGUNDY:
2749 burgundy_init_frame_rates(prop, l);
2750 break ;
2751 default:
2752 awacs_init_frame_rates(prop, l);
2753 break ;
2754 }
2755}
2756
2757/* find things/machines that can't do mac-io byteswap
2758*/
2759
2760static void __init
2761set_hw_byteswap(struct device_node *io)
2762{
2763 struct device_node *mio ;
2764 unsigned int kl = 0 ;
2765
2766 /* if seems that Keylargo can't byte-swap */
2767
2768 for (mio = io->parent; mio ; mio = mio->parent) {
2769 if (strcmp(mio->name, "mac-io") == 0) {
2770 if (device_is_compatible(mio, "Keylargo"))
2771 kl = 1;
2772 break;
2773 }
2774 }
2775 hw_can_byteswap = !kl;
2776}
2777
2778/* Allocate the resources necessary for beep generation. This cannot be (quite)
2779 done statically (yet) because we cannot do virt_to_bus() on static vars when
2780 the code is loaded as a module.
2781
2782 for the sake of saving the possibility that two allocations will incur the
2783 overhead of two pull-ups in DBDMA_ALIGN() we allocate the 'emergency' dmdma
2784 command here as well... even tho' it is not part of the beep process.
2785*/
2786
2787int32_t
2788__init setup_beep(void)
2789{
2790 /* Initialize beep stuff */
2791 /* want one cmd buffer for beeps, and a second one for emergencies
2792 - i.e. dbdma error conditions.
2793 ask for three to allow for pull up in DBDMA_ALIGN().
2794 */
2795 beep_dbdma_cmd_space =
2796 kmalloc((2 + 1) * sizeof(struct dbdma_cmd), GFP_KERNEL);
2797 if(beep_dbdma_cmd_space == NULL) {
2798 printk(KERN_ERR "dmasound_pmac: no beep dbdma cmd space\n") ;
2799 return -ENOMEM ;
2800 }
2801 beep_dbdma_cmd = (volatile struct dbdma_cmd *)
2802 DBDMA_ALIGN(beep_dbdma_cmd_space);
2803 /* set up emergency dbdma cmd */
2804 emergency_dbdma_cmd = beep_dbdma_cmd+1 ;
2805 beep_buf = (short *) kmalloc(BEEP_BUFLEN * 4, GFP_KERNEL);
2806 if (beep_buf == NULL) {
2807 printk(KERN_ERR "dmasound_pmac: no memory for beep buffer\n");
2808 if( beep_dbdma_cmd_space ) kfree(beep_dbdma_cmd_space) ;
2809 return -ENOMEM ;
2810 }
2811 return 0 ;
2812}
2813
2814static struct input_dev awacs_beep_dev = {
2815 .evbit = { BIT(EV_SND) },
2816 .sndbit = { BIT(SND_BELL) | BIT(SND_TONE) },
2817 .event = awacs_beep_event,
2818 .name = "dmasound beeper",
2819 .phys = "macio/input0", /* what the heck is this?? */
2820 .id = {
2821 .bustype = BUS_HOST,
2822 },
2823};
2824
2825int __init dmasound_awacs_init(void)
2826{
2827 struct device_node *io = NULL, *info = NULL;
2828 int vol, res;
2829
2830 if (_machine != _MACH_Pmac)
2831 return -ENODEV;
2832
2833 awacs_subframe = 0;
2834 awacs_revision = 0;
2835 hw_can_byteswap = 1 ; /* most can */
2836
2837 /* look for models we need to handle specially */
2838 set_model() ;
2839
2840 /* find the OF node that tells us about the dbdma stuff
2841 */
2842 io = get_snd_io_node();
2843 if (io == NULL) {
2844#ifdef DEBUG_DMASOUND
2845printk("dmasound_pmac: couldn't find sound io OF node\n");
2846#endif
2847 return -ENODEV ;
2848 }
2849
2850 /* find the OF node that tells us about the sound sub-system
2851 * this doesn't exist on pre-davbus machines (earlier than 9500)
2852 */
2853 if (awacs_revision != AWACS_AWACS) { /* set for pre-davbus */
2854 info = get_snd_info_node(io) ;
2855 if (info == NULL){
2856#ifdef DEBUG_DMASOUND
2857printk("dmasound_pmac: couldn't find 'sound' OF node\n");
2858#endif
2859 return -ENODEV ;
2860 }
2861 }
2862
2863 awacs_revision = get_codec_type(info) ;
2864 if (awacs_revision == 0) {
2865#ifdef DEBUG_DMASOUND
2866printk("dmasound_pmac: couldn't find a Codec we can handle\n");
2867#endif
2868 return -ENODEV ; /* we don't know this type of h/w */
2869 }
2870
2871 /* set up perch, ziva, SRS or whatever else we have as sound
2872 * expansion.
2873 */
2874 get_expansion_type();
2875
2876 /* we've now got enough information to make up the audio topology.
2877 * we will map the sound part of mac-io now so that we can probe for
2878 * other info if necessary (early AWACS we want to read chip ids)
2879 */
2880
2881 if (io->n_addrs < 3 || io->n_intrs < 3) {
2882 /* OK - maybe we need to use the 'awacs' node (on earlier
2883 * machines).
2884 */
2885 if (awacs_node) {
2886 io = awacs_node ;
2887 if (io->n_addrs < 3 || io->n_intrs < 3) {
2888 printk("dmasound_pmac: can't use %s"
2889 " (%d addrs, %d intrs)\n",
2890 io->full_name, io->n_addrs, io->n_intrs);
2891 return -ENODEV;
2892 }
2893 } else {
2894 printk("dmasound_pmac: can't use %s (%d addrs, %d intrs)\n",
2895 io->full_name, io->n_addrs, io->n_intrs);
2896 }
2897 }
2898
2899 if (!request_OF_resource(io, 0, NULL)) {
2900 printk(KERN_ERR "dmasound: can't request IO resource !\n");
2901 return -ENODEV;
2902 }
2903 if (!request_OF_resource(io, 1, " (tx dma)")) {
2904 release_OF_resource(io, 0);
2905 printk(KERN_ERR "dmasound: can't request TX DMA resource !\n");
2906 return -ENODEV;
2907 }
2908
2909 if (!request_OF_resource(io, 2, " (rx dma)")) {
2910 release_OF_resource(io, 0);
2911 release_OF_resource(io, 1);
2912 printk(KERN_ERR "dmasound: can't request RX DMA resource !\n");
2913 return -ENODEV;
2914 }
2915
2916 /* all OF versions I've seen use this value */
2917 if (i2s_node)
2918 i2s = ioremap(io->addrs[0].address, 0x1000);
2919 else
2920 awacs = ioremap(io->addrs[0].address, 0x1000);
2921 awacs_txdma = ioremap(io->addrs[1].address, 0x100);
2922 awacs_rxdma = ioremap(io->addrs[2].address, 0x100);
2923
2924 /* first of all make sure that the chip is powered up....*/
2925 pmac_call_feature(PMAC_FTR_SOUND_CHIP_ENABLE, io, 0, 1);
2926 if (awacs_revision == AWACS_SCREAMER && awacs)
2927 awacs_recalibrate();
2928
2929 awacs_irq = io->intrs[0].line;
2930 awacs_tx_irq = io->intrs[1].line;
2931 awacs_rx_irq = io->intrs[2].line;
2932
2933 /* Hack for legacy crap that will be killed someday */
2934 awacs_node = io;
2935
2936 /* if we have an awacs or screamer - probe the chip to make
2937 * sure we have the right revision.
2938 */
2939
2940 if (awacs_revision <= AWACS_SCREAMER){
2941 uint32_t temp, rev, mfg ;
2942 /* find out the awacs revision from the chip */
2943 temp = in_le32(&awacs->codec_stat);
2944 rev = (temp >> 12) & 0xf;
2945 mfg = (temp >> 8) & 0xf;
2946#ifdef DEBUG_DMASOUND
2947printk("dmasound_pmac: Awacs/Screamer Codec Mfct: %d Rev %d\n", mfg, rev);
2948#endif
2949 if (rev >= AWACS_SCREAMER)
2950 awacs_revision = AWACS_SCREAMER ;
2951 else
2952 awacs_revision = rev ;
2953 }
2954
2955 dmasound.mach = machPMac;
2956
2957 /* find out other bits & pieces from OF, these may be present
2958 only on some models ... so be careful.
2959 */
2960
2961 /* in the absence of a frame rates property we will use the defaults
2962 */
2963
2964 if (info) {
2965 unsigned int *prop, l;
2966
2967 sound_device_id = 0;
2968 /* device ID appears post g3 b&w */
2969 prop = (unsigned int *)get_property(info, "device-id", NULL);
2970 if (prop != 0)
2971 sound_device_id = *prop;
2972
2973 /* look for a property saying what sample rates
2974 are available */
2975
2976 prop = (unsigned int *)get_property(info, "sample-rates", &l);
2977 if (prop == 0)
2978 prop = (unsigned int *) get_property
2979 (info, "output-frame-rates", &l);
2980
2981 /* if it's there use it to set up frame rates */
2982 init_frame_rates(prop, l) ;
2983 }
2984
2985 if (awacs)
2986 out_le32(&awacs->control, 0x11); /* set everything quiesent */
2987
2988 set_hw_byteswap(io) ; /* figure out if the h/w can do it */
2989
2990#ifdef CONFIG_NVRAM
2991 /* get default volume from nvram */
2992 vol = ((pmac_xpram_read( 8 ) & 7 ) << 1 );
2993#else
2994 vol = 0;
2995#endif
2996
2997 /* set up tracking values */
2998 spk_vol = vol * 100 ;
2999 spk_vol /= 7 ; /* get set value to a percentage */
3000 spk_vol |= (spk_vol << 8) ; /* equal left & right */
3001 line_vol = passthru_vol = spk_vol ;
3002
3003 /* fill regs that are shared between AWACS & Burgundy */
3004
3005 awacs_reg[2] = vol + (vol << 6);
3006 awacs_reg[4] = vol + (vol << 6);
3007 awacs_reg[5] = vol + (vol << 6); /* screamer has loopthru vol control */
3008 awacs_reg[6] = 0; /* maybe should be vol << 3 for PCMCIA speaker */
3009 awacs_reg[7] = 0;
3010
3011 awacs_reg[0] = MASK_MUX_CD;
3012 awacs_reg[1] = MASK_LOOPTHRU;
3013
3014 /* FIXME: Only machines with external SRS module need MASK_PAROUT */
3015 if (has_perch || sound_device_id == 0x5
3016 || /*sound_device_id == 0x8 ||*/ sound_device_id == 0xb)
3017 awacs_reg[1] |= MASK_PAROUT0 | MASK_PAROUT1;
3018
3019 switch (awacs_revision) {
3020 case AWACS_TUMBLER:
3021 tas_register_driver(&tas3001c_hooks);
3022 tas_init(I2C_DRIVERID_TAS3001C, I2C_DRIVERNAME_TAS3001C);
3023 tas_dmasound_init();
3024 tas_post_init();
3025 break ;
3026 case AWACS_SNAPPER:
3027 tas_register_driver(&tas3004_hooks);
3028 tas_init(I2C_DRIVERID_TAS3004,I2C_DRIVERNAME_TAS3004);
3029 tas_dmasound_init();
3030 tas_post_init();
3031 break;
3032 case AWACS_DACA:
3033 daca_init();
3034 break;
3035 case AWACS_BURGUNDY:
3036 awacs_burgundy_init();
3037 break ;
3038 case AWACS_SCREAMER:
3039 case AWACS_AWACS:
3040 default:
3041 load_awacs();
3042 break ;
3043 }
3044
3045 /* enable/set-up external modules - when we know how */
3046
3047 if (has_perch)
3048 awacs_enable_amp(100 * 0x101);
3049
3050 /* Reset dbdma channels */
3051 out_le32(&awacs_txdma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
3052 while (in_le32(&awacs_txdma->status) & RUN)
3053 udelay(1);
3054 out_le32(&awacs_rxdma->control, (RUN|PAUSE|FLUSH|WAKE|DEAD) << 16);
3055 while (in_le32(&awacs_rxdma->status) & RUN)
3056 udelay(1);
3057
3058 /* Initialize beep stuff */
3059 if ((res=setup_beep()))
3060 return res ;
3061
3062#ifdef CONFIG_PMAC_PBOOK
3063 pmu_register_sleep_notifier(&awacs_sleep_notifier);
3064#endif /* CONFIG_PMAC_PBOOK */
3065
3066 /* Powerbooks have odd ways of enabling inputs such as
3067 an expansion-bay CD or sound from an internal modem
3068 or a PC-card modem. */
3069 if (is_pbook_3X00) {
3070 /*
3071 * Enable CD and PC-card sound inputs.
3072 * This is done by reading from address
3073 * f301a000, + 0x10 to enable the expansion-bay
3074 * CD sound input, + 0x80 to enable the PC-card
3075 * sound input. The 0x100 enables the SCSI bus
3076 * terminator power.
3077 */
3078 latch_base = ioremap (0xf301a000, 0x1000);
3079 in_8(latch_base + 0x190);
3080
3081 } else if (is_pbook_g3) {
3082 struct device_node* mio;
3083 macio_base = NULL;
3084 for (mio = io->parent; mio; mio = mio->parent) {
3085 if (strcmp(mio->name, "mac-io") == 0
3086 && mio->n_addrs > 0) {
3087 macio_base = ioremap(mio->addrs[0].address, 0x40);
3088 break;
3089 }
3090 }
3091 /*
3092 * Enable CD sound input.
3093 * The relevant bits for writing to this byte are 0x8f.
3094 * I haven't found out what the 0x80 bit does.
3095 * For the 0xf bits, writing 3 or 7 enables the CD
3096 * input, any other value disables it. Values
3097 * 1, 3, 5, 7 enable the microphone. Values 0, 2,
3098 * 4, 6, 8 - f enable the input from the modem.
3099 * -- paulus.
3100 */
3101 if (macio_base)
3102 out_8(macio_base + 0x37, 3);
3103 }
3104
3105 if (hw_can_byteswap)
3106 dmasound.mach.hardware_afmts = (AFMT_S16_BE | AFMT_S16_LE) ;
3107 else
3108 dmasound.mach.hardware_afmts = AFMT_S16_BE ;
3109
3110 /* shut out chips that do output only.
3111 * may need to extend this to machines which have no inputs - even tho'
3112 * they use screamer - IIRC one of the powerbooks is like this.
3113 */
3114
3115 if (awacs_revision != AWACS_DACA) {
3116 dmasound.mach.capabilities = DSP_CAP_DUPLEX ;
3117 dmasound.mach.record = PMacRecord ;
3118 }
3119
3120 dmasound.mach.default_hard = def_hard ;
3121 dmasound.mach.default_soft = def_soft ;
3122
3123 switch (awacs_revision) {
3124 case AWACS_BURGUNDY:
3125 sprintf(awacs_name, "PowerMac Burgundy ") ;
3126 break ;
3127 case AWACS_DACA:
3128 sprintf(awacs_name, "PowerMac DACA ") ;
3129 break ;
3130 case AWACS_TUMBLER:
3131 sprintf(awacs_name, "PowerMac Tumbler ") ;
3132 break ;
3133 case AWACS_SNAPPER:
3134 sprintf(awacs_name, "PowerMac Snapper ") ;
3135 break ;
3136 case AWACS_SCREAMER:
3137 sprintf(awacs_name, "PowerMac Screamer ") ;
3138 break ;
3139 case AWACS_AWACS:
3140 default:
3141 sprintf(awacs_name, "PowerMac AWACS rev %d ", awacs_revision) ;
3142 break ;
3143 }
3144
3145 /*
3146 * XXX: we should handle errors here, but that would mean
3147 * rewriting the whole init code. later..
3148 */
3149 input_register_device(&awacs_beep_dev);
3150
3151 return dmasound_init();
3152}
3153
3154static void __exit dmasound_awacs_cleanup(void)
3155{
3156 input_unregister_device(&awacs_beep_dev);
3157
3158 switch (awacs_revision) {
3159 case AWACS_TUMBLER:
3160 case AWACS_SNAPPER:
3161 tas_dmasound_cleanup();
3162 tas_cleanup();
3163 break ;
3164 case AWACS_DACA:
3165 daca_cleanup();
3166 break;
3167 }
3168 dmasound_deinit();
3169
3170}
3171
3172MODULE_DESCRIPTION("PowerMac built-in audio driver.");
3173MODULE_LICENSE("GPL");
3174
3175module_init(dmasound_awacs_init);
3176module_exit(dmasound_awacs_cleanup);
diff --git a/sound/oss/dmasound/dmasound_core.c b/sound/oss/dmasound/dmasound_core.c
new file mode 100644
index 000000000000..c9302a1e515b
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_core.c
@@ -0,0 +1,1829 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_core.c
3 *
4 *
5 * OSS/Free compatible Atari TT/Falcon and Amiga DMA sound driver for
6 * Linux/m68k
7 * Extended to support Power Macintosh for Linux/ppc by Paul Mackerras
8 *
9 * (c) 1995 by Michael Schlueter & Michael Marte
10 *
11 * Michael Schlueter (michael@duck.syd.de) did the basic structure of the VFS
12 * interface and the u-law to signed byte conversion.
13 *
14 * Michael Marte (marte@informatik.uni-muenchen.de) did the sound queue,
15 * /dev/mixer, /dev/sndstat and complemented the VFS interface. He would like
16 * to thank:
17 * - Michael Schlueter for initial ideas and documentation on the MFP and
18 * the DMA sound hardware.
19 * - Therapy? for their CD 'Troublegum' which really made me rock.
20 *
21 * /dev/sndstat is based on code by Hannu Savolainen, the author of the
22 * VoxWare family of drivers.
23 *
24 * This file is subject to the terms and conditions of the GNU General Public
25 * License. See the file COPYING in the main directory of this archive
26 * for more details.
27 *
28 * History:
29 *
30 * 1995/8/25 First release
31 *
32 * 1995/9/02 Roman Hodek:
33 * - Fixed atari_stram_alloc() call, the timer
34 * programming and several race conditions
35 * 1995/9/14 Roman Hodek:
36 * - After some discussion with Michael Schlueter,
37 * revised the interrupt disabling
38 * - Slightly speeded up U8->S8 translation by using
39 * long operations where possible
40 * - Added 4:3 interpolation for /dev/audio
41 *
42 * 1995/9/20 Torsten Scherer:
43 * - Fixed a bug in sq_write and changed /dev/audio
44 * converting to play at 12517Hz instead of 6258Hz.
45 *
46 * 1995/9/23 Torsten Scherer:
47 * - Changed sq_interrupt() and sq_play() to pre-program
48 * the DMA for another frame while there's still one
49 * running. This allows the IRQ response to be
50 * arbitrarily delayed and playing will still continue.
51 *
52 * 1995/10/14 Guenther Kelleter, Torsten Scherer:
53 * - Better support for Falcon audio (the Falcon doesn't
54 * raise an IRQ at the end of a frame, but at the
55 * beginning instead!). uses 'if (codec_dma)' in lots
56 * of places to simply switch between Falcon and TT
57 * code.
58 *
59 * 1995/11/06 Torsten Scherer:
60 * - Started introducing a hardware abstraction scheme
61 * (may perhaps also serve for Amigas?)
62 * - Can now play samples at almost all frequencies by
63 * means of a more generalized expand routine
64 * - Takes a good deal of care to cut data only at
65 * sample sizes
66 * - Buffer size is now a kernel runtime option
67 * - Implemented fsync() & several minor improvements
68 * Guenther Kelleter:
69 * - Useful hints and bug fixes
70 * - Cross-checked it for Falcons
71 *
72 * 1996/3/9 Geert Uytterhoeven:
73 * - Support added for Amiga, A-law, 16-bit little
74 * endian.
75 * - Unification to drivers/sound/dmasound.c.
76 *
77 * 1996/4/6 Martin Mitchell:
78 * - Updated to 1.3 kernel.
79 *
80 * 1996/6/13 Topi Kanerva:
81 * - Fixed things that were broken (mainly the amiga
82 * 14-bit routines)
83 * - /dev/sndstat shows now the real hardware frequency
84 * - The lowpass filter is disabled by default now
85 *
86 * 1996/9/25 Geert Uytterhoeven:
87 * - Modularization
88 *
89 * 1998/6/10 Andreas Schwab:
90 * - Converted to use sound_core
91 *
92 * 1999/12/28 Richard Zidlicky:
93 * - Added support for Q40
94 *
95 * 2000/2/27 Geert Uytterhoeven:
96 * - Clean up and split the code into 4 parts:
97 * o dmasound_core: machine-independent code
98 * o dmasound_atari: Atari TT and Falcon support
99 * o dmasound_awacs: Apple PowerMac support
100 * o dmasound_paula: Amiga support
101 *
102 * 2000/3/25 Geert Uytterhoeven:
103 * - Integration of dmasound_q40
104 * - Small clean ups
105 *
106 * 2001/01/26 [1.0] Iain Sandoe
107 * - make /dev/sndstat show revision & edition info.
108 * - since dmasound.mach.sq_setup() can fail on pmac
109 * its type has been changed to int and the returns
110 * are checked.
111 * [1.1] - stop missing translations from being called.
112 * 2001/02/08 [1.2] - remove unused translation tables & move machine-
113 * specific tables to low-level.
114 * - return correct info. for SNDCTL_DSP_GETFMTS.
115 * [1.3] - implement SNDCTL_DSP_GETCAPS fully.
116 * [1.4] - make /dev/sndstat text length usage deterministic.
117 * - make /dev/sndstat call to low-level
118 * dmasound.mach.state_info() pass max space to ll driver.
119 * - tidy startup banners and output info.
120 * [1.5] - tidy up a little (removed some unused #defines in
121 * dmasound.h)
122 * - fix up HAS_RECORD conditionalisation.
123 * - add record code in places it is missing...
124 * - change buf-sizes to bytes to allow < 1kb for pmac
125 * if user param entry is < 256 the value is taken to
126 * be in kb > 256 is taken to be in bytes.
127 * - make default buff/frag params conditional on
128 * machine to allow smaller values for pmac.
129 * - made the ioctls, read & write comply with the OSS
130 * rules on setting params.
131 * - added parsing of _setup() params for record.
132 * 2001/04/04 [1.6] - fix bug where sample rates higher than maximum were
133 * being reported as OK.
134 * - fix open() to return -EBUSY as per OSS doc. when
135 * audio is in use - this is independent of O_NOBLOCK.
136 * - fix bug where SNDCTL_DSP_POST was blocking.
137 */
138
139 /* Record capability notes 30/01/2001:
140 * At present these observations apply only to pmac LL driver (the only one
141 * that can do record, at present). However, if other LL drivers for machines
142 * with record are added they may apply.
143 *
144 * The fragment parameters for the record and play channels are separate.
145 * However, if the driver is opened O_RDWR there is no way (in the current OSS
146 * API) to specify their values independently for the record and playback
147 * channels. Since the only common factor between the input & output is the
148 * sample rate (on pmac) it should be possible to open /dev/dspX O_WRONLY and
149 * /dev/dspY O_RDONLY. The input & output channels could then have different
150 * characteristics (other than the first that sets sample rate claiming the
151 * right to set it for ever). As it stands, the format, channels, number of
152 * bits & sample rate are assumed to be common. In the future perhaps these
153 * should be the responsibility of the LL driver - and then if a card really
154 * does not share items between record & playback they can be specified
155 * separately.
156*/
157
158/* Thread-safeness of shared_resources notes: 31/01/2001
159 * If the user opens O_RDWR and then splits record & play between two threads
160 * both of which inherit the fd - and then starts changing things from both
161 * - we will have difficulty telling.
162 *
163 * It's bad application coding - but ...
164 * TODO: think about how to sort this out... without bogging everything down in
165 * semaphores.
166 *
167 * Similarly, the OSS spec says "all changes to parameters must be between
168 * open() and the first read() or write(). - and a bit later on (by
169 * implication) "between SNDCTL_DSP_RESET and the first read() or write() after
170 * it". If the app is multi-threaded and this rule is broken between threads
171 * we will have trouble spotting it - and the fault will be rather obscure :-(
172 *
173 * We will try and put out at least a kmsg if we see it happen... but I think
174 * it will be quite hard to trap it with an -EXXX return... because we can't
175 * see the fault until after the damage is done.
176*/
177
178#include <linux/module.h>
179#include <linux/slab.h>
180#include <linux/sound.h>
181#include <linux/init.h>
182#include <linux/soundcard.h>
183#include <linux/poll.h>
184#include <linux/smp_lock.h>
185
186#include <asm/uaccess.h>
187
188#include "dmasound.h"
189
190#define DMASOUND_CORE_REVISION 1
191#define DMASOUND_CORE_EDITION 6
192
193 /*
194 * Declarations
195 */
196
197int dmasound_catchRadius = 0;
198MODULE_PARM(dmasound_catchRadius, "i");
199
200static unsigned int numWriteBufs = DEFAULT_N_BUFFERS;
201MODULE_PARM(numWriteBufs, "i");
202static unsigned int writeBufSize = DEFAULT_BUFF_SIZE ; /* in bytes */
203MODULE_PARM(writeBufSize, "i");
204
205#ifdef HAS_RECORD
206static unsigned int numReadBufs = DEFAULT_N_BUFFERS;
207MODULE_PARM(numReadBufs, "i");
208static unsigned int readBufSize = DEFAULT_BUFF_SIZE; /* in bytes */
209MODULE_PARM(readBufSize, "i");
210#endif
211
212MODULE_LICENSE("GPL");
213
214#ifdef MODULE
215static int sq_unit = -1;
216static int mixer_unit = -1;
217static int state_unit = -1;
218static int irq_installed;
219#endif /* MODULE */
220
221/* software implemented recording volume! */
222uint software_input_volume = SW_INPUT_VOLUME_SCALE * SW_INPUT_VOLUME_DEFAULT;
223EXPORT_SYMBOL(software_input_volume);
224
225/* control over who can modify resources shared between play/record */
226static mode_t shared_resource_owner;
227static int shared_resources_initialised;
228
229 /*
230 * Mid level stuff
231 */
232
233struct sound_settings dmasound = { .lock = SPIN_LOCK_UNLOCKED };
234
235static inline void sound_silence(void)
236{
237 dmasound.mach.silence(); /* _MUST_ stop DMA */
238}
239
240static inline int sound_set_format(int format)
241{
242 return dmasound.mach.setFormat(format);
243}
244
245
246static int sound_set_speed(int speed)
247{
248 if (speed < 0)
249 return dmasound.soft.speed;
250
251 /* trap out-of-range speed settings.
252 at present we allow (arbitrarily) low rates - using soft
253 up-conversion - but we can't allow > max because there is
254 no soft down-conversion.
255 */
256 if (dmasound.mach.max_dsp_speed &&
257 (speed > dmasound.mach.max_dsp_speed))
258 speed = dmasound.mach.max_dsp_speed ;
259
260 dmasound.soft.speed = speed;
261
262 if (dmasound.minDev == SND_DEV_DSP)
263 dmasound.dsp.speed = dmasound.soft.speed;
264
265 return dmasound.soft.speed;
266}
267
268static int sound_set_stereo(int stereo)
269{
270 if (stereo < 0)
271 return dmasound.soft.stereo;
272
273 stereo = !!stereo; /* should be 0 or 1 now */
274
275 dmasound.soft.stereo = stereo;
276 if (dmasound.minDev == SND_DEV_DSP)
277 dmasound.dsp.stereo = stereo;
278
279 return stereo;
280}
281
282static ssize_t sound_copy_translate(TRANS *trans, const u_char __user *userPtr,
283 size_t userCount, u_char frame[],
284 ssize_t *frameUsed, ssize_t frameLeft)
285{
286 ssize_t (*ct_func)(const u_char __user *, size_t, u_char *, ssize_t *, ssize_t);
287
288 switch (dmasound.soft.format) {
289 case AFMT_MU_LAW:
290 ct_func = trans->ct_ulaw;
291 break;
292 case AFMT_A_LAW:
293 ct_func = trans->ct_alaw;
294 break;
295 case AFMT_S8:
296 ct_func = trans->ct_s8;
297 break;
298 case AFMT_U8:
299 ct_func = trans->ct_u8;
300 break;
301 case AFMT_S16_BE:
302 ct_func = trans->ct_s16be;
303 break;
304 case AFMT_U16_BE:
305 ct_func = trans->ct_u16be;
306 break;
307 case AFMT_S16_LE:
308 ct_func = trans->ct_s16le;
309 break;
310 case AFMT_U16_LE:
311 ct_func = trans->ct_u16le;
312 break;
313 default:
314 return 0;
315 }
316 /* if the user has requested a non-existent translation don't try
317 to call it but just return 0 bytes moved
318 */
319 if (ct_func)
320 return ct_func(userPtr, userCount, frame, frameUsed, frameLeft);
321 return 0;
322}
323
324 /*
325 * /dev/mixer abstraction
326 */
327
328static struct {
329 int busy;
330 int modify_counter;
331} mixer;
332
333static int mixer_open(struct inode *inode, struct file *file)
334{
335 if (!try_module_get(dmasound.mach.owner))
336 return -ENODEV;
337 mixer.busy = 1;
338 return 0;
339}
340
341static int mixer_release(struct inode *inode, struct file *file)
342{
343 lock_kernel();
344 mixer.busy = 0;
345 module_put(dmasound.mach.owner);
346 unlock_kernel();
347 return 0;
348}
349static int mixer_ioctl(struct inode *inode, struct file *file, u_int cmd,
350 u_long arg)
351{
352 if (_SIOC_DIR(cmd) & _SIOC_WRITE)
353 mixer.modify_counter++;
354 switch (cmd) {
355 case OSS_GETVERSION:
356 return IOCTL_OUT(arg, SOUND_VERSION);
357 case SOUND_MIXER_INFO:
358 {
359 mixer_info info;
360 memset(&info, 0, sizeof(info));
361 strlcpy(info.id, dmasound.mach.name2, sizeof(info.id));
362 strlcpy(info.name, dmasound.mach.name2, sizeof(info.name));
363 info.modify_counter = mixer.modify_counter;
364 if (copy_to_user((void __user *)arg, &info, sizeof(info)))
365 return -EFAULT;
366 return 0;
367 }
368 }
369 if (dmasound.mach.mixer_ioctl)
370 return dmasound.mach.mixer_ioctl(cmd, arg);
371 return -EINVAL;
372}
373
374static struct file_operations mixer_fops =
375{
376 .owner = THIS_MODULE,
377 .llseek = no_llseek,
378 .ioctl = mixer_ioctl,
379 .open = mixer_open,
380 .release = mixer_release,
381};
382
383static void mixer_init(void)
384{
385#ifndef MODULE
386 int mixer_unit;
387#endif
388 mixer_unit = register_sound_mixer(&mixer_fops, -1);
389 if (mixer_unit < 0)
390 return;
391
392 mixer.busy = 0;
393 dmasound.treble = 0;
394 dmasound.bass = 0;
395 if (dmasound.mach.mixer_init)
396 dmasound.mach.mixer_init();
397}
398
399
400 /*
401 * Sound queue stuff, the heart of the driver
402 */
403
404struct sound_queue dmasound_write_sq;
405static void sq_reset_output(void) ;
406#ifdef HAS_RECORD
407struct sound_queue dmasound_read_sq;
408static void sq_reset_input(void) ;
409#endif
410
411static int sq_allocate_buffers(struct sound_queue *sq, int num, int size)
412{
413 int i;
414
415 if (sq->buffers)
416 return 0;
417 sq->numBufs = num;
418 sq->bufSize = size;
419 sq->buffers = kmalloc (num * sizeof(char *), GFP_KERNEL);
420 if (!sq->buffers)
421 return -ENOMEM;
422 for (i = 0; i < num; i++) {
423 sq->buffers[i] = dmasound.mach.dma_alloc(size, GFP_KERNEL);
424 if (!sq->buffers[i]) {
425 while (i--)
426 dmasound.mach.dma_free(sq->buffers[i], size);
427 kfree(sq->buffers);
428 sq->buffers = NULL;
429 return -ENOMEM;
430 }
431 }
432 return 0;
433}
434
435static void sq_release_buffers(struct sound_queue *sq)
436{
437 int i;
438
439 if (sq->buffers) {
440 for (i = 0; i < sq->numBufs; i++)
441 dmasound.mach.dma_free(sq->buffers[i], sq->bufSize);
442 kfree(sq->buffers);
443 sq->buffers = NULL;
444 }
445}
446
447
448static int sq_setup(struct sound_queue *sq)
449{
450 int (*setup_func)(void) = NULL;
451 int hard_frame ;
452
453 if (sq->locked) { /* are we already set? - and not changeable */
454#ifdef DEBUG_DMASOUND
455printk("dmasound_core: tried to sq_setup a locked queue\n") ;
456#endif
457 return -EINVAL ;
458 }
459 sq->locked = 1 ; /* don't think we have a race prob. here _check_ */
460
461 /* make sure that the parameters are set up
462 This should have been done already...
463 */
464
465 dmasound.mach.init();
466
467 /* OK. If the user has set fragment parameters explicitly, then we
468 should leave them alone... as long as they are valid.
469 Invalid user fragment params can occur if we allow the whole buffer
470 to be used when the user requests the fragments sizes (with no soft
471 x-lation) and then the user subsequently sets a soft x-lation that
472 requires increased internal buffering.
473
474 Othwerwise (if the user did not set them) OSS says that we should
475 select frag params on the basis of 0.5 s output & 0.1 s input
476 latency. (TODO. For now we will copy in the defaults.)
477 */
478
479 if (sq->user_frags <= 0) {
480 sq->max_count = sq->numBufs ;
481 sq->max_active = sq->numBufs ;
482 sq->block_size = sq->bufSize;
483 /* set up the user info */
484 sq->user_frags = sq->numBufs ;
485 sq->user_frag_size = sq->bufSize ;
486 sq->user_frag_size *=
487 (dmasound.soft.size * (dmasound.soft.stereo+1) ) ;
488 sq->user_frag_size /=
489 (dmasound.hard.size * (dmasound.hard.stereo+1) ) ;
490 } else {
491 /* work out requested block size */
492 sq->block_size = sq->user_frag_size ;
493 sq->block_size *=
494 (dmasound.hard.size * (dmasound.hard.stereo+1) ) ;
495 sq->block_size /=
496 (dmasound.soft.size * (dmasound.soft.stereo+1) ) ;
497 /* the user wants to write frag-size chunks */
498 sq->block_size *= dmasound.hard.speed ;
499 sq->block_size /= dmasound.soft.speed ;
500 /* this only works for size values which are powers of 2 */
501 hard_frame =
502 (dmasound.hard.size * (dmasound.hard.stereo+1))/8 ;
503 sq->block_size += (hard_frame - 1) ;
504 sq->block_size &= ~(hard_frame - 1) ; /* make sure we are aligned */
505 /* let's just check for obvious mistakes */
506 if ( sq->block_size <= 0 || sq->block_size > sq->bufSize) {
507#ifdef DEBUG_DMASOUND
508printk("dmasound_core: invalid frag size (user set %d)\n", sq->user_frag_size) ;
509#endif
510 sq->block_size = sq->bufSize ;
511 }
512 if ( sq->user_frags <= sq->numBufs ) {
513 sq->max_count = sq->user_frags ;
514 /* if user has set max_active - then use it */
515 sq->max_active = (sq->max_active <= sq->max_count) ?
516 sq->max_active : sq->max_count ;
517 } else {
518#ifdef DEBUG_DMASOUND
519printk("dmasound_core: invalid frag count (user set %d)\n", sq->user_frags) ;
520#endif
521 sq->max_count =
522 sq->max_active = sq->numBufs ;
523 }
524 }
525 sq->front = sq->count = sq->rear_size = 0;
526 sq->syncing = 0;
527 sq->active = 0;
528
529 if (sq == &write_sq) {
530 sq->rear = -1;
531 setup_func = dmasound.mach.write_sq_setup;
532 }
533#ifdef HAS_RECORD
534 else {
535 sq->rear = 0;
536 setup_func = dmasound.mach.read_sq_setup;
537 }
538#endif
539 if (setup_func)
540 return setup_func();
541 return 0 ;
542}
543
544static inline void sq_play(void)
545{
546 dmasound.mach.play();
547}
548
549static ssize_t sq_write(struct file *file, const char __user *src, size_t uLeft,
550 loff_t *ppos)
551{
552 ssize_t uWritten = 0;
553 u_char *dest;
554 ssize_t uUsed = 0, bUsed, bLeft;
555 unsigned long flags ;
556
557 /* ++TeSche: Is something like this necessary?
558 * Hey, that's an honest question! Or does any other part of the
559 * filesystem already checks this situation? I really don't know.
560 */
561 if (uLeft == 0)
562 return 0;
563
564 /* implement any changes we have made to the soft/hard params.
565 this is not satisfactory really, all we have done up to now is to
566 say what we would like - there hasn't been any real checking of capability
567 */
568
569 if (shared_resources_initialised == 0) {
570 dmasound.mach.init() ;
571 shared_resources_initialised = 1 ;
572 }
573
574 /* set up the sq if it is not already done. This may seem a dumb place
575 to do it - but it is what OSS requires. It means that write() can
576 return memory allocation errors. To avoid this possibility use the
577 GETBLKSIZE or GETOSPACE ioctls (after you've fiddled with all the
578 params you want to change) - these ioctls also force the setup.
579 */
580
581 if (write_sq.locked == 0) {
582 if ((uWritten = sq_setup(&write_sq)) < 0) return uWritten ;
583 uWritten = 0 ;
584 }
585
586/* FIXME: I think that this may be the wrong behaviour when we get strapped
587 for time and the cpu is close to being (or actually) behind in sending data.
588 - because we've lost the time that the N samples, already in the buffer,
589 would have given us to get here with the next lot from the user.
590*/
591 /* The interrupt doesn't start to play the last, incomplete frame.
592 * Thus we can append to it without disabling the interrupts! (Note
593 * also that write_sq.rear isn't affected by the interrupt.)
594 */
595
596 /* as of 1.6 this behaviour changes if SNDCTL_DSP_POST has been issued:
597 this will mimic the behaviour of syncing and allow the sq_play() to
598 queue a partial fragment. Since sq_play() may/will be called from
599 the IRQ handler - at least on Pmac we have to deal with it.
600 The strategy - possibly not optimum - is to kill _POST status if we
601 get here. This seems, at least, reasonable - in the sense that POST
602 is supposed to indicate that we might not write before the queue
603 is drained - and if we get here in time then it does not apply.
604 */
605
606 spin_lock_irqsave(&dmasound.lock, flags);
607 write_sq.syncing &= ~2 ; /* take out POST status */
608 spin_unlock_irqrestore(&dmasound.lock, flags);
609
610 if (write_sq.count > 0 &&
611 (bLeft = write_sq.block_size-write_sq.rear_size) > 0) {
612 dest = write_sq.buffers[write_sq.rear];
613 bUsed = write_sq.rear_size;
614 uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft,
615 dest, &bUsed, bLeft);
616 if (uUsed <= 0)
617 return uUsed;
618 src += uUsed;
619 uWritten += uUsed;
620 uLeft = (uUsed <= uLeft) ? (uLeft - uUsed) : 0 ; /* paranoia */
621 write_sq.rear_size = bUsed;
622 }
623
624 while (uLeft) {
625 while (write_sq.count >= write_sq.max_active) {
626 sq_play();
627 if (write_sq.open_mode & O_NONBLOCK)
628 return uWritten > 0 ? uWritten : -EAGAIN;
629 SLEEP(write_sq.action_queue);
630 if (signal_pending(current))
631 return uWritten > 0 ? uWritten : -EINTR;
632 }
633
634 /* Here, we can avoid disabling the interrupt by first
635 * copying and translating the data, and then updating
636 * the write_sq variables. Until this is done, the interrupt
637 * won't see the new frame and we can work on it
638 * undisturbed.
639 */
640
641 dest = write_sq.buffers[(write_sq.rear+1) % write_sq.max_count];
642 bUsed = 0;
643 bLeft = write_sq.block_size;
644 uUsed = sound_copy_translate(dmasound.trans_write, src, uLeft,
645 dest, &bUsed, bLeft);
646 if (uUsed <= 0)
647 break;
648 src += uUsed;
649 uWritten += uUsed;
650 uLeft = (uUsed <= uLeft) ? (uLeft - uUsed) : 0 ; /* paranoia */
651 if (bUsed) {
652 write_sq.rear = (write_sq.rear+1) % write_sq.max_count;
653 write_sq.rear_size = bUsed;
654 write_sq.count++;
655 }
656 } /* uUsed may have been 0 */
657
658 sq_play();
659
660 return uUsed < 0? uUsed: uWritten;
661}
662
663static unsigned int sq_poll(struct file *file, struct poll_table_struct *wait)
664{
665 unsigned int mask = 0;
666 int retVal;
667
668 if (write_sq.locked == 0) {
669 if ((retVal = sq_setup(&write_sq)) < 0)
670 return retVal;
671 return 0;
672 }
673 if (file->f_mode & FMODE_WRITE )
674 poll_wait(file, &write_sq.action_queue, wait);
675#ifdef HAS_RECORD
676 if (file->f_mode & FMODE_READ)
677 poll_wait(file, &read_sq.action_queue, wait);
678 if (file->f_mode & FMODE_READ)
679 if (read_sq.block_size - read_sq.rear_size > 0)
680 mask |= POLLIN | POLLRDNORM;
681#endif
682 if (file->f_mode & FMODE_WRITE)
683 if (write_sq.count < write_sq.max_active || write_sq.block_size - write_sq.rear_size > 0)
684 mask |= POLLOUT | POLLWRNORM;
685 return mask;
686
687}
688
689#ifdef HAS_RECORD
690 /*
691 * Here is how the values are used for reading.
692 * The value 'active' simply indicates the DMA is running. This is done
693 * so the driver semantics are DMA starts when the first read is posted.
694 * The value 'front' indicates the buffer we should next send to the user.
695 * The value 'rear' indicates the buffer the DMA is currently filling.
696 * When 'front' == 'rear' the buffer "ring" is empty (we always have an
697 * empty available). The 'rear_size' is used to track partial offsets
698 * into the buffer we are currently returning to the user.
699
700 * This level (> [1.5]) doesn't care what strategy the LL driver uses with
701 * DMA on over-run. It can leave it running (and keep active == 1) or it
702 * can kill it and set active == 0 in which case this routine will spot
703 * it and restart the DMA.
704 */
705
706static ssize_t sq_read(struct file *file, char __user *dst, size_t uLeft,
707 loff_t *ppos)
708{
709
710 ssize_t uRead, bLeft, bUsed, uUsed;
711
712 if (uLeft == 0)
713 return 0;
714
715 /* cater for the compatibility mode - record compiled in but no LL */
716 if (dmasound.mach.record == NULL)
717 return -EINVAL ;
718
719 /* see comment in sq_write()
720 */
721
722 if( shared_resources_initialised == 0) {
723 dmasound.mach.init() ;
724 shared_resources_initialised = 1 ;
725 }
726
727 /* set up the sq if it is not already done. see comments in sq_write().
728 */
729
730 if (read_sq.locked == 0) {
731 if ((uRead = sq_setup(&read_sq)) < 0)
732 return uRead ;
733 }
734
735 uRead = 0;
736
737 /* Move what the user requests, depending upon other options.
738 */
739 while (uLeft > 0) {
740
741 /* we happened to get behind and the LL driver killed DMA
742 then we should set it going again. This also sets it
743 going the first time through.
744 */
745 if ( !read_sq.active )
746 dmasound.mach.record();
747
748 /* When front == rear, the DMA is not done yet.
749 */
750 while (read_sq.front == read_sq.rear) {
751 if (read_sq.open_mode & O_NONBLOCK) {
752 return uRead > 0 ? uRead : -EAGAIN;
753 }
754 SLEEP(read_sq.action_queue);
755 if (signal_pending(current))
756 return uRead > 0 ? uRead : -EINTR;
757 }
758
759 /* The amount we move is either what is left in the
760 * current buffer or what the user wants.
761 */
762 bLeft = read_sq.block_size - read_sq.rear_size;
763 bUsed = read_sq.rear_size;
764 uUsed = sound_copy_translate(dmasound.trans_read, dst, uLeft,
765 read_sq.buffers[read_sq.front],
766 &bUsed, bLeft);
767 if (uUsed <= 0)
768 return uUsed;
769 dst += uUsed;
770 uRead += uUsed;
771 uLeft -= uUsed;
772 read_sq.rear_size += bUsed;
773 if (read_sq.rear_size >= read_sq.block_size) {
774 read_sq.rear_size = 0;
775 read_sq.front++;
776 if (read_sq.front >= read_sq.max_active)
777 read_sq.front = 0;
778 }
779 }
780 return uRead;
781}
782#endif /* HAS_RECORD */
783
784static inline void sq_init_waitqueue(struct sound_queue *sq)
785{
786 init_waitqueue_head(&sq->action_queue);
787 init_waitqueue_head(&sq->open_queue);
788 init_waitqueue_head(&sq->sync_queue);
789 sq->busy = 0;
790}
791
792#if 0 /* blocking open() */
793static inline void sq_wake_up(struct sound_queue *sq, struct file *file,
794 mode_t mode)
795{
796 if (file->f_mode & mode) {
797 sq->busy = 0; /* CHECK: IS THIS OK??? */
798 WAKE_UP(sq->open_queue);
799 }
800}
801#endif
802
803static int sq_open2(struct sound_queue *sq, struct file *file, mode_t mode,
804 int numbufs, int bufsize)
805{
806 int rc = 0;
807
808 if (file->f_mode & mode) {
809 if (sq->busy) {
810#if 0 /* blocking open() */
811 rc = -EBUSY;
812 if (file->f_flags & O_NONBLOCK)
813 return rc;
814 rc = -EINTR;
815 while (sq->busy) {
816 SLEEP(sq->open_queue);
817 if (signal_pending(current))
818 return rc;
819 }
820 rc = 0;
821#else
822 /* OSS manual says we will return EBUSY regardless
823 of O_NOBLOCK.
824 */
825 return -EBUSY ;
826#endif
827 }
828 sq->busy = 1; /* Let's play spot-the-race-condition */
829
830 /* allocate the default number & size of buffers.
831 (i.e. specified in _setup() or as module params)
832 can't be changed at the moment - but _could_ be perhaps
833 in the setfragments ioctl.
834 */
835 if (( rc = sq_allocate_buffers(sq, numbufs, bufsize))) {
836#if 0 /* blocking open() */
837 sq_wake_up(sq, file, mode);
838#else
839 sq->busy = 0 ;
840#endif
841 return rc;
842 }
843
844 sq->open_mode = file->f_mode;
845 }
846 return rc;
847}
848
849#define write_sq_init_waitqueue() sq_init_waitqueue(&write_sq)
850#if 0 /* blocking open() */
851#define write_sq_wake_up(file) sq_wake_up(&write_sq, file, FMODE_WRITE)
852#endif
853#define write_sq_release_buffers() sq_release_buffers(&write_sq)
854#define write_sq_open(file) \
855 sq_open2(&write_sq, file, FMODE_WRITE, numWriteBufs, writeBufSize )
856
857#ifdef HAS_RECORD
858#define read_sq_init_waitqueue() sq_init_waitqueue(&read_sq)
859#if 0 /* blocking open() */
860#define read_sq_wake_up(file) sq_wake_up(&read_sq, file, FMODE_READ)
861#endif
862#define read_sq_release_buffers() sq_release_buffers(&read_sq)
863#define read_sq_open(file) \
864 sq_open2(&read_sq, file, FMODE_READ, numReadBufs, readBufSize )
865#else
866#define read_sq_init_waitqueue() do {} while (0)
867#if 0 /* blocking open() */
868#define read_sq_wake_up(file) do {} while (0)
869#endif
870#define read_sq_release_buffers() do {} while (0)
871#define sq_reset_input() do {} while (0)
872#endif
873
874static int sq_open(struct inode *inode, struct file *file)
875{
876 int rc;
877
878 if (!try_module_get(dmasound.mach.owner))
879 return -ENODEV;
880
881 rc = write_sq_open(file); /* checks the f_mode */
882 if (rc)
883 goto out;
884#ifdef HAS_RECORD
885 if (dmasound.mach.record) {
886 rc = read_sq_open(file); /* checks the f_mode */
887 if (rc)
888 goto out;
889 } else { /* no record function installed; in compat mode */
890 if (file->f_mode & FMODE_READ) {
891 /* TODO: if O_RDWR, release any resources grabbed by write part */
892 rc = -ENXIO;
893 goto out;
894 }
895 }
896#else /* !HAS_RECORD */
897 if (file->f_mode & FMODE_READ) {
898 /* TODO: if O_RDWR, release any resources grabbed by write part */
899 rc = -ENXIO ; /* I think this is what is required by open(2) */
900 goto out;
901 }
902#endif /* HAS_RECORD */
903
904 if (dmasound.mach.sq_open)
905 dmasound.mach.sq_open(file->f_mode);
906
907 /* CHECK whether this is sensible - in the case that dsp0 could be opened
908 O_RDONLY and dsp1 could be opened O_WRONLY
909 */
910
911 dmasound.minDev = iminor(inode) & 0x0f;
912
913 /* OK. - we should make some attempt at consistency. At least the H'ware
914 options should be set with a valid mode. We will make it that the LL
915 driver must supply defaults for hard & soft params.
916 */
917
918 if (shared_resource_owner == 0) {
919 /* you can make this AFMT_U8/mono/8K if you want to mimic old
920 OSS behaviour - while we still have soft translations ;-) */
921 dmasound.soft = dmasound.mach.default_soft ;
922 dmasound.dsp = dmasound.mach.default_soft ;
923 dmasound.hard = dmasound.mach.default_hard ;
924 }
925
926#ifndef DMASOUND_STRICT_OSS_COMPLIANCE
927 /* none of the current LL drivers can actually do this "native" at the moment
928 OSS does not really require us to supply /dev/audio if we can't do it.
929 */
930 if (dmasound.minDev == SND_DEV_AUDIO) {
931 sound_set_speed(8000);
932 sound_set_stereo(0);
933 sound_set_format(AFMT_MU_LAW);
934 }
935#endif
936
937 return 0;
938 out:
939 module_put(dmasound.mach.owner);
940 return rc;
941}
942
943static void sq_reset_output(void)
944{
945 sound_silence(); /* this _must_ stop DMA, we might be about to lose the buffers */
946 write_sq.active = 0;
947 write_sq.count = 0;
948 write_sq.rear_size = 0;
949 /* write_sq.front = (write_sq.rear+1) % write_sq.max_count;*/
950 write_sq.front = 0 ;
951 write_sq.rear = -1 ; /* same as for set-up */
952
953 /* OK - we can unlock the parameters and fragment settings */
954 write_sq.locked = 0 ;
955 write_sq.user_frags = 0 ;
956 write_sq.user_frag_size = 0 ;
957}
958
959#ifdef HAS_RECORD
960
961static void sq_reset_input(void)
962{
963 if (dmasound.mach.record && read_sq.active) {
964 if (dmasound.mach.abort_read) { /* this routine must really be present */
965 read_sq.syncing = 1 ;
966 /* this can use the read_sq.sync_queue to sleep if
967 necessary - it should not return until DMA
968 is really stopped - because we might deallocate
969 the buffers as the next action...
970 */
971 dmasound.mach.abort_read() ;
972 } else {
973 printk(KERN_ERR
974 "dmasound_core: %s has no abort_read()!! all bets are off\n",
975 dmasound.mach.name) ;
976 }
977 }
978 read_sq.syncing =
979 read_sq.active =
980 read_sq.front =
981 read_sq.count =
982 read_sq.rear = 0 ;
983
984 /* OK - we can unlock the parameters and fragment settings */
985 read_sq.locked = 0 ;
986 read_sq.user_frags = 0 ;
987 read_sq.user_frag_size = 0 ;
988}
989
990#endif
991
992static void sq_reset(void)
993{
994 sq_reset_output() ;
995 sq_reset_input() ;
996 /* we could consider resetting the shared_resources_owner here... but I
997 think it is probably still rather non-obvious to application writer
998 */
999
1000 /* we release everything else though */
1001 shared_resources_initialised = 0 ;
1002}
1003
1004static int sq_fsync(struct file *filp, struct dentry *dentry)
1005{
1006 int rc = 0;
1007 int timeout = 5;
1008
1009 write_sq.syncing |= 1;
1010 sq_play(); /* there may be an incomplete frame waiting */
1011
1012 while (write_sq.active) {
1013 SLEEP(write_sq.sync_queue);
1014 if (signal_pending(current)) {
1015 /* While waiting for audio output to drain, an
1016 * interrupt occurred. Stop audio output immediately
1017 * and clear the queue. */
1018 sq_reset_output();
1019 rc = -EINTR;
1020 break;
1021 }
1022 if (!--timeout) {
1023 printk(KERN_WARNING "dmasound: Timeout draining output\n");
1024 sq_reset_output();
1025 rc = -EIO;
1026 break;
1027 }
1028 }
1029
1030 /* flag no sync regardless of whether we had a DSP_POST or not */
1031 write_sq.syncing = 0 ;
1032 return rc;
1033}
1034
1035static int sq_release(struct inode *inode, struct file *file)
1036{
1037 int rc = 0;
1038
1039 lock_kernel();
1040
1041#ifdef HAS_RECORD
1042 /* probably best to do the read side first - so that time taken to do it
1043 overlaps with playing any remaining output samples.
1044 */
1045 if (file->f_mode & FMODE_READ) {
1046 sq_reset_input() ; /* make sure dma is stopped and all is quiet */
1047 read_sq_release_buffers();
1048 read_sq.busy = 0;
1049 }
1050#endif
1051
1052 if (file->f_mode & FMODE_WRITE) {
1053 if (write_sq.busy)
1054 rc = sq_fsync(file, file->f_dentry);
1055
1056 sq_reset_output() ; /* make sure dma is stopped and all is quiet */
1057 write_sq_release_buffers();
1058 write_sq.busy = 0;
1059 }
1060
1061 if (file->f_mode & shared_resource_owner) { /* it's us that has them */
1062 shared_resource_owner = 0 ;
1063 shared_resources_initialised = 0 ;
1064 dmasound.hard = dmasound.mach.default_hard ;
1065 }
1066
1067 module_put(dmasound.mach.owner);
1068
1069#if 0 /* blocking open() */
1070 /* Wake up a process waiting for the queue being released.
1071 * Note: There may be several processes waiting for a call
1072 * to open() returning. */
1073
1074 /* Iain: hmm I don't understand this next comment ... */
1075 /* There is probably a DOS atack here. They change the mode flag. */
1076 /* XXX add check here,*/
1077 read_sq_wake_up(file); /* checks f_mode */
1078 write_sq_wake_up(file); /* checks f_mode */
1079#endif /* blocking open() */
1080
1081 unlock_kernel();
1082
1083 return rc;
1084}
1085
1086/* here we see if we have a right to modify format, channels, size and so on
1087 if no-one else has claimed it already then we do...
1088
1089 TODO: We might change this to mask O_RDWR such that only one or the other channel
1090 is the owner - if we have problems.
1091*/
1092
1093static int shared_resources_are_mine(mode_t md)
1094{
1095 if (shared_resource_owner)
1096 return (shared_resource_owner & md ) ;
1097 else {
1098 shared_resource_owner = md ;
1099 return 1 ;
1100 }
1101}
1102
1103/* if either queue is locked we must deny the right to change shared params
1104*/
1105
1106static int queues_are_quiescent(void)
1107{
1108#ifdef HAS_RECORD
1109 if (dmasound.mach.record)
1110 if (read_sq.locked)
1111 return 0 ;
1112#endif
1113 if (write_sq.locked)
1114 return 0 ;
1115 return 1 ;
1116}
1117
1118/* check and set a queue's fragments per user's wishes...
1119 we will check against the pre-defined literals and the actual sizes.
1120 This is a bit fraught - because soft translations can mess with our
1121 buffer requirements *after* this call - OSS says "call setfrags first"
1122*/
1123
1124/* It is possible to replace all the -EINVAL returns with an override that
1125 just puts the allowable value in. This may be what many OSS apps require
1126*/
1127
1128static int set_queue_frags(struct sound_queue *sq, int bufs, int size)
1129{
1130 if (sq->locked) {
1131#ifdef DEBUG_DMASOUND
1132printk("dmasound_core: tried to set_queue_frags on a locked queue\n") ;
1133#endif
1134 return -EINVAL ;
1135 }
1136
1137 if ((size < MIN_FRAG_SIZE) || (size > MAX_FRAG_SIZE))
1138 return -EINVAL ;
1139 size = (1<<size) ; /* now in bytes */
1140 if (size > sq->bufSize)
1141 return -EINVAL ; /* this might still not work */
1142
1143 if (bufs <= 0)
1144 return -EINVAL ;
1145 if (bufs > sq->numBufs) /* the user is allowed say "don't care" with 0x7fff */
1146 bufs = sq->numBufs ;
1147
1148 /* there is, currently, no way to specify max_active separately
1149 from max_count. This could be a LL driver issue - I guess
1150 if there is a requirement for these values to be different then
1151 we will have to pass that info. up to this level.
1152 */
1153 sq->user_frags =
1154 sq->max_active = bufs ;
1155 sq->user_frag_size = size ;
1156
1157 return 0 ;
1158}
1159
1160static int sq_ioctl(struct inode *inode, struct file *file, u_int cmd,
1161 u_long arg)
1162{
1163 int val, result;
1164 u_long fmt;
1165 int data;
1166 int size, nbufs;
1167 audio_buf_info info;
1168
1169 switch (cmd) {
1170 case SNDCTL_DSP_RESET:
1171 sq_reset();
1172 return 0;
1173 break ;
1174 case SNDCTL_DSP_GETFMTS:
1175 fmt = dmasound.mach.hardware_afmts ; /* this is what OSS says.. */
1176 return IOCTL_OUT(arg, fmt);
1177 break ;
1178 case SNDCTL_DSP_GETBLKSIZE:
1179 /* this should tell the caller about bytes that the app can
1180 read/write - the app doesn't care about our internal buffers.
1181 We force sq_setup() here as per OSS 1.1 (which should
1182 compute the values necessary).
1183 Since there is no mechanism to specify read/write separately, for
1184 fds opened O_RDWR, the write_sq values will, arbitrarily, overwrite
1185 the read_sq ones.
1186 */
1187 size = 0 ;
1188#ifdef HAS_RECORD
1189 if (dmasound.mach.record && (file->f_mode & FMODE_READ)) {
1190 if ( !read_sq.locked )
1191 sq_setup(&read_sq) ; /* set params */
1192 size = read_sq.user_frag_size ;
1193 }
1194#endif
1195 if (file->f_mode & FMODE_WRITE) {
1196 if ( !write_sq.locked )
1197 sq_setup(&write_sq) ;
1198 size = write_sq.user_frag_size ;
1199 }
1200 return IOCTL_OUT(arg, size);
1201 break ;
1202 case SNDCTL_DSP_POST:
1203 /* all we are going to do is to tell the LL that any
1204 partial frags can be queued for output.
1205 The LL will have to clear this flag when last output
1206 is queued.
1207 */
1208 write_sq.syncing |= 0x2 ;
1209 sq_play() ;
1210 return 0 ;
1211 case SNDCTL_DSP_SYNC:
1212 /* This call, effectively, has the same behaviour as SNDCTL_DSP_RESET
1213 except that it waits for output to finish before resetting
1214 everything - read, however, is killed imediately.
1215 */
1216 result = 0 ;
1217 if ((file->f_mode & FMODE_READ) && dmasound.mach.record)
1218 sq_reset_input() ;
1219 if (file->f_mode & FMODE_WRITE) {
1220 result = sq_fsync(file, file->f_dentry);
1221 sq_reset_output() ;
1222 }
1223 /* if we are the shared resource owner then release them */
1224 if (file->f_mode & shared_resource_owner)
1225 shared_resources_initialised = 0 ;
1226 return result ;
1227 break ;
1228 case SOUND_PCM_READ_RATE:
1229 return IOCTL_OUT(arg, dmasound.soft.speed);
1230 case SNDCTL_DSP_SPEED:
1231 /* changing this on the fly will have weird effects on the sound.
1232 Where there are rate conversions implemented in soft form - it
1233 will cause the _ctx_xxx() functions to be substituted.
1234 However, there doesn't appear to be any reason to dis-allow it from
1235 a driver pov.
1236 */
1237 if (shared_resources_are_mine(file->f_mode)) {
1238 IOCTL_IN(arg, data);
1239 data = sound_set_speed(data) ;
1240 shared_resources_initialised = 0 ;
1241 return IOCTL_OUT(arg, data);
1242 } else
1243 return -EINVAL ;
1244 break ;
1245 /* OSS says these next 4 actions are undefined when the device is
1246 busy/active - we will just return -EINVAL.
1247 To be allowed to change one - (a) you have to own the right
1248 (b) the queue(s) must be quiescent
1249 */
1250 case SNDCTL_DSP_STEREO:
1251 if (shared_resources_are_mine(file->f_mode) &&
1252 queues_are_quiescent()) {
1253 IOCTL_IN(arg, data);
1254 shared_resources_initialised = 0 ;
1255 return IOCTL_OUT(arg, sound_set_stereo(data));
1256 } else
1257 return -EINVAL ;
1258 break ;
1259 case SOUND_PCM_WRITE_CHANNELS:
1260 if (shared_resources_are_mine(file->f_mode) &&
1261 queues_are_quiescent()) {
1262 IOCTL_IN(arg, data);
1263 /* the user might ask for 20 channels, we will return 1 or 2 */
1264 shared_resources_initialised = 0 ;
1265 return IOCTL_OUT(arg, sound_set_stereo(data-1)+1);
1266 } else
1267 return -EINVAL ;
1268 break ;
1269 case SNDCTL_DSP_SETFMT:
1270 if (shared_resources_are_mine(file->f_mode) &&
1271 queues_are_quiescent()) {
1272 int format;
1273 IOCTL_IN(arg, data);
1274 shared_resources_initialised = 0 ;
1275 format = sound_set_format(data);
1276 result = IOCTL_OUT(arg, format);
1277 if (result < 0)
1278 return result;
1279 if (format != data && data != AFMT_QUERY)
1280 return -EINVAL;
1281 return 0;
1282 } else
1283 return -EINVAL ;
1284 case SNDCTL_DSP_SUBDIVIDE:
1285 return -EINVAL ;
1286 case SNDCTL_DSP_SETFRAGMENT:
1287 /* we can do this independently for the two queues - with the
1288 proviso that for fds opened O_RDWR we cannot separate the
1289 actions and both queues will be set per the last call.
1290 NOTE: this does *NOT* actually set the queue up - merely
1291 registers our intentions.
1292 */
1293 IOCTL_IN(arg, data);
1294 result = 0 ;
1295 nbufs = (data >> 16) & 0x7fff ; /* 0x7fff is 'use maximum' */
1296 size = data & 0xffff;
1297#ifdef HAS_RECORD
1298 if ((file->f_mode & FMODE_READ) && dmasound.mach.record) {
1299 result = set_queue_frags(&read_sq, nbufs, size) ;
1300 if (result)
1301 return result ;
1302 }
1303#endif
1304 if (file->f_mode & FMODE_WRITE) {
1305 result = set_queue_frags(&write_sq, nbufs, size) ;
1306 if (result)
1307 return result ;
1308 }
1309 /* NOTE: this return value is irrelevant - OSS specifically says that
1310 the value is 'random' and that the user _must_ check the actual
1311 frags values using SNDCTL_DSP_GETBLKSIZE or similar */
1312 return IOCTL_OUT(arg, data);
1313 break ;
1314 case SNDCTL_DSP_GETOSPACE:
1315 /*
1316 */
1317 if (file->f_mode & FMODE_WRITE) {
1318 if ( !write_sq.locked )
1319 sq_setup(&write_sq) ;
1320 info.fragments = write_sq.max_active - write_sq.count;
1321 info.fragstotal = write_sq.max_active;
1322 info.fragsize = write_sq.user_frag_size;
1323 info.bytes = info.fragments * info.fragsize;
1324 if (copy_to_user((void __user *)arg, &info, sizeof(info)))
1325 return -EFAULT;
1326 return 0;
1327 } else
1328 return -EINVAL ;
1329 break ;
1330 case SNDCTL_DSP_GETCAPS:
1331 val = dmasound.mach.capabilities & 0xffffff00;
1332 return IOCTL_OUT(arg,val);
1333
1334 default:
1335 return mixer_ioctl(inode, file, cmd, arg);
1336 }
1337 return -EINVAL;
1338}
1339
1340static struct file_operations sq_fops =
1341{
1342 .owner = THIS_MODULE,
1343 .llseek = no_llseek,
1344 .write = sq_write,
1345 .poll = sq_poll,
1346 .ioctl = sq_ioctl,
1347 .open = sq_open,
1348 .release = sq_release,
1349#ifdef HAS_RECORD
1350 .read = NULL /* default to no read for compat mode */
1351#endif
1352};
1353
1354static int sq_init(void)
1355{
1356#ifndef MODULE
1357 int sq_unit;
1358#endif
1359
1360#ifdef HAS_RECORD
1361 if (dmasound.mach.record)
1362 sq_fops.read = sq_read ;
1363#endif
1364 sq_unit = register_sound_dsp(&sq_fops, -1);
1365 if (sq_unit < 0) {
1366 printk(KERN_ERR "dmasound_core: couldn't register fops\n") ;
1367 return sq_unit ;
1368 }
1369
1370 write_sq_init_waitqueue();
1371 read_sq_init_waitqueue();
1372
1373 /* These parameters will be restored for every clean open()
1374 * in the case of multiple open()s (e.g. dsp0 & dsp1) they
1375 * will be set so long as the shared resources have no owner.
1376 */
1377
1378 if (shared_resource_owner == 0) {
1379 dmasound.soft = dmasound.mach.default_soft ;
1380 dmasound.hard = dmasound.mach.default_hard ;
1381 dmasound.dsp = dmasound.mach.default_soft ;
1382 shared_resources_initialised = 0 ;
1383 }
1384 return 0 ;
1385}
1386
1387
1388 /*
1389 * /dev/sndstat
1390 */
1391
1392/* we allow more space for record-enabled because there are extra output lines.
1393 the number here must include the amount we are prepared to give to the low-level
1394 driver.
1395*/
1396
1397#ifdef HAS_RECORD
1398#define STAT_BUFF_LEN 1024
1399#else
1400#define STAT_BUFF_LEN 768
1401#endif
1402
1403/* this is how much space we will allow the low-level driver to use
1404 in the stat buffer. Currently, 2 * (80 character line + <NL>).
1405 We do not police this (it is up to the ll driver to be honest).
1406*/
1407
1408#define LOW_LEVEL_STAT_ALLOC 162
1409
1410static struct {
1411 int busy;
1412 char buf[STAT_BUFF_LEN]; /* state.buf should not overflow! */
1413 int len, ptr;
1414} state;
1415
1416/* publish this function for use by low-level code, if required */
1417
1418char *get_afmt_string(int afmt)
1419{
1420 switch(afmt) {
1421 case AFMT_MU_LAW:
1422 return "mu-law";
1423 break;
1424 case AFMT_A_LAW:
1425 return "A-law";
1426 break;
1427 case AFMT_U8:
1428 return "unsigned 8 bit";
1429 break;
1430 case AFMT_S8:
1431 return "signed 8 bit";
1432 break;
1433 case AFMT_S16_BE:
1434 return "signed 16 bit BE";
1435 break;
1436 case AFMT_U16_BE:
1437 return "unsigned 16 bit BE";
1438 break;
1439 case AFMT_S16_LE:
1440 return "signed 16 bit LE";
1441 break;
1442 case AFMT_U16_LE:
1443 return "unsigned 16 bit LE";
1444 break;
1445 case 0:
1446 return "format not set" ;
1447 break ;
1448 default:
1449 break ;
1450 }
1451 return "ERROR: Unsupported AFMT_XXXX code" ;
1452}
1453
1454static int state_open(struct inode *inode, struct file *file)
1455{
1456 char *buffer = state.buf;
1457 int len = 0;
1458
1459 if (state.busy)
1460 return -EBUSY;
1461
1462 if (!try_module_get(dmasound.mach.owner))
1463 return -ENODEV;
1464 state.ptr = 0;
1465 state.busy = 1;
1466
1467 len += sprintf(buffer+len, "%sDMA sound driver rev %03d :\n",
1468 dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) +
1469 ((dmasound.mach.version>>8) & 0x0f));
1470 len += sprintf(buffer+len,
1471 "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n",
1472 DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2,
1473 (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ;
1474
1475 /* call the low-level module to fill in any stat info. that it has
1476 if present. Maximum buffer usage is specified.
1477 */
1478
1479 if (dmasound.mach.state_info)
1480 len += dmasound.mach.state_info(buffer+len,
1481 (size_t) LOW_LEVEL_STAT_ALLOC) ;
1482
1483 /* make usage of the state buffer as deterministic as poss.
1484 exceptional conditions could cause overrun - and this is flagged as
1485 a kernel error.
1486 */
1487
1488 /* formats and settings */
1489
1490 len += sprintf(buffer+len,"\t\t === Formats & settings ===\n") ;
1491 len += sprintf(buffer+len,"Parameter %20s%20s\n","soft","hard") ;
1492 len += sprintf(buffer+len,"Format :%20s%20s\n",
1493 get_afmt_string(dmasound.soft.format),
1494 get_afmt_string(dmasound.hard.format));
1495
1496 len += sprintf(buffer+len,"Samp Rate:%14d s/sec%14d s/sec\n",
1497 dmasound.soft.speed, dmasound.hard.speed);
1498
1499 len += sprintf(buffer+len,"Channels :%20s%20s\n",
1500 dmasound.soft.stereo ? "stereo" : "mono",
1501 dmasound.hard.stereo ? "stereo" : "mono" );
1502
1503 /* sound queue status */
1504
1505 len += sprintf(buffer+len,"\t\t === Sound Queue status ===\n");
1506 len += sprintf(buffer+len,"Allocated:%8s%6s\n","Buffers","Size") ;
1507 len += sprintf(buffer+len,"%9s:%8d%6d\n",
1508 "write", write_sq.numBufs, write_sq.bufSize) ;
1509#ifdef HAS_RECORD
1510 if (dmasound.mach.record)
1511 len += sprintf(buffer+len,"%9s:%8d%6d\n",
1512 "read", read_sq.numBufs, read_sq.bufSize) ;
1513#endif
1514 len += sprintf(buffer+len,
1515 "Current : MaxFrg FragSiz MaxAct Frnt Rear "
1516 "Cnt RrSize A B S L xruns\n") ;
1517 len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n",
1518 "write", write_sq.max_count, write_sq.block_size,
1519 write_sq.max_active, write_sq.front, write_sq.rear,
1520 write_sq.count, write_sq.rear_size, write_sq.active,
1521 write_sq.busy, write_sq.syncing, write_sq.locked, write_sq.xruns) ;
1522#ifdef HAS_RECORD
1523 if (dmasound.mach.record)
1524 len += sprintf(buffer+len,"%9s:%7d%8d%7d%5d%5d%4d%7d%2d%2d%2d%2d%7d\n",
1525 "read", read_sq.max_count, read_sq.block_size,
1526 read_sq.max_active, read_sq.front, read_sq.rear,
1527 read_sq.count, read_sq.rear_size, read_sq.active,
1528 read_sq.busy, read_sq.syncing, read_sq.locked, read_sq.xruns) ;
1529#endif
1530#ifdef DEBUG_DMASOUND
1531printk("dmasound: stat buffer used %d bytes\n", len) ;
1532#endif
1533
1534 if (len >= STAT_BUFF_LEN)
1535 printk(KERN_ERR "dmasound_core: stat buffer overflowed!\n");
1536
1537 state.len = len;
1538 return 0;
1539}
1540
1541static int state_release(struct inode *inode, struct file *file)
1542{
1543 lock_kernel();
1544 state.busy = 0;
1545 module_put(dmasound.mach.owner);
1546 unlock_kernel();
1547 return 0;
1548}
1549
1550static ssize_t state_read(struct file *file, char __user *buf, size_t count,
1551 loff_t *ppos)
1552{
1553 int n = state.len - state.ptr;
1554 if (n > count)
1555 n = count;
1556 if (n <= 0)
1557 return 0;
1558 if (copy_to_user(buf, &state.buf[state.ptr], n))
1559 return -EFAULT;
1560 state.ptr += n;
1561 return n;
1562}
1563
1564static struct file_operations state_fops = {
1565 .owner = THIS_MODULE,
1566 .llseek = no_llseek,
1567 .read = state_read,
1568 .open = state_open,
1569 .release = state_release,
1570};
1571
1572static int state_init(void)
1573{
1574#ifndef MODULE
1575 int state_unit;
1576#endif
1577 state_unit = register_sound_special(&state_fops, SND_DEV_STATUS);
1578 if (state_unit < 0)
1579 return state_unit ;
1580 state.busy = 0;
1581 return 0 ;
1582}
1583
1584
1585 /*
1586 * Config & Setup
1587 *
1588 * This function is called by _one_ chipset-specific driver
1589 */
1590
1591int dmasound_init(void)
1592{
1593 int res ;
1594#ifdef MODULE
1595 if (irq_installed)
1596 return -EBUSY;
1597#endif
1598
1599 /* Set up sound queue, /dev/audio and /dev/dsp. */
1600
1601 /* Set default settings. */
1602 if ((res = sq_init()) < 0)
1603 return res ;
1604
1605 /* Set up /dev/sndstat. */
1606 if ((res = state_init()) < 0)
1607 return res ;
1608
1609 /* Set up /dev/mixer. */
1610 mixer_init();
1611
1612 if (!dmasound.mach.irqinit()) {
1613 printk(KERN_ERR "DMA sound driver: Interrupt initialization failed\n");
1614 return -ENODEV;
1615 }
1616#ifdef MODULE
1617 irq_installed = 1;
1618#endif
1619
1620 printk(KERN_INFO "%s DMA sound driver rev %03d installed\n",
1621 dmasound.mach.name, (DMASOUND_CORE_REVISION<<4) +
1622 ((dmasound.mach.version>>8) & 0x0f));
1623 printk(KERN_INFO
1624 "Core driver edition %02d.%02d : %s driver edition %02d.%02d\n",
1625 DMASOUND_CORE_REVISION, DMASOUND_CORE_EDITION, dmasound.mach.name2,
1626 (dmasound.mach.version >> 8), (dmasound.mach.version & 0xff)) ;
1627 printk(KERN_INFO "Write will use %4d fragments of %7d bytes as default\n",
1628 numWriteBufs, writeBufSize) ;
1629#ifdef HAS_RECORD
1630 if (dmasound.mach.record)
1631 printk(KERN_INFO
1632 "Read will use %4d fragments of %7d bytes as default\n",
1633 numReadBufs, readBufSize) ;
1634#endif
1635
1636 return 0;
1637}
1638
1639#ifdef MODULE
1640
1641void dmasound_deinit(void)
1642{
1643 if (irq_installed) {
1644 sound_silence();
1645 dmasound.mach.irqcleanup();
1646 irq_installed = 0;
1647 }
1648
1649 write_sq_release_buffers();
1650 read_sq_release_buffers();
1651
1652 if (mixer_unit >= 0)
1653 unregister_sound_mixer(mixer_unit);
1654 if (state_unit >= 0)
1655 unregister_sound_special(state_unit);
1656 if (sq_unit >= 0)
1657 unregister_sound_dsp(sq_unit);
1658}
1659
1660#else /* !MODULE */
1661
1662static int dmasound_setup(char *str)
1663{
1664 int ints[6], size;
1665
1666 str = get_options(str, ARRAY_SIZE(ints), ints);
1667
1668 /* check the bootstrap parameter for "dmasound=" */
1669
1670 /* FIXME: other than in the most naive of cases there is no sense in these
1671 * buffers being other than powers of two. This is not checked yet.
1672 */
1673
1674 switch (ints[0]) {
1675#ifdef HAS_RECORD
1676 case 5:
1677 if ((ints[5] < 0) || (ints[5] > MAX_CATCH_RADIUS))
1678 printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
1679 else
1680 catchRadius = ints[5];
1681 /* fall through */
1682 case 4:
1683 if (ints[4] < MIN_BUFFERS)
1684 printk("dmasound_setup: invalid number of read buffers, using default = %d\n",
1685 numReadBufs);
1686 else
1687 numReadBufs = ints[4];
1688 /* fall through */
1689 case 3:
1690 if ((size = ints[3]) < 256) /* check for small buffer specs */
1691 size <<= 10 ;
1692 if (size < MIN_BUFSIZE || size > MAX_BUFSIZE)
1693 printk("dmasound_setup: invalid read buffer size, using default = %d\n", readBufSize);
1694 else
1695 readBufSize = size;
1696 /* fall through */
1697#else
1698 case 3:
1699 if ((ints[3] < 0) || (ints[3] > MAX_CATCH_RADIUS))
1700 printk("dmasound_setup: invalid catch radius, using default = %d\n", catchRadius);
1701 else
1702 catchRadius = ints[3];
1703 /* fall through */
1704#endif
1705 case 2:
1706 if (ints[1] < MIN_BUFFERS)
1707 printk("dmasound_setup: invalid number of buffers, using default = %d\n", numWriteBufs);
1708 else
1709 numWriteBufs = ints[1];
1710 /* fall through */
1711 case 1:
1712 if ((size = ints[2]) < 256) /* check for small buffer specs */
1713 size <<= 10 ;
1714 if (size < MIN_BUFSIZE || size > MAX_BUFSIZE)
1715 printk("dmasound_setup: invalid write buffer size, using default = %d\n", writeBufSize);
1716 else
1717 writeBufSize = size;
1718 case 0:
1719 break;
1720 default:
1721 printk("dmasound_setup: invalid number of arguments\n");
1722 return 0;
1723 }
1724 return 1;
1725}
1726
1727__setup("dmasound=", dmasound_setup);
1728
1729#endif /* !MODULE */
1730
1731 /*
1732 * Conversion tables
1733 */
1734
1735#ifdef HAS_8BIT_TABLES
1736/* 8 bit mu-law */
1737
1738char dmasound_ulaw2dma8[] = {
1739 -126, -122, -118, -114, -110, -106, -102, -98,
1740 -94, -90, -86, -82, -78, -74, -70, -66,
1741 -63, -61, -59, -57, -55, -53, -51, -49,
1742 -47, -45, -43, -41, -39, -37, -35, -33,
1743 -31, -30, -29, -28, -27, -26, -25, -24,
1744 -23, -22, -21, -20, -19, -18, -17, -16,
1745 -16, -15, -15, -14, -14, -13, -13, -12,
1746 -12, -11, -11, -10, -10, -9, -9, -8,
1747 -8, -8, -7, -7, -7, -7, -6, -6,
1748 -6, -6, -5, -5, -5, -5, -4, -4,
1749 -4, -4, -4, -4, -3, -3, -3, -3,
1750 -3, -3, -3, -3, -2, -2, -2, -2,
1751 -2, -2, -2, -2, -2, -2, -2, -2,
1752 -1, -1, -1, -1, -1, -1, -1, -1,
1753 -1, -1, -1, -1, -1, -1, -1, -1,
1754 -1, -1, -1, -1, -1, -1, -1, 0,
1755 125, 121, 117, 113, 109, 105, 101, 97,
1756 93, 89, 85, 81, 77, 73, 69, 65,
1757 62, 60, 58, 56, 54, 52, 50, 48,
1758 46, 44, 42, 40, 38, 36, 34, 32,
1759 30, 29, 28, 27, 26, 25, 24, 23,
1760 22, 21, 20, 19, 18, 17, 16, 15,
1761 15, 14, 14, 13, 13, 12, 12, 11,
1762 11, 10, 10, 9, 9, 8, 8, 7,
1763 7, 7, 6, 6, 6, 6, 5, 5,
1764 5, 5, 4, 4, 4, 4, 3, 3,
1765 3, 3, 3, 3, 2, 2, 2, 2,
1766 2, 2, 2, 2, 1, 1, 1, 1,
1767 1, 1, 1, 1, 1, 1, 1, 1,
1768 0, 0, 0, 0, 0, 0, 0, 0,
1769 0, 0, 0, 0, 0, 0, 0, 0,
1770 0, 0, 0, 0, 0, 0, 0, 0
1771};
1772
1773/* 8 bit A-law */
1774
1775char dmasound_alaw2dma8[] = {
1776 -22, -21, -24, -23, -18, -17, -20, -19,
1777 -30, -29, -32, -31, -26, -25, -28, -27,
1778 -11, -11, -12, -12, -9, -9, -10, -10,
1779 -15, -15, -16, -16, -13, -13, -14, -14,
1780 -86, -82, -94, -90, -70, -66, -78, -74,
1781 -118, -114, -126, -122, -102, -98, -110, -106,
1782 -43, -41, -47, -45, -35, -33, -39, -37,
1783 -59, -57, -63, -61, -51, -49, -55, -53,
1784 -2, -2, -2, -2, -2, -2, -2, -2,
1785 -2, -2, -2, -2, -2, -2, -2, -2,
1786 -1, -1, -1, -1, -1, -1, -1, -1,
1787 -1, -1, -1, -1, -1, -1, -1, -1,
1788 -6, -6, -6, -6, -5, -5, -5, -5,
1789 -8, -8, -8, -8, -7, -7, -7, -7,
1790 -3, -3, -3, -3, -3, -3, -3, -3,
1791 -4, -4, -4, -4, -4, -4, -4, -4,
1792 21, 20, 23, 22, 17, 16, 19, 18,
1793 29, 28, 31, 30, 25, 24, 27, 26,
1794 10, 10, 11, 11, 8, 8, 9, 9,
1795 14, 14, 15, 15, 12, 12, 13, 13,
1796 86, 82, 94, 90, 70, 66, 78, 74,
1797 118, 114, 126, 122, 102, 98, 110, 106,
1798 43, 41, 47, 45, 35, 33, 39, 37,
1799 59, 57, 63, 61, 51, 49, 55, 53,
1800 1, 1, 1, 1, 1, 1, 1, 1,
1801 1, 1, 1, 1, 1, 1, 1, 1,
1802 0, 0, 0, 0, 0, 0, 0, 0,
1803 0, 0, 0, 0, 0, 0, 0, 0,
1804 5, 5, 5, 5, 4, 4, 4, 4,
1805 7, 7, 7, 7, 6, 6, 6, 6,
1806 2, 2, 2, 2, 2, 2, 2, 2,
1807 3, 3, 3, 3, 3, 3, 3, 3
1808};
1809#endif /* HAS_8BIT_TABLES */
1810
1811 /*
1812 * Visible symbols for modules
1813 */
1814
1815EXPORT_SYMBOL(dmasound);
1816EXPORT_SYMBOL(dmasound_init);
1817#ifdef MODULE
1818EXPORT_SYMBOL(dmasound_deinit);
1819#endif
1820EXPORT_SYMBOL(dmasound_write_sq);
1821#ifdef HAS_RECORD
1822EXPORT_SYMBOL(dmasound_read_sq);
1823#endif
1824EXPORT_SYMBOL(dmasound_catchRadius);
1825#ifdef HAS_8BIT_TABLES
1826EXPORT_SYMBOL(dmasound_ulaw2dma8);
1827EXPORT_SYMBOL(dmasound_alaw2dma8);
1828#endif
1829EXPORT_SYMBOL(get_afmt_string) ;
diff --git a/sound/oss/dmasound/dmasound_paula.c b/sound/oss/dmasound/dmasound_paula.c
new file mode 100644
index 000000000000..558db5311e06
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_paula.c
@@ -0,0 +1,743 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_paula.c
3 *
4 * Amiga `Paula' DMA Sound Driver
5 *
6 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
7 * prior to 28/01/2001
8 *
9 * 28/01/2001 [0.1] Iain Sandoe
10 * - added versioning
11 * - put in and populated the hardware_afmts field.
12 * [0.2] - put in SNDCTL_DSP_GETCAPS value.
13 * [0.3] - put in constraint on state buffer usage.
14 * [0.4] - put in default hard/soft settings
15*/
16
17
18#include <linux/module.h>
19#include <linux/config.h>
20#include <linux/mm.h>
21#include <linux/init.h>
22#include <linux/ioport.h>
23#include <linux/soundcard.h>
24#include <linux/interrupt.h>
25
26#include <asm/uaccess.h>
27#include <asm/setup.h>
28#include <asm/amigahw.h>
29#include <asm/amigaints.h>
30#include <asm/machdep.h>
31
32#include "dmasound.h"
33
34#define DMASOUND_PAULA_REVISION 0
35#define DMASOUND_PAULA_EDITION 4
36
37 /*
38 * The minimum period for audio depends on htotal (for OCS/ECS/AGA)
39 * (Imported from arch/m68k/amiga/amisound.c)
40 */
41
42extern volatile u_short amiga_audio_min_period;
43
44
45 /*
46 * amiga_mksound() should be able to restore the period after beeping
47 * (Imported from arch/m68k/amiga/amisound.c)
48 */
49
50extern u_short amiga_audio_period;
51
52
53 /*
54 * Audio DMA masks
55 */
56
57#define AMI_AUDIO_OFF (DMAF_AUD0 | DMAF_AUD1 | DMAF_AUD2 | DMAF_AUD3)
58#define AMI_AUDIO_8 (DMAF_SETCLR | DMAF_MASTER | DMAF_AUD0 | DMAF_AUD1)
59#define AMI_AUDIO_14 (AMI_AUDIO_8 | DMAF_AUD2 | DMAF_AUD3)
60
61
62 /*
63 * Helper pointers for 16(14)-bit sound
64 */
65
66static int write_sq_block_size_half, write_sq_block_size_quarter;
67
68
69/*** Low level stuff *********************************************************/
70
71
72static void *AmiAlloc(unsigned int size, int flags);
73static void AmiFree(void *obj, unsigned int size);
74static int AmiIrqInit(void);
75#ifdef MODULE
76static void AmiIrqCleanUp(void);
77#endif
78static void AmiSilence(void);
79static void AmiInit(void);
80static int AmiSetFormat(int format);
81static int AmiSetVolume(int volume);
82static int AmiSetTreble(int treble);
83static void AmiPlayNextFrame(int index);
84static void AmiPlay(void);
85static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp);
86
87#ifdef CONFIG_HEARTBEAT
88
89 /*
90 * Heartbeat interferes with sound since the 7 kHz low-pass filter and the
91 * power LED are controlled by the same line.
92 */
93
94#ifdef CONFIG_APUS
95#define mach_heartbeat ppc_md.heartbeat
96#endif
97
98static void (*saved_heartbeat)(int) = NULL;
99
100static inline void disable_heartbeat(void)
101{
102 if (mach_heartbeat) {
103 saved_heartbeat = mach_heartbeat;
104 mach_heartbeat = NULL;
105 }
106 AmiSetTreble(dmasound.treble);
107}
108
109static inline void enable_heartbeat(void)
110{
111 if (saved_heartbeat)
112 mach_heartbeat = saved_heartbeat;
113}
114#else /* !CONFIG_HEARTBEAT */
115#define disable_heartbeat() do { } while (0)
116#define enable_heartbeat() do { } while (0)
117#endif /* !CONFIG_HEARTBEAT */
118
119
120/*** Mid level stuff *********************************************************/
121
122static void AmiMixerInit(void);
123static int AmiMixerIoctl(u_int cmd, u_long arg);
124static int AmiWriteSqSetup(void);
125static int AmiStateInfo(char *buffer, size_t space);
126
127
128/*** Translations ************************************************************/
129
130/* ++TeSche: radically changed for new expanding purposes...
131 *
132 * These two routines now deal with copying/expanding/translating the samples
133 * from user space into our buffer at the right frequency. They take care about
134 * how much data there's actually to read, how much buffer space there is and
135 * to convert samples into the right frequency/encoding. They will only work on
136 * complete samples so it may happen they leave some bytes in the input stream
137 * if the user didn't write a multiple of the current sample size. They both
138 * return the number of bytes they've used from both streams so you may detect
139 * such a situation. Luckily all programs should be able to cope with that.
140 *
141 * I think I've optimized anything as far as one can do in plain C, all
142 * variables should fit in registers and the loops are really short. There's
143 * one loop for every possible situation. Writing a more generalized and thus
144 * parameterized loop would only produce slower code. Feel free to optimize
145 * this in assembler if you like. :)
146 *
147 * I think these routines belong here because they're not yet really hardware
148 * independent, especially the fact that the Falcon can play 16bit samples
149 * only in stereo is hardcoded in both of them!
150 *
151 * ++geert: split in even more functions (one per format)
152 */
153
154
155 /*
156 * Native format
157 */
158
159static ssize_t ami_ct_s8(const u_char *userPtr, size_t userCount,
160 u_char frame[], ssize_t *frameUsed, ssize_t frameLeft)
161{
162 ssize_t count, used;
163
164 if (!dmasound.soft.stereo) {
165 void *p = &frame[*frameUsed];
166 count = min_t(unsigned long, userCount, frameLeft) & ~1;
167 used = count;
168 if (copy_from_user(p, userPtr, count))
169 return -EFAULT;
170 } else {
171 u_char *left = &frame[*frameUsed>>1];
172 u_char *right = left+write_sq_block_size_half;
173 count = min_t(unsigned long, userCount, frameLeft)>>1 & ~1;
174 used = count*2;
175 while (count > 0) {
176 if (get_user(*left++, userPtr++)
177 || get_user(*right++, userPtr++))
178 return -EFAULT;
179 count--;
180 }
181 }
182 *frameUsed += used;
183 return used;
184}
185
186
187 /*
188 * Copy and convert 8 bit data
189 */
190
191#define GENERATE_AMI_CT8(funcname, convsample) \
192static ssize_t funcname(const u_char *userPtr, size_t userCount, \
193 u_char frame[], ssize_t *frameUsed, \
194 ssize_t frameLeft) \
195{ \
196 ssize_t count, used; \
197 \
198 if (!dmasound.soft.stereo) { \
199 u_char *p = &frame[*frameUsed]; \
200 count = min_t(size_t, userCount, frameLeft) & ~1; \
201 used = count; \
202 while (count > 0) { \
203 u_char data; \
204 if (get_user(data, userPtr++)) \
205 return -EFAULT; \
206 *p++ = convsample(data); \
207 count--; \
208 } \
209 } else { \
210 u_char *left = &frame[*frameUsed>>1]; \
211 u_char *right = left+write_sq_block_size_half; \
212 count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
213 used = count*2; \
214 while (count > 0) { \
215 u_char data; \
216 if (get_user(data, userPtr++)) \
217 return -EFAULT; \
218 *left++ = convsample(data); \
219 if (get_user(data, userPtr++)) \
220 return -EFAULT; \
221 *right++ = convsample(data); \
222 count--; \
223 } \
224 } \
225 *frameUsed += used; \
226 return used; \
227}
228
229#define AMI_CT_ULAW(x) (dmasound_ulaw2dma8[(x)])
230#define AMI_CT_ALAW(x) (dmasound_alaw2dma8[(x)])
231#define AMI_CT_U8(x) ((x) ^ 0x80)
232
233GENERATE_AMI_CT8(ami_ct_ulaw, AMI_CT_ULAW)
234GENERATE_AMI_CT8(ami_ct_alaw, AMI_CT_ALAW)
235GENERATE_AMI_CT8(ami_ct_u8, AMI_CT_U8)
236
237
238 /*
239 * Copy and convert 16 bit data
240 */
241
242#define GENERATE_AMI_CT_16(funcname, convsample) \
243static ssize_t funcname(const u_char *userPtr, size_t userCount, \
244 u_char frame[], ssize_t *frameUsed, \
245 ssize_t frameLeft) \
246{ \
247 ssize_t count, used; \
248 u_short data; \
249 \
250 if (!dmasound.soft.stereo) { \
251 u_char *high = &frame[*frameUsed>>1]; \
252 u_char *low = high+write_sq_block_size_half; \
253 count = min_t(size_t, userCount, frameLeft)>>1 & ~1; \
254 used = count*2; \
255 while (count > 0) { \
256 if (get_user(data, ((u_short *)userPtr)++)) \
257 return -EFAULT; \
258 data = convsample(data); \
259 *high++ = data>>8; \
260 *low++ = (data>>2) & 0x3f; \
261 count--; \
262 } \
263 } else { \
264 u_char *lefth = &frame[*frameUsed>>2]; \
265 u_char *leftl = lefth+write_sq_block_size_quarter; \
266 u_char *righth = lefth+write_sq_block_size_half; \
267 u_char *rightl = righth+write_sq_block_size_quarter; \
268 count = min_t(size_t, userCount, frameLeft)>>2 & ~1; \
269 used = count*4; \
270 while (count > 0) { \
271 if (get_user(data, ((u_short *)userPtr)++)) \
272 return -EFAULT; \
273 data = convsample(data); \
274 *lefth++ = data>>8; \
275 *leftl++ = (data>>2) & 0x3f; \
276 if (get_user(data, ((u_short *)userPtr)++)) \
277 return -EFAULT; \
278 data = convsample(data); \
279 *righth++ = data>>8; \
280 *rightl++ = (data>>2) & 0x3f; \
281 count--; \
282 } \
283 } \
284 *frameUsed += used; \
285 return used; \
286}
287
288#define AMI_CT_S16BE(x) (x)
289#define AMI_CT_U16BE(x) ((x) ^ 0x8000)
290#define AMI_CT_S16LE(x) (le2be16((x)))
291#define AMI_CT_U16LE(x) (le2be16((x)) ^ 0x8000)
292
293GENERATE_AMI_CT_16(ami_ct_s16be, AMI_CT_S16BE)
294GENERATE_AMI_CT_16(ami_ct_u16be, AMI_CT_U16BE)
295GENERATE_AMI_CT_16(ami_ct_s16le, AMI_CT_S16LE)
296GENERATE_AMI_CT_16(ami_ct_u16le, AMI_CT_U16LE)
297
298
299static TRANS transAmiga = {
300 .ct_ulaw = ami_ct_ulaw,
301 .ct_alaw = ami_ct_alaw,
302 .ct_s8 = ami_ct_s8,
303 .ct_u8 = ami_ct_u8,
304 .ct_s16be = ami_ct_s16be,
305 .ct_u16be = ami_ct_u16be,
306 .ct_s16le = ami_ct_s16le,
307 .ct_u16le = ami_ct_u16le,
308};
309
310/*** Low level stuff *********************************************************/
311
312static inline void StopDMA(void)
313{
314 custom.aud[0].audvol = custom.aud[1].audvol = 0;
315 custom.aud[2].audvol = custom.aud[3].audvol = 0;
316 custom.dmacon = AMI_AUDIO_OFF;
317 enable_heartbeat();
318}
319
320static void *AmiAlloc(unsigned int size, int flags)
321{
322 return amiga_chip_alloc((long)size, "dmasound [Paula]");
323}
324
325static void AmiFree(void *obj, unsigned int size)
326{
327 amiga_chip_free (obj);
328}
329
330static int __init AmiIrqInit(void)
331{
332 /* turn off DMA for audio channels */
333 StopDMA();
334
335 /* Register interrupt handler. */
336 if (request_irq(IRQ_AMIGA_AUD0, AmiInterrupt, 0, "DMA sound",
337 AmiInterrupt))
338 return 0;
339 return 1;
340}
341
342#ifdef MODULE
343static void AmiIrqCleanUp(void)
344{
345 /* turn off DMA for audio channels */
346 StopDMA();
347 /* release the interrupt */
348 free_irq(IRQ_AMIGA_AUD0, AmiInterrupt);
349}
350#endif /* MODULE */
351
352static void AmiSilence(void)
353{
354 /* turn off DMA for audio channels */
355 StopDMA();
356}
357
358
359static void AmiInit(void)
360{
361 int period, i;
362
363 AmiSilence();
364
365 if (dmasound.soft.speed)
366 period = amiga_colorclock/dmasound.soft.speed-1;
367 else
368 period = amiga_audio_min_period;
369 dmasound.hard = dmasound.soft;
370 dmasound.trans_write = &transAmiga;
371
372 if (period < amiga_audio_min_period) {
373 /* we would need to squeeze the sound, but we won't do that */
374 period = amiga_audio_min_period;
375 } else if (period > 65535) {
376 period = 65535;
377 }
378 dmasound.hard.speed = amiga_colorclock/(period+1);
379
380 for (i = 0; i < 4; i++)
381 custom.aud[i].audper = period;
382 amiga_audio_period = period;
383}
384
385
386static int AmiSetFormat(int format)
387{
388 int size;
389
390 /* Amiga sound DMA supports 8bit and 16bit (pseudo 14 bit) modes */
391
392 switch (format) {
393 case AFMT_QUERY:
394 return dmasound.soft.format;
395 case AFMT_MU_LAW:
396 case AFMT_A_LAW:
397 case AFMT_U8:
398 case AFMT_S8:
399 size = 8;
400 break;
401 case AFMT_S16_BE:
402 case AFMT_U16_BE:
403 case AFMT_S16_LE:
404 case AFMT_U16_LE:
405 size = 16;
406 break;
407 default: /* :-) */
408 size = 8;
409 format = AFMT_S8;
410 }
411
412 dmasound.soft.format = format;
413 dmasound.soft.size = size;
414 if (dmasound.minDev == SND_DEV_DSP) {
415 dmasound.dsp.format = format;
416 dmasound.dsp.size = dmasound.soft.size;
417 }
418 AmiInit();
419
420 return format;
421}
422
423
424#define VOLUME_VOXWARE_TO_AMI(v) \
425 (((v) < 0) ? 0 : ((v) > 100) ? 64 : ((v) * 64)/100)
426#define VOLUME_AMI_TO_VOXWARE(v) ((v)*100/64)
427
428static int AmiSetVolume(int volume)
429{
430 dmasound.volume_left = VOLUME_VOXWARE_TO_AMI(volume & 0xff);
431 custom.aud[0].audvol = dmasound.volume_left;
432 dmasound.volume_right = VOLUME_VOXWARE_TO_AMI((volume & 0xff00) >> 8);
433 custom.aud[1].audvol = dmasound.volume_right;
434 if (dmasound.hard.size == 16) {
435 if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
436 custom.aud[2].audvol = 1;
437 custom.aud[3].audvol = 1;
438 } else {
439 custom.aud[2].audvol = 0;
440 custom.aud[3].audvol = 0;
441 }
442 }
443 return VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
444 (VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
445}
446
447static int AmiSetTreble(int treble)
448{
449 dmasound.treble = treble;
450 if (treble < 50)
451 ciaa.pra &= ~0x02;
452 else
453 ciaa.pra |= 0x02;
454 return treble;
455}
456
457
458#define AMI_PLAY_LOADED 1
459#define AMI_PLAY_PLAYING 2
460#define AMI_PLAY_MASK 3
461
462
463static void AmiPlayNextFrame(int index)
464{
465 u_char *start, *ch0, *ch1, *ch2, *ch3;
466 u_long size;
467
468 /* used by AmiPlay() if all doubts whether there really is something
469 * to be played are already wiped out.
470 */
471 start = write_sq.buffers[write_sq.front];
472 size = (write_sq.count == index ? write_sq.rear_size
473 : write_sq.block_size)>>1;
474
475 if (dmasound.hard.stereo) {
476 ch0 = start;
477 ch1 = start+write_sq_block_size_half;
478 size >>= 1;
479 } else {
480 ch0 = start;
481 ch1 = start;
482 }
483
484 disable_heartbeat();
485 custom.aud[0].audvol = dmasound.volume_left;
486 custom.aud[1].audvol = dmasound.volume_right;
487 if (dmasound.hard.size == 8) {
488 custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
489 custom.aud[0].audlen = size;
490 custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
491 custom.aud[1].audlen = size;
492 custom.dmacon = AMI_AUDIO_8;
493 } else {
494 size >>= 1;
495 custom.aud[0].audlc = (u_short *)ZTWO_PADDR(ch0);
496 custom.aud[0].audlen = size;
497 custom.aud[1].audlc = (u_short *)ZTWO_PADDR(ch1);
498 custom.aud[1].audlen = size;
499 if (dmasound.volume_left == 64 && dmasound.volume_right == 64) {
500 /* We can play pseudo 14-bit only with the maximum volume */
501 ch3 = ch0+write_sq_block_size_quarter;
502 ch2 = ch1+write_sq_block_size_quarter;
503 custom.aud[2].audvol = 1; /* we are being affected by the beeps */
504 custom.aud[3].audvol = 1; /* restoring volume here helps a bit */
505 custom.aud[2].audlc = (u_short *)ZTWO_PADDR(ch2);
506 custom.aud[2].audlen = size;
507 custom.aud[3].audlc = (u_short *)ZTWO_PADDR(ch3);
508 custom.aud[3].audlen = size;
509 custom.dmacon = AMI_AUDIO_14;
510 } else {
511 custom.aud[2].audvol = 0;
512 custom.aud[3].audvol = 0;
513 custom.dmacon = AMI_AUDIO_8;
514 }
515 }
516 write_sq.front = (write_sq.front+1) % write_sq.max_count;
517 write_sq.active |= AMI_PLAY_LOADED;
518}
519
520
521static void AmiPlay(void)
522{
523 int minframes = 1;
524
525 custom.intena = IF_AUD0;
526
527 if (write_sq.active & AMI_PLAY_LOADED) {
528 /* There's already a frame loaded */
529 custom.intena = IF_SETCLR | IF_AUD0;
530 return;
531 }
532
533 if (write_sq.active & AMI_PLAY_PLAYING)
534 /* Increase threshold: frame 1 is already being played */
535 minframes = 2;
536
537 if (write_sq.count < minframes) {
538 /* Nothing to do */
539 custom.intena = IF_SETCLR | IF_AUD0;
540 return;
541 }
542
543 if (write_sq.count <= minframes &&
544 write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {
545 /* hmmm, the only existing frame is not
546 * yet filled and we're not syncing?
547 */
548 custom.intena = IF_SETCLR | IF_AUD0;
549 return;
550 }
551
552 AmiPlayNextFrame(minframes);
553
554 custom.intena = IF_SETCLR | IF_AUD0;
555}
556
557
558static irqreturn_t AmiInterrupt(int irq, void *dummy, struct pt_regs *fp)
559{
560 int minframes = 1;
561
562 custom.intena = IF_AUD0;
563
564 if (!write_sq.active) {
565 /* Playing was interrupted and sq_reset() has already cleared
566 * the sq variables, so better don't do anything here.
567 */
568 WAKE_UP(write_sq.sync_queue);
569 return IRQ_HANDLED;
570 }
571
572 if (write_sq.active & AMI_PLAY_PLAYING) {
573 /* We've just finished a frame */
574 write_sq.count--;
575 WAKE_UP(write_sq.action_queue);
576 }
577
578 if (write_sq.active & AMI_PLAY_LOADED)
579 /* Increase threshold: frame 1 is already being played */
580 minframes = 2;
581
582 /* Shift the flags */
583 write_sq.active = (write_sq.active<<1) & AMI_PLAY_MASK;
584
585 if (!write_sq.active)
586 /* No frame is playing, disable audio DMA */
587 StopDMA();
588
589 custom.intena = IF_SETCLR | IF_AUD0;
590
591 if (write_sq.count >= minframes)
592 /* Try to play the next frame */
593 AmiPlay();
594
595 if (!write_sq.active)
596 /* Nothing to play anymore.
597 Wake up a process waiting for audio output to drain. */
598 WAKE_UP(write_sq.sync_queue);
599 return IRQ_HANDLED;
600}
601
602/*** Mid level stuff *********************************************************/
603
604
605/*
606 * /dev/mixer abstraction
607 */
608
609static void __init AmiMixerInit(void)
610{
611 dmasound.volume_left = 64;
612 dmasound.volume_right = 64;
613 custom.aud[0].audvol = dmasound.volume_left;
614 custom.aud[3].audvol = 1; /* For pseudo 14bit */
615 custom.aud[1].audvol = dmasound.volume_right;
616 custom.aud[2].audvol = 1; /* For pseudo 14bit */
617 dmasound.treble = 50;
618}
619
620static int AmiMixerIoctl(u_int cmd, u_long arg)
621{
622 int data;
623 switch (cmd) {
624 case SOUND_MIXER_READ_DEVMASK:
625 return IOCTL_OUT(arg, SOUND_MASK_VOLUME | SOUND_MASK_TREBLE);
626 case SOUND_MIXER_READ_RECMASK:
627 return IOCTL_OUT(arg, 0);
628 case SOUND_MIXER_READ_STEREODEVS:
629 return IOCTL_OUT(arg, SOUND_MASK_VOLUME);
630 case SOUND_MIXER_READ_VOLUME:
631 return IOCTL_OUT(arg,
632 VOLUME_AMI_TO_VOXWARE(dmasound.volume_left) |
633 VOLUME_AMI_TO_VOXWARE(dmasound.volume_right) << 8);
634 case SOUND_MIXER_WRITE_VOLUME:
635 IOCTL_IN(arg, data);
636 return IOCTL_OUT(arg, dmasound_set_volume(data));
637 case SOUND_MIXER_READ_TREBLE:
638 return IOCTL_OUT(arg, dmasound.treble);
639 case SOUND_MIXER_WRITE_TREBLE:
640 IOCTL_IN(arg, data);
641 return IOCTL_OUT(arg, dmasound_set_treble(data));
642 }
643 return -EINVAL;
644}
645
646
647static int AmiWriteSqSetup(void)
648{
649 write_sq_block_size_half = write_sq.block_size>>1;
650 write_sq_block_size_quarter = write_sq_block_size_half>>1;
651 return 0;
652}
653
654
655static int AmiStateInfo(char *buffer, size_t space)
656{
657 int len = 0;
658 len += sprintf(buffer+len, "\tsound.volume_left = %d [0...64]\n",
659 dmasound.volume_left);
660 len += sprintf(buffer+len, "\tsound.volume_right = %d [0...64]\n",
661 dmasound.volume_right);
662 if (len >= space) {
663 printk(KERN_ERR "dmasound_paula: overlowed state buffer alloc.\n") ;
664 len = space ;
665 }
666 return len;
667}
668
669
670/*** Machine definitions *****************************************************/
671
672static SETTINGS def_hard = {
673 .format = AFMT_S8,
674 .stereo = 0,
675 .size = 8,
676 .speed = 8000
677} ;
678
679static SETTINGS def_soft = {
680 .format = AFMT_U8,
681 .stereo = 0,
682 .size = 8,
683 .speed = 8000
684} ;
685
686static MACHINE machAmiga = {
687 .name = "Amiga",
688 .name2 = "AMIGA",
689 .owner = THIS_MODULE,
690 .dma_alloc = AmiAlloc,
691 .dma_free = AmiFree,
692 .irqinit = AmiIrqInit,
693#ifdef MODULE
694 .irqcleanup = AmiIrqCleanUp,
695#endif /* MODULE */
696 .init = AmiInit,
697 .silence = AmiSilence,
698 .setFormat = AmiSetFormat,
699 .setVolume = AmiSetVolume,
700 .setTreble = AmiSetTreble,
701 .play = AmiPlay,
702 .mixer_init = AmiMixerInit,
703 .mixer_ioctl = AmiMixerIoctl,
704 .write_sq_setup = AmiWriteSqSetup,
705 .state_info = AmiStateInfo,
706 .min_dsp_speed = 8000,
707 .version = ((DMASOUND_PAULA_REVISION<<8) | DMASOUND_PAULA_EDITION),
708 .hardware_afmts = (AFMT_S8 | AFMT_S16_BE), /* h'ware-supported formats *only* here */
709 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
710};
711
712
713/*** Config & Setup **********************************************************/
714
715
716int __init dmasound_paula_init(void)
717{
718 int err;
719
720 if (MACH_IS_AMIGA && AMIGAHW_PRESENT(AMI_AUDIO)) {
721 if (!request_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40,
722 "dmasound [Paula]"))
723 return -EBUSY;
724 dmasound.mach = machAmiga;
725 dmasound.mach.default_hard = def_hard ;
726 dmasound.mach.default_soft = def_soft ;
727 err = dmasound_init();
728 if (err)
729 release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
730 return err;
731 } else
732 return -ENODEV;
733}
734
735static void __exit dmasound_paula_cleanup(void)
736{
737 dmasound_deinit();
738 release_mem_region(CUSTOM_PHYSADDR+0xa0, 0x40);
739}
740
741module_init(dmasound_paula_init);
742module_exit(dmasound_paula_cleanup);
743MODULE_LICENSE("GPL");
diff --git a/sound/oss/dmasound/dmasound_q40.c b/sound/oss/dmasound/dmasound_q40.c
new file mode 100644
index 000000000000..92c25a0174db
--- /dev/null
+++ b/sound/oss/dmasound/dmasound_q40.c
@@ -0,0 +1,634 @@
1/*
2 * linux/sound/oss/dmasound/dmasound_q40.c
3 *
4 * Q40 DMA Sound Driver
5 *
6 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and credits
7 * prior to 28/01/2001
8 *
9 * 28/01/2001 [0.1] Iain Sandoe
10 * - added versioning
11 * - put in and populated the hardware_afmts field.
12 * [0.2] - put in SNDCTL_DSP_GETCAPS value.
13 * [0.3] - put in default hard/soft settings.
14 */
15
16
17#include <linux/module.h>
18#include <linux/init.h>
19#include <linux/slab.h>
20#include <linux/soundcard.h>
21#include <linux/interrupt.h>
22
23#include <asm/uaccess.h>
24#include <asm/q40ints.h>
25#include <asm/q40_master.h>
26
27#include "dmasound.h"
28
29#define DMASOUND_Q40_REVISION 0
30#define DMASOUND_Q40_EDITION 3
31
32static int expand_bal; /* Balance factor for expanding (not volume!) */
33static int expand_data; /* Data for expanding */
34
35
36/*** Low level stuff *********************************************************/
37
38
39static void *Q40Alloc(unsigned int size, int flags);
40static void Q40Free(void *, unsigned int);
41static int Q40IrqInit(void);
42#ifdef MODULE
43static void Q40IrqCleanUp(void);
44#endif
45static void Q40Silence(void);
46static void Q40Init(void);
47static int Q40SetFormat(int format);
48static int Q40SetVolume(int volume);
49static void Q40PlayNextFrame(int index);
50static void Q40Play(void);
51static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp);
52static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp);
53static void Q40Interrupt(void);
54
55
56/*** Mid level stuff *********************************************************/
57
58
59
60/* userCount, frameUsed, frameLeft == byte counts */
61static ssize_t q40_ct_law(const u_char *userPtr, size_t userCount,
62 u_char frame[], ssize_t *frameUsed,
63 ssize_t frameLeft)
64{
65 char *table = dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8;
66 ssize_t count, used;
67 u_char *p = (u_char *) &frame[*frameUsed];
68
69 used = count = min_t(size_t, userCount, frameLeft);
70 if (copy_from_user(p,userPtr,count))
71 return -EFAULT;
72 while (count > 0) {
73 *p = table[*p]+128;
74 p++;
75 count--;
76 }
77 *frameUsed += used ;
78 return used;
79}
80
81
82static ssize_t q40_ct_s8(const u_char *userPtr, size_t userCount,
83 u_char frame[], ssize_t *frameUsed,
84 ssize_t frameLeft)
85{
86 ssize_t count, used;
87 u_char *p = (u_char *) &frame[*frameUsed];
88
89 used = count = min_t(size_t, userCount, frameLeft);
90 if (copy_from_user(p,userPtr,count))
91 return -EFAULT;
92 while (count > 0) {
93 *p = *p + 128;
94 p++;
95 count--;
96 }
97 *frameUsed += used;
98 return used;
99}
100
101static ssize_t q40_ct_u8(const u_char *userPtr, size_t userCount,
102 u_char frame[], ssize_t *frameUsed,
103 ssize_t frameLeft)
104{
105 ssize_t count, used;
106 u_char *p = (u_char *) &frame[*frameUsed];
107
108 used = count = min_t(size_t, userCount, frameLeft);
109 if (copy_from_user(p,userPtr,count))
110 return -EFAULT;
111 *frameUsed += used;
112 return used;
113}
114
115
116/* a bit too complicated to optimise right now ..*/
117static ssize_t q40_ctx_law(const u_char *userPtr, size_t userCount,
118 u_char frame[], ssize_t *frameUsed,
119 ssize_t frameLeft)
120{
121 unsigned char *table = (unsigned char *)
122 (dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8);
123 unsigned int data = expand_data;
124 u_char *p = (u_char *) &frame[*frameUsed];
125 int bal = expand_bal;
126 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
127 int utotal, ftotal;
128
129 ftotal = frameLeft;
130 utotal = userCount;
131 while (frameLeft) {
132 u_char c;
133 if (bal < 0) {
134 if (userCount == 0)
135 break;
136 if (get_user(c, userPtr++))
137 return -EFAULT;
138 data = table[c];
139 data += 0x80;
140 userCount--;
141 bal += hSpeed;
142 }
143 *p++ = data;
144 frameLeft--;
145 bal -= sSpeed;
146 }
147 expand_bal = bal;
148 expand_data = data;
149 *frameUsed += (ftotal - frameLeft);
150 utotal -= userCount;
151 return utotal;
152}
153
154
155static ssize_t q40_ctx_s8(const u_char *userPtr, size_t userCount,
156 u_char frame[], ssize_t *frameUsed,
157 ssize_t frameLeft)
158{
159 u_char *p = (u_char *) &frame[*frameUsed];
160 unsigned int data = expand_data;
161 int bal = expand_bal;
162 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
163 int utotal, ftotal;
164
165
166 ftotal = frameLeft;
167 utotal = userCount;
168 while (frameLeft) {
169 u_char c;
170 if (bal < 0) {
171 if (userCount == 0)
172 break;
173 if (get_user(c, userPtr++))
174 return -EFAULT;
175 data = c ;
176 data += 0x80;
177 userCount--;
178 bal += hSpeed;
179 }
180 *p++ = data;
181 frameLeft--;
182 bal -= sSpeed;
183 }
184 expand_bal = bal;
185 expand_data = data;
186 *frameUsed += (ftotal - frameLeft);
187 utotal -= userCount;
188 return utotal;
189}
190
191
192static ssize_t q40_ctx_u8(const u_char *userPtr, size_t userCount,
193 u_char frame[], ssize_t *frameUsed,
194 ssize_t frameLeft)
195{
196 u_char *p = (u_char *) &frame[*frameUsed];
197 unsigned int data = expand_data;
198 int bal = expand_bal;
199 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
200 int utotal, ftotal;
201
202 ftotal = frameLeft;
203 utotal = userCount;
204 while (frameLeft) {
205 u_char c;
206 if (bal < 0) {
207 if (userCount == 0)
208 break;
209 if (get_user(c, userPtr++))
210 return -EFAULT;
211 data = c ;
212 userCount--;
213 bal += hSpeed;
214 }
215 *p++ = data;
216 frameLeft--;
217 bal -= sSpeed;
218 }
219 expand_bal = bal;
220 expand_data = data;
221 *frameUsed += (ftotal - frameLeft) ;
222 utotal -= userCount;
223 return utotal;
224}
225
226/* compressing versions */
227static ssize_t q40_ctc_law(const u_char *userPtr, size_t userCount,
228 u_char frame[], ssize_t *frameUsed,
229 ssize_t frameLeft)
230{
231 unsigned char *table = (unsigned char *)
232 (dmasound.soft.format == AFMT_MU_LAW ? dmasound_ulaw2dma8: dmasound_alaw2dma8);
233 unsigned int data = expand_data;
234 u_char *p = (u_char *) &frame[*frameUsed];
235 int bal = expand_bal;
236 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
237 int utotal, ftotal;
238
239 ftotal = frameLeft;
240 utotal = userCount;
241 while (frameLeft) {
242 u_char c;
243 while(bal<0) {
244 if (userCount == 0)
245 goto lout;
246 if (!(bal<(-hSpeed))) {
247 if (get_user(c, userPtr))
248 return -EFAULT;
249 data = 0x80 + table[c];
250 }
251 userPtr++;
252 userCount--;
253 bal += hSpeed;
254 }
255 *p++ = data;
256 frameLeft--;
257 bal -= sSpeed;
258 }
259 lout:
260 expand_bal = bal;
261 expand_data = data;
262 *frameUsed += (ftotal - frameLeft);
263 utotal -= userCount;
264 return utotal;
265}
266
267
268static ssize_t q40_ctc_s8(const u_char *userPtr, size_t userCount,
269 u_char frame[], ssize_t *frameUsed,
270 ssize_t frameLeft)
271{
272 u_char *p = (u_char *) &frame[*frameUsed];
273 unsigned int data = expand_data;
274 int bal = expand_bal;
275 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
276 int utotal, ftotal;
277
278 ftotal = frameLeft;
279 utotal = userCount;
280 while (frameLeft) {
281 u_char c;
282 while (bal < 0) {
283 if (userCount == 0)
284 goto lout;
285 if (!(bal<(-hSpeed))) {
286 if (get_user(c, userPtr))
287 return -EFAULT;
288 data = c + 0x80;
289 }
290 userPtr++;
291 userCount--;
292 bal += hSpeed;
293 }
294 *p++ = data;
295 frameLeft--;
296 bal -= sSpeed;
297 }
298 lout:
299 expand_bal = bal;
300 expand_data = data;
301 *frameUsed += (ftotal - frameLeft);
302 utotal -= userCount;
303 return utotal;
304}
305
306
307static ssize_t q40_ctc_u8(const u_char *userPtr, size_t userCount,
308 u_char frame[], ssize_t *frameUsed,
309 ssize_t frameLeft)
310{
311 u_char *p = (u_char *) &frame[*frameUsed];
312 unsigned int data = expand_data;
313 int bal = expand_bal;
314 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
315 int utotal, ftotal;
316
317 ftotal = frameLeft;
318 utotal = userCount;
319 while (frameLeft) {
320 u_char c;
321 while (bal < 0) {
322 if (userCount == 0)
323 goto lout;
324 if (!(bal<(-hSpeed))) {
325 if (get_user(c, userPtr))
326 return -EFAULT;
327 data = c ;
328 }
329 userPtr++;
330 userCount--;
331 bal += hSpeed;
332 }
333 *p++ = data;
334 frameLeft--;
335 bal -= sSpeed;
336 }
337 lout:
338 expand_bal = bal;
339 expand_data = data;
340 *frameUsed += (ftotal - frameLeft) ;
341 utotal -= userCount;
342 return utotal;
343}
344
345
346static TRANS transQ40Normal = {
347 q40_ct_law, q40_ct_law, q40_ct_s8, q40_ct_u8, NULL, NULL, NULL, NULL
348};
349
350static TRANS transQ40Expanding = {
351 q40_ctx_law, q40_ctx_law, q40_ctx_s8, q40_ctx_u8, NULL, NULL, NULL, NULL
352};
353
354static TRANS transQ40Compressing = {
355 q40_ctc_law, q40_ctc_law, q40_ctc_s8, q40_ctc_u8, NULL, NULL, NULL, NULL
356};
357
358
359/*** Low level stuff *********************************************************/
360
361static void *Q40Alloc(unsigned int size, int flags)
362{
363 return kmalloc(size, flags); /* change to vmalloc */
364}
365
366static void Q40Free(void *ptr, unsigned int size)
367{
368 kfree(ptr);
369}
370
371static int __init Q40IrqInit(void)
372{
373 /* Register interrupt handler. */
374 request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
375 "DMA sound", Q40Interrupt);
376
377 return(1);
378}
379
380
381#ifdef MODULE
382static void Q40IrqCleanUp(void)
383{
384 master_outb(0,SAMPLE_ENABLE_REG);
385 free_irq(Q40_IRQ_SAMPLE, Q40Interrupt);
386}
387#endif /* MODULE */
388
389
390static void Q40Silence(void)
391{
392 master_outb(0,SAMPLE_ENABLE_REG);
393 *DAC_LEFT=*DAC_RIGHT=127;
394}
395
396static char *q40_pp;
397static unsigned int q40_sc;
398
399static void Q40PlayNextFrame(int index)
400{
401 u_char *start;
402 u_long size;
403 u_char speed;
404
405 /* used by Q40Play() if all doubts whether there really is something
406 * to be played are already wiped out.
407 */
408 start = write_sq.buffers[write_sq.front];
409 size = (write_sq.count == index ? write_sq.rear_size : write_sq.block_size);
410
411 q40_pp=start;
412 q40_sc=size;
413
414 write_sq.front = (write_sq.front+1) % write_sq.max_count;
415 write_sq.active++;
416
417 speed=(dmasound.hard.speed==10000 ? 0 : 1);
418
419 master_outb( 0,SAMPLE_ENABLE_REG);
420 free_irq(Q40_IRQ_SAMPLE, Q40Interrupt);
421 if (dmasound.soft.stereo)
422 request_irq(Q40_IRQ_SAMPLE, Q40StereoInterrupt, 0,
423 "Q40 sound", Q40Interrupt);
424 else
425 request_irq(Q40_IRQ_SAMPLE, Q40MonoInterrupt, 0,
426 "Q40 sound", Q40Interrupt);
427
428 master_outb( speed, SAMPLE_RATE_REG);
429 master_outb( 1,SAMPLE_CLEAR_REG);
430 master_outb( 1,SAMPLE_ENABLE_REG);
431}
432
433static void Q40Play(void)
434{
435 unsigned long flags;
436
437 if (write_sq.active || write_sq.count<=0 ) {
438 /* There's already a frame loaded */
439 return;
440 }
441
442 /* nothing in the queue */
443 if (write_sq.count <= 1 && write_sq.rear_size < write_sq.block_size && !write_sq.syncing) {
444 /* hmmm, the only existing frame is not
445 * yet filled and we're not syncing?
446 */
447 return;
448 }
449 spin_lock_irqsave(&dmasound.lock, flags);
450 Q40PlayNextFrame(1);
451 spin_unlock_irqrestore(&dmasound.lock, flags);
452}
453
454static irqreturn_t Q40StereoInterrupt(int irq, void *dummy, struct pt_regs *fp)
455{
456 spin_lock(&dmasound.lock);
457 if (q40_sc>1){
458 *DAC_LEFT=*q40_pp++;
459 *DAC_RIGHT=*q40_pp++;
460 q40_sc -=2;
461 master_outb(1,SAMPLE_CLEAR_REG);
462 }else Q40Interrupt();
463 spin_unlock(&dmasound.lock);
464 return IRQ_HANDLED;
465}
466static irqreturn_t Q40MonoInterrupt(int irq, void *dummy, struct pt_regs *fp)
467{
468 spin_lock(&dmasound.lock);
469 if (q40_sc>0){
470 *DAC_LEFT=*q40_pp;
471 *DAC_RIGHT=*q40_pp++;
472 q40_sc --;
473 master_outb(1,SAMPLE_CLEAR_REG);
474 }else Q40Interrupt();
475 spin_unlock(&dmasound.lock);
476 return IRQ_HANDLED;
477}
478static void Q40Interrupt(void)
479{
480 if (!write_sq.active) {
481 /* playing was interrupted and sq_reset() has already cleared
482 * the sq variables, so better don't do anything here.
483 */
484 WAKE_UP(write_sq.sync_queue);
485 master_outb(0,SAMPLE_ENABLE_REG); /* better safe */
486 goto exit;
487 } else write_sq.active=0;
488 write_sq.count--;
489 Q40Play();
490
491 if (q40_sc<2)
492 { /* there was nothing to play, disable irq */
493 master_outb(0,SAMPLE_ENABLE_REG);
494 *DAC_LEFT=*DAC_RIGHT=127;
495 }
496 WAKE_UP(write_sq.action_queue);
497
498 exit:
499 master_outb(1,SAMPLE_CLEAR_REG);
500}
501
502
503static void Q40Init(void)
504{
505 int i, idx;
506 const int freq[] = {10000, 20000};
507
508 /* search a frequency that fits into the allowed error range */
509
510 idx = -1;
511 for (i = 0; i < 2; i++)
512 if ((100 * abs(dmasound.soft.speed - freq[i]) / freq[i]) <= catchRadius)
513 idx = i;
514
515 dmasound.hard = dmasound.soft;
516 /*sound.hard.stereo=1;*/ /* no longer true */
517 dmasound.hard.size=8;
518
519 if (idx > -1) {
520 dmasound.soft.speed = freq[idx];
521 dmasound.trans_write = &transQ40Normal;
522 } else
523 dmasound.trans_write = &transQ40Expanding;
524
525 Q40Silence();
526
527 if (dmasound.hard.speed > 20200) {
528 /* squeeze the sound, we do that */
529 dmasound.hard.speed = 20000;
530 dmasound.trans_write = &transQ40Compressing;
531 } else if (dmasound.hard.speed > 10000) {
532 dmasound.hard.speed = 20000;
533 } else {
534 dmasound.hard.speed = 10000;
535 }
536 expand_bal = -dmasound.soft.speed;
537}
538
539
540static int Q40SetFormat(int format)
541{
542 /* Q40 sound supports only 8bit modes */
543
544 switch (format) {
545 case AFMT_QUERY:
546 return(dmasound.soft.format);
547 case AFMT_MU_LAW:
548 case AFMT_A_LAW:
549 case AFMT_S8:
550 case AFMT_U8:
551 break;
552 default:
553 format = AFMT_S8;
554 }
555
556 dmasound.soft.format = format;
557 dmasound.soft.size = 8;
558 if (dmasound.minDev == SND_DEV_DSP) {
559 dmasound.dsp.format = format;
560 dmasound.dsp.size = 8;
561 }
562 Q40Init();
563
564 return(format);
565}
566
567static int Q40SetVolume(int volume)
568{
569 return 0;
570}
571
572
573/*** Machine definitions *****************************************************/
574
575static SETTINGS def_hard = {
576 .format = AFMT_U8,
577 .stereo = 0,
578 .size = 8,
579 .speed = 10000
580} ;
581
582static SETTINGS def_soft = {
583 .format = AFMT_U8,
584 .stereo = 0,
585 .size = 8,
586 .speed = 8000
587} ;
588
589static MACHINE machQ40 = {
590 .name = "Q40",
591 .name2 = "Q40",
592 .owner = THIS_MODULE,
593 .dma_alloc = Q40Alloc,
594 .dma_free = Q40Free,
595 .irqinit = Q40IrqInit,
596#ifdef MODULE
597 .irqcleanup = Q40IrqCleanUp,
598#endif /* MODULE */
599 .init = Q40Init,
600 .silence = Q40Silence,
601 .setFormat = Q40SetFormat,
602 .setVolume = Q40SetVolume,
603 .play = Q40Play,
604 .min_dsp_speed = 10000,
605 .version = ((DMASOUND_Q40_REVISION<<8) | DMASOUND_Q40_EDITION),
606 .hardware_afmts = AFMT_U8, /* h'ware-supported formats *only* here */
607 .capabilities = DSP_CAP_BATCH /* As per SNDCTL_DSP_GETCAPS */
608};
609
610
611/*** Config & Setup **********************************************************/
612
613
614int __init dmasound_q40_init(void)
615{
616 if (MACH_IS_Q40) {
617 dmasound.mach = machQ40;
618 dmasound.mach.default_hard = def_hard ;
619 dmasound.mach.default_soft = def_soft ;
620 return dmasound_init();
621 } else
622 return -ENODEV;
623}
624
625static void __exit dmasound_q40_cleanup(void)
626{
627 dmasound_deinit();
628}
629
630module_init(dmasound_q40_init);
631module_exit(dmasound_q40_cleanup);
632
633MODULE_DESCRIPTION("Q40/Q60 sound driver");
634MODULE_LICENSE("GPL");
diff --git a/sound/oss/dmasound/tas3001c.c b/sound/oss/dmasound/tas3001c.c
new file mode 100644
index 000000000000..f227c9f688cc
--- /dev/null
+++ b/sound/oss/dmasound/tas3001c.c
@@ -0,0 +1,850 @@
1/*
2 * Driver for the i2c/i2s based TA3004 sound chip used
3 * on some Apple hardware. Also known as "snapper".
4 *
5 * Tobias Sargeant <tobias.sargeant@bigpond.com>
6 * Based upon, tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
7 *
8 * TODO:
9 * -----
10 * * Enable control over input line 2 (is this connected?)
11 * * Implement sleep support (at least mute everything and
12 * * set gains to minimum during sleep)
13 * * Look into some of Darwin's tweaks regarding the mute
14 * * lines (delays & different behaviour on some HW)
15 *
16 */
17
18#include <linux/module.h>
19#include <linux/slab.h>
20#include <linux/proc_fs.h>
21#include <linux/ioport.h>
22#include <linux/sysctl.h>
23#include <linux/types.h>
24#include <linux/i2c.h>
25#include <linux/init.h>
26#include <linux/soundcard.h>
27#include <linux/workqueue.h>
28#include <asm/uaccess.h>
29#include <asm/errno.h>
30#include <asm/io.h>
31#include <asm/prom.h>
32
33#include "dmasound.h"
34#include "tas_common.h"
35#include "tas3001c.h"
36
37#include "tas_ioctl.h"
38
39#define TAS3001C_BIQUAD_FILTER_COUNT 6
40#define TAS3001C_BIQUAD_CHANNEL_COUNT 2
41
42#define VOL_DEFAULT (100 * 4 / 5)
43#define INPUT_DEFAULT (100 * 4 / 5)
44#define BASS_DEFAULT (100 / 2)
45#define TREBLE_DEFAULT (100 / 2)
46
47struct tas3001c_data_t {
48 struct tas_data_t super;
49 int device_id;
50 int output_id;
51 int speaker_id;
52 struct tas_drce_t drce_state;
53};
54
55
56static const union tas_biquad_t
57tas3001c_eq_unity={
58 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 }
59};
60
61
62static inline unsigned char db_to_regval(short db) {
63 int r=0;
64
65 r=(db+0x59a0) / 0x60;
66
67 if (r < 0x91) return 0x91;
68 if (r > 0xef) return 0xef;
69 return r;
70}
71
72static inline short quantize_db(short db) {
73 return db_to_regval(db) * 0x60 - 0x59a0;
74}
75
76
77static inline int
78register_width(enum tas3001c_reg_t r)
79{
80 switch(r) {
81 case TAS3001C_REG_MCR:
82 case TAS3001C_REG_TREBLE:
83 case TAS3001C_REG_BASS:
84 return 1;
85
86 case TAS3001C_REG_DRC:
87 return 2;
88
89 case TAS3001C_REG_MIXER1:
90 case TAS3001C_REG_MIXER2:
91 return 3;
92
93 case TAS3001C_REG_VOLUME:
94 return 6;
95
96 case TAS3001C_REG_LEFT_BIQUAD0:
97 case TAS3001C_REG_LEFT_BIQUAD1:
98 case TAS3001C_REG_LEFT_BIQUAD2:
99 case TAS3001C_REG_LEFT_BIQUAD3:
100 case TAS3001C_REG_LEFT_BIQUAD4:
101 case TAS3001C_REG_LEFT_BIQUAD5:
102 case TAS3001C_REG_LEFT_BIQUAD6:
103
104 case TAS3001C_REG_RIGHT_BIQUAD0:
105 case TAS3001C_REG_RIGHT_BIQUAD1:
106 case TAS3001C_REG_RIGHT_BIQUAD2:
107 case TAS3001C_REG_RIGHT_BIQUAD3:
108 case TAS3001C_REG_RIGHT_BIQUAD4:
109 case TAS3001C_REG_RIGHT_BIQUAD5:
110 case TAS3001C_REG_RIGHT_BIQUAD6:
111 return 15;
112
113 default:
114 return 0;
115 }
116}
117
118static int
119tas3001c_write_register( struct tas3001c_data_t *self,
120 enum tas3001c_reg_t reg_num,
121 char *data,
122 uint write_mode)
123{
124 if (reg_num==TAS3001C_REG_MCR ||
125 reg_num==TAS3001C_REG_BASS ||
126 reg_num==TAS3001C_REG_TREBLE) {
127 return tas_write_byte_register(&self->super,
128 (uint)reg_num,
129 *data,
130 write_mode);
131 } else {
132 return tas_write_register(&self->super,
133 (uint)reg_num,
134 register_width(reg_num),
135 data,
136 write_mode);
137 }
138}
139
140static int
141tas3001c_sync_register( struct tas3001c_data_t *self,
142 enum tas3001c_reg_t reg_num)
143{
144 if (reg_num==TAS3001C_REG_MCR ||
145 reg_num==TAS3001C_REG_BASS ||
146 reg_num==TAS3001C_REG_TREBLE) {
147 return tas_sync_byte_register(&self->super,
148 (uint)reg_num,
149 register_width(reg_num));
150 } else {
151 return tas_sync_register(&self->super,
152 (uint)reg_num,
153 register_width(reg_num));
154 }
155}
156
157static int
158tas3001c_read_register( struct tas3001c_data_t *self,
159 enum tas3001c_reg_t reg_num,
160 char *data,
161 uint write_mode)
162{
163 return tas_read_register(&self->super,
164 (uint)reg_num,
165 register_width(reg_num),
166 data);
167}
168
169static inline int
170tas3001c_fast_load(struct tas3001c_data_t *self, int fast)
171{
172 if (fast)
173 self->super.shadow[TAS3001C_REG_MCR][0] |= 0x80;
174 else
175 self->super.shadow[TAS3001C_REG_MCR][0] &= 0x7f;
176 return tas3001c_sync_register(self,TAS3001C_REG_MCR);
177}
178
179static uint
180tas3001c_supported_mixers(struct tas3001c_data_t *self)
181{
182 return SOUND_MASK_VOLUME |
183 SOUND_MASK_PCM |
184 SOUND_MASK_ALTPCM |
185 SOUND_MASK_TREBLE |
186 SOUND_MASK_BASS;
187}
188
189static int
190tas3001c_mixer_is_stereo(struct tas3001c_data_t *self,int mixer)
191{
192 switch(mixer) {
193 case SOUND_MIXER_VOLUME:
194 return 1;
195 default:
196 return 0;
197 }
198}
199
200static uint
201tas3001c_stereo_mixers(struct tas3001c_data_t *self)
202{
203 uint r=tas3001c_supported_mixers(self);
204 uint i;
205
206 for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
207 if (r&(1<<i) && !tas3001c_mixer_is_stereo(self,i))
208 r &= ~(1<<i);
209 return r;
210}
211
212static int
213tas3001c_get_mixer_level(struct tas3001c_data_t *self,int mixer,uint *level)
214{
215 if (!self)
216 return -1;
217
218 *level=self->super.mixer[mixer];
219
220 return 0;
221}
222
223static int
224tas3001c_set_mixer_level(struct tas3001c_data_t *self,int mixer,uint level)
225{
226 int rc;
227 tas_shadow_t *shadow;
228
229 uint temp;
230 uint offset=0;
231
232 if (!self)
233 return -1;
234
235 shadow=self->super.shadow;
236
237 if (!tas3001c_mixer_is_stereo(self,mixer))
238 level = tas_mono_to_stereo(level);
239
240 switch(mixer) {
241 case SOUND_MIXER_VOLUME:
242 temp = tas3001c_gain.master[level&0xff];
243 shadow[TAS3001C_REG_VOLUME][0] = (temp >> 16) & 0xff;
244 shadow[TAS3001C_REG_VOLUME][1] = (temp >> 8) & 0xff;
245 shadow[TAS3001C_REG_VOLUME][2] = (temp >> 0) & 0xff;
246 temp = tas3001c_gain.master[(level>>8)&0xff];
247 shadow[TAS3001C_REG_VOLUME][3] = (temp >> 16) & 0xff;
248 shadow[TAS3001C_REG_VOLUME][4] = (temp >> 8) & 0xff;
249 shadow[TAS3001C_REG_VOLUME][5] = (temp >> 0) & 0xff;
250 rc = tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
251 break;
252 case SOUND_MIXER_ALTPCM:
253 /* tas3001c_fast_load(self, 1); */
254 level = tas_mono_to_stereo(level);
255 temp = tas3001c_gain.mixer[level&0xff];
256 shadow[TAS3001C_REG_MIXER2][offset+0] = (temp >> 16) & 0xff;
257 shadow[TAS3001C_REG_MIXER2][offset+1] = (temp >> 8) & 0xff;
258 shadow[TAS3001C_REG_MIXER2][offset+2] = (temp >> 0) & 0xff;
259 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
260 /* tas3001c_fast_load(self, 0); */
261 break;
262 case SOUND_MIXER_PCM:
263 /* tas3001c_fast_load(self, 1); */
264 level = tas_mono_to_stereo(level);
265 temp = tas3001c_gain.mixer[level&0xff];
266 shadow[TAS3001C_REG_MIXER1][offset+0] = (temp >> 16) & 0xff;
267 shadow[TAS3001C_REG_MIXER1][offset+1] = (temp >> 8) & 0xff;
268 shadow[TAS3001C_REG_MIXER1][offset+2] = (temp >> 0) & 0xff;
269 rc = tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
270 /* tas3001c_fast_load(self, 0); */
271 break;
272 case SOUND_MIXER_TREBLE:
273 temp = tas3001c_gain.treble[level&0xff];
274 shadow[TAS3001C_REG_TREBLE][0]=temp&0xff;
275 rc = tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
276 break;
277 case SOUND_MIXER_BASS:
278 temp = tas3001c_gain.bass[level&0xff];
279 shadow[TAS3001C_REG_BASS][0]=temp&0xff;
280 rc = tas3001c_sync_register(self,TAS3001C_REG_BASS);
281 break;
282 default:
283 rc = -1;
284 break;
285 }
286 if (rc < 0)
287 return rc;
288 self->super.mixer[mixer]=level;
289 return 0;
290}
291
292static int
293tas3001c_leave_sleep(struct tas3001c_data_t *self)
294{
295 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
296
297 if (!self)
298 return -1;
299
300 /* Make sure something answers on the i2c bus */
301 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
302 WRITE_NORMAL|FORCE_WRITE) < 0)
303 return -1;
304
305 tas3001c_fast_load(self, 1);
306
307 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
308 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
309 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
310 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
311 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
312 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
313
314 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
315 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
316 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
317 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
318 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
319 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
320
321 tas3001c_fast_load(self, 0);
322
323 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
324 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
325 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
326 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
327 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
328
329 return 0;
330}
331
332static int
333tas3001c_enter_sleep(struct tas3001c_data_t *self)
334{
335 /* Stub for now, but I have the details on low-power mode */
336 if (!self)
337 return -1;
338 return 0;
339}
340
341static int
342tas3001c_sync_biquad( struct tas3001c_data_t *self,
343 u_int channel,
344 u_int filter)
345{
346 enum tas3001c_reg_t reg;
347
348 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
349 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
350
351 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
352
353 return tas3001c_sync_register(self,reg);
354}
355
356static int
357tas3001c_write_biquad_shadow( struct tas3001c_data_t *self,
358 u_int channel,
359 u_int filter,
360 const union tas_biquad_t *biquad)
361{
362 tas_shadow_t *shadow=self->super.shadow;
363 enum tas3001c_reg_t reg;
364
365 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
366 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
367
368 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
369
370 SET_4_20(shadow[reg], 0,biquad->coeff.b0);
371 SET_4_20(shadow[reg], 3,biquad->coeff.b1);
372 SET_4_20(shadow[reg], 6,biquad->coeff.b2);
373 SET_4_20(shadow[reg], 9,biquad->coeff.a1);
374 SET_4_20(shadow[reg],12,biquad->coeff.a2);
375
376 return 0;
377}
378
379static int
380tas3001c_write_biquad( struct tas3001c_data_t *self,
381 u_int channel,
382 u_int filter,
383 const union tas_biquad_t *biquad)
384{
385 int rc;
386
387 rc=tas3001c_write_biquad_shadow(self, channel, filter, biquad);
388 if (rc < 0) return rc;
389
390 return tas3001c_sync_biquad(self, channel, filter);
391}
392
393static int
394tas3001c_write_biquad_list( struct tas3001c_data_t *self,
395 u_int filter_count,
396 u_int flags,
397 struct tas_biquad_ctrl_t *biquads)
398{
399 int i;
400 int rc;
401
402 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
403
404 for (i=0; i<filter_count; i++) {
405 rc=tas3001c_write_biquad(self,
406 biquads[i].channel,
407 biquads[i].filter,
408 &biquads[i].data);
409 if (rc < 0) break;
410 }
411
412 if (flags & TAS_BIQUAD_FAST_LOAD) {
413 tas3001c_fast_load(self,0);
414
415 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
416 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
417 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
418 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
419 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
420 }
421
422 return rc;
423}
424
425static int
426tas3001c_read_biquad( struct tas3001c_data_t *self,
427 u_int channel,
428 u_int filter,
429 union tas_biquad_t *biquad)
430{
431 tas_shadow_t *shadow=self->super.shadow;
432 enum tas3001c_reg_t reg;
433
434 if (channel >= TAS3001C_BIQUAD_CHANNEL_COUNT ||
435 filter >= TAS3001C_BIQUAD_FILTER_COUNT) return -EINVAL;
436
437 reg=( channel ? TAS3001C_REG_RIGHT_BIQUAD0 : TAS3001C_REG_LEFT_BIQUAD0 ) + filter;
438
439 biquad->coeff.b0=GET_4_20(shadow[reg], 0);
440 biquad->coeff.b1=GET_4_20(shadow[reg], 3);
441 biquad->coeff.b2=GET_4_20(shadow[reg], 6);
442 biquad->coeff.a1=GET_4_20(shadow[reg], 9);
443 biquad->coeff.a2=GET_4_20(shadow[reg],12);
444
445 return 0;
446}
447
448static int
449tas3001c_eq_rw( struct tas3001c_data_t *self,
450 u_int cmd,
451 u_long arg)
452{
453 int rc;
454 struct tas_biquad_ctrl_t biquad;
455 void __user *argp = (void __user *)arg;
456
457 if (copy_from_user(&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
458 return -EFAULT;
459 }
460
461 if (cmd & SIOC_IN) {
462 rc=tas3001c_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
463 if (rc != 0) return rc;
464 }
465
466 if (cmd & SIOC_OUT) {
467 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
468 if (rc != 0) return rc;
469
470 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
471 return -EFAULT;
472 }
473
474 }
475 return 0;
476}
477
478static int
479tas3001c_eq_list_rw( struct tas3001c_data_t *self,
480 u_int cmd,
481 u_long arg)
482{
483 int rc;
484 int filter_count;
485 int flags;
486 int i,j;
487 char sync_required[2][6];
488 struct tas_biquad_ctrl_t biquad;
489 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
490
491 memset(sync_required,0,sizeof(sync_required));
492
493 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
494 return -EFAULT;
495
496 if (copy_from_user(&flags, &argp->flags, sizeof(int)))
497 return -EFAULT;
498
499 if (cmd & SIOC_IN) {
500 }
501
502 for (i=0; i < filter_count; i++) {
503 if (copy_from_user(&biquad, &argp->biquads[i],
504 sizeof(struct tas_biquad_ctrl_t))) {
505 return -EFAULT;
506 }
507
508 if (cmd & SIOC_IN) {
509 sync_required[biquad.channel][biquad.filter]=1;
510 rc=tas3001c_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
511 if (rc != 0) return rc;
512 }
513
514 if (cmd & SIOC_OUT) {
515 rc=tas3001c_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
516 if (rc != 0) return rc;
517
518 if (copy_to_user(&argp->biquads[i], &biquad,
519 sizeof(struct tas_biquad_ctrl_t))) {
520 return -EFAULT;
521 }
522 }
523 }
524
525 if (cmd & SIOC_IN) {
526 if (flags & TAS_BIQUAD_FAST_LOAD) tas3001c_fast_load(self,1);
527 for (i=0; i<2; i++) {
528 for (j=0; j<6; j++) {
529 if (sync_required[i][j]) {
530 rc=tas3001c_sync_biquad(self, i, j);
531 if (rc < 0) return rc;
532 }
533 }
534 }
535 if (flags & TAS_BIQUAD_FAST_LOAD) {
536 tas3001c_fast_load(self,0);
537 /* now we need to set up the mixers again,
538 because leaving fast mode resets them. */
539 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
540 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
541 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
542 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
543 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
544 }
545 }
546
547 return 0;
548}
549
550static int
551tas3001c_update_drce( struct tas3001c_data_t *self,
552 int flags,
553 struct tas_drce_t *drce)
554{
555 tas_shadow_t *shadow;
556 shadow=self->super.shadow;
557
558 shadow[TAS3001C_REG_DRC][1] = 0xc1;
559
560 if (flags & TAS_DRCE_THRESHOLD) {
561 self->drce_state.threshold=quantize_db(drce->threshold);
562 shadow[TAS3001C_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
563 }
564
565 if (flags & TAS_DRCE_ENABLE) {
566 self->drce_state.enable = drce->enable;
567 }
568
569 if (!self->drce_state.enable) {
570 shadow[TAS3001C_REG_DRC][0] = 0xf0;
571 }
572
573#ifdef DEBUG_DRCE
574 printk("DRCE IOCTL: set [ ENABLE:%x THRESH:%x\n",
575 self->drce_state.enable,
576 self->drce_state.threshold);
577
578 printk("DRCE IOCTL: reg [ %02x %02x ]\n",
579 (unsigned char)shadow[TAS3001C_REG_DRC][0],
580 (unsigned char)shadow[TAS3001C_REG_DRC][1]);
581#endif
582
583 return tas3001c_sync_register(self, TAS3001C_REG_DRC);
584}
585
586static int
587tas3001c_drce_rw( struct tas3001c_data_t *self,
588 u_int cmd,
589 u_long arg)
590{
591 int rc;
592 struct tas_drce_ctrl_t drce_ctrl;
593 void __user *argp = (void __user *)arg;
594
595 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
596 return -EFAULT;
597
598#ifdef DEBUG_DRCE
599 printk("DRCE IOCTL: input [ FLAGS:%x ENABLE:%x THRESH:%x\n",
600 drce_ctrl.flags,
601 drce_ctrl.data.enable,
602 drce_ctrl.data.threshold);
603#endif
604
605 if (cmd & SIOC_IN) {
606 rc = tas3001c_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
607 if (rc < 0)
608 return rc;
609 }
610
611 if (cmd & SIOC_OUT) {
612 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
613 drce_ctrl.data.enable = self->drce_state.enable;
614
615 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
616 drce_ctrl.data.threshold = self->drce_state.threshold;
617
618 if (copy_to_user(argp, &drce_ctrl,
619 sizeof(struct tas_drce_ctrl_t))) {
620 return -EFAULT;
621 }
622 }
623
624 return 0;
625}
626
627static void
628tas3001c_update_device_parameters(struct tas3001c_data_t *self)
629{
630 int i,j;
631
632 if (!self) return;
633
634 if (self->output_id == TAS_OUTPUT_HEADPHONES) {
635 tas3001c_fast_load(self, 1);
636
637 for (i=0; i<TAS3001C_BIQUAD_CHANNEL_COUNT; i++) {
638 for (j=0; j<TAS3001C_BIQUAD_FILTER_COUNT; j++) {
639 tas3001c_write_biquad(self, i, j, &tas3001c_eq_unity);
640 }
641 }
642
643 tas3001c_fast_load(self, 0);
644
645 (void)tas3001c_sync_register(self,TAS3001C_REG_BASS);
646 (void)tas3001c_sync_register(self,TAS3001C_REG_TREBLE);
647 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER1);
648 (void)tas3001c_sync_register(self,TAS3001C_REG_MIXER2);
649 (void)tas3001c_sync_register(self,TAS3001C_REG_VOLUME);
650
651 return;
652 }
653
654 for (i=0; tas3001c_eq_prefs[i]; i++) {
655 struct tas_eq_pref_t *eq = tas3001c_eq_prefs[i];
656
657 if (eq->device_id == self->device_id &&
658 (eq->output_id == 0 || eq->output_id == self->output_id) &&
659 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
660
661 tas3001c_update_drce(self, TAS_DRCE_ALL, eq->drce);
662 tas3001c_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
663
664 break;
665 }
666 }
667}
668
669static void
670tas3001c_device_change_handler(void *self)
671{
672 if (self)
673 tas3001c_update_device_parameters(self);
674}
675
676static struct work_struct device_change;
677
678static int
679tas3001c_output_device_change( struct tas3001c_data_t *self,
680 int device_id,
681 int output_id,
682 int speaker_id)
683{
684 self->device_id=device_id;
685 self->output_id=output_id;
686 self->speaker_id=speaker_id;
687
688 schedule_work(&device_change);
689 return 0;
690}
691
692static int
693tas3001c_device_ioctl( struct tas3001c_data_t *self,
694 u_int cmd,
695 u_long arg)
696{
697 uint __user *argp = (void __user *)arg;
698 switch (cmd) {
699 case TAS_READ_EQ:
700 case TAS_WRITE_EQ:
701 return tas3001c_eq_rw(self, cmd, arg);
702
703 case TAS_READ_EQ_LIST:
704 case TAS_WRITE_EQ_LIST:
705 return tas3001c_eq_list_rw(self, cmd, arg);
706
707 case TAS_READ_EQ_FILTER_COUNT:
708 put_user(TAS3001C_BIQUAD_FILTER_COUNT, argp);
709 return 0;
710
711 case TAS_READ_EQ_CHANNEL_COUNT:
712 put_user(TAS3001C_BIQUAD_CHANNEL_COUNT, argp);
713 return 0;
714
715 case TAS_READ_DRCE:
716 case TAS_WRITE_DRCE:
717 return tas3001c_drce_rw(self, cmd, arg);
718
719 case TAS_READ_DRCE_CAPS:
720 put_user(TAS_DRCE_ENABLE | TAS_DRCE_THRESHOLD, argp);
721 return 0;
722
723 case TAS_READ_DRCE_MIN:
724 case TAS_READ_DRCE_MAX: {
725 struct tas_drce_ctrl_t drce_ctrl;
726
727 if (copy_from_user(&drce_ctrl, argp,
728 sizeof(struct tas_drce_ctrl_t))) {
729 return -EFAULT;
730 }
731
732 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
733 if (cmd == TAS_READ_DRCE_MIN) {
734 drce_ctrl.data.threshold=-36<<8;
735 } else {
736 drce_ctrl.data.threshold=-6<<8;
737 }
738 }
739
740 if (copy_to_user(argp, &drce_ctrl,
741 sizeof(struct tas_drce_ctrl_t))) {
742 return -EFAULT;
743 }
744 }
745 }
746
747 return -EINVAL;
748}
749
750static int
751tas3001c_init_mixer(struct tas3001c_data_t *self)
752{
753 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
754
755 /* Make sure something answers on the i2c bus */
756 if (tas3001c_write_register(self, TAS3001C_REG_MCR, &mcr,
757 WRITE_NORMAL|FORCE_WRITE) < 0)
758 return -1;
759
760 tas3001c_fast_load(self, 1);
761
762 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD0);
763 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD1);
764 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD2);
765 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD3);
766 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD4);
767 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD5);
768 (void)tas3001c_sync_register(self,TAS3001C_REG_RIGHT_BIQUAD6);
769
770 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD0);
771 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD1);
772 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD2);
773 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD3);
774 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD4);
775 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD5);
776 (void)tas3001c_sync_register(self,TAS3001C_REG_LEFT_BIQUAD6);
777
778 tas3001c_fast_load(self, 0);
779
780 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
781 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
782 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
783
784 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
785 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
786
787 return 0;
788}
789
790static int
791tas3001c_uninit_mixer(struct tas3001c_data_t *self)
792{
793 tas3001c_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
794 tas3001c_set_mixer_level(self, SOUND_MIXER_PCM, 0);
795 tas3001c_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
796
797 tas3001c_set_mixer_level(self, SOUND_MIXER_BASS, 0);
798 tas3001c_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
799
800 return 0;
801}
802
803static int
804tas3001c_init(struct i2c_client *client)
805{
806 struct tas3001c_data_t *self;
807 size_t sz = sizeof(*self) + (TAS3001C_REG_MAX*sizeof(tas_shadow_t));
808 int i, j;
809
810 self = kmalloc(sz, GFP_KERNEL);
811 if (!self)
812 return -ENOMEM;
813 memset(self, 0, sz);
814
815 self->super.client = client;
816 self->super.shadow = (tas_shadow_t *)(self+1);
817 self->output_id = TAS_OUTPUT_HEADPHONES;
818
819 dev_set_drvdata(&client->dev, self);
820
821 for (i = 0; i < TAS3001C_BIQUAD_CHANNEL_COUNT; i++)
822 for (j = 0; j < TAS3001C_BIQUAD_FILTER_COUNT; j++)
823 tas3001c_write_biquad_shadow(self, i, j,
824 &tas3001c_eq_unity);
825
826 INIT_WORK(&device_change, tas3001c_device_change_handler, self);
827 return 0;
828}
829
830static void
831tas3001c_uninit(struct tas3001c_data_t *self)
832{
833 tas3001c_uninit_mixer(self);
834 kfree(self);
835}
836
837struct tas_driver_hooks_t tas3001c_hooks = {
838 .init = (tas_hook_init_t)tas3001c_init,
839 .post_init = (tas_hook_post_init_t)tas3001c_init_mixer,
840 .uninit = (tas_hook_uninit_t)tas3001c_uninit,
841 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3001c_get_mixer_level,
842 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3001c_set_mixer_level,
843 .enter_sleep = (tas_hook_enter_sleep_t)tas3001c_enter_sleep,
844 .leave_sleep = (tas_hook_leave_sleep_t)tas3001c_leave_sleep,
845 .supported_mixers = (tas_hook_supported_mixers_t)tas3001c_supported_mixers,
846 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3001c_mixer_is_stereo,
847 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3001c_stereo_mixers,
848 .output_device_change = (tas_hook_output_device_change_t)tas3001c_output_device_change,
849 .device_ioctl = (tas_hook_device_ioctl_t)tas3001c_device_ioctl
850};
diff --git a/sound/oss/dmasound/tas3001c.h b/sound/oss/dmasound/tas3001c.h
new file mode 100644
index 000000000000..3660da33a2db
--- /dev/null
+++ b/sound/oss/dmasound/tas3001c.h
@@ -0,0 +1,64 @@
1/*
2 * Header file for the i2c/i2s based TA3001c sound chip used
3 * on some Apple hardware. Also known as "tumbler".
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file COPYING in the main directory of this archive
7 * for more details.
8 *
9 * Written by Christopher C. Chimelis <chris@debian.org>
10 */
11
12#ifndef _TAS3001C_H_
13#define _TAS3001C_H_
14
15#include <linux/types.h>
16
17#include "tas_common.h"
18#include "tas_eq_prefs.h"
19
20/*
21 * Macros that correspond to the registers that we write to
22 * when setting the various values.
23 */
24
25#define TAS3001C_VERSION "0.3"
26#define TAS3001C_DATE "20011214"
27
28#define I2C_DRIVERNAME_TAS3001C "TAS3001c driver V " TAS3001C_VERSION
29#define I2C_DRIVERID_TAS3001C (I2C_DRIVERID_TAS_BASE+0)
30
31extern struct tas_driver_hooks_t tas3001c_hooks;
32extern struct tas_gain_t tas3001c_gain;
33extern struct tas_eq_pref_t *tas3001c_eq_prefs[];
34
35enum tas3001c_reg_t {
36 TAS3001C_REG_MCR = 0x01,
37 TAS3001C_REG_DRC = 0x02,
38
39 TAS3001C_REG_VOLUME = 0x04,
40 TAS3001C_REG_TREBLE = 0x05,
41 TAS3001C_REG_BASS = 0x06,
42 TAS3001C_REG_MIXER1 = 0x07,
43 TAS3001C_REG_MIXER2 = 0x08,
44
45 TAS3001C_REG_LEFT_BIQUAD0 = 0x0a,
46 TAS3001C_REG_LEFT_BIQUAD1 = 0x0b,
47 TAS3001C_REG_LEFT_BIQUAD2 = 0x0c,
48 TAS3001C_REG_LEFT_BIQUAD3 = 0x0d,
49 TAS3001C_REG_LEFT_BIQUAD4 = 0x0e,
50 TAS3001C_REG_LEFT_BIQUAD5 = 0x0f,
51 TAS3001C_REG_LEFT_BIQUAD6 = 0x10,
52
53 TAS3001C_REG_RIGHT_BIQUAD0 = 0x13,
54 TAS3001C_REG_RIGHT_BIQUAD1 = 0x14,
55 TAS3001C_REG_RIGHT_BIQUAD2 = 0x15,
56 TAS3001C_REG_RIGHT_BIQUAD3 = 0x16,
57 TAS3001C_REG_RIGHT_BIQUAD4 = 0x17,
58 TAS3001C_REG_RIGHT_BIQUAD5 = 0x18,
59 TAS3001C_REG_RIGHT_BIQUAD6 = 0x19,
60
61 TAS3001C_REG_MAX = 0x20
62};
63
64#endif /* _TAS3001C_H_ */
diff --git a/sound/oss/dmasound/tas3001c_tables.c b/sound/oss/dmasound/tas3001c_tables.c
new file mode 100644
index 000000000000..1768fa95f25b
--- /dev/null
+++ b/sound/oss/dmasound/tas3001c_tables.c
@@ -0,0 +1,375 @@
1#include "tas_common.h"
2#include "tas_eq_prefs.h"
3
4static struct tas_drce_t eqp_0e_2_1_drce = {
5 .enable = 1,
6 .above = { .val = 3.0 * (1<<8), .expand = 0 },
7 .below = { .val = 1.0 * (1<<8), .expand = 0 },
8 .threshold = -15.33 * (1<<8),
9 .energy = 2.4 * (1<<12),
10 .attack = 0.013 * (1<<12),
11 .decay = 0.212 * (1<<12),
12};
13
14static struct tas_biquad_ctrl_t eqp_0e_2_1_biquads[]={
15 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
16 { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
17 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
18 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
19 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
20 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
21
22 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
23 { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
24 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
25 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
26 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
27 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
28};
29
30static struct tas_eq_pref_t eqp_0e_2_1 = {
31 .sample_rate = 44100,
32 .device_id = 0x0e,
33 .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
34 .speaker_id = 0x01,
35
36 .drce = &eqp_0e_2_1_drce,
37
38 .filter_count = 12,
39 .biquads = eqp_0e_2_1_biquads
40};
41
42/* ======================================================================== */
43
44static struct tas_drce_t eqp_10_1_0_drce={
45 .enable = 1,
46 .above = { .val = 3.0 * (1<<8), .expand = 0 },
47 .below = { .val = 1.0 * (1<<8), .expand = 0 },
48 .threshold = -12.46 * (1<<8),
49 .energy = 2.4 * (1<<12),
50 .attack = 0.013 * (1<<12),
51 .decay = 0.212 * (1<<12),
52};
53
54static struct tas_biquad_ctrl_t eqp_10_1_0_biquads[]={
55 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } },
56 { .channel = 0, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } },
57 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } },
58 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } },
59 { .channel = 0, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
60 { .channel = 0, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
61
62 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0F4A12, 0xE16BDA, 0x0F4A12, 0xE173F0, 0x0E9C3A } } },
63 { .channel = 1, .filter = 1, .data = { .coeff = { 0x02DD54, 0x05BAA8, 0x02DD54, 0xF8001D, 0x037532 } } },
64 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0E2FC7, 0xE4D5DC, 0x0D7477, 0xE4D5DC, 0x0BA43F } } },
65 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0E7899, 0xE67CCA, 0x0D0E93, 0xE67CCA, 0x0B872D } } },
66 { .channel = 1, .filter = 4, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
67 { .channel = 1, .filter = 5, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
68};
69
70static struct tas_eq_pref_t eqp_10_1_0 = {
71 .sample_rate = 44100,
72 .device_id = 0x10,
73 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
74 .speaker_id = 0x00,
75
76 .drce = &eqp_10_1_0_drce,
77
78 .filter_count = 12,
79 .biquads = eqp_10_1_0_biquads
80};
81
82/* ======================================================================== */
83
84static struct tas_drce_t eqp_15_2_1_drce={
85 .enable = 1,
86 .above = { .val = 3.0 * (1<<8), .expand = 0 },
87 .below = { .val = 1.0 * (1<<8), .expand = 0 },
88 .threshold = -15.33 * (1<<8),
89 .energy = 2.4 * (1<<12),
90 .attack = 0.013 * (1<<12),
91 .decay = 0.212 * (1<<12),
92};
93
94static struct tas_biquad_ctrl_t eqp_15_2_1_biquads[]={
95 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
96 { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
97 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
98 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
99 { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
100 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
101
102 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
103 { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
104 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
105 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
106 { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
107 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
108};
109
110static struct tas_eq_pref_t eqp_15_2_1 = {
111 .sample_rate = 44100,
112 .device_id = 0x15,
113 .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
114 .speaker_id = 0x01,
115
116 .drce = &eqp_15_2_1_drce,
117
118 .filter_count = 12,
119 .biquads = eqp_15_2_1_biquads
120};
121
122/* ======================================================================== */
123
124static struct tas_drce_t eqp_15_1_0_drce={
125 .enable = 1,
126 .above = { .val = 3.0 * (1<<8), .expand = 0 },
127 .below = { .val = 1.0 * (1<<8), .expand = 0 },
128 .threshold = 0.0 * (1<<8),
129 .energy = 2.4 * (1<<12),
130 .attack = 0.013 * (1<<12),
131 .decay = 0.212 * (1<<12),
132};
133
134static struct tas_biquad_ctrl_t eqp_15_1_0_biquads[]={
135 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } },
136 { .channel = 0, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } },
137 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } },
138 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } },
139 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } },
140 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } },
141
142 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FAD08, 0xE0A5EF, 0x0FAD08, 0xE0A79D, 0x0F5BBE } } },
143 { .channel = 1, .filter = 1, .data = { .coeff = { 0x04B38D, 0x09671B, 0x04B38D, 0x000F71, 0x02BEC5 } } },
144 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FDD32, 0xE0A56F, 0x0F8A69, 0xE0A56F, 0x0F679C } } },
145 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0FD284, 0xE135FB, 0x0F2161, 0xE135FB, 0x0EF3E5 } } },
146 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0E81B1, 0xE6283F, 0x0CE49D, 0xE6283F, 0x0B664F } } },
147 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0F2D62, 0xE98797, 0x0D1E19, 0xE98797, 0x0C4B7B } } },
148};
149
150static struct tas_eq_pref_t eqp_15_1_0 = {
151 .sample_rate = 44100,
152 .device_id = 0x15,
153 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
154 .speaker_id = 0x00,
155
156 .drce = &eqp_15_1_0_drce,
157
158 .filter_count = 12,
159 .biquads = eqp_15_1_0_biquads
160};
161
162/* ======================================================================== */
163
164static struct tas_drce_t eqp_0f_2_1_drce={
165 .enable = 1,
166 .above = { .val = 3.0 * (1<<8), .expand = 0 },
167 .below = { .val = 1.0 * (1<<8), .expand = 0 },
168 .threshold = -15.33 * (1<<8),
169 .energy = 2.4 * (1<<12),
170 .attack = 0.013 * (1<<12),
171 .decay = 0.212 * (1<<12),
172};
173
174static struct tas_biquad_ctrl_t eqp_0f_2_1_biquads[]={
175 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
176 { .channel = 0, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
177 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
178 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
179 { .channel = 0, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
180 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
181
182 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FE143, 0xE05204, 0x0FCCC5, 0xE05266, 0x0FAE6B } } },
183 { .channel = 1, .filter = 1, .data = { .coeff = { 0x102383, 0xE03A03, 0x0FA325, 0xE03A03, 0x0FC6A8 } } },
184 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FF2AB, 0xE06285, 0x0FB20A, 0xE06285, 0x0FA4B5 } } },
185 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F544D, 0xE35971, 0x0D8F3A, 0xE35971, 0x0CE388 } } },
186 { .channel = 1, .filter = 4, .data = { .coeff = { 0x13E1D3, 0xF3ECB5, 0x042227, 0xF3ECB5, 0x0803FA } } },
187 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0AC119, 0x034181, 0x078AB1, 0x034181, 0x024BCA } } },
188};
189
190static struct tas_eq_pref_t eqp_0f_2_1 = {
191 .sample_rate = 44100,
192 .device_id = 0x0f,
193 .output_id = TAS_OUTPUT_EXTERNAL_SPKR,
194 .speaker_id = 0x01,
195
196 .drce = &eqp_0f_2_1_drce,
197
198 .filter_count = 12,
199 .biquads = eqp_0f_2_1_biquads
200};
201
202/* ======================================================================== */
203
204static struct tas_drce_t eqp_0f_1_0_drce={
205 .enable = 1,
206 .above = { .val = 3.0 * (1<<8), .expand = 0 },
207 .below = { .val = 1.0 * (1<<8), .expand = 0 },
208 .threshold = -15.33 * (1<<8),
209 .energy = 2.4 * (1<<12),
210 .attack = 0.013 * (1<<12),
211 .decay = 0.212 * (1<<12),
212};
213
214static struct tas_biquad_ctrl_t eqp_0f_1_0_biquads[]={
215 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
216 { .channel = 0, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
217 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
218 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
219 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
220 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
221
222 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0FCAD3, 0xE06A58, 0x0FCAD3, 0xE06B09, 0x0F9657 } } },
223 { .channel = 1, .filter = 1, .data = { .coeff = { 0x041731, 0x082E63, 0x041731, 0xFD8D08, 0x02CFBD } } },
224 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0FFDC7, 0xE0524C, 0x0FBFAA, 0xE0524C, 0x0FBD72 } } },
225 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0F3D35, 0xE228CA, 0x0EC7B2, 0xE228CA, 0x0E04E8 } } },
226 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0FCEBF, 0xE181C2, 0x0F2656, 0xE181C2, 0x0EF516 } } },
227 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0EC417, 0x073E22, 0x0B0633, 0x073E22, 0x09CA4A } } },
228};
229
230static struct tas_eq_pref_t eqp_0f_1_0 = {
231 .sample_rate = 44100,
232 .device_id = 0x0f,
233 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
234 .speaker_id = 0x00,
235
236 .drce = &eqp_0f_1_0_drce,
237
238 .filter_count = 12,
239 .biquads = eqp_0f_1_0_biquads
240};
241
242/* ======================================================================== */
243
244static uint tas3001c_master_tab[]={
245 0x0, 0x75, 0x9c, 0xbb,
246 0xdb, 0xfb, 0x11e, 0x143,
247 0x16b, 0x196, 0x1c3, 0x1f5,
248 0x229, 0x263, 0x29f, 0x2e1,
249 0x328, 0x373, 0x3c5, 0x41b,
250 0x478, 0x4dc, 0x547, 0x5b8,
251 0x633, 0x6b5, 0x740, 0x7d5,
252 0x873, 0x91c, 0x9d2, 0xa92,
253 0xb5e, 0xc39, 0xd22, 0xe19,
254 0xf20, 0x1037, 0x1161, 0x129e,
255 0x13ed, 0x1551, 0x16ca, 0x185d,
256 0x1a08, 0x1bcc, 0x1dac, 0x1fa7,
257 0x21c1, 0x23fa, 0x2655, 0x28d6,
258 0x2b7c, 0x2e4a, 0x3141, 0x3464,
259 0x37b4, 0x3b35, 0x3ee9, 0x42d3,
260 0x46f6, 0x4b53, 0x4ff0, 0x54ce,
261 0x59f2, 0x5f5f, 0x6519, 0x6b24,
262 0x7183, 0x783c, 0x7f53, 0x86cc,
263 0x8ead, 0x96fa, 0x9fba, 0xa8f2,
264 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa,
265 0xdee8, 0xeb75, 0xf8aa, 0x1068e,
266 0x1152a, 0x12487, 0x134ad, 0x145a5,
267 0x1577b, 0x16a37, 0x17df5, 0x192bd,
268 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1,
269 0x20b55, 0x22727, 0x24456, 0x262f2,
270 0x2830b
271};
272
273static uint tas3001c_mixer_tab[]={
274 0x0, 0x748, 0x9be, 0xbaf,
275 0xda4, 0xfb1, 0x11de, 0x1431,
276 0x16ad, 0x1959, 0x1c37, 0x1f4b,
277 0x2298, 0x2628, 0x29fb, 0x2e12,
278 0x327d, 0x3734, 0x3c47, 0x41b4,
279 0x4787, 0x4dbe, 0x546d, 0x5b86,
280 0x632e, 0x6b52, 0x7400, 0x7d54,
281 0x873b, 0x91c6, 0x9d1a, 0xa920,
282 0xb5e5, 0xc38c, 0xd21b, 0xe18f,
283 0xf1f5, 0x1036a, 0x1160f, 0x129d6,
284 0x13ed0, 0x1550c, 0x16ca0, 0x185c9,
285 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75,
286 0x21c0f, 0x23fa3, 0x26552, 0x28d64,
287 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b,
288 0x37b44, 0x3b353, 0x3ee94, 0x42d30,
289 0x46f55, 0x4b533, 0x4fefc, 0x54ce5,
290 0x59f25, 0x5f5f6, 0x65193, 0x6b23c,
291 0x71835, 0x783c3, 0x7f52c, 0x86cc0,
292 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a,
293 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0,
294 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4,
295 0x1152a3, 0x12486a, 0x134ac8, 0x145a55,
296 0x1577ac, 0x16a370, 0x17df51, 0x192bc2,
297 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04,
298 0x20b542, 0x227268, 0x244564, 0x262f26,
299 0x2830af
300};
301
302static uint tas3001c_treble_tab[]={
303 0x96, 0x95, 0x95, 0x94,
304 0x93, 0x92, 0x92, 0x91,
305 0x90, 0x90, 0x8f, 0x8e,
306 0x8d, 0x8d, 0x8c, 0x8b,
307 0x8a, 0x8a, 0x89, 0x88,
308 0x88, 0x87, 0x86, 0x85,
309 0x85, 0x84, 0x83, 0x83,
310 0x82, 0x81, 0x80, 0x80,
311 0x7f, 0x7e, 0x7e, 0x7d,
312 0x7c, 0x7b, 0x7b, 0x7a,
313 0x79, 0x78, 0x78, 0x77,
314 0x76, 0x76, 0x75, 0x74,
315 0x73, 0x73, 0x72, 0x71,
316 0x71, 0x70, 0x6e, 0x6d,
317 0x6d, 0x6c, 0x6b, 0x6a,
318 0x69, 0x68, 0x67, 0x66,
319 0x65, 0x63, 0x62, 0x62,
320 0x60, 0x5f, 0x5d, 0x5c,
321 0x5a, 0x58, 0x56, 0x55,
322 0x53, 0x51, 0x4f, 0x4c,
323 0x4a, 0x48, 0x45, 0x43,
324 0x40, 0x3d, 0x3a, 0x37,
325 0x35, 0x32, 0x2e, 0x2a,
326 0x27, 0x22, 0x1e, 0x1a,
327 0x15, 0x11, 0xc, 0x7,
328 0x1
329};
330
331static uint tas3001c_bass_tab[]={
332 0x86, 0x83, 0x81, 0x7f,
333 0x7d, 0x7b, 0x79, 0x78,
334 0x76, 0x75, 0x74, 0x72,
335 0x71, 0x6f, 0x6e, 0x6d,
336 0x6c, 0x6b, 0x69, 0x67,
337 0x65, 0x64, 0x61, 0x60,
338 0x5e, 0x5d, 0x5c, 0x5b,
339 0x5a, 0x59, 0x58, 0x57,
340 0x56, 0x55, 0x55, 0x54,
341 0x53, 0x52, 0x50, 0x4f,
342 0x4d, 0x4c, 0x4b, 0x49,
343 0x47, 0x45, 0x44, 0x42,
344 0x41, 0x3f, 0x3e, 0x3d,
345 0x3c, 0x3b, 0x39, 0x38,
346 0x37, 0x36, 0x35, 0x34,
347 0x33, 0x31, 0x30, 0x2f,
348 0x2e, 0x2c, 0x2b, 0x2b,
349 0x29, 0x28, 0x27, 0x26,
350 0x25, 0x24, 0x22, 0x21,
351 0x20, 0x1e, 0x1c, 0x19,
352 0x18, 0x18, 0x17, 0x16,
353 0x15, 0x14, 0x13, 0x12,
354 0x11, 0x10, 0xf, 0xe,
355 0xd, 0xb, 0xa, 0x9,
356 0x8, 0x6, 0x4, 0x2,
357 0x1
358};
359
360struct tas_gain_t tas3001c_gain = {
361 .master = tas3001c_master_tab,
362 .treble = tas3001c_treble_tab,
363 .bass = tas3001c_bass_tab,
364 .mixer = tas3001c_mixer_tab
365};
366
367struct tas_eq_pref_t *tas3001c_eq_prefs[]={
368 &eqp_0e_2_1,
369 &eqp_10_1_0,
370 &eqp_15_2_1,
371 &eqp_15_1_0,
372 &eqp_0f_2_1,
373 &eqp_0f_1_0,
374 NULL
375};
diff --git a/sound/oss/dmasound/tas3004.c b/sound/oss/dmasound/tas3004.c
new file mode 100644
index 000000000000..82eaaca2db9a
--- /dev/null
+++ b/sound/oss/dmasound/tas3004.c
@@ -0,0 +1,1140 @@
1/*
2 * Driver for the i2c/i2s based TA3004 sound chip used
3 * on some Apple hardware. Also known as "snapper".
4 *
5 * Tobias Sargeant <tobias.sargeant@bigpond.com>
6 * Based upon tas3001c.c by Christopher C. Chimelis <chris@debian.org>:
7 *
8 * Input support by Renzo Davoli <renzo@cs.unibo.it>
9 *
10 */
11
12#include <linux/module.h>
13#include <linux/slab.h>
14#include <linux/proc_fs.h>
15#include <linux/ioport.h>
16#include <linux/sysctl.h>
17#include <linux/types.h>
18#include <linux/i2c.h>
19#include <linux/init.h>
20#include <linux/soundcard.h>
21#include <linux/interrupt.h>
22#include <linux/workqueue.h>
23
24#include <asm/uaccess.h>
25#include <asm/errno.h>
26#include <asm/io.h>
27#include <asm/prom.h>
28
29#include "dmasound.h"
30#include "tas_common.h"
31#include "tas3004.h"
32
33#include "tas_ioctl.h"
34
35/* #define DEBUG_DRCE */
36
37#define TAS3004_BIQUAD_FILTER_COUNT 7
38#define TAS3004_BIQUAD_CHANNEL_COUNT 2
39
40#define VOL_DEFAULT (100 * 4 / 5)
41#define INPUT_DEFAULT (100 * 4 / 5)
42#define BASS_DEFAULT (100 / 2)
43#define TREBLE_DEFAULT (100 / 2)
44
45struct tas3004_data_t {
46 struct tas_data_t super;
47 int device_id;
48 int output_id;
49 int speaker_id;
50 struct tas_drce_t drce_state;
51};
52
53#define MAKE_TIME(sec,usec) (((sec)<<12) + (50000+(usec/10)*(1<<12))/100000)
54
55#define MAKE_RATIO(i,f) (((i)<<8) + ((500+(f)*(1<<8))/1000))
56
57
58static const union tas_biquad_t tas3004_eq_unity = {
59 .buf = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 },
60};
61
62
63static const struct tas_drce_t tas3004_drce_min = {
64 .enable = 1,
65 .above = { .val = MAKE_RATIO(16,0), .expand = 0 },
66 .below = { .val = MAKE_RATIO(2,0), .expand = 0 },
67 .threshold = -0x59a0,
68 .energy = MAKE_TIME(0, 1700),
69 .attack = MAKE_TIME(0, 1700),
70 .decay = MAKE_TIME(0, 1700),
71};
72
73
74static const struct tas_drce_t tas3004_drce_max = {
75 .enable = 1,
76 .above = { .val = MAKE_RATIO(1,500), .expand = 1 },
77 .below = { .val = MAKE_RATIO(2,0), .expand = 1 },
78 .threshold = -0x0,
79 .energy = MAKE_TIME(2,400000),
80 .attack = MAKE_TIME(2,400000),
81 .decay = MAKE_TIME(2,400000),
82};
83
84
85static const unsigned short time_constants[]={
86 MAKE_TIME(0, 1700),
87 MAKE_TIME(0, 3500),
88 MAKE_TIME(0, 6700),
89 MAKE_TIME(0, 13000),
90 MAKE_TIME(0, 26000),
91 MAKE_TIME(0, 53000),
92 MAKE_TIME(0,106000),
93 MAKE_TIME(0,212000),
94 MAKE_TIME(0,425000),
95 MAKE_TIME(0,850000),
96 MAKE_TIME(1,700000),
97 MAKE_TIME(2,400000),
98};
99
100static const unsigned short above_threshold_compression_ratio[]={
101 MAKE_RATIO( 1, 70),
102 MAKE_RATIO( 1,140),
103 MAKE_RATIO( 1,230),
104 MAKE_RATIO( 1,330),
105 MAKE_RATIO( 1,450),
106 MAKE_RATIO( 1,600),
107 MAKE_RATIO( 1,780),
108 MAKE_RATIO( 2, 0),
109 MAKE_RATIO( 2,290),
110 MAKE_RATIO( 2,670),
111 MAKE_RATIO( 3,200),
112 MAKE_RATIO( 4, 0),
113 MAKE_RATIO( 5,330),
114 MAKE_RATIO( 8, 0),
115 MAKE_RATIO(16, 0),
116};
117
118static const unsigned short above_threshold_expansion_ratio[]={
119 MAKE_RATIO(1, 60),
120 MAKE_RATIO(1,130),
121 MAKE_RATIO(1,190),
122 MAKE_RATIO(1,250),
123 MAKE_RATIO(1,310),
124 MAKE_RATIO(1,380),
125 MAKE_RATIO(1,440),
126 MAKE_RATIO(1,500)
127};
128
129static const unsigned short below_threshold_compression_ratio[]={
130 MAKE_RATIO(1, 70),
131 MAKE_RATIO(1,140),
132 MAKE_RATIO(1,230),
133 MAKE_RATIO(1,330),
134 MAKE_RATIO(1,450),
135 MAKE_RATIO(1,600),
136 MAKE_RATIO(1,780),
137 MAKE_RATIO(2, 0)
138};
139
140static const unsigned short below_threshold_expansion_ratio[]={
141 MAKE_RATIO(1, 60),
142 MAKE_RATIO(1,130),
143 MAKE_RATIO(1,190),
144 MAKE_RATIO(1,250),
145 MAKE_RATIO(1,310),
146 MAKE_RATIO(1,380),
147 MAKE_RATIO(1,440),
148 MAKE_RATIO(1,500),
149 MAKE_RATIO(1,560),
150 MAKE_RATIO(1,630),
151 MAKE_RATIO(1,690),
152 MAKE_RATIO(1,750),
153 MAKE_RATIO(1,810),
154 MAKE_RATIO(1,880),
155 MAKE_RATIO(1,940),
156 MAKE_RATIO(2, 0)
157};
158
159static inline int
160search( unsigned short val,
161 const unsigned short *arr,
162 const int arrsize) {
163 /*
164 * This could be a binary search, but for small tables,
165 * a linear search is likely to be faster
166 */
167
168 int i;
169
170 for (i=0; i < arrsize; i++)
171 if (arr[i] >= val)
172 goto _1;
173 return arrsize-1;
174 _1:
175 if (i == 0)
176 return 0;
177 return (arr[i]-val < val-arr[i-1]) ? i : i-1;
178}
179
180#define SEARCH(a, b) search(a, b, ARRAY_SIZE(b))
181
182static inline int
183time_index(unsigned short time)
184{
185 return SEARCH(time, time_constants);
186}
187
188
189static inline int
190above_threshold_compression_index(unsigned short ratio)
191{
192 return SEARCH(ratio, above_threshold_compression_ratio);
193}
194
195
196static inline int
197above_threshold_expansion_index(unsigned short ratio)
198{
199 return SEARCH(ratio, above_threshold_expansion_ratio);
200}
201
202
203static inline int
204below_threshold_compression_index(unsigned short ratio)
205{
206 return SEARCH(ratio, below_threshold_compression_ratio);
207}
208
209
210static inline int
211below_threshold_expansion_index(unsigned short ratio)
212{
213 return SEARCH(ratio, below_threshold_expansion_ratio);
214}
215
216static inline unsigned char db_to_regval(short db) {
217 int r=0;
218
219 r=(db+0x59a0) / 0x60;
220
221 if (r < 0x91) return 0x91;
222 if (r > 0xef) return 0xef;
223 return r;
224}
225
226static inline short quantize_db(short db)
227{
228 return db_to_regval(db) * 0x60 - 0x59a0;
229}
230
231static inline int
232register_width(enum tas3004_reg_t r)
233{
234 switch(r) {
235 case TAS3004_REG_MCR:
236 case TAS3004_REG_TREBLE:
237 case TAS3004_REG_BASS:
238 case TAS3004_REG_ANALOG_CTRL:
239 case TAS3004_REG_TEST1:
240 case TAS3004_REG_TEST2:
241 case TAS3004_REG_MCR2:
242 return 1;
243
244 case TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN:
245 case TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN:
246 return 3;
247
248 case TAS3004_REG_DRC:
249 case TAS3004_REG_VOLUME:
250 return 6;
251
252 case TAS3004_REG_LEFT_MIXER:
253 case TAS3004_REG_RIGHT_MIXER:
254 return 9;
255
256 case TAS3004_REG_TEST:
257 return 10;
258
259 case TAS3004_REG_LEFT_BIQUAD0:
260 case TAS3004_REG_LEFT_BIQUAD1:
261 case TAS3004_REG_LEFT_BIQUAD2:
262 case TAS3004_REG_LEFT_BIQUAD3:
263 case TAS3004_REG_LEFT_BIQUAD4:
264 case TAS3004_REG_LEFT_BIQUAD5:
265 case TAS3004_REG_LEFT_BIQUAD6:
266
267 case TAS3004_REG_RIGHT_BIQUAD0:
268 case TAS3004_REG_RIGHT_BIQUAD1:
269 case TAS3004_REG_RIGHT_BIQUAD2:
270 case TAS3004_REG_RIGHT_BIQUAD3:
271 case TAS3004_REG_RIGHT_BIQUAD4:
272 case TAS3004_REG_RIGHT_BIQUAD5:
273 case TAS3004_REG_RIGHT_BIQUAD6:
274
275 case TAS3004_REG_LEFT_LOUD_BIQUAD:
276 case TAS3004_REG_RIGHT_LOUD_BIQUAD:
277 return 15;
278
279 default:
280 return 0;
281 }
282}
283
284static int
285tas3004_write_register( struct tas3004_data_t *self,
286 enum tas3004_reg_t reg_num,
287 char *data,
288 uint write_mode)
289{
290 if (reg_num==TAS3004_REG_MCR ||
291 reg_num==TAS3004_REG_BASS ||
292 reg_num==TAS3004_REG_TREBLE ||
293 reg_num==TAS3004_REG_ANALOG_CTRL) {
294 return tas_write_byte_register(&self->super,
295 (uint)reg_num,
296 *data,
297 write_mode);
298 } else {
299 return tas_write_register(&self->super,
300 (uint)reg_num,
301 register_width(reg_num),
302 data,
303 write_mode);
304 }
305}
306
307static int
308tas3004_sync_register( struct tas3004_data_t *self,
309 enum tas3004_reg_t reg_num)
310{
311 if (reg_num==TAS3004_REG_MCR ||
312 reg_num==TAS3004_REG_BASS ||
313 reg_num==TAS3004_REG_TREBLE ||
314 reg_num==TAS3004_REG_ANALOG_CTRL) {
315 return tas_sync_byte_register(&self->super,
316 (uint)reg_num,
317 register_width(reg_num));
318 } else {
319 return tas_sync_register(&self->super,
320 (uint)reg_num,
321 register_width(reg_num));
322 }
323}
324
325static int
326tas3004_read_register( struct tas3004_data_t *self,
327 enum tas3004_reg_t reg_num,
328 char *data,
329 uint write_mode)
330{
331 return tas_read_register(&self->super,
332 (uint)reg_num,
333 register_width(reg_num),
334 data);
335}
336
337static inline int
338tas3004_fast_load(struct tas3004_data_t *self, int fast)
339{
340 if (fast)
341 self->super.shadow[TAS3004_REG_MCR][0] |= 0x80;
342 else
343 self->super.shadow[TAS3004_REG_MCR][0] &= 0x7f;
344 return tas3004_sync_register(self,TAS3004_REG_MCR);
345}
346
347static uint
348tas3004_supported_mixers(struct tas3004_data_t *self)
349{
350 return SOUND_MASK_VOLUME |
351 SOUND_MASK_PCM |
352 SOUND_MASK_ALTPCM |
353 SOUND_MASK_IMIX |
354 SOUND_MASK_TREBLE |
355 SOUND_MASK_BASS |
356 SOUND_MASK_MIC |
357 SOUND_MASK_LINE;
358}
359
360static int
361tas3004_mixer_is_stereo(struct tas3004_data_t *self, int mixer)
362{
363 switch(mixer) {
364 case SOUND_MIXER_VOLUME:
365 case SOUND_MIXER_PCM:
366 case SOUND_MIXER_ALTPCM:
367 case SOUND_MIXER_IMIX:
368 return 1;
369 default:
370 return 0;
371 }
372}
373
374static uint
375tas3004_stereo_mixers(struct tas3004_data_t *self)
376{
377 uint r = tas3004_supported_mixers(self);
378 uint i;
379
380 for (i=1; i<SOUND_MIXER_NRDEVICES; i++)
381 if (r&(1<<i) && !tas3004_mixer_is_stereo(self,i))
382 r &= ~(1<<i);
383 return r;
384}
385
386static int
387tas3004_get_mixer_level(struct tas3004_data_t *self, int mixer, uint *level)
388{
389 if (!self)
390 return -1;
391
392 *level = self->super.mixer[mixer];
393
394 return 0;
395}
396
397static int
398tas3004_set_mixer_level(struct tas3004_data_t *self, int mixer, uint level)
399{
400 int rc;
401 tas_shadow_t *shadow;
402 uint temp;
403 uint offset=0;
404
405 if (!self)
406 return -1;
407
408 shadow = self->super.shadow;
409
410 if (!tas3004_mixer_is_stereo(self,mixer))
411 level = tas_mono_to_stereo(level);
412 switch(mixer) {
413 case SOUND_MIXER_VOLUME:
414 temp = tas3004_gain.master[level&0xff];
415 SET_4_20(shadow[TAS3004_REG_VOLUME], 0, temp);
416 temp = tas3004_gain.master[(level>>8)&0xff];
417 SET_4_20(shadow[TAS3004_REG_VOLUME], 3, temp);
418 rc = tas3004_sync_register(self,TAS3004_REG_VOLUME);
419 break;
420 case SOUND_MIXER_IMIX:
421 offset += 3;
422 case SOUND_MIXER_ALTPCM:
423 offset += 3;
424 case SOUND_MIXER_PCM:
425 /*
426 * Don't load these in fast mode. The documentation
427 * says it can be done in either mode, but testing it
428 * shows that fast mode produces ugly clicking.
429 */
430 /* tas3004_fast_load(self,1); */
431 temp = tas3004_gain.mixer[level&0xff];
432 SET_4_20(shadow[TAS3004_REG_LEFT_MIXER], offset, temp);
433 temp = tas3004_gain.mixer[(level>>8)&0xff];
434 SET_4_20(shadow[TAS3004_REG_RIGHT_MIXER], offset, temp);
435 rc = tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
436 if (rc == 0)
437 rc=tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
438 /* tas3004_fast_load(self,0); */
439 break;
440 case SOUND_MIXER_TREBLE:
441 temp = tas3004_gain.treble[level&0xff];
442 shadow[TAS3004_REG_TREBLE][0]=temp&0xff;
443 rc = tas3004_sync_register(self,TAS3004_REG_TREBLE);
444 break;
445 case SOUND_MIXER_BASS:
446 temp = tas3004_gain.bass[level&0xff];
447 shadow[TAS3004_REG_BASS][0]=temp&0xff;
448 rc = tas3004_sync_register(self,TAS3004_REG_BASS);
449 break;
450 case SOUND_MIXER_MIC:
451 if ((level&0xff)>0) {
452 software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
453 if (self->super.mixer[mixer] == 0) {
454 self->super.mixer[SOUND_MIXER_LINE] = 0;
455 shadow[TAS3004_REG_ANALOG_CTRL][0]=0xc2;
456 rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
457 } else rc=0;
458 } else {
459 self->super.mixer[SOUND_MIXER_LINE] = SW_INPUT_VOLUME_DEFAULT;
460 software_input_volume = SW_INPUT_VOLUME_SCALE *
461 (self->super.mixer[SOUND_MIXER_LINE]&0xff);
462 shadow[TAS3004_REG_ANALOG_CTRL][0]=0x00;
463 rc = tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
464 }
465 break;
466 case SOUND_MIXER_LINE:
467 if (self->super.mixer[SOUND_MIXER_MIC] == 0) {
468 software_input_volume = SW_INPUT_VOLUME_SCALE * (level&0xff);
469 rc=0;
470 }
471 break;
472 default:
473 rc = -1;
474 break;
475 }
476 if (rc < 0)
477 return rc;
478 self->super.mixer[mixer] = level;
479
480 return 0;
481}
482
483static int
484tas3004_leave_sleep(struct tas3004_data_t *self)
485{
486 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
487
488 if (!self)
489 return -1;
490
491 /* Make sure something answers on the i2c bus */
492 if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
493 WRITE_NORMAL | FORCE_WRITE) < 0)
494 return -1;
495
496 tas3004_fast_load(self, 1);
497
498 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
499 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
500 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
501 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
502 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
503 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
504 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
505
506 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
507 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
508 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
509 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
510 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
511 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
512 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
513
514 tas3004_fast_load(self, 0);
515
516 (void)tas3004_sync_register(self,TAS3004_REG_VOLUME);
517 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_MIXER);
518 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_MIXER);
519 (void)tas3004_sync_register(self,TAS3004_REG_TREBLE);
520 (void)tas3004_sync_register(self,TAS3004_REG_BASS);
521 (void)tas3004_sync_register(self,TAS3004_REG_ANALOG_CTRL);
522
523 return 0;
524}
525
526static int
527tas3004_enter_sleep(struct tas3004_data_t *self)
528{
529 if (!self)
530 return -1;
531 return 0;
532}
533
534static int
535tas3004_sync_biquad( struct tas3004_data_t *self,
536 u_int channel,
537 u_int filter)
538{
539 enum tas3004_reg_t reg;
540
541 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
542 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
543
544 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
545
546 return tas3004_sync_register(self,reg);
547}
548
549static int
550tas3004_write_biquad_shadow( struct tas3004_data_t *self,
551 u_int channel,
552 u_int filter,
553 const union tas_biquad_t *biquad)
554{
555 tas_shadow_t *shadow=self->super.shadow;
556 enum tas3004_reg_t reg;
557
558 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
559 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
560
561 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
562
563 SET_4_20(shadow[reg], 0,biquad->coeff.b0);
564 SET_4_20(shadow[reg], 3,biquad->coeff.b1);
565 SET_4_20(shadow[reg], 6,biquad->coeff.b2);
566 SET_4_20(shadow[reg], 9,biquad->coeff.a1);
567 SET_4_20(shadow[reg],12,biquad->coeff.a2);
568
569 return 0;
570}
571
572static int
573tas3004_write_biquad( struct tas3004_data_t *self,
574 u_int channel,
575 u_int filter,
576 const union tas_biquad_t *biquad)
577{
578 int rc;
579
580 rc=tas3004_write_biquad_shadow(self, channel, filter, biquad);
581 if (rc < 0) return rc;
582
583 return tas3004_sync_biquad(self, channel, filter);
584}
585
586static int
587tas3004_write_biquad_list( struct tas3004_data_t *self,
588 u_int filter_count,
589 u_int flags,
590 struct tas_biquad_ctrl_t *biquads)
591{
592 int i;
593 int rc;
594
595 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
596
597 for (i=0; i<filter_count; i++) {
598 rc=tas3004_write_biquad(self,
599 biquads[i].channel,
600 biquads[i].filter,
601 &biquads[i].data);
602 if (rc < 0) break;
603 }
604
605 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,0);
606
607 return rc;
608}
609
610static int
611tas3004_read_biquad( struct tas3004_data_t *self,
612 u_int channel,
613 u_int filter,
614 union tas_biquad_t *biquad)
615{
616 tas_shadow_t *shadow=self->super.shadow;
617 enum tas3004_reg_t reg;
618
619 if (channel >= TAS3004_BIQUAD_CHANNEL_COUNT ||
620 filter >= TAS3004_BIQUAD_FILTER_COUNT) return -EINVAL;
621
622 reg=( channel ? TAS3004_REG_RIGHT_BIQUAD0 : TAS3004_REG_LEFT_BIQUAD0 ) + filter;
623
624 biquad->coeff.b0=GET_4_20(shadow[reg], 0);
625 biquad->coeff.b1=GET_4_20(shadow[reg], 3);
626 biquad->coeff.b2=GET_4_20(shadow[reg], 6);
627 biquad->coeff.a1=GET_4_20(shadow[reg], 9);
628 biquad->coeff.a2=GET_4_20(shadow[reg],12);
629
630 return 0;
631}
632
633static int
634tas3004_eq_rw( struct tas3004_data_t *self,
635 u_int cmd,
636 u_long arg)
637{
638 void __user *argp = (void __user *)arg;
639 int rc;
640 struct tas_biquad_ctrl_t biquad;
641
642 if (copy_from_user((void *)&biquad, argp, sizeof(struct tas_biquad_ctrl_t))) {
643 return -EFAULT;
644 }
645
646 if (cmd & SIOC_IN) {
647 rc=tas3004_write_biquad(self, biquad.channel, biquad.filter, &biquad.data);
648 if (rc != 0) return rc;
649 }
650
651 if (cmd & SIOC_OUT) {
652 rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
653 if (rc != 0) return rc;
654
655 if (copy_to_user(argp, &biquad, sizeof(struct tas_biquad_ctrl_t))) {
656 return -EFAULT;
657 }
658
659 }
660 return 0;
661}
662
663static int
664tas3004_eq_list_rw( struct tas3004_data_t *self,
665 u_int cmd,
666 u_long arg)
667{
668 int rc = 0;
669 int filter_count;
670 int flags;
671 int i,j;
672 char sync_required[TAS3004_BIQUAD_CHANNEL_COUNT][TAS3004_BIQUAD_FILTER_COUNT];
673 struct tas_biquad_ctrl_t biquad;
674 struct tas_biquad_ctrl_list_t __user *argp = (void __user *)arg;
675
676 memset(sync_required,0,sizeof(sync_required));
677
678 if (copy_from_user(&filter_count, &argp->filter_count, sizeof(int)))
679 return -EFAULT;
680
681 if (copy_from_user(&flags, &argp->flags, sizeof(int)))
682 return -EFAULT;
683
684 if (cmd & SIOC_IN) {
685 }
686
687 for (i=0; i < filter_count; i++) {
688 if (copy_from_user(&biquad, &argp->biquads[i],
689 sizeof(struct tas_biquad_ctrl_t))) {
690 return -EFAULT;
691 }
692
693 if (cmd & SIOC_IN) {
694 sync_required[biquad.channel][biquad.filter]=1;
695 rc=tas3004_write_biquad_shadow(self, biquad.channel, biquad.filter, &biquad.data);
696 if (rc != 0) return rc;
697 }
698
699 if (cmd & SIOC_OUT) {
700 rc=tas3004_read_biquad(self, biquad.channel, biquad.filter, &biquad.data);
701 if (rc != 0) return rc;
702
703 if (copy_to_user(&argp->biquads[i], &biquad,
704 sizeof(struct tas_biquad_ctrl_t))) {
705 return -EFAULT;
706 }
707 }
708 }
709
710 if (cmd & SIOC_IN) {
711 /*
712 * This is OK for the tas3004. For the
713 * tas3001c, going into fast load mode causes
714 * the treble and bass to be reset to 0dB, and
715 * volume controls to be muted.
716 */
717 if (flags & TAS_BIQUAD_FAST_LOAD) tas3004_fast_load(self,1);
718 for (i=0; i<TAS3004_BIQUAD_CHANNEL_COUNT; i++) {
719 for (j=0; j<TAS3004_BIQUAD_FILTER_COUNT; j++) {
720 if (sync_required[i][j]) {
721 rc=tas3004_sync_biquad(self, i, j);
722 if (rc < 0) goto out;
723 }
724 }
725 }
726 out:
727 if (flags & TAS_BIQUAD_FAST_LOAD)
728 tas3004_fast_load(self,0);
729 }
730
731 return rc;
732}
733
734static int
735tas3004_update_drce( struct tas3004_data_t *self,
736 int flags,
737 struct tas_drce_t *drce)
738{
739 tas_shadow_t *shadow;
740 int i;
741 shadow=self->super.shadow;
742
743 if (flags & TAS_DRCE_ABOVE_RATIO) {
744 self->drce_state.above.expand = drce->above.expand;
745 if (drce->above.val == (1<<8)) {
746 self->drce_state.above.val = 1<<8;
747 shadow[TAS3004_REG_DRC][0] = 0x02;
748
749 } else if (drce->above.expand) {
750 i=above_threshold_expansion_index(drce->above.val);
751 self->drce_state.above.val=above_threshold_expansion_ratio[i];
752 shadow[TAS3004_REG_DRC][0] = 0x0a + (i<<3);
753 } else {
754 i=above_threshold_compression_index(drce->above.val);
755 self->drce_state.above.val=above_threshold_compression_ratio[i];
756 shadow[TAS3004_REG_DRC][0] = 0x08 + (i<<3);
757 }
758 }
759
760 if (flags & TAS_DRCE_BELOW_RATIO) {
761 self->drce_state.below.expand = drce->below.expand;
762 if (drce->below.val == (1<<8)) {
763 self->drce_state.below.val = 1<<8;
764 shadow[TAS3004_REG_DRC][1] = 0x02;
765
766 } else if (drce->below.expand) {
767 i=below_threshold_expansion_index(drce->below.val);
768 self->drce_state.below.val=below_threshold_expansion_ratio[i];
769 shadow[TAS3004_REG_DRC][1] = 0x08 + (i<<3);
770 } else {
771 i=below_threshold_compression_index(drce->below.val);
772 self->drce_state.below.val=below_threshold_compression_ratio[i];
773 shadow[TAS3004_REG_DRC][1] = 0x0a + (i<<3);
774 }
775 }
776
777 if (flags & TAS_DRCE_THRESHOLD) {
778 self->drce_state.threshold=quantize_db(drce->threshold);
779 shadow[TAS3004_REG_DRC][2] = db_to_regval(self->drce_state.threshold);
780 }
781
782 if (flags & TAS_DRCE_ENERGY) {
783 i=time_index(drce->energy);
784 self->drce_state.energy=time_constants[i];
785 shadow[TAS3004_REG_DRC][3] = 0x40 + (i<<4);
786 }
787
788 if (flags & TAS_DRCE_ATTACK) {
789 i=time_index(drce->attack);
790 self->drce_state.attack=time_constants[i];
791 shadow[TAS3004_REG_DRC][4] = 0x40 + (i<<4);
792 }
793
794 if (flags & TAS_DRCE_DECAY) {
795 i=time_index(drce->decay);
796 self->drce_state.decay=time_constants[i];
797 shadow[TAS3004_REG_DRC][5] = 0x40 + (i<<4);
798 }
799
800 if (flags & TAS_DRCE_ENABLE) {
801 self->drce_state.enable = drce->enable;
802 }
803
804 if (!self->drce_state.enable) {
805 shadow[TAS3004_REG_DRC][0] |= 0x01;
806 }
807
808#ifdef DEBUG_DRCE
809 printk("DRCE: set [ ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
810 self->drce_state.enable,
811 self->drce_state.above.expand,self->drce_state.above.val,
812 self->drce_state.below.expand,self->drce_state.below.val,
813 self->drce_state.threshold,
814 self->drce_state.energy,
815 self->drce_state.attack,
816 self->drce_state.decay);
817
818 printk("DRCE: reg [ %02x %02x %02x %02x %02x %02x ]\n",
819 (unsigned char)shadow[TAS3004_REG_DRC][0],
820 (unsigned char)shadow[TAS3004_REG_DRC][1],
821 (unsigned char)shadow[TAS3004_REG_DRC][2],
822 (unsigned char)shadow[TAS3004_REG_DRC][3],
823 (unsigned char)shadow[TAS3004_REG_DRC][4],
824 (unsigned char)shadow[TAS3004_REG_DRC][5]);
825#endif
826
827 return tas3004_sync_register(self, TAS3004_REG_DRC);
828}
829
830static int
831tas3004_drce_rw( struct tas3004_data_t *self,
832 u_int cmd,
833 u_long arg)
834{
835 int rc;
836 struct tas_drce_ctrl_t drce_ctrl;
837 void __user *argp = (void __user *)arg;
838
839 if (copy_from_user(&drce_ctrl, argp, sizeof(struct tas_drce_ctrl_t)))
840 return -EFAULT;
841
842#ifdef DEBUG_DRCE
843 printk("DRCE: input [ FLAGS:%x ENABLE:%x ABOVE:%x/%x BELOW:%x/%x THRESH:%x ENERGY:%x ATTACK:%x DECAY:%x\n",
844 drce_ctrl.flags,
845 drce_ctrl.data.enable,
846 drce_ctrl.data.above.expand,drce_ctrl.data.above.val,
847 drce_ctrl.data.below.expand,drce_ctrl.data.below.val,
848 drce_ctrl.data.threshold,
849 drce_ctrl.data.energy,
850 drce_ctrl.data.attack,
851 drce_ctrl.data.decay);
852#endif
853
854 if (cmd & SIOC_IN) {
855 rc = tas3004_update_drce(self, drce_ctrl.flags, &drce_ctrl.data);
856 if (rc < 0) return rc;
857 }
858
859 if (cmd & SIOC_OUT) {
860 if (drce_ctrl.flags & TAS_DRCE_ENABLE)
861 drce_ctrl.data.enable = self->drce_state.enable;
862 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO)
863 drce_ctrl.data.above = self->drce_state.above;
864 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO)
865 drce_ctrl.data.below = self->drce_state.below;
866 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD)
867 drce_ctrl.data.threshold = self->drce_state.threshold;
868 if (drce_ctrl.flags & TAS_DRCE_ENERGY)
869 drce_ctrl.data.energy = self->drce_state.energy;
870 if (drce_ctrl.flags & TAS_DRCE_ATTACK)
871 drce_ctrl.data.attack = self->drce_state.attack;
872 if (drce_ctrl.flags & TAS_DRCE_DECAY)
873 drce_ctrl.data.decay = self->drce_state.decay;
874
875 if (copy_to_user(argp, &drce_ctrl,
876 sizeof(struct tas_drce_ctrl_t))) {
877 return -EFAULT;
878 }
879 }
880
881 return 0;
882}
883
884static void
885tas3004_update_device_parameters(struct tas3004_data_t *self)
886{
887 char data;
888 int i;
889
890 if (!self) return;
891
892 if (self->output_id == TAS_OUTPUT_HEADPHONES) {
893 /* turn on allPass when headphones are plugged in */
894 data = 0x02;
895 } else {
896 data = 0x00;
897 }
898
899 tas3004_write_register(self, TAS3004_REG_MCR2, &data, WRITE_NORMAL | FORCE_WRITE);
900
901 for (i=0; tas3004_eq_prefs[i]; i++) {
902 struct tas_eq_pref_t *eq = tas3004_eq_prefs[i];
903
904 if (eq->device_id == self->device_id &&
905 (eq->output_id == 0 || eq->output_id == self->output_id) &&
906 (eq->speaker_id == 0 || eq->speaker_id == self->speaker_id)) {
907
908 tas3004_update_drce(self, TAS_DRCE_ALL, eq->drce);
909 tas3004_write_biquad_list(self, eq->filter_count, TAS_BIQUAD_FAST_LOAD, eq->biquads);
910
911 break;
912 }
913 }
914}
915
916static void
917tas3004_device_change_handler(void *self)
918{
919 if (!self) return;
920
921 tas3004_update_device_parameters((struct tas3004_data_t *)self);
922}
923
924static struct work_struct device_change;
925
926static int
927tas3004_output_device_change( struct tas3004_data_t *self,
928 int device_id,
929 int output_id,
930 int speaker_id)
931{
932 self->device_id=device_id;
933 self->output_id=output_id;
934 self->speaker_id=speaker_id;
935
936 schedule_work(&device_change);
937
938 return 0;
939}
940
941static int
942tas3004_device_ioctl( struct tas3004_data_t *self,
943 u_int cmd,
944 u_long arg)
945{
946 uint __user *argp = (void __user *)arg;
947 switch (cmd) {
948 case TAS_READ_EQ:
949 case TAS_WRITE_EQ:
950 return tas3004_eq_rw(self, cmd, arg);
951
952 case TAS_READ_EQ_LIST:
953 case TAS_WRITE_EQ_LIST:
954 return tas3004_eq_list_rw(self, cmd, arg);
955
956 case TAS_READ_EQ_FILTER_COUNT:
957 put_user(TAS3004_BIQUAD_FILTER_COUNT, argp);
958 return 0;
959
960 case TAS_READ_EQ_CHANNEL_COUNT:
961 put_user(TAS3004_BIQUAD_CHANNEL_COUNT, argp);
962 return 0;
963
964 case TAS_READ_DRCE:
965 case TAS_WRITE_DRCE:
966 return tas3004_drce_rw(self, cmd, arg);
967
968 case TAS_READ_DRCE_CAPS:
969 put_user(TAS_DRCE_ENABLE |
970 TAS_DRCE_ABOVE_RATIO |
971 TAS_DRCE_BELOW_RATIO |
972 TAS_DRCE_THRESHOLD |
973 TAS_DRCE_ENERGY |
974 TAS_DRCE_ATTACK |
975 TAS_DRCE_DECAY,
976 argp);
977 return 0;
978
979 case TAS_READ_DRCE_MIN:
980 case TAS_READ_DRCE_MAX: {
981 struct tas_drce_ctrl_t drce_ctrl;
982 const struct tas_drce_t *drce_copy;
983
984 if (copy_from_user(&drce_ctrl, argp,
985 sizeof(struct tas_drce_ctrl_t))) {
986 return -EFAULT;
987 }
988
989 if (cmd == TAS_READ_DRCE_MIN) {
990 drce_copy=&tas3004_drce_min;
991 } else {
992 drce_copy=&tas3004_drce_max;
993 }
994
995 if (drce_ctrl.flags & TAS_DRCE_ABOVE_RATIO) {
996 drce_ctrl.data.above=drce_copy->above;
997 }
998 if (drce_ctrl.flags & TAS_DRCE_BELOW_RATIO) {
999 drce_ctrl.data.below=drce_copy->below;
1000 }
1001 if (drce_ctrl.flags & TAS_DRCE_THRESHOLD) {
1002 drce_ctrl.data.threshold=drce_copy->threshold;
1003 }
1004 if (drce_ctrl.flags & TAS_DRCE_ENERGY) {
1005 drce_ctrl.data.energy=drce_copy->energy;
1006 }
1007 if (drce_ctrl.flags & TAS_DRCE_ATTACK) {
1008 drce_ctrl.data.attack=drce_copy->attack;
1009 }
1010 if (drce_ctrl.flags & TAS_DRCE_DECAY) {
1011 drce_ctrl.data.decay=drce_copy->decay;
1012 }
1013
1014 if (copy_to_user(argp, &drce_ctrl,
1015 sizeof(struct tas_drce_ctrl_t))) {
1016 return -EFAULT;
1017 }
1018 }
1019 }
1020
1021 return -EINVAL;
1022}
1023
1024static int
1025tas3004_init_mixer(struct tas3004_data_t *self)
1026{
1027 unsigned char mcr = (1<<6)+(2<<4)+(2<<2);
1028
1029 /* Make sure something answers on the i2c bus */
1030 if (tas3004_write_register(self, TAS3004_REG_MCR, &mcr,
1031 WRITE_NORMAL | FORCE_WRITE) < 0)
1032 return -1;
1033
1034 tas3004_fast_load(self, 1);
1035
1036 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD0);
1037 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD1);
1038 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD2);
1039 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD3);
1040 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD4);
1041 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD5);
1042 (void)tas3004_sync_register(self,TAS3004_REG_RIGHT_BIQUAD6);
1043
1044 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD0);
1045 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD1);
1046 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD2);
1047 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD3);
1048 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD4);
1049 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD5);
1050 (void)tas3004_sync_register(self,TAS3004_REG_LEFT_BIQUAD6);
1051
1052 tas3004_sync_register(self, TAS3004_REG_DRC);
1053
1054 tas3004_sync_register(self, TAS3004_REG_MCR2);
1055
1056 tas3004_fast_load(self, 0);
1057
1058 tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, VOL_DEFAULT<<8 | VOL_DEFAULT);
1059 tas3004_set_mixer_level(self, SOUND_MIXER_PCM, INPUT_DEFAULT<<8 | INPUT_DEFAULT);
1060 tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
1061 tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
1062
1063 tas3004_set_mixer_level(self, SOUND_MIXER_BASS, BASS_DEFAULT);
1064 tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, TREBLE_DEFAULT);
1065
1066 tas3004_set_mixer_level(self, SOUND_MIXER_LINE,SW_INPUT_VOLUME_DEFAULT);
1067
1068 return 0;
1069}
1070
1071static int
1072tas3004_uninit_mixer(struct tas3004_data_t *self)
1073{
1074 tas3004_set_mixer_level(self, SOUND_MIXER_VOLUME, 0);
1075 tas3004_set_mixer_level(self, SOUND_MIXER_PCM, 0);
1076 tas3004_set_mixer_level(self, SOUND_MIXER_ALTPCM, 0);
1077 tas3004_set_mixer_level(self, SOUND_MIXER_IMIX, 0);
1078
1079 tas3004_set_mixer_level(self, SOUND_MIXER_BASS, 0);
1080 tas3004_set_mixer_level(self, SOUND_MIXER_TREBLE, 0);
1081
1082 tas3004_set_mixer_level(self, SOUND_MIXER_LINE, 0);
1083
1084 return 0;
1085}
1086
1087static int
1088tas3004_init(struct i2c_client *client)
1089{
1090 struct tas3004_data_t *self;
1091 size_t sz = sizeof(*self) + (TAS3004_REG_MAX*sizeof(tas_shadow_t));
1092 char drce_init[] = { 0x69, 0x22, 0x9f, 0xb0, 0x60, 0xa0 };
1093 char mcr2 = 0;
1094 int i, j;
1095
1096 self = kmalloc(sz, GFP_KERNEL);
1097 if (!self)
1098 return -ENOMEM;
1099 memset(self, 0, sz);
1100
1101 self->super.client = client;
1102 self->super.shadow = (tas_shadow_t *)(self+1);
1103 self->output_id = TAS_OUTPUT_HEADPHONES;
1104
1105 dev_set_drvdata(&client->dev, self);
1106
1107 for (i = 0; i < TAS3004_BIQUAD_CHANNEL_COUNT; i++)
1108 for (j = 0; j<TAS3004_BIQUAD_FILTER_COUNT; j++)
1109 tas3004_write_biquad_shadow(self, i, j,
1110 &tas3004_eq_unity);
1111
1112 tas3004_write_register(self, TAS3004_REG_MCR2, &mcr2, WRITE_SHADOW);
1113 tas3004_write_register(self, TAS3004_REG_DRC, drce_init, WRITE_SHADOW);
1114
1115 INIT_WORK(&device_change, tas3004_device_change_handler, self);
1116 return 0;
1117}
1118
1119static void
1120tas3004_uninit(struct tas3004_data_t *self)
1121{
1122 tas3004_uninit_mixer(self);
1123 kfree(self);
1124}
1125
1126
1127struct tas_driver_hooks_t tas3004_hooks = {
1128 .init = (tas_hook_init_t)tas3004_init,
1129 .post_init = (tas_hook_post_init_t)tas3004_init_mixer,
1130 .uninit = (tas_hook_uninit_t)tas3004_uninit,
1131 .get_mixer_level = (tas_hook_get_mixer_level_t)tas3004_get_mixer_level,
1132 .set_mixer_level = (tas_hook_set_mixer_level_t)tas3004_set_mixer_level,
1133 .enter_sleep = (tas_hook_enter_sleep_t)tas3004_enter_sleep,
1134 .leave_sleep = (tas_hook_leave_sleep_t)tas3004_leave_sleep,
1135 .supported_mixers = (tas_hook_supported_mixers_t)tas3004_supported_mixers,
1136 .mixer_is_stereo = (tas_hook_mixer_is_stereo_t)tas3004_mixer_is_stereo,
1137 .stereo_mixers = (tas_hook_stereo_mixers_t)tas3004_stereo_mixers,
1138 .output_device_change = (tas_hook_output_device_change_t)tas3004_output_device_change,
1139 .device_ioctl = (tas_hook_device_ioctl_t)tas3004_device_ioctl
1140};
diff --git a/sound/oss/dmasound/tas3004.h b/sound/oss/dmasound/tas3004.h
new file mode 100644
index 000000000000..c6d584bf2ca4
--- /dev/null
+++ b/sound/oss/dmasound/tas3004.h
@@ -0,0 +1,77 @@
1/*
2 * Header file for the i2c/i2s based TA3004 sound chip used
3 * on some Apple hardware. Also known as "tumbler".
4 *
5 * This file is subject to the terms and conditions of the GNU General Public
6 * License. See the file COPYING in the main directory of this archive
7 * for more details.
8 *
9 * Written by Christopher C. Chimelis <chris@debian.org>
10 */
11
12#ifndef _TAS3004_H_
13#define _TAS3004_H_
14
15#include <linux/types.h>
16
17#include "tas_common.h"
18#include "tas_eq_prefs.h"
19
20/*
21 * Macros that correspond to the registers that we write to
22 * when setting the various values.
23 */
24
25#define TAS3004_VERSION "0.3"
26#define TAS3004_DATE "20011214"
27
28#define I2C_DRIVERNAME_TAS3004 "TAS3004 driver V " TAS3004_VERSION
29#define I2C_DRIVERID_TAS3004 (I2C_DRIVERID_TAS_BASE+1)
30
31extern struct tas_driver_hooks_t tas3004_hooks;
32extern struct tas_gain_t tas3004_gain;
33extern struct tas_eq_pref_t *tas3004_eq_prefs[];
34
35enum tas3004_reg_t {
36 TAS3004_REG_MCR = 0x01,
37 TAS3004_REG_DRC = 0x02,
38
39 TAS3004_REG_VOLUME = 0x04,
40 TAS3004_REG_TREBLE = 0x05,
41 TAS3004_REG_BASS = 0x06,
42 TAS3004_REG_LEFT_MIXER = 0x07,
43 TAS3004_REG_RIGHT_MIXER = 0x08,
44
45 TAS3004_REG_LEFT_BIQUAD0 = 0x0a,
46 TAS3004_REG_LEFT_BIQUAD1 = 0x0b,
47 TAS3004_REG_LEFT_BIQUAD2 = 0x0c,
48 TAS3004_REG_LEFT_BIQUAD3 = 0x0d,
49 TAS3004_REG_LEFT_BIQUAD4 = 0x0e,
50 TAS3004_REG_LEFT_BIQUAD5 = 0x0f,
51 TAS3004_REG_LEFT_BIQUAD6 = 0x10,
52
53 TAS3004_REG_RIGHT_BIQUAD0 = 0x13,
54 TAS3004_REG_RIGHT_BIQUAD1 = 0x14,
55 TAS3004_REG_RIGHT_BIQUAD2 = 0x15,
56 TAS3004_REG_RIGHT_BIQUAD3 = 0x16,
57 TAS3004_REG_RIGHT_BIQUAD4 = 0x17,
58 TAS3004_REG_RIGHT_BIQUAD5 = 0x18,
59 TAS3004_REG_RIGHT_BIQUAD6 = 0x19,
60
61 TAS3004_REG_LEFT_LOUD_BIQUAD = 0x21,
62 TAS3004_REG_RIGHT_LOUD_BIQUAD = 0x22,
63
64 TAS3004_REG_LEFT_LOUD_BIQUAD_GAIN = 0x23,
65 TAS3004_REG_RIGHT_LOUD_BIQUAD_GAIN = 0x24,
66
67 TAS3004_REG_TEST = 0x29,
68
69 TAS3004_REG_ANALOG_CTRL = 0x40,
70 TAS3004_REG_TEST1 = 0x41,
71 TAS3004_REG_TEST2 = 0x42,
72 TAS3004_REG_MCR2 = 0x43,
73
74 TAS3004_REG_MAX = 0x44
75};
76
77#endif /* _TAS3004_H_ */
diff --git a/sound/oss/dmasound/tas3004_tables.c b/sound/oss/dmasound/tas3004_tables.c
new file mode 100644
index 000000000000..b910e0a66775
--- /dev/null
+++ b/sound/oss/dmasound/tas3004_tables.c
@@ -0,0 +1,301 @@
1#include "tas3004.h"
2#include "tas_eq_prefs.h"
3
4static struct tas_drce_t eqp_17_1_0_drce={
5 .enable = 1,
6 .above = { .val = 3.0 * (1<<8), .expand = 0 },
7 .below = { .val = 1.0 * (1<<8), .expand = 0 },
8 .threshold = -19.12 * (1<<8),
9 .energy = 2.4 * (1<<12),
10 .attack = 0.013 * (1<<12),
11 .decay = 0.212 * (1<<12),
12};
13
14static struct tas_biquad_ctrl_t eqp_17_1_0_biquads[]={
15 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } },
16 { .channel = 0, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } },
17 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } },
18 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } },
19 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } },
20 { .channel = 0, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } },
21 { .channel = 0, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } },
22
23 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fd0d4, 0xe05e56, 0x0fd0d4, 0xe05ee1, 0x0fa234 } } },
24 { .channel = 1, .filter = 1, .data = { .coeff = { 0x0910d7, 0x088e1a, 0x030651, 0x01dcb1, 0x02c892 } } },
25 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ff895, 0xe0970b, 0x0f7f00, 0xe0970b, 0x0f7795 } } },
26 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fd1c4, 0xe1ac22, 0x0ec8cf, 0xe1ac22, 0x0e9a94 } } },
27 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f7c1c, 0xe3cc03, 0x0df786, 0xe3cc03, 0x0d73a2 } } },
28 { .channel = 1, .filter = 5, .data = { .coeff = { 0x11fb92, 0xf5a1a0, 0x073cd2, 0xf5a1a0, 0x093865 } } },
29 { .channel = 1, .filter = 6, .data = { .coeff = { 0x0e17a9, 0x068b6c, 0x08a0e5, 0x068b6c, 0x06b88e } } }
30};
31
32static struct tas_eq_pref_t eqp_17_1_0 = {
33 .sample_rate = 44100,
34 .device_id = 0x17,
35 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
36 .speaker_id = 0x00,
37
38 .drce = &eqp_17_1_0_drce,
39
40 .filter_count = 14,
41 .biquads = eqp_17_1_0_biquads
42};
43
44/* ======================================================================== */
45
46static struct tas_drce_t eqp_18_1_0_drce={
47 .enable = 1,
48 .above = { .val = 3.0 * (1<<8), .expand = 0 },
49 .below = { .val = 1.0 * (1<<8), .expand = 0 },
50 .threshold = -13.14 * (1<<8),
51 .energy = 2.4 * (1<<12),
52 .attack = 0.013 * (1<<12),
53 .decay = 0.212 * (1<<12),
54};
55
56static struct tas_biquad_ctrl_t eqp_18_1_0_biquads[]={
57 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } },
58 { .channel = 0, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } },
59 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } },
60 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } },
61 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } },
62 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } },
63 { .channel = 0, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } },
64
65 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f5514, 0xe155d7, 0x0f5514, 0xe15cfa, 0x0eb14b } } },
66 { .channel = 1, .filter = 1, .data = { .coeff = { 0x06ec33, 0x02abe3, 0x015eef, 0xf764d9, 0x03922d } } },
67 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0ef5f2, 0xe67d1f, 0x0bcf37, 0xe67d1f, 0x0ac529 } } },
68 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0db050, 0xe5be4d, 0x0d0c78, 0xe5be4d, 0x0abcc8 } } },
69 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0f1298, 0xe64ec6, 0x0cc03e, 0xe64ec6, 0x0bd2d7 } } },
70 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0c641a, 0x06537a, 0x08d155, 0x06537a, 0x053570 } } },
71 { .channel = 1, .filter = 6, .data = { .coeff = { 0x100000, 0x000000, 0x000000, 0x000000, 0x000000 } } }
72};
73
74static struct tas_eq_pref_t eqp_18_1_0 = {
75 .sample_rate = 44100,
76 .device_id = 0x18,
77 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
78 .speaker_id = 0x00,
79
80 .drce = &eqp_18_1_0_drce,
81
82 .filter_count = 14,
83 .biquads = eqp_18_1_0_biquads
84};
85
86/* ======================================================================== */
87
88static struct tas_drce_t eqp_1a_1_0_drce={
89 .enable = 1,
90 .above = { .val = 3.0 * (1<<8), .expand = 0 },
91 .below = { .val = 1.0 * (1<<8), .expand = 0 },
92 .threshold = -10.75 * (1<<8),
93 .energy = 2.4 * (1<<12),
94 .attack = 0.013 * (1<<12),
95 .decay = 0.212 * (1<<12),
96};
97
98static struct tas_biquad_ctrl_t eqp_1a_1_0_biquads[]={
99 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } },
100 { .channel = 0, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } },
101 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } },
102 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } },
103 { .channel = 0, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } },
104 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } },
105 { .channel = 0, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } },
106
107 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0fb8fd, 0xe08e04, 0x0fb8fd, 0xe08f40, 0x0f7336 } } },
108 { .channel = 1, .filter = 1, .data = { .coeff = { 0x06371d, 0x0c6e3a, 0x06371d, 0x05bfd3, 0x031ca2 } } },
109 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0fa1c0, 0xe18692, 0x0f030e, 0xe18692, 0x0ea4ce } } },
110 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0fe495, 0xe17eff, 0x0f0452, 0xe17eff, 0x0ee8e7 } } },
111 { .channel = 1, .filter = 4, .data = { .coeff = { 0x100857, 0xe7e71c, 0x0e9599, 0xe7e71c, 0x0e9df1 } } },
112 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0fb26e, 0x06a82c, 0x0db2b4, 0x06a82c, 0x0d6522 } } },
113 { .channel = 1, .filter = 6, .data = { .coeff = { 0x11419d, 0xf06cbf, 0x0a4f6e, 0xf06cbf, 0x0b910c } } }
114};
115
116static struct tas_eq_pref_t eqp_1a_1_0 = {
117 .sample_rate = 44100,
118 .device_id = 0x1a,
119 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
120 .speaker_id = 0x00,
121
122 .drce = &eqp_1a_1_0_drce,
123
124 .filter_count = 14,
125 .biquads = eqp_1a_1_0_biquads
126};
127
128/* ======================================================================== */
129
130static struct tas_drce_t eqp_1c_1_0_drce={
131 .enable = 1,
132 .above = { .val = 3.0 * (1<<8), .expand = 0 },
133 .below = { .val = 1.0 * (1<<8), .expand = 0 },
134 .threshold = -14.34 * (1<<8),
135 .energy = 2.4 * (1<<12),
136 .attack = 0.013 * (1<<12),
137 .decay = 0.212 * (1<<12),
138};
139
140static struct tas_biquad_ctrl_t eqp_1c_1_0_biquads[]={
141 { .channel = 0, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } },
142 { .channel = 0, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } },
143 { .channel = 0, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } },
144 { .channel = 0, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } },
145 { .channel = 0, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } },
146 { .channel = 0, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } },
147 { .channel = 0, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } },
148
149 { .channel = 1, .filter = 0, .data = { .coeff = { 0x0f4f95, 0xe160d4, 0x0f4f95, 0xe1686e, 0x0ea6c5 } } },
150 { .channel = 1, .filter = 1, .data = { .coeff = { 0x066b92, 0x0290d4, 0x0148a0, 0xf6853f, 0x03bfc7 } } },
151 { .channel = 1, .filter = 2, .data = { .coeff = { 0x0f57dc, 0xe51c91, 0x0dd1cb, 0xe51c91, 0x0d29a8 } } },
152 { .channel = 1, .filter = 3, .data = { .coeff = { 0x0df1cb, 0xe4fa84, 0x0d7cdc, 0xe4fa84, 0x0b6ea7 } } },
153 { .channel = 1, .filter = 4, .data = { .coeff = { 0x0eba36, 0xe6aa48, 0x0b9f52, 0xe6aa48, 0x0a5989 } } },
154 { .channel = 1, .filter = 5, .data = { .coeff = { 0x0caf02, 0x05ef9d, 0x084beb, 0x05ef9d, 0x04faee } } },
155 { .channel = 1, .filter = 6, .data = { .coeff = { 0x0fc686, 0xe22947, 0x0e4b5d, 0xe22947, 0x0e11e4 } } }
156};
157
158static struct tas_eq_pref_t eqp_1c_1_0 = {
159 .sample_rate = 44100,
160 .device_id = 0x1c,
161 .output_id = TAS_OUTPUT_INTERNAL_SPKR,
162 .speaker_id = 0x00,
163
164 .drce = &eqp_1c_1_0_drce,
165
166 .filter_count = 14,
167 .biquads = eqp_1c_1_0_biquads
168};
169
170/* ======================================================================== */
171
172static uint tas3004_master_tab[]={
173 0x0, 0x75, 0x9c, 0xbb,
174 0xdb, 0xfb, 0x11e, 0x143,
175 0x16b, 0x196, 0x1c3, 0x1f5,
176 0x229, 0x263, 0x29f, 0x2e1,
177 0x328, 0x373, 0x3c5, 0x41b,
178 0x478, 0x4dc, 0x547, 0x5b8,
179 0x633, 0x6b5, 0x740, 0x7d5,
180 0x873, 0x91c, 0x9d2, 0xa92,
181 0xb5e, 0xc39, 0xd22, 0xe19,
182 0xf20, 0x1037, 0x1161, 0x129e,
183 0x13ed, 0x1551, 0x16ca, 0x185d,
184 0x1a08, 0x1bcc, 0x1dac, 0x1fa7,
185 0x21c1, 0x23fa, 0x2655, 0x28d6,
186 0x2b7c, 0x2e4a, 0x3141, 0x3464,
187 0x37b4, 0x3b35, 0x3ee9, 0x42d3,
188 0x46f6, 0x4b53, 0x4ff0, 0x54ce,
189 0x59f2, 0x5f5f, 0x6519, 0x6b24,
190 0x7183, 0x783c, 0x7f53, 0x86cc,
191 0x8ead, 0x96fa, 0x9fba, 0xa8f2,
192 0xb2a7, 0xbce1, 0xc7a5, 0xd2fa,
193 0xdee8, 0xeb75, 0xf8aa, 0x1068e,
194 0x1152a, 0x12487, 0x134ad, 0x145a5,
195 0x1577b, 0x16a37, 0x17df5, 0x192bd,
196 0x1a890, 0x1bf7b, 0x1d78d, 0x1f0d1,
197 0x20b55, 0x22727, 0x24456, 0x262f2,
198 0x2830b
199};
200
201static uint tas3004_mixer_tab[]={
202 0x0, 0x748, 0x9be, 0xbaf,
203 0xda4, 0xfb1, 0x11de, 0x1431,
204 0x16ad, 0x1959, 0x1c37, 0x1f4b,
205 0x2298, 0x2628, 0x29fb, 0x2e12,
206 0x327d, 0x3734, 0x3c47, 0x41b4,
207 0x4787, 0x4dbe, 0x546d, 0x5b86,
208 0x632e, 0x6b52, 0x7400, 0x7d54,
209 0x873b, 0x91c6, 0x9d1a, 0xa920,
210 0xb5e5, 0xc38c, 0xd21b, 0xe18f,
211 0xf1f5, 0x1036a, 0x1160f, 0x129d6,
212 0x13ed0, 0x1550c, 0x16ca0, 0x185c9,
213 0x1a07b, 0x1bcc3, 0x1dab9, 0x1fa75,
214 0x21c0f, 0x23fa3, 0x26552, 0x28d64,
215 0x2b7c9, 0x2e4a2, 0x31411, 0x3463b,
216 0x37b44, 0x3b353, 0x3ee94, 0x42d30,
217 0x46f55, 0x4b533, 0x4fefc, 0x54ce5,
218 0x59f25, 0x5f5f6, 0x65193, 0x6b23c,
219 0x71835, 0x783c3, 0x7f52c, 0x86cc0,
220 0x8eacc, 0x96fa5, 0x9fba0, 0xa8f1a,
221 0xb2a71, 0xbce0a, 0xc7a4a, 0xd2fa0,
222 0xdee7b, 0xeb752, 0xf8a9f, 0x1068e4,
223 0x1152a3, 0x12486a, 0x134ac8, 0x145a55,
224 0x1577ac, 0x16a370, 0x17df51, 0x192bc2,
225 0x1a88f8, 0x1bf7b7, 0x1d78c9, 0x1f0d04,
226 0x20b542, 0x227268, 0x244564, 0x262f26,
227 0x2830af
228};
229
230static uint tas3004_treble_tab[]={
231 0x96, 0x95, 0x95, 0x94,
232 0x93, 0x92, 0x92, 0x91,
233 0x90, 0x90, 0x8f, 0x8e,
234 0x8d, 0x8d, 0x8c, 0x8b,
235 0x8a, 0x8a, 0x89, 0x88,
236 0x88, 0x87, 0x86, 0x85,
237 0x85, 0x84, 0x83, 0x83,
238 0x82, 0x81, 0x80, 0x80,
239 0x7f, 0x7e, 0x7e, 0x7d,
240 0x7c, 0x7b, 0x7b, 0x7a,
241 0x79, 0x78, 0x78, 0x77,
242 0x76, 0x76, 0x75, 0x74,
243 0x73, 0x73, 0x72, 0x71,
244 0x71, 0x68, 0x45, 0x5b,
245 0x6d, 0x6c, 0x6b, 0x6a,
246 0x69, 0x68, 0x67, 0x66,
247 0x65, 0x63, 0x62, 0x62,
248 0x60, 0x5e, 0x5c, 0x5b,
249 0x59, 0x57, 0x55, 0x53,
250 0x52, 0x4f, 0x4d, 0x4a,
251 0x48, 0x46, 0x43, 0x40,
252 0x3d, 0x3a, 0x36, 0x33,
253 0x2f, 0x2c, 0x27, 0x23,
254 0x1f, 0x1a, 0x15, 0xf,
255 0x8, 0x5, 0x2, 0x1,
256 0x1
257};
258
259static uint tas3004_bass_tab[]={
260 0x96, 0x95, 0x95, 0x94,
261 0x93, 0x92, 0x92, 0x91,
262 0x90, 0x90, 0x8f, 0x8e,
263 0x8d, 0x8d, 0x8c, 0x8b,
264 0x8a, 0x8a, 0x89, 0x88,
265 0x88, 0x87, 0x86, 0x85,
266 0x85, 0x84, 0x83, 0x83,
267 0x82, 0x81, 0x80, 0x80,
268 0x7f, 0x7e, 0x7e, 0x7d,
269 0x7c, 0x7b, 0x7b, 0x7a,
270 0x79, 0x78, 0x78, 0x77,
271 0x76, 0x76, 0x75, 0x74,
272 0x73, 0x73, 0x72, 0x71,
273 0x70, 0x6f, 0x6e, 0x6d,
274 0x6c, 0x6b, 0x6a, 0x6a,
275 0x69, 0x67, 0x66, 0x66,
276 0x65, 0x63, 0x62, 0x62,
277 0x61, 0x60, 0x5e, 0x5d,
278 0x5b, 0x59, 0x57, 0x55,
279 0x53, 0x51, 0x4f, 0x4c,
280 0x4a, 0x48, 0x46, 0x44,
281 0x41, 0x3e, 0x3b, 0x38,
282 0x36, 0x33, 0x2f, 0x2b,
283 0x28, 0x24, 0x20, 0x1c,
284 0x17, 0x12, 0xd, 0x7,
285 0x1
286};
287
288struct tas_gain_t tas3004_gain={
289 .master = tas3004_master_tab,
290 .treble = tas3004_treble_tab,
291 .bass = tas3004_bass_tab,
292 .mixer = tas3004_mixer_tab
293};
294
295struct tas_eq_pref_t *tas3004_eq_prefs[]={
296 &eqp_17_1_0,
297 &eqp_18_1_0,
298 &eqp_1a_1_0,
299 &eqp_1c_1_0,
300 NULL
301};
diff --git a/sound/oss/dmasound/tas_common.c b/sound/oss/dmasound/tas_common.c
new file mode 100644
index 000000000000..d36a1fe2fcf3
--- /dev/null
+++ b/sound/oss/dmasound/tas_common.c
@@ -0,0 +1,214 @@
1#include <linux/module.h>
2#include <linux/slab.h>
3#include <linux/proc_fs.h>
4#include <linux/ioport.h>
5#include <linux/sysctl.h>
6#include <linux/types.h>
7#include <linux/i2c.h>
8#include <linux/init.h>
9#include <linux/soundcard.h>
10#include <asm/uaccess.h>
11#include <asm/errno.h>
12#include <asm/io.h>
13#include <asm/prom.h>
14
15#include "tas_common.h"
16
17#define CALL0(proc) \
18 do { \
19 struct tas_data_t *self; \
20 if (!tas_client || driver_hooks == NULL) \
21 return -1; \
22 self = dev_get_drvdata(&tas_client->dev); \
23 if (driver_hooks->proc) \
24 return driver_hooks->proc(self); \
25 else \
26 return -EINVAL; \
27 } while (0)
28
29#define CALL(proc,arg...) \
30 do { \
31 struct tas_data_t *self; \
32 if (!tas_client || driver_hooks == NULL) \
33 return -1; \
34 self = dev_get_drvdata(&tas_client->dev); \
35 if (driver_hooks->proc) \
36 return driver_hooks->proc(self, ## arg); \
37 else \
38 return -EINVAL; \
39 } while (0)
40
41
42static u8 tas_i2c_address = 0x34;
43static struct i2c_client *tas_client;
44static struct device_node* tas_node;
45
46static int tas_attach_adapter(struct i2c_adapter *);
47static int tas_detach_client(struct i2c_client *);
48
49struct i2c_driver tas_driver = {
50 .owner = THIS_MODULE,
51 .name = "tas",
52 .flags = I2C_DF_NOTIFY,
53 .attach_adapter = tas_attach_adapter,
54 .detach_client = tas_detach_client,
55};
56
57struct tas_driver_hooks_t *driver_hooks;
58
59int
60tas_register_driver(struct tas_driver_hooks_t *hooks)
61{
62 driver_hooks = hooks;
63 return 0;
64}
65
66int
67tas_get_mixer_level(int mixer, uint *level)
68{
69 CALL(get_mixer_level,mixer,level);
70}
71
72int
73tas_set_mixer_level(int mixer,uint level)
74{
75 CALL(set_mixer_level,mixer,level);
76}
77
78int
79tas_enter_sleep(void)
80{
81 CALL0(enter_sleep);
82}
83
84int
85tas_leave_sleep(void)
86{
87 CALL0(leave_sleep);
88}
89
90int
91tas_supported_mixers(void)
92{
93 CALL0(supported_mixers);
94}
95
96int
97tas_mixer_is_stereo(int mixer)
98{
99 CALL(mixer_is_stereo,mixer);
100}
101
102int
103tas_stereo_mixers(void)
104{
105 CALL0(stereo_mixers);
106}
107
108int
109tas_output_device_change(int device_id,int layout_id,int speaker_id)
110{
111 CALL(output_device_change,device_id,layout_id,speaker_id);
112}
113
114int
115tas_device_ioctl(u_int cmd, u_long arg)
116{
117 CALL(device_ioctl,cmd,arg);
118}
119
120int
121tas_post_init(void)
122{
123 CALL0(post_init);
124}
125
126static int
127tas_detect_client(struct i2c_adapter *adapter, int address)
128{
129 static const char *client_name = "tas Digital Equalizer";
130 struct i2c_client *new_client;
131 int rc = -ENODEV;
132
133 if (!driver_hooks) {
134 printk(KERN_ERR "tas_detect_client called with no hooks !\n");
135 return -ENODEV;
136 }
137
138 new_client = kmalloc(sizeof(*new_client), GFP_KERNEL);
139 if (!new_client)
140 return -ENOMEM;
141 memset(new_client, 0, sizeof(*new_client));
142
143 new_client->addr = address;
144 new_client->adapter = adapter;
145 new_client->driver = &tas_driver;
146 strlcpy(new_client->name, client_name, DEVICE_NAME_SIZE);
147
148 if (driver_hooks->init(new_client))
149 goto bail;
150
151 /* Tell the i2c layer a new client has arrived */
152 if (i2c_attach_client(new_client)) {
153 driver_hooks->uninit(dev_get_drvdata(&new_client->dev));
154 goto bail;
155 }
156
157 tas_client = new_client;
158 return 0;
159 bail:
160 tas_client = NULL;
161 kfree(new_client);
162 return rc;
163}
164
165static int
166tas_attach_adapter(struct i2c_adapter *adapter)
167{
168 if (!strncmp(adapter->name, "mac-io", 6))
169 return tas_detect_client(adapter, tas_i2c_address);
170 return 0;
171}
172
173static int
174tas_detach_client(struct i2c_client *client)
175{
176 if (client == tas_client) {
177 driver_hooks->uninit(dev_get_drvdata(&client->dev));
178
179 i2c_detach_client(client);
180 kfree(client);
181 }
182 return 0;
183}
184
185void
186tas_cleanup(void)
187{
188 i2c_del_driver(&tas_driver);
189}
190
191int __init
192tas_init(int driver_id, const char *driver_name)
193{
194 u32* paddr;
195
196 printk(KERN_INFO "tas driver [%s])\n", driver_name);
197
198#ifndef CONFIG_I2C_KEYWEST
199 request_module("i2c-keywest");
200#endif
201 tas_node = find_devices("deq");
202 if (tas_node == NULL)
203 return -ENODEV;
204 paddr = (u32 *)get_property(tas_node, "i2c-address", NULL);
205 if (paddr) {
206 tas_i2c_address = (*paddr) >> 1;
207 printk(KERN_INFO "using i2c address: 0x%x from device-tree\n",
208 tas_i2c_address);
209 } else
210 printk(KERN_INFO "using i2c address: 0x%x (default)\n",
211 tas_i2c_address);
212
213 return i2c_add_driver(&tas_driver);
214}
diff --git a/sound/oss/dmasound/tas_common.h b/sound/oss/dmasound/tas_common.h
new file mode 100644
index 000000000000..3a6d48666db0
--- /dev/null
+++ b/sound/oss/dmasound/tas_common.h
@@ -0,0 +1,284 @@
1#ifndef _TAS_COMMON_H_
2#define _TAS_COMMON_H_
3
4#include <linux/i2c.h>
5#include <linux/soundcard.h>
6#include <asm/string.h>
7
8#define I2C_DRIVERID_TAS_BASE (0xFEBA)
9
10#define SET_4_20(shadow, offset, val) \
11 do { \
12 (shadow)[(offset)+0] = ((val) >> 16) & 0xff; \
13 (shadow)[(offset)+1] = ((val) >> 8) & 0xff; \
14 (shadow)[(offset)+2] = ((val) >> 0) & 0xff; \
15 } while (0)
16
17#define GET_4_20(shadow, offset) \
18 (((u_int)((shadow)[(offset)+0]) << 16) | \
19 ((u_int)((shadow)[(offset)+1]) << 8) | \
20 ((u_int)((shadow)[(offset)+2]) << 0))
21
22
23#define TAS_BIQUAD_FAST_LOAD 0x01
24
25#define TAS_DRCE_ENABLE 0x01
26#define TAS_DRCE_ABOVE_RATIO 0x02
27#define TAS_DRCE_BELOW_RATIO 0x04
28#define TAS_DRCE_THRESHOLD 0x08
29#define TAS_DRCE_ENERGY 0x10
30#define TAS_DRCE_ATTACK 0x20
31#define TAS_DRCE_DECAY 0x40
32
33#define TAS_DRCE_ALL 0x7f
34
35
36#define TAS_OUTPUT_HEADPHONES 0x00
37#define TAS_OUTPUT_INTERNAL_SPKR 0x01
38#define TAS_OUTPUT_EXTERNAL_SPKR 0x02
39
40
41union tas_biquad_t {
42 struct {
43 int b0,b1,b2,a1,a2;
44 } coeff;
45 int buf[5];
46};
47
48struct tas_biquad_ctrl_t {
49 u_int channel:4;
50 u_int filter:4;
51
52 union tas_biquad_t data;
53};
54
55struct tas_biquad_ctrl_list_t {
56 int flags;
57 int filter_count;
58 struct tas_biquad_ctrl_t biquads[0];
59};
60
61struct tas_ratio_t {
62 unsigned short val; /* 8.8 */
63 unsigned short expand; /* 0 = compress, !0 = expand. */
64};
65
66struct tas_drce_t {
67 unsigned short enable;
68 struct tas_ratio_t above;
69 struct tas_ratio_t below;
70 short threshold; /* dB, 8.8 signed */
71 unsigned short energy; /* seconds, 4.12 unsigned */
72 unsigned short attack; /* seconds, 4.12 unsigned */
73 unsigned short decay; /* seconds, 4.12 unsigned */
74};
75
76struct tas_drce_ctrl_t {
77 uint flags;
78
79 struct tas_drce_t data;
80};
81
82struct tas_gain_t
83{
84 unsigned int *master;
85 unsigned int *treble;
86 unsigned int *bass;
87 unsigned int *mixer;
88};
89
90typedef char tas_shadow_t[0x45];
91
92struct tas_data_t
93{
94 struct i2c_client *client;
95 tas_shadow_t *shadow;
96 uint mixer[SOUND_MIXER_NRDEVICES];
97};
98
99typedef int (*tas_hook_init_t)(struct i2c_client *);
100typedef int (*tas_hook_post_init_t)(struct tas_data_t *);
101typedef void (*tas_hook_uninit_t)(struct tas_data_t *);
102
103typedef int (*tas_hook_get_mixer_level_t)(struct tas_data_t *,int,uint *);
104typedef int (*tas_hook_set_mixer_level_t)(struct tas_data_t *,int,uint);
105
106typedef int (*tas_hook_enter_sleep_t)(struct tas_data_t *);
107typedef int (*tas_hook_leave_sleep_t)(struct tas_data_t *);
108
109typedef int (*tas_hook_supported_mixers_t)(struct tas_data_t *);
110typedef int (*tas_hook_mixer_is_stereo_t)(struct tas_data_t *,int);
111typedef int (*tas_hook_stereo_mixers_t)(struct tas_data_t *);
112
113typedef int (*tas_hook_output_device_change_t)(struct tas_data_t *,int,int,int);
114typedef int (*tas_hook_device_ioctl_t)(struct tas_data_t *,u_int,u_long);
115
116struct tas_driver_hooks_t {
117 /*
118 * All hardware initialisation must be performed in
119 * post_init(), as tas_dmasound_init() does a hardware reset.
120 *
121 * init() is called before tas_dmasound_init() so that
122 * ouput_device_change() is always called after i2c driver
123 * initialisation. The implication is that
124 * output_device_change() must cope with the fact that it
125 * may be called before post_init().
126 */
127
128 tas_hook_init_t init;
129 tas_hook_post_init_t post_init;
130 tas_hook_uninit_t uninit;
131
132 tas_hook_get_mixer_level_t get_mixer_level;
133 tas_hook_set_mixer_level_t set_mixer_level;
134
135 tas_hook_enter_sleep_t enter_sleep;
136 tas_hook_leave_sleep_t leave_sleep;
137
138 tas_hook_supported_mixers_t supported_mixers;
139 tas_hook_mixer_is_stereo_t mixer_is_stereo;
140 tas_hook_stereo_mixers_t stereo_mixers;
141
142 tas_hook_output_device_change_t output_device_change;
143 tas_hook_device_ioctl_t device_ioctl;
144};
145
146enum tas_write_mode_t {
147 WRITE_HW = 0x01,
148 WRITE_SHADOW = 0x02,
149 WRITE_NORMAL = 0x03,
150 FORCE_WRITE = 0x04
151};
152
153static inline uint
154tas_mono_to_stereo(uint mono)
155{
156 mono &=0xff;
157 return mono | (mono<<8);
158}
159
160/*
161 * Todo: make these functions a bit more efficient !
162 */
163static inline int
164tas_write_register( struct tas_data_t *self,
165 uint reg_num,
166 uint reg_width,
167 char *data,
168 uint write_mode)
169{
170 int rc;
171
172 if (reg_width==0 || data==NULL || self==NULL)
173 return -EINVAL;
174 if (!(write_mode & FORCE_WRITE) &&
175 !memcmp(data,self->shadow[reg_num],reg_width))
176 return 0;
177
178 if (write_mode & WRITE_SHADOW)
179 memcpy(self->shadow[reg_num],data,reg_width);
180 if (write_mode & WRITE_HW) {
181 rc=i2c_smbus_write_block_data(self->client,
182 reg_num,
183 reg_width,
184 data);
185 if (rc < 0) {
186 printk("tas: I2C block write failed \n");
187 return rc;
188 }
189 }
190 return 0;
191}
192
193static inline int
194tas_sync_register( struct tas_data_t *self,
195 uint reg_num,
196 uint reg_width)
197{
198 int rc;
199
200 if (reg_width==0 || self==NULL)
201 return -EINVAL;
202 rc=i2c_smbus_write_block_data(self->client,
203 reg_num,
204 reg_width,
205 self->shadow[reg_num]);
206 if (rc < 0) {
207 printk("tas: I2C block write failed \n");
208 return rc;
209 }
210 return 0;
211}
212
213static inline int
214tas_write_byte_register( struct tas_data_t *self,
215 uint reg_num,
216 char data,
217 uint write_mode)
218{
219 if (self==NULL)
220 return -1;
221 if (!(write_mode & FORCE_WRITE) && data != self->shadow[reg_num][0])
222 return 0;
223 if (write_mode & WRITE_SHADOW)
224 self->shadow[reg_num][0]=data;
225 if (write_mode & WRITE_HW) {
226 if (i2c_smbus_write_byte_data(self->client, reg_num, data) < 0) {
227 printk("tas: I2C byte write failed \n");
228 return -1;
229 }
230 }
231 return 0;
232}
233
234static inline int
235tas_sync_byte_register( struct tas_data_t *self,
236 uint reg_num,
237 uint reg_width)
238{
239 if (reg_width==0 || self==NULL)
240 return -1;
241 if (i2c_smbus_write_byte_data(
242 self->client, reg_num, self->shadow[reg_num][0]) < 0) {
243 printk("tas: I2C byte write failed \n");
244 return -1;
245 }
246 return 0;
247}
248
249static inline int
250tas_read_register( struct tas_data_t *self,
251 uint reg_num,
252 uint reg_width,
253 char *data)
254{
255 if (reg_width==0 || data==NULL || self==NULL)
256 return -1;
257 memcpy(data,self->shadow[reg_num],reg_width);
258 return 0;
259}
260
261extern int tas_register_driver(struct tas_driver_hooks_t *hooks);
262
263extern int tas_get_mixer_level(int mixer,uint *level);
264extern int tas_set_mixer_level(int mixer,uint level);
265extern int tas_enter_sleep(void);
266extern int tas_leave_sleep(void);
267extern int tas_supported_mixers(void);
268extern int tas_mixer_is_stereo(int mixer);
269extern int tas_stereo_mixers(void);
270extern int tas_output_device_change(int,int,int);
271extern int tas_device_ioctl(u_int, u_long);
272
273extern void tas_cleanup(void);
274extern int tas_init(int driver_id,const char *driver_name);
275extern int tas_post_init(void);
276
277#endif /* _TAS_COMMON_H_ */
278/*
279 * Local Variables:
280 * tab-width: 8
281 * indent-tabs-mode: t
282 * c-basic-offset: 8
283 * End:
284 */
diff --git a/sound/oss/dmasound/tas_eq_prefs.h b/sound/oss/dmasound/tas_eq_prefs.h
new file mode 100644
index 000000000000..3a994eda6abc
--- /dev/null
+++ b/sound/oss/dmasound/tas_eq_prefs.h
@@ -0,0 +1,24 @@
1#ifndef _TAS_EQ_PREFS_H_
2#define _TAS_EQ_PREFS_H_
3
4struct tas_eq_pref_t {
5 u_int sample_rate;
6 u_int device_id;
7 u_int output_id;
8 u_int speaker_id;
9
10 struct tas_drce_t *drce;
11
12 u_int filter_count;
13 struct tas_biquad_ctrl_t *biquads;
14};
15
16#endif /* _TAS_EQ_PREFS_H_ */
17
18/*
19 * Local Variables:
20 * tab-width: 8
21 * indent-tabs-mode: t
22 * c-basic-offset: 8
23 * End:
24 */
diff --git a/sound/oss/dmasound/tas_ioctl.h b/sound/oss/dmasound/tas_ioctl.h
new file mode 100644
index 000000000000..dccae3a40e01
--- /dev/null
+++ b/sound/oss/dmasound/tas_ioctl.h
@@ -0,0 +1,24 @@
1#ifndef _TAS_IOCTL_H_
2#define _TAS_IOCTL_H_
3
4#include <linux/i2c.h>
5#include <linux/soundcard.h>
6
7
8#define TAS_READ_EQ _SIOR('t',0,struct tas_biquad_ctrl_t)
9#define TAS_WRITE_EQ _SIOW('t',0,struct tas_biquad_ctrl_t)
10
11#define TAS_READ_EQ_LIST _SIOR('t',1,struct tas_biquad_ctrl_t)
12#define TAS_WRITE_EQ_LIST _SIOW('t',1,struct tas_biquad_ctrl_t)
13
14#define TAS_READ_EQ_FILTER_COUNT _SIOR('t',2,int)
15#define TAS_READ_EQ_CHANNEL_COUNT _SIOR('t',3,int)
16
17#define TAS_READ_DRCE _SIOR('t',4,struct tas_drce_ctrl_t)
18#define TAS_WRITE_DRCE _SIOW('t',4,struct tas_drce_ctrl_t)
19
20#define TAS_READ_DRCE_CAPS _SIOR('t',5,int)
21#define TAS_READ_DRCE_MIN _SIOR('t',6,int)
22#define TAS_READ_DRCE_MAX _SIOR('t',7,int)
23
24#endif
diff --git a/sound/oss/dmasound/trans_16.c b/sound/oss/dmasound/trans_16.c
new file mode 100644
index 000000000000..23562e947806
--- /dev/null
+++ b/sound/oss/dmasound/trans_16.c
@@ -0,0 +1,897 @@
1/*
2 * linux/sound/oss/dmasound/trans_16.c
3 *
4 * 16 bit translation routines. Only used by Power mac at present.
5 *
6 * See linux/sound/oss/dmasound/dmasound_core.c for copyright and
7 * history prior to 08/02/2001.
8 *
9 * 08/02/2001 Iain Sandoe
10 * split from dmasound_awacs.c
11 * 11/29/2003 Renzo Davoli (King Enzo)
12 * - input resampling (for soft rate < hard rate)
13 * - software line in gain control
14 */
15
16#include <linux/soundcard.h>
17#include <asm/uaccess.h>
18#include "dmasound.h"
19
20static short dmasound_alaw2dma16[] ;
21static short dmasound_ulaw2dma16[] ;
22
23static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount,
24 u_char frame[], ssize_t *frameUsed,
25 ssize_t frameLeft);
26static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount,
27 u_char frame[], ssize_t *frameUsed,
28 ssize_t frameLeft);
29static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount,
30 u_char frame[], ssize_t *frameUsed,
31 ssize_t frameLeft);
32static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount,
33 u_char frame[], ssize_t *frameUsed,
34 ssize_t frameLeft);
35static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount,
36 u_char frame[], ssize_t *frameUsed,
37 ssize_t frameLeft);
38
39static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount,
40 u_char frame[], ssize_t *frameUsed,
41 ssize_t frameLeft);
42static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount,
43 u_char frame[], ssize_t *frameUsed,
44 ssize_t frameLeft);
45static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount,
46 u_char frame[], ssize_t *frameUsed,
47 ssize_t frameLeft);
48static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount,
49 u_char frame[], ssize_t *frameUsed,
50 ssize_t frameLeft);
51static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount,
52 u_char frame[], ssize_t *frameUsed,
53 ssize_t frameLeft);
54
55static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount,
56 u_char frame[], ssize_t *frameUsed,
57 ssize_t frameLeft);
58static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount,
59 u_char frame[], ssize_t *frameUsed,
60 ssize_t frameLeft);
61
62/*** Translations ************************************************************/
63
64static int expand_data; /* Data for expanding */
65
66static ssize_t pmac_ct_law(const u_char __user *userPtr, size_t userCount,
67 u_char frame[], ssize_t *frameUsed,
68 ssize_t frameLeft)
69{
70 short *table = dmasound.soft.format == AFMT_MU_LAW
71 ? dmasound_ulaw2dma16 : dmasound_alaw2dma16;
72 ssize_t count, used;
73 short *p = (short *) &frame[*frameUsed];
74 int val, stereo = dmasound.soft.stereo;
75
76 frameLeft >>= 2;
77 if (stereo)
78 userCount >>= 1;
79 used = count = min_t(unsigned long, userCount, frameLeft);
80 while (count > 0) {
81 u_char data;
82 if (get_user(data, userPtr++))
83 return -EFAULT;
84 val = table[data];
85 *p++ = val;
86 if (stereo) {
87 if (get_user(data, userPtr++))
88 return -EFAULT;
89 val = table[data];
90 }
91 *p++ = val;
92 count--;
93 }
94 *frameUsed += used * 4;
95 return stereo? used * 2: used;
96}
97
98
99static ssize_t pmac_ct_s8(const u_char __user *userPtr, size_t userCount,
100 u_char frame[], ssize_t *frameUsed,
101 ssize_t frameLeft)
102{
103 ssize_t count, used;
104 short *p = (short *) &frame[*frameUsed];
105 int val, stereo = dmasound.soft.stereo;
106
107 frameLeft >>= 2;
108 if (stereo)
109 userCount >>= 1;
110 used = count = min_t(unsigned long, userCount, frameLeft);
111 while (count > 0) {
112 u_char data;
113 if (get_user(data, userPtr++))
114 return -EFAULT;
115 val = data << 8;
116 *p++ = val;
117 if (stereo) {
118 if (get_user(data, userPtr++))
119 return -EFAULT;
120 val = data << 8;
121 }
122 *p++ = val;
123 count--;
124 }
125 *frameUsed += used * 4;
126 return stereo? used * 2: used;
127}
128
129
130static ssize_t pmac_ct_u8(const u_char __user *userPtr, size_t userCount,
131 u_char frame[], ssize_t *frameUsed,
132 ssize_t frameLeft)
133{
134 ssize_t count, used;
135 short *p = (short *) &frame[*frameUsed];
136 int val, stereo = dmasound.soft.stereo;
137
138 frameLeft >>= 2;
139 if (stereo)
140 userCount >>= 1;
141 used = count = min_t(unsigned long, userCount, frameLeft);
142 while (count > 0) {
143 u_char data;
144 if (get_user(data, userPtr++))
145 return -EFAULT;
146 val = (data ^ 0x80) << 8;
147 *p++ = val;
148 if (stereo) {
149 if (get_user(data, userPtr++))
150 return -EFAULT;
151 val = (data ^ 0x80) << 8;
152 }
153 *p++ = val;
154 count--;
155 }
156 *frameUsed += used * 4;
157 return stereo? used * 2: used;
158}
159
160
161static ssize_t pmac_ct_s16(const u_char __user *userPtr, size_t userCount,
162 u_char frame[], ssize_t *frameUsed,
163 ssize_t frameLeft)
164{
165 ssize_t count, used;
166 int stereo = dmasound.soft.stereo;
167 short *fp = (short *) &frame[*frameUsed];
168
169 frameLeft >>= 2;
170 userCount >>= (stereo? 2: 1);
171 used = count = min_t(unsigned long, userCount, frameLeft);
172 if (!stereo) {
173 short __user *up = (short __user *) userPtr;
174 while (count > 0) {
175 short data;
176 if (get_user(data, up++))
177 return -EFAULT;
178 *fp++ = data;
179 *fp++ = data;
180 count--;
181 }
182 } else {
183 if (copy_from_user(fp, userPtr, count * 4))
184 return -EFAULT;
185 }
186 *frameUsed += used * 4;
187 return stereo? used * 4: used * 2;
188}
189
190static ssize_t pmac_ct_u16(const u_char __user *userPtr, size_t userCount,
191 u_char frame[], ssize_t *frameUsed,
192 ssize_t frameLeft)
193{
194 ssize_t count, used;
195 int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
196 int stereo = dmasound.soft.stereo;
197 short *fp = (short *) &frame[*frameUsed];
198 short __user *up = (short __user *) userPtr;
199
200 frameLeft >>= 2;
201 userCount >>= (stereo? 2: 1);
202 used = count = min_t(unsigned long, userCount, frameLeft);
203 while (count > 0) {
204 short data;
205 if (get_user(data, up++))
206 return -EFAULT;
207 data ^= mask;
208 *fp++ = data;
209 if (stereo) {
210 if (get_user(data, up++))
211 return -EFAULT;
212 data ^= mask;
213 }
214 *fp++ = data;
215 count--;
216 }
217 *frameUsed += used * 4;
218 return stereo? used * 4: used * 2;
219}
220
221
222static ssize_t pmac_ctx_law(const u_char __user *userPtr, size_t userCount,
223 u_char frame[], ssize_t *frameUsed,
224 ssize_t frameLeft)
225{
226 unsigned short *table = (unsigned short *)
227 (dmasound.soft.format == AFMT_MU_LAW
228 ? dmasound_ulaw2dma16 : dmasound_alaw2dma16);
229 unsigned int data = expand_data;
230 unsigned int *p = (unsigned int *) &frame[*frameUsed];
231 int bal = expand_bal;
232 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
233 int utotal, ftotal;
234 int stereo = dmasound.soft.stereo;
235
236 frameLeft >>= 2;
237 if (stereo)
238 userCount >>= 1;
239 ftotal = frameLeft;
240 utotal = userCount;
241 while (frameLeft) {
242 u_char c;
243 if (bal < 0) {
244 if (userCount == 0)
245 break;
246 if (get_user(c, userPtr++))
247 return -EFAULT;
248 data = table[c];
249 if (stereo) {
250 if (get_user(c, userPtr++))
251 return -EFAULT;
252 data = (data << 16) + table[c];
253 } else
254 data = (data << 16) + data;
255 userCount--;
256 bal += hSpeed;
257 }
258 *p++ = data;
259 frameLeft--;
260 bal -= sSpeed;
261 }
262 expand_bal = bal;
263 expand_data = data;
264 *frameUsed += (ftotal - frameLeft) * 4;
265 utotal -= userCount;
266 return stereo? utotal * 2: utotal;
267}
268
269static ssize_t pmac_ctx_s8(const u_char __user *userPtr, size_t userCount,
270 u_char frame[], ssize_t *frameUsed,
271 ssize_t frameLeft)
272{
273 unsigned int *p = (unsigned int *) &frame[*frameUsed];
274 unsigned int data = expand_data;
275 int bal = expand_bal;
276 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
277 int stereo = dmasound.soft.stereo;
278 int utotal, ftotal;
279
280 frameLeft >>= 2;
281 if (stereo)
282 userCount >>= 1;
283 ftotal = frameLeft;
284 utotal = userCount;
285 while (frameLeft) {
286 u_char c;
287 if (bal < 0) {
288 if (userCount == 0)
289 break;
290 if (get_user(c, userPtr++))
291 return -EFAULT;
292 data = c << 8;
293 if (stereo) {
294 if (get_user(c, userPtr++))
295 return -EFAULT;
296 data = (data << 16) + (c << 8);
297 } else
298 data = (data << 16) + data;
299 userCount--;
300 bal += hSpeed;
301 }
302 *p++ = data;
303 frameLeft--;
304 bal -= sSpeed;
305 }
306 expand_bal = bal;
307 expand_data = data;
308 *frameUsed += (ftotal - frameLeft) * 4;
309 utotal -= userCount;
310 return stereo? utotal * 2: utotal;
311}
312
313
314static ssize_t pmac_ctx_u8(const u_char __user *userPtr, size_t userCount,
315 u_char frame[], ssize_t *frameUsed,
316 ssize_t frameLeft)
317{
318 unsigned int *p = (unsigned int *) &frame[*frameUsed];
319 unsigned int data = expand_data;
320 int bal = expand_bal;
321 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
322 int stereo = dmasound.soft.stereo;
323 int utotal, ftotal;
324
325 frameLeft >>= 2;
326 if (stereo)
327 userCount >>= 1;
328 ftotal = frameLeft;
329 utotal = userCount;
330 while (frameLeft) {
331 u_char c;
332 if (bal < 0) {
333 if (userCount == 0)
334 break;
335 if (get_user(c, userPtr++))
336 return -EFAULT;
337 data = (c ^ 0x80) << 8;
338 if (stereo) {
339 if (get_user(c, userPtr++))
340 return -EFAULT;
341 data = (data << 16) + ((c ^ 0x80) << 8);
342 } else
343 data = (data << 16) + data;
344 userCount--;
345 bal += hSpeed;
346 }
347 *p++ = data;
348 frameLeft--;
349 bal -= sSpeed;
350 }
351 expand_bal = bal;
352 expand_data = data;
353 *frameUsed += (ftotal - frameLeft) * 4;
354 utotal -= userCount;
355 return stereo? utotal * 2: utotal;
356}
357
358
359static ssize_t pmac_ctx_s16(const u_char __user *userPtr, size_t userCount,
360 u_char frame[], ssize_t *frameUsed,
361 ssize_t frameLeft)
362{
363 unsigned int *p = (unsigned int *) &frame[*frameUsed];
364 unsigned int data = expand_data;
365 unsigned short __user *up = (unsigned short __user *) userPtr;
366 int bal = expand_bal;
367 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
368 int stereo = dmasound.soft.stereo;
369 int utotal, ftotal;
370
371 frameLeft >>= 2;
372 userCount >>= (stereo? 2: 1);
373 ftotal = frameLeft;
374 utotal = userCount;
375 while (frameLeft) {
376 unsigned short c;
377 if (bal < 0) {
378 if (userCount == 0)
379 break;
380 if (get_user(data, up++))
381 return -EFAULT;
382 if (stereo) {
383 if (get_user(c, up++))
384 return -EFAULT;
385 data = (data << 16) + c;
386 } else
387 data = (data << 16) + data;
388 userCount--;
389 bal += hSpeed;
390 }
391 *p++ = data;
392 frameLeft--;
393 bal -= sSpeed;
394 }
395 expand_bal = bal;
396 expand_data = data;
397 *frameUsed += (ftotal - frameLeft) * 4;
398 utotal -= userCount;
399 return stereo? utotal * 4: utotal * 2;
400}
401
402
403static ssize_t pmac_ctx_u16(const u_char __user *userPtr, size_t userCount,
404 u_char frame[], ssize_t *frameUsed,
405 ssize_t frameLeft)
406{
407 int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
408 unsigned int *p = (unsigned int *) &frame[*frameUsed];
409 unsigned int data = expand_data;
410 unsigned short __user *up = (unsigned short __user *) userPtr;
411 int bal = expand_bal;
412 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
413 int stereo = dmasound.soft.stereo;
414 int utotal, ftotal;
415
416 frameLeft >>= 2;
417 userCount >>= (stereo? 2: 1);
418 ftotal = frameLeft;
419 utotal = userCount;
420 while (frameLeft) {
421 unsigned short c;
422 if (bal < 0) {
423 if (userCount == 0)
424 break;
425 if (get_user(data, up++))
426 return -EFAULT;
427 data ^= mask;
428 if (stereo) {
429 if (get_user(c, up++))
430 return -EFAULT;
431 data = (data << 16) + (c ^ mask);
432 } else
433 data = (data << 16) + data;
434 userCount--;
435 bal += hSpeed;
436 }
437 *p++ = data;
438 frameLeft--;
439 bal -= sSpeed;
440 }
441 expand_bal = bal;
442 expand_data = data;
443 *frameUsed += (ftotal - frameLeft) * 4;
444 utotal -= userCount;
445 return stereo? utotal * 4: utotal * 2;
446}
447
448/* data in routines... */
449
450static ssize_t pmac_ct_s8_read(const u_char __user *userPtr, size_t userCount,
451 u_char frame[], ssize_t *frameUsed,
452 ssize_t frameLeft)
453{
454 ssize_t count, used;
455 short *p = (short *) &frame[*frameUsed];
456 int val, stereo = dmasound.soft.stereo;
457
458 frameLeft >>= 2;
459 if (stereo)
460 userCount >>= 1;
461 used = count = min_t(unsigned long, userCount, frameLeft);
462 while (count > 0) {
463 u_char data;
464
465 val = *p++;
466 val = (val * software_input_volume) >> 7;
467 data = val >> 8;
468 if (put_user(data, (u_char __user *)userPtr++))
469 return -EFAULT;
470 if (stereo) {
471 val = *p;
472 val = (val * software_input_volume) >> 7;
473 data = val >> 8;
474 if (put_user(data, (u_char __user *)userPtr++))
475 return -EFAULT;
476 }
477 p++;
478 count--;
479 }
480 *frameUsed += used * 4;
481 return stereo? used * 2: used;
482}
483
484
485static ssize_t pmac_ct_u8_read(const u_char __user *userPtr, size_t userCount,
486 u_char frame[], ssize_t *frameUsed,
487 ssize_t frameLeft)
488{
489 ssize_t count, used;
490 short *p = (short *) &frame[*frameUsed];
491 int val, stereo = dmasound.soft.stereo;
492
493 frameLeft >>= 2;
494 if (stereo)
495 userCount >>= 1;
496 used = count = min_t(unsigned long, userCount, frameLeft);
497 while (count > 0) {
498 u_char data;
499
500 val = *p++;
501 val = (val * software_input_volume) >> 7;
502 data = (val >> 8) ^ 0x80;
503 if (put_user(data, (u_char __user *)userPtr++))
504 return -EFAULT;
505 if (stereo) {
506 val = *p;
507 val = (val * software_input_volume) >> 7;
508 data = (val >> 8) ^ 0x80;
509 if (put_user(data, (u_char __user *)userPtr++))
510 return -EFAULT;
511 }
512 p++;
513 count--;
514 }
515 *frameUsed += used * 4;
516 return stereo? used * 2: used;
517}
518
519static ssize_t pmac_ct_s16_read(const u_char __user *userPtr, size_t userCount,
520 u_char frame[], ssize_t *frameUsed,
521 ssize_t frameLeft)
522{
523 ssize_t count, used;
524 int stereo = dmasound.soft.stereo;
525 short *fp = (short *) &frame[*frameUsed];
526 short __user *up = (short __user *) userPtr;
527
528 frameLeft >>= 2;
529 userCount >>= (stereo? 2: 1);
530 used = count = min_t(unsigned long, userCount, frameLeft);
531 while (count > 0) {
532 short data;
533
534 data = *fp++;
535 data = (data * software_input_volume) >> 7;
536 if (put_user(data, up++))
537 return -EFAULT;
538 if (stereo) {
539 data = *fp;
540 data = (data * software_input_volume) >> 7;
541 if (put_user(data, up++))
542 return -EFAULT;
543 }
544 fp++;
545 count--;
546 }
547 *frameUsed += used * 4;
548 return stereo? used * 4: used * 2;
549}
550
551static ssize_t pmac_ct_u16_read(const u_char __user *userPtr, size_t userCount,
552 u_char frame[], ssize_t *frameUsed,
553 ssize_t frameLeft)
554{
555 ssize_t count, used;
556 int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
557 int stereo = dmasound.soft.stereo;
558 short *fp = (short *) &frame[*frameUsed];
559 short __user *up = (short __user *) userPtr;
560
561 frameLeft >>= 2;
562 userCount >>= (stereo? 2: 1);
563 used = count = min_t(unsigned long, userCount, frameLeft);
564 while (count > 0) {
565 int data;
566
567 data = *fp++;
568 data = (data * software_input_volume) >> 7;
569 data ^= mask;
570 if (put_user(data, up++))
571 return -EFAULT;
572 if (stereo) {
573 data = *fp;
574 data = (data * software_input_volume) >> 7;
575 data ^= mask;
576 if (put_user(data, up++))
577 return -EFAULT;
578 }
579 fp++;
580 count--;
581 }
582 *frameUsed += used * 4;
583 return stereo? used * 4: used * 2;
584}
585
586/* data in routines (reducing speed)... */
587
588static ssize_t pmac_ctx_s8_read(const u_char __user *userPtr, size_t userCount,
589 u_char frame[], ssize_t *frameUsed,
590 ssize_t frameLeft)
591{
592 short *p = (short *) &frame[*frameUsed];
593 int bal = expand_read_bal;
594 int vall,valr, stereo = dmasound.soft.stereo;
595 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
596 int utotal, ftotal;
597
598 frameLeft >>= 2;
599 if (stereo)
600 userCount >>= 1;
601 ftotal = frameLeft;
602 utotal = userCount;
603 while (frameLeft) {
604 u_char data;
605
606 if (bal<0 && userCount == 0)
607 break;
608 vall = *p++;
609 vall = (vall * software_input_volume) >> 7;
610 if (stereo) {
611 valr = *p;
612 valr = (valr * software_input_volume) >> 7;
613 }
614 p++;
615 if (bal < 0) {
616 data = vall >> 8;
617 if (put_user(data, (u_char __user *)userPtr++))
618 return -EFAULT;
619 if (stereo) {
620 data = valr >> 8;
621 if (put_user(data, (u_char __user *)userPtr++))
622 return -EFAULT;
623 }
624 userCount--;
625 bal += hSpeed;
626 }
627 frameLeft--;
628 bal -= sSpeed;
629 }
630 expand_read_bal=bal;
631 *frameUsed += (ftotal - frameLeft) * 4;
632 utotal -= userCount;
633 return stereo? utotal * 2: utotal;
634}
635
636
637static ssize_t pmac_ctx_u8_read(const u_char __user *userPtr, size_t userCount,
638 u_char frame[], ssize_t *frameUsed,
639 ssize_t frameLeft)
640{
641 short *p = (short *) &frame[*frameUsed];
642 int bal = expand_read_bal;
643 int vall,valr, stereo = dmasound.soft.stereo;
644 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
645 int utotal, ftotal;
646
647 frameLeft >>= 2;
648 if (stereo)
649 userCount >>= 1;
650 ftotal = frameLeft;
651 utotal = userCount;
652 while (frameLeft) {
653 u_char data;
654
655 if (bal<0 && userCount == 0)
656 break;
657
658 vall = *p++;
659 vall = (vall * software_input_volume) >> 7;
660 if (stereo) {
661 valr = *p;
662 valr = (valr * software_input_volume) >> 7;
663 }
664 p++;
665 if (bal < 0) {
666 data = (vall >> 8) ^ 0x80;
667 if (put_user(data, (u_char __user *)userPtr++))
668 return -EFAULT;
669 if (stereo) {
670 data = (valr >> 8) ^ 0x80;
671 if (put_user(data, (u_char __user *)userPtr++))
672 return -EFAULT;
673 }
674 userCount--;
675 bal += hSpeed;
676 }
677 frameLeft--;
678 bal -= sSpeed;
679 }
680 expand_read_bal=bal;
681 *frameUsed += (ftotal - frameLeft) * 4;
682 utotal -= userCount;
683 return stereo? utotal * 2: utotal;
684}
685
686static ssize_t pmac_ctx_s16_read(const u_char __user *userPtr, size_t userCount,
687 u_char frame[], ssize_t *frameUsed,
688 ssize_t frameLeft)
689{
690 int bal = expand_read_bal;
691 short *fp = (short *) &frame[*frameUsed];
692 short __user *up = (short __user *) userPtr;
693 int stereo = dmasound.soft.stereo;
694 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
695 int utotal, ftotal;
696
697 frameLeft >>= 2;
698 userCount >>= (stereo? 2: 1);
699 ftotal = frameLeft;
700 utotal = userCount;
701 while (frameLeft) {
702 int datal,datar;
703
704 if (bal<0 && userCount == 0)
705 break;
706
707 datal = *fp++;
708 datal = (datal * software_input_volume) >> 7;
709 if (stereo) {
710 datar = *fp;
711 datar = (datar * software_input_volume) >> 7;
712 }
713 fp++;
714 if (bal < 0) {
715 if (put_user(datal, up++))
716 return -EFAULT;
717 if (stereo) {
718 if (put_user(datar, up++))
719 return -EFAULT;
720 }
721 userCount--;
722 bal += hSpeed;
723 }
724 frameLeft--;
725 bal -= sSpeed;
726 }
727 expand_read_bal=bal;
728 *frameUsed += (ftotal - frameLeft) * 4;
729 utotal -= userCount;
730 return stereo? utotal * 4: utotal * 2;
731}
732
733static ssize_t pmac_ctx_u16_read(const u_char __user *userPtr, size_t userCount,
734 u_char frame[], ssize_t *frameUsed,
735 ssize_t frameLeft)
736{
737 int bal = expand_read_bal;
738 int mask = (dmasound.soft.format == AFMT_U16_LE? 0x0080: 0x8000);
739 short *fp = (short *) &frame[*frameUsed];
740 short __user *up = (short __user *) userPtr;
741 int stereo = dmasound.soft.stereo;
742 int hSpeed = dmasound.hard.speed, sSpeed = dmasound.soft.speed;
743 int utotal, ftotal;
744
745 frameLeft >>= 2;
746 userCount >>= (stereo? 2: 1);
747 ftotal = frameLeft;
748 utotal = userCount;
749 while (frameLeft) {
750 int datal,datar;
751
752 if (bal<0 && userCount == 0)
753 break;
754
755 datal = *fp++;
756 datal = (datal * software_input_volume) >> 7;
757 datal ^= mask;
758 if (stereo) {
759 datar = *fp;
760 datar = (datar * software_input_volume) >> 7;
761 datar ^= mask;
762 }
763 fp++;
764 if (bal < 0) {
765 if (put_user(datal, up++))
766 return -EFAULT;
767 if (stereo) {
768 if (put_user(datar, up++))
769 return -EFAULT;
770 }
771 userCount--;
772 bal += hSpeed;
773 }
774 frameLeft--;
775 bal -= sSpeed;
776 }
777 expand_read_bal=bal;
778 *frameUsed += (ftotal - frameLeft) * 4;
779 utotal -= userCount;
780 return stereo? utotal * 4: utotal * 2;
781}
782
783
784TRANS transAwacsNormal = {
785 .ct_ulaw= pmac_ct_law,
786 .ct_alaw= pmac_ct_law,
787 .ct_s8= pmac_ct_s8,
788 .ct_u8= pmac_ct_u8,
789 .ct_s16be= pmac_ct_s16,
790 .ct_u16be= pmac_ct_u16,
791 .ct_s16le= pmac_ct_s16,
792 .ct_u16le= pmac_ct_u16,
793};
794
795TRANS transAwacsExpand = {
796 .ct_ulaw= pmac_ctx_law,
797 .ct_alaw= pmac_ctx_law,
798 .ct_s8= pmac_ctx_s8,
799 .ct_u8= pmac_ctx_u8,
800 .ct_s16be= pmac_ctx_s16,
801 .ct_u16be= pmac_ctx_u16,
802 .ct_s16le= pmac_ctx_s16,
803 .ct_u16le= pmac_ctx_u16,
804};
805
806TRANS transAwacsNormalRead = {
807 .ct_s8= pmac_ct_s8_read,
808 .ct_u8= pmac_ct_u8_read,
809 .ct_s16be= pmac_ct_s16_read,
810 .ct_u16be= pmac_ct_u16_read,
811 .ct_s16le= pmac_ct_s16_read,
812 .ct_u16le= pmac_ct_u16_read,
813};
814
815TRANS transAwacsExpandRead = {
816 .ct_s8= pmac_ctx_s8_read,
817 .ct_u8= pmac_ctx_u8_read,
818 .ct_s16be= pmac_ctx_s16_read,
819 .ct_u16be= pmac_ctx_u16_read,
820 .ct_s16le= pmac_ctx_s16_read,
821 .ct_u16le= pmac_ctx_u16_read,
822};
823
824/* translation tables */
825/* 16 bit mu-law */
826
827static short dmasound_ulaw2dma16[] = {
828 -32124, -31100, -30076, -29052, -28028, -27004, -25980, -24956,
829 -23932, -22908, -21884, -20860, -19836, -18812, -17788, -16764,
830 -15996, -15484, -14972, -14460, -13948, -13436, -12924, -12412,
831 -11900, -11388, -10876, -10364, -9852, -9340, -8828, -8316,
832 -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140,
833 -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092,
834 -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004,
835 -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980,
836 -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436,
837 -1372, -1308, -1244, -1180, -1116, -1052, -988, -924,
838 -876, -844, -812, -780, -748, -716, -684, -652,
839 -620, -588, -556, -524, -492, -460, -428, -396,
840 -372, -356, -340, -324, -308, -292, -276, -260,
841 -244, -228, -212, -196, -180, -164, -148, -132,
842 -120, -112, -104, -96, -88, -80, -72, -64,
843 -56, -48, -40, -32, -24, -16, -8, 0,
844 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956,
845 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764,
846 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412,
847 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316,
848 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140,
849 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092,
850 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004,
851 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980,
852 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436,
853 1372, 1308, 1244, 1180, 1116, 1052, 988, 924,
854 876, 844, 812, 780, 748, 716, 684, 652,
855 620, 588, 556, 524, 492, 460, 428, 396,
856 372, 356, 340, 324, 308, 292, 276, 260,
857 244, 228, 212, 196, 180, 164, 148, 132,
858 120, 112, 104, 96, 88, 80, 72, 64,
859 56, 48, 40, 32, 24, 16, 8, 0,
860};
861
862/* 16 bit A-law */
863
864static short dmasound_alaw2dma16[] = {
865 -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736,
866 -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784,
867 -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368,
868 -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392,
869 -22016, -20992, -24064, -23040, -17920, -16896, -19968, -18944,
870 -30208, -29184, -32256, -31232, -26112, -25088, -28160, -27136,
871 -11008, -10496, -12032, -11520, -8960, -8448, -9984, -9472,
872 -15104, -14592, -16128, -15616, -13056, -12544, -14080, -13568,
873 -344, -328, -376, -360, -280, -264, -312, -296,
874 -472, -456, -504, -488, -408, -392, -440, -424,
875 -88, -72, -120, -104, -24, -8, -56, -40,
876 -216, -200, -248, -232, -152, -136, -184, -168,
877 -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184,
878 -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696,
879 -688, -656, -752, -720, -560, -528, -624, -592,
880 -944, -912, -1008, -976, -816, -784, -880, -848,
881 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736,
882 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784,
883 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368,
884 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392,
885 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944,
886 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136,
887 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472,
888 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568,
889 344, 328, 376, 360, 280, 264, 312, 296,
890 472, 456, 504, 488, 408, 392, 440, 424,
891 88, 72, 120, 104, 24, 8, 56, 40,
892 216, 200, 248, 232, 152, 136, 184, 168,
893 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184,
894 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696,
895 688, 656, 752, 720, 560, 528, 624, 592,
896 944, 912, 1008, 976, 816, 784, 880, 848,
897};