diff options
Diffstat (limited to 'sound/soc/codecs/wm8994.c')
-rw-r--r-- | sound/soc/codecs/wm8994.c | 230 |
1 files changed, 77 insertions, 153 deletions
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index a87046a96f2a..7823f92413f3 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -36,9 +36,6 @@ | |||
36 | #include "wm8994.h" | 36 | #include "wm8994.h" |
37 | #include "wm_hubs.h" | 37 | #include "wm_hubs.h" |
38 | 38 | ||
39 | static struct snd_soc_codec *wm8994_codec; | ||
40 | struct snd_soc_codec_device soc_codec_dev_wm8994; | ||
41 | |||
42 | struct fll_config { | 39 | struct fll_config { |
43 | int src; | 40 | int src; |
44 | int in; | 41 | int in; |
@@ -71,7 +68,9 @@ struct wm8994_micdet { | |||
71 | /* codec private data */ | 68 | /* codec private data */ |
72 | struct wm8994_priv { | 69 | struct wm8994_priv { |
73 | struct wm_hubs_data hubs; | 70 | struct wm_hubs_data hubs; |
74 | struct snd_soc_codec codec; | 71 | enum snd_soc_control_type control_type; |
72 | void *control_data; | ||
73 | struct snd_soc_codec *codec; | ||
75 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; | 74 | u16 reg_cache[WM8994_REG_CACHE_SIZE + 1]; |
76 | int sysclk[2]; | 75 | int sysclk[2]; |
77 | int sysclk_rate[2]; | 76 | int sysclk_rate[2]; |
@@ -1901,8 +1900,6 @@ static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | |||
1901 | return snd_soc_put_volsw(kcontrol, ucontrol); | 1900 | return snd_soc_put_volsw(kcontrol, ucontrol); |
1902 | } | 1901 | } |
1903 | 1902 | ||
1904 | |||
1905 | |||
1906 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) | 1903 | static void wm8994_set_drc(struct snd_soc_codec *codec, int drc) |
1907 | { | 1904 | { |
1908 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1905 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -1941,7 +1938,7 @@ static int wm8994_put_drc_enum(struct snd_kcontrol *kcontrol, | |||
1941 | struct snd_ctl_elem_value *ucontrol) | 1938 | struct snd_ctl_elem_value *ucontrol) |
1942 | { | 1939 | { |
1943 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 1940 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
1944 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1941 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1945 | struct wm8994_pdata *pdata = wm8994->pdata; | 1942 | struct wm8994_pdata *pdata = wm8994->pdata; |
1946 | int drc = wm8994_get_drc(kcontrol->id.name); | 1943 | int drc = wm8994_get_drc(kcontrol->id.name); |
1947 | int value = ucontrol->value.integer.value[0]; | 1944 | int value = ucontrol->value.integer.value[0]; |
@@ -2044,7 +2041,7 @@ static int wm8994_put_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2044 | struct snd_ctl_elem_value *ucontrol) | 2041 | struct snd_ctl_elem_value *ucontrol) |
2045 | { | 2042 | { |
2046 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2043 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2047 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2044 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2048 | struct wm8994_pdata *pdata = wm8994->pdata; | 2045 | struct wm8994_pdata *pdata = wm8994->pdata; |
2049 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2046 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2050 | int value = ucontrol->value.integer.value[0]; | 2047 | int value = ucontrol->value.integer.value[0]; |
@@ -2066,7 +2063,7 @@ static int wm8994_get_retune_mobile_enum(struct snd_kcontrol *kcontrol, | |||
2066 | struct snd_ctl_elem_value *ucontrol) | 2063 | struct snd_ctl_elem_value *ucontrol) |
2067 | { | 2064 | { |
2068 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | 2065 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); |
2069 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2066 | struct wm8994_priv *wm8994 =snd_soc_codec_get_drvdata(codec); |
2070 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); | 2067 | int block = wm8994_get_retune_mobile_block(kcontrol->id.name); |
2071 | 2068 | ||
2072 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; | 2069 | ucontrol->value.enumerated.item[0] = wm8994->retune_mobile_cfg[block]; |
@@ -2880,10 +2877,9 @@ static int wm8994_get_fll_config(struct fll_div *fll, | |||
2880 | return 0; | 2877 | return 0; |
2881 | } | 2878 | } |
2882 | 2879 | ||
2883 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | 2880 | static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, |
2884 | unsigned int freq_in, unsigned int freq_out) | 2881 | unsigned int freq_in, unsigned int freq_out) |
2885 | { | 2882 | { |
2886 | struct snd_soc_codec *codec = dai->codec; | ||
2887 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 2883 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
2888 | int reg_offset, ret; | 2884 | int reg_offset, ret; |
2889 | struct fll_div fll; | 2885 | struct fll_div fll; |
@@ -2994,8 +2990,15 @@ static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | |||
2994 | return 0; | 2990 | return 0; |
2995 | } | 2991 | } |
2996 | 2992 | ||
2993 | |||
2997 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; | 2994 | static int opclk_divs[] = { 10, 20, 30, 40, 55, 60, 80, 120, 160 }; |
2998 | 2995 | ||
2996 | static int wm8994_set_fll(struct snd_soc_dai *dai, int id, int src, | ||
2997 | unsigned int freq_in, unsigned int freq_out) | ||
2998 | { | ||
2999 | return _wm8994_set_fll(dai->codec, id, src, freq_in, freq_out); | ||
3000 | } | ||
3001 | |||
2999 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, | 3002 | static int wm8994_set_dai_sysclk(struct snd_soc_dai *dai, |
3000 | int clk_id, unsigned int freq, int dir) | 3003 | int clk_id, unsigned int freq, int dir) |
3001 | { | 3004 | { |
@@ -3507,10 +3510,9 @@ static struct snd_soc_dai_ops wm8994_aif3_dai_ops = { | |||
3507 | .set_tristate = wm8994_set_tristate, | 3510 | .set_tristate = wm8994_set_tristate, |
3508 | }; | 3511 | }; |
3509 | 3512 | ||
3510 | struct snd_soc_dai wm8994_dai[] = { | 3513 | static struct snd_soc_dai_driver wm8994_dai[] = { |
3511 | { | 3514 | { |
3512 | .name = "WM8994 AIF1", | 3515 | .name = "wm8994-aif1", |
3513 | .id = 1, | ||
3514 | .playback = { | 3516 | .playback = { |
3515 | .stream_name = "AIF1 Playback", | 3517 | .stream_name = "AIF1 Playback", |
3516 | .channels_min = 2, | 3518 | .channels_min = 2, |
@@ -3528,8 +3530,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3528 | .ops = &wm8994_aif1_dai_ops, | 3530 | .ops = &wm8994_aif1_dai_ops, |
3529 | }, | 3531 | }, |
3530 | { | 3532 | { |
3531 | .name = "WM8994 AIF2", | 3533 | .name = "wm8994-aif2", |
3532 | .id = 2, | ||
3533 | .playback = { | 3534 | .playback = { |
3534 | .stream_name = "AIF2 Playback", | 3535 | .stream_name = "AIF2 Playback", |
3535 | .channels_min = 2, | 3536 | .channels_min = 2, |
@@ -3547,8 +3548,7 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3547 | .ops = &wm8994_aif2_dai_ops, | 3548 | .ops = &wm8994_aif2_dai_ops, |
3548 | }, | 3549 | }, |
3549 | { | 3550 | { |
3550 | .name = "WM8994 AIF3", | 3551 | .name = "wm8994-aif3", |
3551 | .id = 3, | ||
3552 | .playback = { | 3552 | .playback = { |
3553 | .stream_name = "AIF3 Playback", | 3553 | .stream_name = "AIF3 Playback", |
3554 | .channels_min = 2, | 3554 | .channels_min = 2, |
@@ -3566,20 +3566,17 @@ struct snd_soc_dai wm8994_dai[] = { | |||
3566 | .ops = &wm8994_aif3_dai_ops, | 3566 | .ops = &wm8994_aif3_dai_ops, |
3567 | } | 3567 | } |
3568 | }; | 3568 | }; |
3569 | EXPORT_SYMBOL_GPL(wm8994_dai); | ||
3570 | 3569 | ||
3571 | #ifdef CONFIG_PM | 3570 | #ifdef CONFIG_PM |
3572 | static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | 3571 | static int wm8994_suspend(struct snd_soc_codec *codec, pm_message_t state) |
3573 | { | 3572 | { |
3574 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3575 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3576 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3573 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3577 | int i, ret; | 3574 | int i, ret; |
3578 | 3575 | ||
3579 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { | 3576 | for (i = 0; i < ARRAY_SIZE(wm8994->fll); i++) { |
3580 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], | 3577 | memcpy(&wm8994->fll_suspend[i], &wm8994->fll[i], |
3581 | sizeof(struct fll_config)); | 3578 | sizeof(struct fll_config)); |
3582 | ret = wm8994_set_fll(&codec->dai[0], i + 1, 0, 0, 0); | 3579 | ret = _wm8994_set_fll(codec, i + 1, 0, 0, 0); |
3583 | if (ret < 0) | 3580 | if (ret < 0) |
3584 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", | 3581 | dev_warn(codec->dev, "Failed to stop FLL%d: %d\n", |
3585 | i + 1, ret); | 3582 | i + 1, ret); |
@@ -3590,10 +3587,8 @@ static int wm8994_suspend(struct platform_device *pdev, pm_message_t state) | |||
3590 | return 0; | 3587 | return 0; |
3591 | } | 3588 | } |
3592 | 3589 | ||
3593 | static int wm8994_resume(struct platform_device *pdev) | 3590 | static int wm8994_resume(struct snd_soc_codec *codec) |
3594 | { | 3591 | { |
3595 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3596 | struct snd_soc_codec *codec = socdev->card->codec; | ||
3597 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 3592 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
3598 | u16 *reg_cache = codec->reg_cache; | 3593 | u16 *reg_cache = codec->reg_cache; |
3599 | int i, ret; | 3594 | int i, ret; |
@@ -3622,7 +3617,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3622 | if (!wm8994->fll_suspend[i].out) | 3617 | if (!wm8994->fll_suspend[i].out) |
3623 | continue; | 3618 | continue; |
3624 | 3619 | ||
3625 | ret = wm8994_set_fll(&codec->dai[0], i + 1, | 3620 | ret = _wm8994_set_fll(codec, i + 1, |
3626 | wm8994->fll_suspend[i].src, | 3621 | wm8994->fll_suspend[i].src, |
3627 | wm8994->fll_suspend[i].in, | 3622 | wm8994->fll_suspend[i].in, |
3628 | wm8994->fll_suspend[i].out); | 3623 | wm8994->fll_suspend[i].out); |
@@ -3640,7 +3635,7 @@ static int wm8994_resume(struct platform_device *pdev) | |||
3640 | 3635 | ||
3641 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3636 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3642 | { | 3637 | { |
3643 | struct snd_soc_codec *codec = &wm8994->codec; | 3638 | struct snd_soc_codec *codec = wm8994->codec; |
3644 | struct wm8994_pdata *pdata = wm8994->pdata; | 3639 | struct wm8994_pdata *pdata = wm8994->pdata; |
3645 | struct snd_kcontrol_new controls[] = { | 3640 | struct snd_kcontrol_new controls[] = { |
3646 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3641 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
@@ -3698,16 +3693,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3698 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3693 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
3699 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3694 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3700 | 3695 | ||
3701 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3696 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3702 | ARRAY_SIZE(controls)); | 3697 | ARRAY_SIZE(controls)); |
3703 | if (ret != 0) | 3698 | if (ret != 0) |
3704 | dev_err(wm8994->codec.dev, | 3699 | dev_err(wm8994->codec->dev, |
3705 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3700 | "Failed to add ReTune Mobile controls: %d\n", ret); |
3706 | } | 3701 | } |
3707 | 3702 | ||
3708 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3703 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3709 | { | 3704 | { |
3710 | struct snd_soc_codec *codec = &wm8994->codec; | 3705 | struct snd_soc_codec *codec = wm8994->codec; |
3711 | struct wm8994_pdata *pdata = wm8994->pdata; | 3706 | struct wm8994_pdata *pdata = wm8994->pdata; |
3712 | int ret, i; | 3707 | int ret, i; |
3713 | 3708 | ||
@@ -3739,7 +3734,7 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3739 | wm8994->drc_texts = kmalloc(sizeof(char *) | 3734 | wm8994->drc_texts = kmalloc(sizeof(char *) |
3740 | * pdata->num_drc_cfgs, GFP_KERNEL); | 3735 | * pdata->num_drc_cfgs, GFP_KERNEL); |
3741 | if (!wm8994->drc_texts) { | 3736 | if (!wm8994->drc_texts) { |
3742 | dev_err(wm8994->codec.dev, | 3737 | dev_err(wm8994->codec->dev, |
3743 | "Failed to allocate %d DRC config texts\n", | 3738 | "Failed to allocate %d DRC config texts\n", |
3744 | pdata->num_drc_cfgs); | 3739 | pdata->num_drc_cfgs); |
3745 | return; | 3740 | return; |
@@ -3751,10 +3746,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3751 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3746 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
3752 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3747 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3753 | 3748 | ||
3754 | ret = snd_soc_add_controls(&wm8994->codec, controls, | 3749 | ret = snd_soc_add_controls(wm8994->codec, controls, |
3755 | ARRAY_SIZE(controls)); | 3750 | ARRAY_SIZE(controls)); |
3756 | if (ret != 0) | 3751 | if (ret != 0) |
3757 | dev_err(wm8994->codec.dev, | 3752 | dev_err(wm8994->codec->dev, |
3758 | "Failed to add DRC mode controls: %d\n", ret); | 3753 | "Failed to add DRC mode controls: %d\n", ret); |
3759 | 3754 | ||
3760 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3755 | for (i = 0; i < WM8994_NUM_DRC; i++) |
@@ -3767,62 +3762,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3767 | if (pdata->num_retune_mobile_cfgs) | 3762 | if (pdata->num_retune_mobile_cfgs) |
3768 | wm8994_handle_retune_mobile_pdata(wm8994); | 3763 | wm8994_handle_retune_mobile_pdata(wm8994); |
3769 | else | 3764 | else |
3770 | snd_soc_add_controls(&wm8994->codec, wm8994_eq_controls, | 3765 | snd_soc_add_controls(wm8994->codec, wm8994_eq_controls, |
3771 | ARRAY_SIZE(wm8994_eq_controls)); | 3766 | ARRAY_SIZE(wm8994_eq_controls)); |
3772 | } | 3767 | } |
3773 | 3768 | ||
3774 | static int wm8994_probe(struct platform_device *pdev) | ||
3775 | { | ||
3776 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3777 | struct snd_soc_codec *codec; | ||
3778 | int ret = 0; | ||
3779 | |||
3780 | if (wm8994_codec == NULL) { | ||
3781 | dev_err(&pdev->dev, "Codec device not registered\n"); | ||
3782 | return -ENODEV; | ||
3783 | } | ||
3784 | |||
3785 | socdev->card->codec = wm8994_codec; | ||
3786 | codec = wm8994_codec; | ||
3787 | |||
3788 | /* register pcms */ | ||
3789 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | ||
3790 | if (ret < 0) { | ||
3791 | dev_err(codec->dev, "failed to create pcms: %d\n", ret); | ||
3792 | return ret; | ||
3793 | } | ||
3794 | |||
3795 | wm8994_handle_pdata(snd_soc_codec_get_drvdata(codec)); | ||
3796 | |||
3797 | wm_hubs_add_analogue_controls(codec); | ||
3798 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3799 | ARRAY_SIZE(wm8994_snd_controls)); | ||
3800 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
3801 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
3802 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
3803 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
3804 | |||
3805 | return 0; | ||
3806 | } | ||
3807 | |||
3808 | static int wm8994_remove(struct platform_device *pdev) | ||
3809 | { | ||
3810 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
3811 | |||
3812 | snd_soc_free_pcms(socdev); | ||
3813 | snd_soc_dapm_free(socdev); | ||
3814 | |||
3815 | return 0; | ||
3816 | } | ||
3817 | |||
3818 | struct snd_soc_codec_device soc_codec_dev_wm8994 = { | ||
3819 | .probe = wm8994_probe, | ||
3820 | .remove = wm8994_remove, | ||
3821 | .suspend = wm8994_suspend, | ||
3822 | .resume = wm8994_resume, | ||
3823 | }; | ||
3824 | EXPORT_SYMBOL_GPL(soc_codec_dev_wm8994); | ||
3825 | |||
3826 | /** | 3769 | /** |
3827 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ | 3770 | * wm8994_mic_detect - Enable microphone detection via the WM8994 IRQ |
3828 | * | 3771 | * |
@@ -3881,7 +3824,7 @@ EXPORT_SYMBOL_GPL(wm8994_mic_detect); | |||
3881 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3824 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3882 | { | 3825 | { |
3883 | struct wm8994_priv *priv = data; | 3826 | struct wm8994_priv *priv = data; |
3884 | struct snd_soc_codec *codec = &priv->codec; | 3827 | struct snd_soc_codec *codec = priv->codec; |
3885 | int reg; | 3828 | int reg; |
3886 | int report; | 3829 | int report; |
3887 | 3830 | ||
@@ -3913,47 +3856,20 @@ static irqreturn_t wm8994_mic_irq(int irq, void *data) | |||
3913 | return IRQ_HANDLED; | 3856 | return IRQ_HANDLED; |
3914 | } | 3857 | } |
3915 | 3858 | ||
3916 | static int wm8994_codec_probe(struct platform_device *pdev) | 3859 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
3917 | { | 3860 | { |
3918 | int ret; | ||
3919 | struct wm8994_priv *wm8994; | 3861 | struct wm8994_priv *wm8994; |
3920 | struct snd_soc_codec *codec; | 3862 | int ret, i, rev; |
3921 | int i; | ||
3922 | u16 rev; | ||
3923 | 3863 | ||
3924 | if (wm8994_codec) { | 3864 | codec->control_data = dev_get_drvdata(codec->dev->parent); |
3925 | dev_err(&pdev->dev, "Another WM8994 is registered\n"); | ||
3926 | return -EINVAL; | ||
3927 | } | ||
3928 | 3865 | ||
3929 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); | 3866 | wm8994 = kzalloc(sizeof(struct wm8994_priv), GFP_KERNEL); |
3930 | if (!wm8994) { | 3867 | if (wm8994 == NULL) |
3931 | dev_err(&pdev->dev, "Failed to allocate private data\n"); | ||
3932 | return -ENOMEM; | 3868 | return -ENOMEM; |
3933 | } | ||
3934 | |||
3935 | codec = &wm8994->codec; | ||
3936 | |||
3937 | mutex_init(&codec->mutex); | ||
3938 | INIT_LIST_HEAD(&codec->dapm_widgets); | ||
3939 | INIT_LIST_HEAD(&codec->dapm_paths); | ||
3940 | |||
3941 | snd_soc_codec_set_drvdata(codec, wm8994); | 3869 | snd_soc_codec_set_drvdata(codec, wm8994); |
3942 | codec->control_data = dev_get_drvdata(pdev->dev.parent); | 3870 | |
3943 | codec->name = "WM8994"; | 3871 | wm8994->pdata = dev_get_platdata(codec->dev->parent); |
3944 | codec->owner = THIS_MODULE; | 3872 | wm8994->codec = codec; |
3945 | codec->read = wm8994_read; | ||
3946 | codec->write = wm8994_write; | ||
3947 | codec->readable_register = wm8994_readable; | ||
3948 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3949 | codec->set_bias_level = wm8994_set_bias_level; | ||
3950 | codec->dai = &wm8994_dai[0]; | ||
3951 | codec->num_dai = 3; | ||
3952 | codec->reg_cache_size = WM8994_MAX_REGISTER; | ||
3953 | codec->reg_cache = &wm8994->reg_cache; | ||
3954 | codec->dev = &pdev->dev; | ||
3955 | |||
3956 | wm8994->pdata = pdev->dev.parent->platform_data; | ||
3957 | 3873 | ||
3958 | /* Fill the cache with physical values we inherited; don't reset */ | 3874 | /* Fill the cache with physical values we inherited; don't reset */ |
3959 | ret = wm8994_bulk_read(codec->control_data, 0, | 3875 | ret = wm8994_bulk_read(codec->control_data, 0, |
@@ -3989,25 +3905,25 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
3989 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, | 3905 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_DET, |
3990 | wm8994_mic_irq, "Mic 1 detect", wm8994); | 3906 | wm8994_mic_irq, "Mic 1 detect", wm8994); |
3991 | if (ret != 0) | 3907 | if (ret != 0) |
3992 | dev_warn(&pdev->dev, | 3908 | dev_warn(codec->dev, |
3993 | "Failed to request Mic1 detect IRQ: %d\n", ret); | 3909 | "Failed to request Mic1 detect IRQ: %d\n", ret); |
3994 | 3910 | ||
3995 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, | 3911 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, |
3996 | wm8994_mic_irq, "Mic 1 short", wm8994); | 3912 | wm8994_mic_irq, "Mic 1 short", wm8994); |
3997 | if (ret != 0) | 3913 | if (ret != 0) |
3998 | dev_warn(&pdev->dev, | 3914 | dev_warn(codec->dev, |
3999 | "Failed to request Mic1 short IRQ: %d\n", ret); | 3915 | "Failed to request Mic1 short IRQ: %d\n", ret); |
4000 | 3916 | ||
4001 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, | 3917 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_DET, |
4002 | wm8994_mic_irq, "Mic 2 detect", wm8994); | 3918 | wm8994_mic_irq, "Mic 2 detect", wm8994); |
4003 | if (ret != 0) | 3919 | if (ret != 0) |
4004 | dev_warn(&pdev->dev, | 3920 | dev_warn(codec->dev, |
4005 | "Failed to request Mic2 detect IRQ: %d\n", ret); | 3921 | "Failed to request Mic2 detect IRQ: %d\n", ret); |
4006 | 3922 | ||
4007 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, | 3923 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, |
4008 | wm8994_mic_irq, "Mic 2 short", wm8994); | 3924 | wm8994_mic_irq, "Mic 2 short", wm8994); |
4009 | if (ret != 0) | 3925 | if (ret != 0) |
4010 | dev_warn(&pdev->dev, | 3926 | dev_warn(codec->dev, |
4011 | "Failed to request Mic2 short IRQ: %d\n", ret); | 3927 | "Failed to request Mic2 short IRQ: %d\n", ret); |
4012 | 3928 | ||
4013 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be | 3929 | /* Remember if AIFnLRCLK is configured as a GPIO. This should be |
@@ -4038,13 +3954,8 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4038 | wm8994->lrclk_shared[1] = 0; | 3954 | wm8994->lrclk_shared[1] = 0; |
4039 | } | 3955 | } |
4040 | 3956 | ||
4041 | for (i = 0; i < ARRAY_SIZE(wm8994_dai); i++) | ||
4042 | wm8994_dai[i].dev = codec->dev; | ||
4043 | |||
4044 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 3957 | wm8994_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
4045 | 3958 | ||
4046 | wm8994_codec = codec; | ||
4047 | |||
4048 | /* Latch volume updates (right only; we always do left then right). */ | 3959 | /* Latch volume updates (right only; we always do left then right). */ |
4049 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, | 3960 | snd_soc_update_bits(codec, WM8994_AIF1_DAC1_RIGHT_VOLUME, |
4050 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); | 3961 | WM8994_AIF1DAC1_VU, WM8994_AIF1DAC1_VU); |
@@ -4081,24 +3992,18 @@ static int wm8994_codec_probe(struct platform_device *pdev) | |||
4081 | 3992 | ||
4082 | wm8994_update_class_w(codec); | 3993 | wm8994_update_class_w(codec); |
4083 | 3994 | ||
4084 | ret = snd_soc_register_codec(codec); | 3995 | wm8994_handle_pdata(wm8994); |
4085 | if (ret != 0) { | ||
4086 | dev_err(codec->dev, "Failed to register codec: %d\n", ret); | ||
4087 | goto err_irq; | ||
4088 | } | ||
4089 | |||
4090 | ret = snd_soc_register_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4091 | if (ret != 0) { | ||
4092 | dev_err(codec->dev, "Failed to register DAIs: %d\n", ret); | ||
4093 | goto err_codec; | ||
4094 | } | ||
4095 | 3996 | ||
4096 | platform_set_drvdata(pdev, wm8994); | 3997 | wm_hubs_add_analogue_controls(codec); |
3998 | snd_soc_add_controls(codec, wm8994_snd_controls, | ||
3999 | ARRAY_SIZE(wm8994_snd_controls)); | ||
4000 | snd_soc_dapm_new_controls(codec, wm8994_dapm_widgets, | ||
4001 | ARRAY_SIZE(wm8994_dapm_widgets)); | ||
4002 | wm_hubs_add_analogue_routes(codec, 0, 0); | ||
4003 | snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | ||
4097 | 4004 | ||
4098 | return 0; | 4005 | return 0; |
4099 | 4006 | ||
4100 | err_codec: | ||
4101 | snd_soc_unregister_codec(codec); | ||
4102 | err_irq: | 4007 | err_irq: |
4103 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4008 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4104 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4009 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
@@ -4109,31 +4014,50 @@ err: | |||
4109 | return ret; | 4014 | return ret; |
4110 | } | 4015 | } |
4111 | 4016 | ||
4112 | static int __devexit wm8994_codec_remove(struct platform_device *pdev) | 4017 | static int wm8994_codec_remove(struct snd_soc_codec *codec) |
4113 | { | 4018 | { |
4114 | struct wm8994_priv *wm8994 = platform_get_drvdata(pdev); | 4019 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
4115 | struct snd_soc_codec *codec = &wm8994->codec; | ||
4116 | 4020 | ||
4117 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); | 4021 | wm8994_set_bias_level(codec, SND_SOC_BIAS_OFF); |
4118 | snd_soc_unregister_dais(wm8994_dai, ARRAY_SIZE(wm8994_dai)); | 4022 | |
4119 | snd_soc_unregister_codec(&wm8994->codec); | ||
4120 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); | 4023 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_SHRT, wm8994); |
4121 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); | 4024 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC2_DET, wm8994); |
4122 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); | 4025 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_SHRT, wm8994); |
4123 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); | 4026 | wm8994_free_irq(codec->control_data, WM8994_IRQ_MIC1_DET, wm8994); |
4124 | kfree(wm8994); | 4027 | kfree(wm8994); |
4125 | wm8994_codec = NULL; | ||
4126 | 4028 | ||
4127 | return 0; | 4029 | return 0; |
4128 | } | 4030 | } |
4129 | 4031 | ||
4032 | static struct snd_soc_codec_driver soc_codec_dev_wm8994 = { | ||
4033 | .probe = wm8994_codec_probe, | ||
4034 | .remove = wm8994_codec_remove, | ||
4035 | .suspend = wm8994_suspend, | ||
4036 | .resume = wm8994_resume, | ||
4037 | .read = wm8994_read, | ||
4038 | .write = wm8994_write, | ||
4039 | .set_bias_level = wm8994_set_bias_level, | ||
4040 | }; | ||
4041 | |||
4042 | static int __devinit wm8994_probe(struct platform_device *pdev) | ||
4043 | { | ||
4044 | return snd_soc_register_codec(&pdev->dev, &soc_codec_dev_wm8994, | ||
4045 | wm8994_dai, ARRAY_SIZE(wm8994_dai)); | ||
4046 | } | ||
4047 | |||
4048 | static int __devexit wm8994_remove(struct platform_device *pdev) | ||
4049 | { | ||
4050 | snd_soc_unregister_codec(&pdev->dev); | ||
4051 | return 0; | ||
4052 | } | ||
4053 | |||
4130 | static struct platform_driver wm8994_codec_driver = { | 4054 | static struct platform_driver wm8994_codec_driver = { |
4131 | .driver = { | 4055 | .driver = { |
4132 | .name = "wm8994-codec", | 4056 | .name = "wm8994-codec", |
4133 | .owner = THIS_MODULE, | 4057 | .owner = THIS_MODULE, |
4134 | }, | 4058 | }, |
4135 | .probe = wm8994_codec_probe, | 4059 | .probe = wm8994_probe, |
4136 | .remove = __devexit_p(wm8994_codec_remove), | 4060 | .remove = __devexit_p(wm8994_remove), |
4137 | }; | 4061 | }; |
4138 | 4062 | ||
4139 | static __init int wm8994_init(void) | 4063 | static __init int wm8994_init(void) |