// SPDX-License-Identifier: GPL-2.0 // // TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers // // Copyright 2023 - 2025 Texas Instruments, Inc. // // Author: Shenghao Ding #include #include #include #include #include #include #include #include #include #include #include #include int tasdevice_dev_read(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int *val) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tas_priv->change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_read(map, TASDEVICE_PGRG(reg), val); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_read); int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned char *data, unsigned int len) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tas_priv->change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_bulk_read(map, TASDEVICE_PGRG(reg), data, len); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read); int tasdevice_dev_write(struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned int value) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tas_priv->change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_write(map, TASDEVICE_PGRG(reg), value); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_write); int tasdevice_dev_bulk_write( struct tasdevice_priv *tas_priv, unsigned short chn, unsigned int reg, unsigned char *data, unsigned int len) { int ret = 0; if (chn < tas_priv->ndev) { struct regmap *map = tas_priv->regmap; ret = tas_priv->change_chn_book(tas_priv, chn, TASDEVICE_BOOK_ID(reg)); if (ret < 0) goto out; ret = regmap_bulk_write(map, TASDEVICE_PGRG(reg), data, len); if (ret < 0) dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret); } else { ret = -EINVAL; dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__, chn); } out: return ret; } EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write); static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog) { struct tasdevice_data *tas_dt; struct tasdev_blk *blk; unsigned int i; if (!prog) return; tas_dt = &(prog->dev_data); if (!tas_dt->dev_blks) return; for (i = 0; i < tas_dt->nr_blk; i++) { blk = &(tas_dt->dev_blks[i]); kfree(blk->data); } kfree(tas_dt->dev_blks); } static void tasdev_dsp_prog_remove(struct tasdevice_prog *prog, unsigned short nr) { int i; for (i = 0; i < nr; i++) tasdev_dsp_prog_blk_remove(&prog[i]); kfree(prog); } static void tasdev_dsp_cfg_blk_remove(struct tasdevice_config *cfg) { struct tasdevice_data *tas_dt; struct tasdev_blk *blk; unsigned int i; if (cfg) { tas_dt = &(cfg->dev_data); if (!tas_dt->dev_blks) return; for (i = 0; i < tas_dt->nr_blk; i++) { blk = &(tas_dt->dev_blks[i]); kfree(blk->data); } kfree(tas_dt->dev_blks); } } static void tasdev_dsp_cfg_remove(struct tasdevice_config *config, unsigned short nr) { int i; for (i = 0; i < nr; i++) tasdev_dsp_cfg_blk_remove(&config[i]); kfree(config); } void tasdevice_dsp_remove(void *context) { struct tasdevice_priv *tas_dev = (struct tasdevice_priv *) context; struct tasdevice_fw *tas_fmw = tas_dev->fmw; if (!tas_dev->fmw) return; if (tas_fmw->programs) tasdev_dsp_prog_remove(tas_fmw->programs, tas_fmw->nr_programs); if (tas_fmw->configs) tasdev_dsp_cfg_remove(tas_fmw->configs, tas_fmw->nr_configurations); kfree(tas_fmw); tas_dev->fmw = NULL; } EXPORT_SYMBOL_GPL(tasdevice_dsp_remove); void tasdevice_remove(struct tasdevice_priv *tas_priv) { mutex_destroy(&tas_priv->codec_lock); } EXPORT_SYMBOL_GPL(tasdevice_remove); MODULE_DESCRIPTION("TAS2781 common library"); MODULE_AUTHOR("Shenghao Ding, TI, "); MODULE_LICENSE("GPL");