diff options
author | Daniel Mack <daniel@caiaq.de> | 2009-04-24 10:37:45 -0400 |
---|---|---|
committer | Mark Brown <broonie@opensource.wolfsonmicro.com> | 2009-04-27 15:38:56 -0400 |
commit | 1a4ba05ec8369d62c10155a8931e81267bfbd31c (patch) | |
tree | 3f26e312c8b93adf411178be73ad221681ebbf98 /sound/soc/codecs/cs4270.c | |
parent | 9c935386512a3faa1be1c3d81cba38b7259a43f5 (diff) |
ASoC: cs4270: add Master Playback Switch
This adds a new control named 'Master Playback Switch' for cs4270
codecs. It is implemented using the new SOC_DOUBLE_EXT macro to catch
the put function and store the information about manually set mute
controls from userspace. When a manual mute is set, we don't want the
soc core to un-mute the outputs.
Renamed cs4270_mute() to cs4270_dai_mute() to avoid confusion.
Signed-off-by: Daniel Mack <daniel@caiaq.de>
Acked-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.c | 44 |
1 files changed, 39 insertions, 5 deletions
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 3c34fe67c3d7..ece6ed6a844f 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -109,6 +109,7 @@ struct cs4270_private { | |||
109 | unsigned int mclk; /* Input frequency of the MCLK pin */ | 109 | unsigned int mclk; /* Input frequency of the MCLK pin */ |
110 | unsigned int mode; /* The mode (I2S or left-justified) */ | 110 | unsigned int mode; /* The mode (I2S or left-justified) */ |
111 | unsigned int slave_mode; | 111 | unsigned int slave_mode; |
112 | unsigned int manual_mute; | ||
112 | }; | 113 | }; |
113 | 114 | ||
114 | /** | 115 | /** |
@@ -453,7 +454,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
453 | } | 454 | } |
454 | 455 | ||
455 | /** | 456 | /** |
456 | * cs4270_mute - enable/disable the CS4270 external mute | 457 | * cs4270_dai_mute - enable/disable the CS4270 external mute |
457 | * @dai: the SOC DAI | 458 | * @dai: the SOC DAI |
458 | * @mute: 0 = disable mute, 1 = enable mute | 459 | * @mute: 0 = disable mute, 1 = enable mute |
459 | * | 460 | * |
@@ -462,21 +463,52 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, | |||
462 | * board does not have the MUTEA or MUTEB pins connected to such circuitry, | 463 | * board does not have the MUTEA or MUTEB pins connected to such circuitry, |
463 | * then this function will do nothing. | 464 | * then this function will do nothing. |
464 | */ | 465 | */ |
465 | static int cs4270_mute(struct snd_soc_dai *dai, int mute) | 466 | static int cs4270_dai_mute(struct snd_soc_dai *dai, int mute) |
466 | { | 467 | { |
467 | struct snd_soc_codec *codec = dai->codec; | 468 | struct snd_soc_codec *codec = dai->codec; |
469 | struct cs4270_private *cs4270 = codec->private_data; | ||
468 | int reg6; | 470 | int reg6; |
469 | 471 | ||
470 | reg6 = snd_soc_read(codec, CS4270_MUTE); | 472 | reg6 = snd_soc_read(codec, CS4270_MUTE); |
471 | 473 | ||
472 | if (mute) | 474 | if (mute) |
473 | reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; | 475 | reg6 |= CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B; |
474 | else | 476 | else { |
475 | reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); | 477 | reg6 &= ~(CS4270_MUTE_DAC_A | CS4270_MUTE_DAC_B); |
478 | reg6 |= cs4270->manual_mute; | ||
479 | } | ||
476 | 480 | ||
477 | return snd_soc_write(codec, CS4270_MUTE, reg6); | 481 | return snd_soc_write(codec, CS4270_MUTE, reg6); |
478 | } | 482 | } |
479 | 483 | ||
484 | /** | ||
485 | * cs4270_soc_put_mute - put callback for the 'Master Playback switch' | ||
486 | * alsa control. | ||
487 | * @kcontrol: mixer control | ||
488 | * @ucontrol: control element information | ||
489 | * | ||
490 | * This function basically passes the arguments on to the generic | ||
491 | * snd_soc_put_volsw() function and saves the mute information in | ||
492 | * our private data structure. This is because we want to prevent | ||
493 | * cs4270_dai_mute() neglecting the user's decision to manually | ||
494 | * mute the codec's output. | ||
495 | * | ||
496 | * Returns 0 for success. | ||
497 | */ | ||
498 | static int cs4270_soc_put_mute(struct snd_kcontrol *kcontrol, | ||
499 | struct snd_ctl_elem_value *ucontrol) | ||
500 | { | ||
501 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
502 | struct cs4270_private *cs4270 = codec->private_data; | ||
503 | int left = !ucontrol->value.integer.value[0]; | ||
504 | int right = !ucontrol->value.integer.value[1]; | ||
505 | |||
506 | cs4270->manual_mute = (left ? CS4270_MUTE_DAC_A : 0) | | ||
507 | (right ? CS4270_MUTE_DAC_B : 0); | ||
508 | |||
509 | return snd_soc_put_volsw(kcontrol, ucontrol); | ||
510 | } | ||
511 | |||
480 | /* A list of non-DAPM controls that the CS4270 supports */ | 512 | /* A list of non-DAPM controls that the CS4270 supports */ |
481 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { | 513 | static const struct snd_kcontrol_new cs4270_snd_controls[] = { |
482 | SOC_DOUBLE_R("Master Playback Volume", | 514 | SOC_DOUBLE_R("Master Playback Volume", |
@@ -486,7 +518,9 @@ static const struct snd_kcontrol_new cs4270_snd_controls[] = { | |||
486 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), | 518 | SOC_SINGLE("Zero Cross Switch", CS4270_TRANS, 5, 1, 0), |
487 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), | 519 | SOC_SINGLE("Popguard Switch", CS4270_MODE, 0, 1, 1), |
488 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), | 520 | SOC_SINGLE("Auto-Mute Switch", CS4270_MUTE, 5, 1, 0), |
489 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1) | 521 | SOC_DOUBLE("Master Capture Switch", CS4270_MUTE, 3, 4, 1, 1), |
522 | SOC_DOUBLE_EXT("Master Playback Switch", CS4270_MUTE, 0, 1, 1, 1, | ||
523 | snd_soc_get_volsw, cs4270_soc_put_mute), | ||
490 | }; | 524 | }; |
491 | 525 | ||
492 | /* | 526 | /* |
@@ -506,7 +540,7 @@ static struct snd_soc_dai_ops cs4270_dai_ops = { | |||
506 | .hw_params = cs4270_hw_params, | 540 | .hw_params = cs4270_hw_params, |
507 | .set_sysclk = cs4270_set_dai_sysclk, | 541 | .set_sysclk = cs4270_set_dai_sysclk, |
508 | .set_fmt = cs4270_set_dai_fmt, | 542 | .set_fmt = cs4270_set_dai_fmt, |
509 | .digital_mute = cs4270_mute, | 543 | .digital_mute = cs4270_dai_mute, |
510 | }; | 544 | }; |
511 | 545 | ||
512 | struct snd_soc_dai cs4270_dai = { | 546 | struct snd_soc_dai cs4270_dai = { |