diff options
| -rw-r--r-- | sound/isa/opti9xx/miro.c | 273 |
1 files changed, 147 insertions, 126 deletions
diff --git a/sound/isa/opti9xx/miro.c b/sound/isa/opti9xx/miro.c index e374869e3e21..c67bc3cd2c65 100644 --- a/sound/isa/opti9xx/miro.c +++ b/sound/isa/opti9xx/miro.c | |||
| @@ -1142,28 +1142,39 @@ __skip_mpu: | |||
| 1142 | return 0; | 1142 | return 0; |
| 1143 | } | 1143 | } |
| 1144 | 1144 | ||
| 1145 | static int __devinit snd_miro_opti_check(struct snd_miro *chip) | ||
| 1146 | { | ||
| 1147 | unsigned char value; | ||
| 1148 | |||
| 1149 | chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, | ||
| 1150 | "OPTi9xx MC"); | ||
| 1151 | if (chip->res_mc_base == NULL) | ||
| 1152 | return -ENOMEM; | ||
| 1153 | |||
| 1154 | value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); | ||
| 1155 | if (value != 0xff && value != inb(chip->mc_base + OPTi9XX_MC_REG(1))) | ||
| 1156 | if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) | ||
| 1157 | return 0; | ||
| 1158 | |||
| 1159 | release_and_free_resource(chip->res_mc_base); | ||
| 1160 | chip->res_mc_base = NULL; | ||
| 1161 | |||
| 1162 | return -ENODEV; | ||
| 1163 | } | ||
| 1164 | |||
| 1145 | static int __devinit snd_card_miro_detect(struct snd_card *card, | 1165 | static int __devinit snd_card_miro_detect(struct snd_card *card, |
| 1146 | struct snd_miro *chip) | 1166 | struct snd_miro *chip) |
| 1147 | { | 1167 | { |
| 1148 | int i, err; | 1168 | int i, err; |
| 1149 | unsigned char value; | ||
| 1150 | 1169 | ||
| 1151 | for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { | 1170 | for (i = OPTi9XX_HW_82C929; i <= OPTi9XX_HW_82C924; i++) { |
| 1152 | 1171 | ||
| 1153 | if ((err = snd_miro_init(chip, i)) < 0) | 1172 | if ((err = snd_miro_init(chip, i)) < 0) |
| 1154 | return err; | 1173 | return err; |
| 1155 | 1174 | ||
| 1156 | if ((chip->res_mc_base = request_region(chip->mc_base, chip->mc_base_size, "OPTi9xx MC")) == NULL) | 1175 | err = snd_miro_opti_check(chip); |
| 1157 | continue; | 1176 | if (err == 0) |
| 1158 | 1177 | return 1; | |
| 1159 | value = snd_miro_read(chip, OPTi9XX_MC_REG(1)); | ||
| 1160 | if ((value != 0xff) && (value != inb(chip->mc_base + 1))) | ||
| 1161 | if (value == snd_miro_read(chip, OPTi9XX_MC_REG(1))) | ||
| 1162 | return 1; | ||
| 1163 | |||
| 1164 | release_and_free_resource(chip->res_mc_base); | ||
| 1165 | chip->res_mc_base = NULL; | ||
| 1166 | |||
| 1167 | } | 1178 | } |
| 1168 | 1179 | ||
| 1169 | return -ENODEV; | 1180 | return -ENODEV; |
| @@ -1234,151 +1245,69 @@ static void snd_card_miro_free(struct snd_card *card) | |||
| 1234 | release_and_free_resource(miro->res_mc_base); | 1245 | release_and_free_resource(miro->res_mc_base); |
| 1235 | } | 1246 | } |
| 1236 | 1247 | ||
| 1237 | static int __devinit snd_miro_match(struct device *devptr, unsigned int n) | 1248 | static int __devinit snd_miro_probe(struct snd_card *card) |
| 1238 | { | ||
| 1239 | return 1; | ||
| 1240 | } | ||
| 1241 | |||
| 1242 | static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | ||
| 1243 | { | 1249 | { |
| 1244 | static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; | ||
| 1245 | static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; | ||
| 1246 | static int possible_irqs[] = {11, 9, 10, 7, -1}; | ||
| 1247 | static int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; | ||
| 1248 | static int possible_dma1s[] = {3, 1, 0, -1}; | ||
| 1249 | static int possible_dma2s[][2] = {{1,-1}, {0,-1}, {-1,-1}, {0,-1}}; | ||
| 1250 | |||
| 1251 | int error; | 1250 | int error; |
| 1252 | struct snd_miro *miro; | 1251 | struct snd_miro *miro = card->private_data; |
| 1253 | struct snd_wss *codec; | 1252 | struct snd_wss *codec; |
| 1254 | struct snd_timer *timer; | 1253 | struct snd_timer *timer; |
| 1255 | struct snd_card *card; | ||
| 1256 | struct snd_pcm *pcm; | 1254 | struct snd_pcm *pcm; |
| 1257 | struct snd_rawmidi *rmidi; | 1255 | struct snd_rawmidi *rmidi; |
| 1258 | 1256 | ||
| 1259 | error = snd_card_create(index, id, THIS_MODULE, | 1257 | if (!miro->res_mc_base) { |
| 1260 | sizeof(struct snd_miro), &card); | 1258 | miro->res_mc_base = request_region(miro->mc_base, |
| 1261 | if (error < 0) | 1259 | miro->mc_base_size, |
| 1262 | return error; | 1260 | "miro (OPTi9xx MC)"); |
| 1263 | 1261 | if (miro->res_mc_base == NULL) { | |
| 1264 | card->private_free = snd_card_miro_free; | 1262 | snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); |
| 1265 | miro = card->private_data; | 1263 | return -ENOMEM; |
| 1266 | 1264 | } | |
| 1267 | error = snd_card_miro_detect(card, miro); | ||
| 1268 | if (error < 0) { | ||
| 1269 | snd_card_free(card); | ||
| 1270 | snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); | ||
| 1271 | return -ENODEV; | ||
| 1272 | } | 1265 | } |
| 1273 | 1266 | ||
| 1274 | if ((error = snd_card_miro_aci_detect(card, miro)) < 0) { | 1267 | error = snd_card_miro_aci_detect(card, miro); |
| 1268 | if (error < 0) { | ||
| 1275 | snd_card_free(card); | 1269 | snd_card_free(card); |
| 1276 | snd_printk(KERN_ERR "unable to detect aci chip\n"); | 1270 | snd_printk(KERN_ERR "unable to detect aci chip\n"); |
| 1277 | return -ENODEV; | 1271 | return -ENODEV; |
| 1278 | } | 1272 | } |
| 1279 | 1273 | ||
| 1280 | /* init proc interface */ | ||
| 1281 | snd_miro_proc_init(card, miro); | ||
| 1282 | |||
| 1283 | |||
| 1284 | if (! miro->res_mc_base && | ||
| 1285 | (miro->res_mc_base = request_region(miro->mc_base, miro->mc_base_size, | ||
| 1286 | "miro (OPTi9xx MC)")) == NULL) { | ||
| 1287 | snd_card_free(card); | ||
| 1288 | snd_printk(KERN_ERR "request for OPTI9xx MC failed\n"); | ||
| 1289 | return -ENOMEM; | ||
| 1290 | } | ||
| 1291 | |||
| 1292 | miro->wss_base = port; | 1274 | miro->wss_base = port; |
| 1275 | miro->mpu_port = mpu_port; | ||
| 1293 | miro->irq = irq; | 1276 | miro->irq = irq; |
| 1294 | miro->mpu_irq = mpu_irq; | 1277 | miro->mpu_irq = mpu_irq; |
| 1295 | miro->dma1 = dma1; | 1278 | miro->dma1 = dma1; |
| 1296 | miro->dma2 = dma2; | 1279 | miro->dma2 = dma2; |
| 1297 | 1280 | ||
| 1298 | if (miro->wss_base == SNDRV_AUTO_PORT) { | 1281 | /* init proc interface */ |
| 1299 | if ((miro->wss_base = snd_legacy_find_free_ioport(possible_ports, 4)) < 0) { | 1282 | snd_miro_proc_init(card, miro); |
| 1300 | snd_card_free(card); | ||
| 1301 | snd_printk(KERN_ERR "unable to find a free WSS port\n"); | ||
| 1302 | return -EBUSY; | ||
| 1303 | } | ||
| 1304 | } | ||
| 1305 | |||
| 1306 | if (mpu_port == SNDRV_AUTO_PORT) { | ||
| 1307 | mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); | ||
| 1308 | if (mpu_port < 0) { | ||
| 1309 | snd_card_free(card); | ||
| 1310 | snd_printk(KERN_ERR "unable to find a free MPU401 port\n"); | ||
| 1311 | return -EBUSY; | ||
| 1312 | } | ||
| 1313 | } | ||
| 1314 | miro->mpu_port = mpu_port; | ||
| 1315 | |||
| 1316 | if (miro->irq == SNDRV_AUTO_IRQ) { | ||
| 1317 | if ((miro->irq = snd_legacy_find_free_irq(possible_irqs)) < 0) { | ||
| 1318 | snd_card_free(card); | ||
| 1319 | snd_printk(KERN_ERR "unable to find a free IRQ\n"); | ||
| 1320 | return -EBUSY; | ||
| 1321 | } | ||
| 1322 | } | ||
| 1323 | if (miro->mpu_irq == SNDRV_AUTO_IRQ) { | ||
| 1324 | if ((miro->mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs)) < 0) { | ||
| 1325 | snd_card_free(card); | ||
| 1326 | snd_printk(KERN_ERR "unable to find a free MPU401 IRQ\n"); | ||
| 1327 | return -EBUSY; | ||
| 1328 | } | ||
| 1329 | } | ||
| 1330 | if (miro->dma1 == SNDRV_AUTO_DMA) { | ||
| 1331 | if ((miro->dma1 = snd_legacy_find_free_dma(possible_dma1s)) < 0) { | ||
| 1332 | snd_card_free(card); | ||
| 1333 | snd_printk(KERN_ERR "unable to find a free DMA1\n"); | ||
| 1334 | return -EBUSY; | ||
| 1335 | } | ||
| 1336 | } | ||
| 1337 | if (miro->dma2 == SNDRV_AUTO_DMA) { | ||
| 1338 | if ((miro->dma2 = snd_legacy_find_free_dma(possible_dma2s[miro->dma1 % 4])) < 0) { | ||
| 1339 | snd_card_free(card); | ||
| 1340 | snd_printk(KERN_ERR "unable to find a free DMA2\n"); | ||
| 1341 | return -EBUSY; | ||
| 1342 | } | ||
| 1343 | } | ||
| 1344 | 1283 | ||
| 1345 | error = snd_miro_configure(miro); | 1284 | error = snd_miro_configure(miro); |
| 1346 | if (error) { | 1285 | if (error) |
| 1347 | snd_card_free(card); | ||
| 1348 | return error; | 1286 | return error; |
| 1349 | } | ||
| 1350 | 1287 | ||
| 1351 | error = snd_wss_create(card, miro->wss_base + 4, -1, | 1288 | error = snd_wss_create(card, miro->wss_base + 4, -1, |
| 1352 | miro->irq, miro->dma1, miro->dma2, | 1289 | miro->irq, miro->dma1, miro->dma2, |
| 1353 | WSS_HW_AD1845, 0, &codec); | 1290 | WSS_HW_DETECT, 0, &codec); |
| 1354 | if (error < 0) { | 1291 | if (error < 0) |
| 1355 | snd_card_free(card); | ||
| 1356 | return error; | 1292 | return error; |
| 1357 | } | ||
| 1358 | 1293 | ||
| 1359 | error = snd_wss_pcm(codec, 0, &pcm); | 1294 | error = snd_wss_pcm(codec, 0, &pcm); |
| 1360 | if (error < 0) { | 1295 | if (error < 0) |
| 1361 | snd_card_free(card); | ||
| 1362 | return error; | 1296 | return error; |
| 1363 | } | 1297 | |
| 1364 | error = snd_wss_mixer(codec); | 1298 | error = snd_wss_mixer(codec); |
| 1365 | if (error < 0) { | 1299 | if (error < 0) |
| 1366 | snd_card_free(card); | ||
| 1367 | return error; | 1300 | return error; |
| 1368 | } | 1301 | |
| 1369 | error = snd_wss_timer(codec, 0, &timer); | 1302 | error = snd_wss_timer(codec, 0, &timer); |
| 1370 | if (error < 0) { | 1303 | if (error < 0) |
| 1371 | snd_card_free(card); | ||
| 1372 | return error; | 1304 | return error; |
| 1373 | } | ||
| 1374 | 1305 | ||
| 1375 | miro->pcm = pcm; | 1306 | miro->pcm = pcm; |
| 1376 | 1307 | ||
| 1377 | error = snd_miro_mixer(card, miro); | 1308 | error = snd_miro_mixer(card, miro); |
| 1378 | if (error < 0) { | 1309 | if (error < 0) |
| 1379 | snd_card_free(card); | ||
| 1380 | return error; | 1310 | return error; |
| 1381 | } | ||
| 1382 | 1311 | ||
| 1383 | if (miro->aci->aci_vendor == 'm') { | 1312 | if (miro->aci->aci_vendor == 'm') { |
| 1384 | /* It looks like a miro sound card. */ | 1313 | /* It looks like a miro sound card. */ |
| @@ -1425,20 +1354,111 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
| 1425 | if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { | 1354 | if (fm_port > 0 && fm_port != SNDRV_AUTO_PORT) { |
| 1426 | struct snd_opl3 *opl3 = NULL; | 1355 | struct snd_opl3 *opl3 = NULL; |
| 1427 | struct snd_opl4 *opl4; | 1356 | struct snd_opl4 *opl4; |
| 1357 | |||
| 1428 | if (snd_opl4_create(card, fm_port, fm_port - 8, | 1358 | if (snd_opl4_create(card, fm_port, fm_port - 8, |
| 1429 | 2, &opl3, &opl4) < 0) | 1359 | 2, &opl3, &opl4) < 0) |
| 1430 | snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", | 1360 | snd_printk(KERN_WARNING "no OPL4 device at 0x%lx\n", |
| 1431 | fm_port); | 1361 | fm_port); |
| 1432 | } | 1362 | } |
| 1433 | 1363 | ||
| 1434 | if ((error = snd_set_aci_init_values(miro)) < 0) { | 1364 | error = snd_set_aci_init_values(miro); |
| 1435 | snd_card_free(card); | 1365 | if (error < 0) |
| 1436 | return error; | 1366 | return error; |
| 1367 | |||
| 1368 | return snd_card_register(card); | ||
| 1369 | } | ||
| 1370 | |||
| 1371 | static int __devinit snd_miro_isa_match(struct device *devptr, unsigned int n) | ||
| 1372 | { | ||
| 1373 | return 1; | ||
| 1374 | } | ||
| 1375 | |||
| 1376 | static int __devinit snd_miro_isa_probe(struct device *devptr, unsigned int n) | ||
| 1377 | { | ||
| 1378 | static long possible_ports[] = {0x530, 0xe80, 0xf40, 0x604, -1}; | ||
| 1379 | static long possible_mpu_ports[] = {0x330, 0x300, 0x310, 0x320, -1}; | ||
| 1380 | static int possible_irqs[] = {11, 9, 10, 7, -1}; | ||
| 1381 | static int possible_mpu_irqs[] = {10, 5, 9, 7, -1}; | ||
| 1382 | static int possible_dma1s[] = {3, 1, 0, -1}; | ||
| 1383 | static int possible_dma2s[][2] = { {1, -1}, {0, -1}, {-1, -1}, | ||
| 1384 | {0, -1} }; | ||
| 1385 | |||
| 1386 | int error; | ||
| 1387 | struct snd_miro *miro; | ||
| 1388 | struct snd_card *card; | ||
| 1389 | |||
| 1390 | error = snd_card_create(index, id, THIS_MODULE, | ||
| 1391 | sizeof(struct snd_miro), &card); | ||
| 1392 | if (error < 0) | ||
| 1393 | return error; | ||
| 1394 | |||
| 1395 | card->private_free = snd_card_miro_free; | ||
| 1396 | miro = card->private_data; | ||
| 1397 | |||
| 1398 | error = snd_card_miro_detect(card, miro); | ||
| 1399 | if (error < 0) { | ||
| 1400 | snd_card_free(card); | ||
| 1401 | snd_printk(KERN_ERR "unable to detect OPTi9xx chip\n"); | ||
| 1402 | return -ENODEV; | ||
| 1403 | } | ||
| 1404 | |||
| 1405 | if (port == SNDRV_AUTO_PORT) { | ||
| 1406 | port = snd_legacy_find_free_ioport(possible_ports, 4); | ||
| 1407 | if (port < 0) { | ||
| 1408 | snd_card_free(card); | ||
| 1409 | snd_printk(KERN_ERR "unable to find a free WSS port\n"); | ||
| 1410 | return -EBUSY; | ||
| 1411 | } | ||
| 1412 | } | ||
| 1413 | |||
| 1414 | if (mpu_port == SNDRV_AUTO_PORT) { | ||
| 1415 | mpu_port = snd_legacy_find_free_ioport(possible_mpu_ports, 2); | ||
| 1416 | if (mpu_port < 0) { | ||
| 1417 | snd_card_free(card); | ||
| 1418 | snd_printk(KERN_ERR | ||
| 1419 | "unable to find a free MPU401 port\n"); | ||
| 1420 | return -EBUSY; | ||
| 1421 | } | ||
| 1422 | } | ||
| 1423 | |||
| 1424 | if (irq == SNDRV_AUTO_IRQ) { | ||
| 1425 | irq = snd_legacy_find_free_irq(possible_irqs); | ||
| 1426 | if (irq < 0) { | ||
| 1427 | snd_card_free(card); | ||
| 1428 | snd_printk(KERN_ERR "unable to find a free IRQ\n"); | ||
| 1429 | return -EBUSY; | ||
| 1430 | } | ||
| 1431 | } | ||
| 1432 | if (mpu_irq == SNDRV_AUTO_IRQ) { | ||
| 1433 | mpu_irq = snd_legacy_find_free_irq(possible_mpu_irqs); | ||
| 1434 | if (mpu_irq < 0) { | ||
| 1435 | snd_card_free(card); | ||
| 1436 | snd_printk(KERN_ERR | ||
| 1437 | "unable to find a free MPU401 IRQ\n"); | ||
| 1438 | return -EBUSY; | ||
| 1439 | } | ||
| 1440 | } | ||
| 1441 | if (dma1 == SNDRV_AUTO_DMA) { | ||
| 1442 | dma1 = snd_legacy_find_free_dma(possible_dma1s); | ||
| 1443 | if (dma1 < 0) { | ||
| 1444 | snd_card_free(card); | ||
| 1445 | snd_printk(KERN_ERR "unable to find a free DMA1\n"); | ||
| 1446 | return -EBUSY; | ||
| 1447 | } | ||
| 1448 | } | ||
| 1449 | if (dma2 == SNDRV_AUTO_DMA) { | ||
| 1450 | dma2 = snd_legacy_find_free_dma(possible_dma2s[dma1 % 4]); | ||
| 1451 | if (dma2 < 0) { | ||
| 1452 | snd_card_free(card); | ||
| 1453 | snd_printk(KERN_ERR "unable to find a free DMA2\n"); | ||
| 1454 | return -EBUSY; | ||
| 1455 | } | ||
| 1437 | } | 1456 | } |
| 1438 | 1457 | ||
| 1439 | snd_card_set_dev(card, devptr); | 1458 | snd_card_set_dev(card, devptr); |
| 1440 | 1459 | ||
| 1441 | if ((error = snd_card_register(card))) { | 1460 | error = snd_miro_probe(card); |
| 1461 | if (error < 0) { | ||
| 1442 | snd_card_free(card); | 1462 | snd_card_free(card); |
| 1443 | return error; | 1463 | return error; |
| 1444 | } | 1464 | } |
| @@ -1447,7 +1467,8 @@ static int __devinit snd_miro_probe(struct device *devptr, unsigned int n) | |||
| 1447 | return 0; | 1467 | return 0; |
| 1448 | } | 1468 | } |
| 1449 | 1469 | ||
| 1450 | static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev) | 1470 | static int __devexit snd_miro_isa_remove(struct device *devptr, |
| 1471 | unsigned int dev) | ||
| 1451 | { | 1472 | { |
| 1452 | snd_card_free(dev_get_drvdata(devptr)); | 1473 | snd_card_free(dev_get_drvdata(devptr)); |
| 1453 | dev_set_drvdata(devptr, NULL); | 1474 | dev_set_drvdata(devptr, NULL); |
| @@ -1457,9 +1478,9 @@ static int __devexit snd_miro_remove(struct device *devptr, unsigned int dev) | |||
| 1457 | #define DEV_NAME "miro" | 1478 | #define DEV_NAME "miro" |
| 1458 | 1479 | ||
| 1459 | static struct isa_driver snd_miro_driver = { | 1480 | static struct isa_driver snd_miro_driver = { |
| 1460 | .match = snd_miro_match, | 1481 | .match = snd_miro_isa_match, |
| 1461 | .probe = snd_miro_probe, | 1482 | .probe = snd_miro_isa_probe, |
| 1462 | .remove = __devexit_p(snd_miro_remove), | 1483 | .remove = __devexit_p(snd_miro_isa_remove), |
| 1463 | /* FIXME: suspend/resume */ | 1484 | /* FIXME: suspend/resume */ |
| 1464 | .driver = { | 1485 | .driver = { |
| 1465 | .name = DEV_NAME | 1486 | .name = DEV_NAME |
