0001
0002
0003
0004
0005
0006
0007 #include <linux/kernel.h>
0008 #include <linux/module.h>
0009 #include <linux/isa.h>
0010 #include <linux/delay.h>
0011 #include <linux/io.h>
0012 #include <asm/processor.h>
0013 #include <sound/core.h>
0014 #include <sound/initval.h>
0015 #include <sound/wss.h>
0016 #include <sound/mpu401.h>
0017 #include <sound/opl3.h>
0018
0019 MODULE_DESCRIPTION(CRD_NAME);
0020 MODULE_AUTHOR("Rene Herman");
0021 MODULE_LICENSE("GPL");
0022
0023 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0024 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0025 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
0026
0027 module_param_array(index, int, NULL, 0444);
0028 MODULE_PARM_DESC(index, "Index value for " CRD_NAME " soundcard.");
0029 module_param_array(id, charp, NULL, 0444);
0030 MODULE_PARM_DESC(id, "ID string for " CRD_NAME " soundcard.");
0031 module_param_array(enable, bool, NULL, 0444);
0032 MODULE_PARM_DESC(enable, "Enable " CRD_NAME " soundcard.");
0033
0034 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0035 static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0036 static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0037 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0038 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0039 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0040 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0041 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0042
0043 module_param_hw_array(port, long, ioport, NULL, 0444);
0044 MODULE_PARM_DESC(port, "Port # for " CRD_NAME " driver.");
0045 module_param_hw_array(wss_port, long, ioport, NULL, 0444);
0046 MODULE_PARM_DESC(wss_port, "WSS port # for " CRD_NAME " driver.");
0047 module_param_hw_array(mpu_port, long, ioport, NULL, 0444);
0048 MODULE_PARM_DESC(mpu_port, "MPU-401 port # for " CRD_NAME " driver.");
0049 module_param_hw_array(fm_port, long, ioport, NULL, 0444);
0050 MODULE_PARM_DESC(fm_port, "FM port # for " CRD_NAME " driver.");
0051 module_param_hw_array(irq, int, irq, NULL, 0444);
0052 MODULE_PARM_DESC(irq, "IRQ # for " CRD_NAME " driver.");
0053 module_param_hw_array(mpu_irq, int, irq, NULL, 0444);
0054 MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for " CRD_NAME " driver.");
0055 module_param_hw_array(dma1, int, dma, NULL, 0444);
0056 MODULE_PARM_DESC(dma1, "Playback DMA # for " CRD_NAME " driver.");
0057 module_param_hw_array(dma2, int, dma, NULL, 0444);
0058 MODULE_PARM_DESC(dma2, "Capture DMA # for " CRD_NAME " driver.");
0059
0060
0061
0062
0063
0064 #define DSP_PORT_RESET 0x6
0065 #define DSP_PORT_READ 0xa
0066 #define DSP_PORT_COMMAND 0xc
0067 #define DSP_PORT_STATUS 0xc
0068 #define DSP_PORT_DATA_AVAIL 0xe
0069
0070 #define DSP_SIGNATURE 0xaa
0071
0072 #define DSP_COMMAND_GET_VERSION 0xe1
0073
0074 static int dsp_get_byte(void __iomem *port, u8 *val)
0075 {
0076 int loops = 1000;
0077
0078 while (!(ioread8(port + DSP_PORT_DATA_AVAIL) & 0x80)) {
0079 if (!loops--)
0080 return -EIO;
0081 cpu_relax();
0082 }
0083 *val = ioread8(port + DSP_PORT_READ);
0084 return 0;
0085 }
0086
0087 static int dsp_reset(void __iomem *port)
0088 {
0089 u8 val;
0090
0091 iowrite8(1, port + DSP_PORT_RESET);
0092 udelay(10);
0093 iowrite8(0, port + DSP_PORT_RESET);
0094
0095 if (dsp_get_byte(port, &val) < 0 || val != DSP_SIGNATURE)
0096 return -ENODEV;
0097
0098 return 0;
0099 }
0100
0101 static int dsp_command(void __iomem *port, u8 cmd)
0102 {
0103 int loops = 1000;
0104
0105 while (ioread8(port + DSP_PORT_STATUS) & 0x80) {
0106 if (!loops--)
0107 return -EIO;
0108 cpu_relax();
0109 }
0110 iowrite8(cmd, port + DSP_PORT_COMMAND);
0111 return 0;
0112 }
0113
0114 static int dsp_get_version(void __iomem *port, u8 *major, u8 *minor)
0115 {
0116 int err;
0117
0118 err = dsp_command(port, DSP_COMMAND_GET_VERSION);
0119 if (err < 0)
0120 return err;
0121
0122 err = dsp_get_byte(port, major);
0123 if (err < 0)
0124 return err;
0125
0126 err = dsp_get_byte(port, minor);
0127 if (err < 0)
0128 return err;
0129
0130 return 0;
0131 }
0132
0133
0134
0135
0136
0137 #define WSS_CONFIG_DMA_0 (1 << 0)
0138 #define WSS_CONFIG_DMA_1 (2 << 0)
0139 #define WSS_CONFIG_DMA_3 (3 << 0)
0140 #define WSS_CONFIG_DUPLEX (1 << 2)
0141 #define WSS_CONFIG_IRQ_7 (1 << 3)
0142 #define WSS_CONFIG_IRQ_9 (2 << 3)
0143 #define WSS_CONFIG_IRQ_10 (3 << 3)
0144 #define WSS_CONFIG_IRQ_11 (4 << 3)
0145
0146 #define WSS_PORT_CONFIG 0
0147 #define WSS_PORT_SIGNATURE 3
0148
0149 #define WSS_SIGNATURE 4
0150
0151 static int wss_detect(void __iomem *wss_port)
0152 {
0153 if ((ioread8(wss_port + WSS_PORT_SIGNATURE) & 0x3f) != WSS_SIGNATURE)
0154 return -ENODEV;
0155
0156 return 0;
0157 }
0158
0159 static void wss_set_config(void __iomem *wss_port, u8 wss_config)
0160 {
0161 iowrite8(wss_config, wss_port + WSS_PORT_CONFIG);
0162 }
0163
0164
0165
0166
0167
0168 #define GALAXY_PORT_CONFIG 1024
0169 #define CONFIG_PORT_SET 4
0170
0171 #define DSP_COMMAND_GALAXY_8 8
0172 #define GALAXY_COMMAND_GET_TYPE 5
0173
0174 #define DSP_COMMAND_GALAXY_9 9
0175 #define GALAXY_COMMAND_WSSMODE 0
0176 #define GALAXY_COMMAND_SB8MODE 1
0177
0178 #define GALAXY_MODE_WSS GALAXY_COMMAND_WSSMODE
0179 #define GALAXY_MODE_SB8 GALAXY_COMMAND_SB8MODE
0180
0181 struct snd_galaxy {
0182 void __iomem *port;
0183 void __iomem *config_port;
0184 void __iomem *wss_port;
0185 u32 config;
0186 struct resource *res_port;
0187 struct resource *res_config_port;
0188 struct resource *res_wss_port;
0189 };
0190
0191 static u32 config[SNDRV_CARDS];
0192 static u8 wss_config[SNDRV_CARDS];
0193
0194 static int snd_galaxy_match(struct device *dev, unsigned int n)
0195 {
0196 if (!enable[n])
0197 return 0;
0198
0199 switch (port[n]) {
0200 case SNDRV_AUTO_PORT:
0201 dev_err(dev, "please specify port\n");
0202 return 0;
0203 case 0x220:
0204 config[n] |= GALAXY_CONFIG_SBA_220;
0205 break;
0206 case 0x240:
0207 config[n] |= GALAXY_CONFIG_SBA_240;
0208 break;
0209 case 0x260:
0210 config[n] |= GALAXY_CONFIG_SBA_260;
0211 break;
0212 case 0x280:
0213 config[n] |= GALAXY_CONFIG_SBA_280;
0214 break;
0215 default:
0216 dev_err(dev, "invalid port %#lx\n", port[n]);
0217 return 0;
0218 }
0219
0220 switch (wss_port[n]) {
0221 case SNDRV_AUTO_PORT:
0222 dev_err(dev, "please specify wss_port\n");
0223 return 0;
0224 case 0x530:
0225 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_530;
0226 break;
0227 case 0x604:
0228 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_604;
0229 break;
0230 case 0xe80:
0231 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_E80;
0232 break;
0233 case 0xf40:
0234 config[n] |= GALAXY_CONFIG_WSS_ENABLE | GALAXY_CONFIG_WSSA_F40;
0235 break;
0236 default:
0237 dev_err(dev, "invalid WSS port %#lx\n", wss_port[n]);
0238 return 0;
0239 }
0240
0241 switch (irq[n]) {
0242 case SNDRV_AUTO_IRQ:
0243 dev_err(dev, "please specify irq\n");
0244 return 0;
0245 case 7:
0246 wss_config[n] |= WSS_CONFIG_IRQ_7;
0247 break;
0248 case 2:
0249 irq[n] = 9;
0250 fallthrough;
0251 case 9:
0252 wss_config[n] |= WSS_CONFIG_IRQ_9;
0253 break;
0254 case 10:
0255 wss_config[n] |= WSS_CONFIG_IRQ_10;
0256 break;
0257 case 11:
0258 wss_config[n] |= WSS_CONFIG_IRQ_11;
0259 break;
0260 default:
0261 dev_err(dev, "invalid IRQ %d\n", irq[n]);
0262 return 0;
0263 }
0264
0265 switch (dma1[n]) {
0266 case SNDRV_AUTO_DMA:
0267 dev_err(dev, "please specify dma1\n");
0268 return 0;
0269 case 0:
0270 wss_config[n] |= WSS_CONFIG_DMA_0;
0271 break;
0272 case 1:
0273 wss_config[n] |= WSS_CONFIG_DMA_1;
0274 break;
0275 case 3:
0276 wss_config[n] |= WSS_CONFIG_DMA_3;
0277 break;
0278 default:
0279 dev_err(dev, "invalid playback DMA %d\n", dma1[n]);
0280 return 0;
0281 }
0282
0283 if (dma2[n] == SNDRV_AUTO_DMA || dma2[n] == dma1[n]) {
0284 dma2[n] = -1;
0285 goto mpu;
0286 }
0287
0288 wss_config[n] |= WSS_CONFIG_DUPLEX;
0289 switch (dma2[n]) {
0290 case 0:
0291 break;
0292 case 1:
0293 if (dma1[n] == 0)
0294 break;
0295 fallthrough;
0296 default:
0297 dev_err(dev, "invalid capture DMA %d\n", dma2[n]);
0298 return 0;
0299 }
0300
0301 mpu:
0302 switch (mpu_port[n]) {
0303 case SNDRV_AUTO_PORT:
0304 dev_warn(dev, "mpu_port not specified; not using MPU-401\n");
0305 mpu_port[n] = -1;
0306 goto fm;
0307 case 0x300:
0308 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_300;
0309 break;
0310 case 0x330:
0311 config[n] |= GALAXY_CONFIG_MPU_ENABLE | GALAXY_CONFIG_MPUA_330;
0312 break;
0313 default:
0314 dev_err(dev, "invalid MPU port %#lx\n", mpu_port[n]);
0315 return 0;
0316 }
0317
0318 switch (mpu_irq[n]) {
0319 case SNDRV_AUTO_IRQ:
0320 dev_warn(dev, "mpu_irq not specified: using polling mode\n");
0321 mpu_irq[n] = -1;
0322 break;
0323 case 2:
0324 mpu_irq[n] = 9;
0325 fallthrough;
0326 case 9:
0327 config[n] |= GALAXY_CONFIG_MPUIRQ_2;
0328 break;
0329 #ifdef AZT1605
0330 case 3:
0331 config[n] |= GALAXY_CONFIG_MPUIRQ_3;
0332 break;
0333 #endif
0334 case 5:
0335 config[n] |= GALAXY_CONFIG_MPUIRQ_5;
0336 break;
0337 case 7:
0338 config[n] |= GALAXY_CONFIG_MPUIRQ_7;
0339 break;
0340 #ifdef AZT2316
0341 case 10:
0342 config[n] |= GALAXY_CONFIG_MPUIRQ_10;
0343 break;
0344 #endif
0345 default:
0346 dev_err(dev, "invalid MPU IRQ %d\n", mpu_irq[n]);
0347 return 0;
0348 }
0349
0350 if (mpu_irq[n] == irq[n]) {
0351 dev_err(dev, "cannot share IRQ between WSS and MPU-401\n");
0352 return 0;
0353 }
0354
0355 fm:
0356 switch (fm_port[n]) {
0357 case SNDRV_AUTO_PORT:
0358 dev_warn(dev, "fm_port not specified: not using OPL3\n");
0359 fm_port[n] = -1;
0360 break;
0361 case 0x388:
0362 break;
0363 default:
0364 dev_err(dev, "illegal FM port %#lx\n", fm_port[n]);
0365 return 0;
0366 }
0367
0368 config[n] |= GALAXY_CONFIG_GAME_ENABLE;
0369 return 1;
0370 }
0371
0372 static int galaxy_init(struct snd_galaxy *galaxy, u8 *type)
0373 {
0374 u8 major;
0375 u8 minor;
0376 int err;
0377
0378 err = dsp_reset(galaxy->port);
0379 if (err < 0)
0380 return err;
0381
0382 err = dsp_get_version(galaxy->port, &major, &minor);
0383 if (err < 0)
0384 return err;
0385
0386 if (major != GALAXY_DSP_MAJOR || minor != GALAXY_DSP_MINOR)
0387 return -ENODEV;
0388
0389 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_8);
0390 if (err < 0)
0391 return err;
0392
0393 err = dsp_command(galaxy->port, GALAXY_COMMAND_GET_TYPE);
0394 if (err < 0)
0395 return err;
0396
0397 err = dsp_get_byte(galaxy->port, type);
0398 if (err < 0)
0399 return err;
0400
0401 return 0;
0402 }
0403
0404 static int galaxy_set_mode(struct snd_galaxy *galaxy, u8 mode)
0405 {
0406 int err;
0407
0408 err = dsp_command(galaxy->port, DSP_COMMAND_GALAXY_9);
0409 if (err < 0)
0410 return err;
0411
0412 err = dsp_command(galaxy->port, mode);
0413 if (err < 0)
0414 return err;
0415
0416 #ifdef AZT1605
0417
0418
0419
0420 err = dsp_reset(galaxy->port);
0421 if (err < 0)
0422 return err;
0423 #endif
0424
0425 return 0;
0426 }
0427
0428 static void galaxy_set_config(struct snd_galaxy *galaxy, u32 config)
0429 {
0430 u8 tmp = ioread8(galaxy->config_port + CONFIG_PORT_SET);
0431 int i;
0432
0433 iowrite8(tmp | 0x80, galaxy->config_port + CONFIG_PORT_SET);
0434 for (i = 0; i < GALAXY_CONFIG_SIZE; i++) {
0435 iowrite8(config, galaxy->config_port + i);
0436 config >>= 8;
0437 }
0438 iowrite8(tmp & 0x7f, galaxy->config_port + CONFIG_PORT_SET);
0439 msleep(10);
0440 }
0441
0442 static void galaxy_config(struct snd_galaxy *galaxy, u32 config)
0443 {
0444 int i;
0445
0446 for (i = GALAXY_CONFIG_SIZE; i; i--) {
0447 u8 tmp = ioread8(galaxy->config_port + i - 1);
0448 galaxy->config = (galaxy->config << 8) | tmp;
0449 }
0450 config |= galaxy->config & GALAXY_CONFIG_MASK;
0451 galaxy_set_config(galaxy, config);
0452 }
0453
0454 static int galaxy_wss_config(struct snd_galaxy *galaxy, u8 wss_config)
0455 {
0456 int err;
0457
0458 err = wss_detect(galaxy->wss_port);
0459 if (err < 0)
0460 return err;
0461
0462 wss_set_config(galaxy->wss_port, wss_config);
0463
0464 err = galaxy_set_mode(galaxy, GALAXY_MODE_WSS);
0465 if (err < 0)
0466 return err;
0467
0468 return 0;
0469 }
0470
0471 static void snd_galaxy_free(struct snd_card *card)
0472 {
0473 struct snd_galaxy *galaxy = card->private_data;
0474
0475 if (galaxy->wss_port)
0476 wss_set_config(galaxy->wss_port, 0);
0477 if (galaxy->config_port)
0478 galaxy_set_config(galaxy, galaxy->config);
0479 }
0480
0481 static int __snd_galaxy_probe(struct device *dev, unsigned int n)
0482 {
0483 struct snd_galaxy *galaxy;
0484 struct snd_wss *chip;
0485 struct snd_card *card;
0486 u8 type;
0487 int err;
0488
0489 err = snd_devm_card_new(dev, index[n], id[n], THIS_MODULE,
0490 sizeof(*galaxy), &card);
0491 if (err < 0)
0492 return err;
0493
0494 card->private_free = snd_galaxy_free;
0495 galaxy = card->private_data;
0496
0497 galaxy->res_port = devm_request_region(dev, port[n], 16, DRV_NAME);
0498 if (!galaxy->res_port) {
0499 dev_err(dev, "could not grab ports %#lx-%#lx\n", port[n],
0500 port[n] + 15);
0501 return -EBUSY;
0502 }
0503 galaxy->port = devm_ioport_map(dev, port[n], 16);
0504 if (!galaxy->port)
0505 return -ENOMEM;
0506
0507 err = galaxy_init(galaxy, &type);
0508 if (err < 0) {
0509 dev_err(dev, "did not find a Sound Galaxy at %#lx\n", port[n]);
0510 return err;
0511 }
0512 dev_info(dev, "Sound Galaxy (type %d) found at %#lx\n", type, port[n]);
0513
0514 galaxy->res_config_port =
0515 devm_request_region(dev, port[n] + GALAXY_PORT_CONFIG, 16,
0516 DRV_NAME);
0517 if (!galaxy->res_config_port) {
0518 dev_err(dev, "could not grab ports %#lx-%#lx\n",
0519 port[n] + GALAXY_PORT_CONFIG,
0520 port[n] + GALAXY_PORT_CONFIG + 15);
0521 return -EBUSY;
0522 }
0523 galaxy->config_port =
0524 devm_ioport_map(dev, port[n] + GALAXY_PORT_CONFIG, 16);
0525 if (!galaxy->config_port)
0526 return -ENOMEM;
0527 galaxy_config(galaxy, config[n]);
0528
0529 galaxy->res_wss_port = devm_request_region(dev, wss_port[n], 4, DRV_NAME);
0530 if (!galaxy->res_wss_port) {
0531 dev_err(dev, "could not grab ports %#lx-%#lx\n", wss_port[n],
0532 wss_port[n] + 3);
0533 return -EBUSY;
0534 }
0535 galaxy->wss_port = devm_ioport_map(dev, wss_port[n], 4);
0536 if (!galaxy->wss_port)
0537 return -ENOMEM;
0538
0539 err = galaxy_wss_config(galaxy, wss_config[n]);
0540 if (err < 0) {
0541 dev_err(dev, "could not configure WSS\n");
0542 return err;
0543 }
0544
0545 strcpy(card->driver, DRV_NAME);
0546 strcpy(card->shortname, DRV_NAME);
0547 sprintf(card->longname, "%s at %#lx/%#lx, irq %d, dma %d/%d",
0548 card->shortname, port[n], wss_port[n], irq[n], dma1[n],
0549 dma2[n]);
0550
0551 err = snd_wss_create(card, wss_port[n] + 4, -1, irq[n], dma1[n],
0552 dma2[n], WSS_HW_DETECT, 0, &chip);
0553 if (err < 0)
0554 return err;
0555
0556 err = snd_wss_pcm(chip, 0);
0557 if (err < 0)
0558 return err;
0559
0560 err = snd_wss_mixer(chip);
0561 if (err < 0)
0562 return err;
0563
0564 err = snd_wss_timer(chip, 0);
0565 if (err < 0)
0566 return err;
0567
0568 if (mpu_port[n] >= 0) {
0569 err = snd_mpu401_uart_new(card, 0, MPU401_HW_MPU401,
0570 mpu_port[n], 0, mpu_irq[n], NULL);
0571 if (err < 0)
0572 return err;
0573 }
0574
0575 if (fm_port[n] >= 0) {
0576 struct snd_opl3 *opl3;
0577
0578 err = snd_opl3_create(card, fm_port[n], fm_port[n] + 2,
0579 OPL3_HW_AUTO, 0, &opl3);
0580 if (err < 0) {
0581 dev_err(dev, "no OPL device at %#lx\n", fm_port[n]);
0582 return err;
0583 }
0584 err = snd_opl3_timer_new(opl3, 1, 2);
0585 if (err < 0)
0586 return err;
0587
0588 err = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0589 if (err < 0)
0590 return err;
0591 }
0592
0593 err = snd_card_register(card);
0594 if (err < 0)
0595 return err;
0596
0597 dev_set_drvdata(dev, card);
0598 return 0;
0599 }
0600
0601 static int snd_galaxy_probe(struct device *dev, unsigned int n)
0602 {
0603 return snd_card_free_on_error(dev, __snd_galaxy_probe(dev, n));
0604 }
0605
0606 static struct isa_driver snd_galaxy_driver = {
0607 .match = snd_galaxy_match,
0608 .probe = snd_galaxy_probe,
0609
0610 .driver = {
0611 .name = DEV_NAME
0612 }
0613 };
0614
0615 module_isa_driver(snd_galaxy_driver, SNDRV_CARDS);