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@home.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, this is supported in the Video for Linux
13 * radio-miropcm20 driver.
15 * This Voxware ACI driver currently only supports the ACI functions
16 * on the miroSOUND PCM12 and PCM20 card. Support for miro sound cards
17 * with additional ACI functions can easily be added later.
19 * / NOTE / When compiling as a module, make sure to load the module
20 * after loading the mad16 module. The initialisation code expects the
21 * MAD16 default mixer to be already available.
23 * / NOTE / When compiling as a module, make sure to load the module
24 * after loading the mad16 module. The initialisation code expects the
25 * MAD16 default mixer to be already available.
29 * 1995-11-10 Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
30 * First version written.
31 * 1995-12-31 Markus Kuhn
32 * Second revision, general code cleanup.
33 * 1996-05-16 Hannu Savolainen
34 * Integrated with other parts of the driver.
35 * 1996-05-28 Markus Kuhn
36 * Initialize CS4231A mixer, make ACI first mixer,
37 * use new private mixer API for solo mode.
38 * 1998-08-18 Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
39 * Small modification to export ACI functions and
40 * complete modularisation.
44 * Some driver specific information and features:
46 * This mixer driver identifies itself to applications as "ACI" in
47 * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
49 * Proprietary mixer features that go beyond the standard OSS mixer
52 * Full duplex solo configuration:
55 * ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
57 * solo_mode = 0: deactivate solo mode (default)
58 * solo_mode > 0: activate solo mode
59 * With activated solo mode, the PCM input can not any
60 * longer hear the signals produced by the PCM output.
61 * Activating solo mode is important in duplex mode in order
62 * to avoid feedback distortions.
63 * solo_mode < 0: do not change solo mode (just retrieve the status)
65 * When the ioctl() returns 0, solo_mode contains the previous
66 * status (0 = deactivated, 1 = activated). If solo mode is not
67 * implemented on this card, ioctl() returns -1 and sets errno to
72 #include <linux/config.h> /* for CONFIG_ACI_MIXER */
73 #include <linux/module.h>
75 #include "../sound_config.h"
77 #if defined(CONFIG_ACI_MIXER) || defined(CONFIG_ACI_MIXER_MODULE)
79 #undef DEBUG /* if defined, produce a verbose report via syslog */
81 int aci_port
= 0x354; /* as determined by bit 4 in the OPTi 929 MC4 register */
82 unsigned char aci_idcode
[2] = {0, 0}; /* manufacturer and product ID */
83 unsigned char aci_version
= 0; /* ACI firmware version */
84 int aci_solo
; /* status bit of the card that can't be *
85 * checked with ACI versions prior to 0xb0 */
87 static int aci_present
= 0;
89 #ifdef MODULE /* Whether the aci mixer is to be reset. */
90 int aci_reset
= 0; /* Default: don't reset if the driver is a */
91 MODULE_PARM(aci_reset
,"i");
92 #else /* module; use "insmod aci.o aci_reset=1" */
93 int aci_reset
= 1; /* to override. */
97 #define COMMAND_REGISTER (aci_port)
98 #define STATUS_REGISTER (aci_port + 1)
99 #define BUSY_REGISTER (aci_port + 2)
102 * Wait until the ACI microcontroller has set the READYFLAG in the
103 * Busy/IRQ Source Register to 0. This is required to avoid
104 * overrunning the sound card microcontroller. We do a busy wait here,
105 * because the microcontroller is not supposed to signal a busy
106 * condition for more than a few clock cycles. In case of a time-out,
107 * this function returns -1.
109 * This busy wait code normally requires less than 15 loops and
110 * practically always less than 100 loops on my i486/DX2 66 MHz.
112 * Warning: Waiting on the general status flag after reseting the MUTE
113 * function can take a VERY long time, because the PCM12 does some kind
114 * of fade-in effect. For this reason, access to the MUTE function has
115 * not been implemented at all.
118 static int busy_wait(void)
122 for (timeout
= 0; timeout
< 10000000L; timeout
++)
123 if ((inb_p(BUSY_REGISTER
) & 1) == 0)
127 printk("ACI: READYFLAG timed out.\n");
135 * Read the GENERAL STATUS register.
138 static int read_general_status(void)
145 if (busy_wait()) { restore_flags(flags
); return -1; }
146 status
= (unsigned) inb_p(STATUS_REGISTER
);
147 restore_flags(flags
);
153 * The four ACI command types (implied, write, read and indexed) can
154 * be sent to the microcontroller using the following four functions.
155 * If a problem occurred, they return -1.
158 int aci_implied_cmd(unsigned char opcode
)
163 printk("ACI: aci_implied_cmd(0x%02x)\n", opcode
);
169 if (read_general_status() < 0 || busy_wait()) {
170 restore_flags(flags
);
173 outb_p(opcode
, COMMAND_REGISTER
);
175 restore_flags(flags
);
180 int aci_write_cmd(unsigned char opcode
, unsigned char parameter
)
186 printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode
, parameter
);
192 if (read_general_status() < 0 || busy_wait()) {
193 restore_flags(flags
);
196 outb_p(opcode
, COMMAND_REGISTER
);
197 if (busy_wait()) { restore_flags(flags
); return -1; }
198 outb_p(parameter
, COMMAND_REGISTER
);
200 if ((status
= read_general_status()) < 0) {
201 restore_flags(flags
);
204 /* polarity of the INVALID flag depends on ACI version */
205 if ((aci_version
< 0xb0 && (status
& 0x40) != 0) ||
206 (aci_version
>= 0xb0 && (status
& 0x40) == 0)) {
207 restore_flags(flags
);
208 printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
213 restore_flags(flags
);
218 * This write command send 2 parameters instead of one.
219 * Only used in PCM20 radio frequency tuning control
222 int aci_write_cmd_d(unsigned char opcode
, unsigned char parameter
, unsigned char parameter2
)
228 printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode
, parameter
, parameter2
);
234 if (read_general_status() < 0 || busy_wait()) {
235 restore_flags(flags
);
238 outb_p(opcode
, COMMAND_REGISTER
);
239 if (busy_wait()) { restore_flags(flags
); return -1; }
240 outb_p(parameter
, COMMAND_REGISTER
);
241 if (busy_wait()) { restore_flags(flags
); return -1; }
242 outb_p(parameter2
, COMMAND_REGISTER
);
244 if ((status
= read_general_status()) < 0) {
245 restore_flags(flags
);
248 /* polarity of the INVALID flag depends on ACI version */
249 if ((aci_version
< 0xb0 && (status
& 0x40) != 0) ||
250 (aci_version
>= 0xb0 && (status
& 0x40) == 0)) {
251 restore_flags(flags
);
252 #if 0 /* Frequency tuning works, but the INVALID flag is set ??? */
253 printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
254 opcode
, parameter
, parameter2
);
259 restore_flags(flags
);
263 int aci_read_cmd(unsigned char opcode
, int length
, unsigned char *parameter
)
271 if (read_general_status() < 0) { restore_flags(flags
); return -1; }
273 if (busy_wait()) { restore_flags(flags
); return -1; }
274 outb_p(opcode
, COMMAND_REGISTER
);
275 if (busy_wait()) { restore_flags(flags
); return -1; }
276 parameter
[i
++] = inb_p(STATUS_REGISTER
);
279 printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n", opcode
, length
,
282 printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter
[i
-1]);
286 restore_flags(flags
);
291 int aci_indexed_cmd(unsigned char opcode
, unsigned char index
,
292 unsigned char *parameter
)
299 if (read_general_status() < 0 || busy_wait()) {
300 restore_flags(flags
);
303 outb_p(opcode
, COMMAND_REGISTER
);
304 if (busy_wait()) { restore_flags(flags
); return -1; }
305 outb_p(index
, COMMAND_REGISTER
);
306 if (busy_wait()) { restore_flags(flags
); return -1; }
307 *parameter
= inb_p(STATUS_REGISTER
);
309 printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode
, index
,
313 restore_flags(flags
);
319 * The following macro SCALE can be used to scale one integer volume
320 * value into another one using only integer arithmetic. If the input
321 * value x is in the range 0 <= x <= xmax, then the result will be in
322 * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
324 * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
325 * following nice properties:
327 * - SCALE(xmax,ymax,xmax) = ymax
328 * - SCALE(xmax,ymax,0) = 0
329 * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
331 * In addition, the rounding error is minimal and nicely distributed.
332 * The proofs are left as an exercise to the reader.
335 #define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
338 static int getvolume(caddr_t arg
,
339 unsigned char left_index
, unsigned char right_index
)
345 if (aci_indexed_cmd(0xf0, left_index
, &buf
)) return -EIO
;
346 vol
= SCALE(0x20, 100, buf
< 0x20 ? 0x20-buf
: 0);
348 if (aci_indexed_cmd(0xf0, right_index
, &buf
)) return -EIO
;
349 vol
|= SCALE(0x20, 100, buf
< 0x20 ? 0x20-buf
: 0) << 8;
351 return (*(int *) arg
= vol
);
355 static int setvolume(caddr_t arg
,
356 unsigned char left_index
, unsigned char right_index
)
361 vol
= *(int *)arg
& 0xff;
362 if (vol
> 100) vol
= 100;
363 vol
= SCALE(100, 0x20, vol
);
364 if (aci_write_cmd(left_index
, 0x20 - vol
)) return -EIO
;
365 ret
= SCALE(0x20, 100, vol
);
367 vol
= (*(int *)arg
>> 8) & 0xff;
368 if (vol
> 100) vol
= 100;
369 vol
= SCALE(100, 0x20, vol
);
370 if (aci_write_cmd(right_index
, 0x20 - vol
)) return -EIO
;
371 ret
|= SCALE(0x20, 100, vol
) << 8;
373 return (*(int *) arg
= ret
);
378 aci_mixer_ioctl (int dev
, unsigned int cmd
, caddr_t arg
)
383 /* handle solo mode control */
384 if (cmd
== SOUND_MIXER_PRIVATE1
) {
385 if (*(int *) arg
>= 0) {
386 aci_solo
= !!*(int *) arg
;
387 if (aci_write_cmd(0xd2, aci_solo
)) return -EIO
;
388 } else if (aci_version
>= 0xb0) {
389 if ((status
= read_general_status()) < 0) return -EIO
;
390 return (*(int *) arg
= (status
& 0x20) == 0);
392 return (*(int *) arg
= aci_solo
);
395 if (((cmd
>> 8) & 0xff) == 'M') {
398 switch (cmd
& 0xff) {
399 case SOUND_MIXER_VOLUME
:
400 return setvolume(arg
, 0x01, 0x00);
402 return setvolume(arg
, 0x3c, 0x34);
403 case SOUND_MIXER_MIC
:
404 return setvolume(arg
, 0x38, 0x30);
405 case SOUND_MIXER_LINE
:
406 return setvolume(arg
, 0x39, 0x31);
407 case SOUND_MIXER_SYNTH
:
408 return setvolume(arg
, 0x3b, 0x33);
409 case SOUND_MIXER_PCM
:
410 return setvolume(arg
, 0x3a, 0x32);
411 case SOUND_MIXER_LINE1
: /* AUX1 */
412 return setvolume(arg
, 0x3d, 0x35);
413 case SOUND_MIXER_LINE2
: /* AUX2 */
414 return setvolume(arg
, 0x3e, 0x36);
415 case SOUND_MIXER_IGAIN
: /* MIC pre-amp */
416 vol
= *(int *) arg
& 0xff;
417 if (vol
> 100) vol
= 100;
418 vol
= SCALE(100, 3, vol
);
419 if (aci_write_cmd(0x03, vol
)) return -EIO
;
420 vol
= SCALE(3, 100, vol
);
421 return (*(int *) arg
= vol
| (vol
<< 8));
422 case SOUND_MIXER_RECSRC
:
423 return (*(int *) arg
= 0);
430 switch (cmd
& 0xff) {
431 case SOUND_MIXER_DEVMASK
:
432 return (*(int *) arg
=
433 SOUND_MASK_VOLUME
| SOUND_MASK_CD
|
434 SOUND_MASK_MIC
| SOUND_MASK_LINE
|
435 SOUND_MASK_SYNTH
| SOUND_MASK_PCM
|
439 SOUND_MASK_LINE1
| SOUND_MASK_LINE2
);
441 case SOUND_MIXER_STEREODEVS
:
442 return (*(int *) arg
=
443 SOUND_MASK_VOLUME
| SOUND_MASK_CD
|
444 SOUND_MASK_MIC
| SOUND_MASK_LINE
|
445 SOUND_MASK_SYNTH
| SOUND_MASK_PCM
|
446 SOUND_MASK_LINE1
| SOUND_MASK_LINE2
);
448 case SOUND_MIXER_RECMASK
:
449 return (*(int *) arg
= 0);
451 case SOUND_MIXER_RECSRC
:
452 return (*(int *) arg
= 0);
454 case SOUND_MIXER_CAPS
:
455 return (*(int *) arg
= 0);
457 case SOUND_MIXER_VOLUME
:
458 return getvolume(arg
, 0x04, 0x03);
460 return getvolume(arg
, 0x0a, 0x09);
461 case SOUND_MIXER_MIC
:
462 return getvolume(arg
, 0x06, 0x05);
463 case SOUND_MIXER_LINE
:
464 return getvolume(arg
, 0x08, 0x07);
465 case SOUND_MIXER_SYNTH
:
466 return getvolume(arg
, 0x0c, 0x0b);
467 case SOUND_MIXER_PCM
:
468 return getvolume(arg
, 0x0e, 0x0d);
469 case SOUND_MIXER_LINE1
: /* AUX1 */
470 return getvolume(arg
, 0x11, 0x10);
471 case SOUND_MIXER_LINE2
: /* AUX2 */
472 return getvolume(arg
, 0x13, 0x12);
473 case SOUND_MIXER_IGAIN
: /* MIC pre-amp */
474 if (aci_indexed_cmd(0xf0, 0x21, &buf
)) return -EIO
;
475 vol
= SCALE(3, 100, buf
<= 3 ? buf
: 3);
477 return (*(int *) arg
= vol
);
487 static struct mixer_operations aci_mixer_operations
=
498 outb (0xE3, 0xf8f); /* Write MAD16 password */
499 return inb (port
); /* Read from port */
504 * Check, whether there actually is any ACI port operational and if
505 * one was found, then initialize the ACI interface, reserve the I/O
506 * addresses and attach the new mixer to the relevant VoxWare data
509 * Returns: 1 ACI mixer detected
512 * There is also an internal mixer in the codec (CS4231A or AD1845),
513 * that deserves no purpose in an ACI based system which uses an
514 * external ACI controlled stereo mixer. Make sure that this codec
515 * mixer has the AUX1 input selected as the recording source, that the
516 * input gain is set near maximum and that the other channels going
517 * from the inputs to the codec output are muted.
522 char *boardname
= "unknown";
525 #define MC4_PORT 0xf90
528 (mad_read(MC4_PORT
) & 0x10) ? 0x344 : 0x354;
530 if (check_region(aci_port
, 3)) {
532 printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
533 aci_port
, aci_port
+2);
538 if (aci_read_cmd(0xf2, 2, aci_idcode
)) {
540 printk("ACI: Failed to read idcode.\n");
544 if (aci_read_cmd(0xf1, 1, &aci_version
)) {
546 printk("ACI: Failed to read version.\n");
551 if (aci_idcode
[0] == 0x6d) {
552 /* It looks like a miro sound card. */
553 switch (aci_idcode
[1]) {
555 boardname
= "PCM1 pro / early PCM12";
564 boardname
= "unknown miro";
571 printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
572 aci_version
, aci_idcode
[0], aci_idcode
[1], boardname
, aci_port
);
575 /* initialize ACI mixer */
576 aci_implied_cmd(0xff);
580 /* attach the mixer */
581 request_region(aci_port
, 3, "sound mixer (ACI)");
582 if (num_mixers
< MAX_MIXER_DEV
) {
583 if (num_mixers
> 0 &&
584 !strncmp("MAD16 WSS", mixer_devs
[num_mixers
-1]->name
, 9)) {
586 * The previously registered mixer device is the CS4231A which
587 * has no function on an ACI card. Make the ACI mixer the first
588 * of the two mixer devices.
590 mixer_devs
[num_mixers
] = mixer_devs
[num_mixers
-1];
591 mixer_devs
[num_mixers
-1] = &aci_mixer_operations
;
593 * Initialize the CS4231A mixer with reasonable values. It is
594 * unlikely that the user ever will want to change these as all
595 * channels can be mixed via ACI.
598 mixer_devs
[num_mixers
]->
599 ioctl(num_mixers
, SOUND_MIXER_WRITE_PCM
, (caddr_t
) &volume
);
601 mixer_devs
[num_mixers
]->
602 ioctl(num_mixers
, SOUND_MIXER_WRITE_IGAIN
, (caddr_t
) &volume
);
604 mixer_devs
[num_mixers
]->
605 ioctl(num_mixers
, SOUND_MIXER_WRITE_SPEAKER
, (caddr_t
) &volume
);
607 mixer_devs
[num_mixers
]->
608 ioctl(num_mixers
, SOUND_MIXER_WRITE_MIC
, (caddr_t
) &volume
);
610 mixer_devs
[num_mixers
]->
611 ioctl(num_mixers
, SOUND_MIXER_WRITE_IMIX
, (caddr_t
) &volume
);
613 mixer_devs
[num_mixers
]->
614 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE1
, (caddr_t
) &volume
);
616 mixer_devs
[num_mixers
]->
617 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE2
, (caddr_t
) &volume
);
619 mixer_devs
[num_mixers
]->
620 ioctl(num_mixers
, SOUND_MIXER_WRITE_LINE3
, (caddr_t
) &volume
);
621 volume
= SOUND_MASK_LINE1
;
622 mixer_devs
[num_mixers
]->
623 ioctl(num_mixers
, SOUND_MIXER_WRITE_RECSRC
, (caddr_t
) &volume
);
626 mixer_devs
[num_mixers
++] = &aci_mixer_operations
;
629 /* Just do something; otherwise the first write command fails, at
630 * least with my PCM20.
632 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_READ_VOLUME
, (caddr_t
) &volume
);
635 /* Initialize ACI mixer with reasonable power-up values */
637 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_VOLUME
, (caddr_t
) &volume
);
639 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_SYNTH
, (caddr_t
) &volume
);
641 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_PCM
, (caddr_t
) &volume
);
643 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE
, (caddr_t
) &volume
);
645 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_MIC
, (caddr_t
) &volume
);
647 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_CD
, (caddr_t
) &volume
);
649 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE1
, (caddr_t
) &volume
);
651 aci_mixer_ioctl(num_mixers
-1, SOUND_MIXER_WRITE_LINE2
, (caddr_t
) &volume
);
659 void unload_aci(void)
662 release_region(aci_port
, 3);
669 int init_module(void) {
674 void cleanup_module(void) {