| OLD | NEW |
| 1 /* | 1 /* |
| 2 * wm8776.c -- WM8776 ALSA SoC Audio driver | 2 * wm8776.c -- WM8776 ALSA SoC Audio driver |
| 3 * | 3 * |
| 4 * Copyright 2009 Wolfson Microelectronics plc | 4 * Copyright 2009 Wolfson Microelectronics plc |
| 5 * | 5 * |
| 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> | 6 * Author: Mark Brown <broonie@opensource.wolfsonmicro.com> |
| 7 * | 7 * |
| 8 * This program is free software; you can redistribute it and/or modify | 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 | 9 * it under the terms of the GNU General Public License version 2 as |
| 10 * published by the Free Software Foundation. | 10 * published by the Free Software Foundation. |
| 11 * | 11 * |
| 12 * TODO: Input ALC/limiter support | 12 * TODO: Input ALC/limiter support |
| 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 #include <sound/tlv.h> | 29 #include <sound/tlv.h> |
| 31 | 30 |
| 32 #include "wm8776.h" | 31 #include "wm8776.h" |
| 33 | 32 |
| 34 /* codec private data */ | 33 /* codec private data */ |
| 35 struct wm8776_priv { | 34 struct wm8776_priv { |
| 36 enum snd_soc_control_type control_type; | 35 enum snd_soc_control_type control_type; |
| 37 int sysclk[2]; | 36 int sysclk[2]; |
| 38 }; | 37 }; |
| (...skipping 260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 299 | 298 |
| 300 static int wm8776_set_bias_level(struct snd_soc_codec *codec, | 299 static int wm8776_set_bias_level(struct snd_soc_codec *codec, |
| 301 enum snd_soc_bias_level level) | 300 enum snd_soc_bias_level level) |
| 302 { | 301 { |
| 303 switch (level) { | 302 switch (level) { |
| 304 case SND_SOC_BIAS_ON: | 303 case SND_SOC_BIAS_ON: |
| 305 break; | 304 break; |
| 306 case SND_SOC_BIAS_PREPARE: | 305 case SND_SOC_BIAS_PREPARE: |
| 307 break; | 306 break; |
| 308 case SND_SOC_BIAS_STANDBY: | 307 case SND_SOC_BIAS_STANDBY: |
| 309 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { | 308 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 310 /* Disable the global powerdown; DAPM does the rest */ | 309 /* Disable the global powerdown; DAPM does the rest */ |
| 311 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); | 310 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 0); |
| 312 } | 311 } |
| 313 | 312 |
| 314 break; | 313 break; |
| 315 case SND_SOC_BIAS_OFF: | 314 case SND_SOC_BIAS_OFF: |
| 316 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); | 315 snd_soc_update_bits(codec, WM8776_PWRDOWN, 1, 1); |
| 317 break; | 316 break; |
| 318 } | 317 } |
| 319 | 318 |
| 320 » codec->bias_level = level; | 319 » codec->dapm.bias_level = level; |
| 321 return 0; | 320 return 0; |
| 322 } | 321 } |
| 323 | 322 |
| 324 #define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | 323 #define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ |
| 325 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | 324 SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ |
| 326 SNDRV_PCM_RATE_96000) | 325 SNDRV_PCM_RATE_96000) |
| 327 | 326 |
| 328 | 327 |
| 329 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 328 #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
| 330 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 329 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
| (...skipping 66 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 397 return 0; | 396 return 0; |
| 398 } | 397 } |
| 399 #else | 398 #else |
| 400 #define wm8776_suspend NULL | 399 #define wm8776_suspend NULL |
| 401 #define wm8776_resume NULL | 400 #define wm8776_resume NULL |
| 402 #endif | 401 #endif |
| 403 | 402 |
| 404 static int wm8776_probe(struct snd_soc_codec *codec) | 403 static int wm8776_probe(struct snd_soc_codec *codec) |
| 405 { | 404 { |
| 406 struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); | 405 struct wm8776_priv *wm8776 = snd_soc_codec_get_drvdata(codec); |
| 406 struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 407 int ret = 0; | 407 int ret = 0; |
| 408 | 408 |
| 409 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); | 409 ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8776->control_type); |
| 410 if (ret < 0) { | 410 if (ret < 0) { |
| 411 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 411 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| 412 return ret; | 412 return ret; |
| 413 } | 413 } |
| 414 | 414 |
| 415 ret = wm8776_reset(codec); | 415 ret = wm8776_reset(codec); |
| 416 if (ret < 0) { | 416 if (ret < 0) { |
| 417 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); | 417 dev_err(codec->dev, "Failed to issue reset: %d\n", ret); |
| 418 return ret; | 418 return ret; |
| 419 } | 419 } |
| 420 | 420 |
| 421 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 421 wm8776_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 422 | 422 |
| 423 /* Latch the update bits; right channel only since we always | 423 /* Latch the update bits; right channel only since we always |
| 424 * update both. */ | 424 * update both. */ |
| 425 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); | 425 snd_soc_update_bits(codec, WM8776_HPRVOL, 0x100, 0x100); |
| 426 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); | 426 snd_soc_update_bits(codec, WM8776_DACRVOL, 0x100, 0x100); |
| 427 | 427 |
| 428 snd_soc_add_controls(codec, wm8776_snd_controls, | 428 snd_soc_add_controls(codec, wm8776_snd_controls, |
| 429 ARRAY_SIZE(wm8776_snd_controls)); | 429 ARRAY_SIZE(wm8776_snd_controls)); |
| 430 » snd_soc_dapm_new_controls(codec, wm8776_dapm_widgets, | 430 » snd_soc_dapm_new_controls(dapm, wm8776_dapm_widgets, |
| 431 ARRAY_SIZE(wm8776_dapm_widgets)); | 431 ARRAY_SIZE(wm8776_dapm_widgets)); |
| 432 » snd_soc_dapm_add_routes(codec, routes, ARRAY_SIZE(routes)); | 432 » snd_soc_dapm_add_routes(dapm, routes, ARRAY_SIZE(routes)); |
| 433 | 433 |
| 434 return ret; | 434 return ret; |
| 435 } | 435 } |
| 436 | 436 |
| 437 /* power down chip */ | 437 /* power down chip */ |
| 438 static int wm8776_remove(struct snd_soc_codec *codec) | 438 static int wm8776_remove(struct snd_soc_codec *codec) |
| 439 { | 439 { |
| 440 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); | 440 wm8776_set_bias_level(codec, SND_SOC_BIAS_OFF); |
| 441 return 0; | 441 return 0; |
| 442 } | 442 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 562 #endif | 562 #endif |
| 563 #if defined(CONFIG_SPI_MASTER) | 563 #if defined(CONFIG_SPI_MASTER) |
| 564 spi_unregister_driver(&wm8776_spi_driver); | 564 spi_unregister_driver(&wm8776_spi_driver); |
| 565 #endif | 565 #endif |
| 566 } | 566 } |
| 567 module_exit(wm8776_exit); | 567 module_exit(wm8776_exit); |
| 568 | 568 |
| 569 MODULE_DESCRIPTION("ASoC WM8776 driver"); | 569 MODULE_DESCRIPTION("ASoC WM8776 driver"); |
| 570 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 570 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
| 571 MODULE_LICENSE("GPL"); | 571 MODULE_LICENSE("GPL"); |
| OLD | NEW |