1 // SPDX-License-Identifier: GPL-2.0-or-later
3 * Aztech AZT1605/AZT2316 Driver
4 * Copyright (C) 2007,2010 Rene Herman
7 #include <linux/kernel.h>
8 #include <linux/module.h>
10 #include <linux/delay.h>
12 #include <asm/processor.h>
13 #include <sound/core.h>
14 #include <sound/initval.h>
15 #include <sound/wss.h>
16 #include <sound/mpu401.h>
17 #include <sound/opl3.h>
19 MODULE_DESCRIPTION(CRD_NAME
);
20 MODULE_AUTHOR("Rene Herman");
21 MODULE_LICENSE("GPL");
23 static int index
[SNDRV_CARDS
] = SNDRV_DEFAULT_IDX
;
24 static char *id
[SNDRV_CARDS
] = SNDRV_DEFAULT_STR
;
25 static bool enable
[SNDRV_CARDS
] = SNDRV_DEFAULT_ENABLE
;
27 module_param_array(index
, int, NULL
, 0444);
28 MODULE_PARM_DESC(index
, "Index value for " CRD_NAME
" soundcard.");
29 module_param_array(id
, charp
, NULL
, 0444);
30 MODULE_PARM_DESC(id
, "ID string for " CRD_NAME
" soundcard.");
31 module_param_array(enable
, bool, NULL
, 0444);
32 MODULE_PARM_DESC(enable
, "Enable " CRD_NAME
" soundcard.");
34 static long port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
35 static long wss_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
36 static long mpu_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
37 static long fm_port
[SNDRV_CARDS
] = SNDRV_DEFAULT_PORT
;
38 static int irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
;
39 static int mpu_irq
[SNDRV_CARDS
] = SNDRV_DEFAULT_IRQ
;
40 static int dma1
[SNDRV_CARDS
] = SNDRV_DEFAULT_DMA
;
41 static int dma2
[SNDRV_CARDS
] = SNDRV_DEFAULT_DMA
;
43 module_param_hw_array(port
, long, ioport
, NULL
, 0444);
44 MODULE_PARM_DESC(port
, "Port # for " CRD_NAME
" driver.");
45 module_param_hw_array(wss_port
, long, ioport
, NULL
, 0444);
46 MODULE_PARM_DESC(wss_port
, "WSS port # for " CRD_NAME
" driver.");
47 module_param_hw_array(mpu_port
, long, ioport
, NULL
, 0444);
48 MODULE_PARM_DESC(mpu_port
, "MPU-401 port # for " CRD_NAME
" driver.");
49 module_param_hw_array(fm_port
, long, ioport
, NULL
, 0444);
50 MODULE_PARM_DESC(fm_port
, "FM port # for " CRD_NAME
" driver.");
51 module_param_hw_array(irq
, int, irq
, NULL
, 0444);
52 MODULE_PARM_DESC(irq
, "IRQ # for " CRD_NAME
" driver.");
53 module_param_hw_array(mpu_irq
, int, irq
, NULL
, 0444);
54 MODULE_PARM_DESC(mpu_irq
, "MPU-401 IRQ # for " CRD_NAME
" driver.");
55 module_param_hw_array(dma1
, int, dma
, NULL
, 0444);
56 MODULE_PARM_DESC(dma1
, "Playback DMA # for " CRD_NAME
" driver.");
57 module_param_hw_array(dma2
, int, dma
, NULL
, 0444);
58 MODULE_PARM_DESC(dma2
, "Capture DMA # for " CRD_NAME
" driver.");
61 * Generic SB DSP support routines
64 #define DSP_PORT_RESET 0x6
65 #define DSP_PORT_READ 0xa
66 #define DSP_PORT_COMMAND 0xc
67 #define DSP_PORT_STATUS 0xc
68 #define DSP_PORT_DATA_AVAIL 0xe
70 #define DSP_SIGNATURE 0xaa
72 #define DSP_COMMAND_GET_VERSION 0xe1
74 static int dsp_get_byte(void __iomem
*port
, u8
*val
)
78 while (!(ioread8(port
+ DSP_PORT_DATA_AVAIL
) & 0x80)) {
83 *val
= ioread8(port
+ DSP_PORT_READ
);
87 static int dsp_reset(void __iomem
*port
)
91 iowrite8(1, port
+ DSP_PORT_RESET
);
93 iowrite8(0, port
+ DSP_PORT_RESET
);
95 if (dsp_get_byte(port
, &val
) < 0 || val
!= DSP_SIGNATURE
)
101 static int dsp_command(void __iomem
*port
, u8 cmd
)
105 while (ioread8(port
+ DSP_PORT_STATUS
) & 0x80) {
110 iowrite8(cmd
, port
+ DSP_PORT_COMMAND
);
114 static int dsp_get_version(void __iomem
*port
, u8
*major
, u8
*minor
)
118 err
= dsp_command(port
, DSP_COMMAND_GET_VERSION
);
122 err
= dsp_get_byte(port
, major
);
126 err
= dsp_get_byte(port
, minor
);
134 * Generic WSS support routines
137 #define WSS_CONFIG_DMA_0 (1 << 0)
138 #define WSS_CONFIG_DMA_1 (2 << 0)
139 #define WSS_CONFIG_DMA_3 (3 << 0)
140 #define WSS_CONFIG_DUPLEX (1 << 2)
141 #define WSS_CONFIG_IRQ_7 (1 << 3)
142 #define WSS_CONFIG_IRQ_9 (2 << 3)
143 #define WSS_CONFIG_IRQ_10 (3 << 3)
144 #define WSS_CONFIG_IRQ_11 (4 << 3)
146 #define WSS_PORT_CONFIG 0
147 #define WSS_PORT_SIGNATURE 3
149 #define WSS_SIGNATURE 4
151 static int wss_detect(void __iomem
*wss_port
)
153 if ((ioread8(wss_port
+ WSS_PORT_SIGNATURE
) & 0x3f) != WSS_SIGNATURE
)
159 static void wss_set_config(void __iomem
*wss_port
, u8 wss_config
)
161 iowrite8(wss_config
, wss_port
+ WSS_PORT_CONFIG
);
165 * Aztech Sound Galaxy specifics
168 #define GALAXY_PORT_CONFIG 1024
169 #define CONFIG_PORT_SET 4
171 #define DSP_COMMAND_GALAXY_8 8
172 #define GALAXY_COMMAND_GET_TYPE 5
174 #define DSP_COMMAND_GALAXY_9 9
175 #define GALAXY_COMMAND_WSSMODE 0
176 #define GALAXY_COMMAND_SB8MODE 1
178 #define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
179 #define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
183 void __iomem
*config_port
;
184 void __iomem
*wss_port
;
186 struct resource
*res_port
;
187 struct resource
*res_config_port
;
188 struct resource
*res_wss_port
;
191 static u32 config
[SNDRV_CARDS
];
192 static u8 wss_config
[SNDRV_CARDS
];
194 static int snd_galaxy_match(struct device
*dev
, unsigned int n
)
200 case SNDRV_AUTO_PORT
:
201 dev_err(dev
, "please specify port\n");
204 config
[n
] |= GALAXY_CONFIG_SBA_220
;
207 config
[n
] |= GALAXY_CONFIG_SBA_240
;
210 config
[n
] |= GALAXY_CONFIG_SBA_260
;
213 config
[n
] |= GALAXY_CONFIG_SBA_280
;
216 dev_err(dev
, "invalid port %#lx\n", port
[n
]);
220 switch (wss_port
[n
]) {
221 case SNDRV_AUTO_PORT
:
222 dev_err(dev
, "please specify wss_port\n");
225 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_530
;
228 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_604
;
231 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_E80
;
234 config
[n
] |= GALAXY_CONFIG_WSS_ENABLE
| GALAXY_CONFIG_WSSA_F40
;
237 dev_err(dev
, "invalid WSS port %#lx\n", wss_port
[n
]);
243 dev_err(dev
, "please specify irq\n");
246 wss_config
[n
] |= WSS_CONFIG_IRQ_7
;
252 wss_config
[n
] |= WSS_CONFIG_IRQ_9
;
255 wss_config
[n
] |= WSS_CONFIG_IRQ_10
;
258 wss_config
[n
] |= WSS_CONFIG_IRQ_11
;
261 dev_err(dev
, "invalid IRQ %d\n", irq
[n
]);
267 dev_err(dev
, "please specify dma1\n");
270 wss_config
[n
] |= WSS_CONFIG_DMA_0
;
273 wss_config
[n
] |= WSS_CONFIG_DMA_1
;
276 wss_config
[n
] |= WSS_CONFIG_DMA_3
;
279 dev_err(dev
, "invalid playback DMA %d\n", dma1
[n
]);
283 if (dma2
[n
] == SNDRV_AUTO_DMA
|| dma2
[n
] == dma1
[n
]) {
288 wss_config
[n
] |= WSS_CONFIG_DUPLEX
;
297 dev_err(dev
, "invalid capture DMA %d\n", dma2
[n
]);
302 switch (mpu_port
[n
]) {
303 case SNDRV_AUTO_PORT
:
304 dev_warn(dev
, "mpu_port not specified; not using MPU-401\n");
308 config
[n
] |= GALAXY_CONFIG_MPU_ENABLE
| GALAXY_CONFIG_MPUA_300
;
311 config
[n
] |= GALAXY_CONFIG_MPU_ENABLE
| GALAXY_CONFIG_MPUA_330
;
314 dev_err(dev
, "invalid MPU port %#lx\n", mpu_port
[n
]);
318 switch (mpu_irq
[n
]) {
320 dev_warn(dev
, "mpu_irq not specified: using polling mode\n");
327 config
[n
] |= GALAXY_CONFIG_MPUIRQ_2
;
331 config
[n
] |= GALAXY_CONFIG_MPUIRQ_3
;
335 config
[n
] |= GALAXY_CONFIG_MPUIRQ_5
;
338 config
[n
] |= GALAXY_CONFIG_MPUIRQ_7
;
342 config
[n
] |= GALAXY_CONFIG_MPUIRQ_10
;
346 dev_err(dev
, "invalid MPU IRQ %d\n", mpu_irq
[n
]);
350 if (mpu_irq
[n
] == irq
[n
]) {
351 dev_err(dev
, "cannot share IRQ between WSS and MPU-401\n");
356 switch (fm_port
[n
]) {
357 case SNDRV_AUTO_PORT
:
358 dev_warn(dev
, "fm_port not specified: not using OPL3\n");
364 dev_err(dev
, "illegal FM port %#lx\n", fm_port
[n
]);
368 config
[n
] |= GALAXY_CONFIG_GAME_ENABLE
;
372 static int galaxy_init(struct snd_galaxy
*galaxy
, u8
*type
)
378 err
= dsp_reset(galaxy
->port
);
382 err
= dsp_get_version(galaxy
->port
, &major
, &minor
);
386 if (major
!= GALAXY_DSP_MAJOR
|| minor
!= GALAXY_DSP_MINOR
)
389 err
= dsp_command(galaxy
->port
, DSP_COMMAND_GALAXY_8
);
393 err
= dsp_command(galaxy
->port
, GALAXY_COMMAND_GET_TYPE
);
397 err
= dsp_get_byte(galaxy
->port
, type
);
404 static int galaxy_set_mode(struct snd_galaxy
*galaxy
, u8 mode
)
408 err
= dsp_command(galaxy
->port
, DSP_COMMAND_GALAXY_9
);
412 err
= dsp_command(galaxy
->port
, mode
);
418 * Needed for MPU IRQ on AZT1605, but AZT2316 loses WSS again
420 err
= dsp_reset(galaxy
->port
);
428 static void galaxy_set_config(struct snd_galaxy
*galaxy
, u32 config
)
430 u8 tmp
= ioread8(galaxy
->config_port
+ CONFIG_PORT_SET
);
433 iowrite8(tmp
| 0x80, galaxy
->config_port
+ CONFIG_PORT_SET
);
434 for (i
= 0; i
< GALAXY_CONFIG_SIZE
; i
++) {
435 iowrite8(config
, galaxy
->config_port
+ i
);
438 iowrite8(tmp
& 0x7f, galaxy
->config_port
+ CONFIG_PORT_SET
);
442 static void galaxy_config(struct snd_galaxy
*galaxy
, u32 config
)
446 for (i
= GALAXY_CONFIG_SIZE
; i
; i
--) {
447 u8 tmp
= ioread8(galaxy
->config_port
+ i
- 1);
448 galaxy
->config
= (galaxy
->config
<< 8) | tmp
;
450 config
|= galaxy
->config
& GALAXY_CONFIG_MASK
;
451 galaxy_set_config(galaxy
, config
);
454 static int galaxy_wss_config(struct snd_galaxy
*galaxy
, u8 wss_config
)
458 err
= wss_detect(galaxy
->wss_port
);
462 wss_set_config(galaxy
->wss_port
, wss_config
);
464 err
= galaxy_set_mode(galaxy
, GALAXY_MODE_WSS
);
471 static void snd_galaxy_free(struct snd_card
*card
)
473 struct snd_galaxy
*galaxy
= card
->private_data
;
475 if (galaxy
->wss_port
) {
476 wss_set_config(galaxy
->wss_port
, 0);
477 ioport_unmap(galaxy
->wss_port
);
478 release_and_free_resource(galaxy
->res_wss_port
);
480 if (galaxy
->config_port
) {
481 galaxy_set_config(galaxy
, galaxy
->config
);
482 ioport_unmap(galaxy
->config_port
);
483 release_and_free_resource(galaxy
->res_config_port
);
486 ioport_unmap(galaxy
->port
);
487 release_and_free_resource(galaxy
->res_port
);
491 static int snd_galaxy_probe(struct device
*dev
, unsigned int n
)
493 struct snd_galaxy
*galaxy
;
494 struct snd_wss
*chip
;
495 struct snd_card
*card
;
499 err
= snd_card_new(dev
, index
[n
], id
[n
], THIS_MODULE
,
500 sizeof(*galaxy
), &card
);
504 card
->private_free
= snd_galaxy_free
;
505 galaxy
= card
->private_data
;
507 galaxy
->res_port
= request_region(port
[n
], 16, DRV_NAME
);
508 if (!galaxy
->res_port
) {
509 dev_err(dev
, "could not grab ports %#lx-%#lx\n", port
[n
],
514 galaxy
->port
= ioport_map(port
[n
], 16);
516 err
= galaxy_init(galaxy
, &type
);
518 dev_err(dev
, "did not find a Sound Galaxy at %#lx\n", port
[n
]);
521 dev_info(dev
, "Sound Galaxy (type %d) found at %#lx\n", type
, port
[n
]);
523 galaxy
->res_config_port
= request_region(port
[n
] + GALAXY_PORT_CONFIG
,
525 if (!galaxy
->res_config_port
) {
526 dev_err(dev
, "could not grab ports %#lx-%#lx\n",
527 port
[n
] + GALAXY_PORT_CONFIG
,
528 port
[n
] + GALAXY_PORT_CONFIG
+ 15);
532 galaxy
->config_port
= ioport_map(port
[n
] + GALAXY_PORT_CONFIG
, 16);
534 galaxy_config(galaxy
, config
[n
]);
536 galaxy
->res_wss_port
= request_region(wss_port
[n
], 4, DRV_NAME
);
537 if (!galaxy
->res_wss_port
) {
538 dev_err(dev
, "could not grab ports %#lx-%#lx\n", wss_port
[n
],
543 galaxy
->wss_port
= ioport_map(wss_port
[n
], 4);
545 err
= galaxy_wss_config(galaxy
, wss_config
[n
]);
547 dev_err(dev
, "could not configure WSS\n");
551 strcpy(card
->driver
, DRV_NAME
);
552 strcpy(card
->shortname
, DRV_NAME
);
553 sprintf(card
->longname
, "%s at %#lx/%#lx, irq %d, dma %d/%d",
554 card
->shortname
, port
[n
], wss_port
[n
], irq
[n
], dma1
[n
],
557 err
= snd_wss_create(card
, wss_port
[n
] + 4, -1, irq
[n
], dma1
[n
],
558 dma2
[n
], WSS_HW_DETECT
, 0, &chip
);
562 err
= snd_wss_pcm(chip
, 0);
566 err
= snd_wss_mixer(chip
);
570 err
= snd_wss_timer(chip
, 0);
574 if (mpu_port
[n
] >= 0) {
575 err
= snd_mpu401_uart_new(card
, 0, MPU401_HW_MPU401
,
576 mpu_port
[n
], 0, mpu_irq
[n
], NULL
);
581 if (fm_port
[n
] >= 0) {
582 struct snd_opl3
*opl3
;
584 err
= snd_opl3_create(card
, fm_port
[n
], fm_port
[n
] + 2,
585 OPL3_HW_AUTO
, 0, &opl3
);
587 dev_err(dev
, "no OPL device at %#lx\n", fm_port
[n
]);
590 err
= snd_opl3_timer_new(opl3
, 1, 2);
594 err
= snd_opl3_hwdep_new(opl3
, 0, 1, NULL
);
599 err
= snd_card_register(card
);
603 dev_set_drvdata(dev
, card
);
611 static int snd_galaxy_remove(struct device
*dev
, unsigned int n
)
613 snd_card_free(dev_get_drvdata(dev
));
617 static struct isa_driver snd_galaxy_driver
= {
618 .match
= snd_galaxy_match
,
619 .probe
= snd_galaxy_probe
,
620 .remove
= snd_galaxy_remove
,
627 module_isa_driver(snd_galaxy_driver
, SNDRV_CARDS
);