Lines Matching +full:range +full:- +full:double

1 // SPDX-License-Identifier: GPL-2.0+
3 // soc-ops.c -- Generic ASoC operations
11 // with code, comments and ideas from :-
27 #include <sound/soc-dpcm.h>
31 * snd_soc_info_enum_double - enumerated double mixer info callback
35 * Callback to provide information about a double enumerated
43 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in snd_soc_info_enum_double()
45 return snd_ctl_enum_info(uinfo, e->shift_l == e->shift_r ? 1 : 2, in snd_soc_info_enum_double()
46 e->items, e->texts); in snd_soc_info_enum_double()
51 * snd_soc_get_enum_double - enumerated double mixer get callback
55 * Callback to get the value of a double enumerated mixer.
63 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in snd_soc_get_enum_double()
67 reg_val = snd_soc_component_read(component, e->reg); in snd_soc_get_enum_double()
68 val = (reg_val >> e->shift_l) & e->mask; in snd_soc_get_enum_double()
70 ucontrol->value.enumerated.item[0] = item; in snd_soc_get_enum_double()
71 if (e->shift_l != e->shift_r) { in snd_soc_get_enum_double()
72 val = (reg_val >> e->shift_r) & e->mask; in snd_soc_get_enum_double()
74 ucontrol->value.enumerated.item[1] = item; in snd_soc_get_enum_double()
82 * snd_soc_put_enum_double - enumerated double mixer put callback
86 * Callback to set the value of a double enumerated mixer.
94 struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; in snd_soc_put_enum_double()
95 unsigned int *item = ucontrol->value.enumerated.item; in snd_soc_put_enum_double()
99 if (item[0] >= e->items) in snd_soc_put_enum_double()
100 return -EINVAL; in snd_soc_put_enum_double()
101 val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; in snd_soc_put_enum_double()
102 mask = e->mask << e->shift_l; in snd_soc_put_enum_double()
103 if (e->shift_l != e->shift_r) { in snd_soc_put_enum_double()
104 if (item[1] >= e->items) in snd_soc_put_enum_double()
105 return -EINVAL; in snd_soc_put_enum_double()
106 val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r; in snd_soc_put_enum_double()
107 mask |= e->mask << e->shift_r; in snd_soc_put_enum_double()
110 return snd_soc_component_update_bits(component, e->reg, mask, val); in snd_soc_put_enum_double()
115 * snd_soc_read_signed - Read a codec register and interpret as signed value
125 * the given registervalue into a signed integer if sign_bit is non-zero.
144 /* non-negative number */ in snd_soc_read_signed()
153 * The register most probably does not contain a full-sized int. in snd_soc_read_signed()
155 * representation which has to be translated into a full-sized int. in snd_soc_read_signed()
156 * This is done by filling up all bits above the sign-bit. in snd_soc_read_signed()
158 ret |= ~((int)(BIT(sign_bit) - 1)); in snd_soc_read_signed()
166 * snd_soc_info_volsw - single mixer info callback
170 * Callback to provide information about a single mixer control, or a double
179 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_info_volsw()
183 max = uinfo->value.integer.max = mc->max - mc->min; in snd_soc_info_volsw()
184 if (mc->platform_max && mc->platform_max < max) in snd_soc_info_volsw()
185 max = mc->platform_max; in snd_soc_info_volsw()
189 vol_string = strstr(kcontrol->id.name, " Volume"); in snd_soc_info_volsw()
191 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_soc_info_volsw()
193 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in snd_soc_info_volsw()
195 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_soc_info_volsw()
198 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; in snd_soc_info_volsw()
199 uinfo->value.integer.min = 0; in snd_soc_info_volsw()
200 uinfo->value.integer.max = max; in snd_soc_info_volsw()
207 * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls
211 * Callback to provide information about a single mixer control, or a double
213 * have a range that represents both positive and negative values either side
223 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_info_volsw_sx()
226 if (mc->platform_max) in snd_soc_info_volsw_sx()
227 max = mc->platform_max; in snd_soc_info_volsw_sx()
229 max = mc->max; in snd_soc_info_volsw_sx()
231 if (max == 1 && !strstr(kcontrol->id.name, " Volume")) in snd_soc_info_volsw_sx()
232 uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; in snd_soc_info_volsw_sx()
234 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_soc_info_volsw_sx()
236 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; in snd_soc_info_volsw_sx()
237 uinfo->value.integer.min = 0; in snd_soc_info_volsw_sx()
238 uinfo->value.integer.max = max; in snd_soc_info_volsw_sx()
245 * snd_soc_get_volsw - single mixer get callback
249 * Callback to get the value of a single mixer control, or a double mixer
259 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_get_volsw()
260 unsigned int reg = mc->reg; in snd_soc_get_volsw()
261 unsigned int reg2 = mc->rreg; in snd_soc_get_volsw()
262 unsigned int shift = mc->shift; in snd_soc_get_volsw()
263 unsigned int rshift = mc->rshift; in snd_soc_get_volsw()
264 int max = mc->max; in snd_soc_get_volsw()
265 int min = mc->min; in snd_soc_get_volsw()
266 int sign_bit = mc->sign_bit; in snd_soc_get_volsw()
267 unsigned int mask = (1ULL << fls(max)) - 1; in snd_soc_get_volsw()
268 unsigned int invert = mc->invert; in snd_soc_get_volsw()
273 mask = BIT(sign_bit + 1) - 1; in snd_soc_get_volsw()
279 ucontrol->value.integer.value[0] = val - min; in snd_soc_get_volsw()
281 ucontrol->value.integer.value[0] = in snd_soc_get_volsw()
282 max - ucontrol->value.integer.value[0]; in snd_soc_get_volsw()
294 ucontrol->value.integer.value[1] = val - min; in snd_soc_get_volsw()
296 ucontrol->value.integer.value[1] = in snd_soc_get_volsw()
297 max - ucontrol->value.integer.value[1]; in snd_soc_get_volsw()
305 * snd_soc_put_volsw - single mixer put callback
309 * Callback to set the value of a single mixer control, or a double mixer
319 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_put_volsw()
320 unsigned int reg = mc->reg; in snd_soc_put_volsw()
321 unsigned int reg2 = mc->rreg; in snd_soc_put_volsw()
322 unsigned int shift = mc->shift; in snd_soc_put_volsw()
323 unsigned int rshift = mc->rshift; in snd_soc_put_volsw()
324 int max = mc->max; in snd_soc_put_volsw()
325 int min = mc->min; in snd_soc_put_volsw()
326 unsigned int sign_bit = mc->sign_bit; in snd_soc_put_volsw()
327 unsigned int mask = (1 << fls(max)) - 1; in snd_soc_put_volsw()
328 unsigned int invert = mc->invert; in snd_soc_put_volsw()
335 mask = BIT(sign_bit + 1) - 1; in snd_soc_put_volsw()
337 if (ucontrol->value.integer.value[0] < 0) in snd_soc_put_volsw()
338 return -EINVAL; in snd_soc_put_volsw()
339 val = ucontrol->value.integer.value[0]; in snd_soc_put_volsw()
340 if (mc->platform_max && ((int)val + min) > mc->platform_max) in snd_soc_put_volsw()
341 return -EINVAL; in snd_soc_put_volsw()
342 if (val > max - min) in snd_soc_put_volsw()
343 return -EINVAL; in snd_soc_put_volsw()
346 val = max - val; in snd_soc_put_volsw()
350 if (ucontrol->value.integer.value[1] < 0) in snd_soc_put_volsw()
351 return -EINVAL; in snd_soc_put_volsw()
352 val2 = ucontrol->value.integer.value[1]; in snd_soc_put_volsw()
353 if (mc->platform_max && ((int)val2 + min) > mc->platform_max) in snd_soc_put_volsw()
354 return -EINVAL; in snd_soc_put_volsw()
355 if (val2 > max - min) in snd_soc_put_volsw()
356 return -EINVAL; in snd_soc_put_volsw()
359 val2 = max - val2; in snd_soc_put_volsw()
387 * snd_soc_get_volsw_sx - single mixer get callback
391 * Callback to get the value of a single mixer control, or a double mixer
401 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_get_volsw_sx()
402 unsigned int reg = mc->reg; in snd_soc_get_volsw_sx()
403 unsigned int reg2 = mc->rreg; in snd_soc_get_volsw_sx()
404 unsigned int shift = mc->shift; in snd_soc_get_volsw_sx()
405 unsigned int rshift = mc->rshift; in snd_soc_get_volsw_sx()
406 int max = mc->max; in snd_soc_get_volsw_sx()
407 int min = mc->min; in snd_soc_get_volsw_sx()
408 unsigned int mask = (1U << (fls(min + max) - 1)) - 1; in snd_soc_get_volsw_sx()
412 ucontrol->value.integer.value[0] = ((val >> shift) - min) & mask; in snd_soc_get_volsw_sx()
416 val = ((val >> rshift) - min) & mask; in snd_soc_get_volsw_sx()
417 ucontrol->value.integer.value[1] = val; in snd_soc_get_volsw_sx()
425 * snd_soc_put_volsw_sx - double mixer set callback
429 * Callback to set the value of a double mixer control that spans 2 registers.
438 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_put_volsw_sx()
440 unsigned int reg = mc->reg; in snd_soc_put_volsw_sx()
441 unsigned int reg2 = mc->rreg; in snd_soc_put_volsw_sx()
442 unsigned int shift = mc->shift; in snd_soc_put_volsw_sx()
443 unsigned int rshift = mc->rshift; in snd_soc_put_volsw_sx()
444 int max = mc->max; in snd_soc_put_volsw_sx()
445 int min = mc->min; in snd_soc_put_volsw_sx()
446 unsigned int mask = (1U << (fls(min + max) - 1)) - 1; in snd_soc_put_volsw_sx()
451 if (ucontrol->value.integer.value[0] < 0) in snd_soc_put_volsw_sx()
452 return -EINVAL; in snd_soc_put_volsw_sx()
453 val = ucontrol->value.integer.value[0]; in snd_soc_put_volsw_sx()
454 if (mc->platform_max && val > mc->platform_max) in snd_soc_put_volsw_sx()
455 return -EINVAL; in snd_soc_put_volsw_sx()
457 return -EINVAL; in snd_soc_put_volsw_sx()
468 unsigned int val2 = ucontrol->value.integer.value[1]; in snd_soc_put_volsw_sx()
470 if (mc->platform_max && val2 > mc->platform_max) in snd_soc_put_volsw_sx()
471 return -EINVAL; in snd_soc_put_volsw_sx()
473 return -EINVAL; in snd_soc_put_volsw_sx()
492 * snd_soc_info_volsw_range - single mixer info callback with range.
496 * Callback to provide information, within a range, about a single
505 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_info_volsw_range()
507 int min = mc->min; in snd_soc_info_volsw_range()
509 if (!mc->platform_max) in snd_soc_info_volsw_range()
510 mc->platform_max = mc->max; in snd_soc_info_volsw_range()
511 platform_max = mc->platform_max; in snd_soc_info_volsw_range()
513 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_soc_info_volsw_range()
514 uinfo->count = snd_soc_volsw_is_stereo(mc) ? 2 : 1; in snd_soc_info_volsw_range()
515 uinfo->value.integer.min = 0; in snd_soc_info_volsw_range()
516 uinfo->value.integer.max = platform_max - min; in snd_soc_info_volsw_range()
523 * snd_soc_put_volsw_range - single mixer put value callback with range.
527 * Callback to set the value, within a range, for a single mixer control.
535 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_put_volsw_range()
537 unsigned int reg = mc->reg; in snd_soc_put_volsw_range()
538 unsigned int rreg = mc->rreg; in snd_soc_put_volsw_range()
539 unsigned int shift = mc->shift; in snd_soc_put_volsw_range()
540 int min = mc->min; in snd_soc_put_volsw_range()
541 int max = mc->max; in snd_soc_put_volsw_range()
542 unsigned int mask = (1 << fls(max)) - 1; in snd_soc_put_volsw_range()
543 unsigned int invert = mc->invert; in snd_soc_put_volsw_range()
547 tmp = ucontrol->value.integer.value[0]; in snd_soc_put_volsw_range()
549 return -EINVAL; in snd_soc_put_volsw_range()
550 if (mc->platform_max && tmp > mc->platform_max) in snd_soc_put_volsw_range()
551 return -EINVAL; in snd_soc_put_volsw_range()
552 if (tmp > mc->max - mc->min) in snd_soc_put_volsw_range()
553 return -EINVAL; in snd_soc_put_volsw_range()
556 val = (max - ucontrol->value.integer.value[0]) & mask; in snd_soc_put_volsw_range()
558 val = ((ucontrol->value.integer.value[0] + min) & mask); in snd_soc_put_volsw_range()
568 tmp = ucontrol->value.integer.value[1]; in snd_soc_put_volsw_range()
570 return -EINVAL; in snd_soc_put_volsw_range()
571 if (mc->platform_max && tmp > mc->platform_max) in snd_soc_put_volsw_range()
572 return -EINVAL; in snd_soc_put_volsw_range()
573 if (tmp > mc->max - mc->min) in snd_soc_put_volsw_range()
574 return -EINVAL; in snd_soc_put_volsw_range()
577 val = (max - ucontrol->value.integer.value[1]) & mask; in snd_soc_put_volsw_range()
579 val = ((ucontrol->value.integer.value[1] + min) & mask); in snd_soc_put_volsw_range()
596 * snd_soc_get_volsw_range - single mixer get callback with range
600 * Callback to get the value, within a range, of a single mixer control.
609 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_get_volsw_range()
610 unsigned int reg = mc->reg; in snd_soc_get_volsw_range()
611 unsigned int rreg = mc->rreg; in snd_soc_get_volsw_range()
612 unsigned int shift = mc->shift; in snd_soc_get_volsw_range()
613 int min = mc->min; in snd_soc_get_volsw_range()
614 int max = mc->max; in snd_soc_get_volsw_range()
615 unsigned int mask = (1 << fls(max)) - 1; in snd_soc_get_volsw_range()
616 unsigned int invert = mc->invert; in snd_soc_get_volsw_range()
620 ucontrol->value.integer.value[0] = (val >> shift) & mask; in snd_soc_get_volsw_range()
622 ucontrol->value.integer.value[0] = in snd_soc_get_volsw_range()
623 max - ucontrol->value.integer.value[0]; in snd_soc_get_volsw_range()
625 ucontrol->value.integer.value[0] = in snd_soc_get_volsw_range()
626 ucontrol->value.integer.value[0] - min; in snd_soc_get_volsw_range()
630 ucontrol->value.integer.value[1] = (val >> shift) & mask; in snd_soc_get_volsw_range()
632 ucontrol->value.integer.value[1] = in snd_soc_get_volsw_range()
633 max - ucontrol->value.integer.value[1]; in snd_soc_get_volsw_range()
635 ucontrol->value.integer.value[1] = in snd_soc_get_volsw_range()
636 ucontrol->value.integer.value[1] - min; in snd_soc_get_volsw_range()
644 * snd_soc_limit_volume - Set new limit to an existing volume control.
656 int ret = -EINVAL; in snd_soc_limit_volume()
660 return -EINVAL; in snd_soc_limit_volume()
664 struct soc_mixer_control *mc = (struct soc_mixer_control *)kctl->private_value; in snd_soc_limit_volume()
665 if (max <= mc->max - mc->min) { in snd_soc_limit_volume()
666 mc->platform_max = max; in snd_soc_limit_volume()
678 struct soc_bytes *params = (void *)kcontrol->private_value; in snd_soc_bytes_info()
680 uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; in snd_soc_bytes_info()
681 uinfo->count = params->num_regs * component->val_bytes; in snd_soc_bytes_info()
691 struct soc_bytes *params = (void *)kcontrol->private_value; in snd_soc_bytes_get()
694 if (component->regmap) in snd_soc_bytes_get()
695 ret = regmap_raw_read(component->regmap, params->base, in snd_soc_bytes_get()
696 ucontrol->value.bytes.data, in snd_soc_bytes_get()
697 params->num_regs * component->val_bytes); in snd_soc_bytes_get()
699 ret = -EINVAL; in snd_soc_bytes_get()
702 if (ret == 0 && params->mask) { in snd_soc_bytes_get()
703 switch (component->val_bytes) { in snd_soc_bytes_get()
705 ucontrol->value.bytes.data[0] &= ~params->mask; in snd_soc_bytes_get()
708 ((u16 *)(&ucontrol->value.bytes.data))[0] in snd_soc_bytes_get()
709 &= cpu_to_be16(~params->mask); in snd_soc_bytes_get()
712 ((u32 *)(&ucontrol->value.bytes.data))[0] in snd_soc_bytes_get()
713 &= cpu_to_be32(~params->mask); in snd_soc_bytes_get()
716 return -EINVAL; in snd_soc_bytes_get()
728 struct soc_bytes *params = (void *)kcontrol->private_value; in snd_soc_bytes_put()
732 if (!component->regmap || !params->num_regs) in snd_soc_bytes_put()
733 return -EINVAL; in snd_soc_bytes_put()
735 len = params->num_regs * component->val_bytes; in snd_soc_bytes_put()
737 void *data __free(kfree) = kmemdup(ucontrol->value.bytes.data, len, in snd_soc_bytes_put()
740 return -ENOMEM; in snd_soc_bytes_put()
747 if (params->mask) { in snd_soc_bytes_put()
748 ret = regmap_read(component->regmap, params->base, &val); in snd_soc_bytes_put()
752 val &= params->mask; in snd_soc_bytes_put()
754 switch (component->val_bytes) { in snd_soc_bytes_put()
756 ((u8 *)data)[0] &= ~params->mask; in snd_soc_bytes_put()
760 mask = ~params->mask; in snd_soc_bytes_put()
761 ret = regmap_parse_val(component->regmap, in snd_soc_bytes_put()
768 ret = regmap_parse_val(component->regmap, in snd_soc_bytes_put()
776 mask = ~params->mask; in snd_soc_bytes_put()
777 ret = regmap_parse_val(component->regmap, in snd_soc_bytes_put()
784 ret = regmap_parse_val(component->regmap, in snd_soc_bytes_put()
792 return -EINVAL; in snd_soc_bytes_put()
796 return regmap_raw_write(component->regmap, params->base, data, len); in snd_soc_bytes_put()
803 struct soc_bytes_ext *params = (void *)kcontrol->private_value; in snd_soc_bytes_info_ext()
805 ucontrol->type = SNDRV_CTL_ELEM_TYPE_BYTES; in snd_soc_bytes_info_ext()
806 ucontrol->count = params->max; in snd_soc_bytes_info_ext()
815 struct soc_bytes_ext *params = (void *)kcontrol->private_value; in snd_soc_bytes_tlv_callback()
816 unsigned int count = size < params->max ? size : params->max; in snd_soc_bytes_tlv_callback()
817 int ret = -ENXIO; in snd_soc_bytes_tlv_callback()
821 if (params->get) in snd_soc_bytes_tlv_callback()
822 ret = params->get(kcontrol, tlv, count); in snd_soc_bytes_tlv_callback()
825 if (params->put) in snd_soc_bytes_tlv_callback()
826 ret = params->put(kcontrol, tlv, count); in snd_soc_bytes_tlv_callback()
834 * snd_soc_info_xr_sx - signed multi register info callback
848 (struct soc_mreg_control *)kcontrol->private_value; in snd_soc_info_xr_sx()
849 uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; in snd_soc_info_xr_sx()
850 uinfo->count = 1; in snd_soc_info_xr_sx()
851 uinfo->value.integer.min = mc->min; in snd_soc_info_xr_sx()
852 uinfo->value.integer.max = mc->max; in snd_soc_info_xr_sx()
859 * snd_soc_get_xr_sx - signed multi register get callback
876 (struct soc_mreg_control *)kcontrol->private_value; in snd_soc_get_xr_sx()
877 unsigned int regbase = mc->regbase; in snd_soc_get_xr_sx()
878 unsigned int regcount = mc->regcount; in snd_soc_get_xr_sx()
879 unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; in snd_soc_get_xr_sx()
880 unsigned int regwmask = (1UL<<regwshift)-1; in snd_soc_get_xr_sx()
881 unsigned int invert = mc->invert; in snd_soc_get_xr_sx()
882 unsigned long mask = (1UL<<mc->nbits)-1; in snd_soc_get_xr_sx()
883 long min = mc->min; in snd_soc_get_xr_sx()
884 long max = mc->max; in snd_soc_get_xr_sx()
890 val |= (regval & regwmask) << (regwshift*(regcount-i-1)); in snd_soc_get_xr_sx()
896 val = max - val; in snd_soc_get_xr_sx()
897 ucontrol->value.integer.value[0] = val; in snd_soc_get_xr_sx()
904 * snd_soc_put_xr_sx - signed multi register get callback
921 (struct soc_mreg_control *)kcontrol->private_value; in snd_soc_put_xr_sx()
922 unsigned int regbase = mc->regbase; in snd_soc_put_xr_sx()
923 unsigned int regcount = mc->regcount; in snd_soc_put_xr_sx()
924 unsigned int regwshift = component->val_bytes * BITS_PER_BYTE; in snd_soc_put_xr_sx()
925 unsigned int regwmask = (1UL<<regwshift)-1; in snd_soc_put_xr_sx()
926 unsigned int invert = mc->invert; in snd_soc_put_xr_sx()
927 unsigned long mask = (1UL<<mc->nbits)-1; in snd_soc_put_xr_sx()
928 long max = mc->max; in snd_soc_put_xr_sx()
929 long val = ucontrol->value.integer.value[0]; in snd_soc_put_xr_sx()
933 if (val < mc->min || val > mc->max) in snd_soc_put_xr_sx()
934 return -EINVAL; in snd_soc_put_xr_sx()
936 val = max - val; in snd_soc_put_xr_sx()
939 unsigned int regval = (val >> (regwshift*(regcount-i-1))) & regwmask; in snd_soc_put_xr_sx()
940 unsigned int regmask = (mask >> (regwshift*(regcount-i-1))) & regwmask; in snd_soc_put_xr_sx()
954 * snd_soc_get_strobe - strobe get callback
967 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_get_strobe()
968 unsigned int reg = mc->reg; in snd_soc_get_strobe()
969 unsigned int shift = mc->shift; in snd_soc_get_strobe()
971 unsigned int invert = mc->invert != 0; in snd_soc_get_strobe()
979 ucontrol->value.enumerated.item[0] = val ^ invert; in snd_soc_get_strobe()
986 * snd_soc_put_strobe - strobe put callback
1000 (struct soc_mixer_control *)kcontrol->private_value; in snd_soc_put_strobe()
1001 unsigned int reg = mc->reg; in snd_soc_put_strobe()
1002 unsigned int shift = mc->shift; in snd_soc_put_strobe()
1004 unsigned int invert = mc->invert != 0; in snd_soc_put_strobe()
1005 unsigned int strobe = ucontrol->value.enumerated.item[0] != 0; in snd_soc_put_strobe()