aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tpa6130a2.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-03-01 11:58:44 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-03-01 11:58:44 -0500
commit524df55725217b13d5a232fb5badb5846418ea0e (patch)
treec041613577ac7e68737cfd8af16a37d1ed37e6af /sound/soc/codecs/tpa6130a2.c
parent0f4533979473a456a8adb3869365e12c7a99cf65 (diff)
parent6679ee1870f7ccdd48e2e5c57919240b8f19a6dc (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6: (252 commits) ASoC: Check progress when reporting periods from i.MX FIQ handler ASoC: Remove a unused variables from i.MX FIQ runtime data ALSA: hda - Add/fix ALC269 FSC and Quanta models ALSA: hda - Add ALC670 codec support OMAP4: PMIC: Add support for twl6030 codec ALSA: hda - remove unnecessary msleep on power state transitions usb/gadget/{f_audio,gmidi}.c: follow recent changes in audio.h ASoC: fsi: Modify over/under run error settlement ASoC: OMAP4: Add McPDM platform driver ASoC: OMAP4: Add support for McPDM ASoC: OMAP: data_type and sync_mode configurable in audio dma ALSA: hda - Add missing description in HD-Audio-Models.txt ALSA: add support for Macbook Air 2,1 internal speaker ALSA: usbaudio: consolidate header files ALSA: usbmixer: bail out early when parsing audio class v2 descriptors ALSA: usbaudio: implement basic set of class v2.0 parser ALSA: usbaudio: introduce new types for audio class v2 ALSA: usbaudio: parse USB descriptors with structs ALSA: hda - enable snoop for Intel Cougar Point ALSA: hda - Remove identical definitions for macmini3 model ...
Diffstat (limited to 'sound/soc/codecs/tpa6130a2.c')
-rw-r--r--sound/soc/codecs/tpa6130a2.c115
1 files changed, 91 insertions, 24 deletions
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index 6b650c1aa3d1..958d49c969ac 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -25,6 +25,7 @@
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 <sound/tpa6130a2-plat.h> 29#include <sound/tpa6130a2-plat.h>
29#include <sound/soc.h> 30#include <sound/soc.h>
30#include <sound/soc-dapm.h> 31#include <sound/soc-dapm.h>
@@ -34,10 +35,22 @@
34 35
35static struct i2c_client *tpa6130a2_client; 36static struct i2c_client *tpa6130a2_client;
36 37
38#define TPA6130A2_NUM_SUPPLIES 2
39static const char *tpa6130a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
40 "CPVSS",
41 "Vdd",
42};
43
44static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = {
45 "HPVdd",
46 "AVdd",
47};
48
37/* This struct is used to save the context */ 49/* This struct is used to save the context */
38struct tpa6130a2_data { 50struct tpa6130a2_data {
39 struct mutex mutex; 51 struct mutex mutex;
40 unsigned char regs[TPA6130A2_CACHEREGNUM]; 52 unsigned char regs[TPA6130A2_CACHEREGNUM];
53 struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES];
41 int power_gpio; 54 int power_gpio;
42 unsigned char power_state; 55 unsigned char power_state;
43}; 56};
@@ -106,10 +119,11 @@ static void tpa6130a2_initialize(void)
106 tpa6130a2_i2c_write(i, data->regs[i]); 119 tpa6130a2_i2c_write(i, data->regs[i]);
107} 120}
108 121
109static void tpa6130a2_power(int power) 122static int tpa6130a2_power(int power)
110{ 123{
111 struct tpa6130a2_data *data; 124 struct tpa6130a2_data *data;
112 u8 val; 125 u8 val;
126 int ret;
113 127
114 BUG_ON(tpa6130a2_client == NULL); 128 BUG_ON(tpa6130a2_client == NULL);
115 data = i2c_get_clientdata(tpa6130a2_client); 129 data = i2c_get_clientdata(tpa6130a2_client);
@@ -117,11 +131,20 @@ static void tpa6130a2_power(int power)
117 mutex_lock(&data->mutex); 131 mutex_lock(&data->mutex);
118 if (power) { 132 if (power) {
119 /* Power on */ 133 /* Power on */
120 if (data->power_gpio >= 0) { 134 if (data->power_gpio >= 0)
121 gpio_set_value(data->power_gpio, 1); 135 gpio_set_value(data->power_gpio, 1);
122 data->power_state = 1; 136
123 tpa6130a2_initialize(); 137 ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies),
138 data->supplies);
139 if (ret != 0) {
140 dev_err(&tpa6130a2_client->dev,
141 "Failed to enable supplies: %d\n", ret);
142 goto exit;
124 } 143 }
144
145 data->power_state = 1;
146 tpa6130a2_initialize();
147
125 /* Clear SWS */ 148 /* Clear SWS */
126 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 149 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
127 val &= ~TPA6130A2_SWS; 150 val &= ~TPA6130A2_SWS;
@@ -131,13 +154,25 @@ static void tpa6130a2_power(int power)
131 val = tpa6130a2_read(TPA6130A2_REG_CONTROL); 154 val = tpa6130a2_read(TPA6130A2_REG_CONTROL);
132 val |= TPA6130A2_SWS; 155 val |= TPA6130A2_SWS;
133 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); 156 tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val);
157
134 /* Power off */ 158 /* Power off */
135 if (data->power_gpio >= 0) { 159 if (data->power_gpio >= 0)
136 gpio_set_value(data->power_gpio, 0); 160 gpio_set_value(data->power_gpio, 0);
137 data->power_state = 0; 161
162 ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies),
163 data->supplies);
164 if (ret != 0) {
165 dev_err(&tpa6130a2_client->dev,
166 "Failed to disable supplies: %d\n", ret);
167 goto exit;
138 } 168 }
169
170 data->power_state = 0;
139 } 171 }
172
173exit:
140 mutex_unlock(&data->mutex); 174 mutex_unlock(&data->mutex);
175 return ret;
141} 176}
142 177
143static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, 178static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol,
@@ -237,12 +272,8 @@ static const struct snd_kcontrol_new tpa6130a2_controls[] = {
237 */ 272 */
238static void tpa6130a2_channel_enable(u8 channel, int enable) 273static void tpa6130a2_channel_enable(u8 channel, int enable)
239{ 274{
240 struct tpa6130a2_data *data;
241 u8 val; 275 u8 val;
242 276
243 BUG_ON(tpa6130a2_client == NULL);
244 data = i2c_get_clientdata(tpa6130a2_client);
245
246 if (enable) { 277 if (enable) {
247 /* Enable channel */ 278 /* Enable channel */
248 /* Enable amplifier */ 279 /* Enable amplifier */
@@ -299,15 +330,17 @@ static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w,
299static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w, 330static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w,
300 struct snd_kcontrol *kcontrol, int event) 331 struct snd_kcontrol *kcontrol, int event)
301{ 332{
333 int ret = 0;
334
302 switch (event) { 335 switch (event) {
303 case SND_SOC_DAPM_POST_PMU: 336 case SND_SOC_DAPM_POST_PMU:
304 tpa6130a2_power(1); 337 ret = tpa6130a2_power(1);
305 break; 338 break;
306 case SND_SOC_DAPM_POST_PMD: 339 case SND_SOC_DAPM_POST_PMD:
307 tpa6130a2_power(0); 340 ret = tpa6130a2_power(0);
308 break; 341 break;
309 } 342 }
310 return 0; 343 return ret;
311} 344}
312 345
313static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { 346static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
@@ -346,13 +379,13 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
346} 379}
347EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); 380EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
348 381
349static int tpa6130a2_probe(struct i2c_client *client, 382static int __devinit tpa6130a2_probe(struct i2c_client *client,
350 const struct i2c_device_id *id) 383 const struct i2c_device_id *id)
351{ 384{
352 struct device *dev; 385 struct device *dev;
353 struct tpa6130a2_data *data; 386 struct tpa6130a2_data *data;
354 struct tpa6130a2_platform_data *pdata; 387 struct tpa6130a2_platform_data *pdata;
355 int ret; 388 int i, ret;
356 389
357 dev = &client->dev; 390 dev = &client->dev;
358 391
@@ -387,15 +420,38 @@ static int tpa6130a2_probe(struct i2c_client *client,
387 if (ret < 0) { 420 if (ret < 0) {
388 dev_err(dev, "Failed to request power GPIO (%d)\n", 421 dev_err(dev, "Failed to request power GPIO (%d)\n",
389 data->power_gpio); 422 data->power_gpio);
390 goto fail; 423 goto err_gpio;
391 } 424 }
392 gpio_direction_output(data->power_gpio, 0); 425 gpio_direction_output(data->power_gpio, 0);
393 } else {
394 data->power_state = 1;
395 tpa6130a2_initialize();
396 } 426 }
397 427
398 tpa6130a2_power(1); 428 switch (pdata->id) {
429 case TPA6130A2:
430 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
431 data->supplies[i].supply = tpa6130a2_supply_names[i];
432 break;
433 case TPA6140A2:
434 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
435 data->supplies[i].supply = tpa6140a2_supply_names[i];;
436 break;
437 default:
438 dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
439 pdata->id);
440 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
441 data->supplies[i].supply = tpa6130a2_supply_names[i];
442 }
443
444 ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies),
445 data->supplies);
446 if (ret != 0) {
447 dev_err(dev, "Failed to request supplies: %d\n", ret);
448 goto err_regulator;
449 }
450
451 ret = tpa6130a2_power(1);
452 if (ret != 0)
453 goto err_power;
454
399 455
400 /* Read version */ 456 /* Read version */
401 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) & 457 ret = tpa6130a2_i2c_read(TPA6130A2_REG_VERSION) &
@@ -404,10 +460,18 @@ static int tpa6130a2_probe(struct i2c_client *client,
404 dev_warn(dev, "UNTESTED version detected (%d)\n", ret); 460 dev_warn(dev, "UNTESTED version detected (%d)\n", ret);
405 461
406 /* Disable the chip */ 462 /* Disable the chip */
407 tpa6130a2_power(0); 463 ret = tpa6130a2_power(0);
464 if (ret != 0)
465 goto err_power;
408 466
409 return 0; 467 return 0;
410fail: 468
469err_power:
470 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
471err_regulator:
472 if (data->power_gpio >= 0)
473 gpio_free(data->power_gpio);
474err_gpio:
411 kfree(data); 475 kfree(data);
412 i2c_set_clientdata(tpa6130a2_client, NULL); 476 i2c_set_clientdata(tpa6130a2_client, NULL);
413 tpa6130a2_client = NULL; 477 tpa6130a2_client = NULL;
@@ -415,7 +479,7 @@ fail:
415 return ret; 479 return ret;
416} 480}
417 481
418static int tpa6130a2_remove(struct i2c_client *client) 482static int __devexit tpa6130a2_remove(struct i2c_client *client)
419{ 483{
420 struct tpa6130a2_data *data = i2c_get_clientdata(client); 484 struct tpa6130a2_data *data = i2c_get_clientdata(client);
421 485
@@ -423,6 +487,9 @@ static int tpa6130a2_remove(struct i2c_client *client)
423 487
424 if (data->power_gpio >= 0) 488 if (data->power_gpio >= 0)
425 gpio_free(data->power_gpio); 489 gpio_free(data->power_gpio);
490
491 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies);
492
426 kfree(data); 493 kfree(data);
427 tpa6130a2_client = NULL; 494 tpa6130a2_client = NULL;
428 495