0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015 #include <linux/init.h>
0016 #include <linux/wait.h>
0017 #include <linux/time.h>
0018 #include <linux/pnp.h>
0019 #include <linux/module.h>
0020 #include <sound/core.h>
0021 #include <sound/initval.h>
0022 #include <sound/mpu401.h>
0023 #include <sound/opl3.h>
0024 #include <sound/sb.h>
0025
0026 #define PFX "als100: "
0027
0028 MODULE_DESCRIPTION("Avance Logic ALS007/ALS1X0");
0029 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
0030 MODULE_LICENSE("GPL");
0031
0032 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0033 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0034 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE;
0035 static long 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 dma8[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0041 static int dma16[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0042
0043 module_param_array(index, int, NULL, 0444);
0044 MODULE_PARM_DESC(index, "Index value for Avance Logic based soundcard.");
0045 module_param_array(id, charp, NULL, 0444);
0046 MODULE_PARM_DESC(id, "ID string for Avance Logic based soundcard.");
0047 module_param_array(enable, bool, NULL, 0444);
0048 MODULE_PARM_DESC(enable, "Enable Avance Logic based soundcard.");
0049
0050 MODULE_ALIAS("snd-dt019x");
0051
0052 struct snd_card_als100 {
0053 struct pnp_dev *dev;
0054 struct pnp_dev *devmpu;
0055 struct pnp_dev *devopl;
0056 struct snd_sb *chip;
0057 };
0058
0059 static const struct pnp_card_device_id snd_als100_pnpids[] = {
0060
0061 { .id = "RWB1688",
0062 .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0063 .driver_data = SB_HW_DT019X },
0064
0065 { .id = "ALS0007",
0066 .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0067 .driver_data = SB_HW_DT019X },
0068
0069 { .id = "ALS0001",
0070 .devs = { { "@@@0001" }, { "@X@0001" }, { "@H@0001" } },
0071 .driver_data = SB_HW_ALS100 },
0072
0073 { .id = "ALS0110",
0074 .devs = { { "@@@1001" }, { "@X@1001" }, { "@H@1001" } },
0075 .driver_data = SB_HW_ALS100 },
0076
0077 { .id = "ALS0120",
0078 .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
0079 .driver_data = SB_HW_ALS100 },
0080
0081 { .id = "ALS0200",
0082 .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0001" } },
0083 .driver_data = SB_HW_ALS100 },
0084
0085 { .id = "ALS0200",
0086 .devs = { { "@@@0020" }, { "@X@0020" }, { "@H@0020" } },
0087 .driver_data = SB_HW_ALS100 },
0088
0089 { .id = "RTL3000",
0090 .devs = { { "@@@2001" }, { "@X@2001" }, { "@H@2001" } },
0091 .driver_data = SB_HW_ALS100 },
0092 { .id = "" }
0093 };
0094
0095 MODULE_DEVICE_TABLE(pnp_card, snd_als100_pnpids);
0096
0097 static int snd_card_als100_pnp(int dev, struct snd_card_als100 *acard,
0098 struct pnp_card_link *card,
0099 const struct pnp_card_device_id *id)
0100 {
0101 struct pnp_dev *pdev;
0102 int err;
0103
0104 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
0105 if (acard->dev == NULL)
0106 return -ENODEV;
0107
0108 acard->devmpu = pnp_request_card_device(card, id->devs[1].id, acard->dev);
0109 acard->devopl = pnp_request_card_device(card, id->devs[2].id, acard->dev);
0110
0111 pdev = acard->dev;
0112
0113 err = pnp_activate_dev(pdev);
0114 if (err < 0) {
0115 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
0116 return err;
0117 }
0118 port[dev] = pnp_port_start(pdev, 0);
0119 if (id->driver_data == SB_HW_DT019X)
0120 dma8[dev] = pnp_dma(pdev, 0);
0121 else {
0122 dma8[dev] = pnp_dma(pdev, 1);
0123 dma16[dev] = pnp_dma(pdev, 0);
0124 }
0125 irq[dev] = pnp_irq(pdev, 0);
0126
0127 pdev = acard->devmpu;
0128 if (pdev != NULL) {
0129 err = pnp_activate_dev(pdev);
0130 if (err < 0)
0131 goto __mpu_error;
0132 mpu_port[dev] = pnp_port_start(pdev, 0);
0133 mpu_irq[dev] = pnp_irq(pdev, 0);
0134 } else {
0135 __mpu_error:
0136 if (pdev) {
0137 pnp_release_card_device(pdev);
0138 snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
0139 }
0140 acard->devmpu = NULL;
0141 mpu_port[dev] = -1;
0142 }
0143
0144 pdev = acard->devopl;
0145 if (pdev != NULL) {
0146 err = pnp_activate_dev(pdev);
0147 if (err < 0)
0148 goto __fm_error;
0149 fm_port[dev] = pnp_port_start(pdev, 0);
0150 } else {
0151 __fm_error:
0152 if (pdev) {
0153 pnp_release_card_device(pdev);
0154 snd_printk(KERN_ERR PFX "OPL3 pnp configure failure, skipping\n");
0155 }
0156 acard->devopl = NULL;
0157 fm_port[dev] = -1;
0158 }
0159
0160 return 0;
0161 }
0162
0163 static int snd_card_als100_probe(int dev,
0164 struct pnp_card_link *pcard,
0165 const struct pnp_card_device_id *pid)
0166 {
0167 int error;
0168 struct snd_sb *chip;
0169 struct snd_card *card;
0170 struct snd_card_als100 *acard;
0171 struct snd_opl3 *opl3;
0172
0173 error = snd_devm_card_new(&pcard->card->dev,
0174 index[dev], id[dev], THIS_MODULE,
0175 sizeof(struct snd_card_als100), &card);
0176 if (error < 0)
0177 return error;
0178 acard = card->private_data;
0179
0180 error = snd_card_als100_pnp(dev, acard, pcard, pid);
0181 if (error)
0182 return error;
0183
0184 if (pid->driver_data == SB_HW_DT019X)
0185 dma16[dev] = -1;
0186
0187 error = snd_sbdsp_create(card, port[dev], irq[dev],
0188 snd_sb16dsp_interrupt,
0189 dma8[dev], dma16[dev],
0190 pid->driver_data,
0191 &chip);
0192 if (error < 0)
0193 return error;
0194 acard->chip = chip;
0195
0196 if (pid->driver_data == SB_HW_DT019X) {
0197 strcpy(card->driver, "DT-019X");
0198 strcpy(card->shortname, "Diamond Tech. DT-019X");
0199 snprintf(card->longname, sizeof(card->longname),
0200 "Diamond Tech. DT-019X, %s at 0x%lx, irq %d, dma %d",
0201 chip->name, chip->port, irq[dev], dma8[dev]);
0202 } else {
0203 strcpy(card->driver, "ALS100");
0204 strcpy(card->shortname, "Avance Logic ALS100");
0205 snprintf(card->longname, sizeof(card->longname),
0206 "Avance Logic ALS100, %s at 0x%lx, irq %d, dma %d&%d",
0207 chip->name, chip->port, irq[dev], dma8[dev],
0208 dma16[dev]);
0209 }
0210
0211 error = snd_sb16dsp_pcm(chip, 0);
0212 if (error < 0)
0213 return error;
0214
0215 error = snd_sbmixer_new(chip);
0216 if (error < 0)
0217 return error;
0218
0219 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
0220 int mpu_type = MPU401_HW_ALS100;
0221
0222 if (mpu_irq[dev] == SNDRV_AUTO_IRQ)
0223 mpu_irq[dev] = -1;
0224
0225 if (pid->driver_data == SB_HW_DT019X)
0226 mpu_type = MPU401_HW_MPU401;
0227
0228 if (snd_mpu401_uart_new(card, 0,
0229 mpu_type,
0230 mpu_port[dev], 0,
0231 mpu_irq[dev],
0232 NULL) < 0)
0233 snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
0234 }
0235
0236 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
0237 if (snd_opl3_create(card,
0238 fm_port[dev], fm_port[dev] + 2,
0239 OPL3_HW_AUTO, 0, &opl3) < 0) {
0240 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
0241 fm_port[dev], fm_port[dev] + 2);
0242 } else {
0243 error = snd_opl3_timer_new(opl3, 0, 1);
0244 if (error < 0)
0245 return error;
0246 error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0247 if (error < 0)
0248 return error;
0249 }
0250 }
0251
0252 error = snd_card_register(card);
0253 if (error < 0)
0254 return error;
0255 pnp_set_card_drvdata(pcard, card);
0256 return 0;
0257 }
0258
0259 static unsigned int als100_devices;
0260
0261 static int snd_als100_pnp_detect(struct pnp_card_link *card,
0262 const struct pnp_card_device_id *id)
0263 {
0264 static int dev;
0265 int res;
0266
0267 for ( ; dev < SNDRV_CARDS; dev++) {
0268 if (!enable[dev])
0269 continue;
0270 res = snd_card_als100_probe(dev, card, id);
0271 if (res < 0)
0272 return res;
0273 dev++;
0274 als100_devices++;
0275 return 0;
0276 }
0277 return -ENODEV;
0278 }
0279
0280 #ifdef CONFIG_PM
0281 static int snd_als100_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
0282 {
0283 struct snd_card *card = pnp_get_card_drvdata(pcard);
0284 struct snd_card_als100 *acard = card->private_data;
0285 struct snd_sb *chip = acard->chip;
0286
0287 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
0288 snd_sbmixer_suspend(chip);
0289 return 0;
0290 }
0291
0292 static int snd_als100_pnp_resume(struct pnp_card_link *pcard)
0293 {
0294 struct snd_card *card = pnp_get_card_drvdata(pcard);
0295 struct snd_card_als100 *acard = card->private_data;
0296 struct snd_sb *chip = acard->chip;
0297
0298 snd_sbdsp_reset(chip);
0299 snd_sbmixer_resume(chip);
0300 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
0301 return 0;
0302 }
0303 #endif
0304
0305 static struct pnp_card_driver als100_pnpc_driver = {
0306 .flags = PNP_DRIVER_RES_DISABLE,
0307 .name = "als100",
0308 .id_table = snd_als100_pnpids,
0309 .probe = snd_als100_pnp_detect,
0310 #ifdef CONFIG_PM
0311 .suspend = snd_als100_pnp_suspend,
0312 .resume = snd_als100_pnp_resume,
0313 #endif
0314 };
0315
0316 static int __init alsa_card_als100_init(void)
0317 {
0318 int err;
0319
0320 err = pnp_register_card_driver(&als100_pnpc_driver);
0321 if (err)
0322 return err;
0323
0324 if (!als100_devices) {
0325 pnp_unregister_card_driver(&als100_pnpc_driver);
0326 #ifdef MODULE
0327 snd_printk(KERN_ERR "no Avance Logic based soundcards found\n");
0328 #endif
0329 return -ENODEV;
0330 }
0331 return 0;
0332 }
0333
0334 static void __exit alsa_card_als100_exit(void)
0335 {
0336 pnp_unregister_card_driver(&als100_pnpc_driver);
0337 }
0338
0339 module_init(alsa_card_als100_init)
0340 module_exit(alsa_card_als100_exit)