diff options
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r-- | sound/soc/codecs/cs4270.c | 93 |
1 files changed, 40 insertions, 53 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 2c79a24186fd..cd4a9ee38e46 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -395,17 +395,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
395 | return -EINVAL; | 395 | return -EINVAL; |
396 | } | 396 | } |
397 | 397 | ||
398 | /* Freeze and power-down the codec */ | 398 | /* Set the sample rate */ |
399 | |||
400 | ret = snd_soc_write(codec, CS4270_PWRCTL, CS4270_PWRCTL_FREEZE | | ||
401 | CS4270_PWRCTL_PDN_ADC | CS4270_PWRCTL_PDN_DAC | | ||
402 | CS4270_PWRCTL_PDN); | ||
403 | if (ret < 0) { | ||
404 | dev_err(codec->dev, "i2c write failed\n"); | ||
405 | return ret; | ||
406 | } | ||
407 | |||
408 | /* Program the mode control register */ | ||
409 | 399 | ||
410 | reg = snd_soc_read(codec, CS4270_MODE); | 400 | reg = snd_soc_read(codec, CS4270_MODE); |
411 | reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); | 401 | reg &= ~(CS4270_MODE_SPEED_MASK | CS4270_MODE_DIV_MASK); |
@@ -417,7 +407,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
417 | return ret; | 407 | return ret; |
418 | } | 408 | } |
419 | 409 | ||
420 | /* Program the format register */ | 410 | /* Set the DAI format */ |
421 | 411 | ||
422 | reg = snd_soc_read(codec, CS4270_FORMAT); | 412 | reg = snd_soc_read(codec, CS4270_FORMAT); |
423 | reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); | 413 | reg &= ~(CS4270_FORMAT_DAC_MASK | CS4270_FORMAT_ADC_MASK); |
@@ -440,42 +430,9 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
440 | return ret; | 430 | return ret; |
441 | } | 431 | } |
442 | 432 | ||
443 | /* Disable auto-mute. This feature appears to be buggy, because in | ||
444 | some situations, auto-mute will not deactivate when it should. */ | ||
445 | |||
446 | reg = snd_soc_read(codec, CS4270_MUTE); | ||
447 | reg &= ~CS4270_MUTE_AUTO; | ||
448 | ret = snd_soc_write(codec, CS4270_MUTE, reg); | ||
449 | if (ret < 0) { | ||
450 | dev_err(codec->dev, "i2c write failed\n"); | ||
451 | return ret; | ||
452 | } | ||
453 | |||
454 | /* Disable automatic volume control. It's enabled by default, and | ||
455 | * it causes volume change commands to be delayed, sometimes until | ||
456 | * after playback has started. | ||
457 | */ | ||
458 | |||
459 | reg = cs4270_read_reg_cache(codec, CS4270_TRANS); | ||
460 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | ||
461 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | ||
462 | if (ret < 0) { | ||
463 | dev_err(codec->dev, "i2c write failed\n"); | ||
464 | return ret; | ||
465 | } | ||
466 | |||
467 | /* Thaw and power-up the codec */ | ||
468 | |||
469 | ret = snd_soc_write(codec, CS4270_PWRCTL, 0); | ||
470 | if (ret < 0) { | ||
471 | dev_err(codec->dev, "i2c write failed\n"); | ||
472 | return ret; | ||
473 | } | ||
474 | |||
475 | return ret; | 433 | return ret; |
476 | } | 434 | } |
477 | 435 | ||
478 | #ifdef CONFIG_SND_SOC_CS4270_HWMUTE | ||
479 | /** | 436 | /** |
480 | * cs4270_mute - enable/disable the CS4270 external mute | 437 | * cs4270_mute - enable/disable the CS4270 external mute |
481 | * @dai: the SOC DAI | 438 | * @dai: the SOC DAI |
@@ -494,22 +451,23 @@ static int cs4270_mute(struct snd_soc_dai *dai, int mute) | |||
494 | reg6 = snd_soc_read(codec, CS4270_MUTE); | 451 | reg6 = snd_soc_read(codec, CS4270_MUTE); |
495 | 452 | ||
496 | if (mute) | 453 | if (mute) |
497 | reg6 |= CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 454 | reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; |
498 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; | ||
499 | else | 455 | else |
500 | reg6 &= ~(CS4270_MUTE_ADC_A | CS4270_MUTE_ADC_B | | 456 | reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); |
501 | CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); | ||
502 | 457 | ||
503 | return snd_soc_write(codec, CS4270_MUTE, reg6); | 458 | return snd_soc_write(codec, CS4270_MUTE, reg6); |
504 | } | 459 | } |
505 | #else | ||
506 | #define cs4270_mute NULL | ||
507 | #endif | ||
508 | 460 | ||
509 | /* A list of non-DAPM controls that the CS4270 supports */ | 461 | /* A list of non-DAPM controls that the CS4270 supports */ |
510 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { | 462 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { |
511 | SOC_DOUBLE_R("Master Playback Volume", | 463 | SOC_DOUBLE_R("Master Playback Volume", |
512 | CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1) | 464 | CS4270_VOLA, CS4270_VOLB, 0, 0xFF, 1), |
465 | SOC_SINGLE("Digital Sidetone Switch", CS4270_FORMAT, 5, 1, 0), | ||
466 | SOC_SINGLE("Soft Ramp Switch", CS4270_TRANS, 6, 1, 0), | ||
467 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), | ||
468 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), | ||
469 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), | ||
470 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 0) | ||
513 | }; | 471 | }; |
514 | 472 | ||
515 | /* | 473 | /* |
@@ -637,6 +595,7 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
637 | { | 595 | { |
638 | struct snd_soc_codec *codec; | 596 | struct snd_soc_codec *codec; |
639 | struct cs4270_private *cs4270; | 597 | struct cs4270_private *cs4270; |
598 | unsigned int reg; | ||
640 | int ret; | 599 | int ret; |
641 | 600 | ||
642 | /* For now, we only support one cs4270 device in the system. See the | 601 | /* For now, we only support one cs4270 device in the system. See the |
@@ -702,6 +661,34 @@ static int cs4270_i2c_probe(struct i2c_client *i2c_client, | |||
702 | goto error_free_codec; | 661 | goto error_free_codec; |
703 | } | 662 | } |
704 | 663 | ||
664 | /* Disable auto-mute. This feature appears to be buggy. In some | ||
665 | * situations, auto-mute will not deactivate when it should, so we want | ||
666 | * this feature disabled by default. An application (e.g. alsactl) can | ||
667 | * re-enabled it by using the controls. | ||
668 | */ | ||
669 | |||
670 | reg = cs4270_read_reg_cache(codec, CS4270_MUTE); | ||
671 | reg &= ~CS4270_MUTE_AUTO; | ||
672 | ret = cs4270_i2c_write(codec, CS4270_MUTE, reg); | ||
673 | if (ret < 0) { | ||
674 | dev_err(&i2c_client->dev, "i2c write failed\n"); | ||
675 | return ret; | ||
676 | } | ||
677 | |||
678 | /* Disable automatic volume control. The hardware enables, and it | ||
679 | * causes volume change commands to be delayed, sometimes until after | ||
680 | * playback has started. An application (e.g. alsactl) can | ||
681 | * re-enabled it by using the controls. | ||
682 | */ | ||
683 | |||
684 | reg = cs4270_read_reg_cache(codec, CS4270_TRANS); | ||
685 | reg &= ~(CS4270_TRANS_SOFT | CS4270_TRANS_ZERO); | ||
686 | ret = cs4270_i2c_write(codec, CS4270_TRANS, reg); | ||
687 | if (ret < 0) { | ||
688 | dev_err(&i2c_client->dev, "i2c write failed\n"); | ||
689 | return ret; | ||
690 | } | ||
691 | |||
705 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI | 692 | /* Initialize the DAI. Normally, we'd prefer to have a kmalloc'd DAI |
706 | * structure for each CS4270 device, but the machine driver needs to | 693 | * structure for each CS4270 device, but the machine driver needs to |
707 | * have a pointer to the DAI structure, so for now it must be a global | 694 | * have a pointer to the DAI structure, so for now it must be a global |