2 * drivers/sbus/audio/amd7930.c
4 * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
6 * This is the lowlevel driver for the AMD7930 audio chip found on all
7 * sun4c machines and some sun4m machines.
9 * The amd7930 is actually an ISDN chip which has a very simple
10 * integrated audio encoder/decoder. When Sun decided on what chip to
11 * use for audio, they had the brilliant idea of using the amd7930 and
12 * only connecting the audio encoder/decoder pins.
14 * Thanks to the AMD engineer who was able to get us the AMD79C30
15 * databook which has all the programming information and gain tables.
17 * Advanced Micro Devices' Am79C30A is an ISDN/audio chip used in the
18 * SparcStation 1+. The chip provides microphone and speaker interfaces
19 * which provide mono-channel audio at 8K samples per second via either
20 * 8-bit A-law or 8-bit mu-law encoding. Also, the chip features an
21 * ISDN BRI Line Interface Unit (LIU), I.430 S/T physical interface,
22 * which performs basic D channel LAPD processing and provides raw
23 * B channel data. The digital audio channel, the two ISDN B channels,
24 * and two 64 Kbps channels to the microprocessor are all interconnected
27 * This driver interfaces to the Linux HiSax ISDN driver, which performs
28 * all high-level Q.921 and Q.931 ISDN functions. The file is not
29 * itself a hardware driver; rather it uses functions exported by
30 * the AMD7930 driver in the sparcaudio subsystem (drivers/sbus/audio),
31 * allowing the chip to be simultaneously used for both audio and ISDN data.
32 * The hardware driver does _no_ buffering, but provides several callbacks
33 * which are called during interrupt service and should therefore run quickly.
35 * D channel transmission is performed by passing the hardware driver the
36 * address and size of an skb's data area, then waiting for a callback
37 * to signal successful transmission of the packet. A task is then
38 * queued to notify the HiSax driver that another packet may be transmitted.
40 * D channel reception is quite simple, mainly because of:
41 * 1) the slow speed of the D channel - 16 kbps, and
42 * 2) the presence of an 8- or 32-byte (depending on chip version) FIFO
43 * to buffer the D channel data on the chip
44 * Worst case scenario of back-to-back packets with the 8 byte buffer
45 * at 16 kbps yields an service time of 4 ms - long enough to preclude
46 * the need for fancy buffering. We queue a background task that copies
47 * data out of the receive buffer into an skb, and the hardware driver
48 * simply does nothing until we're done with the receive buffer and
49 * reset it for a new packet.
51 * B channel processing is more complex, because of:
52 * 1) the faster speed - 64 kbps,
53 * 2) the lack of any on-chip buffering (it interrupts for every byte), and
54 * 3) the lack of any chip support for HDLC encapsulation
56 * The HiSax driver can put each B channel into one of three modes -
57 * L1_MODE_NULL (channel disabled), L1_MODE_TRANS (transparent data relay),
58 * and L1_MODE_HDLC (HDLC encapsulation by low-level driver).
59 * L1_MODE_HDLC is the most common, used for almost all "pure" digital
60 * data sessions. L1_MODE_TRANS is used for ISDN audio.
62 * HDLC B channel transmission is performed via a large buffer into
63 * which the skb is copied while performing HDLC bit-stuffing. A CRC
64 * is computed and attached to the end of the buffer, which is then
65 * passed to the low-level routines for raw transmission. Once
66 * transmission is complete, the hardware driver is set to enter HDLC
67 * idle by successive transmission of mark (all 1) bytes, waiting for
68 * the ISDN driver to prepare another packet for transmission and
71 * HDLC B channel reception is performed via an X-byte ring buffer
72 * divided into N sections of X/N bytes each. Defaults: X=256 bytes, N=4.
73 * As the hardware driver notifies us that each section is full, we
74 * hand it the next section and schedule a background task to peruse
75 * the received section, bit-by-bit, with an HDLC decoder. As
76 * packets are detected, they are copied into a large buffer while
77 * decoding HDLC bit-stuffing. The ending CRC is verified, and if
78 * it is correct, we alloc a new skb of the correct length (which we
79 * now know), copy the packet into it, and hand it to the upper layers.
80 * Optimization: for large packets, we hand the buffer (which also
81 * happens to be an skb) directly to the upper layer after an skb_trim,
82 * and alloc a new large buffer for future packets, thus avoiding a copy.
83 * Then we return to HDLC processing; state is saved between calls.
86 #include <linux/module.h>
87 #include <linux/kernel.h>
88 #include <linux/sched.h>
89 #include <linux/errno.h>
90 #include <linux/interrupt.h>
91 #include <linux/malloc.h>
92 #include <linux/init.h>
93 #include <linux/version.h>
94 #include <linux/soundcard.h>
95 #include <asm/openprom.h>
96 #include <asm/oplib.h>
97 #include <asm/system.h>
100 #include <asm/sbus.h>
102 #include <asm/audioio.h>
105 static __u8
bilinear2mulaw(__u8 data
);
106 static __u8
mulaw2bilinear(__u8 data
);
107 static __u8
linear2mulaw(__u16 data
);
108 static __u16
mulaw2linear(__u8 data
);
110 #if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
111 #include "../../isdn/hisax/hisax.h"
112 #include "../../isdn/hisax/isdnl1.h"
113 #include "../../isdn/hisax/foreign.h"
116 #define MAX_DRIVERS 1
118 static struct sparcaudio_driver drivers
[MAX_DRIVERS
];
119 static int num_drivers
;
121 /* Each amd7930 chip has two bi-directional B channels and a D
122 * channel available to the uproc. This structure handles all
123 * the buffering needed to transmit and receive via a single channel.
126 #define CHANNEL_AVAILABLE 0x00
127 #define CHANNEL_INUSE_AUDIO_IN 0x01
128 #define CHANNEL_INUSE_AUDIO_OUT 0x02
129 #define CHANNEL_INUSE_ISDN_B1 0x04
130 #define CHANNEL_INUSE_ISDN_B2 0x08
131 #define CHANNEL_INUSE 0xff
133 struct amd7930_channel
{
135 unsigned char channel_status
;
137 /* Current buffer that the driver is playing on channel */
138 volatile __u8
* output_ptr
;
139 volatile unsigned long output_count
;
140 unsigned char xmit_idle_char
;
142 /* Callback routine (and argument) when output is done on */
143 void (*output_callback
)();
144 void * output_callback_arg
;
146 /* Current buffer that the driver is recording on channel */
147 volatile __u8
* input_ptr
;
148 volatile unsigned long input_count
;
149 volatile unsigned long input_limit
;
151 /* Callback routine (and argument) when input is done on */
152 void (*input_callback
)();
153 void * input_callback_arg
;
160 /* Private information we store for each amd7930 chip. */
161 struct amd7930_info
{
162 struct amd7930_channel D
;
163 struct amd7930_channel Bb
;
164 struct amd7930_channel Bc
;
166 /* Pointers to which B channels are being used for what
167 * These three fields (Baudio, Bisdn[0], and Bisdn[1]) will either
168 * be NULL or point to one of the Bb/Bc structures above.
170 struct amd7930_channel
*Baudio
;
171 struct amd7930_channel
*Bisdn
[2];
173 /* Device registers information. */
174 struct amd7930
*regs
;
175 unsigned long regs_size
;
176 struct amd7930_map map
;
178 /* Volume information. */
179 int pgain
, rgain
, mgain
;
181 /* Device interrupt information. */
183 volatile int ints_on
;
189 /* Someone to signal when the ISDN LIU state changes */
191 void (*liu_callback
)(void *);
192 void *liu_callback_arg
;
197 /* Output a 16-bit quantity in the order that the amd7930 expects. */
198 #define amd7930_out16(regs,v) ({ regs->dr = v & 0xFF; regs->dr = (v >> 8) & 0xFF; })
202 * gx, gr & stg gains. this table must contain 256 elements with
203 * the 0th being "infinity" (the magic value 9008). The remaining
204 * elements match sun's gain curve (but with higher resolution):
205 * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
207 static __const__ __u16 gx_coeff
[256] = {
208 0x9008, 0x8b7c, 0x8b51, 0x8b45, 0x8b42, 0x8b3b, 0x8b36, 0x8b33,
209 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
210 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
211 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
212 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
213 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
214 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
215 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
216 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
217 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
218 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
219 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
220 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
221 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
222 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
223 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
224 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
225 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
226 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
227 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
228 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
229 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
230 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
231 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
232 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
233 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
234 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
235 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
236 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
237 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
238 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
239 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
242 static __const__ __u16 ger_coeff
[] = {
254 0x111f, /* 10.5 dB */
256 0x00dd, /* 11.5 dB */
261 0x2200, /* 15.9 dB */
262 0x000b, /* 16.9 dB */
265 #define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
267 /* Enable amd7930 interrupts atomically. */
268 static __inline__
void amd7930_enable_ints(struct amd7930_info
*info
)
270 register unsigned long flags
;
276 info
->regs
->cr
= AMR_INIT
;
277 info
->regs
->dr
= AM_INIT_ACTIVE
;
278 restore_flags(flags
);
283 /* Disable amd7930 interrupts atomically. */
284 static __inline__
void amd7930_disable_ints(struct amd7930_info
*info
)
286 register unsigned long flags
;
292 info
->regs
->cr
= AMR_INIT
;
293 info
->regs
->dr
= AM_INIT_ACTIVE
| AM_INIT_DISABLE_INTS
;
294 restore_flags(flags
);
299 /* Idle amd7930 (no interrupts, no audio, no data) */
300 static __inline__
void amd7930_idle(struct amd7930_info
*info
)
302 register unsigned long flags
;
308 info
->regs
->cr
= AMR_INIT
;
310 restore_flags(flags
);
315 /* Commit the local copy of the MAP registers to the amd7930. */
316 static void amd7930_write_map(struct sparcaudio_driver
*drv
)
318 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
319 struct amd7930
*regs
= info
->regs
;
320 struct amd7930_map
*map
= &info
->map
;
325 regs
->cr
= AMR_MAP_GX
;
326 amd7930_out16(regs
, map
->gx
);
328 regs
->cr
= AMR_MAP_GR
;
329 amd7930_out16(regs
, map
->gr
);
331 regs
->cr
= AMR_MAP_STGR
;
332 amd7930_out16(regs
, map
->stgr
);
334 regs
->cr
= AMR_MAP_GER
;
335 amd7930_out16(regs
, map
->ger
);
337 regs
->cr
= AMR_MAP_MMR1
;
338 regs
->dr
= map
->mmr1
;
340 regs
->cr
= AMR_MAP_MMR2
;
341 regs
->dr
= map
->mmr2
;
343 restore_flags(flags
);
346 /* Update the MAP registers with new settings. */
347 static void amd7930_update_map(struct sparcaudio_driver
*drv
)
349 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
350 struct amd7930_map
*map
= &info
->map
;
353 map
->gx
= gx_coeff
[info
->rgain
];
354 map
->stgr
= gx_coeff
[info
->mgain
];
356 level
= (info
->pgain
* (256 + NR_GER_COEFFS
)) >> 8;
358 map
->ger
= ger_coeff
[level
- 256];
359 map
->gr
= gx_coeff
[255];
361 map
->ger
= ger_coeff
[0];
362 map
->gr
= gx_coeff
[level
];
365 amd7930_write_map(drv
);
368 /* Bit of a hack here - if the HISAX ISDN driver has got INTSTAT debugging
369 * turned on, we send debugging characters to the ISDN driver:
371 * i# - Interrupt received - number from 0 to 7 is low three bits of IR
372 * > - Loaded a single char into the Dchan xmit FIFO
373 * + - Finished loading an xmit packet into the Dchan xmit FIFO
374 * < - Read a single char from the Dchan recv FIFO
375 * ! - Finished reading a packet from the Dchan recv FIFO
377 * This code needs to be removed if anything other than HISAX uses the ISDN
378 * driver, since D.output_callback_arg is assumed to be a certain struct ptr
383 inline void debug_info(struct amd7930_info
*info
, char c
) {
384 struct IsdnCardState
*cs
;
386 if (!info
|| !info
->D
.output_callback_arg
) return;
388 cs
= (struct IsdnCardState
*)info
->D
.output_callback_arg
;
390 if (!cs
|| !cs
->status_write
) return;
392 if (cs
->debug
& L1_DEB_INTSTAT
) {
393 *(cs
->status_write
++) = c
;
394 if (cs
->status_write
> cs
->status_end
)
395 cs
->status_write
= cs
->status_buf
;
401 #define debug_info(info,c)
406 static void fill_D_xmit_fifo(struct amd7930_info
*info
)
408 /* Send next byte(s) of outgoing data. */
409 while (info
->D
.output_ptr
&& info
->D
.output_count
> 0 &&
410 (info
->regs
->dsr2
& AMR_DSR2_TBE
)) {
412 /* Send the next byte and advance buffer pointer. */
413 info
->regs
->dctb
= *(info
->D
.output_ptr
);
414 info
->D
.output_ptr
++;
415 info
->D
.output_count
--;
417 debug_info(info
, '>');
421 static void transceive_Dchannel(struct amd7930_info
*info
)
425 #define D_XMIT_ERRORS (AMR_DER_COLLISION | AMR_DER_UNRN)
426 #define D_RECV_ERRORS (AMR_DER_RABRT | AMR_DER_RFRAME | AMR_DER_FCS | \
427 AMR_DER_OVFL | AMR_DER_UNFL | AMR_DER_OVRN)
429 /* Transmit if we can */
430 fill_D_xmit_fifo(info
);
432 /* Done with the xmit buffer? Notify the midlevel driver. */
433 if (info
->D
.output_ptr
!= NULL
&& info
->D
.output_count
== 0) {
434 info
->D
.output_ptr
= NULL
;
435 info
->D
.output_count
= 0;
436 debug_info(info
, '+');
437 if (info
->D
.output_callback
)
438 (*info
->D
.output_callback
)
439 (info
->D
.output_callback_arg
,
441 /* info->regs->der & D_XMIT_ERRORS); */
444 /* Read the next byte(s) of incoming data. */
446 while (info
->regs
->dsr2
& AMR_DSR2_RBA
) {
448 if (info
->D
.input_ptr
&&
449 (info
->D
.input_count
< info
->D
.input_limit
)) {
451 /* Get the next byte and advance buffer pointer. */
453 *(info
->D
.input_ptr
) = info
->regs
->dcrb
;
455 info
->D
.input_count
++;
459 /* Overflow - should be detected by chip via RBLR
460 * so we'll just consume data until we see LBRP
463 dummy
= info
->regs
->dcrb
;
467 debug_info(info
, '<');
469 if (info
->regs
->dsr2
& AMR_DSR2_LBRP
) {
471 /* End of recv packet? Notify the midlevel driver. */
475 debug_info(info
, '!');
477 info
->D
.input_ptr
= NULL
;
479 der
= info
->regs
->der
& D_RECV_ERRORS
;
481 /* Read receive byte count - advances FIFOs */
482 info
->regs
->cr
= AMR_DLC_DRCR
;
483 dummy
= info
->regs
->dr
;
484 dummy
= info
->regs
->dr
;
486 if (info
->D
.input_callback
)
487 (*info
->D
.input_callback
)
488 (info
->D
.input_callback_arg
, der
,
489 info
->D
.input_count
);
495 long amd7930_xmit_idles
=0;
497 static void transceive_Bchannel(struct amd7930_channel
*channel
,
498 __volatile__ __u8
*io_reg
)
500 /* Send the next byte of outgoing data. */
501 if (channel
->output_ptr
&& channel
->output_count
> 0) {
503 /* Send the next byte and advance buffer pointer. */
504 switch(channel
->output_format
) {
505 case AUDIO_ENCODING_ULAW
:
506 case AUDIO_ENCODING_ALAW
:
507 *io_reg
= *(channel
->output_ptr
);
509 case AUDIO_ENCODING_LINEAR8
:
510 *io_reg
= bilinear2mulaw(*(channel
->output_ptr
));
512 case AUDIO_ENCODING_LINEAR
:
513 if (channel
->output_count
>= 2) {
514 *io_reg
= linear2mulaw(*((__u16
*)(channel
->output_ptr
)));
515 channel
->output_ptr
++;
516 channel
->output_count
--;
519 channel
->output_ptr
++;
520 channel
->output_count
--;
523 /* Done with the buffer? Notify the midlevel driver. */
524 if (channel
->output_count
== 0) {
525 channel
->output_ptr
= NULL
;
526 channel
->output_count
= 0;
527 if (channel
->output_callback
)
528 (*channel
->output_callback
)
529 (channel
->output_callback_arg
,1);
532 *io_reg
= channel
->xmit_idle_char
;
533 amd7930_xmit_idles
++;
536 /* Read the next byte of incoming data. */
537 if (channel
->input_ptr
&& channel
->input_count
> 0) {
539 /* Get the next byte and advance buffer pointer. */
540 switch(channel
->input_format
) {
541 case AUDIO_ENCODING_ULAW
:
542 case AUDIO_ENCODING_ALAW
:
543 *(channel
->input_ptr
) = *io_reg
;
545 case AUDIO_ENCODING_LINEAR8
:
546 *(channel
->input_ptr
) = mulaw2bilinear(*io_reg
);
548 case AUDIO_ENCODING_LINEAR
:
549 if (channel
->input_count
>= 2) {
550 *((__u16
*)(channel
->input_ptr
)) = mulaw2linear(*io_reg
);
551 channel
->input_ptr
++;
552 channel
->input_count
--;
553 } else *(channel
->input_ptr
) = 0;
555 channel
->input_ptr
++;
556 channel
->input_count
--;
558 /* Done with the buffer? Notify the midlevel driver. */
559 if (channel
->input_count
== 0) {
560 channel
->input_ptr
= NULL
;
561 channel
->input_count
= 0;
562 if (channel
->input_callback
)
563 (*channel
->input_callback
)
564 (channel
->input_callback_arg
, 1);
569 /* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */
570 static void amd7930_interrupt(int irq
, void *dev_id
, struct pt_regs
*intr_regs
)
572 struct sparcaudio_driver
*drv
= (struct sparcaudio_driver
*)dev_id
;
573 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
574 struct amd7930
*regs
= info
->regs
;
578 /* Clear the interrupt. */
581 if (ir
& AMR_IR_BBUF
) {
582 if (info
->Bb
.channel_status
== CHANNEL_INUSE
)
583 transceive_Bchannel(&info
->Bb
, &info
->regs
->bbtb
);
584 if (info
->Bc
.channel_status
== CHANNEL_INUSE
)
585 transceive_Bchannel(&info
->Bc
, &info
->regs
->bctb
);
588 if (ir
& (AMR_IR_DRTHRSH
| AMR_IR_DTTHRSH
| AMR_IR_DSRI
)) {
589 debug_info(info
, 'i');
590 debug_info(info
, '0' + (ir
&7));
591 transceive_Dchannel(info
);
594 if (ir
& AMR_IR_LSRI
) {
595 regs
->cr
= AMR_LIU_LSR
;
598 info
->liu_state
= (lsr
&0x7) + 2;
600 if (info
->liu_callback
)
601 (*info
->liu_callback
)(info
->liu_callback_arg
);
606 static int amd7930_open(struct inode
* inode
, struct file
* file
,
607 struct sparcaudio_driver
*drv
)
609 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
611 switch(MINOR(inode
->i_rdev
) & 0xf) {
612 case SPARCAUDIO_AUDIO_MINOR
:
613 info
->format_type
= AUDIO_ENCODING_ULAW
;
615 case SPARCAUDIO_DSP_MINOR
:
616 info
->format_type
= AUDIO_ENCODING_LINEAR8
;
618 case SPARCAUDIO_DSP16_MINOR
:
619 info
->format_type
= AUDIO_ENCODING_LINEAR
;
627 static void amd7930_release(struct inode
* inode
, struct file
* file
,
628 struct sparcaudio_driver
*drv
)
630 /* amd7930_disable_ints(drv->private); */
634 static void request_Baudio(struct amd7930_info
*info
)
636 if (info
->Bb
.channel_status
== CHANNEL_AVAILABLE
) {
638 info
->Bb
.channel_status
= CHANNEL_INUSE
;
639 info
->Baudio
= &info
->Bb
;
641 /* Multiplexor map - audio (Ba) to Bb */
642 info
->regs
->cr
= AMR_MUX_MCR1
;
643 info
->regs
->dr
= AM_MUX_CHANNEL_Ba
| (AM_MUX_CHANNEL_Bb
<< 4);
645 /* Enable B channel interrupts */
646 info
->regs
->cr
= AMR_MUX_MCR4
;
647 info
->regs
->dr
= AM_MUX_MCR4_ENABLE_INTS
;
649 } else if (info
->Bc
.channel_status
== CHANNEL_AVAILABLE
) {
651 info
->Bc
.channel_status
= CHANNEL_INUSE
;
652 info
->Baudio
= &info
->Bc
;
654 /* Multiplexor map - audio (Ba) to Bc */
655 info
->regs
->cr
= AMR_MUX_MCR1
;
656 info
->regs
->dr
= AM_MUX_CHANNEL_Ba
| (AM_MUX_CHANNEL_Bc
<< 4);
658 /* Enable B channel interrupts */
659 info
->regs
->cr
= AMR_MUX_MCR4
;
660 info
->regs
->dr
= AM_MUX_MCR4_ENABLE_INTS
;
665 static void release_Baudio(struct amd7930_info
*info
)
668 info
->Baudio
->channel_status
= CHANNEL_AVAILABLE
;
669 info
->regs
->cr
= AMR_MUX_MCR1
;
673 if (info
->Bb
.channel_status
== CHANNEL_AVAILABLE
&&
674 info
->Bc
.channel_status
== CHANNEL_AVAILABLE
) {
676 /* Disable B channel interrupts */
677 info
->regs
->cr
= AMR_MUX_MCR4
;
683 static void amd7930_start_output(struct sparcaudio_driver
*drv
,
684 __u8
* buffer
, unsigned long count
)
686 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
688 if (! info
->Baudio
) {
689 request_Baudio(info
);
693 info
->Baudio
->output_ptr
= buffer
;
694 info
->Baudio
->output_count
= count
;
695 info
->Baudio
->output_format
= info
->format_type
;
696 info
->Baudio
->output_callback
= (void *) &sparcaudio_output_done
;
697 info
->Baudio
->output_callback_arg
= (void *) drv
;
698 info
->Baudio
->xmit_idle_char
= 0;
702 static void amd7930_stop_output(struct sparcaudio_driver
*drv
)
704 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
707 info
->Baudio
->output_ptr
= NULL
;
708 info
->Baudio
->output_count
= 0;
709 if (! info
->Baudio
->input_ptr
)
710 release_Baudio(info
);
714 static void amd7930_start_input(struct sparcaudio_driver
*drv
,
715 __u8
* buffer
, unsigned long count
)
717 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
719 if (! info
->Baudio
) {
720 request_Baudio(info
);
724 info
->Baudio
->input_ptr
= buffer
;
725 info
->Baudio
->input_count
= count
;
726 info
->Baudio
->input_format
= info
->format_type
;
727 info
->Baudio
->input_callback
= (void *) &sparcaudio_input_done
;
728 info
->Baudio
->input_callback_arg
= (void *) drv
;
732 static void amd7930_stop_input(struct sparcaudio_driver
*drv
)
734 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
737 info
->Baudio
->input_ptr
= NULL
;
738 info
->Baudio
->input_count
= 0;
739 if (! info
->Baudio
->output_ptr
)
740 release_Baudio(info
);
745 static void amd7930_sunaudio_getdev(struct sparcaudio_driver
*drv
,
746 audio_device_t
* audinfo
)
748 strncpy(audinfo
->name
, "SUNW,am79c30", sizeof(audinfo
->name
) - 1);
749 strncpy(audinfo
->version
, "a", sizeof(audinfo
->version
) - 1);
750 strncpy(audinfo
->config
, "onboard1", sizeof(audinfo
->config
) - 1);
753 static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver
*drv
)
755 return AUDIO_DEV_AMD
;
758 static int amd7930_get_formats(struct sparcaudio_driver
*drv
)
760 return (AFMT_MU_LAW
| AFMT_A_LAW
| AFMT_U8
| AFMT_S16_BE
);
763 static int amd7930_get_output_ports(struct sparcaudio_driver
*drv
)
765 return (AUDIO_SPEAKER
| AUDIO_HEADPHONE
);
768 static int amd7930_get_input_ports(struct sparcaudio_driver
*drv
)
770 return (AUDIO_MICROPHONE
);
773 static int amd7930_set_output_volume(struct sparcaudio_driver
*drv
, int vol
)
775 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
778 amd7930_update_map(drv
);
782 static int amd7930_get_output_volume(struct sparcaudio_driver
*drv
)
784 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
789 static int amd7930_set_input_volume(struct sparcaudio_driver
*drv
, int vol
)
791 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
794 amd7930_update_map(drv
);
798 static int amd7930_get_input_volume(struct sparcaudio_driver
*drv
)
800 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
805 static int amd7930_set_monitor_volume(struct sparcaudio_driver
*drv
, int vol
)
807 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
810 amd7930_update_map(drv
);
814 static int amd7930_get_monitor_volume(struct sparcaudio_driver
*drv
)
816 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
821 /* Cheats. The amd has the minimum capabilities we support */
822 static int amd7930_get_output_balance(struct sparcaudio_driver
*drv
)
824 return AUDIO_MID_BALANCE
;
827 static int amd7930_get_input_balance(struct sparcaudio_driver
*drv
)
829 return AUDIO_MID_BALANCE
;
832 static int amd7930_get_output_channels(struct sparcaudio_driver
*drv
)
834 return AUDIO_MIN_PLAY_CHANNELS
;
837 static int amd7930_set_output_channels(struct sparcaudio_driver
*drv
,
840 return (value
== AUDIO_MIN_PLAY_CHANNELS
) ? 0 : -EINVAL
;
843 static int amd7930_get_input_channels(struct sparcaudio_driver
*drv
)
845 return AUDIO_MIN_REC_CHANNELS
;
849 amd7930_set_input_channels(struct sparcaudio_driver
*drv
, int value
)
851 return (value
== AUDIO_MIN_REC_CHANNELS
) ? 0 : -EINVAL
;
854 static int amd7930_get_output_precision(struct sparcaudio_driver
*drv
)
856 return AUDIO_MIN_PLAY_PRECISION
;
860 amd7930_set_output_precision(struct sparcaudio_driver
*drv
, int value
)
862 return (value
== AUDIO_MIN_PLAY_PRECISION
) ? 0 : -EINVAL
;
865 static int amd7930_get_input_precision(struct sparcaudio_driver
*drv
)
867 return AUDIO_MIN_REC_PRECISION
;
871 amd7930_set_input_precision(struct sparcaudio_driver
*drv
, int value
)
873 return (value
== AUDIO_MIN_REC_PRECISION
) ? 0 : -EINVAL
;
876 static int amd7930_get_output_port(struct sparcaudio_driver
*drv
)
878 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
879 if (info
->map
.mmr2
& AM_MAP_MMR2_LS
)
880 return AUDIO_SPEAKER
;
881 return AUDIO_HEADPHONE
;
884 static int amd7930_set_output_port(struct sparcaudio_driver
*drv
, int value
)
886 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
888 case AUDIO_HEADPHONE
:
889 info
->map
.mmr2
&= ~AM_MAP_MMR2_LS
;
892 info
->map
.mmr2
|= AM_MAP_MMR2_LS
;
897 amd7930_update_map(drv
);
901 /* Only a microphone here, so no troubles */
902 static int amd7930_get_input_port(struct sparcaudio_driver
*drv
)
904 return AUDIO_MICROPHONE
;
907 static int amd7930_get_encoding(struct sparcaudio_driver
*drv
)
909 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
910 if ((info
->map
.mmr1
& AM_MAP_MMR1_ALAW
) &&
911 (info
->format_type
== AUDIO_ENCODING_ALAW
))
912 return AUDIO_ENCODING_ALAW
;
914 return info
->format_type
;
918 amd7930_set_encoding(struct sparcaudio_driver
*drv
, int value
)
920 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
923 case AUDIO_ENCODING_ALAW
:
924 info
->map
.mmr1
|= AM_MAP_MMR1_ALAW
;
926 case AUDIO_ENCODING_LINEAR8
:
927 case AUDIO_ENCODING_LINEAR
:
928 case AUDIO_ENCODING_ULAW
:
929 info
->map
.mmr1
&= ~AM_MAP_MMR1_ALAW
;
935 info
->format_type
= value
;
937 amd7930_update_map(drv
);
941 /* This is what you get. Take it or leave it */
942 static int amd7930_get_output_rate(struct sparcaudio_driver
*drv
)
948 amd7930_set_output_rate(struct sparcaudio_driver
*drv
, int value
)
950 return (value
== AMD7930_RATE
) ? 0 : -EINVAL
;
953 static int amd7930_get_input_rate(struct sparcaudio_driver
*drv
)
959 amd7930_set_input_rate(struct sparcaudio_driver
*drv
, int value
)
961 return (value
== AMD7930_RATE
) ? 0 : -EINVAL
;
964 static int amd7930_get_output_muted(struct sparcaudio_driver
*drv
)
969 static void amd7930_loopback(struct sparcaudio_driver
*drv
, unsigned int value
)
971 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
974 info
->map
.mmr1
|= AM_MAP_MMR1_LOOPBACK
;
976 info
->map
.mmr1
&= ~AM_MAP_MMR1_LOOPBACK
;
977 amd7930_update_map(drv
);
981 static int amd7930_ioctl(struct inode
* inode
, struct file
* file
,
982 unsigned int cmd
, unsigned long arg
,
983 struct sparcaudio_driver
*drv
)
988 case AUDIO_DIAG_LOOPBACK
:
989 amd7930_loopback(drv
, (unsigned int)arg
);
1002 * Many of these routines take an "int dev" argument, which is simply
1003 * an index into the drivers[] array. Currently, we only support a
1004 * single AMD 7930 chip, so the value should always be 0. B channel
1005 * operations require an "int chan", which should be 0 for channel B1
1006 * and 1 for channel B2
1008 * int amd7930_get_irqnum(int dev)
1010 * returns the interrupt number being used by the chip. ISDN4linux
1011 * uses this number to watch the interrupt during initialization and
1012 * make sure something is happening.
1014 * int amd7930_get_liu_state(int dev)
1016 * returns the current state of the ISDN Line Interface Unit (LIU)
1017 * as a number between 2 (state F2) and 7 (state F7). 0 may also be
1018 * returned if the chip doesn't exist or the LIU hasn't been
1019 * activated. The meanings of the states are defined in I.430, ISDN
1020 * BRI Physical Layer Interface. The most important two states are
1021 * F3 (shutdown) and F7 (syncronized).
1023 * void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
1025 * initializes the LIU and optionally registers a callback to be
1026 * signaled upon a change of LIU state. The callback will be called
1027 * with a single opaque callback_arg Once the callback has been
1028 * triggered, amd7930_get_liu_state can be used to determine the LIU
1031 * void amd7930_liu_activate(int dev, int priority)
1033 * requests LIU activation at a given D-channel priority.
1034 * Successful activatation is achieved upon entering state F7, which
1035 * will trigger any callback previously registered with
1038 * void amd7930_liu_deactivate(int dev)
1040 * deactivates LIU. Outstanding D and B channel transactions are
1041 * terminated rudely and without callback notification. LIU change
1042 * of state callback will be triggered, however.
1044 * void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
1045 * void (*callback)(void *, int), void *callback_arg)
1047 * transmits a packet - specified with buffer, count - over the D-channel
1048 * interface. Buffer should begin with the LAPD address field and
1049 * end with the information field. FCS and flag sequences should not
1050 * be included, nor is bit-stuffing required - all these functions are
1051 * performed by the chip. The callback function will be called
1052 * DURING THE TOP HALF OF AN INTERRUPT HANDLER and will be passed
1053 * both the arbitrary callback_arg and an integer error indication:
1055 * 0 - successful transmission; ready for next packet
1056 * non-0 - error value from chip's DER (D-Channel Error Register):
1057 * 4 - collision detect
1058 * 128 - underrun; irq routine didn't service chip fast enough
1060 * The callback routine should defer any time-consuming operations
1061 * to a bottom-half handler; however, amd7930_dxmit may be called
1062 * from within the callback to request back-to-back transmission of
1063 * a second packet (without repeating the priority/collision mechanism)
1065 * A comment about the "collision detect" error, which is signalled
1066 * whenever the echoed D-channel data didn't match the transmitted
1067 * data. This is part of ISDN's normal multi-drop T-interface
1068 * operation, indicating that another device has attempted simultaneous
1069 * transmission, but can also result from line noise. An immediate
1070 * requeue via amd7930_dxmit is suggested, but repeated collision
1071 * errors may indicate a more serious problem.
1073 * void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
1074 * void (*callback)(void *, int, unsigned int),
1075 * void *callback_arg)
1077 * register a buffer - buffer, size - into which a D-channel packet
1078 * can be received. The callback function will be called DURING
1079 * THE TOP HALF OF AN INTERRUPT HANDLER and will be passed an
1080 * arbitrary callback_arg, an integer error indication and the length
1081 * of the received packet, which will start with the address field,
1082 * end with the information field, and not contain flag or FCS
1083 * bytes. Bit-stuffing will already have been corrected for.
1084 * Possible values of second callback argument "error":
1086 * 0 - successful reception
1087 * non-0 - error value from chip's DER (D-Channel Error Register):
1088 * 1 - received packet abort
1089 * 2 - framing error; non-integer number of bytes received
1090 * 8 - FCS error; CRC sequence indicated corrupted data
1091 * 16 - overflow error; packet exceeded size of buffer
1092 * 32 - underflow error; packet smaller than required five bytes
1093 * 64 - overrun error; irq routine didn't service chip fast enough
1095 * int amd7930_bopen(int dev, int chan, u_char xmit_idle_char)
1097 * This function should be called before any other operations on a B
1098 * channel. In addition to arranging for interrupt handling and
1099 * channel multiplexing, it sets the xmit_idle_char which is
1100 * transmitted on the interface when no data buffer is available.
1101 * Suggested values are: 0 for ISDN audio; FF for HDLC mark idle; 7E
1102 * for HDLC flag idle. Returns 0 on a successful open; -1 on error,
1103 * which is quite possible if audio and the other ISDN channel are
1104 * already in use, since the Am7930 can only send two of the three
1105 * channels to the processor
1107 * void amd7930_bclose(int dev, int chan)
1109 * Shuts down a B channel when no longer in use.
1111 * void amd7930_bxmit(int dev, int chan, __u8 *buffer, unsigned int count,
1112 * void (*callback)(void *), void *callback_arg)
1114 * transmits a raw data block - specified with buffer, count - over
1115 * the B channel interface specified by dev/chan. The callback
1116 * function will be called DURING THE TOP HALF OF AN INTERRUPT
1117 * HANDLER and will be passed the arbitrary callback_arg
1119 * The callback routine should defer any time-consuming operations
1120 * to a bottom-half handler; however, amd7930_bxmit may be called
1121 * from within the callback to request back-to-back transmission of
1122 * another data block
1124 * void amd7930_brecv(int dev, int chan, __u8 *buffer, unsigned int size,
1125 * void (*callback)(void *), void *callback_arg)
1127 * receive a raw data block - specified with buffer, size - over the
1128 * B channel interface specified by dev/chan. The callback function
1129 * will be called DURING THE TOP HALF OF AN INTERRUPT HANDLER and
1130 * will be passed the arbitrary callback_arg
1132 * The callback routine should defer any time-consuming operations
1133 * to a bottom-half handler; however, amd7930_brecv may be called
1134 * from within the callback to register another buffer and ensure
1135 * continuous B channel reception without loss of data
1139 #if defined (AMD79C30_ISDN) || defined (LINUX_VERSION_CODE) && LINUX_VERSION_CODE > 0x200ff
1140 static int amd7930_get_irqnum(int dev
)
1142 struct amd7930_info
*info
;
1144 if (dev
> num_drivers
) {
1148 info
= (struct amd7930_info
*) drivers
[dev
].private;
1153 static int amd7930_get_liu_state(int dev
)
1155 struct amd7930_info
*info
;
1157 if (dev
> num_drivers
) {
1161 info
= (struct amd7930_info
*) drivers
[dev
].private;
1163 return info
->liu_state
;
1166 static void amd7930_liu_init(int dev
, void (*callback
)(), void *callback_arg
)
1168 struct amd7930_info
*info
;
1169 register unsigned long flags
;
1171 if (dev
> num_drivers
) {
1175 info
= (struct amd7930_info
*) drivers
[dev
].private;
1177 save_and_cli(flags
);
1179 /* Set callback for LIU state change */
1180 info
->liu_callback
= callback
;
1181 info
->liu_callback_arg
= callback_arg
;
1183 /* De-activate the ISDN Line Interface Unit (LIU) */
1184 info
->regs
->cr
= AMR_LIU_LMR1
;
1187 /* Request interrupt when LIU changes state from/to F3/F7/F8 */
1188 info
->regs
->cr
= AMR_LIU_LMR2
;
1189 info
->regs
->dr
= AM_LIU_LMR2_EN_F3_INT
|
1190 AM_LIU_LMR2_EN_F7_INT
| AM_LIU_LMR2_EN_F8_INT
;
1192 /* amd7930_enable_ints(info); */
1194 /* Activate the ISDN Line Interface Unit (LIU) */
1195 info
->regs
->cr
= AMR_LIU_LMR1
;
1196 info
->regs
->dr
= AM_LIU_LMR1_LIU_ENABL
;
1198 restore_flags(flags
);
1201 static void amd7930_liu_activate(int dev
, int priority
)
1203 struct amd7930_info
*info
;
1204 register unsigned long flags
;
1206 if (dev
> num_drivers
) {
1210 info
= (struct amd7930_info
*) drivers
[dev
].private;
1212 save_and_cli(flags
);
1214 /* Set D-channel access priority
1216 * I.430 defines a priority mechanism based on counting 1s
1217 * in the echo channel before transmitting
1219 * Priority 0 is eight 1s; priority 1 is ten 1s; etc
1222 info
->regs
->cr
= AMR_LIU_LPR
;
1223 info
->regs
->dr
= priority
& 0x0f;
1225 /* request LIU activation */
1227 info
->regs
->cr
= AMR_LIU_LMR1
;
1228 info
->regs
->dr
= AM_LIU_LMR1_LIU_ENABL
| AM_LIU_LMR1_REQ_ACTIV
;
1230 restore_flags(flags
);
1233 static void amd7930_liu_deactivate(int dev
)
1235 struct amd7930_info
*info
;
1236 register unsigned long flags
;
1238 if (dev
> num_drivers
) {
1242 info
= (struct amd7930_info
*) drivers
[dev
].private;
1244 save_and_cli(flags
);
1246 /* deactivate LIU */
1248 info
->regs
->cr
= AMR_LIU_LMR1
;
1251 restore_flags(flags
);
1254 static void amd7930_dxmit(int dev
, __u8
*buffer
, unsigned int count
,
1255 void (*callback
)(void *, int), void *callback_arg
)
1257 struct amd7930_info
*info
;
1258 register unsigned long flags
;
1261 if (dev
> num_drivers
) {
1265 info
= (struct amd7930_info
*) drivers
[dev
].private;
1267 save_and_cli(flags
);
1269 if (info
->D
.output_ptr
) {
1270 restore_flags(flags
);
1271 printk("amd7930_dxmit: transmitter in use\n");
1275 info
->D
.output_ptr
= buffer
;
1276 info
->D
.output_count
= count
;
1277 info
->D
.output_callback
= callback
;
1278 info
->D
.output_callback_arg
= callback_arg
;
1280 /* Enable D-channel Transmit Threshold interrupt; disable addressing */
1281 info
->regs
->cr
= AMR_DLC_DMR1
;
1282 dmr1
= info
->regs
->dr
;
1283 dmr1
|= AMR_DLC_DMR1_DTTHRSH_INT
;
1284 dmr1
&= ~AMR_DLC_DMR1_EN_ADDRS
;
1285 info
->regs
->dr
= dmr1
;
1287 /* Begin xmit by setting D-channel Transmit Byte Count Reg (DTCR) */
1288 info
->regs
->cr
= AMR_DLC_DTCR
;
1289 info
->regs
->dr
= count
& 0xff;
1290 info
->regs
->dr
= (count
>> 8) & 0xff;
1292 /* Prime xmit FIFO */
1293 /* fill_D_xmit_fifo(info); */
1294 transceive_Dchannel(info
);
1296 restore_flags(flags
);
1299 static void amd7930_drecv(int dev
, __u8
*buffer
, unsigned int size
,
1300 void (*callback
)(void *, int, unsigned int),
1303 struct amd7930_info
*info
;
1304 register unsigned long flags
;
1307 if (dev
> num_drivers
) {
1311 info
= (struct amd7930_info
*) drivers
[dev
].private;
1313 save_and_cli(flags
);
1315 if (info
->D
.input_ptr
) {
1316 restore_flags(flags
);
1317 printk("amd7930_drecv: receiver already has buffer!\n");
1321 info
->D
.input_ptr
= buffer
;
1322 info
->D
.input_count
= 0;
1323 info
->D
.input_limit
= size
;
1324 info
->D
.input_callback
= callback
;
1325 info
->D
.input_callback_arg
= callback_arg
;
1327 /* Enable D-channel Receive Threshold interrupt;
1328 * Enable D-channel End of Receive Packet interrupt;
1329 * Disable address recognition
1331 info
->regs
->cr
= AMR_DLC_DMR1
;
1332 dmr1
= info
->regs
->dr
;
1333 dmr1
|= AMR_DLC_DMR1_DRTHRSH_INT
| AMR_DLC_DMR1_EORP_INT
;
1334 dmr1
&= ~AMR_DLC_DMR1_EN_ADDRS
;
1335 info
->regs
->dr
= dmr1
;
1337 /* Set D-channel Receive Byte Count Limit Register */
1338 info
->regs
->cr
= AMR_DLC_DRCR
;
1339 info
->regs
->dr
= size
& 0xff;
1340 info
->regs
->dr
= (size
>> 8) & 0xff;
1342 restore_flags(flags
);
1345 static int amd7930_bopen(int dev
, unsigned int chan
,
1346 int mode
, u_char xmit_idle_char
)
1348 struct amd7930_info
*info
;
1349 register unsigned long flags
;
1351 if (dev
> num_drivers
|| chan
<0 || chan
>1) {
1355 if (mode
== L1_MODE_HDLC
) {
1359 info
= (struct amd7930_info
*) drivers
[dev
].private;
1361 save_and_cli(flags
);
1363 if (info
->Bb
.channel_status
== CHANNEL_AVAILABLE
) {
1365 info
->Bb
.channel_status
= CHANNEL_INUSE
;
1366 info
->Bb
.xmit_idle_char
= xmit_idle_char
;
1367 info
->Bisdn
[chan
] = &info
->Bb
;
1369 /* Multiplexor map - isdn (B1/2) to Bb */
1370 info
->regs
->cr
= AMR_MUX_MCR2
+ chan
;
1371 info
->regs
->dr
= (AM_MUX_CHANNEL_B1
+ chan
) |
1372 (AM_MUX_CHANNEL_Bb
<< 4);
1374 } else if (info
->Bc
.channel_status
== CHANNEL_AVAILABLE
) {
1376 info
->Bc
.channel_status
= CHANNEL_INUSE
;
1377 info
->Bc
.xmit_idle_char
= xmit_idle_char
;
1378 info
->Bisdn
[chan
] = &info
->Bc
;
1380 /* Multiplexor map - isdn (B1/2) to Bc */
1381 info
->regs
->cr
= AMR_MUX_MCR2
+ chan
;
1382 info
->regs
->dr
= (AM_MUX_CHANNEL_B1
+ chan
) |
1383 (AM_MUX_CHANNEL_Bc
<< 4);
1386 restore_flags(flags
);
1390 /* Enable B channel transmit */
1391 info
->regs
->cr
= AMR_LIU_LMR1
;
1392 info
->regs
->dr
|= AM_LIU_LMR1_B1_ENABL
+ chan
;
1394 /* Enable B channel interrupts */
1395 info
->regs
->cr
= AMR_MUX_MCR4
;
1396 info
->regs
->dr
= AM_MUX_MCR4_ENABLE_INTS
| AM_MUX_MCR4_REVERSE_Bb
| AM_MUX_MCR4_REVERSE_Bc
;
1398 restore_flags(flags
);
1402 static void amd7930_bclose(int dev
, unsigned int chan
)
1404 struct amd7930_info
*info
;
1405 register unsigned long flags
;
1407 if (dev
> num_drivers
|| chan
<0 || chan
>1) {
1411 info
= (struct amd7930_info
*) drivers
[dev
].private;
1413 save_and_cli(flags
);
1415 if (info
->Bisdn
[chan
]) {
1416 info
->Bisdn
[chan
]->channel_status
= CHANNEL_AVAILABLE
;
1417 info
->regs
->cr
= AMR_MUX_MCR2
+ chan
;
1419 info
->Bisdn
[chan
] = NULL
;
1421 /* Disable B channel transmit */
1422 info
->regs
->cr
= AMR_LIU_LMR1
;
1423 info
->regs
->dr
&= ~(AM_LIU_LMR1_B1_ENABL
+ chan
);
1425 if (info
->Bb
.channel_status
== CHANNEL_AVAILABLE
&&
1426 info
->Bc
.channel_status
== CHANNEL_AVAILABLE
) {
1428 /* Disable B channel interrupts */
1429 info
->regs
->cr
= AMR_MUX_MCR4
;
1434 restore_flags(flags
);
1437 static void amd7930_bxmit(int dev
, unsigned int chan
,
1438 __u8
* buffer
, unsigned long count
,
1439 void (*callback
)(void *, int), void *callback_arg
)
1441 struct amd7930_info
*info
;
1442 struct amd7930_channel
*Bchan
;
1443 register unsigned long flags
;
1445 if (dev
> num_drivers
) {
1449 info
= (struct amd7930_info
*) drivers
[dev
].private;
1450 Bchan
= info
->Bisdn
[chan
];
1453 save_and_cli(flags
);
1455 Bchan
->output_ptr
= buffer
;
1456 Bchan
->output_count
= count
;
1457 Bchan
->output_format
= AUDIO_ENCODING_ULAW
;
1458 Bchan
->output_callback
= (void *) callback
;
1459 Bchan
->output_callback_arg
= callback_arg
;
1461 restore_flags(flags
);
1465 static void amd7930_brecv(int dev
, unsigned int chan
,
1466 __u8
* buffer
, unsigned long size
,
1467 void (*callback
)(void *, int, unsigned int),
1470 struct amd7930_info
*info
;
1471 struct amd7930_channel
*Bchan
;
1472 register unsigned long flags
;
1474 if (dev
> num_drivers
) {
1478 info
= (struct amd7930_info
*) drivers
[dev
].private;
1479 Bchan
= info
->Bisdn
[chan
];
1482 save_and_cli(flags
);
1484 Bchan
->input_ptr
= buffer
;
1485 Bchan
->input_count
= size
;
1486 Bchan
->input_format
= AUDIO_ENCODING_ULAW
;
1487 Bchan
->input_callback
= (void *) callback
;
1488 Bchan
->input_callback_arg
= callback_arg
;
1490 restore_flags(flags
);
1494 struct foreign_interface amd7930_foreign_interface
= {
1496 amd7930_get_liu_state
,
1498 amd7930_liu_activate
,
1499 amd7930_liu_deactivate
,
1507 EXPORT_SYMBOL(amd7930_foreign_interface
);
1512 * Device detection and initialization.
1515 static struct sparcaudio_operations amd7930_ops
= {
1519 amd7930_start_output
,
1520 amd7930_stop_output
,
1521 amd7930_start_input
,
1523 amd7930_sunaudio_getdev
,
1524 amd7930_set_output_volume
,
1525 amd7930_get_output_volume
,
1526 amd7930_set_input_volume
,
1527 amd7930_get_input_volume
,
1528 amd7930_set_monitor_volume
,
1529 amd7930_get_monitor_volume
,
1530 NULL
, /* amd7930_set_output_balance */
1531 amd7930_get_output_balance
,
1532 NULL
, /* amd7930_set_input_balance */
1533 amd7930_get_input_balance
,
1534 amd7930_set_output_channels
,
1535 amd7930_get_output_channels
,
1536 amd7930_set_input_channels
,
1537 amd7930_get_input_channels
,
1538 amd7930_set_output_precision
,
1539 amd7930_get_output_precision
,
1540 amd7930_set_input_precision
,
1541 amd7930_get_input_precision
,
1542 amd7930_set_output_port
,
1543 amd7930_get_output_port
,
1544 NULL
, /* amd7930_set_input_port */
1545 amd7930_get_input_port
,
1546 amd7930_set_encoding
,
1547 amd7930_get_encoding
,
1548 amd7930_set_encoding
,
1549 amd7930_get_encoding
,
1550 amd7930_set_output_rate
,
1551 amd7930_get_output_rate
,
1552 amd7930_set_input_rate
,
1553 amd7930_get_input_rate
,
1554 amd7930_sunaudio_getdev_sunos
,
1555 amd7930_get_output_ports
,
1556 amd7930_get_input_ports
,
1557 NULL
, /* amd7930_set_output_muted */
1558 amd7930_get_output_muted
,
1559 NULL
, /* amd7930_set_output_pause */
1560 NULL
, /* amd7930_get_output_pause */
1561 NULL
, /* amd7930_set_input_pause */
1562 NULL
, /* amd7930_get_input_pause */
1563 NULL
, /* amd7930_set_output_samples */
1564 NULL
, /* amd7930_get_output_samples */
1565 NULL
, /* amd7930_set_input_samples */
1566 NULL
, /* amd7930_get_input_samples */
1567 NULL
, /* amd7930_set_output_error */
1568 NULL
, /* amd7930_get_output_error */
1569 NULL
, /* amd7930_set_input_error */
1570 NULL
, /* amd7930_get_input_error */
1571 amd7930_get_formats
,
1574 /* Attach to an amd7930 chip given its PROM node. */
1575 static int amd7930_attach(struct sparcaudio_driver
*drv
, int node
,
1576 struct linux_sbus
*sbus
, struct linux_sbus_device
*sdev
)
1578 struct linux_prom_registers regs
;
1579 struct linux_prom_irqs irq
;
1580 struct amd7930_info
*info
;
1583 /* Allocate our private information structure. */
1584 drv
->private = kmalloc(sizeof(struct amd7930_info
), GFP_KERNEL
);
1588 /* Point at the information structure and initialize it. */
1589 drv
->ops
= &amd7930_ops
;
1590 info
= (struct amd7930_info
*)drv
->private;
1591 memset(info
, 0, sizeof(*info
));
1592 info
->ints_on
= 1; /* force disable below */
1596 /* Map the registers into memory. */
1597 prom_getproperty(node
, "reg", (char *)®s
, sizeof(regs
));
1599 prom_apply_sbus_ranges(sbus
, ®s
, 1, sdev
);
1600 info
->regs_size
= regs
.reg_size
;
1601 info
->regs
= sparc_alloc_io(regs
.phys_addr
, 0, regs
.reg_size
,
1602 "amd7930", regs
.which_io
, 0);
1604 printk(KERN_ERR
"amd7930: could not allocate registers\n");
1605 kfree(drv
->private);
1609 /* Put amd7930 in idle mode (interrupts disabled) */
1612 /* Enable extended FIFO operation on D-channel */
1613 info
->regs
->cr
= AMR_DLC_EFCR
;
1614 info
->regs
->dr
= AMR_DLC_EFCR_EXTEND_FIFO
;
1615 info
->regs
->cr
= AMR_DLC_DMR4
;
1616 info
->regs
->dr
= /* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14
;
1618 /* Attach the interrupt handler to the audio interrupt. */
1619 prom_getproperty(node
, "intr", (char *)&irq
, sizeof(irq
));
1620 info
->irq
= irq
.pri
;
1621 request_irq(info
->irq
, amd7930_interrupt
,
1622 SA_INTERRUPT
, "amd7930", drv
);
1623 enable_irq(info
->irq
);
1624 amd7930_enable_ints(info
);
1626 /* Initalize the local copy of the MAP registers. */
1627 memset(&info
->map
, 0, sizeof(info
->map
));
1628 info
->map
.mmr1
= AM_MAP_MMR1_GX
| AM_MAP_MMR1_GER
1629 | AM_MAP_MMR1_GR
| AM_MAP_MMR1_STG
;
1630 /* Start out with speaker, microphone */
1631 info
->map
.mmr2
|= (AM_MAP_MMR2_LS
| AM_MAP_MMR2_AINB
);
1633 /* Set the default audio parameters. */
1637 info
->format_type
= AUDIO_ENCODING_ULAW
;
1638 info
->Bb
.input_format
= AUDIO_ENCODING_ULAW
;
1639 info
->Bb
.output_format
= AUDIO_ENCODING_ULAW
;
1640 info
->Bc
.input_format
= AUDIO_ENCODING_ULAW
;
1641 info
->Bc
.output_format
= AUDIO_ENCODING_ULAW
;
1642 amd7930_update_map(drv
);
1644 /* Register the amd7930 with the midlevel audio driver. */
1645 err
= register_sparcaudio_driver(drv
, 1);
1647 printk(KERN_ERR
"amd7930: unable to register\n");
1648 disable_irq(info
->irq
);
1649 free_irq(info
->irq
, drv
);
1650 sparc_free_io(info
->regs
, info
->regs_size
);
1651 kfree(drv
->private);
1655 /* Announce the hardware to the user. */
1656 printk(KERN_INFO
"amd7930 at 0x%lx irq %d\n",
1657 (unsigned long)info
->regs
, info
->irq
);
1664 /* Detach from an amd7930 chip given the device structure. */
1665 static void amd7930_detach(struct sparcaudio_driver
*drv
)
1667 struct amd7930_info
*info
= (struct amd7930_info
*)drv
->private;
1669 unregister_sparcaudio_driver(drv
, 1);
1671 disable_irq(info
->irq
);
1672 free_irq(info
->irq
, drv
);
1673 sparc_free_io(info
->regs
, info
->regs_size
);
1674 kfree(drv
->private);
1678 /* Probe for the amd7930 chip and then attach the driver. */
1680 int init_module(void)
1682 int __init
amd7930_init(void)
1685 struct linux_sbus
*bus
;
1686 struct linux_sbus_device
*sdev
;
1689 /* Try to find the sun4c "audio" node first. */
1690 node
= prom_getchild(prom_root_node
);
1691 node
= prom_searchsiblings(node
, "audio");
1692 if (node
&& amd7930_attach(&drivers
[0], node
, NULL
, NULL
) == 0)
1697 /* Probe each SBUS for amd7930 chips. */
1698 for_all_sbusdev(sdev
,bus
) {
1699 if (!strcmp(sdev
->prom_name
, "audio")) {
1700 /* Don't go over the max number of drivers. */
1701 if (num_drivers
>= MAX_DRIVERS
)
1704 if (amd7930_attach(&drivers
[num_drivers
],
1705 sdev
->prom_node
, sdev
->my_bus
, sdev
) == 0)
1710 /* Only return success if we found some amd7930 chips. */
1711 return (num_drivers
> 0) ? 0 : -EIO
;
1715 void cleanup_module(void)
1719 for (i
= 0; i
< num_drivers
; i
++) {
1720 amd7930_detach(&drivers
[i
]);
1727 /*************************************************************/
1728 /* Audio format conversion */
1729 /*************************************************************/
1731 /* Translation tables */
1733 static unsigned char ulaw
[] = {
1734 3, 7, 11, 15, 19, 23, 27, 31,
1735 35, 39, 43, 47, 51, 55, 59, 63,
1736 66, 68, 70, 72, 74, 76, 78, 80,
1737 82, 84, 86, 88, 90, 92, 94, 96,
1738 98, 99, 100, 101, 102, 103, 104, 105,
1739 106, 107, 108, 109, 110, 111, 112, 113,
1740 113, 114, 114, 115, 115, 116, 116, 117,
1741 117, 118, 118, 119, 119, 120, 120, 121,
1742 121, 121, 122, 122, 122, 122, 123, 123,
1743 123, 123, 124, 124, 124, 124, 125, 125,
1744 125, 125, 125, 125, 126, 126, 126, 126,
1745 126, 126, 126, 126, 127, 127, 127, 127,
1746 127, 127, 127, 127, 127, 127, 127, 127,
1747 128, 128, 128, 128, 128, 128, 128, 128,
1748 128, 128, 128, 128, 128, 128, 128, 128,
1749 128, 128, 128, 128, 128, 128, 128, 128,
1750 253, 249, 245, 241, 237, 233, 229, 225,
1751 221, 217, 213, 209, 205, 201, 197, 193,
1752 190, 188, 186, 184, 182, 180, 178, 176,
1753 174, 172, 170, 168, 166, 164, 162, 160,
1754 158, 157, 156, 155, 154, 153, 152, 151,
1755 150, 149, 148, 147, 146, 145, 144, 143,
1756 143, 142, 142, 141, 141, 140, 140, 139,
1757 139, 138, 138, 137, 137, 136, 136, 135,
1758 135, 135, 134, 134, 134, 134, 133, 133,
1759 133, 133, 132, 132, 132, 132, 131, 131,
1760 131, 131, 131, 131, 130, 130, 130, 130,
1761 130, 130, 130, 130, 129, 129, 129, 129,
1762 129, 129, 129, 129, 129, 129, 129, 129,
1763 128, 128, 128, 128, 128, 128, 128, 128,
1764 128, 128, 128, 128, 128, 128, 128, 128,
1765 128, 128, 128, 128, 128, 128, 128, 128
1768 static __u8
mulaw2bilinear(__u8 data
)
1774 static unsigned char linear
[] = {
1775 0, 0, 0, 0, 0, 0, 0, 1,
1776 0, 0, 0, 2, 0, 0, 0, 3,
1777 0, 0, 0, 4, 0, 0, 0, 5,
1778 0, 0, 0, 6, 0, 0, 0, 7,
1779 0, 0, 0, 8, 0, 0, 0, 9,
1780 0, 0, 0, 10, 0, 0, 0, 11,
1781 0, 0, 0, 12, 0, 0, 0, 13,
1782 0, 0, 0, 14, 0, 0, 0, 15,
1783 0, 0, 16, 0, 17, 0, 18, 0,
1784 19, 0, 20, 0, 21, 0, 22, 0,
1785 23, 0, 24, 0, 25, 0, 26, 0,
1786 27, 0, 28, 0, 29, 0, 30, 0,
1787 31, 0, 32, 33, 34, 35, 36, 37,
1788 38, 39, 40, 41, 42, 43, 44, 45,
1789 46, 48, 50, 52, 54, 56, 58, 60,
1790 62, 65, 69, 73, 77, 83, 91, 103,
1791 255, 231, 219, 211, 205, 201, 197, 193,
1792 190, 188, 186, 184, 182, 180, 178, 176,
1793 174, 173, 172, 171, 170, 169, 168, 167,
1794 166, 165, 164, 163, 162, 161, 160, 0,
1795 159, 0, 158, 0, 157, 0, 156, 0,
1796 155, 0, 154, 0, 153, 0, 152, 0,
1797 151, 0, 150, 0, 149, 0, 148, 0,
1798 147, 0, 146, 0, 145, 0, 144, 0,
1799 0, 143, 0, 0, 0, 142, 0, 0,
1800 0, 141, 0, 0, 0, 140, 0, 0,
1801 0, 139, 0, 0, 0, 138, 0, 0,
1802 0, 137, 0, 0, 0, 136, 0, 0,
1803 0, 135, 0, 0, 0, 134, 0, 0,
1804 0, 133, 0, 0, 0, 132, 0, 0,
1805 0, 131, 0, 0, 0, 130, 0, 0,
1806 0, 129, 0, 0, 0, 128, 0, 0
1809 static __u8
bilinear2mulaw(__u8 data
)
1811 return linear
[data
];
1814 static int exp_lut
[256] = {
1815 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1816 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1817 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1818 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1819 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1820 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1821 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1822 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1828 #define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8))
1830 static __u8
linear2mulaw(__u16 data
)
1832 static int sign
, exponent
, mantissa
;
1834 /* not really sure, if swapping is ok - comment next line to disable it */
1835 data
= SWAP_ENDIAN(data
);
1837 sign
= (data
>> 8) & 0x80;
1838 if (sign
!= 0) data
= -data
;
1840 if (data
> CLIP
) data
= CLIP
;
1842 exponent
= exp_lut
[(data
>> 7) & 0xFF];
1843 mantissa
= (data
>> (exponent
+ 3)) & 0x0F;
1845 return (~(sign
| (exponent
<< 4) | mantissa
));
1848 static __u16
mulaw2linear(__u8 data
)
1850 /* this conversion is not working */
1855 #define INOUT(x,y) (((x) << 16) | (y))
1856 static int convert_audio(int in_format
, int out_format
, __u8
* buffer
, int count
)
1858 static int i
,sign
,exponent
;
1861 if (in_format
== out_format
) return count
;
1863 switch(INOUT(in_format
, out_format
)) {
1864 case INOUT(AUDIO_ENCODING_ULAW
, AUDIO_ENCODING_LINEAR8
):
1865 for (i
= 0;i
< count
; i
++) {
1866 buffer
[i
] = ulaw
[buffer
[i
]];
1869 case INOUT(AUDIO_ENCODING_ULAW
, AUDIO_ENCODING_LINEAR
):
1871 case INOUT(AUDIO_ENCODING_LINEAR
, AUDIO_ENCODING_ULAW
):
1872 /* buffer is two-byte => convert to first */
1873 for (i
= 0; i
< count
/2; i
++) {
1874 data
= ((__u16
*)buffer
)[i
];
1875 sign
= (data
>> 8) & 0x80;
1876 if (data
> CLIP
) data
= CLIP
;
1878 exponent
= exp_lut
[(data
>> 7) & 0xFF];
1879 buffer
[i
] = ~(sign
| (exponent
<< 4) |
1880 ((data
>> (exponent
+ 3)) & 0x0F));
1883 case INOUT(AUDIO_ENCODING_LINEAR8
, AUDIO_ENCODING_ULAW
):
1884 for (i
= 0; i
< count
; i
++) {
1885 buffer
[i
] = linear
[buffer
[i
]];