0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020 #include <linux/io.h>
0021 #include <linux/delay.h>
0022 #include <linux/init.h>
0023 #include <linux/time.h>
0024 #include <linux/wait.h>
0025 #include <linux/pnp.h>
0026 #include <linux/module.h>
0027 #include <sound/core.h>
0028 #include <sound/initval.h>
0029 #include <sound/wss.h>
0030 #include <sound/mpu401.h>
0031 #include <sound/opl3.h>
0032
0033 #define PFX "azt2320: "
0034
0035 MODULE_AUTHOR("Massimo Piccioni <dafastidio@libero.it>");
0036 MODULE_DESCRIPTION("Aztech Systems AZT2320");
0037 MODULE_LICENSE("GPL");
0038
0039 static int index[SNDRV_CARDS] = SNDRV_DEFAULT_IDX;
0040 static char *id[SNDRV_CARDS] = SNDRV_DEFAULT_STR;
0041 static bool enable[SNDRV_CARDS] = SNDRV_DEFAULT_ENABLE_ISAPNP;
0042 static long port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0043 static long wss_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0044 static long mpu_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0045 static long fm_port[SNDRV_CARDS] = SNDRV_DEFAULT_PORT;
0046 static int irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0047 static int mpu_irq[SNDRV_CARDS] = SNDRV_DEFAULT_IRQ;
0048 static int dma1[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0049 static int dma2[SNDRV_CARDS] = SNDRV_DEFAULT_DMA;
0050
0051 module_param_array(index, int, NULL, 0444);
0052 MODULE_PARM_DESC(index, "Index value for azt2320 based soundcard.");
0053 module_param_array(id, charp, NULL, 0444);
0054 MODULE_PARM_DESC(id, "ID string for azt2320 based soundcard.");
0055 module_param_array(enable, bool, NULL, 0444);
0056 MODULE_PARM_DESC(enable, "Enable azt2320 based soundcard.");
0057
0058 struct snd_card_azt2320 {
0059 int dev_no;
0060 struct pnp_dev *dev;
0061 struct pnp_dev *devmpu;
0062 struct snd_wss *chip;
0063 };
0064
0065 static const struct pnp_card_device_id snd_azt2320_pnpids[] = {
0066
0067 { .id = "AZT1008", .devs = { { "AZT1008" }, { "AZT2001" }, } },
0068
0069 { .id = "AZT2320", .devs = { { "AZT0001" }, { "AZT0002" }, } },
0070
0071 { .id = "AZT3000", .devs = { { "AZT1003" }, { "AZT2001" }, } },
0072
0073 { .id = "AZT3002", .devs = { { "AZT1004" }, { "AZT2001" }, } },
0074
0075 { .id = "AZT3005", .devs = { { "AZT1003" }, { "AZT2001" }, } },
0076
0077 { .id = "AZT3011", .devs = { { "AZT1003" }, { "AZT2001" }, } },
0078 { .id = "" }
0079 };
0080
0081 MODULE_DEVICE_TABLE(pnp_card, snd_azt2320_pnpids);
0082
0083 #define DRIVER_NAME "snd-card-azt2320"
0084
0085 static int snd_card_azt2320_pnp(int dev, struct snd_card_azt2320 *acard,
0086 struct pnp_card_link *card,
0087 const struct pnp_card_device_id *id)
0088 {
0089 struct pnp_dev *pdev;
0090 int err;
0091
0092 acard->dev = pnp_request_card_device(card, id->devs[0].id, NULL);
0093 if (acard->dev == NULL)
0094 return -ENODEV;
0095
0096 acard->devmpu = pnp_request_card_device(card, id->devs[1].id, NULL);
0097
0098 pdev = acard->dev;
0099
0100 err = pnp_activate_dev(pdev);
0101 if (err < 0) {
0102 snd_printk(KERN_ERR PFX "AUDIO pnp configure failure\n");
0103 return err;
0104 }
0105 port[dev] = pnp_port_start(pdev, 0);
0106 fm_port[dev] = pnp_port_start(pdev, 1);
0107 wss_port[dev] = pnp_port_start(pdev, 2);
0108 dma1[dev] = pnp_dma(pdev, 0);
0109 dma2[dev] = pnp_dma(pdev, 1);
0110 irq[dev] = pnp_irq(pdev, 0);
0111
0112 pdev = acard->devmpu;
0113 if (pdev != NULL) {
0114 err = pnp_activate_dev(pdev);
0115 if (err < 0)
0116 goto __mpu_error;
0117 mpu_port[dev] = pnp_port_start(pdev, 0);
0118 mpu_irq[dev] = pnp_irq(pdev, 0);
0119 } else {
0120 __mpu_error:
0121 if (pdev) {
0122 pnp_release_card_device(pdev);
0123 snd_printk(KERN_ERR PFX "MPU401 pnp configure failure, skipping\n");
0124 }
0125 acard->devmpu = NULL;
0126 mpu_port[dev] = -1;
0127 }
0128
0129 return 0;
0130 }
0131
0132
0133 static int snd_card_azt2320_command(unsigned long port, unsigned char val)
0134 {
0135 int i;
0136 unsigned long limit;
0137
0138 limit = jiffies + HZ / 10;
0139 for (i = 50000; i && time_after(limit, jiffies); i--)
0140 if (!(inb(port + 0x0c) & 0x80)) {
0141 outb(val, port + 0x0c);
0142 return 0;
0143 }
0144 return -EBUSY;
0145 }
0146
0147 static int snd_card_azt2320_enable_wss(unsigned long port)
0148 {
0149 int error;
0150
0151 error = snd_card_azt2320_command(port, 0x09);
0152 if (error)
0153 return error;
0154 error = snd_card_azt2320_command(port, 0x00);
0155 if (error)
0156 return error;
0157
0158 mdelay(5);
0159 return 0;
0160 }
0161
0162 static int snd_card_azt2320_probe(int dev,
0163 struct pnp_card_link *pcard,
0164 const struct pnp_card_device_id *pid)
0165 {
0166 int error;
0167 struct snd_card *card;
0168 struct snd_card_azt2320 *acard;
0169 struct snd_wss *chip;
0170 struct snd_opl3 *opl3;
0171
0172 error = snd_devm_card_new(&pcard->card->dev,
0173 index[dev], id[dev], THIS_MODULE,
0174 sizeof(struct snd_card_azt2320), &card);
0175 if (error < 0)
0176 return error;
0177 acard = card->private_data;
0178
0179 error = snd_card_azt2320_pnp(dev, acard, pcard, pid);
0180 if (error)
0181 return error;
0182
0183 error = snd_card_azt2320_enable_wss(port[dev]);
0184 if (error)
0185 return error;
0186
0187 error = snd_wss_create(card, wss_port[dev], -1,
0188 irq[dev],
0189 dma1[dev], dma2[dev],
0190 WSS_HW_DETECT, 0, &chip);
0191 if (error < 0)
0192 return error;
0193
0194 strcpy(card->driver, "AZT2320");
0195 strcpy(card->shortname, "Aztech AZT2320");
0196 sprintf(card->longname, "%s, WSS at 0x%lx, irq %i, dma %i&%i",
0197 card->shortname, chip->port, irq[dev], dma1[dev], dma2[dev]);
0198
0199 error = snd_wss_pcm(chip, 0);
0200 if (error < 0)
0201 return error;
0202 error = snd_wss_mixer(chip);
0203 if (error < 0)
0204 return error;
0205 error = snd_wss_timer(chip, 0);
0206 if (error < 0)
0207 return error;
0208
0209 if (mpu_port[dev] > 0 && mpu_port[dev] != SNDRV_AUTO_PORT) {
0210 if (snd_mpu401_uart_new(card, 0, MPU401_HW_AZT2320,
0211 mpu_port[dev], 0,
0212 mpu_irq[dev], NULL) < 0)
0213 snd_printk(KERN_ERR PFX "no MPU-401 device at 0x%lx\n", mpu_port[dev]);
0214 }
0215
0216 if (fm_port[dev] > 0 && fm_port[dev] != SNDRV_AUTO_PORT) {
0217 if (snd_opl3_create(card,
0218 fm_port[dev], fm_port[dev] + 2,
0219 OPL3_HW_AUTO, 0, &opl3) < 0) {
0220 snd_printk(KERN_ERR PFX "no OPL device at 0x%lx-0x%lx\n",
0221 fm_port[dev], fm_port[dev] + 2);
0222 } else {
0223 error = snd_opl3_timer_new(opl3, 1, 2);
0224 if (error < 0)
0225 return error;
0226 error = snd_opl3_hwdep_new(opl3, 0, 1, NULL);
0227 if (error < 0)
0228 return error;
0229 }
0230 }
0231
0232 error = snd_card_register(card);
0233 if (error < 0)
0234 return error;
0235 pnp_set_card_drvdata(pcard, card);
0236 return 0;
0237 }
0238
0239 static unsigned int azt2320_devices;
0240
0241 static int snd_azt2320_pnp_detect(struct pnp_card_link *card,
0242 const struct pnp_card_device_id *id)
0243 {
0244 static int dev;
0245 int res;
0246
0247 for ( ; dev < SNDRV_CARDS; dev++) {
0248 if (!enable[dev])
0249 continue;
0250 res = snd_card_azt2320_probe(dev, card, id);
0251 if (res < 0)
0252 return res;
0253 dev++;
0254 azt2320_devices++;
0255 return 0;
0256 }
0257 return -ENODEV;
0258 }
0259
0260 #ifdef CONFIG_PM
0261 static int snd_azt2320_pnp_suspend(struct pnp_card_link *pcard, pm_message_t state)
0262 {
0263 struct snd_card *card = pnp_get_card_drvdata(pcard);
0264 struct snd_card_azt2320 *acard = card->private_data;
0265 struct snd_wss *chip = acard->chip;
0266
0267 snd_power_change_state(card, SNDRV_CTL_POWER_D3hot);
0268 chip->suspend(chip);
0269 return 0;
0270 }
0271
0272 static int snd_azt2320_pnp_resume(struct pnp_card_link *pcard)
0273 {
0274 struct snd_card *card = pnp_get_card_drvdata(pcard);
0275 struct snd_card_azt2320 *acard = card->private_data;
0276 struct snd_wss *chip = acard->chip;
0277
0278 chip->resume(chip);
0279 snd_power_change_state(card, SNDRV_CTL_POWER_D0);
0280 return 0;
0281 }
0282 #endif
0283
0284 static struct pnp_card_driver azt2320_pnpc_driver = {
0285 .flags = PNP_DRIVER_RES_DISABLE,
0286 .name = "azt2320",
0287 .id_table = snd_azt2320_pnpids,
0288 .probe = snd_azt2320_pnp_detect,
0289 #ifdef CONFIG_PM
0290 .suspend = snd_azt2320_pnp_suspend,
0291 .resume = snd_azt2320_pnp_resume,
0292 #endif
0293 };
0294
0295 static int __init alsa_card_azt2320_init(void)
0296 {
0297 int err;
0298
0299 err = pnp_register_card_driver(&azt2320_pnpc_driver);
0300 if (err)
0301 return err;
0302
0303 if (!azt2320_devices) {
0304 pnp_unregister_card_driver(&azt2320_pnpc_driver);
0305 #ifdef MODULE
0306 snd_printk(KERN_ERR "no AZT2320 based soundcards found\n");
0307 #endif
0308 return -ENODEV;
0309 }
0310 return 0;
0311 }
0312
0313 static void __exit alsa_card_azt2320_exit(void)
0314 {
0315 pnp_unregister_card_driver(&azt2320_pnpc_driver);
0316 }
0317
0318 module_init(alsa_card_azt2320_init)
0319 module_exit(alsa_card_azt2320_exit)