diff options
Diffstat (limited to 'sound/soc/codecs/tpa6130a2.c')
-rw-r--r-- | sound/soc/codecs/tpa6130a2.c | 103 |
1 files changed, 24 insertions, 79 deletions
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index ee4fb201de60..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 | ||
@@ -78,8 +77,10 @@ static int tpa6130a2_i2c_write(int reg, u8 value) | |||
78 | 77 | ||
79 | if (data->power_state) { | 78 | if (data->power_state) { |
80 | val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); | 79 | val = i2c_smbus_write_byte_data(tpa6130a2_client, reg, value); |
81 | if (val < 0) | 80 | if (val < 0) { |
82 | dev_err(&tpa6130a2_client->dev, "Write failed\n"); | 81 | dev_err(&tpa6130a2_client->dev, "Write failed\n"); |
82 | return val; | ||
83 | } | ||
83 | } | 84 | } |
84 | 85 | ||
85 | /* Either powered on or off, we save the context */ | 86 | /* Either powered on or off, we save the context */ |
@@ -115,7 +116,7 @@ static int tpa6130a2_initialize(void) | |||
115 | return ret; | 116 | return ret; |
116 | } | 117 | } |
117 | 118 | ||
118 | static int tpa6130a2_power(int power) | 119 | static int tpa6130a2_power(u8 power) |
119 | { | 120 | { |
120 | struct tpa6130a2_data *data; | 121 | struct tpa6130a2_data *data; |
121 | u8 val; | 122 | u8 val; |
@@ -125,17 +126,19 @@ static int tpa6130a2_power(int power) | |||
125 | data = i2c_get_clientdata(tpa6130a2_client); | 126 | data = i2c_get_clientdata(tpa6130a2_client); |
126 | 127 | ||
127 | mutex_lock(&data->mutex); | 128 | mutex_lock(&data->mutex); |
128 | if (power && !data->power_state) { | 129 | if (power == data->power_state) |
129 | /* Power on */ | 130 | goto exit; |
130 | if (data->power_gpio >= 0) | ||
131 | gpio_set_value(data->power_gpio, 1); | ||
132 | 131 | ||
132 | if (power) { | ||
133 | ret = regulator_enable(data->supply); | 133 | ret = regulator_enable(data->supply); |
134 | if (ret != 0) { | 134 | if (ret != 0) { |
135 | dev_err(&tpa6130a2_client->dev, | 135 | dev_err(&tpa6130a2_client->dev, |
136 | "Failed to enable supply: %d\n", ret); | 136 | "Failed to enable supply: %d\n", ret); |
137 | goto exit; | 137 | goto exit; |
138 | } | 138 | } |
139 | /* Power on */ | ||
140 | if (data->power_gpio >= 0) | ||
141 | gpio_set_value(data->power_gpio, 1); | ||
139 | 142 | ||
140 | data->power_state = 1; | 143 | data->power_state = 1; |
141 | ret = tpa6130a2_initialize(); | 144 | ret = tpa6130a2_initialize(); |
@@ -148,12 +151,7 @@ static int tpa6130a2_power(int power) | |||
148 | data->power_state = 0; | 151 | data->power_state = 0; |
149 | goto exit; | 152 | goto exit; |
150 | } | 153 | } |
151 | 154 | } else { | |
152 | /* Clear SWS */ | ||
153 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | ||
154 | val &= ~TPA6130A2_SWS; | ||
155 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | ||
156 | } else if (!power && data->power_state) { | ||
157 | /* set SWS */ | 155 | /* set SWS */ |
158 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | 156 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); |
159 | val |= TPA6130A2_SWS; | 157 | val |= TPA6130A2_SWS; |
@@ -298,6 +296,7 @@ static void tpa6130a2_channel_enable(u8 channel, int enable) | |||
298 | /* Enable amplifier */ | 296 | /* Enable amplifier */ |
299 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); | 297 | val = tpa6130a2_read(TPA6130A2_REG_CONTROL); |
300 | val |= channel; | 298 | val |= channel; |
299 | val &= ~TPA6130A2_SWS; | ||
301 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); | 300 | tpa6130a2_i2c_write(TPA6130A2_REG_CONTROL, val); |
302 | 301 | ||
303 | /* Unmute channel */ | 302 | /* Unmute channel */ |
@@ -318,72 +317,24 @@ static void tpa6130a2_channel_enable(u8 channel, int enable) | |||
318 | } | 317 | } |
319 | } | 318 | } |
320 | 319 | ||
321 | static int tpa6130a2_left_event(struct snd_soc_dapm_widget *w, | 320 | int tpa6130a2_stereo_enable(struct snd_soc_codec *codec, int enable) |
322 | struct snd_kcontrol *kcontrol, int event) | ||
323 | { | ||
324 | switch (event) { | ||
325 | case SND_SOC_DAPM_POST_PMU: | ||
326 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 1); | ||
327 | break; | ||
328 | case SND_SOC_DAPM_POST_PMD: | ||
329 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_L, 0); | ||
330 | break; | ||
331 | } | ||
332 | return 0; | ||
333 | } | ||
334 | |||
335 | static int tpa6130a2_right_event(struct snd_soc_dapm_widget *w, | ||
336 | struct snd_kcontrol *kcontrol, int event) | ||
337 | { | ||
338 | switch (event) { | ||
339 | case SND_SOC_DAPM_POST_PMU: | ||
340 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 1); | ||
341 | break; | ||
342 | case SND_SOC_DAPM_POST_PMD: | ||
343 | tpa6130a2_channel_enable(TPA6130A2_HP_EN_R, 0); | ||
344 | break; | ||
345 | } | ||
346 | return 0; | ||
347 | } | ||
348 | |||
349 | static int tpa6130a2_supply_event(struct snd_soc_dapm_widget *w, | ||
350 | struct snd_kcontrol *kcontrol, int event) | ||
351 | { | 321 | { |
352 | int ret = 0; | 322 | int ret = 0; |
353 | 323 | if (enable) { | |
354 | switch (event) { | ||
355 | case SND_SOC_DAPM_POST_PMU: | ||
356 | ret = tpa6130a2_power(1); | 324 | ret = tpa6130a2_power(1); |
357 | break; | 325 | if (ret < 0) |
358 | 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); | ||
359 | ret = tpa6130a2_power(0); | 332 | ret = tpa6130a2_power(0); |
360 | break; | ||
361 | } | 333 | } |
334 | |||
362 | return ret; | 335 | return ret; |
363 | } | 336 | } |
364 | 337 | EXPORT_SYMBOL_GPL(tpa6130a2_stereo_enable); | |
365 | static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = { | ||
366 | SND_SOC_DAPM_PGA_E("TPA6130A2 Left", SND_SOC_NOPM, | ||
367 | 0, 0, NULL, 0, tpa6130a2_left_event, | ||
368 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
369 | SND_SOC_DAPM_PGA_E("TPA6130A2 Right", SND_SOC_NOPM, | ||
370 | 0, 0, NULL, 0, tpa6130a2_right_event, | ||
371 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
372 | SND_SOC_DAPM_SUPPLY("TPA6130A2 Enable", SND_SOC_NOPM, | ||
373 | 0, 0, tpa6130a2_supply_event, | ||
374 | SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), | ||
375 | /* Outputs */ | ||
376 | SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"), | ||
377 | SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"), | ||
378 | }; | ||
379 | |||
380 | static const struct snd_soc_dapm_route audio_map[] = { | ||
381 | {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Left"}, | ||
382 | {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Right"}, | ||
383 | |||
384 | {"TPA6130A2 Headphone Left", NULL, "TPA6130A2 Enable"}, | ||
385 | {"TPA6130A2 Headphone Right", NULL, "TPA6130A2 Enable"}, | ||
386 | }; | ||
387 | 338 | ||
388 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) | 339 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) |
389 | { | 340 | { |
@@ -394,18 +345,12 @@ int tpa6130a2_add_controls(struct snd_soc_codec *codec) | |||
394 | 345 | ||
395 | data = i2c_get_clientdata(tpa6130a2_client); | 346 | data = i2c_get_clientdata(tpa6130a2_client); |
396 | 347 | ||
397 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, | ||
398 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); | ||
399 | |||
400 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
401 | |||
402 | if (data->id == TPA6140A2) | 348 | if (data->id == TPA6140A2) |
403 | return snd_soc_add_controls(codec, tpa6140a2_controls, | 349 | return snd_soc_add_controls(codec, tpa6140a2_controls, |
404 | ARRAY_SIZE(tpa6140a2_controls)); | 350 | ARRAY_SIZE(tpa6140a2_controls)); |
405 | else | 351 | else |
406 | return snd_soc_add_controls(codec, tpa6130a2_controls, | 352 | return snd_soc_add_controls(codec, tpa6130a2_controls, |
407 | ARRAY_SIZE(tpa6130a2_controls)); | 353 | ARRAY_SIZE(tpa6130a2_controls)); |
408 | |||
409 | } | 354 | } |
410 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); | 355 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); |
411 | 356 | ||