aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/omap/rx51.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/omap/rx51.c')
-rw-r--r--sound/soc/omap/rx51.c197
1 files changed, 150 insertions, 47 deletions
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c
index 88052d29617f..0aae998b6540 100644
--- a/sound/soc/omap/rx51.c
+++ b/sound/soc/omap/rx51.c
@@ -3,7 +3,7 @@
3 * 3 *
4 * Copyright (C) 2008 - 2009 Nokia Corporation 4 * Copyright (C) 2008 - 2009 Nokia Corporation
5 * 5 *
6 * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com> 6 * Contact: Peter Ujfalusi <peter.ujfalusi@ti.com>
7 * Eduardo Valentin <eduardo.valentin@nokia.com> 7 * Eduardo Valentin <eduardo.valentin@nokia.com>
8 * Jarkko Nikula <jhnikula@gmail.com> 8 * Jarkko Nikula <jhnikula@gmail.com>
9 * 9 *
@@ -30,16 +30,17 @@
30#include <sound/jack.h> 30#include <sound/jack.h>
31#include <sound/pcm.h> 31#include <sound/pcm.h>
32#include <sound/soc.h> 32#include <sound/soc.h>
33#include <sound/soc-dapm.h> 33#include <plat/mcbsp.h>
34#include "../codecs/tpa6130a2.h"
34 35
35#include <asm/mach-types.h> 36#include <asm/mach-types.h>
36 37
37#include "omap-mcbsp.h" 38#include "omap-mcbsp.h"
38#include "omap-pcm.h" 39#include "omap-pcm.h"
39#include "../codecs/tlv320aic3x.h"
40 40
41#define RX51_TVOUT_SEL_GPIO 40 41#define RX51_TVOUT_SEL_GPIO 40
42#define RX51_JACK_DETECT_GPIO 177 42#define RX51_JACK_DETECT_GPIO 177
43#define RX51_ECI_SW_GPIO 182
43/* 44/*
44 * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This 45 * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This
45 * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c 46 * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c
@@ -48,7 +49,9 @@
48 49
49enum { 50enum {
50 RX51_JACK_DISABLED, 51 RX51_JACK_DISABLED,
51 RX51_JACK_TVOUT, /* tv-out */ 52 RX51_JACK_TVOUT, /* tv-out with stereo output */
53 RX51_JACK_HP, /* headphone: stereo output, no mic */
54 RX51_JACK_HS, /* headset: stereo output with mic */
52}; 55};
53 56
54static int rx51_spk_func; 57static int rx51_spk_func;
@@ -57,26 +60,48 @@ static int rx51_jack_func;
57 60
58static void rx51_ext_control(struct snd_soc_codec *codec) 61static void rx51_ext_control(struct snd_soc_codec *codec)
59{ 62{
63 struct snd_soc_dapm_context *dapm = &codec->dapm;
64 int hp = 0, hs = 0, tvout = 0;
65
66 switch (rx51_jack_func) {
67 case RX51_JACK_TVOUT:
68 tvout = 1;
69 hp = 1;
70 break;
71 case RX51_JACK_HS:
72 hs = 1;
73 case RX51_JACK_HP:
74 hp = 1;
75 break;
76 }
77
60 if (rx51_spk_func) 78 if (rx51_spk_func)
61 snd_soc_dapm_enable_pin(codec, "Ext Spk"); 79 snd_soc_dapm_enable_pin(dapm, "Ext Spk");
62 else 80 else
63 snd_soc_dapm_disable_pin(codec, "Ext Spk"); 81 snd_soc_dapm_disable_pin(dapm, "Ext Spk");
64 if (rx51_dmic_func) 82 if (rx51_dmic_func)
65 snd_soc_dapm_enable_pin(codec, "DMic"); 83 snd_soc_dapm_enable_pin(dapm, "DMic");
84 else
85 snd_soc_dapm_disable_pin(dapm, "DMic");
86 if (hp)
87 snd_soc_dapm_enable_pin(dapm, "Headphone Jack");
66 else 88 else
67 snd_soc_dapm_disable_pin(codec, "DMic"); 89 snd_soc_dapm_disable_pin(dapm, "Headphone Jack");
90 if (hs)
91 snd_soc_dapm_enable_pin(dapm, "HS Mic");
92 else
93 snd_soc_dapm_disable_pin(dapm, "HS Mic");
68 94
69 gpio_set_value(RX51_TVOUT_SEL_GPIO, 95 gpio_set_value(RX51_TVOUT_SEL_GPIO, tvout);
70 rx51_jack_func == RX51_JACK_TVOUT);
71 96
72 snd_soc_dapm_sync(codec); 97 snd_soc_dapm_sync(dapm);
73} 98}
74 99
75static int rx51_startup(struct snd_pcm_substream *substream) 100static int rx51_startup(struct snd_pcm_substream *substream)
76{ 101{
77 struct snd_pcm_runtime *runtime = substream->runtime; 102 struct snd_pcm_runtime *runtime = substream->runtime;
78 struct snd_soc_pcm_runtime *rtd = substream->private_data; 103 struct snd_soc_pcm_runtime *rtd = substream->private_data;
79 struct snd_soc_codec *codec = rtd->socdev->card->codec; 104 struct snd_soc_codec *codec = rtd->codec;
80 105
81 snd_pcm_hw_constraint_minmax(runtime, 106 snd_pcm_hw_constraint_minmax(runtime,
82 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); 107 SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2);
@@ -89,8 +114,8 @@ static int rx51_hw_params(struct snd_pcm_substream *substream,
89 struct snd_pcm_hw_params *params) 114 struct snd_pcm_hw_params *params)
90{ 115{
91 struct snd_soc_pcm_runtime *rtd = substream->private_data; 116 struct snd_soc_pcm_runtime *rtd = substream->private_data;
92 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; 117 struct snd_soc_dai *codec_dai = rtd->codec_dai;
93 struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; 118 struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
94 int err; 119 int err;
95 120
96 /* Set codec DAI configuration */ 121 /* Set codec DAI configuration */
@@ -145,9 +170,22 @@ static int rx51_spk_event(struct snd_soc_dapm_widget *w,
145 struct snd_kcontrol *k, int event) 170 struct snd_kcontrol *k, int event)
146{ 171{
147 if (SND_SOC_DAPM_EVENT_ON(event)) 172 if (SND_SOC_DAPM_EVENT_ON(event))
148 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1); 173 gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 1);
174 else
175 gpio_set_value_cansleep(RX51_SPEAKER_AMP_TWL_GPIO, 0);
176
177 return 0;
178}
179
180static int rx51_hp_event(struct snd_soc_dapm_widget *w,
181 struct snd_kcontrol *k, int event)
182{
183 struct snd_soc_codec *codec = w->dapm->codec;
184
185 if (SND_SOC_DAPM_EVENT_ON(event))
186 tpa6130a2_stereo_enable(codec, 1);
149 else 187 else
150 gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0); 188 tpa6130a2_stereo_enable(codec, 0);
151 189
152 return 0; 190 return 0;
153} 191}
@@ -202,7 +240,7 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
202 { 240 {
203 .gpio = RX51_JACK_DETECT_GPIO, 241 .gpio = RX51_JACK_DETECT_GPIO,
204 .name = "avdet-gpio", 242 .name = "avdet-gpio",
205 .report = SND_JACK_VIDEOOUT, 243 .report = SND_JACK_HEADSET,
206 .invert = 1, 244 .invert = 1,
207 .debounce_time = 200, 245 .debounce_time = 200,
208 }, 246 },
@@ -211,19 +249,38 @@ static struct snd_soc_jack_gpio rx51_av_jack_gpios[] = {
211static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { 249static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = {
212 SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), 250 SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event),
213 SND_SOC_DAPM_MIC("DMic", NULL), 251 SND_SOC_DAPM_MIC("DMic", NULL),
252 SND_SOC_DAPM_HP("Headphone Jack", rx51_hp_event),
253 SND_SOC_DAPM_MIC("HS Mic", NULL),
254 SND_SOC_DAPM_LINE("FM Transmitter", NULL),
255};
256
257static const struct snd_soc_dapm_widget aic34_dapm_widgetsb[] = {
258 SND_SOC_DAPM_SPK("Earphone", NULL),
214}; 259};
215 260
216static const struct snd_soc_dapm_route audio_map[] = { 261static const struct snd_soc_dapm_route audio_map[] = {
217 {"Ext Spk", NULL, "HPLOUT"}, 262 {"Ext Spk", NULL, "HPLOUT"},
218 {"Ext Spk", NULL, "HPROUT"}, 263 {"Ext Spk", NULL, "HPROUT"},
264 {"Headphone Jack", NULL, "LLOUT"},
265 {"Headphone Jack", NULL, "RLOUT"},
266 {"FM Transmitter", NULL, "LLOUT"},
267 {"FM Transmitter", NULL, "RLOUT"},
219 268
220 {"DMic Rate 64", NULL, "Mic Bias 2V"}, 269 {"DMic Rate 64", NULL, "Mic Bias 2V"},
221 {"Mic Bias 2V", NULL, "DMic"}, 270 {"Mic Bias 2V", NULL, "DMic"},
222}; 271};
223 272
273static const struct snd_soc_dapm_route audio_mapb[] = {
274 {"b LINE2R", NULL, "MONO_LOUT"},
275 {"Earphone", NULL, "b HPLOUT"},
276
277 {"LINE1L", NULL, "b Mic Bias 2.5V"},
278 {"b Mic Bias 2.5V", NULL, "HS Mic"}
279};
280
224static const char *spk_function[] = {"Off", "On"}; 281static const char *spk_function[] = {"Off", "On"};
225static const char *input_function[] = {"ADC", "Digital Mic"}; 282static const char *input_function[] = {"ADC", "Digital Mic"};
226static const char *jack_function[] = {"Off", "TV-OUT"}; 283static const char *jack_function[] = {"Off", "TV-OUT", "Headphone", "Headset"};
227 284
228static const struct soc_enum rx51_enum[] = { 285static const struct soc_enum rx51_enum[] = {
229 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), 286 SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function),
@@ -238,17 +295,23 @@ static const struct snd_kcontrol_new aic34_rx51_controls[] = {
238 rx51_get_input, rx51_set_input), 295 rx51_get_input, rx51_set_input),
239 SOC_ENUM_EXT("Jack Function", rx51_enum[2], 296 SOC_ENUM_EXT("Jack Function", rx51_enum[2],
240 rx51_get_jack, rx51_set_jack), 297 rx51_get_jack, rx51_set_jack),
298 SOC_DAPM_PIN_SWITCH("FM Transmitter"),
241}; 299};
242 300
243static int rx51_aic34_init(struct snd_soc_codec *codec) 301static const struct snd_kcontrol_new aic34_rx51_controlsb[] = {
302 SOC_DAPM_PIN_SWITCH("Earphone"),
303};
304
305static int rx51_aic34_init(struct snd_soc_pcm_runtime *rtd)
244{ 306{
245 struct snd_soc_card *card = codec->socdev->card; 307 struct snd_soc_codec *codec = rtd->codec;
308 struct snd_soc_dapm_context *dapm = &codec->dapm;
246 int err; 309 int err;
247 310
248 /* Set up NC codec pins */ 311 /* Set up NC codec pins */
249 snd_soc_dapm_nc_pin(codec, "MIC3L"); 312 snd_soc_dapm_nc_pin(dapm, "MIC3L");
250 snd_soc_dapm_nc_pin(codec, "MIC3R"); 313 snd_soc_dapm_nc_pin(dapm, "MIC3R");
251 snd_soc_dapm_nc_pin(codec, "LINE1R"); 314 snd_soc_dapm_nc_pin(dapm, "LINE1R");
252 315
253 /* Add RX-51 specific controls */ 316 /* Add RX-51 specific controls */
254 err = snd_soc_add_controls(codec, aic34_rx51_controls, 317 err = snd_soc_add_controls(codec, aic34_rx51_controls,
@@ -257,17 +320,27 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)
257 return err; 320 return err;
258 321
259 /* Add RX-51 specific widgets */ 322 /* Add RX-51 specific widgets */
260 snd_soc_dapm_new_controls(codec, aic34_dapm_widgets, 323 snd_soc_dapm_new_controls(dapm, aic34_dapm_widgets,
261 ARRAY_SIZE(aic34_dapm_widgets)); 324 ARRAY_SIZE(aic34_dapm_widgets));
262 325
263 /* Set up RX-51 specific audio path audio_map */ 326 /* Set up RX-51 specific audio path audio_map */
264 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); 327 snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
265 328
266 snd_soc_dapm_sync(codec); 329 err = tpa6130a2_add_controls(codec);
330 if (err < 0)
331 return err;
332 snd_soc_limit_volume(codec, "TPA6130A2 Headphone Playback Volume", 42);
333
334 err = omap_mcbsp_st_add_controls(codec, 1);
335 if (err < 0)
336 return err;
337
338 snd_soc_dapm_sync(dapm);
267 339
268 /* AV jack detection */ 340 /* AV jack detection */
269 err = snd_soc_jack_new(card, "AV Jack", 341 err = snd_soc_jack_new(codec, "AV Jack",
270 SND_JACK_VIDEOOUT, &rx51_av_jack); 342 SND_JACK_HEADSET | SND_JACK_VIDEOOUT,
343 &rx51_av_jack);
271 if (err) 344 if (err)
272 return err; 345 return err;
273 err = snd_soc_jack_add_gpios(&rx51_av_jack, 346 err = snd_soc_jack_add_gpios(&rx51_av_jack,
@@ -277,22 +350,51 @@ static int rx51_aic34_init(struct snd_soc_codec *codec)
277 return err; 350 return err;
278} 351}
279 352
353static int rx51_aic34b_init(struct snd_soc_dapm_context *dapm)
354{
355 int err;
356
357 err = snd_soc_add_controls(dapm->codec, aic34_rx51_controlsb,
358 ARRAY_SIZE(aic34_rx51_controlsb));
359 if (err < 0)
360 return err;
361
362 err = snd_soc_dapm_new_controls(dapm, aic34_dapm_widgetsb,
363 ARRAY_SIZE(aic34_dapm_widgetsb));
364 if (err < 0)
365 return 0;
366
367 return snd_soc_dapm_add_routes(dapm, audio_mapb,
368 ARRAY_SIZE(audio_mapb));
369}
370
280/* Digital audio interface glue - connects codec <--> CPU */ 371/* Digital audio interface glue - connects codec <--> CPU */
281static struct snd_soc_dai_link rx51_dai[] = { 372static struct snd_soc_dai_link rx51_dai[] = {
282 { 373 {
283 .name = "TLV320AIC34", 374 .name = "TLV320AIC34",
284 .stream_name = "AIC34", 375 .stream_name = "AIC34",
285 .cpu_dai = &omap_mcbsp_dai[0], 376 .cpu_dai_name = "omap-mcbsp-dai.1",
286 .codec_dai = &aic3x_dai, 377 .codec_dai_name = "tlv320aic3x-hifi",
378 .platform_name = "omap-pcm-audio",
379 .codec_name = "tlv320aic3x-codec.2-0018",
287 .init = rx51_aic34_init, 380 .init = rx51_aic34_init,
288 .ops = &rx51_ops, 381 .ops = &rx51_ops,
289 }, 382 },
290}; 383};
291 384
292/* Audio private data */ 385struct snd_soc_aux_dev rx51_aux_dev[] = {
293static struct aic3x_setup_data rx51_aic34_setup = { 386 {
294 .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, 387 .name = "TLV320AIC34b",
295 .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, 388 .codec_name = "tlv320aic3x-codec.2-0019",
389 .init = rx51_aic34b_init,
390 },
391};
392
393static struct snd_soc_codec_conf rx51_codec_conf[] = {
394 {
395 .dev_name = "tlv320aic3x-codec.2-0019",
396 .name_prefix = "b",
397 },
296}; 398};
297 399
298/* Audio card */ 400/* Audio card */
@@ -300,14 +402,10 @@ static struct snd_soc_card rx51_sound_card = {
300 .name = "RX-51", 402 .name = "RX-51",
301 .dai_link = rx51_dai, 403 .dai_link = rx51_dai,
302 .num_links = ARRAY_SIZE(rx51_dai), 404 .num_links = ARRAY_SIZE(rx51_dai),
303 .platform = &omap_soc_platform, 405 .aux_dev = rx51_aux_dev,
304}; 406 .num_aux_devs = ARRAY_SIZE(rx51_aux_dev),
305 407 .codec_conf = rx51_codec_conf,
306/* Audio subsystem */ 408 .num_configs = ARRAY_SIZE(rx51_codec_conf),
307static struct snd_soc_device rx51_snd_devdata = {
308 .card = &rx51_sound_card,
309 .codec_dev = &soc_codec_dev_aic3x,
310 .codec_data = &rx51_aic34_setup,
311}; 409};
312 410
313static struct platform_device *rx51_snd_device; 411static struct platform_device *rx51_snd_device;
@@ -319,10 +417,14 @@ static int __init rx51_soc_init(void)
319 if (!machine_is_nokia_rx51()) 417 if (!machine_is_nokia_rx51())
320 return -ENODEV; 418 return -ENODEV;
321 419
322 err = gpio_request(RX51_TVOUT_SEL_GPIO, "tvout_sel"); 420 err = gpio_request_one(RX51_TVOUT_SEL_GPIO,
421 GPIOF_DIR_OUT | GPIOF_INIT_LOW, "tvout_sel");
323 if (err) 422 if (err)
324 goto err_gpio_tvout_sel; 423 goto err_gpio_tvout_sel;
325 gpio_direction_output(RX51_TVOUT_SEL_GPIO, 0); 424 err = gpio_request_one(RX51_ECI_SW_GPIO,
425 GPIOF_DIR_OUT | GPIOF_INIT_HIGH, "eci_sw");
426 if (err)
427 goto err_gpio_eci_sw;
326 428
327 rx51_snd_device = platform_device_alloc("soc-audio", -1); 429 rx51_snd_device = platform_device_alloc("soc-audio", -1);
328 if (!rx51_snd_device) { 430 if (!rx51_snd_device) {
@@ -330,9 +432,7 @@ static int __init rx51_soc_init(void)
330 goto err1; 432 goto err1;
331 } 433 }
332 434
333 platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); 435 platform_set_drvdata(rx51_snd_device, &rx51_sound_card);
334 rx51_snd_devdata.dev = &rx51_snd_device->dev;
335 *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */
336 436
337 err = platform_device_add(rx51_snd_device); 437 err = platform_device_add(rx51_snd_device);
338 if (err) 438 if (err)
@@ -342,6 +442,8 @@ static int __init rx51_soc_init(void)
342err2: 442err2:
343 platform_device_put(rx51_snd_device); 443 platform_device_put(rx51_snd_device);
344err1: 444err1:
445 gpio_free(RX51_ECI_SW_GPIO);
446err_gpio_eci_sw:
345 gpio_free(RX51_TVOUT_SEL_GPIO); 447 gpio_free(RX51_TVOUT_SEL_GPIO);
346err_gpio_tvout_sel: 448err_gpio_tvout_sel:
347 449
@@ -354,6 +456,7 @@ static void __exit rx51_soc_exit(void)
354 rx51_av_jack_gpios); 456 rx51_av_jack_gpios);
355 457
356 platform_device_unregister(rx51_snd_device); 458 platform_device_unregister(rx51_snd_device);
459 gpio_free(RX51_ECI_SW_GPIO);
357 gpio_free(RX51_TVOUT_SEL_GPIO); 460 gpio_free(RX51_TVOUT_SEL_GPIO);
358} 461}
359 462