1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | * ALSA soundcard driver for Miro miroSOUND PCM1 pro |
4 | * miroSOUND PCM12 |
5 | * miroSOUND PCM20 Radio |
6 | * |
7 | * Copyright (C) 2004-2005 Martin Langer <martin-langer@gmx.de> |
8 | * |
9 | * Based on OSS ACI and ALSA OPTi9xx drivers |
10 | */ |
11 | |
12 | #include <linux/init.h> |
13 | #include <linux/err.h> |
14 | #include <linux/isa.h> |
15 | #include <linux/pnp.h> |
16 | #include <linux/delay.h> |
17 | #include <linux/ioport.h> |
18 | #include <linux/module.h> |
19 | #include <linux/io.h> |
20 | #include <asm/dma.h> |
21 | #include <sound/core.h> |
22 | #include <sound/wss.h> |
23 | #include <sound/mpu401.h> |
24 | #include <sound/opl4.h> |
25 | #include <sound/control.h> |
26 | #include <sound/info.h> |
27 | #define SNDRV_LEGACY_FIND_FREE_IOPORT |
28 | #define SNDRV_LEGACY_FIND_FREE_IRQ |
29 | #define SNDRV_LEGACY_FIND_FREE_DMA |
30 | #include <sound/initval.h> |
31 | #include <sound/aci.h> |
32 | |
33 | MODULE_AUTHOR("Martin Langer <martin-langer@gmx.de>" ); |
34 | MODULE_LICENSE("GPL" ); |
35 | MODULE_DESCRIPTION("Miro miroSOUND PCM1 pro, PCM12, PCM20 Radio" ); |
36 | |
37 | static int index = SNDRV_DEFAULT_IDX1; /* Index 0-MAX */ |
38 | static char *id = SNDRV_DEFAULT_STR1; /* ID for this card */ |
39 | static long port = SNDRV_DEFAULT_PORT1; /* 0x530,0xe80,0xf40,0x604 */ |
40 | static long mpu_port = SNDRV_DEFAULT_PORT1; /* 0x300,0x310,0x320,0x330 */ |
41 | static long fm_port = SNDRV_DEFAULT_PORT1; /* 0x388 */ |
42 | static int irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10,11 */ |
43 | static int mpu_irq = SNDRV_DEFAULT_IRQ1; /* 5,7,9,10 */ |
44 | static int dma1 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ |
45 | static int dma2 = SNDRV_DEFAULT_DMA1; /* 0,1,3 */ |
46 | static int wss; |
47 | static int ide; |
48 | #ifdef CONFIG_PNP |
49 | static bool isapnp = 1; /* Enable ISA PnP detection */ |
50 | #endif |
51 | |
52 | module_param(index, int, 0444); |
53 | MODULE_PARM_DESC(index, "Index value for miro soundcard." ); |
54 | module_param(id, charp, 0444); |
55 | MODULE_PARM_DESC(id, "ID string for miro soundcard." ); |
56 | module_param_hw(port, long, ioport, 0444); |
57 | MODULE_PARM_DESC(port, "WSS port # for miro driver." ); |
58 | module_param_hw(mpu_port, long, ioport, 0444); |
59 | MODULE_PARM_DESC(mpu_port, "MPU-401 port # for miro driver." ); |
60 | module_param_hw(fm_port, long, ioport, 0444); |
61 | MODULE_PARM_DESC(fm_port, "FM Port # for miro driver." ); |
62 | module_param_hw(irq, int, irq, 0444); |
63 | MODULE_PARM_DESC(irq, "WSS irq # for miro driver." ); |
64 | module_param_hw(mpu_irq, int, irq, 0444); |
65 | MODULE_PARM_DESC(mpu_irq, "MPU-401 irq # for miro driver." ); |
66 | module_param_hw(dma1, int, dma, 0444); |
67 | MODULE_PARM_DESC(dma1, "1st dma # for miro driver." ); |
68 | module_param_hw(dma2, int, dma, 0444); |
69 | MODULE_PARM_DESC(dma2, "2nd dma # for miro driver." ); |
70 | module_param(wss, int, 0444); |
71 | MODULE_PARM_DESC(wss, "wss mode" ); |
72 | module_param(ide, int, 0444); |
73 | MODULE_PARM_DESC(ide, "enable ide port" ); |
74 | #ifdef CONFIG_PNP |
75 | module_param(isapnp, bool, 0444); |
76 | MODULE_PARM_DESC(isapnp, "Enable ISA PnP detection for specified soundcard." ); |
77 | #endif |
78 | |
79 | #define OPTi9XX_HW_DETECT 0 |
80 | #define OPTi9XX_HW_82C928 1 |
81 | #define OPTi9XX_HW_82C929 2 |
82 | #define OPTi9XX_HW_82C924 3 |
83 | #define OPTi9XX_HW_82C925 4 |
84 | #define OPTi9XX_HW_82C930 5 |
85 | #define OPTi9XX_HW_82C931 6 |
86 | #define OPTi9XX_HW_82C933 7 |
87 | #define OPTi9XX_HW_LAST OPTi9XX_HW_82C933 |
88 | |
89 | #define OPTi9XX_MC_REG(n) n |
90 | |
91 | struct snd_miro { |
92 | unsigned short hardware; |
93 | unsigned char password; |
94 | char name[7]; |
95 | |
96 | struct resource *res_mc_base; |
97 | struct resource *res_aci_port; |
98 | |
99 | unsigned long mc_base; |
100 | unsigned long mc_base_size; |
101 | unsigned long pwd_reg; |
102 | |
103 | spinlock_t lock; |
104 | struct snd_pcm *pcm; |
105 | |
106 | long wss_base; |
107 | int irq; |
108 | int dma1; |
109 | int dma2; |
110 | |
111 | long mpu_port; |
112 | int mpu_irq; |
113 | |
114 | struct snd_miro_aci *aci; |
115 | }; |
116 | |
117 | static struct snd_miro_aci aci_device; |
118 | |
119 | static const char * const snd_opti9xx_names[] = { |
120 | "unknown" , |
121 | "82C928" , "82C929" , |
122 | "82C924" , "82C925" , |
123 | "82C930" , "82C931" , "82C933" |
124 | }; |
125 | |
126 | static int snd_miro_pnp_is_probed; |
127 | |
128 | #ifdef CONFIG_PNP |
129 | |
130 | static const struct pnp_card_device_id snd_miro_pnpids[] = { |
131 | /* PCM20 and PCM12 in PnP mode */ |
132 | { .id = "MIR0924" , |
133 | .devs = { { .id: "MIR0000" }, { "MIR0002" }, { "MIR0005" } }, }, |
134 | { .id = "" } |
135 | }; |
136 | |
137 | MODULE_DEVICE_TABLE(pnp_card, snd_miro_pnpids); |
138 | |
139 | #endif /* CONFIG_PNP */ |
140 | |
141 | /* |
142 | * ACI control |
143 | */ |
144 | |
145 | static int aci_busy_wait(struct snd_miro_aci *aci) |
146 | { |
147 | long timeout; |
148 | unsigned char byte; |
149 | |
150 | for (timeout = 1; timeout <= ACI_MINTIME + 30; timeout++) { |
151 | byte = inb(port: aci->aci_port + ACI_REG_BUSY); |
152 | if ((byte & 1) == 0) { |
153 | if (timeout >= ACI_MINTIME) |
154 | snd_printd("aci ready in round %ld.\n" , |
155 | timeout-ACI_MINTIME); |
156 | return byte; |
157 | } |
158 | if (timeout >= ACI_MINTIME) { |
159 | long out=10*HZ; |
160 | switch (timeout-ACI_MINTIME) { |
161 | case 0 ... 9: |
162 | out /= 10; |
163 | fallthrough; |
164 | case 10 ... 19: |
165 | out /= 10; |
166 | fallthrough; |
167 | case 20 ... 30: |
168 | out /= 10; |
169 | fallthrough; |
170 | default: |
171 | set_current_state(TASK_UNINTERRUPTIBLE); |
172 | schedule_timeout(timeout: out); |
173 | break; |
174 | } |
175 | } |
176 | } |
177 | snd_printk(KERN_ERR "aci_busy_wait() time out\n" ); |
178 | return -EBUSY; |
179 | } |
180 | |
181 | static inline int aci_write(struct snd_miro_aci *aci, unsigned char byte) |
182 | { |
183 | if (aci_busy_wait(aci) >= 0) { |
184 | outb(value: byte, port: aci->aci_port + ACI_REG_COMMAND); |
185 | return 0; |
186 | } else { |
187 | snd_printk(KERN_ERR "aci busy, aci_write(0x%x) stopped.\n" , byte); |
188 | return -EBUSY; |
189 | } |
190 | } |
191 | |
192 | static inline int aci_read(struct snd_miro_aci *aci) |
193 | { |
194 | unsigned char byte; |
195 | |
196 | if (aci_busy_wait(aci) >= 0) { |
197 | byte = inb(port: aci->aci_port + ACI_REG_STATUS); |
198 | return byte; |
199 | } else { |
200 | snd_printk(KERN_ERR "aci busy, aci_read() stopped.\n" ); |
201 | return -EBUSY; |
202 | } |
203 | } |
204 | |
205 | int snd_aci_cmd(struct snd_miro_aci *aci, int write1, int write2, int write3) |
206 | { |
207 | int write[] = {write1, write2, write3}; |
208 | int value, i; |
209 | |
210 | if (mutex_lock_interruptible(&aci->aci_mutex)) |
211 | return -EINTR; |
212 | |
213 | for (i=0; i<3; i++) { |
214 | if (write[i]< 0 || write[i] > 255) |
215 | break; |
216 | else { |
217 | value = aci_write(aci, byte: write[i]); |
218 | if (value < 0) |
219 | goto out; |
220 | } |
221 | } |
222 | |
223 | value = aci_read(aci); |
224 | |
225 | out: mutex_unlock(lock: &aci->aci_mutex); |
226 | return value; |
227 | } |
228 | EXPORT_SYMBOL(snd_aci_cmd); |
229 | |
230 | static int aci_getvalue(struct snd_miro_aci *aci, unsigned char index) |
231 | { |
232 | return snd_aci_cmd(aci, ACI_STATUS, index, -1); |
233 | } |
234 | |
235 | static int aci_setvalue(struct snd_miro_aci *aci, unsigned char index, |
236 | int value) |
237 | { |
238 | return snd_aci_cmd(aci, index, value, -1); |
239 | } |
240 | |
241 | struct snd_miro_aci *snd_aci_get_aci(void) |
242 | { |
243 | if (aci_device.aci_port == 0) |
244 | return NULL; |
245 | return &aci_device; |
246 | } |
247 | EXPORT_SYMBOL(snd_aci_get_aci); |
248 | |
249 | /* |
250 | * MIXER part |
251 | */ |
252 | |
253 | #define snd_miro_info_capture snd_ctl_boolean_mono_info |
254 | |
255 | static int snd_miro_get_capture(struct snd_kcontrol *kcontrol, |
256 | struct snd_ctl_elem_value *ucontrol) |
257 | { |
258 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
259 | int value; |
260 | |
261 | value = aci_getvalue(aci: miro->aci, ACI_S_GENERAL); |
262 | if (value < 0) { |
263 | snd_printk(KERN_ERR "snd_miro_get_capture() failed: %d\n" , |
264 | value); |
265 | return value; |
266 | } |
267 | |
268 | ucontrol->value.integer.value[0] = value & 0x20; |
269 | |
270 | return 0; |
271 | } |
272 | |
273 | static int snd_miro_put_capture(struct snd_kcontrol *kcontrol, |
274 | struct snd_ctl_elem_value *ucontrol) |
275 | { |
276 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
277 | int change, value, error; |
278 | |
279 | value = !(ucontrol->value.integer.value[0]); |
280 | |
281 | error = aci_setvalue(aci: miro->aci, ACI_SET_SOLOMODE, value); |
282 | if (error < 0) { |
283 | snd_printk(KERN_ERR "snd_miro_put_capture() failed: %d\n" , |
284 | error); |
285 | return error; |
286 | } |
287 | |
288 | change = (value != miro->aci->aci_solomode); |
289 | miro->aci->aci_solomode = value; |
290 | |
291 | return change; |
292 | } |
293 | |
294 | static int snd_miro_info_preamp(struct snd_kcontrol *kcontrol, |
295 | struct snd_ctl_elem_info *uinfo) |
296 | { |
297 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
298 | uinfo->count = 1; |
299 | uinfo->value.integer.min = 0; |
300 | uinfo->value.integer.max = 3; |
301 | |
302 | return 0; |
303 | } |
304 | |
305 | static int snd_miro_get_preamp(struct snd_kcontrol *kcontrol, |
306 | struct snd_ctl_elem_value *ucontrol) |
307 | { |
308 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
309 | int value; |
310 | |
311 | if (miro->aci->aci_version <= 176) { |
312 | |
313 | /* |
314 | OSS says it's not readable with versions < 176. |
315 | But it doesn't work on my card, |
316 | which is a PCM12 with aci_version = 176. |
317 | */ |
318 | |
319 | ucontrol->value.integer.value[0] = miro->aci->aci_preamp; |
320 | return 0; |
321 | } |
322 | |
323 | value = aci_getvalue(aci: miro->aci, ACI_GET_PREAMP); |
324 | if (value < 0) { |
325 | snd_printk(KERN_ERR "snd_miro_get_preamp() failed: %d\n" , |
326 | value); |
327 | return value; |
328 | } |
329 | |
330 | ucontrol->value.integer.value[0] = value; |
331 | |
332 | return 0; |
333 | } |
334 | |
335 | static int snd_miro_put_preamp(struct snd_kcontrol *kcontrol, |
336 | struct snd_ctl_elem_value *ucontrol) |
337 | { |
338 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
339 | int error, value, change; |
340 | |
341 | value = ucontrol->value.integer.value[0]; |
342 | |
343 | error = aci_setvalue(aci: miro->aci, ACI_SET_PREAMP, value); |
344 | if (error < 0) { |
345 | snd_printk(KERN_ERR "snd_miro_put_preamp() failed: %d\n" , |
346 | error); |
347 | return error; |
348 | } |
349 | |
350 | change = (value != miro->aci->aci_preamp); |
351 | miro->aci->aci_preamp = value; |
352 | |
353 | return change; |
354 | } |
355 | |
356 | #define snd_miro_info_amp snd_ctl_boolean_mono_info |
357 | |
358 | static int snd_miro_get_amp(struct snd_kcontrol *kcontrol, |
359 | struct snd_ctl_elem_value *ucontrol) |
360 | { |
361 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
362 | ucontrol->value.integer.value[0] = miro->aci->aci_amp; |
363 | |
364 | return 0; |
365 | } |
366 | |
367 | static int snd_miro_put_amp(struct snd_kcontrol *kcontrol, |
368 | struct snd_ctl_elem_value *ucontrol) |
369 | { |
370 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
371 | int error, value, change; |
372 | |
373 | value = ucontrol->value.integer.value[0]; |
374 | |
375 | error = aci_setvalue(aci: miro->aci, ACI_SET_POWERAMP, value); |
376 | if (error < 0) { |
377 | snd_printk(KERN_ERR "snd_miro_put_amp() to %d failed: %d\n" , value, error); |
378 | return error; |
379 | } |
380 | |
381 | change = (value != miro->aci->aci_amp); |
382 | miro->aci->aci_amp = value; |
383 | |
384 | return change; |
385 | } |
386 | |
387 | #define MIRO_DOUBLE(ctl_name, ctl_index, get_right_reg, set_right_reg) \ |
388 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, \ |
389 | .name = ctl_name, \ |
390 | .index = ctl_index, \ |
391 | .info = snd_miro_info_double, \ |
392 | .get = snd_miro_get_double, \ |
393 | .put = snd_miro_put_double, \ |
394 | .private_value = get_right_reg | (set_right_reg << 8) \ |
395 | } |
396 | |
397 | static int snd_miro_info_double(struct snd_kcontrol *kcontrol, |
398 | struct snd_ctl_elem_info *uinfo) |
399 | { |
400 | int reg = kcontrol->private_value & 0xff; |
401 | |
402 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; |
403 | uinfo->count = 2; |
404 | |
405 | if ((reg >= ACI_GET_EQ1) && (reg <= ACI_GET_EQ7)) { |
406 | |
407 | /* equalizer elements */ |
408 | |
409 | uinfo->value.integer.min = - 0x7f; |
410 | uinfo->value.integer.max = 0x7f; |
411 | } else { |
412 | |
413 | /* non-equalizer elements */ |
414 | |
415 | uinfo->value.integer.min = 0; |
416 | uinfo->value.integer.max = 0x20; |
417 | } |
418 | |
419 | return 0; |
420 | } |
421 | |
422 | static int snd_miro_get_double(struct snd_kcontrol *kcontrol, |
423 | struct snd_ctl_elem_value *uinfo) |
424 | { |
425 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
426 | int left_val, right_val; |
427 | |
428 | int right_reg = kcontrol->private_value & 0xff; |
429 | int left_reg = right_reg + 1; |
430 | |
431 | right_val = aci_getvalue(aci: miro->aci, index: right_reg); |
432 | if (right_val < 0) { |
433 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n" , right_reg, right_val); |
434 | return right_val; |
435 | } |
436 | |
437 | left_val = aci_getvalue(aci: miro->aci, index: left_reg); |
438 | if (left_val < 0) { |
439 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n" , left_reg, left_val); |
440 | return left_val; |
441 | } |
442 | |
443 | if ((right_reg >= ACI_GET_EQ1) && (right_reg <= ACI_GET_EQ7)) { |
444 | |
445 | /* equalizer elements */ |
446 | |
447 | if (left_val < 0x80) { |
448 | uinfo->value.integer.value[0] = left_val; |
449 | } else { |
450 | uinfo->value.integer.value[0] = 0x80 - left_val; |
451 | } |
452 | |
453 | if (right_val < 0x80) { |
454 | uinfo->value.integer.value[1] = right_val; |
455 | } else { |
456 | uinfo->value.integer.value[1] = 0x80 - right_val; |
457 | } |
458 | |
459 | } else { |
460 | |
461 | /* non-equalizer elements */ |
462 | |
463 | uinfo->value.integer.value[0] = 0x20 - left_val; |
464 | uinfo->value.integer.value[1] = 0x20 - right_val; |
465 | } |
466 | |
467 | return 0; |
468 | } |
469 | |
470 | static int snd_miro_put_double(struct snd_kcontrol *kcontrol, |
471 | struct snd_ctl_elem_value *ucontrol) |
472 | { |
473 | struct snd_miro *miro = snd_kcontrol_chip(kcontrol); |
474 | struct snd_miro_aci *aci = miro->aci; |
475 | int left, right, left_old, right_old; |
476 | int setreg_left, setreg_right, getreg_left, getreg_right; |
477 | int change, error; |
478 | |
479 | left = ucontrol->value.integer.value[0]; |
480 | right = ucontrol->value.integer.value[1]; |
481 | |
482 | setreg_right = (kcontrol->private_value >> 8) & 0xff; |
483 | setreg_left = setreg_right + 8; |
484 | if (setreg_right == ACI_SET_MASTER) |
485 | setreg_left -= 7; |
486 | |
487 | getreg_right = kcontrol->private_value & 0xff; |
488 | getreg_left = getreg_right + 1; |
489 | |
490 | left_old = aci_getvalue(aci, index: getreg_left); |
491 | if (left_old < 0) { |
492 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n" , getreg_left, left_old); |
493 | return left_old; |
494 | } |
495 | |
496 | right_old = aci_getvalue(aci, index: getreg_right); |
497 | if (right_old < 0) { |
498 | snd_printk(KERN_ERR "aci_getvalue(%d) failed: %d\n" , getreg_right, right_old); |
499 | return right_old; |
500 | } |
501 | |
502 | if ((getreg_right >= ACI_GET_EQ1) && (getreg_right <= ACI_GET_EQ7)) { |
503 | |
504 | /* equalizer elements */ |
505 | |
506 | if (left < -0x7f || left > 0x7f || |
507 | right < -0x7f || right > 0x7f) |
508 | return -EINVAL; |
509 | |
510 | if (left_old > 0x80) |
511 | left_old = 0x80 - left_old; |
512 | if (right_old > 0x80) |
513 | right_old = 0x80 - right_old; |
514 | |
515 | if (left >= 0) { |
516 | error = aci_setvalue(aci, index: setreg_left, value: left); |
517 | if (error < 0) { |
518 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
519 | left, error); |
520 | return error; |
521 | } |
522 | } else { |
523 | error = aci_setvalue(aci, index: setreg_left, value: 0x80 - left); |
524 | if (error < 0) { |
525 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
526 | 0x80 - left, error); |
527 | return error; |
528 | } |
529 | } |
530 | |
531 | if (right >= 0) { |
532 | error = aci_setvalue(aci, index: setreg_right, value: right); |
533 | if (error < 0) { |
534 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
535 | right, error); |
536 | return error; |
537 | } |
538 | } else { |
539 | error = aci_setvalue(aci, index: setreg_right, value: 0x80 - right); |
540 | if (error < 0) { |
541 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
542 | 0x80 - right, error); |
543 | return error; |
544 | } |
545 | } |
546 | |
547 | } else { |
548 | |
549 | /* non-equalizer elements */ |
550 | |
551 | if (left < 0 || left > 0x20 || |
552 | right < 0 || right > 0x20) |
553 | return -EINVAL; |
554 | |
555 | left_old = 0x20 - left_old; |
556 | right_old = 0x20 - right_old; |
557 | |
558 | error = aci_setvalue(aci, index: setreg_left, value: 0x20 - left); |
559 | if (error < 0) { |
560 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
561 | 0x20 - left, error); |
562 | return error; |
563 | } |
564 | error = aci_setvalue(aci, index: setreg_right, value: 0x20 - right); |
565 | if (error < 0) { |
566 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
567 | 0x20 - right, error); |
568 | return error; |
569 | } |
570 | } |
571 | |
572 | change = (left != left_old) || (right != right_old); |
573 | |
574 | return change; |
575 | } |
576 | |
577 | static const struct snd_kcontrol_new snd_miro_controls[] = { |
578 | MIRO_DOUBLE("Master Playback Volume" , 0, ACI_GET_MASTER, ACI_SET_MASTER), |
579 | MIRO_DOUBLE("Mic Playback Volume" , 1, ACI_GET_MIC, ACI_SET_MIC), |
580 | MIRO_DOUBLE("Line Playback Volume" , 1, ACI_GET_LINE, ACI_SET_LINE), |
581 | MIRO_DOUBLE("CD Playback Volume" , 0, ACI_GET_CD, ACI_SET_CD), |
582 | MIRO_DOUBLE("Synth Playback Volume" , 0, ACI_GET_SYNTH, ACI_SET_SYNTH), |
583 | MIRO_DOUBLE("PCM Playback Volume" , 1, ACI_GET_PCM, ACI_SET_PCM), |
584 | MIRO_DOUBLE("Aux Playback Volume" , 2, ACI_GET_LINE2, ACI_SET_LINE2), |
585 | }; |
586 | |
587 | /* Equalizer with seven bands (only PCM20) |
588 | from -12dB up to +12dB on each band */ |
589 | static const struct snd_kcontrol_new snd_miro_eq_controls[] = { |
590 | MIRO_DOUBLE("Tone Control - 28 Hz" , 0, ACI_GET_EQ1, ACI_SET_EQ1), |
591 | MIRO_DOUBLE("Tone Control - 160 Hz" , 0, ACI_GET_EQ2, ACI_SET_EQ2), |
592 | MIRO_DOUBLE("Tone Control - 400 Hz" , 0, ACI_GET_EQ3, ACI_SET_EQ3), |
593 | MIRO_DOUBLE("Tone Control - 1 kHz" , 0, ACI_GET_EQ4, ACI_SET_EQ4), |
594 | MIRO_DOUBLE("Tone Control - 2.5 kHz" , 0, ACI_GET_EQ5, ACI_SET_EQ5), |
595 | MIRO_DOUBLE("Tone Control - 6.3 kHz" , 0, ACI_GET_EQ6, ACI_SET_EQ6), |
596 | MIRO_DOUBLE("Tone Control - 16 kHz" , 0, ACI_GET_EQ7, ACI_SET_EQ7), |
597 | }; |
598 | |
599 | static const struct snd_kcontrol_new snd_miro_radio_control[] = { |
600 | MIRO_DOUBLE("Radio Playback Volume" , 0, ACI_GET_LINE1, ACI_SET_LINE1), |
601 | }; |
602 | |
603 | static const struct snd_kcontrol_new snd_miro_line_control[] = { |
604 | MIRO_DOUBLE("Line Playback Volume" , 2, ACI_GET_LINE1, ACI_SET_LINE1), |
605 | }; |
606 | |
607 | static const struct snd_kcontrol_new snd_miro_preamp_control[] = { |
608 | { |
609 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
610 | .name = "Mic Boost" , |
611 | .index = 1, |
612 | .info = snd_miro_info_preamp, |
613 | .get = snd_miro_get_preamp, |
614 | .put = snd_miro_put_preamp, |
615 | }}; |
616 | |
617 | static const struct snd_kcontrol_new snd_miro_amp_control[] = { |
618 | { |
619 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
620 | .name = "Line Boost" , |
621 | .index = 0, |
622 | .info = snd_miro_info_amp, |
623 | .get = snd_miro_get_amp, |
624 | .put = snd_miro_put_amp, |
625 | }}; |
626 | |
627 | static const struct snd_kcontrol_new snd_miro_capture_control[] = { |
628 | { |
629 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, |
630 | .name = "PCM Capture Switch" , |
631 | .index = 0, |
632 | .info = snd_miro_info_capture, |
633 | .get = snd_miro_get_capture, |
634 | .put = snd_miro_put_capture, |
635 | }}; |
636 | |
637 | static const unsigned char aci_init_values[][2] = { |
638 | { ACI_SET_MUTE, 0x00 }, |
639 | { ACI_SET_POWERAMP, 0x00 }, |
640 | { ACI_SET_PREAMP, 0x00 }, |
641 | { ACI_SET_SOLOMODE, 0x00 }, |
642 | { ACI_SET_MIC + 0, 0x20 }, |
643 | { ACI_SET_MIC + 8, 0x20 }, |
644 | { ACI_SET_LINE + 0, 0x20 }, |
645 | { ACI_SET_LINE + 8, 0x20 }, |
646 | { ACI_SET_CD + 0, 0x20 }, |
647 | { ACI_SET_CD + 8, 0x20 }, |
648 | { ACI_SET_PCM + 0, 0x20 }, |
649 | { ACI_SET_PCM + 8, 0x20 }, |
650 | { ACI_SET_LINE1 + 0, 0x20 }, |
651 | { ACI_SET_LINE1 + 8, 0x20 }, |
652 | { ACI_SET_LINE2 + 0, 0x20 }, |
653 | { ACI_SET_LINE2 + 8, 0x20 }, |
654 | { ACI_SET_SYNTH + 0, 0x20 }, |
655 | { ACI_SET_SYNTH + 8, 0x20 }, |
656 | { ACI_SET_MASTER + 0, 0x20 }, |
657 | { ACI_SET_MASTER + 1, 0x20 }, |
658 | }; |
659 | |
660 | static int snd_set_aci_init_values(struct snd_miro *miro) |
661 | { |
662 | int idx, error; |
663 | struct snd_miro_aci *aci = miro->aci; |
664 | |
665 | /* enable WSS on PCM1 */ |
666 | |
667 | if ((aci->aci_product == 'A') && wss) { |
668 | error = aci_setvalue(aci, ACI_SET_WSS, value: wss); |
669 | if (error < 0) { |
670 | snd_printk(KERN_ERR "enabling WSS mode failed\n" ); |
671 | return error; |
672 | } |
673 | } |
674 | |
675 | /* enable IDE port */ |
676 | |
677 | if (ide) { |
678 | error = aci_setvalue(aci, ACI_SET_IDE, value: ide); |
679 | if (error < 0) { |
680 | snd_printk(KERN_ERR "enabling IDE port failed\n" ); |
681 | return error; |
682 | } |
683 | } |
684 | |
685 | /* set common aci values */ |
686 | |
687 | for (idx = 0; idx < ARRAY_SIZE(aci_init_values); idx++) { |
688 | error = aci_setvalue(aci, index: aci_init_values[idx][0], |
689 | value: aci_init_values[idx][1]); |
690 | if (error < 0) { |
691 | snd_printk(KERN_ERR "aci_setvalue(%d) failed: %d\n" , |
692 | aci_init_values[idx][0], error); |
693 | return error; |
694 | } |
695 | } |
696 | aci->aci_amp = 0; |
697 | aci->aci_preamp = 0; |
698 | aci->aci_solomode = 1; |
699 | |
700 | return 0; |
701 | } |
702 | |
703 | static int snd_miro_mixer(struct snd_card *card, |
704 | struct snd_miro *miro) |
705 | { |
706 | unsigned int idx; |
707 | int err; |
708 | |
709 | if (snd_BUG_ON(!miro || !card)) |
710 | return -EINVAL; |
711 | |
712 | switch (miro->hardware) { |
713 | case OPTi9XX_HW_82C924: |
714 | strcpy(p: card->mixername, q: "ACI & OPTi924" ); |
715 | break; |
716 | case OPTi9XX_HW_82C929: |
717 | strcpy(p: card->mixername, q: "ACI & OPTi929" ); |
718 | break; |
719 | default: |
720 | snd_BUG(); |
721 | break; |
722 | } |
723 | |
724 | for (idx = 0; idx < ARRAY_SIZE(snd_miro_controls); idx++) { |
725 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_controls[idx], private_data: miro)); |
726 | if (err < 0) |
727 | return err; |
728 | } |
729 | |
730 | if ((miro->aci->aci_product == 'A') || |
731 | (miro->aci->aci_product == 'B')) { |
732 | /* PCM1/PCM12 with power-amp and Line 2 */ |
733 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_line_control[0], private_data: miro)); |
734 | if (err < 0) |
735 | return err; |
736 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_amp_control[0], private_data: miro)); |
737 | if (err < 0) |
738 | return err; |
739 | } |
740 | |
741 | if ((miro->aci->aci_product == 'B') || |
742 | (miro->aci->aci_product == 'C')) { |
743 | /* PCM12/PCM20 with mic-preamp */ |
744 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_preamp_control[0], private_data: miro)); |
745 | if (err < 0) |
746 | return err; |
747 | if (miro->aci->aci_version >= 176) { |
748 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_capture_control[0], private_data: miro)); |
749 | if (err < 0) |
750 | return err; |
751 | } |
752 | } |
753 | |
754 | if (miro->aci->aci_product == 'C') { |
755 | /* PCM20 with radio and 7 band equalizer */ |
756 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_radio_control[0], private_data: miro)); |
757 | if (err < 0) |
758 | return err; |
759 | for (idx = 0; idx < ARRAY_SIZE(snd_miro_eq_controls); idx++) { |
760 | err = snd_ctl_add(card, kcontrol: snd_ctl_new1(kcontrolnew: &snd_miro_eq_controls[idx], private_data: miro)); |
761 | if (err < 0) |
762 | return err; |
763 | } |
764 | } |
765 | |
766 | return 0; |
767 | } |
768 | |
769 | static int snd_miro_init(struct snd_miro *chip, |
770 | unsigned short hardware) |
771 | { |
772 | static const int opti9xx_mc_size[] = {7, 7, 10, 10, 2, 2, 2}; |
773 | |
774 | chip->hardware = hardware; |
775 | strcpy(p: chip->name, q: snd_opti9xx_names[hardware]); |
776 | |
777 | chip->mc_base_size = opti9xx_mc_size[hardware]; |
778 | |
779 | spin_lock_init(&chip->lock); |
780 | |
781 | chip->wss_base = -1; |
782 | chip->irq = -1; |
783 | chip->dma1 = -1; |
784 | chip->dma2 = -1; |
785 | chip->mpu_port = -1; |
786 | chip->mpu_irq = -1; |
787 | |
788 | chip->pwd_reg = 3; |
789 | |
790 | #ifdef CONFIG_PNP |
791 | if (isapnp && chip->mc_base) |
792 | /* PnP resource gives the least 10 bits */ |
793 | chip->mc_base |= 0xc00; |
794 | else |
795 | #endif |
796 | chip->mc_base = 0xf8c; |
797 | |
798 | switch (hardware) { |
799 | case OPTi9XX_HW_82C929: |
800 | chip->password = 0xe3; |
801 | break; |
802 | |
803 | case OPTi9XX_HW_82C924: |
804 | chip->password = 0xe5; |
805 | break; |
806 | |
807 | default: |
808 | snd_printk(KERN_ERR "sorry, no support for %d\n" , hardware); |
809 | return -ENODEV; |
810 | } |
811 | |
812 | return 0; |
813 | } |
814 | |
815 | static unsigned char snd_miro_read(struct snd_miro *chip, |
816 | unsigned char reg) |
817 | { |
818 | unsigned long flags; |
819 | unsigned char retval = 0xff; |
820 | |
821 | spin_lock_irqsave(&chip->lock, flags); |
822 | outb(value: chip->password, port: chip->mc_base + chip->pwd_reg); |
823 | |
824 | switch (chip->hardware) { |
825 | case OPTi9XX_HW_82C924: |
826 | if (reg > 7) { |
827 | outb(value: reg, port: chip->mc_base + 8); |
828 | outb(value: chip->password, port: chip->mc_base + chip->pwd_reg); |
829 | retval = inb(port: chip->mc_base + 9); |
830 | break; |
831 | } |
832 | fallthrough; |
833 | |
834 | case OPTi9XX_HW_82C929: |
835 | retval = inb(port: chip->mc_base + reg); |
836 | break; |
837 | |
838 | default: |
839 | snd_printk(KERN_ERR "sorry, no support for %d\n" , chip->hardware); |
840 | } |
841 | |
842 | spin_unlock_irqrestore(lock: &chip->lock, flags); |
843 | return retval; |
844 | } |
845 | |
846 | static void snd_miro_write(struct snd_miro *chip, unsigned char reg, |
847 | unsigned char value) |
848 | { |
849 | unsigned long flags; |
850 | |
851 | spin_lock_irqsave(&chip->lock, flags); |
852 | outb(value: chip->password, port: chip->mc_base + chip->pwd_reg); |
853 | |
854 | switch (chip->hardware) { |
855 | case OPTi9XX_HW_82C924: |
856 | if (reg > 7) { |
857 | outb(value: reg, port: chip->mc_base + 8); |
858 | outb(value: chip->password, port: chip->mc_base + chip->pwd_reg); |
859 | outb(value, port: chip->mc_base + 9); |
860 | break; |
861 | } |
862 | fallthrough; |
863 | |
864 | case OPTi9XX_HW_82C929: |
865 | outb(value, port: chip->mc_base + reg); |
866 | break; |
867 | |
868 | default: |
869 | snd_printk(KERN_ERR "sorry, no support for %d\n" , chip->hardware); |
870 | } |
871 | |
872 | spin_unlock_irqrestore(lock: &chip->lock, flags); |
873 | } |
874 | |
875 | static inline void snd_miro_write_mask(struct snd_miro *chip, |
876 | unsigned char reg, unsigned char value, unsigned char mask) |
877 | { |
878 | unsigned char oldval = snd_miro_read(chip, reg); |
879 | |
880 | snd_miro_write(chip, reg, value: (oldval & ~mask) | (value & mask)); |
881 | } |
882 | |
883 | /* |
884 | * Proc Interface |
885 | */ |
886 | |
887 | static void snd_miro_proc_read(struct snd_info_entry * entry, |
888 | struct snd_info_buffer *buffer) |
889 | { |
890 | struct snd_miro *miro = (struct snd_miro *) entry->private_data; |
891 | struct snd_miro_aci *aci = miro->aci; |
892 | char* model = "unknown" ; |
893 | |
894 | /* miroSOUND PCM1 pro, early PCM12 */ |
895 | |
896 | if ((miro->hardware == OPTi9XX_HW_82C929) && |
897 | (aci->aci_vendor == 'm') && |
898 | (aci->aci_product == 'A')) { |
899 | switch (aci->aci_version) { |
900 | case 3: |
901 | model = "miroSOUND PCM1 pro" ; |
902 | break; |
903 | default: |
904 | model = "miroSOUND PCM1 pro / (early) PCM12" ; |
905 | break; |
906 | } |
907 | } |
908 | |
909 | /* miroSOUND PCM12, PCM12 (Rev. E), PCM12 pnp */ |
910 | |
911 | if ((miro->hardware == OPTi9XX_HW_82C924) && |
912 | (aci->aci_vendor == 'm') && |
913 | (aci->aci_product == 'B')) { |
914 | switch (aci->aci_version) { |
915 | case 4: |
916 | model = "miroSOUND PCM12" ; |
917 | break; |
918 | case 176: |
919 | model = "miroSOUND PCM12 (Rev. E)" ; |
920 | break; |
921 | default: |
922 | model = "miroSOUND PCM12 / PCM12 pnp" ; |
923 | break; |
924 | } |
925 | } |
926 | |
927 | /* miroSOUND PCM20 radio */ |
928 | |
929 | if ((miro->hardware == OPTi9XX_HW_82C924) && |
930 | (aci->aci_vendor == 'm') && |
931 | (aci->aci_product == 'C')) { |
932 | switch (aci->aci_version) { |
933 | case 7: |
934 | model = "miroSOUND PCM20 radio (Rev. E)" ; |
935 | break; |
936 | default: |
937 | model = "miroSOUND PCM20 radio" ; |
938 | break; |
939 | } |
940 | } |
941 | |
942 | snd_iprintf(buffer, "\nGeneral information:\n" ); |
943 | snd_iprintf(buffer, " model : %s\n" , model); |
944 | snd_iprintf(buffer, " opti : %s\n" , miro->name); |
945 | snd_iprintf(buffer, " codec : %s\n" , miro->pcm->name); |
946 | snd_iprintf(buffer, " port : 0x%lx\n" , miro->wss_base); |
947 | snd_iprintf(buffer, " irq : %d\n" , miro->irq); |
948 | snd_iprintf(buffer, " dma : %d,%d\n\n" , miro->dma1, miro->dma2); |
949 | |
950 | snd_iprintf(buffer, "MPU-401:\n" ); |
951 | snd_iprintf(buffer, " port : 0x%lx\n" , miro->mpu_port); |
952 | snd_iprintf(buffer, " irq : %d\n\n" , miro->mpu_irq); |
953 | |
954 | snd_iprintf(buffer, "ACI information:\n" ); |
955 | snd_iprintf(buffer, " vendor : " ); |
956 | switch (aci->aci_vendor) { |
957 | case 'm': |
958 | snd_iprintf(buffer, "Miro\n" ); |
959 | break; |
960 | default: |
961 | snd_iprintf(buffer, "unknown (0x%x)\n" , aci->aci_vendor); |
962 | break; |
963 | } |
964 | |
965 | snd_iprintf(buffer, " product : " ); |
966 | switch (aci->aci_product) { |
967 | case 'A': |
968 | snd_iprintf(buffer, "miroSOUND PCM1 pro / (early) PCM12\n" ); |
969 | break; |
970 | case 'B': |
971 | snd_iprintf(buffer, "miroSOUND PCM12\n" ); |
972 | break; |
973 | case 'C': |
974 | snd_iprintf(buffer, "miroSOUND PCM20 radio\n" ); |
975 | break; |
976 | default: |
977 | snd_iprintf(buffer, "unknown (0x%x)\n" , aci->aci_product); |
978 | break; |
979 | } |
980 | |
981 | snd_iprintf(buffer, " firmware: %d (0x%x)\n" , |
982 | aci->aci_version, aci->aci_version); |
983 | snd_iprintf(buffer, " port : 0x%lx-0x%lx\n" , |
984 | aci->aci_port, aci->aci_port+2); |
985 | snd_iprintf(buffer, " wss : 0x%x\n" , wss); |
986 | snd_iprintf(buffer, " ide : 0x%x\n" , ide); |
987 | snd_iprintf(buffer, " solomode: 0x%x\n" , aci->aci_solomode); |
988 | snd_iprintf(buffer, " amp : 0x%x\n" , aci->aci_amp); |
989 | snd_iprintf(buffer, " preamp : 0x%x\n" , aci->aci_preamp); |
990 | } |
991 | |
992 | static void snd_miro_proc_init(struct snd_card *card, |
993 | struct snd_miro *miro) |
994 | { |
995 | snd_card_ro_proc_new(card, name: "miro" , private_data: miro, read: snd_miro_proc_read); |
996 | } |
997 | |
998 | /* |
999 | * Init |
1000 | */ |
1001 | |
1002 | static int snd_miro_configure(struct snd_miro *chip) |
1003 | { |
1004 | unsigned char wss_base_bits; |
1005 | unsigned char irq_bits; |
1006 | unsigned char dma_bits; |
1007 | unsigned char mpu_port_bits = 0; |
1008 | unsigned char mpu_irq_bits; |
1009 | unsigned long flags; |
1010 | |
1011 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), value: 0x80, mask: 0x80); |
1012 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(2), value: 0x20, mask: 0x20); /* OPL4 */ |
1013 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(5), value: 0x02, mask: 0x02); |
1014 | |
1015 | switch (chip->hardware) { |
1016 | case OPTi9XX_HW_82C924: |
1017 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), value: 0x02, mask: 0x02); |
1018 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(3), value: 0xf0, mask: 0xff); |
1019 | break; |
1020 | case OPTi9XX_HW_82C929: |
1021 | /* untested init commands for OPTi929 */ |
1022 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(4), value: 0x00, mask: 0x0c); |
1023 | break; |
1024 | default: |
1025 | snd_printk(KERN_ERR "chip %d not supported\n" , chip->hardware); |
1026 | return -EINVAL; |
1027 | } |
1028 | |
1029 | /* PnP resource says it decodes only 10 bits of address */ |
1030 | switch (chip->wss_base & 0x3ff) { |
1031 | case 0x130: |
1032 | chip->wss_base = 0x530; |
1033 | wss_base_bits = 0x00; |
1034 | break; |
1035 | case 0x204: |
1036 | chip->wss_base = 0x604; |
1037 | wss_base_bits = 0x03; |
1038 | break; |
1039 | case 0x280: |
1040 | chip->wss_base = 0xe80; |
1041 | wss_base_bits = 0x01; |
1042 | break; |
1043 | case 0x340: |
1044 | chip->wss_base = 0xf40; |
1045 | wss_base_bits = 0x02; |
1046 | break; |
1047 | default: |
1048 | snd_printk(KERN_ERR "WSS port 0x%lx not valid\n" , chip->wss_base); |
1049 | goto __skip_base; |
1050 | } |
1051 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(1), value: wss_base_bits << 4, mask: 0x30); |
1052 | |
1053 | __skip_base: |
1054 | switch (chip->irq) { |
1055 | case 5: |
1056 | irq_bits = 0x05; |
1057 | break; |
1058 | case 7: |
1059 | irq_bits = 0x01; |
1060 | break; |
1061 | case 9: |
1062 | irq_bits = 0x02; |
1063 | break; |
1064 | case 10: |
1065 | irq_bits = 0x03; |
1066 | break; |
1067 | case 11: |
1068 | irq_bits = 0x04; |
1069 | break; |
1070 | default: |
1071 | snd_printk(KERN_ERR "WSS irq # %d not valid\n" , chip->irq); |
1072 | goto __skip_resources; |
1073 | } |
1074 | |
1075 | switch (chip->dma1) { |
1076 | case 0: |
1077 | dma_bits = 0x01; |
1078 | break; |
1079 | case 1: |
1080 | dma_bits = 0x02; |
1081 | break; |
1082 | case 3: |
1083 | dma_bits = 0x03; |
1084 | break; |
1085 | default: |
1086 | snd_printk(KERN_ERR "WSS dma1 # %d not valid\n" , chip->dma1); |
1087 | goto __skip_resources; |
1088 | } |
1089 | |
1090 | if (chip->dma1 == chip->dma2) { |
1091 | snd_printk(KERN_ERR "don't want to share dmas\n" ); |
1092 | return -EBUSY; |
1093 | } |
1094 | |
1095 | switch (chip->dma2) { |
1096 | case 0: |
1097 | case 1: |
1098 | break; |
1099 | default: |
1100 | snd_printk(KERN_ERR "WSS dma2 # %d not valid\n" , chip->dma2); |
1101 | goto __skip_resources; |
1102 | } |
1103 | dma_bits |= 0x04; |
1104 | |
1105 | spin_lock_irqsave(&chip->lock, flags); |
1106 | outb(value: irq_bits << 3 | dma_bits, port: chip->wss_base); |
1107 | spin_unlock_irqrestore(lock: &chip->lock, flags); |
1108 | |
1109 | __skip_resources: |
1110 | if (chip->hardware > OPTi9XX_HW_82C928) { |
1111 | switch (chip->mpu_port) { |
1112 | case 0: |
1113 | case -1: |
1114 | break; |
1115 | case 0x300: |
1116 | mpu_port_bits = 0x03; |
1117 | break; |
1118 | case 0x310: |
1119 | mpu_port_bits = 0x02; |
1120 | break; |
1121 | case 0x320: |
1122 | mpu_port_bits = 0x01; |
1123 | break; |
1124 | case 0x330: |
1125 | mpu_port_bits = 0x00; |
1126 | break; |
1127 | default: |
1128 | snd_printk(KERN_ERR "MPU-401 port 0x%lx not valid\n" , |
1129 | chip->mpu_port); |
1130 | goto __skip_mpu; |
1131 | } |
1132 | |
1133 | switch (chip->mpu_irq) { |
1134 | case 5: |
1135 | mpu_irq_bits = 0x02; |
1136 | break; |
1137 | case 7: |
1138 | mpu_irq_bits = 0x03; |
1139 | break; |
1140 | case 9: |
1141 | mpu_irq_bits = 0x00; |
1142 | break; |
1143 | case 10: |
1144 | mpu_irq_bits = 0x01; |
1145 | break; |
1146 | default: |
1147 | snd_printk(KERN_ERR "MPU-401 irq # %d not valid\n" , |
1148 | chip->mpu_irq); |
1149 | goto __skip_mpu; |
1150 | } |
1151 | |
1152 | snd_miro_write_mask(chip, OPTi9XX_MC_REG(6), |
1153 | value: (chip->mpu_port <= 0) ? 0x00 : |
1154 | 0x80 | mpu_port_bits << 5 | mpu_irq_bits << 3, |
1155 | mask: 0xf8); |
1156 | } |
1157 | __skip_mpu: |
1158 | |
1159 | return 0; |
1160 | } |
1161 | |
1162 | static int snd_miro_opti_check(struct snd_card *card, struct snd_miro *chip) |
1163 | { |
1164 | unsigned char value; |
1165 | |
1166 | chip->res_mc_base = |
1167 | devm_request_region(card->dev, chip->mc_base, |
1168 | chip->mc_base_size, "OPTi9xx MC" ); |
1169 | if (chip->res_mc_base == NULL) |
1170 | return -ENOMEM; |
1171 | |
1172 | value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); |
1173 | if (value != 0xff && value != inb(port: chip->mc_base + OPTi9XX_MC_REG(1))) |
1174 | if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) |
1175 | return 0; |
1176 | |
1177 | devm_release_resource(dev: card->dev, new: chip->res_mc_base); |
1178 | chip->res_mc_base = NULL; |
1179 | |
1180 | return -ENODEV; |
1181 | } |
1182 | |
1183 | static int snd_card_miro_detect(struct snd_card *card, |
1184 | struct snd_miro *chip) |
1185 | { |
1186 | int i, err; |
1187 | |
1188 | for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { |
1189 | |
1190 | err = snd_miro_init(chip, hardware: i); |
1191 | if (err < 0) |
1192 | return err; |
1193 | |
1194 | err = snd_miro_opti_check(card, chip); |
1195 | if (err == 0) |
1196 | return 1; |
1197 | } |
1198 | |
1199 | return -ENODEV; |
1200 | } |
1201 | |
1202 | static int snd_card_miro_aci_detect(struct snd_card *card, |
1203 | struct snd_miro *miro) |
1204 | { |
1205 | unsigned char regval; |
1206 | int i; |
1207 | struct snd_miro_aci *aci = &aci_device; |
1208 | |
1209 | miro->aci = aci; |
1210 | |
1211 | mutex_init(&aci->aci_mutex); |
1212 | |
1213 | /* get ACI port from OPTi9xx MC 4 */ |
1214 | |
1215 | regval=inb(port: miro->mc_base + 4); |
1216 | aci->aci_port = (regval & 0x10) ? 0x344 : 0x354; |
1217 | |
1218 | miro->res_aci_port = |
1219 | devm_request_region(card->dev, aci->aci_port, 3, "miro aci" ); |
1220 | if (miro->res_aci_port == NULL) { |
1221 | snd_printk(KERN_ERR "aci i/o area 0x%lx-0x%lx already used.\n" , |
1222 | aci->aci_port, aci->aci_port+2); |
1223 | return -ENOMEM; |
1224 | } |
1225 | |
1226 | /* force ACI into a known state */ |
1227 | for (i = 0; i < 3; i++) |
1228 | if (snd_aci_cmd(aci, ACI_ERROR_OP, -1, -1) < 0) { |
1229 | snd_printk(KERN_ERR "can't force aci into known state.\n" ); |
1230 | return -ENXIO; |
1231 | } |
1232 | |
1233 | aci->aci_vendor = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); |
1234 | aci->aci_product = snd_aci_cmd(aci, ACI_READ_IDCODE, -1, -1); |
1235 | if (aci->aci_vendor < 0 || aci->aci_product < 0) { |
1236 | snd_printk(KERN_ERR "can't read aci id on 0x%lx.\n" , |
1237 | aci->aci_port); |
1238 | return -ENXIO; |
1239 | } |
1240 | |
1241 | aci->aci_version = snd_aci_cmd(aci, ACI_READ_VERSION, -1, -1); |
1242 | if (aci->aci_version < 0) { |
1243 | snd_printk(KERN_ERR "can't read aci version on 0x%lx.\n" , |
1244 | aci->aci_port); |
1245 | return -ENXIO; |
1246 | } |
1247 | |
1248 | if (snd_aci_cmd(aci, ACI_INIT, -1, -1) < 0 || |
1249 | snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0 || |
1250 | snd_aci_cmd(aci, ACI_ERROR_OP, ACI_ERROR_OP, ACI_ERROR_OP) < 0) { |
1251 | snd_printk(KERN_ERR "can't initialize aci.\n" ); |
1252 | return -ENXIO; |
1253 | } |
1254 | |
1255 | return 0; |
1256 | } |
1257 | |
1258 | static int snd_miro_probe(struct snd_card *card) |
1259 | { |
1260 | int error; |
1261 | struct snd_miro *miro = card->private_data; |
1262 | struct snd_wss *codec; |
1263 | struct snd_rawmidi *rmidi; |
1264 | |
1265 | if (!miro->res_mc_base) { |
1266 | miro->res_mc_base = devm_request_region(card->dev, |
1267 | miro->mc_base, |
1268 | miro->mc_base_size, |
1269 | "miro (OPTi9xx MC)" ); |
1270 | if (miro->res_mc_base == NULL) { |
1271 | snd_printk(KERN_ERR "request for OPTI9xx MC failed\n" ); |
1272 | return -ENOMEM; |
1273 | } |
1274 | } |
1275 | |
1276 | error = snd_card_miro_aci_detect(card, miro); |
1277 | if (error < 0) { |
1278 | snd_printk(KERN_ERR "unable to detect aci chip\n" ); |
1279 | return -ENODEV; |
1280 | } |
1281 | |
1282 | miro->wss_base = port; |
1283 | miro->mpu_port = mpu_port; |
1284 | miro->irq = irq; |
1285 | miro->mpu_irq = mpu_irq; |
1286 | miro->dma1 = dma1; |
1287 | miro->dma2 = dma2; |
1288 | |
1289 | /* init proc interface */ |
1290 | snd_miro_proc_init(card, miro); |
1291 | |
1292 | error = snd_miro_configure(chip: miro); |
1293 | if (error) |
1294 | return error; |
1295 | |
1296 | error = snd_wss_create(card, port: miro->wss_base + 4, cport: -1, |
1297 | irq: miro->irq, dma1: miro->dma1, dma2: miro->dma2, |
1298 | WSS_HW_DETECT, hwshare: 0, rchip: &codec); |
1299 | if (error < 0) |
1300 | return error; |
1301 | |
1302 | error = snd_wss_pcm(chip: codec, device: 0); |
1303 | if (error < 0) |
1304 | return error; |
1305 | |
1306 | error = snd_wss_mixer(chip: codec); |
1307 | if (error < 0) |
1308 | return error; |
1309 | |
1310 | error = snd_wss_timer(chip: codec, device: 0); |
1311 | if (error < 0) |
1312 | return error; |
1313 | |
1314 | miro->pcm = codec->pcm; |
1315 | |
1316 | error = snd_miro_mixer(card, miro); |
1317 | if (error < 0) |
1318 | return error; |
1319 | |
1320 | if (miro->aci->aci_vendor == 'm') { |
1321 | /* It looks like a miro sound card. */ |
1322 | switch (miro->aci->aci_product) { |
1323 | case 'A': |
1324 | sprintf(buf: card->shortname, |
1325 | fmt: "miroSOUND PCM1 pro / PCM12" ); |
1326 | break; |
1327 | case 'B': |
1328 | sprintf(buf: card->shortname, |
1329 | fmt: "miroSOUND PCM12" ); |
1330 | break; |
1331 | case 'C': |
1332 | sprintf(buf: card->shortname, |
1333 | fmt: "miroSOUND PCM20 radio" ); |
1334 | break; |
1335 | default: |
1336 | sprintf(buf: card->shortname, |
1337 | fmt: "unknown miro" ); |
1338 | snd_printk(KERN_INFO "unknown miro aci id\n" ); |
1339 | break; |
1340 | } |
1341 | } else { |
1342 | snd_printk(KERN_INFO "found unsupported aci card\n" ); |
1343 | sprintf(buf: card->shortname, fmt: "unknown Cardinal Technologies" ); |
1344 | } |
1345 | |
1346 | strcpy(p: card->driver, q: "miro" ); |
1347 | scnprintf(buf: card->longname, size: sizeof(card->longname), |
1348 | fmt: "%s: OPTi%s, %s at 0x%lx, irq %d, dma %d&%d" , |
1349 | card->shortname, miro->name, codec->pcm->name, |
1350 | miro->wss_base + 4, miro->irq, miro->dma1, miro->dma2); |
1351 | |
1352 | if (mpu_port <= 0 || mpu_port == SNDRV_AUTO_PORT) |
1353 | rmidi = NULL; |
1354 | else { |
1355 | error = snd_mpu401_uart_new(card, device: 0, MPU401_HW_MPU401, |
1356 | port: mpu_port, info_flags: 0, irq: miro->mpu_irq, rrawmidi: &rmidi); |
1357 | if (error < 0) |
1358 | snd_printk(KERN_WARNING "no MPU-401 device at 0x%lx?\n" , |
1359 | mpu_port); |
1360 | } |
1361 | |
1362 | if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { |
1363 | struct snd_opl3 *opl3 = NULL; |
1364 | struct snd_opl4 *opl4; |
1365 | |
1366 | if (snd_opl4_create(card, fm_port, pcm_port: fm_port - 8, |
1367 | seq_device: 2, opl3: &opl3, opl4: &opl4) < 0) |
1368 | snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n" , |
1369 | fm_port); |
1370 | } |
1371 | |
1372 | error = snd_set_aci_init_values(miro); |
1373 | if (error < 0) |
1374 | return error; |
1375 | |
1376 | return snd_card_register(card); |
1377 | } |
1378 | |
1379 | static int snd_miro_isa_match(struct device *devptr, unsigned int n) |
1380 | { |
1381 | #ifdef CONFIG_PNP |
1382 | if (snd_miro_pnp_is_probed) |
1383 | return 0; |
1384 | if (isapnp) |
1385 | return 0; |
1386 | #endif |
1387 | return 1; |
1388 | } |
1389 | |
1390 | static int snd_miro_isa_probe(struct device *devptr, unsigned int n) |
1391 | { |
1392 | static const long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; |
1393 | static const long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; |
1394 | static const int possible_irqs[] = {11, 9, 10, 7, -1}; |
1395 | static const int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; |
1396 | static const int possible_dma1s[] = {3, 1, 0, -1}; |
1397 | static const int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, |
1398 | {0, -1} }; |
1399 | |
1400 | int error; |
1401 | struct snd_miro *miro; |
1402 | struct snd_card *card; |
1403 | |
1404 | error = snd_devm_card_new(parent: devptr, idx: index, xid: id, THIS_MODULE, |
1405 | extra_size: sizeof(struct snd_miro), card_ret: &card); |
1406 | if (error < 0) |
1407 | return error; |
1408 | |
1409 | miro = card->private_data; |
1410 | |
1411 | error = snd_card_miro_detect(card, chip: miro); |
1412 | if (error < 0) { |
1413 | snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n" ); |
1414 | return -ENODEV; |
1415 | } |
1416 | |
1417 | if (port == SNDRV_AUTO_PORT) { |
1418 | port = snd_legacy_find_free_ioport(port_table: possible_ports, size: 4); |
1419 | if (port < 0) { |
1420 | snd_printk(KERN_ERR "unable to find a free WSS port\n" ); |
1421 | return -EBUSY; |
1422 | } |
1423 | } |
1424 | |
1425 | if (mpu_port == SNDRV_AUTO_PORT) { |
1426 | mpu_port = snd_legacy_find_free_ioport(port_table: possible_mpu_ports, size: 2); |
1427 | if (mpu_port < 0) { |
1428 | snd_printk(KERN_ERR |
1429 | "unable to find a free MPU401 port\n" ); |
1430 | return -EBUSY; |
1431 | } |
1432 | } |
1433 | |
1434 | if (irq == SNDRV_AUTO_IRQ) { |
1435 | irq = snd_legacy_find_free_irq(irq_table: possible_irqs); |
1436 | if (irq < 0) { |
1437 | snd_printk(KERN_ERR "unable to find a free IRQ\n" ); |
1438 | return -EBUSY; |
1439 | } |
1440 | } |
1441 | if (mpu_irq == SNDRV_AUTO_IRQ) { |
1442 | mpu_irq = snd_legacy_find_free_irq(irq_table: possible_mpu_irqs); |
1443 | if (mpu_irq < 0) { |
1444 | snd_printk(KERN_ERR |
1445 | "unable to find a free MPU401 IRQ\n" ); |
1446 | return -EBUSY; |
1447 | } |
1448 | } |
1449 | if (dma1 == SNDRV_AUTO_DMA) { |
1450 | dma1 = snd_legacy_find_free_dma(dma_table: possible_dma1s); |
1451 | if (dma1 < 0) { |
1452 | snd_printk(KERN_ERR "unable to find a free DMA1\n" ); |
1453 | return -EBUSY; |
1454 | } |
1455 | } |
1456 | if (dma2 == SNDRV_AUTO_DMA) { |
1457 | dma2 = snd_legacy_find_free_dma(dma_table: possible_dma2s[dma1 % 4]); |
1458 | if (dma2 < 0) { |
1459 | snd_printk(KERN_ERR "unable to find a free DMA2\n" ); |
1460 | return -EBUSY; |
1461 | } |
1462 | } |
1463 | |
1464 | error = snd_miro_probe(card); |
1465 | if (error < 0) |
1466 | return error; |
1467 | |
1468 | dev_set_drvdata(dev: devptr, data: card); |
1469 | return 0; |
1470 | } |
1471 | |
1472 | #define DEV_NAME "miro" |
1473 | |
1474 | static struct isa_driver snd_miro_driver = { |
1475 | .match = snd_miro_isa_match, |
1476 | .probe = snd_miro_isa_probe, |
1477 | /* FIXME: suspend/resume */ |
1478 | .driver = { |
1479 | .name = DEV_NAME |
1480 | }, |
1481 | }; |
1482 | |
1483 | #ifdef CONFIG_PNP |
1484 | |
1485 | static int snd_card_miro_pnp(struct snd_miro *chip, |
1486 | struct pnp_card_link *card, |
1487 | const struct pnp_card_device_id *pid) |
1488 | { |
1489 | struct pnp_dev *pdev; |
1490 | int err; |
1491 | struct pnp_dev *devmpu; |
1492 | struct pnp_dev *devmc; |
1493 | |
1494 | pdev = pnp_request_card_device(clink: card, id: pid->devs[0].id, NULL); |
1495 | if (pdev == NULL) |
1496 | return -EBUSY; |
1497 | |
1498 | devmpu = pnp_request_card_device(clink: card, id: pid->devs[1].id, NULL); |
1499 | if (devmpu == NULL) |
1500 | return -EBUSY; |
1501 | |
1502 | devmc = pnp_request_card_device(clink: card, id: pid->devs[2].id, NULL); |
1503 | if (devmc == NULL) |
1504 | return -EBUSY; |
1505 | |
1506 | err = pnp_activate_dev(dev: pdev); |
1507 | if (err < 0) { |
1508 | snd_printk(KERN_ERR "AUDIO pnp configure failure: %d\n" , err); |
1509 | return err; |
1510 | } |
1511 | |
1512 | err = pnp_activate_dev(dev: devmc); |
1513 | if (err < 0) { |
1514 | snd_printk(KERN_ERR "MC pnp configure failure: %d\n" , |
1515 | err); |
1516 | return err; |
1517 | } |
1518 | |
1519 | port = pnp_port_start(dev: pdev, bar: 1); |
1520 | fm_port = pnp_port_start(dev: pdev, bar: 2) + 8; |
1521 | |
1522 | /* |
1523 | * The MC(0) is never accessed and the miroSOUND PCM20 card does not |
1524 | * include it in the PnP resource range. OPTI93x include it. |
1525 | */ |
1526 | chip->mc_base = pnp_port_start(dev: devmc, bar: 0) - 1; |
1527 | chip->mc_base_size = pnp_port_len(dev: devmc, bar: 0) + 1; |
1528 | |
1529 | irq = pnp_irq(dev: pdev, bar: 0); |
1530 | dma1 = pnp_dma(dev: pdev, bar: 0); |
1531 | dma2 = pnp_dma(dev: pdev, bar: 1); |
1532 | |
1533 | if (mpu_port > 0) { |
1534 | err = pnp_activate_dev(dev: devmpu); |
1535 | if (err < 0) { |
1536 | snd_printk(KERN_ERR "MPU401 pnp configure failure\n" ); |
1537 | mpu_port = -1; |
1538 | return err; |
1539 | } |
1540 | mpu_port = pnp_port_start(dev: devmpu, bar: 0); |
1541 | mpu_irq = pnp_irq(dev: devmpu, bar: 0); |
1542 | } |
1543 | return 0; |
1544 | } |
1545 | |
1546 | static int snd_miro_pnp_probe(struct pnp_card_link *pcard, |
1547 | const struct pnp_card_device_id *pid) |
1548 | { |
1549 | struct snd_card *card; |
1550 | int err; |
1551 | struct snd_miro *miro; |
1552 | |
1553 | if (snd_miro_pnp_is_probed) |
1554 | return -EBUSY; |
1555 | if (!isapnp) |
1556 | return -ENODEV; |
1557 | err = snd_devm_card_new(parent: &pcard->card->dev, idx: index, xid: id, THIS_MODULE, |
1558 | extra_size: sizeof(struct snd_miro), card_ret: &card); |
1559 | if (err < 0) |
1560 | return err; |
1561 | |
1562 | miro = card->private_data; |
1563 | |
1564 | err = snd_card_miro_pnp(chip: miro, card: pcard, pid); |
1565 | if (err) |
1566 | return err; |
1567 | |
1568 | /* only miroSOUND PCM20 and PCM12 == OPTi924 */ |
1569 | err = snd_miro_init(chip: miro, OPTi9XX_HW_82C924); |
1570 | if (err) |
1571 | return err; |
1572 | |
1573 | err = snd_miro_opti_check(card, chip: miro); |
1574 | if (err) { |
1575 | snd_printk(KERN_ERR "OPTI chip not found\n" ); |
1576 | return err; |
1577 | } |
1578 | |
1579 | err = snd_miro_probe(card); |
1580 | if (err < 0) |
1581 | return err; |
1582 | pnp_set_card_drvdata(pcard, data: card); |
1583 | snd_miro_pnp_is_probed = 1; |
1584 | return 0; |
1585 | } |
1586 | |
1587 | static void snd_miro_pnp_remove(struct pnp_card_link *pcard) |
1588 | { |
1589 | snd_miro_pnp_is_probed = 0; |
1590 | } |
1591 | |
1592 | static struct pnp_card_driver miro_pnpc_driver = { |
1593 | .flags = PNP_DRIVER_RES_DISABLE, |
1594 | .name = "miro" , |
1595 | .id_table = snd_miro_pnpids, |
1596 | .probe = snd_miro_pnp_probe, |
1597 | .remove = snd_miro_pnp_remove, |
1598 | }; |
1599 | #endif |
1600 | |
1601 | static int __init alsa_card_miro_init(void) |
1602 | { |
1603 | #ifdef CONFIG_PNP |
1604 | pnp_register_card_driver(drv: &miro_pnpc_driver); |
1605 | if (snd_miro_pnp_is_probed) |
1606 | return 0; |
1607 | pnp_unregister_card_driver(drv: &miro_pnpc_driver); |
1608 | #endif |
1609 | return isa_register_driver(&snd_miro_driver, 1); |
1610 | } |
1611 | |
1612 | static void __exit alsa_card_miro_exit(void) |
1613 | { |
1614 | if (!snd_miro_pnp_is_probed) { |
1615 | isa_unregister_driver(&snd_miro_driver); |
1616 | return; |
1617 | } |
1618 | #ifdef CONFIG_PNP |
1619 | pnp_unregister_card_driver(drv: &miro_pnpc_driver); |
1620 | #endif |
1621 | } |
1622 | |
1623 | module_init(alsa_card_miro_init) |
1624 | module_exit(alsa_card_miro_exit) |
1625 | |