// SPDX-License-Identifier: GPL-2.0 // // TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers based on I2C // // Copyright 2025 Texas Instruments, Inc. // // Author: Shenghao Ding <shenghao-ding@ti.com>
staticint tasdevice_clamp(int val, int max, unsignedint invert)
{ if (val > max)
val = max; if (invert)
val = max - val; if (val < 0)
val = 0; return val;
}
int tasdevice_amp_putvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; unsignedchar mask; int max = mc->max; int err_cnt = 0; int val, i, ret;
mask = (1 << fls(max)) - 1;
mask <<= mc->shift;
val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert); for (i = 0; i < tas_priv->ndev; i++) {
ret = tasdevice_dev_update_bits(tas_priv, i,
mc->reg, mask, (unsignedint)(val << mc->shift)); if (!ret) continue;
err_cnt++;
dev_err(tas_priv->dev, "set AMP vol error in dev %d\n", i);
}
/* All the devices set error, return 0 */ return (err_cnt == tas_priv->ndev) ? 0 : 1;
}
EXPORT_SYMBOL_GPL(tasdevice_amp_putvol);
int tasdevice_amp_getvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; unsignedchar mask = 0; int max = mc->max; int ret = 0; int val;
/* Read the primary device */
ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val); if (ret) {
dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__); goto out;
}
int tasdevice_digital_getvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; int max = mc->max; int ret, val;
/* Read the primary device as the whole */
ret = tasdevice_dev_read(tas_priv, 0, mc->reg, &val); if (ret) {
dev_err(tas_priv->dev, "%s, get digital vol error\n",
__func__); goto out;
}
val = tasdevice_clamp(val, max, invert);
ucontrol->value.integer.value[0] = val;
out: return ret;
}
EXPORT_SYMBOL_GPL(tasdevice_digital_getvol);
int tasdevice_digital_putvol(struct tasdevice_priv *tas_priv, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; int max = mc->max; int err_cnt = 0; int ret; int val, i;
val = tasdevice_clamp(ucontrol->value.integer.value[0], max, invert);
for (i = 0; i < tas_priv->ndev; i++) {
ret = tasdevice_dev_write(tas_priv, i, mc->reg,
(unsignedint)val); if (!ret) continue;
err_cnt++;
dev_err(tas_priv->dev, "set digital vol err in dev %d\n", i);
}
/* All the devices set error, return 0 */ return (err_cnt == tas_priv->ndev) ? 0 : 1;
}
EXPORT_SYMBOL_GPL(tasdevice_digital_putvol);
void tasdevice_reset(struct tasdevice_priv *tas_dev)
{ int ret, i;
if (tas_dev->reset) {
gpiod_set_value_cansleep(tas_dev->reset, 0);
usleep_range(500, 1000);
gpiod_set_value_cansleep(tas_dev->reset, 1);
} else { for (i = 0; i < tas_dev->ndev; i++) {
ret = tasdevice_dev_write(tas_dev, i,
TASDEVICE_REG_SWRESET,
TASDEVICE_REG_SWRESET_RESET); if (ret < 0)
dev_err(tas_dev->dev, "dev %d swreset fail, %d\n",
i, ret);
}
}
usleep_range(1000, 1050);
}
EXPORT_SYMBOL_GPL(tasdevice_reset);
int tascodec_init(struct tasdevice_priv *tas_priv, void *codec, struct module *module, void (*cont)(conststruct firmware *fw, void *context))
{ int ret = 0;
/* Codec Lock Hold to ensure that codec_probe and firmware parsing and *loadingdonotsimultaneouslyexecute.
*/
mutex_lock(&tas_priv->codec_lock);
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.