File Index
Files and directories
Sign in
FILE

tas2781-comlib.c

File preview with syntax highlighting.

linux-6.19.14/sound/soc/codecs/tas2781-comlib.c C
  1// SPDX-License-Identifier: GPL-2.0
  2//
  3// TAS2563/TAS2781 Common functions for HDA and ASoC Audio drivers
  4//
  5// Copyright 2023 - 2025 Texas Instruments, Inc.
  6//
  7// Author: Shenghao Ding <shenghao-ding@ti.com>
  8
  9#include <linux/crc8.h>
 10#include <linux/dev_printk.h>
 11#include <linux/firmware.h>
 12#include <linux/gpio/consumer.h>
 13#include <linux/init.h>
 14#include <linux/interrupt.h>
 15#include <linux/module.h>
 16#include <linux/of.h>
 17#include <linux/of_irq.h>
 18#include <linux/regmap.h>
 19#include <linux/slab.h>
 20#include <sound/tas2781.h>
 21
 22int tasdevice_dev_read(struct tasdevice_priv *tas_priv,
 23	unsigned short chn, unsigned int reg, unsigned int *val)
 24{
 25	int ret = 0;
 26
 27	if (chn < tas_priv->ndev) {
 28		struct regmap *map = tas_priv->regmap;
 29
 30		ret = tas_priv->change_chn_book(tas_priv, chn,
 31			TASDEVICE_BOOK_ID(reg));
 32		if (ret < 0)
 33			goto out;
 34
 35		ret = regmap_read(map, TASDEVICE_PGRG(reg), val);
 36		if (ret < 0)
 37			dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
 38	} else {
 39		ret = -EINVAL;
 40		dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
 41			chn);
 42	}
 43
 44out:
 45	return ret;
 46}
 47EXPORT_SYMBOL_GPL(tasdevice_dev_read);
 48
 49int tasdevice_dev_bulk_read(struct tasdevice_priv *tas_priv,
 50	unsigned short chn, unsigned int reg, unsigned char *data,
 51	unsigned int len)
 52{
 53	int ret = 0;
 54
 55	if (chn < tas_priv->ndev) {
 56		struct regmap *map = tas_priv->regmap;
 57
 58		ret = tas_priv->change_chn_book(tas_priv, chn,
 59			TASDEVICE_BOOK_ID(reg));
 60		if (ret < 0)
 61			goto out;
 62
 63		ret = regmap_bulk_read(map, TASDEVICE_PGRG(reg), data, len);
 64		if (ret < 0)
 65			dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
 66	} else
 67		dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
 68			chn);
 69
 70out:
 71	return ret;
 72}
 73EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read);
 74
 75int tasdevice_dev_write(struct tasdevice_priv *tas_priv,
 76	unsigned short chn, unsigned int reg, unsigned int value)
 77{
 78	int ret = 0;
 79
 80	if (chn < tas_priv->ndev) {
 81		struct regmap *map = tas_priv->regmap;
 82
 83		ret = tas_priv->change_chn_book(tas_priv, chn,
 84			TASDEVICE_BOOK_ID(reg));
 85		if (ret < 0)
 86			goto out;
 87
 88		ret = regmap_write(map, TASDEVICE_PGRG(reg),
 89			value);
 90		if (ret < 0)
 91			dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
 92	} else {
 93		ret = -EINVAL;
 94		dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
 95			chn);
 96	}
 97
 98out:
 99	return ret;
100}
101EXPORT_SYMBOL_GPL(tasdevice_dev_write);
102
103int tasdevice_dev_bulk_write(
104	struct tasdevice_priv *tas_priv, unsigned short chn,
105	unsigned int reg, unsigned char *data,
106	unsigned int len)
107{
108	int ret = 0;
109
110	if (chn < tas_priv->ndev) {
111		struct regmap *map = tas_priv->regmap;
112
113		ret = tas_priv->change_chn_book(tas_priv, chn,
114			TASDEVICE_BOOK_ID(reg));
115		if (ret < 0)
116			goto out;
117
118		ret = regmap_bulk_write(map, TASDEVICE_PGRG(reg),
119			data, len);
120		if (ret < 0)
121			dev_err(tas_priv->dev, "%s, E=%d\n", __func__, ret);
122	} else {
123		ret = -EINVAL;
124		dev_err(tas_priv->dev, "%s, no such channel(%d)\n", __func__,
125			chn);
126	}
127
128out:
129	return ret;
130}
131EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write);
132
133static void tasdev_dsp_prog_blk_remove(struct tasdevice_prog *prog)
134{
135	struct tasdevice_data *tas_dt;
136	struct tasdev_blk *blk;
137	unsigned int i;
138
139	if (!prog)
140		return;
141
142	tas_dt = &(prog->dev_data);
143
144	if (!tas_dt->dev_blks)
145		return;
146
147	for (i = 0; i < tas_dt->nr_blk; i++) {
148		blk = &(tas_dt->dev_blks[i]);
149		kfree(blk->data);
150	}
151	kfree(tas_dt->dev_blks);
152}
153
154static void tasdev_dsp_prog_remove(struct tasdevice_prog *prog,
155	unsigned short nr)
156{
157	int i;
158
159	for (i = 0; i < nr; i++)
160		tasdev_dsp_prog_blk_remove(&prog[i]);
161	kfree(prog);
162}
163
164static void tasdev_dsp_cfg_blk_remove(struct tasdevice_config *cfg)
165{
166	struct tasdevice_data *tas_dt;
167	struct tasdev_blk *blk;
168	unsigned int i;
169
170	if (cfg) {
171		tas_dt = &(cfg->dev_data);
172
173		if (!tas_dt->dev_blks)
174			return;
175
176		for (i = 0; i < tas_dt->nr_blk; i++) {
177			blk = &(tas_dt->dev_blks[i]);
178			kfree(blk->data);
179		}
180		kfree(tas_dt->dev_blks);
181	}
182}
183
184static void tasdev_dsp_cfg_remove(struct tasdevice_config *config,
185	unsigned short nr)
186{
187	int i;
188
189	for (i = 0; i < nr; i++)
190		tasdev_dsp_cfg_blk_remove(&config[i]);
191	kfree(config);
192}
193
194void tasdevice_dsp_remove(void *context)
195{
196	struct tasdevice_priv *tas_dev = (struct tasdevice_priv *) context;
197	struct tasdevice_fw *tas_fmw = tas_dev->fmw;
198
199	if (!tas_dev->fmw)
200		return;
201
202	if (tas_fmw->programs)
203		tasdev_dsp_prog_remove(tas_fmw->programs,
204			tas_fmw->nr_programs);
205	if (tas_fmw->configs)
206		tasdev_dsp_cfg_remove(tas_fmw->configs,
207			tas_fmw->nr_configurations);
208	kfree(tas_fmw);
209	tas_dev->fmw = NULL;
210}
211EXPORT_SYMBOL_GPL(tasdevice_dsp_remove);
212
213void tasdevice_remove(struct tasdevice_priv *tas_priv)
214{
215	mutex_destroy(&tas_priv->codec_lock);
216}
217EXPORT_SYMBOL_GPL(tasdevice_remove);
218
219MODULE_DESCRIPTION("TAS2781 common library");
220MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
221MODULE_LICENSE("GPL");
~/ Read-only file preview.