/** * snd_soc_info_enum_double - enumerated double mixer info callback * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a double enumerated * mixer control. * * Returns 0 for success.
*/ int snd_soc_info_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ struct soc_enum *e = (struct soc_enum *)kcontrol->private_value;
/** * snd_soc_get_enum_double - enumerated double mixer get callback * @kcontrol: mixer control * @ucontrol: control element information * * Callback to get the value of a double enumerated mixer. * * Returns 0 for success.
*/ int snd_soc_get_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsignedint val, item; unsignedint reg_val;
/** * snd_soc_put_enum_double - enumerated double mixer put callback * @kcontrol: mixer control * @ucontrol: control element information * * Callback to set the value of a double enumerated mixer. * * Returns 0 for success.
*/ int snd_soc_put_enum_double(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; unsignedint *item = ucontrol->value.enumerated.item; unsignedint val; unsignedint mask;
if (item[0] >= e->items) return -EINVAL;
val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l;
mask = e->mask << e->shift_l; if (e->shift_l != e->shift_r) { if (item[1] >= e->items) return -EINVAL;
val |= snd_soc_enum_item_to_val(e, item[1]) << e->shift_r;
mask |= e->mask << e->shift_r;
}
staticint soc_mixer_sx_mask(struct soc_mixer_control *mc)
{ // min + max will take us 1-bit over the size of the mask return GENMASK(fls(mc->min + mc->max) - 2, 0);
}
if (snd_soc_volsw_is_stereo(mc)) { if (mc->reg == mc->rreg) {
val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->rshift, max);
} else {
reg_val = snd_soc_component_read(component, mc->rreg);
val = soc_mixer_reg_to_ctl(mc, reg_val, mask, mc->shift, max);
}
ucontrol->value.integer.value[1] = val;
}
return 0;
}
/** * snd_soc_info_volsw - single mixer info callback with range. * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information, with a range, about a single mixer control, * or a double mixer control that spans 2 registers. * * Returns 0 for success.
*/ int snd_soc_info_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
/** * snd_soc_info_volsw_sx - Mixer info callback for SX TLV controls * @kcontrol: mixer control * @uinfo: control element information * * Callback to provide information about a single mixer control, or a double * mixer control that spans 2 registers of the SX TLV type. SX TLV controls * have a range that represents both positive and negative values either side * of zero but without a sign bit. min is the minimum register value, max is * the number of steps. * * Returns 0 for success.
*/ int snd_soc_info_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
/** * snd_soc_get_volsw - single mixer get callback with range * @kcontrol: mixer control * @ucontrol: control element information * * Callback to get the value, within a range, of a single mixer control, or a * double mixer control that spans 2 registers. * * Returns 0 for success.
*/ int snd_soc_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; unsignedint mask = soc_mixer_mask(mc);
/** * snd_soc_put_volsw - single mixer put callback with range * @kcontrol: mixer control * @ucontrol: control element information * * Callback to set the value , within a range, of a single mixer control, or * a double mixer control that spans 2 registers. * * Returns 0 for success.
*/ int snd_soc_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; unsignedint mask = soc_mixer_mask(mc);
/** * snd_soc_get_volsw_sx - single mixer get callback * @kcontrol: mixer control * @ucontrol: control element information * * Callback to get the value of a single mixer control, or a double mixer * control that spans 2 registers. * * Returns 0 for success.
*/ int snd_soc_get_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; unsignedint mask = soc_mixer_sx_mask(mc);
/** * snd_soc_put_volsw_sx - double mixer set callback * @kcontrol: mixer control * @ucontrol: control element information * * Callback to set the value of a double mixer control that spans 2 registers. * * Returns 0 for success.
*/ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value; unsignedint mask = soc_mixer_sx_mask(mc);
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL); if (!uctl) return -ENOMEM;
ret = kctl->get(kctl, uctl); if (ret < 0) goto out;
if (uctl->value.integer.value[0] > mc->platform_max)
uctl->value.integer.value[0] = mc->platform_max;
if (snd_soc_volsw_is_stereo(mc) &&
uctl->value.integer.value[1] > mc->platform_max)
uctl->value.integer.value[1] = mc->platform_max;
ret = kctl->put(kctl, uctl);
out:
kfree(uctl); return ret;
}
/** * snd_soc_limit_volume - Set new limit to an existing volume control. * * @card: where to look for the control * @name: Name of the control * @max: new maximum limit * * Return 0 for success, else error.
*/ int snd_soc_limit_volume(struct snd_soc_card *card, constchar *name, int max)
{ struct snd_kcontrol *kctl; int ret = -EINVAL;
/* Sanity check for name and max */ if (unlikely(!name || max <= 0)) return -EINVAL;
if (component->regmap)
ret = regmap_raw_read(component->regmap, params->base,
ucontrol->value.bytes.data,
params->num_regs * component->val_bytes); else
ret = -EINVAL;
/* Hide any masked bytes to ensure consistent data reporting */ if (ret == 0 && params->mask) { switch (component->val_bytes) { case 1:
ucontrol->value.bytes.data[0] &= ~params->mask; break; case 2:
((u16 *)(&ucontrol->value.bytes.data))[0]
&= cpu_to_be16(~params->mask); break; case 4:
((u32 *)(&ucontrol->value.bytes.data))[0]
&= cpu_to_be32(~params->mask); break; default: return -EINVAL;
}
}
/* * If we've got a mask then we need to preserve the register * bits. We shouldn't modify the incoming data so take a * copy.
*/ if (params->mask) {
ret = regmap_read(component->regmap, params->base, &val); if (ret != 0) return ret;
val &= params->mask;
switch (component->val_bytes) { case 1:
((u8 *)data)[0] &= ~params->mask;
((u8 *)data)[0] |= val; break; case 2:
mask = ~params->mask;
ret = regmap_parse_val(component->regmap, &mask, &mask); if (ret != 0) return ret;
((u16 *)data)[0] &= mask;
ret = regmap_parse_val(component->regmap, &val, &val); if (ret != 0) return ret;
((u16 *)data)[0] |= val; break; case 4:
mask = ~params->mask;
ret = regmap_parse_val(component->regmap, &mask, &mask); if (ret != 0) return ret;
((u32 *)data)[0] &= mask;
ret = regmap_parse_val(component->regmap, &val, &val); if (ret != 0) return ret;
int snd_soc_bytes_tlv_callback(struct snd_kcontrol *kcontrol, int op_flag, unsignedint size, unsignedint __user *tlv)
{ struct soc_bytes_ext *params = (void *)kcontrol->private_value; unsignedint count = size < params->max ? size : params->max; int ret = -ENXIO;
switch (op_flag) { case SNDRV_CTL_TLV_OP_READ: if (params->get)
ret = params->get(kcontrol, tlv, count); break; case SNDRV_CTL_TLV_OP_WRITE: if (params->put)
ret = params->put(kcontrol, tlv, count); break;
}
/** * snd_soc_info_xr_sx - signed multi register info callback * @kcontrol: mreg control * @uinfo: control element information * * Callback to provide information of a control that can span multiple * codec registers which together forms a single signed value. Note * that unlike the non-xr variant of sx controls these may or may not * include the sign bit, depending on nbits, and there is no shift. * * Returns 0 for success.
*/ int snd_soc_info_xr_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_info *uinfo)
{ struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value;
/** * snd_soc_get_xr_sx - signed multi register get callback * @kcontrol: mreg control * @ucontrol: control element information * * Callback to get the value of a control that can span multiple codec * registers which together forms a single signed value. The control * supports specifying total no of bits used to allow for bitfields * across the multiple codec registers. Note that unlike the non-xr * variant of sx controls these may or may not include the sign bit, * depending on nbits, and there is no shift. * * Returns 0 for success.
*/ int snd_soc_get_xr_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value; unsignedint regbase = mc->regbase; unsignedint regcount = mc->regcount; unsignedint regwshift = component->val_bytes * BITS_PER_BYTE; unsignedint regwmask = GENMASK(regwshift - 1, 0); unsignedlong mask = GENMASK(mc->nbits - 1, 0); long val = 0; unsignedint i;
for (i = 0; i < regcount; i++) { unsignedint regval = snd_soc_component_read(component, regbase + i);
val |= (regval & regwmask) << (regwshift * (regcount - i - 1));
}
val &= mask; if (mc->min < 0 && val > mc->max)
val |= ~mask; if (mc->invert)
val = mc->max - val;
ucontrol->value.integer.value[0] = val;
return 0;
}
EXPORT_SYMBOL_GPL(snd_soc_get_xr_sx);
/** * snd_soc_put_xr_sx - signed multi register get callback * @kcontrol: mreg control * @ucontrol: control element information * * Callback to set the value of a control that can span multiple codec * registers which together forms a single signed value. The control * supports specifying total no of bits used to allow for bitfields * across the multiple codec registers. Note that unlike the non-xr * variant of sx controls these may or may not include the sign bit, * depending on nbits, and there is no shift. * * Returns 0 for success.
*/ int snd_soc_put_xr_sx(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); struct soc_mreg_control *mc =
(struct soc_mreg_control *)kcontrol->private_value; unsignedint regbase = mc->regbase; unsignedint regcount = mc->regcount; unsignedint regwshift = component->val_bytes * BITS_PER_BYTE; unsignedint regwmask = GENMASK(regwshift - 1, 0); unsignedlong mask = GENMASK(mc->nbits - 1, 0); long val = ucontrol->value.integer.value[0]; int ret = 0; unsignedint i;
if (val < mc->min || val > mc->max) return -EINVAL; if (mc->invert)
val = mc->max - val;
val &= mask; for (i = 0; i < regcount; i++) { unsignedint regval = (val >> (regwshift * (regcount - i - 1))) &
regwmask; unsignedint regmask = (mask >> (regwshift * (regcount - i - 1))) &
regwmask; int err = snd_soc_component_update_bits(component, regbase + i,
regmask, regval);
if (err < 0) return err; if (err > 0)
ret = err;
}
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.2Bemerkung:
(vorverarbeitet)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.