diff options
Diffstat (limited to 'sound/soc/codecs/wm8903.c')
-rw-r--r-- | sound/soc/codecs/wm8903.c | 268 |
1 files changed, 125 insertions, 143 deletions
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index ce40d7877605..bde74546db4a 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 | ||
36 | struct 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 */ |
50 | static u16 wm8903_reg_defaults[] = { | 37 | static 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 | ||
213 | struct 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 | |||
226 | static unsigned int wm8903_read_reg_cache(struct snd_soc_codec *codec, | 230 | static 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) | |||
360 | static void wm8903_reset(struct snd_soc_codec *codec) | 364 | static 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 |
@@ -392,6 +398,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w, | |||
392 | break; | 398 | break; |
393 | default: | 399 | default: |
394 | BUG(); | 400 | BUG(); |
401 | return -EINVAL; /* Spurious warning from some compilers */ | ||
395 | } | 402 | } |
396 | 403 | ||
397 | switch (w->shift) { | 404 | switch (w->shift) { |
@@ -403,6 +410,7 @@ static int wm8903_output_event(struct snd_soc_dapm_widget *w, | |||
403 | break; | 410 | break; |
404 | default: | 411 | default: |
405 | BUG(); | 412 | BUG(); |
413 | return -EINVAL; /* Spurious warning from some compilers */ | ||
406 | } | 414 | } |
407 | 415 | ||
408 | if (event & SND_SOC_DAPM_PRE_PMU) { | 416 | if (event & SND_SOC_DAPM_PRE_PMU) { |
@@ -773,14 +781,14 @@ static const struct snd_kcontrol_new left_output_mixer[] = { | |||
773 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), | 781 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_LEFT_MIX_0, 3, 1, 0), |
774 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), | 782 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_LEFT_MIX_0, 2, 1, 0), |
775 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 783 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), |
776 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 1, 1, 0), | 784 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_LEFT_MIX_0, 0, 1, 0), |
777 | }; | 785 | }; |
778 | 786 | ||
779 | static const struct snd_kcontrol_new right_output_mixer[] = { | 787 | static const struct snd_kcontrol_new right_output_mixer[] = { |
780 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), | 788 | SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 3, 1, 0), |
781 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), | 789 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 2, 1, 0), |
782 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 790 | SOC_DAPM_SINGLE_W("Left Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), |
783 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 1, 1, 0), | 791 | SOC_DAPM_SINGLE_W("Right Bypass Switch", WM8903_ANALOGUE_RIGHT_MIX_0, 0, 1, 0), |
784 | }; | 792 | }; |
785 | 793 | ||
786 | static const struct snd_kcontrol_new left_speaker_mixer[] = { | 794 | static const struct snd_kcontrol_new left_speaker_mixer[] = { |
@@ -788,7 +796,7 @@ SOC_DAPM_SINGLE("DACL Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 3, 1, 0), | |||
788 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), | 796 | SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 2, 1, 0), |
789 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), | 797 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, 1, 1, 0), |
790 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, | 798 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_LEFT_0, |
791 | 1, 1, 0), | 799 | 0, 1, 0), |
792 | }; | 800 | }; |
793 | 801 | ||
794 | static const struct snd_kcontrol_new right_speaker_mixer[] = { | 802 | static const struct snd_kcontrol_new right_speaker_mixer[] = { |
@@ -797,7 +805,7 @@ SOC_DAPM_SINGLE("DACR Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, 2, 1, 0), | |||
797 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 805 | SOC_DAPM_SINGLE("Left Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, |
798 | 1, 1, 0), | 806 | 1, 1, 0), |
799 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, | 807 | SOC_DAPM_SINGLE("Right Bypass Switch", WM8903_ANALOGUE_SPK_MIX_RIGHT_0, |
800 | 1, 1, 0), | 808 | 0, 1, 0), |
801 | }; | 809 | }; |
802 | 810 | ||
803 | static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { | 811 | static const struct snd_soc_dapm_widget wm8903_dapm_widgets[] = { |
@@ -989,6 +997,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
989 | 997 | ||
990 | case SND_SOC_BIAS_STANDBY: | 998 | case SND_SOC_BIAS_STANDBY: |
991 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 999 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
1000 | wm8903_write(codec, WM8903_CLOCK_RATES_2, | ||
1001 | WM8903_CLK_SYS_ENA); | ||
1002 | |||
992 | wm8903_run_sequence(codec, 0); | 1003 | wm8903_run_sequence(codec, 0); |
993 | wm8903_sync_reg_cache(codec, codec->reg_cache); | 1004 | wm8903_sync_reg_cache(codec, codec->reg_cache); |
994 | 1005 | ||
@@ -1019,6 +1030,9 @@ static int wm8903_set_bias_level(struct snd_soc_codec *codec, | |||
1019 | 1030 | ||
1020 | case SND_SOC_BIAS_OFF: | 1031 | case SND_SOC_BIAS_OFF: |
1021 | wm8903_run_sequence(codec, 32); | 1032 | wm8903_run_sequence(codec, 32); |
1033 | reg = wm8903_read(codec, WM8903_CLOCK_RATES_2); | ||
1034 | reg &= ~WM8903_CLK_SYS_ENA; | ||
1035 | wm8903_write(codec, WM8903_CLOCK_RATES_2, reg); | ||
1022 | break; | 1036 | break; |
1023 | } | 1037 | } |
1024 | 1038 | ||
@@ -1257,7 +1271,8 @@ static struct { | |||
1257 | { 0, 0 }, | 1271 | { 0, 0 }, |
1258 | }; | 1272 | }; |
1259 | 1273 | ||
1260 | static int wm8903_startup(struct snd_pcm_substream *substream) | 1274 | static int wm8903_startup(struct snd_pcm_substream *substream, |
1275 | struct snd_soc_dai *dai) | ||
1261 | { | 1276 | { |
1262 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1277 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1263 | struct snd_soc_device *socdev = rtd->socdev; | 1278 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1298,7 +1313,8 @@ static int wm8903_startup(struct snd_pcm_substream *substream) | |||
1298 | return 0; | 1313 | return 0; |
1299 | } | 1314 | } |
1300 | 1315 | ||
1301 | static void wm8903_shutdown(struct snd_pcm_substream *substream) | 1316 | static void wm8903_shutdown(struct snd_pcm_substream *substream, |
1317 | struct snd_soc_dai *dai) | ||
1302 | { | 1318 | { |
1303 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1319 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1304 | struct snd_soc_device *socdev = rtd->socdev; | 1320 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1317,7 +1333,8 @@ static void wm8903_shutdown(struct snd_pcm_substream *substream) | |||
1317 | } | 1333 | } |
1318 | 1334 | ||
1319 | static int wm8903_hw_params(struct snd_pcm_substream *substream, | 1335 | static int wm8903_hw_params(struct snd_pcm_substream *substream, |
1320 | struct snd_pcm_hw_params *params) | 1336 | struct snd_pcm_hw_params *params, |
1337 | struct snd_soc_dai *dai) | ||
1321 | { | 1338 | { |
1322 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 1339 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
1323 | struct snd_soc_device *socdev = rtd->socdev; | 1340 | struct snd_soc_device *socdev = rtd->socdev; |
@@ -1515,8 +1532,6 @@ struct snd_soc_dai wm8903_dai = { | |||
1515 | .startup = wm8903_startup, | 1532 | .startup = wm8903_startup, |
1516 | .shutdown = wm8903_shutdown, | 1533 | .shutdown = wm8903_shutdown, |
1517 | .hw_params = wm8903_hw_params, | 1534 | .hw_params = wm8903_hw_params, |
1518 | }, | ||
1519 | .dai_ops = { | ||
1520 | .digital_mute = wm8903_digital_mute, | 1535 | .digital_mute = wm8903_digital_mute, |
1521 | .set_fmt = wm8903_set_dai_fmt, | 1536 | .set_fmt = wm8903_set_dai_fmt, |
1522 | .set_sysclk = wm8903_set_dai_sysclk | 1537 | .set_sysclk = wm8903_set_dai_sysclk |
@@ -1560,39 +1575,48 @@ static int wm8903_resume(struct platform_device *pdev) | |||
1560 | return 0; | 1575 | return 0; |
1561 | } | 1576 | } |
1562 | 1577 | ||
1563 | /* | 1578 | static struct snd_soc_codec *wm8903_codec; |
1564 | * initialise the WM8903 driver | 1579 | |
1565 | * register the mixer and dsp interfaces with the kernel | 1580 | static int wm8903_i2c_probe(struct i2c_client *i2c, |
1566 | */ | 1581 | const struct i2c_device_id *id) |
1567 | static int wm8903_init(struct snd_soc_device *socdev) | ||
1568 | { | 1582 | { |
1569 | struct snd_soc_codec *codec = socdev->codec; | 1583 | struct wm8903_priv *wm8903; |
1570 | struct i2c_client *i2c = codec->control_data; | 1584 | struct snd_soc_codec *codec; |
1571 | int ret = 0; | 1585 | int ret; |
1572 | u16 val; | 1586 | u16 val; |
1573 | 1587 | ||
1574 | val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); | 1588 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); |
1575 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | 1589 | if (wm8903 == NULL) |
1576 | dev_err(&i2c->dev, | 1590 | return -ENOMEM; |
1577 | "Device with ID register %x is not a WM8903\n", val); | 1591 | |
1578 | return -ENODEV; | 1592 | codec = &wm8903->codec; |
1579 | } | ||
1580 | 1593 | ||
1594 | mutex_init(&codec->mutex); | ||
1595 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1596 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1597 | |||
1598 | codec->dev = &i2c->dev; | ||
1581 | codec->name = "WM8903"; | 1599 | codec->name = "WM8903"; |
1582 | codec->owner = THIS_MODULE; | 1600 | codec->owner = THIS_MODULE; |
1583 | codec->read = wm8903_read; | 1601 | codec->read = wm8903_read; |
1584 | codec->write = wm8903_write; | 1602 | codec->write = wm8903_write; |
1603 | codec->hw_write = (hw_write_t)i2c_master_send; | ||
1585 | codec->bias_level = SND_SOC_BIAS_OFF; | 1604 | codec->bias_level = SND_SOC_BIAS_OFF; |
1586 | codec->set_bias_level = wm8903_set_bias_level; | 1605 | codec->set_bias_level = wm8903_set_bias_level; |
1587 | codec->dai = &wm8903_dai; | 1606 | codec->dai = &wm8903_dai; |
1588 | codec->num_dai = 1; | 1607 | codec->num_dai = 1; |
1589 | codec->reg_cache_size = ARRAY_SIZE(wm8903_reg_defaults); | 1608 | codec->reg_cache_size = ARRAY_SIZE(wm8903->reg_cache); |
1590 | codec->reg_cache = kmemdup(wm8903_reg_defaults, | 1609 | codec->reg_cache = &wm8903->reg_cache[0]; |
1591 | sizeof(wm8903_reg_defaults), | 1610 | codec->private_data = wm8903; |
1592 | GFP_KERNEL); | 1611 | |
1593 | if (codec->reg_cache == NULL) { | 1612 | i2c_set_clientdata(i2c, codec); |
1594 | dev_err(&i2c->dev, "Failed to allocate register cache\n"); | 1613 | codec->control_data = i2c; |
1595 | return -ENOMEM; | 1614 | |
1615 | val = wm8903_hw_read(codec, WM8903_SW_RESET_AND_ID); | ||
1616 | if (val != wm8903_reg_defaults[WM8903_SW_RESET_AND_ID]) { | ||
1617 | dev_err(&i2c->dev, | ||
1618 | "Device with ID register %x is not a WM8903\n", val); | ||
1619 | return -ENODEV; | ||
1596 | } | 1620 | } |
1597 | 1621 | ||
1598 | val = wm8903_read(codec, WM8903_REVISION_NUMBER); | 1622 | val = wm8903_read(codec, WM8903_REVISION_NUMBER); |
@@ -1601,16 +1625,6 @@ static int wm8903_init(struct snd_soc_device *socdev) | |||
1601 | 1625 | ||
1602 | wm8903_reset(codec); | 1626 | wm8903_reset(codec); |
1603 | 1627 | ||
1604 | /* register pcms */ | ||
1605 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
1606 | if (ret < 0) { | ||
1607 | dev_err(&i2c->dev, "failed to create pcms\n"); | ||
1608 | goto pcm_err; | ||
1609 | } | ||
1610 | |||
1611 | /* SYSCLK is required for pretty much anything */ | ||
1612 | wm8903_write(codec, WM8903_CLOCK_RATES_2, WM8903_CLK_SYS_ENA); | ||
1613 | |||
1614 | /* power on device */ | 1628 | /* power on device */ |
1615 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1629 | wm8903_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1616 | 1630 | ||
@@ -1645,47 +1659,45 @@ static int wm8903_init(struct snd_soc_device *socdev) | |||
1645 | val |= WM8903_DAC_MUTEMODE; | 1659 | val |= WM8903_DAC_MUTEMODE; |
1646 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); | 1660 | wm8903_write(codec, WM8903_DAC_DIGITAL_1, val); |
1647 | 1661 | ||
1648 | wm8903_add_controls(codec); | 1662 | wm8903_dai.dev = &i2c->dev; |
1649 | wm8903_add_widgets(codec); | 1663 | wm8903_codec = codec; |
1650 | ret = snd_soc_register_card(socdev); | 1664 | |
1651 | if (ret < 0) { | 1665 | ret = snd_soc_register_codec(codec); |
1652 | dev_err(&i2c->dev, "wm8903: failed to register card\n"); | 1666 | if (ret != 0) { |
1653 | goto card_err; | 1667 | dev_err(&i2c->dev, "Failed to register codec: %d\n", ret); |
1668 | goto err; | ||
1669 | } | ||
1670 | |||
1671 | ret = snd_soc_register_dai(&wm8903_dai); | ||
1672 | if (ret != 0) { | ||
1673 | dev_err(&i2c->dev, "Failed to register DAI: %d\n", ret); | ||
1674 | goto err_codec; | ||
1654 | } | 1675 | } |
1655 | 1676 | ||
1656 | return ret; | 1677 | return ret; |
1657 | 1678 | ||
1658 | card_err: | 1679 | err_codec: |
1659 | snd_soc_free_pcms(socdev); | 1680 | snd_soc_unregister_codec(codec); |
1660 | snd_soc_dapm_free(socdev); | 1681 | err: |
1661 | pcm_err: | 1682 | wm8903_codec = NULL; |
1662 | kfree(codec->reg_cache); | 1683 | kfree(wm8903); |
1663 | return ret; | 1684 | return ret; |
1664 | } | 1685 | } |
1665 | 1686 | ||
1666 | static struct snd_soc_device *wm8903_socdev; | 1687 | static int wm8903_i2c_remove(struct i2c_client *client) |
1667 | |||
1668 | static int wm8903_i2c_probe(struct i2c_client *i2c, | ||
1669 | const struct i2c_device_id *id) | ||
1670 | { | 1688 | { |
1671 | struct snd_soc_device *socdev = wm8903_socdev; | 1689 | struct snd_soc_codec *codec = i2c_get_clientdata(client); |
1672 | struct snd_soc_codec *codec = socdev->codec; | ||
1673 | int ret; | ||
1674 | 1690 | ||
1675 | i2c_set_clientdata(i2c, codec); | 1691 | snd_soc_unregister_dai(&wm8903_dai); |
1676 | codec->control_data = i2c; | 1692 | snd_soc_unregister_codec(codec); |
1677 | 1693 | ||
1678 | ret = wm8903_init(socdev); | 1694 | wm8903_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1679 | if (ret < 0) | ||
1680 | dev_err(&i2c->dev, "Device initialisation failed\n"); | ||
1681 | 1695 | ||
1682 | return ret; | 1696 | kfree(codec->private_data); |
1683 | } | 1697 | |
1698 | wm8903_codec = NULL; | ||
1699 | wm8903_dai.dev = NULL; | ||
1684 | 1700 | ||
1685 | static int wm8903_i2c_remove(struct i2c_client *client) | ||
1686 | { | ||
1687 | struct snd_soc_codec *codec = i2c_get_clientdata(client); | ||
1688 | kfree(codec->reg_cache); | ||
1689 | return 0; | 1701 | return 0; |
1690 | } | 1702 | } |
1691 | 1703 | ||
@@ -1709,75 +1721,37 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
1709 | static int wm8903_probe(struct platform_device *pdev) | 1721 | static int wm8903_probe(struct platform_device *pdev) |
1710 | { | 1722 | { |
1711 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1723 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
1712 | struct wm8903_setup_data *setup; | ||
1713 | struct snd_soc_codec *codec; | ||
1714 | struct wm8903_priv *wm8903; | ||
1715 | struct i2c_board_info board_info; | ||
1716 | struct i2c_adapter *adapter; | ||
1717 | struct i2c_client *i2c_client; | ||
1718 | int ret = 0; | 1724 | int ret = 0; |
1719 | 1725 | ||
1720 | setup = socdev->codec_data; | 1726 | if (!wm8903_codec) { |
1721 | 1727 | dev_err(&pdev->dev, "I2C device not yet probed\n"); | |
1722 | if (!setup->i2c_address) { | 1728 | goto err; |
1723 | dev_err(&pdev->dev, "No codec address provided\n"); | ||
1724 | return -ENODEV; | ||
1725 | } | 1729 | } |
1726 | 1730 | ||
1727 | codec = kzalloc(sizeof(struct snd_soc_codec), GFP_KERNEL); | 1731 | socdev->codec = wm8903_codec; |
1728 | if (codec == NULL) | ||
1729 | return -ENOMEM; | ||
1730 | 1732 | ||
1731 | wm8903 = kzalloc(sizeof(struct wm8903_priv), GFP_KERNEL); | 1733 | /* register pcms */ |
1732 | if (wm8903 == NULL) { | 1734 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1733 | ret = -ENOMEM; | 1735 | if (ret < 0) { |
1734 | goto err_codec; | 1736 | dev_err(&pdev->dev, "failed to create pcms\n"); |
1737 | goto err; | ||
1735 | } | 1738 | } |
1736 | 1739 | ||
1737 | codec->private_data = wm8903; | 1740 | wm8903_add_controls(socdev->codec); |
1738 | socdev->codec = codec; | 1741 | wm8903_add_widgets(socdev->codec); |
1739 | mutex_init(&codec->mutex); | ||
1740 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
1741 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
1742 | |||
1743 | wm8903_socdev = socdev; | ||
1744 | 1742 | ||
1745 | codec->hw_write = (hw_write_t)i2c_master_send; | 1743 | ret = snd_soc_init_card(socdev); |
1746 | ret = i2c_add_driver(&wm8903_i2c_driver); | 1744 | if (ret < 0) { |
1747 | if (ret != 0) { | 1745 | dev_err(&pdev->dev, "wm8903: failed to register card\n"); |
1748 | dev_err(&pdev->dev, "can't add i2c driver\n"); | 1746 | goto card_err; |
1749 | goto err_priv; | ||
1750 | } else { | ||
1751 | memset(&board_info, 0, sizeof(board_info)); | ||
1752 | strlcpy(board_info.type, "wm8903", I2C_NAME_SIZE); | ||
1753 | board_info.addr = setup->i2c_address; | ||
1754 | |||
1755 | adapter = i2c_get_adapter(setup->i2c_bus); | ||
1756 | if (!adapter) { | ||
1757 | dev_err(&pdev->dev, "Can't get I2C bus %d\n", | ||
1758 | setup->i2c_bus); | ||
1759 | ret = -ENODEV; | ||
1760 | goto err_adapter; | ||
1761 | } | ||
1762 | |||
1763 | i2c_client = i2c_new_device(adapter, &board_info); | ||
1764 | i2c_put_adapter(adapter); | ||
1765 | if (i2c_client == NULL) { | ||
1766 | dev_err(&pdev->dev, | ||
1767 | "I2C driver registration failed\n"); | ||
1768 | ret = -ENODEV; | ||
1769 | goto err_adapter; | ||
1770 | } | ||
1771 | } | 1747 | } |
1772 | 1748 | ||
1773 | return ret; | 1749 | return ret; |
1774 | 1750 | ||
1775 | err_adapter: | 1751 | card_err: |
1776 | i2c_del_driver(&wm8903_i2c_driver); | 1752 | snd_soc_free_pcms(socdev); |
1777 | err_priv: | 1753 | snd_soc_dapm_free(socdev); |
1778 | kfree(codec->private_data); | 1754 | err: |
1779 | err_codec: | ||
1780 | kfree(codec); | ||
1781 | return ret; | 1755 | return ret; |
1782 | } | 1756 | } |
1783 | 1757 | ||
@@ -1792,10 +1766,6 @@ static int wm8903_remove(struct platform_device *pdev) | |||
1792 | 1766 | ||
1793 | snd_soc_free_pcms(socdev); | 1767 | snd_soc_free_pcms(socdev); |
1794 | snd_soc_dapm_free(socdev); | 1768 | snd_soc_dapm_free(socdev); |
1795 | i2c_unregister_device(socdev->codec->control_data); | ||
1796 | i2c_del_driver(&wm8903_i2c_driver); | ||
1797 | kfree(codec->private_data); | ||
1798 | kfree(codec); | ||
1799 | 1769 | ||
1800 | return 0; | 1770 | return 0; |
1801 | } | 1771 | } |
@@ -1808,6 +1778,18 @@ struct snd_soc_codec_device soc_codec_dev_wm8903 = { | |||
1808 | }; | 1778 | }; |
1809 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); | 1779 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8903); |
1810 | 1780 | ||
1781 | static int __init wm8903_modinit(void) | ||
1782 | { | ||
1783 | return i2c_add_driver(&wm8903_i2c_driver); | ||
1784 | } | ||
1785 | module_init(wm8903_modinit); | ||
1786 | |||
1787 | static void __exit wm8903_exit(void) | ||
1788 | { | ||
1789 | i2c_del_driver(&wm8903_i2c_driver); | ||
1790 | } | ||
1791 | module_exit(wm8903_exit); | ||
1792 | |||
1811 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 1793 | MODULE_DESCRIPTION("ASoC WM8903 driver"); |
1812 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 1794 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); |
1813 | MODULE_LICENSE("GPL"); | 1795 | MODULE_LICENSE("GPL"); |