Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(744)

Side by Side Diff: sound/soc/codecs/tpa6130a2.c

Issue 6577007: CHROMIUM: ASoC: Import entire upstream ASoC tree (Closed)
Patch Set: Created 9 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « sound/soc/codecs/tpa6130a2.h ('k') | sound/soc/codecs/twl4030.c » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 /* 1 /*
2 * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver 2 * ALSA SoC Texas Instruments TPA6130A2 headset stereo amplifier driver
3 * 3 *
4 * Copyright (C) Nokia Corporation 4 * Copyright (C) Nokia Corporation
5 * 5 *
6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com> 6 * Author: Peter Ujfalusi <peter.ujfalusi@nokia.com>
7 * 7 *
8 * This program is free software; you can redistribute it and/or 8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License 9 * modify it under the terms of the GNU General Public License
10 * version 2 as published by the Free Software Foundation. 10 * version 2 as published by the Free Software Foundation.
(...skipping 11 matching lines...) Expand all
22 22
23 #include <linux/module.h> 23 #include <linux/module.h>
24 #include <linux/errno.h> 24 #include <linux/errno.h>
25 #include <linux/device.h> 25 #include <linux/device.h>
26 #include <linux/i2c.h> 26 #include <linux/i2c.h>
27 #include <linux/gpio.h> 27 #include <linux/gpio.h>
28 #include <linux/regulator/consumer.h> 28 #include <linux/regulator/consumer.h>
29 #include <linux/slab.h> 29 #include <linux/slab.h>
30 #include <sound/tpa6130a2-plat.h> 30 #include <sound/tpa6130a2-plat.h>
31 #include <sound/soc.h> 31 #include <sound/soc.h>
32 #include <sound/soc-dapm.h>
33 #include <sound/tlv.h> 32 #include <sound/tlv.h>
34 33
35 #include "tpa6130a2.h" 34 #include "tpa6130a2.h"
36 35
37 static struct i2c_client *tpa6130a2_client; 36 static struct i2c_client *tpa6130a2_client;
38 37
39 /* This struct is used to save the context */ 38 /* This struct is used to save the context */
40 struct tpa6130a2_data { 39 struct tpa6130a2_data {
41 struct mutex mutex; 40 struct mutex mutex;
42 unsigned char regs[TPA6130A2_CACHEREGNUM]; 41 unsigned char regs[TPA6130A2_CACHEREGNUM];
43 struct regulator *supply; 42 struct regulator *supply;
44 int power_gpio; 43 int power_gpio;
45 » unsigned char power_state; 44 » u8 power_state:1;
46 enum tpa_model id; 45 enum tpa_model id;
47 }; 46 };
48 47
49 static int tpa6130a2_i2c_read(int reg) 48 static int tpa6130a2_i2c_read(int reg)
50 { 49 {
51 struct tpa6130a2_data *data; 50 struct tpa6130a2_data *data;
52 int val; 51 int val;
53 52
54 BUG_ON(tpa6130a2_client == NULL); 53 BUG_ON(tpa6130a2_client == NULL);
55 data = i2c_get_clientdata(tpa6130a2_client); 54 data = i2c_get_clientdata(tpa6130a2_client);
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 109
111 for (i = 1; i < TPA6130A2_REG_VERSION; i++) { 110 for (i = 1; i < TPA6130A2_REG_VERSION; i++) {
112 ret = tpa6130a2_i2c_write(i, data->regs[i]); 111 ret = tpa6130a2_i2c_write(i, data->regs[i]);
113 if (ret < 0) 112 if (ret < 0)
114 break; 113 break;
115 } 114 }
116 115
117 return ret; 116 return ret;
118 } 117 }
119 118
120 static int tpa6130a2_power(int power) 119 static int tpa6130a2_power(u8 power)
121 { 120 {
122 struct tpa6130a2_data *data; 121 struct tpa6130a2_data *data;
123 u8 val; 122 u8 val;
124 int ret = 0; 123 int ret = 0;
125 124
126 BUG_ON(tpa6130a2_client == NULL); 125 BUG_ON(tpa6130a2_client == NULL);
127 data = i2c_get_clientdata(tpa6130a2_client); 126 data = i2c_get_clientdata(tpa6130a2_client);
128 127
129 mutex_lock(&data->mutex); 128 mutex_lock(&data->mutex);
130 » if (power && !data->power_state) { 129 » if (power == data->power_state)
131 » » /* Power on */ 130 » » goto exit;
132 » » if (data->power_gpio >= 0)
133 » » » gpio_set_value(data->power_gpio, 1);
134 131
132 if (power) {
135 ret = regulator_enable(data->supply); 133 ret = regulator_enable(data->supply);
136 if (ret != 0) { 134 if (ret != 0) {
137 dev_err(&tpa6130a2_client->dev, 135 dev_err(&tpa6130a2_client->dev,
138 "Failed to enable supply: %d\n", ret); 136 "Failed to enable supply: %d\n", ret);
139 goto exit; 137 goto exit;
140 } 138 }
139 /* Power on */
140 if (data->power_gpio >= 0)
141 gpio_set_value(data->power_gpio, 1);
141 142
142 data->power_state = 1; 143 data->power_state = 1;
143 ret = tpa6130a2_initialize(); 144 ret = tpa6130a2_initialize();
144 if (ret < 0) { 145 if (ret < 0) {
145 dev_err(&tpa6130a2_client->dev, 146 dev_err(&tpa6130a2_client->dev,
146 "Failed to initialize chip\n"); 147 "Failed to initialize chip\n");
147 if (data->power_gpio >= 0) 148 if (data->power_gpio >= 0)
148 gpio_set_value(data->power_gpio, 0); 149 gpio_set_value(data->power_gpio, 0);
149 regulator_disable(data->supply); 150 regulator_disable(data->supply);
150 data->power_state = 0; 151 data->power_state = 0;
151 goto exit; 152 goto exit;
152 } 153 }
153 154 » } else {
154 » » /* Clear SWS */
155 » » val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
156 » » val &= ~TPA6130A2_SWS;
157 » » tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
158 » } else if (!power && data->power_state) {
159 /* set SWS */ 155 /* set SWS */
160 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 156 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
161 val |= TPA6130A2_SWS; 157 val |= TPA6130A2_SWS;
162 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 158 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
163 159
164 /* Power off */ 160 /* Power off */
165 if (data->power_gpio >= 0) 161 if (data->power_gpio >= 0)
166 gpio_set_value(data->power_gpio, 0); 162 gpio_set_value(data->power_gpio, 0);
167 163
168 ret = regulator_disable(data->supply); 164 ret = regulator_disable(data->supply);
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
293 */ 289 */
294 static void tpa6130a2_channel_enable(u8 channel, int enable) 290 static void tpa6130a2_channel_enable(u8 channel, int enable)
295 { 291 {
296 u8 val; 292 u8 val;
297 293
298 if (enable) { 294 if (enable) {
299 /* Enable channel */ 295 /* Enable channel */
300 /* Enable amplifier */ 296 /* Enable amplifier */
301 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 297 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
302 val |= channel; 298 val |= channel;
299 val &= ~TPA6130A2_SWS;
303 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 300 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
304 301
305 /* Unmute channel */ 302 /* Unmute channel */
306 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); 303 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
307 val &= ~channel; 304 val &= ~channel;
308 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); 305 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
309 } else { 306 } else {
310 /* Disable channel */ 307 /* Disable channel */
311 /* Mute channel */ 308 /* Mute channel */
312 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE); 309 val = tpa6130a2_read(TPA6130A2_REG_VOL_MUTE);
313 val |= channel; 310 val |= channel;
314 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val); 311 tpa6130a2_i2c_write(TPA6130A2_REG_VOL_MUTE, val);
315 312
316 /* Disable amplifier */ 313 /* Disable amplifier */
317 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 314 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
318 val &= ~channel; 315 val &= ~channel;
319 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 316 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
320 } 317 }
321 } 318 }
322 319
323 static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w, 320 int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable)
324 » » struct snd_kcontrol *kcontrol, int event)
325 {
326 » switch (event) {
327 » case SND_SOC_DAPM_POST_PMU:
328 » » tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1);
329 » » break;
330 » case SND_SOC_DAPM_POST_PMD:
331 » » tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0);
332 » » break;
333 » }
334 » return 0;
335 }
336
337 static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
338 » » struct snd_kcontrol *kcontrol, int event)
339 {
340 » switch (event) {
341 » case SND_SOC_DAPM_POST_PMU:
342 » » tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1);
343 » » break;
344 » case SND_SOC_DAPM_POST_PMD:
345 » » tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0);
346 » » break;
347 » }
348 » return 0;
349 }
350
351 static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
352 » » struct snd_kcontrol *kcontrol, int event)
353 { 321 {
354 int ret = 0; 322 int ret = 0;
323 if (enable) {
324 ret = tpa6130a2_power(1);
325 if (ret < 0)
326 return ret;
327 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
328 1);
329 } else {
330 tpa6130a2_channel_enable(TPA6130A2_HP_EN_R | TPA6130A2_HP_EN_L,
331 0);
332 ret = tpa6130a2_power(0);
333 }
355 334
356 switch (event) {
357 case SND_SOC_DAPM_POST_PMU:
358 ret = tpa6130a2_power(1);
359 break;
360 case SND_SOC_DAPM_POST_PMD:
361 ret = tpa6130a2_power(0);
362 break;
363 }
364 return ret; 335 return ret;
365 } 336 }
366 337 EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
367 static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
368 » SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM,
369 » » » 0, 0, NULL, 0, tpa6130a2_left_event,
370 » » » SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
371 » SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM,
372 » » » 0, 0, NULL, 0, tpa6130a2_right_event,
373 » » » SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
374 » SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM,
375 » » » 0, 0, tpa6130a2_supply_event,
376 » » » SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
377 » /* Outputs */
378 » SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
379 » SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
380 };
381
382 static const struct snd_soc_dapm_route audio_map[] = {
383 » {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"},
384 » {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"},
385
386 » {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"},
387 » {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"},
388 };
389 338
390 int tpa6130a2_add_controls(struct snd_soc_codec *codec) 339 int tpa6130a2_add_controls(struct snd_soc_codec *codec)
391 { 340 {
392 struct tpa6130a2_data *data; 341 struct tpa6130a2_data *data;
393 342
394 if (tpa6130a2_client == NULL) 343 if (tpa6130a2_client == NULL)
395 return -ENODEV; 344 return -ENODEV;
396 345
397 data = i2c_get_clientdata(tpa6130a2_client); 346 data = i2c_get_clientdata(tpa6130a2_client);
398 347
399 snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets,
400 ARRAY_SIZE(tpa6130a2_dapm_widgets));
401
402 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
403
404 if (data->id == TPA6140A2) 348 if (data->id == TPA6140A2)
405 return snd_soc_add_controls(codec, tpa6140a2_controls, 349 return snd_soc_add_controls(codec, tpa6140a2_controls,
406 ARRAY_SIZE(tpa6140a2_controls)); 350 ARRAY_SIZE(tpa6140a2_controls));
407 else 351 else
408 return snd_soc_add_controls(codec, tpa6130a2_controls, 352 return snd_soc_add_controls(codec, tpa6130a2_controls,
409 ARRAY_SIZE(tpa6130a2_controls)); 353 ARRAY_SIZE(tpa6130a2_controls));
410
411 } 354 }
412 EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); 355 EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
413 356
414 static int __devinit tpa6130a2_probe(struct i2c_client *client, 357 static int __devinit tpa6130a2_probe(struct i2c_client *client,
415 const struct i2c_device_id *id) 358 const struct i2c_device_id *id)
416 { 359 {
417 struct device *dev; 360 struct device *dev;
418 struct tpa6130a2_data *data; 361 struct tpa6130a2_data *data;
419 struct tpa6130a2_platform_data *pdata; 362 struct tpa6130a2_platform_data *pdata;
420 const char *regulator; 363 const char *regulator;
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after
551 { 494 {
552 i2c_del_driver(&tpa6130a2_i2c_driver); 495 i2c_del_driver(&tpa6130a2_i2c_driver);
553 } 496 }
554 497
555 MODULE_AUTHOR("Peter Ujfalusi"); 498 MODULE_AUTHOR("Peter Ujfalusi");
556 MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); 499 MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver");
557 MODULE_LICENSE("GPL"); 500 MODULE_LICENSE("GPL");
558 501
559 module_init(tpa6130a2_init); 502 module_init(tpa6130a2_init);
560 module_exit(tpa6130a2_exit); 503 module_exit(tpa6130a2_exit);
OLDNEW
« no previous file with comments | « sound/soc/codecs/tpa6130a2.h ('k') | sound/soc/codecs/twl4030.c » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698