~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/sound/aci.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  1 /*
  2  * Audio Command Interface (ACI) driver (sound/aci.c)
  3  *
  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.
  9  *
 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.
 14  * 
 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.
 18  *
 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.
 22  *
 23  * Revision history:
 24  *
 25  *   1995-11-10  Markus Kuhn <mskuhn@cip.informatik.uni-erlangen.de>
 26  *        First version written.
 27  *   1995-12-31  Markus Kuhn
 28  *        Second revision, general code cleanup.
 29  *   1996-05-16  Hannu Savolainen
 30  *        Integrated with other parts of the driver.
 31  *   1996-05-28  Markus Kuhn
 32  *        Initialize CS4231A mixer, make ACI first mixer,
 33  *        use new private mixer API for solo mode.
 34  *   1998-08-18  Ruurd Reitsma <R.A.Reitsma@wbmt.tudelft.nl>
 35  *        Small modification to export ACI functions and 
 36  *        complete modularisation.
 37  */
 38 
 39 /*
 40  * Some driver specific information and features:
 41  *
 42  * This mixer driver identifies itself to applications as "ACI" in
 43  * mixer_info.id as retrieved by ioctl(fd, SOUND_MIXER_INFO, &mixer_info).
 44  *
 45  * Proprietary mixer features that go beyond the standard OSS mixer
 46  * interface are:
 47  * 
 48  * Full duplex solo configuration:
 49  *
 50  *   int solo_mode;
 51  *   ioctl(fd, SOUND_MIXER_PRIVATE1, &solo_mode);
 52  *
 53  *   solo_mode = 0: deactivate solo mode (default)
 54  *   solo_mode > 0: activate solo mode
 55  *                  With activated solo mode, the PCM input can not any
 56  *                  longer hear the signals produced by the PCM output.
 57  *                  Activating solo mode is important in duplex mode in order
 58  *                  to avoid feedback distortions.
 59  *   solo_mode < 0: do not change solo mode (just retrieve the status)
 60  *
 61  *   When the ioctl() returns 0, solo_mode contains the previous
 62  *   status (0 = deactivated, 1 = activated). If solo mode is not
 63  *   implemented on this card, ioctl() returns -1 and sets errno to
 64  *   EINVAL.
 65  *
 66  */
 67 
 68 #include <linux/init.h>
 69 #include <linux/module.h> 
 70 
 71 #include "sound_config.h"
 72 
 73 #undef  DEBUG           /* if defined, produce a verbose report via syslog */
 74 
 75 int aci_port = 0x354;   /* as determined by bit 4 in the OPTi 929 MC4 register */
 76 unsigned char aci_idcode[2] = {0, 0};   /* manufacturer and product ID */
 77 unsigned char aci_version = 0;          /* ACI firmware version */
 78 int aci_solo;           /* status bit of the card that can't be         *
 79                          * checked with ACI versions prior to 0xb0      */
 80 
 81 static int aci_present = 0;
 82 
 83 #ifdef MODULE                  /* Whether the aci mixer is to be reset.    */
 84 int aci_reset = 0;             /* Default: don't reset if the driver is a  */
 85 MODULE_PARM(aci_reset,"i");
 86 #else                          /* module; use "insmod aci.o aci_reset=1" */
 87 int aci_reset = 1;             /* to override.                             */
 88 #endif
 89 
 90 
 91 #define COMMAND_REGISTER    (aci_port)
 92 #define STATUS_REGISTER     (aci_port + 1)
 93 #define BUSY_REGISTER       (aci_port + 2)
 94 
 95 /*
 96  * Wait until the ACI microcontroller has set the READYFLAG in the
 97  * Busy/IRQ Source Register to 0. This is required to avoid
 98  * overrunning the sound card microcontroller. We do a busy wait here,
 99  * because the microcontroller is not supposed to signal a busy
100  * condition for more than a few clock cycles. In case of a time-out,
101  * this function returns -1.
102  *
103  * This busy wait code normally requires less than 15 loops and
104  * practically always less than 100 loops on my i486/DX2 66 MHz.
105  *
106  * Warning: Waiting on the general status flag after reseting the MUTE
107  * function can take a VERY long time, because the PCM12 does some kind
108  * of fade-in effect. For this reason, access to the MUTE function has
109  * not been implemented at all.
110  */
111 
112 static int busy_wait(void)
113 {
114         long timeout;
115 
116         for (timeout = 0; timeout < 10000000L; timeout++)
117                 if ((inb_p(BUSY_REGISTER) & 1) == 0)
118                         return 0;
119 
120 #ifdef DEBUG
121         printk("ACI: READYFLAG timed out.\n");
122 #endif
123 
124         return -1;
125 }
126 
127 
128 /*
129  * Read the GENERAL STATUS register.
130  */
131 
132 static int read_general_status(void)
133 {
134         unsigned long flags;
135         int status;
136 
137         save_flags(flags);
138         cli();
139         
140         if (busy_wait()) {
141                 restore_flags(flags);
142                 return -1;
143         }
144         
145         status = (unsigned) inb_p(STATUS_REGISTER);
146         restore_flags(flags);
147         return status;
148 }
149 
150 
151 /*
152  * The four ACI command types (implied, write, read and indexed) can
153  * be sent to the microcontroller using the following four functions.
154  * If a problem occurred, they return -1.
155  */
156 
157 int aci_implied_cmd(unsigned char opcode)
158 {
159         unsigned long flags;
160 
161 #ifdef DEBUG
162         printk("ACI: aci_implied_cmd(0x%02x)\n", opcode);
163 #endif
164 
165         save_flags(flags);
166         cli();
167   
168         if (read_general_status() < 0 || busy_wait()) {
169                 restore_flags(flags);
170                 return -1;
171         }
172         
173         outb_p(opcode, COMMAND_REGISTER);
174 
175         restore_flags(flags);
176         return 0;
177 }
178 
179 
180 int aci_write_cmd(unsigned char opcode, unsigned char parameter)
181 {
182         unsigned long flags;
183         int status;
184 
185 #ifdef DEBUG
186         printk("ACI: aci_write_cmd(0x%02x, 0x%02x)\n", opcode, parameter);
187 #endif
188 
189         save_flags(flags);
190         cli();
191         
192         if (read_general_status() < 0 || busy_wait()) {
193                 restore_flags(flags);
194                 return -1;
195         }
196 
197         outb_p(opcode, COMMAND_REGISTER);
198         if (busy_wait()) {
199                 restore_flags(flags);
200                 return -1;
201         }
202 
203         outb_p(parameter, COMMAND_REGISTER);
204 
205         if ((status = read_general_status()) < 0) {
206                 restore_flags(flags);
207                 return -1;
208         }
209 
210         /* polarity of the INVALID flag depends on ACI version */
211         if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
212           (aci_version >= 0xb0 && (status & 0x40) == 0)) {
213                 restore_flags(flags);
214                 printk("ACI: invalid write command 0x%02x, 0x%02x.\n",
215                         opcode, parameter);
216                 return -1;
217         }
218 
219         restore_flags(flags);
220         return 0;
221 }
222 
223 /*
224  * This write command send 2 parameters instead of one.
225  * Only used in PCM20 radio frequency tuning control
226  */
227 
228 int aci_write_cmd_d(unsigned char opcode, unsigned char parameter, unsigned char parameter2)
229 {
230         unsigned long flags;
231         int status;
232 
233 #ifdef DEBUG
234         printk("ACI: aci_write_cmd_d(0x%02x, 0x%02x)\n", opcode, parameter, parameter2);
235 #endif
236 
237         save_flags(flags);
238         cli();
239         
240         if (read_general_status() < 0 || busy_wait()) {
241                 restore_flags(flags);
242                 return -1;
243         }
244 
245         outb_p(opcode, COMMAND_REGISTER);
246         if (busy_wait()) {
247                 restore_flags(flags);
248                 return -1;
249         }
250 
251         outb_p(parameter, COMMAND_REGISTER);
252         if (busy_wait()) {
253                 restore_flags(flags);
254                 return -1;
255         }
256         
257         outb_p(parameter2, COMMAND_REGISTER);
258         
259         if ((status = read_general_status()) < 0) {
260                 restore_flags(flags);
261                 return -1;
262         }
263         
264         /* polarity of the INVALID flag depends on ACI version */
265         if ((aci_version <  0xb0 && (status & 0x40) != 0) ||
266           (aci_version >= 0xb0 && (status & 0x40) == 0)) {
267                 restore_flags(flags);
268 #if 0   /* Frequency tuning works, but the INVALID flag is set ??? */
269                 printk("ACI: invalid write (double) command 0x%02x, 0x%02x, 0x%02x.\n",
270                         opcode, parameter, parameter2);
271 #endif
272                 return -1;
273         }
274         
275         restore_flags(flags);
276         return 0;
277 }
278 
279 int aci_read_cmd(unsigned char opcode, int length, unsigned char *parameter)
280 {
281         unsigned long flags;
282         int i = 0;
283         
284         save_flags(flags);
285         cli();
286  
287         if (read_general_status() < 0) {
288                 restore_flags(flags);
289                 return -1;
290         }
291         while (i < length) {
292                 if (busy_wait()) {
293                         restore_flags(flags);
294                         return -1;
295                 }
296                         
297                 outb_p(opcode, COMMAND_REGISTER);
298                 if (busy_wait()) {
299                         restore_flags(flags);
300                         return -1;
301                 }
302                         
303                 parameter[i++] = inb_p(STATUS_REGISTER);
304 #ifdef DEBUG
305                 if (i == 1)
306                         printk("ACI: aci_read_cmd(0x%02x, %d) = 0x%02x\n",
307                                 opcode, length, parameter[i-1]);
308                 else
309                         printk("ACI: aci_read_cmd cont.: 0x%02x\n", parameter[i-1]);
310 #endif
311         }
312 
313         restore_flags(flags);
314         return 0;
315 }
316 
317 
318 int aci_indexed_cmd(unsigned char opcode, unsigned char index,
319                        unsigned char *parameter)
320 {
321         unsigned long flags;
322 
323         save_flags(flags);
324         cli();
325   
326         if (read_general_status() < 0 || busy_wait()) {
327                 restore_flags(flags);
328                 return -1;
329         }
330         
331         outb_p(opcode, COMMAND_REGISTER);
332         if (busy_wait()) {
333                 restore_flags(flags);
334                 return -1;
335         }
336         
337         outb_p(index, COMMAND_REGISTER);
338         if (busy_wait()) {
339                 restore_flags(flags);
340                 return -1;
341         }
342         
343         *parameter = inb_p(STATUS_REGISTER);
344 #ifdef DEBUG
345         printk("ACI: aci_indexed_cmd(0x%02x, 0x%02x) = 0x%02x\n", opcode, index,
346                 *parameter);
347 #endif
348 
349         restore_flags(flags);
350         return 0;
351 }
352 
353 
354 /*
355  * The following macro SCALE can be used to scale one integer volume
356  * value into another one using only integer arithmetic. If the input
357  * value x is in the range 0 <= x <= xmax, then the result will be in
358  * the range 0 <= SCALE(xmax,ymax,x) <= ymax.
359  *
360  * This macro has for all xmax, ymax > 0 and all 0 <= x <= xmax the
361  * following nice properties:
362  *
363  * - SCALE(xmax,ymax,xmax) = ymax
364  * - SCALE(xmax,ymax,0) = 0
365  * - SCALE(xmax,ymax,SCALE(ymax,xmax,SCALE(xmax,ymax,x))) = SCALE(xmax,ymax,x)
366  *
367  * In addition, the rounding error is minimal and nicely distributed.
368  * The proofs are left as an exercise to the reader.
369  */
370 
371 #define SCALE(xmax,ymax,x) (((x)*(ymax)+(xmax)/2)/(xmax))
372 
373 
374 static int getvolume(caddr_t arg,
375                      unsigned char left_index, unsigned char right_index)
376 {
377         int vol;
378         unsigned char buf;
379 
380         /* left channel */
381         if (aci_indexed_cmd(0xf0, left_index, &buf))
382                 return -EIO;
383         vol = SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0);
384         
385         /* right channel */
386         if (aci_indexed_cmd(0xf0, right_index, &buf))
387                 return -EIO;
388         vol |= SCALE(0x20, 100, buf < 0x20 ? 0x20-buf : 0) << 8;
389 
390         return (*(int *) arg = vol);
391 }
392 
393 
394 static int setvolume(caddr_t arg, 
395                      unsigned char left_index, unsigned char right_index)
396 {
397         int vol, ret;
398 
399         /* left channel */
400         vol = *(int *)arg & 0xff;
401         if (vol > 100)
402                 vol = 100;
403         vol = SCALE(100, 0x20, vol);
404         if (aci_write_cmd(left_index, 0x20 - vol))
405                 return -EIO;
406         ret = SCALE(0x20, 100, vol);
407 
408 
409         /* right channel */
410         vol = (*(int *)arg >> 8) & 0xff;
411         if (vol > 100)
412                 vol = 100;
413         vol = SCALE(100, 0x20, vol);
414         if (aci_write_cmd(right_index, 0x20 - vol))
415                 return -EIO;
416         ret |= SCALE(0x20, 100, vol) << 8;
417  
418         return (*(int *) arg = ret);
419 }
420 
421 
422 static int
423 aci_mixer_ioctl (int dev, unsigned int cmd, caddr_t arg)
424 {
425         int status, vol;
426         unsigned char buf;
427 
428         /* handle solo mode control */
429         if (cmd == SOUND_MIXER_PRIVATE1) {
430                 if (*(int *) arg >= 0) {
431                         aci_solo = !!*(int *) arg;
432                         if (aci_write_cmd(0xd2, aci_solo))
433                                 return -EIO;
434                 } else if (aci_version >= 0xb0) {
435                         if ((status = read_general_status()) < 0)
436                                 return -EIO;
437                         return (*(int *) arg = (status & 0x20) == 0);
438                 }
439                 
440                 return (*(int *) arg = aci_solo);
441         }
442         
443         if (((cmd >> 8) & 0xff) == 'M') {
444                 if (cmd & SIOC_IN)
445                         /* read and write */
446                         switch (cmd & 0xff) {
447                                 case SOUND_MIXER_VOLUME:
448                                         return setvolume(arg, 0x01, 0x00);
449                                 case SOUND_MIXER_CD:
450                                         return setvolume(arg, 0x3c, 0x34);
451                                 case SOUND_MIXER_MIC:
452                                         return setvolume(arg, 0x38, 0x30);
453                                 case SOUND_MIXER_LINE:
454                                         return setvolume(arg, 0x39, 0x31);
455                                 case SOUND_MIXER_SYNTH:
456                                         return setvolume(arg, 0x3b, 0x33);
457                                 case SOUND_MIXER_PCM:
458                                         return setvolume(arg, 0x3a, 0x32);
459                                 case SOUND_MIXER_LINE1:  /* AUX1 */
460                                         return setvolume(arg, 0x3d, 0x35);
461                                 case SOUND_MIXER_LINE2:  /* AUX2 */
462                                         return setvolume(arg, 0x3e, 0x36);
463                                 case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
464                                         vol = *(int *) arg & 0xff;
465                                         if (vol > 100)
466                                                 vol = 100;
467                                         vol = SCALE(100, 3, vol);
468                                         if (aci_write_cmd(0x03, vol))
469                                                 return -EIO;
470                                         vol = SCALE(3, 100, vol);
471                                         return (*(int *) arg = vol | (vol << 8));
472                                 case SOUND_MIXER_RECSRC:
473                                         return (*(int *) arg = 0);
474                                         break;
475                                 default:
476                                         return -EINVAL;
477                         }
478                 else
479                         /* only read */
480                         switch (cmd & 0xff) {
481                                 case SOUND_MIXER_DEVMASK:
482                                         return (*(int *) arg =
483                                  SOUND_MASK_VOLUME | SOUND_MASK_CD    |
484                                  SOUND_MASK_MIC    | SOUND_MASK_LINE  |
485                                  SOUND_MASK_SYNTH  | SOUND_MASK_PCM   |
486 #if 0
487                                  SOUND_MASK_IGAIN  |
488 #endif
489                                  SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
490                                         break;
491                                 case SOUND_MIXER_STEREODEVS:
492                                         return (*(int *) arg =
493                                  SOUND_MASK_VOLUME | SOUND_MASK_CD   |
494                                  SOUND_MASK_MIC    | SOUND_MASK_LINE |
495                                  SOUND_MASK_SYNTH  | SOUND_MASK_PCM  |
496                                  SOUND_MASK_LINE1  | SOUND_MASK_LINE2);
497                                         break;
498                                 case SOUND_MIXER_RECMASK:
499                                         return (*(int *) arg = 0);
500                                         break;
501                                 case SOUND_MIXER_RECSRC:
502                                         return (*(int *) arg = 0);
503                                         break;
504                                 case SOUND_MIXER_CAPS:
505                                         return (*(int *) arg = 0);
506                                         break;
507                                 case SOUND_MIXER_VOLUME:
508                                         return getvolume(arg, 0x04, 0x03);
509                                 case SOUND_MIXER_CD:
510                                         return getvolume(arg, 0x0a, 0x09);
511                                 case SOUND_MIXER_MIC:
512                                         return getvolume(arg, 0x06, 0x05);
513                                 case SOUND_MIXER_LINE:
514                                         return getvolume(arg, 0x08, 0x07);
515                                 case SOUND_MIXER_SYNTH:
516                                         return getvolume(arg, 0x0c, 0x0b);
517                                 case SOUND_MIXER_PCM:
518                                         return getvolume(arg, 0x0e, 0x0d);
519                                 case SOUND_MIXER_LINE1:  /* AUX1 */
520                                         return getvolume(arg, 0x11, 0x10);
521                                 case SOUND_MIXER_LINE2:  /* AUX2 */
522                                         return getvolume(arg, 0x13, 0x12);
523                                 case SOUND_MIXER_IGAIN:  /* MIC pre-amp */
524                                         if (aci_indexed_cmd(0xf0, 0x21, &buf))
525                                                 return -EIO;
526                                         vol = SCALE(3, 100, buf <= 3 ? buf : 3);
527                                         vol |= vol << 8;
528                                         return (*(int *) arg = vol);
529                                 default:
530                                         return -EINVAL;
531                         }
532         }
533         
534         return -EINVAL;
535 }
536 
537 
538 static struct mixer_operations aci_mixer_operations =
539 {
540         owner:  THIS_MODULE,
541         id:     "ACI",
542         name:   "ACI mixer",
543         ioctl:  aci_mixer_ioctl
544 };
545 
546 static unsigned char
547 mad_read (int port)
548 {
549         outb (0xE3, 0xf8f); /* Write MAD16 password */
550         return inb (port);  /* Read from port */
551 }
552 
553 
554 /*
555  * Check, whether there actually is any ACI port operational and if
556  * one was found, then initialize the ACI interface, reserve the I/O
557  * addresses and attach the new mixer to the relevant VoxWare data
558  * structures.
559  *
560  * Returns:  1   ACI mixer detected
561  *           0   nothing there
562  *
563  * There is also an internal mixer in the codec (CS4231A or AD1845),
564  * that deserves no purpose in an ACI based system which uses an
565  * external ACI controlled stereo mixer. Make sure that this codec
566  * mixer has the AUX1 input selected as the recording source, that the
567  * input gain is set near maximum and that the other channels going
568  * from the inputs to the codec output are muted.
569  */
570 
571 static int __init attach_aci(void)
572 {
573         char *boardname = "unknown";
574         int volume;
575 
576 #define MC4_PORT        0xf90
577 
578         aci_port =
579                 (mad_read(MC4_PORT) & 0x10) ? 0x344 : 0x354;
580 
581         if (check_region(aci_port, 3)) {
582 #ifdef DEBUG
583                 printk("ACI: I/O area 0x%03x-0x%03x already used.\n",
584                         aci_port, aci_port+2);
585 #endif
586                 return 0;
587         }
588         
589         if (aci_read_cmd(0xf2, 2, aci_idcode)) {
590 #ifdef DEBUG
591                 printk("ACI: Failed to read idcode.\n");
592 #endif
593                 return 0;
594         }
595         
596         if (aci_read_cmd(0xf1, 1, &aci_version)) {
597 #ifdef DEBUG
598                 printk("ACI: Failed to read version.\n");
599 #endif
600                 return 0;
601         }
602 
603         if (aci_idcode[0] == 0x6d) {
604                 /* It looks like a miro sound card. */
605                 switch (aci_idcode[1]) {
606                         case 0x41:
607                                 boardname = "PCM1 pro / early PCM12";
608                                 break;
609                         case 0x42:
610                                 boardname = "PCM12";
611                                 break;
612                         case 0x43:
613                                 boardname = "PCM20";
614                                 break;
615                         default:
616                                 boardname = "unknown miro";
617                 }
618         } else
619 #ifndef DEBUG
620         return 0;
621 #endif
622   
623         printk("<ACI %02x, id %02x %02x (%s)> at 0x%03x\n",
624                 aci_version, aci_idcode[0], aci_idcode[1], boardname, aci_port);
625 
626         if (aci_reset) {
627                 /* initialize ACI mixer */
628                 aci_implied_cmd(0xff);
629                 aci_solo = 0;
630         }
631 
632         /* attach the mixer */
633         request_region(aci_port, 3, "sound mixer (ACI)");
634         if (num_mixers < MAX_MIXER_DEV) {
635                 if (num_mixers > 0 &&
636                   !strncmp("MAD16 WSS", mixer_devs[num_mixers-1]->name, 9)) {
637                         /*
638                          * The previously registered mixer device is the CS4231A which
639                          * has no function on an ACI card. Make the ACI mixer the first
640                          * of the two mixer devices.
641                          */
642                         mixer_devs[num_mixers] = mixer_devs[num_mixers-1];
643                         mixer_devs[num_mixers-1] = &aci_mixer_operations;
644                         /*
645                          * Initialize the CS4231A mixer with reasonable values. It is
646                          * unlikely that the user ever will want to change these as all
647                          * channels can be mixed via ACI.
648                          */
649                         volume = 0x6464;
650                         mixer_devs[num_mixers]->ioctl(num_mixers,
651                                 SOUND_MIXER_WRITE_PCM, (caddr_t) &volume);
652                         volume = 0x6464;
653                         mixer_devs[num_mixers]->ioctl(num_mixers,
654                                 SOUND_MIXER_WRITE_IGAIN,   (caddr_t) &volume);
655                         volume = 0;
656                         mixer_devs[num_mixers]->ioctl(num_mixers,
657                                 SOUND_MIXER_WRITE_SPEAKER, (caddr_t) &volume);
658                         volume = 0;
659                         mixer_devs[num_mixers]->ioctl(num_mixers,
660                                 SOUND_MIXER_WRITE_MIC, (caddr_t) &volume);
661                         volume = 0;
662                         mixer_devs[num_mixers]->ioctl(num_mixers,
663                                 SOUND_MIXER_WRITE_IMIX, (caddr_t) &volume);
664                         volume = 0;
665                         mixer_devs[num_mixers]->ioctl(num_mixers,
666                                 SOUND_MIXER_WRITE_LINE1, (caddr_t) &volume);
667                         volume = 0;
668                         mixer_devs[num_mixers]->ioctl(num_mixers,
669                                 SOUND_MIXER_WRITE_LINE2, (caddr_t) &volume);
670                         volume = 0;
671                         mixer_devs[num_mixers]->ioctl(num_mixers,
672                                 SOUND_MIXER_WRITE_LINE3, (caddr_t) &volume);
673                         volume = SOUND_MASK_LINE1;
674                         mixer_devs[num_mixers]->ioctl(num_mixers,
675                                 SOUND_MIXER_WRITE_RECSRC, (caddr_t) &volume);
676                         num_mixers++;
677                 } else
678                         mixer_devs[num_mixers++] = &aci_mixer_operations;
679         }
680 
681         /* Just do something; otherwise the first write command fails, at
682          * least with my PCM20.
683          */
684         aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_READ_VOLUME, (caddr_t) &volume);
685         
686         if (aci_reset) {
687                 /* Initialize ACI mixer with reasonable power-up values */
688                 volume = 0x3232;
689                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_VOLUME, (caddr_t) &volume);
690                 volume = 0x3232;
691                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_SYNTH,  (caddr_t) &volume);
692                 volume = 0x3232;
693                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_PCM,    (caddr_t) &volume);
694                 volume = 0x3232;
695                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE,   (caddr_t) &volume);
696                 volume = 0x3232;
697                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_MIC,    (caddr_t) &volume);
698                 volume = 0x3232;
699                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_CD,     (caddr_t) &volume);
700                 volume = 0x3232;
701                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE1,  (caddr_t) &volume);
702                 volume = 0x3232;
703                 aci_mixer_ioctl(num_mixers-1, SOUND_MIXER_WRITE_LINE2,  (caddr_t) &volume);
704         }
705 
706         aci_present = 1;
707 
708         return 1;
709 }
710 
711 static void __exit unload_aci(void)
712 {
713         if (aci_present)
714                 release_region(aci_port, 3);
715 }
716 
717 module_init(attach_aci);
718 module_exit(unload_aci);
719 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.