aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/tpa6130a2.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/tpa6130a2.c')
-rw-r--r--sound/soc/codecs/tpa6130a2.c99
1 files changed, 21 insertions, 78 deletions
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index d2c243095673..1f1ac8110bef 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -29,7 +29,6 @@
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"
@@ -42,7 +41,7 @@ struct tpa6130a2_data {
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
@@ -117,7 +116,7 @@ static int tpa6130a2_initialize(void)
117 return ret; 116 return ret;
118} 117}
119 118
120static int tpa6130a2_power(int power) 119static int tpa6130a2_power(u8 power)
121{ 120{
122 struct tpa6130a2_data *data; 121 struct tpa6130a2_data *data;
123 u8 val; 122 u8 val;
@@ -127,17 +126,19 @@ static int tpa6130a2_power(int power)
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();
@@ -150,12 +151,7 @@ static int tpa6130a2_power(int power)
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;
@@ -300,6 +296,7 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
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 */
@@ -320,72 +317,24 @@ static void tpa6130a2_channel_enable(u8 channel, int enable)
320 } 317 }
321} 318}
322 319
323static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w, 320int 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
337static 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
351static 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;
355 323 if (enable) {
356 switch (event) {
357 case SND_SOC_DAPM_POST_PMU:
358 ret = tpa6130a2_power(1); 324 ret = tpa6130a2_power(1);
359 break; 325 if (ret < 0)
360 case SND_SOC_DAPM_POST_PMD: 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);
361 ret = tpa6130a2_power(0); 332 ret = tpa6130a2_power(0);
362 break;
363 } 333 }
334
364 return ret; 335 return ret;
365} 336}
366 337EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable);
367static 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
382static 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
390int tpa6130a2_add_controls(struct snd_soc_codec *codec) 339int tpa6130a2_add_controls(struct snd_soc_codec *codec)
391{ 340{
@@ -396,18 +345,12 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec)
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}
412EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); 355EXPORT_SYMBOL_GPL(tpa6130a2_add_controls);
413 356