diff options
author | Jarkko Nikula <jhnikula@gmail.com> | 2010-12-06 09:27:07 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-12-06 14:14:46 -0500 |
commit | 589c3563f6476950f26b5bcc9beb1b39a7bcc644 (patch) | |
tree | 8d3d5ef20fc37e36f014fd80059bc0e9f6e42f99 /sound/soc/soc-core.c | |
parent | 0afc8c733e95642ee9200966081da82564af8f8f (diff) |
ASoC: Merge common code in DAI link and auxiliary codec probing/removal
Commit 2eea392 "ASoC: Add support for optional auxiliary dailess codecs"
added much of code that can be shared with DAI link codec probing/removal.
Merge now this common code into new soc_probe_codec, soc_remove_codec and
soc_post_component_init functions.
Error prints in these functions are converted to use dev_err and to print
the error code.
Signed-off-by: Jarkko Nikula <jhnikula@gmail.com>
Acked-by: Liam Girdwood <lrg@slimlogic.co.uk>
Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 284 |
1 files changed, 132 insertions, 152 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 17dcd56a2520..b3605a1c8c46 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1328,6 +1328,27 @@ out: | |||
1328 | return 1; | 1328 | return 1; |
1329 | } | 1329 | } |
1330 | 1330 | ||
1331 | static void soc_remove_codec(struct snd_soc_codec *codec) | ||
1332 | { | ||
1333 | int err; | ||
1334 | |||
1335 | if (codec->driver->remove) { | ||
1336 | err = codec->driver->remove(codec); | ||
1337 | if (err < 0) | ||
1338 | dev_err(codec->dev, | ||
1339 | "asoc: failed to remove %s: %d\n", | ||
1340 | codec->name, err); | ||
1341 | } | ||
1342 | |||
1343 | /* Make sure all DAPM widgets are freed */ | ||
1344 | snd_soc_dapm_free(&codec->dapm); | ||
1345 | |||
1346 | soc_cleanup_codec_debugfs(codec); | ||
1347 | codec->probed = 0; | ||
1348 | list_del(&codec->card_list); | ||
1349 | module_put(codec->dev->driver->owner); | ||
1350 | } | ||
1351 | |||
1331 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) | 1352 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) |
1332 | { | 1353 | { |
1333 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1354 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
@@ -1339,6 +1360,7 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1339 | /* unregister the rtd device */ | 1360 | /* unregister the rtd device */ |
1340 | if (rtd->dev_registered) { | 1361 | if (rtd->dev_registered) { |
1341 | device_remove_file(&rtd->dev, &dev_attr_pmdown_time); | 1362 | device_remove_file(&rtd->dev, &dev_attr_pmdown_time); |
1363 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1342 | device_unregister(&rtd->dev); | 1364 | device_unregister(&rtd->dev); |
1343 | rtd->dev_registered = 0; | 1365 | rtd->dev_registered = 0; |
1344 | } | 1366 | } |
@@ -1367,22 +1389,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1367 | } | 1389 | } |
1368 | 1390 | ||
1369 | /* remove the CODEC */ | 1391 | /* remove the CODEC */ |
1370 | if (codec && codec->probed) { | 1392 | if (codec && codec->probed) |
1371 | if (codec->driver->remove) { | 1393 | soc_remove_codec(codec); |
1372 | err = codec->driver->remove(codec); | ||
1373 | if (err < 0) | ||
1374 | printk(KERN_ERR "asoc: failed to remove %s\n", codec->name); | ||
1375 | } | ||
1376 | |||
1377 | /* Make sure all DAPM widgets are freed */ | ||
1378 | snd_soc_dapm_free(&codec->dapm); | ||
1379 | |||
1380 | soc_cleanup_codec_debugfs(codec); | ||
1381 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1382 | codec->probed = 0; | ||
1383 | list_del(&codec->card_list); | ||
1384 | module_put(codec->dev->driver->owner); | ||
1385 | } | ||
1386 | 1394 | ||
1387 | /* remove the cpu_dai */ | 1395 | /* remove the cpu_dai */ |
1388 | if (cpu_dai && cpu_dai->probed) { | 1396 | if (cpu_dai && cpu_dai->probed) { |
@@ -1414,8 +1422,105 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1414 | } | 1422 | } |
1415 | } | 1423 | } |
1416 | 1424 | ||
1425 | static int soc_probe_codec(struct snd_soc_card *card, | ||
1426 | struct snd_soc_codec *codec) | ||
1427 | { | ||
1428 | int ret = 0; | ||
1429 | |||
1430 | codec->card = card; | ||
1431 | codec->dapm.card = card; | ||
1432 | soc_set_name_prefix(card, codec); | ||
1433 | |||
1434 | if (codec->driver->probe) { | ||
1435 | ret = codec->driver->probe(codec); | ||
1436 | if (ret < 0) { | ||
1437 | dev_err(codec->dev, | ||
1438 | "asoc: failed to probe CODEC %s: %d\n", | ||
1439 | codec->name, ret); | ||
1440 | return ret; | ||
1441 | } | ||
1442 | } | ||
1443 | |||
1444 | soc_init_codec_debugfs(codec); | ||
1445 | |||
1446 | /* mark codec as probed and add to card codec list */ | ||
1447 | codec->probed = 1; | ||
1448 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1449 | |||
1450 | return ret; | ||
1451 | } | ||
1452 | |||
1417 | static void rtd_release(struct device *dev) {} | 1453 | static void rtd_release(struct device *dev) {} |
1418 | 1454 | ||
1455 | static int soc_post_component_init(struct snd_soc_card *card, | ||
1456 | struct snd_soc_codec *codec, | ||
1457 | int num, int dailess) | ||
1458 | { | ||
1459 | struct snd_soc_dai_link *dai_link = NULL; | ||
1460 | struct snd_soc_aux_dev *aux_dev = NULL; | ||
1461 | struct snd_soc_pcm_runtime *rtd; | ||
1462 | const char *temp, *name; | ||
1463 | int ret = 0; | ||
1464 | |||
1465 | if (!dailess) { | ||
1466 | dai_link = &card->dai_link[num]; | ||
1467 | rtd = &card->rtd[num]; | ||
1468 | name = dai_link->name; | ||
1469 | } else { | ||
1470 | aux_dev = &card->aux_dev[num]; | ||
1471 | rtd = &card->rtd_aux[num]; | ||
1472 | name = aux_dev->name; | ||
1473 | } | ||
1474 | |||
1475 | /* machine controls, routes and widgets are not prefixed */ | ||
1476 | temp = codec->name_prefix; | ||
1477 | codec->name_prefix = NULL; | ||
1478 | |||
1479 | /* do machine specific initialization */ | ||
1480 | if (!dailess && dai_link->init) | ||
1481 | ret = dai_link->init(rtd); | ||
1482 | else if (dailess && aux_dev->init) | ||
1483 | ret = aux_dev->init(&codec->dapm); | ||
1484 | if (ret < 0) { | ||
1485 | dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret); | ||
1486 | return ret; | ||
1487 | } | ||
1488 | codec->name_prefix = temp; | ||
1489 | |||
1490 | /* Make sure all DAPM widgets are instantiated */ | ||
1491 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
1492 | snd_soc_dapm_sync(&codec->dapm); | ||
1493 | |||
1494 | /* register the rtd device */ | ||
1495 | rtd->codec = codec; | ||
1496 | rtd->card = card; | ||
1497 | rtd->dev.parent = card->dev; | ||
1498 | rtd->dev.release = rtd_release; | ||
1499 | rtd->dev.init_name = name; | ||
1500 | ret = device_register(&rtd->dev); | ||
1501 | if (ret < 0) { | ||
1502 | dev_err(card->dev, | ||
1503 | "asoc: failed to register runtime device: %d\n", ret); | ||
1504 | return ret; | ||
1505 | } | ||
1506 | rtd->dev_registered = 1; | ||
1507 | |||
1508 | /* add DAPM sysfs entries for this codec */ | ||
1509 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1510 | if (ret < 0) | ||
1511 | dev_err(codec->dev, | ||
1512 | "asoc: failed to add codec dapm sysfs entries: %d\n", | ||
1513 | ret); | ||
1514 | |||
1515 | /* add codec sysfs entries */ | ||
1516 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1517 | if (ret < 0) | ||
1518 | dev_err(codec->dev, | ||
1519 | "asoc: failed to add codec sysfs files: %d\n", ret); | ||
1520 | |||
1521 | return 0; | ||
1522 | } | ||
1523 | |||
1419 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) | 1524 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) |
1420 | { | 1525 | { |
1421 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1526 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
@@ -1423,17 +1528,13 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1423 | struct snd_soc_codec *codec = rtd->codec; | 1528 | struct snd_soc_codec *codec = rtd->codec; |
1424 | struct snd_soc_platform *platform = rtd->platform; | 1529 | struct snd_soc_platform *platform = rtd->platform; |
1425 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; | 1530 | struct snd_soc_dai *codec_dai = rtd->codec_dai, *cpu_dai = rtd->cpu_dai; |
1426 | const char *temp; | ||
1427 | int ret; | 1531 | int ret; |
1428 | 1532 | ||
1429 | dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); | 1533 | dev_dbg(card->dev, "probe %s dai link %d\n", card->name, num); |
1430 | 1534 | ||
1431 | /* config components */ | 1535 | /* config components */ |
1432 | codec_dai->codec = codec; | 1536 | codec_dai->codec = codec; |
1433 | codec->card = card; | ||
1434 | cpu_dai->platform = platform; | 1537 | cpu_dai->platform = platform; |
1435 | rtd->card = card; | ||
1436 | rtd->dev.parent = card->dev; | ||
1437 | codec_dai->card = card; | 1538 | codec_dai->card = card; |
1438 | cpu_dai->card = card; | 1539 | cpu_dai->card = card; |
1439 | 1540 | ||
@@ -1457,22 +1558,9 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1457 | 1558 | ||
1458 | /* probe the CODEC */ | 1559 | /* probe the CODEC */ |
1459 | if (!codec->probed) { | 1560 | if (!codec->probed) { |
1460 | codec->dapm.card = card; | 1561 | ret = soc_probe_codec(card, codec); |
1461 | soc_set_name_prefix(card, codec); | 1562 | if (ret < 0) |
1462 | if (codec->driver->probe) { | 1563 | return ret; |
1463 | ret = codec->driver->probe(codec); | ||
1464 | if (ret < 0) { | ||
1465 | printk(KERN_ERR "asoc: failed to probe CODEC %s\n", | ||
1466 | codec->name); | ||
1467 | return ret; | ||
1468 | } | ||
1469 | } | ||
1470 | |||
1471 | soc_init_codec_debugfs(codec); | ||
1472 | |||
1473 | /* mark codec as probed and add to card codec list */ | ||
1474 | codec->probed = 1; | ||
1475 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1476 | } | 1564 | } |
1477 | 1565 | ||
1478 | /* probe the platform */ | 1566 | /* probe the platform */ |
@@ -1509,47 +1597,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1509 | /* DAPM dai link stream work */ | 1597 | /* DAPM dai link stream work */ |
1510 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | 1598 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); |
1511 | 1599 | ||
1512 | /* now that all clients have probed, initialise the DAI link */ | 1600 | ret = soc_post_component_init(card, codec, num, 0); |
1513 | if (dai_link->init) { | 1601 | if (ret) |
1514 | /* machine controls, routes and widgets are not prefixed */ | ||
1515 | temp = rtd->codec->name_prefix; | ||
1516 | rtd->codec->name_prefix = NULL; | ||
1517 | ret = dai_link->init(rtd); | ||
1518 | if (ret < 0) { | ||
1519 | printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); | ||
1520 | return ret; | ||
1521 | } | ||
1522 | rtd->codec->name_prefix = temp; | ||
1523 | } | ||
1524 | |||
1525 | /* Make sure all DAPM widgets are instantiated */ | ||
1526 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
1527 | snd_soc_dapm_sync(&codec->dapm); | ||
1528 | |||
1529 | /* register the rtd device */ | ||
1530 | rtd->dev.release = rtd_release; | ||
1531 | rtd->dev.init_name = dai_link->name; | ||
1532 | ret = device_register(&rtd->dev); | ||
1533 | if (ret < 0) { | ||
1534 | printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret); | ||
1535 | return ret; | 1602 | return ret; |
1536 | } | ||
1537 | 1603 | ||
1538 | rtd->dev_registered = 1; | ||
1539 | ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); | 1604 | ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); |
1540 | if (ret < 0) | 1605 | if (ret < 0) |
1541 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | 1606 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); |
1542 | 1607 | ||
1543 | /* add DAPM sysfs entries for this codec */ | ||
1544 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1545 | if (ret < 0) | ||
1546 | printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n"); | ||
1547 | |||
1548 | /* add codec sysfs entries */ | ||
1549 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1550 | if (ret < 0) | ||
1551 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | ||
1552 | |||
1553 | /* create the pcm */ | 1608 | /* create the pcm */ |
1554 | ret = soc_new_pcm(rtd, num); | 1609 | ret = soc_new_pcm(rtd, num); |
1555 | if (ret < 0) { | 1610 | if (ret < 0) { |
@@ -1607,9 +1662,7 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) | |||
1607 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | 1662 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) |
1608 | { | 1663 | { |
1609 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1664 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1610 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1611 | struct snd_soc_codec *codec; | 1665 | struct snd_soc_codec *codec; |
1612 | const char *temp; | ||
1613 | int ret = -ENODEV; | 1666 | int ret = -ENODEV; |
1614 | 1667 | ||
1615 | /* find CODEC from registered CODECs*/ | 1668 | /* find CODEC from registered CODECs*/ |
@@ -1632,67 +1685,11 @@ found: | |||
1632 | if (!try_module_get(codec->dev->driver->owner)) | 1685 | if (!try_module_get(codec->dev->driver->owner)) |
1633 | return -ENODEV; | 1686 | return -ENODEV; |
1634 | 1687 | ||
1635 | codec->card = card; | 1688 | ret = soc_probe_codec(card, codec); |
1636 | codec->dapm.card = card; | ||
1637 | |||
1638 | soc_set_name_prefix(card, codec); | ||
1639 | if (codec->driver->probe) { | ||
1640 | ret = codec->driver->probe(codec); | ||
1641 | if (ret < 0) { | ||
1642 | dev_err(codec->dev, "asoc: failed to probe CODEC"); | ||
1643 | return ret; | ||
1644 | } | ||
1645 | } | ||
1646 | |||
1647 | soc_init_codec_debugfs(codec); | ||
1648 | |||
1649 | /* mark codec as probed and add to card codec list */ | ||
1650 | codec->probed = 1; | ||
1651 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1652 | |||
1653 | /* now that all clients have probed, initialise the DAI link */ | ||
1654 | if (aux_dev->init) { | ||
1655 | /* machine controls, routes and widgets are not prefixed */ | ||
1656 | temp = codec->name_prefix; | ||
1657 | codec->name_prefix = NULL; | ||
1658 | ret = aux_dev->init(&codec->dapm); | ||
1659 | if (ret < 0) { | ||
1660 | dev_err(codec->dev, | ||
1661 | "asoc: failed to init %s\n", aux_dev->name); | ||
1662 | return ret; | ||
1663 | } | ||
1664 | codec->name_prefix = temp; | ||
1665 | } | ||
1666 | |||
1667 | /* Make sure all DAPM widgets are instantiated */ | ||
1668 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
1669 | snd_soc_dapm_sync(&codec->dapm); | ||
1670 | |||
1671 | /* register the rtd device */ | ||
1672 | rtd->codec = codec; | ||
1673 | rtd->card = card; | ||
1674 | rtd->dev.parent = card->dev; | ||
1675 | rtd->dev.release = rtd_release; | ||
1676 | rtd->dev.init_name = aux_dev->name; | ||
1677 | ret = device_register(&rtd->dev); | ||
1678 | if (ret < 0) { | ||
1679 | dev_err(codec->dev, | ||
1680 | "asoc: failed to register aux runtime device %d\n", | ||
1681 | ret); | ||
1682 | return ret; | ||
1683 | } | ||
1684 | rtd->dev_registered = 1; | ||
1685 | |||
1686 | /* add DAPM sysfs entries for this codec */ | ||
1687 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1688 | if (ret < 0) | 1689 | if (ret < 0) |
1689 | dev_err(codec->dev, | 1690 | return ret; |
1690 | "asoc: failed to add codec dapm sysfs entries\n"); | ||
1691 | 1691 | ||
1692 | /* add codec sysfs entries */ | 1692 | ret = soc_post_component_init(card, codec, num, 1); |
1693 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1694 | if (ret < 0) | ||
1695 | dev_err(codec->dev, "asoc: failed to add codec sysfs files\n"); | ||
1696 | 1693 | ||
1697 | out: | 1694 | out: |
1698 | return ret; | 1695 | return ret; |
@@ -1702,33 +1699,16 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | |||
1702 | { | 1699 | { |
1703 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1700 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
1704 | struct snd_soc_codec *codec = rtd->codec; | 1701 | struct snd_soc_codec *codec = rtd->codec; |
1705 | int err; | ||
1706 | 1702 | ||
1707 | /* unregister the rtd device */ | 1703 | /* unregister the rtd device */ |
1708 | if (rtd->dev_registered) { | 1704 | if (rtd->dev_registered) { |
1705 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1709 | device_unregister(&rtd->dev); | 1706 | device_unregister(&rtd->dev); |
1710 | rtd->dev_registered = 0; | 1707 | rtd->dev_registered = 0; |
1711 | } | 1708 | } |
1712 | 1709 | ||
1713 | /* remove the CODEC */ | 1710 | if (codec && codec->probed) |
1714 | if (codec && codec->probed) { | 1711 | soc_remove_codec(codec); |
1715 | if (codec->driver->remove) { | ||
1716 | err = codec->driver->remove(codec); | ||
1717 | if (err < 0) | ||
1718 | dev_err(codec->dev, | ||
1719 | "asoc: failed to remove %s\n", | ||
1720 | codec->name); | ||
1721 | } | ||
1722 | |||
1723 | /* Make sure all DAPM widgets are freed */ | ||
1724 | snd_soc_dapm_free(&codec->dapm); | ||
1725 | |||
1726 | soc_cleanup_codec_debugfs(codec); | ||
1727 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1728 | codec->probed = 0; | ||
1729 | list_del(&codec->card_list); | ||
1730 | module_put(codec->dev->driver->owner); | ||
1731 | } | ||
1732 | } | 1712 | } |
1733 | 1713 | ||
1734 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, | 1714 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, |