aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
Diffstat (limited to 'sound')
-rw-r--r--sound/isa/Kconfig14
-rw-r--r--sound/isa/opti9xx/Makefile2
-rw-r--r--sound/isa/opti9xx/miro.c1457
-rw-r--r--sound/isa/opti9xx/miro.h73
4 files changed, 1546 insertions, 0 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ff8fef932786..2a1c7334210a 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -292,6 +292,20 @@ config SND_OPTI93X
292 To compile this driver as a module, choose M here: the module 292 To compile this driver as a module, choose M here: the module
293 will be called snd-opti93x. 293 will be called snd-opti93x.
294 294
295config SND_MIRO
296 tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
297 depends on SND
298 select SND_OPL4_LIB
299 select SND_CS4231_LIB
300 select SND_MPU401_UART
301 select SND_PCM
302 help
303 Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro,
304 miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards.
305
306 To compile this driver as a module, choose M here: the module
307 will be called snd-miro.
308
295config SND_SB8 309config SND_SB8
296 tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" 310 tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
297 depends on SND 311 depends on SND
diff --git a/sound/isa/opti9xx/Makefile b/sound/isa/opti9xx/Makefile
index 28c64070cd56..0e41bfd5a403 100644
--- a/sound/isa/opti9xx/Makefile
+++ b/sound/isa/opti9xx/Makefile
@@ -6,8 +6,10 @@
6snd-opti92x-ad1848-objs := opti92x-ad1848.o 6snd-opti92x-ad1848-objs := opti92x-ad1848.o
7snd-opti92x-cs4231-objs := opti92x-cs4231.o 7snd-opti92x-cs4231-objs := opti92x-cs4231.o
8snd-opti93x-objs := opti93x.o 8snd-opti93x-objs := opti93x.o
9snd-miro-objs := miro.o
9 10
10# Toplevel Module Dependency 11# Toplevel Module Dependency
11obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o 12obj-$(CONFIG_SND_OPTI92X_AD1848) += snd-opti92x-ad1848.o
12obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o 13obj-$(CONFIG_SND_OPTI92X_CS4231) += snd-opti92x-cs4231.o
13obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o 14obj-$(CONFIG_SND_OPTI93X) += snd-opti93x.o
15obj-$(CONFIG_SND_MIRO) += snd-miro.o
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c
new file mode 100644
index 000000000000..49ba334c0d24
--- /dev/null
+++ b/sound/isa/opti9xx/miro.c
@@ -0,0 +1,1457 @@
1/*
2 * ALSA soundcard driver for Miro miroSOUND PCM1 pro
3 * miroSOUND PCM12
4 * miroSOUND PCM20 Radio
5 *
6 * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de>
7 *
8 * Based on OSS ACI and ALSA OPTi9xx drivers
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or
13 * (at your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 */
24
25#include <sound/driver.h>
26#include <linux/init.h>
27#include <linux/err.h>
28#include <linux/platform_device.h>
29#include <linux/delay.h>
30#include <linux/slab.h>
31#include <linux/ioport.h>
32#include <linux/moduleparam.h>
33#include <asm/io.h>
34#include <asm/dma.h>
35#include <sound/core.h>
36#include <sound/cs4231.h>
37#include <sound/mpu401.h>
38#include <sound/opl4.h>
39#include <sound/control.h>
40#include <sound/info.h>
41#define SNDRV_LEGACY_FIND_FREE_IRQ
42#define SNDRV_LEGACY_FIND_FREE_DMA
43#include <sound/initval.h>
44#include "miro.h"
45
46MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>");
47MODULE_LICENSE("GPL");
48MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio");
49MODULE_SUPPORTED_DEVICE("{{Miro,miroSOUND PCM1 pro}, "
50 "{Miro,miroSOUND PCM12}, "
51 "{Miro,miroSOUND PCM20 Radio}}");
52
53static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */
54static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */
55static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */
56static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */
57static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */
58static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */
59static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */
60static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
61static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */
62static int wss;
63static int ide;
64
65module_param(index, int, 0444);
66MODULE_PARM_DESC(index, "Index value for miro soundcard.");
67module_param(id, charp, 0444);
68MODULE_PARM_DESC(id, "ID string for miro soundcard.");
69module_param(port, long, 0444);
70MODULE_PARM_DESC(port, "WSS port # for miro driver.");
71module_param(mpu_port, long, 0444);
72MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver.");
73module_param(fm_port, long, 0444);
74MODULE_PARM_DESC(fm_port, "FM Port # for miro driver.");
75module_param(irq, int, 0444);
76MODULE_PARM_DESC(irq, "WSS irq # for miro driver.");
77module_param(mpu_irq, int, 0444);
78MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver.");
79module_param(dma1, int, 0444);
80MODULE_PARM_DESC(dma1, "1st dma # for miro driver.");
81module_param(dma2, int, 0444);
82MODULE_PARM_DESC(dma2, "2nd dma # for miro driver.");
83module_param(wss, int, 0444);
84MODULE_PARM_DESC(wss, "wss mode");
85module_param(ide, int, 0444);
86MODULE_PARM_DESC(ide, "enable ide port");
87
88#define OPTi9XX_HW_DETECT 0
89#define OPTi9XX_HW_82C928 1
90#define OPTi9XX_HW_82C929 2
91#define OPTi9XX_HW_82C924 3
92#define OPTi9XX_HW_82C925 4
93#define OPTi9XX_HW_82C930 5
94#define OPTi9XX_HW_82C931 6
95#define OPTi9XX_HW_82C933 7
96#define OPTi9XX_HW_LAST OPTi9XX_HW_82C933
97
98#define OPTi9XX_MC_REG(n) n
99
100
101struct snd_miro {
102 unsigned short hardware;
103 unsigned char password;
104 char name[7];
105
106 struct resource *res_mc_base;
107 struct resource *res_aci_port;
108
109 unsigned long mc_base;
110 unsigned long mc_base_size;
111 unsigned long pwd_reg;
112
113 spinlock_t lock;
114 struct snd_card *card;
115 struct snd_pcm *pcm;
116
117 long wss_base;
118 int irq;
119 int dma1;
120 int dma2;
121
122 long fm_port;
123
124 long mpu_port;
125 int mpu_irq;
126
127 unsigned long aci_port;
128 int aci_vendor;
129 int aci_product;
130 int aci_version;
131 int aci_amp;
132 int aci_preamp;
133 int aci_solomode;
134
135 struct mutex aci_mutex;
136};
137
138static void snd_miro_proc_init(struct snd_miro * miro);
139
140#define DRIVER_NAME "snd-miro"
141
142static struct platform_device *device;
143
144static char * snd_opti9xx_names[] = {
145 "unkown",
146 "82C928", "82C929",
147 "82C924", "82C925",
148 "82C930", "82C931", "82C933"
149};
150
151/*
152 * ACI control
153 */
154
155static int aci_busy_wait(struct snd_miro * miro)
156{
157 long timeout;
158 unsigned char byte;
159
160 for (timeout = 1; timeout <= ACI_MINTIME+30; timeout++) {
161 if (((byte=inb(miro->aci_port + ACI_REG_BUSY)) & 1) == 0) {
162 if (timeout >= ACI_MINTIME)
163 snd_printd("aci ready in round %ld.\n",
164 timeout-ACI_MINTIME);
165 return byte;
166 }
167 if (timeout >= ACI_MINTIME) {
168 long out=10*HZ;
169 switch (timeout-ACI_MINTIME) {
170 case 0 ... 9:
171 out /= 10;
172 case 10 ... 19:
173 out /= 10;
174 case 20 ... 30:
175 out /= 10;
176 default:
177 set_current_state(TASK_UNINTERRUPTIBLE);
178 schedule_timeout(out);
179 break;
180 }
181 }
182 }
183 snd_printk(KERN_ERR "aci_busy_wait() time out\n");
184 return -EBUSY;
185}
186
187static inline int aci_write(struct snd_miro * miro, unsigned char byte)
188{
189 if (aci_busy_wait(miro) >= 0) {
190 outb(byte, miro->aci_port + ACI_REG_COMMAND);
191 return 0;
192 } else {
193 snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n", byte);
194 return -EBUSY;
195 }
196}
197
198static inline int aci_read(struct snd_miro * miro)
199{
200 unsigned char byte;
201
202 if (aci_busy_wait(miro) >= 0) {
203 byte=inb(miro->aci_port + ACI_REG_STATUS);
204 return byte;
205 } else {
206 snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n");
207 return -EBUSY;
208 }
209}
210
211static int aci_cmd(struct snd_miro * miro, int write1, int write2, int write3)
212{
213 int write[] = {write1, write2, write3};
214 int value, i;
215
216 if (mutex_lock_interruptible(&miro->aci_mutex))
217 return -EINTR;
218
219 for (i=0; i<3; i++) {
220 if (write[i]< 0 || write[i] > 255)
221 break;
222 else {
223 value = aci_write(miro, write[i]);
224 if (value < 0)
225 goto out;
226 }
227 }
228
229 value = aci_read(miro);
230
231out: mutex_unlock(&miro->aci_mutex);
232 return value;
233}
234
235static int aci_getvalue(struct snd_miro * miro, unsigned char index)
236{
237 return aci_cmd(miro, ACI_STATUS, index, -1);
238}
239
240static int aci_setvalue(struct snd_miro * miro, unsigned char index, int value)
241{
242 return aci_cmd(miro, index, value, -1);
243}
244
245/*
246 * MIXER part
247 */
248
249static int snd_miro_info_capture(struct snd_kcontrol *kcontrol,
250 struct snd_ctl_elem_info *uinfo)
251{
252 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
253 uinfo->count = 1;
254
255 return 0;
256}
257
258static int snd_miro_get_capture(struct snd_kcontrol *kcontrol,
259 struct snd_ctl_elem_value *ucontrol)
260{
261 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
262 int value;
263
264 if ((value = aci_getvalue(miro, ACI_S_GENERAL)) < 0) {
265 snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n", value);
266 return value;
267 }
268
269 ucontrol->value.integer.value[0] = value & 0x20;
270
271 return 0;
272}
273
274static int snd_miro_put_capture(struct snd_kcontrol *kcontrol,
275 struct snd_ctl_elem_value *ucontrol)
276{
277 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
278 int change, value, error;
279
280 value = !(ucontrol->value.integer.value[0]);
281
282 if ((error = aci_setvalue(miro, ACI_SET_SOLOMODE, value)) < 0) {
283 snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n", error);
284 return error;
285 }
286
287 change = (value != miro->aci_solomode);
288 miro->aci_solomode = value;
289
290 return change;
291}
292
293static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol,
294 struct snd_ctl_elem_info *uinfo)
295{
296 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
297 uinfo->count = 1;
298 uinfo->value.integer.min = 0;
299 uinfo->value.integer.max = 3;
300
301 return 0;
302}
303
304static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol,
305 struct snd_ctl_elem_value *ucontrol)
306{
307 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
308 int value;
309
310 if (miro->aci_version <= 176) {
311
312 /*
313 OSS says it's not readable with versions < 176.
314 But it doesn't work on my card,
315 which is a PCM12 with aci_version = 176.
316 */
317
318 ucontrol->value.integer.value[0] = miro->aci_preamp;
319 return 0;
320 }
321
322 if ((value = aci_getvalue(miro, ACI_GET_PREAMP)) < 0) {
323 snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n", value);
324 return value;
325 }
326
327 ucontrol->value.integer.value[0] = value;
328
329 return 0;
330}
331
332static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol,
333 struct snd_ctl_elem_value *ucontrol)
334{
335 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
336 int error, value, change;
337
338 value = ucontrol->value.integer.value[0];
339
340 if ((error = aci_setvalue(miro, ACI_SET_PREAMP, value)) < 0) {
341 snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n", error);
342 return error;
343 }
344
345 change = (value != miro->aci_preamp);
346 miro->aci_preamp = value;
347
348 return change;
349}
350
351static int snd_miro_info_amp(struct snd_kcontrol *kcontrol,
352 struct snd_ctl_elem_info *uinfo)
353{
354 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
355 uinfo->count = 1;
356
357 return 0;
358}
359
360static int snd_miro_get_amp(struct snd_kcontrol *kcontrol,
361 struct snd_ctl_elem_value *ucontrol)
362{
363 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
364 ucontrol->value.integer.value[0] = miro->aci_amp;
365
366 return 0;
367}
368
369static int snd_miro_put_amp(struct snd_kcontrol *kcontrol,
370 struct snd_ctl_elem_value *ucontrol)
371{
372 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
373 int error, value, change;
374
375 value = ucontrol->value.integer.value[0];
376
377 if ((error = aci_setvalue(miro, ACI_SET_POWERAMP, value)) < 0) {
378 snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n", value, error);
379 return error;
380 }
381
382 change = (value != miro->aci_amp);
383 miro->aci_amp = value;
384
385 return change;
386}
387
388#define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \
389{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \
390 .name = ctl_name, \
391 .index = ctl_index, \
392 .info = snd_miro_info_double, \
393 .get = snd_miro_get_double, \
394 .put = snd_miro_put_double, \
395 .private_value = get_right_reg | (set_right_reg << 8) \
396}
397
398static int snd_miro_info_double(struct snd_kcontrol *kcontrol,
399 struct snd_ctl_elem_info *uinfo)
400{
401 int reg = kcontrol->private_value & 0xff;
402
403 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
404 uinfo->count = 2;
405
406 if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) {
407
408 /* equalizer elements */
409
410 uinfo->value.integer.min = - 0x7f;
411 uinfo->value.integer.max = 0x7f;
412 } else {
413
414 /* non-equalizer elements */
415
416 uinfo->value.integer.min = 0;
417 uinfo->value.integer.max = 0x20;
418 }
419
420 return 0;
421}
422
423static int snd_miro_get_double(struct snd_kcontrol *kcontrol,
424 struct snd_ctl_elem_value *uinfo)
425{
426 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
427 int left_val, right_val;
428
429 int right_reg = kcontrol->private_value & 0xff;
430 int left_reg = right_reg + 1;
431
432 if ((right_val = aci_getvalue(miro, right_reg)) < 0) {
433 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", right_reg, right_val);
434 return right_val;
435 }
436
437 if ((left_val = aci_getvalue(miro, left_reg)) < 0) {
438 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", left_reg, left_val);
439 return left_val;
440 }
441
442 if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) {
443
444 /* equalizer elements */
445
446 if (left_val < 0x80) {
447 uinfo->value.integer.value[0] = left_val;
448 } else {
449 uinfo->value.integer.value[0] = 0x80 - left_val;
450 }
451
452 if (right_val < 0x80) {
453 uinfo->value.integer.value[1] = right_val;
454 } else {
455 uinfo->value.integer.value[1] = 0x80 - right_val;
456 }
457
458 } else {
459
460 /* non-equalizer elements */
461
462 uinfo->value.integer.value[0] = 0x20 - left_val;
463 uinfo->value.integer.value[1] = 0x20 - right_val;
464 }
465
466 return 0;
467}
468
469static int snd_miro_put_double(struct snd_kcontrol *kcontrol,
470 struct snd_ctl_elem_value *ucontrol)
471{
472 struct snd_miro *miro = snd_kcontrol_chip(kcontrol);
473 int left, right, left_old, right_old;
474 int setreg_left, setreg_right, getreg_left, getreg_right;
475 int change, error;
476
477 left = ucontrol->value.integer.value[0];
478 right = ucontrol->value.integer.value[1];
479
480 setreg_right = (kcontrol->private_value >> 8) & 0xff;
481 if (setreg_right == ACI_SET_MASTER) {
482 setreg_left = setreg_right + 1;
483 } else {
484 setreg_left = setreg_right + 8;
485 }
486
487 getreg_right = kcontrol->private_value & 0xff;
488 getreg_left = getreg_right + 1;
489
490 if ((left_old = aci_getvalue(miro, getreg_left)) < 0) {
491 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_left, left_old);
492 return left_old;
493 }
494
495 if ((right_old = aci_getvalue(miro, getreg_right)) < 0) {
496 snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n", getreg_right, right_old);
497 return right_old;
498 }
499
500 if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) {
501
502 /* equalizer elements */
503
504 if (left_old > 0x80)
505 left_old = 0x80 - left_old;
506 if (right_old > 0x80)
507 right_old = 0x80 - right_old;
508
509 if (left >= 0) {
510 if ((error = aci_setvalue(miro, setreg_left, left)) < 0) {
511 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
512 left, error);
513 return error;
514 }
515 } else {
516 if ((error = aci_setvalue(miro, setreg_left, 0x80 - left)) < 0) {
517 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
518 0x80 - left, error);
519 return error;
520 }
521 }
522
523 if (right >= 0) {
524 if ((error = aci_setvalue(miro, setreg_right, right)) < 0) {
525 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
526 right, error);
527 return error;
528 }
529 } else {
530 if ((error = aci_setvalue(miro, setreg_right, 0x80 - right)) < 0) {
531 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
532 0x80 - right, error);
533 return error;
534 }
535 }
536
537 } else {
538
539 /* non-equalizer elements */
540
541 left_old = 0x20 - left_old;
542 right_old = 0x20 - right_old;
543
544 if ((error = aci_setvalue(miro, setreg_left, 0x20 - left)) < 0) {
545 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
546 0x20 - left, error);
547 return error;
548 }
549 if ((error = aci_setvalue(miro, setreg_right, 0x20 - right)) < 0) {
550 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
551 0x20 - right, error);
552 return error;
553 }
554 }
555
556 change = (left != left_old) || (right != right_old);
557
558 return change;
559}
560
561static struct snd_kcontrol_new snd_miro_controls[] = {
562MIRO_DOUBLE("Master Playback Volume", 0, ACI_GET_MASTER, ACI_SET_MASTER),
563MIRO_DOUBLE("Mic Playback Volume", 1, ACI_GET_MIC, ACI_SET_MIC),
564MIRO_DOUBLE("Line Playback Volume", 1, ACI_GET_LINE, ACI_SET_LINE),
565MIRO_DOUBLE("CD Playback Volume", 0, ACI_GET_CD, ACI_SET_CD),
566MIRO_DOUBLE("Synth Playback Volume", 0, ACI_GET_SYNTH, ACI_SET_SYNTH),
567MIRO_DOUBLE("PCM Playback Volume", 1, ACI_GET_PCM, ACI_SET_PCM),
568MIRO_DOUBLE("Aux Playback Volume", 2, ACI_GET_LINE2, ACI_SET_LINE2),
569};
570
571/* Equalizer with seven bands (only PCM20)
572 from -12dB up to +12dB on each band */
573static struct snd_kcontrol_new snd_miro_eq_controls[] = {
574MIRO_DOUBLE("Tone Control - 28 Hz", 0, ACI_GET_EQ1, ACI_SET_EQ1),
575MIRO_DOUBLE("Tone Control - 160 Hz", 0, ACI_GET_EQ2, ACI_SET_EQ2),
576MIRO_DOUBLE("Tone Control - 400 Hz", 0, ACI_GET_EQ3, ACI_SET_EQ3),
577MIRO_DOUBLE("Tone Control - 1 kHz", 0, ACI_GET_EQ4, ACI_SET_EQ4),
578MIRO_DOUBLE("Tone Control - 2.5 kHz", 0, ACI_GET_EQ5, ACI_SET_EQ5),
579MIRO_DOUBLE("Tone Control - 6.3 kHz", 0, ACI_GET_EQ6, ACI_SET_EQ6),
580MIRO_DOUBLE("Tone Control - 16 kHz", 0, ACI_GET_EQ7, ACI_SET_EQ7),
581};
582
583static struct snd_kcontrol_new snd_miro_radio_control[] = {
584MIRO_DOUBLE("Radio Playback Volume", 0, ACI_GET_LINE1, ACI_SET_LINE1),
585};
586
587static struct snd_kcontrol_new snd_miro_line_control[] = {
588MIRO_DOUBLE("Line Playback Volume", 2, ACI_GET_LINE1, ACI_SET_LINE1),
589};
590
591static struct snd_kcontrol_new snd_miro_preamp_control[] = {
592{
593 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
594 .name = "Mic Boost",
595 .index = 1,
596 .info = snd_miro_info_preamp,
597 .get = snd_miro_get_preamp,
598 .put = snd_miro_put_preamp,
599}};
600
601static struct snd_kcontrol_new snd_miro_amp_control[] = {
602{
603 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
604 .name = "Line Boost",
605 .index = 0,
606 .info = snd_miro_info_amp,
607 .get = snd_miro_get_amp,
608 .put = snd_miro_put_amp,
609}};
610
611static struct snd_kcontrol_new snd_miro_capture_control[] = {
612{
613 .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
614 .name = "PCM Capture Switch",
615 .index = 0,
616 .info = snd_miro_info_capture,
617 .get = snd_miro_get_capture,
618 .put = snd_miro_put_capture,
619}};
620
621static unsigned char aci_init_values[][2] __initdata = {
622 { ACI_SET_MUTE, 0x00 },
623 { ACI_SET_POWERAMP, 0x00 },
624 { ACI_SET_PREAMP, 0x00 },
625 { ACI_SET_SOLOMODE, 0x00 },
626 { ACI_SET_MIC + 0, 0x20 },
627 { ACI_SET_MIC + 8, 0x20 },
628 { ACI_SET_LINE + 0, 0x20 },
629 { ACI_SET_LINE + 8, 0x20 },
630 { ACI_SET_CD + 0, 0x20 },
631 { ACI_SET_CD + 8, 0x20 },
632 { ACI_SET_PCM + 0, 0x20 },
633 { ACI_SET_PCM + 8, 0x20 },
634 { ACI_SET_LINE1 + 0, 0x20 },
635 { ACI_SET_LINE1 + 8, 0x20 },
636 { ACI_SET_LINE2 + 0, 0x20 },
637 { ACI_SET_LINE2 + 8, 0x20 },
638 { ACI_SET_SYNTH + 0, 0x20 },
639 { ACI_SET_SYNTH + 8, 0x20 },
640 { ACI_SET_MASTER + 0, 0x20 },
641 { ACI_SET_MASTER + 1, 0x20 },
642};
643
644static int __init snd_set_aci_init_values(struct snd_miro *miro)
645{
646 int idx, error;
647
648 /* enable WSS on PCM1 */
649
650 if ((miro->aci_product == 'A') && wss) {
651 if ((error = aci_setvalue(miro, ACI_SET_WSS, wss)) < 0) {
652 snd_printk(KERN_ERR "enabling WSS mode failed\n");
653 return error;
654 }
655 }
656
657 /* enable IDE port */
658
659 if (ide) {
660 if ((error = aci_setvalue(miro, ACI_SET_IDE, ide)) < 0) {
661 snd_printk(KERN_ERR "enabling IDE port failed\n");
662 return error;
663 }
664 }
665
666 /* set common aci values */
667
668 for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++)
669 if ((error = aci_setvalue(miro, aci_init_values[idx][0],
670 aci_init_values[idx][1])) < 0) {
671 snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n",
672 aci_init_values[idx][0], error);
673 return error;
674 }
675
676 miro->aci_amp = 0;
677 miro->aci_preamp = 0;
678 miro->aci_solomode = 1;
679
680 return 0;
681}
682
683static int snd_miro_mixer(struct snd_miro *miro)
684{
685 struct snd_card *card;
686 unsigned int idx;
687 int err;
688
689 snd_assert(miro != NULL && miro->card != NULL, return -EINVAL);
690
691 card = miro->card;
692
693 switch (miro->hardware) {
694 case OPTi9XX_HW_82C924:
695 strcpy(card->mixername, "ACI & OPTi924");
696 break;
697 case OPTi9XX_HW_82C929:
698 strcpy(card->mixername, "ACI & OPTi929");
699 break;
700 default:
701 snd_BUG();
702 break;
703 }
704
705 for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) {
706 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_controls[idx], miro))) < 0)
707 return err;
708 }
709
710 if ((miro->aci_product == 'A') || (miro->aci_product == 'B')) {
711 /* PCM1/PCM12 with power-amp and Line 2 */
712 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_line_control[0], miro))) < 0)
713 return err;
714 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_amp_control[0], miro))) < 0)
715 return err;
716 }
717
718 if ((miro->aci_product == 'B') || (miro->aci_product == 'C')) {
719 /* PCM12/PCM20 with mic-preamp */
720 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_preamp_control[0], miro))) < 0)
721 return err;
722 if (miro->aci_version >= 176)
723 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_capture_control[0], miro))) < 0)
724 return err;
725 }
726
727 if (miro->aci_product == 'C') {
728 /* PCM20 with radio and 7 band equalizer */
729 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_radio_control[0], miro))) < 0)
730 return err;
731 for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) {
732 if ((err = snd_ctl_add(card, snd_ctl_new1(&snd_miro_eq_controls[idx], miro))) < 0)
733 return err;
734 }
735 }
736
737 return 0;
738}
739
740static long snd_legacy_find_free_ioport(long *port_table, long size)
741{
742 while (*port_table != -1) {
743 struct resource *res;
744 if ((res = request_region(*port_table, size,
745 "ALSA test")) != NULL) {
746 release_resource(res);
747 kfree_nocheck(res);
748 return *port_table;
749 }
750 port_table++;
751 }
752 return -1;
753}
754
755static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
756{
757 static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
758
759 chip->hardware = hardware;
760 strcpy(chip->name, snd_opti9xx_names[hardware]);
761
762 chip->mc_base_size = opti9xx_mc_size[hardware];
763
764 spin_lock_init(&chip->lock);
765
766 chip->wss_base = -1;
767 chip->irq = -1;
768 chip->dma1 = -1;
769 chip->dma2 = -1;
770 chip->fm_port = -1;
771 chip->mpu_port = -1;
772 chip->mpu_irq = -1;
773
774 switch (hardware) {
775 case OPTi9XX_HW_82C929:
776 chip->mc_base = 0xf8c;
777 chip->password = 0xe3;
778 chip->pwd_reg = 3;
779 break;
780
781 case OPTi9XX_HW_82C924:
782 chip->mc_base = 0xf8c;
783 chip->password = 0xe5;
784 chip->pwd_reg = 3;
785 break;
786
787 default:
788 snd_printk(KERN_ERR "sorry, no support for %d\n", hardware);
789 return -ENODEV;
790 }
791
792 return 0;
793}
794
795static unsigned char snd_miro_read(struct snd_miro *chip,
796 unsigned char reg)
797{
798 unsigned long flags;
799 unsigned char retval = 0xff;
800
801 spin_lock_irqsave(&chip->lock, flags);
802 outb(chip->password, chip->mc_base + chip->pwd_reg);
803
804 switch (chip->hardware) {
805 case OPTi9XX_HW_82C924:
806 if (reg > 7) {
807 outb(reg, chip->mc_base + 8);
808 outb(chip->password, chip->mc_base + chip->pwd_reg);
809 retval = inb(chip->mc_base + 9);
810 break;
811 }
812
813 case OPTi9XX_HW_82C929:
814 retval = inb(chip->mc_base + reg);
815 break;
816
817 default:
818 snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
819 }
820
821 spin_unlock_irqrestore(&chip->lock, flags);
822 return retval;
823}
824
825static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
826 unsigned char value)
827{
828 unsigned long flags;
829
830 spin_lock_irqsave(&chip->lock, flags);
831 outb(chip->password, chip->mc_base + chip->pwd_reg);
832
833 switch (chip->hardware) {
834 case OPTi9XX_HW_82C924:
835 if (reg > 7) {
836 outb(reg, chip->mc_base + 8);
837 outb(chip->password, chip->mc_base + chip->pwd_reg);
838 outb(value, chip->mc_base + 9);
839 break;
840 }
841
842 case OPTi9XX_HW_82C929:
843 outb(value, chip->mc_base + reg);
844 break;
845
846 default:
847 snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
848 }
849
850 spin_unlock_irqrestore(&chip->lock, flags);
851}
852
853
854#define snd_miro_write_mask(chip, reg, value, mask) \
855 snd_miro_write(chip, reg, \
856 (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
857
858/*
859 * Proc Interface
860 */
861
862static void snd_miro_proc_read(struct snd_info_entry * entry,
863 struct snd_info_buffer *buffer)
864{
865 struct snd_miro *miro = (struct snd_miro *) entry->private_data;
866 char* model = "unknown";
867
868 /* miroSOUND PCM1 pro, early PCM12 */
869
870 if ((miro->hardware == OPTi9XX_HW_82C929) &&
871 (miro->aci_vendor == 'm') &&
872 (miro->aci_product == 'A')) {
873 switch(miro->aci_version) {
874 case 3:
875 model = "miroSOUND PCM1 pro";
876 break;
877 default:
878 model = "miroSOUND PCM1 pro / (early) PCM12";
879 break;
880 }
881 }
882
883 /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
884
885 if ((miro->hardware == OPTi9XX_HW_82C924) &&
886 (miro->aci_vendor == 'm') &&
887 (miro->aci_product == 'B')) {
888 switch(miro->aci_version) {
889 case 4:
890 model = "miroSOUND PCM12";
891 break;
892 case 176:
893 model = "miroSOUND PCM12 (Rev. E)";
894 break;
895 default:
896 model = "miroSOUND PCM12 / PCM12 pnp";
897 break;
898 }
899 }
900
901 /* miroSOUND PCM20 radio */
902
903 if ((miro->hardware == OPTi9XX_HW_82C924) &&
904 (miro->aci_vendor == 'm') &&
905 (miro->aci_product == 'C')) {
906 switch(miro->aci_version) {
907 case 7:
908 model = "miroSOUND PCM20 radio (Rev. E)";
909 break;
910 default:
911 model = "miroSOUND PCM20 radio";
912 break;
913 }
914 }
915
916 snd_iprintf(buffer, "\nGeneral information:\n");
917 snd_iprintf(buffer, " model : %s\n", model);
918 snd_iprintf(buffer, " opti : %s\n", miro->name);
919 snd_iprintf(buffer, " codec : %s\n", miro->pcm->name);
920 snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base);
921 snd_iprintf(buffer, " irq : %d\n", miro->irq);
922 snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2);
923
924 snd_iprintf(buffer, "MPU-401:\n");
925 snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port);
926 snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq);
927
928 snd_iprintf(buffer, "ACI information:\n");
929 snd_iprintf(buffer, " vendor : ");
930 switch(miro->aci_vendor) {
931 case 'm':
932 snd_iprintf(buffer, "Miro\n");
933 break;
934 default:
935 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor);
936 break;
937 }
938
939 snd_iprintf(buffer, " product : ");
940 switch(miro->aci_product) {
941 case 'A':
942 snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
943 break;
944 case 'B':
945 snd_iprintf(buffer, "miroSOUND PCM12\n");
946 break;
947 case 'C':
948 snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
949 break;
950 default:
951 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product);
952 break;
953 }
954
955 snd_iprintf(buffer, " firmware: %d (0x%x)\n",
956 miro->aci_version, miro->aci_version);
957 snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
958 miro->aci_port, miro->aci_port+2);
959 snd_iprintf(buffer, " wss : 0x%x\n", wss);
960 snd_iprintf(buffer, " ide : 0x%x\n", ide);
961 snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode);
962 snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp);
963 snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp);
964}
965
966static void __init snd_miro_proc_init(struct snd_miro * miro)
967{
968 struct snd_info_entry *entry;
969
970 if (! snd_card_proc_new(miro->card, "miro", &entry))
971 snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
972}
973
974/*
975 * Init
976 */
977
978static int __init snd_miro_configure(struct snd_miro *chip)
979{
980 unsigned char wss_base_bits;
981 unsigned char irq_bits;
982 unsigned char dma_bits;
983 unsigned char mpu_port_bits = 0;
984 unsigned char mpu_irq_bits;
985 unsigned long flags;
986
987 switch (chip->hardware) {
988 case OPTi9XX_HW_82C924:
989 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
990 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
991 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
992 snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
993 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
994 break;
995 case OPTi9XX_HW_82C929:
996 /* untested init commands for OPTi929 */
997 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
998 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
999 snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
1000 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
1001 break;
1002 default:
1003 snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
1004 return -EINVAL;
1005 }
1006
1007 switch (chip->wss_base) {
1008 case 0x530:
1009 wss_base_bits = 0x00;
1010 break;
1011 case 0x604:
1012 wss_base_bits = 0x03;
1013 break;
1014 case 0xe80:
1015 wss_base_bits = 0x01;
1016 break;
1017 case 0xf40:
1018 wss_base_bits = 0x02;
1019 break;
1020 default:
1021 snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base);
1022 goto __skip_base;
1023 }
1024 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
1025
1026__skip_base:
1027 switch (chip->irq) {
1028 case 5:
1029 irq_bits = 0x05;
1030 break;
1031 case 7:
1032 irq_bits = 0x01;
1033 break;
1034 case 9:
1035 irq_bits = 0x02;
1036 break;
1037 case 10:
1038 irq_bits = 0x03;
1039 break;
1040 case 11:
1041 irq_bits = 0x04;
1042 break;
1043 default:
1044 snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq);
1045 goto __skip_resources;
1046 }
1047
1048 switch (chip->dma1) {
1049 case 0:
1050 dma_bits = 0x01;
1051 break;
1052 case 1:
1053 dma_bits = 0x02;
1054 break;
1055 case 3:
1056 dma_bits = 0x03;
1057 break;
1058 default:
1059 snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1);
1060 goto __skip_resources;
1061 }
1062
1063 if (chip->dma1 == chip->dma2) {
1064 snd_printk(KERN_ERR "don't want to share dmas\n");
1065 return -EBUSY;
1066 }
1067
1068 switch (chip->dma2) {
1069 case 0:
1070 case 1:
1071 break;
1072 default:
1073 snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2);
1074 goto __skip_resources;
1075 }
1076 dma_bits |= 0x04;
1077
1078 spin_lock_irqsave(&chip->lock, flags);
1079 outb(irq_bits << 3 | dma_bits, chip->wss_base);
1080 spin_unlock_irqrestore(&chip->lock, flags);
1081
1082__skip_resources:
1083 if (chip->hardware > OPTi9XX_HW_82C928) {
1084 switch (chip->mpu_port) {
1085 case 0:
1086 case -1:
1087 break;
1088 case 0x300:
1089 mpu_port_bits = 0x03;
1090 break;
1091 case 0x310:
1092 mpu_port_bits = 0x02;
1093 break;
1094 case 0x320:
1095 mpu_port_bits = 0x01;
1096 break;
1097 case 0x330:
1098 mpu_port_bits = 0x00;
1099 break;
1100 default:
1101 snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n",
1102 chip->mpu_port);
1103 goto __skip_mpu;
1104 }
1105
1106 switch (chip->mpu_irq) {
1107 case 5:
1108 mpu_irq_bits = 0x02;
1109 break;
1110 case 7:
1111 mpu_irq_bits = 0x03;
1112 break;
1113 case 9:
1114 mpu_irq_bits = 0x00;
1115 break;
1116 case 10:
1117 mpu_irq_bits = 0x01;
1118 break;
1119 default:
1120 snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n",
1121 chip->mpu_irq);
1122 goto __skip_mpu;
1123 }
1124
1125 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6),
1126 (chip->mpu_port <= 0) ? 0x00 :
1127 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
1128 0xf8);
1129 }
1130__skip_mpu:
1131
1132 return 0;
1133}
1134
1135static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
1136{
1137 int i, err;
1138 unsigned char value;
1139
1140 for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
1141
1142 if ((err = snd_miro_init(chip, i)) < 0)
1143 return err;
1144
1145 if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
1146 continue;
1147
1148 value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
1149 if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
1150 if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
1151 return 1;
1152
1153 release_resource(chip->res_mc_base);
1154 kfree_nocheck(chip->res_mc_base);
1155 chip->res_mc_base = NULL;
1156
1157 }
1158
1159 return -ENODEV;
1160}
1161
1162static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
1163{
1164 unsigned char regval;
1165 int i;
1166
1167 mutex_init(&miro->aci_mutex);
1168
1169 /* get ACI port from OPTi9xx MC 4 */
1170
1171 miro->mc_base = 0xf8c;
1172 regval=inb(miro->mc_base + 4);
1173 miro->aci_port = (regval & 0x10) ? 0x344: 0x354;
1174
1175 if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) {
1176 snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
1177 miro->aci_port, miro->aci_port+2);
1178 return -ENOMEM;
1179 }
1180
1181 /* force ACI into a known state */
1182 for (i = 0; i < 3; i++)
1183 if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
1184 snd_card_free(card);
1185 snd_printk(KERN_ERR "can't force aci into known state.\n");
1186 return -ENXIO;
1187 }
1188
1189 if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
1190 (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
1191 snd_card_free(card);
1192 snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
1193 return -ENXIO;
1194 }
1195
1196 if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
1197 snd_card_free(card);
1198 snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
1199 miro->aci_port);
1200 return -ENXIO;
1201 }
1202
1203 if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 ||
1204 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
1205 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
1206 snd_printk(KERN_ERR "can't initialize aci.\n");
1207 return -ENXIO;
1208 }
1209
1210 return 0;
1211}
1212
1213static void snd_card_miro_free(struct snd_card *card)
1214{
1215 struct snd_miro *miro = card->private_data;
1216
1217 release_and_free_resource(miro->res_aci_port);
1218 release_and_free_resource(miro->res_mc_base);
1219}
1220
1221static int __init snd_miro_probe(struct platform_device *devptr)
1222{
1223 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
1224 static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
1225 static int possible_irqs[] = {11, 9, 10, 7, -1};
1226 static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
1227 static int possible_dma1s[] = {3, 1, 0, -1};
1228 static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
1229
1230 int error;
1231 struct snd_miro *miro;
1232 struct snd_cs4231 *codec;
1233 struct snd_timer *timer;
1234 struct snd_card *card;
1235 struct snd_pcm *pcm;
1236 struct snd_rawmidi *rmidi;
1237
1238 if (!(card = snd_card_new(index, id, THIS_MODULE,
1239 sizeof(struct snd_miro))))
1240 return -ENOMEM;
1241
1242 card->private_free = snd_card_miro_free;
1243 miro = card->private_data;
1244 miro->card = card;
1245
1246 if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
1247 snd_card_free(card);
1248 snd_printk(KERN_ERR "unable to detect aci chip\n");
1249 return -ENODEV;
1250 }
1251
1252 /* init proc interface */
1253 snd_miro_proc_init(miro);
1254
1255 if ((error = snd_card_miro_detect(card, miro)) < 0) {
1256 snd_card_free(card);
1257 snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
1258 return -ENODEV;
1259 }
1260
1261 if (! miro->res_mc_base &&
1262 (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
1263 "miro (OPTi9xx MC)")) == NULL) {
1264 snd_card_free(card);
1265 snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
1266 return -ENOMEM;
1267 }
1268
1269 miro->wss_base = port;
1270 miro->fm_port = fm_port;
1271 miro->mpu_port = mpu_port;
1272 miro->irq = irq;
1273 miro->mpu_irq = mpu_irq;
1274 miro->dma1 = dma1;
1275 miro->dma2 = dma2;
1276
1277 if (miro->wss_base == SNDRV_AUTO_PORT) {
1278 if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
1279 snd_card_free(card);
1280 snd_printk(KERN_ERR "unable to find a free WSS port\n");
1281 return -EBUSY;
1282 }
1283 }
1284
1285 if (miro->mpu_port == SNDRV_AUTO_PORT) {
1286 if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
1287 snd_card_free(card);
1288 snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
1289 return -EBUSY;
1290 }
1291 }
1292 if (miro->irq == SNDRV_AUTO_IRQ) {
1293 if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
1294 snd_card_free(card);
1295 snd_printk(KERN_ERR "unable to find a free IRQ\n");
1296 return -EBUSY;
1297 }
1298 }
1299 if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
1300 if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
1301 snd_card_free(card);
1302 snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
1303 return -EBUSY;
1304 }
1305 }
1306 if (miro->dma1 == SNDRV_AUTO_DMA) {
1307 if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
1308 snd_card_free(card);
1309 snd_printk(KERN_ERR "unable to find a free DMA1\n");
1310 return -EBUSY;
1311 }
1312 }
1313 if (miro->dma2 == SNDRV_AUTO_DMA) {
1314 if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
1315 snd_card_free(card);
1316 snd_printk(KERN_ERR "unable to find a free DMA2\n");
1317 return -EBUSY;
1318 }
1319 }
1320
1321 if ((error = snd_miro_configure(miro))) {
1322 snd_card_free(card);
1323 return error;
1324 }
1325
1326 if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
1327 miro->irq, miro->dma1, miro->dma2,
1328 CS4231_HW_AD1845,
1329 0,
1330 &codec)) < 0) {
1331 snd_card_free(card);
1332 return error;
1333 }
1334
1335 if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
1336 snd_card_free(card);
1337 return error;
1338 }
1339 if ((error = snd_cs4231_mixer(codec)) < 0) {
1340 snd_card_free(card);
1341 return error;
1342 }
1343 if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
1344 snd_card_free(card);
1345 return error;
1346 }
1347
1348 miro->pcm = pcm;
1349
1350 if ((error = snd_miro_mixer(miro)) < 0) {
1351 snd_card_free(card);
1352 return error;
1353 }
1354
1355 if (miro->aci_vendor == 'm') {
1356 /* It looks like a miro sound card. */
1357 switch (miro->aci_product) {
1358 case 'A':
1359 sprintf(card->shortname,
1360 "miroSOUND PCM1 pro / PCM12");
1361 break;
1362 case 'B':
1363 sprintf(card->shortname,
1364 "miroSOUND PCM12");
1365 break;
1366 case 'C':
1367 sprintf(card->shortname,
1368 "miroSOUND PCM20 radio");
1369 break;
1370 default:
1371 sprintf(card->shortname,
1372 "unknown miro");
1373 snd_printk(KERN_INFO "unknown miro aci id\n");
1374 break;
1375 }
1376 } else {
1377 snd_printk(KERN_INFO "found unsupported aci card\n");
1378 sprintf(card->shortname, "unknown Cardinal Technologies");
1379 }
1380
1381 strcpy(card->driver, "miro");
1382 sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
1383 card->shortname, miro->name, pcm->name, miro->wss_base + 4,
1384 miro->irq, miro->dma1, miro->dma2);
1385
1386 if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT)
1387 rmidi = NULL;
1388 else
1389 if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
1390 miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT,
1391 &rmidi)))
1392 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port);
1393
1394 if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) {
1395 struct snd_opl3 *opl3 = NULL;
1396 struct snd_opl4 *opl4;
1397 if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8,
1398 2, &opl3, &opl4) < 0)
1399 snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port);
1400 }
1401
1402 if ((error = snd_set_aci_init_values(miro)) < 0) {
1403 snd_card_free(card);
1404 return error;
1405 }
1406
1407 snd_card_set_dev(card, &devptr->dev);
1408
1409 if ((error = snd_card_register(card))) {
1410 snd_card_free(card);
1411 return error;
1412 }
1413
1414 platform_set_drvdata(devptr, card);
1415 return 0;
1416}
1417
1418static int __devexit snd_miro_remove(struct platform_device *devptr)
1419{
1420 snd_card_free(platform_get_drvdata(devptr));
1421 platform_set_drvdata(devptr, NULL);
1422 return 0;
1423}
1424
1425static struct platform_driver snd_miro_driver = {
1426 .probe = snd_miro_probe,
1427 .remove = __devexit_p(snd_miro_remove),
1428 /* FIXME: suspend/resume */
1429 .driver = {
1430 .name = DRIVER_NAME
1431 },
1432};
1433
1434static int __init alsa_card_miro_init(void)
1435{
1436 int error;
1437
1438 if ((error = platform_driver_register(&snd_miro_driver)) < 0)
1439 return error;
1440 device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
1441 if (! IS_ERR(device))
1442 return 0;
1443#ifdef MODULE
1444 printk(KERN_ERR "no miro soundcard found\n");
1445#endif
1446 platform_driver_unregister(&snd_miro_driver);
1447 return PTR_ERR(device);
1448}
1449
1450static void __exit alsa_card_miro_exit(void)
1451{
1452 platform_device_unregister(device);
1453 platform_driver_unregister(&snd_miro_driver);
1454}
1455
1456module_init(alsa_card_miro_init)
1457module_exit(alsa_card_miro_exit)
diff --git a/sound/isa/opti9xx/miro.h b/sound/isa/opti9xx/miro.h
new file mode 100644
index 000000000000..6e1385b8e07e
--- /dev/null
+++ b/sound/isa/opti9xx/miro.h
@@ -0,0 +1,73 @@
1#ifndef _MIRO_H_
2#define _MIRO_H_
3
4#define ACI_REG_COMMAND 0 /* write register offset */
5#define ACI_REG_STATUS 1 /* read register offset */
6#define ACI_REG_BUSY 2 /* busy register offset */
7#define ACI_REG_RDS 2 /* PCM20: RDS register offset */
8#define ACI_MINTIME 500 /* ACI time out limit */
9
10#define ACI_SET_MUTE 0x0d
11#define ACI_SET_POWERAMP 0x0f
12#define ACI_SET_TUNERMUTE 0xa3
13#define ACI_SET_TUNERMONO 0xa4
14#define ACI_SET_IDE 0xd0
15#define ACI_SET_WSS 0xd1
16#define ACI_SET_SOLOMODE 0xd2
17#define ACI_SET_PREAMP 0x03
18#define ACI_GET_PREAMP 0x21
19#define ACI_WRITE_TUNE 0xa7
20#define ACI_READ_TUNERSTEREO 0xa8
21#define ACI_READ_TUNERSTATION 0xa9
22#define ACI_READ_VERSION 0xf1
23#define ACI_READ_IDCODE 0xf2
24#define ACI_INIT 0xff
25#define ACI_STATUS 0xf0
26#define ACI_S_GENERAL 0x00
27#define ACI_ERROR_OP 0xdf
28
29/* ACI Mixer */
30
31/* These are the values for the right channel GET registers.
32 Add an offset of 0x01 for the left channel register.
33 (left=right+0x01) */
34
35#define ACI_GET_MASTER 0x03
36#define ACI_GET_MIC 0x05
37#define ACI_GET_LINE 0x07
38#define ACI_GET_CD 0x09
39#define ACI_GET_SYNTH 0x0b
40#define ACI_GET_PCM 0x0d
41#define ACI_GET_LINE1 0x10 /* Radio on PCM20 */
42#define ACI_GET_LINE2 0x12
43
44#define ACI_GET_EQ1 0x22 /* from Bass ... */
45#define ACI_GET_EQ2 0x24
46#define ACI_GET_EQ3 0x26
47#define ACI_GET_EQ4 0x28
48#define ACI_GET_EQ5 0x2a
49#define ACI_GET_EQ6 0x2c
50#define ACI_GET_EQ7 0x2e /* ... to Treble */
51
52/* And these are the values for the right channel SET registers.
53 For left channel access you have to add an offset of 0x08.
54 MASTER is an exception, which needs an offset of 0x01 */
55
56#define ACI_SET_MASTER 0x00
57#define ACI_SET_MIC 0x30
58#define ACI_SET_LINE 0x31
59#define ACI_SET_CD 0x34
60#define ACI_SET_SYNTH 0x33
61#define ACI_SET_PCM 0x32
62#define ACI_SET_LINE1 0x35 /* Radio on PCM20 */
63#define ACI_SET_LINE2 0x36
64
65#define ACI_SET_EQ1 0x40 /* from Bass ... */
66#define ACI_SET_EQ2 0x41
67#define ACI_SET_EQ3 0x42
68#define ACI_SET_EQ4 0x43
69#define ACI_SET_EQ5 0x44
70#define ACI_SET_EQ6 0x45
71#define ACI_SET_EQ7 0x46 /* ... to Treble */
72
73#endif /* _MIRO_H_ */