2 * Audio Command Interface (ACI) driver (sound/aci.c)
4 * ACI is a protocol used to communicate with the microcontroller on
5 * some sound cards produced by miro, e.g. the miroSOUND PCM12 and
6 * PCM20. The ACI has been developed for miro by Norberto Pellicci
7 * <pellicci@ix.netcom.com>. Special thanks to both him and miro for
8 * providing the ACI specification.
10 * The main function of the ACI is to control the mixer and to get a
11 * product identification. On the PCM20, ACI also controls the radio
12 * tuner on this card, however this is not yet supported in this
15 * This Voxware ACI driver currently only supports the ACI functions
16 * on the miroSOUND PCM12 card. Support for miro soundcards with
17 * additional ACI functions can easily be added later.
21 * 1995-11-10 Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
22 * First version written.
23 * 1995-12-31 Markus Kuhn
24 * Second revision, general code cleanup.
25 * 1996-05-16 Hannu Savolainen
26 * Integrated with other parts of the driver.
27 * 1996-05-28 Markus Kuhn
28 * Initialize CS4231A mixer, make ACI first mixer,
29 * use new private mixer API for solo mode.
33 * Some driver specific information and features:
35 * This mixer driver identifies itself to applications as "ACI" in
36 * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
38 * Proprietary mixer features that go beyond the standard OSS mixer
41 * Full duplex solo configuration:
44 * ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
46 * solo_mode = 0: deactivate solo mode (default)
47 * solo_mode > 0: activate solo mode
48 * With activated solo mode, the PCM input can not any
49 * longer hear the signals produced by the PCM output.
50 * Activating solo mode is important in duplex mode in order
51 * to avoid feedback distortions.
52 * solo_mode < 0: do not change solo mode (just retrieve the status)
54 * When the ioctl() returns 0, solo_mode contains the previous
55 * status (0 = deactivated, 1 = activated). If solo mode is not
56 * implemented on this card, ioctl() returns -1 and sets errno to
62 #include "../sound_config.h"
64 #ifdef CONFIG_ACI_MIXER
66 #undef DEBUG /* if defined, produce a verbose report via syslog */
68 int aci_port
= 0x354; /* as determined by bit 4 in the OPTi 929 MC4 register */
69 unsigned char aci_idcode
[2] = {0, 0}; /* manufacturer and product ID */
70 unsigned char aci_version
= 0; /* ACI firmware version */
71 int aci_solo
; /* status bit of the card that can't be *
72 * checked with ACI versions prior to 0xb0 */
74 static int aci_present
= 0;
76 #ifdef MODULE /* Whether the aci mixer is to be reset. */
77 int aci_reset
= 0; /* Default: don't reset if the driver is a */
78 #else /* module; use "insmod sound.o aci_reset=1" */
79 int aci_reset
= 1; /* to override. */
83 #define COMMAND_REGISTER (aci_port)
84 #define STATUS_REGISTER (aci_port + 1)
85 #define BUSY_REGISTER (aci_port + 2)
88 * Wait until the ACI microcontroller has set the READYFLAG in the
89 * Busy/IRQ Source Register to 0. This is required to avoid
90 * overrunning the soundcard microcontroller. We do a busy wait here,
91 * because the microcontroller is not supposed to signal a busy
92 * condition for more than a few clock cycles. In case of a time-out,
93 * this function returns -1.
95 * This busy wait code normally requires less than 15 loops and
96 * practically always less than 100 loops on my i486/DX2 66 MHz.
98 * Warning: Waiting on the general status flag after reseting the MUTE
99 * function can take a VERY long time, because the PCM12 does some kind
100 * of fade-in effect. For this reason, access to the MUTE function has
101 * not been implemented at all.
104 static int busy_wait(void)
108 for (timeout
= 0; timeout
< 10000000L; timeout
++)
109 if ((inb_p(BUSY_REGISTER
) & 1) == 0)
113 printk("ACI: READYFLAG timed out.\n");
121 * Read the GENERAL STATUS register.
124 static int read_general_status(void)
131 if (busy_wait()) { restore_flags(flags
); return -1; }
132 status
= (unsigned) inb_p(STATUS_REGISTER
);
133 restore_flags(flags
);
139 * The four ACI command types (implied, write, read and indexed) can
140 * be sent to the microcontroller using the following four functions.
141 * If a problem occurred, they return -1.
144 static int implied_cmd(unsigned char opcode
)
149 printk("ACI: implied_cmd(0x%02x)\n", opcode
);
155 if (read_general_status() < 0 || busy_wait()) {
156 restore_flags(flags
);
159 outb_p(opcode
, COMMAND_REGISTER
);
161 restore_flags(flags
);
166 static int write_cmd(unsigned char opcode
, unsigned char parameter
)
172 printk("ACI: write_cmd(0x%02x, 0x%02x)\n", opcode
, parameter
);
178 if (read_general_status() < 0 || busy_wait()) {
179 restore_flags(flags
);
182 outb_p(opcode
, COMMAND_REGISTER
);
183 if (busy_wait()) { restore_flags(flags
); return -1; }
184 outb_p(parameter
, COMMAND_REGISTER
);
186 if ((status
= read_general_status()) < 0) {
187 restore_flags(flags
);
190 /* polarity of the INVALID flag depends on ACI version */
191 if ((aci_version
< 0xb0 && (status
& 0x40) != 0) ||
192 (aci_version
>= 0xb0 && (status
& 0x40) == 0)) {
193 restore_flags(flags
);
194 printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
199 restore_flags(flags
);
204 static int read_cmd(unsigned char opcode
, int length
, unsigned char *parameter
)
212 if (read_general_status() < 0) { restore_flags(flags
); return -1; }
214 if (busy_wait()) { restore_flags(flags
); return -1; }
215 outb_p(opcode
, COMMAND_REGISTER
);
216 if (busy_wait()) { restore_flags(flags
); return -1; }
217 parameter
[i
++] = inb_p(STATUS_REGISTER
);
220 printk("ACI: read_cmd(0x%02x, %d) = 0x%02x\n", opcode
, length
,
223 printk("ACI: read_cmd cont.: 0x%02x\n", parameter
[i
-1]);
227 restore_flags(flags
);
232 static int indexed_cmd(unsigned char opcode
, unsigned char index
,
233 unsigned char *parameter
)
240 if (read_general_status() < 0 || busy_wait()) {
241 restore_flags(flags
);
244 outb_p(opcode
, COMMAND_REGISTER
);
245 if (busy_wait()) { restore_flags(flags
); return -1; }
246 outb_p(index
, COMMAND_REGISTER
);
247 if (busy_wait()) { restore_flags(flags
); return -1; }
248 *parameter
= inb_p(STATUS_REGISTER
);
250 printk("ACI: indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode
, index
,
254 restore_flags(flags
);
260 * The following macro SCALE can be used to scale one integer volume
261 * value into another one using only integer arithmetic. If the input
262 * value x is in the range 0 <= x <= xmax, then the result will be in
263 * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
265 * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
266 * following nice properties:
268 * - SCALE(xmax,ymax,xmax) = ymax
269 * - SCALE(xmax,ymax,0) = 0
270 * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
272 * In addition, the rounding error is minimal and nicely distributed.
273 * The proofs are left as an exercise to the reader.
276 #define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
279 static int getvolume(caddr_t arg
,
280 unsigned char left_index
, unsigned char right_index
)
286 if (indexed_cmd(0xf0, left_index
, &buf
)) return -EIO
;
287 vol
= SCALE(0x20, 100, buf
< 0x20 ? 0x20-buf
: 0);
289 if (indexed_cmd(0xf0, right_index
, &buf
)) return -EIO
;
290 vol
|= SCALE(0x20, 100, buf
< 0x20 ? 0x20-buf
: 0) << 8;
292 return (*(int *) arg
= vol
);
296 static int setvolume(caddr_t arg
,
297 unsigned char left_index
, unsigned char right_index
)
302 vol
= *(int *)arg
& 0xff;
303 if (vol
> 100) vol
= 100;
304 vol
= SCALE(100, 0x20, vol
);
305 if (write_cmd(left_index
, 0x20 - vol
)) return -EIO
;
306 ret
= SCALE(0x20, 100, vol
);
308 vol
= (*(int *)arg
>> 8) & 0xff;
309 if (vol
> 100) vol
= 100;
310 vol
= SCALE(100, 0x20, vol
);
311 if (write_cmd(right_index
, 0x20 - vol
)) return -EIO
;
312 ret
|= SCALE(0x20, 100, vol
) << 8;
314 return (*(int *) arg
= ret
);
319 aci_mixer_ioctl (int dev
, unsigned int cmd
, caddr_t arg
)
324 /* handle solo mode control */
325 if (cmd
== SOUND_MIXER_PRIVATE1
) {
326 if (*(int *) arg
>= 0) {
327 aci_solo
= !!*(int *) arg
;
328 if (write_cmd(0xd2, aci_solo
)) return -EIO
;
329 } else if (aci_version
>= 0xb0) {
330 if ((status
= read_general_status()) < 0) return -EIO
;
331 return (*(int *) arg
= (status
& 0x20) == 0);
333 return (*(int *) arg
= aci_solo
);
336 if (((cmd
>> 8) & 0xff) == 'M') {
339 switch (cmd
& 0xff) {
340 case SOUND_MIXER_VOLUME
:
341 return setvolume(arg
, 0x01, 0x00);
343 return setvolume(arg
, 0x3c, 0x34);
344 case SOUND_MIXER_MIC
:
345 return setvolume(arg
, 0x38, 0x30);
346 case SOUND_MIXER_LINE
:
347 return setvolume(arg
, 0x39, 0x31);
348 case SOUND_MIXER_SYNTH
:
349 return setvolume(arg
, 0x3b, 0x33);
350 case SOUND_MIXER_PCM
:
351 return setvolume(arg
, 0x3a, 0x32);
352 case SOUND_MIXER_LINE1
: /* AUX1 */
353 return setvolume(arg
, 0x3d, 0x35);
354 case SOUND_MIXER_LINE2
: /* AUX2 */
355 return setvolume(arg
, 0x3e, 0x36);
356 case SOUND_MIXER_IGAIN
: /* MIC pre-amp */
357 vol
= *(int *) arg
& 0xff;
358 if (vol
> 100) vol
= 100;
359 vol
= SCALE(100, 3, vol
);
360 if (write_cmd(0x03, vol
)) return -EIO
;
361 vol
= SCALE(3, 100, vol
);
362 return (*(int *) arg
= vol
| (vol
<< 8));
363 case SOUND_MIXER_RECSRC
:
364 return (*(int *) arg
= 0);
371 switch (cmd
& 0xff) {
372 case SOUND_MIXER_DEVMASK
:
373 return (*(int *) arg
=
374 SOUND_MASK_VOLUME
| SOUND_MASK_CD
|
375 SOUND_MASK_MIC
| SOUND_MASK_LINE
|
376 SOUND_MASK_SYNTH
| SOUND_MASK_PCM
|
380 SOUND_MASK_LINE1
| SOUND_MASK_LINE2
);
382 case SOUND_MIXER_STEREODEVS
:
383 return (*(int *) arg
=
384 SOUND_MASK_VOLUME
| SOUND_MASK_CD
|
385 SOUND_MASK_MIC
| SOUND_MASK_LINE
|
386 SOUND_MASK_SYNTH
| SOUND_MASK_PCM
|
387 SOUND_MASK_LINE1
| SOUND_MASK_LINE2
);
389 case SOUND_MIXER_RECMASK
:
390 return (*(int *) arg
= 0);
392 case SOUND_MIXER_RECSRC
:
393 return (*(int *) arg
= 0);
395 case SOUND_MIXER_CAPS
:
396 return (*(int *) arg
= 0);
398 case SOUND_MIXER_VOLUME
:
399 return getvolume(arg
, 0x04, 0x03);
401 return getvolume(arg
, 0x0a, 0x09);
402 case SOUND_MIXER_MIC
:
403 return getvolume(arg
, 0x06, 0x05);
404 case SOUND_MIXER_LINE
:
405 return getvolume(arg
, 0x08, 0x07);
406 case SOUND_MIXER_SYNTH
:
407 return getvolume(arg
, 0x0c, 0x0b);
408 case SOUND_MIXER_PCM
:
409 return getvolume(arg
, 0x0e, 0x0d);
410 case SOUND_MIXER_LINE1
: /* AUX1 */
411 return getvolume(arg
, 0x11, 0x10);
412 case SOUND_MIXER_LINE2
: /* AUX2 */
413 return getvolume(arg
, 0x13, 0x12);
414 case SOUND_MIXER_IGAIN
: /* MIC pre-amp */
415 if (indexed_cmd(0xf0, 0x21, &buf
)) return -EIO
;
416 vol
= SCALE(3, 100, buf
<= 3 ? buf
: 3);
418 return (*(int *) arg
= vol
);
428 static struct mixer_operations aci_mixer_operations
=
439 outb (0xE3, 0xf8f); /* Write MAD16 password */
440 return inb (port
); /* Read from port */
445 * Check, whether there actually is any ACI port operational and if
446 * one was found, then initialize the ACI interface, reserve the I/O
447 * addresses and attach the new mixer to the relevant VoxWare data
450 * Returns: 1 ACI mixer detected
453 * There is also an internal mixer in the codec (CS4231A or AD1845),
454 * that deserves no purpose in an ACI based system which uses an
455 * external ACI controlled stereo mixer. Make sure that this codec
456 * mixer has the AUX1 input selected as the recording source, that the
457 * input gain is set near maximum and that the other channels going
458 * from the inputs to the codec output are muted.
463 char *boardname
= "unknown";
466 #define MC4_PORT 0xf90
469 (mad_read(MC4_PORT
) & 0x10) ? 0x344 : 0x354;
471 if (check_region(aci_port
, 3)) {
473 printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
474 aci_port
, aci_port
+2);
479 if (read_cmd(0xf2, 2, aci_idcode
)) {
481 printk("ACI: Failed to read idcode.\n");
485 if (read_cmd(0xf1, 1, &aci_version
)) {
487 printk("ACI: Failed to read version.\n");
492 if (aci_idcode
[0] == 0x6d) {
493 /* it looks like a miro soundcard */
494 switch (aci_idcode
[1]) {
496 boardname
= "PCM1 pro / early PCM12";
505 boardname
= "unknown miro";
512 printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
513 aci_version
, aci_idcode
[0], aci_idcode
[1], boardname
, aci_port
);
516 /* initialize ACI mixer */
521 /* attach the mixer */
522 request_region(aci_port
, 3, "sound mixer (ACI)");
523 if (num_mixers
< MAX_MIXER_DEV
) {
524 if (num_mixers
> 0 &&
525 !strncmp("MAD16 WSS", mixer_devs
[num_mixers
-1]->name
, 9)) {
527 * The previously registered mixer device is the CS4231A which
528 * has no function on an ACI card. Make the ACI mixer the first
529 * of the two mixer devices.
531 mixer_devs
[num_mixers
] = mixer_devs
[num_mixers
-1];
532 mixer_devs
[num_mixers
-1] = &aci_mixer_operations
;
534 * Initialize the CS4231A mixer with reasonable values. It is
535 * unlikely that the user ever will want to change these as all
536 * channels can be mixed via ACI.
539 mixer_devs
[num_mixers
]->
540 ioctl(num_mixers
, SOUND_MIXER_WRITE_PCM
, (caddr_t
) &volume
);
542 mixer_devs
[num_mixers
]->
543 ioctl(num_mixers
, SOUND_MIXER_WRITE_IGAIN
, (caddr_t
) &volume
);
545 mixer_devs
[num_mixers
]->
546 ioctl(num_mixers
, SOUND_MIXER_WRITE_SPEAKER
, (caddr_t
) &volume
);
548 mixer_devs
[num_mixers
]->
549 ioctl(num_mixers
, SOUND_MIXER_WRITE_MIC
, (caddr_t
) &volume
);
551 mixer_devs
[num_mixers
]->
552 ioctl(num_mixers
, SOUND_MIXER_WRITE_IMIX
, (caddr_t
) &volume
);
554 mixer_devs
[num_mixers
]->
555 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE1
, (caddr_t
) &volume
);
557 mixer_devs
[num_mixers
]->
558 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE2
, (caddr_t
) &volume
);
560 mixer_devs
[num_mixers
]->
561 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE3
, (caddr_t
) &volume
);
562 volume
= SOUND_MASK_LINE1
;
563 mixer_devs
[num_mixers
]->
564 ioctl(num_mixers
, SOUND_MIXER_WRITE_RECSRC
, (caddr_t
) &volume
);
567 mixer_devs
[num_mixers
++] = &aci_mixer_operations
;
570 /* Just do something; otherwise the first write command fails, at
571 * least with my PCM20.
573 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_READ_VOLUME
, (caddr_t
) &volume
);
576 /* Initialize ACI mixer with reasonable power-up values */
578 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_VOLUME
, (caddr_t
) &volume
);
580 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_SYNTH
, (caddr_t
) &volume
);
582 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_PCM
, (caddr_t
) &volume
);
584 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE
, (caddr_t
) &volume
);
586 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_MIC
, (caddr_t
) &volume
);
588 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_CD
, (caddr_t
) &volume
);
590 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE1
, (caddr_t
) &volume
);
592 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE2
, (caddr_t
) &volume
);
600 void unload_aci(void)
603 release_region(aci_port
, 3);