aboutsummaryrefslogtreecommitdiffstats
path: root/sound/isa/sscape.c
diff options
context:
space:
mode:
authorTakashi Iwai <tiwai@suse.de>2005-11-17 11:13:12 -0500
committerJaroslav Kysela <perex@suse.cz>2006-01-03 06:28:31 -0500
commit277e926c9b2722317a6bf89ed921d97f6784e0cc (patch)
treea8f5ae3307e26fecd61f11ac60205c34ebe587ac /sound/isa/sscape.c
parentfeb158e6ada20b7871f625e1edd429216ac00d3c (diff)
[ALSA] sscape - Use platform_device
Modules: Sound Scape driver Rewrite the probe/remove with platform_device. Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/isa/sscape.c')
-rw-r--r--sound/isa/sscape.c282
1 files changed, 112 insertions, 170 deletions
diff --git a/sound/isa/sscape.c b/sound/isa/sscape.c
index d07963eddb3f..6271efe689df 100644
--- a/sound/isa/sscape.c
+++ b/sound/isa/sscape.c
@@ -23,6 +23,8 @@
23 23
24#include <sound/driver.h> 24#include <sound/driver.h>
25#include <linux/init.h> 25#include <linux/init.h>
26#include <linux/err.h>
27#include <linux/platform_device.h>
26#include <linux/delay.h> 28#include <linux/delay.h>
27#include <linux/pnp.h> 29#include <linux/pnp.h>
28#include <linux/spinlock.h> 30#include <linux/spinlock.h>
@@ -75,8 +77,6 @@ static struct pnp_card_device_id sscape_pnpids[] = {
75MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids); 77MODULE_DEVICE_TABLE(pnp_card, sscape_pnpids);
76#endif 78#endif
77 79
78static struct snd_card *sscape_card[SNDRV_CARDS];
79
80 80
81#define MPU401_IO(i) ((i) + 0) 81#define MPU401_IO(i) ((i) + 0)
82#define MIDI_DATA_IO(i) ((i) + 0) 82#define MIDI_DATA_IO(i) ((i) + 0)
@@ -1080,48 +1080,18 @@ static int __devinit create_ad1845(struct snd_card *card, unsigned port, int irq
1080} 1080}
1081 1081
1082 1082
1083struct params
1084{
1085 int index;
1086 const char *id;
1087 unsigned port;
1088 int irq;
1089 int mpu_irq;
1090 int dma1;
1091};
1092
1093
1094static inline struct params*
1095init_params(struct params *params,
1096 int index,
1097 const char *id,
1098 unsigned port,
1099 int irq,
1100 int mpu_irq,
1101 int dma1)
1102{
1103 params->index = index;
1104 params->id = id;
1105 params->port = port;
1106 params->irq = irq;
1107 params->mpu_irq = mpu_irq;
1108 params->dma1 = (dma1 & 0x03);
1109
1110 return params;
1111}
1112
1113
1114/* 1083/*
1115 * Create an ALSA soundcard entry for the SoundScape, using 1084 * Create an ALSA soundcard entry for the SoundScape, using
1116 * the given list of port, IRQ and DMA resources. 1085 * the given list of port, IRQ and DMA resources.
1117 */ 1086 */
1118static int __devinit create_sscape(const struct params *params, struct snd_card **rcardp) 1087static int __devinit create_sscape(int dev, struct snd_card **rcardp)
1119{ 1088{
1120 struct snd_card *card; 1089 struct snd_card *card;
1121 register struct soundscape *sscape; 1090 register struct soundscape *sscape;
1122 register unsigned dma_cfg; 1091 register unsigned dma_cfg;
1123 unsigned irq_cfg; 1092 unsigned irq_cfg;
1124 unsigned mpu_irq_cfg; 1093 unsigned mpu_irq_cfg;
1094 unsigned xport;
1125 struct resource *io_res; 1095 struct resource *io_res;
1126 unsigned long flags; 1096 unsigned long flags;
1127 int err; 1097 int err;
@@ -1129,32 +1099,33 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1129 /* 1099 /*
1130 * Check that the user didn't pass us garbage data ... 1100 * Check that the user didn't pass us garbage data ...
1131 */ 1101 */
1132 irq_cfg = get_irq_config(params->irq); 1102 irq_cfg = get_irq_config(irq[dev]);
1133 if (irq_cfg == INVALID_IRQ) { 1103 if (irq_cfg == INVALID_IRQ) {
1134 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->irq); 1104 snd_printk(KERN_ERR "sscape: Invalid IRQ %d\n", irq[dev]);
1135 return -ENXIO; 1105 return -ENXIO;
1136 } 1106 }
1137 1107
1138 mpu_irq_cfg = get_irq_config(params->mpu_irq); 1108 mpu_irq_cfg = get_irq_config(mpu_irq[dev]);
1139 if (mpu_irq_cfg == INVALID_IRQ) { 1109 if (mpu_irq_cfg == INVALID_IRQ) {
1140 printk(KERN_ERR "sscape: Invalid IRQ %d\n", params->mpu_irq); 1110 printk(KERN_ERR "sscape: Invalid IRQ %d\n", mpu_irq[dev]);
1141 return -ENXIO; 1111 return -ENXIO;
1142 } 1112 }
1113 xport = port[dev];
1143 1114
1144 /* 1115 /*
1145 * Grab IO ports that we will need to probe so that we 1116 * Grab IO ports that we will need to probe so that we
1146 * can detect and control this hardware ... 1117 * can detect and control this hardware ...
1147 */ 1118 */
1148 if ((io_res = request_region(params->port, 8, "SoundScape")) == NULL) { 1119 if ((io_res = request_region(xport, 8, "SoundScape")) == NULL) {
1149 snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", params->port); 1120 snd_printk(KERN_ERR "sscape: can't grab port 0x%x\n", xport);
1150 return -EBUSY; 1121 return -EBUSY;
1151 } 1122 }
1152 1123
1153 /* 1124 /*
1154 * Grab both DMA channels (OK, only one for now) ... 1125 * Grab both DMA channels (OK, only one for now) ...
1155 */ 1126 */
1156 if ((err = request_dma(params->dma1, "SoundScape")) < 0) { 1127 if ((err = request_dma(dma[dev], "SoundScape")) < 0) {
1157 snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", params->dma1); 1128 snd_printk(KERN_ERR "sscape: can't grab DMA %d\n", dma[dev]);
1158 goto _release_region; 1129 goto _release_region;
1159 } 1130 }
1160 1131
@@ -1162,7 +1133,8 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1162 * Create a new ALSA sound card entry, in anticipation 1133 * Create a new ALSA sound card entry, in anticipation
1163 * of detecting our hardware ... 1134 * of detecting our hardware ...
1164 */ 1135 */
1165 if ((card = snd_card_new(params->index, params->id, THIS_MODULE, sizeof(struct soundscape))) == NULL) { 1136 if ((card = snd_card_new(index[dev], id[dev], THIS_MODULE,
1137 sizeof(struct soundscape))) == NULL) {
1166 err = -ENOMEM; 1138 err = -ENOMEM;
1167 goto _release_dma; 1139 goto _release_dma;
1168 } 1140 }
@@ -1171,7 +1143,7 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1171 spin_lock_init(&sscape->lock); 1143 spin_lock_init(&sscape->lock);
1172 spin_lock_init(&sscape->fwlock); 1144 spin_lock_init(&sscape->fwlock);
1173 sscape->io_res = io_res; 1145 sscape->io_res = io_res;
1174 sscape->io_base = params->port; 1146 sscape->io_base = xport;
1175 1147
1176 if (!detect_sscape(sscape)) { 1148 if (!detect_sscape(sscape)) {
1177 printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base); 1149 printk(KERN_ERR "sscape: hardware not detected at 0x%x\n", sscape->io_base);
@@ -1180,7 +1152,7 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1180 } 1152 }
1181 1153
1182 printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n", 1154 printk(KERN_INFO "sscape: hardware detected at 0x%x, using IRQ %d, DMA %d\n",
1183 sscape->io_base, params->irq, params->dma1); 1155 sscape->io_base, irq[dev], dma[dev]);
1184 1156
1185 /* 1157 /*
1186 * Now create the hardware-specific device so that we can 1158 * Now create the hardware-specific device so that we can
@@ -1223,7 +1195,7 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1223 sscape_write_unsafe(sscape->io_base, 1195 sscape_write_unsafe(sscape->io_base,
1224 GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg); 1196 GA_INTCFG_REG, 0xf0 | (mpu_irq_cfg << 2) | mpu_irq_cfg);
1225 sscape_write_unsafe(sscape->io_base, 1197 sscape_write_unsafe(sscape->io_base,
1226 GA_CDCFG_REG, 0x09 | DMA_8BIT | (params->dma1 << 4) | (irq_cfg << 1)); 1198 GA_CDCFG_REG, 0x09 | DMA_8BIT | (dma[dev] << 4) | (irq_cfg << 1));
1227 1199
1228 spin_unlock_irqrestore(&sscape->lock, flags); 1200 spin_unlock_irqrestore(&sscape->lock, flags);
1229 1201
@@ -1231,15 +1203,15 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1231 * We have now enabled the codec chip, and so we should 1203 * We have now enabled the codec chip, and so we should
1232 * detect the AD1845 device ... 1204 * detect the AD1845 device ...
1233 */ 1205 */
1234 if ((err = create_ad1845(card, CODEC_IO(params->port), params->irq, params->dma1)) < 0) { 1206 if ((err = create_ad1845(card, CODEC_IO(xport), irq[dev], dma[dev])) < 0) {
1235 printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n", 1207 printk(KERN_ERR "sscape: No AD1845 device at 0x%x, IRQ %d\n",
1236 CODEC_IO(params->port), params->irq); 1208 CODEC_IO(xport), irq[dev]);
1237 goto _release_card; 1209 goto _release_card;
1238 } 1210 }
1239#define MIDI_DEVNUM 0 1211#define MIDI_DEVNUM 0
1240 if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(params->port), params->mpu_irq)) < 0) { 1212 if ((err = create_mpu401(card, MIDI_DEVNUM, MPU401_IO(xport), mpu_irq[dev])) < 0) {
1241 printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n", 1213 printk(KERN_ERR "sscape: Failed to create MPU-401 device at 0x%x\n",
1242 MPU401_IO(params->port)); 1214 MPU401_IO(xport));
1243 goto _release_card; 1215 goto _release_card;
1244 } 1216 }
1245 1217
@@ -1271,7 +1243,7 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1271 snd_card_free(card); 1243 snd_card_free(card);
1272 1244
1273 _release_dma: 1245 _release_dma:
1274 free_dma(params->dma1); 1246 free_dma(dma[dev]);
1275 1247
1276 _release_region: 1248 _release_region:
1277 release_and_free_resource(io_res); 1249 release_and_free_resource(io_res);
@@ -1280,44 +1252,66 @@ static int __devinit create_sscape(const struct params *params, struct snd_card
1280} 1252}
1281 1253
1282 1254
1283static int sscape_cards __devinitdata; 1255static int __init snd_sscape_probe(struct platform_device *pdev)
1284static struct params sscape_params[SNDRV_CARDS] __devinitdata; 1256{
1257 int dev = pdev->id;
1258 struct snd_card *card;
1259 int ret;
1260
1261 dma[dev] &= 0x03;
1262 ret = create_sscape(dev, &card);
1263 if (ret < 0)
1264 return ret;
1265 snd_card_set_dev(card, &pdev->dev);
1266 if ((ret = snd_card_register(card)) < 0) {
1267 printk(KERN_ERR "sscape: Failed to register sound card\n");
1268 return ret;
1269 }
1270 platform_set_drvdata(pdev, card);
1271 return 0;
1272}
1273
1274static int __devexit snd_sscape_remove(struct platform_device *devptr)
1275{
1276 snd_card_free(platform_get_drvdata(devptr));
1277 platform_set_drvdata(devptr, NULL);
1278 return 0;
1279}
1280
1281#define SSCAPE_DRIVER "snd_sscape"
1282
1283static struct platform_driver snd_sscape_driver = {
1284 .probe = snd_sscape_probe,
1285 .remove = __devexit_p(snd_sscape_remove),
1286 /* FIXME: suspend/resume */
1287 .driver = {
1288 .name = SSCAPE_DRIVER
1289 },
1290};
1285 1291
1286#ifdef CONFIG_PNP 1292#ifdef CONFIG_PNP
1287static inline int __devinit get_next_autoindex(int i) 1293static inline int __devinit get_next_autoindex(int i)
1288{ 1294{
1289 while ((i < SNDRV_CARDS) && (port[i] != SNDRV_AUTO_PORT)) { 1295 while (i < SNDRV_CARDS && port[i] != SNDRV_AUTO_PORT)
1290 ++i; 1296 ++i;
1291 } /* while */
1292
1293 return i; 1297 return i;
1294} 1298}
1295 1299
1296 1300
1297static inline int __devinit is_port_known(unsigned io, struct params *params, int cards)
1298{
1299 while (--cards >= 0) {
1300 if (params[cards].port == io)
1301 return 1;
1302 } /* while */
1303
1304 return 0;
1305}
1306
1307static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard, 1301static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
1308 const struct pnp_card_device_id *pid) 1302 const struct pnp_card_device_id *pid)
1309{ 1303{
1310 struct pnp_dev *dev;
1311 static int idx = 0; 1304 static int idx = 0;
1305 struct pnp_dev *dev;
1306 struct snd_card *card;
1312 int ret; 1307 int ret;
1313 1308
1314 /* 1309 /*
1315 * Allow this function to fail *quietly* if all the ISA PnP 1310 * Allow this function to fail *quietly* if all the ISA PnP
1316 * devices were configured using module parameters instead. 1311 * devices were configured using module parameters instead.
1317 */ 1312 */
1318 if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS) { 1313 if ((idx = get_next_autoindex(idx)) >= SNDRV_CARDS)
1319 return -ENOSPC; 1314 return -ENOSPC;
1320 }
1321 1315
1322 /* 1316 /*
1323 * We have found a candidate ISA PnP card. Now we 1317 * We have found a candidate ISA PnP card. Now we
@@ -1339,66 +1333,45 @@ static int __devinit sscape_pnp_detect(struct pnp_card_link *pcard,
1339 /* 1333 /*
1340 * Check that we still have room for another sound card ... 1334 * Check that we still have room for another sound card ...
1341 */ 1335 */
1342 if (sscape_cards >= SNDRV_CARDS) {
1343 printk(KERN_ERR "sscape: No room for another ALSA device\n");
1344 return -ENOSPC;
1345 }
1346
1347 ret = -ENODEV;
1348
1349 dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL); 1336 dev = pnp_request_card_device(pcard, pid->devs[0].id, NULL);
1350 if (dev) { 1337 if (! dev)
1351 struct params *this; 1338 return -ENODEV;
1352 if (!pnp_is_active(dev)) {
1353 if (pnp_activate_dev(dev) < 0) {
1354 printk(KERN_INFO "sscape: device is inactive\n");
1355 return -EBUSY;
1356 }
1357 }
1358 /*
1359 * Read the correct parameters off the ISA PnP bus ...
1360 */
1361 this = init_params(&sscape_params[sscape_cards],
1362 index[idx],
1363 id[idx],
1364 pnp_port_start(dev, 0),
1365 pnp_irq(dev, 0),
1366 pnp_irq(dev, 1),
1367 pnp_dma(dev, 0));
1368 1339
1369 /* 1340 if (!pnp_is_active(dev)) {
1370 * Do we know about this sound card already? 1341 if (pnp_activate_dev(dev) < 0) {
1371 */ 1342 printk(KERN_INFO "sscape: device is inactive\n");
1372 if ( !is_port_known(this->port, sscape_params, sscape_cards) ) { 1343 return -EBUSY;
1373 struct snd_card *card;
1374
1375 ret = create_sscape(this, &card);
1376 if (ret < 0)
1377 return ret;
1378 snd_card_set_dev(card, &pcard->card->dev);
1379
1380 if ((ret = snd_card_register(card)) < 0) {
1381 printk(KERN_ERR "sscape: Failed to register sound card\n");
1382 snd_card_free(card);
1383 return ret;
1384 }
1385
1386 pnp_set_card_drvdata(pcard, card);
1387 ++sscape_cards;
1388 ++idx;
1389 } 1344 }
1390 } 1345 }
1391 1346
1347 /*
1348 * Read the correct parameters off the ISA PnP bus ...
1349 */
1350 port[idx] = pnp_port_start(dev, 0);
1351 irq[idx] = pnp_irq(dev, 0);
1352 mpu_irq[idx] = pnp_irq(dev, 1);
1353 dma[idx] = pnp_dma(dev, 0) & 0x03;
1354
1355 ret = create_sscape(idx, &card);
1356 if (ret < 0)
1357 return ret;
1358 snd_card_set_dev(card, &pcard->card->dev);
1359 if ((ret = snd_card_register(card)) < 0) {
1360 printk(KERN_ERR "sscape: Failed to register sound card\n");
1361 snd_card_free(card);
1362 return ret;
1363 }
1364
1365 pnp_set_card_drvdata(pcard, card);
1366 ++idx;
1367
1392 return ret; 1368 return ret;
1393} 1369}
1394 1370
1395static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard) 1371static void __devexit sscape_pnp_remove(struct pnp_card_link * pcard)
1396{ 1372{
1397 struct snd_card *card = (struct snd_card *) pnp_get_card_drvdata(pcard); 1373 snd_card_free(pnp_get_card_drvdata(pcard));
1398
1399 pnp_set_card_drvdata(pcard, NULL); 1374 pnp_set_card_drvdata(pcard, NULL);
1400 snd_card_disconnect(card);
1401 snd_card_free_in_thread(card);
1402} 1375}
1403 1376
1404static struct pnp_card_driver sscape_pnpc_driver = { 1377static struct pnp_card_driver sscape_pnpc_driver = {
@@ -1411,11 +1384,14 @@ static struct pnp_card_driver sscape_pnpc_driver = {
1411 1384
1412#endif /* CONFIG_PNP */ 1385#endif /* CONFIG_PNP */
1413 1386
1414static int __init sscape_manual_probe(struct params *params) 1387static int __init sscape_manual_probe(void)
1415{ 1388{
1416 int ret; 1389 struct platform_device *device;
1417 unsigned i; 1390 int i, ret;
1418 struct snd_card *card; 1391
1392 ret = platform_driver_register(&snd_sscape_driver);
1393 if (ret < 0)
1394 return ret;
1419 1395
1420 for (i = 0; i < SNDRV_CARDS; ++i) { 1396 for (i = 0; i < SNDRV_CARDS; ++i) {
1421 /* 1397 /*
@@ -1430,52 +1406,32 @@ static int __init sscape_manual_probe(struct params *params)
1430 /* 1406 /*
1431 * Make sure we were given ALL of the other parameters. 1407 * Make sure we were given ALL of the other parameters.
1432 */ 1408 */
1433 if ( (irq[i] == SNDRV_AUTO_IRQ) || 1409 if (irq[i] == SNDRV_AUTO_IRQ ||
1434 (mpu_irq[i] == SNDRV_AUTO_IRQ) || 1410 mpu_irq[i] == SNDRV_AUTO_IRQ ||
1435 (dma[i] == SNDRV_AUTO_DMA) ) { 1411 dma[i] == SNDRV_AUTO_DMA) {
1436 printk(KERN_INFO 1412 printk(KERN_INFO
1437 "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n"); 1413 "sscape: insufficient parameters, need IO, IRQ, MPU-IRQ and DMA\n");
1414 platform_driver_unregister(&snd_sscape_driver);
1438 return -ENXIO; 1415 return -ENXIO;
1439 } 1416 }
1440 1417
1441 /* 1418 /*
1442 * This cards looks OK ... 1419 * This cards looks OK ...
1443 */ 1420 */
1444 init_params(params, index[i], id[i], port[i], irq[i], mpu_irq[i], dma[i]); 1421 device = platform_device_register_simple(SSCAPE_DRIVER,
1445 1422 i, NULL, 0);
1446 ret = create_sscape(params, &card); 1423 if (IS_ERR(device)) {
1447 if (ret < 0) 1424 platform_driver_unregister(&snd_sscape_driver);
1448 return ret; 1425 return PTR_ERR(device);
1449
1450 if ((ret = snd_card_set_generic_dev(card)) < 0) {
1451 snd_card_free(card);
1452 return ret;
1453 }
1454 if ((ret = snd_card_register(card)) < 0) {
1455 printk(KERN_ERR "sscape: Failed to register sound card\n");
1456 snd_card_free(card);
1457 return ret;
1458 } 1426 }
1459 1427 }
1460 sscape_card[sscape_cards] = card;
1461 params++;
1462 sscape_cards++;
1463 } /* for */
1464
1465 return 0; 1428 return 0;
1466} 1429}
1467 1430
1468
1469static void sscape_exit(void) 1431static void sscape_exit(void)
1470{ 1432{
1471 unsigned i;
1472
1473#ifdef CONFIG_PNP
1474 pnp_unregister_card_driver(&sscape_pnpc_driver); 1433 pnp_unregister_card_driver(&sscape_pnpc_driver);
1475#endif 1434 platform_driver_unregister(&snd_sscape_driver);
1476 for (i = 0; i < ARRAY_SIZE(sscape_card); ++i) {
1477 snd_card_free(sscape_card[i]);
1478 } /* for */
1479} 1435}
1480 1436
1481 1437
@@ -1489,24 +1445,10 @@ static int __init sscape_init(void)
1489 * of allocating cards, because the operator is 1445 * of allocating cards, because the operator is
1490 * S-P-E-L-L-I-N-G it out for us... 1446 * S-P-E-L-L-I-N-G it out for us...
1491 */ 1447 */
1492 ret = sscape_manual_probe(sscape_params); 1448 ret = sscape_manual_probe();
1493 if (ret < 0) { 1449 if (ret < 0)
1494 int i;
1495 for (i = 0; i < sscape_cards; ++i)
1496 snd_card_free(sscape_card[i]);
1497 return ret; 1450 return ret;
1498 } 1451 pnp_register_card_driver(&sscape_pnpc_driver);
1499
1500#ifdef CONFIG_PNP
1501 if (sscape_cards < SNDRV_CARDS) {
1502 ret = pnp_register_card_driver(&sscape_pnpc_driver);
1503 if (ret < 0) {
1504 sscape_exit();
1505 return ret;
1506 }
1507 }
1508#endif
1509
1510 return 0; 1452 return 0;
1511} 1453}
1512 1454