xref: /openbmc/linux/sound/soc/codecs/tpa6130a2.c (revision de2bdb3d)
1 /*
2  * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
3  *
4  * Copyright (C) Nokia Corporation
5  *
6  * Author: Peter Ujfalusi <peter.ujfalusi@ti.com>
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful, but
13  * WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20  * 02110-1301 USA
21  */
22 
23 #include <linux/module.h>
24 #include <linux/errno.h>
25 #include <linux/device.h>
26 #include <linux/i2c.h>
27 #include <linux/gpio.h>
28 #include <linux/regulator/consumer.h>
29 #include <linux/slab.h>
30 #include <sound/tpa6130a2-plat.h>
31 #include <sound/soc.h>
32 #include <sound/tlv.h>
33 #include <linux/of.h>
34 #include <linux/of_gpio.h>
35 #include <linux/regmap.h>
36 
37 #include "tpa6130a2.h"
38 
39 enum tpa_model {
40 	TPA6130A2,
41 	TPA6140A2,
42 };
43 
44 /* This struct is used to save the context */
45 struct tpa6130a2_data {
46 	struct device *dev;
47 	struct regmap *regmap;
48 	struct regulator *supply;
49 	int power_gpio;
50 	enum tpa_model id;
51 };
52 
53 static int tpa6130a2_power(struct tpa6130a2_data *data, bool enable)
54 {
55 	int ret = 0, ret2;
56 
57 	if (enable) {
58 		ret = regulator_enable(data->supply);
59 		if (ret != 0) {
60 			dev_err(data->dev,
61 				"Failed to enable supply: %d\n", ret);
62 			return ret;
63 		}
64 		/* Power on */
65 		if (data->power_gpio >= 0)
66 			gpio_set_value(data->power_gpio, 1);
67 
68 		/* Sync registers */
69 		regcache_cache_only(data->regmap, false);
70 		ret = regcache_sync(data->regmap);
71 		if (ret != 0) {
72 			dev_err(data->dev,
73 				"Failed to sync registers: %d\n", ret);
74 			regcache_cache_only(data->regmap, true);
75 			if (data->power_gpio >= 0)
76 				gpio_set_value(data->power_gpio, 0);
77 			ret2 = regulator_disable(data->supply);
78 			if (ret2 != 0)
79 				dev_err(data->dev,
80 					"Failed to disable supply: %d\n", ret2);
81 			return ret;
82 		}
83 	} else {
84 		/* Powered off device does not retain registers. While device
85 		 * is off, any register updates (i.e. volume changes) should
86 		 * happen in cache only.
87 		 */
88 		regcache_mark_dirty(data->regmap);
89 		regcache_cache_only(data->regmap, true);
90 
91 		/* Power off */
92 		if (data->power_gpio >= 0)
93 			gpio_set_value(data->power_gpio, 0);
94 
95 		ret = regulator_disable(data->supply);
96 		if (ret != 0) {
97 			dev_err(data->dev,
98 				"Failed to disable supply: %d\n", ret);
99 			return ret;
100 		}
101 	}
102 
103 	return ret;
104 }
105 
106 static int tpa6130a2_power_event(struct snd_soc_dapm_widget *w,
107 				 struct snd_kcontrol *kctrl, int event)
108 {
109 	struct snd_soc_component *c = snd_soc_dapm_to_component(w->dapm);
110 	struct tpa6130a2_data *data = snd_soc_component_get_drvdata(c);
111 
112 	if (SND_SOC_DAPM_EVENT_ON(event)) {
113 		/* Before widget power up: turn chip on, sync registers */
114 		return tpa6130a2_power(data, true);
115 	} else {
116 		/* After widget power down: turn chip off */
117 		return tpa6130a2_power(data, false);
118 	}
119 }
120 
121 /*
122  * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going
123  * down in gain.
124  */
125 static const DECLARE_TLV_DB_RANGE(tpa6130_tlv,
126 	0, 1, TLV_DB_SCALE_ITEM(-5950, 600, 0),
127 	2, 3, TLV_DB_SCALE_ITEM(-5000, 250, 0),
128 	4, 5, TLV_DB_SCALE_ITEM(-4550, 160, 0),
129 	6, 7, TLV_DB_SCALE_ITEM(-4140, 190, 0),
130 	8, 9, TLV_DB_SCALE_ITEM(-3650, 120, 0),
131 	10, 11, TLV_DB_SCALE_ITEM(-3330, 160, 0),
132 	12, 13, TLV_DB_SCALE_ITEM(-3040, 180, 0),
133 	14, 20, TLV_DB_SCALE_ITEM(-2710, 110, 0),
134 	21, 37, TLV_DB_SCALE_ITEM(-1960, 74, 0),
135 	38, 63, TLV_DB_SCALE_ITEM(-720, 45, 0)
136 );
137 
138 static const struct snd_kcontrol_new tpa6130a2_controls[] = {
139 	SOC_SINGLE_TLV("Headphone Playback Volume",
140 		       TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0,
141 		       tpa6130_tlv),
142 };
143 
144 static const DECLARE_TLV_DB_RANGE(tpa6140_tlv,
145 	0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0),
146 	9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0),
147 	17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0)
148 );
149 
150 static const struct snd_kcontrol_new tpa6140a2_controls[] = {
151 	SOC_SINGLE_TLV("Headphone Playback Volume",
152 		       TPA6130A2_REG_VOL_MUTE, 1, 0x1f, 0,
153 		       tpa6140_tlv),
154 };
155 
156 static int tpa6130a2_component_probe(struct snd_soc_component *component)
157 {
158 	struct tpa6130a2_data *data = snd_soc_component_get_drvdata(component);
159 
160 	if (data->id == TPA6140A2)
161 		return snd_soc_add_component_controls(component,
162 			tpa6140a2_controls, ARRAY_SIZE(tpa6140a2_controls));
163 	else
164 		return snd_soc_add_component_controls(component,
165 			tpa6130a2_controls, ARRAY_SIZE(tpa6130a2_controls));
166 }
167 
168 static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
169 	SND_SOC_DAPM_INPUT("LEFTIN"),
170 	SND_SOC_DAPM_INPUT("RIGHTIN"),
171 	SND_SOC_DAPM_OUTPUT("HPLEFT"),
172 	SND_SOC_DAPM_OUTPUT("HPRIGHT"),
173 
174 	SND_SOC_DAPM_PGA("Left Mute", TPA6130A2_REG_VOL_MUTE,
175 			 TPA6130A2_HP_EN_L_SHIFT, 1, NULL, 0),
176 	SND_SOC_DAPM_PGA("Right Mute", TPA6130A2_REG_VOL_MUTE,
177 			 TPA6130A2_HP_EN_R_SHIFT, 1, NULL, 0),
178 	SND_SOC_DAPM_PGA("Left PGA", TPA6130A2_REG_CONTROL,
179 			 TPA6130A2_HP_EN_L_SHIFT, 0, NULL, 0),
180 	SND_SOC_DAPM_PGA("Right PGA", TPA6130A2_REG_CONTROL,
181 			 TPA6130A2_HP_EN_R_SHIFT, 0, NULL, 0),
182 
183 	SND_SOC_DAPM_SUPPLY("Power", TPA6130A2_REG_CONTROL,
184 			    TPA6130A2_SWS_SHIFT, 1, tpa6130a2_power_event,
185 			    SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD),
186 };
187 
188 static const struct snd_soc_dapm_route tpa6130a2_dapm_routes[] = {
189 	{ "Left PGA", NULL, "LEFTIN" },
190 	{ "Right PGA", NULL, "RIGHTIN" },
191 
192 	{ "Left Mute", NULL, "Left PGA" },
193 	{ "Right Mute", NULL, "Right PGA" },
194 
195 	{ "HPLEFT", NULL, "Left Mute" },
196 	{ "HPRIGHT", NULL, "Right Mute" },
197 
198 	{ "Left PGA", NULL, "Power" },
199 	{ "Right PGA", NULL, "Power" },
200 };
201 
202 static const struct snd_soc_component_driver tpa6130a2_component_driver = {
203 	.name = "tpa6130a2",
204 	.probe = tpa6130a2_component_probe,
205 	.dapm_widgets = tpa6130a2_dapm_widgets,
206 	.num_dapm_widgets = ARRAY_SIZE(tpa6130a2_dapm_widgets),
207 	.dapm_routes = tpa6130a2_dapm_routes,
208 	.num_dapm_routes = ARRAY_SIZE(tpa6130a2_dapm_routes),
209 };
210 
211 static const struct reg_default tpa6130a2_reg_defaults[] = {
212 	{ TPA6130A2_REG_CONTROL, TPA6130A2_SWS },
213 	{ TPA6130A2_REG_VOL_MUTE, TPA6130A2_MUTE_R | TPA6130A2_MUTE_L },
214 };
215 
216 static const struct regmap_config tpa6130a2_regmap_config = {
217 	.reg_bits = 8,
218 	.val_bits = 8,
219 	.max_register = TPA6130A2_REG_VERSION,
220 	.reg_defaults = tpa6130a2_reg_defaults,
221 	.num_reg_defaults = ARRAY_SIZE(tpa6130a2_reg_defaults),
222 	.cache_type = REGCACHE_RBTREE,
223 };
224 
225 static int tpa6130a2_probe(struct i2c_client *client,
226 			   const struct i2c_device_id *id)
227 {
228 	struct device *dev;
229 	struct tpa6130a2_data *data;
230 	struct tpa6130a2_platform_data *pdata = client->dev.platform_data;
231 	struct device_node *np = client->dev.of_node;
232 	const char *regulator;
233 	unsigned int version;
234 	int ret;
235 
236 	dev = &client->dev;
237 
238 	data = devm_kzalloc(&client->dev, sizeof(*data), GFP_KERNEL);
239 	if (!data)
240 		return -ENOMEM;
241 
242 	data->dev = dev;
243 
244 	data->regmap = devm_regmap_init_i2c(client, &tpa6130a2_regmap_config);
245 	if (IS_ERR(data->regmap))
246 		return PTR_ERR(data->regmap);
247 
248 	if (pdata) {
249 		data->power_gpio = pdata->power_gpio;
250 	} else if (np) {
251 		data->power_gpio = of_get_named_gpio(np, "power-gpio", 0);
252 	} else {
253 		dev_err(dev, "Platform data not set\n");
254 		dump_stack();
255 		return -ENODEV;
256 	}
257 
258 	i2c_set_clientdata(client, data);
259 
260 	data->id = id->driver_data;
261 
262 	if (data->power_gpio >= 0) {
263 		ret = devm_gpio_request(dev, data->power_gpio,
264 					"tpa6130a2 enable");
265 		if (ret < 0) {
266 			dev_err(dev, "Failed to request power GPIO (%d)\n",
267 				data->power_gpio);
268 			return ret;
269 		}
270 		gpio_direction_output(data->power_gpio, 0);
271 	}
272 
273 	switch (data->id) {
274 	default:
275 		dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
276 			 data->id);
277 	case TPA6130A2:
278 		regulator = "Vdd";
279 		break;
280 	case TPA6140A2:
281 		regulator = "AVdd";
282 		break;
283 	}
284 
285 	data->supply = devm_regulator_get(dev, regulator);
286 	if (IS_ERR(data->supply)) {
287 		ret = PTR_ERR(data->supply);
288 		dev_err(dev, "Failed to request supply: %d\n", ret);
289 		return ret;
290 	}
291 
292 	ret = tpa6130a2_power(data, true);
293 	if (ret != 0)
294 		return ret;
295 
296 
297 	/* Read version */
298 	regmap_read(data->regmap, TPA6130A2_REG_VERSION, &version);
299 	version &= TPA6130A2_VERSION_MASK;
300 	if ((version != 1) && (version != 2))
301 		dev_warn(dev, "UNTESTED version detected (%d)\n", version);
302 
303 	/* Disable the chip */
304 	ret = tpa6130a2_power(data, false);
305 	if (ret != 0)
306 		return ret;
307 
308 	return devm_snd_soc_register_component(&client->dev,
309 			&tpa6130a2_component_driver, NULL, 0);
310 }
311 
312 static const struct i2c_device_id tpa6130a2_id[] = {
313 	{ "tpa6130a2", TPA6130A2 },
314 	{ "tpa6140a2", TPA6140A2 },
315 	{ }
316 };
317 MODULE_DEVICE_TABLE(i2c, tpa6130a2_id);
318 
319 #if IS_ENABLED(CONFIG_OF)
320 static const struct of_device_id tpa6130a2_of_match[] = {
321 	{ .compatible = "ti,tpa6130a2", },
322 	{ .compatible = "ti,tpa6140a2" },
323 	{},
324 };
325 MODULE_DEVICE_TABLE(of, tpa6130a2_of_match);
326 #endif
327 
328 static struct i2c_driver tpa6130a2_i2c_driver = {
329 	.driver = {
330 		.name = "tpa6130a2",
331 		.of_match_table = of_match_ptr(tpa6130a2_of_match),
332 	},
333 	.probe = tpa6130a2_probe,
334 	.id_table = tpa6130a2_id,
335 };
336 
337 module_i2c_driver(tpa6130a2_i2c_driver);
338 
339 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
340 MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
341 MODULE_LICENSE("GPL");
342