aboutsummaryrefslogtreecommitdiffstats
path: root/sound/sparc
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/sparc
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/sparc')
-rw-r--r--sound/sparc/Kconfig18
-rw-r--r--sound/sparc/Makefile12
-rw-r--r--sound/sparc/amd7930.c1146
-rw-r--r--sound/sparc/cs4231.c2245
4 files changed, 3421 insertions, 0 deletions
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
new file mode 100644
index 000000000000..2358df1c45a9
--- /dev/null
+++ b/sound/sparc/Kconfig
@@ -0,0 +1,18 @@
1# ALSA Sparc drivers
2
3menu "ALSA Sparc devices"
4 depends on SND!=n && (SPARC32 || SPARC64)
5
6config SND_SUN_AMD7930
7 tristate "Sun AMD7930"
8 depends on SBUS && SND
9 select SND_PCM
10
11# dep_tristate 'Sun DBRI' CONFIG_SND_SUN_DBRI $CONFIG_SND
12config SND_SUN_CS4231
13 tristate "Sun CS4231"
14 depends on SND
15 select SND_PCM
16
17endmenu
18
diff --git a/sound/sparc/Makefile b/sound/sparc/Makefile
new file mode 100644
index 000000000000..6809cc92d276
--- /dev/null
+++ b/sound/sparc/Makefile
@@ -0,0 +1,12 @@
1#
2# Makefile for ALSA
3# Copyright (c) 2002 by David S. Miller <davem@redhat.com>
4#
5
6snd-sun-amd7930-objs := amd7930.o
7#snd-sun-dbri-objs := dbri.o
8snd-sun-cs4231-objs := cs4231.o
9
10obj-$(CONFIG_SND_SUN_AMD7930) += snd-sun-amd7930.o
11#obj-$(CONFIG_SND_SUN_DBRI) += snd-sun-dbri.o
12obj-$(CONFIG_SND_SUN_CS4231) += snd-sun-cs4231.o
diff --git a/sound/sparc/amd7930.c b/sound/sparc/amd7930.c
new file mode 100644
index 000000000000..bd8a850e93ea
--- /dev/null
+++ b/sound/sparc/amd7930.c
@@ -0,0 +1,1146 @@
1/*
2 * Driver for AMD7930 sound chips found on Sparcs.
3 * Copyright (C) 2002 David S. Miller <davem@redhat.com>
4 *
5 * Based entirely upon drivers/sbus/audio/amd7930.c which is:
6 * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
7 *
8 * --- Notes from Thomas's original driver ---
9 * This is the lowlevel driver for the AMD7930 audio chip found on all
10 * sun4c machines and some sun4m machines.
11 *
12 * The amd7930 is actually an ISDN chip which has a very simple
13 * integrated audio encoder/decoder. When Sun decided on what chip to
14 * use for audio, they had the brilliant idea of using the amd7930 and
15 * only connecting the audio encoder/decoder pins.
16 *
17 * Thanks to the AMD engineer who was able to get us the AMD79C30
18 * databook which has all the programming information and gain tables.
19 *
20 * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
21 * SparcStation 1+. The chip provides microphone and speaker interfaces
22 * which provide mono-channel audio at 8K samples per second via either
23 * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an
24 * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
25 * which performs basic D channel LAPD processing and provides raw
26 * B channel data. The digital audio channel, the two ISDN B channels,
27 * and two 64 Kbps channels to the microprocessor are all interconnected
28 * via a multiplexer.
29 * --- End of notes from Thoamas's original driver ---
30 */
31
32#include <linux/module.h>
33#include <linux/kernel.h>
34#include <linux/slab.h>
35#include <linux/init.h>
36#include <linux/interrupt.h>
37#include <linux/moduleparam.h>
38
39#include <sound/driver.h>
40#include <sound/core.h>
41#include <sound/pcm.h>
42#include <sound/info.h>
43#include <sound/control.h>
44#include <sound/initval.h>
45
46#include <asm/io.h>
47#include <asm/irq.h>
48#include <asm/sbus.h>
49
50static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
51static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
52static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
53
54module_param_array(index, int, NULL, 0444);
55MODULE_PARM_DESC(index, "Index value for Sun AMD7930 soundcard.");
56module_param_array(id, charp, NULL, 0444);
57MODULE_PARM_DESC(id, "ID string for Sun AMD7930 soundcard.");
58module_param_array(enable, bool, NULL, 0444);
59MODULE_PARM_DESC(enable, "Enable Sun AMD7930 soundcard.");
60MODULE_AUTHOR("Thomas K. Dyas and David S. Miller");
61MODULE_DESCRIPTION("Sun AMD7930");
62MODULE_LICENSE("GPL");
63MODULE_SUPPORTED_DEVICE("{{Sun,AMD7930}}");
64
65/* Device register layout. */
66
67/* Register interface presented to the CPU by the amd7930. */
68#define AMD7930_CR 0x00UL /* Command Register (W) */
69#define AMD7930_IR AMD7930_CR /* Interrupt Register (R) */
70#define AMD7930_DR 0x01UL /* Data Register (R/W) */
71#define AMD7930_DSR1 0x02UL /* D-channel Status Register 1 (R) */
72#define AMD7930_DER 0x03UL /* D-channel Error Register (R) */
73#define AMD7930_DCTB 0x04UL /* D-channel Transmit Buffer (W) */
74#define AMD7930_DCRB AMD7930_DCTB /* D-channel Receive Buffer (R) */
75#define AMD7930_BBTB 0x05UL /* Bb-channel Transmit Buffer (W) */
76#define AMD7930_BBRB AMD7930_BBTB /* Bb-channel Receive Buffer (R) */
77#define AMD7930_BCTB 0x06UL /* Bc-channel Transmit Buffer (W) */
78#define AMD7930_BCRB AMD7930_BCTB /* Bc-channel Receive Buffer (R) */
79#define AMD7930_DSR2 0x07UL /* D-channel Status Register 2 (R) */
80
81/* Indirect registers in the Main Audio Processor. */
82struct amd7930_map {
83 __u16 x[8];
84 __u16 r[8];
85 __u16 gx;
86 __u16 gr;
87 __u16 ger;
88 __u16 stgr;
89 __u16 ftgr;
90 __u16 atgr;
91 __u8 mmr1;
92 __u8 mmr2;
93};
94
95/* After an amd7930 interrupt, reading the Interrupt Register (ir)
96 * clears the interrupt and returns a bitmask indicating which
97 * interrupt source(s) require service.
98 */
99
100#define AMR_IR_DTTHRSH 0x01 /* D-channel xmit threshold */
101#define AMR_IR_DRTHRSH 0x02 /* D-channel recv threshold */
102#define AMR_IR_DSRI 0x04 /* D-channel packet status */
103#define AMR_IR_DERI 0x08 /* D-channel error */
104#define AMR_IR_BBUF 0x10 /* B-channel data xfer */
105#define AMR_IR_LSRI 0x20 /* LIU status */
106#define AMR_IR_DSR2I 0x40 /* D-channel buffer status */
107#define AMR_IR_MLTFRMI 0x80 /* multiframe or PP */
108
109/* The amd7930 has "indirect registers" which are accessed by writing
110 * the register number into the Command Register and then reading or
111 * writing values from the Data Register as appropriate. We define the
112 * AMR_* macros to be the indirect register numbers and AM_* macros to
113 * be bits in whatever register is referred to.
114 */
115
116/* Initialization */
117#define AMR_INIT 0x21
118#define AM_INIT_ACTIVE 0x01
119#define AM_INIT_DATAONLY 0x02
120#define AM_INIT_POWERDOWN 0x03
121#define AM_INIT_DISABLE_INTS 0x04
122#define AMR_INIT2 0x20
123#define AM_INIT2_ENABLE_POWERDOWN 0x20
124#define AM_INIT2_ENABLE_MULTIFRAME 0x10
125
126/* Line Interface Unit */
127#define AMR_LIU_LSR 0xA1
128#define AM_LIU_LSR_STATE 0x07
129#define AM_LIU_LSR_F3 0x08
130#define AM_LIU_LSR_F7 0x10
131#define AM_LIU_LSR_F8 0x20
132#define AM_LIU_LSR_HSW 0x40
133#define AM_LIU_LSR_HSW_CHG 0x80
134#define AMR_LIU_LPR 0xA2
135#define AMR_LIU_LMR1 0xA3
136#define AM_LIU_LMR1_B1_ENABL 0x01
137#define AM_LIU_LMR1_B2_ENABL 0x02
138#define AM_LIU_LMR1_F_DISABL 0x04
139#define AM_LIU_LMR1_FA_DISABL 0x08
140#define AM_LIU_LMR1_REQ_ACTIV 0x10
141#define AM_LIU_LMR1_F8_F3 0x20
142#define AM_LIU_LMR1_LIU_ENABL 0x40
143#define AMR_LIU_LMR2 0xA4
144#define AM_LIU_LMR2_DECHO 0x01
145#define AM_LIU_LMR2_DLOOP 0x02
146#define AM_LIU_LMR2_DBACKOFF 0x04
147#define AM_LIU_LMR2_EN_F3_INT 0x08
148#define AM_LIU_LMR2_EN_F8_INT 0x10
149#define AM_LIU_LMR2_EN_HSW_INT 0x20
150#define AM_LIU_LMR2_EN_F7_INT 0x40
151#define AMR_LIU_2_4 0xA5
152#define AMR_LIU_MF 0xA6
153#define AMR_LIU_MFSB 0xA7
154#define AMR_LIU_MFQB 0xA8
155
156/* Multiplexor */
157#define AMR_MUX_MCR1 0x41
158#define AMR_MUX_MCR2 0x42
159#define AMR_MUX_MCR3 0x43
160#define AM_MUX_CHANNEL_B1 0x01
161#define AM_MUX_CHANNEL_B2 0x02
162#define AM_MUX_CHANNEL_Ba 0x03
163#define AM_MUX_CHANNEL_Bb 0x04
164#define AM_MUX_CHANNEL_Bc 0x05
165#define AM_MUX_CHANNEL_Bd 0x06
166#define AM_MUX_CHANNEL_Be 0x07
167#define AM_MUX_CHANNEL_Bf 0x08
168#define AMR_MUX_MCR4 0x44
169#define AM_MUX_MCR4_ENABLE_INTS 0x08
170#define AM_MUX_MCR4_REVERSE_Bb 0x10
171#define AM_MUX_MCR4_REVERSE_Bc 0x20
172#define AMR_MUX_1_4 0x45
173
174/* Main Audio Processor */
175#define AMR_MAP_X 0x61
176#define AMR_MAP_R 0x62
177#define AMR_MAP_GX 0x63
178#define AMR_MAP_GR 0x64
179#define AMR_MAP_GER 0x65
180#define AMR_MAP_STGR 0x66
181#define AMR_MAP_FTGR_1_2 0x67
182#define AMR_MAP_ATGR_1_2 0x68
183#define AMR_MAP_MMR1 0x69
184#define AM_MAP_MMR1_ALAW 0x01
185#define AM_MAP_MMR1_GX 0x02
186#define AM_MAP_MMR1_GR 0x04
187#define AM_MAP_MMR1_GER 0x08
188#define AM_MAP_MMR1_X 0x10
189#define AM_MAP_MMR1_R 0x20
190#define AM_MAP_MMR1_STG 0x40
191#define AM_MAP_MMR1_LOOPBACK 0x80
192#define AMR_MAP_MMR2 0x6A
193#define AM_MAP_MMR2_AINB 0x01
194#define AM_MAP_MMR2_LS 0x02
195#define AM_MAP_MMR2_ENABLE_DTMF 0x04
196#define AM_MAP_MMR2_ENABLE_TONEGEN 0x08
197#define AM_MAP_MMR2_ENABLE_TONERING 0x10
198#define AM_MAP_MMR2_DISABLE_HIGHPASS 0x20
199#define AM_MAP_MMR2_DISABLE_AUTOZERO 0x40
200#define AMR_MAP_1_10 0x6B
201#define AMR_MAP_MMR3 0x6C
202#define AMR_MAP_STRA 0x6D
203#define AMR_MAP_STRF 0x6E
204#define AMR_MAP_PEAKX 0x70
205#define AMR_MAP_PEAKR 0x71
206#define AMR_MAP_15_16 0x72
207
208/* Data Link Controller */
209#define AMR_DLC_FRAR_1_2_3 0x81
210#define AMR_DLC_SRAR_1_2_3 0x82
211#define AMR_DLC_TAR 0x83
212#define AMR_DLC_DRLR 0x84
213#define AMR_DLC_DTCR 0x85
214#define AMR_DLC_DMR1 0x86
215#define AMR_DLC_DMR1_DTTHRSH_INT 0x01
216#define AMR_DLC_DMR1_DRTHRSH_INT 0x02
217#define AMR_DLC_DMR1_TAR_ENABL 0x04
218#define AMR_DLC_DMR1_EORP_INT 0x08
219#define AMR_DLC_DMR1_EN_ADDR1 0x10
220#define AMR_DLC_DMR1_EN_ADDR2 0x20
221#define AMR_DLC_DMR1_EN_ADDR3 0x40
222#define AMR_DLC_DMR1_EN_ADDR4 0x80
223#define AMR_DLC_DMR1_EN_ADDRS 0xf0
224#define AMR_DLC_DMR2 0x87
225#define AMR_DLC_DMR2_RABRT_INT 0x01
226#define AMR_DLC_DMR2_RESID_INT 0x02
227#define AMR_DLC_DMR2_COLL_INT 0x04
228#define AMR_DLC_DMR2_FCS_INT 0x08
229#define AMR_DLC_DMR2_OVFL_INT 0x10
230#define AMR_DLC_DMR2_UNFL_INT 0x20
231#define AMR_DLC_DMR2_OVRN_INT 0x40
232#define AMR_DLC_DMR2_UNRN_INT 0x80
233#define AMR_DLC_1_7 0x88
234#define AMR_DLC_DRCR 0x89
235#define AMR_DLC_RNGR1 0x8A
236#define AMR_DLC_RNGR2 0x8B
237#define AMR_DLC_FRAR4 0x8C
238#define AMR_DLC_SRAR4 0x8D
239#define AMR_DLC_DMR3 0x8E
240#define AMR_DLC_DMR3_VA_INT 0x01
241#define AMR_DLC_DMR3_EOTP_INT 0x02
242#define AMR_DLC_DMR3_LBRP_INT 0x04
243#define AMR_DLC_DMR3_RBA_INT 0x08
244#define AMR_DLC_DMR3_LBT_INT 0x10
245#define AMR_DLC_DMR3_TBE_INT 0x20
246#define AMR_DLC_DMR3_RPLOST_INT 0x40
247#define AMR_DLC_DMR3_KEEP_FCS 0x80
248#define AMR_DLC_DMR4 0x8F
249#define AMR_DLC_DMR4_RCV_1 0x00
250#define AMR_DLC_DMR4_RCV_2 0x01
251#define AMR_DLC_DMR4_RCV_4 0x02
252#define AMR_DLC_DMR4_RCV_8 0x03
253#define AMR_DLC_DMR4_RCV_16 0x01
254#define AMR_DLC_DMR4_RCV_24 0x02
255#define AMR_DLC_DMR4_RCV_30 0x03
256#define AMR_DLC_DMR4_XMT_1 0x00
257#define AMR_DLC_DMR4_XMT_2 0x04
258#define AMR_DLC_DMR4_XMT_4 0x08
259#define AMR_DLC_DMR4_XMT_8 0x0c
260#define AMR_DLC_DMR4_XMT_10 0x08
261#define AMR_DLC_DMR4_XMT_14 0x0c
262#define AMR_DLC_DMR4_IDLE_MARK 0x00
263#define AMR_DLC_DMR4_IDLE_FLAG 0x10
264#define AMR_DLC_DMR4_ADDR_BOTH 0x00
265#define AMR_DLC_DMR4_ADDR_1ST 0x20
266#define AMR_DLC_DMR4_ADDR_2ND 0xa0
267#define AMR_DLC_DMR4_CR_ENABLE 0x40
268#define AMR_DLC_12_15 0x90
269#define AMR_DLC_ASR 0x91
270#define AMR_DLC_EFCR 0x92
271#define AMR_DLC_EFCR_EXTEND_FIFO 0x01
272#define AMR_DLC_EFCR_SEC_PKT_INT 0x02
273
274#define AMR_DSR1_VADDR 0x01
275#define AMR_DSR1_EORP 0x02
276#define AMR_DSR1_PKT_IP 0x04
277#define AMR_DSR1_DECHO_ON 0x08
278#define AMR_DSR1_DLOOP_ON 0x10
279#define AMR_DSR1_DBACK_OFF 0x20
280#define AMR_DSR1_EOTP 0x40
281#define AMR_DSR1_CXMT_ABRT 0x80
282
283#define AMR_DSR2_LBRP 0x01
284#define AMR_DSR2_RBA 0x02
285#define AMR_DSR2_RPLOST 0x04
286#define AMR_DSR2_LAST_BYTE 0x08
287#define AMR_DSR2_TBE 0x10
288#define AMR_DSR2_MARK_IDLE 0x20
289#define AMR_DSR2_FLAG_IDLE 0x40
290#define AMR_DSR2_SECOND_PKT 0x80
291
292#define AMR_DER_RABRT 0x01
293#define AMR_DER_RFRAME 0x02
294#define AMR_DER_COLLISION 0x04
295#define AMR_DER_FCS 0x08
296#define AMR_DER_OVFL 0x10
297#define AMR_DER_UNFL 0x20
298#define AMR_DER_OVRN 0x40
299#define AMR_DER_UNRN 0x80
300
301/* Peripheral Port */
302#define AMR_PP_PPCR1 0xC0
303#define AMR_PP_PPSR 0xC1
304#define AMR_PP_PPIER 0xC2
305#define AMR_PP_MTDR 0xC3
306#define AMR_PP_MRDR 0xC3
307#define AMR_PP_CITDR0 0xC4
308#define AMR_PP_CIRDR0 0xC4
309#define AMR_PP_CITDR1 0xC5
310#define AMR_PP_CIRDR1 0xC5
311#define AMR_PP_PPCR2 0xC8
312#define AMR_PP_PPCR3 0xC9
313
314typedef struct snd_amd7930 {
315 spinlock_t lock;
316 void __iomem *regs;
317 u32 flags;
318#define AMD7930_FLAG_PLAYBACK 0x00000001
319#define AMD7930_FLAG_CAPTURE 0x00000002
320
321 struct amd7930_map map;
322
323 snd_card_t *card;
324 snd_pcm_t *pcm;
325 snd_pcm_substream_t *playback_substream;
326 snd_pcm_substream_t *capture_substream;
327
328 /* Playback/Capture buffer state. */
329 unsigned char *p_orig, *p_cur;
330 int p_left;
331 unsigned char *c_orig, *c_cur;
332 int c_left;
333
334 int rgain;
335 int pgain;
336 int mgain;
337
338 struct sbus_dev *sdev;
339 unsigned int irq;
340 unsigned int regs_size;
341 struct snd_amd7930 *next;
342} amd7930_t;
343
344static amd7930_t *amd7930_list;
345
346/* Idle the AMD7930 chip. The amd->lock is not held. */
347static __inline__ void amd7930_idle(amd7930_t *amd)
348{
349 unsigned long flags;
350
351 spin_lock_irqsave(&amd->lock, flags);
352 sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR);
353 sbus_writeb(0, amd->regs + AMD7930_DR);
354 spin_unlock_irqrestore(&amd->lock, flags);
355}
356
357/* Enable chip interrupts. The amd->lock is not held. */
358static __inline__ void amd7930_enable_ints(amd7930_t *amd)
359{
360 unsigned long flags;
361
362 spin_lock_irqsave(&amd->lock, flags);
363 sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR);
364 sbus_writeb(AM_INIT_ACTIVE, amd->regs + AMD7930_DR);
365 spin_unlock_irqrestore(&amd->lock, flags);
366}
367
368/* Disable chip interrupts. The amd->lock is not held. */
369static __inline__ void amd7930_disable_ints(amd7930_t *amd)
370{
371 unsigned long flags;
372
373 spin_lock_irqsave(&amd->lock, flags);
374 sbus_writeb(AMR_INIT, amd->regs + AMD7930_CR);
375 sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS, amd->regs + AMD7930_DR);
376 spin_unlock_irqrestore(&amd->lock, flags);
377}
378
379/* Commit amd7930_map settings to the hardware.
380 * The amd->lock is held and local interrupts are disabled.
381 */
382static void __amd7930_write_map(amd7930_t *amd)
383{
384 struct amd7930_map *map = &amd->map;
385
386 sbus_writeb(AMR_MAP_GX, amd->regs + AMD7930_CR);
387 sbus_writeb(((map->gx >> 0) & 0xff), amd->regs + AMD7930_DR);
388 sbus_writeb(((map->gx >> 8) & 0xff), amd->regs + AMD7930_DR);
389
390 sbus_writeb(AMR_MAP_GR, amd->regs + AMD7930_CR);
391 sbus_writeb(((map->gr >> 0) & 0xff), amd->regs + AMD7930_DR);
392 sbus_writeb(((map->gr >> 8) & 0xff), amd->regs + AMD7930_DR);
393
394 sbus_writeb(AMR_MAP_STGR, amd->regs + AMD7930_CR);
395 sbus_writeb(((map->stgr >> 0) & 0xff), amd->regs + AMD7930_DR);
396 sbus_writeb(((map->stgr >> 8) & 0xff), amd->regs + AMD7930_DR);
397
398 sbus_writeb(AMR_MAP_GER, amd->regs + AMD7930_CR);
399 sbus_writeb(((map->ger >> 0) & 0xff), amd->regs + AMD7930_DR);
400 sbus_writeb(((map->ger >> 8) & 0xff), amd->regs + AMD7930_DR);
401
402 sbus_writeb(AMR_MAP_MMR1, amd->regs + AMD7930_CR);
403 sbus_writeb(map->mmr1, amd->regs + AMD7930_DR);
404
405 sbus_writeb(AMR_MAP_MMR2, amd->regs + AMD7930_CR);
406 sbus_writeb(map->mmr2, amd->regs + AMD7930_DR);
407}
408
409/* gx, gr & stg gains. this table must contain 256 elements with
410 * the 0th being "infinity" (the magic value 9008). The remaining
411 * elements match sun's gain curve (but with higher resolution):
412 * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
413 */
414static __const__ __u16 gx_coeff[256] = {
415 0x9008, 0x8b7c, 0x8b51, 0x8b45, 0x8b42, 0x8b3b, 0x8b36, 0x8b33,
416 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
417 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
418 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
419 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
420 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
421 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
422 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
423 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
424 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
425 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
426 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
427 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
428 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
429 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
430 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
431 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
432 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
433 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
434 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
435 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
436 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
437 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
438 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
439 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
440 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
441 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
442 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
443 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
444 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
445 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
446 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
447};
448
449static __const__ __u16 ger_coeff[] = {
450 0x431f, /* 5. dB */
451 0x331f, /* 5.5 dB */
452 0x40dd, /* 6. dB */
453 0x11dd, /* 6.5 dB */
454 0x440f, /* 7. dB */
455 0x411f, /* 7.5 dB */
456 0x311f, /* 8. dB */
457 0x5520, /* 8.5 dB */
458 0x10dd, /* 9. dB */
459 0x4211, /* 9.5 dB */
460 0x410f, /* 10. dB */
461 0x111f, /* 10.5 dB */
462 0x600b, /* 11. dB */
463 0x00dd, /* 11.5 dB */
464 0x4210, /* 12. dB */
465 0x110f, /* 13. dB */
466 0x7200, /* 14. dB */
467 0x2110, /* 15. dB */
468 0x2200, /* 15.9 dB */
469 0x000b, /* 16.9 dB */
470 0x000f /* 18. dB */
471};
472
473/* Update amd7930_map settings and program them into the hardware.
474 * The amd->lock is held and local interrupts are disabled.
475 */
476static void __amd7930_update_map(amd7930_t *amd)
477{
478 struct amd7930_map *map = &amd->map;
479 int level;
480
481 map->gx = gx_coeff[amd->rgain];
482 map->stgr = gx_coeff[amd->mgain];
483 level = (amd->pgain * (256 + ARRAY_SIZE(ger_coeff))) >> 8;
484 if (level >= 256) {
485 map->ger = ger_coeff[level - 256];
486 map->gr = gx_coeff[255];
487 } else {
488 map->ger = ger_coeff[0];
489 map->gr = gx_coeff[level];
490 }
491 __amd7930_write_map(amd);
492}
493
494static irqreturn_t snd_amd7930_interrupt(int irq, void *dev_id, struct pt_regs *regs)
495{
496 amd7930_t *amd = dev_id;
497 unsigned int elapsed;
498 u8 ir;
499
500 spin_lock(&amd->lock);
501
502 elapsed = 0;
503
504 ir = sbus_readb(amd->regs + AMD7930_IR);
505 if (ir & AMR_IR_BBUF) {
506 u8 byte;
507
508 if (amd->flags & AMD7930_FLAG_PLAYBACK) {
509 if (amd->p_left > 0) {
510 byte = *(amd->p_cur++);
511 amd->p_left--;
512 sbus_writeb(byte, amd->regs + AMD7930_BBTB);
513 if (amd->p_left == 0)
514 elapsed |= AMD7930_FLAG_PLAYBACK;
515 } else
516 sbus_writeb(0, amd->regs + AMD7930_BBTB);
517 } else if (amd->flags & AMD7930_FLAG_CAPTURE) {
518 byte = sbus_readb(amd->regs + AMD7930_BBRB);
519 if (amd->c_left > 0) {
520 *(amd->c_cur++) = byte;
521 amd->c_left--;
522 if (amd->c_left == 0)
523 elapsed |= AMD7930_FLAG_CAPTURE;
524 }
525 }
526 }
527 spin_unlock(&amd->lock);
528
529 if (elapsed & AMD7930_FLAG_PLAYBACK)
530 snd_pcm_period_elapsed(amd->playback_substream);
531 else
532 snd_pcm_period_elapsed(amd->capture_substream);
533
534 return IRQ_HANDLED;
535}
536
537static int snd_amd7930_trigger(amd7930_t *amd, unsigned int flag, int cmd)
538{
539 unsigned long flags;
540 int result = 0;
541
542 spin_lock_irqsave(&amd->lock, flags);
543 if (cmd == SNDRV_PCM_TRIGGER_START) {
544 if (!(amd->flags & flag)) {
545 amd->flags |= flag;
546
547 /* Enable B channel interrupts. */
548 sbus_writeb(AMR_MUX_MCR4, amd->regs + AMD7930_CR);
549 sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, amd->regs + AMD7930_DR);
550 }
551 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
552 if (amd->flags & flag) {
553 amd->flags &= ~flag;
554
555 /* Disable B channel interrupts. */
556 sbus_writeb(AMR_MUX_MCR4, amd->regs + AMD7930_CR);
557 sbus_writeb(0, amd->regs + AMD7930_DR);
558 }
559 } else {
560 result = -EINVAL;
561 }
562 spin_unlock_irqrestore(&amd->lock, flags);
563
564 return result;
565}
566
567static int snd_amd7930_playback_trigger(snd_pcm_substream_t * substream,
568 int cmd)
569{
570 amd7930_t *amd = snd_pcm_substream_chip(substream);
571 return snd_amd7930_trigger(amd, AMD7930_FLAG_PLAYBACK, cmd);
572}
573
574static int snd_amd7930_capture_trigger(snd_pcm_substream_t * substream,
575 int cmd)
576{
577 amd7930_t *amd = snd_pcm_substream_chip(substream);
578 return snd_amd7930_trigger(amd, AMD7930_FLAG_CAPTURE, cmd);
579}
580
581static int snd_amd7930_playback_prepare(snd_pcm_substream_t * substream)
582{
583 amd7930_t *amd = snd_pcm_substream_chip(substream);
584 snd_pcm_runtime_t *runtime = substream->runtime;
585 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
586 unsigned long flags;
587 u8 new_mmr1;
588
589 spin_lock_irqsave(&amd->lock, flags);
590
591 amd->flags |= AMD7930_FLAG_PLAYBACK;
592
593 /* Setup the pseudo-dma transfer pointers. */
594 amd->p_orig = amd->p_cur = runtime->dma_area;
595 amd->p_left = size;
596
597 /* Put the chip into the correct encoding format. */
598 new_mmr1 = amd->map.mmr1;
599 if (runtime->format == SNDRV_PCM_FORMAT_A_LAW)
600 new_mmr1 |= AM_MAP_MMR1_ALAW;
601 else
602 new_mmr1 &= ~AM_MAP_MMR1_ALAW;
603 if (new_mmr1 != amd->map.mmr1) {
604 amd->map.mmr1 = new_mmr1;
605 __amd7930_update_map(amd);
606 }
607
608 spin_unlock_irqrestore(&amd->lock, flags);
609
610 return 0;
611}
612
613static int snd_amd7930_capture_prepare(snd_pcm_substream_t * substream)
614{
615 amd7930_t *amd = snd_pcm_substream_chip(substream);
616 snd_pcm_runtime_t *runtime = substream->runtime;
617 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
618 unsigned long flags;
619 u8 new_mmr1;
620
621 spin_lock_irqsave(&amd->lock, flags);
622
623 amd->flags |= AMD7930_FLAG_CAPTURE;
624
625 /* Setup the pseudo-dma transfer pointers. */
626 amd->c_orig = amd->c_cur = runtime->dma_area;
627 amd->c_left = size;
628
629 /* Put the chip into the correct encoding format. */
630 new_mmr1 = amd->map.mmr1;
631 if (runtime->format == SNDRV_PCM_FORMAT_A_LAW)
632 new_mmr1 |= AM_MAP_MMR1_ALAW;
633 else
634 new_mmr1 &= ~AM_MAP_MMR1_ALAW;
635 if (new_mmr1 != amd->map.mmr1) {
636 amd->map.mmr1 = new_mmr1;
637 __amd7930_update_map(amd);
638 }
639
640 spin_unlock_irqrestore(&amd->lock, flags);
641
642 return 0;
643}
644
645static snd_pcm_uframes_t snd_amd7930_playback_pointer(snd_pcm_substream_t * substream)
646{
647 amd7930_t *amd = snd_pcm_substream_chip(substream);
648 size_t ptr;
649
650 if (!(amd->flags & AMD7930_FLAG_PLAYBACK))
651 return 0;
652 ptr = amd->p_cur - amd->p_orig;
653 return bytes_to_frames(substream->runtime, ptr);
654}
655
656static snd_pcm_uframes_t snd_amd7930_capture_pointer(snd_pcm_substream_t * substream)
657{
658 amd7930_t *amd = snd_pcm_substream_chip(substream);
659 size_t ptr;
660
661 if (!(amd->flags & AMD7930_FLAG_CAPTURE))
662 return 0;
663
664 ptr = amd->c_cur - amd->c_orig;
665 return bytes_to_frames(substream->runtime, ptr);
666}
667
668/* Playback and capture have identical properties. */
669static snd_pcm_hardware_t snd_amd7930_pcm_hw =
670{
671 .info = (SNDRV_PCM_INFO_MMAP |
672 SNDRV_PCM_INFO_MMAP_VALID |
673 SNDRV_PCM_INFO_INTERLEAVED |
674 SNDRV_PCM_INFO_BLOCK_TRANSFER |
675 SNDRV_PCM_INFO_HALF_DUPLEX),
676 .formats = SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW,
677 .rates = SNDRV_PCM_RATE_8000,
678 .rate_min = 8000,
679 .rate_max = 8000,
680 .channels_min = 1,
681 .channels_max = 1,
682 .buffer_bytes_max = (64*1024),
683 .period_bytes_min = 1,
684 .period_bytes_max = (64*1024),
685 .periods_min = 1,
686 .periods_max = 1024,
687};
688
689static int snd_amd7930_playback_open(snd_pcm_substream_t * substream)
690{
691 amd7930_t *amd = snd_pcm_substream_chip(substream);
692 snd_pcm_runtime_t *runtime = substream->runtime;
693
694 amd->playback_substream = substream;
695 runtime->hw = snd_amd7930_pcm_hw;
696 return 0;
697}
698
699static int snd_amd7930_capture_open(snd_pcm_substream_t * substream)
700{
701 amd7930_t *amd = snd_pcm_substream_chip(substream);
702 snd_pcm_runtime_t *runtime = substream->runtime;
703
704 amd->capture_substream = substream;
705 runtime->hw = snd_amd7930_pcm_hw;
706 return 0;
707}
708
709static int snd_amd7930_playback_close(snd_pcm_substream_t * substream)
710{
711 amd7930_t *amd = snd_pcm_substream_chip(substream);
712
713 amd->playback_substream = NULL;
714 return 0;
715}
716
717static int snd_amd7930_capture_close(snd_pcm_substream_t * substream)
718{
719 amd7930_t *amd = snd_pcm_substream_chip(substream);
720
721 amd->capture_substream = NULL;
722 return 0;
723}
724
725static int snd_amd7930_hw_params(snd_pcm_substream_t * substream,
726 snd_pcm_hw_params_t * hw_params)
727{
728 return snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params));
729}
730
731static int snd_amd7930_hw_free(snd_pcm_substream_t * substream)
732{
733 return snd_pcm_lib_free_pages(substream);
734}
735
736static snd_pcm_ops_t snd_amd7930_playback_ops = {
737 .open = snd_amd7930_playback_open,
738 .close = snd_amd7930_playback_close,
739 .ioctl = snd_pcm_lib_ioctl,
740 .hw_params = snd_amd7930_hw_params,
741 .hw_free = snd_amd7930_hw_free,
742 .prepare = snd_amd7930_playback_prepare,
743 .trigger = snd_amd7930_playback_trigger,
744 .pointer = snd_amd7930_playback_pointer,
745};
746
747static snd_pcm_ops_t snd_amd7930_capture_ops = {
748 .open = snd_amd7930_capture_open,
749 .close = snd_amd7930_capture_close,
750 .ioctl = snd_pcm_lib_ioctl,
751 .hw_params = snd_amd7930_hw_params,
752 .hw_free = snd_amd7930_hw_free,
753 .prepare = snd_amd7930_capture_prepare,
754 .trigger = snd_amd7930_capture_trigger,
755 .pointer = snd_amd7930_capture_pointer,
756};
757
758static void snd_amd7930_pcm_free(snd_pcm_t *pcm)
759{
760 amd7930_t *amd = pcm->private_data;
761
762 amd->pcm = NULL;
763 snd_pcm_lib_preallocate_free_for_all(pcm);
764}
765
766static int __init snd_amd7930_pcm(amd7930_t *amd)
767{
768 snd_pcm_t *pcm;
769 int err;
770
771 if ((err = snd_pcm_new(amd->card,
772 /* ID */ "sun_amd7930",
773 /* device */ 0,
774 /* playback count */ 1,
775 /* capture count */ 1, &pcm)) < 0)
776 return err;
777 snd_assert(pcm != NULL, return -EINVAL);
778
779 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_amd7930_playback_ops);
780 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_amd7930_capture_ops);
781
782 pcm->private_data = amd;
783 pcm->private_free = snd_amd7930_pcm_free;
784 pcm->info_flags = 0;
785 strcpy(pcm->name, amd->card->shortname);
786 amd->pcm = pcm;
787
788 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_CONTINUOUS,
789 snd_dma_continuous_data(GFP_KERNEL),
790 64*1024, 64*1024);
791
792 return 0;
793}
794
795#define VOLUME_MONITOR 0
796#define VOLUME_CAPTURE 1
797#define VOLUME_PLAYBACK 2
798
799static int snd_amd7930_info_volume(snd_kcontrol_t *kctl, snd_ctl_elem_info_t *uinfo)
800{
801 int type = kctl->private_value;
802
803 snd_assert(type == VOLUME_MONITOR ||
804 type == VOLUME_CAPTURE ||
805 type == VOLUME_PLAYBACK, return -EINVAL);
806 (void) type;
807
808 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
809 uinfo->count = 1;
810 uinfo->value.integer.min = 0;
811 uinfo->value.integer.max = 255;
812
813 return 0;
814}
815
816static int snd_amd7930_get_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *ucontrol)
817{
818 amd7930_t *amd = snd_kcontrol_chip(kctl);
819 int type = kctl->private_value;
820 int *swval;
821
822 snd_assert(type == VOLUME_MONITOR ||
823 type == VOLUME_CAPTURE ||
824 type == VOLUME_PLAYBACK, return -EINVAL);
825
826 switch (type) {
827 case VOLUME_MONITOR:
828 swval = &amd->mgain;
829 break;
830 case VOLUME_CAPTURE:
831 swval = &amd->rgain;
832 break;
833 case VOLUME_PLAYBACK:
834 default:
835 swval = &amd->pgain;
836 break;
837 };
838
839 ucontrol->value.integer.value[0] = *swval;
840
841 return 0;
842}
843
844static int snd_amd7930_put_volume(snd_kcontrol_t *kctl, snd_ctl_elem_value_t *ucontrol)
845{
846 amd7930_t *amd = snd_kcontrol_chip(kctl);
847 unsigned long flags;
848 int type = kctl->private_value;
849 int *swval, change;
850
851 snd_assert(type == VOLUME_MONITOR ||
852 type == VOLUME_CAPTURE ||
853 type == VOLUME_PLAYBACK, return -EINVAL);
854
855 switch (type) {
856 case VOLUME_MONITOR:
857 swval = &amd->mgain;
858 break;
859 case VOLUME_CAPTURE:
860 swval = &amd->rgain;
861 break;
862 case VOLUME_PLAYBACK:
863 default:
864 swval = &amd->pgain;
865 break;
866 };
867
868 spin_lock_irqsave(&amd->lock, flags);
869
870 if (*swval != ucontrol->value.integer.value[0]) {
871 *swval = ucontrol->value.integer.value[0];
872 __amd7930_update_map(amd);
873 change = 1;
874 } else
875 change = 0;
876
877 spin_unlock_irqrestore(&amd->lock, flags);
878
879 return change;
880}
881
882static snd_kcontrol_new_t amd7930_controls[] __initdata = {
883 {
884 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
885 .name = "Monitor Volume",
886 .index = 0,
887 .info = snd_amd7930_info_volume,
888 .get = snd_amd7930_get_volume,
889 .put = snd_amd7930_put_volume,
890 .private_value = VOLUME_MONITOR,
891 },
892 {
893 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
894 .name = "Capture Volume",
895 .index = 0,
896 .info = snd_amd7930_info_volume,
897 .get = snd_amd7930_get_volume,
898 .put = snd_amd7930_put_volume,
899 .private_value = VOLUME_CAPTURE,
900 },
901 {
902 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
903 .name = "Playback Volume",
904 .index = 0,
905 .info = snd_amd7930_info_volume,
906 .get = snd_amd7930_get_volume,
907 .put = snd_amd7930_put_volume,
908 .private_value = VOLUME_PLAYBACK,
909 },
910};
911
912static int __init snd_amd7930_mixer(amd7930_t *amd)
913{
914 snd_card_t *card;
915 int idx, err;
916
917 snd_assert(amd != NULL && amd->card != NULL, return -EINVAL);
918
919 card = amd->card;
920 strcpy(card->mixername, card->shortname);
921
922 for (idx = 0; idx < ARRAY_SIZE(amd7930_controls); idx++) {
923 if ((err = snd_ctl_add(card,
924 snd_ctl_new1(&amd7930_controls[idx], amd))) < 0)
925 return err;
926 }
927
928 return 0;
929}
930
931static int snd_amd7930_free(amd7930_t *amd)
932{
933 amd7930_idle(amd);
934
935 if (amd->irq)
936 free_irq(amd->irq, amd);
937
938 if (amd->regs)
939 sbus_iounmap(amd->regs, amd->regs_size);
940
941 kfree(amd);
942
943 return 0;
944}
945
946static int snd_amd7930_dev_free(snd_device_t *device)
947{
948 amd7930_t *amd = device->device_data;
949
950 return snd_amd7930_free(amd);
951}
952
953static snd_device_ops_t snd_amd7930_dev_ops = {
954 .dev_free = snd_amd7930_dev_free,
955};
956
957static int __init snd_amd7930_create(snd_card_t *card,
958 struct sbus_dev *sdev,
959 struct resource *rp,
960 unsigned int reg_size,
961 struct linux_prom_irqs *irq_prop,
962 int dev,
963 amd7930_t **ramd)
964{
965 unsigned long flags;
966 amd7930_t *amd;
967 int err;
968
969 *ramd = NULL;
970 amd = kcalloc(1, sizeof(*amd), GFP_KERNEL);
971 if (amd == NULL)
972 return -ENOMEM;
973
974 spin_lock_init(&amd->lock);
975 amd->card = card;
976 amd->sdev = sdev;
977 amd->regs_size = reg_size;
978
979 amd->regs = sbus_ioremap(rp, 0, amd->regs_size, "amd7930");
980 if (!amd->regs) {
981 snd_printk("amd7930-%d: Unable to map chip registers.\n", dev);
982 return -EIO;
983 }
984
985 amd7930_idle(amd);
986
987 if (request_irq(irq_prop->pri, snd_amd7930_interrupt,
988 SA_INTERRUPT | SA_SHIRQ, "amd7930", amd)) {
989 snd_printk("amd7930-%d: Unable to grab IRQ %s\n",
990 dev,
991 __irq_itoa(irq_prop->pri));
992 snd_amd7930_free(amd);
993 return -EBUSY;
994 }
995 amd->irq = irq_prop->pri;
996
997 amd7930_enable_ints(amd);
998
999 spin_lock_irqsave(&amd->lock, flags);
1000
1001 amd->rgain = 128;
1002 amd->pgain = 200;
1003 amd->mgain = 0;
1004
1005 memset(&amd->map, 0, sizeof(amd->map));
1006 amd->map.mmr1 = (AM_MAP_MMR1_GX | AM_MAP_MMR1_GER |
1007 AM_MAP_MMR1_GR | AM_MAP_MMR1_STG);
1008 amd->map.mmr2 = (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB);
1009
1010 __amd7930_update_map(amd);
1011
1012 /* Always MUX audio (Ba) to channel Bb. */
1013 sbus_writeb(AMR_MUX_MCR1, amd->regs + AMD7930_CR);
1014 sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4),
1015 amd->regs + AMD7930_DR);
1016
1017 spin_unlock_irqrestore(&amd->lock, flags);
1018
1019 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
1020 amd, &snd_amd7930_dev_ops)) < 0) {
1021 snd_amd7930_free(amd);
1022 return err;
1023 }
1024
1025 *ramd = amd;
1026 return 0;
1027}
1028
1029static int __init amd7930_attach(int prom_node, struct sbus_dev *sdev)
1030{
1031 static int dev;
1032 struct linux_prom_registers reg_prop;
1033 struct linux_prom_irqs irq_prop;
1034 struct resource res, *rp;
1035 snd_card_t *card;
1036 amd7930_t *amd;
1037 int err;
1038
1039 if (dev >= SNDRV_CARDS)
1040 return -ENODEV;
1041 if (!enable[dev]) {
1042 dev++;
1043 return -ENOENT;
1044 }
1045
1046 err = prom_getproperty(prom_node, "intr",
1047 (char *) &irq_prop, sizeof(irq_prop));
1048 if (err < 0) {
1049 snd_printk("amd7930-%d: Firmware node lacks IRQ property.\n", dev);
1050 return -ENODEV;
1051 }
1052
1053 err = prom_getproperty(prom_node, "reg",
1054 (char *) &reg_prop, sizeof(reg_prop));
1055 if (err < 0) {
1056 snd_printk("amd7930-%d: Firmware node lacks register property.\n", dev);
1057 return -ENODEV;
1058 }
1059
1060 if (sdev) {
1061 rp = &sdev->resource[0];
1062 } else {
1063 rp = &res;
1064 rp->start = reg_prop.phys_addr;
1065 rp->end = rp->start + reg_prop.reg_size - 1;
1066 rp->flags = IORESOURCE_IO | (reg_prop.which_io & 0xff);
1067 }
1068
1069 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1070 if (card == NULL)
1071 return -ENOMEM;
1072
1073 strcpy(card->driver, "AMD7930");
1074 strcpy(card->shortname, "Sun AMD7930");
1075 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
1076 card->shortname,
1077 rp->flags & 0xffL,
1078 rp->start,
1079 __irq_itoa(irq_prop.pri));
1080
1081 if ((err = snd_amd7930_create(card, sdev, rp, reg_prop.reg_size,
1082 &irq_prop, dev, &amd)) < 0)
1083 goto out_err;
1084
1085 if ((err = snd_amd7930_pcm(amd)) < 0)
1086 goto out_err;
1087
1088 if ((err = snd_amd7930_mixer(amd)) < 0)
1089 goto out_err;
1090
1091 if ((err = snd_card_register(card)) < 0)
1092 goto out_err;
1093
1094 amd->next = amd7930_list;
1095 amd7930_list = amd;
1096
1097 dev++;
1098 return 0;
1099
1100out_err:
1101 snd_card_free(card);
1102 return err;
1103}
1104
1105static int __init amd7930_init(void)
1106{
1107 struct sbus_bus *sbus;
1108 struct sbus_dev *sdev;
1109 int node, found;
1110
1111 found = 0;
1112
1113 /* Try to find the sun4c "audio" node first. */
1114 node = prom_getchild(prom_root_node);
1115 node = prom_searchsiblings(node, "audio");
1116 if (node && amd7930_attach(node, NULL) == 0)
1117 found++;
1118
1119 /* Probe each SBUS for amd7930 chips. */
1120 for_all_sbusdev(sdev, sbus) {
1121 if (!strcmp(sdev->prom_name, "audio")) {
1122 if (amd7930_attach(sdev->prom_node, sdev) == 0)
1123 found++;
1124 }
1125 }
1126
1127 return (found > 0) ? 0 : -EIO;
1128}
1129
1130static void __exit amd7930_exit(void)
1131{
1132 amd7930_t *p = amd7930_list;
1133
1134 while (p != NULL) {
1135 amd7930_t *next = p->next;
1136
1137 snd_card_free(p->card);
1138
1139 p = next;
1140 }
1141
1142 amd7930_list = NULL;
1143}
1144
1145module_init(amd7930_init);
1146module_exit(amd7930_exit);
diff --git a/sound/sparc/cs4231.c b/sound/sparc/cs4231.c
new file mode 100644
index 000000000000..36f9fe4d7bea
--- /dev/null
+++ b/sound/sparc/cs4231.c
@@ -0,0 +1,2245 @@
1/*
2 * Driver for CS4231 sound chips found on Sparcs.
3 * Copyright (C) 2002 David S. Miller <davem@redhat.com>
4 *
5 * Based entirely upon drivers/sbus/audio/cs4231.c which is:
6 * Copyright (C) 1996, 1997, 1998, 1998 Derrick J Brashear (shadow@andrew.cmu.edu)
7 * and also sound/isa/cs423x/cs4231_lib.c which is:
8 * Copyright (c) by Jaroslav Kysela <perex@suse.cz>
9 */
10
11#include <linux/config.h>
12#include <linux/module.h>
13#include <linux/kernel.h>
14#include <linux/slab.h>
15#include <linux/delay.h>
16#include <linux/init.h>
17#include <linux/interrupt.h>
18#include <linux/moduleparam.h>
19
20#include <sound/driver.h>
21#include <sound/core.h>
22#include <sound/pcm.h>
23#include <sound/info.h>
24#include <sound/control.h>
25#include <sound/timer.h>
26#include <sound/initval.h>
27#include <sound/pcm_params.h>
28
29#include <asm/io.h>
30#include <asm/irq.h>
31
32#ifdef CONFIG_SBUS
33#define SBUS_SUPPORT
34#endif
35
36#ifdef SBUS_SUPPORT
37#include <asm/sbus.h>
38#endif
39
40#if defined(CONFIG_PCI) && defined(CONFIG_SPARC64)
41#define EBUS_SUPPORT
42#endif
43
44#ifdef EBUS_SUPPORT
45#include <linux/pci.h>
46#include <asm/ebus.h>
47#endif
48
49static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
50static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
51static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_PNP; /* Enable this card */
52
53module_param_array(index, int, NULL, 0444);
54MODULE_PARM_DESC(index, "Index value for Sun CS4231 soundcard.");
55module_param_array(id, charp, NULL, 0444);
56MODULE_PARM_DESC(id, "ID string for Sun CS4231 soundcard.");
57module_param_array(enable, bool, NULL, 0444);
58MODULE_PARM_DESC(enable, "Enable Sun CS4231 soundcard.");
59MODULE_AUTHOR("Jaroslav Kysela, Derrick J. Brashear and David S. Miller");
60MODULE_DESCRIPTION("Sun CS4231");
61MODULE_LICENSE("GPL");
62MODULE_SUPPORTED_DEVICE("{{Sun,CS4231}}");
63
64typedef struct snd_cs4231 {
65 spinlock_t lock;
66 void __iomem *port;
67#ifdef EBUS_SUPPORT
68 struct ebus_dma_info eb2c;
69 struct ebus_dma_info eb2p;
70#endif
71
72 u32 flags;
73#define CS4231_FLAG_EBUS 0x00000001
74#define CS4231_FLAG_PLAYBACK 0x00000002
75#define CS4231_FLAG_CAPTURE 0x00000004
76
77 snd_card_t *card;
78 snd_pcm_t *pcm;
79 snd_pcm_substream_t *playback_substream;
80 unsigned int p_periods_sent;
81 snd_pcm_substream_t *capture_substream;
82 unsigned int c_periods_sent;
83 snd_timer_t *timer;
84
85 unsigned short mode;
86#define CS4231_MODE_NONE 0x0000
87#define CS4231_MODE_PLAY 0x0001
88#define CS4231_MODE_RECORD 0x0002
89#define CS4231_MODE_TIMER 0x0004
90#define CS4231_MODE_OPEN (CS4231_MODE_PLAY|CS4231_MODE_RECORD|CS4231_MODE_TIMER)
91
92 unsigned char image[32]; /* registers image */
93 int mce_bit;
94 int calibrate_mute;
95 struct semaphore mce_mutex;
96 struct semaphore open_mutex;
97
98 union {
99#ifdef SBUS_SUPPORT
100 struct sbus_dev *sdev;
101#endif
102#ifdef EBUS_SUPPORT
103 struct pci_dev *pdev;
104#endif
105 } dev_u;
106 unsigned int irq[2];
107 unsigned int regs_size;
108 struct snd_cs4231 *next;
109} cs4231_t;
110
111static cs4231_t *cs4231_list;
112
113/* Eventually we can use sound/isa/cs423x/cs4231_lib.c directly, but for
114 * now.... -DaveM
115 */
116
117/* IO ports */
118
119#define CS4231P(chip, x) ((chip)->port + c_d_c_CS4231##x)
120
121/* XXX offsets are different than PC ISA chips... */
122#define c_d_c_CS4231REGSEL 0x0
123#define c_d_c_CS4231REG 0x4
124#define c_d_c_CS4231STATUS 0x8
125#define c_d_c_CS4231PIO 0xc
126
127/* codec registers */
128
129#define CS4231_LEFT_INPUT 0x00 /* left input control */
130#define CS4231_RIGHT_INPUT 0x01 /* right input control */
131#define CS4231_AUX1_LEFT_INPUT 0x02 /* left AUX1 input control */
132#define CS4231_AUX1_RIGHT_INPUT 0x03 /* right AUX1 input control */
133#define CS4231_AUX2_LEFT_INPUT 0x04 /* left AUX2 input control */
134#define CS4231_AUX2_RIGHT_INPUT 0x05 /* right AUX2 input control */
135#define CS4231_LEFT_OUTPUT 0x06 /* left output control register */
136#define CS4231_RIGHT_OUTPUT 0x07 /* right output control register */
137#define CS4231_PLAYBK_FORMAT 0x08 /* clock and data format - playback - bits 7-0 MCE */
138#define CS4231_IFACE_CTRL 0x09 /* interface control - bits 7-2 MCE */
139#define CS4231_PIN_CTRL 0x0a /* pin control */
140#define CS4231_TEST_INIT 0x0b /* test and initialization */
141#define CS4231_MISC_INFO 0x0c /* miscellaneaous information */
142#define CS4231_LOOPBACK 0x0d /* loopback control */
143#define CS4231_PLY_UPR_CNT 0x0e /* playback upper base count */
144#define CS4231_PLY_LWR_CNT 0x0f /* playback lower base count */
145#define CS4231_ALT_FEATURE_1 0x10 /* alternate #1 feature enable */
146#define CS4231_ALT_FEATURE_2 0x11 /* alternate #2 feature enable */
147#define CS4231_LEFT_LINE_IN 0x12 /* left line input control */
148#define CS4231_RIGHT_LINE_IN 0x13 /* right line input control */
149#define CS4231_TIMER_LOW 0x14 /* timer low byte */
150#define CS4231_TIMER_HIGH 0x15 /* timer high byte */
151#define CS4231_LEFT_MIC_INPUT 0x16 /* left MIC input control register (InterWave only) */
152#define CS4231_RIGHT_MIC_INPUT 0x17 /* right MIC input control register (InterWave only) */
153#define CS4236_EXT_REG 0x17 /* extended register access */
154#define CS4231_IRQ_STATUS 0x18 /* irq status register */
155#define CS4231_LINE_LEFT_OUTPUT 0x19 /* left line output control register (InterWave only) */
156#define CS4231_VERSION 0x19 /* CS4231(A) - version values */
157#define CS4231_MONO_CTRL 0x1a /* mono input/output control */
158#define CS4231_LINE_RIGHT_OUTPUT 0x1b /* right line output control register (InterWave only) */
159#define CS4235_LEFT_MASTER 0x1b /* left master output control */
160#define CS4231_REC_FORMAT 0x1c /* clock and data format - record - bits 7-0 MCE */
161#define CS4231_PLY_VAR_FREQ 0x1d /* playback variable frequency */
162#define CS4235_RIGHT_MASTER 0x1d /* right master output control */
163#define CS4231_REC_UPR_CNT 0x1e /* record upper count */
164#define CS4231_REC_LWR_CNT 0x1f /* record lower count */
165
166/* definitions for codec register select port - CODECP( REGSEL ) */
167
168#define CS4231_INIT 0x80 /* CODEC is initializing */
169#define CS4231_MCE 0x40 /* mode change enable */
170#define CS4231_TRD 0x20 /* transfer request disable */
171
172/* definitions for codec status register - CODECP( STATUS ) */
173
174#define CS4231_GLOBALIRQ 0x01 /* IRQ is active */
175
176/* definitions for codec irq status */
177
178#define CS4231_PLAYBACK_IRQ 0x10
179#define CS4231_RECORD_IRQ 0x20
180#define CS4231_TIMER_IRQ 0x40
181#define CS4231_ALL_IRQS 0x70
182#define CS4231_REC_UNDERRUN 0x08
183#define CS4231_REC_OVERRUN 0x04
184#define CS4231_PLY_OVERRUN 0x02
185#define CS4231_PLY_UNDERRUN 0x01
186
187/* definitions for CS4231_LEFT_INPUT and CS4231_RIGHT_INPUT registers */
188
189#define CS4231_ENABLE_MIC_GAIN 0x20
190
191#define CS4231_MIXS_LINE 0x00
192#define CS4231_MIXS_AUX1 0x40
193#define CS4231_MIXS_MIC 0x80
194#define CS4231_MIXS_ALL 0xc0
195
196/* definitions for clock and data format register - CS4231_PLAYBK_FORMAT */
197
198#define CS4231_LINEAR_8 0x00 /* 8-bit unsigned data */
199#define CS4231_ALAW_8 0x60 /* 8-bit A-law companded */
200#define CS4231_ULAW_8 0x20 /* 8-bit U-law companded */
201#define CS4231_LINEAR_16 0x40 /* 16-bit twos complement data - little endian */
202#define CS4231_LINEAR_16_BIG 0xc0 /* 16-bit twos complement data - big endian */
203#define CS4231_ADPCM_16 0xa0 /* 16-bit ADPCM */
204#define CS4231_STEREO 0x10 /* stereo mode */
205/* bits 3-1 define frequency divisor */
206#define CS4231_XTAL1 0x00 /* 24.576 crystal */
207#define CS4231_XTAL2 0x01 /* 16.9344 crystal */
208
209/* definitions for interface control register - CS4231_IFACE_CTRL */
210
211#define CS4231_RECORD_PIO 0x80 /* record PIO enable */
212#define CS4231_PLAYBACK_PIO 0x40 /* playback PIO enable */
213#define CS4231_CALIB_MODE 0x18 /* calibration mode bits */
214#define CS4231_AUTOCALIB 0x08 /* auto calibrate */
215#define CS4231_SINGLE_DMA 0x04 /* use single DMA channel */
216#define CS4231_RECORD_ENABLE 0x02 /* record enable */
217#define CS4231_PLAYBACK_ENABLE 0x01 /* playback enable */
218
219/* definitions for pin control register - CS4231_PIN_CTRL */
220
221#define CS4231_IRQ_ENABLE 0x02 /* enable IRQ */
222#define CS4231_XCTL1 0x40 /* external control #1 */
223#define CS4231_XCTL0 0x80 /* external control #0 */
224
225/* definitions for test and init register - CS4231_TEST_INIT */
226
227#define CS4231_CALIB_IN_PROGRESS 0x20 /* auto calibrate in progress */
228#define CS4231_DMA_REQUEST 0x10 /* DMA request in progress */
229
230/* definitions for misc control register - CS4231_MISC_INFO */
231
232#define CS4231_MODE2 0x40 /* MODE 2 */
233#define CS4231_IW_MODE3 0x6c /* MODE 3 - InterWave enhanced mode */
234#define CS4231_4236_MODE3 0xe0 /* MODE 3 - CS4236+ enhanced mode */
235
236/* definitions for alternate feature 1 register - CS4231_ALT_FEATURE_1 */
237
238#define CS4231_DACZ 0x01 /* zero DAC when underrun */
239#define CS4231_TIMER_ENABLE 0x40 /* codec timer enable */
240#define CS4231_OLB 0x80 /* output level bit */
241
242/* SBUS DMA register defines. */
243
244#define APCCSR 0x10UL /* APC DMA CSR */
245#define APCCVA 0x20UL /* APC Capture DMA Address */
246#define APCCC 0x24UL /* APC Capture Count */
247#define APCCNVA 0x28UL /* APC Capture DMA Next Address */
248#define APCCNC 0x2cUL /* APC Capture Next Count */
249#define APCPVA 0x30UL /* APC Play DMA Address */
250#define APCPC 0x34UL /* APC Play Count */
251#define APCPNVA 0x38UL /* APC Play DMA Next Address */
252#define APCPNC 0x3cUL /* APC Play Next Count */
253
254/* APCCSR bits */
255
256#define APC_INT_PENDING 0x800000 /* Interrupt Pending */
257#define APC_PLAY_INT 0x400000 /* Playback interrupt */
258#define APC_CAPT_INT 0x200000 /* Capture interrupt */
259#define APC_GENL_INT 0x100000 /* General interrupt */
260#define APC_XINT_ENA 0x80000 /* General ext int. enable */
261#define APC_XINT_PLAY 0x40000 /* Playback ext intr */
262#define APC_XINT_CAPT 0x20000 /* Capture ext intr */
263#define APC_XINT_GENL 0x10000 /* Error ext intr */
264#define APC_XINT_EMPT 0x8000 /* Pipe empty interrupt (0 write to pva) */
265#define APC_XINT_PEMP 0x4000 /* Play pipe empty (pva and pnva not set) */
266#define APC_XINT_PNVA 0x2000 /* Playback NVA dirty */
267#define APC_XINT_PENA 0x1000 /* play pipe empty Int enable */
268#define APC_XINT_COVF 0x800 /* Cap data dropped on floor */
269#define APC_XINT_CNVA 0x400 /* Capture NVA dirty */
270#define APC_XINT_CEMP 0x200 /* Capture pipe empty (cva and cnva not set) */
271#define APC_XINT_CENA 0x100 /* Cap. pipe empty int enable */
272#define APC_PPAUSE 0x80 /* Pause the play DMA */
273#define APC_CPAUSE 0x40 /* Pause the capture DMA */
274#define APC_CDC_RESET 0x20 /* CODEC RESET */
275#define APC_PDMA_READY 0x08 /* Play DMA Go */
276#define APC_CDMA_READY 0x04 /* Capture DMA Go */
277#define APC_CHIP_RESET 0x01 /* Reset the chip */
278
279/* EBUS DMA register offsets */
280
281#define EBDMA_CSR 0x00UL /* Control/Status */
282#define EBDMA_ADDR 0x04UL /* DMA Address */
283#define EBDMA_COUNT 0x08UL /* DMA Count */
284
285/*
286 * Some variables
287 */
288
289static unsigned char freq_bits[14] = {
290 /* 5510 */ 0x00 | CS4231_XTAL2,
291 /* 6620 */ 0x0E | CS4231_XTAL2,
292 /* 8000 */ 0x00 | CS4231_XTAL1,
293 /* 9600 */ 0x0E | CS4231_XTAL1,
294 /* 11025 */ 0x02 | CS4231_XTAL2,
295 /* 16000 */ 0x02 | CS4231_XTAL1,
296 /* 18900 */ 0x04 | CS4231_XTAL2,
297 /* 22050 */ 0x06 | CS4231_XTAL2,
298 /* 27042 */ 0x04 | CS4231_XTAL1,
299 /* 32000 */ 0x06 | CS4231_XTAL1,
300 /* 33075 */ 0x0C | CS4231_XTAL2,
301 /* 37800 */ 0x08 | CS4231_XTAL2,
302 /* 44100 */ 0x0A | CS4231_XTAL2,
303 /* 48000 */ 0x0C | CS4231_XTAL1
304};
305
306static unsigned int rates[14] = {
307 5510, 6620, 8000, 9600, 11025, 16000, 18900, 22050,
308 27042, 32000, 33075, 37800, 44100, 48000
309};
310
311static snd_pcm_hw_constraint_list_t hw_constraints_rates = {
312 .count = 14,
313 .list = rates,
314};
315
316static int snd_cs4231_xrate(snd_pcm_runtime_t *runtime)
317{
318 return snd_pcm_hw_constraint_list(runtime, 0,
319 SNDRV_PCM_HW_PARAM_RATE,
320 &hw_constraints_rates);
321}
322
323static unsigned char snd_cs4231_original_image[32] =
324{
325 0x00, /* 00/00 - lic */
326 0x00, /* 01/01 - ric */
327 0x9f, /* 02/02 - la1ic */
328 0x9f, /* 03/03 - ra1ic */
329 0x9f, /* 04/04 - la2ic */
330 0x9f, /* 05/05 - ra2ic */
331 0xbf, /* 06/06 - loc */
332 0xbf, /* 07/07 - roc */
333 0x20, /* 08/08 - pdfr */
334 CS4231_AUTOCALIB, /* 09/09 - ic */
335 0x00, /* 0a/10 - pc */
336 0x00, /* 0b/11 - ti */
337 CS4231_MODE2, /* 0c/12 - mi */
338 0x00, /* 0d/13 - lbc */
339 0x00, /* 0e/14 - pbru */
340 0x00, /* 0f/15 - pbrl */
341 0x80, /* 10/16 - afei */
342 0x01, /* 11/17 - afeii */
343 0x9f, /* 12/18 - llic */
344 0x9f, /* 13/19 - rlic */
345 0x00, /* 14/20 - tlb */
346 0x00, /* 15/21 - thb */
347 0x00, /* 16/22 - la3mic/reserved */
348 0x00, /* 17/23 - ra3mic/reserved */
349 0x00, /* 18/24 - afs */
350 0x00, /* 19/25 - lamoc/version */
351 0x00, /* 1a/26 - mioc */
352 0x00, /* 1b/27 - ramoc/reserved */
353 0x20, /* 1c/28 - cdfr */
354 0x00, /* 1d/29 - res4 */
355 0x00, /* 1e/30 - cbru */
356 0x00, /* 1f/31 - cbrl */
357};
358
359static u8 __cs4231_readb(cs4231_t *cp, void __iomem *reg_addr)
360{
361#ifdef EBUS_SUPPORT
362 if (cp->flags & CS4231_FLAG_EBUS) {
363 return readb(reg_addr);
364 } else {
365#endif
366#ifdef SBUS_SUPPORT
367 return sbus_readb(reg_addr);
368#endif
369#ifdef EBUS_SUPPORT
370 }
371#endif
372}
373
374static void __cs4231_writeb(cs4231_t *cp, u8 val, void __iomem *reg_addr)
375{
376#ifdef EBUS_SUPPORT
377 if (cp->flags & CS4231_FLAG_EBUS) {
378 return writeb(val, reg_addr);
379 } else {
380#endif
381#ifdef SBUS_SUPPORT
382 return sbus_writeb(val, reg_addr);
383#endif
384#ifdef EBUS_SUPPORT
385 }
386#endif
387}
388
389/*
390 * Basic I/O functions
391 */
392
393static void snd_cs4231_outm(cs4231_t *chip, unsigned char reg,
394 unsigned char mask, unsigned char value)
395{
396 int timeout;
397 unsigned char tmp;
398
399 for (timeout = 250;
400 timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
401 timeout--)
402 udelay(100);
403#ifdef CONFIG_SND_DEBUG
404 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
405 snd_printk("outm: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
406#endif
407 if (chip->calibrate_mute) {
408 chip->image[reg] &= mask;
409 chip->image[reg] |= value;
410 } else {
411 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
412 mb();
413 tmp = (chip->image[reg] & mask) | value;
414 __cs4231_writeb(chip, tmp, CS4231P(chip, REG));
415 chip->image[reg] = tmp;
416 mb();
417 }
418}
419
420static void snd_cs4231_dout(cs4231_t *chip, unsigned char reg, unsigned char value)
421{
422 int timeout;
423
424 for (timeout = 250;
425 timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
426 timeout--)
427 udelay(100);
428 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
429 __cs4231_writeb(chip, value, CS4231P(chip, REG));
430 mb();
431}
432
433static void snd_cs4231_out(cs4231_t *chip, unsigned char reg, unsigned char value)
434{
435 int timeout;
436
437 for (timeout = 250;
438 timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
439 timeout--)
440 udelay(100);
441#ifdef CONFIG_SND_DEBUG
442 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
443 snd_printk("out: auto calibration time out - reg = 0x%x, value = 0x%x\n", reg, value);
444#endif
445 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
446 __cs4231_writeb(chip, value, CS4231P(chip, REG));
447 chip->image[reg] = value;
448 mb();
449#if 0
450 printk("codec out - reg 0x%x = 0x%x\n", chip->mce_bit | reg, value);
451#endif
452}
453
454static unsigned char snd_cs4231_in(cs4231_t *chip, unsigned char reg)
455{
456 int timeout;
457 unsigned char ret;
458
459 for (timeout = 250;
460 timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
461 timeout--)
462 udelay(100);
463#ifdef CONFIG_SND_DEBUG
464 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
465 snd_printk("in: auto calibration time out - reg = 0x%x\n", reg);
466#endif
467 __cs4231_writeb(chip, chip->mce_bit | reg, CS4231P(chip, REGSEL));
468 mb();
469 ret = __cs4231_readb(chip, CS4231P(chip, REG));
470#if 0
471 printk("codec in - reg 0x%x = 0x%x\n", chip->mce_bit | reg, ret);
472#endif
473 return ret;
474}
475
476#if 0
477
478static void snd_cs4231_debug(cs4231_t *chip)
479{
480 printk("CS4231 REGS: INDEX = 0x%02x ",
481 __cs4231_readb(chip, CS4231P(chip, REGSEL)));
482 printk(" STATUS = 0x%02x\n",
483 __cs4231_readb(chip, CS4231P(chip, STATUS)));
484 printk(" 0x00: left input = 0x%02x ", snd_cs4231_in(chip, 0x00));
485 printk(" 0x10: alt 1 (CFIG 2) = 0x%02x\n", snd_cs4231_in(chip, 0x10));
486 printk(" 0x01: right input = 0x%02x ", snd_cs4231_in(chip, 0x01));
487 printk(" 0x11: alt 2 (CFIG 3) = 0x%02x\n", snd_cs4231_in(chip, 0x11));
488 printk(" 0x02: GF1 left input = 0x%02x ", snd_cs4231_in(chip, 0x02));
489 printk(" 0x12: left line in = 0x%02x\n", snd_cs4231_in(chip, 0x12));
490 printk(" 0x03: GF1 right input = 0x%02x ", snd_cs4231_in(chip, 0x03));
491 printk(" 0x13: right line in = 0x%02x\n", snd_cs4231_in(chip, 0x13));
492 printk(" 0x04: CD left input = 0x%02x ", snd_cs4231_in(chip, 0x04));
493 printk(" 0x14: timer low = 0x%02x\n", snd_cs4231_in(chip, 0x14));
494 printk(" 0x05: CD right input = 0x%02x ", snd_cs4231_in(chip, 0x05));
495 printk(" 0x15: timer high = 0x%02x\n", snd_cs4231_in(chip, 0x15));
496 printk(" 0x06: left output = 0x%02x ", snd_cs4231_in(chip, 0x06));
497 printk(" 0x16: left MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x16));
498 printk(" 0x07: right output = 0x%02x ", snd_cs4231_in(chip, 0x07));
499 printk(" 0x17: right MIC (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x17));
500 printk(" 0x08: playback format = 0x%02x ", snd_cs4231_in(chip, 0x08));
501 printk(" 0x18: IRQ status = 0x%02x\n", snd_cs4231_in(chip, 0x18));
502 printk(" 0x09: iface (CFIG 1) = 0x%02x ", snd_cs4231_in(chip, 0x09));
503 printk(" 0x19: left line out = 0x%02x\n", snd_cs4231_in(chip, 0x19));
504 printk(" 0x0a: pin control = 0x%02x ", snd_cs4231_in(chip, 0x0a));
505 printk(" 0x1a: mono control = 0x%02x\n", snd_cs4231_in(chip, 0x1a));
506 printk(" 0x0b: init & status = 0x%02x ", snd_cs4231_in(chip, 0x0b));
507 printk(" 0x1b: right line out = 0x%02x\n", snd_cs4231_in(chip, 0x1b));
508 printk(" 0x0c: revision & mode = 0x%02x ", snd_cs4231_in(chip, 0x0c));
509 printk(" 0x1c: record format = 0x%02x\n", snd_cs4231_in(chip, 0x1c));
510 printk(" 0x0d: loopback = 0x%02x ", snd_cs4231_in(chip, 0x0d));
511 printk(" 0x1d: var freq (PnP) = 0x%02x\n", snd_cs4231_in(chip, 0x1d));
512 printk(" 0x0e: ply upr count = 0x%02x ", snd_cs4231_in(chip, 0x0e));
513 printk(" 0x1e: rec upr count = 0x%02x\n", snd_cs4231_in(chip, 0x1e));
514 printk(" 0x0f: ply lwr count = 0x%02x ", snd_cs4231_in(chip, 0x0f));
515 printk(" 0x1f: rec lwr count = 0x%02x\n", snd_cs4231_in(chip, 0x1f));
516}
517
518#endif
519
520/*
521 * CS4231 detection / MCE routines
522 */
523
524static void snd_cs4231_busy_wait(cs4231_t *chip)
525{
526 int timeout;
527
528 /* huh.. looks like this sequence is proper for CS4231A chip (GUS MAX) */
529 for (timeout = 5; timeout > 0; timeout--)
530 __cs4231_readb(chip, CS4231P(chip, REGSEL));
531 /* end of cleanup sequence */
532 for (timeout = 250;
533 timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT);
534 timeout--)
535 udelay(100);
536}
537
538static void snd_cs4231_mce_up(cs4231_t *chip)
539{
540 unsigned long flags;
541 int timeout;
542
543 spin_lock_irqsave(&chip->lock, flags);
544 for (timeout = 250; timeout > 0 && (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT); timeout--)
545 udelay(100);
546#ifdef CONFIG_SND_DEBUG
547 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
548 snd_printk("mce_up - auto calibration time out (0)\n");
549#endif
550 chip->mce_bit |= CS4231_MCE;
551 timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
552 if (timeout == 0x80)
553 snd_printk("mce_up [%p]: serious init problem - codec still busy\n", chip->port);
554 if (!(timeout & CS4231_MCE))
555 __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
556 spin_unlock_irqrestore(&chip->lock, flags);
557}
558
559static void snd_cs4231_mce_down(cs4231_t *chip)
560{
561 unsigned long flags;
562 int timeout;
563
564 spin_lock_irqsave(&chip->lock, flags);
565 snd_cs4231_busy_wait(chip);
566#if 0
567 printk("(1) timeout = %i\n", timeout);
568#endif
569#ifdef CONFIG_SND_DEBUG
570 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
571 snd_printk("mce_down [%p] - auto calibration time out (0)\n", CS4231P(chip, REGSEL));
572#endif
573 chip->mce_bit &= ~CS4231_MCE;
574 timeout = __cs4231_readb(chip, CS4231P(chip, REGSEL));
575 __cs4231_writeb(chip, chip->mce_bit | (timeout & 0x1f), CS4231P(chip, REGSEL));
576 if (timeout == 0x80)
577 snd_printk("mce_down [%p]: serious init problem - codec still busy\n", chip->port);
578 if ((timeout & CS4231_MCE) == 0) {
579 spin_unlock_irqrestore(&chip->lock, flags);
580 return;
581 }
582 snd_cs4231_busy_wait(chip);
583
584 /* calibration process */
585
586 for (timeout = 500; timeout > 0 && (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0; timeout--)
587 udelay(100);
588 if ((snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) == 0) {
589 snd_printd("cs4231_mce_down - auto calibration time out (1)\n");
590 spin_unlock_irqrestore(&chip->lock, flags);
591 return;
592 }
593#if 0
594 printk("(2) timeout = %i, jiffies = %li\n", timeout, jiffies);
595#endif
596 /* in 10ms increments, check condition, up to 250ms */
597 timeout = 25;
598 while (snd_cs4231_in(chip, CS4231_TEST_INIT) & CS4231_CALIB_IN_PROGRESS) {
599 spin_unlock_irqrestore(&chip->lock, flags);
600 if (--timeout < 0) {
601 snd_printk("mce_down - auto calibration time out (2)\n");
602 return;
603 }
604 msleep(10);
605 spin_lock_irqsave(&chip->lock, flags);
606 }
607#if 0
608 printk("(3) jiffies = %li\n", jiffies);
609#endif
610 /* in 10ms increments, check condition, up to 100ms */
611 timeout = 10;
612 while (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT) {
613 spin_unlock_irqrestore(&chip->lock, flags);
614 if (--timeout < 0) {
615 snd_printk("mce_down - auto calibration time out (3)\n");
616 return;
617 }
618 msleep(10);
619 spin_lock_irqsave(&chip->lock, flags);
620 }
621 spin_unlock_irqrestore(&chip->lock, flags);
622#if 0
623 printk("(4) jiffies = %li\n", jiffies);
624 snd_printk("mce_down - exit = 0x%x\n", __cs4231_readb(chip, CS4231P(chip, REGSEL)));
625#endif
626}
627
628#if 0 /* Unused for now... */
629static unsigned int snd_cs4231_get_count(unsigned char format, unsigned int size)
630{
631 switch (format & 0xe0) {
632 case CS4231_LINEAR_16:
633 case CS4231_LINEAR_16_BIG:
634 size >>= 1;
635 break;
636 case CS4231_ADPCM_16:
637 return size >> 2;
638 }
639 if (format & CS4231_STEREO)
640 size >>= 1;
641 return size;
642}
643#endif
644
645#ifdef EBUS_SUPPORT
646static void snd_cs4231_ebus_advance_dma(struct ebus_dma_info *p, snd_pcm_substream_t *substream, unsigned int *periods_sent)
647{
648 snd_pcm_runtime_t *runtime = substream->runtime;
649
650 while (1) {
651 unsigned int dma_size = snd_pcm_lib_period_bytes(substream);
652 unsigned int offset = dma_size * (*periods_sent);
653
654 if (dma_size >= (1 << 24))
655 BUG();
656
657 if (ebus_dma_request(p, runtime->dma_addr + offset, dma_size))
658 return;
659#if 0
660 printk("ebus_advance: Sent period %u (size[%x] offset[%x])\n",
661 (*periods_sent), dma_size, offset);
662#endif
663 (*periods_sent) = ((*periods_sent) + 1) % runtime->periods;
664 }
665}
666#endif
667
668static void cs4231_dma_trigger(cs4231_t *chip, unsigned int what, int on)
669{
670#ifdef EBUS_SUPPORT
671 if (chip->flags & CS4231_FLAG_EBUS) {
672 if (what & CS4231_PLAYBACK_ENABLE) {
673 if (on) {
674 ebus_dma_prepare(&chip->eb2p, 0);
675 ebus_dma_enable(&chip->eb2p, 1);
676 snd_cs4231_ebus_advance_dma(&chip->eb2p,
677 chip->playback_substream,
678 &chip->p_periods_sent);
679 } else {
680 ebus_dma_enable(&chip->eb2p, 0);
681 }
682 }
683 if (what & CS4231_RECORD_ENABLE) {
684 if (on) {
685 ebus_dma_prepare(&chip->eb2c, 1);
686 ebus_dma_enable(&chip->eb2c, 1);
687 snd_cs4231_ebus_advance_dma(&chip->eb2c,
688 chip->capture_substream,
689 &chip->c_periods_sent);
690 } else {
691 ebus_dma_enable(&chip->eb2c, 0);
692 }
693 }
694 } else {
695#endif
696#ifdef SBUS_SUPPORT
697#endif
698#ifdef EBUS_SUPPORT
699 }
700#endif
701}
702
703static int snd_cs4231_trigger(snd_pcm_substream_t *substream, int cmd)
704{
705 cs4231_t *chip = snd_pcm_substream_chip(substream);
706 int result = 0;
707
708 switch (cmd) {
709 case SNDRV_PCM_TRIGGER_START:
710 case SNDRV_PCM_TRIGGER_STOP:
711 {
712 unsigned int what = 0;
713 snd_pcm_substream_t *s;
714 struct list_head *pos;
715 unsigned long flags;
716
717 snd_pcm_group_for_each(pos, substream) {
718 s = snd_pcm_group_substream_entry(pos);
719 if (s == chip->playback_substream) {
720 what |= CS4231_PLAYBACK_ENABLE;
721 snd_pcm_trigger_done(s, substream);
722 } else if (s == chip->capture_substream) {
723 what |= CS4231_RECORD_ENABLE;
724 snd_pcm_trigger_done(s, substream);
725 }
726 }
727
728#if 0
729 printk("TRIGGER: what[%x] on(%d)\n",
730 what, (cmd == SNDRV_PCM_TRIGGER_START));
731#endif
732
733 spin_lock_irqsave(&chip->lock, flags);
734 if (cmd == SNDRV_PCM_TRIGGER_START) {
735 cs4231_dma_trigger(chip, what, 1);
736 chip->image[CS4231_IFACE_CTRL] |= what;
737 if (what & CS4231_PLAYBACK_ENABLE) {
738 snd_cs4231_out(chip, CS4231_PLY_LWR_CNT, 0xff);
739 snd_cs4231_out(chip, CS4231_PLY_UPR_CNT, 0xff);
740 }
741 if (what & CS4231_RECORD_ENABLE) {
742 snd_cs4231_out(chip, CS4231_REC_LWR_CNT, 0xff);
743 snd_cs4231_out(chip, CS4231_REC_UPR_CNT, 0xff);
744 }
745 } else {
746 cs4231_dma_trigger(chip, what, 0);
747 chip->image[CS4231_IFACE_CTRL] &= ~what;
748 }
749 snd_cs4231_out(chip, CS4231_IFACE_CTRL,
750 chip->image[CS4231_IFACE_CTRL]);
751 spin_unlock_irqrestore(&chip->lock, flags);
752 break;
753 }
754 default:
755 result = -EINVAL;
756 break;
757 }
758#if 0
759 snd_cs4231_debug(chip);
760#endif
761 return result;
762}
763
764/*
765 * CODEC I/O
766 */
767
768static unsigned char snd_cs4231_get_rate(unsigned int rate)
769{
770 int i;
771
772 for (i = 0; i < 14; i++)
773 if (rate == rates[i])
774 return freq_bits[i];
775 // snd_BUG();
776 return freq_bits[13];
777}
778
779static unsigned char snd_cs4231_get_format(cs4231_t *chip, int format, int channels)
780{
781 unsigned char rformat;
782
783 rformat = CS4231_LINEAR_8;
784 switch (format) {
785 case SNDRV_PCM_FORMAT_MU_LAW: rformat = CS4231_ULAW_8; break;
786 case SNDRV_PCM_FORMAT_A_LAW: rformat = CS4231_ALAW_8; break;
787 case SNDRV_PCM_FORMAT_S16_LE: rformat = CS4231_LINEAR_16; break;
788 case SNDRV_PCM_FORMAT_S16_BE: rformat = CS4231_LINEAR_16_BIG; break;
789 case SNDRV_PCM_FORMAT_IMA_ADPCM: rformat = CS4231_ADPCM_16; break;
790 }
791 if (channels > 1)
792 rformat |= CS4231_STEREO;
793#if 0
794 snd_printk("get_format: 0x%x (mode=0x%x)\n", format, mode);
795#endif
796 return rformat;
797}
798
799static void snd_cs4231_calibrate_mute(cs4231_t *chip, int mute)
800{
801 unsigned long flags;
802
803 mute = mute ? 1 : 0;
804 spin_lock_irqsave(&chip->lock, flags);
805 if (chip->calibrate_mute == mute) {
806 spin_unlock_irqrestore(&chip->lock, flags);
807 return;
808 }
809 if (!mute) {
810 snd_cs4231_dout(chip, CS4231_LEFT_INPUT,
811 chip->image[CS4231_LEFT_INPUT]);
812 snd_cs4231_dout(chip, CS4231_RIGHT_INPUT,
813 chip->image[CS4231_RIGHT_INPUT]);
814 snd_cs4231_dout(chip, CS4231_LOOPBACK,
815 chip->image[CS4231_LOOPBACK]);
816 }
817 snd_cs4231_dout(chip, CS4231_AUX1_LEFT_INPUT,
818 mute ? 0x80 : chip->image[CS4231_AUX1_LEFT_INPUT]);
819 snd_cs4231_dout(chip, CS4231_AUX1_RIGHT_INPUT,
820 mute ? 0x80 : chip->image[CS4231_AUX1_RIGHT_INPUT]);
821 snd_cs4231_dout(chip, CS4231_AUX2_LEFT_INPUT,
822 mute ? 0x80 : chip->image[CS4231_AUX2_LEFT_INPUT]);
823 snd_cs4231_dout(chip, CS4231_AUX2_RIGHT_INPUT,
824 mute ? 0x80 : chip->image[CS4231_AUX2_RIGHT_INPUT]);
825 snd_cs4231_dout(chip, CS4231_LEFT_OUTPUT,
826 mute ? 0x80 : chip->image[CS4231_LEFT_OUTPUT]);
827 snd_cs4231_dout(chip, CS4231_RIGHT_OUTPUT,
828 mute ? 0x80 : chip->image[CS4231_RIGHT_OUTPUT]);
829 snd_cs4231_dout(chip, CS4231_LEFT_LINE_IN,
830 mute ? 0x80 : chip->image[CS4231_LEFT_LINE_IN]);
831 snd_cs4231_dout(chip, CS4231_RIGHT_LINE_IN,
832 mute ? 0x80 : chip->image[CS4231_RIGHT_LINE_IN]);
833 snd_cs4231_dout(chip, CS4231_MONO_CTRL,
834 mute ? 0xc0 : chip->image[CS4231_MONO_CTRL]);
835 chip->calibrate_mute = mute;
836 spin_unlock_irqrestore(&chip->lock, flags);
837}
838
839static void snd_cs4231_playback_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
840 unsigned char pdfr)
841{
842 unsigned long flags;
843
844 down(&chip->mce_mutex);
845 snd_cs4231_calibrate_mute(chip, 1);
846
847 snd_cs4231_mce_up(chip);
848
849 spin_lock_irqsave(&chip->lock, flags);
850 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
851 (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) ?
852 (pdfr & 0xf0) | (chip->image[CS4231_REC_FORMAT] & 0x0f) :
853 pdfr);
854 spin_unlock_irqrestore(&chip->lock, flags);
855
856 snd_cs4231_mce_down(chip);
857
858 snd_cs4231_calibrate_mute(chip, 0);
859 up(&chip->mce_mutex);
860}
861
862static void snd_cs4231_capture_format(cs4231_t *chip, snd_pcm_hw_params_t *params,
863 unsigned char cdfr)
864{
865 unsigned long flags;
866
867 down(&chip->mce_mutex);
868 snd_cs4231_calibrate_mute(chip, 1);
869
870 snd_cs4231_mce_up(chip);
871
872 spin_lock_irqsave(&chip->lock, flags);
873 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE)) {
874 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT,
875 ((chip->image[CS4231_PLAYBK_FORMAT]) & 0xf0) |
876 (cdfr & 0x0f));
877 spin_unlock_irqrestore(&chip->lock, flags);
878 snd_cs4231_mce_down(chip);
879 snd_cs4231_mce_up(chip);
880 spin_lock_irqsave(&chip->lock, flags);
881 }
882 snd_cs4231_out(chip, CS4231_REC_FORMAT, cdfr);
883 spin_unlock_irqrestore(&chip->lock, flags);
884
885 snd_cs4231_mce_down(chip);
886
887 snd_cs4231_calibrate_mute(chip, 0);
888 up(&chip->mce_mutex);
889}
890
891/*
892 * Timer interface
893 */
894
895static unsigned long snd_cs4231_timer_resolution(snd_timer_t *timer)
896{
897 cs4231_t *chip = snd_timer_chip(timer);
898
899 return chip->image[CS4231_PLAYBK_FORMAT] & 1 ? 9969 : 9920;
900}
901
902static int snd_cs4231_timer_start(snd_timer_t *timer)
903{
904 unsigned long flags;
905 unsigned int ticks;
906 cs4231_t *chip = snd_timer_chip(timer);
907
908 spin_lock_irqsave(&chip->lock, flags);
909 ticks = timer->sticks;
910 if ((chip->image[CS4231_ALT_FEATURE_1] & CS4231_TIMER_ENABLE) == 0 ||
911 (unsigned char)(ticks >> 8) != chip->image[CS4231_TIMER_HIGH] ||
912 (unsigned char)ticks != chip->image[CS4231_TIMER_LOW]) {
913 snd_cs4231_out(chip, CS4231_TIMER_HIGH,
914 chip->image[CS4231_TIMER_HIGH] =
915 (unsigned char) (ticks >> 8));
916 snd_cs4231_out(chip, CS4231_TIMER_LOW,
917 chip->image[CS4231_TIMER_LOW] =
918 (unsigned char) ticks);
919 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
920 chip->image[CS4231_ALT_FEATURE_1] | CS4231_TIMER_ENABLE);
921 }
922 spin_unlock_irqrestore(&chip->lock, flags);
923
924 return 0;
925}
926
927static int snd_cs4231_timer_stop(snd_timer_t *timer)
928{
929 unsigned long flags;
930 cs4231_t *chip = snd_timer_chip(timer);
931
932 spin_lock_irqsave(&chip->lock, flags);
933 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1,
934 chip->image[CS4231_ALT_FEATURE_1] &= ~CS4231_TIMER_ENABLE);
935 spin_unlock_irqrestore(&chip->lock, flags);
936
937 return 0;
938}
939
940static void snd_cs4231_init(cs4231_t *chip)
941{
942 unsigned long flags;
943
944 snd_cs4231_mce_down(chip);
945
946#ifdef SNDRV_DEBUG_MCE
947 snd_printk("init: (1)\n");
948#endif
949 snd_cs4231_mce_up(chip);
950 spin_lock_irqsave(&chip->lock, flags);
951 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
952 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO |
953 CS4231_CALIB_MODE);
954 chip->image[CS4231_IFACE_CTRL] |= CS4231_AUTOCALIB;
955 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
956 spin_unlock_irqrestore(&chip->lock, flags);
957 snd_cs4231_mce_down(chip);
958
959#ifdef SNDRV_DEBUG_MCE
960 snd_printk("init: (2)\n");
961#endif
962
963 snd_cs4231_mce_up(chip);
964 spin_lock_irqsave(&chip->lock, flags);
965 snd_cs4231_out(chip, CS4231_ALT_FEATURE_1, chip->image[CS4231_ALT_FEATURE_1]);
966 spin_unlock_irqrestore(&chip->lock, flags);
967 snd_cs4231_mce_down(chip);
968
969#ifdef SNDRV_DEBUG_MCE
970 snd_printk("init: (3) - afei = 0x%x\n", chip->image[CS4231_ALT_FEATURE_1]);
971#endif
972
973 spin_lock_irqsave(&chip->lock, flags);
974 snd_cs4231_out(chip, CS4231_ALT_FEATURE_2, chip->image[CS4231_ALT_FEATURE_2]);
975 spin_unlock_irqrestore(&chip->lock, flags);
976
977 snd_cs4231_mce_up(chip);
978 spin_lock_irqsave(&chip->lock, flags);
979 snd_cs4231_out(chip, CS4231_PLAYBK_FORMAT, chip->image[CS4231_PLAYBK_FORMAT]);
980 spin_unlock_irqrestore(&chip->lock, flags);
981 snd_cs4231_mce_down(chip);
982
983#ifdef SNDRV_DEBUG_MCE
984 snd_printk("init: (4)\n");
985#endif
986
987 snd_cs4231_mce_up(chip);
988 spin_lock_irqsave(&chip->lock, flags);
989 snd_cs4231_out(chip, CS4231_REC_FORMAT, chip->image[CS4231_REC_FORMAT]);
990 spin_unlock_irqrestore(&chip->lock, flags);
991 snd_cs4231_mce_down(chip);
992
993#ifdef SNDRV_DEBUG_MCE
994 snd_printk("init: (5)\n");
995#endif
996}
997
998static int snd_cs4231_open(cs4231_t *chip, unsigned int mode)
999{
1000 unsigned long flags;
1001
1002 down(&chip->open_mutex);
1003 if ((chip->mode & mode)) {
1004 up(&chip->open_mutex);
1005 return -EAGAIN;
1006 }
1007 if (chip->mode & CS4231_MODE_OPEN) {
1008 chip->mode |= mode;
1009 up(&chip->open_mutex);
1010 return 0;
1011 }
1012 /* ok. now enable and ack CODEC IRQ */
1013 spin_lock_irqsave(&chip->lock, flags);
1014 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
1015 CS4231_RECORD_IRQ |
1016 CS4231_TIMER_IRQ);
1017 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
1018 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1019 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1020
1021 snd_cs4231_out(chip, CS4231_IRQ_STATUS, CS4231_PLAYBACK_IRQ |
1022 CS4231_RECORD_IRQ |
1023 CS4231_TIMER_IRQ);
1024 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
1025 spin_unlock_irqrestore(&chip->lock, flags);
1026
1027 chip->mode = mode;
1028 up(&chip->open_mutex);
1029 return 0;
1030}
1031
1032static void snd_cs4231_close(cs4231_t *chip, unsigned int mode)
1033{
1034 unsigned long flags;
1035
1036 down(&chip->open_mutex);
1037 chip->mode &= ~mode;
1038 if (chip->mode & CS4231_MODE_OPEN) {
1039 up(&chip->open_mutex);
1040 return;
1041 }
1042 snd_cs4231_calibrate_mute(chip, 1);
1043
1044 /* disable IRQ */
1045 spin_lock_irqsave(&chip->lock, flags);
1046 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
1047 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1048 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1049
1050 /* now disable record & playback */
1051
1052 if (chip->image[CS4231_IFACE_CTRL] &
1053 (CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
1054 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO)) {
1055 spin_unlock_irqrestore(&chip->lock, flags);
1056 snd_cs4231_mce_up(chip);
1057 spin_lock_irqsave(&chip->lock, flags);
1058 chip->image[CS4231_IFACE_CTRL] &=
1059 ~(CS4231_PLAYBACK_ENABLE | CS4231_PLAYBACK_PIO |
1060 CS4231_RECORD_ENABLE | CS4231_RECORD_PIO);
1061 snd_cs4231_out(chip, CS4231_IFACE_CTRL, chip->image[CS4231_IFACE_CTRL]);
1062 spin_unlock_irqrestore(&chip->lock, flags);
1063 snd_cs4231_mce_down(chip);
1064 spin_lock_irqsave(&chip->lock, flags);
1065 }
1066
1067 /* clear IRQ again */
1068 snd_cs4231_out(chip, CS4231_IRQ_STATUS, 0);
1069 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1070 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS)); /* clear IRQ */
1071 spin_unlock_irqrestore(&chip->lock, flags);
1072
1073 snd_cs4231_calibrate_mute(chip, 0);
1074
1075 chip->mode = 0;
1076 up(&chip->open_mutex);
1077}
1078
1079/*
1080 * timer open/close
1081 */
1082
1083static int snd_cs4231_timer_open(snd_timer_t *timer)
1084{
1085 cs4231_t *chip = snd_timer_chip(timer);
1086 snd_cs4231_open(chip, CS4231_MODE_TIMER);
1087 return 0;
1088}
1089
1090static int snd_cs4231_timer_close(snd_timer_t * timer)
1091{
1092 cs4231_t *chip = snd_timer_chip(timer);
1093 snd_cs4231_close(chip, CS4231_MODE_TIMER);
1094 return 0;
1095}
1096
1097static struct _snd_timer_hardware snd_cs4231_timer_table =
1098{
1099 .flags = SNDRV_TIMER_HW_AUTO,
1100 .resolution = 9945,
1101 .ticks = 65535,
1102 .open = snd_cs4231_timer_open,
1103 .close = snd_cs4231_timer_close,
1104 .c_resolution = snd_cs4231_timer_resolution,
1105 .start = snd_cs4231_timer_start,
1106 .stop = snd_cs4231_timer_stop,
1107};
1108
1109/*
1110 * ok.. exported functions..
1111 */
1112
1113static int snd_cs4231_playback_hw_params(snd_pcm_substream_t *substream,
1114 snd_pcm_hw_params_t *hw_params)
1115{
1116 cs4231_t *chip = snd_pcm_substream_chip(substream);
1117 unsigned char new_pdfr;
1118 int err;
1119
1120 if ((err = snd_pcm_lib_malloc_pages(substream,
1121 params_buffer_bytes(hw_params))) < 0)
1122 return err;
1123 new_pdfr = snd_cs4231_get_format(chip, params_format(hw_params),
1124 params_channels(hw_params)) |
1125 snd_cs4231_get_rate(params_rate(hw_params));
1126 snd_cs4231_playback_format(chip, hw_params, new_pdfr);
1127
1128 return 0;
1129}
1130
1131static int snd_cs4231_playback_hw_free(snd_pcm_substream_t *substream)
1132{
1133 return snd_pcm_lib_free_pages(substream);
1134}
1135
1136static int snd_cs4231_playback_prepare(snd_pcm_substream_t *substream)
1137{
1138 cs4231_t *chip = snd_pcm_substream_chip(substream);
1139 unsigned long flags;
1140
1141 spin_lock_irqsave(&chip->lock, flags);
1142 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_PLAYBACK_ENABLE |
1143 CS4231_PLAYBACK_PIO);
1144 spin_unlock_irqrestore(&chip->lock, flags);
1145
1146 return 0;
1147}
1148
1149static int snd_cs4231_capture_hw_params(snd_pcm_substream_t *substream,
1150 snd_pcm_hw_params_t *hw_params)
1151{
1152 cs4231_t *chip = snd_pcm_substream_chip(substream);
1153 unsigned char new_cdfr;
1154 int err;
1155
1156 if ((err = snd_pcm_lib_malloc_pages(substream,
1157 params_buffer_bytes(hw_params))) < 0)
1158 return err;
1159 new_cdfr = snd_cs4231_get_format(chip, params_format(hw_params),
1160 params_channels(hw_params)) |
1161 snd_cs4231_get_rate(params_rate(hw_params));
1162 snd_cs4231_capture_format(chip, hw_params, new_cdfr);
1163
1164 return 0;
1165}
1166
1167static int snd_cs4231_capture_hw_free(snd_pcm_substream_t *substream)
1168{
1169 return snd_pcm_lib_free_pages(substream);
1170}
1171
1172static int snd_cs4231_capture_prepare(snd_pcm_substream_t *substream)
1173{
1174 cs4231_t *chip = snd_pcm_substream_chip(substream);
1175 unsigned long flags;
1176
1177 spin_lock_irqsave(&chip->lock, flags);
1178 chip->image[CS4231_IFACE_CTRL] &= ~(CS4231_RECORD_ENABLE |
1179 CS4231_RECORD_PIO);
1180
1181 spin_unlock_irqrestore(&chip->lock, flags);
1182
1183 return 0;
1184}
1185
1186static void snd_cs4231_overrange(cs4231_t *chip)
1187{
1188 unsigned long flags;
1189 unsigned char res;
1190
1191 spin_lock_irqsave(&chip->lock, flags);
1192 res = snd_cs4231_in(chip, CS4231_TEST_INIT);
1193 spin_unlock_irqrestore(&chip->lock, flags);
1194
1195 if (res & (0x08 | 0x02)) /* detect overrange only above 0dB; may be user selectable? */
1196 chip->capture_substream->runtime->overrange++;
1197}
1198
1199static void snd_cs4231_generic_interrupt(cs4231_t *chip)
1200{
1201 unsigned long flags;
1202 unsigned char status;
1203
1204 status = snd_cs4231_in(chip, CS4231_IRQ_STATUS);
1205 if (!status)
1206 return;
1207
1208 if (status & CS4231_TIMER_IRQ) {
1209 if (chip->timer)
1210 snd_timer_interrupt(chip->timer, chip->timer->sticks);
1211 }
1212 if (status & CS4231_PLAYBACK_IRQ)
1213 snd_pcm_period_elapsed(chip->playback_substream);
1214 if (status & CS4231_RECORD_IRQ) {
1215 snd_cs4231_overrange(chip);
1216 snd_pcm_period_elapsed(chip->capture_substream);
1217 }
1218
1219 /* ACK the CS4231 interrupt. */
1220 spin_lock_irqsave(&chip->lock, flags);
1221 snd_cs4231_outm(chip, CS4231_IRQ_STATUS, ~CS4231_ALL_IRQS | ~status, 0);
1222 spin_unlock_irqrestore(&chip->lock, flags);
1223}
1224
1225#ifdef SBUS_SUPPORT
1226static irqreturn_t snd_cs4231_sbus_interrupt(int irq, void *dev_id, struct pt_regs *regs)
1227{
1228 cs4231_t *chip = dev_id;
1229 u32 csr;
1230
1231 csr = sbus_readl(chip->port + APCCSR);
1232 if (!(csr & (APC_INT_PENDING |
1233 APC_PLAY_INT |
1234 APC_CAPT_INT |
1235 APC_GENL_INT |
1236 APC_XINT_PEMP |
1237 APC_XINT_CEMP)))
1238 return IRQ_NONE;
1239
1240 /* ACK the APC interrupt. */
1241 sbus_writel(csr, chip->port + APCCSR);
1242
1243 snd_cs4231_generic_interrupt(chip);
1244
1245 return IRQ_HANDLED;
1246}
1247#endif
1248
1249#ifdef EBUS_SUPPORT
1250static void snd_cs4231_ebus_play_callback(struct ebus_dma_info *p, int event, void *cookie)
1251{
1252 cs4231_t *chip = cookie;
1253
1254 if (chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE) {
1255 snd_pcm_period_elapsed(chip->playback_substream);
1256 snd_cs4231_ebus_advance_dma(p, chip->playback_substream,
1257 &chip->p_periods_sent);
1258 }
1259}
1260
1261static void snd_cs4231_ebus_capture_callback(struct ebus_dma_info *p, int event, void *cookie)
1262{
1263 cs4231_t *chip = cookie;
1264
1265 if (chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE) {
1266 snd_pcm_period_elapsed(chip->capture_substream);
1267 snd_cs4231_ebus_advance_dma(p, chip->capture_substream,
1268 &chip->c_periods_sent);
1269 }
1270}
1271#endif
1272
1273static snd_pcm_uframes_t snd_cs4231_playback_pointer(snd_pcm_substream_t *substream)
1274{
1275 cs4231_t *chip = snd_pcm_substream_chip(substream);
1276 size_t ptr, residue, period_bytes;
1277
1278 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_PLAYBACK_ENABLE))
1279 return 0;
1280 period_bytes = snd_pcm_lib_period_bytes(substream);
1281 ptr = period_bytes * chip->p_periods_sent;
1282#ifdef EBUS_SUPPORT
1283 if (chip->flags & CS4231_FLAG_EBUS) {
1284 residue = ebus_dma_residue(&chip->eb2p);
1285 } else {
1286#endif
1287#ifdef SBUS_SUPPORT
1288 residue = sbus_readl(chip->port + APCPC);
1289#endif
1290#ifdef EBUS_SUPPORT
1291 }
1292#endif
1293 ptr += (period_bytes - residue);
1294 return bytes_to_frames(substream->runtime, ptr);
1295}
1296
1297static snd_pcm_uframes_t snd_cs4231_capture_pointer(snd_pcm_substream_t * substream)
1298{
1299 cs4231_t *chip = snd_pcm_substream_chip(substream);
1300 size_t ptr, residue, period_bytes;
1301
1302 if (!(chip->image[CS4231_IFACE_CTRL] & CS4231_RECORD_ENABLE))
1303 return 0;
1304 period_bytes = snd_pcm_lib_period_bytes(substream);
1305 ptr = period_bytes * chip->c_periods_sent;
1306#ifdef EBUS_SUPPORT
1307 if (chip->flags & CS4231_FLAG_EBUS) {
1308 residue = ebus_dma_residue(&chip->eb2c);
1309 } else {
1310#endif
1311#ifdef SBUS_SUPPORT
1312 residue = sbus_readl(chip->port + APCCC);
1313#endif
1314#ifdef EBUS_SUPPORT
1315 }
1316#endif
1317 ptr += (period_bytes - residue);
1318 return bytes_to_frames(substream->runtime, ptr);
1319}
1320
1321/*
1322
1323 */
1324
1325static int snd_cs4231_probe(cs4231_t *chip)
1326{
1327 unsigned long flags;
1328 int i, id, vers;
1329 unsigned char *ptr;
1330
1331#if 0
1332 snd_cs4231_debug(chip);
1333#endif
1334 id = vers = 0;
1335 for (i = 0; i < 50; i++) {
1336 mb();
1337 if (__cs4231_readb(chip, CS4231P(chip, REGSEL)) & CS4231_INIT)
1338 udelay(2000);
1339 else {
1340 spin_lock_irqsave(&chip->lock, flags);
1341 snd_cs4231_out(chip, CS4231_MISC_INFO, CS4231_MODE2);
1342 id = snd_cs4231_in(chip, CS4231_MISC_INFO) & 0x0f;
1343 vers = snd_cs4231_in(chip, CS4231_VERSION);
1344 spin_unlock_irqrestore(&chip->lock, flags);
1345 if (id == 0x0a)
1346 break; /* this is valid value */
1347 }
1348 }
1349 snd_printdd("cs4231: port = %p, id = 0x%x\n", chip->port, id);
1350 if (id != 0x0a)
1351 return -ENODEV; /* no valid device found */
1352
1353 spin_lock_irqsave(&chip->lock, flags);
1354
1355
1356 /* Reset DMA engine. */
1357#ifdef EBUS_SUPPORT
1358 if (chip->flags & CS4231_FLAG_EBUS) {
1359 /* Done by ebus_dma_register */
1360 } else {
1361#endif
1362#ifdef SBUS_SUPPORT
1363 sbus_writel(APC_CHIP_RESET, chip->port + APCCSR);
1364 sbus_writel(0x00, chip->port + APCCSR);
1365 sbus_writel(sbus_readl(chip->port + APCCSR) | APC_CDC_RESET,
1366 chip->port + APCCSR);
1367
1368 udelay(20);
1369
1370 sbus_writel(sbus_readl(chip->port + APCCSR) & ~APC_CDC_RESET,
1371 chip->port + APCCSR);
1372 sbus_writel(sbus_readl(chip->port + APCCSR) | (APC_XINT_ENA |
1373 APC_XINT_PENA |
1374 APC_XINT_CENA),
1375 chip->port + APCCSR);
1376#endif
1377#ifdef EBUS_SUPPORT
1378 }
1379#endif
1380
1381 __cs4231_readb(chip, CS4231P(chip, STATUS)); /* clear any pendings IRQ */
1382 __cs4231_writeb(chip, 0, CS4231P(chip, STATUS));
1383 mb();
1384
1385 spin_unlock_irqrestore(&chip->lock, flags);
1386
1387 chip->image[CS4231_MISC_INFO] = CS4231_MODE2;
1388 chip->image[CS4231_IFACE_CTRL] =
1389 chip->image[CS4231_IFACE_CTRL] & ~CS4231_SINGLE_DMA;
1390 chip->image[CS4231_ALT_FEATURE_1] = 0x80;
1391 chip->image[CS4231_ALT_FEATURE_2] = 0x01;
1392 if (vers & 0x20)
1393 chip->image[CS4231_ALT_FEATURE_2] |= 0x02;
1394
1395 ptr = (unsigned char *) &chip->image;
1396
1397 snd_cs4231_mce_down(chip);
1398
1399 spin_lock_irqsave(&chip->lock, flags);
1400
1401 for (i = 0; i < 32; i++) /* ok.. fill all CS4231 registers */
1402 snd_cs4231_out(chip, i, *ptr++);
1403
1404 spin_unlock_irqrestore(&chip->lock, flags);
1405
1406 snd_cs4231_mce_up(chip);
1407
1408 snd_cs4231_mce_down(chip);
1409
1410 mdelay(2);
1411
1412 return 0; /* all things are ok.. */
1413}
1414
1415static snd_pcm_hardware_t snd_cs4231_playback =
1416{
1417 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1418 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
1419 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
1420 SNDRV_PCM_FMTBIT_IMA_ADPCM |
1421 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1422 SNDRV_PCM_FMTBIT_S16_BE),
1423 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1424 .rate_min = 5510,
1425 .rate_max = 48000,
1426 .channels_min = 1,
1427 .channels_max = 2,
1428 .buffer_bytes_max = (32*1024),
1429 .period_bytes_min = 4096,
1430 .period_bytes_max = (32*1024),
1431 .periods_min = 1,
1432 .periods_max = 1024,
1433};
1434
1435static snd_pcm_hardware_t snd_cs4231_capture =
1436{
1437 .info = (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
1438 SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_SYNC_START),
1439 .formats = (SNDRV_PCM_FMTBIT_MU_LAW | SNDRV_PCM_FMTBIT_A_LAW |
1440 SNDRV_PCM_FMTBIT_IMA_ADPCM |
1441 SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S16_LE |
1442 SNDRV_PCM_FMTBIT_S16_BE),
1443 .rates = SNDRV_PCM_RATE_KNOT | SNDRV_PCM_RATE_8000_48000,
1444 .rate_min = 5510,
1445 .rate_max = 48000,
1446 .channels_min = 1,
1447 .channels_max = 2,
1448 .buffer_bytes_max = (32*1024),
1449 .period_bytes_min = 4096,
1450 .period_bytes_max = (32*1024),
1451 .periods_min = 1,
1452 .periods_max = 1024,
1453};
1454
1455static int snd_cs4231_playback_open(snd_pcm_substream_t *substream)
1456{
1457 cs4231_t *chip = snd_pcm_substream_chip(substream);
1458 snd_pcm_runtime_t *runtime = substream->runtime;
1459 int err;
1460
1461 runtime->hw = snd_cs4231_playback;
1462
1463 if ((err = snd_cs4231_open(chip, CS4231_MODE_PLAY)) < 0) {
1464 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1465 return err;
1466 }
1467 chip->playback_substream = substream;
1468 chip->p_periods_sent = 0;
1469 snd_pcm_set_sync(substream);
1470 snd_cs4231_xrate(runtime);
1471
1472 return 0;
1473}
1474
1475static int snd_cs4231_capture_open(snd_pcm_substream_t *substream)
1476{
1477 cs4231_t *chip = snd_pcm_substream_chip(substream);
1478 snd_pcm_runtime_t *runtime = substream->runtime;
1479 int err;
1480
1481 runtime->hw = snd_cs4231_capture;
1482
1483 if ((err = snd_cs4231_open(chip, CS4231_MODE_RECORD)) < 0) {
1484 snd_free_pages(runtime->dma_area, runtime->dma_bytes);
1485 return err;
1486 }
1487 chip->capture_substream = substream;
1488 chip->c_periods_sent = 0;
1489 snd_pcm_set_sync(substream);
1490 snd_cs4231_xrate(runtime);
1491
1492 return 0;
1493}
1494
1495static int snd_cs4231_playback_close(snd_pcm_substream_t *substream)
1496{
1497 cs4231_t *chip = snd_pcm_substream_chip(substream);
1498
1499 chip->playback_substream = NULL;
1500 snd_cs4231_close(chip, CS4231_MODE_PLAY);
1501
1502 return 0;
1503}
1504
1505static int snd_cs4231_capture_close(snd_pcm_substream_t *substream)
1506{
1507 cs4231_t *chip = snd_pcm_substream_chip(substream);
1508
1509 chip->capture_substream = NULL;
1510 snd_cs4231_close(chip, CS4231_MODE_RECORD);
1511
1512 return 0;
1513}
1514
1515/* XXX We can do some power-management, in particular on EBUS using
1516 * XXX the audio AUXIO register...
1517 */
1518
1519static snd_pcm_ops_t snd_cs4231_playback_ops = {
1520 .open = snd_cs4231_playback_open,
1521 .close = snd_cs4231_playback_close,
1522 .ioctl = snd_pcm_lib_ioctl,
1523 .hw_params = snd_cs4231_playback_hw_params,
1524 .hw_free = snd_cs4231_playback_hw_free,
1525 .prepare = snd_cs4231_playback_prepare,
1526 .trigger = snd_cs4231_trigger,
1527 .pointer = snd_cs4231_playback_pointer,
1528};
1529
1530static snd_pcm_ops_t snd_cs4231_capture_ops = {
1531 .open = snd_cs4231_capture_open,
1532 .close = snd_cs4231_capture_close,
1533 .ioctl = snd_pcm_lib_ioctl,
1534 .hw_params = snd_cs4231_capture_hw_params,
1535 .hw_free = snd_cs4231_capture_hw_free,
1536 .prepare = snd_cs4231_capture_prepare,
1537 .trigger = snd_cs4231_trigger,
1538 .pointer = snd_cs4231_capture_pointer,
1539};
1540
1541static void snd_cs4231_pcm_free(snd_pcm_t *pcm)
1542{
1543 cs4231_t *chip = pcm->private_data;
1544 chip->pcm = NULL;
1545 snd_pcm_lib_preallocate_free_for_all(pcm);
1546}
1547
1548int snd_cs4231_pcm(cs4231_t *chip)
1549{
1550 snd_pcm_t *pcm;
1551 int err;
1552
1553 if ((err = snd_pcm_new(chip->card, "CS4231", 0, 1, 1, &pcm)) < 0)
1554 return err;
1555
1556 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_cs4231_playback_ops);
1557 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_cs4231_capture_ops);
1558
1559 /* global setup */
1560 pcm->private_data = chip;
1561 pcm->private_free = snd_cs4231_pcm_free;
1562 pcm->info_flags = SNDRV_PCM_INFO_JOINT_DUPLEX;
1563 strcpy(pcm->name, "CS4231");
1564
1565#ifdef EBUS_SUPPORT
1566 if (chip->flags & CS4231_FLAG_EBUS) {
1567 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_DEV,
1568 snd_dma_pci_data(chip->dev_u.pdev),
1569 64*1024, 128*1024);
1570 } else {
1571#endif
1572#ifdef SBUS_SUPPORT
1573 snd_pcm_lib_preallocate_pages_for_all(pcm, SNDRV_DMA_TYPE_SBUS,
1574 snd_dma_sbus_data(chip->dev_u.sdev),
1575 64*1024, 128*1024);
1576#endif
1577#ifdef EBUS_SUPPORT
1578 }
1579#endif
1580
1581 chip->pcm = pcm;
1582
1583 return 0;
1584}
1585
1586static void snd_cs4231_timer_free(snd_timer_t *timer)
1587{
1588 cs4231_t *chip = timer->private_data;
1589 chip->timer = NULL;
1590}
1591
1592int snd_cs4231_timer(cs4231_t *chip)
1593{
1594 snd_timer_t *timer;
1595 snd_timer_id_t tid;
1596 int err;
1597
1598 /* Timer initialization */
1599 tid.dev_class = SNDRV_TIMER_CLASS_CARD;
1600 tid.dev_sclass = SNDRV_TIMER_SCLASS_NONE;
1601 tid.card = chip->card->number;
1602 tid.device = 0;
1603 tid.subdevice = 0;
1604 if ((err = snd_timer_new(chip->card, "CS4231", &tid, &timer)) < 0)
1605 return err;
1606 strcpy(timer->name, "CS4231");
1607 timer->private_data = chip;
1608 timer->private_free = snd_cs4231_timer_free;
1609 timer->hw = snd_cs4231_timer_table;
1610 chip->timer = timer;
1611
1612 return 0;
1613}
1614
1615/*
1616 * MIXER part
1617 */
1618
1619static int snd_cs4231_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1620{
1621 static char *texts[4] = {
1622 "Line", "CD", "Mic", "Mix"
1623 };
1624 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1625
1626 snd_assert(chip->card != NULL, return -EINVAL);
1627 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1628 uinfo->count = 2;
1629 uinfo->value.enumerated.items = 4;
1630 if (uinfo->value.enumerated.item > 3)
1631 uinfo->value.enumerated.item = 3;
1632 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1633
1634 return 0;
1635}
1636
1637static int snd_cs4231_get_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1638{
1639 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1640 unsigned long flags;
1641
1642 spin_lock_irqsave(&chip->lock, flags);
1643 ucontrol->value.enumerated.item[0] =
1644 (chip->image[CS4231_LEFT_INPUT] & CS4231_MIXS_ALL) >> 6;
1645 ucontrol->value.enumerated.item[1] =
1646 (chip->image[CS4231_RIGHT_INPUT] & CS4231_MIXS_ALL) >> 6;
1647 spin_unlock_irqrestore(&chip->lock, flags);
1648
1649 return 0;
1650}
1651
1652static int snd_cs4231_put_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1653{
1654 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1655 unsigned long flags;
1656 unsigned short left, right;
1657 int change;
1658
1659 if (ucontrol->value.enumerated.item[0] > 3 ||
1660 ucontrol->value.enumerated.item[1] > 3)
1661 return -EINVAL;
1662 left = ucontrol->value.enumerated.item[0] << 6;
1663 right = ucontrol->value.enumerated.item[1] << 6;
1664
1665 spin_lock_irqsave(&chip->lock, flags);
1666
1667 left = (chip->image[CS4231_LEFT_INPUT] & ~CS4231_MIXS_ALL) | left;
1668 right = (chip->image[CS4231_RIGHT_INPUT] & ~CS4231_MIXS_ALL) | right;
1669 change = left != chip->image[CS4231_LEFT_INPUT] ||
1670 right != chip->image[CS4231_RIGHT_INPUT];
1671 snd_cs4231_out(chip, CS4231_LEFT_INPUT, left);
1672 snd_cs4231_out(chip, CS4231_RIGHT_INPUT, right);
1673
1674 spin_unlock_irqrestore(&chip->lock, flags);
1675
1676 return change;
1677}
1678
1679int snd_cs4231_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1680{
1681 int mask = (kcontrol->private_value >> 16) & 0xff;
1682
1683 uinfo->type = (mask == 1) ?
1684 SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1685 uinfo->count = 1;
1686 uinfo->value.integer.min = 0;
1687 uinfo->value.integer.max = mask;
1688
1689 return 0;
1690}
1691
1692int snd_cs4231_get_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1693{
1694 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1695 unsigned long flags;
1696 int reg = kcontrol->private_value & 0xff;
1697 int shift = (kcontrol->private_value >> 8) & 0xff;
1698 int mask = (kcontrol->private_value >> 16) & 0xff;
1699 int invert = (kcontrol->private_value >> 24) & 0xff;
1700
1701 spin_lock_irqsave(&chip->lock, flags);
1702
1703 ucontrol->value.integer.value[0] = (chip->image[reg] >> shift) & mask;
1704
1705 spin_unlock_irqrestore(&chip->lock, flags);
1706
1707 if (invert)
1708 ucontrol->value.integer.value[0] =
1709 (mask - ucontrol->value.integer.value[0]);
1710
1711 return 0;
1712}
1713
1714int snd_cs4231_put_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1715{
1716 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1717 unsigned long flags;
1718 int reg = kcontrol->private_value & 0xff;
1719 int shift = (kcontrol->private_value >> 8) & 0xff;
1720 int mask = (kcontrol->private_value >> 16) & 0xff;
1721 int invert = (kcontrol->private_value >> 24) & 0xff;
1722 int change;
1723 unsigned short val;
1724
1725 val = (ucontrol->value.integer.value[0] & mask);
1726 if (invert)
1727 val = mask - val;
1728 val <<= shift;
1729
1730 spin_lock_irqsave(&chip->lock, flags);
1731
1732 val = (chip->image[reg] & ~(mask << shift)) | val;
1733 change = val != chip->image[reg];
1734 snd_cs4231_out(chip, reg, val);
1735
1736 spin_unlock_irqrestore(&chip->lock, flags);
1737
1738 return change;
1739}
1740
1741int snd_cs4231_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
1742{
1743 int mask = (kcontrol->private_value >> 24) & 0xff;
1744
1745 uinfo->type = mask == 1 ?
1746 SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1747 uinfo->count = 2;
1748 uinfo->value.integer.min = 0;
1749 uinfo->value.integer.max = mask;
1750
1751 return 0;
1752}
1753
1754int snd_cs4231_get_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1755{
1756 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1757 unsigned long flags;
1758 int left_reg = kcontrol->private_value & 0xff;
1759 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1760 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1761 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1762 int mask = (kcontrol->private_value >> 24) & 0xff;
1763 int invert = (kcontrol->private_value >> 22) & 1;
1764
1765 spin_lock_irqsave(&chip->lock, flags);
1766
1767 ucontrol->value.integer.value[0] = (chip->image[left_reg] >> shift_left) & mask;
1768 ucontrol->value.integer.value[1] = (chip->image[right_reg] >> shift_right) & mask;
1769
1770 spin_unlock_irqrestore(&chip->lock, flags);
1771
1772 if (invert) {
1773 ucontrol->value.integer.value[0] =
1774 (mask - ucontrol->value.integer.value[0]);
1775 ucontrol->value.integer.value[1] =
1776 (mask - ucontrol->value.integer.value[1]);
1777 }
1778
1779 return 0;
1780}
1781
1782int snd_cs4231_put_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
1783{
1784 cs4231_t *chip = snd_kcontrol_chip(kcontrol);
1785 unsigned long flags;
1786 int left_reg = kcontrol->private_value & 0xff;
1787 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1788 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1789 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1790 int mask = (kcontrol->private_value >> 24) & 0xff;
1791 int invert = (kcontrol->private_value >> 22) & 1;
1792 int change;
1793 unsigned short val1, val2;
1794
1795 val1 = ucontrol->value.integer.value[0] & mask;
1796 val2 = ucontrol->value.integer.value[1] & mask;
1797 if (invert) {
1798 val1 = mask - val1;
1799 val2 = mask - val2;
1800 }
1801 val1 <<= shift_left;
1802 val2 <<= shift_right;
1803
1804 spin_lock_irqsave(&chip->lock, flags);
1805
1806 val1 = (chip->image[left_reg] & ~(mask << shift_left)) | val1;
1807 val2 = (chip->image[right_reg] & ~(mask << shift_right)) | val2;
1808 change = val1 != chip->image[left_reg] || val2 != chip->image[right_reg];
1809 snd_cs4231_out(chip, left_reg, val1);
1810 snd_cs4231_out(chip, right_reg, val2);
1811
1812 spin_unlock_irqrestore(&chip->lock, flags);
1813
1814 return change;
1815}
1816
1817#define CS4231_SINGLE(xname, xindex, reg, shift, mask, invert) \
1818{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1819 .info = snd_cs4231_info_single, \
1820 .get = snd_cs4231_get_single, .put = snd_cs4231_put_single, \
1821 .private_value = reg | (shift << 8) | (mask << 16) | (invert << 24) }
1822
1823#define CS4231_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1824{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xindex, \
1825 .info = snd_cs4231_info_double, \
1826 .get = snd_cs4231_get_double, .put = snd_cs4231_put_double, \
1827 .private_value = left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1828
1829static snd_kcontrol_new_t snd_cs4231_controls[] = {
1830CS4231_DOUBLE("PCM Playback Switch", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 7, 7, 1, 1),
1831CS4231_DOUBLE("PCM Playback Volume", 0, CS4231_LEFT_OUTPUT, CS4231_RIGHT_OUTPUT, 0, 0, 63, 1),
1832CS4231_DOUBLE("Line Playback Switch", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 7, 7, 1, 1),
1833CS4231_DOUBLE("Line Playback Volume", 0, CS4231_LEFT_LINE_IN, CS4231_RIGHT_LINE_IN, 0, 0, 31, 1),
1834CS4231_DOUBLE("Aux Playback Switch", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 7, 7, 1, 1),
1835CS4231_DOUBLE("Aux Playback Volume", 0, CS4231_AUX1_LEFT_INPUT, CS4231_AUX1_RIGHT_INPUT, 0, 0, 31, 1),
1836CS4231_DOUBLE("Aux Playback Switch", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 7, 7, 1, 1),
1837CS4231_DOUBLE("Aux Playback Volume", 1, CS4231_AUX2_LEFT_INPUT, CS4231_AUX2_RIGHT_INPUT, 0, 0, 31, 1),
1838CS4231_SINGLE("Mono Playback Switch", 0, CS4231_MONO_CTRL, 7, 1, 1),
1839CS4231_SINGLE("Mono Playback Volume", 0, CS4231_MONO_CTRL, 0, 15, 1),
1840CS4231_SINGLE("Mono Output Playback Switch", 0, CS4231_MONO_CTRL, 6, 1, 1),
1841CS4231_SINGLE("Mono Output Playback Bypass", 0, CS4231_MONO_CTRL, 5, 1, 0),
1842CS4231_DOUBLE("Capture Volume", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 0, 0, 15, 0),
1843{
1844 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
1845 .name = "Capture Source",
1846 .info = snd_cs4231_info_mux,
1847 .get = snd_cs4231_get_mux,
1848 .put = snd_cs4231_put_mux,
1849},
1850CS4231_DOUBLE("Mic Boost", 0, CS4231_LEFT_INPUT, CS4231_RIGHT_INPUT, 5, 5, 1, 0),
1851CS4231_SINGLE("Loopback Capture Switch", 0, CS4231_LOOPBACK, 0, 1, 0),
1852CS4231_SINGLE("Loopback Capture Volume", 0, CS4231_LOOPBACK, 2, 63, 1),
1853/* SPARC specific uses of XCTL{0,1} general purpose outputs. */
1854CS4231_SINGLE("Line Out Switch", 0, CS4231_PIN_CTRL, 6, 1, 1),
1855CS4231_SINGLE("Headphone Out Switch", 0, CS4231_PIN_CTRL, 7, 1, 1)
1856};
1857
1858int snd_cs4231_mixer(cs4231_t *chip)
1859{
1860 snd_card_t *card;
1861 int err, idx;
1862
1863 snd_assert(chip != NULL && chip->pcm != NULL, return -EINVAL);
1864
1865 card = chip->card;
1866
1867 strcpy(card->mixername, chip->pcm->name);
1868
1869 for (idx = 0; idx < ARRAY_SIZE(snd_cs4231_controls); idx++) {
1870 if ((err = snd_ctl_add(card,
1871 snd_ctl_new1(&snd_cs4231_controls[idx],
1872 chip))) < 0)
1873 return err;
1874 }
1875 return 0;
1876}
1877
1878static int dev;
1879
1880static int cs4231_attach_begin(snd_card_t **rcard)
1881{
1882 snd_card_t *card;
1883
1884 *rcard = NULL;
1885
1886 if (dev >= SNDRV_CARDS)
1887 return -ENODEV;
1888
1889 if (!enable[dev]) {
1890 dev++;
1891 return -ENOENT;
1892 }
1893
1894 card = snd_card_new(index[dev], id[dev], THIS_MODULE, 0);
1895 if (card == NULL)
1896 return -ENOMEM;
1897
1898 strcpy(card->driver, "CS4231");
1899 strcpy(card->shortname, "Sun CS4231");
1900
1901 *rcard = card;
1902 return 0;
1903}
1904
1905static int cs4231_attach_finish(snd_card_t *card, cs4231_t *chip)
1906{
1907 int err;
1908
1909 if ((err = snd_cs4231_pcm(chip)) < 0)
1910 goto out_err;
1911
1912 if ((err = snd_cs4231_mixer(chip)) < 0)
1913 goto out_err;
1914
1915 if ((err = snd_cs4231_timer(chip)) < 0)
1916 goto out_err;
1917
1918 if ((err = snd_card_register(card)) < 0)
1919 goto out_err;
1920
1921 chip->next = cs4231_list;
1922 cs4231_list = chip;
1923
1924 dev++;
1925 return 0;
1926
1927out_err:
1928 snd_card_free(card);
1929 return err;
1930}
1931
1932#ifdef SBUS_SUPPORT
1933static int snd_cs4231_sbus_free(cs4231_t *chip)
1934{
1935 if (chip->irq[0])
1936 free_irq(chip->irq[0], chip);
1937
1938 if (chip->port)
1939 sbus_iounmap(chip->port, chip->regs_size);
1940
1941 if (chip->timer)
1942 snd_device_free(chip->card, chip->timer);
1943
1944 kfree(chip);
1945
1946 return 0;
1947}
1948
1949static int snd_cs4231_sbus_dev_free(snd_device_t *device)
1950{
1951 cs4231_t *cp = device->device_data;
1952
1953 return snd_cs4231_sbus_free(cp);
1954}
1955
1956static snd_device_ops_t snd_cs4231_sbus_dev_ops = {
1957 .dev_free = snd_cs4231_sbus_dev_free,
1958};
1959
1960static int __init snd_cs4231_sbus_create(snd_card_t *card,
1961 struct sbus_dev *sdev,
1962 int dev,
1963 cs4231_t **rchip)
1964{
1965 cs4231_t *chip;
1966 int err;
1967
1968 *rchip = NULL;
1969 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
1970 if (chip == NULL)
1971 return -ENOMEM;
1972
1973 spin_lock_init(&chip->lock);
1974 init_MUTEX(&chip->mce_mutex);
1975 init_MUTEX(&chip->open_mutex);
1976 chip->card = card;
1977 chip->dev_u.sdev = sdev;
1978 chip->regs_size = sdev->reg_addrs[0].reg_size;
1979 memcpy(&chip->image, &snd_cs4231_original_image,
1980 sizeof(snd_cs4231_original_image));
1981
1982 chip->port = sbus_ioremap(&sdev->resource[0], 0,
1983 chip->regs_size, "cs4231");
1984 if (!chip->port) {
1985 snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
1986 return -EIO;
1987 }
1988
1989 if (request_irq(sdev->irqs[0], snd_cs4231_sbus_interrupt,
1990 SA_SHIRQ, "cs4231", chip)) {
1991 snd_printk("cs4231-%d: Unable to grab SBUS IRQ %s\n",
1992 dev,
1993 __irq_itoa(sdev->irqs[0]));
1994 snd_cs4231_sbus_free(chip);
1995 return -EBUSY;
1996 }
1997 chip->irq[0] = sdev->irqs[0];
1998
1999 if (snd_cs4231_probe(chip) < 0) {
2000 snd_cs4231_sbus_free(chip);
2001 return -ENODEV;
2002 }
2003 snd_cs4231_init(chip);
2004
2005 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
2006 chip, &snd_cs4231_sbus_dev_ops)) < 0) {
2007 snd_cs4231_sbus_free(chip);
2008 return err;
2009 }
2010
2011 *rchip = chip;
2012 return 0;
2013}
2014
2015static int cs4231_sbus_attach(struct sbus_dev *sdev)
2016{
2017 struct resource *rp = &sdev->resource[0];
2018 cs4231_t *cp;
2019 snd_card_t *card;
2020 int err;
2021
2022 err = cs4231_attach_begin(&card);
2023 if (err)
2024 return err;
2025
2026 sprintf(card->longname, "%s at 0x%02lx:0x%08lx, irq %s",
2027 card->shortname,
2028 rp->flags & 0xffL,
2029 rp->start,
2030 __irq_itoa(sdev->irqs[0]));
2031
2032 if ((err = snd_cs4231_sbus_create(card, sdev, dev, &cp)) < 0) {
2033 snd_card_free(card);
2034 return err;
2035 }
2036
2037 return cs4231_attach_finish(card, cp);
2038}
2039#endif
2040
2041#ifdef EBUS_SUPPORT
2042static int snd_cs4231_ebus_free(cs4231_t *chip)
2043{
2044 if (chip->eb2c.regs) {
2045 ebus_dma_unregister(&chip->eb2c);
2046 iounmap(chip->eb2c.regs);
2047 }
2048 if (chip->eb2p.regs) {
2049 ebus_dma_unregister(&chip->eb2p);
2050 iounmap(chip->eb2p.regs);
2051 }
2052
2053 if (chip->port)
2054 iounmap(chip->port);
2055 if (chip->timer)
2056 snd_device_free(chip->card, chip->timer);
2057
2058 kfree(chip);
2059
2060 return 0;
2061}
2062
2063static int snd_cs4231_ebus_dev_free(snd_device_t *device)
2064{
2065 cs4231_t *cp = device->device_data;
2066
2067 return snd_cs4231_ebus_free(cp);
2068}
2069
2070static snd_device_ops_t snd_cs4231_ebus_dev_ops = {
2071 .dev_free = snd_cs4231_ebus_dev_free,
2072};
2073
2074static int __init snd_cs4231_ebus_create(snd_card_t *card,
2075 struct linux_ebus_device *edev,
2076 int dev,
2077 cs4231_t **rchip)
2078{
2079 cs4231_t *chip;
2080 int err;
2081
2082 *rchip = NULL;
2083 chip = kcalloc(1, sizeof(*chip), GFP_KERNEL);
2084 if (chip == NULL)
2085 return -ENOMEM;
2086
2087 spin_lock_init(&chip->lock);
2088 spin_lock_init(&chip->eb2c.lock);
2089 spin_lock_init(&chip->eb2p.lock);
2090 init_MUTEX(&chip->mce_mutex);
2091 init_MUTEX(&chip->open_mutex);
2092 chip->flags |= CS4231_FLAG_EBUS;
2093 chip->card = card;
2094 chip->dev_u.pdev = edev->bus->self;
2095 memcpy(&chip->image, &snd_cs4231_original_image,
2096 sizeof(snd_cs4231_original_image));
2097 strcpy(chip->eb2c.name, "cs4231(capture)");
2098 chip->eb2c.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
2099 chip->eb2c.callback = snd_cs4231_ebus_capture_callback;
2100 chip->eb2c.client_cookie = chip;
2101 chip->eb2c.irq = edev->irqs[0];
2102 strcpy(chip->eb2p.name, "cs4231(play)");
2103 chip->eb2p.flags = EBUS_DMA_FLAG_USE_EBDMA_HANDLER;
2104 chip->eb2p.callback = snd_cs4231_ebus_play_callback;
2105 chip->eb2p.client_cookie = chip;
2106 chip->eb2p.irq = edev->irqs[1];
2107
2108 chip->port = ioremap(edev->resource[0].start, 0x10);
2109 chip->eb2p.regs = ioremap(edev->resource[1].start, 0x10);
2110 chip->eb2c.regs = ioremap(edev->resource[2].start, 0x10);
2111 if (!chip->port || !chip->eb2p.regs || !chip->eb2c.regs) {
2112 snd_cs4231_ebus_free(chip);
2113 snd_printk("cs4231-%d: Unable to map chip registers.\n", dev);
2114 return -EIO;
2115 }
2116
2117 if (ebus_dma_register(&chip->eb2c)) {
2118 snd_cs4231_ebus_free(chip);
2119 snd_printk("cs4231-%d: Unable to register EBUS capture DMA\n", dev);
2120 return -EBUSY;
2121 }
2122 if (ebus_dma_irq_enable(&chip->eb2c, 1)) {
2123 snd_cs4231_ebus_free(chip);
2124 snd_printk("cs4231-%d: Unable to enable EBUS capture IRQ\n", dev);
2125 return -EBUSY;
2126 }
2127
2128 if (ebus_dma_register(&chip->eb2p)) {
2129 snd_cs4231_ebus_free(chip);
2130 snd_printk("cs4231-%d: Unable to register EBUS play DMA\n", dev);
2131 return -EBUSY;
2132 }
2133 if (ebus_dma_irq_enable(&chip->eb2p, 1)) {
2134 snd_cs4231_ebus_free(chip);
2135 snd_printk("cs4231-%d: Unable to enable EBUS play IRQ\n", dev);
2136 return -EBUSY;
2137 }
2138
2139 if (snd_cs4231_probe(chip) < 0) {
2140 snd_cs4231_ebus_free(chip);
2141 return -ENODEV;
2142 }
2143 snd_cs4231_init(chip);
2144
2145 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL,
2146 chip, &snd_cs4231_ebus_dev_ops)) < 0) {
2147 snd_cs4231_ebus_free(chip);
2148 return err;
2149 }
2150
2151 *rchip = chip;
2152 return 0;
2153}
2154
2155static int cs4231_ebus_attach(struct linux_ebus_device *edev)
2156{
2157 snd_card_t *card;
2158 cs4231_t *chip;
2159 int err;
2160
2161 err = cs4231_attach_begin(&card);
2162 if (err)
2163 return err;
2164
2165 sprintf(card->longname, "%s at 0x%lx, irq %s",
2166 card->shortname,
2167 edev->resource[0].start,
2168 __irq_itoa(edev->irqs[0]));
2169
2170 if ((err = snd_cs4231_ebus_create(card, edev, dev, &chip)) < 0) {
2171 snd_card_free(card);
2172 return err;
2173 }
2174
2175 return cs4231_attach_finish(card, chip);
2176}
2177#endif
2178
2179static int __init cs4231_init(void)
2180{
2181#ifdef SBUS_SUPPORT
2182 struct sbus_bus *sbus;
2183 struct sbus_dev *sdev;
2184#endif
2185#ifdef EBUS_SUPPORT
2186 struct linux_ebus *ebus;
2187 struct linux_ebus_device *edev;
2188#endif
2189 int found;
2190
2191 found = 0;
2192
2193#ifdef SBUS_SUPPORT
2194 for_all_sbusdev(sdev, sbus) {
2195 if (!strcmp(sdev->prom_name, "SUNW,CS4231")) {
2196 if (cs4231_sbus_attach(sdev) == 0)
2197 found++;
2198 }
2199 }
2200#endif
2201#ifdef EBUS_SUPPORT
2202 for_each_ebus(ebus) {
2203 for_each_ebusdev(edev, ebus) {
2204 int match = 0;
2205
2206 if (!strcmp(edev->prom_name, "SUNW,CS4231")) {
2207 match = 1;
2208 } else if (!strcmp(edev->prom_name, "audio")) {
2209 char compat[16];
2210
2211 prom_getstring(edev->prom_node, "compatible",
2212 compat, sizeof(compat));
2213 compat[15] = '\0';
2214 if (!strcmp(compat, "SUNW,CS4231"))
2215 match = 1;
2216 }
2217
2218 if (match &&
2219 cs4231_ebus_attach(edev) == 0)
2220 found++;
2221 }
2222 }
2223#endif
2224
2225
2226 return (found > 0) ? 0 : -EIO;
2227}
2228
2229static void __exit cs4231_exit(void)
2230{
2231 cs4231_t *p = cs4231_list;
2232
2233 while (p != NULL) {
2234 cs4231_t *next = p->next;
2235
2236 snd_card_free(p->card);
2237
2238 p = next;
2239 }
2240
2241 cs4231_list = NULL;
2242}
2243
2244module_init(cs4231_init);
2245module_exit(cs4231_exit);