diff options
author | Krzysztof Helt <krzysztof.h1@wp.pl> | 2009-11-30 01:45:47 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2009-11-30 05:26:22 -0500 |
commit | 70a5f1187bcb3fac93a7d5c5fcfc5fc76b9c3f55 (patch) | |
tree | 18e91a2cd17770d51634ceb053f014b6b1c9092b /sound/isa/opti9xx/miro.c | |
parent | abe6becb7c603991b925c0d2dd908e31dd6611f5 (diff) |
ALSA: opti-miro: separate comon probing code
Separate common probing code in order to use it
for PnP probing.
Signed-off-by: Krzysztof Helt <krzysztof.h1@wp.pl>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa/opti9xx/miro.c')
-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 |