Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-#include <sound/driver.h>
#include <linux/init.h>
-#include <linux/sched.h>
#include <linux/wait.h>
#include <linux/pnp.h>
#include <linux/moduleparam.h>
MODULE_PARM_DESC(id, "ID string for DT-019X based soundcard.");
module_param_array(enable, bool, NULL, 0444);
MODULE_PARM_DESC(enable, "Enable DT-019X based soundcard.");
-module_param_array(port, long, NULL, 0444);
-MODULE_PARM_DESC(port, "Port # for dt019x driver.");
-module_param_array(mpu_port, long, NULL, 0444);
-MODULE_PARM_DESC(mpu_port, "MPU-401 port # for dt019x driver.");
-module_param_array(fm_port, long, NULL, 0444);
-MODULE_PARM_DESC(fm_port, "FM port # for dt019x driver.");
-module_param_array(irq, int, NULL, 0444);
-MODULE_PARM_DESC(irq, "IRQ # for dt019x driver.");
-module_param_array(mpu_irq, int, NULL, 0444);
-MODULE_PARM_DESC(mpu_irq, "MPU-401 IRQ # for dt019x driver.");
-module_param_array(dma8, int, NULL, 0444);
-MODULE_PARM_DESC(dma8, "8-bit DMA # for dt019x driver.");
struct snd_card_dt019x {
struct pnp_dev *dev;
struct pnp_dev *devmpu;
struct pnp_dev *devopl;
+ struct snd_sb *chip;
};
static struct pnp_card_device_id snd_dt019x_pnpids[] = {
const struct pnp_card_device_id *pid)
{
struct pnp_dev *pdev;
- struct pnp_resource_table * cfg = kmalloc(sizeof(struct pnp_resource_table), GFP_KERNEL);
int err;
- if (!cfg)
- return -ENOMEM;
-
acard->dev = pnp_request_card_device(card, pid->devs[0].id, NULL);
- if (acard->dev == NULL) {
- kfree (cfg);
+ if (acard->dev == NULL)
return -ENODEV;
- }
+
acard->devmpu = pnp_request_card_device(card, pid->devs[1].id, NULL);
acard->devopl = pnp_request_card_device(card, pid->devs[2].id, NULL);
pdev = acard->dev;
- pnp_init_resource_table(cfg);
-
- if (port[dev] != SNDRV_AUTO_PORT)
- pnp_resource_change(&cfg->port_resource[0], port[dev], 16);
- if (dma8[dev] != SNDRV_AUTO_DMA)
- pnp_resource_change(&cfg->dma_resource[0], dma8[dev], 1);
- if (irq[dev] != SNDRV_AUTO_IRQ)
- pnp_resource_change(&cfg->irq_resource[0], irq[dev], 1);
- if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
- snd_printk(KERN_ERR PFX "DT-019X AUDIO the requested resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
snd_printk(KERN_ERR PFX "DT-019X AUDIO pnp configure failure\n");
- kfree(cfg);
return err;
}
port[dev],irq[dev],dma8[dev]);
pdev = acard->devmpu;
-
if (pdev != NULL) {
- pnp_init_resource_table(cfg);
- if (mpu_port[dev] != SNDRV_AUTO_PORT)
- pnp_resource_change(&cfg->port_resource[0], mpu_port[dev], 2);
- if (mpu_irq[dev] != SNDRV_AUTO_IRQ)
- pnp_resource_change(&cfg->irq_resource[0], mpu_irq[dev], 1);
- if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
- snd_printk(KERN_ERR PFX "DT-019X MPU401 the requested resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
pnp_release_card_device(pdev);
pdev = acard->devopl;
if (pdev != NULL) {
- pnp_init_resource_table(cfg);
- if (fm_port[dev] != SNDRV_AUTO_PORT)
- pnp_resource_change(&cfg->port_resource[0], fm_port[dev], 4);
- if ((pnp_manual_config_dev(pdev, cfg, 0)) < 0)
- snd_printk(KERN_ERR PFX "DT-019X OPL3 the requested resources are invalid, using auto config\n");
err = pnp_activate_dev(pdev);
if (err < 0) {
pnp_release_card_device(pdev);
fm_port[dev] = -1;
}
- kfree(cfg);
return 0;
}
if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
sizeof(struct snd_card_dt019x))) == NULL)
return -ENOMEM;
- acard = (struct snd_card_dt019x *)card->private_data;
+ acard = card->private_data;
snd_card_set_dev(card, &pcard->card->dev);
if ((error = snd_card_dt019x_pnp(dev, acard, pcard, pid))) {
snd_card_free(card);
return error;
}
+ acard->chip = chip;
strcpy(card->driver, "DT-019X");
strcpy(card->shortname, "Diamond Tech. DT-019X");
MPU401_HW_MPU401,
mpu_port[dev], 0,
mpu_irq[dev],
- mpu_irq[dev] >= 0 ? SA_INTERRUPT : 0,
+ mpu_irq[dev] >= 0 ? IRQF_DISABLED : 0,
NULL) < 0)
snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx ?\n", mpu_port[dev]);
}
return 0;
}
+static unsigned int __devinitdata dt019x_devices;
+
static int __devinit snd_dt019x_pnp_probe(struct pnp_card_link *card,
const struct pnp_card_device_id *pid)
{
if (res < 0)
return res;
dev++;
+ dt019x_devices++;
return 0;
}
return -ENODEV;
static void __devexit snd_dt019x_pnp_remove(struct pnp_card_link * pcard)
{
- struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard);
- snd_card_disconnect(card);
- snd_card_free_in_thread(card);
+ snd_card_free(pnp_get_card_drvdata(pcard));
+ pnp_set_card_drvdata(pcard, NULL);
+}
+
+#ifdef CONFIG_PM
+static int snd_dt019x_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_dt019x *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
+ snd_pcm_suspend_all(chip->pcm);
+ snd_sbmixer_suspend(chip);
+ return 0;
+}
+
+static int snd_dt019x_pnp_resume(struct pnp_card_link *pcard)
+{
+ struct snd_card *card = pnp_get_card_drvdata(pcard);
+ struct snd_card_dt019x *acard = card->private_data;
+ struct snd_sb *chip = acard->chip;
+
+ snd_sbdsp_reset(chip);
+ snd_sbmixer_resume(chip);
+ snd_power_change_state(card, SNDRV_CTL_POWER_D0);
+ return 0;
}
+#endif
static struct pnp_card_driver dt019x_pnpc_driver = {
.flags = PNP_DRIVER_RES_DISABLE,
.id_table = snd_dt019x_pnpids,
.probe = snd_dt019x_pnp_probe,
.remove = __devexit_p(snd_dt019x_pnp_remove),
+#ifdef CONFIG_PM
+ .suspend = snd_dt019x_pnp_suspend,
+ .resume = snd_dt019x_pnp_resume,
+#endif
};
static int __init alsa_card_dt019x_init(void)
{
- int cards = 0;
+ int err;
- cards += pnp_register_card_driver(&dt019x_pnpc_driver);
+ err = pnp_register_card_driver(&dt019x_pnpc_driver);
+ if (err)
+ return err;
-#ifdef MODULE
- if (!cards) {
+ if (!dt019x_devices) {
pnp_unregister_card_driver(&dt019x_pnpc_driver);
+#ifdef MODULE
snd_printk(KERN_ERR "no DT-019X / ALS-007 based soundcards found\n");
- }
#endif
- return cards ? 0 : -ENODEV;
+ return -ENODEV;
+ }
+ return 0;
}
static void __exit alsa_card_dt019x_exit(void)