diff options
-rw-r--r-- | include/sound/max9768.h | 24 | ||||
-rw-r--r-- | sound/soc/codecs/Kconfig | 4 | ||||
-rw-r--r-- | sound/soc/codecs/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/codecs/max9768.c | 253 |
4 files changed, 283 insertions, 0 deletions
diff --git a/include/sound/max9768.h b/include/sound/max9768.h new file mode 100644 index 000000000000..0f78b41d030e --- /dev/null +++ b/include/sound/max9768.h | |||
@@ -0,0 +1,24 @@ | |||
1 | /* | ||
2 | * Platform data for MAX9768 | ||
3 | * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K. | ||
4 | * same licence as the driver | ||
5 | */ | ||
6 | |||
7 | #ifndef __SOUND_MAX9768_PDATA_H__ | ||
8 | #define __SOUND_MAX9768_PDATA_H__ | ||
9 | |||
10 | /** | ||
11 | * struct max9768_pdata - optional platform specific MAX9768 configuration | ||
12 | * @shdn_gpio: GPIO to SHDN pin. If not valid, pin must be hardwired HIGH | ||
13 | * @mute_gpio: GPIO to MUTE pin. If not valid, control for mute won't be added | ||
14 | * @flags: configuration flags, e.g. set classic PWM mode (check datasheet | ||
15 | * regarding "filterless modulation" which is default). | ||
16 | */ | ||
17 | struct max9768_pdata { | ||
18 | int shdn_gpio; | ||
19 | int mute_gpio; | ||
20 | unsigned flags; | ||
21 | #define MAX9768_FLAG_CLASSIC_PWM (1 << 0) | ||
22 | }; | ||
23 | |||
24 | #endif /* __SOUND_MAX9768_PDATA_H__*/ | ||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 39aec3c12cff..6508e8b790bb 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -40,6 +40,7 @@ config SND_SOC_ALL_CODECS | |||
40 | select SND_SOC_MAX98088 if I2C | 40 | select SND_SOC_MAX98088 if I2C |
41 | select SND_SOC_MAX98095 if I2C | 41 | select SND_SOC_MAX98095 if I2C |
42 | select SND_SOC_MAX9850 if I2C | 42 | select SND_SOC_MAX9850 if I2C |
43 | select SND_SOC_MAX9768 if I2C | ||
43 | select SND_SOC_MAX9877 if I2C | 44 | select SND_SOC_MAX9877 if I2C |
44 | select SND_SOC_PCM3008 | 45 | select SND_SOC_PCM3008 |
45 | select SND_SOC_RT5631 if I2C | 46 | select SND_SOC_RT5631 if I2C |
@@ -429,6 +430,9 @@ config SND_SOC_WM9713 | |||
429 | config SND_SOC_LM4857 | 430 | config SND_SOC_LM4857 |
430 | tristate | 431 | tristate |
431 | 432 | ||
433 | config SND_SOC_MAX9768 | ||
434 | tristate | ||
435 | |||
432 | config SND_SOC_MAX9877 | 436 | config SND_SOC_MAX9877 |
433 | tristate | 437 | tristate |
434 | 438 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 716c5842bfd6..6662eb0cdcc0 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -25,6 +25,7 @@ snd-soc-dmic-objs := dmic.o | |||
25 | snd-soc-jz4740-codec-objs := jz4740.o | 25 | snd-soc-jz4740-codec-objs := jz4740.o |
26 | snd-soc-l3-objs := l3.o | 26 | snd-soc-l3-objs := l3.o |
27 | snd-soc-lm4857-objs := lm4857.o | 27 | snd-soc-lm4857-objs := lm4857.o |
28 | snd-soc-max9768-objs := max9768.o | ||
28 | snd-soc-max98088-objs := max98088.o | 29 | snd-soc-max98088-objs := max98088.o |
29 | snd-soc-max98095-objs := max98095.o | 30 | snd-soc-max98095-objs := max98095.o |
30 | snd-soc-max9850-objs := max9850.o | 31 | snd-soc-max9850-objs := max9850.o |
@@ -130,6 +131,7 @@ obj-$(CONFIG_SND_SOC_DMIC) += snd-soc-dmic.o | |||
130 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o | 131 | obj-$(CONFIG_SND_SOC_L3) += snd-soc-l3.o |
131 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o | 132 | obj-$(CONFIG_SND_SOC_LM4857) += snd-soc-lm4857.o |
132 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o | 133 | obj-$(CONFIG_SND_SOC_JZ4740_CODEC) += snd-soc-jz4740-codec.o |
134 | obj-$(CONFIG_SND_SOC_MAX9768) += snd-soc-max9768.o | ||
133 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o | 135 | obj-$(CONFIG_SND_SOC_MAX98088) += snd-soc-max98088.o |
134 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o | 136 | obj-$(CONFIG_SND_SOC_MAX98095) += snd-soc-max98095.o |
135 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o | 137 | obj-$(CONFIG_SND_SOC_MAX9850) += snd-soc-max9850.o |
diff --git a/sound/soc/codecs/max9768.c b/sound/soc/codecs/max9768.c new file mode 100644 index 000000000000..634899525848 --- /dev/null +++ b/sound/soc/codecs/max9768.c | |||
@@ -0,0 +1,253 @@ | |||
1 | /* | ||
2 | * MAX9768 AMP driver | ||
3 | * | ||
4 | * Copyright (C) 2011, 2012 by Wolfram Sang, Pengutronix e.K. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; version 2 of the License. | ||
9 | */ | ||
10 | |||
11 | #include <linux/init.h> | ||
12 | #include <linux/module.h> | ||
13 | #include <linux/i2c.h> | ||
14 | #include <linux/slab.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/regmap.h> | ||
17 | |||
18 | #include <sound/core.h> | ||
19 | #include <sound/soc.h> | ||
20 | #include <sound/tlv.h> | ||
21 | #include <sound/max9768.h> | ||
22 | |||
23 | /* "Registers" */ | ||
24 | #define MAX9768_VOL 0 | ||
25 | #define MAX9768_CTRL 3 | ||
26 | |||
27 | /* Commands */ | ||
28 | #define MAX9768_CTRL_PWM 0x15 | ||
29 | #define MAX9768_CTRL_FILTERLESS 0x16 | ||
30 | |||
31 | struct max9768 { | ||
32 | struct regmap *regmap; | ||
33 | int mute_gpio; | ||
34 | int shdn_gpio; | ||
35 | u32 flags; | ||
36 | }; | ||
37 | |||
38 | static struct reg_default max9768_default_regs[] = { | ||
39 | { 0, 0 }, | ||
40 | { 3, MAX9768_CTRL_FILTERLESS}, | ||
41 | }; | ||
42 | |||
43 | static int max9768_get_gpio(struct snd_kcontrol *kcontrol, | ||
44 | struct snd_ctl_elem_value *ucontrol) | ||
45 | { | ||
46 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
47 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | ||
48 | int val = gpio_get_value_cansleep(max9768->mute_gpio); | ||
49 | |||
50 | ucontrol->value.integer.value[0] = !val; | ||
51 | |||
52 | return 0; | ||
53 | } | ||
54 | |||
55 | static int max9768_set_gpio(struct snd_kcontrol *kcontrol, | ||
56 | struct snd_ctl_elem_value *ucontrol) | ||
57 | { | ||
58 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
59 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | ||
60 | |||
61 | gpio_set_value_cansleep(max9768->mute_gpio, !ucontrol->value.integer.value[0]); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static const unsigned int volume_tlv[] = { | ||
67 | TLV_DB_RANGE_HEAD(43), | ||
68 | 0, 0, TLV_DB_SCALE_ITEM(-16150, 0, 0), | ||
69 | 1, 1, TLV_DB_SCALE_ITEM(-9280, 0, 0), | ||
70 | 2, 2, TLV_DB_SCALE_ITEM(-9030, 0, 0), | ||
71 | 3, 3, TLV_DB_SCALE_ITEM(-8680, 0, 0), | ||
72 | 4, 4, TLV_DB_SCALE_ITEM(-8430, 0, 0), | ||
73 | 5, 5, TLV_DB_SCALE_ITEM(-8080, 0, 0), | ||
74 | 6, 6, TLV_DB_SCALE_ITEM(-7830, 0, 0), | ||
75 | 7, 7, TLV_DB_SCALE_ITEM(-7470, 0, 0), | ||
76 | 8, 8, TLV_DB_SCALE_ITEM(-7220, 0, 0), | ||
77 | 9, 9, TLV_DB_SCALE_ITEM(-6870, 0, 0), | ||
78 | 10, 10, TLV_DB_SCALE_ITEM(-6620, 0, 0), | ||
79 | 11, 11, TLV_DB_SCALE_ITEM(-6270, 0, 0), | ||
80 | 12, 12, TLV_DB_SCALE_ITEM(-6020, 0, 0), | ||
81 | 13, 13, TLV_DB_SCALE_ITEM(-5670, 0, 0), | ||
82 | 14, 14, TLV_DB_SCALE_ITEM(-5420, 0, 0), | ||
83 | 15, 17, TLV_DB_SCALE_ITEM(-5060, 250, 0), | ||
84 | 18, 18, TLV_DB_SCALE_ITEM(-4370, 0, 0), | ||
85 | 19, 19, TLV_DB_SCALE_ITEM(-4210, 0, 0), | ||
86 | 20, 20, TLV_DB_SCALE_ITEM(-3960, 0, 0), | ||
87 | 21, 21, TLV_DB_SCALE_ITEM(-3760, 0, 0), | ||
88 | 22, 22, TLV_DB_SCALE_ITEM(-3600, 0, 0), | ||
89 | 23, 23, TLV_DB_SCALE_ITEM(-3340, 0, 0), | ||
90 | 24, 24, TLV_DB_SCALE_ITEM(-3150, 0, 0), | ||
91 | 25, 25, TLV_DB_SCALE_ITEM(-2980, 0, 0), | ||
92 | 26, 26, TLV_DB_SCALE_ITEM(-2720, 0, 0), | ||
93 | 27, 27, TLV_DB_SCALE_ITEM(-2520, 0, 0), | ||
94 | 28, 30, TLV_DB_SCALE_ITEM(-2350, 190, 0), | ||
95 | 31, 31, TLV_DB_SCALE_ITEM(-1750, 0, 0), | ||
96 | 32, 34, TLV_DB_SCALE_ITEM(-1640, 100, 0), | ||
97 | 35, 37, TLV_DB_SCALE_ITEM(-1310, 110, 0), | ||
98 | 38, 39, TLV_DB_SCALE_ITEM(-990, 100, 0), | ||
99 | 40, 40, TLV_DB_SCALE_ITEM(-710, 0, 0), | ||
100 | 41, 41, TLV_DB_SCALE_ITEM(-600, 0, 0), | ||
101 | 42, 42, TLV_DB_SCALE_ITEM(-500, 0, 0), | ||
102 | 43, 43, TLV_DB_SCALE_ITEM(-340, 0, 0), | ||
103 | 44, 44, TLV_DB_SCALE_ITEM(-190, 0, 0), | ||
104 | 45, 45, TLV_DB_SCALE_ITEM(-50, 0, 0), | ||
105 | 46, 46, TLV_DB_SCALE_ITEM(50, 0, 0), | ||
106 | 47, 50, TLV_DB_SCALE_ITEM(120, 40, 0), | ||
107 | 51, 57, TLV_DB_SCALE_ITEM(290, 50, 0), | ||
108 | 58, 58, TLV_DB_SCALE_ITEM(650, 0, 0), | ||
109 | 59, 62, TLV_DB_SCALE_ITEM(700, 60, 0), | ||
110 | 63, 63, TLV_DB_SCALE_ITEM(950, 0, 0), | ||
111 | }; | ||
112 | |||
113 | static const struct snd_kcontrol_new max9768_volume[] = { | ||
114 | SOC_SINGLE_TLV("Playback Volume", MAX9768_VOL, 0, 63, 0, volume_tlv), | ||
115 | }; | ||
116 | |||
117 | static const struct snd_kcontrol_new max9768_mute[] = { | ||
118 | SOC_SINGLE_BOOL_EXT("Mute Switch", 0, max9768_get_gpio, max9768_set_gpio), | ||
119 | }; | ||
120 | |||
121 | static int max9768_probe(struct snd_soc_codec *codec) | ||
122 | { | ||
123 | struct max9768 *max9768 = snd_soc_codec_get_drvdata(codec); | ||
124 | int ret; | ||
125 | |||
126 | codec->control_data = max9768->regmap; | ||
127 | ret = snd_soc_codec_set_cache_io(codec, 2, 6, SND_SOC_REGMAP); | ||
128 | if (ret) | ||
129 | return ret; | ||
130 | |||
131 | if (max9768->flags & MAX9768_FLAG_CLASSIC_PWM) { | ||
132 | ret = snd_soc_write(codec, MAX9768_CTRL, MAX9768_CTRL_PWM); | ||
133 | if (ret) | ||
134 | return ret; | ||
135 | } | ||
136 | |||
137 | if (gpio_is_valid(max9768->mute_gpio)) { | ||
138 | ret = snd_soc_add_controls(codec, max9768_mute, | ||
139 | ARRAY_SIZE(max9768_mute)); | ||
140 | if (ret) | ||
141 | return ret; | ||
142 | } | ||
143 | |||
144 | return 0; | ||
145 | } | ||
146 | |||
147 | static struct snd_soc_codec_driver max9768_codec_driver = { | ||
148 | .probe = max9768_probe, | ||
149 | .controls = max9768_volume, | ||
150 | .num_controls = ARRAY_SIZE(max9768_volume), | ||
151 | }; | ||
152 | |||
153 | static bool max9768_always_false(struct device *dev, unsigned int reg) | ||
154 | { | ||
155 | return false; | ||
156 | } | ||
157 | |||
158 | static const struct regmap_config max9768_i2c_regmap_config = { | ||
159 | .reg_bits = 2, | ||
160 | .val_bits = 6, | ||
161 | .max_register = 3, | ||
162 | .reg_defaults = max9768_default_regs, | ||
163 | .num_reg_defaults = ARRAY_SIZE(max9768_default_regs), | ||
164 | .volatile_reg = max9768_always_false, | ||
165 | .cache_type = REGCACHE_RBTREE, | ||
166 | }; | ||
167 | |||
168 | static int __devinit max9768_i2c_probe(struct i2c_client *client, | ||
169 | const struct i2c_device_id *id) | ||
170 | { | ||
171 | struct max9768 *max9768; | ||
172 | struct max9768_pdata *pdata = client->dev.platform_data; | ||
173 | int err; | ||
174 | |||
175 | max9768 = devm_kzalloc(&client->dev, sizeof(*max9768), GFP_KERNEL); | ||
176 | if (!max9768) | ||
177 | return -ENOMEM; | ||
178 | |||
179 | if (pdata) { | ||
180 | /* Mute on powerup to avoid clicks */ | ||
181 | err = gpio_request_one(pdata->mute_gpio, GPIOF_INIT_HIGH, "MAX9768 Mute"); | ||
182 | max9768->mute_gpio = err ?: pdata->mute_gpio; | ||
183 | |||
184 | /* Activate chip by releasing shutdown, enables I2C */ | ||
185 | err = gpio_request_one(pdata->shdn_gpio, GPIOF_INIT_HIGH, "MAX9768 Shutdown"); | ||
186 | max9768->shdn_gpio = err ?: pdata->shdn_gpio; | ||
187 | |||
188 | max9768->flags = pdata->flags; | ||
189 | } else { | ||
190 | max9768->shdn_gpio = -EINVAL; | ||
191 | max9768->mute_gpio = -EINVAL; | ||
192 | } | ||
193 | |||
194 | i2c_set_clientdata(client, max9768); | ||
195 | |||
196 | max9768->regmap = regmap_init_i2c(client, &max9768_i2c_regmap_config); | ||
197 | if (IS_ERR(max9768->regmap)) { | ||
198 | err = PTR_ERR(max9768->regmap); | ||
199 | goto err_gpio_free; | ||
200 | } | ||
201 | |||
202 | err = snd_soc_register_codec(&client->dev, &max9768_codec_driver, NULL, 0); | ||
203 | if (err) | ||
204 | goto err_regmap_free; | ||
205 | |||
206 | return 0; | ||
207 | |||
208 | err_regmap_free: | ||
209 | regmap_exit(max9768->regmap); | ||
210 | err_gpio_free: | ||
211 | if (gpio_is_valid(max9768->shdn_gpio)) | ||
212 | gpio_free(max9768->shdn_gpio); | ||
213 | if (gpio_is_valid(max9768->mute_gpio)) | ||
214 | gpio_free(max9768->mute_gpio); | ||
215 | |||
216 | return err; | ||
217 | } | ||
218 | |||
219 | static int __devexit max9768_i2c_remove(struct i2c_client *client) | ||
220 | { | ||
221 | struct max9768 *max9768 = i2c_get_clientdata(client); | ||
222 | |||
223 | snd_soc_unregister_codec(&client->dev); | ||
224 | regmap_exit(max9768->regmap); | ||
225 | |||
226 | if (gpio_is_valid(max9768->shdn_gpio)) | ||
227 | gpio_free(max9768->shdn_gpio); | ||
228 | if (gpio_is_valid(max9768->mute_gpio)) | ||
229 | gpio_free(max9768->mute_gpio); | ||
230 | |||
231 | return 0; | ||
232 | } | ||
233 | |||
234 | static const struct i2c_device_id max9768_i2c_id[] = { | ||
235 | { "max9768", 0 }, | ||
236 | { } | ||
237 | }; | ||
238 | MODULE_DEVICE_TABLE(i2c, max9768_i2c_id); | ||
239 | |||
240 | static struct i2c_driver max9768_i2c_driver = { | ||
241 | .driver = { | ||
242 | .name = "max9768", | ||
243 | .owner = THIS_MODULE, | ||
244 | }, | ||
245 | .probe = max9768_i2c_probe, | ||
246 | .remove = __devexit_p(max9768_i2c_remove), | ||
247 | .id_table = max9768_i2c_id, | ||
248 | }; | ||
249 | module_i2c_driver(max9768_i2c_driver); | ||
250 | |||
251 | MODULE_AUTHOR("Wolfram Sang <w.sang@pengutronix.de>"); | ||
252 | MODULE_DESCRIPTION("ASoC MAX9768 amplifier driver"); | ||
253 | MODULE_LICENSE("GPL v2"); | ||