| OLD | NEW |
| 1 /* | 1 /* |
| 2 * wm8523.c -- WM8523 ALSA SoC Audio driver | 2 * wm8523.c -- WM8523 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 * | 8 * |
| 9 * This program is free software; you can redistribute it and/or modify | 9 * This program is free software; you can redistribute it and/or modify |
| 10 * it under the terms of the GNU General Public License version 2 as | 10 * it under the terms of the GNU General Public License version 2 as |
| 11 * published by the Free Software Foundation. | 11 * published by the Free Software Foundation. |
| 12 */ | 12 */ |
| 13 | 13 |
| 14 #include <linux/module.h> | 14 #include <linux/module.h> |
| 15 #include <linux/moduleparam.h> | 15 #include <linux/moduleparam.h> |
| 16 #include <linux/init.h> | 16 #include <linux/init.h> |
| 17 #include <linux/delay.h> | 17 #include <linux/delay.h> |
| 18 #include <linux/pm.h> | 18 #include <linux/pm.h> |
| 19 #include <linux/i2c.h> | 19 #include <linux/i2c.h> |
| 20 #include <linux/platform_device.h> | 20 #include <linux/platform_device.h> |
| 21 #include <linux/regulator/consumer.h> | 21 #include <linux/regulator/consumer.h> |
| 22 #include <linux/slab.h> | 22 #include <linux/slab.h> |
| 23 #include <sound/core.h> | 23 #include <sound/core.h> |
| 24 #include <sound/pcm.h> | 24 #include <sound/pcm.h> |
| 25 #include <sound/pcm_params.h> | 25 #include <sound/pcm_params.h> |
| 26 #include <sound/soc.h> | 26 #include <sound/soc.h> |
| 27 #include <sound/soc-dapm.h> | |
| 28 #include <sound/initval.h> | 27 #include <sound/initval.h> |
| 29 #include <sound/tlv.h> | 28 #include <sound/tlv.h> |
| 30 | 29 |
| 31 #include "wm8523.h" | 30 #include "wm8523.h" |
| 32 | 31 |
| 33 #define WM8523_NUM_SUPPLIES 2 | 32 #define WM8523_NUM_SUPPLIES 2 |
| 34 static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { | 33 static const char *wm8523_supply_names[WM8523_NUM_SUPPLIES] = { |
| 35 "AVDD", | 34 "AVDD", |
| 36 "LINEVDD", | 35 "LINEVDD", |
| 37 }; | 36 }; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 52 0x0001, /* R1 - REVISION */ | 51 0x0001, /* R1 - REVISION */ |
| 53 0x0000, /* R2 - PSCTRL1 */ | 52 0x0000, /* R2 - PSCTRL1 */ |
| 54 0x1812, /* R3 - AIF_CTRL1 */ | 53 0x1812, /* R3 - AIF_CTRL1 */ |
| 55 0x0000, /* R4 - AIF_CTRL2 */ | 54 0x0000, /* R4 - AIF_CTRL2 */ |
| 56 0x0001, /* R5 - DAC_CTRL3 */ | 55 0x0001, /* R5 - DAC_CTRL3 */ |
| 57 0x0190, /* R6 - DAC_GAINL */ | 56 0x0190, /* R6 - DAC_GAINL */ |
| 58 0x0190, /* R7 - DAC_GAINR */ | 57 0x0190, /* R7 - DAC_GAINR */ |
| 59 0x0000, /* R8 - ZERO_DETECT */ | 58 0x0000, /* R8 - ZERO_DETECT */ |
| 60 }; | 59 }; |
| 61 | 60 |
| 62 static int wm8523_volatile_register(unsigned int reg) | 61 static int wm8523_volatile_register(struct snd_soc_codec *codec, unsigned int re
g) |
| 63 { | 62 { |
| 64 switch (reg) { | 63 switch (reg) { |
| 65 case WM8523_DEVICE_ID: | 64 case WM8523_DEVICE_ID: |
| 66 case WM8523_REVISION: | 65 case WM8523_REVISION: |
| 67 return 1; | 66 return 1; |
| 68 default: | 67 default: |
| 69 return 0; | 68 return 0; |
| 70 } | 69 } |
| 71 } | 70 } |
| 72 | 71 |
| (...skipping 29 matching lines...) Expand all Loading... |
| 102 SND_SOC_DAPM_OUTPUT("LINEVOUTR"), | 101 SND_SOC_DAPM_OUTPUT("LINEVOUTR"), |
| 103 }; | 102 }; |
| 104 | 103 |
| 105 static const struct snd_soc_dapm_route intercon[] = { | 104 static const struct snd_soc_dapm_route intercon[] = { |
| 106 { "LINEVOUTL", NULL, "DAC" }, | 105 { "LINEVOUTL", NULL, "DAC" }, |
| 107 { "LINEVOUTR", NULL, "DAC" }, | 106 { "LINEVOUTR", NULL, "DAC" }, |
| 108 }; | 107 }; |
| 109 | 108 |
| 110 static int wm8523_add_widgets(struct snd_soc_codec *codec) | 109 static int wm8523_add_widgets(struct snd_soc_codec *codec) |
| 111 { | 110 { |
| 112 » snd_soc_dapm_new_controls(codec, wm8523_dapm_widgets, | 111 » struct snd_soc_dapm_context *dapm = &codec->dapm; |
| 112 |
| 113 » snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets, |
| 113 ARRAY_SIZE(wm8523_dapm_widgets)); | 114 ARRAY_SIZE(wm8523_dapm_widgets)); |
| 114 | 115 » snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); |
| 115 » snd_soc_dapm_add_routes(codec, intercon, ARRAY_SIZE(intercon)); | |
| 116 | 116 |
| 117 return 0; | 117 return 0; |
| 118 } | 118 } |
| 119 | 119 |
| 120 static struct { | 120 static struct { |
| 121 int value; | 121 int value; |
| 122 int ratio; | 122 int ratio; |
| 123 } lrclk_ratios[WM8523_NUM_RATES] = { | 123 } lrclk_ratios[WM8523_NUM_RATES] = { |
| 124 { 1, 128 }, | 124 { 1, 128 }, |
| 125 { 2, 192 }, | 125 { 2, 192 }, |
| (...skipping 194 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 320 case SND_SOC_BIAS_ON: | 320 case SND_SOC_BIAS_ON: |
| 321 break; | 321 break; |
| 322 | 322 |
| 323 case SND_SOC_BIAS_PREPARE: | 323 case SND_SOC_BIAS_PREPARE: |
| 324 /* Full power on */ | 324 /* Full power on */ |
| 325 snd_soc_update_bits(codec, WM8523_PSCTRL1, | 325 snd_soc_update_bits(codec, WM8523_PSCTRL1, |
| 326 WM8523_SYS_ENA_MASK, 3); | 326 WM8523_SYS_ENA_MASK, 3); |
| 327 break; | 327 break; |
| 328 | 328 |
| 329 case SND_SOC_BIAS_STANDBY: | 329 case SND_SOC_BIAS_STANDBY: |
| 330 » » if (codec->bias_level == SND_SOC_BIAS_OFF) { | 330 » » if (codec->dapm.bias_level == SND_SOC_BIAS_OFF) { |
| 331 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies)
, | 331 ret = regulator_bulk_enable(ARRAY_SIZE(wm8523->supplies)
, |
| 332 wm8523->supplies); | 332 wm8523->supplies); |
| 333 if (ret != 0) { | 333 if (ret != 0) { |
| 334 dev_err(codec->dev, | 334 dev_err(codec->dev, |
| 335 "Failed to enable supplies: %d\n", | 335 "Failed to enable supplies: %d\n", |
| 336 ret); | 336 ret); |
| 337 return ret; | 337 return ret; |
| 338 } | 338 } |
| 339 | 339 |
| 340 /* Initial power up */ | 340 /* Initial power up */ |
| (...skipping 18 matching lines...) Expand all Loading... |
| 359 case SND_SOC_BIAS_OFF: | 359 case SND_SOC_BIAS_OFF: |
| 360 /* The chip runs through the power down sequence for us. */ | 360 /* The chip runs through the power down sequence for us. */ |
| 361 snd_soc_update_bits(codec, WM8523_PSCTRL1, | 361 snd_soc_update_bits(codec, WM8523_PSCTRL1, |
| 362 WM8523_SYS_ENA_MASK, 0); | 362 WM8523_SYS_ENA_MASK, 0); |
| 363 msleep(100); | 363 msleep(100); |
| 364 | 364 |
| 365 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), | 365 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), |
| 366 wm8523->supplies); | 366 wm8523->supplies); |
| 367 break; | 367 break; |
| 368 } | 368 } |
| 369 » codec->bias_level = level; | 369 » codec->dapm.bias_level = level; |
| 370 return 0; | 370 return 0; |
| 371 } | 371 } |
| 372 | 372 |
| 373 #define WM8523_RATES SNDRV_PCM_RATE_8000_192000 | 373 #define WM8523_RATES SNDRV_PCM_RATE_8000_192000 |
| 374 | 374 |
| 375 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 375 #define WM8523_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
| 376 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 376 SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
| 377 | 377 |
| 378 static struct snd_soc_dai_ops wm8523_dai_ops = { | 378 static struct snd_soc_dai_ops wm8523_dai_ops = { |
| 379 .startup = wm8523_startup, | 379 .startup = wm8523_startup, |
| (...skipping 27 matching lines...) Expand all Loading... |
| 407 return 0; | 407 return 0; |
| 408 } | 408 } |
| 409 #else | 409 #else |
| 410 #define wm8523_suspend NULL | 410 #define wm8523_suspend NULL |
| 411 #define wm8523_resume NULL | 411 #define wm8523_resume NULL |
| 412 #endif | 412 #endif |
| 413 | 413 |
| 414 static int wm8523_probe(struct snd_soc_codec *codec) | 414 static int wm8523_probe(struct snd_soc_codec *codec) |
| 415 { | 415 { |
| 416 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); | 416 struct wm8523_priv *wm8523 = snd_soc_codec_get_drvdata(codec); |
| 417 u16 *reg_cache = codec->reg_cache; | |
| 418 int ret, i; | 417 int ret, i; |
| 419 | 418 |
| 420 codec->hw_write = (hw_write_t)i2c_master_send; | 419 codec->hw_write = (hw_write_t)i2c_master_send; |
| 421 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; | 420 wm8523->rate_constraint.list = &wm8523->rate_constraint_list[0]; |
| 422 wm8523->rate_constraint.count = | 421 wm8523->rate_constraint.count = |
| 423 ARRAY_SIZE(wm8523->rate_constraint_list); | 422 ARRAY_SIZE(wm8523->rate_constraint_list); |
| 424 | 423 |
| 425 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); | 424 ret = snd_soc_codec_set_cache_io(codec, 8, 16, wm8523->control_type); |
| 426 if (ret != 0) { | 425 if (ret != 0) { |
| 427 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 426 dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 464 dev_info(codec->dev, "revision %c\n", | 463 dev_info(codec->dev, "revision %c\n", |
| 465 (ret & WM8523_CHIP_REV_MASK) + 'A'); | 464 (ret & WM8523_CHIP_REV_MASK) + 'A'); |
| 466 | 465 |
| 467 ret = wm8523_reset(codec); | 466 ret = wm8523_reset(codec); |
| 468 if (ret < 0) { | 467 if (ret < 0) { |
| 469 dev_err(codec->dev, "Failed to issue reset\n"); | 468 dev_err(codec->dev, "Failed to issue reset\n"); |
| 470 goto err_enable; | 469 goto err_enable; |
| 471 } | 470 } |
| 472 | 471 |
| 473 /* Change some default settings - latch VU and enable ZC */ | 472 /* Change some default settings - latch VU and enable ZC */ |
| 474 » reg_cache[WM8523_DAC_GAINR] |= WM8523_DACR_VU; | 473 » snd_soc_update_bits(codec, WM8523_DAC_GAINR, |
| 475 » reg_cache[WM8523_DAC_CTRL3] |= WM8523_ZC; | 474 » » » WM8523_DACR_VU, WM8523_DACR_VU); |
| 475 » snd_soc_update_bits(codec, WM8523_DAC_CTRL3, WM8523_ZC, WM8523_ZC); |
| 476 | 476 |
| 477 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 477 wm8523_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
| 478 | 478 |
| 479 /* Bias level configuration will have done an extra enable */ | 479 /* Bias level configuration will have done an extra enable */ |
| 480 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 480 regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
| 481 | 481 |
| 482 snd_soc_add_controls(codec, wm8523_snd_controls, | 482 snd_soc_add_controls(codec, wm8523_snd_controls, |
| 483 ARRAY_SIZE(wm8523_snd_controls)); | 483 ARRAY_SIZE(wm8523_snd_controls)); |
| 484 wm8523_add_widgets(codec); | 484 wm8523_add_widgets(codec); |
| 485 | 485 |
| (...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 578 { | 578 { |
| 579 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 579 #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
| 580 i2c_del_driver(&wm8523_i2c_driver); | 580 i2c_del_driver(&wm8523_i2c_driver); |
| 581 #endif | 581 #endif |
| 582 } | 582 } |
| 583 module_exit(wm8523_exit); | 583 module_exit(wm8523_exit); |
| 584 | 584 |
| 585 MODULE_DESCRIPTION("ASoC WM8523 driver"); | 585 MODULE_DESCRIPTION("ASoC WM8523 driver"); |
| 586 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 586 MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
| 587 MODULE_LICENSE("GPL"); | 587 MODULE_LICENSE("GPL"); |
| OLD | NEW |