blob: a5f57ce44665f580e1fb3e4dc7765023bedec64d [file] [log] [blame]
Mark Brown3a66d382010-02-11 13:27:19 +00001/*
2 * wm2000.c -- WM2000 ALSA Soc Audio driver
3 *
4 * Copyright 2008-2010 Wolfson Microelectronics PLC.
5 *
6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com>
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License version 2 as
10 * published by the Free Software Foundation.
11 *
12 * The download image for the WM2000 will be requested as
13 * 'wm2000_anc.bin' by default (overridable via platform data) at
14 * runtime and is expected to be in flat binary format. This is
15 * generated by Wolfson configuration tools and includes
16 * system-specific callibration information. If supplied as a
17 * sequence of ASCII-encoded hexidecimal bytes this can be converted
18 * into a flat binary with a command such as this on the command line:
19 *
20 * perl -e 'while (<>) { s/[\r\n]+// ; printf("%c", hex($_)); }'
21 * < file > wm2000_anc.bin
22 */
23
24#include <linux/module.h>
25#include <linux/moduleparam.h>
Mark Brown3a66d382010-02-11 13:27:19 +000026#include <linux/kernel.h>
27#include <linux/init.h>
28#include <linux/firmware.h>
29#include <linux/delay.h>
30#include <linux/pm.h>
31#include <linux/i2c.h>
Mark Brown8aa1fe82011-12-02 21:57:19 +000032#include <linux/regmap.h>
Mark Brown3a66d382010-02-11 13:27:19 +000033#include <linux/debugfs.h>
Tejun Heo5a0e3ad2010-03-24 17:04:11 +090034#include <linux/slab.h>
Mark Brown3a66d382010-02-11 13:27:19 +000035#include <sound/core.h>
36#include <sound/pcm.h>
37#include <sound/pcm_params.h>
38#include <sound/soc.h>
Mark Brown3a66d382010-02-11 13:27:19 +000039#include <sound/initval.h>
40#include <sound/tlv.h>
41
42#include <sound/wm2000.h>
43
44#include "wm2000.h"
45
46enum wm2000_anc_mode {
47 ANC_ACTIVE = 0,
48 ANC_BYPASS = 1,
49 ANC_STANDBY = 2,
50 ANC_OFF = 3,
51};
52
53struct wm2000_priv {
54 struct i2c_client *i2c;
Mark Brown8aa1fe82011-12-02 21:57:19 +000055 struct regmap *regmap;
Mark Brown3a66d382010-02-11 13:27:19 +000056
57 enum wm2000_anc_mode anc_mode;
58
59 unsigned int anc_active:1;
60 unsigned int anc_eng_ena:1;
61 unsigned int spk_ena:1;
62
63 unsigned int mclk_div:1;
64 unsigned int speech_clarity:1;
65
66 int anc_download_size;
67 char *anc_download;
68};
69
70static struct i2c_client *wm2000_i2c;
71
72static int wm2000_write(struct i2c_client *i2c, unsigned int reg,
73 unsigned int value)
74{
Mark Brown8aa1fe82011-12-02 21:57:19 +000075 struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
76 return regmap_write(wm2000->regmap, reg, value);
Mark Brown3a66d382010-02-11 13:27:19 +000077}
78
79static unsigned int wm2000_read(struct i2c_client *i2c, unsigned int r)
80{
Mark Brown8aa1fe82011-12-02 21:57:19 +000081 struct wm2000_priv *wm2000 = i2c_get_clientdata(i2c);
82 unsigned int val;
Mark Brown3a66d382010-02-11 13:27:19 +000083 int ret;
84
Mark Brown8aa1fe82011-12-02 21:57:19 +000085 ret = regmap_read(wm2000->regmap, r, &val);
86 if (ret < 0)
87 return -1;
Mark Brown3a66d382010-02-11 13:27:19 +000088
Mark Brown8aa1fe82011-12-02 21:57:19 +000089 return val;
Mark Brown3a66d382010-02-11 13:27:19 +000090}
91
92static void wm2000_reset(struct wm2000_priv *wm2000)
93{
94 struct i2c_client *i2c = wm2000->i2c;
95
96 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
97 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);
98 wm2000_write(i2c, WM2000_REG_ID1, 0);
99
100 wm2000->anc_mode = ANC_OFF;
101}
102
103static int wm2000_poll_bit(struct i2c_client *i2c,
104 unsigned int reg, u8 mask, int timeout)
105{
106 int val;
107
108 val = wm2000_read(i2c, reg);
109
110 while (!(val & mask) && --timeout) {
111 msleep(1);
112 val = wm2000_read(i2c, reg);
113 }
114
115 if (timeout == 0)
116 return 0;
117 else
118 return 1;
119}
120
121static int wm2000_power_up(struct i2c_client *i2c, int analogue)
122{
123 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
124 int ret, timeout;
125
126 BUG_ON(wm2000->anc_mode != ANC_OFF);
127
128 dev_dbg(&i2c->dev, "Beginning power up\n");
129
130 if (!wm2000->mclk_div) {
131 dev_dbg(&i2c->dev, "Disabling MCLK divider\n");
132 wm2000_write(i2c, WM2000_REG_SYS_CTL2,
133 WM2000_MCLK_DIV2_ENA_CLR);
134 } else {
135 dev_dbg(&i2c->dev, "Enabling MCLK divider\n");
136 wm2000_write(i2c, WM2000_REG_SYS_CTL2,
137 WM2000_MCLK_DIV2_ENA_SET);
138 }
139
140 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_CLR);
141 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_ENG_SET);
142
143 /* Wait for ANC engine to become ready */
144 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
145 WM2000_ANC_ENG_IDLE, 1)) {
146 dev_err(&i2c->dev, "ANC engine failed to reset\n");
147 return -ETIMEDOUT;
148 }
149
150 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
151 WM2000_STATUS_BOOT_COMPLETE, 1)) {
152 dev_err(&i2c->dev, "ANC engine failed to initialise\n");
153 return -ETIMEDOUT;
154 }
155
156 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
157
158 /* Open code download of the data since it is the only bulk
159 * write we do. */
160 dev_dbg(&i2c->dev, "Downloading %d bytes\n",
161 wm2000->anc_download_size - 2);
162
163 ret = i2c_master_send(i2c, wm2000->anc_download,
164 wm2000->anc_download_size);
165 if (ret < 0) {
166 dev_err(&i2c->dev, "i2c_transfer() failed: %d\n", ret);
167 return ret;
168 }
169 if (ret != wm2000->anc_download_size) {
170 dev_err(&i2c->dev, "i2c_transfer() failed, %d != %d\n",
171 ret, wm2000->anc_download_size);
172 return -EIO;
173 }
174
175 dev_dbg(&i2c->dev, "Download complete\n");
176
177 if (analogue) {
178 timeout = 248;
179 wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4);
180
181 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
182 WM2000_MODE_ANA_SEQ_INCLUDE |
183 WM2000_MODE_MOUSE_ENABLE |
184 WM2000_MODE_THERMAL_ENABLE);
185 } else {
186 timeout = 10;
187
188 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
189 WM2000_MODE_MOUSE_ENABLE |
190 WM2000_MODE_THERMAL_ENABLE);
191 }
192
193 ret = wm2000_read(i2c, WM2000_REG_SPEECH_CLARITY);
194 if (wm2000->speech_clarity)
195 ret &= ~WM2000_SPEECH_CLARITY;
196 else
197 ret |= WM2000_SPEECH_CLARITY;
198 wm2000_write(i2c, WM2000_REG_SPEECH_CLARITY, ret);
199
200 wm2000_write(i2c, WM2000_REG_SYS_START0, 0x33);
201 wm2000_write(i2c, WM2000_REG_SYS_START1, 0x02);
202
203 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);
204
205 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
206 WM2000_STATUS_MOUSE_ACTIVE, timeout)) {
207 dev_err(&i2c->dev, "Timed out waiting for device after %dms\n",
208 timeout * 10);
209 return -ETIMEDOUT;
210 }
211
212 dev_dbg(&i2c->dev, "ANC active\n");
213 if (analogue)
214 dev_dbg(&i2c->dev, "Analogue active\n");
215 wm2000->anc_mode = ANC_ACTIVE;
216
217 return 0;
218}
219
220static int wm2000_power_down(struct i2c_client *i2c, int analogue)
221{
222 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
223 int timeout;
224
225 if (analogue) {
226 timeout = 248;
227 wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4);
228 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
229 WM2000_MODE_ANA_SEQ_INCLUDE |
230 WM2000_MODE_POWER_DOWN);
231 } else {
232 timeout = 10;
233 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
234 WM2000_MODE_POWER_DOWN);
235 }
236
237 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
238 WM2000_STATUS_POWER_DOWN_COMPLETE, timeout)) {
239 dev_err(&i2c->dev, "Timeout waiting for ANC power down\n");
240 return -ETIMEDOUT;
241 }
242
243 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
244 WM2000_ANC_ENG_IDLE, 1)) {
245 dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n");
246 return -ETIMEDOUT;
247 }
248
249 dev_dbg(&i2c->dev, "powered off\n");
250 wm2000->anc_mode = ANC_OFF;
251
252 return 0;
253}
254
255static int wm2000_enter_bypass(struct i2c_client *i2c, int analogue)
256{
257 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
258
259 BUG_ON(wm2000->anc_mode != ANC_ACTIVE);
260
261 if (analogue) {
262 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
263 WM2000_MODE_ANA_SEQ_INCLUDE |
264 WM2000_MODE_THERMAL_ENABLE |
265 WM2000_MODE_BYPASS_ENTRY);
266 } else {
267 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
268 WM2000_MODE_THERMAL_ENABLE |
269 WM2000_MODE_BYPASS_ENTRY);
270 }
271
272 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
273 WM2000_STATUS_ANC_DISABLED, 10)) {
274 dev_err(&i2c->dev, "Timeout waiting for ANC disable\n");
275 return -ETIMEDOUT;
276 }
277
278 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT,
279 WM2000_ANC_ENG_IDLE, 1)) {
280 dev_err(&i2c->dev, "Timeout waiting for ANC engine idle\n");
281 return -ETIMEDOUT;
282 }
283
284 wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
285 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);
286
287 wm2000->anc_mode = ANC_BYPASS;
288 dev_dbg(&i2c->dev, "bypass enabled\n");
289
290 return 0;
291}
292
293static int wm2000_exit_bypass(struct i2c_client *i2c, int analogue)
294{
295 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
296
297 BUG_ON(wm2000->anc_mode != ANC_BYPASS);
298
299 wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);
300
301 if (analogue) {
302 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
303 WM2000_MODE_ANA_SEQ_INCLUDE |
304 WM2000_MODE_MOUSE_ENABLE |
305 WM2000_MODE_THERMAL_ENABLE);
306 } else {
307 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
308 WM2000_MODE_MOUSE_ENABLE |
309 WM2000_MODE_THERMAL_ENABLE);
310 }
311
312 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
313 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);
314
315 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
316 WM2000_STATUS_MOUSE_ACTIVE, 10)) {
317 dev_err(&i2c->dev, "Timed out waiting for MOUSE\n");
318 return -ETIMEDOUT;
319 }
320
321 wm2000->anc_mode = ANC_ACTIVE;
322 dev_dbg(&i2c->dev, "MOUSE active\n");
323
324 return 0;
325}
326
327static int wm2000_enter_standby(struct i2c_client *i2c, int analogue)
328{
329 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
330 int timeout;
331
332 BUG_ON(wm2000->anc_mode != ANC_ACTIVE);
333
334 if (analogue) {
335 timeout = 248;
336 wm2000_write(i2c, WM2000_REG_ANA_VMID_PD_TIME, timeout / 4);
337
338 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
339 WM2000_MODE_ANA_SEQ_INCLUDE |
340 WM2000_MODE_THERMAL_ENABLE |
341 WM2000_MODE_STANDBY_ENTRY);
342 } else {
343 timeout = 10;
344
345 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
346 WM2000_MODE_THERMAL_ENABLE |
347 WM2000_MODE_STANDBY_ENTRY);
348 }
349
350 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
351 WM2000_STATUS_ANC_DISABLED, timeout)) {
352 dev_err(&i2c->dev,
353 "Timed out waiting for ANC disable after 1ms\n");
354 return -ETIMEDOUT;
355 }
356
357 if (!wm2000_poll_bit(i2c, WM2000_REG_ANC_STAT, WM2000_ANC_ENG_IDLE,
358 1)) {
359 dev_err(&i2c->dev,
360 "Timed out waiting for standby after %dms\n",
361 timeout * 10);
362 return -ETIMEDOUT;
363 }
364
365 wm2000_write(i2c, WM2000_REG_SYS_CTL1, WM2000_SYS_STBY);
366 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_CLR);
367
368 wm2000->anc_mode = ANC_STANDBY;
369 dev_dbg(&i2c->dev, "standby\n");
370 if (analogue)
371 dev_dbg(&i2c->dev, "Analogue disabled\n");
372
373 return 0;
374}
375
376static int wm2000_exit_standby(struct i2c_client *i2c, int analogue)
377{
378 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
379 int timeout;
380
381 BUG_ON(wm2000->anc_mode != ANC_STANDBY);
382
383 wm2000_write(i2c, WM2000_REG_SYS_CTL1, 0);
384
385 if (analogue) {
386 timeout = 248;
387 wm2000_write(i2c, WM2000_REG_ANA_VMID_PU_TIME, timeout / 4);
388
389 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
390 WM2000_MODE_ANA_SEQ_INCLUDE |
391 WM2000_MODE_THERMAL_ENABLE |
392 WM2000_MODE_MOUSE_ENABLE);
393 } else {
394 timeout = 10;
395
396 wm2000_write(i2c, WM2000_REG_SYS_MODE_CNTRL,
397 WM2000_MODE_THERMAL_ENABLE |
398 WM2000_MODE_MOUSE_ENABLE);
399 }
400
401 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_RAM_SET);
402 wm2000_write(i2c, WM2000_REG_SYS_CTL2, WM2000_ANC_INT_N_CLR);
403
404 if (!wm2000_poll_bit(i2c, WM2000_REG_SYS_STATUS,
405 WM2000_STATUS_MOUSE_ACTIVE, timeout)) {
406 dev_err(&i2c->dev, "Timed out waiting for MOUSE after %dms\n",
407 timeout * 10);
408 return -ETIMEDOUT;
409 }
410
411 wm2000->anc_mode = ANC_ACTIVE;
412 dev_dbg(&i2c->dev, "MOUSE active\n");
413 if (analogue)
414 dev_dbg(&i2c->dev, "Analogue enabled\n");
415
416 return 0;
417}
418
419typedef int (*wm2000_mode_fn)(struct i2c_client *i2c, int analogue);
420
421static struct {
422 enum wm2000_anc_mode source;
423 enum wm2000_anc_mode dest;
424 int analogue;
425 wm2000_mode_fn step[2];
426} anc_transitions[] = {
427 {
428 .source = ANC_OFF,
429 .dest = ANC_ACTIVE,
430 .analogue = 1,
431 .step = {
432 wm2000_power_up,
433 },
434 },
435 {
436 .source = ANC_OFF,
437 .dest = ANC_STANDBY,
438 .step = {
439 wm2000_power_up,
440 wm2000_enter_standby,
441 },
442 },
443 {
444 .source = ANC_OFF,
445 .dest = ANC_BYPASS,
446 .analogue = 1,
447 .step = {
448 wm2000_power_up,
449 wm2000_enter_bypass,
450 },
451 },
452 {
453 .source = ANC_ACTIVE,
454 .dest = ANC_BYPASS,
455 .analogue = 1,
456 .step = {
457 wm2000_enter_bypass,
458 },
459 },
460 {
461 .source = ANC_ACTIVE,
462 .dest = ANC_STANDBY,
463 .analogue = 1,
464 .step = {
465 wm2000_enter_standby,
466 },
467 },
468 {
469 .source = ANC_ACTIVE,
470 .dest = ANC_OFF,
471 .analogue = 1,
472 .step = {
473 wm2000_power_down,
474 },
475 },
476 {
477 .source = ANC_BYPASS,
478 .dest = ANC_ACTIVE,
479 .analogue = 1,
480 .step = {
481 wm2000_exit_bypass,
482 },
483 },
484 {
485 .source = ANC_BYPASS,
486 .dest = ANC_STANDBY,
487 .analogue = 1,
488 .step = {
489 wm2000_exit_bypass,
490 wm2000_enter_standby,
491 },
492 },
493 {
494 .source = ANC_BYPASS,
495 .dest = ANC_OFF,
496 .step = {
497 wm2000_exit_bypass,
498 wm2000_power_down,
499 },
500 },
501 {
502 .source = ANC_STANDBY,
503 .dest = ANC_ACTIVE,
504 .analogue = 1,
505 .step = {
506 wm2000_exit_standby,
507 },
508 },
509 {
510 .source = ANC_STANDBY,
511 .dest = ANC_BYPASS,
512 .analogue = 1,
513 .step = {
514 wm2000_exit_standby,
515 wm2000_enter_bypass,
516 },
517 },
518 {
519 .source = ANC_STANDBY,
520 .dest = ANC_OFF,
521 .step = {
522 wm2000_exit_standby,
523 wm2000_power_down,
524 },
525 },
526};
527
528static int wm2000_anc_transition(struct wm2000_priv *wm2000,
529 enum wm2000_anc_mode mode)
530{
531 struct i2c_client *i2c = wm2000->i2c;
532 int i, j;
533 int ret;
534
535 if (wm2000->anc_mode == mode)
536 return 0;
537
538 for (i = 0; i < ARRAY_SIZE(anc_transitions); i++)
539 if (anc_transitions[i].source == wm2000->anc_mode &&
540 anc_transitions[i].dest == mode)
541 break;
542 if (i == ARRAY_SIZE(anc_transitions)) {
543 dev_err(&i2c->dev, "No transition for %d->%d\n",
544 wm2000->anc_mode, mode);
545 return -EINVAL;
546 }
547
548 for (j = 0; j < ARRAY_SIZE(anc_transitions[j].step); j++) {
549 if (!anc_transitions[i].step[j])
550 break;
551 ret = anc_transitions[i].step[j](i2c,
552 anc_transitions[i].analogue);
553 if (ret != 0)
554 return ret;
555 }
556
557 return 0;
558}
559
560static int wm2000_anc_set_mode(struct wm2000_priv *wm2000)
561{
562 struct i2c_client *i2c = wm2000->i2c;
563 enum wm2000_anc_mode mode;
564
565 if (wm2000->anc_eng_ena && wm2000->spk_ena)
566 if (wm2000->anc_active)
567 mode = ANC_ACTIVE;
568 else
569 mode = ANC_BYPASS;
570 else
571 mode = ANC_STANDBY;
572
573 dev_dbg(&i2c->dev, "Set mode %d (enabled %d, mute %d, active %d)\n",
574 mode, wm2000->anc_eng_ena, !wm2000->spk_ena,
575 wm2000->anc_active);
576
577 return wm2000_anc_transition(wm2000, mode);
578}
579
580static int wm2000_anc_mode_get(struct snd_kcontrol *kcontrol,
581 struct snd_ctl_elem_value *ucontrol)
582{
583 struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
584
585 ucontrol->value.enumerated.item[0] = wm2000->anc_active;
586
587 return 0;
588}
589
590static int wm2000_anc_mode_put(struct snd_kcontrol *kcontrol,
591 struct snd_ctl_elem_value *ucontrol)
592{
593 struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
594 int anc_active = ucontrol->value.enumerated.item[0];
595
596 if (anc_active > 1)
597 return -EINVAL;
598
599 wm2000->anc_active = anc_active;
600
601 return wm2000_anc_set_mode(wm2000);
602}
603
604static int wm2000_speaker_get(struct snd_kcontrol *kcontrol,
605 struct snd_ctl_elem_value *ucontrol)
606{
607 struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
608
609 ucontrol->value.enumerated.item[0] = wm2000->spk_ena;
610
611 return 0;
612}
613
614static int wm2000_speaker_put(struct snd_kcontrol *kcontrol,
615 struct snd_ctl_elem_value *ucontrol)
616{
617 struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
618 int val = ucontrol->value.enumerated.item[0];
619
620 if (val > 1)
621 return -EINVAL;
622
623 wm2000->spk_ena = val;
624
625 return wm2000_anc_set_mode(wm2000);
626}
627
628static const struct snd_kcontrol_new wm2000_controls[] = {
629 SOC_SINGLE_BOOL_EXT("WM2000 ANC Switch", 0,
630 wm2000_anc_mode_get,
631 wm2000_anc_mode_put),
632 SOC_SINGLE_BOOL_EXT("WM2000 Switch", 0,
633 wm2000_speaker_get,
634 wm2000_speaker_put),
635};
636
637static int wm2000_anc_power_event(struct snd_soc_dapm_widget *w,
638 struct snd_kcontrol *kcontrol, int event)
639{
640 struct wm2000_priv *wm2000 = dev_get_drvdata(&wm2000_i2c->dev);
641
642 if (SND_SOC_DAPM_EVENT_ON(event))
643 wm2000->anc_eng_ena = 1;
644
645 if (SND_SOC_DAPM_EVENT_OFF(event))
646 wm2000->anc_eng_ena = 0;
647
648 return wm2000_anc_set_mode(wm2000);
649}
650
651static const struct snd_soc_dapm_widget wm2000_dapm_widgets[] = {
652/* Externally visible pins */
653SND_SOC_DAPM_OUTPUT("WM2000 SPKN"),
654SND_SOC_DAPM_OUTPUT("WM2000 SPKP"),
655
656SND_SOC_DAPM_INPUT("WM2000 LINN"),
657SND_SOC_DAPM_INPUT("WM2000 LINP"),
658
659SND_SOC_DAPM_PGA_E("ANC Engine", SND_SOC_NOPM, 0, 0, NULL, 0,
660 wm2000_anc_power_event,
661 SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD),
662};
663
664/* Target, Path, Source */
665static const struct snd_soc_dapm_route audio_map[] = {
666 { "WM2000 SPKN", NULL, "ANC Engine" },
667 { "WM2000 SPKP", NULL, "ANC Engine" },
668 { "ANC Engine", NULL, "WM2000 LINN" },
669 { "ANC Engine", NULL, "WM2000 LINP" },
670};
671
672/* Called from the machine driver */
673int wm2000_add_controls(struct snd_soc_codec *codec)
674{
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200675 struct snd_soc_dapm_context *dapm = &codec->dapm;
Mark Brown3a66d382010-02-11 13:27:19 +0000676 int ret;
677
678 if (!wm2000_i2c) {
679 pr_err("WM2000 not yet probed\n");
680 return -ENODEV;
681 }
682
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200683 ret = snd_soc_dapm_new_controls(dapm, wm2000_dapm_widgets,
Mark Brown3a66d382010-02-11 13:27:19 +0000684 ARRAY_SIZE(wm2000_dapm_widgets));
685 if (ret < 0)
686 return ret;
687
Liam Girdwoodce6120c2010-11-05 15:53:46 +0200688 ret = snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map));
Mark Brown3a66d382010-02-11 13:27:19 +0000689 if (ret < 0)
690 return ret;
691
692 return snd_soc_add_controls(codec, wm2000_controls,
693 ARRAY_SIZE(wm2000_controls));
694}
695EXPORT_SYMBOL_GPL(wm2000_add_controls);
696
Mark Brown8aa1fe82011-12-02 21:57:19 +0000697static const struct regmap_config wm2000_regmap = {
698 .reg_bits = 8,
699 .val_bits = 8,
700};
701
Mark Brown3a66d382010-02-11 13:27:19 +0000702static int __devinit wm2000_i2c_probe(struct i2c_client *i2c,
703 const struct i2c_device_id *i2c_id)
704{
705 struct wm2000_priv *wm2000;
706 struct wm2000_platform_data *pdata;
707 const char *filename;
708 const struct firmware *fw;
709 int reg, ret;
710 u16 id;
711
712 if (wm2000_i2c) {
713 dev_err(&i2c->dev, "Another WM2000 is already registered\n");
714 return -EINVAL;
715 }
716
Mark Brownb03e96e2011-12-02 21:28:31 +0000717 wm2000 = devm_kzalloc(&i2c->dev, sizeof(struct wm2000_priv),
718 GFP_KERNEL);
Mark Brown3a66d382010-02-11 13:27:19 +0000719 if (wm2000 == NULL) {
720 dev_err(&i2c->dev, "Unable to allocate private data\n");
721 return -ENOMEM;
722 }
723
Mark Brown8aa1fe82011-12-02 21:57:19 +0000724 dev_set_drvdata(&i2c->dev, wm2000);
725
726 wm2000->regmap = regmap_init_i2c(i2c, &wm2000_regmap);
727 if (IS_ERR(wm2000->regmap)) {
728 ret = PTR_ERR(wm2000->regmap);
729 dev_err(&i2c->dev, "Failed to allocate register map: %d\n",
730 ret);
731 goto err;
732 }
733
Mark Brown3a66d382010-02-11 13:27:19 +0000734 /* Verify that this is a WM2000 */
735 reg = wm2000_read(i2c, WM2000_REG_ID1);
736 id = reg << 8;
737 reg = wm2000_read(i2c, WM2000_REG_ID2);
738 id |= reg & 0xff;
739
740 if (id != 0x2000) {
741 dev_err(&i2c->dev, "Device is not a WM2000 - ID %x\n", id);
742 ret = -ENODEV;
Mark Brown8aa1fe82011-12-02 21:57:19 +0000743 goto err_regmap;
Mark Brown3a66d382010-02-11 13:27:19 +0000744 }
745
746 reg = wm2000_read(i2c, WM2000_REG_REVISON);
747 dev_info(&i2c->dev, "revision %c\n", reg + 'A');
748
749 filename = "wm2000_anc.bin";
750 pdata = dev_get_platdata(&i2c->dev);
751 if (pdata) {
752 wm2000->mclk_div = pdata->mclkdiv2;
753 wm2000->speech_clarity = !pdata->speech_enh_disable;
754
755 if (pdata->download_file)
756 filename = pdata->download_file;
757 }
758
759 ret = request_firmware(&fw, filename, &i2c->dev);
760 if (ret != 0) {
761 dev_err(&i2c->dev, "Failed to acquire ANC data: %d\n", ret);
Mark Brown8aa1fe82011-12-02 21:57:19 +0000762 goto err_regmap;
Mark Brown3a66d382010-02-11 13:27:19 +0000763 }
764
765 /* Pre-cook the concatenation of the register address onto the image */
766 wm2000->anc_download_size = fw->size + 2;
Mark Brownb03e96e2011-12-02 21:28:31 +0000767 wm2000->anc_download = devm_kzalloc(&i2c->dev,
768 wm2000->anc_download_size,
769 GFP_KERNEL);
Mark Brown3a66d382010-02-11 13:27:19 +0000770 if (wm2000->anc_download == NULL) {
771 dev_err(&i2c->dev, "Out of memory\n");
772 ret = -ENOMEM;
773 goto err_fw;
774 }
775
776 wm2000->anc_download[0] = 0x80;
777 wm2000->anc_download[1] = 0x00;
778 memcpy(wm2000->anc_download + 2, fw->data, fw->size);
779
780 release_firmware(fw);
781
Mark Brown3a66d382010-02-11 13:27:19 +0000782 wm2000->anc_eng_ena = 1;
Mark Browne71fa372010-06-15 15:14:00 +0100783 wm2000->anc_active = 1;
784 wm2000->spk_ena = 1;
Mark Brown3a66d382010-02-11 13:27:19 +0000785 wm2000->i2c = i2c;
786
787 wm2000_reset(wm2000);
788
789 /* This will trigger a transition to standby mode by default */
790 wm2000_anc_set_mode(wm2000);
791
792 wm2000_i2c = i2c;
793
794 return 0;
795
796err_fw:
797 release_firmware(fw);
Mark Brown8aa1fe82011-12-02 21:57:19 +0000798err_regmap:
799 regmap_exit(wm2000->regmap);
Mark Brown3a66d382010-02-11 13:27:19 +0000800err:
Mark Brown3a66d382010-02-11 13:27:19 +0000801 return ret;
802}
803
804static __devexit int wm2000_i2c_remove(struct i2c_client *i2c)
805{
806 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
807
808 wm2000_anc_transition(wm2000, ANC_OFF);
809
Mark Brown8aa1fe82011-12-02 21:57:19 +0000810 regmap_exit(wm2000->regmap);
811
Mark Brown3a66d382010-02-11 13:27:19 +0000812 wm2000_i2c = NULL;
Mark Brown3a66d382010-02-11 13:27:19 +0000813
814 return 0;
815}
816
817static void wm2000_i2c_shutdown(struct i2c_client *i2c)
818{
819 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
820
821 wm2000_anc_transition(wm2000, ANC_OFF);
822}
823
824#ifdef CONFIG_PM
Mark Brownb3111a92011-02-25 12:25:18 +0000825static int wm2000_i2c_suspend(struct device *dev)
Mark Brown3a66d382010-02-11 13:27:19 +0000826{
Mark Brownb3111a92011-02-25 12:25:18 +0000827 struct i2c_client *i2c = to_i2c_client(dev);
Mark Brown3a66d382010-02-11 13:27:19 +0000828 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
829
830 return wm2000_anc_transition(wm2000, ANC_OFF);
831}
832
Mark Brownb3111a92011-02-25 12:25:18 +0000833static int wm2000_i2c_resume(struct device *dev)
Mark Brown3a66d382010-02-11 13:27:19 +0000834{
Mark Brownb3111a92011-02-25 12:25:18 +0000835 struct i2c_client *i2c = to_i2c_client(dev);
Mark Brown3a66d382010-02-11 13:27:19 +0000836 struct wm2000_priv *wm2000 = dev_get_drvdata(&i2c->dev);
837
838 return wm2000_anc_set_mode(wm2000);
839}
Mark Brown3a66d382010-02-11 13:27:19 +0000840#endif
841
Mark Brownb3111a92011-02-25 12:25:18 +0000842static SIMPLE_DEV_PM_OPS(wm2000_pm, wm2000_i2c_suspend, wm2000_i2c_resume);
843
Mark Brown3a66d382010-02-11 13:27:19 +0000844static const struct i2c_device_id wm2000_i2c_id[] = {
845 { "wm2000", 0 },
846 { }
847};
848MODULE_DEVICE_TABLE(i2c, wm2000_i2c_id);
849
850static struct i2c_driver wm2000_i2c_driver = {
851 .driver = {
852 .name = "wm2000",
853 .owner = THIS_MODULE,
Mark Brownb3111a92011-02-25 12:25:18 +0000854 .pm = &wm2000_pm,
Mark Brown3a66d382010-02-11 13:27:19 +0000855 },
856 .probe = wm2000_i2c_probe,
857 .remove = __devexit_p(wm2000_i2c_remove),
Mark Brown3a66d382010-02-11 13:27:19 +0000858 .shutdown = wm2000_i2c_shutdown,
859 .id_table = wm2000_i2c_id,
860};
861
862static int __init wm2000_init(void)
863{
864 return i2c_add_driver(&wm2000_i2c_driver);
865}
866module_init(wm2000_init);
867
868static void __exit wm2000_exit(void)
869{
870 i2c_del_driver(&wm2000_i2c_driver);
871}
872module_exit(wm2000_exit);
873
874MODULE_DESCRIPTION("ASoC WM2000 driver");
875MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>");
876MODULE_LICENSE("GPL");