/* * In our TAS2781 SPI mode, if read from other book (not book 0), * or read from page number larger than 1 in book 0, one more byte * read is needed, and first byte is a dummy byte, need to be ignored.
*/ if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) { unsignedchar data[2];
ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
data, sizeof(data));
*val = data[1];
} else {
ret = tasdevice_dev_read(tas_priv, chn, reg, val);
} if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
/* * In our TAS2781 SPI mode, if read from other book (not book 0), * or read from page number larger than 1 in book 0, one more byte * read is needed, and first byte is a dummy byte, need to be ignored.
*/ if ((TASDEVICE_BOOK_ID(reg) > 0) || (TASDEVICE_PAGE_ID(reg) > 1)) { unsignedchar buf[TASDEVICE_WIN_LEN + 1];
ret = tasdevice_dev_bulk_read(tas_priv, chn, reg,
buf, len + 1);
memcpy(data, buf + 1, len);
} else {
ret = tasdevice_dev_bulk_read(tas_priv, chn, reg, data, len);
} if (ret < 0)
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
/* * In our TAS2781 SPI mode, read/write was masked in last bit of * address, it cause regmap_update_bits() not work as expected.
*/
ret = tasdevice_dev_read(tas_priv, chn, reg, &val); if (ret < 0) {
dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); return ret;
}
/* * Codec Lock Hold to ensure that codec_probe and firmware parsing and * loading do not simultaneously execute.
*/
guard(mutex)(&tas_priv->codec_lock);
staticint tasdevice_spi_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 val, ret;
mask = rounddown_pow_of_two(max);
mask <<= mc->shift;
val = clamp(invert ? max - ucontrol->value.integer.value[0] :
ucontrol->value.integer.value[0], 0, max);
ret = tasdevice_spi_dev_update_bits(tas_priv, tas_priv->index,
mc->reg, mask, (unsignedint)(val << mc->shift)); if (ret)
dev_err(tas_priv->dev, "set AMP vol error in dev %d\n",
tas_priv->index);
return ret;
}
staticint tasdevice_spi_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, val;
ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index, mc->reg, &val); if (ret) {
dev_err(tas_priv->dev, "%s, get AMP vol error\n", __func__); return ret;
}
mask = rounddown_pow_of_two(max);
mask <<= mc->shift;
val = (val & mask) >> mc->shift;
val = clamp(invert ? max - val : val, 0, max);
ucontrol->value.integer.value[0] = val;
return ret;
}
staticint tasdevice_spi_digital_putvol(struct tasdevice_priv *p, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; int max = mc->max; int val, ret;
val = clamp(invert ? max - ucontrol->value.integer.value[0] :
ucontrol->value.integer.value[0], 0, max);
ret = tasdevice_dev_write(p, p->index, mc->reg, (unsignedint)val); if (ret)
dev_err(p->dev, "set digital vol err in dev %d\n", p->index);
return ret;
}
staticint tasdevice_spi_digital_getvol(struct tasdevice_priv *p, struct snd_ctl_elem_value *ucontrol, struct soc_mixer_control *mc)
{ unsignedint invert = mc->invert; int max = mc->max; int ret, val;
ret = tasdevice_spi_dev_read(p, p->index, mc->reg, &val); if (ret) {
dev_err(p->dev, "%s, get digital vol err\n", __func__); return ret;
}
val = clamp(invert ? max - val : val, 0, max);
ucontrol->value.integer.value[0] = val;
property = "ti,dev-index";
ret = device_property_count_u32(physdev, property); if (ret <= 0 || ret > ARRAY_SIZE(values)) {
ret = -EINVAL; goto err;
}
p->ndev = nval = ret;
ret = device_property_read_u32_array(physdev, property, values, nval); if (ret) goto err;
p->index = U8_MAX; for (i = 0; i < nval; i++) { if (values[i] == id) {
p->index = i; break;
}
} if (p->index == U8_MAX) {
dev_dbg(p->dev, "No index found in %s\n", property);
ret = -ENODEV; goto err;
}
if (p->index == 0) { /* All of amps share same RESET pin. */
p->reset = devm_gpiod_get_index_optional(physdev, "reset",
p->index, GPIOD_OUT_LOW); if (IS_ERR(p->reset)) {
ret = PTR_ERR(p->reset);
dev_err_probe(p->dev, ret, "Failed on reset GPIO\n"); goto err;
}
}
put_device(physdev);
if (action == HDA_GEN_PCM_ACT_OPEN) {
pm_runtime_get_sync(dev);
guard(mutex)(&tas_priv->codec_lock); if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
tasdevice_tuning_switch(tas_hda->priv, 0);
} elseif (action == HDA_GEN_PCM_ACT_CLOSE) {
guard(mutex)(&tas_priv->codec_lock); if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK)
tasdevice_tuning_switch(tas_priv, 1);
pm_runtime_put_autosuspend(dev);
}
}
/* * tas2781_digital_getvol - get the volum control * @kcontrol: control pointer * @ucontrol: User data * * Customer Kcontrol for tas2781 is primarily for regmap booking, paging * depends on internal regmap mechanism. * tas2781 contains book and page two-level register map, especially * book switching will set the register BXXP00R7F, after switching to the * correct book, then leverage the mechanism for paging to access the * register. * * Return 0 if succeeded.
*/ staticint tas2781_digital_getvol(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol)
{ struct tasdevice_priv *tas_priv = snd_kcontrol_chip(kcontrol); struct soc_mixer_control *mc =
(struct soc_mixer_control *)kcontrol->private_value;
ret = tas2781_hda_spi_dsp_ctls(tas_hda); if (ret) goto out; /* Perform AMP reset before firmware download. */
tas2781_spi_reset(tas_priv);
tas_priv->rcabin.profile_cfg_id = 0;
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
ret = tasdevice_spi_dev_read(tas_priv, tas_priv->index,
TAS2781_REG_CLK_CONFIG, &val); if (ret < 0) goto out;
if (val == TAS2781_REG_CLK_CONFIG_RESET) {
ret = tasdevice_prmg_load(tas_priv, 0); if (ret < 0) {
dev_err(tas_priv->dev, "FW download failed = %d\n",
ret); goto out;
}
tas_priv->fw_state = TASDEVICE_DSP_FW_ALL_OK;
} if (tas_priv->fmw->nr_programs > 0)
tas_priv->tasdevice[tas_priv->index].cur_prog = 0; if (tas_priv->fmw->nr_configurations > 0)
tas_priv->tasdevice[tas_priv->index].cur_conf = 0;
/* * If calibrated data occurs error, dsp will still works with default * calibrated data inside algo.
*/
tas2781_save_calibration(tas_hda);
out:
release_firmware(fmw);
pm_runtime_put_autosuspend(tas_hda->priv->dev);
}
ret = pm_runtime_force_suspend(dev); if (ret) return ret;
/* Shutdown chip before system suspend */ if (tas_priv->fw_state == TASDEVICE_DSP_FW_ALL_OK
&& tas_priv->playback_started)
tasdevice_tuning_switch(tas_priv, 1);
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.