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
tasdevice_dev_read(struct tasdevice_priv * tas_priv,unsigned short chn,unsigned int reg,unsigned int * val)22 int 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
44 out:
45 return ret;
46 }
47 EXPORT_SYMBOL_GPL(tasdevice_dev_read);
48
tasdevice_dev_bulk_read(struct tasdevice_priv * tas_priv,unsigned short chn,unsigned int reg,unsigned char * data,unsigned int len)49 int 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
70 out:
71 return ret;
72 }
73 EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_read);
74
tasdevice_dev_write(struct tasdevice_priv * tas_priv,unsigned short chn,unsigned int reg,unsigned int value)75 int 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
98 out:
99 return ret;
100 }
101 EXPORT_SYMBOL_GPL(tasdevice_dev_write);
102
tasdevice_dev_bulk_write(struct tasdevice_priv * tas_priv,unsigned short chn,unsigned int reg,unsigned char * data,unsigned int len)103 int 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
128 out:
129 return ret;
130 }
131 EXPORT_SYMBOL_GPL(tasdevice_dev_bulk_write);
132
tasdev_dsp_prog_blk_remove(struct tasdevice_prog * prog)133 static 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
tasdev_dsp_prog_remove(struct tasdevice_prog * prog,unsigned short nr)154 static 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
tasdev_dsp_cfg_blk_remove(struct tasdevice_config * cfg)164 static 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
tasdev_dsp_cfg_remove(struct tasdevice_config * config,unsigned short nr)184 static 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
tasdevice_dsp_remove(void * context)194 void 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 }
211 EXPORT_SYMBOL_GPL(tasdevice_dsp_remove);
212
tasdevice_remove(struct tasdevice_priv * tas_priv)213 void tasdevice_remove(struct tasdevice_priv *tas_priv)
214 {
215 mutex_destroy(&tas_priv->codec_lock);
216 }
217 EXPORT_SYMBOL_GPL(tasdevice_remove);
218
219 MODULE_DESCRIPTION("TAS2781 common library");
220 MODULE_AUTHOR("Shenghao Ding, TI, <shenghao-ding@ti.com>");
221 MODULE_LICENSE("GPL");
222