aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/cs4270.c
diff options
context:
space:
mode:
authorTimur Tabi <timur@freescale.com>2009-02-03 12:09:32 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-02-13 08:32:51 -0500
commitd5e9ba1d58b6da1c58a91113fc350ece97ec5a0b (patch)
treec6b9435abab7a889784f76ef6a746316d914a934 /sound/soc/codecs/cs4270.c
parent9e32ebdb3aa4e5d2366b032baa16b95f3d7788b9 (diff)
ASoC: add additional controls to the CS4270 codec driver
Update the CS4270 codec driver to allow applications to use the mixer to control Digital Loopback, Soft Ramp, Zero Cross, Popguard, and Auto-Mute. Soft Ramp, Zero Cross, and Auto-Mute are disabled by the driver when it first initializes the hardware, but these features either don't work or interfere with normal ALSA behavior. However, they can now be re-enabled by an application if desired. Remove CONFIG_SND_SOC_CS4270_HWMUTE and always allow ASoC to control the mute bits. The driver previously and erroneously assumed that these bits control only external muting circuitry, but they also control internal muting circuitry, so they should always be used. Signed-off-by: Timur Tabi <timur@freescale.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound/soc/codecs/cs4270.c')
-rw-r--r--sound/soc/codecs/cs4270.c93
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 */
510static const struct snd_kcontrol_new cs4270_snd_controls[] = { 462static 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