aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitris Papastamos <dp@opensource.wolfsonmicro.com>2012-08-23 10:59:56 -0400
committerMark Brown <broonie@opensource.wolfsonmicro.com>2012-08-23 11:12:12 -0400
commite3523e01869da20fdd12ffd19ae1df7bf492650e (patch)
treeb482de80b3b92f08169ae8c54994506407a8bfb6
parent52ca1138fa55bf6f46a5e02a2c1088756a5c8f2e (diff)
ASoC: wm0010: Add initial wm0010 DSP driver
The WM0010 is a compact digital signal processor that has been highly optimised for low-power audio applications. Extensive memory resources and core optimisation allow the device to manage all audio processing algorithms efficiently and autonomously, while the host processor sleeps or performs other tasks. Signed-off-by: Dimitris Papastamos <dp@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
-rw-r--r--include/sound/wm0010.h27
-rw-r--r--sound/soc/codecs/Kconfig4
-rw-r--r--sound/soc/codecs/Makefile2
-rw-r--r--sound/soc/codecs/wm0010.c930
4 files changed, 963 insertions, 0 deletions
diff --git a/include/sound/wm0010.h b/include/sound/wm0010.h
new file mode 100644
index 000000000000..3261e90815af
--- /dev/null
+++ b/include/sound/wm0010.h
@@ -0,0 +1,27 @@
1/*
2 * wm0010.h -- Platform data for WM0010 DSP Driver
3 *
4 * Copyright 2012 Wolfson Microelectronics PLC.
5 *
6 * Author: Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify it
9 * under the terms of the GNU General Public License as published by the
10 * Free Software Foundation; either version 2 of the License, or (at your
11 * option) any later version.
12 */
13
14#ifndef WM0010_PDATA_H
15#define WM0010_PDATA_H
16
17struct wm0010_pdata {
18 int gpio_reset;
19
20 /* Set if there is an inverter between the GPIO controlling
21 * the reset signal and the device.
22 */
23 int reset_active_high;
24 int irq_flags;
25};
26
27#endif
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig
index 9f8e8594aeb9..3684255e5fba 100644
--- a/sound/soc/codecs/Kconfig
+++ b/sound/soc/codecs/Kconfig
@@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS
70 select SND_SOC_UDA134X 70 select SND_SOC_UDA134X
71 select SND_SOC_UDA1380 if I2C 71 select SND_SOC_UDA1380 if I2C
72 select SND_SOC_WL1273 if MFD_WL1273_CORE 72 select SND_SOC_WL1273 if MFD_WL1273_CORE
73 select SND_SOC_WM0010 if SPI_MASTER
73 select SND_SOC_WM1250_EV1 if I2C 74 select SND_SOC_WM1250_EV1 if I2C
74 select SND_SOC_WM2000 if I2C 75 select SND_SOC_WM2000 if I2C
75 select SND_SOC_WM2200 if I2C 76 select SND_SOC_WM2200 if I2C
@@ -326,6 +327,9 @@ config SND_SOC_UDA1380
326config SND_SOC_WL1273 327config SND_SOC_WL1273
327 tristate 328 tristate
328 329
330config SND_SOC_WM0010
331 tristate
332
329config SND_SOC_WM1250_EV1 333config SND_SOC_WM1250_EV1
330 tristate 334 tristate
331 335
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile
index 34148bb59c68..ca508b251df7 100644
--- a/sound/soc/codecs/Makefile
+++ b/sound/soc/codecs/Makefile
@@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o
61snd-soc-uda134x-objs := uda134x.o 61snd-soc-uda134x-objs := uda134x.o
62snd-soc-uda1380-objs := uda1380.o 62snd-soc-uda1380-objs := uda1380.o
63snd-soc-wl1273-objs := wl1273.o 63snd-soc-wl1273-objs := wl1273.o
64snd-soc-wm0010-objs := wm0010.o
64snd-soc-wm1250-ev1-objs := wm1250-ev1.o 65snd-soc-wm1250-ev1-objs := wm1250-ev1.o
65snd-soc-wm2000-objs := wm2000.o 66snd-soc-wm2000-objs := wm2000.o
66snd-soc-wm2200-objs := wm2200.o 67snd-soc-wm2200-objs := wm2200.o
@@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o
177obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o 178obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o
178obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o 179obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o
179obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o 180obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o
181obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o
180obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o 182obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o
181obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o 183obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o
182obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o 184obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c
new file mode 100644
index 000000000000..8e0b6d6bffaf
--- /dev/null
+++ b/sound/soc/codecs/wm0010.c
@@ -0,0 +1,930 @@
1/*
2 * wm0010.c -- WM0010 DSP Driver
3 *
4 * Copyright 2012 Wolfson Microelectronics PLC.
5 *
6 * Authors: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 * Dimitris Papastamos <dp@opensource.wolfsonmicro.com>
8 * Scott Ling <sl@opensource.wolfsonmicro.com>
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License version 2 as
12 * published by the Free Software Foundation.
13 */
14
15#include <linux/module.h>
16#include <linux/moduleparam.h>
17#include <linux/irqreturn.h>
18#include <linux/init.h>
19#include <linux/spi/spi.h>
20#include <linux/firmware.h>
21#include <linux/delay.h>
22#include <linux/fs.h>
23#include <linux/miscdevice.h>
24#include <linux/gpio.h>
25#include <linux/regulator/consumer.h>
26#include <linux/mutex.h>
27#include <linux/workqueue.h>
28
29#include <sound/soc.h>
30#include <sound/wm0010.h>
31
32#define DEVICE_ID_WM0010 10
33
34enum dfw_cmd {
35 DFW_CMD_FUSE = 0x01,
36 DFW_CMD_CODE_HDR,
37 DFW_CMD_CODE_DATA,
38 DFW_CMD_PLL,
39 DFW_CMD_INFO = 0xff
40};
41
42struct dfw_binrec {
43 u8 command;
44 u32 length:24;
45 u32 address;
46 uint8_t data[0];
47} __packed;
48
49struct dfw_pllrec {
50 u8 command;
51 u32 length:24;
52 u32 address;
53 u32 clkctrl1;
54 u32 clkctrl2;
55 u32 clkctrl3;
56 u32 ldetctrl;
57 u32 uart_div;
58 u32 spi_div;
59} __packed;
60
61static struct pll_clock_map {
62 int max_sysclk;
63 int max_pll_spi_speed;
64 u32 pll_clkctrl1;
65} pll_clock_map[] = { /* Dividers */
66 { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */
67 { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */
68 { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */
69 { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */
70 { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */
71 { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */
72};
73
74enum wm0010_state {
75 WM0010_POWER_OFF,
76 WM0010_OUT_OF_RESET,
77 WM0010_BOOTROM,
78 WM0010_STAGE2,
79 WM0010_FIRMWARE,
80};
81
82struct wm0010_priv {
83 struct snd_soc_codec *codec;
84
85 struct mutex lock;
86 struct device *dev;
87
88 struct wm0010_pdata pdata;
89
90 int gpio_reset;
91 int gpio_reset_value;
92
93 struct regulator_bulk_data core_supplies[2];
94 struct regulator *dbvdd;
95
96 int sysclk;
97
98 enum wm0010_state state;
99 bool boot_failed;
100 int boot_done;
101 bool ready;
102 bool pll_running;
103 int max_spi_freq;
104 int board_max_spi_speed;
105 u32 pll_clkctrl1;
106
107 spinlock_t irq_lock;
108 int irq;
109
110 struct completion boot_completion;
111};
112
113struct wm0010_spi_msg {
114 struct spi_message m;
115 struct spi_transfer t;
116 u8 *tx_buf;
117 u8 *rx_buf;
118 size_t len;
119};
120
121static const struct snd_soc_dapm_route wm0010_dapm_routes[] = {
122 { "SDI2 Playback", NULL, "SDI1 Playback" },
123};
124
125static const char *wm0010_state_to_str(enum wm0010_state state)
126{
127 const char *state_to_str[] = {
128 "Power off",
129 "Out of reset",
130 "Bootrom",
131 "Stage2",
132 "Firmware"
133 };
134
135 if (state < 0 || state >= ARRAY_SIZE(state_to_str))
136 return "null";
137 return state_to_str[state];
138}
139
140/* Called with wm0010->lock held */
141static void wm0010_halt(struct snd_soc_codec *codec)
142{
143 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
144 unsigned long flags;
145 enum wm0010_state state;
146
147 /* Fetch the wm0010 state */
148 spin_lock_irqsave(&wm0010->irq_lock, flags);
149 state = wm0010->state;
150 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
151
152 switch (state) {
153 case WM0010_POWER_OFF:
154 /* If there's nothing to do, bail out */
155 return;
156 case WM0010_OUT_OF_RESET:
157 case WM0010_BOOTROM:
158 case WM0010_STAGE2:
159 case WM0010_FIRMWARE:
160 /* Remember to put chip back into reset */
161 gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value);
162 /* Disable the regulators */
163 regulator_disable(wm0010->dbvdd);
164 regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies),
165 wm0010->core_supplies);
166 break;
167 }
168
169 spin_lock_irqsave(&wm0010->irq_lock, flags);
170 wm0010->state = WM0010_POWER_OFF;
171 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
172}
173
174struct wm0010_boot_xfer {
175 struct list_head list;
176 struct snd_soc_codec *codec;
177 struct completion *done;
178 struct spi_message m;
179 struct spi_transfer t;
180};
181
182/* Called with wm0010->lock held */
183static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010)
184{
185 enum wm0010_state state;
186 unsigned long flags;
187
188 spin_lock_irqsave(&wm0010->irq_lock, flags);
189 state = wm0010->state;
190 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
191
192 dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n",
193 wm0010_state_to_str(state), wm0010_state_to_str(state + 1));
194
195 wm0010->boot_failed = true;
196}
197
198static void wm0010_boot_xfer_complete(void *data)
199{
200 struct wm0010_boot_xfer *xfer = data;
201 struct snd_soc_codec *codec = xfer->codec;
202 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
203 u32 *out32 = xfer->t.rx_buf;
204 int i;
205
206 if (xfer->m.status != 0) {
207 dev_err(codec->dev, "SPI transfer failed: %d\n",
208 xfer->m.status);
209 wm0010_mark_boot_failure(wm0010);
210 if (xfer->done)
211 complete(xfer->done);
212 return;
213 }
214
215 for (i = 0; i < xfer->t.len / 4; i++) {
216 dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]);
217
218 switch (be32_to_cpu(out32[i])) {
219 case 0xe0e0e0e0:
220 dev_err(codec->dev,
221 "%d: ROM error reported in stage 2\n", i);
222 wm0010_mark_boot_failure(wm0010);
223 break;
224
225 case 0x55555555:
226 if (wm0010->boot_done == 0)
227 break;
228 dev_err(codec->dev,
229 "%d: ROM bootloader running in stage 2\n", i);
230 wm0010_mark_boot_failure(wm0010);
231 break;
232
233 case 0x0fed0000:
234 dev_dbg(codec->dev, "Stage2 loader running\n");
235 break;
236
237 case 0x0fed0007:
238 dev_dbg(codec->dev, "CODE_HDR packet received\n");
239 break;
240
241 case 0x0fed0008:
242 dev_dbg(codec->dev, "CODE_DATA packet received\n");
243 break;
244
245 case 0x0fed0009:
246 dev_dbg(codec->dev, "Download complete\n");
247 break;
248
249 case 0x0fed000c:
250 dev_dbg(codec->dev, "Application start\n");
251 break;
252
253 case 0x0fed000e:
254 dev_dbg(codec->dev, "PLL packet received\n");
255 wm0010->pll_running = true;
256 break;
257
258 case 0x0fed0025:
259 dev_err(codec->dev, "Device reports image too long\n");
260 wm0010_mark_boot_failure(wm0010);
261 break;
262
263 case 0x0fed002c:
264 dev_err(codec->dev, "Device reports bad SPI packet\n");
265 wm0010_mark_boot_failure(wm0010);
266 break;
267
268 case 0x0fed0031:
269 dev_err(codec->dev, "Device reports SPI read overflow\n");
270 wm0010_mark_boot_failure(wm0010);
271 break;
272
273 case 0x0fed0032:
274 dev_err(codec->dev, "Device reports SPI underclock\n");
275 wm0010_mark_boot_failure(wm0010);
276 break;
277
278 case 0x0fed0033:
279 dev_err(codec->dev, "Device reports bad header packet\n");
280 wm0010_mark_boot_failure(wm0010);
281 break;
282
283 case 0x0fed0034:
284 dev_err(codec->dev, "Device reports invalid packet type\n");
285 wm0010_mark_boot_failure(wm0010);
286 break;
287
288 case 0x0fed0035:
289 dev_err(codec->dev, "Device reports data before header error\n");
290 wm0010_mark_boot_failure(wm0010);
291 break;
292
293 case 0x0fed0038:
294 dev_err(codec->dev, "Device reports invalid PLL packet\n");
295 break;
296
297 case 0x0fed003a:
298 dev_err(codec->dev, "Device reports packet alignment error\n");
299 wm0010_mark_boot_failure(wm0010);
300 break;
301
302 default:
303 dev_err(codec->dev, "Unrecognised return 0x%x\n",
304 be32_to_cpu(out32[i]));
305 wm0010_mark_boot_failure(wm0010);
306 break;
307 }
308
309 if (wm0010->boot_failed)
310 break;
311 }
312
313 wm0010->boot_done++;
314 if (xfer->done)
315 complete(xfer->done);
316}
317
318static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len)
319{
320 int i;
321
322 for (i = 0; i < len / 8; i++)
323 data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i]));
324}
325
326static int wm0010_boot(struct snd_soc_codec *codec)
327{
328 struct spi_device *spi = to_spi_device(codec->dev);
329 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
330 unsigned long flags;
331 struct list_head xfer_list;
332 struct wm0010_boot_xfer *xfer;
333 int ret;
334 struct completion done;
335 const struct firmware *fw;
336 const struct dfw_binrec *rec;
337 struct spi_message m;
338 struct spi_transfer t;
339 struct dfw_pllrec pll_rec;
340 u32 *img, *p;
341 u64 *img_swap;
342 u8 *out;
343 u32 len, offset;
344 int i;
345
346 spin_lock_irqsave(&wm0010->irq_lock, flags);
347 if (wm0010->state != WM0010_POWER_OFF)
348 dev_warn(wm0010->dev, "DSP already powered up!\n");
349 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
350
351 if (wm0010->sysclk > 26000000) {
352 dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n");
353 ret = -ECANCELED;
354 goto err;
355 }
356
357 INIT_LIST_HEAD(&xfer_list);
358
359 mutex_lock(&wm0010->lock);
360 wm0010->pll_running = false;
361
362 dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq);
363
364 ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies),
365 wm0010->core_supplies);
366 if (ret != 0) {
367 dev_err(&spi->dev, "Failed to enable core supplies: %d\n",
368 ret);
369 mutex_unlock(&wm0010->lock);
370 goto err;
371 }
372
373 ret = regulator_enable(wm0010->dbvdd);
374 if (ret != 0) {
375 dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret);
376 goto err_core;
377 }
378
379 /* Release reset */
380 gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value);
381 spin_lock_irqsave(&wm0010->irq_lock, flags);
382 wm0010->state = WM0010_OUT_OF_RESET;
383 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
384
385 /* First the bootloader */
386 ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev);
387 if (ret != 0) {
388 dev_err(codec->dev, "Failed to request stage2 loader: %d\n",
389 ret);
390 goto abort;
391 }
392
393 if (!wait_for_completion_timeout(&wm0010->boot_completion,
394 msecs_to_jiffies(10)))
395 dev_err(codec->dev, "Failed to get interrupt from DSP\n");
396
397 spin_lock_irqsave(&wm0010->irq_lock, flags);
398 wm0010->state = WM0010_BOOTROM;
399 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
400
401 dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size);
402
403 /* Copy to local buffer first as vmalloc causes problems for dma */
404 img = kzalloc(fw->size, GFP_KERNEL);
405 if (!img) {
406 dev_err(codec->dev, "Failed to allocate image buffer\n");
407 goto abort;
408 }
409
410 out = kzalloc(fw->size, GFP_KERNEL);
411 if (!out) {
412 dev_err(codec->dev, "Failed to allocate output buffer\n");
413 goto abort;
414 }
415
416 memcpy(img, &fw->data[0], fw->size);
417
418 spi_message_init(&m);
419 memset(&t, 0, sizeof(t));
420 t.rx_buf = out;
421 t.tx_buf = img;
422 t.len = fw->size;
423 t.bits_per_word = 8;
424 t.speed_hz = wm0010->sysclk / 10;
425 spi_message_add_tail(&t, &m);
426
427 dev_dbg(codec->dev, "Starting initial download at %dHz\n",
428 t.speed_hz);
429
430 ret = spi_sync(spi, &m);
431 if (ret != 0) {
432 dev_err(codec->dev, "Initial download failed: %d\n", ret);
433 goto abort;
434 }
435
436 /* Look for errors from the boot ROM */
437 for (i = 0; i < fw->size; i++) {
438 if (out[i] != 0x55) {
439 ret = -EBUSY;
440 dev_err(codec->dev, "Boot ROM error: %x in %d\n",
441 out[i], i);
442 wm0010_mark_boot_failure(wm0010);
443 goto abort;
444 }
445 }
446
447 release_firmware(fw);
448 kfree(img);
449 kfree(out);
450
451 if (!wait_for_completion_timeout(&wm0010->boot_completion,
452 msecs_to_jiffies(10)))
453 dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n");
454
455 spin_lock_irqsave(&wm0010->irq_lock, flags);
456 wm0010->state = WM0010_STAGE2;
457 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
458
459 /* Only initialise PLL if max_spi_freq initialised */
460 if (wm0010->max_spi_freq) {
461
462 /* Initialise a PLL record */
463 memset(&pll_rec, 0, sizeof(pll_rec));
464 pll_rec.command = DFW_CMD_PLL;
465 pll_rec.length = (sizeof(pll_rec) - 8);
466
467 /* On wm0010 only the CLKCTRL1 value is used */
468 pll_rec.clkctrl1 = wm0010->pll_clkctrl1;
469
470 len = pll_rec.length + 8;
471 out = kzalloc(len, GFP_KERNEL);
472 if (!out) {
473 dev_err(codec->dev,
474 "Failed to allocate RX buffer\n");
475 goto abort;
476 }
477
478 img_swap = kzalloc(len, GFP_KERNEL);
479 if (!img_swap) {
480 dev_err(codec->dev,
481 "Failed to allocate image buffer\n");
482 goto abort;
483 }
484
485 /* We need to re-order for 0010 */
486 byte_swap_64((u64 *)&pll_rec, img_swap, len);
487
488 spi_message_init(&m);
489 memset(&t, 0, sizeof(t));
490 t.rx_buf = out;
491 t.tx_buf = img_swap;
492 t.len = len;
493 t.bits_per_word = 8;
494 t.speed_hz = wm0010->sysclk / 6;
495 spi_message_add_tail(&t, &m);
496
497 ret = spi_sync(spi, &m);
498 if (ret != 0) {
499 dev_err(codec->dev, "First PLL write failed: %d\n", ret);
500 goto abort;
501 }
502
503 /* Use a second send of the message to get the return status */
504 ret = spi_sync(spi, &m);
505 if (ret != 0) {
506 dev_err(codec->dev, "Second PLL write failed: %d\n", ret);
507 goto abort;
508 }
509
510 p = (u32 *)out;
511
512 /* Look for PLL active code from the DSP */
513 for (i = 0; i < len / 4; i++) {
514 if (*p == 0x0e00ed0f) {
515 dev_dbg(codec->dev, "PLL packet received\n");
516 wm0010->pll_running = true;
517 break;
518 }
519 p++;
520 }
521
522 kfree(img_swap);
523 kfree(out);
524 } else
525 dev_dbg(codec->dev, "Not enabling DSP PLL.");
526
527 ret = request_firmware(&fw, "wm0010.dfw", codec->dev);
528 if (ret != 0) {
529 dev_err(codec->dev, "Failed to request application: %d\n",
530 ret);
531 goto abort;
532 }
533
534 rec = (const struct dfw_binrec *)fw->data;
535 offset = 0;
536 wm0010->boot_done = 0;
537 wm0010->boot_failed = false;
538 BUG_ON(!list_empty(&xfer_list));
539 init_completion(&done);
540
541 /* First record should be INFO */
542 if (rec->command != DFW_CMD_INFO) {
543 dev_err(codec->dev, "First record not INFO\r\n");
544 goto abort;
545 }
546
547 /* Check it's a 0010 file */
548 if (rec->data[0] != DEVICE_ID_WM0010) {
549 dev_err(codec->dev, "Not a WM0010 firmware file.\r\n");
550 goto abort;
551 }
552
553 /* Skip the info record as we don't need to send it */
554 offset += ((rec->length) + 8);
555 rec = (void *)&rec->data[rec->length];
556
557 while (offset < fw->size) {
558 dev_dbg(codec->dev,
559 "Packet: command %d, data length = 0x%x\r\n",
560 rec->command, rec->length);
561 len = rec->length + 8;
562
563 out = kzalloc(len, GFP_KERNEL);
564 if (!out) {
565 dev_err(codec->dev,
566 "Failed to allocate RX buffer\n");
567 goto abort;
568 }
569
570 img_swap = kzalloc(len, GFP_KERNEL);
571 if (!img_swap) {
572 dev_err(codec->dev,
573 "Failed to allocate image buffer\n");
574 goto abort;
575 }
576
577 /* We need to re-order for 0010 */
578 byte_swap_64((u64 *)&rec->command, img_swap, len);
579
580 xfer = kzalloc(sizeof(*xfer), GFP_KERNEL);
581 if (!xfer) {
582 dev_err(codec->dev, "Failed to allocate xfer\n");
583 goto abort;
584 }
585
586 xfer->codec = codec;
587 list_add_tail(&xfer->list, &xfer_list);
588
589 spi_message_init(&xfer->m);
590 xfer->m.complete = wm0010_boot_xfer_complete;
591 xfer->m.context = xfer;
592 xfer->t.tx_buf = img_swap;
593 xfer->t.rx_buf = out;
594 xfer->t.len = len;
595 xfer->t.bits_per_word = 8;
596
597 if (!wm0010->pll_running) {
598 xfer->t.speed_hz = wm0010->sysclk / 6;
599 } else {
600 xfer->t.speed_hz = wm0010->max_spi_freq;
601
602 if (wm0010->board_max_spi_speed &&
603 (wm0010->board_max_spi_speed < wm0010->max_spi_freq))
604 xfer->t.speed_hz = wm0010->board_max_spi_speed;
605 }
606
607 /* Store max usable spi frequency for later use */
608 wm0010->max_spi_freq = xfer->t.speed_hz;
609
610 spi_message_add_tail(&xfer->t, &xfer->m);
611
612 offset += ((rec->length) + 8);
613 rec = (void *)&rec->data[rec->length];
614
615 if (offset >= fw->size) {
616 dev_dbg(codec->dev, "All transfers scheduled\n");
617 xfer->done = &done;
618 }
619
620 ret = spi_async(spi, &xfer->m);
621 if (ret != 0) {
622 dev_err(codec->dev, "Write failed: %d\n", ret);
623 goto abort;
624 }
625
626 if (wm0010->boot_failed)
627 goto abort;
628 }
629
630 wait_for_completion(&done);
631
632 spin_lock_irqsave(&wm0010->irq_lock, flags);
633 wm0010->state = WM0010_FIRMWARE;
634 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
635
636 mutex_unlock(&wm0010->lock);
637
638 release_firmware(fw);
639
640 while (!list_empty(&xfer_list)) {
641 xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer,
642 list);
643 kfree(xfer->t.rx_buf);
644 kfree(xfer->t.tx_buf);
645 list_del(&xfer->list);
646 kfree(xfer);
647 }
648
649 return 0;
650
651abort:
652 /* Put the chip back into reset */
653 wm0010_halt(codec);
654 mutex_unlock(&wm0010->lock);
655 return ret;
656err_core:
657 regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies),
658 wm0010->core_supplies);
659err:
660 return ret;
661}
662
663static int wm0010_set_bias_level(struct snd_soc_codec *codec,
664 enum snd_soc_bias_level level)
665{
666 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
667
668 switch (level) {
669 case SND_SOC_BIAS_ON:
670 if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE)
671 wm0010_boot(codec);
672 break;
673 case SND_SOC_BIAS_PREPARE:
674 break;
675 case SND_SOC_BIAS_STANDBY:
676 if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) {
677 mutex_lock(&wm0010->lock);
678 wm0010_halt(codec);
679 mutex_unlock(&wm0010->lock);
680 }
681 break;
682 case SND_SOC_BIAS_OFF:
683 break;
684 }
685
686 codec->dapm.bias_level = level;
687
688 return 0;
689}
690
691static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source,
692 int clk_id, unsigned int freq, int dir)
693{
694 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
695 unsigned int i;
696
697 wm0010->sysclk = freq;
698
699 if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) {
700 wm0010->max_spi_freq = 0;
701 } else {
702 for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++)
703 if (freq >= pll_clock_map[i].max_sysclk)
704 break;
705
706 wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed;
707 wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1;
708 }
709
710 return 0;
711}
712
713static int wm0010_probe(struct snd_soc_codec *codec);
714
715static struct snd_soc_codec_driver soc_codec_dev_wm0010 = {
716 .probe = wm0010_probe,
717 .set_bias_level = wm0010_set_bias_level,
718 .set_sysclk = wm0010_set_sysclk,
719
720 .dapm_routes = wm0010_dapm_routes,
721 .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes),
722};
723
724#define WM0010_RATES (SNDRV_PCM_RATE_48000)
725#define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\
726 SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\
727 SNDRV_PCM_FMTBIT_S32_LE)
728
729static struct snd_soc_dai_driver wm0010_dai[] = {
730 {
731 .name = "wm0010-sdi1",
732 .playback = {
733 .stream_name = "SDI1 Playback",
734 .channels_min = 1,
735 .channels_max = 2,
736 .rates = WM0010_RATES,
737 .formats = WM0010_FORMATS,
738 },
739 .capture = {
740 .stream_name = "SDI1 Capture",
741 .channels_min = 1,
742 .channels_max = 2,
743 .rates = WM0010_RATES,
744 .formats = WM0010_FORMATS,
745 },
746 },
747 {
748 .name = "wm0010-sdi2",
749 .playback = {
750 .stream_name = "SDI2 Playback",
751 .channels_min = 1,
752 .channels_max = 2,
753 .rates = WM0010_RATES,
754 .formats = WM0010_FORMATS,
755 },
756 .capture = {
757 .stream_name = "SDI2 Capture",
758 .channels_min = 1,
759 .channels_max = 2,
760 .rates = WM0010_RATES,
761 .formats = WM0010_FORMATS,
762 },
763 },
764};
765
766static irqreturn_t wm0010_irq(int irq, void *data)
767{
768 struct wm0010_priv *wm0010 = data;
769
770 switch (wm0010->state) {
771 case WM0010_POWER_OFF:
772 case WM0010_OUT_OF_RESET:
773 case WM0010_BOOTROM:
774 case WM0010_STAGE2:
775 spin_lock(&wm0010->irq_lock);
776 complete(&wm0010->boot_completion);
777 spin_unlock(&wm0010->irq_lock);
778 return IRQ_HANDLED;
779 default:
780 return IRQ_NONE;
781 }
782
783 return IRQ_NONE;
784}
785
786static int wm0010_probe(struct snd_soc_codec *codec)
787{
788 struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec);
789 struct spi_device *spi = to_spi_device(wm0010->dev);
790 unsigned long flags;
791 unsigned long gpio_flags;
792 int ret;
793 int trigger;
794 int irq;
795
796 wm0010->codec = codec;
797
798 init_completion(&wm0010->boot_completion);
799
800 wm0010->core_supplies[0].supply = "AVDD";
801 wm0010->core_supplies[1].supply = "DCVDD";
802 ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies),
803 wm0010->core_supplies);
804 if (ret != 0) {
805 dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n",
806 ret);
807 return ret;
808 }
809
810 wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD");
811 if (IS_ERR(wm0010->dbvdd)) {
812 ret = PTR_ERR(wm0010->dbvdd);
813 dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret);
814 return ret;
815 }
816
817 if (wm0010->pdata.gpio_reset) {
818 wm0010->gpio_reset = wm0010->pdata.gpio_reset;
819
820 if (wm0010->pdata.reset_active_high)
821 wm0010->gpio_reset_value = 1;
822 else
823 wm0010->gpio_reset_value = 0;
824
825 if (wm0010->gpio_reset_value)
826 gpio_flags = GPIOF_OUT_INIT_HIGH;
827 else
828 gpio_flags = GPIOF_OUT_INIT_LOW;
829
830 ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset,
831 gpio_flags, "wm0010 reset");
832 if (ret < 0) {
833 dev_err(wm0010->dev,
834 "Failed to request GPIO for DSP reset: %d\n",
835 ret);
836 return ret;
837 }
838 } else {
839 dev_err(wm0010->dev, "No reset GPIO configured\n");
840 return ret;
841 }
842
843 irq = spi->irq;
844 if (wm0010->pdata.irq_flags)
845 trigger = wm0010->pdata.irq_flags;
846 else
847 trigger = IRQF_TRIGGER_FALLING;
848 trigger |= IRQF_ONESHOT;
849
850 ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger,
851 "wm0010", wm0010);
852 if (ret)
853 dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n",
854 irq, ret);
855 wm0010->irq = irq;
856
857 if (spi->max_speed_hz)
858 wm0010->board_max_spi_speed = spi->max_speed_hz;
859 else
860 wm0010->board_max_spi_speed = 0;
861
862 spin_lock_irqsave(&wm0010->irq_lock, flags);
863 wm0010->state = WM0010_POWER_OFF;
864 spin_unlock_irqrestore(&wm0010->irq_lock, flags);
865
866 return 0;
867}
868
869static int __devinit wm0010_spi_probe(struct spi_device *spi)
870{
871 struct wm0010_priv *wm0010;
872 int ret;
873
874 wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010),
875 GFP_KERNEL);
876 if (!wm0010)
877 return -ENOMEM;
878
879 mutex_init(&wm0010->lock);
880 spin_lock_init(&wm0010->irq_lock);
881
882 spi_set_drvdata(spi, wm0010);
883 wm0010->dev = &spi->dev;
884
885 if (dev_get_platdata(&spi->dev))
886 memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev),
887 sizeof(wm0010->pdata));
888
889 ret = snd_soc_register_codec(&spi->dev,
890 &soc_codec_dev_wm0010, wm0010_dai,
891 ARRAY_SIZE(wm0010_dai));
892 if (ret < 0)
893 return ret;
894
895 return 0;
896}
897
898static int __devexit wm0010_spi_remove(struct spi_device *spi)
899{
900 struct wm0010_priv *wm0010 = spi_get_drvdata(spi);
901
902 snd_soc_unregister_codec(&spi->dev);
903
904 if (wm0010->gpio_reset) {
905 /* Remember to put chip back into reset */
906 gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value);
907 gpio_free(wm0010->gpio_reset);
908 }
909
910 if (wm0010->irq)
911 free_irq(wm0010->irq, wm0010);
912
913 return 0;
914}
915
916static struct spi_driver wm0010_spi_driver = {
917 .driver = {
918 .name = "wm0010",
919 .bus = &spi_bus_type,
920 .owner = THIS_MODULE,
921 },
922 .probe = wm0010_spi_probe,
923 .remove = __devexit_p(wm0010_spi_remove),
924};
925
926module_spi_driver(wm0010_spi_driver);
927
928MODULE_DESCRIPTION("ASoC WM0010 driver");
929MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>");
930MODULE_LICENSE("GPL");