aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc')
-rw-r--r--sound/soc/codecs/tlv320dac33.c5
-rw-r--r--sound/soc/codecs/tpa6130a2.c56
-rw-r--r--sound/soc/codecs/twl4030.c12
-rw-r--r--sound/soc/codecs/twl6040.c21
-rw-r--r--sound/soc/omap/Kconfig9
-rw-r--r--sound/soc/omap/Makefile2
-rw-r--r--sound/soc/omap/omap-mcbsp.c28
-rw-r--r--sound/soc/omap/sdp4430.c233
8 files changed, 324 insertions, 42 deletions
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c
index 007fe830be46..bcf6d934499a 100644
--- a/sound/soc/codecs/tlv320dac33.c
+++ b/sound/soc/codecs/tlv320dac33.c
@@ -352,7 +352,7 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power)
352 352
353 /* Safety check */ 353 /* Safety check */
354 if (unlikely(power == dac33->chip_power)) { 354 if (unlikely(power == dac33->chip_power)) {
355 dev_warn(codec->dev, "Trying to set the same power state: %s\n", 355 dev_dbg(codec->dev, "Trying to set the same power state: %s\n",
356 power ? "ON" : "OFF"); 356 power ? "ON" : "OFF");
357 goto exit; 357 goto exit;
358 } 358 }
@@ -589,6 +589,9 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec,
589 } 589 }
590 break; 590 break;
591 case SND_SOC_BIAS_OFF: 591 case SND_SOC_BIAS_OFF:
592 /* Do not power off, when the codec is already off */
593 if (codec->bias_level == SND_SOC_BIAS_OFF)
594 return 0;
592 ret = dac33_hard_power(codec, 0); 595 ret = dac33_hard_power(codec, 0);
593 if (ret != 0) 596 if (ret != 0)
594 return ret; 597 return ret;
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c
index fa4fa33a51aa..20ac67700395 100644
--- a/sound/soc/codecs/tpa6130a2.c
+++ b/sound/soc/codecs/tpa6130a2.c
@@ -35,22 +35,11 @@
35 35
36static struct i2c_client *tpa6130a2_client; 36static struct i2c_client *tpa6130a2_client;
37 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
49/* This struct is used to save the context */ 38/* This struct is used to save the context */
50struct tpa6130a2_data { 39struct tpa6130a2_data {
51 struct mutex mutex; 40 struct mutex mutex;
52 unsigned char regs[TPA6130A2_CACHEREGNUM]; 41 unsigned char regs[TPA6130A2_CACHEREGNUM];
53 struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; 42 struct regulator *supply;
54 int power_gpio; 43 int power_gpio;
55 unsigned char power_state; 44 unsigned char power_state;
56 enum tpa_model id; 45 enum tpa_model id;
@@ -135,11 +124,10 @@ static int tpa6130a2_power(int power)
135 if (data->power_gpio >= 0) 124 if (data->power_gpio >= 0)
136 gpio_set_value(data->power_gpio, 1); 125 gpio_set_value(data->power_gpio, 1);
137 126
138 ret = regulator_bulk_enable(ARRAY_SIZE(data->supplies), 127 ret = regulator_enable(data->supply);
139 data->supplies);
140 if (ret != 0) { 128 if (ret != 0) {
141 dev_err(&tpa6130a2_client->dev, 129 dev_err(&tpa6130a2_client->dev,
142 "Failed to enable supplies: %d\n", ret); 130 "Failed to enable supply: %d\n", ret);
143 goto exit; 131 goto exit;
144 } 132 }
145 133
@@ -160,11 +148,10 @@ static int tpa6130a2_power(int power)
160 if (data->power_gpio >= 0) 148 if (data->power_gpio >= 0)
161 gpio_set_value(data->power_gpio, 0); 149 gpio_set_value(data->power_gpio, 0);
162 150
163 ret = regulator_bulk_disable(ARRAY_SIZE(data->supplies), 151 ret = regulator_disable(data->supply);
164 data->supplies);
165 if (ret != 0) { 152 if (ret != 0) {
166 dev_err(&tpa6130a2_client->dev, 153 dev_err(&tpa6130a2_client->dev,
167 "Failed to disable supplies: %d\n", ret); 154 "Failed to disable supply: %d\n", ret);
168 goto exit; 155 goto exit;
169 } 156 }
170 157
@@ -371,8 +358,8 @@ static const struct snd_soc_dapm_widget tpa6130a2_dapm_widgets[] = {
371 0, 0, tpa6130a2_supply_event, 358 0, 0, tpa6130a2_supply_event,
372 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD), 359 SND_SOC_DAPM_POST_PMU|SND_SOC_DAPM_POST_PMD),
373 /* Outputs */ 360 /* Outputs */
374 SND_SOC_DAPM_HP("TPA6130A2 Headphone Left", NULL), 361 SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Left"),
375 SND_SOC_DAPM_HP("TPA6130A2 Headphone Right", NULL), 362 SND_SOC_DAPM_OUTPUT("TPA6130A2 Headphone Right"),
376}; 363};
377 364
378static const struct snd_soc_dapm_route audio_map[] = { 365static const struct snd_soc_dapm_route audio_map[] = {
@@ -411,7 +398,8 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
411 struct device *dev; 398 struct device *dev;
412 struct tpa6130a2_data *data; 399 struct tpa6130a2_data *data;
413 struct tpa6130a2_platform_data *pdata; 400 struct tpa6130a2_platform_data *pdata;
414 int i, ret; 401 const char *regulator;
402 int ret;
415 403
416 dev = &client->dev; 404 dev = &client->dev;
417 405
@@ -453,25 +441,21 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
453 } 441 }
454 442
455 switch (data->id) { 443 switch (data->id) {
444 default:
445 dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
446 pdata->id);
456 case TPA6130A2: 447 case TPA6130A2:
457 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 448 regulator = "Vdd";
458 data->supplies[i].supply = tpa6130a2_supply_names[i];
459 break; 449 break;
460 case TPA6140A2: 450 case TPA6140A2:
461 for (i = 0; i < ARRAY_SIZE(data->supplies); i++) 451 regulator = "AVdd";
462 data->supplies[i].supply = tpa6140a2_supply_names[i];;
463 break; 452 break;
464 default:
465 dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n",
466 pdata->id);
467 for (i = 0; i < ARRAY_SIZE(data->supplies); i++)
468 data->supplies[i].supply = tpa6130a2_supply_names[i];
469 } 453 }
470 454
471 ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), 455 data->supply = regulator_get(dev, regulator);
472 data->supplies); 456 if (IS_ERR(data->supply)) {
473 if (ret != 0) { 457 ret = PTR_ERR(data->supply);
474 dev_err(dev, "Failed to request supplies: %d\n", ret); 458 dev_err(dev, "Failed to request supply: %d\n", ret);
475 goto err_regulator; 459 goto err_regulator;
476 } 460 }
477 461
@@ -494,7 +478,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client,
494 return 0; 478 return 0;
495 479
496err_power: 480err_power:
497 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); 481 regulator_put(data->supply);
498err_regulator: 482err_regulator:
499 if (data->power_gpio >= 0) 483 if (data->power_gpio >= 0)
500 gpio_free(data->power_gpio); 484 gpio_free(data->power_gpio);
@@ -515,7 +499,7 @@ static int __devexit tpa6130a2_remove(struct i2c_client *client)
515 if (data->power_gpio >= 0) 499 if (data->power_gpio >= 0)
516 gpio_free(data->power_gpio); 500 gpio_free(data->power_gpio);
517 501
518 regulator_bulk_free(ARRAY_SIZE(data->supplies), data->supplies); 502 regulator_put(data->supply);
519 503
520 kfree(data); 504 kfree(data);
521 tpa6130a2_client = NULL; 505 tpa6130a2_client = NULL;
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 0fe74d1e2c5f..6a34f562b563 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -1102,6 +1102,16 @@ static const struct soc_enum twl4030_vibradir_enum =
1102 ARRAY_SIZE(twl4030_vibradir_texts), 1102 ARRAY_SIZE(twl4030_vibradir_texts),
1103 twl4030_vibradir_texts); 1103 twl4030_vibradir_texts);
1104 1104
1105/* Digimic Left and right swapping */
1106static const char *twl4030_digimicswap_texts[] = {
1107 "Not swapped", "Swapped",
1108};
1109
1110static const struct soc_enum twl4030_digimicswap_enum =
1111 SOC_ENUM_SINGLE(TWL4030_REG_MISC_SET_1, 0,
1112 ARRAY_SIZE(twl4030_digimicswap_texts),
1113 twl4030_digimicswap_texts);
1114
1105static const struct snd_kcontrol_new twl4030_snd_controls[] = { 1115static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1106 /* Codec operation mode control */ 1116 /* Codec operation mode control */
1107 SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum, 1117 SOC_ENUM_EXT("Codec Operation Mode", twl4030_op_modes_enum,
@@ -1178,6 +1188,8 @@ static const struct snd_kcontrol_new twl4030_snd_controls[] = {
1178 1188
1179 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum), 1189 SOC_ENUM("Vibra H-bridge mode", twl4030_vibradirmode_enum),
1180 SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum), 1190 SOC_ENUM("Vibra H-bridge direction", twl4030_vibradir_enum),
1191
1192 SOC_ENUM("Digimic LR Swap", twl4030_digimicswap_enum),
1181}; 1193};
1182 1194
1183static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { 1195static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = {
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index 2ae442edeb9a..af36346ff336 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -432,6 +432,12 @@ static DECLARE_TLV_DB_SCALE(hs_tlv, -3000, 200, 0);
432 */ 432 */
433static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0); 433static DECLARE_TLV_DB_SCALE(hf_tlv, -5200, 200, 0);
434 434
435/*
436 * EPGAIN volume control:
437 * from -24 to 6 dB in 2 dB steps
438 */
439static DECLARE_TLV_DB_SCALE(ep_tlv, -2400, 200, 0);
440
435/* Left analog microphone selection */ 441/* Left analog microphone selection */
436static const char *twl6040_amicl_texts[] = 442static const char *twl6040_amicl_texts[] =
437 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"}; 443 {"Headset Mic", "Main Mic", "Aux/FM Left", "Off"};
@@ -479,6 +485,9 @@ static const struct snd_kcontrol_new hfl_driver_switch_controls =
479static const struct snd_kcontrol_new hfr_driver_switch_controls = 485static const struct snd_kcontrol_new hfr_driver_switch_controls =
480 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0); 486 SOC_DAPM_SINGLE("Switch", TWL6040_REG_HFRCTL, 4, 1, 0);
481 487
488static const struct snd_kcontrol_new ep_driver_switch_controls =
489 SOC_DAPM_SINGLE("Switch", TWL6040_REG_EARCTL, 0, 1, 0);
490
482static const struct snd_kcontrol_new twl6040_snd_controls[] = { 491static const struct snd_kcontrol_new twl6040_snd_controls[] = {
483 /* Capture gains */ 492 /* Capture gains */
484 SOC_DOUBLE_TLV("Capture Preamplifier Volume", 493 SOC_DOUBLE_TLV("Capture Preamplifier Volume",
@@ -491,7 +500,8 @@ static const struct snd_kcontrol_new twl6040_snd_controls[] = {
491 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv), 500 TWL6040_REG_HSGAIN, 0, 4, 0xF, 1, hs_tlv),
492 SOC_DOUBLE_R_TLV("Handsfree Playback Volume", 501 SOC_DOUBLE_R_TLV("Handsfree Playback Volume",
493 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv), 502 TWL6040_REG_HFLGAIN, TWL6040_REG_HFRGAIN, 0, 0x1D, 1, hf_tlv),
494 503 SOC_SINGLE_TLV("Earphone Playback Volume",
504 TWL6040_REG_EARCTL, 1, 0xF, 1, ep_tlv),
495}; 505};
496 506
497static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = { 507static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
@@ -507,6 +517,7 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
507 SND_SOC_DAPM_OUTPUT("HSOR"), 517 SND_SOC_DAPM_OUTPUT("HSOR"),
508 SND_SOC_DAPM_OUTPUT("HFL"), 518 SND_SOC_DAPM_OUTPUT("HFL"),
509 SND_SOC_DAPM_OUTPUT("HFR"), 519 SND_SOC_DAPM_OUTPUT("HFR"),
520 SND_SOC_DAPM_OUTPUT("EP"),
510 521
511 /* Analog input muxes for the capture amplifiers */ 522 /* Analog input muxes for the capture amplifiers */
512 SND_SOC_DAPM_MUX("Analog Left Capture Route", 523 SND_SOC_DAPM_MUX("Analog Left Capture Route",
@@ -572,6 +583,10 @@ static const struct snd_soc_dapm_widget twl6040_dapm_widgets[] = {
572 SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls, 583 SND_SOC_NOPM, 0, 0, &hfr_driver_switch_controls,
573 twl6040_power_mode_event, 584 twl6040_power_mode_event,
574 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), 585 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
586 SND_SOC_DAPM_SWITCH_E("Earphone Driver",
587 SND_SOC_NOPM, 0, 0, &ep_driver_switch_controls,
588 twl6040_power_mode_event,
589 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD),
575 590
576 /* Analog playback PGAs */ 591 /* Analog playback PGAs */
577 SND_SOC_DAPM_PGA("HFDAC Left PGA", 592 SND_SOC_DAPM_PGA("HFDAC Left PGA",
@@ -607,6 +622,10 @@ static const struct snd_soc_dapm_route intercon[] = {
607 {"HSOL", NULL, "Headset Left Driver"}, 622 {"HSOL", NULL, "Headset Left Driver"},
608 {"HSOR", NULL, "Headset Right Driver"}, 623 {"HSOR", NULL, "Headset Right Driver"},
609 624
625 /* Earphone playback path */
626 {"Earphone Driver", "Switch", "HSDAC Left"},
627 {"EP", NULL, "Earphone Driver"},
628
610 /* Handsfree playback path */ 629 /* Handsfree playback path */
611 {"HFDAC Left Playback", "Switch", "HFDAC Left"}, 630 {"HFDAC Left Playback", "Switch", "HFDAC Left"},
612 {"HFDAC Right Playback", "Switch", "HFDAC Right"}, 631 {"HFDAC Right Playback", "Switch", "HFDAC Right"},
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig
index 83be4a76d2bb..d542ea2ff6be 100644
--- a/sound/soc/omap/Kconfig
+++ b/sound/soc/omap/Kconfig
@@ -98,6 +98,15 @@ config SND_OMAP_SOC_SDP3430
98 Say Y if you want to add support for SoC audio on Texas Instruments 98 Say Y if you want to add support for SoC audio on Texas Instruments
99 SDP3430. 99 SDP3430.
100 100
101config SND_OMAP_SOC_SDP4430
102 tristate "SoC Audio support for Texas Instruments SDP4430"
103 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP_4430SDP
104 select SND_OMAP_SOC_MCPDM
105 select SND_SOC_TWL6040
106 help
107 Say Y if you want to add support for SoC audio on Texas Instruments
108 SDP4430.
109
101config SND_OMAP_SOC_OMAP3_PANDORA 110config SND_OMAP_SOC_OMAP3_PANDORA
102 tristate "SoC Audio support for OMAP3 Pandora" 111 tristate "SoC Audio support for OMAP3 Pandora"
103 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA 112 depends on TWL4030_CORE && SND_OMAP_SOC && MACH_OMAP3_PANDORA
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile
index 3a75755f25e4..ba9fc650db28 100644
--- a/sound/soc/omap/Makefile
+++ b/sound/soc/omap/Makefile
@@ -17,6 +17,7 @@ snd-soc-omap2evm-objs := omap2evm.o
17snd-soc-omap3evm-objs := omap3evm.o 17snd-soc-omap3evm-objs := omap3evm.o
18snd-soc-am3517evm-objs := am3517evm.o 18snd-soc-am3517evm-objs := am3517evm.o
19snd-soc-sdp3430-objs := sdp3430.o 19snd-soc-sdp3430-objs := sdp3430.o
20snd-soc-sdp4430-objs := sdp4430.o
20snd-soc-omap3pandora-objs := omap3pandora.o 21snd-soc-omap3pandora-objs := omap3pandora.o
21snd-soc-omap3beagle-objs := omap3beagle.o 22snd-soc-omap3beagle-objs := omap3beagle.o
22snd-soc-zoom2-objs := zoom2.o 23snd-soc-zoom2-objs := zoom2.o
@@ -31,6 +32,7 @@ obj-$(CONFIG_SND_OMAP_SOC_OMAP2EVM) += snd-soc-omap2evm.o
31obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o 32obj-$(CONFIG_SND_OMAP_SOC_OMAP3EVM) += snd-soc-omap3evm.o
32obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o 33obj-$(CONFIG_SND_OMAP_SOC_AM3517EVM) += snd-soc-am3517evm.o
33obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o 34obj-$(CONFIG_SND_OMAP_SOC_SDP3430) += snd-soc-sdp3430.o
35obj-$(CONFIG_SND_OMAP_SOC_SDP4430) += snd-soc-sdp4430.o
34obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o 36obj-$(CONFIG_SND_OMAP_SOC_OMAP3_PANDORA) += snd-soc-omap3pandora.o
35obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o 37obj-$(CONFIG_SND_OMAP_SOC_OMAP3_BEAGLE) += snd-soc-omap3beagle.o
36obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o 38obj-$(CONFIG_SND_OMAP_SOC_ZOOM2) += snd-soc-zoom2.o
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index 2d33a89f147a..6f44cb4d30b8 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -320,8 +320,18 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
320 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma; 320 omap_mcbsp_dai_dma_params[id][substream->stream].dma_req = dma;
321 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port; 321 omap_mcbsp_dai_dma_params[id][substream->stream].port_addr = port;
322 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode; 322 omap_mcbsp_dai_dma_params[id][substream->stream].sync_mode = sync_mode;
323 omap_mcbsp_dai_dma_params[id][substream->stream].data_type = 323 switch (params_format(params)) {
324 OMAP_DMA_DATA_TYPE_S16; 324 case SNDRV_PCM_FORMAT_S16_LE:
325 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
326 OMAP_DMA_DATA_TYPE_S16;
327 break;
328 case SNDRV_PCM_FORMAT_S32_LE:
329 omap_mcbsp_dai_dma_params[id][substream->stream].data_type =
330 OMAP_DMA_DATA_TYPE_S32;
331 break;
332 default:
333 return -EINVAL;
334 }
325 335
326 snd_soc_dai_set_dma_data(cpu_dai, substream, 336 snd_soc_dai_set_dma_data(cpu_dai, substream,
327 &omap_mcbsp_dai_dma_params[id][substream->stream]); 337 &omap_mcbsp_dai_dma_params[id][substream->stream]);
@@ -356,6 +366,14 @@ static int omap_mcbsp_dai_hw_params(struct snd_pcm_substream *substream,
356 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16); 366 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_16);
357 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16); 367 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_16);
358 break; 368 break;
369 case SNDRV_PCM_FORMAT_S32_LE:
370 /* Set word lengths */
371 wlen = 32;
372 regs->rcr2 |= RWDLEN2(OMAP_MCBSP_WORD_32);
373 regs->rcr1 |= RWDLEN1(OMAP_MCBSP_WORD_32);
374 regs->xcr2 |= XWDLEN2(OMAP_MCBSP_WORD_32);
375 regs->xcr1 |= XWDLEN1(OMAP_MCBSP_WORD_32);
376 break;
359 default: 377 default:
360 /* Unsupported PCM format */ 378 /* Unsupported PCM format */
361 return -EINVAL; 379 return -EINVAL;
@@ -659,13 +677,15 @@ static struct snd_soc_dai_ops omap_mcbsp_dai_ops = {
659 .channels_min = 1, \ 677 .channels_min = 1, \
660 .channels_max = 16, \ 678 .channels_max = 16, \
661 .rates = OMAP_MCBSP_RATES, \ 679 .rates = OMAP_MCBSP_RATES, \
662 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 680 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
681 SNDRV_PCM_FMTBIT_S32_LE, \
663 }, \ 682 }, \
664 .capture = { \ 683 .capture = { \
665 .channels_min = 1, \ 684 .channels_min = 1, \
666 .channels_max = 16, \ 685 .channels_max = 16, \
667 .rates = OMAP_MCBSP_RATES, \ 686 .rates = OMAP_MCBSP_RATES, \
668 .formats = SNDRV_PCM_FMTBIT_S16_LE, \ 687 .formats = SNDRV_PCM_FMTBIT_S16_LE | \
688 SNDRV_PCM_FMTBIT_S32_LE, \
669 }, \ 689 }, \
670 .ops = &omap_mcbsp_dai_ops, \ 690 .ops = &omap_mcbsp_dai_ops, \
671 .private_data = &mcbsp_data[(link_id)].bus_id, \ 691 .private_data = &mcbsp_data[(link_id)].bus_id, \
diff --git a/sound/soc/omap/sdp4430.c b/sound/soc/omap/sdp4430.c
new file mode 100644
index 000000000000..4ebbde6b565f
--- /dev/null
+++ b/sound/soc/omap/sdp4430.c
@@ -0,0 +1,233 @@
1/*
2 * sdp4430.c -- SoC audio for TI OMAP4430 SDP
3 *
4 * Author: Misael Lopez Cruz <x0052729@ti.com>
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * version 2 as published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
18 * 02110-1301 USA
19 *
20 */
21
22#include <linux/clk.h>
23#include <linux/platform_device.h>
24#include <sound/core.h>
25#include <sound/pcm.h>
26#include <sound/soc.h>
27#include <sound/soc-dapm.h>
28
29#include <asm/mach-types.h>
30#include <plat/hardware.h>
31#include <plat/mux.h>
32
33#include "mcpdm.h"
34#include "omap-mcpdm.h"
35#include "omap-pcm.h"
36#include "../codecs/twl6040.h"
37
38static int twl6040_power_mode;
39
40static int sdp4430_hw_params(struct snd_pcm_substream *substream,
41 struct snd_pcm_hw_params *params)
42{
43 struct snd_soc_pcm_runtime *rtd = substream->private_data;
44 struct snd_soc_dai *codec_dai = rtd->dai->codec_dai;
45 int clk_id, freq;
46 int ret;
47
48 if (twl6040_power_mode) {
49 clk_id = TWL6040_SYSCLK_SEL_HPPLL;
50 freq = 38400000;
51 } else {
52 clk_id = TWL6040_SYSCLK_SEL_LPPLL;
53 freq = 32768;
54 }
55
56 /* set the codec mclk */
57 ret = snd_soc_dai_set_sysclk(codec_dai, clk_id, freq,
58 SND_SOC_CLOCK_IN);
59 if (ret) {
60 printk(KERN_ERR "can't set codec system clock\n");
61 return ret;
62 }
63}
64
65static struct snd_soc_ops sdp4430_ops = {
66 .hw_params = sdp4430_hw_params,
67};
68
69static int sdp4430_get_power_mode(struct snd_kcontrol *kcontrol,
70 struct snd_ctl_elem_value *ucontrol)
71{
72 ucontrol->value.integer.value[0] = twl6040_power_mode;
73 return 0;
74}
75
76static int sdp4430_set_power_mode(struct snd_kcontrol *kcontrol,
77 struct snd_ctl_elem_value *ucontrol)
78{
79 if (twl6040_power_mode == ucontrol->value.integer.value[0])
80 return 0;
81
82 twl6040_power_mode = ucontrol->value.integer.value[0];
83
84 return 1;
85}
86
87static const char *power_texts[] = {"Low-Power", "High-Performance"};
88
89static const struct soc_enum sdp4430_enum[] = {
90 SOC_ENUM_SINGLE_EXT(2, power_texts),
91};
92
93static const struct snd_kcontrol_new sdp4430_controls[] = {
94 SOC_ENUM_EXT("TWL6040 Power Mode", sdp4430_enum[0],
95 sdp4430_get_power_mode, sdp4430_set_power_mode),
96};
97
98/* SDP4430 machine DAPM */
99static const struct snd_soc_dapm_widget sdp4430_twl6040_dapm_widgets[] = {
100 SND_SOC_DAPM_MIC("Ext Mic", NULL),
101 SND_SOC_DAPM_SPK("Ext Spk", NULL),
102 SND_SOC_DAPM_MIC("Headset Mic", NULL),
103 SND_SOC_DAPM_HP("Headset Stereophone", NULL),
104 SND_SOC_DAPM_SPK("Earphone Spk", NULL),
105};
106
107static const struct snd_soc_dapm_route audio_map[] = {
108 /* External Mics: MAINMIC, SUBMIC with bias*/
109 {"MAINMIC", NULL, "Main Mic Bias"},
110 {"SUBMIC", NULL, "Main Mic Bias"},
111 {"Main Mic Bias", NULL, "Ext Mic"},
112
113 /* External Speakers: HFL, HFR */
114 {"Ext Spk", NULL, "HFL"},
115 {"Ext Spk", NULL, "HFR"},
116
117 /* Headset Mic: HSMIC with bias */
118 {"HSMIC", NULL, "Headset Mic Bias"},
119 {"Headset Mic Bias", NULL, "Headset Mic"},
120
121 /* Headset Stereophone (Headphone): HSOL, HSOR */
122 {"Headset Stereophone", NULL, "HSOL"},
123 {"Headset Stereophone", NULL, "HSOR"},
124
125 /* Earphone speaker */
126 {"Earphone Spk", NULL, "EP"},
127};
128
129static int sdp4430_twl6040_init(struct snd_soc_codec *codec)
130{
131 int ret;
132
133 /* Add SDP4430 specific controls */
134 ret = snd_soc_add_controls(codec, sdp4430_controls,
135 ARRAY_SIZE(sdp4430_controls));
136 if (ret)
137 return ret;
138
139 /* Add SDP4430 specific widgets */
140 ret = snd_soc_dapm_new_controls(codec, sdp4430_twl6040_dapm_widgets,
141 ARRAY_SIZE(sdp4430_twl6040_dapm_widgets));
142 if (ret)
143 return ret;
144
145 /* Set up SDP4430 specific audio path audio_map */
146 snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map));
147
148 /* SDP4430 connected pins */
149 snd_soc_dapm_enable_pin(codec, "Ext Mic");
150 snd_soc_dapm_enable_pin(codec, "Ext Spk");
151 snd_soc_dapm_enable_pin(codec, "Headset Mic");
152 snd_soc_dapm_enable_pin(codec, "Headset Stereophone");
153
154 /* TWL6040 not connected pins */
155 snd_soc_dapm_nc_pin(codec, "AFML");
156 snd_soc_dapm_nc_pin(codec, "AFMR");
157
158 ret = snd_soc_dapm_sync(codec);
159
160 return ret;
161}
162
163/* Digital audio interface glue - connects codec <--> CPU */
164static struct snd_soc_dai_link sdp4430_dai = {
165 .name = "TWL6040",
166 .stream_name = "TWL6040",
167 .cpu_dai = &omap_mcpdm_dai,
168 .codec_dai = &twl6040_dai,
169 .init = sdp4430_twl6040_init,
170 .ops = &sdp4430_ops,
171};
172
173/* Audio machine driver */
174static struct snd_soc_card snd_soc_sdp4430 = {
175 .name = "SDP4430",
176 .platform = &omap_soc_platform,
177 .dai_link = &sdp4430_dai,
178 .num_links = 1,
179};
180
181/* Audio subsystem */
182static struct snd_soc_device sdp4430_snd_devdata = {
183 .card = &snd_soc_sdp4430,
184 .codec_dev = &soc_codec_dev_twl6040,
185};
186
187static struct platform_device *sdp4430_snd_device;
188
189static int __init sdp4430_soc_init(void)
190{
191 int ret;
192
193 if (!machine_is_omap_4430sdp()) {
194 pr_debug("Not SDP4430!\n");
195 return -ENODEV;
196 }
197 printk(KERN_INFO "SDP4430 SoC init\n");
198
199 sdp4430_snd_device = platform_device_alloc("soc-audio", -1);
200 if (!sdp4430_snd_device) {
201 printk(KERN_ERR "Platform device allocation failed\n");
202 return -ENOMEM;
203 }
204
205 platform_set_drvdata(sdp4430_snd_device, &sdp4430_snd_devdata);
206 sdp4430_snd_devdata.dev = &sdp4430_snd_device->dev;
207
208 ret = platform_device_add(sdp4430_snd_device);
209 if (ret)
210 goto err;
211
212 /* Codec starts in HP mode */
213 twl6040_power_mode = 1;
214
215 return 0;
216
217err:
218 printk(KERN_ERR "Unable to add platform device\n");
219 platform_device_put(sdp4430_snd_device);
220 return ret;
221}
222module_init(sdp4430_soc_init);
223
224static void __exit sdp4430_soc_exit(void)
225{
226 platform_device_unregister(sdp4430_snd_device);
227}
228module_exit(sdp4430_soc_exit);
229
230MODULE_AUTHOR("Misael Lopez Cruz <x0052729@ti.com>");
231MODULE_DESCRIPTION("ALSA SoC SDP4430");
232MODULE_LICENSE("GPL");
233