diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-11 06:06:48 -0500 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2013-02-11 06:06:48 -0500 |
commit | 3dc4b7af38d14fc7eeab18f3c08d533ad84a187e (patch) | |
tree | 3735ad7203ef0f200bda6bac58a2e9b3c6d6e46c | |
parent | efad6eed2698a975ef4c82d97ab7a6279e978fd0 (diff) | |
parent | 3f3af6eeff3e048e27eb864519e779aedc194386 (diff) |
Merge remote-tracking branch 'asoc/topic/wm2000' into asoc-next
-rw-r--r-- | include/sound/wm2000.h | 3 | ||||
-rw-r--r-- | sound/soc/codecs/wm2000.c | 35 | ||||
-rw-r--r-- | sound/soc/codecs/wm2000.h | 3 |
3 files changed, 34 insertions, 7 deletions
diff --git a/include/sound/wm2000.h b/include/sound/wm2000.h index aa388ca9ec64..4de81f41c90f 100644 --- a/include/sound/wm2000.h +++ b/include/sound/wm2000.h | |||
@@ -15,9 +15,6 @@ struct wm2000_platform_data { | |||
15 | /** Filename for system-specific image to download to device. */ | 15 | /** Filename for system-specific image to download to device. */ |
16 | const char *download_file; | 16 | const char *download_file; |
17 | 17 | ||
18 | /** Divide MCLK by 2 for system clock? */ | ||
19 | unsigned int mclkdiv2:1; | ||
20 | |||
21 | /** Disable speech clarity enhancement, for use when an | 18 | /** Disable speech clarity enhancement, for use when an |
22 | * external algorithm is used. */ | 19 | * external algorithm is used. */ |
23 | unsigned int speech_enh_disable:1; | 20 | unsigned int speech_enh_disable:1; |
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index eb96b8768098..f2ac38b61a1b 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/kernel.h> | 26 | #include <linux/kernel.h> |
27 | #include <linux/init.h> | 27 | #include <linux/init.h> |
28 | #include <linux/firmware.h> | 28 | #include <linux/firmware.h> |
29 | #include <linux/clk.h> | ||
29 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
30 | #include <linux/pm.h> | 31 | #include <linux/pm.h> |
31 | #include <linux/i2c.h> | 32 | #include <linux/i2c.h> |
@@ -62,6 +63,7 @@ enum wm2000_anc_mode { | |||
62 | struct wm2000_priv { | 63 | struct wm2000_priv { |
63 | struct i2c_client *i2c; | 64 | struct i2c_client *i2c; |
64 | struct regmap *regmap; | 65 | struct regmap *regmap; |
66 | struct clk *mclk; | ||
65 | 67 | ||
66 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; | 68 | struct regulator_bulk_data supplies[WM2000_NUM_SUPPLIES]; |
67 | 69 | ||
@@ -71,7 +73,6 @@ struct wm2000_priv { | |||
71 | unsigned int anc_eng_ena:1; | 73 | unsigned int anc_eng_ena:1; |
72 | unsigned int spk_ena:1; | 74 | unsigned int spk_ena:1; |
73 | 75 | ||
74 | unsigned int mclk_div:1; | ||
75 | unsigned int speech_clarity:1; | 76 | unsigned int speech_clarity:1; |
76 | 77 | ||
77 | int anc_download_size; | 78 | int anc_download_size; |
@@ -133,6 +134,7 @@ static int wm2000_poll_bit(struct i2c_client *i2c, | |||
133 | static int wm2000_power_up(struct i2c_client *i2c, int analogue) | 134 | static int wm2000_power_up(struct i2c_client *i2c, int analogue) |
134 | { | 135 | { |
135 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); | 136 | struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev); |
137 | unsigned long rate; | ||
136 | int ret; | 138 | int ret; |
137 | 139 | ||
138 | BUG_ON(wm2000->anc_mode != ANC_OFF); | 140 | BUG_ON(wm2000->anc_mode != ANC_OFF); |
@@ -145,7 +147,8 @@ static int wm2000_power_up(struct i2c_client *i2c, int analogue) | |||
145 | return ret; | 147 | return ret; |
146 | } | 148 | } |
147 | 149 | ||
148 | if (!wm2000->mclk_div) { | 150 | rate = clk_get_rate(wm2000->mclk); |
151 | if (rate <= 13500000) { | ||
149 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); | 152 | dev_dbg(&i2c->dev, "Disabling MCLK divider\n"); |
150 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, | 153 | wm2000_write(i2c, WM2000_REG_SYS_CTL2, |
151 | WM2000_MCLK_DIV2_ENA_CLR); | 154 | WM2000_MCLK_DIV2_ENA_CLR); |
@@ -552,6 +555,15 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000, | |||
552 | return -EINVAL; | 555 | return -EINVAL; |
553 | } | 556 | } |
554 | 557 | ||
558 | /* Maintain clock while active */ | ||
559 | if (anc_transitions[i].source == ANC_OFF) { | ||
560 | ret = clk_prepare_enable(wm2000->mclk); | ||
561 | if (ret != 0) { | ||
562 | dev_err(&i2c->dev, "Failed to enable MCLK: %d\n", ret); | ||
563 | return ret; | ||
564 | } | ||
565 | } | ||
566 | |||
555 | for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { | 567 | for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) { |
556 | if (!anc_transitions[i].step[j]) | 568 | if (!anc_transitions[i].step[j]) |
557 | break; | 569 | break; |
@@ -561,7 +573,10 @@ static int wm2000_anc_transition(struct wm2000_priv *wm2000, | |||
561 | return ret; | 573 | return ret; |
562 | } | 574 | } |
563 | 575 | ||
564 | return 0; | 576 | if (anc_transitions[i].dest == ANC_OFF) |
577 | clk_disable_unprepare(wm2000->mclk); | ||
578 | |||
579 | return ret; | ||
565 | } | 580 | } |
566 | 581 | ||
567 | static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) | 582 | static int wm2000_anc_set_mode(struct wm2000_priv *wm2000) |
@@ -651,6 +666,7 @@ static int wm2000_speaker_put(struct snd_kcontrol *kcontrol, | |||
651 | } | 666 | } |
652 | 667 | ||
653 | static const struct snd_kcontrol_new wm2000_controls[] = { | 668 | static const struct snd_kcontrol_new wm2000_controls[] = { |
669 | SOC_SINGLE("ANC Volume", WM2000_REG_ANC_GAIN_CTRL, 0, 255, 0), | ||
654 | SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0, | 670 | SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0, |
655 | wm2000_anc_mode_get, | 671 | wm2000_anc_mode_get, |
656 | wm2000_anc_mode_put), | 672 | wm2000_anc_mode_put), |
@@ -725,6 +741,9 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg) | |||
725 | { | 741 | { |
726 | switch (reg) { | 742 | switch (reg) { |
727 | case WM2000_REG_SYS_START: | 743 | case WM2000_REG_SYS_START: |
744 | case WM2000_REG_ANC_GAIN_CTRL: | ||
745 | case WM2000_REG_MSE_TH1: | ||
746 | case WM2000_REG_MSE_TH2: | ||
728 | case WM2000_REG_SPEECH_CLARITY: | 747 | case WM2000_REG_SPEECH_CLARITY: |
729 | case WM2000_REG_SYS_WATCHDOG: | 748 | case WM2000_REG_SYS_WATCHDOG: |
730 | case WM2000_REG_ANA_VMID_PD_TIME: | 749 | case WM2000_REG_ANA_VMID_PD_TIME: |
@@ -760,6 +779,8 @@ static int wm2000_probe(struct snd_soc_codec *codec) | |||
760 | { | 779 | { |
761 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); | 780 | struct wm2000_priv *wm2000 = dev_get_drvdata(codec->dev); |
762 | 781 | ||
782 | snd_soc_codec_set_cache_io(codec, 16, 8, SND_SOC_REGMAP); | ||
783 | |||
763 | /* This will trigger a transition to standby mode by default */ | 784 | /* This will trigger a transition to standby mode by default */ |
764 | wm2000_anc_set_mode(wm2000); | 785 | wm2000_anc_set_mode(wm2000); |
765 | 786 | ||
@@ -848,10 +869,16 @@ static int wm2000_i2c_probe(struct i2c_client *i2c, | |||
848 | reg = wm2000_read(i2c, WM2000_REG_REVISON); | 869 | reg = wm2000_read(i2c, WM2000_REG_REVISON); |
849 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); | 870 | dev_info(&i2c->dev, "revision %c\n", reg + 'A'); |
850 | 871 | ||
872 | wm2000->mclk = devm_clk_get(&i2c->dev, "MCLK"); | ||
873 | if (IS_ERR(wm2000->mclk)) { | ||
874 | ret = PTR_ERR(wm2000->mclk); | ||
875 | dev_err(&i2c->dev, "Failed to get MCLK: %d\n", ret); | ||
876 | goto err_supplies; | ||
877 | } | ||
878 | |||
851 | filename = "wm2000_anc.bin"; | 879 | filename = "wm2000_anc.bin"; |
852 | pdata = dev_get_platdata(&i2c->dev); | 880 | pdata = dev_get_platdata(&i2c->dev); |
853 | if (pdata) { | 881 | if (pdata) { |
854 | wm2000->mclk_div = pdata->mclkdiv2; | ||
855 | wm2000->speech_clarity = !pdata->speech_enh_disable; | 882 | wm2000->speech_clarity = !pdata->speech_enh_disable; |
856 | 883 | ||
857 | if (pdata->download_file) | 884 | if (pdata->download_file) |
diff --git a/sound/soc/codecs/wm2000.h b/sound/soc/codecs/wm2000.h index abcd82a93995..fb812cd9e77d 100644 --- a/sound/soc/codecs/wm2000.h +++ b/sound/soc/codecs/wm2000.h | |||
@@ -10,6 +10,9 @@ | |||
10 | #define _WM2000_H | 10 | #define _WM2000_H |
11 | 11 | ||
12 | #define WM2000_REG_SYS_START 0x8000 | 12 | #define WM2000_REG_SYS_START 0x8000 |
13 | #define WM2000_REG_ANC_GAIN_CTRL 0x8fa2 | ||
14 | #define WM2000_REG_MSE_TH2 0x8fdf | ||
15 | #define WM2000_REG_MSE_TH1 0x8fe0 | ||
13 | #define WM2000_REG_SPEECH_CLARITY 0x8fef | 16 | #define WM2000_REG_SPEECH_CLARITY 0x8fef |
14 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 | 17 | #define WM2000_REG_SYS_WATCHDOG 0x8ff6 |
15 | #define WM2000_REG_ANA_VMID_PD_TIME 0x8ff7 | 18 | #define WM2000_REG_ANA_VMID_PD_TIME 0x8ff7 |