aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa
diff options
context:
space:
mode:
Diffstat (limited to 'sound/isa')
-rw-r--r--sound/isa/Kconfig23
-rw-r--r--sound/isa/Makefile2
-rw-r--r--sound/isa/adlib.c161
-rw-r--r--sound/isa/cmi8330.c4
-rw-r--r--sound/isa/opti9xx/Makefile2
-rw-r--r--sound/isa/opti9xx/miro.c1455
-rw-r--r--sound/isa/opti9xx/miro.h73
7 files changed, 1718 insertions, 2 deletions
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index ff8fef932786..557c4de22960 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -11,6 +11,15 @@ config SND_CS4231_LIB
11 tristate 11 tristate
12 select SND_PCM 12 select SND_PCM
13 13
14config SND_ADLIB
15 tristate "AdLib FM card"
16 select SND_OPL3_LIB
17 help
18 Say Y here to include support for AdLib FM cards.
19
20 To compile this driver as a module, choose M here: the module
21 will be called snd-adlib.
22
14config SND_AD1816A 23config SND_AD1816A
15 tristate "Analog Devices SoundPort AD1816A" 24 tristate "Analog Devices SoundPort AD1816A"
16 depends on SND && PNP && ISA 25 depends on SND && PNP && ISA
@@ -292,6 +301,20 @@ config SND_OPTI93X
292 To compile this driver as a module, choose M here: the module 301 To compile this driver as a module, choose M here: the module
293 will be called snd-opti93x. 302 will be called snd-opti93x.
294 303
304config SND_MIRO
305 tristate "Miro miroSOUND PCM1pro/PCM12/PCM20radio driver"
306 depends on SND
307 select SND_OPL4_LIB
308 select SND_CS4231_LIB
309 select SND_MPU401_UART
310 select SND_PCM
311 help
312 Say 'Y' or 'M' to include support for Miro miroSOUND PCM1 pro,
313 miroSOUND PCM12 and miroSOUND PCM20 Radio soundcards.
314
315 To compile this driver as a module, choose M here: the module
316 will be called snd-miro.
317
295config SND_SB8 318config SND_SB8
296 tristate "Sound Blaster 1.0/2.0/Pro (8-bit)" 319 tristate "Sound Blaster 1.0/2.0/Pro (8-bit)"
297 depends on SND 320 depends on SND
diff --git a/sound/isa/Makefile b/sound/isa/Makefile
index 05724eb7bfe4..bb317ccc170f 100644
--- a/sound/isa/Makefile
+++ b/sound/isa/Makefile
@@ -3,6 +3,7 @@
3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz> 3# Copyright (c) 2001 by Jaroslav Kysela <perex@suse.cz>
4# 4#
5 5
6snd-adlib-objs := adlib.o
6snd-als100-objs := als100.o 7snd-als100-objs := als100.o
7snd-azt2320-objs := azt2320.o 8snd-azt2320-objs := azt2320.o
8snd-cmi8330-objs := cmi8330.o 9snd-cmi8330-objs := cmi8330.o
@@ -13,6 +14,7 @@ snd-sgalaxy-objs := sgalaxy.o
13snd-sscape-objs := sscape.o 14snd-sscape-objs := sscape.o
14 15
15# Toplevel Module Dependency 16# Toplevel Module Dependency
17obj-$(CONFIG_SND_ADLIB) += snd-adlib.o
16obj-$(CONFIG_SND_ALS100) += snd-als100.o 18obj-$(CONFIG_SND_ALS100) += snd-als100.o
17obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o 19obj-$(CONFIG_SND_AZT2320) += snd-azt2320.o
18obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o 20obj-$(CONFIG_SND_CMI8330) += snd-cmi8330.o
diff --git a/sound/isa/adlib.c b/sound/isa/adlib.c
new file mode 100644
index 000000000000..a253a14e6a45
--- /dev/null
+++ b/sound/isa/adlib.c
@@ -0,0 +1,161 @@
1/*
2 * AdLib FM card driver.
3 */
4
5#include <sound/driver.h>
6#include <linux/kernel.h>
7#include <linux/module.h>
8#include <linux/platform_device.h>
9#include <sound/core.h>
10#include <sound/initval.h>
11#include <sound/opl3.h>
12
13#define CRD_NAME "AdLib FM"
14#define DRV_NAME "snd_adlib"
15
16MODULE_DESCRIPTION(CRD_NAME);
17MODULE_AUTHOR("Rene Herman");
18MODULE_LICENSE("GPL");
19
20static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
21static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
22static int enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
23static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
24
25module_param_array(index, int, NULL, 0444);
26MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
27module_param_array(id, charp, NULL, 0444);
28MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
29module_param_array(enable, bool, NULL, 0444);
30MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
31module_param_array(port, long, NULL, 0444);
32MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
33
34static struct platform_device *devices[SNDRV_CARDS];
35
36static void snd_adlib_free(struct snd_card *card)
37{
38 release_and_free_resource(card->private_data);
39}
40
41static int __devinit snd_adlib_probe(struct platform_device *device)
42{
43 struct snd_card *card;
44 struct snd_opl3 *opl3;
45
46 int error;
47 int i = device->id;
48
49 if (port[i] == SNDRV_AUTO_PORT) {
50 snd_printk(KERN_ERR DRV_NAME ": please specify port\n");
51 error = -EINVAL;
52 goto out0;
53 }
54
55 card = snd_card_new(index[i], id[i], THIS_MODULE, 0);
56 if (!card) {
57 snd_printk(KERN_ERR DRV_NAME ": could not create card\n");
58 error = -EINVAL;
59 goto out0;
60 }
61
62 card->private_data = request_region(port[i], 4, CRD_NAME);
63 if (!card->private_data) {
64 snd_printk(KERN_ERR DRV_NAME ": could not grab ports\n");
65 error = -EBUSY;
66 goto out1;
67 }
68 card->private_free = snd_adlib_free;
69
70 error = snd_opl3_create(card, port[i], port[i] + 2, OPL3_HW_AUTO, 1, &opl3);
71 if (error < 0) {
72 snd_printk(KERN_ERR DRV_NAME ": could not create OPL\n");
73 goto out1;
74 }
75
76 error = snd_opl3_hwdep_new(opl3, 0, 0, NULL);
77 if (error < 0) {
78 snd_printk(KERN_ERR DRV_NAME ": could not create FM\n");
79 goto out1;
80 }
81
82 strcpy(card->driver, DRV_NAME);
83 strcpy(card->shortname, CRD_NAME);
84 sprintf(card->longname, CRD_NAME " at %#lx", port[i]);
85
86 snd_card_set_dev(card, &device->dev);
87
88 error = snd_card_register(card);
89 if (error < 0) {
90 snd_printk(KERN_ERR DRV_NAME ": could not register card\n");
91 goto out1;
92 }
93
94 platform_set_drvdata(device, card);
95 return 0;
96
97out1: snd_card_free(card);
98 out0: error = -EINVAL; /* FIXME: should be the original error code */
99 return error;
100}
101
102static int __devexit snd_adlib_remove(struct platform_device *device)
103{
104 snd_card_free(platform_get_drvdata(device));
105 platform_set_drvdata(device, NULL);
106 return 0;
107}
108
109static struct platform_driver snd_adlib_driver = {
110 .probe = snd_adlib_probe,
111 .remove = __devexit_p(snd_adlib_remove),
112
113 .driver = {
114 .name = DRV_NAME
115 }
116};
117
118static int __init alsa_card_adlib_init(void)
119{
120 int i, cards;
121
122 if (platform_driver_register(&snd_adlib_driver) < 0) {
123 snd_printk(KERN_ERR DRV_NAME ": could not register driver\n");
124 return -ENODEV;
125 }
126
127 for (cards = 0, i = 0; i < SNDRV_CARDS; i++) {
128 struct platform_device *device;
129
130 if (!enable[i])
131 continue;
132
133 device = platform_device_register_simple(DRV_NAME, i, NULL, 0);
134 if (IS_ERR(device))
135 continue;
136
137 devices[i] = device;
138 cards++;
139 }
140
141 if (!cards) {
142#ifdef MODULE
143 printk(KERN_ERR CRD_NAME " soundcard not found or device busy\n");
144#endif
145 platform_driver_unregister(&snd_adlib_driver);
146 return -ENODEV;
147 }
148 return 0;
149}
150
151static void __exit alsa_card_adlib_exit(void)
152{
153 int i;
154
155 for (i = 0; i < SNDRV_CARDS; i++)
156 platform_device_unregister(devices[i]);
157 platform_driver_unregister(&snd_adlib_driver);
158}
159
160module_init(alsa_card_adlib_init);
161module_exit(alsa_card_adlib_exit);
diff --git a/sound/isa/cmi8330.c b/sound/isa/cmi8330.c
index fa63048a8b9d..bc0f5ebf5d3c 100644
--- a/sound/isa/cmi8330.c
+++ b/sound/isa/cmi8330.c
@@ -693,9 +693,9 @@ static int __init alsa_card_cmi8330_init(void)
693 if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0) 693 if ((err = platform_driver_register(&snd_cmi8330_driver)) < 0)
694 return err; 694 return err;
695 695
696 for (i = 0; i < SNDRV_CARDS && enable[i]; i++) { 696 for (i = 0; i < SNDRV_CARDS; i++) {
697 struct platform_device *device; 697 struct platform_device *device;
698 if (is_isapnp_selected(i)) 698 if (! enable[i] || is_isapnp_selected(i))
699 continue; 699 continue;
700 device = platform_device_register_simple(CMI8330_DRIVER, 700 device = platform_device_register_simple(CMI8330_DRIVER,
701 i, NULL, 0); 701 i, NULL, 0);
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..09384d03dc31
--- /dev/null
+++ b/sound/isa/opti9xx/miro.c
@@ -0,0 +1,1455 @@
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_and_free_resource(res);
747 return *port_table;
748 }
749 port_table++;
750 }
751 return -1;
752}
753
754static int __init snd_miro_init(struct snd_miro *chip, unsigned short hardware)
755{
756 static int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2};
757
758 chip->hardware = hardware;
759 strcpy(chip->name, snd_opti9xx_names[hardware]);
760
761 chip->mc_base_size = opti9xx_mc_size[hardware];
762
763 spin_lock_init(&chip->lock);
764
765 chip->wss_base = -1;
766 chip->irq = -1;
767 chip->dma1 = -1;
768 chip->dma2 = -1;
769 chip->fm_port = -1;
770 chip->mpu_port = -1;
771 chip->mpu_irq = -1;
772
773 switch (hardware) {
774 case OPTi9XX_HW_82C929:
775 chip->mc_base = 0xf8c;
776 chip->password = 0xe3;
777 chip->pwd_reg = 3;
778 break;
779
780 case OPTi9XX_HW_82C924:
781 chip->mc_base = 0xf8c;
782 chip->password = 0xe5;
783 chip->pwd_reg = 3;
784 break;
785
786 default:
787 snd_printk(KERN_ERR "sorry, no support for %d\n", hardware);
788 return -ENODEV;
789 }
790
791 return 0;
792}
793
794static unsigned char snd_miro_read(struct snd_miro *chip,
795 unsigned char reg)
796{
797 unsigned long flags;
798 unsigned char retval = 0xff;
799
800 spin_lock_irqsave(&chip->lock, flags);
801 outb(chip->password, chip->mc_base + chip->pwd_reg);
802
803 switch (chip->hardware) {
804 case OPTi9XX_HW_82C924:
805 if (reg > 7) {
806 outb(reg, chip->mc_base + 8);
807 outb(chip->password, chip->mc_base + chip->pwd_reg);
808 retval = inb(chip->mc_base + 9);
809 break;
810 }
811
812 case OPTi9XX_HW_82C929:
813 retval = inb(chip->mc_base + reg);
814 break;
815
816 default:
817 snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
818 }
819
820 spin_unlock_irqrestore(&chip->lock, flags);
821 return retval;
822}
823
824static void snd_miro_write(struct snd_miro *chip, unsigned char reg,
825 unsigned char value)
826{
827 unsigned long flags;
828
829 spin_lock_irqsave(&chip->lock, flags);
830 outb(chip->password, chip->mc_base + chip->pwd_reg);
831
832 switch (chip->hardware) {
833 case OPTi9XX_HW_82C924:
834 if (reg > 7) {
835 outb(reg, chip->mc_base + 8);
836 outb(chip->password, chip->mc_base + chip->pwd_reg);
837 outb(value, chip->mc_base + 9);
838 break;
839 }
840
841 case OPTi9XX_HW_82C929:
842 outb(value, chip->mc_base + reg);
843 break;
844
845 default:
846 snd_printk(KERN_ERR "sorry, no support for %d\n", chip->hardware);
847 }
848
849 spin_unlock_irqrestore(&chip->lock, flags);
850}
851
852
853#define snd_miro_write_mask(chip, reg, value, mask) \
854 snd_miro_write(chip, reg, \
855 (snd_miro_read(chip, reg) & ~(mask)) | ((value) & (mask)))
856
857/*
858 * Proc Interface
859 */
860
861static void snd_miro_proc_read(struct snd_info_entry * entry,
862 struct snd_info_buffer *buffer)
863{
864 struct snd_miro *miro = (struct snd_miro *) entry->private_data;
865 char* model = "unknown";
866
867 /* miroSOUND PCM1 pro, early PCM12 */
868
869 if ((miro->hardware == OPTi9XX_HW_82C929) &&
870 (miro->aci_vendor == 'm') &&
871 (miro->aci_product == 'A')) {
872 switch(miro->aci_version) {
873 case 3:
874 model = "miroSOUND PCM1 pro";
875 break;
876 default:
877 model = "miroSOUND PCM1 pro / (early) PCM12";
878 break;
879 }
880 }
881
882 /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */
883
884 if ((miro->hardware == OPTi9XX_HW_82C924) &&
885 (miro->aci_vendor == 'm') &&
886 (miro->aci_product == 'B')) {
887 switch(miro->aci_version) {
888 case 4:
889 model = "miroSOUND PCM12";
890 break;
891 case 176:
892 model = "miroSOUND PCM12 (Rev. E)";
893 break;
894 default:
895 model = "miroSOUND PCM12 / PCM12 pnp";
896 break;
897 }
898 }
899
900 /* miroSOUND PCM20 radio */
901
902 if ((miro->hardware == OPTi9XX_HW_82C924) &&
903 (miro->aci_vendor == 'm') &&
904 (miro->aci_product == 'C')) {
905 switch(miro->aci_version) {
906 case 7:
907 model = "miroSOUND PCM20 radio (Rev. E)";
908 break;
909 default:
910 model = "miroSOUND PCM20 radio";
911 break;
912 }
913 }
914
915 snd_iprintf(buffer, "\nGeneral information:\n");
916 snd_iprintf(buffer, " model : %s\n", model);
917 snd_iprintf(buffer, " opti : %s\n", miro->name);
918 snd_iprintf(buffer, " codec : %s\n", miro->pcm->name);
919 snd_iprintf(buffer, " port : 0x%lx\n", miro->wss_base);
920 snd_iprintf(buffer, " irq : %d\n", miro->irq);
921 snd_iprintf(buffer, " dma : %d,%d\n\n", miro->dma1, miro->dma2);
922
923 snd_iprintf(buffer, "MPU-401:\n");
924 snd_iprintf(buffer, " port : 0x%lx\n", miro->mpu_port);
925 snd_iprintf(buffer, " irq : %d\n\n", miro->mpu_irq);
926
927 snd_iprintf(buffer, "ACI information:\n");
928 snd_iprintf(buffer, " vendor : ");
929 switch(miro->aci_vendor) {
930 case 'm':
931 snd_iprintf(buffer, "Miro\n");
932 break;
933 default:
934 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_vendor);
935 break;
936 }
937
938 snd_iprintf(buffer, " product : ");
939 switch(miro->aci_product) {
940 case 'A':
941 snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n");
942 break;
943 case 'B':
944 snd_iprintf(buffer, "miroSOUND PCM12\n");
945 break;
946 case 'C':
947 snd_iprintf(buffer, "miroSOUND PCM20 radio\n");
948 break;
949 default:
950 snd_iprintf(buffer, "unknown (0x%x)\n", miro->aci_product);
951 break;
952 }
953
954 snd_iprintf(buffer, " firmware: %d (0x%x)\n",
955 miro->aci_version, miro->aci_version);
956 snd_iprintf(buffer, " port : 0x%lx-0x%lx\n",
957 miro->aci_port, miro->aci_port+2);
958 snd_iprintf(buffer, " wss : 0x%x\n", wss);
959 snd_iprintf(buffer, " ide : 0x%x\n", ide);
960 snd_iprintf(buffer, " solomode: 0x%x\n", miro->aci_solomode);
961 snd_iprintf(buffer, " amp : 0x%x\n", miro->aci_amp);
962 snd_iprintf(buffer, " preamp : 0x%x\n", miro->aci_preamp);
963}
964
965static void __init snd_miro_proc_init(struct snd_miro * miro)
966{
967 struct snd_info_entry *entry;
968
969 if (! snd_card_proc_new(miro->card, "miro", &entry))
970 snd_info_set_text_ops(entry, miro, 1024, snd_miro_proc_read);
971}
972
973/*
974 * Init
975 */
976
977static int __init snd_miro_configure(struct snd_miro *chip)
978{
979 unsigned char wss_base_bits;
980 unsigned char irq_bits;
981 unsigned char dma_bits;
982 unsigned char mpu_port_bits = 0;
983 unsigned char mpu_irq_bits;
984 unsigned long flags;
985
986 switch (chip->hardware) {
987 case OPTi9XX_HW_82C924:
988 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), 0x02, 0x02);
989 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
990 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
991 snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), 0xf0, 0xff);
992 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
993 break;
994 case OPTi9XX_HW_82C929:
995 /* untested init commands for OPTi929 */
996 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), 0x80, 0x80);
997 snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), 0x20, 0x20); /* OPL4 */
998 snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), 0x00, 0x0c);
999 snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), 0x02, 0x02);
1000 break;
1001 default:
1002 snd_printk(KERN_ERR "chip %d not supported\n", chip->hardware);
1003 return -EINVAL;
1004 }
1005
1006 switch (chip->wss_base) {
1007 case 0x530:
1008 wss_base_bits = 0x00;
1009 break;
1010 case 0x604:
1011 wss_base_bits = 0x03;
1012 break;
1013 case 0xe80:
1014 wss_base_bits = 0x01;
1015 break;
1016 case 0xf40:
1017 wss_base_bits = 0x02;
1018 break;
1019 default:
1020 snd_printk(KERN_ERR "WSS port 0x%lx not valid\n", chip->wss_base);
1021 goto __skip_base;
1022 }
1023 snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), wss_base_bits << 4, 0x30);
1024
1025__skip_base:
1026 switch (chip->irq) {
1027 case 5:
1028 irq_bits = 0x05;
1029 break;
1030 case 7:
1031 irq_bits = 0x01;
1032 break;
1033 case 9:
1034 irq_bits = 0x02;
1035 break;
1036 case 10:
1037 irq_bits = 0x03;
1038 break;
1039 case 11:
1040 irq_bits = 0x04;
1041 break;
1042 default:
1043 snd_printk(KERN_ERR "WSS irq # %d not valid\n", chip->irq);
1044 goto __skip_resources;
1045 }
1046
1047 switch (chip->dma1) {
1048 case 0:
1049 dma_bits = 0x01;
1050 break;
1051 case 1:
1052 dma_bits = 0x02;
1053 break;
1054 case 3:
1055 dma_bits = 0x03;
1056 break;
1057 default:
1058 snd_printk(KERN_ERR "WSS dma1 # %d not valid\n", chip->dma1);
1059 goto __skip_resources;
1060 }
1061
1062 if (chip->dma1 == chip->dma2) {
1063 snd_printk(KERN_ERR "don't want to share dmas\n");
1064 return -EBUSY;
1065 }
1066
1067 switch (chip->dma2) {
1068 case 0:
1069 case 1:
1070 break;
1071 default:
1072 snd_printk(KERN_ERR "WSS dma2 # %d not valid\n", chip->dma2);
1073 goto __skip_resources;
1074 }
1075 dma_bits |= 0x04;
1076
1077 spin_lock_irqsave(&chip->lock, flags);
1078 outb(irq_bits << 3 | dma_bits, chip->wss_base);
1079 spin_unlock_irqrestore(&chip->lock, flags);
1080
1081__skip_resources:
1082 if (chip->hardware > OPTi9XX_HW_82C928) {
1083 switch (chip->mpu_port) {
1084 case 0:
1085 case -1:
1086 break;
1087 case 0x300:
1088 mpu_port_bits = 0x03;
1089 break;
1090 case 0x310:
1091 mpu_port_bits = 0x02;
1092 break;
1093 case 0x320:
1094 mpu_port_bits = 0x01;
1095 break;
1096 case 0x330:
1097 mpu_port_bits = 0x00;
1098 break;
1099 default:
1100 snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n",
1101 chip->mpu_port);
1102 goto __skip_mpu;
1103 }
1104
1105 switch (chip->mpu_irq) {
1106 case 5:
1107 mpu_irq_bits = 0x02;
1108 break;
1109 case 7:
1110 mpu_irq_bits = 0x03;
1111 break;
1112 case 9:
1113 mpu_irq_bits = 0x00;
1114 break;
1115 case 10:
1116 mpu_irq_bits = 0x01;
1117 break;
1118 default:
1119 snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n",
1120 chip->mpu_irq);
1121 goto __skip_mpu;
1122 }
1123
1124 snd_miro_write_mask(chip, OPTi9XX_MC_REG(6),
1125 (chip->mpu_port <= 0) ? 0x00 :
1126 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3,
1127 0xf8);
1128 }
1129__skip_mpu:
1130
1131 return 0;
1132}
1133
1134static int __init snd_card_miro_detect(struct snd_card *card, struct snd_miro *chip)
1135{
1136 int i, err;
1137 unsigned char value;
1138
1139 for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) {
1140
1141 if ((err = snd_miro_init(chip, i)) < 0)
1142 return err;
1143
1144 if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL)
1145 continue;
1146
1147 value = snd_miro_read(chip, OPTi9XX_MC_REG(1));
1148 if ((value != 0xff) && (value != inb(chip->mc_base + 1)))
1149 if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1)))
1150 return 1;
1151
1152 release_and_free_resource(chip->res_mc_base);
1153 chip->res_mc_base = NULL;
1154
1155 }
1156
1157 return -ENODEV;
1158}
1159
1160static int __init snd_card_miro_aci_detect(struct snd_card *card, struct snd_miro * miro)
1161{
1162 unsigned char regval;
1163 int i;
1164
1165 mutex_init(&miro->aci_mutex);
1166
1167 /* get ACI port from OPTi9xx MC 4 */
1168
1169 miro->mc_base = 0xf8c;
1170 regval=inb(miro->mc_base + 4);
1171 miro->aci_port = (regval & 0x10) ? 0x344: 0x354;
1172
1173 if ((miro->res_aci_port = request_region(miro->aci_port, 3, "miro aci")) == NULL) {
1174 snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n",
1175 miro->aci_port, miro->aci_port+2);
1176 return -ENOMEM;
1177 }
1178
1179 /* force ACI into a known state */
1180 for (i = 0; i < 3; i++)
1181 if (aci_cmd(miro, ACI_ERROR_OP, -1, -1) < 0) {
1182 snd_card_free(card);
1183 snd_printk(KERN_ERR "can't force aci into known state.\n");
1184 return -ENXIO;
1185 }
1186
1187 if ((miro->aci_vendor=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0 ||
1188 (miro->aci_product=aci_cmd(miro, ACI_READ_IDCODE, -1, -1)) < 0) {
1189 snd_card_free(card);
1190 snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n", miro->aci_port);
1191 return -ENXIO;
1192 }
1193
1194 if ((miro->aci_version=aci_cmd(miro, ACI_READ_VERSION, -1, -1)) < 0) {
1195 snd_card_free(card);
1196 snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n",
1197 miro->aci_port);
1198 return -ENXIO;
1199 }
1200
1201 if (aci_cmd(miro, ACI_INIT, -1, -1) < 0 ||
1202 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 ||
1203 aci_cmd(miro, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) {
1204 snd_printk(KERN_ERR "can't initialize aci.\n");
1205 return -ENXIO;
1206 }
1207
1208 return 0;
1209}
1210
1211static void snd_card_miro_free(struct snd_card *card)
1212{
1213 struct snd_miro *miro = card->private_data;
1214
1215 release_and_free_resource(miro->res_aci_port);
1216 release_and_free_resource(miro->res_mc_base);
1217}
1218
1219static int __init snd_miro_probe(struct platform_device *devptr)
1220{
1221 static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1};
1222 static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1};
1223 static int possible_irqs[] = {11, 9, 10, 7, -1};
1224 static int possible_mpu_irqs[] = {10, 5, 9, 7, -1};
1225 static int possible_dma1s[] = {3, 1, 0, -1};
1226 static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}};
1227
1228 int error;
1229 struct snd_miro *miro;
1230 struct snd_cs4231 *codec;
1231 struct snd_timer *timer;
1232 struct snd_card *card;
1233 struct snd_pcm *pcm;
1234 struct snd_rawmidi *rmidi;
1235
1236 if (!(card = snd_card_new(index, id, THIS_MODULE,
1237 sizeof(struct snd_miro))))
1238 return -ENOMEM;
1239
1240 card->private_free = snd_card_miro_free;
1241 miro = card->private_data;
1242 miro->card = card;
1243
1244 if ((error = snd_card_miro_aci_detect(card, miro)) < 0) {
1245 snd_card_free(card);
1246 snd_printk(KERN_ERR "unable to detect aci chip\n");
1247 return -ENODEV;
1248 }
1249
1250 /* init proc interface */
1251 snd_miro_proc_init(miro);
1252
1253 if ((error = snd_card_miro_detect(card, miro)) < 0) {
1254 snd_card_free(card);
1255 snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n");
1256 return -ENODEV;
1257 }
1258
1259 if (! miro->res_mc_base &&
1260 (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size,
1261 "miro (OPTi9xx MC)")) == NULL) {
1262 snd_card_free(card);
1263 snd_printk(KERN_ERR "request for OPTI9xx MC failed\n");
1264 return -ENOMEM;
1265 }
1266
1267 miro->wss_base = port;
1268 miro->fm_port = fm_port;
1269 miro->mpu_port = mpu_port;
1270 miro->irq = irq;
1271 miro->mpu_irq = mpu_irq;
1272 miro->dma1 = dma1;
1273 miro->dma2 = dma2;
1274
1275 if (miro->wss_base == SNDRV_AUTO_PORT) {
1276 if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) {
1277 snd_card_free(card);
1278 snd_printk(KERN_ERR "unable to find a free WSS port\n");
1279 return -EBUSY;
1280 }
1281 }
1282
1283 if (miro->mpu_port == SNDRV_AUTO_PORT) {
1284 if ((miro->mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2)) < 0) {
1285 snd_card_free(card);
1286 snd_printk(KERN_ERR "unable to find a free MPU401 port\n");
1287 return -EBUSY;
1288 }
1289 }
1290 if (miro->irq == SNDRV_AUTO_IRQ) {
1291 if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) {
1292 snd_card_free(card);
1293 snd_printk(KERN_ERR "unable to find a free IRQ\n");
1294 return -EBUSY;
1295 }
1296 }
1297 if (miro->mpu_irq == SNDRV_AUTO_IRQ) {
1298 if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) {
1299 snd_card_free(card);
1300 snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n");
1301 return -EBUSY;
1302 }
1303 }
1304 if (miro->dma1 == SNDRV_AUTO_DMA) {
1305 if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) {
1306 snd_card_free(card);
1307 snd_printk(KERN_ERR "unable to find a free DMA1\n");
1308 return -EBUSY;
1309 }
1310 }
1311 if (miro->dma2 == SNDRV_AUTO_DMA) {
1312 if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) {
1313 snd_card_free(card);
1314 snd_printk(KERN_ERR "unable to find a free DMA2\n");
1315 return -EBUSY;
1316 }
1317 }
1318
1319 if ((error = snd_miro_configure(miro))) {
1320 snd_card_free(card);
1321 return error;
1322 }
1323
1324 if ((error = snd_cs4231_create(card, miro->wss_base + 4, -1,
1325 miro->irq, miro->dma1, miro->dma2,
1326 CS4231_HW_AD1845,
1327 0,
1328 &codec)) < 0) {
1329 snd_card_free(card);
1330 return error;
1331 }
1332
1333 if ((error = snd_cs4231_pcm(codec, 0, &pcm)) < 0) {
1334 snd_card_free(card);
1335 return error;
1336 }
1337 if ((error = snd_cs4231_mixer(codec)) < 0) {
1338 snd_card_free(card);
1339 return error;
1340 }
1341 if ((error = snd_cs4231_timer(codec, 0, &timer)) < 0) {
1342 snd_card_free(card);
1343 return error;
1344 }
1345
1346 miro->pcm = pcm;
1347
1348 if ((error = snd_miro_mixer(miro)) < 0) {
1349 snd_card_free(card);
1350 return error;
1351 }
1352
1353 if (miro->aci_vendor == 'm') {
1354 /* It looks like a miro sound card. */
1355 switch (miro->aci_product) {
1356 case 'A':
1357 sprintf(card->shortname,
1358 "miroSOUND PCM1 pro / PCM12");
1359 break;
1360 case 'B':
1361 sprintf(card->shortname,
1362 "miroSOUND PCM12");
1363 break;
1364 case 'C':
1365 sprintf(card->shortname,
1366 "miroSOUND PCM20 radio");
1367 break;
1368 default:
1369 sprintf(card->shortname,
1370 "unknown miro");
1371 snd_printk(KERN_INFO "unknown miro aci id\n");
1372 break;
1373 }
1374 } else {
1375 snd_printk(KERN_INFO "found unsupported aci card\n");
1376 sprintf(card->shortname, "unknown Cardinal Technologies");
1377 }
1378
1379 strcpy(card->driver, "miro");
1380 sprintf(card->longname, "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d",
1381 card->shortname, miro->name, pcm->name, miro->wss_base + 4,
1382 miro->irq, miro->dma1, miro->dma2);
1383
1384 if (miro->mpu_port <= 0 || miro->mpu_port == SNDRV_AUTO_PORT)
1385 rmidi = NULL;
1386 else
1387 if ((error = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
1388 miro->mpu_port, 0, miro->mpu_irq, SA_INTERRUPT,
1389 &rmidi)))
1390 snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n", miro->mpu_port);
1391
1392 if (miro->fm_port > 0 && miro->fm_port != SNDRV_AUTO_PORT) {
1393 struct snd_opl3 *opl3 = NULL;
1394 struct snd_opl4 *opl4;
1395 if (snd_opl4_create(card, miro->fm_port, miro->fm_port - 8,
1396 2, &opl3, &opl4) < 0)
1397 snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", miro->fm_port);
1398 }
1399
1400 if ((error = snd_set_aci_init_values(miro)) < 0) {
1401 snd_card_free(card);
1402 return error;
1403 }
1404
1405 snd_card_set_dev(card, &devptr->dev);
1406
1407 if ((error = snd_card_register(card))) {
1408 snd_card_free(card);
1409 return error;
1410 }
1411
1412 platform_set_drvdata(devptr, card);
1413 return 0;
1414}
1415
1416static int __devexit snd_miro_remove(struct platform_device *devptr)
1417{
1418 snd_card_free(platform_get_drvdata(devptr));
1419 platform_set_drvdata(devptr, NULL);
1420 return 0;
1421}
1422
1423static struct platform_driver snd_miro_driver = {
1424 .probe = snd_miro_probe,
1425 .remove = __devexit_p(snd_miro_remove),
1426 /* FIXME: suspend/resume */
1427 .driver = {
1428 .name = DRIVER_NAME
1429 },
1430};
1431
1432static int __init alsa_card_miro_init(void)
1433{
1434 int error;
1435
1436 if ((error = platform_driver_register(&snd_miro_driver)) < 0)
1437 return error;
1438 device = platform_device_register_simple(DRIVER_NAME, -1, NULL, 0);
1439 if (! IS_ERR(device))
1440 return 0;
1441#ifdef MODULE
1442 printk(KERN_ERR "no miro soundcard found\n");
1443#endif
1444 platform_driver_unregister(&snd_miro_driver);
1445 return PTR_ERR(device);
1446}
1447
1448static void __exit alsa_card_miro_exit(void)
1449{
1450 platform_device_unregister(device);
1451 platform_driver_unregister(&snd_miro_driver);
1452}
1453
1454module_init(alsa_card_miro_init)
1455module_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_ */