aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
authorMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-10 13:36:42 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2008-12-10 14:47:44 -0500
commitd58d5d5567ea9483346f57c83a94ce05992cd47c (patch)
tree068237c7f8fa0a2290bac0d0e80125677cc1697e /sound/soc
parent78e19a39d3985e2a06354493a70a200c0d432de5 (diff)
ASoC: Convert WM8903 driver to register at I2C probe time
The driver now registers the codec and DAI when probed as an I2C device. Also convert the driver to use a single dynamic allocation to simplify error handling. Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/wm8903.c230
-rw-r--r--sound/soc/codecs/wm8903.h5
2 files changed, 97 insertions, 138 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c
index b1f5cf77a87..c80968fe326 100644
--- a/sound/soc/codecs/wm8903.c
+++ b/sound/soc/codecs/wm8903.c
@@ -33,19 +33,6 @@
33 33
34#include "wm8903.h" 34#include "wm8903.h"
35 35
36struct wm8903_priv {
37 int sysclk;
38
39 /* Reference counts */
40 int charge_pump_users;
41 int class_w_users;
42 int playback_active;
43 int capture_active;
44
45 struct snd_pcm_substream *master_substream;
46 struct snd_pcm_substream *slave_substream;
47};
48
49/* Register defaults at reset */ 36/* Register defaults at reset */
50static u16 wm8903_reg_defaults[] = { 37static u16 wm8903_reg_defaults[] = {
51 0x8903, /* R0 - SW Reset and ID */ 38 0x8903, /* R0 - SW Reset and ID */
@@ -223,6 +210,23 @@ static u16 wm8903_reg_defaults[] = {
223 0x0000, /* R172 - Analogue Output Bias 0 */ 210 0x0000, /* R172 - Analogue Output Bias 0 */
224}; 211};
225 212
213struct wm8903_priv {
214 struct snd_soc_codec codec;
215 u16 reg_cache[ARRAY_SIZE(wm8903_reg_defaults)];
216
217 int sysclk;
218
219 /* Reference counts */
220 int charge_pump_users;
221 int class_w_users;
222 int playback_active;
223 int capture_active;
224
225 struct snd_pcm_substream *master_substream;
226 struct snd_pcm_substream *slave_substream;
227};
228
229
226static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, 230static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec,
227 unsigned int reg) 231 unsigned int reg)
228{ 232{
@@ -360,6 +364,8 @@ static void wm8903_sync_reg_cache(struct snd_soc_codec *codec, u16 *cache)
360static void wm8903_reset(struct snd_soc_codec *codec) 364static void wm8903_reset(struct snd_soc_codec *codec)
361{ 365{
362 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0); 366 wm8903_write(codec, WM8903_SW_RESET_AND_ID, 0);
367 memcpy(codec->reg_cache, wm8903_reg_defaults,
368 sizeof(wm8903_reg_defaults));
363} 369}
364 370
365#define WM8903_OUTPUT_SHORT 0x8 371#define WM8903_OUTPUT_SHORT 0x8
@@ -1563,39 +1569,48 @@ static int wm8903_resume(struct platform_device *pdev)
1563 return 0; 1569 return 0;
1564} 1570}
1565 1571
1566/* 1572static struct snd_soc_codec *wm8903_codec;
1567 * initialise the WM8903 driver 1573
1568 * register the mixer and dsp interfaces with the kernel 1574static int wm8903_i2c_probe(struct i2c_client *i2c,
1569 */ 1575 const struct i2c_device_id *id)
1570static int wm8903_init(struct snd_soc_device *socdev)
1571{ 1576{
1572 struct snd_soc_codec *codec = socdev->codec; 1577 struct wm8903_priv *wm8903;
1573 struct i2c_client *i2c = codec->control_data; 1578 struct snd_soc_codec *codec;
1574 int ret = 0; 1579 int ret;
1575 u16 val; 1580 u16 val;
1576 1581
1577 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); 1582 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL);
1578 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { 1583 if (wm8903 == NULL)
1579 dev_err(&i2c->dev, 1584 return -ENOMEM;
1580 "Device with ID register %x is not a WM8903\n", val);
1581 return -ENODEV;
1582 }
1583 1585
1586 codec = &wm8903->codec;
1587
1588 mutex_init(&codec->mutex);
1589 INIT_LIST_HEAD(&codec->dapm_widgets);
1590 INIT_LIST_HEAD(&codec->dapm_paths);
1591
1592 codec->dev = &i2c->dev;
1584 codec->name = "WM8903"; 1593 codec->name = "WM8903";
1585 codec->owner = THIS_MODULE; 1594 codec->owner = THIS_MODULE;
1586 codec->read = wm8903_read; 1595 codec->read = wm8903_read;
1587 codec->write = wm8903_write; 1596 codec->write = wm8903_write;
1597 codec->hw_write = (hw_write_t)i2c_master_send;
1588 codec->bias_level = SND_SOC_BIAS_OFF; 1598 codec->bias_level = SND_SOC_BIAS_OFF;
1589 codec->set_bias_level = wm8903_set_bias_level; 1599 codec->set_bias_level = wm8903_set_bias_level;
1590 codec->dai = &wm8903_dai; 1600 codec->dai = &wm8903_dai;
1591 codec->num_dai = 1; 1601 codec->num_dai = 1;
1592 codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults); 1602 codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache);
1593 codec->reg_cache = kmemdup(wm8903_reg_defaults, 1603 codec->reg_cache = &wm8903->reg_cache[0];
1594 sizeof(wm8903_reg_defaults), 1604 codec->private_data = wm8903;
1595 GFP_KERNEL); 1605
1596 if (codec->reg_cache == NULL) { 1606 i2c_set_clientdata(i2c, codec);
1597 dev_err(&i2c->dev, "Failed to allocate register cache\n"); 1607 codec->control_data = i2c;
1598 return -ENOMEM; 1608
1609 val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID);
1610 if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) {
1611 dev_err(&i2c->dev,
1612 "Device with ID register %x is not a WM8903\n", val);
1613 return -ENODEV;
1599 } 1614 }
1600 1615
1601 val = wm8903_read(codec, WM8903_REVISION_NUMBER); 1616 val = wm8903_read(codec, WM8903_REVISION_NUMBER);
@@ -1604,13 +1619,6 @@ static int wm8903_init(struct snd_soc_device *socdev)
1604 1619
1605 wm8903_reset(codec); 1620 wm8903_reset(codec);
1606 1621
1607 /* register pcms */
1608 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1609 if (ret < 0) {
1610 dev_err(&i2c->dev, "failed to create pcms\n");
1611 goto pcm_err;
1612 }
1613
1614 /* SYSCLK is required for pretty much anything */ 1622 /* SYSCLK is required for pretty much anything */
1615 wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA); 1623 wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA);
1616 1624
@@ -1648,47 +1656,45 @@ static int wm8903_init(struct snd_soc_device *socdev)
1648 val |= WM8903_DAC_MUTEMODE; 1656 val |= WM8903_DAC_MUTEMODE;
1649 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); 1657 wm8903_write(codec, WM8903_DAC_DIGITAL_1, val);
1650 1658
1651 wm8903_add_controls(codec); 1659 wm8903_dai.dev = &i2c->dev;
1652 wm8903_add_widgets(codec); 1660 wm8903_codec = codec;
1653 ret = snd_soc_init_card(socdev); 1661
1654 if (ret < 0) { 1662 ret = snd_soc_register_codec(codec);
1655 dev_err(&i2c->dev, "wm8903: failed to register card\n"); 1663 if (ret != 0) {
1656 goto card_err; 1664 dev_err(&i2c->dev, "Failed to register codec: %d\n", ret);
1665 goto err;
1666 }
1667
1668 ret = snd_soc_register_dai(&wm8903_dai);
1669 if (ret != 0) {
1670 dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret);
1671 goto err_codec;
1657 } 1672 }
1658 1673
1659 return ret; 1674 return ret;
1660 1675
1661card_err: 1676err_codec:
1662 snd_soc_free_pcms(socdev); 1677 snd_soc_unregister_codec(codec);
1663 snd_soc_dapm_free(socdev); 1678err:
1664pcm_err: 1679 wm8903_codec = NULL;
1665 kfree(codec->reg_cache); 1680 kfree(wm8903);
1666 return ret; 1681 return ret;
1667} 1682}
1668 1683
1669static struct snd_soc_device *wm8903_socdev; 1684static int wm8903_i2c_remove(struct i2c_client *client)
1670
1671static int wm8903_i2c_probe(struct i2c_client *i2c,
1672 const struct i2c_device_id *id)
1673{ 1685{
1674 struct snd_soc_device *socdev = wm8903_socdev; 1686 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1675 struct snd_soc_codec *codec = socdev->codec;
1676 int ret;
1677 1687
1678 i2c_set_clientdata(i2c, codec); 1688 snd_soc_unregister_dai(&wm8903_dai);
1679 codec->control_data = i2c; 1689 snd_soc_unregister_codec(codec);
1680 1690
1681 ret = wm8903_init(socdev); 1691 wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF);
1682 if (ret < 0)
1683 dev_err(&i2c->dev, "Device initialisation failed\n");
1684 1692
1685 return ret; 1693 kfree(codec->private_data);
1686} 1694
1695 wm8903_codec = NULL;
1696 wm8903_dai.dev = NULL;
1687 1697
1688static int wm8903_i2c_remove(struct i2c_client *client)
1689{
1690 struct snd_soc_codec *codec = i2c_get_clientdata(client);
1691 kfree(codec->reg_cache);
1692 return 0; 1698 return 0;
1693} 1699}
1694 1700
@@ -1712,75 +1718,37 @@ static struct i2c_driver wm8903_i2c_driver = {
1712static int wm8903_probe(struct platform_device *pdev) 1718static int wm8903_probe(struct platform_device *pdev)
1713{ 1719{
1714 struct snd_soc_device *socdev = platform_get_drvdata(pdev); 1720 struct snd_soc_device *socdev = platform_get_drvdata(pdev);
1715 struct wm8903_setup_data *setup;
1716 struct snd_soc_codec *codec;
1717 struct wm8903_priv *wm8903;
1718 struct i2c_board_info board_info;
1719 struct i2c_adapter *adapter;
1720 struct i2c_client *i2c_client;
1721 int ret = 0; 1721 int ret = 0;
1722 1722
1723 setup = socdev->codec_data; 1723 if (!wm8903_codec) {
1724 1724 dev_err(&pdev->dev, "I2C device not yet probed\n");
1725 if (!setup->i2c_address) { 1725 goto err;
1726 dev_err(&pdev->dev, "No codec address provided\n");
1727 return -ENODEV;
1728 } 1726 }
1729 1727
1730 codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); 1728 socdev->codec = wm8903_codec;
1731 if (codec == NULL)
1732 return -ENOMEM;
1733 1729
1734 wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); 1730 /* register pcms */
1735 if (wm8903 == NULL) { 1731 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
1736 ret = -ENOMEM; 1732 if (ret < 0) {
1737 goto err_codec; 1733 dev_err(&pdev->dev, "failed to create pcms\n");
1734 goto err;
1738 } 1735 }
1739 1736
1740 codec->private_data = wm8903; 1737 wm8903_add_controls(socdev->codec);
1741 socdev->codec = codec; 1738 wm8903_add_widgets(socdev->codec);
1742 mutex_init(&codec->mutex);
1743 INIT_LIST_HEAD(&codec->dapm_widgets);
1744 INIT_LIST_HEAD(&codec->dapm_paths);
1745 1739
1746 wm8903_socdev = socdev; 1740 ret = snd_soc_init_card(socdev);
1747 1741 if (ret < 0) {
1748 codec->hw_write = (hw_write_t)i2c_master_send; 1742 dev_err(&pdev->dev, "wm8903: failed to register card\n");
1749 ret = i2c_add_driver(&wm8903_i2c_driver); 1743 goto card_err;
1750 if (ret != 0) {
1751 dev_err(&pdev->dev, "can't add i2c driver\n");
1752 goto err_priv;
1753 } else {
1754 memset(&board_info, 0, sizeof(board_info));
1755 strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE);
1756 board_info.addr = setup->i2c_address;
1757
1758 adapter = i2c_get_adapter(setup->i2c_bus);
1759 if (!adapter) {
1760 dev_err(&pdev->dev, "Can't get I2C bus %d\n",
1761 setup->i2c_bus);
1762 ret = -ENODEV;
1763 goto err_adapter;
1764 }
1765
1766 i2c_client = i2c_new_device(adapter, &board_info);
1767 i2c_put_adapter(adapter);
1768 if (i2c_client == NULL) {
1769 dev_err(&pdev->dev,
1770 "I2C driver registration failed\n");
1771 ret = -ENODEV;
1772 goto err_adapter;
1773 }
1774 } 1744 }
1775 1745
1776 return ret; 1746 return ret;
1777 1747
1778err_adapter: 1748card_err:
1779 i2c_del_driver(&wm8903_i2c_driver); 1749 snd_soc_free_pcms(socdev);
1780err_priv: 1750 snd_soc_dapm_free(socdev);
1781 kfree(codec->private_data); 1751err:
1782err_codec:
1783 kfree(codec);
1784 return ret; 1752 return ret;
1785} 1753}
1786 1754
@@ -1795,10 +1763,6 @@ static int wm8903_remove(struct platform_device *pdev)
1795 1763
1796 snd_soc_free_pcms(socdev); 1764 snd_soc_free_pcms(socdev);
1797 snd_soc_dapm_free(socdev); 1765 snd_soc_dapm_free(socdev);
1798 i2c_unregister_device(socdev->codec->control_data);
1799 i2c_del_driver(&wm8903_i2c_driver);
1800 kfree(codec->private_data);
1801 kfree(codec);
1802 1766
1803 return 0; 1767 return 0;
1804} 1768}
@@ -1813,13 +1777,13 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903);
1813 1777
1814static int __init wm8903_modinit(void) 1778static int __init wm8903_modinit(void)
1815{ 1779{
1816 return snd_soc_register_dai(&wm8903_dai); 1780 return i2c_add_driver(&wm8903_i2c_driver);
1817} 1781}
1818module_init(wm8903_modinit); 1782module_init(wm8903_modinit);
1819 1783
1820static void __exit wm8903_exit(void) 1784static void __exit wm8903_exit(void)
1821{ 1785{
1822 snd_soc_unregister_dai(&wm8903_dai); 1786 i2c_del_driver(&wm8903_i2c_driver);
1823} 1787}
1824module_exit(wm8903_exit); 1788module_exit(wm8903_exit);
1825 1789
diff --git a/sound/soc/codecs/wm8903.h b/sound/soc/codecs/wm8903.h
index cec622f2f66..0ea27e2b996 100644
--- a/sound/soc/codecs/wm8903.h
+++ b/sound/soc/codecs/wm8903.h
@@ -18,11 +18,6 @@
18extern struct snd_soc_dai wm8903_dai; 18extern struct snd_soc_dai wm8903_dai;
19extern struct snd_soc_codec_device soc_codec_dev_wm8903; 19extern struct snd_soc_codec_device soc_codec_dev_wm8903;
20 20
21struct wm8903_setup_data {
22 int i2c_bus;
23 int i2c_address;
24};
25
26#define WM8903_MCLK_DIV_2 1 21#define WM8903_MCLK_DIV_2 1
27#define WM8903_CLK_SYS 2 22#define WM8903_CLK_SYS 2
28#define WM8903_BCLK 3 23#define WM8903_BCLK 3