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 *)®s, 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