diff options
author | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-07 11:38:26 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2010-05-07 11:38:26 -0400 |
commit | 305787649826d6c84a6f9f71bc3318460610aba4 (patch) | |
tree | b36cfe60e6f806414b1e6c042f0be233f114986f /sound/soc | |
parent | c4806174c516d26bf4a72db1789cfc96e4950d07 (diff) | |
parent | aeb29a82de7c80d4d0253b042f17eb1f725b08f1 (diff) |
Merge branch 'topic/asoc' of git://git.kernel.org/pub/scm/linux/kernel/git/tiwai/sound-2.6 into for-2.6.35
Diffstat (limited to 'sound/soc')
-rw-r--r-- | sound/soc/codecs/tlv320aic3x.c | 25 | ||||
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 223 | ||||
-rw-r--r-- | sound/soc/codecs/tpa6130a2.c | 99 | ||||
-rw-r--r-- | sound/soc/codecs/twl4030.c | 86 | ||||
-rw-r--r-- | sound/soc/omap/Kconfig | 10 | ||||
-rw-r--r-- | sound/soc/omap/Makefile | 2 | ||||
-rw-r--r-- | sound/soc/omap/omap3pandora.c | 2 | ||||
-rw-r--r-- | sound/soc/omap/rx51.c | 294 | ||||
-rw-r--r-- | sound/soc/omap/zoom2.c | 3 |
9 files changed, 601 insertions, 143 deletions
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 584bc1e67f76..d57372be7a96 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/gpio.h> | ||
41 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
42 | #include <linux/platform_device.h> | 43 | #include <linux/platform_device.h> |
43 | #include <sound/core.h> | 44 | #include <sound/core.h> |
@@ -47,6 +48,7 @@ | |||
47 | #include <sound/soc-dapm.h> | 48 | #include <sound/soc-dapm.h> |
48 | #include <sound/initval.h> | 49 | #include <sound/initval.h> |
49 | #include <sound/tlv.h> | 50 | #include <sound/tlv.h> |
51 | #include <sound/tlv320aic3x.h> | ||
50 | 52 | ||
51 | #include "tlv320aic3x.h" | 53 | #include "tlv320aic3x.h" |
52 | 54 | ||
@@ -64,6 +66,7 @@ struct aic3x_priv { | |||
64 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; | 66 | struct regulator_bulk_data supplies[AIC3X_NUM_SUPPLIES]; |
65 | unsigned int sysclk; | 67 | unsigned int sysclk; |
66 | int master; | 68 | int master; |
69 | int gpio_reset; | ||
67 | }; | 70 | }; |
68 | 71 | ||
69 | /* | 72 | /* |
@@ -1278,6 +1281,10 @@ static int aic3x_unregister(struct aic3x_priv *aic3x) | |||
1278 | snd_soc_unregister_dai(&aic3x_dai); | 1281 | snd_soc_unregister_dai(&aic3x_dai); |
1279 | snd_soc_unregister_codec(&aic3x->codec); | 1282 | snd_soc_unregister_codec(&aic3x->codec); |
1280 | 1283 | ||
1284 | if (aic3x->gpio_reset >= 0) { | ||
1285 | gpio_set_value(aic3x->gpio_reset, 0); | ||
1286 | gpio_free(aic3x->gpio_reset); | ||
1287 | } | ||
1281 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1288 | regulator_bulk_disable(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
1282 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1289 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
1283 | 1290 | ||
@@ -1302,6 +1309,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1302 | { | 1309 | { |
1303 | struct snd_soc_codec *codec; | 1310 | struct snd_soc_codec *codec; |
1304 | struct aic3x_priv *aic3x; | 1311 | struct aic3x_priv *aic3x; |
1312 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | ||
1305 | int ret, i; | 1313 | int ret, i; |
1306 | 1314 | ||
1307 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); | 1315 | aic3x = kzalloc(sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1318,6 +1326,15 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1318 | 1326 | ||
1319 | i2c_set_clientdata(i2c, aic3x); | 1327 | i2c_set_clientdata(i2c, aic3x); |
1320 | 1328 | ||
1329 | aic3x->gpio_reset = -1; | ||
1330 | if (pdata && pdata->gpio_reset >= 0) { | ||
1331 | ret = gpio_request(pdata->gpio_reset, "tlv320aic3x reset"); | ||
1332 | if (ret != 0) | ||
1333 | goto err_gpio; | ||
1334 | aic3x->gpio_reset = pdata->gpio_reset; | ||
1335 | gpio_direction_output(aic3x->gpio_reset, 0); | ||
1336 | } | ||
1337 | |||
1321 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) | 1338 | for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) |
1322 | aic3x->supplies[i].supply = aic3x_supply_names[i]; | 1339 | aic3x->supplies[i].supply = aic3x_supply_names[i]; |
1323 | 1340 | ||
@@ -1335,11 +1352,19 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1335 | goto err_enable; | 1352 | goto err_enable; |
1336 | } | 1353 | } |
1337 | 1354 | ||
1355 | if (aic3x->gpio_reset >= 0) { | ||
1356 | udelay(1); | ||
1357 | gpio_set_value(aic3x->gpio_reset, 1); | ||
1358 | } | ||
1359 | |||
1338 | return aic3x_register(codec); | 1360 | return aic3x_register(codec); |
1339 | 1361 | ||
1340 | err_enable: | 1362 | err_enable: |
1341 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); | 1363 | regulator_bulk_free(ARRAY_SIZE(aic3x->supplies), aic3x->supplies); |
1342 | err_get: | 1364 | err_get: |
1365 | if (aic3x->gpio_reset >= 0) | ||
1366 | gpio_free(aic3x->gpio_reset); | ||
1367 | err_gpio: | ||
1343 | kfree(aic3x); | 1368 | kfree(aic3x); |
1344 | return ret; | 1369 | return ret; |
1345 | } | 1370 | } |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 3eddaec728c1..ad5e2636c944 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -61,6 +61,8 @@ | |||
61 | #define US_TO_SAMPLES(rate, us) \ | 61 | #define US_TO_SAMPLES(rate, us) \ |
62 | (rate / (1000000 / us)) | 62 | (rate / (1000000 / us)) |
63 | 63 | ||
64 | static void dac33_calculate_times(struct snd_pcm_substream *substream); | ||
65 | static int dac33_prepare_chip(struct snd_pcm_substream *substream); | ||
64 | 66 | ||
65 | static struct snd_soc_codec *tlv320dac33_codec; | 67 | static struct snd_soc_codec *tlv320dac33_codec; |
66 | 68 | ||
@@ -91,6 +93,7 @@ struct tlv320dac33_priv { | |||
91 | struct work_struct work; | 93 | struct work_struct work; |
92 | struct snd_soc_codec codec; | 94 | struct snd_soc_codec codec; |
93 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; | 95 | struct regulator_bulk_data supplies[DAC33_NUM_SUPPLIES]; |
96 | struct snd_pcm_substream *substream; | ||
94 | int power_gpio; | 97 | int power_gpio; |
95 | int chip_power; | 98 | int chip_power; |
96 | int irq; | 99 | int irq; |
@@ -284,45 +287,47 @@ static int dac33_write16(struct snd_soc_codec *codec, unsigned int reg, | |||
284 | return ret; | 287 | return ret; |
285 | } | 288 | } |
286 | 289 | ||
287 | static void dac33_restore_regs(struct snd_soc_codec *codec) | 290 | static void dac33_init_chip(struct snd_soc_codec *codec) |
288 | { | 291 | { |
289 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 292 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
290 | u8 *cache = codec->reg_cache; | ||
291 | u8 data[2]; | ||
292 | int i, ret; | ||
293 | 293 | ||
294 | if (!dac33->chip_power) | 294 | if (unlikely(!dac33->chip_power)) |
295 | return; | 295 | return; |
296 | 296 | ||
297 | for (i = DAC33_PWR_CTRL; i <= DAC33_INTP_CTRL_B; i++) { | 297 | /* 44-46: DAC Control Registers */ |
298 | data[0] = i; | 298 | /* A : DAC sample rate Fsref/1.5 */ |
299 | data[1] = cache[i]; | 299 | dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); |
300 | /* Skip the read only registers */ | 300 | /* B : DAC src=normal, not muted */ |
301 | if ((i >= DAC33_INT_OSC_STATUS && | 301 | dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | |
302 | i <= DAC33_INT_OSC_FREQ_RAT_READ_B) || | 302 | DAC33_DACSRCL_LEFT); |
303 | (i >= DAC33_FIFO_WPTR_MSB && i <= DAC33_FIFO_IRQ_FLAG) || | 303 | /* C : (defaults) */ |
304 | i == DAC33_DAC_STATUS_FLAGS || | 304 | dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); |
305 | i == DAC33_SRC_EST_REF_CLK_RATIO_A || | 305 | |
306 | i == DAC33_SRC_EST_REF_CLK_RATIO_B) | 306 | /* 73 : volume soft stepping control, |
307 | continue; | 307 | clock source = internal osc (?) */ |
308 | ret = codec->hw_write(codec->control_data, data, 2); | 308 | dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); |
309 | if (ret != 2) | 309 | |
310 | dev_err(codec->dev, "Write failed (%d)\n", ret); | 310 | dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); |
311 | } | 311 | |
312 | for (i = DAC33_LDAC_PWR_CTRL; i <= DAC33_LINEL_TO_LLO_VOL; i++) { | 312 | /* Restore only selected registers (gains mostly) */ |
313 | data[0] = i; | 313 | dac33_write(codec, DAC33_LDAC_DIG_VOL_CTRL, |
314 | data[1] = cache[i]; | 314 | dac33_read_reg_cache(codec, DAC33_LDAC_DIG_VOL_CTRL)); |
315 | ret = codec->hw_write(codec->control_data, data, 2); | 315 | dac33_write(codec, DAC33_RDAC_DIG_VOL_CTRL, |
316 | if (ret != 2) | 316 | dac33_read_reg_cache(codec, DAC33_RDAC_DIG_VOL_CTRL)); |
317 | dev_err(codec->dev, "Write failed (%d)\n", ret); | 317 | |
318 | } | 318 | dac33_write(codec, DAC33_LINEL_TO_LLO_VOL, |
319 | for (i = DAC33_LINER_TO_RLO_VOL; i <= DAC33_OSC_TRIM; i++) { | 319 | dac33_read_reg_cache(codec, DAC33_LINEL_TO_LLO_VOL)); |
320 | data[0] = i; | 320 | dac33_write(codec, DAC33_LINER_TO_RLO_VOL, |
321 | data[1] = cache[i]; | 321 | dac33_read_reg_cache(codec, DAC33_LINER_TO_RLO_VOL)); |
322 | ret = codec->hw_write(codec->control_data, data, 2); | 322 | } |
323 | if (ret != 2) | 323 | |
324 | dev_err(codec->dev, "Write failed (%d)\n", ret); | 324 | static inline void dac33_read_id(struct snd_soc_codec *codec) |
325 | } | 325 | { |
326 | u8 reg; | ||
327 | |||
328 | dac33_read(codec, DAC33_DEVICE_ID_MSB, ®); | ||
329 | dac33_read(codec, DAC33_DEVICE_ID_LSB, ®); | ||
330 | dac33_read(codec, DAC33_DEVICE_REV_ID, ®); | ||
326 | } | 331 | } |
327 | 332 | ||
328 | static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) | 333 | static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) |
@@ -341,9 +346,17 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) | |||
341 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) | 346 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) |
342 | { | 347 | { |
343 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 348 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
344 | int ret; | 349 | int ret = 0; |
345 | 350 | ||
346 | mutex_lock(&dac33->mutex); | 351 | mutex_lock(&dac33->mutex); |
352 | |||
353 | /* Safety check */ | ||
354 | if (unlikely(power == dac33->chip_power)) { | ||
355 | dev_warn(codec->dev, "Trying to set the same power state: %s\n", | ||
356 | power ? "ON" : "OFF"); | ||
357 | goto exit; | ||
358 | } | ||
359 | |||
347 | if (power) { | 360 | if (power) { |
348 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), | 361 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), |
349 | dac33->supplies); | 362 | dac33->supplies); |
@@ -357,11 +370,6 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) | |||
357 | gpio_set_value(dac33->power_gpio, 1); | 370 | gpio_set_value(dac33->power_gpio, 1); |
358 | 371 | ||
359 | dac33->chip_power = 1; | 372 | dac33->chip_power = 1; |
360 | |||
361 | /* Restore registers */ | ||
362 | dac33_restore_regs(codec); | ||
363 | |||
364 | dac33_soft_power(codec, 1); | ||
365 | } else { | 373 | } else { |
366 | dac33_soft_power(codec, 0); | 374 | dac33_soft_power(codec, 0); |
367 | if (dac33->power_gpio >= 0) | 375 | if (dac33->power_gpio >= 0) |
@@ -383,6 +391,22 @@ exit: | |||
383 | return ret; | 391 | return ret; |
384 | } | 392 | } |
385 | 393 | ||
394 | static int playback_event(struct snd_soc_dapm_widget *w, | ||
395 | struct snd_kcontrol *kcontrol, int event) | ||
396 | { | ||
397 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); | ||
398 | |||
399 | switch (event) { | ||
400 | case SND_SOC_DAPM_PRE_PMU: | ||
401 | if (likely(dac33->substream)) { | ||
402 | dac33_calculate_times(dac33->substream); | ||
403 | dac33_prepare_chip(dac33->substream); | ||
404 | } | ||
405 | break; | ||
406 | } | ||
407 | return 0; | ||
408 | } | ||
409 | |||
386 | static int dac33_get_nsample(struct snd_kcontrol *kcontrol, | 410 | static int dac33_get_nsample(struct snd_kcontrol *kcontrol, |
387 | struct snd_ctl_elem_value *ucontrol) | 411 | struct snd_ctl_elem_value *ucontrol) |
388 | { | 412 | { |
@@ -512,6 +536,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { | |||
512 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), | 536 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), |
513 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", | 537 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", |
514 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), | 538 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), |
539 | |||
540 | SND_SOC_DAPM_PRE("Prepare Playback", playback_event), | ||
515 | }; | 541 | }; |
516 | 542 | ||
517 | static const struct snd_soc_dapm_route audio_map[] = { | 543 | static const struct snd_soc_dapm_route audio_map[] = { |
@@ -554,18 +580,18 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
554 | break; | 580 | break; |
555 | case SND_SOC_BIAS_STANDBY: | 581 | case SND_SOC_BIAS_STANDBY: |
556 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 582 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
583 | /* Coming from OFF, switch on the codec */ | ||
557 | ret = dac33_hard_power(codec, 1); | 584 | ret = dac33_hard_power(codec, 1); |
558 | if (ret != 0) | 585 | if (ret != 0) |
559 | return ret; | 586 | return ret; |
560 | } | ||
561 | 587 | ||
562 | dac33_soft_power(codec, 0); | 588 | dac33_init_chip(codec); |
589 | } | ||
563 | break; | 590 | break; |
564 | case SND_SOC_BIAS_OFF: | 591 | case SND_SOC_BIAS_OFF: |
565 | ret = dac33_hard_power(codec, 0); | 592 | ret = dac33_hard_power(codec, 0); |
566 | if (ret != 0) | 593 | if (ret != 0) |
567 | return ret; | 594 | return ret; |
568 | |||
569 | break; | 595 | break; |
570 | } | 596 | } |
571 | codec->bias_level = level; | 597 | codec->bias_level = level; |
@@ -708,6 +734,31 @@ static void dac33_oscwait(struct snd_soc_codec *codec) | |||
708 | "internal oscillator calibration failed\n"); | 734 | "internal oscillator calibration failed\n"); |
709 | } | 735 | } |
710 | 736 | ||
737 | static int dac33_startup(struct snd_pcm_substream *substream, | ||
738 | struct snd_soc_dai *dai) | ||
739 | { | ||
740 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
741 | struct snd_soc_device *socdev = rtd->socdev; | ||
742 | struct snd_soc_codec *codec = socdev->card->codec; | ||
743 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | ||
744 | |||
745 | /* Stream started, save the substream pointer */ | ||
746 | dac33->substream = substream; | ||
747 | |||
748 | return 0; | ||
749 | } | ||
750 | |||
751 | static void dac33_shutdown(struct snd_pcm_substream *substream, | ||
752 | struct snd_soc_dai *dai) | ||
753 | { | ||
754 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
755 | struct snd_soc_device *socdev = rtd->socdev; | ||
756 | struct snd_soc_codec *codec = socdev->card->codec; | ||
757 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | ||
758 | |||
759 | dac33->substream = NULL; | ||
760 | } | ||
761 | |||
711 | static int dac33_hw_params(struct snd_pcm_substream *substream, | 762 | static int dac33_hw_params(struct snd_pcm_substream *substream, |
712 | struct snd_pcm_hw_params *params, | 763 | struct snd_pcm_hw_params *params, |
713 | struct snd_soc_dai *dai) | 764 | struct snd_soc_dai *dai) |
@@ -791,6 +842,16 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) | |||
791 | } | 842 | } |
792 | 843 | ||
793 | mutex_lock(&dac33->mutex); | 844 | mutex_lock(&dac33->mutex); |
845 | |||
846 | if (!dac33->chip_power) { | ||
847 | /* | ||
848 | * Chip is not powered yet. | ||
849 | * Do the init in the dac33_set_bias_level later. | ||
850 | */ | ||
851 | mutex_unlock(&dac33->mutex); | ||
852 | return 0; | ||
853 | } | ||
854 | |||
794 | dac33_soft_power(codec, 0); | 855 | dac33_soft_power(codec, 0); |
795 | dac33_soft_power(codec, 1); | 856 | dac33_soft_power(codec, 1); |
796 | 857 | ||
@@ -997,15 +1058,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) | |||
997 | 1058 | ||
998 | } | 1059 | } |
999 | 1060 | ||
1000 | static int dac33_pcm_prepare(struct snd_pcm_substream *substream, | ||
1001 | struct snd_soc_dai *dai) | ||
1002 | { | ||
1003 | dac33_calculate_times(substream); | ||
1004 | dac33_prepare_chip(substream); | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | 1061 | static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, |
1010 | struct snd_soc_dai *dai) | 1062 | struct snd_soc_dai *dai) |
1011 | { | 1063 | { |
@@ -1269,35 +1321,6 @@ static int dac33_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
1269 | return 0; | 1321 | return 0; |
1270 | } | 1322 | } |
1271 | 1323 | ||
1272 | static void dac33_init_chip(struct snd_soc_codec *codec) | ||
1273 | { | ||
1274 | /* 44-46: DAC Control Registers */ | ||
1275 | /* A : DAC sample rate Fsref/1.5 */ | ||
1276 | dac33_write(codec, DAC33_DAC_CTRL_A, DAC33_DACRATE(0)); | ||
1277 | /* B : DAC src=normal, not muted */ | ||
1278 | dac33_write(codec, DAC33_DAC_CTRL_B, DAC33_DACSRCR_RIGHT | | ||
1279 | DAC33_DACSRCL_LEFT); | ||
1280 | /* C : (defaults) */ | ||
1281 | dac33_write(codec, DAC33_DAC_CTRL_C, 0x00); | ||
1282 | |||
1283 | /* 64-65 : L&R DAC power control | ||
1284 | Line In -> OUT 1V/V Gain, DAC -> OUT 4V/V Gain*/ | ||
1285 | dac33_write(codec, DAC33_LDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); | ||
1286 | dac33_write(codec, DAC33_RDAC_PWR_CTRL, DAC33_LROUT_GAIN(2)); | ||
1287 | |||
1288 | /* 73 : volume soft stepping control, | ||
1289 | clock source = internal osc (?) */ | ||
1290 | dac33_write(codec, DAC33_ANA_VOL_SOFT_STEP_CTRL, DAC33_VOLCLKEN); | ||
1291 | |||
1292 | /* 66 : LOP/LOM Modes */ | ||
1293 | dac33_write(codec, DAC33_OUT_AMP_CM_CTRL, 0xff); | ||
1294 | |||
1295 | /* 68 : LOM inverted from LOP */ | ||
1296 | dac33_write(codec, DAC33_OUT_AMP_CTRL, (3<<2)); | ||
1297 | |||
1298 | dac33_write(codec, DAC33_PWR_CTRL, DAC33_PDNALLB); | ||
1299 | } | ||
1300 | |||
1301 | static int dac33_soc_probe(struct platform_device *pdev) | 1324 | static int dac33_soc_probe(struct platform_device *pdev) |
1302 | { | 1325 | { |
1303 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 1326 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
@@ -1311,11 +1334,6 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1311 | socdev->card->codec = codec; | 1334 | socdev->card->codec = codec; |
1312 | dac33 = snd_soc_codec_get_drvdata(codec); | 1335 | dac33 = snd_soc_codec_get_drvdata(codec); |
1313 | 1336 | ||
1314 | /* Power up the codec */ | ||
1315 | dac33_hard_power(codec, 1); | ||
1316 | /* Set default configuration */ | ||
1317 | dac33_init_chip(codec); | ||
1318 | |||
1319 | /* register pcms */ | 1337 | /* register pcms */ |
1320 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); | 1338 | ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); |
1321 | if (ret < 0) { | 1339 | if (ret < 0) { |
@@ -1332,12 +1350,6 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1332 | 1350 | ||
1333 | dac33_add_widgets(codec); | 1351 | dac33_add_widgets(codec); |
1334 | 1352 | ||
1335 | /* power on device */ | ||
1336 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1337 | |||
1338 | /* Bias level configuration has enabled regulator an extra time */ | ||
1339 | regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1340 | |||
1341 | return 0; | 1353 | return 0; |
1342 | 1354 | ||
1343 | pcm_err: | 1355 | pcm_err: |
@@ -1374,6 +1386,8 @@ static int dac33_soc_resume(struct platform_device *pdev) | |||
1374 | struct snd_soc_codec *codec = socdev->card->codec; | 1386 | struct snd_soc_codec *codec = socdev->card->codec; |
1375 | 1387 | ||
1376 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1388 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1389 | if (codec->suspend_bias_level == SND_SOC_BIAS_ON) | ||
1390 | dac33_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
1377 | dac33_set_bias_level(codec, codec->suspend_bias_level); | 1391 | dac33_set_bias_level(codec, codec->suspend_bias_level); |
1378 | 1392 | ||
1379 | return 0; | 1393 | return 0; |
@@ -1392,8 +1406,9 @@ EXPORT_SYMBOL_GPL(soc_codec_dev_tlv320dac33); | |||
1392 | #define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE | 1406 | #define DAC33_FORMATS SNDRV_PCM_FMTBIT_S16_LE |
1393 | 1407 | ||
1394 | static struct snd_soc_dai_ops dac33_dai_ops = { | 1408 | static struct snd_soc_dai_ops dac33_dai_ops = { |
1409 | .startup = dac33_startup, | ||
1410 | .shutdown = dac33_shutdown, | ||
1395 | .hw_params = dac33_hw_params, | 1411 | .hw_params = dac33_hw_params, |
1396 | .prepare = dac33_pcm_prepare, | ||
1397 | .trigger = dac33_pcm_trigger, | 1412 | .trigger = dac33_pcm_trigger, |
1398 | .delay = dac33_dai_delay, | 1413 | .delay = dac33_dai_delay, |
1399 | .set_sysclk = dac33_set_dai_sysclk, | 1414 | .set_sysclk = dac33_set_dai_sysclk, |
@@ -1447,6 +1462,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1447 | codec->hw_write = (hw_write_t) i2c_master_send; | 1462 | codec->hw_write = (hw_write_t) i2c_master_send; |
1448 | codec->bias_level = SND_SOC_BIAS_OFF; | 1463 | codec->bias_level = SND_SOC_BIAS_OFF; |
1449 | codec->set_bias_level = dac33_set_bias_level; | 1464 | codec->set_bias_level = dac33_set_bias_level; |
1465 | codec->idle_bias_off = 1; | ||
1450 | codec->dai = &dac33_dai; | 1466 | codec->dai = &dac33_dai; |
1451 | codec->num_dai = 1; | 1467 | codec->num_dai = 1; |
1452 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); | 1468 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); |
@@ -1487,8 +1503,6 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1487 | goto error_gpio; | 1503 | goto error_gpio; |
1488 | } | 1504 | } |
1489 | gpio_direction_output(dac33->power_gpio, 0); | 1505 | gpio_direction_output(dac33->power_gpio, 0); |
1490 | } else { | ||
1491 | dac33->chip_power = 1; | ||
1492 | } | 1506 | } |
1493 | 1507 | ||
1494 | /* Check if the IRQ number is valid and request it */ | 1508 | /* Check if the IRQ number is valid and request it */ |
@@ -1526,12 +1540,14 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1526 | goto err_get; | 1540 | goto err_get; |
1527 | } | 1541 | } |
1528 | 1542 | ||
1529 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), | 1543 | /* Read the tlv320dac33 ID registers */ |
1530 | dac33->supplies); | 1544 | ret = dac33_hard_power(codec, 1); |
1531 | if (ret != 0) { | 1545 | if (ret != 0) { |
1532 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 1546 | dev_err(codec->dev, "Failed to power up codec: %d\n", ret); |
1533 | goto err_enable; | 1547 | goto error_codec; |
1534 | } | 1548 | } |
1549 | dac33_read_id(codec); | ||
1550 | dac33_hard_power(codec, 0); | ||
1535 | 1551 | ||
1536 | ret = snd_soc_register_codec(codec); | 1552 | ret = snd_soc_register_codec(codec); |
1537 | if (ret != 0) { | 1553 | if (ret != 0) { |
@@ -1546,14 +1562,9 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1546 | goto error_codec; | 1562 | goto error_codec; |
1547 | } | 1563 | } |
1548 | 1564 | ||
1549 | /* Shut down the codec for now */ | ||
1550 | dac33_hard_power(codec, 0); | ||
1551 | |||
1552 | return ret; | 1565 | return ret; |
1553 | 1566 | ||
1554 | error_codec: | 1567 | error_codec: |
1555 | regulator_bulk_disable(ARRAY_SIZE(dac33->supplies), dac33->supplies); | ||
1556 | err_enable: | ||
1557 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); | 1568 | regulator_bulk_free(ARRAY_SIZE(dac33->supplies), dac33->supplies); |
1558 | err_get: | 1569 | err_get: |
1559 | if (dac33->irq >= 0) { | 1570 | if (dac33->irq >= 0) { |
@@ -1577,7 +1588,9 @@ static int __devexit dac33_i2c_remove(struct i2c_client *client) | |||
1577 | struct tlv320dac33_priv *dac33; | 1588 | struct tlv320dac33_priv *dac33; |
1578 | 1589 | ||
1579 | dac33 = i2c_get_clientdata(client); | 1590 | dac33 = i2c_get_clientdata(client); |
1580 | dac33_hard_power(&dac33->codec, 0); | 1591 | |
1592 | if (unlikely(dac33->chip_power)) | ||
1593 | dac33_hard_power(&dac33->codec, 0); | ||
1581 | 1594 | ||
1582 | if (dac33->power_gpio >= 0) | 1595 | if (dac33->power_gpio >= 0) |
1583 | gpio_free(dac33->power_gpio); | 1596 | gpio_free(dac33->power_gpio); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 958d49c969ac..31f67b527ca1 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -46,6 +46,9 @@ static const char *tpa6140a2_supply_names[TPA6130A2_NUM_SUPPLIES] = { | |||
46 | "AVdd", | 46 | "AVdd", |
47 | }; | 47 | }; |
48 | 48 | ||
49 | #define TPA6130A2_GAIN_MAX 0x3f | ||
50 | #define TPA6140A2_GAIN_MAX 0x1f | ||
51 | |||
49 | /* This struct is used to save the context */ | 52 | /* This struct is used to save the context */ |
50 | struct tpa6130a2_data { | 53 | struct tpa6130a2_data { |
51 | struct mutex mutex; | 54 | struct mutex mutex; |
@@ -53,6 +56,8 @@ struct tpa6130a2_data { | |||
53 | struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; | 56 | struct regulator_bulk_data supplies[TPA6130A2_NUM_SUPPLIES]; |
54 | int power_gpio; | 57 | int power_gpio; |
55 | unsigned char power_state; | 58 | unsigned char power_state; |
59 | enum tpa_model id; | ||
60 | int gain_limit; | ||
56 | }; | 61 | }; |
57 | 62 | ||
58 | static int tpa6130a2_i2c_read(int reg) | 63 | static int tpa6130a2_i2c_read(int reg) |
@@ -175,6 +180,40 @@ exit: | |||
175 | return ret; | 180 | return ret; |
176 | } | 181 | } |
177 | 182 | ||
183 | static int tpa6130a2_info_volsw(struct snd_kcontrol *kcontrol, | ||
184 | struct snd_ctl_elem_info *uinfo) | ||
185 | { | ||
186 | struct soc_mixer_control *mc = | ||
187 | (struct soc_mixer_control *)kcontrol->private_value; | ||
188 | struct tpa6130a2_data *data; | ||
189 | |||
190 | BUG_ON(tpa6130a2_client == NULL); | ||
191 | data = i2c_get_clientdata(tpa6130a2_client); | ||
192 | |||
193 | mutex_lock(&data->mutex); | ||
194 | switch (mc->reg) { | ||
195 | case TPA6130A2_REG_VOL_MUTE: | ||
196 | if (data->gain_limit != mc->max) | ||
197 | mc->max = data->gain_limit; | ||
198 | break; | ||
199 | default: | ||
200 | dev_err(&tpa6130a2_client->dev, | ||
201 | "Invalid register: 0x02%x\n", mc->reg); | ||
202 | goto out; | ||
203 | } | ||
204 | if (unlikely(mc->max == 1)) | ||
205 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
206 | else | ||
207 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
208 | |||
209 | uinfo->count = 1; | ||
210 | uinfo->value.integer.min = 0; | ||
211 | uinfo->value.integer.max = mc->max; | ||
212 | out: | ||
213 | mutex_unlock(&data->mutex); | ||
214 | return 0; | ||
215 | } | ||
216 | |||
178 | static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, | 217 | static int tpa6130a2_get_reg(struct snd_kcontrol *kcontrol, |
179 | struct snd_ctl_elem_value *ucontrol) | 218 | struct snd_ctl_elem_value *ucontrol) |
180 | { | 219 | { |
@@ -238,6 +277,15 @@ static int tpa6130a2_set_reg(struct snd_kcontrol *kcontrol, | |||
238 | return 1; | 277 | return 1; |
239 | } | 278 | } |
240 | 279 | ||
280 | #define SOC_SINGLE_EXT_TLV_TPA(xname, xreg, xshift, xmax, xinvert, tlv_array) \ | ||
281 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
282 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
283 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
284 | .tlv.p = (tlv_array), \ | ||
285 | .info = tpa6130a2_info_volsw, \ | ||
286 | .get = tpa6130a2_get_reg, .put = tpa6130a2_set_reg, \ | ||
287 | .private_value = SOC_SINGLE_VALUE(xreg, xshift, xmax, xinvert) } | ||
288 | |||
241 | /* | 289 | /* |
242 | * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going | 290 | * TPA6130 volume. From -59.5 to 4 dB with increasing step size when going |
243 | * down in gain. | 291 | * down in gain. |
@@ -257,10 +305,22 @@ static const unsigned int tpa6130_tlv[] = { | |||
257 | }; | 305 | }; |
258 | 306 | ||
259 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { | 307 | static const struct snd_kcontrol_new tpa6130a2_controls[] = { |
260 | SOC_SINGLE_EXT_TLV("TPA6130A2 Headphone Playback Volume", | 308 | SOC_SINGLE_EXT_TLV_TPA("TPA6130A2 Headphone Playback Volume", |
261 | TPA6130A2_REG_VOL_MUTE, 0, 0x3f, 0, | 309 | TPA6130A2_REG_VOL_MUTE, 0, TPA6130A2_GAIN_MAX, 0, |
262 | tpa6130a2_get_reg, tpa6130a2_set_reg, | 310 | tpa6130_tlv), |
263 | tpa6130_tlv), | 311 | }; |
312 | |||
313 | static const unsigned int tpa6140_tlv[] = { | ||
314 | TLV_DB_RANGE_HEAD(3), | ||
315 | 0, 8, TLV_DB_SCALE_ITEM(-5900, 400, 0), | ||
316 | 9, 16, TLV_DB_SCALE_ITEM(-2500, 200, 0), | ||
317 | 17, 31, TLV_DB_SCALE_ITEM(-1000, 100, 0), | ||
318 | }; | ||
319 | |||
320 | static const struct snd_kcontrol_new tpa6140a2_controls[] = { | ||
321 | SOC_SINGLE_EXT_TLV_TPA("TPA6140A2 Headphone Playback Volume", | ||
322 | TPA6130A2_REG_VOL_MUTE, 1, TPA6140A2_GAIN_MAX, 0, | ||
323 | tpa6140_tlv), | ||
264 | }; | 324 | }; |
265 | 325 | ||
266 | /* | 326 | /* |
@@ -368,13 +428,22 @@ static const struct snd_soc_dapm_route audio_map[] = { | |||
368 | 428 | ||
369 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) | 429 | int tpa6130a2_add_controls(struct snd_soc_codec *codec) |
370 | { | 430 | { |
431 | struct tpa6130a2_data *data; | ||
432 | |||
433 | BUG_ON(tpa6130a2_client == NULL); | ||
434 | data = i2c_get_clientdata(tpa6130a2_client); | ||
435 | |||
371 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, | 436 | snd_soc_dapm_new_controls(codec, tpa6130a2_dapm_widgets, |
372 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); | 437 | ARRAY_SIZE(tpa6130a2_dapm_widgets)); |
373 | 438 | ||
374 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | 439 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); |
375 | 440 | ||
376 | return snd_soc_add_controls(codec, tpa6130a2_controls, | 441 | if (data->id == TPA6140A2) |
377 | ARRAY_SIZE(tpa6130a2_controls)); | 442 | return snd_soc_add_controls(codec, tpa6140a2_controls, |
443 | ARRAY_SIZE(tpa6140a2_controls)); | ||
444 | else | ||
445 | return snd_soc_add_controls(codec, tpa6130a2_controls, | ||
446 | ARRAY_SIZE(tpa6130a2_controls)); | ||
378 | 447 | ||
379 | } | 448 | } |
380 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); | 449 | EXPORT_SYMBOL_GPL(tpa6130a2_add_controls); |
@@ -407,6 +476,7 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
407 | 476 | ||
408 | pdata = client->dev.platform_data; | 477 | pdata = client->dev.platform_data; |
409 | data->power_gpio = pdata->power_gpio; | 478 | data->power_gpio = pdata->power_gpio; |
479 | data->id = pdata->id; | ||
410 | 480 | ||
411 | mutex_init(&data->mutex); | 481 | mutex_init(&data->mutex); |
412 | 482 | ||
@@ -425,20 +495,35 @@ static int __devinit tpa6130a2_probe(struct i2c_client *client, | |||
425 | gpio_direction_output(data->power_gpio, 0); | 495 | gpio_direction_output(data->power_gpio, 0); |
426 | } | 496 | } |
427 | 497 | ||
428 | switch (pdata->id) { | 498 | switch (data->id) { |
429 | case TPA6130A2: | 499 | case TPA6130A2: |
430 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | 500 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) |
431 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | 501 | data->supplies[i].supply = tpa6130a2_supply_names[i]; |
502 | if (pdata->limit_gain > 0 && | ||
503 | pdata->limit_gain < TPA6130A2_GAIN_MAX) | ||
504 | data->gain_limit = pdata->limit_gain; | ||
505 | else | ||
506 | data->gain_limit = TPA6130A2_GAIN_MAX; | ||
432 | break; | 507 | break; |
433 | case TPA6140A2: | 508 | case TPA6140A2: |
434 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | 509 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) |
435 | data->supplies[i].supply = tpa6140a2_supply_names[i];; | 510 | data->supplies[i].supply = tpa6140a2_supply_names[i];; |
511 | if (pdata->limit_gain > 0 && | ||
512 | pdata->limit_gain < TPA6140A2_GAIN_MAX) | ||
513 | data->gain_limit = pdata->limit_gain; | ||
514 | else | ||
515 | data->gain_limit = TPA6140A2_GAIN_MAX; | ||
436 | break; | 516 | break; |
437 | default: | 517 | default: |
438 | dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", | 518 | dev_warn(dev, "Unknown TPA model (%d). Assuming 6130A2\n", |
439 | pdata->id); | 519 | pdata->id); |
440 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) | 520 | for (i = 0; i < ARRAY_SIZE(data->supplies); i++) |
441 | data->supplies[i].supply = tpa6130a2_supply_names[i]; | 521 | data->supplies[i].supply = tpa6130a2_supply_names[i]; |
522 | if (pdata->limit_gain > 0 && | ||
523 | pdata->limit_gain < TPA6130A2_GAIN_MAX) | ||
524 | data->gain_limit = pdata->limit_gain; | ||
525 | else | ||
526 | data->gain_limit = TPA6130A2_GAIN_MAX; | ||
442 | } | 527 | } |
443 | 528 | ||
444 | ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), | 529 | ret = regulator_bulk_get(dev, ARRAY_SIZE(data->supplies), |
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c index 2e025a3a2618..b717a03dfacf 100644 --- a/sound/soc/codecs/twl4030.c +++ b/sound/soc/codecs/twl4030.c | |||
@@ -123,6 +123,8 @@ struct twl4030_priv { | |||
123 | struct snd_soc_codec codec; | 123 | struct snd_soc_codec codec; |
124 | 124 | ||
125 | unsigned int codec_powered; | 125 | unsigned int codec_powered; |
126 | |||
127 | /* reference counts of AIF/APLL users */ | ||
126 | unsigned int apll_enabled; | 128 | unsigned int apll_enabled; |
127 | 129 | ||
128 | struct snd_pcm_substream *master_substream; | 130 | struct snd_pcm_substream *master_substream; |
@@ -259,22 +261,22 @@ static void twl4030_init_chip(struct snd_soc_codec *codec) | |||
259 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) | 261 | static void twl4030_apll_enable(struct snd_soc_codec *codec, int enable) |
260 | { | 262 | { |
261 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); | 263 | struct twl4030_priv *twl4030 = snd_soc_codec_get_drvdata(codec); |
262 | int status; | 264 | int status = -1; |
263 | |||
264 | if (enable == twl4030->apll_enabled) | ||
265 | return; | ||
266 | 265 | ||
267 | if (enable) | 266 | if (enable) { |
268 | /* Enable PLL */ | 267 | twl4030->apll_enabled++; |
269 | status = twl4030_codec_enable_resource(TWL4030_CODEC_RES_APLL); | 268 | if (twl4030->apll_enabled == 1) |
270 | else | 269 | status = twl4030_codec_enable_resource( |
271 | /* Disable PLL */ | 270 | TWL4030_CODEC_RES_APLL); |
272 | status = twl4030_codec_disable_resource(TWL4030_CODEC_RES_APLL); | 271 | } else { |
272 | twl4030->apll_enabled--; | ||
273 | if (!twl4030->apll_enabled) | ||
274 | status = twl4030_codec_disable_resource( | ||
275 | TWL4030_CODEC_RES_APLL); | ||
276 | } | ||
273 | 277 | ||
274 | if (status >= 0) | 278 | if (status >= 0) |
275 | twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); | 279 | twl4030_write_reg_cache(codec, TWL4030_REG_APLL_CTL, status); |
276 | |||
277 | twl4030->apll_enabled = enable; | ||
278 | } | 280 | } |
279 | 281 | ||
280 | static void twl4030_power_up(struct snd_soc_codec *codec) | 282 | static void twl4030_power_up(struct snd_soc_codec *codec) |
@@ -672,6 +674,31 @@ static int apll_event(struct snd_soc_dapm_widget *w, | |||
672 | return 0; | 674 | return 0; |
673 | } | 675 | } |
674 | 676 | ||
677 | static int aif_event(struct snd_soc_dapm_widget *w, | ||
678 | struct snd_kcontrol *kcontrol, int event) | ||
679 | { | ||
680 | u8 audio_if; | ||
681 | |||
682 | audio_if = twl4030_read_reg_cache(w->codec, TWL4030_REG_AUDIO_IF); | ||
683 | switch (event) { | ||
684 | case SND_SOC_DAPM_PRE_PMU: | ||
685 | /* Enable AIF */ | ||
686 | /* enable the PLL before we use it to clock the DAI */ | ||
687 | twl4030_apll_enable(w->codec, 1); | ||
688 | |||
689 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | ||
690 | audio_if | TWL4030_AIF_EN); | ||
691 | break; | ||
692 | case SND_SOC_DAPM_POST_PMD: | ||
693 | /* disable the DAI before we stop it's source PLL */ | ||
694 | twl4030_write(w->codec, TWL4030_REG_AUDIO_IF, | ||
695 | audio_if & ~TWL4030_AIF_EN); | ||
696 | twl4030_apll_enable(w->codec, 0); | ||
697 | break; | ||
698 | } | ||
699 | return 0; | ||
700 | } | ||
701 | |||
675 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) | 702 | static void headset_ramp(struct snd_soc_codec *codec, int ramp) |
676 | { | 703 | { |
677 | struct snd_soc_device *socdev = codec->socdev; | 704 | struct snd_soc_device *socdev = codec->socdev; |
@@ -1167,8 +1194,6 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1167 | SND_SOC_DAPM_INPUT("DIGIMIC1"), | 1194 | SND_SOC_DAPM_INPUT("DIGIMIC1"), |
1168 | 1195 | ||
1169 | /* Outputs */ | 1196 | /* Outputs */ |
1170 | SND_SOC_DAPM_OUTPUT("OUTL"), | ||
1171 | SND_SOC_DAPM_OUTPUT("OUTR"), | ||
1172 | SND_SOC_DAPM_OUTPUT("EARPIECE"), | 1197 | SND_SOC_DAPM_OUTPUT("EARPIECE"), |
1173 | SND_SOC_DAPM_OUTPUT("PREDRIVEL"), | 1198 | SND_SOC_DAPM_OUTPUT("PREDRIVEL"), |
1174 | SND_SOC_DAPM_OUTPUT("PREDRIVER"), | 1199 | SND_SOC_DAPM_OUTPUT("PREDRIVER"), |
@@ -1180,6 +1205,11 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1180 | SND_SOC_DAPM_OUTPUT("HFR"), | 1205 | SND_SOC_DAPM_OUTPUT("HFR"), |
1181 | SND_SOC_DAPM_OUTPUT("VIBRA"), | 1206 | SND_SOC_DAPM_OUTPUT("VIBRA"), |
1182 | 1207 | ||
1208 | /* AIF and APLL clocks for running DAIs (including loopback) */ | ||
1209 | SND_SOC_DAPM_OUTPUT("Virtual HiFi OUT"), | ||
1210 | SND_SOC_DAPM_INPUT("Virtual HiFi IN"), | ||
1211 | SND_SOC_DAPM_OUTPUT("Virtual Voice OUT"), | ||
1212 | |||
1183 | /* DACs */ | 1213 | /* DACs */ |
1184 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", | 1214 | SND_SOC_DAPM_DAC("DAC Right1", "Right Front HiFi Playback", |
1185 | SND_SOC_NOPM, 0, 0), | 1215 | SND_SOC_NOPM, 0, 0), |
@@ -1243,7 +1273,8 @@ static const struct snd_soc_dapm_widget twl4030_dapm_widgets[] = { | |||
1243 | SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event, | 1273 | SND_SOC_DAPM_SUPPLY("APLL Enable", SND_SOC_NOPM, 0, 0, apll_event, |
1244 | SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), | 1274 | SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), |
1245 | 1275 | ||
1246 | SND_SOC_DAPM_SUPPLY("AIF Enable", TWL4030_REG_AUDIO_IF, 0, 0, NULL, 0), | 1276 | SND_SOC_DAPM_SUPPLY("AIF Enable", SND_SOC_NOPM, 0, 0, aif_event, |
1277 | SND_SOC_DAPM_PRE_PMU|SND_SOC_DAPM_POST_PMD), | ||
1247 | 1278 | ||
1248 | /* Output MIXER controls */ | 1279 | /* Output MIXER controls */ |
1249 | /* Earpiece */ | 1280 | /* Earpiece */ |
@@ -1373,10 +1404,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1373 | {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, | 1404 | {"Digital Voice Playback Mixer", NULL, "DAC Voice"}, |
1374 | 1405 | ||
1375 | /* Supply for the digital part (APLL) */ | 1406 | /* Supply for the digital part (APLL) */ |
1376 | {"Digital R1 Playback Mixer", NULL, "APLL Enable"}, | ||
1377 | {"Digital L1 Playback Mixer", NULL, "APLL Enable"}, | ||
1378 | {"Digital R2 Playback Mixer", NULL, "APLL Enable"}, | ||
1379 | {"Digital L2 Playback Mixer", NULL, "APLL Enable"}, | ||
1380 | {"Digital Voice Playback Mixer", NULL, "APLL Enable"}, | 1407 | {"Digital Voice Playback Mixer", NULL, "APLL Enable"}, |
1381 | 1408 | ||
1382 | {"Digital R1 Playback Mixer", NULL, "AIF Enable"}, | 1409 | {"Digital R1 Playback Mixer", NULL, "AIF Enable"}, |
@@ -1450,8 +1477,14 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1450 | {"Vibra Mux", "AudioR2", "DAC Right2"}, | 1477 | {"Vibra Mux", "AudioR2", "DAC Right2"}, |
1451 | 1478 | ||
1452 | /* outputs */ | 1479 | /* outputs */ |
1453 | {"OUTL", NULL, "Analog L2 Playback Mixer"}, | 1480 | /* Must be always connected (for AIF and APLL) */ |
1454 | {"OUTR", NULL, "Analog R2 Playback Mixer"}, | 1481 | {"Virtual HiFi OUT", NULL, "Digital L1 Playback Mixer"}, |
1482 | {"Virtual HiFi OUT", NULL, "Digital R1 Playback Mixer"}, | ||
1483 | {"Virtual HiFi OUT", NULL, "Digital L2 Playback Mixer"}, | ||
1484 | {"Virtual HiFi OUT", NULL, "Digital R2 Playback Mixer"}, | ||
1485 | /* Must be always connected (for APLL) */ | ||
1486 | {"Virtual Voice OUT", NULL, "Digital Voice Playback Mixer"}, | ||
1487 | /* Physical outputs */ | ||
1455 | {"EARPIECE", NULL, "Earpiece PGA"}, | 1488 | {"EARPIECE", NULL, "Earpiece PGA"}, |
1456 | {"PREDRIVEL", NULL, "PredriveL PGA"}, | 1489 | {"PREDRIVEL", NULL, "PredriveL PGA"}, |
1457 | {"PREDRIVER", NULL, "PredriveR PGA"}, | 1490 | {"PREDRIVER", NULL, "PredriveR PGA"}, |
@@ -1465,6 +1498,12 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1465 | {"VIBRA", NULL, "Vibra Route"}, | 1498 | {"VIBRA", NULL, "Vibra Route"}, |
1466 | 1499 | ||
1467 | /* Capture path */ | 1500 | /* Capture path */ |
1501 | /* Must be always connected (for AIF and APLL) */ | ||
1502 | {"ADC Virtual Left1", NULL, "Virtual HiFi IN"}, | ||
1503 | {"ADC Virtual Right1", NULL, "Virtual HiFi IN"}, | ||
1504 | {"ADC Virtual Left2", NULL, "Virtual HiFi IN"}, | ||
1505 | {"ADC Virtual Right2", NULL, "Virtual HiFi IN"}, | ||
1506 | /* Physical inputs */ | ||
1468 | {"Analog Left", "Main Mic Capture Switch", "MAINMIC"}, | 1507 | {"Analog Left", "Main Mic Capture Switch", "MAINMIC"}, |
1469 | {"Analog Left", "Headset Mic Capture Switch", "HSMIC"}, | 1508 | {"Analog Left", "Headset Mic Capture Switch", "HSMIC"}, |
1470 | {"Analog Left", "AUXL Capture Switch", "AUXL"}, | 1509 | {"Analog Left", "AUXL Capture Switch", "AUXL"}, |
@@ -1497,11 +1536,6 @@ static const struct snd_soc_dapm_route intercon[] = { | |||
1497 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, | 1536 | {"ADC Virtual Left2", NULL, "TX2 Capture Route"}, |
1498 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, | 1537 | {"ADC Virtual Right2", NULL, "TX2 Capture Route"}, |
1499 | 1538 | ||
1500 | {"ADC Virtual Left1", NULL, "APLL Enable"}, | ||
1501 | {"ADC Virtual Right1", NULL, "APLL Enable"}, | ||
1502 | {"ADC Virtual Left2", NULL, "APLL Enable"}, | ||
1503 | {"ADC Virtual Right2", NULL, "APLL Enable"}, | ||
1504 | |||
1505 | {"ADC Virtual Left1", NULL, "AIF Enable"}, | 1539 | {"ADC Virtual Left1", NULL, "AIF Enable"}, |
1506 | {"ADC Virtual Right1", NULL, "AIF Enable"}, | 1540 | {"ADC Virtual Right1", NULL, "AIF Enable"}, |
1507 | {"ADC Virtual Left2", NULL, "AIF Enable"}, | 1541 | {"ADC Virtual Left2", NULL, "AIF Enable"}, |
diff --git a/sound/soc/omap/Kconfig b/sound/soc/omap/Kconfig index f11963c21873..83be4a76d2bb 100644 --- a/sound/soc/omap/Kconfig +++ b/sound/soc/omap/Kconfig | |||
@@ -18,6 +18,16 @@ config SND_OMAP_SOC_N810 | |||
18 | help | 18 | help |
19 | Say Y if you want to add support for SoC audio on Nokia N810. | 19 | Say Y if you want to add support for SoC audio on Nokia N810. |
20 | 20 | ||
21 | config SND_OMAP_SOC_RX51 | ||
22 | tristate "SoC Audio support for Nokia RX-51" | ||
23 | depends on SND_OMAP_SOC && MACH_NOKIA_RX51 | ||
24 | select OMAP_MCBSP | ||
25 | select SND_OMAP_SOC_MCBSP | ||
26 | select SND_SOC_TLV320AIC3X | ||
27 | help | ||
28 | Say Y if you want to add support for SoC audio on Nokia RX-51 | ||
29 | hardware. This is also known as Nokia N900 product. | ||
30 | |||
21 | config SND_OMAP_SOC_AMS_DELTA | 31 | config SND_OMAP_SOC_AMS_DELTA |
22 | tristate "SoC Audio support for Amstrad E3 (Delta) videophone" | 32 | tristate "SoC Audio support for Amstrad E3 (Delta) videophone" |
23 | depends on SND_OMAP_SOC && MACH_AMS_DELTA | 33 | depends on SND_OMAP_SOC && MACH_AMS_DELTA |
diff --git a/sound/soc/omap/Makefile b/sound/soc/omap/Makefile index 0bc00ca14b37..3a75755f25e4 100644 --- a/sound/soc/omap/Makefile +++ b/sound/soc/omap/Makefile | |||
@@ -9,6 +9,7 @@ obj-$(CONFIG_SND_OMAP_SOC_MCPDM) += snd-soc-omap-mcpdm.o | |||
9 | 9 | ||
10 | # OMAP Machine Support | 10 | # OMAP Machine Support |
11 | snd-soc-n810-objs := n810.o | 11 | snd-soc-n810-objs := n810.o |
12 | snd-soc-rx51-objs := rx51.o | ||
12 | snd-soc-ams-delta-objs := ams-delta.o | 13 | snd-soc-ams-delta-objs := ams-delta.o |
13 | snd-soc-osk5912-objs := osk5912.o | 14 | snd-soc-osk5912-objs := osk5912.o |
14 | snd-soc-overo-objs := overo.o | 15 | snd-soc-overo-objs := overo.o |
@@ -22,6 +23,7 @@ snd-soc-zoom2-objs := zoom2.o | |||
22 | snd-soc-igep0020-objs := igep0020.o | 23 | snd-soc-igep0020-objs := igep0020.o |
23 | 24 | ||
24 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o | 25 | obj-$(CONFIG_SND_OMAP_SOC_N810) += snd-soc-n810.o |
26 | obj-$(CONFIG_SND_OMAP_SOC_RX51) += snd-soc-rx51.o | ||
25 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o | 27 | obj-$(CONFIG_SND_OMAP_SOC_AMS_DELTA) += snd-soc-ams-delta.o |
26 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o | 28 | obj-$(CONFIG_SND_OMAP_SOC_OSK5912) += snd-soc-osk5912.o |
27 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o | 29 | obj-$(CONFIG_SND_OMAP_SOC_OVERO) += snd-soc-overo.o |
diff --git a/sound/soc/omap/omap3pandora.c b/sound/soc/omap/omap3pandora.c index de10f76baded..87ce842fa2e8 100644 --- a/sound/soc/omap/omap3pandora.c +++ b/sound/soc/omap/omap3pandora.c | |||
@@ -188,8 +188,6 @@ static int omap3pandora_out_init(struct snd_soc_codec *codec) | |||
188 | int ret; | 188 | int ret; |
189 | 189 | ||
190 | /* All TWL4030 output pins are floating */ | 190 | /* All TWL4030 output pins are floating */ |
191 | snd_soc_dapm_nc_pin(codec, "OUTL"); | ||
192 | snd_soc_dapm_nc_pin(codec, "OUTR"); | ||
193 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); | 191 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); |
194 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); | 192 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); |
195 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); | 193 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); |
diff --git a/sound/soc/omap/rx51.c b/sound/soc/omap/rx51.c new file mode 100644 index 000000000000..47d831ef2dbb --- /dev/null +++ b/sound/soc/omap/rx51.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * rx51.c -- SoC audio for Nokia RX-51 | ||
3 | * | ||
4 | * Copyright (C) 2008 - 2009 Nokia Corporation | ||
5 | * | ||
6 | * Contact: Peter Ujfalusi <peter.ujfalusi@nokia.com> | ||
7 | * Eduardo Valentin <eduardo.valentin@nokia.com> | ||
8 | * Jarkko Nikula <jhnikula@gmail.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or | ||
11 | * modify it under the terms of the GNU General Public License | ||
12 | * version 2 as published by the Free Software Foundation. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License | ||
20 | * along with this program; if not, write to the Free Software | ||
21 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA | ||
22 | * 02110-1301 USA | ||
23 | * | ||
24 | */ | ||
25 | |||
26 | #include <linux/delay.h> | ||
27 | #include <linux/gpio.h> | ||
28 | #include <linux/platform_device.h> | ||
29 | #include <sound/core.h> | ||
30 | #include <sound/pcm.h> | ||
31 | #include <sound/soc.h> | ||
32 | #include <sound/soc-dapm.h> | ||
33 | |||
34 | #include <asm/mach-types.h> | ||
35 | |||
36 | #include "omap-mcbsp.h" | ||
37 | #include "omap-pcm.h" | ||
38 | #include "../codecs/tlv320aic3x.h" | ||
39 | |||
40 | /* | ||
41 | * REVISIT: TWL4030 GPIO base in RX-51. Now statically defined to 192. This | ||
42 | * gpio is reserved in arch/arm/mach-omap2/board-rx51-peripherals.c | ||
43 | */ | ||
44 | #define RX51_SPEAKER_AMP_TWL_GPIO (192 + 7) | ||
45 | |||
46 | static int rx51_spk_func; | ||
47 | static int rx51_dmic_func; | ||
48 | |||
49 | static void rx51_ext_control(struct snd_soc_codec *codec) | ||
50 | { | ||
51 | if (rx51_spk_func) | ||
52 | snd_soc_dapm_enable_pin(codec, "Ext Spk"); | ||
53 | else | ||
54 | snd_soc_dapm_disable_pin(codec, "Ext Spk"); | ||
55 | if (rx51_dmic_func) | ||
56 | snd_soc_dapm_enable_pin(codec, "DMic"); | ||
57 | else | ||
58 | snd_soc_dapm_disable_pin(codec, "DMic"); | ||
59 | |||
60 | snd_soc_dapm_sync(codec); | ||
61 | } | ||
62 | |||
63 | static int rx51_startup(struct snd_pcm_substream *substream) | ||
64 | { | ||
65 | struct snd_pcm_runtime *runtime = substream->runtime; | ||
66 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
67 | struct snd_soc_codec *codec = rtd->socdev->card->codec; | ||
68 | |||
69 | snd_pcm_hw_constraint_minmax(runtime, | ||
70 | SNDRV_PCM_HW_PARAM_CHANNELS, 2, 2); | ||
71 | rx51_ext_control(codec); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static int rx51_hw_params(struct snd_pcm_substream *substream, | ||
77 | struct snd_pcm_hw_params *params) | ||
78 | { | ||
79 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | ||
80 | struct snd_soc_dai *codec_dai = rtd->dai->codec_dai; | ||
81 | struct snd_soc_dai *cpu_dai = rtd->dai->cpu_dai; | ||
82 | int err; | ||
83 | |||
84 | /* Set codec DAI configuration */ | ||
85 | err = snd_soc_dai_set_fmt(codec_dai, | ||
86 | SND_SOC_DAIFMT_DSP_A | | ||
87 | SND_SOC_DAIFMT_IB_NF | | ||
88 | SND_SOC_DAIFMT_CBM_CFM); | ||
89 | if (err < 0) | ||
90 | return err; | ||
91 | |||
92 | /* Set cpu DAI configuration */ | ||
93 | err = snd_soc_dai_set_fmt(cpu_dai, | ||
94 | SND_SOC_DAIFMT_DSP_A | | ||
95 | SND_SOC_DAIFMT_IB_NF | | ||
96 | SND_SOC_DAIFMT_CBM_CFM); | ||
97 | if (err < 0) | ||
98 | return err; | ||
99 | |||
100 | /* Set the codec system clock for DAC and ADC */ | ||
101 | return snd_soc_dai_set_sysclk(codec_dai, 0, 19200000, | ||
102 | SND_SOC_CLOCK_IN); | ||
103 | } | ||
104 | |||
105 | static struct snd_soc_ops rx51_ops = { | ||
106 | .startup = rx51_startup, | ||
107 | .hw_params = rx51_hw_params, | ||
108 | }; | ||
109 | |||
110 | static int rx51_get_spk(struct snd_kcontrol *kcontrol, | ||
111 | struct snd_ctl_elem_value *ucontrol) | ||
112 | { | ||
113 | ucontrol->value.integer.value[0] = rx51_spk_func; | ||
114 | |||
115 | return 0; | ||
116 | } | ||
117 | |||
118 | static int rx51_set_spk(struct snd_kcontrol *kcontrol, | ||
119 | struct snd_ctl_elem_value *ucontrol) | ||
120 | { | ||
121 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
122 | |||
123 | if (rx51_spk_func == ucontrol->value.integer.value[0]) | ||
124 | return 0; | ||
125 | |||
126 | rx51_spk_func = ucontrol->value.integer.value[0]; | ||
127 | rx51_ext_control(codec); | ||
128 | |||
129 | return 1; | ||
130 | } | ||
131 | |||
132 | static int rx51_spk_event(struct snd_soc_dapm_widget *w, | ||
133 | struct snd_kcontrol *k, int event) | ||
134 | { | ||
135 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
136 | gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 1); | ||
137 | else | ||
138 | gpio_set_value(RX51_SPEAKER_AMP_TWL_GPIO, 0); | ||
139 | |||
140 | return 0; | ||
141 | } | ||
142 | |||
143 | static int rx51_get_input(struct snd_kcontrol *kcontrol, | ||
144 | struct snd_ctl_elem_value *ucontrol) | ||
145 | { | ||
146 | ucontrol->value.integer.value[0] = rx51_dmic_func; | ||
147 | |||
148 | return 0; | ||
149 | } | ||
150 | |||
151 | static int rx51_set_input(struct snd_kcontrol *kcontrol, | ||
152 | struct snd_ctl_elem_value *ucontrol) | ||
153 | { | ||
154 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
155 | |||
156 | if (rx51_dmic_func == ucontrol->value.integer.value[0]) | ||
157 | return 0; | ||
158 | |||
159 | rx51_dmic_func = ucontrol->value.integer.value[0]; | ||
160 | rx51_ext_control(codec); | ||
161 | |||
162 | return 1; | ||
163 | } | ||
164 | |||
165 | static const struct snd_soc_dapm_widget aic34_dapm_widgets[] = { | ||
166 | SND_SOC_DAPM_SPK("Ext Spk", rx51_spk_event), | ||
167 | SND_SOC_DAPM_MIC("DMic", NULL), | ||
168 | }; | ||
169 | |||
170 | static const struct snd_soc_dapm_route audio_map[] = { | ||
171 | {"Ext Spk", NULL, "HPLOUT"}, | ||
172 | {"Ext Spk", NULL, "HPROUT"}, | ||
173 | |||
174 | {"DMic Rate 64", NULL, "Mic Bias 2V"}, | ||
175 | {"Mic Bias 2V", NULL, "DMic"}, | ||
176 | }; | ||
177 | |||
178 | static const char *spk_function[] = {"Off", "On"}; | ||
179 | static const char *input_function[] = {"ADC", "Digital Mic"}; | ||
180 | |||
181 | static const struct soc_enum rx51_enum[] = { | ||
182 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(spk_function), spk_function), | ||
183 | SOC_ENUM_SINGLE_EXT(ARRAY_SIZE(input_function), input_function), | ||
184 | }; | ||
185 | |||
186 | static const struct snd_kcontrol_new aic34_rx51_controls[] = { | ||
187 | SOC_ENUM_EXT("Speaker Function", rx51_enum[0], | ||
188 | rx51_get_spk, rx51_set_spk), | ||
189 | SOC_ENUM_EXT("Input Select", rx51_enum[1], | ||
190 | rx51_get_input, rx51_set_input), | ||
191 | }; | ||
192 | |||
193 | static int rx51_aic34_init(struct snd_soc_codec *codec) | ||
194 | { | ||
195 | int err; | ||
196 | |||
197 | /* Set up NC codec pins */ | ||
198 | snd_soc_dapm_nc_pin(codec, "MIC3L"); | ||
199 | snd_soc_dapm_nc_pin(codec, "MIC3R"); | ||
200 | snd_soc_dapm_nc_pin(codec, "LINE1R"); | ||
201 | |||
202 | /* Add RX-51 specific controls */ | ||
203 | err = snd_soc_add_controls(codec, aic34_rx51_controls, | ||
204 | ARRAY_SIZE(aic34_rx51_controls)); | ||
205 | if (err < 0) | ||
206 | return err; | ||
207 | |||
208 | /* Add RX-51 specific widgets */ | ||
209 | snd_soc_dapm_new_controls(codec, aic34_dapm_widgets, | ||
210 | ARRAY_SIZE(aic34_dapm_widgets)); | ||
211 | |||
212 | /* Set up RX-51 specific audio path audio_map */ | ||
213 | snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | ||
214 | |||
215 | snd_soc_dapm_sync(codec); | ||
216 | |||
217 | return 0; | ||
218 | } | ||
219 | |||
220 | /* Digital audio interface glue - connects codec <--> CPU */ | ||
221 | static struct snd_soc_dai_link rx51_dai[] = { | ||
222 | { | ||
223 | .name = "TLV320AIC34", | ||
224 | .stream_name = "AIC34", | ||
225 | .cpu_dai = &omap_mcbsp_dai[0], | ||
226 | .codec_dai = &aic3x_dai, | ||
227 | .init = rx51_aic34_init, | ||
228 | .ops = &rx51_ops, | ||
229 | }, | ||
230 | }; | ||
231 | |||
232 | /* Audio private data */ | ||
233 | static struct aic3x_setup_data rx51_aic34_setup = { | ||
234 | .gpio_func[0] = AIC3X_GPIO1_FUNC_DISABLED, | ||
235 | .gpio_func[1] = AIC3X_GPIO2_FUNC_DIGITAL_MIC_INPUT, | ||
236 | }; | ||
237 | |||
238 | /* Audio card */ | ||
239 | static struct snd_soc_card rx51_sound_card = { | ||
240 | .name = "RX-51", | ||
241 | .dai_link = rx51_dai, | ||
242 | .num_links = ARRAY_SIZE(rx51_dai), | ||
243 | .platform = &omap_soc_platform, | ||
244 | }; | ||
245 | |||
246 | /* Audio subsystem */ | ||
247 | static struct snd_soc_device rx51_snd_devdata = { | ||
248 | .card = &rx51_sound_card, | ||
249 | .codec_dev = &soc_codec_dev_aic3x, | ||
250 | .codec_data = &rx51_aic34_setup, | ||
251 | }; | ||
252 | |||
253 | static struct platform_device *rx51_snd_device; | ||
254 | |||
255 | static int __init rx51_soc_init(void) | ||
256 | { | ||
257 | int err; | ||
258 | |||
259 | if (!machine_is_nokia_rx51()) | ||
260 | return -ENODEV; | ||
261 | |||
262 | rx51_snd_device = platform_device_alloc("soc-audio", -1); | ||
263 | if (!rx51_snd_device) { | ||
264 | err = -ENOMEM; | ||
265 | goto err1; | ||
266 | } | ||
267 | |||
268 | platform_set_drvdata(rx51_snd_device, &rx51_snd_devdata); | ||
269 | rx51_snd_devdata.dev = &rx51_snd_device->dev; | ||
270 | *(unsigned int *)rx51_dai[0].cpu_dai->private_data = 1; /* McBSP2 */ | ||
271 | |||
272 | err = platform_device_add(rx51_snd_device); | ||
273 | if (err) | ||
274 | goto err2; | ||
275 | |||
276 | return 0; | ||
277 | err2: | ||
278 | platform_device_put(rx51_snd_device); | ||
279 | err1: | ||
280 | |||
281 | return err; | ||
282 | } | ||
283 | |||
284 | static void __exit rx51_soc_exit(void) | ||
285 | { | ||
286 | platform_device_unregister(rx51_snd_device); | ||
287 | } | ||
288 | |||
289 | module_init(rx51_soc_init); | ||
290 | module_exit(rx51_soc_exit); | ||
291 | |||
292 | MODULE_AUTHOR("Nokia Corporation"); | ||
293 | MODULE_DESCRIPTION("ALSA SoC Nokia RX-51"); | ||
294 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/omap/zoom2.c b/sound/soc/omap/zoom2.c index f90a2ac888cf..50a94ee76ecc 100644 --- a/sound/soc/omap/zoom2.c +++ b/sound/soc/omap/zoom2.c | |||
@@ -181,9 +181,6 @@ static int zoom2_twl4030_init(struct snd_soc_codec *codec) | |||
181 | snd_soc_dapm_nc_pin(codec, "CARKITMIC"); | 181 | snd_soc_dapm_nc_pin(codec, "CARKITMIC"); |
182 | snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); | 182 | snd_soc_dapm_nc_pin(codec, "DIGIMIC0"); |
183 | snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); | 183 | snd_soc_dapm_nc_pin(codec, "DIGIMIC1"); |
184 | |||
185 | snd_soc_dapm_nc_pin(codec, "OUTL"); | ||
186 | snd_soc_dapm_nc_pin(codec, "OUTR"); | ||
187 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); | 184 | snd_soc_dapm_nc_pin(codec, "EARPIECE"); |
188 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); | 185 | snd_soc_dapm_nc_pin(codec, "PREDRIVEL"); |
189 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); | 186 | snd_soc_dapm_nc_pin(codec, "PREDRIVER"); |