aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/sh/rcar/dvc.c34
1 files changed, 29 insertions, 5 deletions
diff --git a/sound/soc/sh/rcar/dvc.c b/sound/soc/sh/rcar/dvc.c
index 12a0a2068d34..3f443930c2b1 100644
--- a/sound/soc/sh/rcar/dvc.c
+++ b/sound/soc/sh/rcar/dvc.c
@@ -21,6 +21,7 @@ struct rsnd_dvc {
21 struct rsnd_mod mod; 21 struct rsnd_mod mod;
22 struct clk *clk; 22 struct clk *clk;
23 u8 volume[RSND_DVC_VOLUME_NUM]; 23 u8 volume[RSND_DVC_VOLUME_NUM];
24 u8 mute[RSND_DVC_VOLUME_NUM];
24}; 25};
25 26
26#define rsnd_mod_to_dvc(_mod) \ 27#define rsnd_mod_to_dvc(_mod) \
@@ -37,13 +38,18 @@ static void rsnd_dvc_volume_update(struct rsnd_mod *mod)
37 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod); 38 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
38 u32 max = (0x00800000 - 1); 39 u32 max = (0x00800000 - 1);
39 u32 vol[RSND_DVC_VOLUME_NUM]; 40 u32 vol[RSND_DVC_VOLUME_NUM];
41 u32 mute = 0;
40 int i; 42 int i;
41 43
42 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) 44 for (i = 0; i < RSND_DVC_VOLUME_NUM; i++) {
43 vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i]; 45 vol[i] = max / RSND_DVC_VOLUME_MAX * dvc->volume[i];
46 mute |= (!!dvc->mute[i]) << i;
47 }
44 48
45 rsnd_mod_write(mod, DVC_VOL0R, vol[0]); 49 rsnd_mod_write(mod, DVC_VOL0R, vol[0]);
46 rsnd_mod_write(mod, DVC_VOL1R, vol[1]); 50 rsnd_mod_write(mod, DVC_VOL1R, vol[1]);
51
52 rsnd_mod_write(mod, DVC_ZCMCR, mute);
47} 53}
48 54
49static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, 55static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod,
@@ -96,8 +102,8 @@ static int rsnd_dvc_init(struct rsnd_mod *dvc_mod,
96 102
97 rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod)); 103 rsnd_mod_write(dvc_mod, DVC_ADINR, rsnd_get_adinr(dvc_mod));
98 104
99 /* enable Volume */ 105 /* enable Volume / Mute */
100 rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x100); 106 rsnd_mod_write(dvc_mod, DVC_DVUCR, 0x101);
101 107
102 /* ch0/ch1 Volume */ 108 /* ch0/ch1 Volume */
103 rsnd_dvc_volume_update(dvc_mod); 109 rsnd_dvc_volume_update(dvc_mod);
@@ -140,10 +146,20 @@ static int rsnd_dvc_stop(struct rsnd_mod *mod,
140static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, 146static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl,
141 struct snd_ctl_elem_info *uinfo) 147 struct snd_ctl_elem_info *uinfo)
142{ 148{
143 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; 149 struct rsnd_mod *mod = snd_kcontrol_chip(kctrl);
150 struct rsnd_dvc *dvc = rsnd_mod_to_dvc(mod);
151 u8 *val = (u8 *)kctrl->private_value;
152
144 uinfo->count = RSND_DVC_VOLUME_NUM; 153 uinfo->count = RSND_DVC_VOLUME_NUM;
145 uinfo->value.integer.min = 0; 154 uinfo->value.integer.min = 0;
146 uinfo->value.integer.max = RSND_DVC_VOLUME_MAX; 155
156 if (val == dvc->volume) {
157 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
158 uinfo->value.integer.max = RSND_DVC_VOLUME_MAX;
159 } else {
160 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN;
161 uinfo->value.integer.max = 1;
162 }
147 163
148 return 0; 164 return 0;
149} 165}
@@ -223,6 +239,14 @@ static int rsnd_dvc_pcm_new(struct rsnd_mod *mod,
223 if (ret < 0) 239 if (ret < 0)
224 return ret; 240 return ret;
225 241
242 /* Mute */
243 ret = __rsnd_dvc_pcm_new(mod, rdai, rtd,
244 rsnd_dai_is_play(rdai, io) ?
245 "DVC Out Mute Switch" : "DVC In Mute Switch",
246 dvc->mute);
247 if (ret < 0)
248 return ret;
249
226 return 0; 250 return 0;
227} 251}
228 252