diff options
author | Philipp Zabel <philipp.zabel@gmail.com> | 2008-01-10 08:37:42 -0500 |
---|---|---|
committer | Jaroslav Kysela <perex@perex.cz> | 2008-01-31 11:29:50 -0500 |
commit | a7a4ac86b4754f44eb06221f3087debb4775d588 (patch) | |
tree | 63240035ca77fca21c4bb3b0db7566f53501053a | |
parent | 0b4d221b8d56deefca4984d01b3a010107ae1f72 (diff) |
[ALSA] ASoC TLV support
Add TLV support to ASoC.
Signed-off-by: Philipp Zabel <philipp.zabel@gmail.com>
Signed-off-by: Liam Girdwood <lg@opensource.wolfsonmicro.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Jaroslav Kysela <perex@perex.cz>
-rw-r--r-- | include/sound/soc-dapm.h | 24 | ||||
-rw-r--r-- | include/sound/soc.h | 58 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 66 | ||||
-rw-r--r-- | sound/soc/soc-dapm.c | 14 |
4 files changed, 114 insertions, 48 deletions
diff --git a/include/sound/soc-dapm.h b/include/sound/soc-dapm.h index 4158cbaa0f25..491f81e89847 100644 --- a/include/sound/soc-dapm.h +++ b/include/sound/soc-dapm.h | |||
@@ -131,18 +131,34 @@ | |||
131 | .shift = wshift, .invert = winvert} | 131 | .shift = wshift, .invert = winvert} |
132 | 132 | ||
133 | /* dapm kcontrol types */ | 133 | /* dapm kcontrol types */ |
134 | #define SOC_DAPM_SINGLE(xname, reg, shift, mask, invert) \ | 134 | #define SOC_DAPM_SINGLE(xname, reg, shift, max, invert) \ |
135 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 135 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
136 | .info = snd_soc_info_volsw, \ | 136 | .info = snd_soc_info_volsw, \ |
137 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | 137 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ |
138 | .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } | 138 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } |
139 | #define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, mask, invert, \ | 139 | #define SOC_DAPM_DOUBLE(xname, reg, shift_left, shift_right, max, invert, \ |
140 | power) \ | 140 | power) \ |
141 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 141 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
142 | .info = snd_soc_info_volsw, \ | 142 | .info = snd_soc_info_volsw, \ |
143 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | 143 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ |
144 | .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\ | 144 | .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\ |
145 | ((mask) << 16) | ((invert) << 24) } | 145 | ((max) << 16) | ((invert) << 24) } |
146 | #define SOC_DAPM_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ | ||
147 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
148 | .info = snd_soc_info_volsw, \ | ||
149 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
150 | .tlv.p = (tlv_array), \ | ||
151 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | ||
152 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
153 | #define SOC_DAPM_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, \ | ||
154 | power, tlv_array) \ | ||
155 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | ||
156 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
157 | .tlv.p = (tlv_array), \ | ||
158 | .info = snd_soc_info_volsw, \ | ||
159 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw, \ | ||
160 | .private_value = (reg) | ((shift_left) << 8) | ((shift_right) << 12) |\ | ||
161 | ((max) << 16) | ((invert) << 24) } | ||
146 | #define SOC_DAPM_ENUM(xname, xenum) \ | 162 | #define SOC_DAPM_ENUM(xname, xenum) \ |
147 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 163 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
148 | .info = snd_soc_info_enum_double, \ | 164 | .info = snd_soc_info_enum_double, \ |
diff --git a/include/sound/soc.h b/include/sound/soc.h index add5f948e383..0afcdfe42a46 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -26,27 +26,53 @@ | |||
26 | /* | 26 | /* |
27 | * Convenience kcontrol builders | 27 | * Convenience kcontrol builders |
28 | */ | 28 | */ |
29 | #define SOC_SINGLE_VALUE(reg,shift,mask,invert) ((reg) | ((shift) << 8) |\ | 29 | #define SOC_SINGLE_VALUE(reg, shift, max, invert) ((reg) | ((shift) << 8) |\ |
30 | ((shift) << 12) | ((mask) << 16) | ((invert) << 24)) | 30 | ((shift) << 12) | ((max) << 16) | ((invert) << 24)) |
31 | #define SOC_SINGLE_VALUE_EXT(reg,mask,invert) ((reg) | ((mask) << 16) |\ | 31 | #define SOC_SINGLE_VALUE_EXT(reg, max, invert) ((reg) | ((max) << 16) |\ |
32 | ((invert) << 31)) | 32 | ((invert) << 31)) |
33 | #define SOC_SINGLE(xname, reg, shift, mask, invert) \ | 33 | #define SOC_SINGLE(xname, reg, shift, max, invert) \ |
34 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 34 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
35 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | 35 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ |
36 | .put = snd_soc_put_volsw, \ | 36 | .put = snd_soc_put_volsw, \ |
37 | .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } | 37 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } |
38 | #define SOC_DOUBLE(xname, reg, shift_left, shift_right, mask, invert) \ | 38 | #define SOC_SINGLE_TLV(xname, reg, shift, max, invert, tlv_array) \ |
39 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
40 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
41 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
42 | .tlv.p = (tlv_array), \ | ||
43 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | ||
44 | .put = snd_soc_put_volsw, \ | ||
45 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
46 | #define SOC_DOUBLE(xname, reg, shift_left, shift_right, max, invert) \ | ||
39 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | 47 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ |
40 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ | 48 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ |
41 | .put = snd_soc_put_volsw, \ | 49 | .put = snd_soc_put_volsw, \ |
42 | .private_value = (reg) | ((shift_left) << 8) | \ | 50 | .private_value = (reg) | ((shift_left) << 8) | \ |
43 | ((shift_right) << 12) | ((mask) << 16) | ((invert) << 24) } | 51 | ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) } |
44 | #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, mask, invert) \ | 52 | #define SOC_DOUBLE_R(xname, reg_left, reg_right, shift, max, invert) \ |
45 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 53 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ |
46 | .info = snd_soc_info_volsw_2r, \ | 54 | .info = snd_soc_info_volsw_2r, \ |
47 | .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ | 55 | .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ |
48 | .private_value = (reg_left) | ((shift) << 8) | \ | 56 | .private_value = (reg_left) | ((shift) << 8) | \ |
49 | ((mask) << 12) | ((invert) << 20) | ((reg_right) << 24) } | 57 | ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) } |
58 | #define SOC_DOUBLE_TLV(xname, reg, shift_left, shift_right, max, invert, tlv_array) \ | ||
59 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | ||
60 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
61 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
62 | .tlv.p = (tlv_array), \ | ||
63 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, \ | ||
64 | .put = snd_soc_put_volsw, \ | ||
65 | .private_value = (reg) | ((shift_left) << 8) | \ | ||
66 | ((shift_right) << 12) | ((max) << 16) | ((invert) << 24) } | ||
67 | #define SOC_DOUBLE_R_TLV(xname, reg_left, reg_right, shift, max, invert, tlv_array) \ | ||
68 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname),\ | ||
69 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | ||
70 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
71 | .tlv.p = (tlv_array), \ | ||
72 | .info = snd_soc_info_volsw_2r, \ | ||
73 | .get = snd_soc_get_volsw_2r, .put = snd_soc_put_volsw_2r, \ | ||
74 | .private_value = (reg_left) | ((shift) << 8) | \ | ||
75 | ((max) << 12) | ((invert) << 20) | ((reg_right) << 24) } | ||
50 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ | 76 | #define SOC_ENUM_DOUBLE(xreg, xshift_l, xshift_r, xmask, xtexts) \ |
51 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ | 77 | { .reg = xreg, .shift_l = xshift_l, .shift_r = xshift_r, \ |
52 | .mask = xmask, .texts = xtexts } | 78 | .mask = xmask, .texts = xtexts } |
@@ -104,9 +130,21 @@ | |||
104 | #define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */ | 130 | #define SND_SOC_DAIFMT_GATED (1 << 4) /* clock is gated when not Tx/Rx */ |
105 | 131 | ||
106 | /* | 132 | /* |
133 | * DAI Sync | ||
134 | * Synchronous LR (Left Right) clocks and Frame signals. | ||
135 | */ | ||
136 | #define SND_SOC_DAIFMT_SYNC (0 << 5) /* Tx FRM = Rx FRM */ | ||
137 | #define SND_SOC_DAIFMT_ASYNC (1 << 5) /* Tx FRM ~ Rx FRM */ | ||
138 | |||
139 | /* | ||
140 | * TDM | ||
141 | */ | ||
142 | #define SND_SOC_DAIFMT_TDM (1 << 6) | ||
143 | |||
144 | /* | ||
107 | * DAI hardware signal inversions | 145 | * DAI hardware signal inversions |
108 | */ | 146 | */ |
109 | #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bit clock + frame */ | 147 | #define SND_SOC_DAIFMT_NB_NF (0 << 8) /* normal bclk + frm */ |
110 | #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ | 148 | #define SND_SOC_DAIFMT_NB_IF (1 << 8) /* normal bclk + inv frm */ |
111 | #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ | 149 | #define SND_SOC_DAIFMT_IB_NF (2 << 8) /* invert bclk + nor frm */ |
112 | #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ | 150 | #define SND_SOC_DAIFMT_IB_IF (3 << 8) /* invert bclk + frm */ |
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index bd656db347ee..e748b00466b7 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1213,7 +1213,6 @@ struct snd_kcontrol *snd_soc_cnew(const struct snd_kcontrol_new *_template, | |||
1213 | memcpy(&template, _template, sizeof(template)); | 1213 | memcpy(&template, _template, sizeof(template)); |
1214 | if (long_name) | 1214 | if (long_name) |
1215 | template.name = long_name; | 1215 | template.name = long_name; |
1216 | template.access = SNDRV_CTL_ELEM_ACCESS_READWRITE; | ||
1217 | template.index = 0; | 1216 | template.index = 0; |
1218 | 1217 | ||
1219 | return snd_ctl_new1(&template, data); | 1218 | return snd_ctl_new1(&template, data); |
@@ -1348,13 +1347,16 @@ EXPORT_SYMBOL_GPL(snd_soc_info_enum_ext); | |||
1348 | int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, | 1347 | int snd_soc_info_volsw_ext(struct snd_kcontrol *kcontrol, |
1349 | struct snd_ctl_elem_info *uinfo) | 1348 | struct snd_ctl_elem_info *uinfo) |
1350 | { | 1349 | { |
1351 | int mask = kcontrol->private_value; | 1350 | int max = kcontrol->private_value; |
1351 | |||
1352 | if (max == 1) | ||
1353 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1354 | else | ||
1355 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1352 | 1356 | ||
1353 | uinfo->type = | ||
1354 | mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1355 | uinfo->count = 1; | 1357 | uinfo->count = 1; |
1356 | uinfo->value.integer.min = 0; | 1358 | uinfo->value.integer.min = 0; |
1357 | uinfo->value.integer.max = mask; | 1359 | uinfo->value.integer.max = max; |
1358 | return 0; | 1360 | return 0; |
1359 | } | 1361 | } |
1360 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); | 1362 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); |
@@ -1371,15 +1373,18 @@ EXPORT_SYMBOL_GPL(snd_soc_info_volsw_ext); | |||
1371 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, | 1373 | int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, |
1372 | struct snd_ctl_elem_info *uinfo) | 1374 | struct snd_ctl_elem_info *uinfo) |
1373 | { | 1375 | { |
1374 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1376 | int max = (kcontrol->private_value >> 16) & 0xff; |
1375 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1377 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1376 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1378 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1377 | 1379 | ||
1378 | uinfo->type = | 1380 | if (max == 1) |
1379 | mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | 1381 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; |
1382 | else | ||
1383 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1384 | |||
1380 | uinfo->count = shift == rshift ? 1 : 2; | 1385 | uinfo->count = shift == rshift ? 1 : 2; |
1381 | uinfo->value.integer.min = 0; | 1386 | uinfo->value.integer.min = 0; |
1382 | uinfo->value.integer.max = mask; | 1387 | uinfo->value.integer.max = max; |
1383 | return 0; | 1388 | return 0; |
1384 | } | 1389 | } |
1385 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); | 1390 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw); |
@@ -1400,7 +1405,8 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
1400 | int reg = kcontrol->private_value & 0xff; | 1405 | int reg = kcontrol->private_value & 0xff; |
1401 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1406 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1402 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1407 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1403 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1408 | int max = (kcontrol->private_value >> 16) & 0xff; |
1409 | int mask = (1 << fls(max)) - 1; | ||
1404 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1410 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1405 | 1411 | ||
1406 | ucontrol->value.integer.value[0] = | 1412 | ucontrol->value.integer.value[0] = |
@@ -1410,10 +1416,10 @@ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, | |||
1410 | (snd_soc_read(codec, reg) >> rshift) & mask; | 1416 | (snd_soc_read(codec, reg) >> rshift) & mask; |
1411 | if (invert) { | 1417 | if (invert) { |
1412 | ucontrol->value.integer.value[0] = | 1418 | ucontrol->value.integer.value[0] = |
1413 | mask - ucontrol->value.integer.value[0]; | 1419 | max - ucontrol->value.integer.value[0]; |
1414 | if (shift != rshift) | 1420 | if (shift != rshift) |
1415 | ucontrol->value.integer.value[1] = | 1421 | ucontrol->value.integer.value[1] = |
1416 | mask - ucontrol->value.integer.value[1]; | 1422 | max - ucontrol->value.integer.value[1]; |
1417 | } | 1423 | } |
1418 | 1424 | ||
1419 | return 0; | 1425 | return 0; |
@@ -1436,25 +1442,24 @@ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, | |||
1436 | int reg = kcontrol->private_value & 0xff; | 1442 | int reg = kcontrol->private_value & 0xff; |
1437 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1443 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1438 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1444 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1439 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1445 | int max = (kcontrol->private_value >> 16) & 0xff; |
1446 | int mask = (1 << fls(max)) - 1; | ||
1440 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1447 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1441 | int err; | ||
1442 | unsigned short val, val2, val_mask; | 1448 | unsigned short val, val2, val_mask; |
1443 | 1449 | ||
1444 | val = (ucontrol->value.integer.value[0] & mask); | 1450 | val = (ucontrol->value.integer.value[0] & mask); |
1445 | if (invert) | 1451 | if (invert) |
1446 | val = mask - val; | 1452 | val = max - val; |
1447 | val_mask = mask << shift; | 1453 | val_mask = mask << shift; |
1448 | val = val << shift; | 1454 | val = val << shift; |
1449 | if (shift != rshift) { | 1455 | if (shift != rshift) { |
1450 | val2 = (ucontrol->value.integer.value[1] & mask); | 1456 | val2 = (ucontrol->value.integer.value[1] & mask); |
1451 | if (invert) | 1457 | if (invert) |
1452 | val2 = mask - val2; | 1458 | val2 = max - val2; |
1453 | val_mask |= mask << rshift; | 1459 | val_mask |= mask << rshift; |
1454 | val |= val2 << rshift; | 1460 | val |= val2 << rshift; |
1455 | } | 1461 | } |
1456 | err = snd_soc_update_bits(codec, reg, val_mask, val); | 1462 | return snd_soc_update_bits(codec, reg, val_mask, val); |
1457 | return err; | ||
1458 | } | 1463 | } |
1459 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | 1464 | EXPORT_SYMBOL_GPL(snd_soc_put_volsw); |
1460 | 1465 | ||
@@ -1471,13 +1476,16 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw); | |||
1471 | int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, | 1476 | int snd_soc_info_volsw_2r(struct snd_kcontrol *kcontrol, |
1472 | struct snd_ctl_elem_info *uinfo) | 1477 | struct snd_ctl_elem_info *uinfo) |
1473 | { | 1478 | { |
1474 | int mask = (kcontrol->private_value >> 12) & 0xff; | 1479 | int max = (kcontrol->private_value >> 12) & 0xff; |
1480 | |||
1481 | if (max == 1) | ||
1482 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
1483 | else | ||
1484 | uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1475 | 1485 | ||
1476 | uinfo->type = | ||
1477 | mask == 1 ? SNDRV_CTL_ELEM_TYPE_BOOLEAN : SNDRV_CTL_ELEM_TYPE_INTEGER; | ||
1478 | uinfo->count = 2; | 1486 | uinfo->count = 2; |
1479 | uinfo->value.integer.min = 0; | 1487 | uinfo->value.integer.min = 0; |
1480 | uinfo->value.integer.max = mask; | 1488 | uinfo->value.integer.max = max; |
1481 | return 0; | 1489 | return 0; |
1482 | } | 1490 | } |
1483 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); | 1491 | EXPORT_SYMBOL_GPL(snd_soc_info_volsw_2r); |
@@ -1498,7 +1506,8 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, | |||
1498 | int reg = kcontrol->private_value & 0xff; | 1506 | int reg = kcontrol->private_value & 0xff; |
1499 | int reg2 = (kcontrol->private_value >> 24) & 0xff; | 1507 | int reg2 = (kcontrol->private_value >> 24) & 0xff; |
1500 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1508 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1501 | int mask = (kcontrol->private_value >> 12) & 0xff; | 1509 | int max = (kcontrol->private_value >> 12) & 0xff; |
1510 | int mask = (1<<fls(max))-1; | ||
1502 | int invert = (kcontrol->private_value >> 20) & 0x01; | 1511 | int invert = (kcontrol->private_value >> 20) & 0x01; |
1503 | 1512 | ||
1504 | ucontrol->value.integer.value[0] = | 1513 | ucontrol->value.integer.value[0] = |
@@ -1507,9 +1516,9 @@ int snd_soc_get_volsw_2r(struct snd_kcontrol *kcontrol, | |||
1507 | (snd_soc_read(codec, reg2) >> shift) & mask; | 1516 | (snd_soc_read(codec, reg2) >> shift) & mask; |
1508 | if (invert) { | 1517 | if (invert) { |
1509 | ucontrol->value.integer.value[0] = | 1518 | ucontrol->value.integer.value[0] = |
1510 | mask - ucontrol->value.integer.value[0]; | 1519 | max - ucontrol->value.integer.value[0]; |
1511 | ucontrol->value.integer.value[1] = | 1520 | ucontrol->value.integer.value[1] = |
1512 | mask - ucontrol->value.integer.value[1]; | 1521 | max - ucontrol->value.integer.value[1]; |
1513 | } | 1522 | } |
1514 | 1523 | ||
1515 | return 0; | 1524 | return 0; |
@@ -1532,7 +1541,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, | |||
1532 | int reg = kcontrol->private_value & 0xff; | 1541 | int reg = kcontrol->private_value & 0xff; |
1533 | int reg2 = (kcontrol->private_value >> 24) & 0xff; | 1542 | int reg2 = (kcontrol->private_value >> 24) & 0xff; |
1534 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1543 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1535 | int mask = (kcontrol->private_value >> 12) & 0xff; | 1544 | int max = (kcontrol->private_value >> 12) & 0xff; |
1545 | int mask = (1 << fls(max)) - 1; | ||
1536 | int invert = (kcontrol->private_value >> 20) & 0x01; | 1546 | int invert = (kcontrol->private_value >> 20) & 0x01; |
1537 | int err; | 1547 | int err; |
1538 | unsigned short val, val2, val_mask; | 1548 | unsigned short val, val2, val_mask; |
@@ -1542,8 +1552,8 @@ int snd_soc_put_volsw_2r(struct snd_kcontrol *kcontrol, | |||
1542 | val2 = (ucontrol->value.integer.value[1] & mask); | 1552 | val2 = (ucontrol->value.integer.value[1] & mask); |
1543 | 1553 | ||
1544 | if (invert) { | 1554 | if (invert) { |
1545 | val = mask - val; | 1555 | val = max - val; |
1546 | val2 = mask - val2; | 1556 | val2 = max - val2; |
1547 | } | 1557 | } |
1548 | 1558 | ||
1549 | val = val << shift; | 1559 | val = val << shift; |
diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index 16ebb60ed3d4..7eb6c5c03775 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c | |||
@@ -1018,8 +1018,9 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
1018 | int reg = kcontrol->private_value & 0xff; | 1018 | int reg = kcontrol->private_value & 0xff; |
1019 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1019 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1020 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1020 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1021 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1021 | int max = (kcontrol->private_value >> 16) & 0xff; |
1022 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1022 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1023 | int mask = (1 << fls(max)) - 1; | ||
1023 | 1024 | ||
1024 | /* return the saved value if we are powered down */ | 1025 | /* return the saved value if we are powered down */ |
1025 | if (widget->id == snd_soc_dapm_pga && !widget->power) { | 1026 | if (widget->id == snd_soc_dapm_pga && !widget->power) { |
@@ -1034,10 +1035,10 @@ int snd_soc_dapm_get_volsw(struct snd_kcontrol *kcontrol, | |||
1034 | (snd_soc_read(widget->codec, reg) >> rshift) & mask; | 1035 | (snd_soc_read(widget->codec, reg) >> rshift) & mask; |
1035 | if (invert) { | 1036 | if (invert) { |
1036 | ucontrol->value.integer.value[0] = | 1037 | ucontrol->value.integer.value[0] = |
1037 | mask - ucontrol->value.integer.value[0]; | 1038 | max - ucontrol->value.integer.value[0]; |
1038 | if (shift != rshift) | 1039 | if (shift != rshift) |
1039 | ucontrol->value.integer.value[1] = | 1040 | ucontrol->value.integer.value[1] = |
1040 | mask - ucontrol->value.integer.value[1]; | 1041 | max - ucontrol->value.integer.value[1]; |
1041 | } | 1042 | } |
1042 | 1043 | ||
1043 | return 0; | 1044 | return 0; |
@@ -1060,7 +1061,8 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1060 | int reg = kcontrol->private_value & 0xff; | 1061 | int reg = kcontrol->private_value & 0xff; |
1061 | int shift = (kcontrol->private_value >> 8) & 0x0f; | 1062 | int shift = (kcontrol->private_value >> 8) & 0x0f; |
1062 | int rshift = (kcontrol->private_value >> 12) & 0x0f; | 1063 | int rshift = (kcontrol->private_value >> 12) & 0x0f; |
1063 | int mask = (kcontrol->private_value >> 16) & 0xff; | 1064 | int max = (kcontrol->private_value >> 16) & 0xff; |
1065 | int mask = (1 << fls(max)) - 1; | ||
1064 | int invert = (kcontrol->private_value >> 24) & 0x01; | 1066 | int invert = (kcontrol->private_value >> 24) & 0x01; |
1065 | unsigned short val, val2, val_mask; | 1067 | unsigned short val, val2, val_mask; |
1066 | int ret; | 1068 | int ret; |
@@ -1068,13 +1070,13 @@ int snd_soc_dapm_put_volsw(struct snd_kcontrol *kcontrol, | |||
1068 | val = (ucontrol->value.integer.value[0] & mask); | 1070 | val = (ucontrol->value.integer.value[0] & mask); |
1069 | 1071 | ||
1070 | if (invert) | 1072 | if (invert) |
1071 | val = mask - val; | 1073 | val = max - val; |
1072 | val_mask = mask << shift; | 1074 | val_mask = mask << shift; |
1073 | val = val << shift; | 1075 | val = val << shift; |
1074 | if (shift != rshift) { | 1076 | if (shift != rshift) { |
1075 | val2 = (ucontrol->value.integer.value[1] & mask); | 1077 | val2 = (ucontrol->value.integer.value[1] & mask); |
1076 | if (invert) | 1078 | if (invert) |
1077 | val2 = mask - val2; | 1079 | val2 = max - val2; |
1078 | val_mask |= mask << rshift; | 1080 | val_mask |= mask << rshift; |
1079 | val |= val2 << rshift; | 1081 | val |= val2 << rshift; |
1080 | } | 1082 | } |