1 /* $Id: amd7930.c,v 1.28 2001/10/13 01:47:29 davem Exp $
2  * drivers/sbus/audio/amd7930.c
3  *
4  * Copyright (C) 1996,1997 Thomas K. Dyas (tdyas@eden.rutgers.edu)
5  *
6  * This is the lowlevel driver for the AMD7930 audio chip found on all
7  * sun4c machines and some sun4m machines.
8  *
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.
13  *
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.
16  *
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
25  * via a multiplexer.
26  *
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.
34  *
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.
39  *
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.
50  *
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
55  *
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.
61  *
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
69  * deliver it.
70  *
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.
84  */
85 
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>
98 #include <asm/irq.h>
99 #include <asm/io.h>
100 #include <asm/sbus.h>
101 
102 #include <asm/audioio.h>
103 #include "amd7930.h"
104 
105 static __u8  bilinear2mulaw(__u8 data);
106 static __u8  mulaw2bilinear(__u8 data);
107 static __u8  linear2mulaw(__u16 data);
108 static __u16 mulaw2linear(__u8 data);
109 
110 #if defined (AMD79C30_ISDN)
111 #include "../../isdn/hisax/hisax.h"
112 #include "../../isdn/hisax/isdnl1.h"
113 #include "../../isdn/hisax/foreign.h"
114 #endif
115 
116 #define MAX_DRIVERS 1
117 
118 static struct sparcaudio_driver drivers[MAX_DRIVERS];
119 static int num_drivers;
120 
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.
124  */
125 
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
132 
133 struct amd7930_channel {
134 	/* Channel status */
135 	u8 channel_status;
136 
137 	/* Current buffer that the driver is playing on channel */
138 	volatile __u8 * output_ptr;
139 	volatile u32 output_count;
140 	u8 xmit_idle_char;
141 
142 	/* Callback routine (and argument) when output is done on */
143 	void (*output_callback)(void *, unsigned char);
144 	void * output_callback_arg;
145 
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;
150 
151 	/* Callback routine (and argument) when input is done on */
152 	void (*input_callback)(void *, unsigned char, unsigned long);
153 	void * input_callback_arg;
154 
155 	int input_format;
156 	int output_format;
157 };
158 
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;
164 
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.
168 	 */
169 	struct amd7930_channel *Baudio;
170 	struct amd7930_channel *Bisdn[2];
171 
172 	/* Device registers information. */
173 	unsigned long regs;
174 	unsigned long regs_size;
175 	struct amd7930_map map;
176 
177 	/* Volume information. */
178 	int pgain, rgain, mgain;
179 
180 	/* Device interrupt information. */
181 	int irq;
182 	volatile int ints_on;
183 
184 	/* Format type */
185 	int format_type;
186 
187 	/* Someone to signal when the ISDN LIU state changes */
188 	int liu_state;
189 	void (*liu_callback)(void *);
190 	void *liu_callback_arg;
191 };
192 
193 /* Output a 16-bit quantity in the order that the amd7930 expects. */
amd7930_out16(unsigned long regs,u16 val)194 static __inline__ void amd7930_out16(unsigned long regs, u16 val)
195 {
196 	sbus_writeb(val & 0xff, regs + DR);
197 	sbus_writeb(val >> 8, regs + DR);
198 }
199 
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.
204  */
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,
238 };
239 
240 static __const__ __u16 ger_coeff[] = {
241 	0x431f, /* 5. dB */
242 	0x331f, /* 5.5 dB */
243 	0x40dd, /* 6. dB */
244 	0x11dd, /* 6.5 dB */
245 	0x440f, /* 7. dB */
246 	0x411f, /* 7.5 dB */
247 	0x311f, /* 8. dB */
248 	0x5520, /* 8.5 dB */
249 	0x10dd, /* 9. dB */
250 	0x4211, /* 9.5 dB */
251 	0x410f, /* 10. dB */
252 	0x111f, /* 10.5 dB */
253 	0x600b, /* 11. dB */
254 	0x00dd, /* 11.5 dB */
255 	0x4210, /* 12. dB */
256 	0x110f, /* 13. dB */
257 	0x7200, /* 14. dB */
258 	0x2110, /* 15. dB */
259 	0x2200, /* 15.9 dB */
260 	0x000b, /* 16.9 dB */
261 	0x000f  /* 18. dB */
262 };
263 #define NR_GER_COEFFS (sizeof(ger_coeff) / sizeof(ger_coeff[0]))
264 
265 /* Enable amd7930 interrupts atomically. */
amd7930_enable_ints(struct amd7930_info * info)266 static void amd7930_enable_ints(struct amd7930_info *info)
267 {
268 	unsigned long flags;
269 
270 	save_and_cli(flags);
271 	if (!info->ints_on) {
272 		sbus_writeb(AMR_INIT, info->regs + CR);
273 		sbus_writeb(AM_INIT_ACTIVE, info->regs + DR);
274 		info->ints_on = 1;
275 	}
276 	restore_flags(flags);
277 }
278 
279 /* Disable amd7930 interrupts atomically. */
amd7930_disable_ints(struct amd7930_info * info)280 static __inline__ void amd7930_disable_ints(struct amd7930_info *info)
281 {
282 	unsigned long flags;
283 
284 	save_and_cli(flags);
285 	if (info->ints_on) {
286 		sbus_writeb(AMR_INIT, info->regs + CR);
287 		sbus_writeb(AM_INIT_ACTIVE | AM_INIT_DISABLE_INTS,
288 			    info->regs + DR);
289 		info->ints_on = 0;
290 	}
291 	restore_flags(flags);
292 
293 }
294 
295 /* Idle amd7930 (no interrupts, no audio, no data) */
amd7930_idle(struct amd7930_info * info)296 static __inline__ void amd7930_idle(struct amd7930_info *info)
297 {
298 	unsigned long flags;
299 
300 	save_and_cli(flags);
301 	if (info->ints_on) {
302 		sbus_writeb(AMR_INIT, info->regs + CR);
303 		sbus_writeb(0, info->regs + DR);
304 		info->ints_on = 0;
305 	}
306 	restore_flags(flags);
307 }
308 
309 /* Commit the local copy of the MAP registers to the amd7930. */
amd7930_write_map(struct sparcaudio_driver * drv)310 static void amd7930_write_map(struct sparcaudio_driver *drv)
311 {
312 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
313 	unsigned long        regs = info->regs;
314 	struct amd7930_map  *map  = &info->map;
315 	unsigned long flags;
316 
317 	save_and_cli(flags);
318 
319 	sbus_writeb(AMR_MAP_GX, regs + CR);
320 	amd7930_out16(regs, map->gx);
321 
322 	sbus_writeb(AMR_MAP_GR, regs + CR);
323 	amd7930_out16(regs, map->gr);
324 
325 	sbus_writeb(AMR_MAP_STGR, regs + CR);
326 	amd7930_out16(regs, map->stgr);
327 
328 	sbus_writeb(AMR_MAP_GER, regs + CR);
329 	amd7930_out16(regs, map->ger);
330 
331 	sbus_writeb(AMR_MAP_MMR1, regs + CR);
332 	sbus_writeb(map->mmr1, regs + DR);
333 
334 	sbus_writeb(AMR_MAP_MMR2, regs + CR);
335 	sbus_writeb(map->mmr2, regs + DR);
336 
337 	restore_flags(flags);
338 }
339 
340 /* Update the MAP registers with new settings. */
amd7930_update_map(struct sparcaudio_driver * drv)341 static void amd7930_update_map(struct sparcaudio_driver *drv)
342 {
343 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
344 	struct amd7930_map  *map  = &info->map;
345 	int level;
346 
347 	map->gx = gx_coeff[info->rgain];
348 	map->stgr = gx_coeff[info->mgain];
349 
350 	level = (info->pgain * (256 + NR_GER_COEFFS)) >> 8;
351 	if (level >= 256) {
352 		map->ger = ger_coeff[level - 256];
353 		map->gr = gx_coeff[255];
354 	} else {
355 		map->ger = ger_coeff[0];
356 		map->gr = gx_coeff[level];
357 	}
358 
359 	amd7930_write_map(drv);
360 }
361 
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:
364  *
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
370  *
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
373  */
374 
375 #ifdef L2FRAME_DEBUG
376 
debug_info(struct amd7930_info * info,char c)377 inline void debug_info(struct amd7930_info *info, char c)
378 {
379 	struct IsdnCardState *cs;
380 
381 	if (!info || !info->D.output_callback_arg)
382 		return;
383 
384 	cs = (struct IsdnCardState *) info->D.output_callback_arg;
385 
386 	if (!cs || !cs->status_write)
387 		return;
388 
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;
393 	}
394 }
395 
396 #else
397 
398 #define debug_info(info,c)
399 
400 #endif
401 
fill_D_xmit_fifo(struct amd7930_info * info)402 static void fill_D_xmit_fifo(struct amd7930_info *info)
403 {
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);
408 
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--;
413 
414 		debug_info(info, '>');
415         }
416 }
417 
transceive_Dchannel(struct amd7930_info * info)418 static void transceive_Dchannel(struct amd7930_info *info)
419 {
420 	__u8 dummy;
421 
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)
425 
426 	/* Transmit if we can */
427 	fill_D_xmit_fifo(info);
428 
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); */
439 	}
440 
441 	/* Read the next byte(s) of incoming data. */
442 
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);
448 			info->D.input_ptr++;
449 			info->D.input_count++;
450 		} else {
451 			/* Overflow - should be detected by chip via RBLR
452 			 * so we'll just consume data until we see LBRP
453 			 */
454 			dummy = sbus_readb(info->regs + DCRB);
455 		}
456 
457 		debug_info(info, '<');
458 
459 		if (sbus_readb(info->regs + DSR2) & AMR_DSR2_LBRP) {
460 			__u8 der;
461 
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;
466 
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);
471 
472 			if (info->D.input_callback)
473 				(*info->D.input_callback)
474 					(info->D.input_callback_arg, der,
475 					 info->D.input_count);
476 		}
477 
478 	}
479 }
480 
481 long amd7930_xmit_idles = 0;
482 
transceive_Bchannel(struct amd7930_channel * channel,unsigned long reg)483 static void transceive_Bchannel(struct amd7930_channel *channel,
484 				unsigned long reg)
485 {
486 	/* Send the next byte of outgoing data. */
487 	if (channel->output_ptr && channel->output_count > 0) {
488 		u8 byte;
489 
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);
496 			break;
497 		case AUDIO_ENCODING_LINEAR8:
498 			byte = bilinear2mulaw(*(channel->output_ptr));
499 			sbus_writeb(byte, reg);
500 			break;
501 		case AUDIO_ENCODING_LINEAR:
502 			if (channel->output_count >= 2) {
503 				u16 val = channel->output_ptr[0] << 8;
504 
505 				val |= channel->output_ptr[1];
506 				byte = linear2mulaw(val);
507 				sbus_writeb(byte, reg);
508 				channel->output_ptr++;
509 				channel->output_count--;
510 			};
511 		};
512 		channel->output_ptr++;
513 		channel->output_count--;
514 
515 
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);
523 		}
524 	} else {
525 		sbus_writeb(channel->xmit_idle_char, reg);
526 		amd7930_xmit_idles++;
527         }
528 
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);
536 			break;
537 		case AUDIO_ENCODING_LINEAR8:
538 			*(channel->input_ptr) = mulaw2bilinear(sbus_readb(reg));
539 			break;
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--;
547 			} else {
548 				*(channel->input_ptr) = 0;
549 			}
550 		};
551 		channel->input_ptr++;
552 		channel->input_count--;
553 
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);
561 		}
562 	}
563 }
564 
565 /* Interrupt handler (The chip takes only one byte per interrupt. Grrr!) */
amd7930_interrupt(int irq,void * dev_id,struct pt_regs * intr_regs)566 static void amd7930_interrupt(int irq, void *dev_id, struct pt_regs *intr_regs)
567 {
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;
571 	__u8 ir;
572 
573 	/* Clear the interrupt. */
574 	ir = sbus_readb(regs + IR);
575 
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);
581 	}
582 
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);
587 	}
588 
589 	if (ir & AMR_IR_LSRI) {
590 		__u8 lsr;
591 
592 		sbus_writeb(AMR_LIU_LSR, regs + CR);
593 		lsr = sbus_readb(regs + DR);
594 
595                 info->liu_state = (lsr & 0x7) + 2;
596 
597                 if (info->liu_callback)
598 			(*info->liu_callback)(info->liu_callback_arg);
599         }
600 }
601 
amd7930_open(struct inode * inode,struct file * file,struct sparcaudio_driver * drv)602 static int amd7930_open(struct inode * inode, struct file * file,
603 			struct sparcaudio_driver *drv)
604 {
605 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
606 
607 	switch(MINOR(inode->i_rdev) & 0xf) {
608 	case SPARCAUDIO_AUDIO_MINOR:
609 		info->format_type = AUDIO_ENCODING_ULAW;
610 		break;
611 	case SPARCAUDIO_DSP_MINOR:
612 		info->format_type = AUDIO_ENCODING_LINEAR8;
613 		break;
614 	case SPARCAUDIO_DSP16_MINOR:
615 		info->format_type = AUDIO_ENCODING_LINEAR;
616 		break;
617 	};
618 
619 	MOD_INC_USE_COUNT;
620 	return 0;
621 }
622 
amd7930_release(struct inode * inode,struct file * file,struct sparcaudio_driver * drv)623 static void amd7930_release(struct inode * inode, struct file * file,
624 			    struct sparcaudio_driver *drv)
625 {
626 	/* amd7930_disable_ints(drv->private); */
627 	MOD_DEC_USE_COUNT;
628 }
629 
request_Baudio(struct amd7930_info * info)630 static void request_Baudio(struct amd7930_info *info)
631 {
632 	if (info->Bb.channel_status == CHANNEL_AVAILABLE) {
633 		info->Bb.channel_status = CHANNEL_INUSE;
634 		info->Baudio = &info->Bb;
635 
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),
639 			    info->regs + DR);
640 
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;
647 
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),
651 			    info->regs + DR);
652 
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);
656 	}
657 }
658 
release_Baudio(struct amd7930_info * info)659 static void release_Baudio(struct amd7930_info *info)
660 {
661 	if (info->Baudio) {
662 		info->Baudio->channel_status = CHANNEL_AVAILABLE;
663 		sbus_writeb(AMR_MUX_MCR1, info->regs + CR);
664 		sbus_writeb(0, info->regs + DR);
665 		info->Baudio = NULL;
666 
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);
672 		}
673 	}
674 }
675 
amd7930_start_output(struct sparcaudio_driver * drv,__u8 * buffer,unsigned long count)676 static void amd7930_start_output(struct sparcaudio_driver *drv,
677 				 __u8 * buffer, unsigned long count)
678 {
679 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
680 
681 	if (! info->Baudio)
682 		request_Baudio(info);
683 
684 	if (info->Baudio) {
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;
691 	}
692 }
693 
amd7930_stop_output(struct sparcaudio_driver * drv)694 static void amd7930_stop_output(struct sparcaudio_driver *drv)
695 {
696 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
697 
698 	if (info->Baudio) {
699 		info->Baudio->output_ptr = NULL;
700 		info->Baudio->output_count = 0;
701 		if (! info->Baudio->input_ptr)
702 			release_Baudio(info);
703 	}
704 }
705 
amd7930_start_input(struct sparcaudio_driver * drv,__u8 * buffer,unsigned long count)706 static void amd7930_start_input(struct sparcaudio_driver *drv,
707 				__u8 * buffer, unsigned long count)
708 {
709 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
710 
711 	if (! info->Baudio)
712 		request_Baudio(info);
713 
714 	if (info->Baudio) {
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;
720 	}
721 }
722 
amd7930_stop_input(struct sparcaudio_driver * drv)723 static void amd7930_stop_input(struct sparcaudio_driver *drv)
724 {
725 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
726 
727 	if (info->Baudio) {
728 		info->Baudio->input_ptr = NULL;
729 		info->Baudio->input_count = 0;
730 		if (! info->Baudio->output_ptr)
731 			release_Baudio(info);
732 	}
733 
734 }
735 
amd7930_sunaudio_getdev(struct sparcaudio_driver * drv,audio_device_t * audinfo)736 static void amd7930_sunaudio_getdev(struct sparcaudio_driver *drv,
737 				 audio_device_t * audinfo)
738 {
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);
742 }
743 
amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver * drv)744 static int amd7930_sunaudio_getdev_sunos(struct sparcaudio_driver *drv)
745 {
746 	return AUDIO_DEV_AMD;
747 }
748 
amd7930_get_formats(struct sparcaudio_driver * drv)749 static int amd7930_get_formats(struct sparcaudio_driver *drv)
750 {
751       return (AFMT_MU_LAW | AFMT_A_LAW | AFMT_U8 | AFMT_S16_BE);
752 }
753 
amd7930_get_output_ports(struct sparcaudio_driver * drv)754 static int amd7930_get_output_ports(struct sparcaudio_driver *drv)
755 {
756       return (AUDIO_SPEAKER | AUDIO_HEADPHONE);
757 }
758 
amd7930_get_input_ports(struct sparcaudio_driver * drv)759 static int amd7930_get_input_ports(struct sparcaudio_driver *drv)
760 {
761       return (AUDIO_MICROPHONE);
762 }
763 
amd7930_set_output_volume(struct sparcaudio_driver * drv,int vol)764 static int amd7930_set_output_volume(struct sparcaudio_driver *drv, int vol)
765 {
766 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
767 
768 	info->pgain = vol;
769 	amd7930_update_map(drv);
770 	return 0;
771 }
772 
amd7930_get_output_volume(struct sparcaudio_driver * drv)773 static int amd7930_get_output_volume(struct sparcaudio_driver *drv)
774 {
775 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
776 
777 	return info->pgain;
778 }
779 
amd7930_set_input_volume(struct sparcaudio_driver * drv,int vol)780 static int amd7930_set_input_volume(struct sparcaudio_driver *drv, int vol)
781 {
782 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
783 
784 	info->rgain = vol;
785 	amd7930_update_map(drv);
786 	return 0;
787 }
788 
amd7930_get_input_volume(struct sparcaudio_driver * drv)789 static int amd7930_get_input_volume(struct sparcaudio_driver *drv)
790 {
791 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
792 
793 	return info->rgain;
794 }
795 
amd7930_set_monitor_volume(struct sparcaudio_driver * drv,int vol)796 static int amd7930_set_monitor_volume(struct sparcaudio_driver *drv, int vol)
797 {
798 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
799 
800 	info->mgain = vol;
801 	amd7930_update_map(drv);
802 	return 0;
803 }
804 
amd7930_get_monitor_volume(struct sparcaudio_driver * drv)805 static int amd7930_get_monitor_volume(struct sparcaudio_driver *drv)
806 {
807       struct amd7930_info *info = (struct amd7930_info *) drv->private;
808 
809       return info->mgain;
810 }
811 
812 /* Cheats. The amd has the minimum capabilities we support */
amd7930_get_output_balance(struct sparcaudio_driver * drv)813 static int amd7930_get_output_balance(struct sparcaudio_driver *drv)
814 {
815 	return AUDIO_MID_BALANCE;
816 }
817 
amd7930_get_input_balance(struct sparcaudio_driver * drv)818 static int amd7930_get_input_balance(struct sparcaudio_driver *drv)
819 {
820 	return AUDIO_MID_BALANCE;
821 }
822 
amd7930_get_output_channels(struct sparcaudio_driver * drv)823 static int amd7930_get_output_channels(struct sparcaudio_driver *drv)
824 {
825 	return AUDIO_MIN_PLAY_CHANNELS;
826 }
827 
amd7930_set_output_channels(struct sparcaudio_driver * drv,int value)828 static int amd7930_set_output_channels(struct sparcaudio_driver *drv,
829 				       int value)
830 {
831   return (value == AUDIO_MIN_PLAY_CHANNELS) ? 0 : -EINVAL;
832 }
833 
amd7930_get_input_channels(struct sparcaudio_driver * drv)834 static int amd7930_get_input_channels(struct sparcaudio_driver *drv)
835 {
836 	return AUDIO_MIN_REC_CHANNELS;
837 }
838 
839 static int
amd7930_set_input_channels(struct sparcaudio_driver * drv,int value)840 amd7930_set_input_channels(struct sparcaudio_driver *drv, int value)
841 {
842 	return (value == AUDIO_MIN_REC_CHANNELS) ? 0 : -EINVAL;
843 }
844 
amd7930_get_output_precision(struct sparcaudio_driver * drv)845 static int amd7930_get_output_precision(struct sparcaudio_driver *drv)
846 {
847 	return AUDIO_MIN_PLAY_PRECISION;
848 }
849 
850 static int
amd7930_set_output_precision(struct sparcaudio_driver * drv,int value)851 amd7930_set_output_precision(struct sparcaudio_driver *drv, int value)
852 {
853 	return (value == AUDIO_MIN_PLAY_PRECISION) ? 0 : -EINVAL;
854 }
855 
amd7930_get_input_precision(struct sparcaudio_driver * drv)856 static int amd7930_get_input_precision(struct sparcaudio_driver *drv)
857 {
858 	return AUDIO_MIN_REC_PRECISION;
859 }
860 
861 static int
amd7930_set_input_precision(struct sparcaudio_driver * drv,int value)862 amd7930_set_input_precision(struct sparcaudio_driver *drv, int value)
863 {
864 	return (value == AUDIO_MIN_REC_PRECISION) ? 0 : -EINVAL;
865 }
866 
amd7930_get_output_port(struct sparcaudio_driver * drv)867 static int amd7930_get_output_port(struct sparcaudio_driver *drv)
868 {
869 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
870 
871 	if (info->map.mmr2 & AM_MAP_MMR2_LS)
872 		return AUDIO_SPEAKER;
873 
874 	return AUDIO_HEADPHONE;
875 }
876 
amd7930_set_output_port(struct sparcaudio_driver * drv,int value)877 static int amd7930_set_output_port(struct sparcaudio_driver *drv, int value)
878 {
879 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
880 
881 	switch (value) {
882 	case AUDIO_HEADPHONE:
883 		info->map.mmr2 &= ~AM_MAP_MMR2_LS;
884 		break;
885 	case AUDIO_SPEAKER:
886 		info->map.mmr2 |= AM_MAP_MMR2_LS;
887 		break;
888 	default:
889 		return -EINVAL;
890 	};
891 
892 	amd7930_update_map(drv);
893 	return 0;
894 }
895 
896 /* Only a microphone here, so no troubles */
amd7930_get_input_port(struct sparcaudio_driver * drv)897 static int amd7930_get_input_port(struct sparcaudio_driver *drv)
898 {
899 	return AUDIO_MICROPHONE;
900 }
901 
amd7930_get_encoding(struct sparcaudio_driver * drv)902 static int amd7930_get_encoding(struct sparcaudio_driver *drv)
903 {
904 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
905 
906 	if ((info->map.mmr1 & AM_MAP_MMR1_ALAW) &&
907 	    (info->format_type == AUDIO_ENCODING_ALAW))
908 		return AUDIO_ENCODING_ALAW;
909 
910 	return info->format_type;
911 }
912 
913 static int
amd7930_set_encoding(struct sparcaudio_driver * drv,int value)914 amd7930_set_encoding(struct sparcaudio_driver *drv, int value)
915 {
916 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
917 
918 	switch (value) {
919 	case AUDIO_ENCODING_ALAW:
920 		info->map.mmr1 |= AM_MAP_MMR1_ALAW;
921 		break;
922 	case AUDIO_ENCODING_LINEAR8:
923 	case AUDIO_ENCODING_LINEAR:
924 	case AUDIO_ENCODING_ULAW:
925 		info->map.mmr1 &= ~AM_MAP_MMR1_ALAW;
926 		break;
927 	default:
928 		return -EINVAL;
929 	};
930 
931 	info->format_type = value;
932 
933 	amd7930_update_map(drv);
934 	return 0;
935 }
936 
937 /* This is what you get. Take it or leave it */
amd7930_get_output_rate(struct sparcaudio_driver * drv)938 static int amd7930_get_output_rate(struct sparcaudio_driver *drv)
939 {
940 	return AMD7930_RATE;
941 }
942 
943 static int
amd7930_set_output_rate(struct sparcaudio_driver * drv,int value)944 amd7930_set_output_rate(struct sparcaudio_driver *drv, int value)
945 {
946 	return (value == AMD7930_RATE) ? 0 : -EINVAL;
947 }
948 
amd7930_get_input_rate(struct sparcaudio_driver * drv)949 static int amd7930_get_input_rate(struct sparcaudio_driver *drv)
950 {
951 	return AMD7930_RATE;
952 }
953 
954 static int
amd7930_set_input_rate(struct sparcaudio_driver * drv,int value)955 amd7930_set_input_rate(struct sparcaudio_driver *drv, int value)
956 {
957 	return (value == AMD7930_RATE) ? 0 : -EINVAL;
958 }
959 
amd7930_get_output_muted(struct sparcaudio_driver * drv)960 static int amd7930_get_output_muted(struct sparcaudio_driver *drv)
961 {
962       return 0;
963 }
964 
amd7930_loopback(struct sparcaudio_driver * drv,unsigned int value)965 static void amd7930_loopback(struct sparcaudio_driver *drv, unsigned int value)
966 {
967 	struct amd7930_info *info = (struct amd7930_info *) drv->private;
968 
969 	if (value)
970 		info->map.mmr1 |= AM_MAP_MMR1_LOOPBACK;
971 	else
972 		info->map.mmr1 &= ~AM_MAP_MMR1_LOOPBACK;
973 	amd7930_update_map(drv);
974 }
975 
amd7930_ioctl(struct inode * inode,struct file * file,unsigned int cmd,unsigned long arg,struct sparcaudio_driver * drv)976 static int amd7930_ioctl(struct inode * inode, struct file * file,
977                          unsigned int cmd, unsigned long arg,
978                          struct sparcaudio_driver *drv)
979 {
980 	int retval = 0;
981 
982 	switch (cmd) {
983 	case AUDIO_DIAG_LOOPBACK:
984 		amd7930_loopback(drv, (unsigned int)arg);
985 		break;
986 	default:
987 		retval = -EINVAL;
988 	};
989 
990 	return retval;
991 }
992 
993 
994 /*
995  *       ISDN operations
996  *
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
1002  *
1003  * int amd7930_get_irqnum(int dev)
1004  *
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.
1008  *
1009  * int amd7930_get_liu_state(int dev)
1010  *
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).
1017  *
1018  * void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
1019  *
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
1024  *   current state.
1025  *
1026  * void amd7930_liu_activate(int dev, int priority)
1027  *
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
1031  *   amd7930_liu_init.
1032  *
1033  * void amd7930_liu_deactivate(int dev)
1034  *
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.
1038  *
1039  * void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
1040  *               void (*callback)(void *, int), void *callback_arg)
1041  *
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:
1049  *
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
1054  *
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)
1059  *
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.
1067  *
1068  * void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
1069  *               void (*callback)(void *, int, unsigned int),
1070  *               void *callback_arg)
1071  *
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":
1080  *
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
1089  *
1090  * int amd7930_bopen(int dev, int chan, u_char xmit_idle_char)
1091  *
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
1101  *
1102  * void amd7930_bclose(int dev, int chan)
1103  *
1104  *   Shuts down a B channel when no longer in use.
1105  *
1106  * void amd7930_bxmit(int dev, int chan, __u8 *buffer, unsigned int count,
1107  *               void (*callback)(void *), void *callback_arg)
1108  *
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
1113  *
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
1118  *
1119  * void amd7930_brecv(int dev, int chan, __u8 *buffer, unsigned int size,
1120  *               void (*callback)(void *), void *callback_arg)
1121  *
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
1126  *
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
1131  *
1132  */
1133 
1134 #if defined (AMD79C30_ISDN)
amd7930_get_irqnum(int dev)1135 static int amd7930_get_irqnum(int dev)
1136 {
1137 	struct amd7930_info *info;
1138 
1139 	if (dev > num_drivers)
1140 		return(0);
1141 
1142 	info = (struct amd7930_info *) drivers[dev].private;
1143 
1144 	return info->irq;
1145 }
1146 
amd7930_get_liu_state(int dev)1147 static int amd7930_get_liu_state(int dev)
1148 {
1149 	struct amd7930_info *info;
1150 
1151 	if (dev > num_drivers)
1152 		return(0);
1153 
1154 	info = (struct amd7930_info *) drivers[dev].private;
1155 
1156 	return info->liu_state;
1157 }
1158 
amd7930_liu_init(int dev,void (* callback)(),void * callback_arg)1159 static void amd7930_liu_init(int dev, void (*callback)(), void *callback_arg)
1160 {
1161 	struct amd7930_info *info;
1162 	unsigned long flags;
1163 
1164 	if (dev > num_drivers)
1165 		return;
1166 
1167 	info = (struct amd7930_info *) drivers[dev].private;
1168 
1169 	save_and_cli(flags);
1170 
1171 	/* Set callback for LIU state change */
1172         info->liu_callback = callback;
1173 	info->liu_callback_arg = callback_arg;
1174 
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);
1178 
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,
1184 		    info->regs + DR);
1185 
1186 	/* amd7930_enable_ints(info); */
1187 
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);
1191 
1192 	restore_flags(flags);
1193 }
1194 
amd7930_liu_activate(int dev,int priority)1195 static void amd7930_liu_activate(int dev, int priority)
1196 {
1197 	struct amd7930_info *info;
1198 	unsigned long flags;
1199 
1200 	if (dev > num_drivers)
1201 		return;
1202 
1203 	info = (struct amd7930_info *) drivers[dev].private;
1204 
1205 	save_and_cli(flags);
1206 
1207         /* Set D-channel access priority
1208          *
1209          * I.430 defines a priority mechanism based on counting 1s
1210          * in the echo channel before transmitting
1211          *
1212          * Priority 0 is eight 1s; priority 1 is ten 1s; etc
1213          */
1214         sbus_writeb(AMR_LIU_LPR, info->regs + CR);
1215         sbus_writeb(priority & 0x0f, info->regs + DR);
1216 
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,
1220 		    info->regs + DR);
1221 
1222 	restore_flags(flags);
1223 }
1224 
amd7930_liu_deactivate(int dev)1225 static void amd7930_liu_deactivate(int dev)
1226 {
1227 	struct amd7930_info *info;
1228 	unsigned long flags;
1229 
1230 	if (dev > num_drivers)
1231 		return;
1232 
1233 	info = (struct amd7930_info *) drivers[dev].private;
1234 
1235 	save_and_cli(flags);
1236 
1237 	/* deactivate LIU */
1238 	sbus_writeb(AMR_LIU_LMR1, info->regs + CR);
1239 	sbus_writeb(0, info->regs + DR);
1240 
1241 	restore_flags(flags);
1242 }
1243 
amd7930_dxmit(int dev,__u8 * buffer,unsigned int count,void (* callback)(void *,int),void * callback_arg)1244 static void amd7930_dxmit(int dev, __u8 *buffer, unsigned int count,
1245 			  void (*callback)(void *, int), void *callback_arg)
1246 {
1247 	struct amd7930_info *info;
1248 	unsigned long flags;
1249 	__u8 dmr1;
1250 
1251 	if (dev > num_drivers)
1252 		return;
1253 
1254 	info = (struct amd7930_info *) drivers[dev].private;
1255 
1256 	save_and_cli(flags);
1257 
1258 	if (info->D.output_ptr) {
1259 		restore_flags(flags);
1260 		printk("amd7930_dxmit: transmitter in use\n");
1261 		return;
1262 	}
1263 
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;
1268 
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);
1275 
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);
1280 
1281 	/* Prime xmit FIFO */
1282 	/* fill_D_xmit_fifo(info); */
1283 	transceive_Dchannel(info);
1284 
1285 	restore_flags(flags);
1286 }
1287 
amd7930_drecv(int dev,__u8 * buffer,unsigned int size,void (* callback)(void *,int,unsigned int),void * callback_arg)1288 static void amd7930_drecv(int dev, __u8 *buffer, unsigned int size,
1289 			  void (*callback)(void *, int, unsigned int),
1290 			  void *callback_arg)
1291 {
1292 	struct amd7930_info *info;
1293 	unsigned long flags;
1294 	__u8 dmr1;
1295 
1296 	if (dev > num_drivers)
1297 		return;
1298 
1299 	info = (struct amd7930_info *) drivers[dev].private;
1300 
1301 	save_and_cli(flags);
1302 
1303 	if (info->D.input_ptr) {
1304 		restore_flags(flags);
1305 		printk("amd7930_drecv: receiver already has buffer!\n");
1306 		return;
1307 	}
1308 
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;
1314 
1315 	/* Enable D-channel Receive Threshold interrupt;
1316 	 * Enable D-channel End of Receive Packet interrupt;
1317 	 * Disable address recognition
1318 	 */
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);
1324 
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);
1329 
1330 	restore_flags(flags);
1331 }
1332 
amd7930_bopen(int dev,unsigned int chan,int mode,u_char xmit_idle_char)1333 static int amd7930_bopen(int dev, unsigned int chan,
1334                          int mode, u_char xmit_idle_char)
1335 {
1336 	struct amd7930_info *info;
1337 	unsigned long flags;
1338 	u8 tmp;
1339 
1340 	if (dev > num_drivers || chan<0 || chan>1)
1341 		return -1;
1342 
1343 	if (mode == L1_MODE_HDLC)
1344 		return -1;
1345 
1346 	info = (struct amd7930_info *) drivers[dev].private;
1347 
1348 	save_and_cli(flags);
1349 
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;
1354 
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),
1359 			    info->regs + DR);
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;
1364 
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),
1369 			    info->regs + DR);
1370 	} else {
1371 		restore_flags(flags);
1372 		return (-1);
1373 	}
1374 
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);
1380 
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,
1386 		    info->regs + DR);
1387 
1388 	restore_flags(flags);
1389 	return 0;
1390 }
1391 
amd7930_bclose(int dev,unsigned int chan)1392 static void amd7930_bclose(int dev, unsigned int chan)
1393 {
1394 	struct amd7930_info *info;
1395 	unsigned long flags;
1396 
1397 	if (dev > num_drivers || chan<0 || chan>1)
1398 		return;
1399 
1400 	info = (struct amd7930_info *) drivers[dev].private;
1401 
1402 	save_and_cli(flags);
1403 
1404 	if (info->Bisdn[chan]) {
1405 		u8 tmp;
1406 
1407 		info->Bisdn[chan]->channel_status = CHANNEL_AVAILABLE;
1408 
1409 		sbus_writeb(AMR_MUX_MCR2 + chan, info->regs + CR);
1410 		sbus_writeb(0, info->regs + DR);
1411 
1412 		info->Bisdn[chan] = NULL;
1413 
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);
1419 
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);
1425 		}
1426 	}
1427 
1428 	restore_flags(flags);
1429 }
1430 
amd7930_bxmit(int dev,unsigned int chan,__u8 * buffer,unsigned long count,void (* callback)(void *,int),void * callback_arg)1431 static void amd7930_bxmit(int dev, unsigned int chan,
1432                           __u8 * buffer, unsigned long count,
1433 			  void (*callback)(void *, int), void *callback_arg)
1434 {
1435 	struct amd7930_info *info;
1436 	struct amd7930_channel *Bchan;
1437 	unsigned long flags;
1438 
1439 	if (dev > num_drivers)
1440 		return;
1441 
1442 	info = (struct amd7930_info *) drivers[dev].private;
1443 	Bchan = info->Bisdn[chan];
1444 
1445 	if (Bchan) {
1446 		save_and_cli(flags);
1447 
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;
1453 
1454 		restore_flags(flags);
1455 	}
1456 }
1457 
amd7930_brecv(int dev,unsigned int chan,__u8 * buffer,unsigned long size,void (* callback)(void *,int,unsigned int),void * callback_arg)1458 static void amd7930_brecv(int dev, unsigned int chan,
1459                           __u8 * buffer, unsigned long size,
1460                           void (*callback)(void *, int, unsigned int),
1461                           void *callback_arg)
1462 {
1463 	struct amd7930_info *info;
1464 	struct amd7930_channel *Bchan;
1465 	unsigned long flags;
1466 
1467 	if (dev > num_drivers)
1468 		return;
1469 
1470 	info = (struct amd7930_info *) drivers[dev].private;
1471 	Bchan = info->Bisdn[chan];
1472 
1473 	if (Bchan) {
1474 		save_and_cli(flags);
1475 
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;
1481 
1482 		restore_flags(flags);
1483 	}
1484 }
1485 
1486 struct foreign_interface amd7930_foreign_interface = {
1487         amd7930_get_irqnum,
1488         amd7930_get_liu_state,
1489         amd7930_liu_init,
1490         amd7930_liu_activate,
1491         amd7930_liu_deactivate,
1492         amd7930_dxmit,
1493         amd7930_drecv,
1494         amd7930_bopen,
1495         amd7930_bclose,
1496         amd7930_bxmit,
1497         amd7930_brecv
1498 };
1499 EXPORT_SYMBOL(amd7930_foreign_interface);
1500 #endif
1501 
1502 
1503 /*
1504  *	Device detection and initialization.
1505  */
1506 
1507 static struct sparcaudio_operations amd7930_ops = {
1508 	amd7930_open,
1509 	amd7930_release,
1510 	amd7930_ioctl,
1511 	amd7930_start_output,
1512 	amd7930_stop_output,
1513 	amd7930_start_input,
1514 	amd7930_stop_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,
1564 };
1565 
1566 /* Attach to an amd7930 chip given its PROM node. */
amd7930_attach(struct sparcaudio_driver * drv,int node,struct sbus_bus * sbus,struct sbus_dev * sdev)1567 static int amd7930_attach(struct sparcaudio_driver *drv, int node,
1568 			  struct sbus_bus *sbus, struct sbus_dev *sdev)
1569 {
1570 	struct linux_prom_registers regs;
1571 	struct linux_prom_irqs irq;
1572 	struct resource res, *resp;
1573 	struct amd7930_info *info;
1574 	int err;
1575 
1576 	/* Allocate our private information structure. */
1577 	drv->private = kmalloc(sizeof(struct amd7930_info), GFP_KERNEL);
1578 	if (drv->private == NULL)
1579 		return -ENOMEM;
1580 
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 */
1586 
1587 	drv->dev = sdev;
1588 
1589 	/* Map the registers into memory. */
1590 	prom_getproperty(node, "reg", (char *)&regs, sizeof(regs));
1591 	if (sbus && sdev) {
1592 		resp = &sdev->resource[0];
1593 	} else {
1594 		resp = &res;
1595 		res.start = regs.phys_addr;
1596 		res.end = res.start + regs.reg_size - 1;
1597 		res.flags = IORESOURCE_IO | (regs.which_io & 0xff);
1598 	}
1599 	info->regs_size = regs.reg_size;
1600 	info->regs = sbus_ioremap(resp, 0, regs.reg_size, "amd7930");
1601 	if (!info->regs) {
1602 		printk(KERN_ERR "amd7930: could not remap registers\n");
1603 		kfree(drv->private);
1604 		return -EIO;
1605 	}
1606 
1607 	/* Put amd7930 in idle mode (interrupts disabled) */
1608 	amd7930_idle(info);
1609 
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,
1615 		    info->regs + DR);
1616 
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);
1623 
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);
1630 
1631 	/* Set the default audio parameters. */
1632 	info->rgain = 128;
1633 	info->pgain = 200;
1634 	info->mgain = 0;
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);
1641 
1642 	/* Register the amd7930 with the midlevel audio driver. */
1643 	err = register_sparcaudio_driver(drv, 1);
1644 	if (err < 0) {
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);
1649 		return -EIO;
1650 	}
1651 
1652 	/* Announce the hardware to the user. */
1653 	printk(KERN_INFO "amd7930 at %lx irq %d\n",
1654 	       info->regs, info->irq);
1655 
1656 	/* Success! */
1657 	return 0;
1658 }
1659 
1660 /* Detach from an amd7930 chip given the device structure. */
amd7930_detach(struct sparcaudio_driver * drv)1661 static void __exit amd7930_detach(struct sparcaudio_driver *drv)
1662 {
1663 	struct amd7930_info *info = (struct amd7930_info *)drv->private;
1664 
1665 	unregister_sparcaudio_driver(drv, 1);
1666 	amd7930_idle(info);
1667 	free_irq(info->irq, drv);
1668 	sbus_iounmap(info->regs, info->regs_size);
1669 	kfree(drv->private);
1670 }
1671 
1672 /* Probe for the amd7930 chip and then attach the driver. */
amd7930_init(void)1673 static int __init amd7930_init(void)
1674 {
1675 	struct sbus_bus *sbus;
1676 	struct sbus_dev *sdev;
1677 	int node;
1678 
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)
1683 		num_drivers = 1;
1684 	else
1685 		num_drivers = 0;
1686 
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)
1692 				continue;
1693 
1694 			if (amd7930_attach(&drivers[num_drivers],
1695 					   sdev->prom_node, sdev->bus, sdev) == 0)
1696 				num_drivers++;
1697 		}
1698 	}
1699 
1700 	/* Only return success if we found some amd7930 chips. */
1701 	return (num_drivers > 0) ? 0 : -EIO;
1702 }
1703 
amd7930_exit(void)1704 static void __exit amd7930_exit(void)
1705 {
1706 	register int i;
1707 
1708 	for (i = 0; i < num_drivers; i++) {
1709 		amd7930_detach(&drivers[i]);
1710 		num_drivers--;
1711 	}
1712 }
1713 
1714 module_init(amd7930_init);
1715 module_exit(amd7930_exit);
1716 MODULE_LICENSE("GPL");
1717 
1718 /*************************************************************/
1719 /*                 Audio format conversion                   */
1720 /*************************************************************/
1721 
1722 /* Translation tables */
1723 
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
1757 };
1758 
mulaw2bilinear(__u8 data)1759 static __u8 mulaw2bilinear(__u8 data)
1760 {
1761 	return ulaw[data];
1762 }
1763 
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
1797 };
1798 
bilinear2mulaw(__u8 data)1799 static __u8 bilinear2mulaw(__u8 data)
1800 {
1801 	return linear[data];
1802 }
1803 
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
1813 };
1814 
1815 #define BIAS 0x84
1816 #define CLIP 32635
1817 
1818 #define SWAP_ENDIAN(x) ((x >> 8) | ((x & 0xff) << 8))
1819 
linear2mulaw(__u16 data)1820 static __u8  linear2mulaw(__u16 data)
1821 {
1822 	static int sign, exponent, mantissa;
1823 
1824 	/* not really sure, if swapping is ok - comment next line to disable it */
1825 	data = SWAP_ENDIAN(data);
1826 
1827 	sign = (data >> 8) & 0x80;
1828 	if (sign != 0) data = -data;
1829 
1830 	if (data > CLIP) data = CLIP;
1831 	data += BIAS;
1832 	exponent = exp_lut[(data >> 7) & 0xFF];
1833 	mantissa = (data >> (exponent + 3)) & 0x0F;
1834 
1835 	return (~(sign | (exponent << 4) | mantissa));
1836 }
1837 
mulaw2linear(__u8 data)1838 static __u16 mulaw2linear(__u8 data)
1839 {
1840 	/* this conversion is not working */
1841 	return data;
1842 }
1843 
1844 #if 0
1845 #define INOUT(x,y) (((x) << 16) | (y))
1846 static int convert_audio(int in_format, int out_format, __u8* buffer, int count)
1847 {
1848 	static int i,sign,exponent;
1849 	static __u16 data;
1850 
1851 	if (in_format == out_format) return count;
1852 
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]];
1857 		};
1858 		break;
1859 	case INOUT(AUDIO_ENCODING_ULAW, AUDIO_ENCODING_LINEAR):
1860 		break;
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;
1867 			data += BIAS;
1868 			exponent = exp_lut[(data >> 7) & 0xFF];
1869 			buffer[i] = ~(sign | (exponent << 4) |
1870 						  ((data >> (exponent + 3)) & 0x0F));
1871 		};
1872 		break;
1873 	case INOUT(AUDIO_ENCODING_LINEAR8, AUDIO_ENCODING_ULAW):
1874 		for (i = 0; i < count; i++) {
1875 			buffer[i] = linear[buffer[i]];
1876 		};
1877 		break;
1878 	default:
1879 		return 0;
1880 	};
1881 
1882 	return count;
1883 }
1884 #undef INOUT
1885 #endif
1886 
1887 #undef BIAS
1888 #undef CLIP
1889 #undef SWAP_ENDIAN
1890