diff options
Diffstat (limited to 'sound/soc/codecs/wm8960.c')
-rw-r--r-- | sound/soc/codecs/wm8960.c | 216 |
1 files changed, 181 insertions, 35 deletions
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index d07bcc1e1c60..7233cc68435a 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -15,6 +15,7 @@ | |||
15 | #include <linux/pm.h> | 15 | #include <linux/pm.h> |
16 | #include <linux/i2c.h> | 16 | #include <linux/i2c.h> |
17 | #include <linux/platform_device.h> | 17 | #include <linux/platform_device.h> |
18 | #include <linux/slab.h> | ||
18 | #include <sound/core.h> | 19 | #include <sound/core.h> |
19 | #include <sound/pcm.h> | 20 | #include <sound/pcm.h> |
20 | #include <sound/pcm_params.h> | 21 | #include <sound/pcm_params.h> |
@@ -22,6 +23,7 @@ | |||
22 | #include <sound/soc-dapm.h> | 23 | #include <sound/soc-dapm.h> |
23 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
24 | #include <sound/tlv.h> | 25 | #include <sound/tlv.h> |
26 | #include <sound/wm8960.h> | ||
25 | 27 | ||
26 | #include "wm8960.h" | 28 | #include "wm8960.h" |
27 | 29 | ||
@@ -30,8 +32,14 @@ | |||
30 | struct snd_soc_codec_device soc_codec_dev_wm8960; | 32 | struct snd_soc_codec_device soc_codec_dev_wm8960; |
31 | 33 | ||
32 | /* R25 - Power 1 */ | 34 | /* R25 - Power 1 */ |
35 | #define WM8960_VMID_MASK 0x180 | ||
33 | #define WM8960_VREF 0x40 | 36 | #define WM8960_VREF 0x40 |
34 | 37 | ||
38 | /* R26 - Power 2 */ | ||
39 | #define WM8960_PWR2_LOUT1 0x40 | ||
40 | #define WM8960_PWR2_ROUT1 0x20 | ||
41 | #define WM8960_PWR2_OUT3 0x02 | ||
42 | |||
35 | /* R28 - Anti-pop 1 */ | 43 | /* R28 - Anti-pop 1 */ |
36 | #define WM8960_POBCTRL 0x80 | 44 | #define WM8960_POBCTRL 0x80 |
37 | #define WM8960_BUFDCOPEN 0x10 | 45 | #define WM8960_BUFDCOPEN 0x10 |
@@ -41,6 +49,7 @@ struct snd_soc_codec_device soc_codec_dev_wm8960; | |||
41 | 49 | ||
42 | /* R29 - Anti-pop 2 */ | 50 | /* R29 - Anti-pop 2 */ |
43 | #define WM8960_DISOP 0x40 | 51 | #define WM8960_DISOP 0x40 |
52 | #define WM8960_DRES_MASK 0x30 | ||
44 | 53 | ||
45 | /* | 54 | /* |
46 | * wm8960 register cache | 55 | * wm8960 register cache |
@@ -67,6 +76,9 @@ static const u16 wm8960_reg[WM8960_CACHEREGNUM] = { | |||
67 | struct wm8960_priv { | 76 | struct wm8960_priv { |
68 | u16 reg_cache[WM8960_CACHEREGNUM]; | 77 | u16 reg_cache[WM8960_CACHEREGNUM]; |
69 | struct snd_soc_codec codec; | 78 | struct snd_soc_codec codec; |
79 | struct snd_soc_dapm_widget *lout1; | ||
80 | struct snd_soc_dapm_widget *rout1; | ||
81 | struct snd_soc_dapm_widget *out3; | ||
70 | }; | 82 | }; |
71 | 83 | ||
72 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) | 84 | #define wm8960_reset(c) snd_soc_write(c, WM8960_RESET, 0) |
@@ -225,10 +237,6 @@ SND_SOC_DAPM_MIXER("Right Output Mixer", WM8960_POWER3, 2, 0, | |||
225 | &wm8960_routput_mixer[0], | 237 | &wm8960_routput_mixer[0], |
226 | ARRAY_SIZE(wm8960_routput_mixer)), | 238 | ARRAY_SIZE(wm8960_routput_mixer)), |
227 | 239 | ||
228 | SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, | ||
229 | &wm8960_mono_out[0], | ||
230 | ARRAY_SIZE(wm8960_mono_out)), | ||
231 | |||
232 | SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), | 240 | SND_SOC_DAPM_PGA("LOUT1 PGA", WM8960_POWER2, 6, 0, NULL, 0), |
233 | SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), | 241 | SND_SOC_DAPM_PGA("ROUT1 PGA", WM8960_POWER2, 5, 0, NULL, 0), |
234 | 242 | ||
@@ -247,6 +255,17 @@ SND_SOC_DAPM_OUTPUT("SPK_RN"), | |||
247 | SND_SOC_DAPM_OUTPUT("OUT3"), | 255 | SND_SOC_DAPM_OUTPUT("OUT3"), |
248 | }; | 256 | }; |
249 | 257 | ||
258 | static const struct snd_soc_dapm_widget wm8960_dapm_widgets_out3[] = { | ||
259 | SND_SOC_DAPM_MIXER("Mono Output Mixer", WM8960_POWER2, 1, 0, | ||
260 | &wm8960_mono_out[0], | ||
261 | ARRAY_SIZE(wm8960_mono_out)), | ||
262 | }; | ||
263 | |||
264 | /* Represent OUT3 as a PGA so that it gets turned on with LOUT1/ROUT1 */ | ||
265 | static const struct snd_soc_dapm_widget wm8960_dapm_widgets_capless[] = { | ||
266 | SND_SOC_DAPM_PGA("OUT3 VMID", WM8960_POWER2, 1, 0, NULL, 0), | ||
267 | }; | ||
268 | |||
250 | static const struct snd_soc_dapm_route audio_paths[] = { | 269 | static const struct snd_soc_dapm_route audio_paths[] = { |
251 | { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, | 270 | { "Left Boost Mixer", "LINPUT1 Switch", "LINPUT1" }, |
252 | { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, | 271 | { "Left Boost Mixer", "LINPUT2 Switch", "LINPUT2" }, |
@@ -277,9 +296,6 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
277 | { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , | 296 | { "Right Output Mixer", "Boost Bypass Switch", "Right Boost Mixer" } , |
278 | { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, | 297 | { "Right Output Mixer", "PCM Playback Switch", "Right DAC" }, |
279 | 298 | ||
280 | { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, | ||
281 | { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, | ||
282 | |||
283 | { "LOUT1 PGA", NULL, "Left Output Mixer" }, | 299 | { "LOUT1 PGA", NULL, "Left Output Mixer" }, |
284 | { "ROUT1 PGA", NULL, "Right Output Mixer" }, | 300 | { "ROUT1 PGA", NULL, "Right Output Mixer" }, |
285 | 301 | ||
@@ -296,17 +312,65 @@ static const struct snd_soc_dapm_route audio_paths[] = { | |||
296 | { "SPK_LP", NULL, "Left Speaker Output" }, | 312 | { "SPK_LP", NULL, "Left Speaker Output" }, |
297 | { "SPK_RN", NULL, "Right Speaker Output" }, | 313 | { "SPK_RN", NULL, "Right Speaker Output" }, |
298 | { "SPK_RP", NULL, "Right Speaker Output" }, | 314 | { "SPK_RP", NULL, "Right Speaker Output" }, |
315 | }; | ||
316 | |||
317 | static const struct snd_soc_dapm_route audio_paths_out3[] = { | ||
318 | { "Mono Output Mixer", "Left Switch", "Left Output Mixer" }, | ||
319 | { "Mono Output Mixer", "Right Switch", "Right Output Mixer" }, | ||
299 | 320 | ||
300 | { "OUT3", NULL, "Mono Output Mixer", } | 321 | { "OUT3", NULL, "Mono Output Mixer", } |
301 | }; | 322 | }; |
302 | 323 | ||
324 | static const struct snd_soc_dapm_route audio_paths_capless[] = { | ||
325 | { "HP_L", NULL, "OUT3 VMID" }, | ||
326 | { "HP_R", NULL, "OUT3 VMID" }, | ||
327 | |||
328 | { "OUT3 VMID", NULL, "Left Output Mixer" }, | ||
329 | { "OUT3 VMID", NULL, "Right Output Mixer" }, | ||
330 | }; | ||
331 | |||
303 | static int wm8960_add_widgets(struct snd_soc_codec *codec) | 332 | static int wm8960_add_widgets(struct snd_soc_codec *codec) |
304 | { | 333 | { |
334 | struct wm8960_data *pdata = codec->dev->platform_data; | ||
335 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
336 | struct snd_soc_dapm_widget *w; | ||
337 | |||
305 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, | 338 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets, |
306 | ARRAY_SIZE(wm8960_dapm_widgets)); | 339 | ARRAY_SIZE(wm8960_dapm_widgets)); |
307 | 340 | ||
308 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); | 341 | snd_soc_dapm_add_routes(codec, audio_paths, ARRAY_SIZE(audio_paths)); |
309 | 342 | ||
343 | /* In capless mode OUT3 is used to provide VMID for the | ||
344 | * headphone outputs, otherwise it is used as a mono mixer. | ||
345 | */ | ||
346 | if (pdata && pdata->capless) { | ||
347 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_capless, | ||
348 | ARRAY_SIZE(wm8960_dapm_widgets_capless)); | ||
349 | |||
350 | snd_soc_dapm_add_routes(codec, audio_paths_capless, | ||
351 | ARRAY_SIZE(audio_paths_capless)); | ||
352 | } else { | ||
353 | snd_soc_dapm_new_controls(codec, wm8960_dapm_widgets_out3, | ||
354 | ARRAY_SIZE(wm8960_dapm_widgets_out3)); | ||
355 | |||
356 | snd_soc_dapm_add_routes(codec, audio_paths_out3, | ||
357 | ARRAY_SIZE(audio_paths_out3)); | ||
358 | } | ||
359 | |||
360 | /* We need to power up the headphone output stage out of | ||
361 | * sequence for capless mode. To save scanning the widget | ||
362 | * list each time to find the desired power state do so now | ||
363 | * and save the result. | ||
364 | */ | ||
365 | list_for_each_entry(w, &codec->dapm_widgets, list) { | ||
366 | if (strcmp(w->name, "LOUT1 PGA") == 0) | ||
367 | wm8960->lout1 = w; | ||
368 | if (strcmp(w->name, "ROUT1 PGA") == 0) | ||
369 | wm8960->rout1 = w; | ||
370 | if (strcmp(w->name, "OUT3 VMID") == 0) | ||
371 | wm8960->out3 = w; | ||
372 | } | ||
373 | |||
310 | return 0; | 374 | return 0; |
311 | } | 375 | } |
312 | 376 | ||
@@ -407,10 +471,9 @@ static int wm8960_mute(struct snd_soc_dai *dai, int mute) | |||
407 | return 0; | 471 | return 0; |
408 | } | 472 | } |
409 | 473 | ||
410 | static int wm8960_set_bias_level(struct snd_soc_codec *codec, | 474 | static int wm8960_set_bias_level_out3(struct snd_soc_codec *codec, |
411 | enum snd_soc_bias_level level) | 475 | enum snd_soc_bias_level level) |
412 | { | 476 | { |
413 | struct wm8960_data *pdata = codec->dev->platform_data; | ||
414 | u16 reg; | 477 | u16 reg; |
415 | 478 | ||
416 | switch (level) { | 479 | switch (level) { |
@@ -429,18 +492,8 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
429 | if (codec->bias_level == SND_SOC_BIAS_OFF) { | 492 | if (codec->bias_level == SND_SOC_BIAS_OFF) { |
430 | /* Enable anti-pop features */ | 493 | /* Enable anti-pop features */ |
431 | snd_soc_write(codec, WM8960_APOP1, | 494 | snd_soc_write(codec, WM8960_APOP1, |
432 | WM8960_POBCTRL | WM8960_SOFT_ST | | 495 | WM8960_POBCTRL | WM8960_SOFT_ST | |
433 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); | 496 | WM8960_BUFDCOPEN | WM8960_BUFIOEN); |
434 | |||
435 | /* Discharge HP output */ | ||
436 | reg = WM8960_DISOP; | ||
437 | if (pdata) | ||
438 | reg |= pdata->dres << 4; | ||
439 | snd_soc_write(codec, WM8960_APOP2, reg); | ||
440 | |||
441 | msleep(400); | ||
442 | |||
443 | snd_soc_write(codec, WM8960_APOP2, 0); | ||
444 | 497 | ||
445 | /* Enable & ramp VMID at 2x50k */ | 498 | /* Enable & ramp VMID at 2x50k */ |
446 | reg = snd_soc_read(codec, WM8960_POWER1); | 499 | reg = snd_soc_read(codec, WM8960_POWER1); |
@@ -471,8 +524,101 @@ static int wm8960_set_bias_level(struct snd_soc_codec *codec, | |||
471 | /* Disable VMID and VREF, let them discharge */ | 524 | /* Disable VMID and VREF, let them discharge */ |
472 | snd_soc_write(codec, WM8960_POWER1, 0); | 525 | snd_soc_write(codec, WM8960_POWER1, 0); |
473 | msleep(600); | 526 | msleep(600); |
527 | break; | ||
528 | } | ||
529 | |||
530 | codec->bias_level = level; | ||
531 | |||
532 | return 0; | ||
533 | } | ||
534 | |||
535 | static int wm8960_set_bias_level_capless(struct snd_soc_codec *codec, | ||
536 | enum snd_soc_bias_level level) | ||
537 | { | ||
538 | struct wm8960_priv *wm8960 = snd_soc_codec_get_drvdata(codec); | ||
539 | int reg; | ||
540 | |||
541 | switch (level) { | ||
542 | case SND_SOC_BIAS_ON: | ||
543 | break; | ||
544 | |||
545 | case SND_SOC_BIAS_PREPARE: | ||
546 | switch (codec->bias_level) { | ||
547 | case SND_SOC_BIAS_STANDBY: | ||
548 | /* Enable anti pop mode */ | ||
549 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
550 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
551 | WM8960_BUFDCOPEN, | ||
552 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
553 | WM8960_BUFDCOPEN); | ||
554 | |||
555 | /* Enable LOUT1, ROUT1 and OUT3 if they're enabled */ | ||
556 | reg = 0; | ||
557 | if (wm8960->lout1 && wm8960->lout1->power) | ||
558 | reg |= WM8960_PWR2_LOUT1; | ||
559 | if (wm8960->rout1 && wm8960->rout1->power) | ||
560 | reg |= WM8960_PWR2_ROUT1; | ||
561 | if (wm8960->out3 && wm8960->out3->power) | ||
562 | reg |= WM8960_PWR2_OUT3; | ||
563 | snd_soc_update_bits(codec, WM8960_POWER2, | ||
564 | WM8960_PWR2_LOUT1 | | ||
565 | WM8960_PWR2_ROUT1 | | ||
566 | WM8960_PWR2_OUT3, reg); | ||
567 | |||
568 | /* Enable VMID at 2*50k */ | ||
569 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
570 | WM8960_VMID_MASK, 0x80); | ||
571 | |||
572 | /* Ramp */ | ||
573 | msleep(100); | ||
574 | |||
575 | /* Enable VREF */ | ||
576 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
577 | WM8960_VREF, WM8960_VREF); | ||
578 | |||
579 | msleep(100); | ||
580 | break; | ||
581 | |||
582 | case SND_SOC_BIAS_ON: | ||
583 | /* Enable anti-pop mode */ | ||
584 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
585 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
586 | WM8960_BUFDCOPEN, | ||
587 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
588 | WM8960_BUFDCOPEN); | ||
589 | |||
590 | /* Disable VMID and VREF */ | ||
591 | snd_soc_update_bits(codec, WM8960_POWER1, | ||
592 | WM8960_VREF | WM8960_VMID_MASK, 0); | ||
593 | break; | ||
594 | |||
595 | default: | ||
596 | break; | ||
597 | } | ||
598 | break; | ||
474 | 599 | ||
475 | snd_soc_write(codec, WM8960_APOP1, 0); | 600 | case SND_SOC_BIAS_STANDBY: |
601 | switch (codec->bias_level) { | ||
602 | case SND_SOC_BIAS_PREPARE: | ||
603 | /* Disable HP discharge */ | ||
604 | snd_soc_update_bits(codec, WM8960_APOP2, | ||
605 | WM8960_DISOP | WM8960_DRES_MASK, | ||
606 | 0); | ||
607 | |||
608 | /* Disable anti-pop features */ | ||
609 | snd_soc_update_bits(codec, WM8960_APOP1, | ||
610 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
611 | WM8960_BUFDCOPEN, | ||
612 | WM8960_POBCTRL | WM8960_SOFT_ST | | ||
613 | WM8960_BUFDCOPEN); | ||
614 | break; | ||
615 | |||
616 | default: | ||
617 | break; | ||
618 | } | ||
619 | break; | ||
620 | |||
621 | case SND_SOC_BIAS_OFF: | ||
476 | break; | 622 | break; |
477 | } | 623 | } |
478 | 624 | ||
@@ -593,10 +739,6 @@ static int wm8960_set_dai_clkdiv(struct snd_soc_dai *codec_dai, | |||
593 | u16 reg; | 739 | u16 reg; |
594 | 740 | ||
595 | switch (div_id) { | 741 | switch (div_id) { |
596 | case WM8960_SYSCLKSEL: | ||
597 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1fe; | ||
598 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); | ||
599 | break; | ||
600 | case WM8960_SYSCLKDIV: | 742 | case WM8960_SYSCLKDIV: |
601 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; | 743 | reg = snd_soc_read(codec, WM8960_CLOCK1) & 0x1f9; |
602 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); | 744 | snd_soc_write(codec, WM8960_CLOCK1, reg | div); |
@@ -662,7 +804,7 @@ static int wm8960_suspend(struct platform_device *pdev, pm_message_t state) | |||
662 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 804 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
663 | struct snd_soc_codec *codec = socdev->card->codec; | 805 | struct snd_soc_codec *codec = socdev->card->codec; |
664 | 806 | ||
665 | wm8960_set_bias_level(codec, SND_SOC_BIAS_OFF); | 807 | codec->set_bias_level(codec, SND_SOC_BIAS_OFF); |
666 | return 0; | 808 | return 0; |
667 | } | 809 | } |
668 | 810 | ||
@@ -681,8 +823,8 @@ static int wm8960_resume(struct platform_device *pdev) | |||
681 | codec->hw_write(codec->control_data, data, 2); | 823 | codec->hw_write(codec->control_data, data, 2); |
682 | } | 824 | } |
683 | 825 | ||
684 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 826 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
685 | wm8960_set_bias_level(codec, codec->suspend_bias_level); | 827 | |
686 | return 0; | 828 | return 0; |
687 | } | 829 | } |
688 | 830 | ||
@@ -752,6 +894,8 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
752 | goto err; | 894 | goto err; |
753 | } | 895 | } |
754 | 896 | ||
897 | codec->set_bias_level = wm8960_set_bias_level_out3; | ||
898 | |||
755 | if (!pdata) { | 899 | if (!pdata) { |
756 | dev_warn(codec->dev, "No platform data supplied\n"); | 900 | dev_warn(codec->dev, "No platform data supplied\n"); |
757 | } else { | 901 | } else { |
@@ -759,17 +903,19 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
759 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); | 903 | dev_err(codec->dev, "Invalid DRES: %d\n", pdata->dres); |
760 | pdata->dres = 0; | 904 | pdata->dres = 0; |
761 | } | 905 | } |
906 | |||
907 | if (pdata->capless) | ||
908 | codec->set_bias_level = wm8960_set_bias_level_capless; | ||
762 | } | 909 | } |
763 | 910 | ||
764 | mutex_init(&codec->mutex); | 911 | mutex_init(&codec->mutex); |
765 | INIT_LIST_HEAD(&codec->dapm_widgets); | 912 | INIT_LIST_HEAD(&codec->dapm_widgets); |
766 | INIT_LIST_HEAD(&codec->dapm_paths); | 913 | INIT_LIST_HEAD(&codec->dapm_paths); |
767 | 914 | ||
768 | codec->private_data = wm8960; | 915 | snd_soc_codec_set_drvdata(codec, wm8960); |
769 | codec->name = "WM8960"; | 916 | codec->name = "WM8960"; |
770 | codec->owner = THIS_MODULE; | 917 | codec->owner = THIS_MODULE; |
771 | codec->bias_level = SND_SOC_BIAS_OFF; | 918 | codec->bias_level = SND_SOC_BIAS_OFF; |
772 | codec->set_bias_level = wm8960_set_bias_level; | ||
773 | codec->dai = &wm8960_dai; | 919 | codec->dai = &wm8960_dai; |
774 | codec->num_dai = 1; | 920 | codec->num_dai = 1; |
775 | codec->reg_cache_size = WM8960_CACHEREGNUM; | 921 | codec->reg_cache_size = WM8960_CACHEREGNUM; |
@@ -791,7 +937,7 @@ static int wm8960_register(struct wm8960_priv *wm8960, | |||
791 | 937 | ||
792 | wm8960_dai.dev = codec->dev; | 938 | wm8960_dai.dev = codec->dev; |
793 | 939 | ||
794 | wm8960_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 940 | codec->set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
795 | 941 | ||
796 | /* Latch the update bits */ | 942 | /* Latch the update bits */ |
797 | reg = snd_soc_read(codec, WM8960_LINVOL); | 943 | reg = snd_soc_read(codec, WM8960_LINVOL); |
@@ -840,7 +986,7 @@ err: | |||
840 | 986 | ||
841 | static void wm8960_unregister(struct wm8960_priv *wm8960) | 987 | static void wm8960_unregister(struct wm8960_priv *wm8960) |
842 | { | 988 | { |
843 | wm8960_set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); | 989 | wm8960->codec.set_bias_level(&wm8960->codec, SND_SOC_BIAS_OFF); |
844 | snd_soc_unregister_dai(&wm8960_dai); | 990 | snd_soc_unregister_dai(&wm8960_dai); |
845 | snd_soc_unregister_codec(&wm8960->codec); | 991 | snd_soc_unregister_codec(&wm8960->codec); |
846 | kfree(wm8960); | 992 | kfree(wm8960); |
@@ -882,7 +1028,7 @@ MODULE_DEVICE_TABLE(i2c, wm8960_i2c_id); | |||
882 | 1028 | ||
883 | static struct i2c_driver wm8960_i2c_driver = { | 1029 | static struct i2c_driver wm8960_i2c_driver = { |
884 | .driver = { | 1030 | .driver = { |
885 | .name = "WM8960 I2C Codec", | 1031 | .name = "wm8960", |
886 | .owner = THIS_MODULE, | 1032 | .owner = THIS_MODULE, |
887 | }, | 1033 | }, |
888 | .probe = wm8960_i2c_probe, | 1034 | .probe = wm8960_i2c_probe, |