From c282866101bfde888a44da3babd2f9ab265ca6f9 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sat, 4 Apr 2009 14:48:32 +0200 Subject: ALSA: sc6000: add support for SC-6600 and SC-7000 Add support for later cards based on CompuMedia ASC-9408 chipsets. These cards were produced by Gallant. This patch make the OSS aedsp16 driver redundant. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/Kconfig | 7 ++- sound/isa/sc6000.c | 127 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 104 insertions(+), 30 deletions(-) (limited to 'sound/isa') diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig index c5c9a9218ff..64129bf2205 100644 --- a/sound/isa/Kconfig +++ b/sound/isa/Kconfig @@ -177,15 +177,18 @@ config SND_ES18XX will be called snd-es18xx. config SND_SC6000 - tristate "Gallant SC-6000, Audio Excel DSP 16" + tristate "Gallant SC-6000/6600/7000 and Audio Excel DSP 16" depends on HAS_IOPORT select SND_WSS_LIB select SND_OPL3_LIB select SND_MPU401_UART help - Say Y here to include support for Gallant SC-6000 card and clones: + Say Y here to include support for Gallant SC-6000, SC-6600, SC-7000 + cards and clones: Audio Excel DSP 16 and Zoltrix AV302. + These cards are based on CompuMedia ASC-9308 or ASC-9408 chips. + To compile this driver as a module, choose M here: the module will be called snd-sc6000. diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 782010608ef..983ab7e3b5b 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -2,6 +2,8 @@ * Driver for Gallant SC-6000 soundcard. This card is also known as * Audio Excel DSP 16 or Zoltrix AV302. * These cards use CompuMedia ASC-9308 chip + AD1848 codec. + * SC-6600 and SC-7000 cards are also supported. They are based on + * CompuMedia ASC-9408 chip and CS4231 codec. * * Copyright (C) 2007 Krzysztof Helt * @@ -191,7 +193,7 @@ static __devinit unsigned char sc6000_mpu_irq_to_softcfg(int mpu_irq) return val; } -static __devinit int sc6000_wait_data(char __iomem *vport) +static int sc6000_wait_data(char __iomem *vport) { int loop = 1000; unsigned char val = 0; @@ -206,7 +208,7 @@ static __devinit int sc6000_wait_data(char __iomem *vport) return -EAGAIN; } -static __devinit int sc6000_read(char __iomem *vport) +static int sc6000_read(char __iomem *vport) { if (sc6000_wait_data(vport)) return -EBUSY; @@ -215,7 +217,7 @@ static __devinit int sc6000_read(char __iomem *vport) } -static __devinit int sc6000_write(char __iomem *vport, int cmd) +static int sc6000_write(char __iomem *vport, int cmd) { unsigned char val; int loop = 500000; @@ -276,8 +278,33 @@ static int __devinit sc6000_dsp_reset(char __iomem *vport) } /* detection and initialization */ -static int __devinit sc6000_cfg_write(char __iomem *vport, - unsigned char softcfg) +static int __devinit sc6000_hw_cfg_write(char __iomem *vport, const int *cfg) +{ + if (sc6000_write(vport, COMMAND_6C) < 0) { + snd_printk(KERN_WARNING "CMD 0x%x: failed!\n", COMMAND_6C); + return -EIO; + } + if (sc6000_write(vport, COMMAND_5C) < 0) { + snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_5C); + return -EIO; + } + if (sc6000_write(vport, cfg[0]) < 0) { + snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[0]); + return -EIO; + } + if (sc6000_write(vport, cfg[1]) < 0) { + snd_printk(KERN_ERR "DATA 0x%x: failed!\n", cfg[1]); + return -EIO; + } + if (sc6000_write(vport, COMMAND_C5) < 0) { + snd_printk(KERN_ERR "CMD 0x%x: failed!\n", COMMAND_C5); + return -EIO; + } + + return 0; +} + +static int sc6000_cfg_write(char __iomem *vport, unsigned char softcfg) { if (sc6000_write(vport, WRITE_MDIRQ_CFG)) { @@ -291,7 +318,7 @@ static int __devinit sc6000_cfg_write(char __iomem *vport, return 0; } -static int __devinit sc6000_setup_board(char __iomem *vport, int config) +static int sc6000_setup_board(char __iomem *vport, int config) { int loop = 10; @@ -334,16 +361,38 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config, return 0; } -static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, - char __iomem *vmss_port, int mpu_irq) +static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, + long xport, long xmpu, + long xmss_port) +{ + cfg[0] = 0; + cfg[1] = 0; + if (xport == 0x240) + cfg[0] |= 1; + if (xmpu != SNDRV_AUTO_PORT) { + cfg[0] |= (xmpu & 0x30) >> 2; + cfg[1] |= 0x20; + } + if (xmss_port == 0xe80) + cfg[0] |= 0x10; + cfg[0] |= 0x40; /* always set */ + cfg[1] |= 0x80; /* enable WSS system */ + cfg[1] &= ~0x40; /* disable IDE */ + snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); +} + +static int __devinit sc6000_init_board(char __iomem *vport, + char __iomem *vmss_port, int dev) { char answer[15]; char version[2]; - int mss_config = sc6000_irq_to_softcfg(irq) | - sc6000_dma_to_softcfg(dma); + int mss_config = sc6000_irq_to_softcfg(irq[dev]) | + sc6000_dma_to_softcfg(dma[dev]); int config = mss_config | - sc6000_mpu_irq_to_softcfg(mpu_irq); + sc6000_mpu_irq_to_softcfg(mpu_irq[dev]); int err; + int cfg[2]; + int old = 0; err = sc6000_dsp_reset(vport); if (err < 0) { @@ -360,7 +409,6 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, /* * My SC-6000 card return "SC-6000" in DSPCopyright, so * if we have something different, we have to be warned. - * Mine returns "SC-6000A " - KH */ if (strncmp("SC-6000", answer, 7)) snd_printk(KERN_WARNING "Warning: non SC-6000 audio card!\n"); @@ -372,13 +420,29 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, printk(KERN_INFO PFX "Detected model: %s, DSP version %d.%d\n", answer, version[0], version[1]); - /* - * 0x0A == (IRQ 7, DMA 1, MIRQ 0) - */ - err = sc6000_cfg_write(vport, 0x0a); + /* set configuration */ + sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], + mss_port[dev]); + if (sc6000_hw_cfg_write(vport, cfg) < 0) { + snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); + return -EIO; + } + err = sc6000_setup_board(vport, config); if (err < 0) { - snd_printk(KERN_ERR "sc6000_cfg_write: failed!\n"); - return -EFAULT; + snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); + return -ENODEV; + } + + sc6000_dsp_reset(vport); + sc6000_write(vport, COMMAND_5C); + if (sc6000_read(vport) < 0) + old = 1; + sc6000_dsp_reset(vport); + + if (!old) { + sc6000_write(vport, COMMAND_60); + sc6000_write(vport, 0x02); + sc6000_dsp_reset(vport); } err = sc6000_setup_board(vport, config); @@ -386,10 +450,9 @@ static int __devinit sc6000_init_board(char __iomem *vport, int irq, int dma, snd_printk(KERN_ERR "sc6000_setup_board: failed!\n"); return -ENODEV; } - err = sc6000_init_mss(vport, config, vmss_port, mss_config); if (err < 0) { - snd_printk(KERN_ERR "Can not initialize " + snd_printk(KERN_ERR "Cannot initialize " "Microsoft Sound System mode.\n"); return -ENODEV; } @@ -485,14 +548,16 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) struct snd_card *card; struct snd_wss *chip; struct snd_opl3 *opl3; - char __iomem *vport; + char __iomem **vport; char __iomem *vmss_port; - err = snd_card_create(index[dev], id[dev], THIS_MODULE, 0, &card); + err = snd_card_create(index[dev], id[dev], THIS_MODULE, sizeof(vport), + &card); if (err < 0) return err; + vport = card->private_data; if (xirq == SNDRV_AUTO_IRQ) { xirq = snd_legacy_find_free_irq(possible_irqs); if (xirq < 0) { @@ -517,8 +582,8 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) err = -EBUSY; goto err_exit; } - vport = devm_ioport_map(devptr, port[dev], 0x10); - if (!vport) { + *vport = devm_ioport_map(devptr, port[dev], 0x10); + if (*vport == NULL) { snd_printk(KERN_ERR PFX "I/O port cannot be iomaped.\n"); err = -EBUSY; @@ -533,7 +598,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) goto err_unmap1; } vmss_port = devm_ioport_map(devptr, mss_port[dev], 4); - if (!vport) { + if (!vmss_port) { snd_printk(KERN_ERR PFX "MSS port I/O cannot be iomaped.\n"); err = -EBUSY; @@ -544,7 +609,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) port[dev], xirq, xdma, mpu_irq[dev] == SNDRV_AUTO_IRQ ? 0 : mpu_irq[dev]); - err = sc6000_init_board(vport, xirq, xdma, vmss_port, mpu_irq[dev]); + err = sc6000_init_board(*vport, vmss_port, dev); if (err < 0) goto err_unmap2; @@ -552,7 +617,6 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) WSS_HW_DETECT, 0, &chip); if (err < 0) goto err_unmap2; - card->private_data = chip; err = snd_wss_pcm(chip, 0, NULL); if (err < 0) { @@ -608,6 +672,7 @@ static int __devinit snd_sc6000_probe(struct device *devptr, unsigned int dev) return 0; err_unmap2: + sc6000_setup_board(*vport, 0); release_region(mss_port[dev], 4); err_unmap1: release_region(port[dev], 0x10); @@ -618,11 +683,17 @@ err_exit: static int __devexit snd_sc6000_remove(struct device *devptr, unsigned int dev) { + struct snd_card *card = dev_get_drvdata(devptr); + char __iomem **vport = card->private_data; + + if (sc6000_setup_board(*vport, 0) < 0) + snd_printk(KERN_WARNING "sc6000_setup_board failed on exit!\n"); + release_region(port[dev], 0x10); release_region(mss_port[dev], 4); - snd_card_free(dev_get_drvdata(devptr)); dev_set_drvdata(devptr, NULL); + snd_card_free(card); return 0; } -- cgit v1.2.3 From 0cfcdedaddf2468cb53e3cff9c3abfef14b4d784 Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Thu, 23 Apr 2009 21:46:19 +0200 Subject: ALSA: sc6000: fix older card initialization The last patch to handle newer cards like SC7000 broke initialization of the SC6000. Fix this. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/sc6000.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) (limited to 'sound/isa') diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index 983ab7e3b5b..c803b2e30df 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -391,7 +391,6 @@ static int __devinit sc6000_init_board(char __iomem *vport, int config = mss_config | sc6000_mpu_irq_to_softcfg(mpu_irq[dev]); int err; - int cfg[2]; int old = 0; err = sc6000_dsp_reset(vport); @@ -421,11 +420,18 @@ static int __devinit sc6000_init_board(char __iomem *vport, answer, version[0], version[1]); /* set configuration */ - sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], - mss_port[dev]); - if (sc6000_hw_cfg_write(vport, cfg) < 0) { - snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); - return -EIO; + sc6000_write(vport, COMMAND_5C); + if (sc6000_read(vport) < 0) + old = 1; + + if (!old) { + int cfg[2]; + sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], + mss_port[dev]); + if (sc6000_hw_cfg_write(vport, cfg) < 0) { + snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); + return -EIO; + } } err = sc6000_setup_board(vport, config); if (err < 0) { @@ -434,10 +440,6 @@ static int __devinit sc6000_init_board(char __iomem *vport, } sc6000_dsp_reset(vport); - sc6000_write(vport, COMMAND_5C); - if (sc6000_read(vport) < 0) - old = 1; - sc6000_dsp_reset(vport); if (!old) { sc6000_write(vport, COMMAND_60); -- cgit v1.2.3 From b0ec3a30bc01c15cc6277b223fae136f7b71e90c Mon Sep 17 00:00:00 2001 From: Krzysztof Helt Date: Sun, 3 May 2009 10:39:19 +0200 Subject: ALSA: sc6000: enable joystick port Add module parameter to enable or disable joystick port (gameport) on the SC6600 and later cards. Signed-off-by: Krzysztof Helt Signed-off-by: Takashi Iwai --- sound/isa/sc6000.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'sound/isa') diff --git a/sound/isa/sc6000.c b/sound/isa/sc6000.c index c803b2e30df..9a8bbf6dd62 100644 --- a/sound/isa/sc6000.c +++ b/sound/isa/sc6000.c @@ -56,6 +56,7 @@ static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT; /* 0x300, 0x310, 0x320, 0x330 */ static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ; /* 5, 7, 9, 10, 0 */ static int dma[SNDRV_CARDS] = SNDRV_DEFAULT_DMA; /* 0, 1, 3 */ +static bool joystick[SNDRV_CARDS] = { [0 ... (SNDRV_CARDS-1)] = false }; module_param_array(index, int, NULL, 0444); MODULE_PARM_DESC(index, "Index value for sc-6000 based soundcard."); @@ -75,6 +76,8 @@ module_param_array(mpu_irq, int, NULL, 0444); MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for sc-6000 driver."); module_param_array(dma, int, NULL, 0444); MODULE_PARM_DESC(dma, "DMA # for sc-6000 driver."); +module_param_array(joystick, bool, NULL, 0444); +MODULE_PARM_DESC(joystick, "Enable gameport."); /* * Commands of SC6000's DSP (SBPRO+special). @@ -363,7 +366,7 @@ static int __devinit sc6000_init_mss(char __iomem *vport, int config, static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, long xport, long xmpu, - long xmss_port) + long xmss_port, int joystick) { cfg[0] = 0; cfg[1] = 0; @@ -376,6 +379,8 @@ static void __devinit sc6000_hw_cfg_encode(char __iomem *vport, int *cfg, if (xmss_port == 0xe80) cfg[0] |= 0x10; cfg[0] |= 0x40; /* always set */ + if (!joystick) + cfg[0] |= 0x02; cfg[1] |= 0x80; /* enable WSS system */ cfg[1] &= ~0x40; /* disable IDE */ snd_printd("hw cfg %x, %x\n", cfg[0], cfg[1]); @@ -427,7 +432,7 @@ static int __devinit sc6000_init_board(char __iomem *vport, if (!old) { int cfg[2]; sc6000_hw_cfg_encode(vport, &cfg[0], port[dev], mpu_port[dev], - mss_port[dev]); + mss_port[dev], joystick[dev]); if (sc6000_hw_cfg_write(vport, cfg) < 0) { snd_printk(KERN_ERR "sc6000_hw_cfg_write: failed!\n"); return -EIO; -- cgit v1.2.3