28 #include <linux/module.h>
38 #define SNDRV_LEGACY_FIND_FREE_IRQ
39 #define SNDRV_LEGACY_FIND_FREE_DMA
46 "{AudioExcel, Audio Excel DSP 16},"
86 #define WRITE_MDIRQ_CFG 0x50
87 #define COMMAND_52 0x52
88 #define READ_HARD_CFG 0x58
89 #define COMMAND_5C 0x5c
90 #define COMMAND_60 0x60
91 #define COMMAND_66 0x66
92 #define COMMAND_6C 0x6c
93 #define COMMAND_6E 0x6e
94 #define COMMAND_88 0x88
95 #define DSP_INIT_MSS 0x8c
96 #define COMMAND_C5 0xc5
97 #define GET_DSP_VERSION 0xe1
98 #define GET_DSP_COPYRIGHT 0xe3
109 #define DSP_RESET 0x06
110 #define DSP_READ 0x0a
111 #define DSP_WRITE 0x0c
112 #define DSP_COMMAND 0x0c
113 #define DSP_STATUS 0x0c
114 #define DSP_DATAVAIL 0x0e
116 #define PFX "sc6000: "
117 #define DRV_NAME "SC-6000"
124 static __devinit unsigned char sc6000_irq_to_softcfg(
int irq)
126 unsigned char val = 0;
153 static __devinit unsigned char sc6000_dma_to_softcfg(
int dma)
155 unsigned char val = 0;
176 static __devinit unsigned char sc6000_mpu_irq_to_softcfg(
int mpu_irq)
178 unsigned char val = 0;
202 unsigned char val = 0;
214 static int sc6000_read(
char __iomem *vport)
216 if (sc6000_wait_data(vport))
223 static int sc6000_write(
char __iomem *vport,
int cmd)
250 if (sc6000_write(vport, command)) {
256 int val = sc6000_read(vport);
263 }
while (len < data_len);
269 return len ? len : -
EIO;
278 if (sc6000_read(vport) == 0xaa)
294 if (sc6000_write(vport, cfg[0]) < 0) {
298 if (sc6000_write(vport, cfg[1]) < 0) {
310 static int sc6000_cfg_write(
char __iomem *vport,
unsigned char softcfg)
317 if (sc6000_write(vport, softcfg)) {
324 static int sc6000_setup_board(
char __iomem *vport,
int config)
334 }
while ((sc6000_wait_data(vport) < 0) && loop--);
336 if (sc6000_read(vport) < 0) {
342 if (sc6000_cfg_write(vport, config))
349 char __iomem *vmss_port,
int mss_config)
359 if (sc6000_cfg_write(vport, config))
368 long xport,
long xmpu,
369 long xmss_port,
int joystick)
376 cfg[0] |= (xmpu & 0x30) >> 2;
379 if (xmss_port == 0xe80)
386 snd_printd(
"hw cfg %x, %x\n", cfg[0], cfg[1]);
394 int mss_config = sc6000_irq_to_softcfg(irq[dev]) |
395 sc6000_dma_to_softcfg(dma[dev]);
396 int config = mss_config |
397 sc6000_mpu_irq_to_softcfg(mpu_irq[dev]);
401 err = sc6000_dsp_reset(vport);
407 memset(answer, 0,
sizeof(answer));
417 if (
strncmp(
"SC-6000", answer, 7))
425 answer, version[0], version[1]);
429 if (sc6000_read(vport) < 0)
434 sc6000_hw_cfg_encode(vport, &cfg[0],
port[dev], mpu_port[dev],
435 mss_port[dev], joystick[dev]);
436 if (sc6000_hw_cfg_write(vport, cfg) < 0) {
441 err = sc6000_setup_board(vport, config);
447 sc6000_dsp_reset(vport);
451 sc6000_write(vport, 0x02);
452 sc6000_dsp_reset(vport);
455 err = sc6000_setup_board(vport, config);
460 err = sc6000_init_mss(vport, config, vmss_port, mss_config);
463 "Microsoft Sound System mode.\n");
505 static int __devinit snd_sc6000_match(
struct device *devptr,
unsigned int dev)
517 if (
port[dev] != 0x220 &&
port[dev] != 0x240) {
521 if (mss_port[dev] != 0x530 && mss_port[dev] != 0xe80) {
525 if (irq[dev] !=
SNDRV_AUTO_IRQ && !sc6000_irq_to_softcfg(irq[dev])) {
529 if (dma[dev] !=
SNDRV_AUTO_DMA && !sc6000_dma_to_softcfg(dma[dev])) {
534 (mpu_port[dev] & ~0x30L) != 0x300) {
541 !sc6000_mpu_irq_to_softcfg(mpu_irq[dev])) {
548 static int __devinit snd_sc6000_probe(
struct device *devptr,
unsigned int dev)
550 static int possible_irqs[] = { 5, 7, 9, 10, 11, -1 };
551 static int possible_dmas[] = { 1, 3, 0, -1 };
569 xirq = snd_legacy_find_free_irq(possible_irqs);
578 xdma = snd_legacy_find_free_dma(possible_dmas);
588 "I/O port region is already in use.\n");
592 *vport = devm_ioport_map(devptr,
port[dev], 0x10);
593 if (*vport ==
NULL) {
595 "I/O port cannot be iomaped.\n");
603 "SC-6000 port I/O port region is already in use.\n");
607 vmss_port = devm_ioport_map(devptr, mss_port[dev], 4);
610 "MSS port I/O cannot be iomaped.\n");
615 snd_printd(
"Initializing BASE[0x%lx] IRQ[%d] DMA[%d] MIRQ[%d]\n",
616 port[dev], xirq, xdma,
619 err = sc6000_init_board(*vport, vmss_port, dev);
631 "error creating new WSS PCM device\n");
639 err = snd_sc6000_mixer(chip);
661 mpu_irq[dev],
NULL) < 0)
669 mss_port[dev], xirq, xdma);
681 sc6000_setup_board(*vport, 0);
690 static int __devexit snd_sc6000_remove(
struct device *devptr,
unsigned int dev)
695 if (sc6000_setup_board(*vport, 0) < 0)
706 static struct isa_driver snd_sc6000_driver = {
707 .match = snd_sc6000_match,
708 .probe = snd_sc6000_probe,
717 static int __init alsa_card_sc6000_init(
void)
722 static void __exit alsa_card_sc6000_exit(
void)