2 * Aztech AZT1605/AZT2316 Driver
3 * Copyright (C) 2007,2010 Rene Herman
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include <linux/kernel.h>
21 #include <linux/module.h>
22 #include <linux/isa.h>
23 #include <linux/delay.h>
25 #include <asm/processor.h>
26 #include <sound/core.h>
27 #include <sound/initval.h>
28 #include <sound/wss.h>
29 #include <sound/mpu401.h>
30 #include <sound/opl3.h>
32 MODULE_DESCRIPTION(CRD_NAME
);
33 MODULE_AUTHOR("Rene Herman");
34 MODULE_LICENSE("GPL");
36 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
;
37 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
;
38 static bool enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE
;
40 module_param_array(index
, int, NULL
, 0444);
41 MODULE_PARM_DESC(index
, "Index value for " CRD_NAME
" soundcard.");
42 module_param_array(id
, charp
, NULL
, 0444);
43 MODULE_PARM_DESC(id
, "ID string for " CRD_NAME
" soundcard.");
44 module_param_array(enable
, bool, NULL
, 0444);
45 MODULE_PARM_DESC(enable
, "Enable " CRD_NAME
" soundcard.");
47 static long port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
48 static long wss_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
49 static long mpu_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
50 static long fm_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
51 static int irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
;
52 static int mpu_irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
;
53 static int dma1
[SNDRV_CARDS
] = SNDRV_DEFAULT_DMA
;
54 static int dma2
[SNDRV_CARDS
] = SNDRV_DEFAULT_DMA
;
56 module_param_array(port
, long, NULL
, 0444);
57 MODULE_PARM_DESC(port
, "Port # for " CRD_NAME
" driver.");
58 module_param_array(wss_port
, long, NULL
, 0444);
59 MODULE_PARM_DESC(wss_port
, "WSS port # for " CRD_NAME
" driver.");
60 module_param_array(mpu_port
, long, NULL
, 0444);
61 MODULE_PARM_DESC(mpu_port
, "MPU-401 port # for " CRD_NAME
" driver.");
62 module_param_array(fm_port
, long, NULL
, 0444);
63 MODULE_PARM_DESC(fm_port
, "FM port # for " CRD_NAME
" driver.");
64 module_param_array(irq
, int, NULL
, 0444);
65 MODULE_PARM_DESC(irq
, "IRQ # for " CRD_NAME
" driver.");
66 module_param_array(mpu_irq
, int, NULL
, 0444);
67 MODULE_PARM_DESC(mpu_irq
, "MPU-401 IRQ # for " CRD_NAME
" driver.");
68 module_param_array(dma1
, int, NULL
, 0444);
69 MODULE_PARM_DESC(dma1
, "Playback DMA # for " CRD_NAME
" driver.");
70 module_param_array(dma2
, int, NULL
, 0444);
71 MODULE_PARM_DESC(dma2
, "Capture DMA # for " CRD_NAME
" driver.");
74 * Generic SB DSP support routines
77 #define DSP_PORT_RESET 0x6
78 #define DSP_PORT_READ 0xa
79 #define DSP_PORT_COMMAND 0xc
80 #define DSP_PORT_STATUS 0xc
81 #define DSP_PORT_DATA_AVAIL 0xe
83 #define DSP_SIGNATURE 0xaa
85 #define DSP_COMMAND_GET_VERSION 0xe1
87 static int dsp_get_byte(void __iomem
*port
, u8
*val
)
91 while (!(ioread8(port
+ DSP_PORT_DATA_AVAIL
) & 0x80)) {
96 *val
= ioread8(port
+ DSP_PORT_READ
);
100 static int dsp_reset(void __iomem
*port
)
104 iowrite8(1, port
+ DSP_PORT_RESET
);
106 iowrite8(0, port
+ DSP_PORT_RESET
);
108 if (dsp_get_byte(port
, &val
) < 0 || val
!= DSP_SIGNATURE
)
114 static int dsp_command(void __iomem
*port
, u8 cmd
)
118 while (ioread8(port
+ DSP_PORT_STATUS
) & 0x80) {
123 iowrite8(cmd
, port
+ DSP_PORT_COMMAND
);
127 static int dsp_get_version(void __iomem
*port
, u8
*major
, u8
*minor
)
131 err
= dsp_command(port
, DSP_COMMAND_GET_VERSION
);
135 err
= dsp_get_byte(port
, major
);
139 err
= dsp_get_byte(port
, minor
);
147 * Generic WSS support routines
150 #define WSS_CONFIG_DMA_0 (1 << 0)
151 #define WSS_CONFIG_DMA_1 (2 << 0)
152 #define WSS_CONFIG_DMA_3 (3 << 0)
153 #define WSS_CONFIG_DUPLEX (1 << 2)
154 #define WSS_CONFIG_IRQ_7 (1 << 3)
155 #define WSS_CONFIG_IRQ_9 (2 << 3)
156 #define WSS_CONFIG_IRQ_10 (3 << 3)
157 #define WSS_CONFIG_IRQ_11 (4 << 3)
159 #define WSS_PORT_CONFIG 0
160 #define WSS_PORT_SIGNATURE 3
162 #define WSS_SIGNATURE 4
164 static int wss_detect(void __iomem
*wss_port
)
166 if ((ioread8(wss_port
+ WSS_PORT_SIGNATURE
) & 0x3f) != WSS_SIGNATURE
)
172 static void wss_set_config(void __iomem
*wss_port
, u8 wss_config
)
174 iowrite8(wss_config
, wss_port
+ WSS_PORT_CONFIG
);
178 * Aztech Sound Galaxy specifics
181 #define GALAXY_PORT_CONFIG 1024
182 #define CONFIG_PORT_SET 4
184 #define DSP_COMMAND_GALAXY_8 8
185 #define GALAXY_COMMAND_GET_TYPE 5
187 #define DSP_COMMAND_GALAXY_9 9
188 #define GALAXY_COMMAND_WSSMODE 0
189 #define GALAXY_COMMAND_SB8MODE 1
191 #define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
192 #define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
196 void __iomem
*config_port
;
197 void __iomem
*wss_port
;
199 struct resource
*res_port
;
200 struct resource
*res_config_port
;
201 struct resource
*res_wss_port
;
204 static u32 config
[SNDRV_CARDS
];
205 static u8 wss_config
[SNDRV_CARDS
];
207 static int snd_galaxy_match(struct device
*dev
, unsigned int n
)
213 case SNDRV_AUTO_PORT
:
214 dev_err(dev
, "please specify port\n");
217 config
[n
] |= GALAXY_CONFIG_SBA_220
;
220 config
[n
] |= GALAXY_CONFIG_SBA_240
;
223 config
[n
] |= GALAXY_CONFIG_SBA_260
;
226 config
[n
] |= GALAXY_CONFIG_SBA_280
;
229 dev_err(dev
, "invalid port %#lx\n", port
[n
]);
233 switch (wss_port
[n
]) {
234 case SNDRV_AUTO_PORT
:
235 dev_err(dev
, "please specify wss_port\n");
238 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_530
;
241 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_604
;
244 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_E80
;
247 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_F40
;
250 dev_err(dev
, "invalid WSS port %#lx\n", wss_port
[n
]);
256 dev_err(dev
, "please specify irq\n");
259 wss_config
[n
] |= WSS_CONFIG_IRQ_7
;
264 wss_config
[n
] |= WSS_CONFIG_IRQ_9
;
267 wss_config
[n
] |= WSS_CONFIG_IRQ_10
;
270 wss_config
[n
] |= WSS_CONFIG_IRQ_11
;
273 dev_err(dev
, "invalid IRQ %d\n", irq
[n
]);
279 dev_err(dev
, "please specify dma1\n");
282 wss_config
[n
] |= WSS_CONFIG_DMA_0
;
285 wss_config
[n
] |= WSS_CONFIG_DMA_1
;
288 wss_config
[n
] |= WSS_CONFIG_DMA_3
;
291 dev_err(dev
, "invalid playback DMA %d\n", dma1
[n
]);
295 if (dma2
[n
] == SNDRV_AUTO_DMA
|| dma2
[n
] == dma1
[n
]) {
300 wss_config
[n
] |= WSS_CONFIG_DUPLEX
;
308 dev_err(dev
, "invalid capture DMA %d\n", dma2
[n
]);
313 switch (mpu_port
[n
]) {
314 case SNDRV_AUTO_PORT
:
315 dev_warn(dev
, "mpu_port not specified; not using MPU-401\n");
319 config
[n
] |= GALAXY_CONFIG_MPU_ENABLE
| GALAXY_CONFIG_MPUA_300
;
322 config
[n
] |= GALAXY_CONFIG_MPU_ENABLE
| GALAXY_CONFIG_MPUA_330
;
325 dev_err(dev
, "invalid MPU port %#lx\n", mpu_port
[n
]);
329 switch (mpu_irq
[n
]) {
331 dev_warn(dev
, "mpu_irq not specified: using polling mode\n");
337 config
[n
] |= GALAXY_CONFIG_MPUIRQ_2
;
341 config
[n
] |= GALAXY_CONFIG_MPUIRQ_3
;
345 config
[n
] |= GALAXY_CONFIG_MPUIRQ_5
;
348 config
[n
] |= GALAXY_CONFIG_MPUIRQ_7
;
352 config
[n
] |= GALAXY_CONFIG_MPUIRQ_10
;
356 dev_err(dev
, "invalid MPU IRQ %d\n", mpu_irq
[n
]);
360 if (mpu_irq
[n
] == irq
[n
]) {
361 dev_err(dev
, "cannot share IRQ between WSS and MPU-401\n");
366 switch (fm_port
[n
]) {
367 case SNDRV_AUTO_PORT
:
368 dev_warn(dev
, "fm_port not specified: not using OPL3\n");
374 dev_err(dev
, "illegal FM port %#lx\n", fm_port
[n
]);
378 config
[n
] |= GALAXY_CONFIG_GAME_ENABLE
;
382 static int galaxy_init(struct snd_galaxy
*galaxy
, u8
*type
)
388 err
= dsp_reset(galaxy
->port
);
392 err
= dsp_get_version(galaxy
->port
, &major
, &minor
);
396 if (major
!= GALAXY_DSP_MAJOR
|| minor
!= GALAXY_DSP_MINOR
)
399 err
= dsp_command(galaxy
->port
, DSP_COMMAND_GALAXY_8
);
403 err
= dsp_command(galaxy
->port
, GALAXY_COMMAND_GET_TYPE
);
407 err
= dsp_get_byte(galaxy
->port
, type
);
414 static int galaxy_set_mode(struct snd_galaxy
*galaxy
, u8 mode
)
418 err
= dsp_command(galaxy
->port
, DSP_COMMAND_GALAXY_9
);
422 err
= dsp_command(galaxy
->port
, mode
);
428 * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
430 err
= dsp_reset(galaxy
->port
);
438 static void galaxy_set_config(struct snd_galaxy
*galaxy
, u32 config
)
440 u8 tmp
= ioread8(galaxy
->config_port
+ CONFIG_PORT_SET
);
443 iowrite8(tmp
| 0x80, galaxy
->config_port
+ CONFIG_PORT_SET
);
444 for (i
= 0; i
< GALAXY_CONFIG_SIZE
; i
++) {
445 iowrite8(config
, galaxy
->config_port
+ i
);
448 iowrite8(tmp
& 0x7f, galaxy
->config_port
+ CONFIG_PORT_SET
);
452 static void galaxy_config(struct snd_galaxy
*galaxy
, u32 config
)
456 for (i
= GALAXY_CONFIG_SIZE
; i
; i
--) {
457 u8 tmp
= ioread8(galaxy
->config_port
+ i
- 1);
458 galaxy
->config
= (galaxy
->config
<< 8) | tmp
;
460 config
|= galaxy
->config
& GALAXY_CONFIG_MASK
;
461 galaxy_set_config(galaxy
, config
);
464 static int galaxy_wss_config(struct snd_galaxy
*galaxy
, u8 wss_config
)
468 err
= wss_detect(galaxy
->wss_port
);
472 wss_set_config(galaxy
->wss_port
, wss_config
);
474 err
= galaxy_set_mode(galaxy
, GALAXY_MODE_WSS
);
481 static void snd_galaxy_free(struct snd_card
*card
)
483 struct snd_galaxy
*galaxy
= card
->private_data
;
485 if (galaxy
->wss_port
) {
486 wss_set_config(galaxy
->wss_port
, 0);
487 ioport_unmap(galaxy
->wss_port
);
488 release_and_free_resource(galaxy
->res_wss_port
);
490 if (galaxy
->config_port
) {
491 galaxy_set_config(galaxy
, galaxy
->config
);
492 ioport_unmap(galaxy
->config_port
);
493 release_and_free_resource(galaxy
->res_config_port
);
496 ioport_unmap(galaxy
->port
);
497 release_and_free_resource(galaxy
->res_port
);
501 static int snd_galaxy_probe(struct device
*dev
, unsigned int n
)
503 struct snd_galaxy
*galaxy
;
504 struct snd_wss
*chip
;
505 struct snd_card
*card
;
509 err
= snd_card_new(dev
, index
[n
], id
[n
], THIS_MODULE
,
510 sizeof(*galaxy
), &card
);
514 card
->private_free
= snd_galaxy_free
;
515 galaxy
= card
->private_data
;
517 galaxy
->res_port
= request_region(port
[n
], 16, DRV_NAME
);
518 if (!galaxy
->res_port
) {
519 dev_err(dev
, "could not grab ports %#lx-%#lx\n", port
[n
],
524 galaxy
->port
= ioport_map(port
[n
], 16);
526 err
= galaxy_init(galaxy
, &type
);
528 dev_err(dev
, "did not find a Sound Galaxy at %#lx\n", port
[n
]);
531 dev_info(dev
, "Sound Galaxy (type %d) found at %#lx\n", type
, port
[n
]);
533 galaxy
->res_config_port
= request_region(port
[n
] + GALAXY_PORT_CONFIG
,
535 if (!galaxy
->res_config_port
) {
536 dev_err(dev
, "could not grab ports %#lx-%#lx\n",
537 port
[n
] + GALAXY_PORT_CONFIG
,
538 port
[n
] + GALAXY_PORT_CONFIG
+ 15);
542 galaxy
->config_port
= ioport_map(port
[n
] + GALAXY_PORT_CONFIG
, 16);
544 galaxy_config(galaxy
, config
[n
]);
546 galaxy
->res_wss_port
= request_region(wss_port
[n
], 4, DRV_NAME
);
547 if (!galaxy
->res_wss_port
) {
548 dev_err(dev
, "could not grab ports %#lx-%#lx\n", wss_port
[n
],
553 galaxy
->wss_port
= ioport_map(wss_port
[n
], 4);
555 err
= galaxy_wss_config(galaxy
, wss_config
[n
]);
557 dev_err(dev
, "could not configure WSS\n");
561 strcpy(card
->driver
, DRV_NAME
);
562 strcpy(card
->shortname
, DRV_NAME
);
563 sprintf(card
->longname
, "%s at %#lx/%#lx, irq %d, dma %d/%d",
564 card
->shortname
, port
[n
], wss_port
[n
], irq
[n
], dma1
[n
],
567 err
= snd_wss_create(card
, wss_port
[n
] + 4, -1, irq
[n
], dma1
[n
],
568 dma2
[n
], WSS_HW_DETECT
, 0, &chip
);
572 err
= snd_wss_pcm(chip
, 0);
576 err
= snd_wss_mixer(chip
);
580 err
= snd_wss_timer(chip
, 0);
584 if (mpu_port
[n
] >= 0) {
585 err
= snd_mpu401_uart_new(card
, 0, MPU401_HW_MPU401
,
586 mpu_port
[n
], 0, mpu_irq
[n
], NULL
);
591 if (fm_port
[n
] >= 0) {
592 struct snd_opl3
*opl3
;
594 err
= snd_opl3_create(card
, fm_port
[n
], fm_port
[n
] + 2,
595 OPL3_HW_AUTO
, 0, &opl3
);
597 dev_err(dev
, "no OPL device at %#lx\n", fm_port
[n
]);
600 err
= snd_opl3_timer_new(opl3
, 1, 2);
604 err
= snd_opl3_hwdep_new(opl3
, 0, 1, NULL
);
609 err
= snd_card_register(card
);
613 dev_set_drvdata(dev
, card
);
621 static int snd_galaxy_remove(struct device
*dev
, unsigned int n
)
623 snd_card_free(dev_get_drvdata(dev
));
627 static struct isa_driver snd_galaxy_driver
= {
628 .match
= snd_galaxy_match
,
629 .probe
= snd_galaxy_probe
,
630 .remove
= snd_galaxy_remove
,
637 module_isa_driver(snd_galaxy_driver
, SNDRV_CARDS
);