source: GPL/alsa-kernel/isa/es18xx.c@ 1

Last change on this file since 1 was 1, checked in by vladest, 20 years ago

initial import

File size: 70.0 KB
Line 
1/*
2 * Driver for generic ESS AudioDrive ES18xx soundcards
3 * Copyright (c) by Christian Fischbach <fishbach@pool.informatik.rwth-aachen.de>
4 * Copyright (c) by Abramo Bagnara <abramo@alsa-project.org>
5 *
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 *
21 */
22/* GENERAL NOTES:
23 *
24 * BUGS:
25 * - There are pops (we can't delay in trigger function, cause midlevel
26 * often need to trigger down and then up very quickly).
27 * Any ideas?
28 * - Support for 16 bit DMA seems to be broken. I've no hardware to tune it.
29 */
30
31/*
32 * ES1868 NOTES:
33 * - The chip has one half duplex pcm (with very limited full duplex support).
34 *
35 * - Duplex stereophonic sound is impossible.
36 * - Record and playback must share the same frequency rate.
37 *
38 * - The driver use dma2 for playback and dma1 for capture.
39 */
40
41/*
42 * ES1869 NOTES:
43 *
44 * - there are a first full duplex pcm and a second playback only pcm
45 * (incompatible with first pcm capture)
46 *
47 * - there is support for the capture volume and ESS Spatializer 3D effect.
48 *
49 * - contrarily to some pages in DS_1869.PDF the rates can be set
50 * independently.
51 *
52 * BUGS:
53 *
54 * - There is a major trouble I noted:
55 *
56 * using both channel for playback stereo 16 bit samples at 44100 Hz
57 * the second pcm (Audio1) DMA slows down irregularly and sound is garbled.
58 *
59 * The same happens using Audio1 for captureing.
60 *
61 * The Windows driver does not suffer of this (although it use Audio1
62 * only for captureing). I'm unable to discover why.
63 *
64 */
65
66
67#define SNDRV_MAIN_OBJECT_FILE
68#include <sound/driver.h>
69#include <sound/control.h>
70#include <sound/pcm.h>
71#include <sound/mpu401.h>
72#include <sound/opl3.h>
73#define SNDRV_LEGACY_AUTO_PROBE
74#define SNDRV_LEGACY_FIND_FREE_IRQ
75#define SNDRV_LEGACY_FIND_FREE_DMA
76#define SNDRV_GET_ID
77#include <sound/initval.h>
78
79struct _snd_es18xx {
80 unsigned long port; /* port of ESS chip */
81 unsigned long mpu_port; /* MPU-401 port of ESS chip */
82 unsigned long fm_port; /* FM port */
83 unsigned long ctrl_port; /* Control port of ESS chip */
84 struct resource *res_port;
85 struct resource *res_mpu_port;
86 struct resource *res_ctrl_port;
87 int irq; /* IRQ number of ESS chip */
88 int dma1; /* DMA1 */
89 int dma2; /* DMA2 */
90 unsigned short version; /* version of ESS chip */
91 int caps; /* Chip capabilities */
92 unsigned short audio2_vol; /* volume level of audio2 */
93
94 unsigned short active; /* active channel mask */
95 unsigned int dma1_size;
96 unsigned int dma2_size;
97 unsigned int dma1_shift;
98 unsigned int dma2_shift;
99
100 snd_card_t *card;
101 snd_pcm_t *pcm;
102 snd_pcm_substream_t *playback_a_substream;
103 snd_pcm_substream_t *capture_a_substream;
104 snd_pcm_substream_t *playback_b_substream;
105
106 snd_rawmidi_t *rmidi;
107
108 snd_kcontrol_t *hw_volume;
109 snd_kcontrol_t *hw_switch;
110 snd_kcontrol_t *master_volume;
111 snd_kcontrol_t *master_switch;
112
113 spinlock_t reg_lock;
114 spinlock_t mixer_lock;
115 spinlock_t ctrl_lock;
116};
117
118#define AUDIO1_IRQ 0x01
119#define AUDIO2_IRQ 0x02
120#define HWV_IRQ 0x04
121#define MPU_IRQ 0x08
122
123#define ES18XX_PCM2 0x0001 /* Has two useable PCM */
124#define ES18XX_SPATIALIZER 0x0002 /* Has 3D Spatializer */
125#define ES18XX_RECMIX 0x0004 /* Has record mixer */
126#define ES18XX_DUPLEX_MONO 0x0008 /* Has mono duplex only */
127#define ES18XX_DUPLEX_SAME 0x0010 /* Playback and record must share the same rate */
128#define ES18XX_NEW_RATE 0x0020 /* More precise rate setting */
129#define ES18XX_AUXB 0x0040 /* AuxB mixer control */
130#define ES18XX_HWV 0x0080 /* Has hardware volume */
131#define ES18XX_MONO 0x0100 /* Mono_in mixer control */
132#define ES18XX_I2S 0x0200 /* I2S mixer control */
133#define ES18XX_MUTEREC 0x0400 /* Record source can be muted */
134#define ES18XX_CONTROL 0x0800 /* Has control ports */
135
136typedef struct _snd_es18xx es18xx_t;
137
138#define chip_t es18xx_t
139
140/* Lowlevel */
141
142#define DAC1 0x01
143#define ADC1 0x02
144#define DAC2 0x04
145#define MILLISECOND 10000
146
147static int snd_es18xx_dsp_command(es18xx_t *chip, unsigned char val)
148{
149 int i;
150
151 for(i = MILLISECOND; i; i--)
152 if ((inb(chip->port + 0x0C) & 0x80) == 0) {
153 outb(val, chip->port + 0x0C);
154 return 0;
155 }
156 snd_printk("dsp_command: timeout (0x%x)\n", val);
157 return -EINVAL;
158}
159
160static int snd_es18xx_dsp_get_byte(es18xx_t *chip)
161{
162 int i;
163
164 for(i = MILLISECOND/10; i; i--)
165 if (inb(chip->port + 0x0C) & 0x40)
166 return inb(chip->port + 0x0A);
167 snd_printk("dsp_get_byte failed: 0x%lx = 0x%x!!!\n", chip->port + 0x0A, inb(chip->port + 0x0A));
168 return -ENODEV;
169}
170
171#undef REG_DEBUG
172
173static int snd_es18xx_write(es18xx_t *chip,
174 unsigned char reg, unsigned char data)
175{
176 unsigned long flags;
177 int ret;
178
179 spin_lock_irqsave(&chip->reg_lock, flags);
180 ret = snd_es18xx_dsp_command(chip, reg);
181 if (ret < 0)
182 goto end;
183 ret = snd_es18xx_dsp_command(chip, data);
184 end:
185 spin_unlock_irqrestore(&chip->reg_lock, flags);
186#ifdef REG_DEBUG
187 snd_printk("Reg %02x set to %02x\n", reg, data);
188#endif
189 return ret;
190}
191
192static int snd_es18xx_read(es18xx_t *chip, unsigned char reg)
193{
194 unsigned long flags;
195 int ret, data;
196 spin_lock_irqsave(&chip->reg_lock, flags);
197 ret = snd_es18xx_dsp_command(chip, 0xC0);
198 if (ret < 0)
199 goto end;
200 ret = snd_es18xx_dsp_command(chip, reg);
201 if (ret < 0)
202 goto end;
203 data = snd_es18xx_dsp_get_byte(chip);
204 ret = data;
205#ifdef REG_DEBUG
206 snd_printk("Reg %02x now is %02x (%d)\n", reg, data, ret);
207#endif
208 end:
209 spin_unlock_irqrestore(&chip->reg_lock, flags);
210 return ret;
211}
212
213/* Return old value */
214static int snd_es18xx_bits(es18xx_t *chip, unsigned char reg,
215 unsigned char mask, unsigned char val)
216{
217 int ret;
218 unsigned char old, new, oval;
219 unsigned long flags;
220 spin_lock_irqsave(&chip->reg_lock, flags);
221 ret = snd_es18xx_dsp_command(chip, 0xC0);
222 if (ret < 0)
223 goto end;
224 ret = snd_es18xx_dsp_command(chip, reg);
225 if (ret < 0)
226 goto end;
227 ret = snd_es18xx_dsp_get_byte(chip);
228 if (ret < 0) {
229 goto end;
230 }
231 old = ret;
232 oval = old & mask;
233 if (val != oval) {
234 ret = snd_es18xx_dsp_command(chip, reg);
235 if (ret < 0)
236 goto end;
237 new = (old & ~mask) | (val & mask);
238 ret = snd_es18xx_dsp_command(chip, new);
239 if (ret < 0)
240 goto end;
241#ifdef REG_DEBUG
242 snd_printk("Reg %02x was %02x, set to %02x (%d)\n", reg, old, new, ret);
243#endif
244 }
245 ret = oval;
246 end:
247 spin_unlock_irqrestore(&chip->reg_lock, flags);
248 return ret;
249}
250
251inline void snd_es18xx_mixer_write(es18xx_t *chip,
252 unsigned char reg, unsigned char data)
253{
254 unsigned long flags;
255 spin_lock_irqsave(&chip->mixer_lock, flags);
256 outb(reg, chip->port + 0x04);
257 outb(data, chip->port + 0x05);
258 spin_unlock_irqrestore(&chip->mixer_lock, flags);
259#ifdef REG_DEBUG
260 snd_printk("Mixer reg %02x set to %02x\n", reg, data);
261#endif
262}
263
264inline int snd_es18xx_mixer_read(es18xx_t *chip, unsigned char reg)
265{
266 unsigned long flags;
267 int data;
268 spin_lock_irqsave(&chip->mixer_lock, flags);
269 outb(reg, chip->port + 0x04);
270 data = inb(chip->port + 0x05);
271 spin_unlock_irqrestore(&chip->mixer_lock, flags);
272#ifdef REG_DEBUG
273 snd_printk("Mixer reg %02x now is %02x\n", reg, data);
274#endif
275 return data;
276}
277
278/* Return old value */
279static inline int snd_es18xx_mixer_bits(es18xx_t *chip, unsigned char reg,
280 unsigned char mask, unsigned char val)
281{
282 unsigned char old, new, oval;
283 unsigned long flags;
284 spin_lock_irqsave(&chip->mixer_lock, flags);
285 outb(reg, chip->port + 0x04);
286 old = inb(chip->port + 0x05);
287 oval = old & mask;
288 if (val != oval) {
289 new = (old & ~mask) | (val & mask);
290 outb(new, chip->port + 0x05);
291#ifdef REG_DEBUG
292 snd_printk("Mixer reg %02x was %02x, set to %02x\n", reg, old, new);
293#endif
294 }
295 spin_unlock_irqrestore(&chip->mixer_lock, flags);
296 return oval;
297}
298
299static inline int snd_es18xx_mixer_writable(es18xx_t *chip, unsigned char reg,
300 unsigned char mask)
301{
302 int old, expected, new;
303 unsigned long flags;
304 spin_lock_irqsave(&chip->mixer_lock, flags);
305 outb(reg, chip->port + 0x04);
306 old = inb(chip->port + 0x05);
307 expected = old ^ mask;
308 outb(expected, chip->port + 0x05);
309 new = inb(chip->port + 0x05);
310 spin_unlock_irqrestore(&chip->mixer_lock, flags);
311#ifdef REG_DEBUG
312 snd_printk("Mixer reg %02x was %02x, set to %02x, now is %02x\n", reg, old, expected, new);
313#endif
314 return expected == new;
315}
316
317
318static int snd_es18xx_reset(es18xx_t *chip)
319{
320 int i;
321 outb(0x03, chip->port + 0x06);
322 inb(chip->port + 0x06);
323 outb(0x00, chip->port + 0x06);
324 for(i = 0; i < MILLISECOND && !(inb(chip->port + 0x0E) & 0x80); i++);
325 if (inb(chip->port + 0x0A) != 0xAA)
326 return -1;
327 return 0;
328}
329
330static int snd_es18xx_reset_fifo(es18xx_t *chip)
331{
332 outb(0x02, chip->port + 0x06);
333 inb(chip->port + 0x06);
334 outb(0x00, chip->port + 0x06);
335 return 0;
336}
337
338#ifdef TARGET_OS2
339static ratnum_t new_clocks[2] = {
340 {
341/* num: */ 793800,
342/* den_min: */ 1,
343/* den_max: */ 128,
344/* den_step: */ 1,
345 },
346 {
347/* num: */ 768000,
348/* den_min: */ 1,
349/* den_max: */ 128,
350/* den_step: */ 1,
351 }
352};
353
354static snd_pcm_hw_constraint_ratnums_t new_hw_constraints_clocks = {
355/* nrats: */ 2,
356/* rats: */ new_clocks,
357};
358
359static ratnum_t old_clocks[2] = {
360 {
361/* num: */ 795444,
362/* den_min: */ 1,
363/* den_max: */ 128,
364/* den_step: */ 1,
365 },
366 {
367/* num: */ 397722,
368/* den_min: */ 1,
369/* den_max: */ 128,
370/* den_step: */ 1,
371 }
372};
373
374static snd_pcm_hw_constraint_ratnums_t old_hw_constraints_clocks = {
375/* nrats: */ 2,
376/* rats: */ old_clocks,
377};
378#else
379static ratnum_t new_clocks[2] = {
380 {
381 num: 793800,
382 den_min: 1,
383 den_max: 128,
384 den_step: 1,
385 },
386 {
387 num: 768000,
388 den_min: 1,
389 den_max: 128,
390 den_step: 1,
391 }
392};
393
394static snd_pcm_hw_constraint_ratnums_t new_hw_constraints_clocks = {
395 nrats: 2,
396 rats: new_clocks,
397};
398
399static ratnum_t old_clocks[2] = {
400 {
401 num: 795444,
402 den_min: 1,
403 den_max: 128,
404 den_step: 1,
405 },
406 {
407 num: 397722,
408 den_min: 1,
409 den_max: 128,
410 den_step: 1,
411 }
412};
413
414static snd_pcm_hw_constraint_ratnums_t old_hw_constraints_clocks = {
415 nrats: 2,
416 rats: old_clocks,
417};
418#endif
419
420static void snd_es18xx_rate_set(es18xx_t *chip,
421 snd_pcm_substream_t *substream,
422 int mode)
423{
424 unsigned int bits, div0;
425 snd_pcm_runtime_t *runtime = substream->runtime;
426 if (chip->caps & ES18XX_NEW_RATE) {
427 if (runtime->rate_num == new_clocks[0].num)
428 bits = 128 - runtime->rate_den;
429 else
430 bits = 256 - runtime->rate_den;
431 } else {
432 if (runtime->rate_num == old_clocks[0].num)
433 bits = 256 - runtime->rate_den;
434 else
435 bits = 128 - runtime->rate_den;
436 }
437
438 /* set filter register */
439 div0 = 256 - 7160000*20/(8*82*runtime->rate);
440
441 if ((chip->caps & ES18XX_PCM2) && mode == DAC2) {
442 snd_es18xx_mixer_write(chip, 0x70, bits);
443 snd_es18xx_mixer_write(chip, 0x72, div0);
444 } else {
445 snd_es18xx_write(chip, 0xA1, bits);
446 snd_es18xx_write(chip, 0xA2, div0);
447 }
448}
449
450static int snd_es18xx_playback_hw_params(snd_pcm_substream_t * substream,
451 snd_pcm_hw_params_t * hw_params)
452{
453 es18xx_t *chip = snd_pcm_substream_chip(substream);
454 int shift, err;
455
456 shift = 0;
457 if (params_channels(hw_params) == 2)
458 shift++;
459 if (snd_pcm_format_width(params_format(hw_params)) == 16)
460 shift++;
461
462 switch (substream->number) {
463 case 0:
464 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
465 (chip->capture_a_substream) &&
466 params_channels(hw_params) != 1) {
467 _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS);
468 return -EBUSY;
469 }
470 chip->dma2_shift = shift;
471 break;
472 case 1:
473 chip->dma1_shift = shift;
474 break;
475 }
476 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
477 return err;
478 return 0;
479}
480
481static int snd_es18xx_playback1_prepare(es18xx_t *chip,
482 snd_pcm_substream_t *substream)
483{
484 snd_pcm_runtime_t *runtime = substream->runtime;
485 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
486 unsigned int count = snd_pcm_lib_period_bytes(substream);
487
488 chip->dma2_size = size;
489
490 snd_es18xx_rate_set(chip, substream, DAC2);
491
492 /* Transfer Count Reload */
493 count = 0x10000 - count;
494 snd_es18xx_mixer_write(chip, 0x74, count & 0xff);
495 snd_es18xx_mixer_write(chip, 0x76, count >> 8);
496
497 /* Set format */
498 snd_es18xx_mixer_bits(chip, 0x7A, 0x07,
499 ((runtime->channels == 1) ? 0x00 : 0x02) |
500 (snd_pcm_format_width(runtime->format) == 16 ? 0x01 : 0x00) |
501 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x04));
502
503 /* Set DMA controller */
504 snd_dma_program(chip->dma2, runtime->dma_area, size, DMA_MODE_WRITE | DMA_AUTOINIT);
505
506 return 0;
507}
508
509static int snd_es18xx_playback1_trigger(es18xx_t *chip,
510 snd_pcm_substream_t * substream,
511 int cmd)
512{
513 if (cmd == SNDRV_PCM_TRIGGER_START) {
514 if (chip->active & DAC2)
515 return 0;
516 chip->active |= DAC2;
517 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
518 if (!(chip->active & DAC2))
519 return 0;
520 chip->active &= ~DAC2;
521 } else {
522 return -EINVAL;
523 }
524
525 if (cmd == SNDRV_PCM_TRIGGER_START) {
526 /* Start DMA */
527 if (chip->dma2 >= 4)
528 snd_es18xx_mixer_write(chip, 0x78, 0xb3);
529 else
530 snd_es18xx_mixer_write(chip, 0x78, 0x93);
531#ifdef AVOID_POPS
532 /* Avoid pops */
533 udelay(100000);
534 if (chip->caps & ES18XX_PCM2)
535 /* Restore Audio 2 volume */
536 snd_es18xx_mixer_write(chip, 0x7C, chip->audio2_vol);
537 else
538 /* Enable PCM output */
539 snd_es18xx_dsp_command(chip, 0xD1);
540#endif
541 }
542 else {
543 /* Stop DMA */
544 snd_es18xx_mixer_write(chip, 0x78, 0x00);
545#ifdef AVOID_POPS
546 udelay(25000);
547 if (chip->caps & ES18XX_PCM2)
548 /* Set Audio 2 volume to 0 */
549 snd_es18xx_mixer_write(chip, 0x7C, 0);
550 else
551 /* Disable PCM output */
552 snd_es18xx_dsp_command(chip, 0xD3);
553#endif
554 }
555
556 return 0;
557}
558
559static int snd_es18xx_capture_hw_params(snd_pcm_substream_t * substream,
560 snd_pcm_hw_params_t * hw_params)
561{
562 es18xx_t *chip = snd_pcm_substream_chip(substream);
563 int shift, err;
564
565 shift = 0;
566 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
567 chip->playback_a_substream &&
568 params_channels(hw_params) != 1) {
569 _snd_pcm_hw_param_setempty(hw_params, SNDRV_PCM_HW_PARAM_CHANNELS);
570 return -EBUSY;
571 }
572 if (params_channels(hw_params) == 2)
573 shift++;
574 if (snd_pcm_format_width(params_format(hw_params)) == 16)
575 shift++;
576 chip->dma1_shift = shift;
577 if ((err = snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(hw_params))) < 0)
578 return err;
579 return 0;
580}
581
582static int snd_es18xx_capture_prepare(snd_pcm_substream_t *substream)
583{
584 es18xx_t *chip = snd_pcm_substream_chip(substream);
585 snd_pcm_runtime_t *runtime = substream->runtime;
586 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
587 unsigned int count = snd_pcm_lib_period_bytes(substream);
588
589 chip->dma1_size = size;
590
591 snd_es18xx_reset_fifo(chip);
592
593 /* Set stereo/mono */
594 snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01);
595
596 snd_es18xx_rate_set(chip, substream, ADC1);
597
598 /* Transfer Count Reload */
599 count = 0x10000 - count;
600 snd_es18xx_write(chip, 0xA4, count & 0xff);
601 snd_es18xx_write(chip, 0xA5, count >> 8);
602
603#ifdef AVOID_POPS
604 udelay(100000);
605#endif
606
607 /* Set format */
608 snd_es18xx_write(chip, 0xB7,
609 snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71);
610 snd_es18xx_write(chip, 0xB7, 0x90 |
611 ((runtime->channels == 1) ? 0x40 : 0x08) |
612 (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
613 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
614
615 /* Set DMA controler */
616 snd_dma_program(chip->dma1, runtime->dma_area, size, DMA_MODE_READ | DMA_AUTOINIT);
617
618 return 0;
619}
620
621static int snd_es18xx_capture_trigger(snd_pcm_substream_t *substream,
622 int cmd)
623{
624 es18xx_t *chip = snd_pcm_substream_chip(substream);
625
626 if (cmd == SNDRV_PCM_TRIGGER_START) {
627 if (chip->active & ADC1)
628 return 0;
629 chip->active |= ADC1;
630 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
631 if (!(chip->active & ADC1))
632 return 0;
633 chip->active &= ~ADC1;
634 } else {
635 return -EINVAL;
636 }
637
638 if (cmd == SNDRV_PCM_TRIGGER_START)
639 /* Start DMA */
640 snd_es18xx_write(chip, 0xB8, 0x0f);
641 else
642 /* Stop DMA */
643 snd_es18xx_write(chip, 0xB8, 0x00);
644 return 0;
645}
646
647static int snd_es18xx_playback2_prepare(es18xx_t *chip,
648 snd_pcm_substream_t *substream)
649{
650 snd_pcm_runtime_t *runtime = substream->runtime;
651 unsigned int size = snd_pcm_lib_buffer_bytes(substream);
652 unsigned int count = snd_pcm_lib_period_bytes(substream);
653
654 chip->dma1_size = size;
655
656 snd_es18xx_reset_fifo(chip);
657
658 /* Set stereo/mono */
659 snd_es18xx_bits(chip, 0xA8, 0x03, runtime->channels == 1 ? 0x02 : 0x01);
660
661 snd_es18xx_rate_set(chip, substream, DAC1);
662
663 /* Transfer Count Reload */
664 count = 0x10000 - count;
665 snd_es18xx_write(chip, 0xA4, count & 0xff);
666 snd_es18xx_write(chip, 0xA5, count >> 8);
667
668 /* Set format */
669 snd_es18xx_write(chip, 0xB6,
670 snd_pcm_format_unsigned(runtime->format) ? 0x80 : 0x00);
671 snd_es18xx_write(chip, 0xB7,
672 snd_pcm_format_unsigned(runtime->format) ? 0x51 : 0x71);
673 snd_es18xx_write(chip, 0xB7, 0x90 |
674 (runtime->channels == 1 ? 0x40 : 0x08) |
675 (snd_pcm_format_width(runtime->format) == 16 ? 0x04 : 0x00) |
676 (snd_pcm_format_unsigned(runtime->format) ? 0x00 : 0x20));
677
678 /* Set DMA controler */
679 snd_dma_program(chip->dma1, runtime->dma_area, size, DMA_MODE_WRITE | DMA_AUTOINIT);
680
681 return 0;
682}
683
684static int snd_es18xx_playback2_trigger(es18xx_t *chip,
685 snd_pcm_substream_t *substream,
686 int cmd)
687{
688 if (cmd == SNDRV_PCM_TRIGGER_START) {
689 if (chip->active & DAC1)
690 return 0;
691 chip->active |= DAC1;
692 } else if (cmd == SNDRV_PCM_TRIGGER_STOP) {
693 if (!(chip->active & DAC1))
694 return 0;
695 chip->active &= ~DAC1;
696 } else {
697 return -EINVAL;
698 }
699
700 if (cmd == SNDRV_PCM_TRIGGER_START) {
701 /* Start DMA */
702 snd_es18xx_write(chip, 0xB8, 0x05);
703#ifdef AVOID_POPS
704 /* Avoid pops */
705 udelay(100000);
706 /* Enable Audio 1 */
707 snd_es18xx_dsp_command(chip, 0xD1);
708#endif
709 }
710 else {
711 /* Stop DMA */
712 snd_es18xx_write(chip, 0xB8, 0x00);
713#ifdef AVOID_POPS
714 /* Avoid pops */
715 udelay(25000);
716 /* Disable Audio 1 */
717 snd_es18xx_dsp_command(chip, 0xD3);
718#endif
719 }
720 return 0;
721}
722
723static int snd_es18xx_playback_prepare(snd_pcm_substream_t *substream)
724{
725 es18xx_t *chip = snd_pcm_substream_chip(substream);
726 switch (substream->number) {
727 case 0:
728 return snd_es18xx_playback1_prepare(chip, substream);
729 case 1:
730 return snd_es18xx_playback2_prepare(chip, substream);
731 }
732 return -EINVAL;
733}
734
735static int snd_es18xx_playback_trigger(snd_pcm_substream_t *substream,
736 int cmd)
737{
738 es18xx_t *chip = snd_pcm_substream_chip(substream);
739 switch (substream->number) {
740 case 0:
741 return snd_es18xx_playback1_trigger(chip, substream, cmd);
742 case 1:
743 return snd_es18xx_playback2_trigger(chip, substream, cmd);
744 }
745 return -EINVAL;
746}
747
748static void snd_es18xx_interrupt(int irq, void *dev_id, struct pt_regs *regs)
749{
750 es18xx_t *chip = snd_magic_cast(es18xx_t, dev_id, return);
751 unsigned char status;
752
753
754 if (chip->caps & ES18XX_CONTROL) {
755 /* Read Interrupt status */
756 status = inb(chip->ctrl_port + 6);
757 } else {
758 /* Read Interrupt status */
759 status = snd_es18xx_mixer_read(chip, 0x7f) >> 4;
760 }
761#if 0
762 else {
763 status = 0;
764 if (inb(chip->port + 0x0C) & 0x01)
765 status |= AUDIO1_IRQ;
766 if (snd_es18xx_mixer_read(chip, 0x7A) & 0x80)
767 status |= AUDIO2_IRQ;
768 if ((chip->caps & ES18XX_HWV) &&
769 snd_es18xx_mixer_read(chip, 0x64) & 0x10)
770 status |= HWV_IRQ;
771 }
772#endif
773
774 /* Audio 1 & Audio 2 */
775 if (status & AUDIO2_IRQ) {
776 if (chip->active & DAC2)
777 snd_pcm_period_elapsed(chip->playback_a_substream);
778 /* ack interrupt */
779 snd_es18xx_mixer_bits(chip, 0x7A, 0x80, 0x00);
780 }
781 if (status & AUDIO1_IRQ) {
782 /* ok.. capture is active */
783 if (chip->active & ADC1)
784 snd_pcm_period_elapsed(chip->capture_a_substream);
785 /* ok.. playback2 is active */
786 else if (chip->active & DAC1)
787 snd_pcm_period_elapsed(chip->playback_b_substream);
788 /* ack interrupt */
789 inb(chip->port + 0x0E);
790 }
791
792 /* MPU */
793 if ((status & MPU_IRQ) && chip->rmidi)
794 snd_mpu401_uart_interrupt(irq, chip->rmidi->private_data, regs);
795
796 /* Hardware volume */
797 if (status & HWV_IRQ) {
798 int split = snd_es18xx_mixer_read(chip, 0x64) & 0x80;
799 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_switch->id);
800 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->hw_volume->id);
801 if (!split) {
802 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_switch->id);
803 snd_ctl_notify(chip->card, SNDRV_CTL_EVENT_MASK_VALUE, &chip->master_volume->id);
804 }
805 /* ack interrupt */
806 snd_es18xx_mixer_write(chip, 0x66, 0x00);
807 }
808
809}
810
811static snd_pcm_uframes_t snd_es18xx_playback_pointer(snd_pcm_substream_t * substream)
812{
813 es18xx_t *chip = snd_pcm_substream_chip(substream);
814 int pos;
815
816 switch (substream->number) {
817 case 0:
818 if (!(chip->active & DAC2))
819 return 0;
820 pos = chip->dma2_size - snd_dma_residue(chip->dma2);
821 return pos >> chip->dma2_shift;
822 case 1:
823 if (!(chip->active & DAC1))
824 return 0;
825 pos = chip->dma1_size - snd_dma_residue(chip->dma1);
826 return pos >> chip->dma1_shift;
827 }
828 return 0;
829}
830
831static snd_pcm_uframes_t snd_es18xx_capture_pointer(snd_pcm_substream_t * substream)
832{
833 es18xx_t *chip = snd_pcm_substream_chip(substream);
834 int pos;
835
836 if (!(chip->active & ADC1))
837 return 0;
838 pos = chip->dma1_size - snd_dma_residue(chip->dma1);
839 return pos >> chip->dma1_shift;
840}
841
842#ifdef TARGET_OS2
843static snd_pcm_hardware_t snd_es18xx_playback =
844{
845/* info: */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
846 SNDRV_PCM_INFO_MMAP_VALID),
847/* formats: */ (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
848 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
849/* rates: */ SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
850/* rate_min: */ 4000,
851/* rate_max: */ 48000,
852/* channels_min: */ 1,
853/* channels_max: */ 2,
854/* buffer_bytes_max: */ 65536,
855/* period_bytes_min: */ 64,
856/* period_bytes_max: */ 65536,
857/* periods_min: */ 1,
858/* periods_max: */ 1024,
859/* fifo_size: */ 0,
860};
861
862static snd_pcm_hardware_t snd_es18xx_capture =
863{
864/* info: */ (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
865 SNDRV_PCM_INFO_MMAP_VALID),
866/* formats: */ (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
867 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
868/* rates: */ SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
869/* rate_min: */ 4000,
870/* rate_max: */ 48000,
871/* channels_min: */ 1,
872/* channels_max: */ 2,
873/* buffer_bytes_max: */ 65536,
874/* period_bytes_min: */ 64,
875/* period_bytes_max: */ 65536,
876/* periods_min: */ 1,
877/* periods_max: */ 1024,
878/* fifo_size: */ 0,
879};
880#else
881static snd_pcm_hardware_t snd_es18xx_playback =
882{
883 info: (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
884 SNDRV_PCM_INFO_MMAP_VALID),
885 formats: (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
886 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
887 rates: SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
888 rate_min: 4000,
889 rate_max: 48000,
890 channels_min: 1,
891 channels_max: 2,
892 buffer_bytes_max: 65536,
893 period_bytes_min: 64,
894 period_bytes_max: 65536,
895 periods_min: 1,
896 periods_max: 1024,
897 fifo_size: 0,
898};
899
900static snd_pcm_hardware_t snd_es18xx_capture =
901{
902 info: (SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_INTERLEAVED |
903 SNDRV_PCM_INFO_MMAP_VALID),
904 formats: (SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S8 |
905 SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_U16_LE),
906 rates: SNDRV_PCM_RATE_CONTINUOUS | SNDRV_PCM_RATE_8000_48000,
907 rate_min: 4000,
908 rate_max: 48000,
909 channels_min: 1,
910 channels_max: 2,
911 buffer_bytes_max: 65536,
912 period_bytes_min: 64,
913 period_bytes_max: 65536,
914 periods_min: 1,
915 periods_max: 1024,
916 fifo_size: 0,
917};
918#endif
919
920static int snd_es18xx_playback_open(snd_pcm_substream_t * substream)
921{
922 snd_pcm_runtime_t *runtime = substream->runtime;
923 es18xx_t *chip = snd_pcm_substream_chip(substream);
924
925 switch (substream->number) {
926 case 0:
927 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
928 chip->capture_a_substream &&
929 chip->capture_a_substream->runtime->channels != 1)
930 return -EAGAIN;
931 chip->playback_a_substream = substream;
932 break;
933 case 1:
934 if (chip->capture_a_substream)
935 return -EAGAIN;
936 chip->playback_b_substream = substream;
937 break;
938 default:
939 snd_BUG();
940 return -EINVAL;
941 }
942 substream->runtime->hw = snd_es18xx_playback;
943 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
944 (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks);
945 return 0;
946}
947
948static int snd_es18xx_capture_open(snd_pcm_substream_t * substream)
949{
950 snd_pcm_runtime_t *runtime = substream->runtime;
951 es18xx_t *chip = snd_pcm_substream_chip(substream);
952
953 if (chip->playback_b_substream)
954 return -EAGAIN;
955 if ((chip->caps & ES18XX_DUPLEX_MONO) &&
956 chip->playback_a_substream &&
957 chip->playback_a_substream->runtime->channels != 1)
958 return -EAGAIN;
959 chip->capture_a_substream = substream;
960 substream->runtime->hw = snd_es18xx_capture;
961 snd_pcm_hw_constraint_ratnums(runtime, 0, SNDRV_PCM_HW_PARAM_RATE,
962 (chip->caps & ES18XX_NEW_RATE) ? &new_hw_constraints_clocks : &old_hw_constraints_clocks);
963 return 0;
964}
965
966static int snd_es18xx_playback_close(snd_pcm_substream_t * substream)
967{
968 es18xx_t *chip = snd_pcm_substream_chip(substream);
969
970 switch (substream->number) {
971 case 0:
972 chip->playback_a_substream = NULL;
973 break;
974 case 1:
975 chip->playback_b_substream = NULL;
976 break;
977 default:
978 snd_BUG();
979 return -EINVAL;
980 }
981
982 snd_pcm_lib_free_pages(substream);
983 return 0;
984}
985
986static int snd_es18xx_capture_close(snd_pcm_substream_t * substream)
987{
988 es18xx_t *chip = snd_pcm_substream_chip(substream);
989
990 chip->capture_a_substream = NULL;
991 snd_pcm_lib_free_pages(substream);
992 return 0;
993}
994
995/*
996 * MIXER part
997 */
998
999static int snd_es18xx_info_mux(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1000{
1001 static char *texts[8] = {
1002 "Mic", "Mic Master", "CD", "AOUT",
1003 "Mic1", "Mix", "Line", "Master"
1004 };
1005
1006 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1007 uinfo->count = 1;
1008 uinfo->value.enumerated.items = 8;
1009 if (uinfo->value.enumerated.item > 7)
1010 uinfo->value.enumerated.item = 7;
1011 strcpy(uinfo->value.enumerated.name, texts[uinfo->value.enumerated.item]);
1012 return 0;
1013}
1014
1015static int snd_es18xx_get_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1016{
1017 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1018 ucontrol->value.enumerated.item[0] = snd_es18xx_mixer_read(chip, 0x1c) & 0x07;
1019 return 0;
1020}
1021
1022static int snd_es18xx_put_mux(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1023{
1024 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1025 unsigned char val = ucontrol->value.enumerated.item[0];
1026
1027 if (val > 7)
1028 return -EINVAL;
1029 return snd_es18xx_mixer_bits(chip, 0x1c, 0x07, val) != val;
1030}
1031
1032static int snd_es18xx_info_spatializer_enable(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1033{
1034 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1035 uinfo->count = 1;
1036 uinfo->value.integer.min = 0;
1037 uinfo->value.integer.max = 1;
1038 return 0;
1039}
1040
1041static int snd_es18xx_get_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1042{
1043 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1044 unsigned char val = snd_es18xx_mixer_read(chip, 0x50);
1045 ucontrol->value.integer.value[0] = !!(val & 8);
1046 return 0;
1047}
1048
1049static int snd_es18xx_put_spatializer_enable(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1050{
1051 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1052 unsigned char oval, nval;
1053 int change;
1054 nval = ucontrol->value.integer.value[0] ? 0x0c : 0x04;
1055 oval = snd_es18xx_mixer_read(chip, 0x50) & 0x0c;
1056 change = nval != oval;
1057 if (change) {
1058 snd_es18xx_mixer_write(chip, 0x50, nval & ~0x04);
1059 snd_es18xx_mixer_write(chip, 0x50, nval);
1060 }
1061 return change;
1062}
1063
1064static int snd_es18xx_info_hw_volume(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1065{
1066 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
1067 uinfo->count = 2;
1068 uinfo->value.integer.min = 0;
1069 uinfo->value.integer.max = 63;
1070 return 0;
1071}
1072
1073static int snd_es18xx_get_hw_volume(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1074{
1075 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1076 ucontrol->value.integer.value[0] = snd_es18xx_mixer_read(chip, 0x61) & 0x3f;
1077 ucontrol->value.integer.value[1] = snd_es18xx_mixer_read(chip, 0x63) & 0x3f;
1078 return 0;
1079}
1080
1081static int snd_es18xx_info_hw_switch(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1082{
1083 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
1084 uinfo->count = 2;
1085 uinfo->value.integer.min = 0;
1086 uinfo->value.integer.max = 1;
1087 return 0;
1088}
1089
1090static int snd_es18xx_get_hw_switch(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1091{
1092 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1093 ucontrol->value.integer.value[0] = !(snd_es18xx_mixer_read(chip, 0x61) & 0x40);
1094 ucontrol->value.integer.value[1] = !(snd_es18xx_mixer_read(chip, 0x63) & 0x40);
1095 return 0;
1096}
1097
1098static void snd_es18xx_hwv_free(snd_kcontrol_t *kcontrol)
1099{
1100 es18xx_t *chip = snd_magic_cast(es18xx_t, _snd_kcontrol_chip(kcontrol), return);
1101 chip->master_volume = NULL;
1102 chip->master_switch = NULL;
1103 chip->hw_volume = NULL;
1104 chip->hw_switch = NULL;
1105}
1106
1107static int snd_es18xx_reg_bits(es18xx_t *chip, unsigned char reg,
1108 unsigned char mask, unsigned char val)
1109{
1110 if (reg < 0xa0)
1111 return snd_es18xx_mixer_bits(chip, reg, mask, val);
1112 else
1113 return snd_es18xx_bits(chip, reg, mask, val);
1114}
1115
1116static int snd_es18xx_reg_read(es18xx_t *chip, unsigned char reg)
1117{
1118 if (reg < 0xa0)
1119 return snd_es18xx_mixer_read(chip, reg);
1120 else
1121 return snd_es18xx_read(chip, reg);
1122}
1123
1124#ifdef TARGET_OS2
1125#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \
1126{ SNDRV_CTL_ELEM_IFACE_MIXER, 0, 0, xname, xindex, \
1127 0, 0, snd_es18xx_info_single, \
1128 snd_es18xx_get_single, snd_es18xx_put_single, \
1129 reg | (shift << 8) | (mask << 16) | (invert << 24) }
1130#else
1131#define ES18XX_SINGLE(xname, xindex, reg, shift, mask, invert) \
1132{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, index: xindex, \
1133 info: snd_es18xx_info_single, \
1134 get: snd_es18xx_get_single, put: snd_es18xx_put_single, \
1135 private_value: reg | (shift << 8) | (mask << 16) | (invert << 24) }
1136#endif
1137
1138static int snd_es18xx_info_single(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1139{
1140 int mask = (kcontrol->private_value >> 16) & 0xff;
1141
1142 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1143 uinfo->count = 1;
1144 uinfo->value.integer.min = 0;
1145 uinfo->value.integer.max = mask;
1146 return 0;
1147}
1148
1149static int snd_es18xx_get_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1150{
1151 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1152 int reg = kcontrol->private_value & 0xff;
1153 int shift = (kcontrol->private_value >> 8) & 0xff;
1154 int mask = (kcontrol->private_value >> 16) & 0xff;
1155 int invert = (kcontrol->private_value >> 24) & 0xff;
1156 int val;
1157
1158 val = snd_es18xx_reg_read(chip, reg);
1159 ucontrol->value.integer.value[0] = (val >> shift) & mask;
1160 if (invert)
1161 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1162 return 0;
1163}
1164
1165static int snd_es18xx_put_single(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1166{
1167 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1168 int reg = kcontrol->private_value & 0xff;
1169 int shift = (kcontrol->private_value >> 8) & 0xff;
1170 int mask = (kcontrol->private_value >> 16) & 0xff;
1171 int invert = (kcontrol->private_value >> 24) & 0xff;
1172 unsigned char val;
1173
1174 val = (ucontrol->value.integer.value[0] & mask);
1175 if (invert)
1176 val = mask - val;
1177 mask <<= shift;
1178 val <<= shift;
1179 return snd_es18xx_reg_bits(chip, reg, mask, val) != val;
1180}
1181
1182#ifdef TARGET_OS2
1183#define ES18XX_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1184{ SNDRV_CTL_ELEM_IFACE_MIXER, 0, 0, xname, xindex, \
1185 0, 0, snd_es18xx_info_double, \
1186 snd_es18xx_get_double, snd_es18xx_put_double, \
1187 left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1188#else
1189#define ES18XX_DOUBLE(xname, xindex, left_reg, right_reg, shift_left, shift_right, mask, invert) \
1190{ iface: SNDRV_CTL_ELEM_IFACE_MIXER, name: xname, index: xindex, \
1191 info: snd_es18xx_info_double, \
1192 get: snd_es18xx_get_double, put: snd_es18xx_put_double, \
1193 private_value: left_reg | (right_reg << 8) | (shift_left << 16) | (shift_right << 19) | (mask << 24) | (invert << 22) }
1194#endif
1195
1196static int snd_es18xx_info_double(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t * uinfo)
1197{
1198 int mask = (kcontrol->private_value >> 24) & 0xff;
1199
1200 uinfo->type = mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER;
1201 uinfo->count = 2;
1202 uinfo->value.integer.min = 0;
1203 uinfo->value.integer.max = mask;
1204 return 0;
1205}
1206
1207static int snd_es18xx_get_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1208{
1209 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1210 int left_reg = kcontrol->private_value & 0xff;
1211 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1212 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1213 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1214 int mask = (kcontrol->private_value >> 24) & 0xff;
1215 int invert = (kcontrol->private_value >> 22) & 1;
1216 unsigned char left, right;
1217
1218 left = snd_es18xx_reg_read(chip, left_reg);
1219 if (left_reg != right_reg)
1220 right = snd_es18xx_reg_read(chip, right_reg);
1221 else
1222 right = left;
1223 ucontrol->value.integer.value[0] = (left >> shift_left) & mask;
1224 ucontrol->value.integer.value[1] = (right >> shift_right) & mask;
1225 if (invert) {
1226 ucontrol->value.integer.value[0] = mask - ucontrol->value.integer.value[0];
1227 ucontrol->value.integer.value[1] = mask - ucontrol->value.integer.value[1];
1228 }
1229 return 0;
1230}
1231
1232static int snd_es18xx_put_double(snd_kcontrol_t * kcontrol, snd_ctl_elem_value_t * ucontrol)
1233{
1234 es18xx_t *chip = snd_kcontrol_chip(kcontrol);
1235 int left_reg = kcontrol->private_value & 0xff;
1236 int right_reg = (kcontrol->private_value >> 8) & 0xff;
1237 int shift_left = (kcontrol->private_value >> 16) & 0x07;
1238 int shift_right = (kcontrol->private_value >> 19) & 0x07;
1239 int mask = (kcontrol->private_value >> 24) & 0xff;
1240 int invert = (kcontrol->private_value >> 22) & 1;
1241 int change;
1242 unsigned char val1, val2, mask1, mask2;
1243
1244 val1 = ucontrol->value.integer.value[0] & mask;
1245 val2 = ucontrol->value.integer.value[1] & mask;
1246 if (invert) {
1247 val1 = mask - val1;
1248 val2 = mask - val2;
1249 }
1250 val1 <<= shift_left;
1251 val2 <<= shift_right;
1252 mask1 = mask << shift_left;
1253 mask2 = mask << shift_right;
1254 if (left_reg != right_reg) {
1255 change = 0;
1256 if (snd_es18xx_reg_bits(chip, left_reg, mask1, val1) != val1)
1257 change = 1;
1258 if (snd_es18xx_reg_bits(chip, right_reg, mask2, val2) != val2)
1259 change = 1;
1260 } else {
1261 change = (snd_es18xx_reg_bits(chip, left_reg, mask1 | mask2,
1262 val1 | val2) != (val1 | val2));
1263 }
1264 return change;
1265}
1266
1267static snd_kcontrol_new_t snd_es18xx_base_controls[] = {
1268ES18XX_DOUBLE("Master Playback Volume", 0, 0x60, 0x62, 0, 0, 63, 0),
1269ES18XX_DOUBLE("Master Playback Switch", 0, 0x60, 0x62, 6, 6, 1, 1),
1270ES18XX_DOUBLE("Line Playback Volume", 0, 0x3e, 0x3e, 4, 0, 15, 0),
1271ES18XX_DOUBLE("CD Playback Volume", 0, 0x38, 0x38, 4, 0, 15, 0),
1272ES18XX_DOUBLE("FM Playback Volume", 0, 0x36, 0x36, 4, 0, 15, 0),
1273ES18XX_DOUBLE("Mono Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0),
1274ES18XX_DOUBLE("Mic Playback Volume", 0, 0x1a, 0x1a, 4, 0, 15, 0),
1275ES18XX_DOUBLE("Aux Playback Volume", 0, 0x3a, 0x3a, 4, 0, 15, 0),
1276ES18XX_SINGLE("PC Speaker Playback Volume", 0, 0x3c, 0, 7, 0),
1277ES18XX_SINGLE("Record Monitor", 0, 0xa8, 3, 1, 0),
1278ES18XX_DOUBLE("Capture Volume", 0, 0xb4, 0xb4, 4, 0, 15, 0),
1279ES18XX_SINGLE("Capture Switch", 0, 0x1c, 4, 1, 1),
1280{
1281#ifdef TARGET_OS2
1282 SNDRV_CTL_ELEM_IFACE_MIXER,
1283 0,0,
1284 "Capture Source", 0, 0, 0,
1285 snd_es18xx_info_mux,
1286 snd_es18xx_get_mux,
1287 snd_es18xx_put_mux, 0
1288#else
1289 iface: SNDRV_CTL_ELEM_IFACE_MIXER,
1290 name: "Capture Source",
1291 info: snd_es18xx_info_mux,
1292 get: snd_es18xx_get_mux,
1293 put: snd_es18xx_put_mux,
1294#endif
1295}
1296};
1297
1298static snd_kcontrol_new_t snd_es18xx_mono_in_control =
1299ES18XX_DOUBLE("Mono Input Playback Volume", 0, 0x6d, 0x6d, 4, 0, 15, 0);
1300
1301static snd_kcontrol_new_t snd_es18xx_recmix_controls[] = {
1302ES18XX_DOUBLE("PCM Capture Volume", 0, 0x69, 0x69, 4, 0, 15, 0),
1303ES18XX_DOUBLE("Mic Capture Volume", 0, 0x68, 0x68, 4, 0, 15, 0),
1304ES18XX_DOUBLE("Line Capture Volume", 0, 0x6e, 0x6e, 4, 0, 15, 0),
1305ES18XX_DOUBLE("FM Capture Volume", 0, 0x6b, 0x6b, 4, 0, 15, 0),
1306ES18XX_DOUBLE("Mono Capture Volume", 0, 0x6f, 0x6f, 4, 0, 15, 0),
1307ES18XX_DOUBLE("CD Capture Volume", 0, 0x6a, 0x6a, 4, 0, 15, 0),
1308ES18XX_DOUBLE("Aux Capture Volume", 0, 0x6c, 0x6c, 4, 0, 15, 0)
1309};
1310
1311static snd_kcontrol_new_t snd_es18xx_pcm1_controls[] = {
1312ES18XX_DOUBLE("PCM Playback Volume", 0, 0x14, 0x14, 4, 0, 15, 0),
1313};
1314
1315static snd_kcontrol_new_t snd_es18xx_pcm2_controls[] = {
1316ES18XX_DOUBLE("PCM Playback Volume", 0, 0x7c, 0x7c, 4, 0, 15, 0),
1317ES18XX_DOUBLE("PCM Playback Volume", 1, 0x14, 0x14, 4, 0, 15, 0)
1318};
1319
1320static snd_kcontrol_new_t snd_es18xx_spatializer_controls[] = {
1321ES18XX_SINGLE("3D Control - Level", 0, 0x52, 0, 63, 0),
1322{
1323#ifdef TARGET_OS2
1324 SNDRV_CTL_ELEM_IFACE_MIXER,
1325 0,0,
1326 "3D Control - Switch", 0, 0, 0,
1327 snd_es18xx_info_spatializer_enable,
1328 snd_es18xx_get_spatializer_enable,
1329 snd_es18xx_put_spatializer_enable,
1330#else
1331 iface: SNDRV_CTL_ELEM_IFACE_MIXER,
1332 name: "3D Control - Switch",
1333 info: snd_es18xx_info_spatializer_enable,
1334 get: snd_es18xx_get_spatializer_enable,
1335 put: snd_es18xx_put_spatializer_enable,
1336#endif
1337}
1338};
1339
1340static snd_kcontrol_new_t snd_es18xx_micpre1_control =
1341ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0xa9, 2, 1, 0);
1342
1343static snd_kcontrol_new_t snd_es18xx_micpre2_control =
1344ES18XX_SINGLE("Mic Boost (+26dB)", 0, 0x7d, 3, 1, 0);
1345
1346static snd_kcontrol_new_t snd_es18xx_hw_volume_controls[] = {
1347#ifdef TARGET_OS2
1348{
1349 SNDRV_CTL_ELEM_IFACE_MIXER, 0, 0,
1350 "Hardware Master Playback Volume",0,
1351 SNDRV_CTL_ELEM_ACCESS_READ, 0,
1352 snd_es18xx_info_hw_volume,
1353 snd_es18xx_get_hw_volume,0, 0
1354},
1355{
1356 SNDRV_CTL_ELEM_IFACE_MIXER, 0, 0,
1357 "Hardware Master Playback Switch",0,
1358 SNDRV_CTL_ELEM_ACCESS_READ, 0,
1359 snd_es18xx_info_hw_switch,
1360 snd_es18xx_get_hw_switch,0, 0
1361},
1362#else
1363{
1364 iface: SNDRV_CTL_ELEM_IFACE_MIXER,
1365 name: "Hardware Master Playback Volume",
1366 access: SNDRV_CTL_ELEM_ACCESS_READ,
1367 info: snd_es18xx_info_hw_volume,
1368 get: snd_es18xx_get_hw_volume,
1369},
1370{
1371 iface: SNDRV_CTL_ELEM_IFACE_MIXER,
1372 name: "Hardware Master Playback Switch",
1373 access: SNDRV_CTL_ELEM_ACCESS_READ,
1374 info: snd_es18xx_info_hw_switch,
1375 get: snd_es18xx_get_hw_switch,
1376},
1377#endif
1378ES18XX_SINGLE("Hardware Master Volume Split", 0, 0x64, 7, 1, 0),
1379};
1380
1381#if 0
1382static int __init snd_es18xx_config_read(es18xx_t *chip, unsigned char reg)
1383{
1384 int data;
1385 unsigned long flags;
1386 spin_lock_irqsave(&chip->ctrl_lock, flags);
1387 outb(reg, chip->ctrl_port);
1388 data = inb(chip->ctrl_port + 1);
1389 spin_unlock_irqrestore(&chip->ctrl_lock, flags);
1390 return data;
1391}
1392#endif
1393
1394static void __init snd_es18xx_config_write(es18xx_t *chip,
1395 unsigned char reg, unsigned char data)
1396{
1397 /* No need for spinlocks, this function is used only in
1398 otherwise protected init code */
1399 outb(reg, chip->ctrl_port);
1400 outb(data, chip->ctrl_port + 1);
1401#ifdef REG_DEBUG
1402 snd_printk("Config reg %02x set to %02x\n", reg, data);
1403#endif
1404}
1405
1406static int __init snd_es18xx_initialize(es18xx_t *chip)
1407{
1408 int mask = 0;
1409
1410 /* enable extended mode */
1411 snd_es18xx_dsp_command(chip, 0xC6);
1412 /* Reset mixer registers */
1413 snd_es18xx_mixer_write(chip, 0x00, 0x00);
1414
1415 /* Audio 1 DMA demand mode (4 bytes/request) */
1416 snd_es18xx_write(chip, 0xB9, 2);
1417 if (chip->caps & ES18XX_CONTROL) {
1418 /* Hardware volume IRQ */
1419 snd_es18xx_config_write(chip, 0x27, chip->irq);
1420 if (chip->fm_port > SNDRV_AUTO_PORT) {
1421 /* FM I/O */
1422 snd_es18xx_config_write(chip, 0x62, chip->fm_port >> 8);
1423 snd_es18xx_config_write(chip, 0x63, chip->fm_port & 0xff);
1424 }
1425 if (chip->mpu_port > SNDRV_AUTO_PORT) {
1426 /* MPU-401 I/O */
1427 snd_es18xx_config_write(chip, 0x64, chip->mpu_port >> 8);
1428 snd_es18xx_config_write(chip, 0x65, chip->mpu_port & 0xff);
1429 /* MPU-401 IRQ */
1430 snd_es18xx_config_write(chip, 0x28, chip->irq);
1431 }
1432 /* Audio1 IRQ */
1433 snd_es18xx_config_write(chip, 0x70, chip->irq);
1434 /* Audio2 IRQ */
1435 snd_es18xx_config_write(chip, 0x72, chip->irq);
1436 /* Audio1 DMA */
1437 snd_es18xx_config_write(chip, 0x74, chip->dma1);
1438 /* Audio2 DMA */
1439 snd_es18xx_config_write(chip, 0x75, chip->dma2);
1440
1441 /* Enable Audio 1 IRQ */
1442 snd_es18xx_write(chip, 0xB1, 0x50);
1443 /* Enable Audio 2 IRQ */
1444 snd_es18xx_mixer_write(chip, 0x7A, 0x40);
1445 /* Enable Audio 1 DMA */
1446 snd_es18xx_write(chip, 0xB2, 0x50);
1447 /* Enable MPU and hardware volume interrupt */
1448 snd_es18xx_mixer_write(chip, 0x64, 0x42);
1449 }
1450 else {
1451 int irqmask, dma1mask, dma2mask;
1452 switch (chip->irq) {
1453 case 2:
1454 case 9:
1455 irqmask = 0;
1456 break;
1457 case 5:
1458 irqmask = 1;
1459 break;
1460 case 7:
1461 irqmask = 2;
1462 break;
1463 case 10:
1464 irqmask = 3;
1465 break;
1466 default:
1467 snd_printk("invalid irq %d\n", chip->irq);
1468 return -ENODEV;
1469 }
1470 switch (chip->dma1) {
1471 case 0:
1472 dma1mask = 1;
1473 break;
1474 case 1:
1475 dma1mask = 2;
1476 break;
1477 case 3:
1478 dma1mask = 3;
1479 break;
1480 default:
1481 snd_printk("invalid dma1 %d\n", chip->dma1);
1482 return -ENODEV;
1483 }
1484 switch (chip->dma2) {
1485 case 0:
1486 dma2mask = 0;
1487 break;
1488 case 1:
1489 dma2mask = 1;
1490 break;
1491 case 3:
1492 dma2mask = 2;
1493 break;
1494 case 5:
1495 dma2mask = 3;
1496 break;
1497 default:
1498 snd_printk("invalid dma2 %d\n", chip->dma2);
1499 return -ENODEV;
1500 }
1501
1502 /* Enable and set Audio 1 IRQ */
1503 snd_es18xx_write(chip, 0xB1, 0x50 | (irqmask << 2));
1504 /* Enable and set Audio 1 DMA */
1505 snd_es18xx_write(chip, 0xB2, 0x50 | (dma1mask << 2));
1506 /* Set Audio 2 DMA */
1507 snd_es18xx_mixer_bits(chip, 0x7d, 0x07, 0x04 | dma2mask);
1508 /* Enable Audio 2 IRQ and DMA
1509 Set capture mixer input */
1510 snd_es18xx_mixer_write(chip, 0x7A, 0x68);
1511 /* Enable and set hardware volume interrupt */
1512 snd_es18xx_mixer_write(chip, 0x64, 0x06);
1513 if (chip->mpu_port > SNDRV_AUTO_PORT) {
1514 /* MPU401 share irq with audio
1515 Joystick enabled
1516 FM enabled */
1517 snd_es18xx_mixer_write(chip, 0x40, 0x43 | (chip->mpu_port & 0xf0) >> 1);
1518 }
1519 snd_es18xx_mixer_write(chip, 0x7f, ((irqmask + 1) << 1) | 0x01);
1520 }
1521 if (chip->caps & ES18XX_NEW_RATE) {
1522 /* Change behaviour of register A1
1523 4x oversampling
1524 2nd channel DAC asynchronous */
1525 snd_es18xx_mixer_write(chip, 0x71, 0x32);
1526 }
1527 if (!(chip->caps & ES18XX_PCM2)) {
1528 /* Enable DMA FIFO */
1529 snd_es18xx_write(chip, 0xB7, 0x80);
1530 }
1531 if (chip->caps & ES18XX_SPATIALIZER) {
1532 /* Set spatializer parameters to recommended values */
1533 snd_es18xx_mixer_write(chip, 0x54, 0x8f);
1534 snd_es18xx_mixer_write(chip, 0x56, 0x95);
1535 snd_es18xx_mixer_write(chip, 0x58, 0x94);
1536 snd_es18xx_mixer_write(chip, 0x5a, 0x80);
1537 }
1538 /* Mute input source */
1539 if (chip->caps & ES18XX_MUTEREC)
1540 mask = 0x10;
1541 if (chip->caps & ES18XX_RECMIX)
1542 snd_es18xx_mixer_write(chip, 0x1c, 0x05 | mask);
1543 else {
1544 snd_es18xx_mixer_write(chip, 0x1c, 0x00 | mask);
1545 snd_es18xx_write(chip, 0xb4, 0x00);
1546 }
1547#ifndef AVOID_POPS
1548 /* Enable PCM output */
1549 snd_es18xx_dsp_command(chip, 0xD1);
1550#endif
1551
1552 return 0;
1553}
1554
1555static int __init snd_es18xx_identify(es18xx_t *chip)
1556{
1557 int hi,lo;
1558
1559 /* reset */
1560 if (snd_es18xx_reset(chip) < 0) {
1561 snd_printk("reset at 0x%lx failed!!!\n", chip->port);
1562 return -ENODEV;
1563 }
1564
1565 snd_es18xx_dsp_command(chip, 0xe7);
1566 hi = snd_es18xx_dsp_get_byte(chip);
1567 if (hi < 0) {
1568 return hi;
1569 }
1570 lo = snd_es18xx_dsp_get_byte(chip);
1571 if ((lo & 0xf0) != 0x80) {
1572 return -ENODEV;
1573 }
1574 if (hi == 0x48) {
1575 chip->version = 0x488;
1576 return 0;
1577 }
1578 if (hi != 0x68) {
1579 return -ENODEV;
1580 }
1581 if ((lo & 0x0f) < 8) {
1582 chip->version = 0x688;
1583 return 0;
1584 }
1585
1586 outb(0x40, chip->port + 0x04);
1587 hi = inb(chip->port + 0x05);
1588 lo = inb(chip->port + 0x05);
1589 if (hi != lo) {
1590 chip->version = hi << 8 | lo;
1591 chip->ctrl_port = inb(chip->port + 0x05) << 8;
1592 chip->ctrl_port += inb(chip->port + 0x05);
1593
1594 if ((chip->res_ctrl_port = request_region(chip->ctrl_port, 8, "ES18xx - CTRL")) == NULL)
1595 return -EBUSY;
1596
1597 return 0;
1598 }
1599
1600 /* If has Hardware volume */
1601 if (snd_es18xx_mixer_writable(chip, 0x64, 0x04)) {
1602 /* If has Audio2 */
1603 if (snd_es18xx_mixer_writable(chip, 0x70, 0x7f)) {
1604 /* If has volume count */
1605 if (snd_es18xx_mixer_writable(chip, 0x64, 0x20)) {
1606 chip->version = 0x1887;
1607 } else {
1608 chip->version = 0x1888;
1609 }
1610 } else {
1611 chip->version = 0x1788;
1612 }
1613 }
1614 else
1615 chip->version = 0x1688;
1616 return 0;
1617}
1618
1619static int __init snd_es18xx_probe(es18xx_t *chip)
1620{
1621 if (snd_es18xx_identify(chip) < 0) {
1622 snd_printk("[0x%lx] ESS chip not found\n", chip->port);
1623 return -ENODEV;
1624 }
1625
1626 switch (chip->version) {
1627 case 0x1868:
1628 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_CONTROL | ES18XX_HWV;
1629 break;
1630 case 0x1869:
1631 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_MONO | ES18XX_MUTEREC | ES18XX_CONTROL | ES18XX_HWV;
1632 break;
1633 case 0x1878:
1634 chip->caps = ES18XX_DUPLEX_MONO | ES18XX_DUPLEX_SAME | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
1635 break;
1636 case 0x1879:
1637 chip->caps = ES18XX_PCM2 | ES18XX_SPATIALIZER | ES18XX_RECMIX | ES18XX_NEW_RATE | ES18XX_AUXB | ES18XX_I2S | ES18XX_CONTROL | ES18XX_HWV;
1638 break;
1639 case 0x1887:
1640 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_HWV;
1641 break;
1642 case 0x1888:
1643 chip->caps = ES18XX_PCM2 | ES18XX_RECMIX | ES18XX_AUXB | ES18XX_DUPLEX_SAME | ES18XX_HWV;
1644 break;
1645 default:
1646 snd_printk("[0x%lx] unsupported chip ES%x\n",
1647 chip->port, chip->version);
1648 return -ENODEV;
1649 }
1650
1651 snd_printd("[0x%lx] ESS%x chip found\n", chip->port, chip->version);
1652
1653 return snd_es18xx_initialize(chip);
1654}
1655
1656#ifdef TARGET_OS2
1657static snd_pcm_ops_t snd_es18xx_playback_ops = {
1658/* open: */ snd_es18xx_playback_open,
1659/* close: */ snd_es18xx_playback_close,
1660/* ioctl: */ snd_pcm_lib_ioctl,
1661/* hw_params:*/ snd_es18xx_playback_hw_params,
1662 0,
1663/* prepare: */ snd_es18xx_playback_prepare,
1664/* trigger: */ snd_es18xx_playback_trigger,
1665/* pointer: */ snd_es18xx_playback_pointer,
1666 0, 0
1667};
1668
1669static snd_pcm_ops_t snd_es18xx_capture_ops = {
1670/* open: */ snd_es18xx_capture_open,
1671/* close: */ snd_es18xx_capture_close,
1672/* ioctl: */ snd_pcm_lib_ioctl,
1673/* hw_params:*/ snd_es18xx_capture_hw_params,
1674 0,
1675/* prepare: */ snd_es18xx_capture_prepare,
1676/* trigger: */ snd_es18xx_capture_trigger,
1677/* pointer: */ snd_es18xx_capture_pointer,
1678 0, 0
1679};
1680#else
1681static snd_pcm_ops_t snd_es18xx_playback_ops = {
1682 open: snd_es18xx_playback_open,
1683 close: snd_es18xx_playback_close,
1684 ioctl: snd_pcm_lib_ioctl,
1685 hw_params: snd_es18xx_playback_hw_params,
1686 prepare: snd_es18xx_playback_prepare,
1687 trigger: snd_es18xx_playback_trigger,
1688 pointer: snd_es18xx_playback_pointer,
1689};
1690
1691static snd_pcm_ops_t snd_es18xx_capture_ops = {
1692 open: snd_es18xx_capture_open,
1693 close: snd_es18xx_capture_close,
1694 ioctl: snd_pcm_lib_ioctl,
1695 hw_params: snd_es18xx_capture_hw_params,
1696 prepare: snd_es18xx_capture_prepare,
1697 trigger: snd_es18xx_capture_trigger,
1698 pointer: snd_es18xx_capture_pointer,
1699};
1700#endif
1701
1702static void snd_es18xx_pcm_free(snd_pcm_t *pcm)
1703{
1704 es18xx_t *codec = snd_magic_cast(es18xx_t, pcm->private_data, return);
1705 codec->pcm = NULL;
1706 snd_pcm_lib_preallocate_free_for_all(pcm);
1707}
1708
1709int __init snd_es18xx_pcm(es18xx_t *chip, int device, snd_pcm_t ** rpcm)
1710{
1711 snd_pcm_t *pcm;
1712 char str[16];
1713 int err;
1714
1715 if (rpcm)
1716 *rpcm = NULL;
1717 sprintf(str, "ES%x", chip->version);
1718 if (chip->caps & ES18XX_PCM2) {
1719 err = snd_pcm_new(chip->card, str, device, 2, 1, &pcm);
1720 } else {
1721 err = snd_pcm_new(chip->card, str, device, 1, 1, &pcm);
1722 }
1723 if (err < 0)
1724 return err;
1725
1726 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &snd_es18xx_playback_ops);
1727 snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &snd_es18xx_capture_ops);
1728
1729 /* global setup */
1730 pcm->private_data = chip;
1731 pcm->private_free = snd_es18xx_pcm_free;
1732 pcm->info_flags = 0;
1733 if (chip->caps & ES18XX_DUPLEX_SAME)
1734 pcm->info_flags |= SNDRV_PCM_INFO_JOINT_DUPLEX;
1735 sprintf(pcm->name, "ESS AudioDrive ES%x", chip->version);
1736 chip->pcm = pcm;
1737
1738 snd_pcm_lib_preallocate_pages_for_all(pcm, 64*1024, chip->dma1 > 3 || chip->dma2 > 3 ? 128*1024 : 64*1024, GFP_KERNEL|GFP_DMA);
1739
1740 if (rpcm)
1741 *rpcm = pcm;
1742 return 0;
1743}
1744
1745static int snd_es18xx_free(es18xx_t *chip)
1746{
1747 if (chip->res_port)
1748 release_resource(chip->res_port);
1749 if (chip->res_ctrl_port)
1750 release_resource(chip->res_ctrl_port);
1751 if (chip->res_mpu_port)
1752 release_resource(chip->res_mpu_port);
1753 if (chip->irq >= 0)
1754 free_irq(chip->irq, (void *) chip);
1755 if (chip->dma1 >= 0) {
1756 disable_dma(chip->dma1);
1757 free_dma(chip->dma1);
1758 }
1759 if (chip->dma2 >= 0) {
1760 disable_dma(chip->dma2);
1761 free_dma(chip->dma2);
1762 }
1763 snd_magic_kfree(chip);
1764 return 0;
1765}
1766
1767static int snd_es18xx_dev_free(snd_device_t *device)
1768{
1769 es18xx_t *chip = snd_magic_cast(es18xx_t, device->device_data, return -ENXIO);
1770 return snd_es18xx_free(chip);
1771}
1772
1773static int __init snd_es18xx_new_device(snd_card_t * card,
1774 unsigned long port,
1775 unsigned long mpu_port,
1776 unsigned long fm_port,
1777 int irq, int dma1, int dma2,
1778 es18xx_t ** rchip)
1779{
1780 es18xx_t *chip;
1781#ifdef TARGET_OS2
1782 static snd_device_ops_t ops = {
1783 snd_es18xx_dev_free,0,0
1784 };
1785#else
1786 static snd_device_ops_t ops = {
1787 dev_free: snd_es18xx_dev_free,
1788 };
1789#endif
1790 int err;
1791
1792 *rchip = NULL;
1793 chip = snd_magic_kcalloc(es18xx_t, 0, GFP_KERNEL);
1794 if (chip == NULL)
1795 return -ENOMEM;
1796 spin_lock_init(&chip->reg_lock);
1797 spin_lock_init(&chip->mixer_lock);
1798 spin_lock_init(&chip->ctrl_lock);
1799 chip->card = card;
1800 chip->port = port;
1801 chip->mpu_port = mpu_port;
1802 chip->fm_port = fm_port;
1803 chip->irq = -1;
1804 chip->dma1 = -1;
1805 chip->dma2 = -1;
1806 chip->audio2_vol = 0x00;
1807 chip->active = 0;
1808
1809 if ((chip->res_port = request_region(port, 16, "ES18xx")) == NULL) {
1810 snd_es18xx_free(chip);
1811 snd_printk("unable to grap ports 0x%lx-0x%lx\n", port, port + 16 - 1);
1812 return -EBUSY;
1813 }
1814
1815 if (mpu_port > SNDRV_AUTO_PORT && (chip->res_mpu_port = request_region(mpu_port, 2, "ES18xx - MPU401")) == NULL) {
1816 snd_es18xx_free(chip);
1817 snd_printk("unable to grap MPU401 ports 0x%lx-0x%lx\n", mpu_port, mpu_port + 2 - 1);
1818 return -EBUSY;
1819 }
1820
1821 if (request_irq(irq, snd_es18xx_interrupt, SA_INTERRUPT, "ES18xx", (void *) chip)) {
1822 snd_es18xx_free(chip);
1823 snd_printk("unable to grap IRQ %d\n", irq);
1824 return -EBUSY;
1825 }
1826 chip->irq = irq;
1827
1828 if (request_dma(dma1, "ES18xx DMA 1")) {
1829 snd_es18xx_free(chip);
1830 snd_printk("unable to grap DMA1 %d\n", dma1);
1831 return -EBUSY;
1832 }
1833 chip->dma1 = dma1;
1834
1835 if (request_dma(dma2, "ES18xx DMA 2")) {
1836 snd_es18xx_free(chip);
1837 snd_printk("unable to grap DMA2 %d\n", dma2);
1838 return -EBUSY;
1839 }
1840 chip->dma2 = dma2;
1841
1842 if (snd_es18xx_probe(chip) < 0) {
1843 snd_es18xx_free(chip);
1844 return -ENODEV;
1845 }
1846 if ((err = snd_device_new(card, SNDRV_DEV_LOWLEVEL, chip, &ops)) < 0) {
1847 snd_es18xx_free(chip);
1848 return err;
1849 }
1850 *rchip = chip;
1851 return 0;
1852}
1853
1854static int __init snd_es18xx_mixer(es18xx_t *chip)
1855{
1856 snd_card_t *card;
1857 int err, idx;
1858
1859 card = chip->card;
1860
1861 strcpy(card->mixername, chip->pcm->name);
1862
1863 for (idx = 0; idx < sizeof(snd_es18xx_base_controls) /
1864 sizeof(snd_es18xx_base_controls[0]); idx++) {
1865 snd_kcontrol_t *kctl;
1866 kctl = snd_ctl_new1(&snd_es18xx_base_controls[idx], chip);
1867 if (chip->caps & ES18XX_HWV) {
1868 switch (idx) {
1869 case 0:
1870 chip->master_volume = kctl;
1871 kctl->private_free = snd_es18xx_hwv_free;
1872 break;
1873 case 1:
1874 chip->master_switch = kctl;
1875 kctl->private_free = snd_es18xx_hwv_free;
1876 break;
1877 }
1878 }
1879 if ((err = snd_ctl_add(card, kctl)) < 0)
1880 return err;
1881 }
1882 if (chip->caps & ES18XX_PCM2) {
1883 for (idx = 0; idx < sizeof(snd_es18xx_pcm2_controls) /
1884 sizeof(snd_es18xx_pcm2_controls[0]); idx++) {
1885 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm2_controls[idx], chip))) < 0)
1886 return err;
1887 }
1888 } else {
1889 for (idx = 0; idx < sizeof(snd_es18xx_pcm1_controls) /
1890 sizeof(snd_es18xx_pcm1_controls[0]); idx++) {
1891 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_pcm1_controls[idx], chip))) < 0)
1892 return err;
1893 }
1894 }
1895
1896 if (chip->caps & ES18XX_MONO) {
1897 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_mono_in_control, chip))) < 0)
1898 return err;
1899 }
1900 if (chip->caps & ES18XX_RECMIX) {
1901 for (idx = 0; idx < sizeof(snd_es18xx_recmix_controls) /
1902 sizeof(snd_es18xx_recmix_controls[0]); idx++) {
1903 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_recmix_controls[idx], chip))) < 0)
1904 return err;
1905 }
1906 }
1907 switch (chip->version) {
1908 default:
1909 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre1_control, chip))) < 0)
1910 return err;
1911 case 0x1869:
1912 case 0x1879:
1913 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_micpre2_control, chip))) < 0)
1914 return err;
1915 }
1916 if (chip->caps & ES18XX_SPATIALIZER) {
1917 for (idx = 0; idx < sizeof(snd_es18xx_spatializer_controls) /
1918 sizeof(snd_es18xx_spatializer_controls[0]); idx++) {
1919 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_es18xx_spatializer_controls[idx], chip))) < 0)
1920 return err;
1921 }
1922 }
1923 if (chip->caps & ES18XX_HWV) {
1924 for (idx = 0; idx < sizeof(snd_es18xx_hw_volume_controls) /
1925 sizeof(snd_es18xx_hw_volume_controls[0]); idx++) {
1926 snd_kcontrol_t *kctl;
1927 kctl = snd_ctl_new1(&snd_es18xx_hw_volume_controls[idx], chip);
1928 if (idx == 0)
1929 chip->hw_volume = kctl;
1930 else
1931 chip->hw_switch = kctl;
1932 kctl->private_free = snd_es18xx_hwv_free;
1933 if ((err = snd_ctl_add(card, kctl)) < 0)
1934 return err;
1935
1936 }
1937 }
1938 return 0;
1939}
1940
1941
1942/* Card level */
1943
1944EXPORT_NO_SYMBOLS;
1945MODULE_DESCRIPTION("ESS ES18xx AudioDrive");
1946MODULE_CLASSES("{sound}");
1947MODULE_DEVICES("{{ESS,ES1868 PnP AudioDrive},"
1948 "{ESS,ES1869 PnP AudioDrive},"
1949 "{ESS,ES1878 PnP AudioDrive},"
1950 "{ESS,ES1879 PnP AudioDrive},"
1951 "{ESS,ES1887 PnP AudioDrive},"
1952 "{ESS,ES1888 PnP AudioDrive},"
1953 "{ESS,ES1887 AudioDrive}"
1954 "{ESS,ES1888 AudioDrive}}");
1955
1956static int snd_index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX; /* Index 0-MAX */
1957static char *snd_id[SNDRV_CARDS] = SNDRV_DEFAULT_STR; /* ID for this card */
1958static int snd_enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE; /* Enable this card */
1959#ifdef __ISAPNP__
1960#ifdef TARGET_OS2
1961static int snd_isapnp[SNDRV_CARDS] = {1,1,1,1,1,1,1,1};
1962#else
1963static int snd_isapnp[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = 1};
1964#endif
1965#endif
1966static long snd_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x220,0x240,0x260,0x280 */
1967#ifndef __ISAPNP__
1968#ifdef TARGET_OS2
1969static long snd_mpu_port[SNDRV_CARDS] = {-1,-1,-1,-1,-1,-1,-1,-1};
1970#else
1971static long snd_mpu_port[SNDRV_CARDS] = {[0 ... (SNDRV_CARDS - 1)] = -1};
1972#endif
1973#else
1974static long snd_mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
1975#endif
1976static long snd_fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
1977static int snd_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5,7,9,10 */
1978static int snd_dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
1979static int snd_dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0,1,3 */
1980
1981MODULE_PARM(snd_index, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
1982MODULE_PARM_DESC(snd_index, "Index value for ES18xx soundcard.");
1983MODULE_PARM_SYNTAX(snd_index, SNDRV_INDEX_DESC);
1984MODULE_PARM(snd_id, "1-" __MODULE_STRING(SNDRV_CARDS) "s");
1985MODULE_PARM_DESC(snd_id, "ID string for ES18xx soundcard.");
1986MODULE_PARM_SYNTAX(snd_id, SNDRV_ID_DESC);
1987MODULE_PARM(snd_enable, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
1988MODULE_PARM_DESC(snd_enable, "Enable ES18xx soundcard.");
1989MODULE_PARM_SYNTAX(snd_enable, SNDRV_ENABLE_DESC);
1990#ifdef __ISAPNP__
1991MODULE_PARM(snd_isapnp, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
1992MODULE_PARM_DESC(snd_isapnp, "ISA PnP detection for specified soundcard.");
1993MODULE_PARM_SYNTAX(snd_isapnp, SNDRV_ISAPNP_DESC);
1994#endif
1995MODULE_PARM(snd_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
1996MODULE_PARM_DESC(snd_port, "Port # for ES18xx driver.");
1997MODULE_PARM_SYNTAX(snd_port, SNDRV_ENABLED ",allows:{{0x220,0x280,0x20}},prefers:{0x220},base:16,dialog:list");
1998MODULE_PARM(snd_mpu_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
1999MODULE_PARM_DESC(snd_mpu_port, "MPU-401 port # for ES18xx driver.");
2000MODULE_PARM_SYNTAX(snd_mpu_port, SNDRV_ENABLED ",allows:{{0x300,0x330,0x30},{0x800,0xffe,0x2}},prefers:{0x330,0x300},base:16,dialog:combo");
2001MODULE_PARM(snd_fm_port, "1-" __MODULE_STRING(SNDRV_CARDS) "l");
2002MODULE_PARM_DESC(snd_fm_port, "FM port # for ES18xx driver.");
2003MODULE_PARM_SYNTAX(snd_fm_port, SNDRV_ENABLED ",allows:{{0x388},{0x800,0xffc,0x4}},prefers:{0x388},base:16,dialog:combo");
2004MODULE_PARM(snd_irq, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
2005MODULE_PARM_DESC(snd_irq, "IRQ # for ES18xx driver.");
2006MODULE_PARM_SYNTAX(snd_irq, SNDRV_IRQ_DESC ",prefers:{5}");
2007MODULE_PARM(snd_dma1, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
2008MODULE_PARM_DESC(snd_dma1, "DMA 1 # for ES18xx driver.");
2009MODULE_PARM_SYNTAX(snd_dma1, SNDRV_DMA8_DESC ",prefers:{1}");
2010MODULE_PARM(snd_dma2, "1-" __MODULE_STRING(SNDRV_CARDS) "i");
2011MODULE_PARM_DESC(snd_dma2, "DMA 2 # for ES18xx driver.");
2012MODULE_PARM_SYNTAX(snd_dma2, SNDRV_ENABLED ",allows:{{0},{1},{3},{5}},dialog:list,prefers:{0}");
2013
2014struct snd_audiodrive {
2015#ifdef __ISAPNP__
2016 struct isapnp_dev *dev;
2017 struct isapnp_dev *devc;
2018#endif
2019};
2020
2021static snd_card_t *snd_audiodrive_cards[SNDRV_CARDS] = SNDRV_DEFAULT_PTR;
2022
2023#ifdef __ISAPNP__
2024
2025static struct isapnp_card *snd_audiodrive_isapnp_cards[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
2026static const struct isapnp_card_id *snd_audiodrive_isapnp_id[SNDRV_CARDS] __devinitdata = SNDRV_DEFAULT_PTR;
2027
2028#ifdef TARGET_OS2
2029#define ISAPNP_ES18XX(_va, _vb, _vc, _device, _audio, _control) \
2030 { \
2031 0, ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
2032 { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), \
2033 ISAPNP_DEVICE_ID(_va, _vb, _vc, _control) } \
2034 }
2035#else
2036#define ISAPNP_ES18XX(_va, _vb, _vc, _device, _audio, _control) \
2037 { \
2038 ISAPNP_CARD_ID(_va, _vb, _vc, _device), \
2039 devs : { ISAPNP_DEVICE_ID(_va, _vb, _vc, _audio), \
2040 ISAPNP_DEVICE_ID(_va, _vb, _vc, _control) } \
2041 }
2042#endif
2043
2044static struct isapnp_card_id snd_audiodrive_pnpids[] __devinitdata = {
2045 /* ESS 1868 (integrated on Compaq dual P-Pro motherboard and Genius 18PnP 3D) */
2046 ISAPNP_ES18XX('E','S','S',0x1868,0x1868,0x0000),
2047 /* ESS 1868 (integrated on Maxisound Cards) */
2048 ISAPNP_ES18XX('E','S','S',0x1868,0x8601,0x8600),
2049 /* ESS 1868 (integrated on Maxisound Cards) */
2050 ISAPNP_ES18XX('E','S','S',0x1868,0x8611,0x8610),
2051 /* ESS ES1869 Plug and Play AudioDrive */
2052 ISAPNP_ES18XX('E','S','S',0x0003,0x1869,0x0006),
2053 /* ESS 1869 */
2054 ISAPNP_ES18XX('E','S','S',0x1869,0x1869,0x0006),
2055 /* ESS 1878 */
2056 ISAPNP_ES18XX('E','S','S',0x1878,0x1878,0x0004),
2057 /* ESS 1879 */
2058 ISAPNP_ES18XX('E','S','S',0x1879,0x1879,0x0009),
2059 /* --- */
2060 { ISAPNP_CARD_END, } /* end */
2061};
2062
2063ISAPNP_CARD_TABLE(snd_audiodrive_pnpids);
2064
2065static int __init snd_audiodrive_isapnp(int dev, struct snd_audiodrive *acard)
2066{
2067 const struct isapnp_card_id *id = snd_audiodrive_isapnp_id[dev];
2068 struct isapnp_card *card = snd_audiodrive_isapnp_cards[dev];
2069 struct isapnp_dev *pdev;
2070
2071 acard->dev = isapnp_find_dev(card, id->devs[0].vendor, id->devs[0].function, NULL);
2072 if (acard->dev->active) {
2073 acard->dev = NULL;
2074 return -EBUSY;
2075 }
2076 acard->devc = isapnp_find_dev(card, id->devs[1].vendor, id->devs[1].function, NULL);
2077 if (acard->devc->active) {
2078 acard->dev = acard->devc = NULL;
2079 return -EBUSY;
2080 }
2081 /* Control port initialization */
2082 if (acard->devc->prepare(acard->devc)<0)
2083 return -EAGAIN;
2084 if (acard->devc->activate(acard->devc)<0) {
2085 snd_printk("isapnp control configure failure (out of resources?)\n");
2086 return -EAGAIN;
2087 }
2088 snd_printdd("isapnp: port=0x%lx\n", acard->devc->resource[0].start);
2089 /* PnP initialization */
2090 pdev = acard->dev;
2091 if (pdev->prepare(pdev)<0) {
2092 acard->devc->deactivate(acard->devc);
2093 return -EAGAIN;
2094 }
2095 if (snd_port[dev] != SNDRV_AUTO_PORT)
2096 isapnp_resource_change(&pdev->resource[0], snd_port[dev], 16);
2097 if (snd_fm_port[dev] != SNDRV_AUTO_PORT)
2098 isapnp_resource_change(&pdev->resource[1], snd_fm_port[dev], 4);
2099 if (snd_mpu_port[dev] != SNDRV_AUTO_PORT)
2100 isapnp_resource_change(&pdev->resource[2], snd_mpu_port[dev], 2);
2101 if (snd_dma1[dev] != SNDRV_AUTO_DMA)
2102 isapnp_resource_change(&pdev->dma_resource[0], snd_dma1[dev], 1);
2103 if (snd_dma2[dev] != SNDRV_AUTO_DMA)
2104 isapnp_resource_change(&pdev->dma_resource[1], snd_dma2[dev], 1);
2105 if (snd_irq[dev] != SNDRV_AUTO_IRQ)
2106 isapnp_resource_change(&pdev->irq_resource[0], snd_irq[dev], 1);
2107 if (pdev->activate(pdev)<0) {
2108 snd_printk("isapnp configure failure (out of resources?)\n");
2109 acard->devc->deactivate(acard->devc);
2110 return -EBUSY;
2111 }
2112 /* ok. hack using Vendor-Defined Card-Level registers */
2113 /* skip csn and logdev initialization - already done in isapnp_configure */
2114 isapnp_cfg_begin(pdev->bus->number, pdev->devfn);
2115 isapnp_write_byte(0x27, pdev->irq_resource[0].start); /* Hardware Volume IRQ Number */
2116 if (snd_mpu_port[dev] > SNDRV_AUTO_PORT)
2117 isapnp_write_byte(0x28, pdev->irq); /* MPU-401 IRQ Number */
2118 isapnp_write_byte(0x72, pdev->irq_resource[0].start); /* second IRQ */
2119 isapnp_cfg_end();
2120 snd_port[dev] = pdev->resource[0].start;
2121 snd_fm_port[dev] = pdev->resource[1].start;
2122 snd_mpu_port[dev] = pdev->resource[2].start;
2123 snd_dma1[dev] = pdev->dma_resource[0].start;
2124 snd_dma2[dev] = pdev->dma_resource[1].start;
2125 snd_irq[dev] = pdev->irq_resource[0].start;
2126 snd_printdd("isapnp ES18xx: port=0x%lx, fm port=0x%lx, mpu port=0x%lx\n", snd_port[dev], snd_fm_port[dev], snd_mpu_port[dev]);
2127 snd_printdd("isapnp ES18xx: dma1=%i, dma2=%i, irq=%i\n", snd_dma1[dev], snd_dma2[dev], snd_irq[dev]);
2128 return 0;
2129}
2130
2131static void snd_audiodrive_deactivate(struct snd_audiodrive *acard)
2132{
2133 if (acard->devc) {
2134 acard->devc->deactivate(acard->devc);
2135 acard->devc = NULL;
2136 }
2137 if (acard->dev) {
2138 acard->dev->deactivate(acard->dev);
2139 acard->dev = NULL;
2140 }
2141}
2142#endif /* __ISAPNP__ */
2143
2144static void snd_audiodrive_free(snd_card_t *card)
2145{
2146 struct snd_audiodrive *acard = (struct snd_audiodrive *)card->private_data;
2147
2148 if (acard) {
2149#ifdef __ISAPNP__
2150 snd_audiodrive_deactivate(acard);
2151#endif
2152 }
2153}
2154
2155static int __init snd_audiodrive_probe(int dev)
2156{
2157 static int possible_irqs[] = {5, 9, 10, 7, 11, 12, -1};
2158 static int possible_dmas[] = {1, 0, 3, 5, -1};
2159 int irq, dma1, dma2;
2160 snd_card_t *card;
2161 struct snd_audiodrive *acard;
2162 snd_rawmidi_t *rmidi = NULL;
2163 es18xx_t *chip;
2164 opl3_t *opl3;
2165 int err;
2166
2167 card = snd_card_new(snd_index[dev], snd_id[dev], THIS_MODULE,
2168 sizeof(struct snd_audiodrive));
2169 if (card == NULL)
2170 return -ENOMEM;
2171 acard = (struct snd_audiodrive *)card->private_data;
2172 card->private_free = snd_audiodrive_free;
2173#ifdef __ISAPNP__
2174 if (snd_isapnp[dev] && (err = snd_audiodrive_isapnp(dev, acard)) < 0) {
2175 snd_card_free(card);
2176 return err;
2177 }
2178#endif
2179
2180 irq = snd_irq[dev];
2181 if (irq == SNDRV_AUTO_IRQ) {
2182 if ((irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
2183 snd_card_free(card);
2184 snd_printk("unable to find a free IRQ\n");
2185 return -EBUSY;
2186 }
2187 }
2188 dma1 = snd_dma1[dev];
2189 if (dma1 == SNDRV_AUTO_DMA) {
2190 if ((dma1 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
2191 snd_card_free(card);
2192 snd_printk("unable to find a free DMA1\n");
2193 return -EBUSY;
2194 }
2195 }
2196 dma2 = snd_dma2[dev];
2197 if (dma2 == SNDRV_AUTO_DMA) {
2198 if ((dma2 = snd_legacy_find_free_dma(possible_dmas)) < 0) {
2199 snd_card_free(card);
2200 snd_printk("unable to find a free DMA2\n");
2201 return -EBUSY;
2202 }
2203 }
2204
2205 if ((err = snd_es18xx_new_device(card,
2206 snd_port[dev],
2207 snd_mpu_port[dev],
2208 snd_fm_port[dev],
2209 irq, dma1, dma2,
2210 &chip)) < 0) {
2211 snd_card_free(card);
2212 return err;
2213 }
2214 if ((err = snd_es18xx_pcm(chip, 0, NULL)) < 0) {
2215 snd_card_free(card);
2216 return err;
2217 }
2218 if ((err = snd_es18xx_mixer(chip)) < 0) {
2219 snd_card_free(card);
2220 return err;
2221 }
2222
2223 if (snd_opl3_create(card, chip->fm_port, chip->fm_port + 2, OPL3_HW_OPL3, 0, &opl3) < 0) {
2224 snd_printk("opl3 not detected at 0x%lx\n", chip->port);
2225 } else {
2226 if ((err = snd_opl3_hwdep_new(opl3, 0, 1, NULL)) < 0) {
2227 snd_card_free(card);
2228 return err;
2229 }
2230 }
2231
2232 if (snd_mpu_port[dev] > SNDRV_AUTO_PORT) {
2233 if ((err = snd_mpu401_uart_new(card, 0, MPU401_HW_ES18XX,
2234 chip->mpu_port, 0,
2235 irq, 0,
2236 &rmidi)) < 0) {
2237 snd_card_free(card);
2238 return err;
2239 }
2240 chip->rmidi = rmidi;
2241 }
2242 sprintf(card->driver, "ES%x", chip->version);
2243 sprintf(card->shortname, "ESS AudioDrive ES%x", chip->version);
2244 sprintf(card->longname, "%s at 0x%lx, irq %d, dma1 %d, dma2 %d",
2245 card->shortname,
2246 chip->port,
2247 irq, dma1, dma2);
2248 if ((err = snd_card_register(card)) < 0) {
2249 snd_card_free(card);
2250 return err;
2251 }
2252 snd_audiodrive_cards[dev] = card;
2253 return 0;
2254}
2255
2256static int __init snd_audiodrive_probe_legacy_port(unsigned long port)
2257{
2258 static int dev = 0;
2259 int res;
2260
2261 for ( ; dev < SNDRV_CARDS; dev++) {
2262 if (!snd_enable[dev] || snd_port[dev] != SNDRV_AUTO_PORT)
2263 continue;
2264#ifdef __ISAPNP__
2265 if (snd_isapnp[dev])
2266 continue;
2267#endif
2268 snd_port[dev] = port;
2269 res = snd_audiodrive_probe(dev);
2270 if (res < 0)
2271 snd_port[dev] = SNDRV_AUTO_PORT;
2272 return res;
2273 }
2274 return -ENODEV;
2275}
2276
2277
2278#ifdef __ISAPNP__
2279static int __init snd_audiodrive_isapnp_detect(struct isapnp_card *card,
2280 const struct isapnp_card_id *id)
2281{
2282 static int dev = 0;
2283 int res;
2284
2285 for ( ; dev < SNDRV_CARDS; dev++) {
2286 if (!snd_enable[dev] || !snd_isapnp[dev])
2287 continue;
2288 snd_audiodrive_isapnp_cards[dev] = card;
2289 snd_audiodrive_isapnp_id[dev] = id;
2290 res = snd_audiodrive_probe(dev);
2291 if (res < 0)
2292 return res;
2293 dev++;
2294 return 0;
2295 }
2296
2297 return -ENODEV;
2298}
2299#endif /* __ISAPNP__ */
2300
2301static int __init alsa_card_es18xx_init(void)
2302{
2303 static unsigned long possible_ports[] = {0x220, 0x240, 0x260, 0x280, -1};
2304 int dev, cards = 0;
2305
2306 /* legacy non-auto cards at first */
2307 for (dev = 0; dev < SNDRV_CARDS; dev++) {
2308 if (!snd_enable[dev] || snd_port[dev] == SNDRV_AUTO_PORT)
2309 continue;
2310#ifdef __ISAPNP__
2311 if (snd_isapnp[dev])
2312 continue;
2313#endif
2314 if (snd_audiodrive_probe(dev) >= 0)
2315 cards++;
2316 }
2317 /* legacy auto configured cards */
2318 cards += snd_legacy_auto_probe(possible_ports, snd_audiodrive_probe_legacy_port);
2319#ifdef __ISAPNP__
2320 /* ISA PnP cards at last */
2321 cards += isapnp_probe_cards(snd_audiodrive_pnpids, snd_audiodrive_isapnp_detect);
2322#endif
2323 if(!cards) {
2324#ifdef MODULE
2325 snd_printk("ESS AudioDrive ES18xx soundcard not found or device busy\n");
2326#endif
2327 return -ENODEV;
2328 }
2329 return 0;
2330}
2331
2332static void __exit alsa_card_es18xx_exit(void)
2333{
2334 int idx;
2335
2336 for(idx = 0; idx < SNDRV_CARDS; idx++)
2337 snd_card_free(snd_audiodrive_cards[idx]);
2338}
2339
2340module_init(alsa_card_es18xx_init)
2341module_exit(alsa_card_es18xx_exit)
2342
2343#ifndef MODULE
2344
2345/* format is: snd-card-es18xx=snd_enable,snd_index,snd_id,snd_isapnp,
2346 snd_port,snd_mpu_port,snd_fm_port,snd_irq,
2347 snd_dma1,snd_dma2 */
2348
2349static int __init alsa_card_es18xx_setup(char *str)
2350{
2351 static unsigned __initdata nr_dev = 0;
2352 int __attribute__ ((__unused__)) pnp = INT_MAX;
2353
2354 if (nr_dev >= SNDRV_CARDS)
2355 return 0;
2356 (void)(get_option(&str,&snd_enable[nr_dev]) == 2 &&
2357 get_option(&str,&snd_index[nr_dev]) == 2 &&
2358 get_id(&str,&snd_id[nr_dev]) == 2 &&
2359 get_option(&str,&pnp) == 2 &&
2360 get_option(&str,(int *)&snd_port[nr_dev]) == 2 &&
2361 get_option(&str,(int *)&snd_mpu_port[nr_dev]) == 2 &&
2362 get_option(&str,(int *)&snd_fm_port[nr_dev]) == 2 &&
2363 get_option(&str,&snd_irq[nr_dev]) == 2 &&
2364 get_option(&str,&snd_dma1[nr_dev]) == 2 &&
2365 get_option(&str,&snd_dma2[nr_dev]) == 2);
2366#ifdef __ISAPNP__
2367 if (pnp != INT_MAX)
2368 snd_isapnp[nr_dev] = pnp;
2369#endif
2370 nr_dev++;
2371 return 1;
2372}
2373
2374__setup("snd-card-es18xx=", alsa_card_es18xx_setup);
2375
2376#endif /* ifndef MODULE */
Note: See TracBrowser for help on using the repository browser.