diff options
Diffstat (limited to 'sound/soc/codecs/tlv320dac33.c')
-rw-r--r-- | sound/soc/codecs/tlv320dac33.c | 66 |
1 files changed, 45 insertions, 21 deletions
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 50d152215abd..68b7ccbf2e7c 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 | ||
@@ -355,9 +357,17 @@ static inline void dac33_soft_power(struct snd_soc_codec *codec, int power) | |||
355 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) | 357 | static int dac33_hard_power(struct snd_soc_codec *codec, int power) |
356 | { | 358 | { |
357 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); | 359 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(codec); |
358 | int ret; | 360 | int ret = 0; |
359 | 361 | ||
360 | mutex_lock(&dac33->mutex); | 362 | mutex_lock(&dac33->mutex); |
363 | |||
364 | /* Safety check */ | ||
365 | if (unlikely(power == dac33->chip_power)) { | ||
366 | dev_warn(codec->dev, "Trying to set the same power state: %s\n", | ||
367 | power ? "ON" : "OFF"); | ||
368 | goto exit; | ||
369 | } | ||
370 | |||
361 | if (power) { | 371 | if (power) { |
362 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), | 372 | ret = regulator_bulk_enable(ARRAY_SIZE(dac33->supplies), |
363 | dac33->supplies); | 373 | dac33->supplies); |
@@ -371,10 +381,6 @@ static int dac33_hard_power(struct snd_soc_codec *codec, int power) | |||
371 | gpio_set_value(dac33->power_gpio, 1); | 381 | gpio_set_value(dac33->power_gpio, 1); |
372 | 382 | ||
373 | dac33->chip_power = 1; | 383 | dac33->chip_power = 1; |
374 | |||
375 | dac33_init_chip(codec); | ||
376 | |||
377 | dac33_soft_power(codec, 1); | ||
378 | } else { | 384 | } else { |
379 | dac33_soft_power(codec, 0); | 385 | dac33_soft_power(codec, 0); |
380 | if (dac33->power_gpio >= 0) | 386 | if (dac33->power_gpio >= 0) |
@@ -396,6 +402,22 @@ exit: | |||
396 | return ret; | 402 | return ret; |
397 | } | 403 | } |
398 | 404 | ||
405 | static int playback_event(struct snd_soc_dapm_widget *w, | ||
406 | struct snd_kcontrol *kcontrol, int event) | ||
407 | { | ||
408 | struct tlv320dac33_priv *dac33 = snd_soc_codec_get_drvdata(w->codec); | ||
409 | |||
410 | switch (event) { | ||
411 | case SND_SOC_DAPM_PRE_PMU: | ||
412 | if (likely(dac33->substream)) { | ||
413 | dac33_calculate_times(dac33->substream); | ||
414 | dac33_prepare_chip(dac33->substream); | ||
415 | } | ||
416 | break; | ||
417 | } | ||
418 | return 0; | ||
419 | } | ||
420 | |||
399 | static int dac33_get_nsample(struct snd_kcontrol *kcontrol, | 421 | static int dac33_get_nsample(struct snd_kcontrol *kcontrol, |
400 | struct snd_ctl_elem_value *ucontrol) | 422 | struct snd_ctl_elem_value *ucontrol) |
401 | { | 423 | { |
@@ -525,6 +547,8 @@ static const struct snd_soc_dapm_widget dac33_dapm_widgets[] = { | |||
525 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), | 547 | DAC33_OUT_AMP_PWR_CTRL, 6, 3, 3, 0), |
526 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", | 548 | SND_SOC_DAPM_REG(snd_soc_dapm_mixer, "Output Right Amp Power", |
527 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), | 549 | DAC33_OUT_AMP_PWR_CTRL, 4, 3, 3, 0), |
550 | |||
551 | SND_SOC_DAPM_PRE("Prepare Playback", playback_event), | ||
528 | }; | 552 | }; |
529 | 553 | ||
530 | static const struct snd_soc_dapm_route audio_map[] = { | 554 | static const struct snd_soc_dapm_route audio_map[] = { |
@@ -567,18 +591,18 @@ static int dac33_set_bias_level(struct snd_soc_codec *codec, | |||
567 | break; | 591 | break; |
568 | case SND_SOC_BIAS_STANDBY: | 592 | case SND_SOC_BIAS_STANDBY: |
569 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 593 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
594 | /* Coming from OFF, switch on the codec */ | ||
570 | ret = dac33_hard_power(codec, 1); | 595 | ret = dac33_hard_power(codec, 1); |
571 | if (ret != 0) | 596 | if (ret != 0) |
572 | return ret; | 597 | return ret; |
573 | } | ||
574 | 598 | ||
575 | dac33_soft_power(codec, 0); | 599 | dac33_init_chip(codec); |
600 | } | ||
576 | break; | 601 | break; |
577 | case SND_SOC_BIAS_OFF: | 602 | case SND_SOC_BIAS_OFF: |
578 | ret = dac33_hard_power(codec, 0); | 603 | ret = dac33_hard_power(codec, 0); |
579 | if (ret != 0) | 604 | if (ret != 0) |
580 | return ret; | 605 | return ret; |
581 | |||
582 | break; | 606 | break; |
583 | } | 607 | } |
584 | codec->bias_level = level; | 608 | codec->bias_level = level; |
@@ -829,6 +853,16 @@ static int dac33_prepare_chip(struct snd_pcm_substream *substream) | |||
829 | } | 853 | } |
830 | 854 | ||
831 | mutex_lock(&dac33->mutex); | 855 | mutex_lock(&dac33->mutex); |
856 | |||
857 | if (!dac33->chip_power) { | ||
858 | /* | ||
859 | * Chip is not powered yet. | ||
860 | * Do the init in the dac33_set_bias_level later. | ||
861 | */ | ||
862 | mutex_unlock(&dac33->mutex); | ||
863 | return 0; | ||
864 | } | ||
865 | |||
832 | dac33_soft_power(codec, 0); | 866 | dac33_soft_power(codec, 0); |
833 | dac33_soft_power(codec, 1); | 867 | dac33_soft_power(codec, 1); |
834 | 868 | ||
@@ -1035,15 +1069,6 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream) | |||
1035 | 1069 | ||
1036 | } | 1070 | } |
1037 | 1071 | ||
1038 | static int dac33_pcm_prepare(struct snd_pcm_substream *substream, | ||
1039 | struct snd_soc_dai *dai) | ||
1040 | { | ||
1041 | dac33_calculate_times(substream); | ||
1042 | dac33_prepare_chip(substream); | ||
1043 | |||
1044 | return 0; | ||
1045 | } | ||
1046 | |||
1047 | static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, | 1072 | static int dac33_pcm_trigger(struct snd_pcm_substream *substream, int cmd, |
1048 | struct snd_soc_dai *dai) | 1073 | struct snd_soc_dai *dai) |
1049 | { | 1074 | { |
@@ -1336,9 +1361,6 @@ static int dac33_soc_probe(struct platform_device *pdev) | |||
1336 | 1361 | ||
1337 | dac33_add_widgets(codec); | 1362 | dac33_add_widgets(codec); |
1338 | 1363 | ||
1339 | /* power on device */ | ||
1340 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1341 | |||
1342 | return 0; | 1364 | return 0; |
1343 | 1365 | ||
1344 | pcm_err: | 1366 | pcm_err: |
@@ -1375,6 +1397,8 @@ static int dac33_soc_resume(struct platform_device *pdev) | |||
1375 | struct snd_soc_codec *codec = socdev->card->codec; | 1397 | struct snd_soc_codec *codec = socdev->card->codec; |
1376 | 1398 | ||
1377 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1399 | dac33_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1400 | if (codec->suspend_bias_level == SND_SOC_BIAS_ON) | ||
1401 | dac33_set_bias_level(codec, SND_SOC_BIAS_PREPARE); | ||
1378 | dac33_set_bias_level(codec, codec->suspend_bias_level); | 1402 | dac33_set_bias_level(codec, codec->suspend_bias_level); |
1379 | 1403 | ||
1380 | return 0; | 1404 | return 0; |
@@ -1396,7 +1420,6 @@ static struct snd_soc_dai_ops dac33_dai_ops = { | |||
1396 | .startup = dac33_startup, | 1420 | .startup = dac33_startup, |
1397 | .shutdown = dac33_shutdown, | 1421 | .shutdown = dac33_shutdown, |
1398 | .hw_params = dac33_hw_params, | 1422 | .hw_params = dac33_hw_params, |
1399 | .prepare = dac33_pcm_prepare, | ||
1400 | .trigger = dac33_pcm_trigger, | 1423 | .trigger = dac33_pcm_trigger, |
1401 | .delay = dac33_dai_delay, | 1424 | .delay = dac33_dai_delay, |
1402 | .set_sysclk = dac33_set_dai_sysclk, | 1425 | .set_sysclk = dac33_set_dai_sysclk, |
@@ -1450,6 +1473,7 @@ static int __devinit dac33_i2c_probe(struct i2c_client *client, | |||
1450 | codec->hw_write = (hw_write_t) i2c_master_send; | 1473 | codec->hw_write = (hw_write_t) i2c_master_send; |
1451 | codec->bias_level = SND_SOC_BIAS_OFF; | 1474 | codec->bias_level = SND_SOC_BIAS_OFF; |
1452 | codec->set_bias_level = dac33_set_bias_level; | 1475 | codec->set_bias_level = dac33_set_bias_level; |
1476 | codec->idle_bias_off = 1; | ||
1453 | codec->dai = &dac33_dai; | 1477 | codec->dai = &dac33_dai; |
1454 | codec->num_dai = 1; | 1478 | codec->num_dai = 1; |
1455 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); | 1479 | codec->reg_cache_size = ARRAY_SIZE(dac33_reg); |