aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPhilipp Zabel <philipp.zabel@gmail.com>2009-03-03 10:10:54 -0500
committerMark Brown <broonie@opensource.wolfsonmicro.com>2009-03-03 10:54:10 -0500
commitef9e5e5c31cb2c6254760611289ac13e4e41b964 (patch)
treec22bc109481c5ae446c8ddfab4c9486bd9cf5e7a
parenta3c7729e6c5d41bbeb3e13befbcf8e4ef76e55dc (diff)
ASoC: UDA1380: change decimator/interpolator register handling
If the UDA1380's interpolator or decimator are set to be clocked from the WSPLL (which syncs to the WSI signal), the DAI link must be running to change the interpolator/decimator registers (which include volume controls and digital mute setting). * Queue work in the alsa PCM_START .trigger to flush registers as soon as the link is running. This replaces the .prepare and .digital_mute callbacks. * Use the SILENCE override instead of MTM for muting and remove its alsa control to avoid confusion. Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--sound/soc/codecs/uda1380.c102
1 files changed, 48 insertions, 54 deletions
diff --git a/sound/soc/codecs/uda1380.c b/sound/soc/codecs/uda1380.c
index 8686a554536e..1c9d2a75addb 100644
--- a/sound/soc/codecs/uda1380.c
+++ b/sound/soc/codecs/uda1380.c
@@ -25,6 +25,7 @@
25#include <linux/ioctl.h> 25#include <linux/ioctl.h>
26#include <linux/delay.h> 26#include <linux/delay.h>
27#include <linux/i2c.h> 27#include <linux/i2c.h>
28#include <linux/workqueue.h>
28#include <sound/core.h> 29#include <sound/core.h>
29#include <sound/control.h> 30#include <sound/control.h>
30#include <sound/initval.h> 31#include <sound/initval.h>
@@ -35,6 +36,9 @@
35 36
36#include "uda1380.h" 37#include "uda1380.h"
37 38
39static struct work_struct uda1380_work;
40static struct snd_soc_codec *uda1380_codec;
41
38/* 42/*
39 * uda1380 register cache 43 * uda1380 register cache
40 */ 44 */
@@ -50,6 +54,8 @@ static const u16 uda1380_reg[UDA1380_CACHEREGNUM] = {
50 0x0000, 0x8000, 0x0002, 0x0000, 54 0x0000, 0x8000, 0x0002, 0x0000,
51}; 55};
52 56
57static unsigned long uda1380_cache_dirty;
58
53/* 59/*
54 * read uda1380 register cache 60 * read uda1380 register cache
55 */ 61 */
@@ -71,8 +77,11 @@ static inline void uda1380_write_reg_cache(struct snd_soc_codec *codec,
71 u16 reg, unsigned int value) 77 u16 reg, unsigned int value)
72{ 78{
73 u16 *cache = codec->reg_cache; 79 u16 *cache = codec->reg_cache;
80
74 if (reg >= UDA1380_CACHEREGNUM) 81 if (reg >= UDA1380_CACHEREGNUM)
75 return; 82 return;
83 if ((reg >= 0x10) && (cache[reg] != value))
84 set_bit(reg - 0x10, &uda1380_cache_dirty);
76 cache[reg] = value; 85 cache[reg] = value;
77} 86}
78 87
@@ -111,6 +120,8 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
111 (data[0]<<8) | data[1]); 120 (data[0]<<8) | data[1]);
112 return -EIO; 121 return -EIO;
113 } 122 }
123 if (reg >= 0x10)
124 clear_bit(reg - 0x10, &uda1380_cache_dirty);
114 return 0; 125 return 0;
115 } else 126 } else
116 return -EIO; 127 return -EIO;
@@ -118,6 +129,20 @@ static int uda1380_write(struct snd_soc_codec *codec, unsigned int reg,
118 129
119#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0) 130#define uda1380_reset(c) uda1380_write(c, UDA1380_RESET, 0)
120 131
132static void uda1380_flush_work(struct work_struct *work)
133{
134 int bit, reg;
135
136 for_each_bit(bit, &uda1380_cache_dirty, UDA1380_CACHEREGNUM - 0x10) {
137 reg = 0x10 + bit;
138 pr_debug("uda1380: flush reg %x val %x:\n", reg,
139 uda1380_read_reg_cache(uda1380_codec, reg));
140 uda1380_write(uda1380_codec, reg,
141 uda1380_read_reg_cache(uda1380_codec, reg));
142 clear_bit(bit, &uda1380_cache_dirty);
143 }
144}
145
121/* declarations of ALSA reg_elem_REAL controls */ 146/* declarations of ALSA reg_elem_REAL controls */
122static const char *uda1380_deemp[] = { 147static const char *uda1380_deemp[] = {
123 "None", 148 "None",
@@ -252,7 +277,6 @@ static const struct snd_kcontrol_new uda1380_snd_controls[] = {
252 SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */ 277 SOC_SINGLE("DAC Polarity inverting Switch", UDA1380_MIXER, 15, 1, 0), /* DA_POL_INV */
253 SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */ 278 SOC_ENUM("Noise Shaper", uda1380_sel_ns_enum), /* SEL_NS */
254 SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */ 279 SOC_ENUM("Digital Mixer Signal Control", uda1380_mix_enum), /* MIX_POS, MIX */
255 SOC_SINGLE("Silence Switch", UDA1380_MIXER, 7, 1, 0), /* SILENCE, force DAC output to silence */
256 SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */ 280 SOC_SINGLE("Silence Detector Switch", UDA1380_MIXER, 6, 1, 0), /* SDET_ON */
257 SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */ 281 SOC_ENUM("Silence Detector Setting", uda1380_sdet_enum), /* SD_VALUE */
258 SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */ 282 SOC_ENUM("Oversampling Input", uda1380_os_enum), /* OS */
@@ -438,41 +462,28 @@ static int uda1380_set_dai_fmt_capture(struct snd_soc_dai *codec_dai,
438 return 0; 462 return 0;
439} 463}
440 464
441/* 465static int uda1380_trigger(struct snd_pcm_substream *substream, int cmd,
442 * Flush reg cache 466 struct snd_soc_dai *dai)
443 * We can only write the interpolator and decimator registers
444 * when the DAI is being clocked by the CPU DAI. It's up to the
445 * machine and cpu DAI driver to do this before we are called.
446 */
447static int uda1380_pcm_prepare(struct snd_pcm_substream *substream,
448 struct snd_soc_dai *dai)
449{ 467{
450 struct snd_soc_pcm_runtime *rtd = substream->private_data; 468 struct snd_soc_pcm_runtime *rtd = substream->private_data;
451 struct snd_soc_device *socdev = rtd->socdev; 469 struct snd_soc_device *socdev = rtd->socdev;
452 struct snd_soc_codec *codec = socdev->card->codec; 470 struct snd_soc_codec *codec = socdev->card->codec;
453 int reg, reg_start, reg_end, clk; 471 int mixer = uda1380_read_reg_cache(codec, UDA1380_MIXER);
454 472
455 if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { 473 switch (cmd) {
456 reg_start = UDA1380_MVOL; 474 case SNDRV_PCM_TRIGGER_START:
457 reg_end = UDA1380_MIXER; 475 case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
458 } else { 476 uda1380_write_reg_cache(codec, UDA1380_MIXER,
459 reg_start = UDA1380_DEC; 477 mixer & ~R14_SILENCE);
460 reg_end = UDA1380_AGC; 478 schedule_work(&uda1380_work);
461 } 479 break;
462 480 case SNDRV_PCM_TRIGGER_STOP:
463 /* FIXME disable DAC_CLK */ 481 case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
464 clk = uda1380_read_reg_cache(codec, UDA1380_CLK); 482 uda1380_write_reg_cache(codec, UDA1380_MIXER,
465 uda1380_write(codec, UDA1380_CLK, clk & ~R00_DAC_CLK); 483 mixer | R14_SILENCE);
466 484 schedule_work(&uda1380_work);
467 for (reg = reg_start; reg <= reg_end; reg++) { 485 break;
468 pr_debug("uda1380: flush reg %x val %x:", reg,
469 uda1380_read_reg_cache(codec, reg));
470 uda1380_write(codec, reg, uda1380_read_reg_cache(codec, reg));
471 } 486 }
472
473 /* FIXME restore DAC_CLK */
474 uda1380_write(codec, UDA1380_CLK, clk);
475
476 return 0; 487 return 0;
477} 488}
478 489
@@ -538,24 +549,6 @@ static void uda1380_pcm_shutdown(struct snd_pcm_substream *substream,
538 uda1380_write(codec, UDA1380_CLK, clk); 549 uda1380_write(codec, UDA1380_CLK, clk);
539} 550}
540 551
541static int uda1380_mute(struct snd_soc_dai *codec_dai, int mute)
542{
543 struct snd_soc_codec *codec = codec_dai->codec;
544 u16 mute_reg = uda1380_read_reg_cache(codec, UDA1380_DEEMP) & ~R13_MTM;
545
546 /* FIXME: mute(codec,0) is called when the magician clock is already
547 * set to WSPLL, but for some unknown reason writing to interpolator
548 * registers works only when clocked by SYSCLK */
549 u16 clk = uda1380_read_reg_cache(codec, UDA1380_CLK);
550 uda1380_write(codec, UDA1380_CLK, ~R00_DAC_CLK & clk);
551 if (mute)
552 uda1380_write(codec, UDA1380_DEEMP, mute_reg | R13_MTM);
553 else
554 uda1380_write(codec, UDA1380_DEEMP, mute_reg);
555 uda1380_write(codec, UDA1380_CLK, clk);
556 return 0;
557}
558
559static int uda1380_set_bias_level(struct snd_soc_codec *codec, 552static int uda1380_set_bias_level(struct snd_soc_codec *codec,
560 enum snd_soc_bias_level level) 553 enum snd_soc_bias_level level)
561{ 554{
@@ -597,10 +590,9 @@ struct snd_soc_dai uda1380_dai[] = {
597 .rates = UDA1380_RATES, 590 .rates = UDA1380_RATES,
598 .formats = SNDRV_PCM_FMTBIT_S16_LE,}, 591 .formats = SNDRV_PCM_FMTBIT_S16_LE,},
599 .ops = { 592 .ops = {
593 .trigger = uda1380_trigger,
600 .hw_params = uda1380_pcm_hw_params, 594 .hw_params = uda1380_pcm_hw_params,
601 .shutdown = uda1380_pcm_shutdown, 595 .shutdown = uda1380_pcm_shutdown,
602 .prepare = uda1380_pcm_prepare,
603 .digital_mute = uda1380_mute,
604 .set_fmt = uda1380_set_dai_fmt_both, 596 .set_fmt = uda1380_set_dai_fmt_both,
605 }, 597 },
606}, 598},
@@ -614,10 +606,9 @@ struct snd_soc_dai uda1380_dai[] = {
614 .formats = SNDRV_PCM_FMTBIT_S16_LE, 606 .formats = SNDRV_PCM_FMTBIT_S16_LE,
615 }, 607 },
616 .ops = { 608 .ops = {
609 .trigger = uda1380_trigger,
617 .hw_params = uda1380_pcm_hw_params, 610 .hw_params = uda1380_pcm_hw_params,
618 .shutdown = uda1380_pcm_shutdown, 611 .shutdown = uda1380_pcm_shutdown,
619 .prepare = uda1380_pcm_prepare,
620 .digital_mute = uda1380_mute,
621 .set_fmt = uda1380_set_dai_fmt_playback, 612 .set_fmt = uda1380_set_dai_fmt_playback,
622 }, 613 },
623}, 614},
@@ -631,9 +622,9 @@ struct snd_soc_dai uda1380_dai[] = {
631 .formats = SNDRV_PCM_FMTBIT_S16_LE, 622 .formats = SNDRV_PCM_FMTBIT_S16_LE,
632 }, 623 },
633 .ops = { 624 .ops = {
625 .trigger = uda1380_trigger,
634 .hw_params = uda1380_pcm_hw_params, 626 .hw_params = uda1380_pcm_hw_params,
635 .shutdown = uda1380_pcm_shutdown, 627 .shutdown = uda1380_pcm_shutdown,
636 .prepare = uda1380_pcm_prepare,
637 .set_fmt = uda1380_set_dai_fmt_capture, 628 .set_fmt = uda1380_set_dai_fmt_capture,
638 }, 629 },
639}, 630},
@@ -692,6 +683,9 @@ static int uda1380_init(struct snd_soc_device *socdev, int dac_clk)
692 codec->reg_cache_step = 1; 683 codec->reg_cache_step = 1;
693 uda1380_reset(codec); 684 uda1380_reset(codec);
694 685
686 uda1380_codec = codec;
687 INIT_WORK(&uda1380_work, uda1380_flush_work);
688
695 /* register pcms */ 689 /* register pcms */
696 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1); 690 ret = snd_soc_new_pcms(socdev, SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1);
697 if (ret < 0) { 691 if (ret < 0) {