ASoC: sigmadsp: Restructure in preparation for fw v2 support
[deliverable/linux.git] / sound / soc / codecs / sigmadsp.c
CommitLineData
e359dc24
MF
1/*
2 * Load Analog Devices SigmaStudio firmware files
3 *
d48b088e 4 * Copyright 2009-2014 Analog Devices Inc.
e359dc24
MF
5 *
6 * Licensed under the GPL-2 or later.
7 */
8
9#include <linux/crc32.h>
e359dc24
MF
10#include <linux/firmware.h>
11#include <linux/kernel.h>
12#include <linux/i2c.h>
38fd54ee 13#include <linux/regmap.h>
27c46a25 14#include <linux/module.h>
d48b088e
LPC
15#include <linux/slab.h>
16
17#include <sound/soc.h>
40216ce7
LPC
18
19#include "sigmadsp.h"
e359dc24 20
a4c1d7e6
LPC
21#define SIGMA_MAGIC "ADISIGM"
22
d48b088e
LPC
23struct sigmadsp_data {
24 struct list_head head;
25 unsigned int addr;
26 unsigned int length;
27 uint8_t data[];
28};
29
a4c1d7e6
LPC
30struct sigma_firmware_header {
31 unsigned char magic[7];
32 u8 version;
33 __le32 crc;
34} __packed;
35
36enum {
37 SIGMA_ACTION_WRITEXBYTES = 0,
38 SIGMA_ACTION_WRITESINGLE,
39 SIGMA_ACTION_WRITESAFELOAD,
a4c1d7e6
LPC
40 SIGMA_ACTION_END,
41};
42
d48b088e
LPC
43struct sigma_action {
44 u8 instr;
45 u8 len_hi;
46 __le16 len;
47 __be16 addr;
48 unsigned char payload[];
49} __packed;
50
51static int sigmadsp_write(struct sigmadsp *sigmadsp, unsigned int addr,
52 const uint8_t data[], size_t len)
53{
54 return sigmadsp->write(sigmadsp->control_data, addr, data, len);
55}
56
a4c1d7e6
LPC
57static inline u32 sigma_action_len(struct sigma_action *sa)
58{
59 return (sa->len_hi << 16) | le16_to_cpu(sa->len);
60}
61
4f718a29
LPC
62static size_t sigma_action_size(struct sigma_action *sa)
63{
64 size_t payload = 0;
65
66 switch (sa->instr) {
67 case SIGMA_ACTION_WRITEXBYTES:
68 case SIGMA_ACTION_WRITESINGLE:
69 case SIGMA_ACTION_WRITESAFELOAD:
70 payload = sigma_action_len(sa);
71 break;
72 default:
73 break;
74 }
75
76 payload = ALIGN(payload, 2);
77
78 return payload + sizeof(struct sigma_action);
79}
80
81/*
82 * Returns a negative error value in case of an error, 0 if processing of
83 * the firmware should be stopped after this action, 1 otherwise.
84 */
d48b088e
LPC
85static int process_sigma_action(struct sigmadsp *sigmadsp,
86 struct sigma_action *sa)
e359dc24 87{
e359dc24 88 size_t len = sigma_action_len(sa);
d48b088e 89 struct sigmadsp_data *data;
e359dc24
MF
90
91 pr_debug("%s: instr:%i addr:%#x len:%zu\n", __func__,
92 sa->instr, sa->addr, len);
93
94 switch (sa->instr) {
95 case SIGMA_ACTION_WRITEXBYTES:
96 case SIGMA_ACTION_WRITESINGLE:
97 case SIGMA_ACTION_WRITESAFELOAD:
d48b088e 98 if (len < 3)
e359dc24 99 return -EINVAL;
d48b088e
LPC
100
101 data = kzalloc(sizeof(*data) + len - 2, GFP_KERNEL);
102 if (!data)
103 return -ENOMEM;
104
105 data->addr = be16_to_cpu(sa->addr);
106 data->length = len - 2;
107 memcpy(data->data, sa->payload, data->length);
108 list_add_tail(&data->head, &sigmadsp->data_list);
e359dc24 109 break;
e359dc24 110 case SIGMA_ACTION_END:
4f718a29 111 return 0;
e359dc24
MF
112 default:
113 return -EINVAL;
114 }
115
4f718a29 116 return 1;
e359dc24
MF
117}
118
d48b088e
LPC
119static int sigmadsp_fw_load_v1(struct sigmadsp *sigmadsp,
120 const struct firmware *fw)
e359dc24 121{
4f718a29 122 struct sigma_action *sa;
d48b088e 123 size_t size, pos;
4f718a29
LPC
124 int ret;
125
d48b088e
LPC
126 pos = sizeof(struct sigma_firmware_header);
127
128 while (pos + sizeof(*sa) <= fw->size) {
129 sa = (struct sigma_action *)(fw->data + pos);
4f718a29
LPC
130
131 size = sigma_action_size(sa);
d48b088e
LPC
132 pos += size;
133 if (pos > fw->size || size == 0)
4f718a29
LPC
134 break;
135
d48b088e 136 ret = process_sigma_action(sigmadsp, sa);
e359dc24 137
e359dc24 138 pr_debug("%s: action returned %i\n", __func__, ret);
4f718a29
LPC
139
140 if (ret <= 0)
e359dc24
MF
141 return ret;
142 }
4f718a29 143
d48b088e 144 if (pos != fw->size)
4f718a29
LPC
145 return -EINVAL;
146
147 return 0;
e359dc24
MF
148}
149
d48b088e 150static void sigmadsp_firmware_release(struct sigmadsp *sigmadsp)
e359dc24 151{
d48b088e
LPC
152 struct sigmadsp_data *data, *_data;
153
154 list_for_each_entry_safe(data, _data, &sigmadsp->data_list, head)
155 kfree(data);
156
157 INIT_LIST_HEAD(&sigmadsp->data_list);
158}
159
160static void devm_sigmadsp_release(struct device *dev, void *res)
161{
162 sigmadsp_firmware_release((struct sigmadsp *)res);
163}
164
165static int sigmadsp_firmware_load(struct sigmadsp *sigmadsp, const char *name)
166{
167 const struct sigma_firmware_header *ssfw_head;
e359dc24 168 const struct firmware *fw;
d48b088e 169 int ret;
e359dc24
MF
170 u32 crc;
171
e359dc24 172 /* first load the blob */
d48b088e 173 ret = request_firmware(&fw, name, sigmadsp->dev);
e359dc24
MF
174 if (ret) {
175 pr_debug("%s: request_firmware() failed with %i\n", __func__, ret);
d48b088e 176 goto done;
e359dc24 177 }
e359dc24
MF
178
179 /* then verify the header */
180 ret = -EINVAL;
4f718a29
LPC
181
182 /*
183 * Reject too small or unreasonable large files. The upper limit has been
184 * chosen a bit arbitrarily, but it should be enough for all practical
185 * purposes and having the limit makes it easier to avoid integer
186 * overflows later in the loading process.
187 */
48afc527 188 if (fw->size < sizeof(*ssfw_head) || fw->size >= 0x4000000) {
d48b088e 189 dev_err(sigmadsp->dev, "Failed to load firmware: Invalid size\n");
e359dc24 190 goto done;
48afc527 191 }
e359dc24
MF
192
193 ssfw_head = (void *)fw->data;
48afc527 194 if (memcmp(ssfw_head->magic, SIGMA_MAGIC, ARRAY_SIZE(ssfw_head->magic))) {
d48b088e 195 dev_err(sigmadsp->dev, "Failed to load firmware: Invalid magic\n");
50c0f21b
LPC
196 goto done;
197 }
198
c56935bd
LPC
199 crc = crc32(0, fw->data + sizeof(*ssfw_head),
200 fw->size - sizeof(*ssfw_head));
e359dc24 201 pr_debug("%s: crc=%x\n", __func__, crc);
48afc527 202 if (crc != le32_to_cpu(ssfw_head->crc)) {
d48b088e 203 dev_err(sigmadsp->dev, "Failed to load firmware: Wrong crc checksum: expected %x got %x\n",
48afc527 204 le32_to_cpu(ssfw_head->crc), crc);
e359dc24 205 goto done;
48afc527 206 }
e359dc24 207
d48b088e
LPC
208 switch (ssfw_head->version) {
209 case 1:
210 ret = sigmadsp_fw_load_v1(sigmadsp, fw);
211 break;
212 default:
213 dev_err(sigmadsp->dev,
214 "Failed to load firmware: Invalid version %d. Supported firmware versions: 1\n",
215 ssfw_head->version);
216 ret = -EINVAL;
217 break;
218 }
e359dc24 219
d48b088e
LPC
220 if (ret)
221 sigmadsp_firmware_release(sigmadsp);
e359dc24 222
d48b088e 223done:
e359dc24
MF
224 release_firmware(fw);
225
d48b088e
LPC
226 return ret;
227}
228
229static int sigmadsp_init(struct sigmadsp *sigmadsp, struct device *dev,
230 const struct sigmadsp_ops *ops, const char *firmware_name)
231{
232 sigmadsp->ops = ops;
233 sigmadsp->dev = dev;
234
235 INIT_LIST_HEAD(&sigmadsp->data_list);
236
237 return sigmadsp_firmware_load(sigmadsp, firmware_name);
238}
239
240/**
241 * devm_sigmadsp_init() - Initialize SigmaDSP instance
242 * @dev: The parent device
243 * @ops: The sigmadsp_ops to use for this instance
244 * @firmware_name: Name of the firmware file to load
245 *
246 * Allocates a SigmaDSP instance and loads the specified firmware file.
247 *
248 * Returns a pointer to a struct sigmadsp on success, or a PTR_ERR() on error.
249 */
250struct sigmadsp *devm_sigmadsp_init(struct device *dev,
251 const struct sigmadsp_ops *ops, const char *firmware_name)
252{
253 struct sigmadsp *sigmadsp;
254 int ret;
255
256 sigmadsp = devres_alloc(devm_sigmadsp_release, sizeof(*sigmadsp),
257 GFP_KERNEL);
258 if (!sigmadsp)
259 return ERR_PTR(-ENOMEM);
260
261 ret = sigmadsp_init(sigmadsp, dev, ops, firmware_name);
262 if (ret) {
263 devres_free(sigmadsp);
264 return ERR_PTR(ret);
265 }
266
267 devres_add(dev, sigmadsp);
268
269 return sigmadsp;
270}
271EXPORT_SYMBOL_GPL(devm_sigmadsp_init);
272
273/**
274 * sigmadsp_attach() - Attach a sigmadsp instance to a ASoC component
275 * @sigmadsp: The sigmadsp instance to attach
276 * @component: The component to attach to
277 *
278 * Typically called in the components probe callback.
279 *
280 * Note, once this function has been called the firmware must not be released
281 * until after the ALSA snd_card that the component belongs to has been
282 * disconnected, even if sigmadsp_attach() returns an error.
283 */
284int sigmadsp_attach(struct sigmadsp *sigmadsp,
285 struct snd_soc_component *component)
286{
287 sigmadsp->component = component;
288
289 return 0;
290}
291EXPORT_SYMBOL_GPL(sigmadsp_attach);
292
293/**
294 * sigmadsp_setup() - Setup the DSP for the specified samplerate
295 * @sigmadsp: The sigmadsp instance to configure
296 * @samplerate: The samplerate the DSP should be configured for
297 *
298 * Loads the appropriate firmware program and parameter memory (if not already
299 * loaded) and enables the controls for the specified samplerate. Any control
300 * parameter changes that have been made previously will be restored.
301 *
302 * Returns 0 on success, a negative error code otherwise.
303 */
304int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate)
305{
306 struct sigmadsp_data *data;
307 int ret;
308
309 if (sigmadsp->current_samplerate == samplerate)
310 return 0;
311
312 list_for_each_entry(data, &sigmadsp->data_list, head) {
313 ret = sigmadsp_write(sigmadsp, data->addr, data->data,
314 data->length);
315 if (ret)
316 goto err;
317 }
318
319 sigmadsp->current_samplerate = samplerate;
320
321 return 0;
322err:
323 sigmadsp_reset(sigmadsp);
e359dc24
MF
324
325 return ret;
326}
d48b088e
LPC
327EXPORT_SYMBOL_GPL(sigmadsp_setup);
328
329/**
330 * sigmadsp_reset() - Notify the sigmadsp instance that the DSP has been reset
331 * @sigmadsp: The sigmadsp instance to reset
332 *
333 * Should be called whenever the DSP has been reset and parameter and program
334 * memory need to be re-loaded.
335 */
336void sigmadsp_reset(struct sigmadsp *sigmadsp)
337{
338 sigmadsp->current_samplerate = 0;
339}
340EXPORT_SYMBOL_GPL(sigmadsp_reset);
341
342/**
343 * sigmadsp_restrict_params() - Applies DSP firmware specific constraints
344 * @sigmadsp: The sigmadsp instance
345 * @substream: The substream to restrict
346 *
347 * Applies samplerate constraints that may be required by the firmware Should
348 * typically be called from the CODEC/component drivers startup callback.
349 *
350 * Returns 0 on success, a negative error code otherwise.
351 */
352int sigmadsp_restrict_params(struct sigmadsp *sigmadsp,
353 struct snd_pcm_substream *substream)
354{
355 return 0;
356}
357EXPORT_SYMBOL_GPL(sigmadsp_restrict_params);
38fd54ee 358
27c46a25 359MODULE_LICENSE("GPL");
This page took 0.213785 seconds and 5 git commands to generate.