diff options
-rw-r--r-- | sound/soc/sh/rcar/dvc.c | 34 |
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 | ||
49 | static int rsnd_dvc_probe_gen2(struct rsnd_mod *mod, | 55 | static 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, | |||
140 | static int rsnd_dvc_volume_info(struct snd_kcontrol *kctrl, | 146 | static 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 | ||