1 /* $Id: amd7930.c,v 1.1.1.1 2005/04/11 02:50:34 jack Exp $
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/slab.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)
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 {
137 /* Current buffer that the driver is playing on channel */
138 volatile __u8 * output_ptr;
139 volatile u32 output_count;
142 /* Callback routine (and argument) when output is done on */
143 void (*output_callback)(void *, unsigned char);
144 void * output_callback_arg;
146 /* Current buffer that the driver is recording on channel */
147 volatile __u8 * input_ptr;
148 volatile u32 input_count;
149 volatile u32 input_limit;
151 /* Callback routine (and argument) when input is done on */
152 void (*input_callback)(void *, unsigned char, unsigned long);
153 void * input_callback_arg;
159 /* Private information we store for each amd7930 chip. */
160 struct amd7930_info {
161 struct amd7930_channel D;
162 struct amd7930_channel Bb;
163 struct amd7930_channel Bc;
165 /* Pointers to which B channels are being used for what
166 * These three fields (Baudio, Bisdn[0], and Bisdn[1]) will either
167 * be NULL or point to one of the Bb/Bc structures above.
169 struct amd7930_channel *Baudio;
170 struct amd7930_channel *Bisdn[2];
172 /* Device registers information. */
174 unsigned long regs_size;
175 struct amd7930_map map;
177 /* Volume information. */
178 int pgain, rgain, mgain;
180 /* Device interrupt information. */
182 volatile int ints_on;
187 /* Someone to signal when the ISDN LIU state changes */
189 void (*liu_callback)(void *);
190 void *liu_callback_arg;
193 /* Output a 16-bit quantity in the order that the amd7930 expects. */
194 static __inline__ void amd7930_out16(unsigned long regs, u16 val)
196 sbus_writeb(val & 0xff, regs + DR);
197 sbus_writeb(val >> 8, regs + DR);
200 /* gx, gr & stg gains. this table must contain 256 elements with
201 * the 0th being "infinity" (the magic value 9008). The remaining
202 * elements match sun's gain curve (but with higher resolution):
203 * -18 to 0dB in .16dB steps then 0 to 12dB in .08dB steps.
205 static __const__ __u16 gx_coeff[256] = {
206 0x9008, 0x8b7c, 0x8b51, 0x8b45, 0x8b42, 0x8b3b, 0x8b36, 0x8b33,
207 0x8b32, 0x8b2a, 0x8b2b, 0x8b2c, 0x8b25, 0x8b23, 0x8b22, 0x8b22,
208 0x9122, 0x8b1a, 0x8aa3, 0x8aa3, 0x8b1c, 0x8aa6, 0x912d, 0x912b,
209 0x8aab, 0x8b12, 0x8aaa, 0x8ab2, 0x9132, 0x8ab4, 0x913c, 0x8abb,
210 0x9142, 0x9144, 0x9151, 0x8ad5, 0x8aeb, 0x8a79, 0x8a5a, 0x8a4a,
211 0x8b03, 0x91c2, 0x91bb, 0x8a3f, 0x8a33, 0x91b2, 0x9212, 0x9213,
212 0x8a2c, 0x921d, 0x8a23, 0x921a, 0x9222, 0x9223, 0x922d, 0x9231,
213 0x9234, 0x9242, 0x925b, 0x92dd, 0x92c1, 0x92b3, 0x92ab, 0x92a4,
214 0x92a2, 0x932b, 0x9341, 0x93d3, 0x93b2, 0x93a2, 0x943c, 0x94b2,
215 0x953a, 0x9653, 0x9782, 0x9e21, 0x9d23, 0x9cd2, 0x9c23, 0x9baa,
216 0x9bde, 0x9b33, 0x9b22, 0x9b1d, 0x9ab2, 0xa142, 0xa1e5, 0x9a3b,
217 0xa213, 0xa1a2, 0xa231, 0xa2eb, 0xa313, 0xa334, 0xa421, 0xa54b,
218 0xada4, 0xac23, 0xab3b, 0xaaab, 0xaa5c, 0xb1a3, 0xb2ca, 0xb3bd,
219 0xbe24, 0xbb2b, 0xba33, 0xc32b, 0xcb5a, 0xd2a2, 0xe31d, 0x0808,
220 0x72ba, 0x62c2, 0x5c32, 0x52db, 0x513e, 0x4cce, 0x43b2, 0x4243,
221 0x41b4, 0x3b12, 0x3bc3, 0x3df2, 0x34bd, 0x3334, 0x32c2, 0x3224,
222 0x31aa, 0x2a7b, 0x2aaa, 0x2b23, 0x2bba, 0x2c42, 0x2e23, 0x25bb,
223 0x242b, 0x240f, 0x231a, 0x22bb, 0x2241, 0x2223, 0x221f, 0x1a33,
224 0x1a4a, 0x1acd, 0x2132, 0x1b1b, 0x1b2c, 0x1b62, 0x1c12, 0x1c32,
225 0x1d1b, 0x1e71, 0x16b1, 0x1522, 0x1434, 0x1412, 0x1352, 0x1323,
226 0x1315, 0x12bc, 0x127a, 0x1235, 0x1226, 0x11a2, 0x1216, 0x0a2a,
227 0x11bc, 0x11d1, 0x1163, 0x0ac2, 0x0ab2, 0x0aab, 0x0b1b, 0x0b23,
228 0x0b33, 0x0c0f, 0x0bb3, 0x0c1b, 0x0c3e, 0x0cb1, 0x0d4c, 0x0ec1,
229 0x079a, 0x0614, 0x0521, 0x047c, 0x0422, 0x03b1, 0x03e3, 0x0333,
230 0x0322, 0x031c, 0x02aa, 0x02ba, 0x02f2, 0x0242, 0x0232, 0x0227,
231 0x0222, 0x021b, 0x01ad, 0x0212, 0x01b2, 0x01bb, 0x01cb, 0x01f6,
232 0x0152, 0x013a, 0x0133, 0x0131, 0x012c, 0x0123, 0x0122, 0x00a2,
233 0x011b, 0x011e, 0x0114, 0x00b1, 0x00aa, 0x00b3, 0x00bd, 0x00ba,
234 0x00c5, 0x00d3, 0x00f3, 0x0062, 0x0051, 0x0042, 0x003b, 0x0033,
235 0x0032, 0x002a, 0x002c, 0x0025, 0x0023, 0x0022, 0x001a, 0x0021,
236 0x001b, 0x001b, 0x001d, 0x0015, 0x0013, 0x0013, 0x0012, 0x0012,
237 0x000a, 0x000a, 0x0011, 0x0011, 0x000b, 0x000b, 0x000c, 0x000e,
240 static __const__ __u16 ger_coeff[] = {
252 0x111f, /* 10.5 dB */
254 0x00dd, /* 11.5 dB */
259 0x2200, /* 15.9 dB */
260 0x000b, /* 16.9 dB */
263 #define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
265 /* Enable amd7930 interrupts atomically. */
266 static void amd7930_enable_ints(struct amd7930_info *info)
271 if (!info->ints_on) {
272 sbus_writeb(AMR_INIT, info->regs + CR);
273 sbus_writeb(AM_INIT_ACTIVE, info->regs + DR);
276 restore_flags(flags);
279 /* Disable amd7930 interrupts atomically. */
280 static __inline__ void amd7930_disable_ints(struct amd7930_info *info)
286 sbus_writeb(AMR_INIT, info->regs + CR);
287 sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS,
291 restore_flags(flags);
295 /* Idle amd7930 (no interrupts, no audio, no data) */
296 static __inline__ void amd7930_idle(struct amd7930_info *info)
302 sbus_writeb(AMR_INIT, info->regs + CR);
303 sbus_writeb(0, info->regs + DR);
306 restore_flags(flags);
309 /* Commit the local copy of the MAP registers to the amd7930. */
310 static void amd7930_write_map(struct sparcaudio_driver *drv)
312 struct amd7930_info *info = (struct amd7930_info *) drv->private;
313 unsigned long regs = info->regs;
314 struct amd7930_map *map = &info->map;
319 sbus_writeb(AMR_MAP_GX, regs + CR);
320 amd7930_out16(regs, map->gx);
322 sbus_writeb(AMR_MAP_GR, regs + CR);
323 amd7930_out16(regs, map->gr);
325 sbus_writeb(AMR_MAP_STGR, regs + CR);
326 amd7930_out16(regs, map->stgr);
328 sbus_writeb(AMR_MAP_GER, regs + CR);
329 amd7930_out16(regs, map->ger);
331 sbus_writeb(AMR_MAP_MMR1, regs + CR);
332 sbus_writeb(map->mmr1, regs + DR);
334 sbus_writeb(AMR_MAP_MMR2, regs + CR);
335 sbus_writeb(map->mmr2, regs + DR);
337 restore_flags(flags);
340 /* Update the MAP registers with new settings. */
341 static void amd7930_update_map(struct sparcaudio_driver *drv)
343 struct amd7930_info *info = (struct amd7930_info *) drv->private;
344 struct amd7930_map *map = &info->map;
347 map->gx = gx_coeff[info->rgain];
348 map->stgr = gx_coeff[info->mgain];
350 level = (info->pgain * (256 + NR_GER_COEFFS)) >> 8;
352 map->ger = ger_coeff[level - 256];
353 map->gr = gx_coeff[255];
355 map->ger = ger_coeff[0];
356 map->gr = gx_coeff[level];
359 amd7930_write_map(drv);
362 /* Bit of a hack here - if the HISAX ISDN driver has got INTSTAT debugging
363 * turned on, we send debugging characters to the ISDN driver:
365 * i# - Interrupt received - number from 0 to 7 is low three bits of IR
366 * > - Loaded a single char into the Dchan xmit FIFO
367 * + - Finished loading an xmit packet into the Dchan xmit FIFO
368 * < - Read a single char from the Dchan recv FIFO
369 * ! - Finished reading a packet from the Dchan recv FIFO
371 * This code needs to be removed if anything other than HISAX uses the ISDN
372 * driver, since D.output_callback_arg is assumed to be a certain struct ptr
377 inline void debug_info(struct amd7930_info *info, char c)
379 struct IsdnCardState *cs;
381 if (!info || !info->D.output_callback_arg)
384 cs = (struct IsdnCardState *) info->D.output_callback_arg;
386 if (!cs || !cs->status_write)
389 if (cs->debug & L1_DEB_INTSTAT) {
390 *(cs->status_write++) = c;
391 if (cs->status_write > cs->status_end)
392 cs->status_write = cs->status_buf;
398 #define debug_info(info,c)
402 static void fill_D_xmit_fifo(struct amd7930_info *info)
404 /* Send next byte(s) of outgoing data. */
405 while (info->D.output_ptr && info->D.output_count > 0 &&
406 (sbus_readb(info->regs + DSR2) & AMR_DSR2_TBE)) {
407 u8 byte = *(info->D.output_ptr);
409 /* Send the next byte and advance buffer pointer. */
410 sbus_writeb(byte, info->regs + DCTB);
411 info->D.output_ptr++;
412 info->D.output_count--;
414 debug_info(info, '>');
418 static void transceive_Dchannel(struct amd7930_info *info)
422 #define D_XMIT_ERRORS (AMR_DER_COLLISION | AMR_DER_UNRN)
423 #define D_RECV_ERRORS (AMR_DER_RABRT | AMR_DER_RFRAME | AMR_DER_FCS | \
424 AMR_DER_OVFL | AMR_DER_UNFL | AMR_DER_OVRN)
426 /* Transmit if we can */
427 fill_D_xmit_fifo(info);
429 /* Done with the xmit buffer? Notify the midlevel driver. */
430 if (info->D.output_ptr != NULL && info->D.output_count == 0) {
431 info->D.output_ptr = NULL;
432 info->D.output_count = 0;
433 debug_info(info, '+');
434 if (info->D.output_callback)
435 (*info->D.output_callback)
436 (info->D.output_callback_arg,
437 sbus_readb(info->regs + DER));
438 /* sbus_readb(info->regs + DER) & D_XMIT_ERRORS); */
441 /* Read the next byte(s) of incoming data. */
443 while (sbus_readb(info->regs + DSR2) & AMR_DSR2_RBA) {
444 if (info->D.input_ptr &&
445 (info->D.input_count < info->D.input_limit)) {
446 /* Get the next byte and advance buffer pointer. */
447 *(info->D.input_ptr) = sbus_readb(info->regs + DCRB);
449 info->D.input_count++;
451 /* Overflow - should be detected by chip via RBLR
452 * so we'll just consume data until we see LBRP
454 dummy = sbus_readb(info->regs + DCRB);
457 debug_info(info, '<');
459 if (sbus_readb(info->regs + DSR2) & AMR_DSR2_LBRP) {
462 /* End of recv packet? Notify the midlevel driver. */
463 debug_info(info, '!');
464 info->D.input_ptr = NULL;
465 der = sbus_readb(info->regs + DER) & D_RECV_ERRORS;
467 /* Read receive byte count - advances FIFOs */
468 sbus_writeb(AMR_DLC_DRCR, info->regs + CR);
469 dummy = sbus_readb(info->regs + DR);
470 dummy = sbus_readb(info->regs + DR);
472 if (info->D.input_callback)
473 (*info->D.input_callback)
474 (info->D.input_callback_arg, der,
475 info->D.input_count);
481 long amd7930_xmit_idles = 0;
483 static void transceive_Bchannel(struct amd7930_channel *channel,
486 /* Send the next byte of outgoing data. */
487 if (channel->output_ptr && channel->output_count > 0) {
490 /* Send the next byte and advance buffer pointer. */
491 switch(channel->output_format) {
492 case AUDIO_ENCODING_ULAW:
493 case AUDIO_ENCODING_ALAW:
494 byte = *(channel->output_ptr);
495 sbus_writeb(byte, reg);
497 case AUDIO_ENCODING_LINEAR8:
498 byte = bilinear2mulaw(*(channel->output_ptr));
499 sbus_writeb(byte, reg);
501 case AUDIO_ENCODING_LINEAR:
502 if (channel->output_count >= 2) {
503 u16 val = channel->output_ptr[0] << 8;
505 val |= channel->output_ptr[1];
506 byte = linear2mulaw(val);
507 sbus_writeb(byte, reg);
508 channel->output_ptr++;
509 channel->output_count--;
512 channel->output_ptr++;
513 channel->output_count--;
516 /* Done with the buffer? Notify the midlevel driver. */
517 if (channel->output_count == 0) {
518 channel->output_ptr = NULL;
519 channel->output_count = 0;
520 if (channel->output_callback)
521 (*channel->output_callback)
522 (channel->output_callback_arg,1);
525 sbus_writeb(channel->xmit_idle_char, reg);
526 amd7930_xmit_idles++;
529 /* Read the next byte of incoming data. */
530 if (channel->input_ptr && channel->input_count > 0) {
531 /* Get the next byte and advance buffer pointer. */
532 switch(channel->input_format) {
533 case AUDIO_ENCODING_ULAW:
534 case AUDIO_ENCODING_ALAW:
535 *(channel->input_ptr) = sbus_readb(reg);
537 case AUDIO_ENCODING_LINEAR8:
538 *(channel->input_ptr) = mulaw2bilinear(sbus_readb(reg));
540 case AUDIO_ENCODING_LINEAR:
541 if (channel->input_count >= 2) {
542 u16 val = mulaw2linear(sbus_readb(reg));
543 channel->input_ptr[0] = val >> 8;
544 channel->input_ptr[1] = val & 0xff;
545 channel->input_ptr++;
546 channel->input_count--;
548 *(channel->input_ptr) = 0;
551 channel->input_ptr++;
552 channel->input_count--;
554 /* Done with the buffer? Notify the midlevel driver. */
555 if (channel->input_count == 0) {
556 channel->input_ptr = NULL;
557 channel->input_count = 0;
558 if (channel->input_callback)
559 (*channel->input_callback)
560 (channel->input_callback_arg, 1, 0);
565 /* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */
566 static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs)
568 struct sparcaudio_driver *drv = (struct sparcaudio_driver *) dev_id;
569 struct amd7930_info *info = (struct amd7930_info *) drv->private;
570 unsigned long regs = info->regs;
573 /* Clear the interrupt. */
574 ir = sbus_readb(regs + IR);
576 if (ir & AMR_IR_BBUF) {
577 if (info->Bb.channel_status == CHANNEL_INUSE)
578 transceive_Bchannel(&info->Bb, info->regs + BBTB);
579 if (info->Bc.channel_status == CHANNEL_INUSE)
580 transceive_Bchannel(&info->Bc, info->regs + BCTB);
583 if (ir & (AMR_IR_DRTHRSH | AMR_IR_DTTHRSH | AMR_IR_DSRI)) {
584 debug_info(info, 'i');
585 debug_info(info, '0' + (ir&7));
586 transceive_Dchannel(info);
589 if (ir & AMR_IR_LSRI) {
592 sbus_writeb(AMR_LIU_LSR, regs + CR);
593 lsr = sbus_readb(regs + DR);
595 info->liu_state = (lsr & 0x7) + 2;
597 if (info->liu_callback)
598 (*info->liu_callback)(info->liu_callback_arg);
602 static int amd7930_open(struct inode * inode, struct file * file,
603 struct sparcaudio_driver *drv)
605 struct amd7930_info *info = (struct amd7930_info *) drv->private;
607 switch(MINOR(inode->i_rdev) & 0xf) {
608 case SPARCAUDIO_AUDIO_MINOR:
609 info->format_type = AUDIO_ENCODING_ULAW;
611 case SPARCAUDIO_DSP_MINOR:
612 info->format_type = AUDIO_ENCODING_LINEAR8;
614 case SPARCAUDIO_DSP16_MINOR:
615 info->format_type = AUDIO_ENCODING_LINEAR;
623 static void amd7930_release(struct inode * inode, struct file * file,
624 struct sparcaudio_driver *drv)
626 /* amd7930_disable_ints(drv->private); */
630 static void request_Baudio(struct amd7930_info *info)
632 if (info->Bb.channel_status == CHANNEL_AVAILABLE) {
633 info->Bb.channel_status = CHANNEL_INUSE;
634 info->Baudio = &info->Bb;
636 /* Multiplexor map - audio (Ba) to Bb */
637 sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
638 sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bb << 4),
641 /* Enable B channel interrupts */
642 sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
643 sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);
644 } else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {
645 info->Bc.channel_status = CHANNEL_INUSE;
646 info->Baudio = &info->Bc;
648 /* Multiplexor map - audio (Ba) to Bc */
649 sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
650 sbus_writeb(AM_MUX_CHANNEL_Ba | (AM_MUX_CHANNEL_Bc << 4),
653 /* Enable B channel interrupts */
654 sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
655 sbus_writeb(AM_MUX_MCR4_ENABLE_INTS, info->regs + DR);
659 static void release_Baudio(struct amd7930_info *info)
662 info->Baudio->channel_status = CHANNEL_AVAILABLE;
663 sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
664 sbus_writeb(0, info->regs + DR);
667 if (info->Bb.channel_status == CHANNEL_AVAILABLE &&
668 info->Bc.channel_status == CHANNEL_AVAILABLE) {
669 /* Disable B channel interrupts */
670 sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
671 sbus_writeb(0, info->regs + DR);
676 static void amd7930_start_output(struct sparcaudio_driver *drv,
677 __u8 * buffer, unsigned long count)
679 struct amd7930_info *info = (struct amd7930_info *) drv->private;
682 request_Baudio(info);
685 info->Baudio->output_ptr = buffer;
686 info->Baudio->output_count = count;
687 info->Baudio->output_format = info->format_type;
688 info->Baudio->output_callback = (void *) &sparcaudio_output_done;
689 info->Baudio->output_callback_arg = (void *) drv;
690 info->Baudio->xmit_idle_char = 0;
694 static void amd7930_stop_output(struct sparcaudio_driver *drv)
696 struct amd7930_info *info = (struct amd7930_info *) drv->private;
699 info->Baudio->output_ptr = NULL;
700 info->Baudio->output_count = 0;
701 if (! info->Baudio->input_ptr)
702 release_Baudio(info);
706 static void amd7930_start_input(struct sparcaudio_driver *drv,
707 __u8 * buffer, unsigned long count)
709 struct amd7930_info *info = (struct amd7930_info *) drv->private;
712 request_Baudio(info);
715 info->Baudio->input_ptr = buffer;
716 info->Baudio->input_count = count;
717 info->Baudio->input_format = info->format_type;
718 info->Baudio->input_callback = (void *) &sparcaudio_input_done;
719 info->Baudio->input_callback_arg = (void *) drv;
723 static void amd7930_stop_input(struct sparcaudio_driver *drv)
725 struct amd7930_info *info = (struct amd7930_info *) drv->private;
728 info->Baudio->input_ptr = NULL;
729 info->Baudio->input_count = 0;
730 if (! info->Baudio->output_ptr)
731 release_Baudio(info);
736 static void amd7930_sunaudio_getdev(struct sparcaudio_driver *drv,
737 audio_device_t * audinfo)
739 strncpy(audinfo->name, "SUNW,am79c30", sizeof(audinfo->name) - 1);
740 strncpy(audinfo->version, "a", sizeof(audinfo->version) - 1);
741 strncpy(audinfo->config, "onboard1", sizeof(audinfo->config) - 1);
744 static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv)
746 return AUDIO_DEV_AMD;
749 static int amd7930_get_formats(struct sparcaudio_driver *drv)
751 return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S16_BE);
754 static int amd7930_get_output_ports(struct sparcaudio_driver *drv)
756 return (AUDIO_SPEAKER | AUDIO_HEADPHONE);
759 static int amd7930_get_input_ports(struct sparcaudio_driver *drv)
761 return (AUDIO_MICROPHONE);
764 static int amd7930_set_output_volume(struct sparcaudio_driver *drv, int vol)
766 struct amd7930_info *info = (struct amd7930_info *) drv->private;
769 amd7930_update_map(drv);
773 static int amd7930_get_output_volume(struct sparcaudio_driver *drv)
775 struct amd7930_info *info = (struct amd7930_info *) drv->private;
780 static int amd7930_set_input_volume(struct sparcaudio_driver *drv, int vol)
782 struct amd7930_info *info = (struct amd7930_info *) drv->private;
785 amd7930_update_map(drv);
789 static int amd7930_get_input_volume(struct sparcaudio_driver *drv)
791 struct amd7930_info *info = (struct amd7930_info *) drv->private;
796 static int amd7930_set_monitor_volume(struct sparcaudio_driver *drv, int vol)
798 struct amd7930_info *info = (struct amd7930_info *) drv->private;
801 amd7930_update_map(drv);
805 static int amd7930_get_monitor_volume(struct sparcaudio_driver *drv)
807 struct amd7930_info *info = (struct amd7930_info *) drv->private;
812 /* Cheats. The amd has the minimum capabilities we support */
813 static int amd7930_get_output_balance(struct sparcaudio_driver *drv)
815 return AUDIO_MID_BALANCE;
818 static int amd7930_get_input_balance(struct sparcaudio_driver *drv)
820 return AUDIO_MID_BALANCE;
823 static int amd7930_get_output_channels(struct sparcaudio_driver *drv)
825 return AUDIO_MIN_PLAY_CHANNELS;
828 static int amd7930_set_output_channels(struct sparcaudio_driver *drv,
831 return (value == AUDIO_MIN_PLAY_CHANNELS) ? 0 : -EINVAL;
834 static int amd7930_get_input_channels(struct sparcaudio_driver *drv)
836 return AUDIO_MIN_REC_CHANNELS;
840 amd7930_set_input_channels(struct sparcaudio_driver *drv, int value)
842 return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL;
845 static int amd7930_get_output_precision(struct sparcaudio_driver *drv)
847 return AUDIO_MIN_PLAY_PRECISION;
851 amd7930_set_output_precision(struct sparcaudio_driver *drv, int value)
853 return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL;
856 static int amd7930_get_input_precision(struct sparcaudio_driver *drv)
858 return AUDIO_MIN_REC_PRECISION;
862 amd7930_set_input_precision(struct sparcaudio_driver *drv, int value)
864 return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL;
867 static int amd7930_get_output_port(struct sparcaudio_driver *drv)
869 struct amd7930_info *info = (struct amd7930_info *) drv->private;
871 if (info->map.mmr2 & AM_MAP_MMR2_LS)
872 return AUDIO_SPEAKER;
874 return AUDIO_HEADPHONE;
877 static int amd7930_set_output_port(struct sparcaudio_driver *drv, int value)
879 struct amd7930_info *info = (struct amd7930_info *) drv->private;
882 case AUDIO_HEADPHONE:
883 info->map.mmr2 &= ~AM_MAP_MMR2_LS;
886 info->map.mmr2 |= AM_MAP_MMR2_LS;
892 amd7930_update_map(drv);
896 /* Only a microphone here, so no troubles */
897 static int amd7930_get_input_port(struct sparcaudio_driver *drv)
899 return AUDIO_MICROPHONE;
902 static int amd7930_get_encoding(struct sparcaudio_driver *drv)
904 struct amd7930_info *info = (struct amd7930_info *) drv->private;
906 if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) &&
907 (info->format_type == AUDIO_ENCODING_ALAW))
908 return AUDIO_ENCODING_ALAW;
910 return info->format_type;
914 amd7930_set_encoding(struct sparcaudio_driver *drv, int value)
916 struct amd7930_info *info = (struct amd7930_info *) drv->private;
919 case AUDIO_ENCODING_ALAW:
920 info->map.mmr1 |= AM_MAP_MMR1_ALAW;
922 case AUDIO_ENCODING_LINEAR8:
923 case AUDIO_ENCODING_LINEAR:
924 case AUDIO_ENCODING_ULAW:
925 info->map.mmr1 &= ~AM_MAP_MMR1_ALAW;
931 info->format_type = value;
933 amd7930_update_map(drv);
937 /* This is what you get. Take it or leave it */
938 static int amd7930_get_output_rate(struct sparcaudio_driver *drv)
944 amd7930_set_output_rate(struct sparcaudio_driver *drv, int value)
946 return (value == AMD7930_RATE) ? 0 : -EINVAL;
949 static int amd7930_get_input_rate(struct sparcaudio_driver *drv)
955 amd7930_set_input_rate(struct sparcaudio_driver *drv, int value)
957 return (value == AMD7930_RATE) ? 0 : -EINVAL;
960 static int amd7930_get_output_muted(struct sparcaudio_driver *drv)
965 static void amd7930_loopback(struct sparcaudio_driver *drv, unsigned int value)
967 struct amd7930_info *info = (struct amd7930_info *) drv->private;
970 info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK;
972 info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK;
973 amd7930_update_map(drv);
976 static int amd7930_ioctl(struct inode * inode, struct file * file,
977 unsigned int cmd, unsigned long arg,
978 struct sparcaudio_driver *drv)
983 case AUDIO_DIAG_LOOPBACK:
984 amd7930_loopback(drv, (unsigned int)arg);
997 * Many of these routines take an "int dev" argument, which is simply
998 * an index into the drivers[] array. Currently, we only support a
999 * single AMD 7930 chip, so the value should always be 0. B channel
1000 * operations require an "int chan", which should be 0 for channel B1
1001 * and 1 for channel B2
1003 * int amd7930_get_irqnum(int dev)
1005 * returns the interrupt number being used by the chip. ISDN4linux
1006 * uses this number to watch the interrupt during initialization and
1007 * make sure something is happening.
1009 * int amd7930_get_liu_state(int dev)
1011 * returns the current state of the ISDN Line Interface Unit (LIU)
1012 * as a number between 2 (state F2) and 7 (state F7). 0 may also be
1013 * returned if the chip doesn't exist or the LIU hasn't been
1014 * activated. The meanings of the states are defined in I.430, ISDN
1015 * BRI Physical Layer Interface. The most important two states are
1016 * F3 (shutdown) and F7 (syncronized).
1018 * void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
1020 * initializes the LIU and optionally registers a callback to be
1021 * signaled upon a change of LIU state. The callback will be called
1022 * with a single opaque callback_arg Once the callback has been
1023 * triggered, amd7930_get_liu_state can be used to determine the LIU
1026 * void amd7930_liu_activate(int dev, int priority)
1028 * requests LIU activation at a given D-channel priority.
1029 * Successful activatation is achieved upon entering state F7, which
1030 * will trigger any callback previously registered with
1033 * void amd7930_liu_deactivate(int dev)
1035 * deactivates LIU. Outstanding D and B channel transactions are
1036 * terminated rudely and without callback notification. LIU change
1037 * of state callback will be triggered, however.
1039 * void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
1040 * void (*callback)(void *, int), void *callback_arg)
1042 * transmits a packet - specified with buffer, count - over the D-channel
1043 * interface. Buffer should begin with the LAPD address field and
1044 * end with the information field. FCS and flag sequences should not
1045 * be included, nor is bit-stuffing required - all these functions are
1046 * performed by the chip. The callback function will be called
1047 * DURING THE TOP HALF OF AN INTERRUPT HANDLER and will be passed
1048 * both the arbitrary callback_arg and an integer error indication:
1050 * 0 - successful transmission; ready for next packet
1051 * non-0 - error value from chip's DER (D-Channel Error Register):
1052 * 4 - collision detect
1053 * 128 - underrun; irq routine didn't service chip fast enough
1055 * The callback routine should defer any time-consuming operations
1056 * to a bottom-half handler; however, amd7930_dxmit may be called
1057 * from within the callback to request back-to-back transmission of
1058 * a second packet (without repeating the priority/collision mechanism)
1060 * A comment about the "collision detect" error, which is signalled
1061 * whenever the echoed D-channel data didn't match the transmitted
1062 * data. This is part of ISDN's normal multi-drop T-interface
1063 * operation, indicating that another device has attempted simultaneous
1064 * transmission, but can also result from line noise. An immediate
1065 * requeue via amd7930_dxmit is suggested, but repeated collision
1066 * errors may indicate a more serious problem.
1068 * void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
1069 * void (*callback)(void *, int, unsigned int),
1070 * void *callback_arg)
1072 * register a buffer - buffer, size - into which a D-channel packet
1073 * can be received. The callback function will be called DURING
1074 * THE TOP HALF OF AN INTERRUPT HANDLER and will be passed an
1075 * arbitrary callback_arg, an integer error indication and the length
1076 * of the received packet, which will start with the address field,
1077 * end with the information field, and not contain flag or FCS
1078 * bytes. Bit-stuffing will already have been corrected for.
1079 * Possible values of second callback argument "error":
1081 * 0 - successful reception
1082 * non-0 - error value from chip's DER (D-Channel Error Register):
1083 * 1 - received packet abort
1084 * 2 - framing error; non-integer number of bytes received
1085 * 8 - FCS error; CRC sequence indicated corrupted data
1086 * 16 - overflow error; packet exceeded size of buffer
1087 * 32 - underflow error; packet smaller than required five bytes
1088 * 64 - overrun error; irq routine didn't service chip fast enough
1090 * int amd7930_bopen(int dev, int chan, u_char xmit_idle_char)
1092 * This function should be called before any other operations on a B
1093 * channel. In addition to arranging for interrupt handling and
1094 * channel multiplexing, it sets the xmit_idle_char which is
1095 * transmitted on the interface when no data buffer is available.
1096 * Suggested values are: 0 for ISDN audio; FF for HDLC mark idle; 7E
1097 * for HDLC flag idle. Returns 0 on a successful open; -1 on error,
1098 * which is quite possible if audio and the other ISDN channel are
1099 * already in use, since the Am7930 can only send two of the three
1100 * channels to the processor
1102 * void amd7930_bclose(int dev, int chan)
1104 * Shuts down a B channel when no longer in use.
1106 * void amd7930_bxmit(int dev, int chan, __u8 *buffer, unsigned int count,
1107 * void (*callback)(void *), void *callback_arg)
1109 * transmits a raw data block - specified with buffer, count - over
1110 * the B channel interface specified by dev/chan. The callback
1111 * function will be called DURING THE TOP HALF OF AN INTERRUPT
1112 * HANDLER and will be passed the arbitrary callback_arg
1114 * The callback routine should defer any time-consuming operations
1115 * to a bottom-half handler; however, amd7930_bxmit may be called
1116 * from within the callback to request back-to-back transmission of
1117 * another data block
1119 * void amd7930_brecv(int dev, int chan, __u8 *buffer, unsigned int size,
1120 * void (*callback)(void *), void *callback_arg)
1122 * receive a raw data block - specified with buffer, size - over the
1123 * B channel interface specified by dev/chan. The callback function
1124 * will be called DURING THE TOP HALF OF AN INTERRUPT HANDLER and
1125 * will be passed the arbitrary callback_arg
1127 * The callback routine should defer any time-consuming operations
1128 * to a bottom-half handler; however, amd7930_brecv may be called
1129 * from within the callback to register another buffer and ensure
1130 * continuous B channel reception without loss of data
1134 #if defined (AMD79C30_ISDN)
1135 static int amd7930_get_irqnum(int dev)
1137 struct amd7930_info *info;
1139 if (dev > num_drivers)
1142 info = (struct amd7930_info *) drivers[dev].private;
1147 static int amd7930_get_liu_state(int dev)
1149 struct amd7930_info *info;
1151 if (dev > num_drivers)
1154 info = (struct amd7930_info *) drivers[dev].private;
1156 return info->liu_state;
1159 static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
1161 struct amd7930_info *info;
1162 unsigned long flags;
1164 if (dev > num_drivers)
1167 info = (struct amd7930_info *) drivers[dev].private;
1169 save_and_cli(flags);
1171 /* Set callback for LIU state change */
1172 info->liu_callback = callback;
1173 info->liu_callback_arg = callback_arg;
1175 /* De-activate the ISDN Line Interface Unit (LIU) */
1176 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1177 sbus_writeb(0, info->regs + DR);
1179 /* Request interrupt when LIU changes state from/to F3/F7/F8 */
1180 sbus_writeb(AMR_LIU_LMR2, info->regs + CR);
1181 sbus_writeb(AM_LIU_LMR2_EN_F3_INT |
1182 AM_LIU_LMR2_EN_F7_INT |
1183 AM_LIU_LMR2_EN_F8_INT,
1186 /* amd7930_enable_ints(info); */
1188 /* Activate the ISDN Line Interface Unit (LIU) */
1189 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1190 sbus_writeb(AM_LIU_LMR1_LIU_ENABL, info->regs + DR);
1192 restore_flags(flags);
1195 static void amd7930_liu_activate(int dev, int priority)
1197 struct amd7930_info *info;
1198 unsigned long flags;
1200 if (dev > num_drivers)
1203 info = (struct amd7930_info *) drivers[dev].private;
1205 save_and_cli(flags);
1207 /* Set D-channel access priority
1209 * I.430 defines a priority mechanism based on counting 1s
1210 * in the echo channel before transmitting
1212 * Priority 0 is eight 1s; priority 1 is ten 1s; etc
1214 sbus_writeb(AMR_LIU_LPR, info->regs + CR);
1215 sbus_writeb(priority & 0x0f, info->regs + DR);
1217 /* request LIU activation */
1218 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1219 sbus_writeb(AM_LIU_LMR1_LIU_ENABL | AM_LIU_LMR1_REQ_ACTIV,
1222 restore_flags(flags);
1225 static void amd7930_liu_deactivate(int dev)
1227 struct amd7930_info *info;
1228 unsigned long flags;
1230 if (dev > num_drivers)
1233 info = (struct amd7930_info *) drivers[dev].private;
1235 save_and_cli(flags);
1237 /* deactivate LIU */
1238 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1239 sbus_writeb(0, info->regs + DR);
1241 restore_flags(flags);
1244 static void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
1245 void (*callback)(void *, int), void *callback_arg)
1247 struct amd7930_info *info;
1248 unsigned long flags;
1251 if (dev > num_drivers)
1254 info = (struct amd7930_info *) drivers[dev].private;
1256 save_and_cli(flags);
1258 if (info->D.output_ptr) {
1259 restore_flags(flags);
1260 printk("amd7930_dxmit: transmitter in use\n");
1264 info->D.output_ptr = buffer;
1265 info->D.output_count = count;
1266 info->D.output_callback = callback;
1267 info->D.output_callback_arg = callback_arg;
1269 /* Enable D-channel Transmit Threshold interrupt; disable addressing */
1270 sbus_writeb(AMR_DLC_DMR1, info->regs + CR);
1271 dmr1 = sbus_readb(info->regs + DR);
1272 dmr1 |= AMR_DLC_DMR1_DTTHRSH_INT;
1273 dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;
1274 sbus_writeb(dmr1, info->regs + DR);
1276 /* Begin xmit by setting D-channel Transmit Byte Count Reg (DTCR) */
1277 sbus_writeb(AMR_DLC_DTCR, info->regs + CR);
1278 sbus_writeb(count & 0xff, info->regs + DR);
1279 sbus_writeb((count >> 8) & 0xff, info->regs + DR);
1281 /* Prime xmit FIFO */
1282 /* fill_D_xmit_fifo(info); */
1283 transceive_Dchannel(info);
1285 restore_flags(flags);
1288 static void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
1289 void (*callback)(void *, int, unsigned int),
1292 struct amd7930_info *info;
1293 unsigned long flags;
1296 if (dev > num_drivers)
1299 info = (struct amd7930_info *) drivers[dev].private;
1301 save_and_cli(flags);
1303 if (info->D.input_ptr) {
1304 restore_flags(flags);
1305 printk("amd7930_drecv: receiver already has buffer!\n");
1309 info->D.input_ptr = buffer;
1310 info->D.input_count = 0;
1311 info->D.input_limit = size;
1312 info->D.input_callback = callback;
1313 info->D.input_callback_arg = callback_arg;
1315 /* Enable D-channel Receive Threshold interrupt;
1316 * Enable D-channel End of Receive Packet interrupt;
1317 * Disable address recognition
1319 sbus_writeb(AMR_DLC_DMR1, info->regs + CR);
1320 dmr1 = sbus_readb(info->regs + DR);
1321 dmr1 |= AMR_DLC_DMR1_DRTHRSH_INT | AMR_DLC_DMR1_EORP_INT;
1322 dmr1 &= ~AMR_DLC_DMR1_EN_ADDRS;
1323 sbus_writeb(dmr1, info->regs + DR);
1325 /* Set D-channel Receive Byte Count Limit Register */
1326 sbus_writeb(AMR_DLC_DRCR, info->regs + CR);
1327 sbus_writeb(size & 0xff, info->regs + DR);
1328 sbus_writeb((size >> 8) & 0xff, info->regs + DR);
1330 restore_flags(flags);
1333 static int amd7930_bopen(int dev, unsigned int chan,
1334 int mode, u_char xmit_idle_char)
1336 struct amd7930_info *info;
1337 unsigned long flags;
1340 if (dev > num_drivers || chan<0 || chan>1)
1343 if (mode == L1_MODE_HDLC)
1346 info = (struct amd7930_info *) drivers[dev].private;
1348 save_and_cli(flags);
1350 if (info->Bb.channel_status == CHANNEL_AVAILABLE) {
1351 info->Bb.channel_status = CHANNEL_INUSE;
1352 info->Bb.xmit_idle_char = xmit_idle_char;
1353 info->Bisdn[chan] = &info->Bb;
1355 /* Multiplexor map - isdn (B1/2) to Bb */
1356 sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
1357 sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |
1358 (AM_MUX_CHANNEL_Bb << 4),
1360 } else if (info->Bc.channel_status == CHANNEL_AVAILABLE) {
1361 info->Bc.channel_status = CHANNEL_INUSE;
1362 info->Bc.xmit_idle_char = xmit_idle_char;
1363 info->Bisdn[chan] = &info->Bc;
1365 /* Multiplexor map - isdn (B1/2) to Bc */
1366 sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
1367 sbus_writeb((AM_MUX_CHANNEL_B1 + chan) |
1368 (AM_MUX_CHANNEL_Bc << 4),
1371 restore_flags(flags);
1375 /* Enable B channel transmit */
1376 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1377 tmp = sbus_readb(info->regs + DR);
1378 tmp |= AM_LIU_LMR1_B1_ENABL + chan;
1379 sbus_writeb(tmp, info->regs + DR);
1381 /* Enable B channel interrupts */
1382 sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
1383 sbus_writeb(AM_MUX_MCR4_ENABLE_INTS |
1384 AM_MUX_MCR4_REVERSE_Bb |
1385 AM_MUX_MCR4_REVERSE_Bc,
1388 restore_flags(flags);
1392 static void amd7930_bclose(int dev, unsigned int chan)
1394 struct amd7930_info *info;
1395 unsigned long flags;
1397 if (dev > num_drivers || chan<0 || chan>1)
1400 info = (struct amd7930_info *) drivers[dev].private;
1402 save_and_cli(flags);
1404 if (info->Bisdn[chan]) {
1407 info->Bisdn[chan]->channel_status = CHANNEL_AVAILABLE;
1409 sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
1410 sbus_writeb(0, info->regs + DR);
1412 info->Bisdn[chan] = NULL;
1414 /* Disable B channel transmit */
1415 sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1416 tmp = sbus_readb(info->regs + DR);
1417 tmp &= ~(AM_LIU_LMR1_B1_ENABL + chan);
1418 sbus_writeb(tmp, info->regs + DR);
1420 if (info->Bb.channel_status == CHANNEL_AVAILABLE &&
1421 info->Bc.channel_status == CHANNEL_AVAILABLE) {
1422 /* Disable B channel interrupts */
1423 sbus_writeb(AMR_MUX_MCR4, info->regs + CR);
1424 sbus_writeb(0, info->regs + DR);
1428 restore_flags(flags);
1431 static void amd7930_bxmit(int dev, unsigned int chan,
1432 __u8 * buffer, unsigned long count,
1433 void (*callback)(void *, int), void *callback_arg)
1435 struct amd7930_info *info;
1436 struct amd7930_channel *Bchan;
1437 unsigned long flags;
1439 if (dev > num_drivers)
1442 info = (struct amd7930_info *) drivers[dev].private;
1443 Bchan = info->Bisdn[chan];
1446 save_and_cli(flags);
1448 Bchan->output_ptr = buffer;
1449 Bchan->output_count = count;
1450 Bchan->output_format = AUDIO_ENCODING_ULAW;
1451 Bchan->output_callback = (void *) callback;
1452 Bchan->output_callback_arg = callback_arg;
1454 restore_flags(flags);
1458 static void amd7930_brecv(int dev, unsigned int chan,
1459 __u8 * buffer, unsigned long size,
1460 void (*callback)(void *, int, unsigned int),
1463 struct amd7930_info *info;
1464 struct amd7930_channel *Bchan;
1465 unsigned long flags;
1467 if (dev > num_drivers)
1470 info = (struct amd7930_info *) drivers[dev].private;
1471 Bchan = info->Bisdn[chan];
1474 save_and_cli(flags);
1476 Bchan->input_ptr = buffer;
1477 Bchan->input_count = size;
1478 Bchan->input_format = AUDIO_ENCODING_ULAW;
1479 Bchan->input_callback = (void *) callback;
1480 Bchan->input_callback_arg = callback_arg;
1482 restore_flags(flags);
1486 struct foreign_interface amd7930_foreign_interface = {
1488 amd7930_get_liu_state,
1490 amd7930_liu_activate,
1491 amd7930_liu_deactivate,
1499 EXPORT_SYMBOL(amd7930_foreign_interface);
1504 * Device detection and initialization.
1507 static struct sparcaudio_operations amd7930_ops = {
1511 amd7930_start_output,
1512 amd7930_stop_output,
1513 amd7930_start_input,
1515 amd7930_sunaudio_getdev,
1516 amd7930_set_output_volume,
1517 amd7930_get_output_volume,
1518 amd7930_set_input_volume,
1519 amd7930_get_input_volume,
1520 amd7930_set_monitor_volume,
1521 amd7930_get_monitor_volume,
1522 NULL, /* amd7930_set_output_balance */
1523 amd7930_get_output_balance,
1524 NULL, /* amd7930_set_input_balance */
1525 amd7930_get_input_balance,
1526 amd7930_set_output_channels,
1527 amd7930_get_output_channels,
1528 amd7930_set_input_channels,
1529 amd7930_get_input_channels,
1530 amd7930_set_output_precision,
1531 amd7930_get_output_precision,
1532 amd7930_set_input_precision,
1533 amd7930_get_input_precision,
1534 amd7930_set_output_port,
1535 amd7930_get_output_port,
1536 NULL, /* amd7930_set_input_port */
1537 amd7930_get_input_port,
1538 amd7930_set_encoding,
1539 amd7930_get_encoding,
1540 amd7930_set_encoding,
1541 amd7930_get_encoding,
1542 amd7930_set_output_rate,
1543 amd7930_get_output_rate,
1544 amd7930_set_input_rate,
1545 amd7930_get_input_rate,
1546 amd7930_sunaudio_getdev_sunos,
1547 amd7930_get_output_ports,
1548 amd7930_get_input_ports,
1549 NULL, /* amd7930_set_output_muted */
1550 amd7930_get_output_muted,
1551 NULL, /* amd7930_set_output_pause */
1552 NULL, /* amd7930_get_output_pause */
1553 NULL, /* amd7930_set_input_pause */
1554 NULL, /* amd7930_get_input_pause */
1555 NULL, /* amd7930_set_output_samples */
1556 NULL, /* amd7930_get_output_samples */
1557 NULL, /* amd7930_set_input_samples */
1558 NULL, /* amd7930_get_input_samples */
1559 NULL, /* amd7930_set_output_error */
1560 NULL, /* amd7930_get_output_error */
1561 NULL, /* amd7930_set_input_error */
1562 NULL, /* amd7930_get_input_error */
1563 amd7930_get_formats,
1566 /* Attach to an amd7930 chip given its PROM node. */
1567 static int amd7930_attach(struct sparcaudio_driver *drv, int node,
1568 struct sbus_bus *sbus, struct sbus_dev *sdev)
1570 struct linux_prom_registers regs;
1571 struct linux_prom_irqs irq;
1572 struct resource res, *resp;
1573 struct amd7930_info *info;
1576 /* Allocate our private information structure. */
1577 drv->private = kmalloc(sizeof(struct amd7930_info), GFP_KERNEL);
1578 if (drv->private == NULL)
1581 /* Point at the information structure and initialize it. */
1582 drv->ops = &amd7930_ops;
1583 info = (struct amd7930_info *)drv->private;
1584 memset(info, 0, sizeof(*info));
1585 info->ints_on = 1; /* force disable below */
1589 /* Map the registers into memory. */
1590 prom_getproperty(node, "reg", (char *)®s, sizeof(regs));
1592 resp = &sdev->resource[0];
1595 res.start = regs.phys_addr;
1596 res.end = res.start + regs.reg_size - 1;
1597 res.flags = IORESOURCE_IO | (regs.which_io & 0xff);
1599 info->regs_size = regs.reg_size;
1600 info->regs = sbus_ioremap(resp, 0, regs.reg_size, "amd7930");
1602 printk(KERN_ERR "amd7930: could not remap registers\n");
1603 kfree(drv->private);
1607 /* Put amd7930 in idle mode (interrupts disabled) */
1610 /* Enable extended FIFO operation on D-channel */
1611 sbus_writeb(AMR_DLC_EFCR, info->regs + CR);
1612 sbus_writeb(AMR_DLC_EFCR_EXTEND_FIFO, info->regs + DR);
1613 sbus_writeb(AMR_DLC_DMR4, info->regs + CR);
1614 sbus_writeb(/* AMR_DLC_DMR4_RCV_30 | */ AMR_DLC_DMR4_XMT_14,
1617 /* Attach the interrupt handler to the audio interrupt. */
1618 prom_getproperty(node, "intr", (char *)&irq, sizeof(irq));
1619 info->irq = irq.pri;
1620 request_irq(info->irq, amd7930_interrupt,
1621 SA_INTERRUPT, "amd7930", drv);
1622 amd7930_enable_ints(info);
1624 /* Initalize the local copy of the MAP registers. */
1625 memset(&info->map, 0, sizeof(info->map));
1626 info->map.mmr1 = AM_MAP_MMR1_GX | AM_MAP_MMR1_GER |
1627 AM_MAP_MMR1_GR | AM_MAP_MMR1_STG;
1628 /* Start out with speaker, microphone */
1629 info->map.mmr2 |= (AM_MAP_MMR2_LS | AM_MAP_MMR2_AINB);
1631 /* Set the default audio parameters. */
1635 info->format_type = AUDIO_ENCODING_ULAW;
1636 info->Bb.input_format = AUDIO_ENCODING_ULAW;
1637 info->Bb.output_format = AUDIO_ENCODING_ULAW;
1638 info->Bc.input_format = AUDIO_ENCODING_ULAW;
1639 info->Bc.output_format = AUDIO_ENCODING_ULAW;
1640 amd7930_update_map(drv);
1642 /* Register the amd7930 with the midlevel audio driver. */
1643 err = register_sparcaudio_driver(drv, 1);
1645 printk(KERN_ERR "amd7930: unable to register\n");
1646 free_irq(info->irq, drv);
1647 sbus_iounmap(info->regs, info->regs_size);
1648 kfree(drv->private);
1652 /* Announce the hardware to the user. */
1653 printk(KERN_INFO "amd7930 at %lx irq %d\n",
1654 info->regs, info->irq);
1660 /* Detach from an amd7930 chip given the device structure. */
1661 static void __exit amd7930_detach(struct sparcaudio_driver *drv)
1663 struct amd7930_info *info = (struct amd7930_info *)drv->private;
1665 unregister_sparcaudio_driver(drv, 1);
1667 free_irq(info->irq, drv);
1668 sbus_iounmap(info->regs, info->regs_size);
1669 kfree(drv->private);
1672 /* Probe for the amd7930 chip and then attach the driver. */
1673 static int __init amd7930_init(void)
1675 struct sbus_bus *sbus;
1676 struct sbus_dev *sdev;
1679 /* Try to find the sun4c "audio" node first. */
1680 node = prom_getchild(prom_root_node);
1681 node = prom_searchsiblings(node, "audio");
1682 if (node && amd7930_attach(&drivers[0], node, NULL, NULL) == 0)
1687 /* Probe each SBUS for amd7930 chips. */
1688 for_all_sbusdev(sdev, sbus) {
1689 if (!strcmp(sdev->prom_name, "audio")) {
1690 /* Don't go over the max number of drivers. */
1691 if (num_drivers >= MAX_DRIVERS)
1694 if (amd7930_attach(&drivers[num_drivers],
1695 sdev->prom_node, sdev->bus, sdev) == 0)
1700 /* Only return success if we found some amd7930 chips. */
1701 return (num_drivers > 0) ? 0 : -EIO;
1704 static void __exit amd7930_exit(void)
1708 for (i = 0; i < num_drivers; i++) {
1709 amd7930_detach(&drivers[i]);
1714 module_init(amd7930_init);
1715 module_exit(amd7930_exit);
1716 MODULE_LICENSE("GPL");
1718 /*************************************************************/
1719 /* Audio format conversion */
1720 /*************************************************************/
1722 /* Translation tables */
1724 static unsigned char ulaw[] = {
1725 3, 7, 11, 15, 19, 23, 27, 31,
1726 35, 39, 43, 47, 51, 55, 59, 63,
1727 66, 68, 70, 72, 74, 76, 78, 80,
1728 82, 84, 86, 88, 90, 92, 94, 96,
1729 98, 99, 100, 101, 102, 103, 104, 105,
1730 106, 107, 108, 109, 110, 111, 112, 113,
1731 113, 114, 114, 115, 115, 116, 116, 117,
1732 117, 118, 118, 119, 119, 120, 120, 121,
1733 121, 121, 122, 122, 122, 122, 123, 123,
1734 123, 123, 124, 124, 124, 124, 125, 125,
1735 125, 125, 125, 125, 126, 126, 126, 126,
1736 126, 126, 126, 126, 127, 127, 127, 127,
1737 127, 127, 127, 127, 127, 127, 127, 127,
1738 128, 128, 128, 128, 128, 128, 128, 128,
1739 128, 128, 128, 128, 128, 128, 128, 128,
1740 128, 128, 128, 128, 128, 128, 128, 128,
1741 253, 249, 245, 241, 237, 233, 229, 225,
1742 221, 217, 213, 209, 205, 201, 197, 193,
1743 190, 188, 186, 184, 182, 180, 178, 176,
1744 174, 172, 170, 168, 166, 164, 162, 160,
1745 158, 157, 156, 155, 154, 153, 152, 151,
1746 150, 149, 148, 147, 146, 145, 144, 143,
1747 143, 142, 142, 141, 141, 140, 140, 139,
1748 139, 138, 138, 137, 137, 136, 136, 135,
1749 135, 135, 134, 134, 134, 134, 133, 133,
1750 133, 133, 132, 132, 132, 132, 131, 131,
1751 131, 131, 131, 131, 130, 130, 130, 130,
1752 130, 130, 130, 130, 129, 129, 129, 129,
1753 129, 129, 129, 129, 129, 129, 129, 129,
1754 128, 128, 128, 128, 128, 128, 128, 128,
1755 128, 128, 128, 128, 128, 128, 128, 128,
1756 128, 128, 128, 128, 128, 128, 128, 128
1759 static __u8 mulaw2bilinear(__u8 data)
1764 static unsigned char linear[] = {
1765 0, 0, 0, 0, 0, 0, 0, 1,
1766 0, 0, 0, 2, 0, 0, 0, 3,
1767 0, 0, 0, 4, 0, 0, 0, 5,
1768 0, 0, 0, 6, 0, 0, 0, 7,
1769 0, 0, 0, 8, 0, 0, 0, 9,
1770 0, 0, 0, 10, 0, 0, 0, 11,
1771 0, 0, 0, 12, 0, 0, 0, 13,
1772 0, 0, 0, 14, 0, 0, 0, 15,
1773 0, 0, 16, 0, 17, 0, 18, 0,
1774 19, 0, 20, 0, 21, 0, 22, 0,
1775 23, 0, 24, 0, 25, 0, 26, 0,
1776 27, 0, 28, 0, 29, 0, 30, 0,
1777 31, 0, 32, 33, 34, 35, 36, 37,
1778 38, 39, 40, 41, 42, 43, 44, 45,
1779 46, 48, 50, 52, 54, 56, 58, 60,
1780 62, 65, 69, 73, 77, 83, 91, 103,
1781 255, 231, 219, 211, 205, 201, 197, 193,
1782 190, 188, 186, 184, 182, 180, 178, 176,
1783 174, 173, 172, 171, 170, 169, 168, 167,
1784 166, 165, 164, 163, 162, 161, 160, 0,
1785 159, 0, 158, 0, 157, 0, 156, 0,
1786 155, 0, 154, 0, 153, 0, 152, 0,
1787 151, 0, 150, 0, 149, 0, 148, 0,
1788 147, 0, 146, 0, 145, 0, 144, 0,
1789 0, 143, 0, 0, 0, 142, 0, 0,
1790 0, 141, 0, 0, 0, 140, 0, 0,
1791 0, 139, 0, 0, 0, 138, 0, 0,
1792 0, 137, 0, 0, 0, 136, 0, 0,
1793 0, 135, 0, 0, 0, 134, 0, 0,
1794 0, 133, 0, 0, 0, 132, 0, 0,
1795 0, 131, 0, 0, 0, 130, 0, 0,
1796 0, 129, 0, 0, 0, 128, 0, 0
1799 static __u8 bilinear2mulaw(__u8 data)
1801 return linear[data];
1804 static int exp_lut[256] = {
1805 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,
1806 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,
1807 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,
1808 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,
1809 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,
1810 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,
1811 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,
1812 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
1818 #define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8))
1820 static __u8 linear2mulaw(__u16 data)
1822 static int sign, exponent, mantissa;
1824 /* not really sure, if swapping is ok - comment next line to disable it */
1825 data = SWAP_ENDIAN(data);
1827 sign = (data >> 8) & 0x80;
1828 if (sign != 0) data = -data;
1830 if (data > CLIP) data = CLIP;
1832 exponent = exp_lut[(data >> 7) & 0xFF];
1833 mantissa = (data >> (exponent + 3)) & 0x0F;
1835 return (~(sign | (exponent << 4) | mantissa));
1838 static __u16 mulaw2linear(__u8 data)
1840 /* this conversion is not working */
1845 #define INOUT(x,y) (((x) << 16) | (y))
1846 static int convert_audio(int in_format, int out_format, __u8* buffer, int count)
1848 static int i,sign,exponent;
1851 if (in_format == out_format) return count;
1853 switch(INOUT(in_format, out_format)) {
1854 case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR8):
1855 for (i = 0;i < count; i++) {
1856 buffer[i] = ulaw[buffer[i]];
1859 case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR):
1861 case INOUT(AUDIO_ENCODING_LINEAR, AUDIO_ENCODING_ULAW):
1862 /* buffer is two-byte => convert to first */
1863 for (i = 0; i < count/2; i++) {
1864 data = ((__u16*)buffer)[i];
1865 sign = (data >> 8) & 0x80;
1866 if (data > CLIP) data = CLIP;
1868 exponent = exp_lut[(data >> 7) & 0xFF];
1869 buffer[i] = ~(sign | (exponent << 4) |
1870 ((data >> (exponent + 3)) & 0x0F));
1873 case INOUT(AUDIO_ENCODING_LINEAR8, AUDIO_ENCODING_ULAW):
1874 for (i = 0; i < count; i++) {
1875 buffer[i] = linear[buffer[i]];