| OLD | NEW |
| 1 /* | 1 /* |
| 2 * wm8750.c -- WM8750 ALSA SoC audio driver | 2 * wm8750.c -- WM8750 ALSA SoC audio driver |
| 3 * | 3 * |
| 4 * Copyright 2005 Openedhand Ltd. | 4 * Copyright 2005 Openedhand Ltd. |
| 5 * | 5 * |
| 6 * Author: Richard Purdie <richard@openedhand.com> | 6 * Author: Richard Purdie <richard@openedhand.com> |
| 7 * | 7 * |
| 8 * Based on WM8753.c | 8 * Based on WM8753.c |
| 9 * | 9 * |
| 10 * This program is free software; you can redistribute it and/or modify | 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 | 11 * it under the terms of the GNU General Public License version 2 as |
| 12 * published by the Free Software Foundation. | 12 * published by the Free Software Foundation. |
| 13 */ | 13 */ |
| 14 | 14 |
| 15 #include <linux/module.h> | 15 #include <linux/module.h> |
| 16 #include <linux/moduleparam.h> | 16 #include <linux/moduleparam.h> |
| 17 #include <linux/init.h> | 17 #include <linux/init.h> |
| 18 #include <linux/delay.h> | 18 #include <linux/delay.h> |
| 19 #include <linux/pm.h> | 19 #include <linux/pm.h> |
| 20 #include <linux/i2c.h> | 20 #include <linux/i2c.h> |
| 21 #include <linux/platform_device.h> | 21 #include <linux/platform_device.h> |
| 22 #include <linux/spi/spi.h> | 22 #include <linux/spi/spi.h> |
| 23 #include <linux/slab.h> | 23 #include <linux/slab.h> |
| 24 #include <sound/core.h> | 24 #include <sound/core.h> |
| 25 #include <sound/pcm.h> | 25 #include <sound/pcm.h> |
| 26 #include <sound/pcm_params.h> | 26 #include <sound/pcm_params.h> |
| 27 #include <sound/soc.h> | 27 #include <sound/soc.h> |
| 28 #include <sound/soc-dapm.h> | |
| 29 #include <sound/initval.h> | 28 #include <sound/initval.h> |
| 30 | 29 |
| 31 #include "wm8750.h" | 30 #include "wm8750.h" |
| 32 | 31 |
| 33 /* | 32 /* |
| 34 * wm8750 register cache | 33 * wm8750 register cache |
| 35 * We can't read the WM8750 register space when we | 34 * We can't read the WM8750 register space when we |
| 36 * are using 2 wire for device control, so we cache them instead. | 35 * are using 2 wire for device control, so we cache them instead. |
| 37 */ | 36 */ |
| 38 static const u16 wm8750_reg[] = { | 37 static const u16 wm8750_reg[] = { |
| 39 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ | 38 0x0097, 0x0097, 0x0079, 0x0079, /* 0 */ |
| 40 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ | 39 0x0000, 0x0008, 0x0000, 0x000a, /* 4 */ |
| 41 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ | 40 0x0000, 0x0000, 0x00ff, 0x00ff, /* 8 */ |
| 42 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ | 41 0x000f, 0x000f, 0x0000, 0x0000, /* 12 */ |
| 43 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ | 42 0x0000, 0x007b, 0x0000, 0x0032, /* 16 */ |
| 44 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ | 43 0x0000, 0x00c3, 0x00c3, 0x00c0, /* 20 */ |
| 45 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ | 44 0x0000, 0x0000, 0x0000, 0x0000, /* 24 */ |
| 46 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ | 45 0x0000, 0x0000, 0x0000, 0x0000, /* 28 */ |
| 47 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ | 46 0x0000, 0x0000, 0x0050, 0x0050, /* 32 */ |
| 48 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ | 47 0x0050, 0x0050, 0x0050, 0x0050, /* 36 */ |
| 49 0x0079, 0x0079, 0x0079, /* 40 */ | 48 0x0079, 0x0079, 0x0079, /* 40 */ |
| 50 }; | 49 }; |
| 51 | 50 |
| 52 /* codec private data */ | 51 /* codec private data */ |
| 53 struct wm8750_priv { | 52 struct wm8750_priv { |
| 54 unsigned int sysclk; | 53 unsigned int sysclk; |
| 55 enum snd_soc_control_type control_type; | 54 enum snd_soc_control_type control_type; |
| 56 u16 reg_cache[ARRAY_SIZE(wm8750_reg)]; | |
| 57 }; | 55 }; |
| 58 | 56 |
| 59 #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) | 57 #define wm8750_reset(c) snd_soc_write(c, WM8750_RESET, 0) |
| 60 | 58 |
| 61 /* | 59 /* |
| 62 * WM8750 Controls | 60 * WM8750 Controls |
| 63 */ | 61 */ |
| 64 static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"}; | 62 static const char *wm8750_bass[] = {"Linear Control", "Adaptive Boost"}; |
| 65 static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; | 63 static const char *wm8750_bass_filter[] = { "130Hz @ 48kHz", "200Hz @ 48kHz" }; |
| 66 static const char *wm8750_treble[] = {"8kHz", "4kHz"}; | 64 static const char *wm8750_treble[] = {"8kHz", "4kHz"}; |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, | 390 {"Right ADC Mux", "Mono (Right)", "Right PGA Mux"}, |
| 393 {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, | 391 {"Right ADC Mux", "Digital Mono", "Right PGA Mux"}, |
| 394 | 392 |
| 395 /* ADC */ | 393 /* ADC */ |
| 396 {"Left ADC", NULL, "Left ADC Mux"}, | 394 {"Left ADC", NULL, "Left ADC Mux"}, |
| 397 {"Right ADC", NULL, "Right ADC Mux"}, | 395 {"Right ADC", NULL, "Right ADC Mux"}, |
| 398 }; | 396 }; |
| 399 | 397 |
| 400 static int wm8750_add_widgets(struct snd_soc_codec *codec) | 398 static int wm8750_add_widgets(struct snd_soc_codec *codec) |
| 401 { | 399 { |
| 402 » snd_soc_dapm_new_controls(codec, wm8750_dapm_widgets, | 400 » struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 401 |
| 402 » snd_soc_dapm_new_controls(dapm, wm8750_dapm_widgets, |
| 403 ARRAY_SIZE(wm8750_dapm_widgets)); | 403 ARRAY_SIZE(wm8750_dapm_widgets)); |
| 404 | 404 » snd_soc_dapm_add_routes(dapm, audio_map, ARRAY_SIZE(audio_map)); |
| 405 » snd_soc_dapm_add_routes(codec, audio_map, ARRAY_SIZE(audio_map)); | |
| 406 | 405 |
| 407 return 0; | 406 return 0; |
| 408 } | 407 } |
| 409 | 408 |
| 410 struct _coeff_div { | 409 struct _coeff_div { |
| 411 u32 mclk; | 410 u32 mclk; |
| 412 u32 rate; | 411 u32 rate; |
| 413 u16 fs; | 412 u16 fs; |
| 414 u8 sr:5; | 413 u8 sr:5; |
| 415 u8 usb:1; | 414 u8 usb:1; |
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 608 u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e; | 607 u16 pwr_reg = snd_soc_read(codec, WM8750_PWR1) & 0xfe3e; |
| 609 | 608 |
| 610 switch (level) { | 609 switch (level) { |
| 611 case SND_SOC_BIAS_ON: | 610 case SND_SOC_BIAS_ON: |
| 612 /* set vmid to 50k and unmute dac */ | 611 /* set vmid to 50k and unmute dac */ |
| 613 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); | 612 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x00c0); |
| 614 break; | 613 break; |
| 615 case SND_SOC_BIAS_PREPARE: | 614 case SND_SOC_BIAS_PREPARE: |
| 616 break; | 615 break; |
| 617 case SND_SOC_BIAS_STANDBY: | 616 case SND_SOC_BIAS_STANDBY: |
| 618 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { | 617 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 619 /* Set VMID to 5k */ | 618 /* Set VMID to 5k */ |
| 620 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); | 619 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x01c1); |
| 621 | 620 |
| 622 /* ...and ramp */ | 621 /* ...and ramp */ |
| 623 msleep(1000); | 622 msleep(1000); |
| 624 } | 623 } |
| 625 | 624 |
| 626 /* mute dac and set vmid to 500k, enable VREF */ | 625 /* mute dac and set vmid to 500k, enable VREF */ |
| 627 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); | 626 snd_soc_write(codec, WM8750_PWR1, pwr_reg | 0x0141); |
| 628 break; | 627 break; |
| 629 case SND_SOC_BIAS_OFF: | 628 case SND_SOC_BIAS_OFF: |
| 630 snd_soc_write(codec, WM8750_PWR1, 0x0001); | 629 snd_soc_write(codec, WM8750_PWR1, 0x0001); |
| 631 break; | 630 break; |
| 632 } | 631 } |
| 633 » codec->bias_level = level; | 632 » codec->dapm.bias_level = level; |
| 634 return 0; | 633 return 0; |
| 635 } | 634 } |
| 636 | 635 |
| 637 #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 636 #define WM8750_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
| 638 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ | 637 SNDRV_PCM_RATE_16000 | SNDRV_PCM_RATE_22050 | SNDRV_PCM_RATE_44100 | \ |
| 639 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) | 638 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000) |
| 640 | 639 |
| 641 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 640 #define WM8750_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
| 642 SNDRV_PCM_FMTBIT_S24_LE) | 641 SNDRV_PCM_FMTBIT_S24_LE) |
| 643 | 642 |
| (...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 863 #endif | 862 #endif |
| 864 #if defined(CONFIG_SPI_MASTER) | 863 #if defined(CONFIG_SPI_MASTER) |
| 865 spi_unregister_driver(&wm8750_spi_driver); | 864 spi_unregister_driver(&wm8750_spi_driver); |
| 866 #endif | 865 #endif |
| 867 } | 866 } |
| 868 module_exit(wm8750_exit); | 867 module_exit(wm8750_exit); |
| 869 | 868 |
| 870 MODULE_DESCRIPTION("ASoC WM8750 driver"); | 869 MODULE_DESCRIPTION("ASoC WM8750 driver"); |
| 871 MODULE_AUTHOR("Liam Girdwood"); | 870 MODULE_AUTHOR("Liam Girdwood"); |
| 872 MODULE_LICENSE("GPL"); | 871 MODULE_LICENSE("GPL"); |
| OLD | NEW |