staticint audio_iio_aux_get_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value; int max = chan->max; int min = chan->min; bool invert_range = chan->is_invert_range; int ret; int val;
ret = iio_read_channel_raw(chan->iio_chan, &val); if (ret < 0) return ret;
ucontrol->value.integer.value[0] = val - min; if (invert_range)
ucontrol->value.integer.value[0] = max - ucontrol->value.integer.value[0];
return 0;
}
staticint audio_iio_aux_put_volsw(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct audio_iio_aux_chan *chan = (struct audio_iio_aux_chan *)kcontrol->private_value; int max = chan->max; int min = chan->min; bool invert_range = chan->is_invert_range; int val; int ret; int tmp;
val = ucontrol->value.integer.value[0]; if (val < 0) return -EINVAL; if (val > max - min) return -EINVAL;
val = val + min; if (invert_range)
val = max - val;
ret = iio_read_channel_raw(chan->iio_chan, &tmp); if (ret < 0) return ret;
if (tmp == val) return 0;
ret = iio_write_channel_raw(chan->iio_chan, val); if (ret) return ret;
/* * These data could be on stack but they are pretty big. * As ASoC internally copy them and protect them against concurrent accesses * (snd_soc_bind_card() protects using client_mutex), keep them in the global * data area.
*/ staticstruct snd_soc_dapm_widget widgets[3]; staticstruct snd_soc_dapm_route routes[2];
/* Be sure sizes are correct (need 3 widgets and 2 routes) */
static_assert(ARRAY_SIZE(widgets) >= 3, "3 widgets are needed");
static_assert(ARRAY_SIZE(routes) >= 2, "2 routes are needed");
staticint audio_iio_aux_component_probe(struct snd_soc_component *component)
{ struct audio_iio_aux *iio_aux = snd_soc_component_get_drvdata(component); struct audio_iio_aux_chan *chan; int ret; int i;
for (i = 0; i < iio_aux->num_chans; i++) {
chan = iio_aux->chans + i;
ret = iio_read_max_channel_raw(chan->iio_chan, &chan->max); if (ret) return dev_err_probe(component->dev, ret, "chan[%d] %s: Cannot get max raw value\n",
i, chan->name);
ret = iio_read_min_channel_raw(chan->iio_chan, &chan->min); if (ret) return dev_err_probe(component->dev, ret, "chan[%d] %s: Cannot get min raw value\n",
i, chan->name);
if (chan->min > chan->max) { /* * This should never happen but to avoid any check * later, just swap values here to ensure that the * minimum value is lower than the maximum value.
*/
dev_dbg(component->dev, "chan[%d] %s: Swap min and max\n",
i, chan->name);
swap(chan->min, chan->max);
}
/* Set initial value */
ret = iio_write_channel_raw(chan->iio_chan,
chan->is_invert_range ? chan->max : chan->min); if (ret) return dev_err_probe(component->dev, ret, "chan[%d] %s: Cannot set initial value\n",
i, chan->name);
ret = audio_iio_aux_add_controls(component, chan); if (ret) return ret;
ret = audio_iio_aux_add_dapms(component, chan); if (ret) return ret;
ret = device_property_read_string_array(dev, "io-channel-names",
names, iio_aux->num_chans); if (ret < 0) return dev_err_probe(dev, ret, "failed to read io-channel-names\n");
/* * snd-control-invert-range is optional and can contain fewer items * than the number of channels. Unset values default to 0.
*/
count = device_property_count_u32(dev, "snd-control-invert-range"); if (count > 0) {
count = min_t(unsignedint, count, iio_aux->num_chans);
ret = device_property_read_u32_array(dev, "snd-control-invert-range",
invert_ranges, count); if (ret < 0) return dev_err_probe(dev, ret, "failed to read snd-control-invert-range\n");
}
for (i = 0; i < iio_aux->num_chans; i++) {
iio_aux_chan = iio_aux->chans + i;
iio_aux_chan->name = names[i];
iio_aux_chan->is_invert_range = invert_ranges[i];
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.