diff options
author | Takashi Iwai <tiwai@suse.de> | 2011-09-22 03:56:12 -0400 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2011-09-22 03:56:12 -0400 |
commit | af1910a817c5ad52c32dddacc1744cfa1b35889e (patch) | |
tree | 2d6504a2ac5971bb84e0172bbdd309b781048849 /sound/soc/codecs | |
parent | 5495ffbd7b56d8bffebc5e30f03ea374590f1bb4 (diff) | |
parent | f648de832dbf6d1947ce5a7c0ed24a3a71d8545b (diff) |
Merge branch 'topic/asoc' into topic/remove-irqf_disable
Diffstat (limited to 'sound/soc/codecs')
40 files changed, 2539 insertions, 407 deletions
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 665d9240c4ae..71b46c8f70d7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -17,6 +17,7 @@ config SND_SOC_ALL_CODECS | |||
17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI | 17 | select SND_SOC_AD193X if SND_SOC_I2C_AND_SPI |
18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS | 18 | select SND_SOC_AD1980 if SND_SOC_AC97_BUS |
19 | select SND_SOC_AD73311 | 19 | select SND_SOC_AD73311 |
20 | select SND_SOC_ADAU1373 if I2C | ||
20 | select SND_SOC_ADAV80X | 21 | select SND_SOC_ADAV80X |
21 | select SND_SOC_ADS117X | 22 | select SND_SOC_ADS117X |
22 | select SND_SOC_AK4104 if SPI_MASTER | 23 | select SND_SOC_AK4104 if SPI_MASTER |
@@ -139,6 +140,9 @@ config SND_SOC_ADAU1701 | |||
139 | select SIGMA | 140 | select SIGMA |
140 | tristate | 141 | tristate |
141 | 142 | ||
143 | config SND_SOC_ADAU1373 | ||
144 | tristate | ||
145 | |||
142 | config SND_SOC_ADAV80X | 146 | config SND_SOC_ADAV80X |
143 | tristate | 147 | tristate |
144 | 148 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 5119a7e2c1a8..70c1769acd15 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -5,6 +5,7 @@ snd-soc-ad193x-objs := ad193x.o | |||
5 | snd-soc-ad1980-objs := ad1980.o | 5 | snd-soc-ad1980-objs := ad1980.o |
6 | snd-soc-ad73311-objs := ad73311.o | 6 | snd-soc-ad73311-objs := ad73311.o |
7 | snd-soc-adau1701-objs := adau1701.o | 7 | snd-soc-adau1701-objs := adau1701.o |
8 | snd-soc-adau1373-objs := adau1373.o | ||
8 | snd-soc-adav80x-objs := adav80x.o | 9 | snd-soc-adav80x-objs := adav80x.o |
9 | snd-soc-ads117x-objs := ads117x.o | 10 | snd-soc-ads117x-objs := ads117x.o |
10 | snd-soc-ak4104-objs := ak4104.o | 11 | snd-soc-ak4104-objs := ak4104.o |
@@ -100,6 +101,7 @@ obj-$(CONFIG_SND_SOC_AD1836) += snd-soc-ad1836.o | |||
100 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o | 101 | obj-$(CONFIG_SND_SOC_AD193X) += snd-soc-ad193x.o |
101 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o | 102 | obj-$(CONFIG_SND_SOC_AD1980) += snd-soc-ad1980.o |
102 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o | 103 | obj-$(CONFIG_SND_SOC_AD73311) += snd-soc-ad73311.o |
104 | obj-$(CONFIG_SND_SOC_ADAU1373) += snd-soc-adau1373.o | ||
103 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o | 105 | obj-$(CONFIG_SND_SOC_ADAU1701) += snd-soc-adau1701.o |
104 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o | 106 | obj-$(CONFIG_SND_SOC_ADAV80X) += snd-soc-adav80x.o |
105 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o | 107 | obj-$(CONFIG_SND_SOC_ADS117X) += snd-soc-ads117x.o |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index eedb6f5e5823..f934670199a5 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -23,7 +23,7 @@ | |||
23 | 23 | ||
24 | /* codec private data */ | 24 | /* codec private data */ |
25 | struct ad193x_priv { | 25 | struct ad193x_priv { |
26 | enum snd_soc_control_type control_type; | 26 | struct regmap *regmap; |
27 | int sysclk; | 27 | int sysclk; |
28 | }; | 28 | }; |
29 | 29 | ||
@@ -349,10 +349,8 @@ static int ad193x_probe(struct snd_soc_codec *codec) | |||
349 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 349 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
350 | int ret; | 350 | int ret; |
351 | 351 | ||
352 | if (ad193x->control_type == SND_SOC_I2C) | 352 | codec->control_data = ad193x->regmap; |
353 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, ad193x->control_type); | 353 | ret = snd_soc_codec_set_cache_io(codec, 0, 0, SND_SOC_REGMAP); |
354 | else | ||
355 | ret = snd_soc_codec_set_cache_io(codec, 16, 8, ad193x->control_type); | ||
356 | if (ret < 0) { | 354 | if (ret < 0) { |
357 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | 355 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); |
358 | return ret; | 356 | return ret; |
@@ -388,6 +386,14 @@ static struct snd_soc_codec_driver soc_codec_dev_ad193x = { | |||
388 | }; | 386 | }; |
389 | 387 | ||
390 | #if defined(CONFIG_SPI_MASTER) | 388 | #if defined(CONFIG_SPI_MASTER) |
389 | |||
390 | static const struct regmap_config ad193x_spi_regmap_config = { | ||
391 | .val_bits = 8, | ||
392 | .reg_bits = 16, | ||
393 | .read_flag_mask = 0x09, | ||
394 | .write_flag_mask = 0x08, | ||
395 | }; | ||
396 | |||
391 | static int __devinit ad193x_spi_probe(struct spi_device *spi) | 397 | static int __devinit ad193x_spi_probe(struct spi_device *spi) |
392 | { | 398 | { |
393 | struct ad193x_priv *ad193x; | 399 | struct ad193x_priv *ad193x; |
@@ -397,20 +403,36 @@ static int __devinit ad193x_spi_probe(struct spi_device *spi) | |||
397 | if (ad193x == NULL) | 403 | if (ad193x == NULL) |
398 | return -ENOMEM; | 404 | return -ENOMEM; |
399 | 405 | ||
406 | ad193x->regmap = regmap_init_spi(spi, &ad193x_spi_regmap_config); | ||
407 | if (IS_ERR(ad193x->regmap)) { | ||
408 | ret = PTR_ERR(ad193x->regmap); | ||
409 | goto err_free; | ||
410 | } | ||
411 | |||
400 | spi_set_drvdata(spi, ad193x); | 412 | spi_set_drvdata(spi, ad193x); |
401 | ad193x->control_type = SND_SOC_SPI; | ||
402 | 413 | ||
403 | ret = snd_soc_register_codec(&spi->dev, | 414 | ret = snd_soc_register_codec(&spi->dev, |
404 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 415 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
405 | if (ret < 0) | 416 | if (ret < 0) |
406 | kfree(ad193x); | 417 | goto err_regmap_exit; |
418 | |||
419 | return 0; | ||
420 | |||
421 | err_regmap_exit: | ||
422 | regmap_exit(ad193x->regmap); | ||
423 | err_free: | ||
424 | kfree(ad193x); | ||
425 | |||
407 | return ret; | 426 | return ret; |
408 | } | 427 | } |
409 | 428 | ||
410 | static int __devexit ad193x_spi_remove(struct spi_device *spi) | 429 | static int __devexit ad193x_spi_remove(struct spi_device *spi) |
411 | { | 430 | { |
431 | struct ad193x_priv *ad193x = spi_get_drvdata(spi); | ||
432 | |||
412 | snd_soc_unregister_codec(&spi->dev); | 433 | snd_soc_unregister_codec(&spi->dev); |
413 | kfree(spi_get_drvdata(spi)); | 434 | regmap_exit(ad193x->regmap); |
435 | kfree(ad193x); | ||
414 | return 0; | 436 | return 0; |
415 | } | 437 | } |
416 | 438 | ||
@@ -425,6 +447,12 @@ static struct spi_driver ad193x_spi_driver = { | |||
425 | #endif | 447 | #endif |
426 | 448 | ||
427 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 449 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
450 | |||
451 | static const struct regmap_config ad193x_i2c_regmap_config = { | ||
452 | .val_bits = 8, | ||
453 | .reg_bits = 8, | ||
454 | }; | ||
455 | |||
428 | static const struct i2c_device_id ad193x_id[] = { | 456 | static const struct i2c_device_id ad193x_id[] = { |
429 | { "ad1936", 0 }, | 457 | { "ad1936", 0 }, |
430 | { "ad1937", 0 }, | 458 | { "ad1937", 0 }, |
@@ -442,20 +470,35 @@ static int __devinit ad193x_i2c_probe(struct i2c_client *client, | |||
442 | if (ad193x == NULL) | 470 | if (ad193x == NULL) |
443 | return -ENOMEM; | 471 | return -ENOMEM; |
444 | 472 | ||
473 | ad193x->regmap = regmap_init_i2c(client, &ad193x_i2c_regmap_config); | ||
474 | if (IS_ERR(ad193x->regmap)) { | ||
475 | ret = PTR_ERR(ad193x->regmap); | ||
476 | goto err_free; | ||
477 | } | ||
478 | |||
445 | i2c_set_clientdata(client, ad193x); | 479 | i2c_set_clientdata(client, ad193x); |
446 | ad193x->control_type = SND_SOC_I2C; | ||
447 | 480 | ||
448 | ret = snd_soc_register_codec(&client->dev, | 481 | ret = snd_soc_register_codec(&client->dev, |
449 | &soc_codec_dev_ad193x, &ad193x_dai, 1); | 482 | &soc_codec_dev_ad193x, &ad193x_dai, 1); |
450 | if (ret < 0) | 483 | if (ret < 0) |
451 | kfree(ad193x); | 484 | goto err_regmap_exit; |
485 | |||
486 | return 0; | ||
487 | |||
488 | err_regmap_exit: | ||
489 | regmap_exit(ad193x->regmap); | ||
490 | err_free: | ||
491 | kfree(ad193x); | ||
452 | return ret; | 492 | return ret; |
453 | } | 493 | } |
454 | 494 | ||
455 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) | 495 | static int __devexit ad193x_i2c_remove(struct i2c_client *client) |
456 | { | 496 | { |
497 | struct ad193x_priv *ad193x = i2c_get_clientdata(client); | ||
498 | |||
457 | snd_soc_unregister_codec(&client->dev); | 499 | snd_soc_unregister_codec(&client->dev); |
458 | kfree(i2c_get_clientdata(client)); | 500 | regmap_exit(ad193x->regmap); |
501 | kfree(ad193x); | ||
459 | return 0; | 502 | return 0; |
460 | } | 503 | } |
461 | 504 | ||
diff --git a/sound/soc/codecs/ad193x.h b/sound/soc/codecs/ad193x.h index cccc2e8e5fbd..536e5f2b136e 100644 --- a/sound/soc/codecs/ad193x.h +++ b/sound/soc/codecs/ad193x.h | |||
@@ -9,20 +9,20 @@ | |||
9 | #ifndef __AD193X_H__ | 9 | #ifndef __AD193X_H__ |
10 | #define __AD193X_H__ | 10 | #define __AD193X_H__ |
11 | 11 | ||
12 | #define AD193X_PLL_CLK_CTRL0 0x800 | 12 | #define AD193X_PLL_CLK_CTRL0 0x00 |
13 | #define AD193X_PLL_POWERDOWN 0x01 | 13 | #define AD193X_PLL_POWERDOWN 0x01 |
14 | #define AD193X_PLL_INPUT_MASK (~0x6) | 14 | #define AD193X_PLL_INPUT_MASK (~0x6) |
15 | #define AD193X_PLL_INPUT_256 (0 << 1) | 15 | #define AD193X_PLL_INPUT_256 (0 << 1) |
16 | #define AD193X_PLL_INPUT_384 (1 << 1) | 16 | #define AD193X_PLL_INPUT_384 (1 << 1) |
17 | #define AD193X_PLL_INPUT_512 (2 << 1) | 17 | #define AD193X_PLL_INPUT_512 (2 << 1) |
18 | #define AD193X_PLL_INPUT_768 (3 << 1) | 18 | #define AD193X_PLL_INPUT_768 (3 << 1) |
19 | #define AD193X_PLL_CLK_CTRL1 0x801 | 19 | #define AD193X_PLL_CLK_CTRL1 0x01 |
20 | #define AD193X_DAC_CTRL0 0x802 | 20 | #define AD193X_DAC_CTRL0 0x02 |
21 | #define AD193X_DAC_POWERDOWN 0x01 | 21 | #define AD193X_DAC_POWERDOWN 0x01 |
22 | #define AD193X_DAC_SERFMT_MASK 0xC0 | 22 | #define AD193X_DAC_SERFMT_MASK 0xC0 |
23 | #define AD193X_DAC_SERFMT_STEREO (0 << 6) | 23 | #define AD193X_DAC_SERFMT_STEREO (0 << 6) |
24 | #define AD193X_DAC_SERFMT_TDM (1 << 6) | 24 | #define AD193X_DAC_SERFMT_TDM (1 << 6) |
25 | #define AD193X_DAC_CTRL1 0x803 | 25 | #define AD193X_DAC_CTRL1 0x03 |
26 | #define AD193X_DAC_2_CHANNELS 0 | 26 | #define AD193X_DAC_2_CHANNELS 0 |
27 | #define AD193X_DAC_4_CHANNELS 1 | 27 | #define AD193X_DAC_4_CHANNELS 1 |
28 | #define AD193X_DAC_8_CHANNELS 2 | 28 | #define AD193X_DAC_8_CHANNELS 2 |
@@ -33,11 +33,11 @@ | |||
33 | #define AD193X_DAC_BCLK_MASTER (1 << 5) | 33 | #define AD193X_DAC_BCLK_MASTER (1 << 5) |
34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) | 34 | #define AD193X_DAC_LEFT_HIGH (1 << 3) |
35 | #define AD193X_DAC_BCLK_INV (1 << 7) | 35 | #define AD193X_DAC_BCLK_INV (1 << 7) |
36 | #define AD193X_DAC_CTRL2 0x804 | 36 | #define AD193X_DAC_CTRL2 0x04 |
37 | #define AD193X_DAC_WORD_LEN_SHFT 3 | 37 | #define AD193X_DAC_WORD_LEN_SHFT 3 |
38 | #define AD193X_DAC_WORD_LEN_MASK 0x18 | 38 | #define AD193X_DAC_WORD_LEN_MASK 0x18 |
39 | #define AD193X_DAC_MASTER_MUTE 1 | 39 | #define AD193X_DAC_MASTER_MUTE 1 |
40 | #define AD193X_DAC_CHNL_MUTE 0x805 | 40 | #define AD193X_DAC_CHNL_MUTE 0x05 |
41 | #define AD193X_DACL1_MUTE 0 | 41 | #define AD193X_DACL1_MUTE 0 |
42 | #define AD193X_DACR1_MUTE 1 | 42 | #define AD193X_DACR1_MUTE 1 |
43 | #define AD193X_DACL2_MUTE 2 | 43 | #define AD193X_DACL2_MUTE 2 |
@@ -46,28 +46,28 @@ | |||
46 | #define AD193X_DACR3_MUTE 5 | 46 | #define AD193X_DACR3_MUTE 5 |
47 | #define AD193X_DACL4_MUTE 6 | 47 | #define AD193X_DACL4_MUTE 6 |
48 | #define AD193X_DACR4_MUTE 7 | 48 | #define AD193X_DACR4_MUTE 7 |
49 | #define AD193X_DAC_L1_VOL 0x806 | 49 | #define AD193X_DAC_L1_VOL 0x06 |
50 | #define AD193X_DAC_R1_VOL 0x807 | 50 | #define AD193X_DAC_R1_VOL 0x07 |
51 | #define AD193X_DAC_L2_VOL 0x808 | 51 | #define AD193X_DAC_L2_VOL 0x08 |
52 | #define AD193X_DAC_R2_VOL 0x809 | 52 | #define AD193X_DAC_R2_VOL 0x09 |
53 | #define AD193X_DAC_L3_VOL 0x80a | 53 | #define AD193X_DAC_L3_VOL 0x0a |
54 | #define AD193X_DAC_R3_VOL 0x80b | 54 | #define AD193X_DAC_R3_VOL 0x0b |
55 | #define AD193X_DAC_L4_VOL 0x80c | 55 | #define AD193X_DAC_L4_VOL 0x0c |
56 | #define AD193X_DAC_R4_VOL 0x80d | 56 | #define AD193X_DAC_R4_VOL 0x0d |
57 | #define AD193X_ADC_CTRL0 0x80e | 57 | #define AD193X_ADC_CTRL0 0x0e |
58 | #define AD193X_ADC_POWERDOWN 0x01 | 58 | #define AD193X_ADC_POWERDOWN 0x01 |
59 | #define AD193X_ADC_HIGHPASS_FILTER 1 | 59 | #define AD193X_ADC_HIGHPASS_FILTER 1 |
60 | #define AD193X_ADCL1_MUTE 2 | 60 | #define AD193X_ADCL1_MUTE 2 |
61 | #define AD193X_ADCR1_MUTE 3 | 61 | #define AD193X_ADCR1_MUTE 3 |
62 | #define AD193X_ADCL2_MUTE 4 | 62 | #define AD193X_ADCL2_MUTE 4 |
63 | #define AD193X_ADCR2_MUTE 5 | 63 | #define AD193X_ADCR2_MUTE 5 |
64 | #define AD193X_ADC_CTRL1 0x80f | 64 | #define AD193X_ADC_CTRL1 0x0f |
65 | #define AD193X_ADC_SERFMT_MASK 0x60 | 65 | #define AD193X_ADC_SERFMT_MASK 0x60 |
66 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) | 66 | #define AD193X_ADC_SERFMT_STEREO (0 << 5) |
67 | #define AD193X_ADC_SERFMT_TDM (1 << 5) | 67 | #define AD193X_ADC_SERFMT_TDM (1 << 5) |
68 | #define AD193X_ADC_SERFMT_AUX (2 << 5) | 68 | #define AD193X_ADC_SERFMT_AUX (2 << 5) |
69 | #define AD193X_ADC_WORD_LEN_MASK 0x3 | 69 | #define AD193X_ADC_WORD_LEN_MASK 0x3 |
70 | #define AD193X_ADC_CTRL2 0x810 | 70 | #define AD193X_ADC_CTRL2 0x10 |
71 | #define AD193X_ADC_2_CHANNELS 0 | 71 | #define AD193X_ADC_2_CHANNELS 0 |
72 | #define AD193X_ADC_4_CHANNELS 1 | 72 | #define AD193X_ADC_4_CHANNELS 1 |
73 | #define AD193X_ADC_8_CHANNELS 2 | 73 | #define AD193X_ADC_8_CHANNELS 2 |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 923b364a3e41..4c0fc30a4ccb 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -200,18 +200,22 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
200 | } | 200 | } |
201 | 201 | ||
202 | /* Read out vendor ID to make sure it is ad1980 */ | 202 | /* Read out vendor ID to make sure it is ad1980 */ |
203 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) | 203 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { |
204 | ret = -ENODEV; | ||
204 | goto reset_err; | 205 | goto reset_err; |
206 | } | ||
205 | 207 | ||
206 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); | 208 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); |
207 | 209 | ||
208 | if (vendor_id2 != 0x5370) { | 210 | if (vendor_id2 != 0x5370) { |
209 | if (vendor_id2 != 0x5374) | 211 | if (vendor_id2 != 0x5374) { |
212 | ret = -ENODEV; | ||
210 | goto reset_err; | 213 | goto reset_err; |
211 | else | 214 | } else { |
212 | printk(KERN_WARNING "ad1980: " | 215 | printk(KERN_WARNING "ad1980: " |
213 | "Found AD1981 - only 2/2 IN/OUT Channels " | 216 | "Found AD1981 - only 2/2 IN/OUT Channels " |
214 | "supported\n"); | 217 | "supported\n"); |
218 | } | ||
215 | } | 219 | } |
216 | 220 | ||
217 | /* unmute captures and playbacks volume */ | 221 | /* unmute captures and playbacks volume */ |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c new file mode 100644 index 000000000000..2aa40c3731d0 --- /dev/null +++ b/sound/soc/codecs/adau1373.c | |||
@@ -0,0 +1,1414 @@ | |||
1 | /* | ||
2 | * Analog Devices ADAU1373 Audio Codec drive | ||
3 | * | ||
4 | * Copyright 2011 Analog Devices Inc. | ||
5 | * Author: Lars-Peter Clausen <lars@metafoo.de> | ||
6 | * | ||
7 | * Licensed under the GPL-2 or later. | ||
8 | */ | ||
9 | |||
10 | #include <linux/module.h> | ||
11 | #include <linux/init.h> | ||
12 | #include <linux/delay.h> | ||
13 | #include <linux/pm.h> | ||
14 | #include <linux/i2c.h> | ||
15 | #include <linux/slab.h> | ||
16 | #include <linux/gcd.h> | ||
17 | |||
18 | #include <sound/core.h> | ||
19 | #include <sound/pcm.h> | ||
20 | #include <sound/pcm_params.h> | ||
21 | #include <sound/tlv.h> | ||
22 | #include <sound/soc.h> | ||
23 | #include <sound/adau1373.h> | ||
24 | |||
25 | #include "adau1373.h" | ||
26 | |||
27 | struct adau1373_dai { | ||
28 | unsigned int clk_src; | ||
29 | unsigned int sysclk; | ||
30 | bool enable_src; | ||
31 | bool master; | ||
32 | }; | ||
33 | |||
34 | struct adau1373 { | ||
35 | struct adau1373_dai dais[3]; | ||
36 | }; | ||
37 | |||
38 | #define ADAU1373_INPUT_MODE 0x00 | ||
39 | #define ADAU1373_AINL_CTRL(x) (0x01 + (x) * 2) | ||
40 | #define ADAU1373_AINR_CTRL(x) (0x02 + (x) * 2) | ||
41 | #define ADAU1373_LLINE_OUT(x) (0x9 + (x) * 2) | ||
42 | #define ADAU1373_RLINE_OUT(x) (0xa + (x) * 2) | ||
43 | #define ADAU1373_LSPK_OUT 0x0d | ||
44 | #define ADAU1373_RSPK_OUT 0x0e | ||
45 | #define ADAU1373_LHP_OUT 0x0f | ||
46 | #define ADAU1373_RHP_OUT 0x10 | ||
47 | #define ADAU1373_ADC_GAIN 0x11 | ||
48 | #define ADAU1373_LADC_MIXER 0x12 | ||
49 | #define ADAU1373_RADC_MIXER 0x13 | ||
50 | #define ADAU1373_LLINE1_MIX 0x14 | ||
51 | #define ADAU1373_RLINE1_MIX 0x15 | ||
52 | #define ADAU1373_LLINE2_MIX 0x16 | ||
53 | #define ADAU1373_RLINE2_MIX 0x17 | ||
54 | #define ADAU1373_LSPK_MIX 0x18 | ||
55 | #define ADAU1373_RSPK_MIX 0x19 | ||
56 | #define ADAU1373_LHP_MIX 0x1a | ||
57 | #define ADAU1373_RHP_MIX 0x1b | ||
58 | #define ADAU1373_EP_MIX 0x1c | ||
59 | #define ADAU1373_HP_CTRL 0x1d | ||
60 | #define ADAU1373_HP_CTRL2 0x1e | ||
61 | #define ADAU1373_LS_CTRL 0x1f | ||
62 | #define ADAU1373_EP_CTRL 0x21 | ||
63 | #define ADAU1373_MICBIAS_CTRL1 0x22 | ||
64 | #define ADAU1373_MICBIAS_CTRL2 0x23 | ||
65 | #define ADAU1373_OUTPUT_CTRL 0x24 | ||
66 | #define ADAU1373_PWDN_CTRL1 0x25 | ||
67 | #define ADAU1373_PWDN_CTRL2 0x26 | ||
68 | #define ADAU1373_PWDN_CTRL3 0x27 | ||
69 | #define ADAU1373_DPLL_CTRL(x) (0x28 + (x) * 7) | ||
70 | #define ADAU1373_PLL_CTRL1(x) (0x29 + (x) * 7) | ||
71 | #define ADAU1373_PLL_CTRL2(x) (0x2a + (x) * 7) | ||
72 | #define ADAU1373_PLL_CTRL3(x) (0x2b + (x) * 7) | ||
73 | #define ADAU1373_PLL_CTRL4(x) (0x2c + (x) * 7) | ||
74 | #define ADAU1373_PLL_CTRL5(x) (0x2d + (x) * 7) | ||
75 | #define ADAU1373_PLL_CTRL6(x) (0x2e + (x) * 7) | ||
76 | #define ADAU1373_PLL_CTRL7(x) (0x2f + (x) * 7) | ||
77 | #define ADAU1373_HEADDECT 0x36 | ||
78 | #define ADAU1373_ADC_DAC_STATUS 0x37 | ||
79 | #define ADAU1373_ADC_CTRL 0x3c | ||
80 | #define ADAU1373_DAI(x) (0x44 + (x)) | ||
81 | #define ADAU1373_CLK_SRC_DIV(x) (0x40 + (x) * 2) | ||
82 | #define ADAU1373_BCLKDIV(x) (0x47 + (x)) | ||
83 | #define ADAU1373_SRC_RATIOA(x) (0x4a + (x) * 2) | ||
84 | #define ADAU1373_SRC_RATIOB(x) (0x4b + (x) * 2) | ||
85 | #define ADAU1373_DEEMP_CTRL 0x50 | ||
86 | #define ADAU1373_SRC_DAI_CTRL(x) (0x51 + (x)) | ||
87 | #define ADAU1373_DIN_MIX_CTRL(x) (0x56 + (x)) | ||
88 | #define ADAU1373_DOUT_MIX_CTRL(x) (0x5b + (x)) | ||
89 | #define ADAU1373_DAI_PBL_VOL(x) (0x62 + (x) * 2) | ||
90 | #define ADAU1373_DAI_PBR_VOL(x) (0x63 + (x) * 2) | ||
91 | #define ADAU1373_DAI_RECL_VOL(x) (0x68 + (x) * 2) | ||
92 | #define ADAU1373_DAI_RECR_VOL(x) (0x69 + (x) * 2) | ||
93 | #define ADAU1373_DAC1_PBL_VOL 0x6e | ||
94 | #define ADAU1373_DAC1_PBR_VOL 0x6f | ||
95 | #define ADAU1373_DAC2_PBL_VOL 0x70 | ||
96 | #define ADAU1373_DAC2_PBR_VOL 0x71 | ||
97 | #define ADAU1373_ADC_RECL_VOL 0x72 | ||
98 | #define ADAU1373_ADC_RECR_VOL 0x73 | ||
99 | #define ADAU1373_DMIC_RECL_VOL 0x74 | ||
100 | #define ADAU1373_DMIC_RECR_VOL 0x75 | ||
101 | #define ADAU1373_VOL_GAIN1 0x76 | ||
102 | #define ADAU1373_VOL_GAIN2 0x77 | ||
103 | #define ADAU1373_VOL_GAIN3 0x78 | ||
104 | #define ADAU1373_HPF_CTRL 0x7d | ||
105 | #define ADAU1373_BASS1 0x7e | ||
106 | #define ADAU1373_BASS2 0x7f | ||
107 | #define ADAU1373_DRC(x) (0x80 + (x) * 0x10) | ||
108 | #define ADAU1373_3D_CTRL1 0xc0 | ||
109 | #define ADAU1373_3D_CTRL2 0xc1 | ||
110 | #define ADAU1373_FDSP_SEL1 0xdc | ||
111 | #define ADAU1373_FDSP_SEL2 0xdd | ||
112 | #define ADAU1373_FDSP_SEL3 0xde | ||
113 | #define ADAU1373_FDSP_SEL4 0xdf | ||
114 | #define ADAU1373_DIGMICCTRL 0xe2 | ||
115 | #define ADAU1373_DIGEN 0xeb | ||
116 | #define ADAU1373_SOFT_RESET 0xff | ||
117 | |||
118 | |||
119 | #define ADAU1373_PLL_CTRL6_DPLL_BYPASS BIT(1) | ||
120 | #define ADAU1373_PLL_CTRL6_PLL_EN BIT(0) | ||
121 | |||
122 | #define ADAU1373_DAI_INVERT_BCLK BIT(7) | ||
123 | #define ADAU1373_DAI_MASTER BIT(6) | ||
124 | #define ADAU1373_DAI_INVERT_LRCLK BIT(4) | ||
125 | #define ADAU1373_DAI_WLEN_16 0x0 | ||
126 | #define ADAU1373_DAI_WLEN_20 0x4 | ||
127 | #define ADAU1373_DAI_WLEN_24 0x8 | ||
128 | #define ADAU1373_DAI_WLEN_32 0xc | ||
129 | #define ADAU1373_DAI_WLEN_MASK 0xc | ||
130 | #define ADAU1373_DAI_FORMAT_RIGHT_J 0x0 | ||
131 | #define ADAU1373_DAI_FORMAT_LEFT_J 0x1 | ||
132 | #define ADAU1373_DAI_FORMAT_I2S 0x2 | ||
133 | #define ADAU1373_DAI_FORMAT_DSP 0x3 | ||
134 | |||
135 | #define ADAU1373_BCLKDIV_SOURCE BIT(5) | ||
136 | #define ADAU1373_BCLKDIV_32 0x03 | ||
137 | #define ADAU1373_BCLKDIV_64 0x02 | ||
138 | #define ADAU1373_BCLKDIV_128 0x01 | ||
139 | #define ADAU1373_BCLKDIV_256 0x00 | ||
140 | |||
141 | #define ADAU1373_ADC_CTRL_PEAK_DETECT BIT(0) | ||
142 | #define ADAU1373_ADC_CTRL_RESET BIT(1) | ||
143 | #define ADAU1373_ADC_CTRL_RESET_FORCE BIT(2) | ||
144 | |||
145 | #define ADAU1373_OUTPUT_CTRL_LDIFF BIT(3) | ||
146 | #define ADAU1373_OUTPUT_CTRL_LNFBEN BIT(2) | ||
147 | |||
148 | #define ADAU1373_PWDN_CTRL3_PWR_EN BIT(0) | ||
149 | |||
150 | #define ADAU1373_EP_CTRL_MICBIAS1_OFFSET 4 | ||
151 | #define ADAU1373_EP_CTRL_MICBIAS2_OFFSET 2 | ||
152 | |||
153 | static const uint8_t adau1373_default_regs[] = { | ||
154 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x00 */ | ||
155 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
156 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x10 */ | ||
157 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
158 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x20 */ | ||
159 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, | ||
160 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, /* 0x30 */ | ||
161 | 0x00, 0x00, 0x00, 0x80, 0x00, 0x01, 0x00, 0x00, | ||
162 | 0x00, 0x00, 0x00, 0x00, 0x0a, 0x0a, 0x0a, 0x00, /* 0x40 */ | ||
163 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
164 | 0x00, 0x08, 0x08, 0x08, 0x00, 0x00, 0x00, 0x00, /* 0x50 */ | ||
165 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
166 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x60 */ | ||
167 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
168 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0x70 */ | ||
169 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
170 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x80 */ | ||
171 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
172 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0x90 */ | ||
173 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
174 | 0x78, 0x18, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x00, /* 0xa0 */ | ||
175 | 0x00, 0xc0, 0x88, 0x7a, 0xdf, 0x20, 0x00, 0x00, | ||
176 | 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xff, /* 0xb0 */ | ||
177 | 0xff, 0xff, 0xff, 0xff, 0xff, 0x1f, 0x00, 0x00, | ||
178 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xc0 */ | ||
179 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
180 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0xd0 */ | ||
181 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | ||
182 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, /* 0xe0 */ | ||
183 | 0x00, 0x1f, 0x0f, 0x00, 0x00, | ||
184 | }; | ||
185 | |||
186 | static const unsigned int adau1373_out_tlv[] = { | ||
187 | TLV_DB_RANGE_HEAD(4), | ||
188 | 0, 7, TLV_DB_SCALE_ITEM(-7900, 400, 1), | ||
189 | 8, 15, TLV_DB_SCALE_ITEM(-4700, 300, 0), | ||
190 | 16, 23, TLV_DB_SCALE_ITEM(-2300, 200, 0), | ||
191 | 24, 31, TLV_DB_SCALE_ITEM(-700, 100, 0), | ||
192 | }; | ||
193 | |||
194 | static const DECLARE_TLV_DB_MINMAX(adau1373_digital_tlv, -9563, 0); | ||
195 | static const DECLARE_TLV_DB_SCALE(adau1373_in_pga_tlv, -1300, 100, 1); | ||
196 | static const DECLARE_TLV_DB_SCALE(adau1373_ep_tlv, -600, 600, 1); | ||
197 | |||
198 | static const DECLARE_TLV_DB_SCALE(adau1373_input_boost_tlv, 0, 2000, 0); | ||
199 | static const DECLARE_TLV_DB_SCALE(adau1373_gain_boost_tlv, 0, 600, 0); | ||
200 | static const DECLARE_TLV_DB_SCALE(adau1373_speaker_boost_tlv, 1200, 600, 0); | ||
201 | |||
202 | static const char *adau1373_fdsp_sel_text[] = { | ||
203 | "None", | ||
204 | "Channel 1", | ||
205 | "Channel 2", | ||
206 | "Channel 3", | ||
207 | "Channel 4", | ||
208 | "Channel 5", | ||
209 | }; | ||
210 | |||
211 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc1_channel_enum, | ||
212 | ADAU1373_FDSP_SEL1, 4, adau1373_fdsp_sel_text); | ||
213 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc2_channel_enum, | ||
214 | ADAU1373_FDSP_SEL1, 0, adau1373_fdsp_sel_text); | ||
215 | static const SOC_ENUM_SINGLE_DECL(adau1373_drc3_channel_enum, | ||
216 | ADAU1373_FDSP_SEL2, 0, adau1373_fdsp_sel_text); | ||
217 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_channel_enum, | ||
218 | ADAU1373_FDSP_SEL3, 0, adau1373_fdsp_sel_text); | ||
219 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_channel_enum, | ||
220 | ADAU1373_FDSP_SEL4, 4, adau1373_fdsp_sel_text); | ||
221 | |||
222 | static const char *adau1373_hpf_cutoff_text[] = { | ||
223 | "3.7Hz", "50Hz", "100Hz", "150Hz", "200Hz", "250Hz", "300Hz", "350Hz", | ||
224 | "400Hz", "450Hz", "500Hz", "550Hz", "600Hz", "650Hz", "700Hz", "750Hz", | ||
225 | "800Hz", | ||
226 | }; | ||
227 | |||
228 | static const SOC_ENUM_SINGLE_DECL(adau1373_hpf_cutoff_enum, | ||
229 | ADAU1373_HPF_CTRL, 3, adau1373_hpf_cutoff_text); | ||
230 | |||
231 | static const char *adau1373_bass_lpf_cutoff_text[] = { | ||
232 | "801Hz", "1001Hz", | ||
233 | }; | ||
234 | |||
235 | static const char *adau1373_bass_clip_level_text[] = { | ||
236 | "0.125", "0.250", "0.370", "0.500", "0.625", "0.750", "0.875", | ||
237 | }; | ||
238 | |||
239 | static const unsigned int adau1373_bass_clip_level_values[] = { | ||
240 | 1, 2, 3, 4, 5, 6, 7, | ||
241 | }; | ||
242 | |||
243 | static const char *adau1373_bass_hpf_cutoff_text[] = { | ||
244 | "158Hz", "232Hz", "347Hz", "520Hz", | ||
245 | }; | ||
246 | |||
247 | static const unsigned int adau1373_bass_tlv[] = { | ||
248 | TLV_DB_RANGE_HEAD(4), | ||
249 | 0, 2, TLV_DB_SCALE_ITEM(-600, 600, 1), | ||
250 | 3, 4, TLV_DB_SCALE_ITEM(950, 250, 0), | ||
251 | 5, 7, TLV_DB_SCALE_ITEM(1400, 150, 0), | ||
252 | }; | ||
253 | |||
254 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_lpf_cutoff_enum, | ||
255 | ADAU1373_BASS1, 5, adau1373_bass_lpf_cutoff_text); | ||
256 | |||
257 | static const SOC_VALUE_ENUM_SINGLE_DECL(adau1373_bass_clip_level_enum, | ||
258 | ADAU1373_BASS1, 2, 7, adau1373_bass_clip_level_text, | ||
259 | adau1373_bass_clip_level_values); | ||
260 | |||
261 | static const SOC_ENUM_SINGLE_DECL(adau1373_bass_hpf_cutoff_enum, | ||
262 | ADAU1373_BASS1, 0, adau1373_bass_hpf_cutoff_text); | ||
263 | |||
264 | static const char *adau1373_3d_level_text[] = { | ||
265 | "0%", "6.67%", "13.33%", "20%", "26.67%", "33.33%", | ||
266 | "40%", "46.67%", "53.33%", "60%", "66.67%", "73.33%", | ||
267 | "80%", "86.67", "99.33%", "100%" | ||
268 | }; | ||
269 | |||
270 | static const char *adau1373_3d_cutoff_text[] = { | ||
271 | "No 3D", "0.03125 fs", "0.04583 fs", "0.075 fs", "0.11458 fs", | ||
272 | "0.16875 fs", "0.27083 fs" | ||
273 | }; | ||
274 | |||
275 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_level_enum, | ||
276 | ADAU1373_3D_CTRL1, 4, adau1373_3d_level_text); | ||
277 | static const SOC_ENUM_SINGLE_DECL(adau1373_3d_cutoff_enum, | ||
278 | ADAU1373_3D_CTRL1, 0, adau1373_3d_cutoff_text); | ||
279 | |||
280 | static const unsigned int adau1373_3d_tlv[] = { | ||
281 | TLV_DB_RANGE_HEAD(2), | ||
282 | 0, 0, TLV_DB_SCALE_ITEM(0, 0, 0), | ||
283 | 1, 7, TLV_DB_LINEAR_ITEM(-1800, -120), | ||
284 | }; | ||
285 | |||
286 | static const char *adau1373_lr_mux_text[] = { | ||
287 | "Mute", | ||
288 | "Right Channel (L+R)", | ||
289 | "Left Channel (L+R)", | ||
290 | "Stereo", | ||
291 | }; | ||
292 | |||
293 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout1_lr_mux_enum, | ||
294 | ADAU1373_OUTPUT_CTRL, 4, adau1373_lr_mux_text); | ||
295 | static const SOC_ENUM_SINGLE_DECL(adau1373_lineout2_lr_mux_enum, | ||
296 | ADAU1373_OUTPUT_CTRL, 6, adau1373_lr_mux_text); | ||
297 | static const SOC_ENUM_SINGLE_DECL(adau1373_speaker_lr_mux_enum, | ||
298 | ADAU1373_LS_CTRL, 4, adau1373_lr_mux_text); | ||
299 | |||
300 | static const struct snd_kcontrol_new adau1373_controls[] = { | ||
301 | SOC_DOUBLE_R_TLV("AIF1 Capture Volume", ADAU1373_DAI_RECL_VOL(0), | ||
302 | ADAU1373_DAI_RECR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), | ||
303 | SOC_DOUBLE_R_TLV("AIF2 Capture Volume", ADAU1373_DAI_RECL_VOL(1), | ||
304 | ADAU1373_DAI_RECR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), | ||
305 | SOC_DOUBLE_R_TLV("AIF3 Capture Volume", ADAU1373_DAI_RECL_VOL(2), | ||
306 | ADAU1373_DAI_RECR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), | ||
307 | |||
308 | SOC_DOUBLE_R_TLV("ADC Capture Volume", ADAU1373_ADC_RECL_VOL, | ||
309 | ADAU1373_ADC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
310 | SOC_DOUBLE_R_TLV("DMIC Capture Volume", ADAU1373_DMIC_RECL_VOL, | ||
311 | ADAU1373_DMIC_RECR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
312 | |||
313 | SOC_DOUBLE_R_TLV("AIF1 Playback Volume", ADAU1373_DAI_PBL_VOL(0), | ||
314 | ADAU1373_DAI_PBR_VOL(0), 0, 0xff, 1, adau1373_digital_tlv), | ||
315 | SOC_DOUBLE_R_TLV("AIF2 Playback Volume", ADAU1373_DAI_PBL_VOL(1), | ||
316 | ADAU1373_DAI_PBR_VOL(1), 0, 0xff, 1, adau1373_digital_tlv), | ||
317 | SOC_DOUBLE_R_TLV("AIF3 Playback Volume", ADAU1373_DAI_PBL_VOL(2), | ||
318 | ADAU1373_DAI_PBR_VOL(2), 0, 0xff, 1, adau1373_digital_tlv), | ||
319 | |||
320 | SOC_DOUBLE_R_TLV("DAC1 Playback Volume", ADAU1373_DAC1_PBL_VOL, | ||
321 | ADAU1373_DAC1_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
322 | SOC_DOUBLE_R_TLV("DAC2 Playback Volume", ADAU1373_DAC2_PBL_VOL, | ||
323 | ADAU1373_DAC2_PBR_VOL, 0, 0xff, 1, adau1373_digital_tlv), | ||
324 | |||
325 | SOC_DOUBLE_R_TLV("Lineout1 Playback Volume", ADAU1373_LLINE_OUT(0), | ||
326 | ADAU1373_RLINE_OUT(0), 0, 0x1f, 0, adau1373_out_tlv), | ||
327 | SOC_DOUBLE_R_TLV("Speaker Playback Volume", ADAU1373_LSPK_OUT, | ||
328 | ADAU1373_RSPK_OUT, 0, 0x1f, 0, adau1373_out_tlv), | ||
329 | SOC_DOUBLE_R_TLV("Headphone Playback Volume", ADAU1373_LHP_OUT, | ||
330 | ADAU1373_RHP_OUT, 0, 0x1f, 0, adau1373_out_tlv), | ||
331 | |||
332 | SOC_DOUBLE_R_TLV("Input 1 Capture Volume", ADAU1373_AINL_CTRL(0), | ||
333 | ADAU1373_AINR_CTRL(0), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
334 | SOC_DOUBLE_R_TLV("Input 2 Capture Volume", ADAU1373_AINL_CTRL(1), | ||
335 | ADAU1373_AINR_CTRL(1), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
336 | SOC_DOUBLE_R_TLV("Input 3 Capture Volume", ADAU1373_AINL_CTRL(2), | ||
337 | ADAU1373_AINR_CTRL(2), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
338 | SOC_DOUBLE_R_TLV("Input 4 Capture Volume", ADAU1373_AINL_CTRL(3), | ||
339 | ADAU1373_AINR_CTRL(3), 0, 0x1f, 0, adau1373_in_pga_tlv), | ||
340 | |||
341 | SOC_SINGLE_TLV("Earpiece Playback Volume", ADAU1373_EP_CTRL, 0, 3, 0, | ||
342 | adau1373_ep_tlv), | ||
343 | |||
344 | SOC_DOUBLE_TLV("AIF3 Boost Playback Volume", ADAU1373_VOL_GAIN1, 4, 5, | ||
345 | 1, 0, adau1373_gain_boost_tlv), | ||
346 | SOC_DOUBLE_TLV("AIF2 Boost Playback Volume", ADAU1373_VOL_GAIN1, 2, 3, | ||
347 | 1, 0, adau1373_gain_boost_tlv), | ||
348 | SOC_DOUBLE_TLV("AIF1 Boost Playback Volume", ADAU1373_VOL_GAIN1, 0, 1, | ||
349 | 1, 0, adau1373_gain_boost_tlv), | ||
350 | SOC_DOUBLE_TLV("AIF3 Boost Capture Volume", ADAU1373_VOL_GAIN2, 4, 5, | ||
351 | 1, 0, adau1373_gain_boost_tlv), | ||
352 | SOC_DOUBLE_TLV("AIF2 Boost Capture Volume", ADAU1373_VOL_GAIN2, 2, 3, | ||
353 | 1, 0, adau1373_gain_boost_tlv), | ||
354 | SOC_DOUBLE_TLV("AIF1 Boost Capture Volume", ADAU1373_VOL_GAIN2, 0, 1, | ||
355 | 1, 0, adau1373_gain_boost_tlv), | ||
356 | SOC_DOUBLE_TLV("DMIC Boost Capture Volume", ADAU1373_VOL_GAIN3, 6, 7, | ||
357 | 1, 0, adau1373_gain_boost_tlv), | ||
358 | SOC_DOUBLE_TLV("ADC Boost Capture Volume", ADAU1373_VOL_GAIN3, 4, 5, | ||
359 | 1, 0, adau1373_gain_boost_tlv), | ||
360 | SOC_DOUBLE_TLV("DAC2 Boost Playback Volume", ADAU1373_VOL_GAIN3, 2, 3, | ||
361 | 1, 0, adau1373_gain_boost_tlv), | ||
362 | SOC_DOUBLE_TLV("DAC1 Boost Playback Volume", ADAU1373_VOL_GAIN3, 0, 1, | ||
363 | 1, 0, adau1373_gain_boost_tlv), | ||
364 | |||
365 | SOC_DOUBLE_TLV("Input 1 Boost Capture Volume", ADAU1373_ADC_GAIN, 0, 4, | ||
366 | 1, 0, adau1373_input_boost_tlv), | ||
367 | SOC_DOUBLE_TLV("Input 2 Boost Capture Volume", ADAU1373_ADC_GAIN, 1, 5, | ||
368 | 1, 0, adau1373_input_boost_tlv), | ||
369 | SOC_DOUBLE_TLV("Input 3 Boost Capture Volume", ADAU1373_ADC_GAIN, 2, 6, | ||
370 | 1, 0, adau1373_input_boost_tlv), | ||
371 | SOC_DOUBLE_TLV("Input 4 Boost Capture Volume", ADAU1373_ADC_GAIN, 3, 7, | ||
372 | 1, 0, adau1373_input_boost_tlv), | ||
373 | |||
374 | SOC_DOUBLE_TLV("Speaker Boost Playback Volume", ADAU1373_LS_CTRL, 2, 3, | ||
375 | 1, 0, adau1373_speaker_boost_tlv), | ||
376 | |||
377 | SOC_ENUM("Lineout1 LR Mux", adau1373_lineout1_lr_mux_enum), | ||
378 | SOC_ENUM("Speaker LR Mux", adau1373_speaker_lr_mux_enum), | ||
379 | |||
380 | SOC_ENUM("HPF Cutoff", adau1373_hpf_cutoff_enum), | ||
381 | SOC_DOUBLE("HPF Switch", ADAU1373_HPF_CTRL, 1, 0, 1, 0), | ||
382 | SOC_ENUM("HPF Channel", adau1373_hpf_channel_enum), | ||
383 | |||
384 | SOC_ENUM("Bass HPF Cutoff", adau1373_bass_hpf_cutoff_enum), | ||
385 | SOC_VALUE_ENUM("Bass Clip Level Threshold", | ||
386 | adau1373_bass_clip_level_enum), | ||
387 | SOC_ENUM("Bass LPF Cutoff", adau1373_bass_lpf_cutoff_enum), | ||
388 | SOC_DOUBLE("Bass Playback Switch", ADAU1373_BASS2, 0, 1, 1, 0), | ||
389 | SOC_SINGLE_TLV("Bass Playback Volume", ADAU1373_BASS2, 2, 7, 0, | ||
390 | adau1373_bass_tlv), | ||
391 | SOC_ENUM("Bass Channel", adau1373_bass_channel_enum), | ||
392 | |||
393 | SOC_ENUM("3D Freq", adau1373_3d_cutoff_enum), | ||
394 | SOC_ENUM("3D Level", adau1373_3d_level_enum), | ||
395 | SOC_SINGLE("3D Playback Switch", ADAU1373_3D_CTRL2, 0, 1, 0), | ||
396 | SOC_SINGLE_TLV("3D Playback Volume", ADAU1373_3D_CTRL2, 2, 7, 0, | ||
397 | adau1373_3d_tlv), | ||
398 | SOC_ENUM("3D Channel", adau1373_bass_channel_enum), | ||
399 | |||
400 | SOC_SINGLE("Zero Cross Switch", ADAU1373_PWDN_CTRL3, 7, 1, 0), | ||
401 | }; | ||
402 | |||
403 | static const struct snd_kcontrol_new adau1373_lineout2_controls[] = { | ||
404 | SOC_DOUBLE_R_TLV("Lineout2 Playback Volume", ADAU1373_LLINE_OUT(1), | ||
405 | ADAU1373_RLINE_OUT(1), 0, 0x1f, 0, adau1373_out_tlv), | ||
406 | SOC_ENUM("Lineout2 LR Mux", adau1373_lineout2_lr_mux_enum), | ||
407 | }; | ||
408 | |||
409 | static const struct snd_kcontrol_new adau1373_drc_controls[] = { | ||
410 | SOC_ENUM("DRC1 Channel", adau1373_drc1_channel_enum), | ||
411 | SOC_ENUM("DRC2 Channel", adau1373_drc2_channel_enum), | ||
412 | SOC_ENUM("DRC3 Channel", adau1373_drc3_channel_enum), | ||
413 | }; | ||
414 | |||
415 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, | ||
416 | struct snd_kcontrol *kcontrol, int event) | ||
417 | { | ||
418 | struct snd_soc_codec *codec = w->codec; | ||
419 | unsigned int pll_id = w->name[3] - '1'; | ||
420 | unsigned int val; | ||
421 | |||
422 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
423 | val = ADAU1373_PLL_CTRL6_PLL_EN; | ||
424 | else | ||
425 | val = 0; | ||
426 | |||
427 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
428 | ADAU1373_PLL_CTRL6_PLL_EN, val); | ||
429 | |||
430 | if (SND_SOC_DAPM_EVENT_ON(event)) | ||
431 | mdelay(5); | ||
432 | |||
433 | return 0; | ||
434 | } | ||
435 | |||
436 | static const char *adau1373_decimator_text[] = { | ||
437 | "ADC", | ||
438 | "DMIC1", | ||
439 | }; | ||
440 | |||
441 | static const struct soc_enum adau1373_decimator_enum = | ||
442 | SOC_ENUM_SINGLE(0, 0, 2, adau1373_decimator_text); | ||
443 | |||
444 | static const struct snd_kcontrol_new adau1373_decimator_mux = | ||
445 | SOC_DAPM_ENUM_VIRT("Decimator Mux", adau1373_decimator_enum); | ||
446 | |||
447 | static const struct snd_kcontrol_new adau1373_left_adc_mixer_controls[] = { | ||
448 | SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_LADC_MIXER, 4, 1, 0), | ||
449 | SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_LADC_MIXER, 3, 1, 0), | ||
450 | SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_LADC_MIXER, 2, 1, 0), | ||
451 | SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_LADC_MIXER, 1, 1, 0), | ||
452 | SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_LADC_MIXER, 0, 1, 0), | ||
453 | }; | ||
454 | |||
455 | static const struct snd_kcontrol_new adau1373_right_adc_mixer_controls[] = { | ||
456 | SOC_DAPM_SINGLE("DAC1 Switch", ADAU1373_RADC_MIXER, 4, 1, 0), | ||
457 | SOC_DAPM_SINGLE("Input 4 Switch", ADAU1373_RADC_MIXER, 3, 1, 0), | ||
458 | SOC_DAPM_SINGLE("Input 3 Switch", ADAU1373_RADC_MIXER, 2, 1, 0), | ||
459 | SOC_DAPM_SINGLE("Input 2 Switch", ADAU1373_RADC_MIXER, 1, 1, 0), | ||
460 | SOC_DAPM_SINGLE("Input 1 Switch", ADAU1373_RADC_MIXER, 0, 1, 0), | ||
461 | }; | ||
462 | |||
463 | #define DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(_name, _reg) \ | ||
464 | const struct snd_kcontrol_new _name[] = { \ | ||
465 | SOC_DAPM_SINGLE("Left DAC2 Switch", _reg, 7, 1, 0), \ | ||
466 | SOC_DAPM_SINGLE("Right DAC2 Switch", _reg, 6, 1, 0), \ | ||
467 | SOC_DAPM_SINGLE("Left DAC1 Switch", _reg, 5, 1, 0), \ | ||
468 | SOC_DAPM_SINGLE("Right DAC1 Switch", _reg, 4, 1, 0), \ | ||
469 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", _reg, 3, 1, 0), \ | ||
470 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", _reg, 2, 1, 0), \ | ||
471 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", _reg, 1, 1, 0), \ | ||
472 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", _reg, 0, 1, 0), \ | ||
473 | } | ||
474 | |||
475 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line1_mixer_controls, | ||
476 | ADAU1373_LLINE1_MIX); | ||
477 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line1_mixer_controls, | ||
478 | ADAU1373_RLINE1_MIX); | ||
479 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_line2_mixer_controls, | ||
480 | ADAU1373_LLINE2_MIX); | ||
481 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_line2_mixer_controls, | ||
482 | ADAU1373_RLINE2_MIX); | ||
483 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_left_spk_mixer_controls, | ||
484 | ADAU1373_LSPK_MIX); | ||
485 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_right_spk_mixer_controls, | ||
486 | ADAU1373_RSPK_MIX); | ||
487 | static DECLARE_ADAU1373_OUTPUT_MIXER_CTRLS(adau1373_ep_mixer_controls, | ||
488 | ADAU1373_EP_MIX); | ||
489 | |||
490 | static const struct snd_kcontrol_new adau1373_left_hp_mixer_controls[] = { | ||
491 | SOC_DAPM_SINGLE("Left DAC1 Switch", ADAU1373_LHP_MIX, 5, 1, 0), | ||
492 | SOC_DAPM_SINGLE("Left DAC2 Switch", ADAU1373_LHP_MIX, 4, 1, 0), | ||
493 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_LHP_MIX, 3, 1, 0), | ||
494 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_LHP_MIX, 2, 1, 0), | ||
495 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_LHP_MIX, 1, 1, 0), | ||
496 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_LHP_MIX, 0, 1, 0), | ||
497 | }; | ||
498 | |||
499 | static const struct snd_kcontrol_new adau1373_right_hp_mixer_controls[] = { | ||
500 | SOC_DAPM_SINGLE("Right DAC1 Switch", ADAU1373_RHP_MIX, 5, 1, 0), | ||
501 | SOC_DAPM_SINGLE("Right DAC2 Switch", ADAU1373_RHP_MIX, 4, 1, 0), | ||
502 | SOC_DAPM_SINGLE("Input 4 Bypass Switch", ADAU1373_RHP_MIX, 3, 1, 0), | ||
503 | SOC_DAPM_SINGLE("Input 3 Bypass Switch", ADAU1373_RHP_MIX, 2, 1, 0), | ||
504 | SOC_DAPM_SINGLE("Input 2 Bypass Switch", ADAU1373_RHP_MIX, 1, 1, 0), | ||
505 | SOC_DAPM_SINGLE("Input 1 Bypass Switch", ADAU1373_RHP_MIX, 0, 1, 0), | ||
506 | }; | ||
507 | |||
508 | #define DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(_name, _reg) \ | ||
509 | const struct snd_kcontrol_new _name[] = { \ | ||
510 | SOC_DAPM_SINGLE("DMIC2 Swapped Switch", _reg, 6, 1, 0), \ | ||
511 | SOC_DAPM_SINGLE("DMIC2 Switch", _reg, 5, 1, 0), \ | ||
512 | SOC_DAPM_SINGLE("ADC/DMIC1 Swapped Switch", _reg, 4, 1, 0), \ | ||
513 | SOC_DAPM_SINGLE("ADC/DMIC1 Switch", _reg, 3, 1, 0), \ | ||
514 | SOC_DAPM_SINGLE("AIF3 Switch", _reg, 2, 1, 0), \ | ||
515 | SOC_DAPM_SINGLE("AIF2 Switch", _reg, 1, 1, 0), \ | ||
516 | SOC_DAPM_SINGLE("AIF1 Switch", _reg, 0, 1, 0), \ | ||
517 | } | ||
518 | |||
519 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel1_mixer_controls, | ||
520 | ADAU1373_DIN_MIX_CTRL(0)); | ||
521 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel2_mixer_controls, | ||
522 | ADAU1373_DIN_MIX_CTRL(1)); | ||
523 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel3_mixer_controls, | ||
524 | ADAU1373_DIN_MIX_CTRL(2)); | ||
525 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel4_mixer_controls, | ||
526 | ADAU1373_DIN_MIX_CTRL(3)); | ||
527 | static DECLARE_ADAU1373_DSP_CHANNEL_MIXER_CTRLS(adau1373_dsp_channel5_mixer_controls, | ||
528 | ADAU1373_DIN_MIX_CTRL(4)); | ||
529 | |||
530 | #define DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(_name, _reg) \ | ||
531 | const struct snd_kcontrol_new _name[] = { \ | ||
532 | SOC_DAPM_SINGLE("DSP Channel5 Switch", _reg, 4, 1, 0), \ | ||
533 | SOC_DAPM_SINGLE("DSP Channel4 Switch", _reg, 3, 1, 0), \ | ||
534 | SOC_DAPM_SINGLE("DSP Channel3 Switch", _reg, 2, 1, 0), \ | ||
535 | SOC_DAPM_SINGLE("DSP Channel2 Switch", _reg, 1, 1, 0), \ | ||
536 | SOC_DAPM_SINGLE("DSP Channel1 Switch", _reg, 0, 1, 0), \ | ||
537 | } | ||
538 | |||
539 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif1_mixer_controls, | ||
540 | ADAU1373_DOUT_MIX_CTRL(0)); | ||
541 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif2_mixer_controls, | ||
542 | ADAU1373_DOUT_MIX_CTRL(1)); | ||
543 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_aif3_mixer_controls, | ||
544 | ADAU1373_DOUT_MIX_CTRL(2)); | ||
545 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac1_mixer_controls, | ||
546 | ADAU1373_DOUT_MIX_CTRL(3)); | ||
547 | static DECLARE_ADAU1373_DSP_OUTPUT_MIXER_CTRLS(adau1373_dac2_mixer_controls, | ||
548 | ADAU1373_DOUT_MIX_CTRL(4)); | ||
549 | |||
550 | static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { | ||
551 | /* Datasheet claims Left ADC is bit 6 and Right ADC is bit 7, but that | ||
552 | * doesn't seem to be the case. */ | ||
553 | SND_SOC_DAPM_ADC("Left ADC", NULL, ADAU1373_PWDN_CTRL1, 7, 0), | ||
554 | SND_SOC_DAPM_ADC("Right ADC", NULL, ADAU1373_PWDN_CTRL1, 6, 0), | ||
555 | |||
556 | SND_SOC_DAPM_ADC("DMIC1", NULL, ADAU1373_DIGMICCTRL, 0, 0), | ||
557 | SND_SOC_DAPM_ADC("DMIC2", NULL, ADAU1373_DIGMICCTRL, 2, 0), | ||
558 | |||
559 | SND_SOC_DAPM_VIRT_MUX("Decimator Mux", SND_SOC_NOPM, 0, 0, | ||
560 | &adau1373_decimator_mux), | ||
561 | |||
562 | SND_SOC_DAPM_SUPPLY("MICBIAS2", ADAU1373_PWDN_CTRL1, 5, 0, NULL, 0), | ||
563 | SND_SOC_DAPM_SUPPLY("MICBIAS1", ADAU1373_PWDN_CTRL1, 4, 0, NULL, 0), | ||
564 | |||
565 | SND_SOC_DAPM_PGA("IN4PGA", ADAU1373_PWDN_CTRL1, 3, 0, NULL, 0), | ||
566 | SND_SOC_DAPM_PGA("IN3PGA", ADAU1373_PWDN_CTRL1, 2, 0, NULL, 0), | ||
567 | SND_SOC_DAPM_PGA("IN2PGA", ADAU1373_PWDN_CTRL1, 1, 0, NULL, 0), | ||
568 | SND_SOC_DAPM_PGA("IN1PGA", ADAU1373_PWDN_CTRL1, 0, 0, NULL, 0), | ||
569 | |||
570 | SND_SOC_DAPM_DAC("Left DAC2", NULL, ADAU1373_PWDN_CTRL2, 7, 0), | ||
571 | SND_SOC_DAPM_DAC("Right DAC2", NULL, ADAU1373_PWDN_CTRL2, 6, 0), | ||
572 | SND_SOC_DAPM_DAC("Left DAC1", NULL, ADAU1373_PWDN_CTRL2, 5, 0), | ||
573 | SND_SOC_DAPM_DAC("Right DAC1", NULL, ADAU1373_PWDN_CTRL2, 4, 0), | ||
574 | |||
575 | SOC_MIXER_ARRAY("Left ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
576 | adau1373_left_adc_mixer_controls), | ||
577 | SOC_MIXER_ARRAY("Right ADC Mixer", SND_SOC_NOPM, 0, 0, | ||
578 | adau1373_right_adc_mixer_controls), | ||
579 | |||
580 | SOC_MIXER_ARRAY("Left Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 3, 0, | ||
581 | adau1373_left_line2_mixer_controls), | ||
582 | SOC_MIXER_ARRAY("Right Lineout2 Mixer", ADAU1373_PWDN_CTRL2, 2, 0, | ||
583 | adau1373_right_line2_mixer_controls), | ||
584 | SOC_MIXER_ARRAY("Left Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 1, 0, | ||
585 | adau1373_left_line1_mixer_controls), | ||
586 | SOC_MIXER_ARRAY("Right Lineout1 Mixer", ADAU1373_PWDN_CTRL2, 0, 0, | ||
587 | adau1373_right_line1_mixer_controls), | ||
588 | |||
589 | SOC_MIXER_ARRAY("Earpiece Mixer", ADAU1373_PWDN_CTRL3, 4, 0, | ||
590 | adau1373_ep_mixer_controls), | ||
591 | SOC_MIXER_ARRAY("Left Speaker Mixer", ADAU1373_PWDN_CTRL3, 3, 0, | ||
592 | adau1373_left_spk_mixer_controls), | ||
593 | SOC_MIXER_ARRAY("Right Speaker Mixer", ADAU1373_PWDN_CTRL3, 2, 0, | ||
594 | adau1373_right_spk_mixer_controls), | ||
595 | SOC_MIXER_ARRAY("Left Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
596 | adau1373_left_hp_mixer_controls), | ||
597 | SOC_MIXER_ARRAY("Right Headphone Mixer", SND_SOC_NOPM, 0, 0, | ||
598 | adau1373_right_hp_mixer_controls), | ||
599 | SND_SOC_DAPM_SUPPLY("Headphone Enable", ADAU1373_PWDN_CTRL3, 1, 0, | ||
600 | NULL, 0), | ||
601 | |||
602 | SND_SOC_DAPM_SUPPLY("AIF1 CLK", ADAU1373_SRC_DAI_CTRL(0), 0, 0, | ||
603 | NULL, 0), | ||
604 | SND_SOC_DAPM_SUPPLY("AIF2 CLK", ADAU1373_SRC_DAI_CTRL(1), 0, 0, | ||
605 | NULL, 0), | ||
606 | SND_SOC_DAPM_SUPPLY("AIF3 CLK", ADAU1373_SRC_DAI_CTRL(2), 0, 0, | ||
607 | NULL, 0), | ||
608 | SND_SOC_DAPM_SUPPLY("AIF1 IN SRC", ADAU1373_SRC_DAI_CTRL(0), 2, 0, | ||
609 | NULL, 0), | ||
610 | SND_SOC_DAPM_SUPPLY("AIF1 OUT SRC", ADAU1373_SRC_DAI_CTRL(0), 1, 0, | ||
611 | NULL, 0), | ||
612 | SND_SOC_DAPM_SUPPLY("AIF2 IN SRC", ADAU1373_SRC_DAI_CTRL(1), 2, 0, | ||
613 | NULL, 0), | ||
614 | SND_SOC_DAPM_SUPPLY("AIF2 OUT SRC", ADAU1373_SRC_DAI_CTRL(1), 1, 0, | ||
615 | NULL, 0), | ||
616 | SND_SOC_DAPM_SUPPLY("AIF3 IN SRC", ADAU1373_SRC_DAI_CTRL(2), 2, 0, | ||
617 | NULL, 0), | ||
618 | SND_SOC_DAPM_SUPPLY("AIF3 OUT SRC", ADAU1373_SRC_DAI_CTRL(2), 1, 0, | ||
619 | NULL, 0), | ||
620 | |||
621 | SND_SOC_DAPM_AIF_IN("AIF1 IN", "AIF1 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
622 | SND_SOC_DAPM_AIF_OUT("AIF1 OUT", "AIF1 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
623 | SND_SOC_DAPM_AIF_IN("AIF2 IN", "AIF2 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
624 | SND_SOC_DAPM_AIF_OUT("AIF2 OUT", "AIF2 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
625 | SND_SOC_DAPM_AIF_IN("AIF3 IN", "AIF3 Playback", 0, SND_SOC_NOPM, 0, 0), | ||
626 | SND_SOC_DAPM_AIF_OUT("AIF3 OUT", "AIF3 Capture", 0, SND_SOC_NOPM, 0, 0), | ||
627 | |||
628 | SOC_MIXER_ARRAY("DSP Channel1 Mixer", SND_SOC_NOPM, 0, 0, | ||
629 | adau1373_dsp_channel1_mixer_controls), | ||
630 | SOC_MIXER_ARRAY("DSP Channel2 Mixer", SND_SOC_NOPM, 0, 0, | ||
631 | adau1373_dsp_channel2_mixer_controls), | ||
632 | SOC_MIXER_ARRAY("DSP Channel3 Mixer", SND_SOC_NOPM, 0, 0, | ||
633 | adau1373_dsp_channel3_mixer_controls), | ||
634 | SOC_MIXER_ARRAY("DSP Channel4 Mixer", SND_SOC_NOPM, 0, 0, | ||
635 | adau1373_dsp_channel4_mixer_controls), | ||
636 | SOC_MIXER_ARRAY("DSP Channel5 Mixer", SND_SOC_NOPM, 0, 0, | ||
637 | adau1373_dsp_channel5_mixer_controls), | ||
638 | |||
639 | SOC_MIXER_ARRAY("AIF1 Mixer", SND_SOC_NOPM, 0, 0, | ||
640 | adau1373_aif1_mixer_controls), | ||
641 | SOC_MIXER_ARRAY("AIF2 Mixer", SND_SOC_NOPM, 0, 0, | ||
642 | adau1373_aif2_mixer_controls), | ||
643 | SOC_MIXER_ARRAY("AIF3 Mixer", SND_SOC_NOPM, 0, 0, | ||
644 | adau1373_aif3_mixer_controls), | ||
645 | SOC_MIXER_ARRAY("DAC1 Mixer", SND_SOC_NOPM, 0, 0, | ||
646 | adau1373_dac1_mixer_controls), | ||
647 | SOC_MIXER_ARRAY("DAC2 Mixer", SND_SOC_NOPM, 0, 0, | ||
648 | adau1373_dac2_mixer_controls), | ||
649 | |||
650 | SND_SOC_DAPM_SUPPLY("DSP", ADAU1373_DIGEN, 4, 0, NULL, 0), | ||
651 | SND_SOC_DAPM_SUPPLY("Recording Engine B", ADAU1373_DIGEN, 3, 0, NULL, 0), | ||
652 | SND_SOC_DAPM_SUPPLY("Recording Engine A", ADAU1373_DIGEN, 2, 0, NULL, 0), | ||
653 | SND_SOC_DAPM_SUPPLY("Playback Engine B", ADAU1373_DIGEN, 1, 0, NULL, 0), | ||
654 | SND_SOC_DAPM_SUPPLY("Playback Engine A", ADAU1373_DIGEN, 0, 0, NULL, 0), | ||
655 | |||
656 | SND_SOC_DAPM_SUPPLY("PLL1", SND_SOC_NOPM, 0, 0, adau1373_pll_event, | ||
657 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
658 | SND_SOC_DAPM_SUPPLY("PLL2", SND_SOC_NOPM, 0, 0, adau1373_pll_event, | ||
659 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
660 | SND_SOC_DAPM_SUPPLY("SYSCLK1", ADAU1373_CLK_SRC_DIV(0), 7, 0, NULL, 0), | ||
661 | SND_SOC_DAPM_SUPPLY("SYSCLK2", ADAU1373_CLK_SRC_DIV(1), 7, 0, NULL, 0), | ||
662 | |||
663 | SND_SOC_DAPM_INPUT("AIN1L"), | ||
664 | SND_SOC_DAPM_INPUT("AIN1R"), | ||
665 | SND_SOC_DAPM_INPUT("AIN2L"), | ||
666 | SND_SOC_DAPM_INPUT("AIN2R"), | ||
667 | SND_SOC_DAPM_INPUT("AIN3L"), | ||
668 | SND_SOC_DAPM_INPUT("AIN3R"), | ||
669 | SND_SOC_DAPM_INPUT("AIN4L"), | ||
670 | SND_SOC_DAPM_INPUT("AIN4R"), | ||
671 | |||
672 | SND_SOC_DAPM_INPUT("DMIC1DAT"), | ||
673 | SND_SOC_DAPM_INPUT("DMIC2DAT"), | ||
674 | |||
675 | SND_SOC_DAPM_OUTPUT("LOUT1L"), | ||
676 | SND_SOC_DAPM_OUTPUT("LOUT1R"), | ||
677 | SND_SOC_DAPM_OUTPUT("LOUT2L"), | ||
678 | SND_SOC_DAPM_OUTPUT("LOUT2R"), | ||
679 | SND_SOC_DAPM_OUTPUT("HPL"), | ||
680 | SND_SOC_DAPM_OUTPUT("HPR"), | ||
681 | SND_SOC_DAPM_OUTPUT("SPKL"), | ||
682 | SND_SOC_DAPM_OUTPUT("SPKR"), | ||
683 | SND_SOC_DAPM_OUTPUT("EP"), | ||
684 | }; | ||
685 | |||
686 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | ||
687 | struct snd_soc_dapm_widget *sink) | ||
688 | { | ||
689 | struct snd_soc_codec *codec = source->codec; | ||
690 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
691 | unsigned int dai; | ||
692 | const char *clk; | ||
693 | |||
694 | dai = sink->name[3] - '1'; | ||
695 | |||
696 | if (!adau1373->dais[dai].master) | ||
697 | return 0; | ||
698 | |||
699 | if (adau1373->dais[dai].clk_src == ADAU1373_CLK_SRC_PLL1) | ||
700 | clk = "SYSCLK1"; | ||
701 | else | ||
702 | clk = "SYSCLK2"; | ||
703 | |||
704 | return strcmp(source->name, clk) == 0; | ||
705 | } | ||
706 | |||
707 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, | ||
708 | struct snd_soc_dapm_widget *sink) | ||
709 | { | ||
710 | struct snd_soc_codec *codec = source->codec; | ||
711 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
712 | unsigned int dai; | ||
713 | |||
714 | dai = sink->name[3] - '1'; | ||
715 | |||
716 | return adau1373->dais[dai].enable_src; | ||
717 | } | ||
718 | |||
719 | #define DSP_CHANNEL_MIXER_ROUTES(_sink) \ | ||
720 | { _sink, "DMIC2 Swapped Switch", "DMIC2" }, \ | ||
721 | { _sink, "DMIC2 Switch", "DMIC2" }, \ | ||
722 | { _sink, "ADC/DMIC1 Swapped Switch", "Decimator Mux" }, \ | ||
723 | { _sink, "ADC/DMIC1 Switch", "Decimator Mux" }, \ | ||
724 | { _sink, "AIF1 Switch", "AIF1 IN" }, \ | ||
725 | { _sink, "AIF2 Switch", "AIF2 IN" }, \ | ||
726 | { _sink, "AIF3 Switch", "AIF3 IN" } | ||
727 | |||
728 | #define DSP_OUTPUT_MIXER_ROUTES(_sink) \ | ||
729 | { _sink, "DSP Channel1 Switch", "DSP Channel1 Mixer" }, \ | ||
730 | { _sink, "DSP Channel2 Switch", "DSP Channel2 Mixer" }, \ | ||
731 | { _sink, "DSP Channel3 Switch", "DSP Channel3 Mixer" }, \ | ||
732 | { _sink, "DSP Channel4 Switch", "DSP Channel4 Mixer" }, \ | ||
733 | { _sink, "DSP Channel5 Switch", "DSP Channel5 Mixer" } | ||
734 | |||
735 | #define LEFT_OUTPUT_MIXER_ROUTES(_sink) \ | ||
736 | { _sink, "Right DAC2 Switch", "Right DAC2" }, \ | ||
737 | { _sink, "Left DAC2 Switch", "Left DAC2" }, \ | ||
738 | { _sink, "Right DAC1 Switch", "Right DAC1" }, \ | ||
739 | { _sink, "Left DAC1 Switch", "Left DAC1" }, \ | ||
740 | { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ | ||
741 | { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ | ||
742 | { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ | ||
743 | { _sink, "Input 4 Bypass Switch", "IN4PGA" } | ||
744 | |||
745 | #define RIGHT_OUTPUT_MIXER_ROUTES(_sink) \ | ||
746 | { _sink, "Right DAC2 Switch", "Right DAC2" }, \ | ||
747 | { _sink, "Left DAC2 Switch", "Left DAC2" }, \ | ||
748 | { _sink, "Right DAC1 Switch", "Right DAC1" }, \ | ||
749 | { _sink, "Left DAC1 Switch", "Left DAC1" }, \ | ||
750 | { _sink, "Input 1 Bypass Switch", "IN1PGA" }, \ | ||
751 | { _sink, "Input 2 Bypass Switch", "IN2PGA" }, \ | ||
752 | { _sink, "Input 3 Bypass Switch", "IN3PGA" }, \ | ||
753 | { _sink, "Input 4 Bypass Switch", "IN4PGA" } | ||
754 | |||
755 | static const struct snd_soc_dapm_route adau1373_dapm_routes[] = { | ||
756 | { "Left ADC Mixer", "DAC1 Switch", "Left DAC1" }, | ||
757 | { "Left ADC Mixer", "Input 1 Switch", "IN1PGA" }, | ||
758 | { "Left ADC Mixer", "Input 2 Switch", "IN2PGA" }, | ||
759 | { "Left ADC Mixer", "Input 3 Switch", "IN3PGA" }, | ||
760 | { "Left ADC Mixer", "Input 4 Switch", "IN4PGA" }, | ||
761 | |||
762 | { "Right ADC Mixer", "DAC1 Switch", "Right DAC1" }, | ||
763 | { "Right ADC Mixer", "Input 1 Switch", "IN1PGA" }, | ||
764 | { "Right ADC Mixer", "Input 2 Switch", "IN2PGA" }, | ||
765 | { "Right ADC Mixer", "Input 3 Switch", "IN3PGA" }, | ||
766 | { "Right ADC Mixer", "Input 4 Switch", "IN4PGA" }, | ||
767 | |||
768 | { "Left ADC", NULL, "Left ADC Mixer" }, | ||
769 | { "Right ADC", NULL, "Right ADC Mixer" }, | ||
770 | |||
771 | { "Decimator Mux", "ADC", "Left ADC" }, | ||
772 | { "Decimator Mux", "ADC", "Right ADC" }, | ||
773 | { "Decimator Mux", "DMIC1", "DMIC1" }, | ||
774 | |||
775 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel1 Mixer"), | ||
776 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel2 Mixer"), | ||
777 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel3 Mixer"), | ||
778 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel4 Mixer"), | ||
779 | DSP_CHANNEL_MIXER_ROUTES("DSP Channel5 Mixer"), | ||
780 | |||
781 | DSP_OUTPUT_MIXER_ROUTES("AIF1 Mixer"), | ||
782 | DSP_OUTPUT_MIXER_ROUTES("AIF2 Mixer"), | ||
783 | DSP_OUTPUT_MIXER_ROUTES("AIF3 Mixer"), | ||
784 | DSP_OUTPUT_MIXER_ROUTES("DAC1 Mixer"), | ||
785 | DSP_OUTPUT_MIXER_ROUTES("DAC2 Mixer"), | ||
786 | |||
787 | { "AIF1 OUT", NULL, "AIF1 Mixer" }, | ||
788 | { "AIF2 OUT", NULL, "AIF2 Mixer" }, | ||
789 | { "AIF3 OUT", NULL, "AIF3 Mixer" }, | ||
790 | { "Left DAC1", NULL, "DAC1 Mixer" }, | ||
791 | { "Right DAC1", NULL, "DAC1 Mixer" }, | ||
792 | { "Left DAC2", NULL, "DAC2 Mixer" }, | ||
793 | { "Right DAC2", NULL, "DAC2 Mixer" }, | ||
794 | |||
795 | LEFT_OUTPUT_MIXER_ROUTES("Left Lineout1 Mixer"), | ||
796 | RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout1 Mixer"), | ||
797 | LEFT_OUTPUT_MIXER_ROUTES("Left Lineout2 Mixer"), | ||
798 | RIGHT_OUTPUT_MIXER_ROUTES("Right Lineout2 Mixer"), | ||
799 | LEFT_OUTPUT_MIXER_ROUTES("Left Speaker Mixer"), | ||
800 | RIGHT_OUTPUT_MIXER_ROUTES("Right Speaker Mixer"), | ||
801 | |||
802 | { "Left Headphone Mixer", "Left DAC2 Switch", "Left DAC2" }, | ||
803 | { "Left Headphone Mixer", "Left DAC1 Switch", "Left DAC1" }, | ||
804 | { "Left Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
805 | { "Left Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
806 | { "Left Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
807 | { "Left Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
808 | { "Right Headphone Mixer", "Right DAC2 Switch", "Right DAC2" }, | ||
809 | { "Right Headphone Mixer", "Right DAC1 Switch", "Right DAC1" }, | ||
810 | { "Right Headphone Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
811 | { "Right Headphone Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
812 | { "Right Headphone Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
813 | { "Right Headphone Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
814 | |||
815 | { "Left Headphone Mixer", NULL, "Headphone Enable" }, | ||
816 | { "Right Headphone Mixer", NULL, "Headphone Enable" }, | ||
817 | |||
818 | { "Earpiece Mixer", "Right DAC2 Switch", "Right DAC2" }, | ||
819 | { "Earpiece Mixer", "Left DAC2 Switch", "Left DAC2" }, | ||
820 | { "Earpiece Mixer", "Right DAC1 Switch", "Right DAC1" }, | ||
821 | { "Earpiece Mixer", "Left DAC1 Switch", "Left DAC1" }, | ||
822 | { "Earpiece Mixer", "Input 1 Bypass Switch", "IN1PGA" }, | ||
823 | { "Earpiece Mixer", "Input 2 Bypass Switch", "IN2PGA" }, | ||
824 | { "Earpiece Mixer", "Input 3 Bypass Switch", "IN3PGA" }, | ||
825 | { "Earpiece Mixer", "Input 4 Bypass Switch", "IN4PGA" }, | ||
826 | |||
827 | { "LOUT1L", NULL, "Left Lineout1 Mixer" }, | ||
828 | { "LOUT1R", NULL, "Right Lineout1 Mixer" }, | ||
829 | { "LOUT2L", NULL, "Left Lineout2 Mixer" }, | ||
830 | { "LOUT2R", NULL, "Right Lineout2 Mixer" }, | ||
831 | { "SPKL", NULL, "Left Speaker Mixer" }, | ||
832 | { "SPKR", NULL, "Right Speaker Mixer" }, | ||
833 | { "HPL", NULL, "Left Headphone Mixer" }, | ||
834 | { "HPR", NULL, "Right Headphone Mixer" }, | ||
835 | { "EP", NULL, "Earpiece Mixer" }, | ||
836 | |||
837 | { "IN1PGA", NULL, "AIN1L" }, | ||
838 | { "IN2PGA", NULL, "AIN2L" }, | ||
839 | { "IN3PGA", NULL, "AIN3L" }, | ||
840 | { "IN4PGA", NULL, "AIN4L" }, | ||
841 | { "IN1PGA", NULL, "AIN1R" }, | ||
842 | { "IN2PGA", NULL, "AIN2R" }, | ||
843 | { "IN3PGA", NULL, "AIN3R" }, | ||
844 | { "IN4PGA", NULL, "AIN4R" }, | ||
845 | |||
846 | { "SYSCLK1", NULL, "PLL1" }, | ||
847 | { "SYSCLK2", NULL, "PLL2" }, | ||
848 | |||
849 | { "Left DAC1", NULL, "SYSCLK1" }, | ||
850 | { "Right DAC1", NULL, "SYSCLK1" }, | ||
851 | { "Left DAC2", NULL, "SYSCLK1" }, | ||
852 | { "Right DAC2", NULL, "SYSCLK1" }, | ||
853 | { "Left ADC", NULL, "SYSCLK1" }, | ||
854 | { "Right ADC", NULL, "SYSCLK1" }, | ||
855 | |||
856 | { "DSP", NULL, "SYSCLK1" }, | ||
857 | |||
858 | { "AIF1 Mixer", NULL, "DSP" }, | ||
859 | { "AIF2 Mixer", NULL, "DSP" }, | ||
860 | { "AIF3 Mixer", NULL, "DSP" }, | ||
861 | { "DAC1 Mixer", NULL, "DSP" }, | ||
862 | { "DAC2 Mixer", NULL, "DSP" }, | ||
863 | { "DAC1 Mixer", NULL, "Playback Engine A" }, | ||
864 | { "DAC2 Mixer", NULL, "Playback Engine B" }, | ||
865 | { "Left ADC Mixer", NULL, "Recording Engine A" }, | ||
866 | { "Right ADC Mixer", NULL, "Recording Engine A" }, | ||
867 | |||
868 | { "AIF1 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
869 | { "AIF2 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
870 | { "AIF3 CLK", NULL, "SYSCLK1", adau1373_check_aif_clk }, | ||
871 | { "AIF1 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
872 | { "AIF2 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
873 | { "AIF3 CLK", NULL, "SYSCLK2", adau1373_check_aif_clk }, | ||
874 | |||
875 | { "AIF1 IN", NULL, "AIF1 CLK" }, | ||
876 | { "AIF1 OUT", NULL, "AIF1 CLK" }, | ||
877 | { "AIF2 IN", NULL, "AIF2 CLK" }, | ||
878 | { "AIF2 OUT", NULL, "AIF2 CLK" }, | ||
879 | { "AIF3 IN", NULL, "AIF3 CLK" }, | ||
880 | { "AIF3 OUT", NULL, "AIF3 CLK" }, | ||
881 | { "AIF1 IN", NULL, "AIF1 IN SRC", adau1373_check_src }, | ||
882 | { "AIF1 OUT", NULL, "AIF1 OUT SRC", adau1373_check_src }, | ||
883 | { "AIF2 IN", NULL, "AIF2 IN SRC", adau1373_check_src }, | ||
884 | { "AIF2 OUT", NULL, "AIF2 OUT SRC", adau1373_check_src }, | ||
885 | { "AIF3 IN", NULL, "AIF3 IN SRC", adau1373_check_src }, | ||
886 | { "AIF3 OUT", NULL, "AIF3 OUT SRC", adau1373_check_src }, | ||
887 | |||
888 | { "DMIC1", NULL, "DMIC1DAT" }, | ||
889 | { "DMIC1", NULL, "SYSCLK1" }, | ||
890 | { "DMIC1", NULL, "Recording Engine A" }, | ||
891 | { "DMIC2", NULL, "DMIC2DAT" }, | ||
892 | { "DMIC2", NULL, "SYSCLK1" }, | ||
893 | { "DMIC2", NULL, "Recording Engine B" }, | ||
894 | }; | ||
895 | |||
896 | static int adau1373_hw_params(struct snd_pcm_substream *substream, | ||
897 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | ||
898 | { | ||
899 | struct snd_soc_codec *codec = dai->codec; | ||
900 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
901 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
902 | unsigned int div; | ||
903 | unsigned int freq; | ||
904 | unsigned int ctrl; | ||
905 | |||
906 | freq = adau1373_dai->sysclk; | ||
907 | |||
908 | if (freq % params_rate(params) != 0) | ||
909 | return -EINVAL; | ||
910 | |||
911 | switch (freq / params_rate(params)) { | ||
912 | case 1024: /* sysclk / 256 */ | ||
913 | div = 0; | ||
914 | break; | ||
915 | case 1536: /* 2/3 sysclk / 256 */ | ||
916 | div = 1; | ||
917 | break; | ||
918 | case 2048: /* 1/2 sysclk / 256 */ | ||
919 | div = 2; | ||
920 | break; | ||
921 | case 3072: /* 1/3 sysclk / 256 */ | ||
922 | div = 3; | ||
923 | break; | ||
924 | case 4096: /* 1/4 sysclk / 256 */ | ||
925 | div = 4; | ||
926 | break; | ||
927 | case 6144: /* 1/6 sysclk / 256 */ | ||
928 | div = 5; | ||
929 | break; | ||
930 | case 5632: /* 2/11 sysclk / 256 */ | ||
931 | div = 6; | ||
932 | break; | ||
933 | default: | ||
934 | return -EINVAL; | ||
935 | } | ||
936 | |||
937 | adau1373_dai->enable_src = (div != 0); | ||
938 | |||
939 | snd_soc_update_bits(codec, ADAU1373_BCLKDIV(dai->id), | ||
940 | ~ADAU1373_BCLKDIV_SOURCE, (div << 2) | ADAU1373_BCLKDIV_64); | ||
941 | |||
942 | switch (params_format(params)) { | ||
943 | case SNDRV_PCM_FORMAT_S16_LE: | ||
944 | ctrl = ADAU1373_DAI_WLEN_16; | ||
945 | break; | ||
946 | case SNDRV_PCM_FORMAT_S20_3LE: | ||
947 | ctrl = ADAU1373_DAI_WLEN_20; | ||
948 | break; | ||
949 | case SNDRV_PCM_FORMAT_S24_LE: | ||
950 | ctrl = ADAU1373_DAI_WLEN_24; | ||
951 | break; | ||
952 | case SNDRV_PCM_FORMAT_S32_LE: | ||
953 | ctrl = ADAU1373_DAI_WLEN_32; | ||
954 | break; | ||
955 | default: | ||
956 | return -EINVAL; | ||
957 | } | ||
958 | |||
959 | return snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), | ||
960 | ADAU1373_DAI_WLEN_MASK, ctrl); | ||
961 | } | ||
962 | |||
963 | static int adau1373_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) | ||
964 | { | ||
965 | struct snd_soc_codec *codec = dai->codec; | ||
966 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | ||
967 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
968 | unsigned int ctrl; | ||
969 | |||
970 | switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { | ||
971 | case SND_SOC_DAIFMT_CBM_CFM: | ||
972 | ctrl = ADAU1373_DAI_MASTER; | ||
973 | adau1373_dai->master = true; | ||
974 | break; | ||
975 | case SND_SOC_DAIFMT_CBS_CFS: | ||
976 | ctrl = 0; | ||
977 | adau1373_dai->master = true; | ||
978 | break; | ||
979 | default: | ||
980 | return -EINVAL; | ||
981 | } | ||
982 | |||
983 | switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { | ||
984 | case SND_SOC_DAIFMT_I2S: | ||
985 | ctrl |= ADAU1373_DAI_FORMAT_I2S; | ||
986 | break; | ||
987 | case SND_SOC_DAIFMT_LEFT_J: | ||
988 | ctrl |= ADAU1373_DAI_FORMAT_LEFT_J; | ||
989 | break; | ||
990 | case SND_SOC_DAIFMT_RIGHT_J: | ||
991 | ctrl |= ADAU1373_DAI_FORMAT_RIGHT_J; | ||
992 | break; | ||
993 | case SND_SOC_DAIFMT_DSP_B: | ||
994 | ctrl |= ADAU1373_DAI_FORMAT_DSP; | ||
995 | break; | ||
996 | default: | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
1000 | switch (fmt & SND_SOC_DAIFMT_INV_MASK) { | ||
1001 | case SND_SOC_DAIFMT_NB_NF: | ||
1002 | break; | ||
1003 | case SND_SOC_DAIFMT_IB_NF: | ||
1004 | ctrl |= ADAU1373_DAI_INVERT_BCLK; | ||
1005 | break; | ||
1006 | case SND_SOC_DAIFMT_NB_IF: | ||
1007 | ctrl |= ADAU1373_DAI_INVERT_LRCLK; | ||
1008 | break; | ||
1009 | case SND_SOC_DAIFMT_IB_IF: | ||
1010 | ctrl |= ADAU1373_DAI_INVERT_LRCLK | ADAU1373_DAI_INVERT_BCLK; | ||
1011 | break; | ||
1012 | default: | ||
1013 | return -EINVAL; | ||
1014 | } | ||
1015 | |||
1016 | snd_soc_update_bits(codec, ADAU1373_DAI(dai->id), | ||
1017 | ~ADAU1373_DAI_WLEN_MASK, ctrl); | ||
1018 | |||
1019 | return 0; | ||
1020 | } | ||
1021 | |||
1022 | static int adau1373_set_dai_sysclk(struct snd_soc_dai *dai, | ||
1023 | int clk_id, unsigned int freq, int dir) | ||
1024 | { | ||
1025 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(dai->codec); | ||
1026 | struct adau1373_dai *adau1373_dai = &adau1373->dais[dai->id]; | ||
1027 | |||
1028 | switch (clk_id) { | ||
1029 | case ADAU1373_CLK_SRC_PLL1: | ||
1030 | case ADAU1373_CLK_SRC_PLL2: | ||
1031 | break; | ||
1032 | default: | ||
1033 | return -EINVAL; | ||
1034 | } | ||
1035 | |||
1036 | adau1373_dai->sysclk = freq; | ||
1037 | adau1373_dai->clk_src = clk_id; | ||
1038 | |||
1039 | snd_soc_update_bits(dai->codec, ADAU1373_BCLKDIV(dai->id), | ||
1040 | ADAU1373_BCLKDIV_SOURCE, clk_id << 5); | ||
1041 | |||
1042 | return 0; | ||
1043 | } | ||
1044 | |||
1045 | static const struct snd_soc_dai_ops adau1373_dai_ops = { | ||
1046 | .hw_params = adau1373_hw_params, | ||
1047 | .set_sysclk = adau1373_set_dai_sysclk, | ||
1048 | .set_fmt = adau1373_set_dai_fmt, | ||
1049 | }; | ||
1050 | |||
1051 | #define ADAU1373_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ | ||
1052 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
1053 | |||
1054 | static struct snd_soc_dai_driver adau1373_dai_driver[] = { | ||
1055 | { | ||
1056 | .id = 0, | ||
1057 | .name = "adau1373-aif1", | ||
1058 | .playback = { | ||
1059 | .stream_name = "AIF1 Playback", | ||
1060 | .channels_min = 2, | ||
1061 | .channels_max = 2, | ||
1062 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1063 | .formats = ADAU1373_FORMATS, | ||
1064 | }, | ||
1065 | .capture = { | ||
1066 | .stream_name = "AIF1 Capture", | ||
1067 | .channels_min = 2, | ||
1068 | .channels_max = 2, | ||
1069 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1070 | .formats = ADAU1373_FORMATS, | ||
1071 | }, | ||
1072 | .ops = &adau1373_dai_ops, | ||
1073 | .symmetric_rates = 1, | ||
1074 | }, | ||
1075 | { | ||
1076 | .id = 1, | ||
1077 | .name = "adau1373-aif2", | ||
1078 | .playback = { | ||
1079 | .stream_name = "AIF2 Playback", | ||
1080 | .channels_min = 2, | ||
1081 | .channels_max = 2, | ||
1082 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1083 | .formats = ADAU1373_FORMATS, | ||
1084 | }, | ||
1085 | .capture = { | ||
1086 | .stream_name = "AIF2 Capture", | ||
1087 | .channels_min = 2, | ||
1088 | .channels_max = 2, | ||
1089 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1090 | .formats = ADAU1373_FORMATS, | ||
1091 | }, | ||
1092 | .ops = &adau1373_dai_ops, | ||
1093 | .symmetric_rates = 1, | ||
1094 | }, | ||
1095 | { | ||
1096 | .id = 2, | ||
1097 | .name = "adau1373-aif3", | ||
1098 | .playback = { | ||
1099 | .stream_name = "AIF3 Playback", | ||
1100 | .channels_min = 2, | ||
1101 | .channels_max = 2, | ||
1102 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1103 | .formats = ADAU1373_FORMATS, | ||
1104 | }, | ||
1105 | .capture = { | ||
1106 | .stream_name = "AIF3 Capture", | ||
1107 | .channels_min = 2, | ||
1108 | .channels_max = 2, | ||
1109 | .rates = SNDRV_PCM_RATE_8000_48000, | ||
1110 | .formats = ADAU1373_FORMATS, | ||
1111 | }, | ||
1112 | .ops = &adau1373_dai_ops, | ||
1113 | .symmetric_rates = 1, | ||
1114 | }, | ||
1115 | }; | ||
1116 | |||
1117 | static int adau1373_set_pll(struct snd_soc_codec *codec, int pll_id, | ||
1118 | int source, unsigned int freq_in, unsigned int freq_out) | ||
1119 | { | ||
1120 | unsigned int dpll_div = 0; | ||
1121 | unsigned int x, r, n, m, i, j, mode; | ||
1122 | |||
1123 | switch (pll_id) { | ||
1124 | case ADAU1373_PLL1: | ||
1125 | case ADAU1373_PLL2: | ||
1126 | break; | ||
1127 | default: | ||
1128 | return -EINVAL; | ||
1129 | } | ||
1130 | |||
1131 | switch (source) { | ||
1132 | case ADAU1373_PLL_SRC_BCLK1: | ||
1133 | case ADAU1373_PLL_SRC_BCLK2: | ||
1134 | case ADAU1373_PLL_SRC_BCLK3: | ||
1135 | case ADAU1373_PLL_SRC_LRCLK1: | ||
1136 | case ADAU1373_PLL_SRC_LRCLK2: | ||
1137 | case ADAU1373_PLL_SRC_LRCLK3: | ||
1138 | case ADAU1373_PLL_SRC_MCLK1: | ||
1139 | case ADAU1373_PLL_SRC_MCLK2: | ||
1140 | case ADAU1373_PLL_SRC_GPIO1: | ||
1141 | case ADAU1373_PLL_SRC_GPIO2: | ||
1142 | case ADAU1373_PLL_SRC_GPIO3: | ||
1143 | case ADAU1373_PLL_SRC_GPIO4: | ||
1144 | break; | ||
1145 | default: | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | if (freq_in < 7813 || freq_in > 27000000) | ||
1150 | return -EINVAL; | ||
1151 | |||
1152 | if (freq_out < 45158000 || freq_out > 49152000) | ||
1153 | return -EINVAL; | ||
1154 | |||
1155 | /* APLL input needs to be >= 8Mhz, so in case freq_in is less we use the | ||
1156 | * DPLL to get it there. DPLL_out = (DPLL_in / div) * 1024 */ | ||
1157 | while (freq_in < 8000000) { | ||
1158 | freq_in *= 2; | ||
1159 | dpll_div++; | ||
1160 | } | ||
1161 | |||
1162 | if (freq_out % freq_in != 0) { | ||
1163 | /* fout = fin * (r + (n/m)) / x */ | ||
1164 | x = DIV_ROUND_UP(freq_in, 13500000); | ||
1165 | freq_in /= x; | ||
1166 | r = freq_out / freq_in; | ||
1167 | i = freq_out % freq_in; | ||
1168 | j = gcd(i, freq_in); | ||
1169 | n = i / j; | ||
1170 | m = freq_in / j; | ||
1171 | x--; | ||
1172 | mode = 1; | ||
1173 | } else { | ||
1174 | /* fout = fin / r */ | ||
1175 | r = freq_out / freq_in; | ||
1176 | n = 0; | ||
1177 | m = 0; | ||
1178 | x = 0; | ||
1179 | mode = 0; | ||
1180 | } | ||
1181 | |||
1182 | if (r < 2 || r > 8 || x > 3 || m > 0xffff || n > 0xffff) | ||
1183 | return -EINVAL; | ||
1184 | |||
1185 | if (dpll_div) { | ||
1186 | dpll_div = 11 - dpll_div; | ||
1187 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
1188 | ADAU1373_PLL_CTRL6_DPLL_BYPASS, 0); | ||
1189 | } else { | ||
1190 | snd_soc_update_bits(codec, ADAU1373_PLL_CTRL6(pll_id), | ||
1191 | ADAU1373_PLL_CTRL6_DPLL_BYPASS, | ||
1192 | ADAU1373_PLL_CTRL6_DPLL_BYPASS); | ||
1193 | } | ||
1194 | |||
1195 | snd_soc_write(codec, ADAU1373_DPLL_CTRL(pll_id), | ||
1196 | (source << 4) | dpll_div); | ||
1197 | snd_soc_write(codec, ADAU1373_PLL_CTRL1(pll_id), (m >> 8) & 0xff); | ||
1198 | snd_soc_write(codec, ADAU1373_PLL_CTRL2(pll_id), m & 0xff); | ||
1199 | snd_soc_write(codec, ADAU1373_PLL_CTRL3(pll_id), (n >> 8) & 0xff); | ||
1200 | snd_soc_write(codec, ADAU1373_PLL_CTRL4(pll_id), n & 0xff); | ||
1201 | snd_soc_write(codec, ADAU1373_PLL_CTRL5(pll_id), | ||
1202 | (r << 3) | (x << 1) | mode); | ||
1203 | |||
1204 | /* Set sysclk to pll_rate / 4 */ | ||
1205 | snd_soc_update_bits(codec, ADAU1373_CLK_SRC_DIV(pll_id), 0x3f, 0x09); | ||
1206 | |||
1207 | return 0; | ||
1208 | } | ||
1209 | |||
1210 | static void adau1373_load_drc_settings(struct snd_soc_codec *codec, | ||
1211 | unsigned int nr, uint8_t *drc) | ||
1212 | { | ||
1213 | unsigned int i; | ||
1214 | |||
1215 | for (i = 0; i < ADAU1373_DRC_SIZE; ++i) | ||
1216 | snd_soc_write(codec, ADAU1373_DRC(nr) + i, drc[i]); | ||
1217 | } | ||
1218 | |||
1219 | static bool adau1373_valid_micbias(enum adau1373_micbias_voltage micbias) | ||
1220 | { | ||
1221 | switch (micbias) { | ||
1222 | case ADAU1373_MICBIAS_2_9V: | ||
1223 | case ADAU1373_MICBIAS_2_2V: | ||
1224 | case ADAU1373_MICBIAS_2_6V: | ||
1225 | case ADAU1373_MICBIAS_1_8V: | ||
1226 | return true; | ||
1227 | default: | ||
1228 | break; | ||
1229 | } | ||
1230 | return false; | ||
1231 | } | ||
1232 | |||
1233 | static int adau1373_probe(struct snd_soc_codec *codec) | ||
1234 | { | ||
1235 | struct adau1373_platform_data *pdata = codec->dev->platform_data; | ||
1236 | bool lineout_differential = false; | ||
1237 | unsigned int val; | ||
1238 | int ret; | ||
1239 | int i; | ||
1240 | |||
1241 | ret = snd_soc_codec_set_cache_io(codec, 8, 8, SND_SOC_I2C); | ||
1242 | if (ret) { | ||
1243 | dev_err(codec->dev, "failed to set cache I/O: %d\n", ret); | ||
1244 | return ret; | ||
1245 | } | ||
1246 | |||
1247 | codec->dapm.idle_bias_off = true; | ||
1248 | |||
1249 | if (pdata) { | ||
1250 | if (pdata->num_drc > ARRAY_SIZE(pdata->drc_setting)) | ||
1251 | return -EINVAL; | ||
1252 | |||
1253 | if (!adau1373_valid_micbias(pdata->micbias1) || | ||
1254 | !adau1373_valid_micbias(pdata->micbias2)) | ||
1255 | return -EINVAL; | ||
1256 | |||
1257 | for (i = 0; i < pdata->num_drc; ++i) { | ||
1258 | adau1373_load_drc_settings(codec, i, | ||
1259 | pdata->drc_setting[i]); | ||
1260 | } | ||
1261 | |||
1262 | snd_soc_add_controls(codec, adau1373_drc_controls, | ||
1263 | pdata->num_drc); | ||
1264 | |||
1265 | val = 0; | ||
1266 | for (i = 0; i < 4; ++i) { | ||
1267 | if (pdata->input_differential[i]) | ||
1268 | val |= BIT(i); | ||
1269 | } | ||
1270 | snd_soc_write(codec, ADAU1373_INPUT_MODE, val); | ||
1271 | |||
1272 | val = 0; | ||
1273 | if (pdata->lineout_differential) | ||
1274 | val |= ADAU1373_OUTPUT_CTRL_LDIFF; | ||
1275 | if (pdata->lineout_ground_sense) | ||
1276 | val |= ADAU1373_OUTPUT_CTRL_LNFBEN; | ||
1277 | snd_soc_write(codec, ADAU1373_OUTPUT_CTRL, val); | ||
1278 | |||
1279 | lineout_differential = pdata->lineout_differential; | ||
1280 | |||
1281 | snd_soc_write(codec, ADAU1373_EP_CTRL, | ||
1282 | (pdata->micbias1 << ADAU1373_EP_CTRL_MICBIAS1_OFFSET) | | ||
1283 | (pdata->micbias2 << ADAU1373_EP_CTRL_MICBIAS2_OFFSET)); | ||
1284 | } | ||
1285 | |||
1286 | if (!lineout_differential) { | ||
1287 | snd_soc_add_controls(codec, adau1373_lineout2_controls, | ||
1288 | ARRAY_SIZE(adau1373_lineout2_controls)); | ||
1289 | } | ||
1290 | |||
1291 | snd_soc_write(codec, ADAU1373_ADC_CTRL, | ||
1292 | ADAU1373_ADC_CTRL_RESET_FORCE | ADAU1373_ADC_CTRL_PEAK_DETECT); | ||
1293 | |||
1294 | return 0; | ||
1295 | } | ||
1296 | |||
1297 | static int adau1373_set_bias_level(struct snd_soc_codec *codec, | ||
1298 | enum snd_soc_bias_level level) | ||
1299 | { | ||
1300 | switch (level) { | ||
1301 | case SND_SOC_BIAS_ON: | ||
1302 | break; | ||
1303 | case SND_SOC_BIAS_PREPARE: | ||
1304 | break; | ||
1305 | case SND_SOC_BIAS_STANDBY: | ||
1306 | snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, | ||
1307 | ADAU1373_PWDN_CTRL3_PWR_EN, ADAU1373_PWDN_CTRL3_PWR_EN); | ||
1308 | break; | ||
1309 | case SND_SOC_BIAS_OFF: | ||
1310 | snd_soc_update_bits(codec, ADAU1373_PWDN_CTRL3, | ||
1311 | ADAU1373_PWDN_CTRL3_PWR_EN, 0); | ||
1312 | break; | ||
1313 | } | ||
1314 | codec->dapm.bias_level = level; | ||
1315 | return 0; | ||
1316 | } | ||
1317 | |||
1318 | static int adau1373_remove(struct snd_soc_codec *codec) | ||
1319 | { | ||
1320 | adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1321 | return 0; | ||
1322 | } | ||
1323 | |||
1324 | static int adau1373_suspend(struct snd_soc_codec *codec, pm_message_t state) | ||
1325 | { | ||
1326 | return adau1373_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
1327 | } | ||
1328 | |||
1329 | static int adau1373_resume(struct snd_soc_codec *codec) | ||
1330 | { | ||
1331 | adau1373_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | ||
1332 | snd_soc_cache_sync(codec); | ||
1333 | |||
1334 | return 0; | ||
1335 | } | ||
1336 | |||
1337 | static struct snd_soc_codec_driver adau1373_codec_driver = { | ||
1338 | .probe = adau1373_probe, | ||
1339 | .remove = adau1373_remove, | ||
1340 | .suspend = adau1373_suspend, | ||
1341 | .resume = adau1373_resume, | ||
1342 | .set_bias_level = adau1373_set_bias_level, | ||
1343 | .reg_cache_size = ARRAY_SIZE(adau1373_default_regs), | ||
1344 | .reg_cache_default = adau1373_default_regs, | ||
1345 | .reg_word_size = sizeof(uint8_t), | ||
1346 | |||
1347 | .set_pll = adau1373_set_pll, | ||
1348 | |||
1349 | .controls = adau1373_controls, | ||
1350 | .num_controls = ARRAY_SIZE(adau1373_controls), | ||
1351 | .dapm_widgets = adau1373_dapm_widgets, | ||
1352 | .num_dapm_widgets = ARRAY_SIZE(adau1373_dapm_widgets), | ||
1353 | .dapm_routes = adau1373_dapm_routes, | ||
1354 | .num_dapm_routes = ARRAY_SIZE(adau1373_dapm_routes), | ||
1355 | }; | ||
1356 | |||
1357 | static int __devinit adau1373_i2c_probe(struct i2c_client *client, | ||
1358 | const struct i2c_device_id *id) | ||
1359 | { | ||
1360 | struct adau1373 *adau1373; | ||
1361 | int ret; | ||
1362 | |||
1363 | adau1373 = kzalloc(sizeof(*adau1373), GFP_KERNEL); | ||
1364 | if (!adau1373) | ||
1365 | return -ENOMEM; | ||
1366 | |||
1367 | dev_set_drvdata(&client->dev, adau1373); | ||
1368 | |||
1369 | ret = snd_soc_register_codec(&client->dev, &adau1373_codec_driver, | ||
1370 | adau1373_dai_driver, ARRAY_SIZE(adau1373_dai_driver)); | ||
1371 | if (ret < 0) | ||
1372 | kfree(adau1373); | ||
1373 | |||
1374 | return ret; | ||
1375 | } | ||
1376 | |||
1377 | static int __devexit adau1373_i2c_remove(struct i2c_client *client) | ||
1378 | { | ||
1379 | snd_soc_unregister_codec(&client->dev); | ||
1380 | kfree(dev_get_drvdata(&client->dev)); | ||
1381 | return 0; | ||
1382 | } | ||
1383 | |||
1384 | static const struct i2c_device_id adau1373_i2c_id[] = { | ||
1385 | { "adau1373", 0 }, | ||
1386 | { } | ||
1387 | }; | ||
1388 | MODULE_DEVICE_TABLE(i2c, adau1373_i2c_id); | ||
1389 | |||
1390 | static struct i2c_driver adau1373_i2c_driver = { | ||
1391 | .driver = { | ||
1392 | .name = "adau1373", | ||
1393 | .owner = THIS_MODULE, | ||
1394 | }, | ||
1395 | .probe = adau1373_i2c_probe, | ||
1396 | .remove = __devexit_p(adau1373_i2c_remove), | ||
1397 | .id_table = adau1373_i2c_id, | ||
1398 | }; | ||
1399 | |||
1400 | static int __init adau1373_init(void) | ||
1401 | { | ||
1402 | return i2c_add_driver(&adau1373_i2c_driver); | ||
1403 | } | ||
1404 | module_init(adau1373_init); | ||
1405 | |||
1406 | static void __exit adau1373_exit(void) | ||
1407 | { | ||
1408 | i2c_del_driver(&adau1373_i2c_driver); | ||
1409 | } | ||
1410 | module_exit(adau1373_exit); | ||
1411 | |||
1412 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); | ||
1413 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | ||
1414 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/adau1373.h b/sound/soc/codecs/adau1373.h new file mode 100644 index 000000000000..c6ab5530760c --- /dev/null +++ b/sound/soc/codecs/adau1373.h | |||
@@ -0,0 +1,29 @@ | |||
1 | #ifndef __ADAU1373_H__ | ||
2 | #define __ADAU1373_H__ | ||
3 | |||
4 | enum adau1373_pll_src { | ||
5 | ADAU1373_PLL_SRC_MCLK1 = 0, | ||
6 | ADAU1373_PLL_SRC_BCLK1 = 1, | ||
7 | ADAU1373_PLL_SRC_BCLK2 = 2, | ||
8 | ADAU1373_PLL_SRC_BCLK3 = 3, | ||
9 | ADAU1373_PLL_SRC_LRCLK1 = 4, | ||
10 | ADAU1373_PLL_SRC_LRCLK2 = 5, | ||
11 | ADAU1373_PLL_SRC_LRCLK3 = 6, | ||
12 | ADAU1373_PLL_SRC_GPIO1 = 7, | ||
13 | ADAU1373_PLL_SRC_GPIO2 = 8, | ||
14 | ADAU1373_PLL_SRC_GPIO3 = 9, | ||
15 | ADAU1373_PLL_SRC_GPIO4 = 10, | ||
16 | ADAU1373_PLL_SRC_MCLK2 = 11, | ||
17 | }; | ||
18 | |||
19 | enum adau1373_pll { | ||
20 | ADAU1373_PLL1 = 0, | ||
21 | ADAU1373_PLL2 = 1, | ||
22 | }; | ||
23 | |||
24 | enum adau1373_clk_src { | ||
25 | ADAU1373_CLK_SRC_PLL1 = 0, | ||
26 | ADAU1373_CLK_SRC_PLL2 = 1, | ||
27 | }; | ||
28 | |||
29 | #endif | ||
diff --git a/sound/soc/codecs/adav80x.c b/sound/soc/codecs/adav80x.c index 300c04b70e71..f9f08948e5e8 100644 --- a/sound/soc/codecs/adav80x.c +++ b/sound/soc/codecs/adav80x.c | |||
@@ -523,7 +523,8 @@ static int adav80x_hw_params(struct snd_pcm_substream *substream, | |||
523 | } | 523 | } |
524 | 524 | ||
525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, | 525 | static int adav80x_set_sysclk(struct snd_soc_codec *codec, |
526 | int clk_id, unsigned int freq, int dir) | 526 | int clk_id, int source, |
527 | unsigned int freq, int dir) | ||
527 | { | 528 | { |
528 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); | 529 | struct adav80x *adav80x = snd_soc_codec_get_drvdata(codec); |
529 | 530 | ||
diff --git a/sound/soc/codecs/alc5623.c b/sound/soc/codecs/alc5623.c index eecffb548947..05173159507e 100644 --- a/sound/soc/codecs/alc5623.c +++ b/sound/soc/codecs/alc5623.c | |||
@@ -41,7 +41,6 @@ MODULE_PARM_DESC(caps_charge, "ALC5623 cap charge time (msecs)"); | |||
41 | struct alc5623_priv { | 41 | struct alc5623_priv { |
42 | enum snd_soc_control_type control_type; | 42 | enum snd_soc_control_type control_type; |
43 | void *control_data; | 43 | void *control_data; |
44 | struct mutex mutex; | ||
45 | u8 id; | 44 | u8 id; |
46 | unsigned int sysclk; | 45 | unsigned int sysclk; |
47 | u16 reg_cache[ALC5623_VENDOR_ID2+2]; | 46 | u16 reg_cache[ALC5623_VENDOR_ID2+2]; |
@@ -1052,7 +1051,6 @@ static int alc5623_i2c_probe(struct i2c_client *client, | |||
1052 | i2c_set_clientdata(client, alc5623); | 1051 | i2c_set_clientdata(client, alc5623); |
1053 | alc5623->control_data = client; | 1052 | alc5623->control_data = client; |
1054 | alc5623->control_type = SND_SOC_I2C; | 1053 | alc5623->control_type = SND_SOC_I2C; |
1055 | mutex_init(&alc5623->mutex); | ||
1056 | 1054 | ||
1057 | ret = snd_soc_register_codec(&client->dev, | 1055 | ret = snd_soc_register_codec(&client->dev, |
1058 | &soc_codec_device_alc5623, &alc5623_dai, 1); | 1056 | &soc_codec_device_alc5623, &alc5623_dai, 1); |
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 7e4066e131e6..91130fbc6913 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/regulator/driver.h> | 20 | #include <linux/regulator/driver.h> |
21 | #include <linux/regulator/machine.h> | 21 | #include <linux/regulator/machine.h> |
22 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/tlv.h> | 25 | #include <sound/tlv.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
@@ -1436,10 +1437,17 @@ static const struct i2c_device_id sgtl5000_id[] = { | |||
1436 | 1437 | ||
1437 | MODULE_DEVICE_TABLE(i2c, sgtl5000_id); | 1438 | MODULE_DEVICE_TABLE(i2c, sgtl5000_id); |
1438 | 1439 | ||
1440 | static const struct of_device_id sgtl5000_dt_ids[] = { | ||
1441 | { .compatible = "fsl,sgtl5000", }, | ||
1442 | { /* sentinel */ } | ||
1443 | }; | ||
1444 | MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); | ||
1445 | |||
1439 | static struct i2c_driver sgtl5000_i2c_driver = { | 1446 | static struct i2c_driver sgtl5000_i2c_driver = { |
1440 | .driver = { | 1447 | .driver = { |
1441 | .name = "sgtl5000", | 1448 | .name = "sgtl5000", |
1442 | .owner = THIS_MODULE, | 1449 | .owner = THIS_MODULE, |
1450 | .of_match_table = sgtl5000_dt_ids, | ||
1443 | }, | 1451 | }, |
1444 | .probe = sgtl5000_i2c_probe, | 1452 | .probe = sgtl5000_i2c_probe, |
1445 | .remove = __devexit_p(sgtl5000_i2c_remove), | 1453 | .remove = __devexit_p(sgtl5000_i2c_remove), |
diff --git a/sound/soc/codecs/sn95031.c b/sound/soc/codecs/sn95031.c index 84ffdebb8a8b..29945b004135 100644 --- a/sound/soc/codecs/sn95031.c +++ b/sound/soc/codecs/sn95031.c | |||
@@ -79,7 +79,7 @@ static void configure_adc(struct snd_soc_codec *sn95031_codec, int val) | |||
79 | */ | 79 | */ |
80 | static int find_free_channel(struct snd_soc_codec *sn95031_codec) | 80 | static int find_free_channel(struct snd_soc_codec *sn95031_codec) |
81 | { | 81 | { |
82 | int ret = 0, i, value; | 82 | int i, value; |
83 | 83 | ||
84 | /* check whether ADC is enabled */ | 84 | /* check whether ADC is enabled */ |
85 | value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); | 85 | value = snd_soc_read(sn95031_codec, SN95031_ADC1CNTL1); |
@@ -91,12 +91,10 @@ static int find_free_channel(struct snd_soc_codec *sn95031_codec) | |||
91 | for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { | 91 | for (i = 0; i < SN95031_ADC_CHANLS_MAX; i++) { |
92 | value = snd_soc_read(sn95031_codec, | 92 | value = snd_soc_read(sn95031_codec, |
93 | SN95031_ADC_CHNL_START_ADDR + i); | 93 | SN95031_ADC_CHNL_START_ADDR + i); |
94 | if (value & SN95031_STOPBIT_MASK) { | 94 | if (value & SN95031_STOPBIT_MASK) |
95 | ret = i; | ||
96 | break; | 95 | break; |
97 | } | ||
98 | } | 96 | } |
99 | return (ret > SN95031_ADC_LOOP_MAX) ? (-EINVAL) : ret; | 97 | return (i == SN95031_ADC_CHANLS_MAX) ? (-EINVAL) : i; |
100 | } | 98 | } |
101 | 99 | ||
102 | /* Initialize the ADC for reading micbias values. Can sleep. */ | 100 | /* Initialize the ADC for reading micbias values. Can sleep. */ |
@@ -660,7 +658,7 @@ static int sn95031_pcm_spkr_mute(struct snd_soc_dai *dai, int mute) | |||
660 | return 0; | 658 | return 0; |
661 | } | 659 | } |
662 | 660 | ||
663 | int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, | 661 | static int sn95031_pcm_hw_params(struct snd_pcm_substream *substream, |
664 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 662 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
665 | { | 663 | { |
666 | unsigned int format, rate; | 664 | unsigned int format, rate; |
diff --git a/sound/soc/codecs/ssm2602.c b/sound/soc/codecs/ssm2602.c index 84f4ad568556..cceb0022f02c 100644 --- a/sound/soc/codecs/ssm2602.c +++ b/sound/soc/codecs/ssm2602.c | |||
@@ -294,7 +294,6 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 294 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
295 | struct snd_soc_codec *codec = rtd->codec; | 295 | struct snd_soc_codec *codec = rtd->codec; |
296 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); | 296 | struct ssm2602_priv *ssm2602 = snd_soc_codec_get_drvdata(codec); |
297 | struct i2c_client *i2c = codec->control_data; | ||
298 | struct snd_pcm_runtime *master_runtime; | 297 | struct snd_pcm_runtime *master_runtime; |
299 | 298 | ||
300 | /* The DAI has shared clocks so if we already have a playback or | 299 | /* The DAI has shared clocks so if we already have a playback or |
@@ -303,7 +302,7 @@ static int ssm2602_startup(struct snd_pcm_substream *substream, | |||
303 | */ | 302 | */ |
304 | if (ssm2602->master_substream) { | 303 | if (ssm2602->master_substream) { |
305 | master_runtime = ssm2602->master_substream->runtime; | 304 | master_runtime = ssm2602->master_substream->runtime; |
306 | dev_dbg(&i2c->dev, "Constraining to %d bits at %dHz\n", | 305 | dev_dbg(codec->dev, "Constraining to %d bits at %dHz\n", |
307 | master_runtime->sample_bits, | 306 | master_runtime->sample_bits, |
308 | master_runtime->rate); | 307 | master_runtime->rate); |
309 | 308 | ||
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index fbd7eb9e61ce..5c7def3979c0 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -524,13 +524,17 @@ static int sta32x_hw_params(struct snd_pcm_substream *substream, | |||
524 | rate = params_rate(params); | 524 | rate = params_rate(params); |
525 | pr_debug("rate: %u\n", rate); | 525 | pr_debug("rate: %u\n", rate); |
526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) | 526 | for (i = 0; i < ARRAY_SIZE(interpolation_ratios); i++) |
527 | if (interpolation_ratios[i].fs == rate) | 527 | if (interpolation_ratios[i].fs == rate) { |
528 | ir = interpolation_ratios[i].ir; | 528 | ir = interpolation_ratios[i].ir; |
529 | break; | ||
530 | } | ||
529 | if (ir < 0) | 531 | if (ir < 0) |
530 | return -EINVAL; | 532 | return -EINVAL; |
531 | for (i = 0; mclk_ratios[ir][i].ratio; i++) | 533 | for (i = 0; mclk_ratios[ir][i].ratio; i++) |
532 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) | 534 | if (mclk_ratios[ir][i].ratio * rate == sta32x->mclk) { |
533 | mcs = mclk_ratios[ir][i].mcs; | 535 | mcs = mclk_ratios[ir][i].mcs; |
536 | break; | ||
537 | } | ||
534 | if (mcs < 0) | 538 | if (mcs < 0) |
535 | return -EINVAL; | 539 | return -EINVAL; |
536 | 540 | ||
@@ -808,6 +812,7 @@ static int sta32x_remove(struct snd_soc_codec *codec) | |||
808 | { | 812 | { |
809 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); | 813 | struct sta32x_priv *sta32x = snd_soc_codec_get_drvdata(codec); |
810 | 814 | ||
815 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
811 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 816 | regulator_bulk_disable(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
812 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | 817 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); |
813 | 818 | ||
@@ -867,18 +872,8 @@ static __devinit int sta32x_i2c_probe(struct i2c_client *i2c, | |||
867 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) | 872 | static __devexit int sta32x_i2c_remove(struct i2c_client *client) |
868 | { | 873 | { |
869 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); | 874 | struct sta32x_priv *sta32x = i2c_get_clientdata(client); |
870 | struct snd_soc_codec *codec = sta32x->codec; | ||
871 | |||
872 | if (codec) | ||
873 | sta32x_set_bias_level(codec, SND_SOC_BIAS_OFF); | ||
874 | |||
875 | regulator_bulk_free(ARRAY_SIZE(sta32x->supplies), sta32x->supplies); | ||
876 | |||
877 | if (codec) { | ||
878 | snd_soc_unregister_codec(&client->dev); | ||
879 | snd_soc_codec_set_drvdata(codec, NULL); | ||
880 | } | ||
881 | 875 | ||
876 | snd_soc_unregister_codec(&client->dev); | ||
882 | kfree(sta32x); | 877 | kfree(sta32x); |
883 | return 0; | 878 | return 0; |
884 | } | 879 | } |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 239e0c461068..b2572c451c35 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -446,7 +446,6 @@ err_regulator: | |||
446 | gpio_free(data->power_gpio); | 446 | gpio_free(data->power_gpio); |
447 | err_gpio: | 447 | err_gpio: |
448 | kfree(data); | 448 | kfree(data); |
449 | i2c_set_clientdata(tpa6130a2_client, NULL); | ||
450 | tpa6130a2_client = NULL; | 449 | tpa6130a2_client = NULL; |
451 | 450 | ||
452 | return ret; | 451 | return ret; |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 443032b3b329..81645c632447 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -118,8 +118,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { | |||
118 | 0x4A, /* TWL6040_LPPLLDIV 0x09 */ | 118 | 0x4A, /* TWL6040_LPPLLDIV 0x09 */ |
119 | 0x00, /* TWL6040_AMICBCTL 0x0A */ | 119 | 0x00, /* TWL6040_AMICBCTL 0x0A */ |
120 | 0x00, /* TWL6040_DMICBCTL 0x0B */ | 120 | 0x00, /* TWL6040_DMICBCTL 0x0B */ |
121 | 0x18, /* TWL6040_MICLCTL 0x0C - No input selected on Left Mic */ | 121 | 0x00, /* TWL6040_MICLCTL 0x0C */ |
122 | 0x18, /* TWL6040_MICRCTL 0x0D - No input selected on Right Mic */ | 122 | 0x00, /* TWL6040_MICRCTL 0x0D */ |
123 | 0x00, /* TWL6040_MICGAIN 0x0E */ | 123 | 0x00, /* TWL6040_MICGAIN 0x0E */ |
124 | 0x1B, /* TWL6040_LINEGAIN 0x0F */ | 124 | 0x1B, /* TWL6040_LINEGAIN 0x0F */ |
125 | 0x00, /* TWL6040_HSLCTL 0x10 */ | 125 | 0x00, /* TWL6040_HSLCTL 0x10 */ |
@@ -155,41 +155,8 @@ static const u8 twl6040_reg[TWL6040_CACHEREGNUM] = { | |||
155 | 0x00, /* TWL6040_STATUS (ro) 0x2E */ | 155 | 0x00, /* TWL6040_STATUS (ro) 0x2E */ |
156 | }; | 156 | }; |
157 | 157 | ||
158 | /* | 158 | /* List of registers to be restored after power up */ |
159 | * twl6040 vio/gnd registers: | 159 | static const int twl6040_restore_list[] = { |
160 | * registers under vio/gnd supply can be accessed | ||
161 | * before the power-up sequence, after NRESPWRON goes high | ||
162 | */ | ||
163 | static const int twl6040_vio_reg[TWL6040_VIOREGNUM] = { | ||
164 | TWL6040_REG_ASICID, | ||
165 | TWL6040_REG_ASICREV, | ||
166 | TWL6040_REG_INTID, | ||
167 | TWL6040_REG_INTMR, | ||
168 | TWL6040_REG_NCPCTL, | ||
169 | TWL6040_REG_LDOCTL, | ||
170 | TWL6040_REG_AMICBCTL, | ||
171 | TWL6040_REG_DMICBCTL, | ||
172 | TWL6040_REG_HKCTL1, | ||
173 | TWL6040_REG_HKCTL2, | ||
174 | TWL6040_REG_GPOCTL, | ||
175 | TWL6040_REG_TRIM1, | ||
176 | TWL6040_REG_TRIM2, | ||
177 | TWL6040_REG_TRIM3, | ||
178 | TWL6040_REG_HSOTRIM, | ||
179 | TWL6040_REG_HFOTRIM, | ||
180 | TWL6040_REG_ACCCTL, | ||
181 | TWL6040_REG_STATUS, | ||
182 | }; | ||
183 | |||
184 | /* | ||
185 | * twl6040 vdd/vss registers: | ||
186 | * registers under vdd/vss supplies can only be accessed | ||
187 | * after the power-up sequence | ||
188 | */ | ||
189 | static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { | ||
190 | TWL6040_REG_HPPLLCTL, | ||
191 | TWL6040_REG_LPPLLCTL, | ||
192 | TWL6040_REG_LPPLLDIV, | ||
193 | TWL6040_REG_MICLCTL, | 160 | TWL6040_REG_MICLCTL, |
194 | TWL6040_REG_MICRCTL, | 161 | TWL6040_REG_MICRCTL, |
195 | TWL6040_REG_MICGAIN, | 162 | TWL6040_REG_MICGAIN, |
@@ -202,12 +169,6 @@ static const int twl6040_vdd_reg[TWL6040_VDDREGNUM] = { | |||
202 | TWL6040_REG_HFLGAIN, | 169 | TWL6040_REG_HFLGAIN, |
203 | TWL6040_REG_HFRCTL, | 170 | TWL6040_REG_HFRCTL, |
204 | TWL6040_REG_HFRGAIN, | 171 | TWL6040_REG_HFRGAIN, |
205 | TWL6040_REG_VIBCTLL, | ||
206 | TWL6040_REG_VIBDATL, | ||
207 | TWL6040_REG_VIBCTLR, | ||
208 | TWL6040_REG_VIBDATR, | ||
209 | TWL6040_REG_ALB, | ||
210 | TWL6040_REG_DLB, | ||
211 | }; | 172 | }; |
212 | 173 | ||
213 | /* set of rates for each pll: low-power and high-performance */ | 174 | /* set of rates for each pll: low-power and high-performance */ |
@@ -296,56 +257,27 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
296 | return twl6040_reg_write(twl6040, reg, value); | 257 | return twl6040_reg_write(twl6040, reg, value); |
297 | } | 258 | } |
298 | 259 | ||
299 | static void twl6040_init_vio_regs(struct snd_soc_codec *codec) | 260 | static void twl6040_init_chip(struct snd_soc_codec *codec) |
300 | { | 261 | { |
301 | u8 *cache = codec->reg_cache; | 262 | struct twl6040 *twl6040 = codec->control_data; |
302 | int reg, i; | 263 | u8 val; |
303 | 264 | ||
304 | for (i = 0; i < TWL6040_VIOREGNUM; i++) { | 265 | val = twl6040_get_revid(twl6040); |
305 | reg = twl6040_vio_reg[i]; | 266 | twl6040_write_reg_cache(codec, TWL6040_REG_ASICREV, val); |
306 | /* | 267 | |
307 | * skip read-only registers (ASICID, ASICREV, STATUS) | 268 | /* Change chip defaults */ |
308 | * and registers shared among MFD children | 269 | /* No imput selected for microphone amplifiers */ |
309 | */ | 270 | twl6040_write_reg_cache(codec, TWL6040_REG_MICLCTL, 0x18); |
310 | switch (reg) { | 271 | twl6040_write_reg_cache(codec, TWL6040_REG_MICRCTL, 0x18); |
311 | case TWL6040_REG_ASICID: | ||
312 | case TWL6040_REG_ASICREV: | ||
313 | case TWL6040_REG_INTID: | ||
314 | case TWL6040_REG_INTMR: | ||
315 | case TWL6040_REG_NCPCTL: | ||
316 | case TWL6040_REG_LDOCTL: | ||
317 | case TWL6040_REG_GPOCTL: | ||
318 | case TWL6040_REG_ACCCTL: | ||
319 | case TWL6040_REG_STATUS: | ||
320 | continue; | ||
321 | default: | ||
322 | break; | ||
323 | } | ||
324 | twl6040_write(codec, reg, cache[reg]); | ||
325 | } | ||
326 | } | 272 | } |
327 | 273 | ||
328 | static void twl6040_init_vdd_regs(struct snd_soc_codec *codec) | 274 | static void twl6040_restore_regs(struct snd_soc_codec *codec) |
329 | { | 275 | { |
330 | u8 *cache = codec->reg_cache; | 276 | u8 *cache = codec->reg_cache; |
331 | int reg, i; | 277 | int reg, i; |
332 | 278 | ||
333 | for (i = 0; i < TWL6040_VDDREGNUM; i++) { | 279 | for (i = 0; i < ARRAY_SIZE(twl6040_restore_list); i++) { |
334 | reg = twl6040_vdd_reg[i]; | 280 | reg = twl6040_restore_list[i]; |
335 | /* skip vibra and PLL registers */ | ||
336 | switch (reg) { | ||
337 | case TWL6040_REG_VIBCTLL: | ||
338 | case TWL6040_REG_VIBDATL: | ||
339 | case TWL6040_REG_VIBCTLR: | ||
340 | case TWL6040_REG_VIBDATR: | ||
341 | case TWL6040_REG_HPPLLCTL: | ||
342 | case TWL6040_REG_LPPLLCTL: | ||
343 | case TWL6040_REG_LPPLLDIV: | ||
344 | continue; | ||
345 | default: | ||
346 | break; | ||
347 | } | ||
348 | |||
349 | twl6040_write(codec, reg, cache[reg]); | 281 | twl6040_write(codec, reg, cache[reg]); |
350 | } | 282 | } |
351 | } | 283 | } |
@@ -1325,8 +1257,7 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec, | |||
1325 | 1257 | ||
1326 | priv->codec_powered = 1; | 1258 | priv->codec_powered = 1; |
1327 | 1259 | ||
1328 | /* initialize vdd/vss registers with reg_cache */ | 1260 | twl6040_restore_regs(codec); |
1329 | twl6040_init_vdd_regs(codec); | ||
1330 | 1261 | ||
1331 | /* Set external boost GPO */ | 1262 | /* Set external boost GPO */ |
1332 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); | 1263 | twl6040_write(codec, TWL6040_REG_GPOCTL, 0x02); |
@@ -1468,7 +1399,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1468 | .playback = { | 1399 | .playback = { |
1469 | .stream_name = "Playback", | 1400 | .stream_name = "Playback", |
1470 | .channels_min = 1, | 1401 | .channels_min = 1, |
1471 | .channels_max = 2, | 1402 | .channels_max = 5, |
1472 | .rates = TWL6040_RATES, | 1403 | .rates = TWL6040_RATES, |
1473 | .formats = TWL6040_FORMATS, | 1404 | .formats = TWL6040_FORMATS, |
1474 | }, | 1405 | }, |
@@ -1518,8 +1449,8 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1518 | .name = "twl6040-vib", | 1449 | .name = "twl6040-vib", |
1519 | .playback = { | 1450 | .playback = { |
1520 | .stream_name = "Vibra Playback", | 1451 | .stream_name = "Vibra Playback", |
1521 | .channels_min = 2, | 1452 | .channels_min = 1, |
1522 | .channels_max = 2, | 1453 | .channels_max = 1, |
1523 | .rates = SNDRV_PCM_RATE_CONTINUOUS, | 1454 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
1524 | .formats = TWL6040_FORMATS, | 1455 | .formats = TWL6040_FORMATS, |
1525 | }, | 1456 | }, |
@@ -1620,8 +1551,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1620 | goto plugirq_err; | 1551 | goto plugirq_err; |
1621 | } | 1552 | } |
1622 | 1553 | ||
1623 | /* init vio registers */ | 1554 | twl6040_init_chip(codec); |
1624 | twl6040_init_vio_regs(codec); | ||
1625 | 1555 | ||
1626 | /* power on device */ | 1556 | /* power on device */ |
1627 | ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1557 | ret = twl6040_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
diff --git a/sound/soc/codecs/wm1250-ev1.c b/sound/soc/codecs/wm1250-ev1.c index bcc208967917..4523c4cec02b 100644 --- a/sound/soc/codecs/wm1250-ev1.c +++ b/sound/soc/codecs/wm1250-ev1.c | |||
@@ -56,8 +56,26 @@ static struct snd_soc_codec_driver soc_codec_dev_wm1250_ev1 = { | |||
56 | }; | 56 | }; |
57 | 57 | ||
58 | static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, | 58 | static int __devinit wm1250_ev1_probe(struct i2c_client *i2c, |
59 | const struct i2c_device_id *id) | 59 | const struct i2c_device_id *i2c_id) |
60 | { | 60 | { |
61 | int id, board, rev; | ||
62 | |||
63 | board = i2c_smbus_read_byte_data(i2c, 0); | ||
64 | if (board < 0) { | ||
65 | dev_err(&i2c->dev, "Failed to read ID: %d\n", board); | ||
66 | return board; | ||
67 | } | ||
68 | |||
69 | id = (board & 0xfe) >> 2; | ||
70 | rev = board & 0x3; | ||
71 | |||
72 | if (id != 1) { | ||
73 | dev_err(&i2c->dev, "Unknown board ID %d\n", id); | ||
74 | return -ENODEV; | ||
75 | } | ||
76 | |||
77 | dev_info(&i2c->dev, "revision %d\n", rev + 1); | ||
78 | |||
61 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, | 79 | return snd_soc_register_codec(&i2c->dev, &soc_codec_dev_wm1250_ev1, |
62 | &wm1250_ev1_dai, 1); | 80 | &wm1250_ev1_dai, 1); |
63 | } | 81 | } |
diff --git a/sound/soc/codecs/wm8510.c b/sound/soc/codecs/wm8510.c index db0dced74843..55a4c830e111 100644 --- a/sound/soc/codecs/wm8510.c +++ b/sound/soc/codecs/wm8510.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/platform_device.h> | 20 | #include <linux/platform_device.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -598,6 +599,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8510 = { | |||
598 | .reg_cache_default =wm8510_reg, | 599 | .reg_cache_default =wm8510_reg, |
599 | }; | 600 | }; |
600 | 601 | ||
602 | static const struct of_device_id wm8510_of_match[] = { | ||
603 | { .compatible = "wlf,wm8510" }, | ||
604 | { }, | ||
605 | }; | ||
606 | |||
601 | #if defined(CONFIG_SPI_MASTER) | 607 | #if defined(CONFIG_SPI_MASTER) |
602 | static int __devinit wm8510_spi_probe(struct spi_device *spi) | 608 | static int __devinit wm8510_spi_probe(struct spi_device *spi) |
603 | { | 609 | { |
@@ -628,6 +634,7 @@ static struct spi_driver wm8510_spi_driver = { | |||
628 | .driver = { | 634 | .driver = { |
629 | .name = "wm8510", | 635 | .name = "wm8510", |
630 | .owner = THIS_MODULE, | 636 | .owner = THIS_MODULE, |
637 | .of_match_table = wm8510_of_match, | ||
631 | }, | 638 | }, |
632 | .probe = wm8510_spi_probe, | 639 | .probe = wm8510_spi_probe, |
633 | .remove = __devexit_p(wm8510_spi_remove), | 640 | .remove = __devexit_p(wm8510_spi_remove), |
@@ -671,6 +678,7 @@ static struct i2c_driver wm8510_i2c_driver = { | |||
671 | .driver = { | 678 | .driver = { |
672 | .name = "wm8510-codec", | 679 | .name = "wm8510-codec", |
673 | .owner = THIS_MODULE, | 680 | .owner = THIS_MODULE, |
681 | .of_match_table = wm8510_of_match, | ||
674 | }, | 682 | }, |
675 | .probe = wm8510_i2c_probe, | 683 | .probe = wm8510_i2c_probe, |
676 | .remove = __devexit_p(wm8510_i2c_remove), | 684 | .remove = __devexit_p(wm8510_i2c_remove), |
diff --git a/sound/soc/codecs/wm8523.c b/sound/soc/codecs/wm8523.c index 4fd4d8dca0fc..5355a7a944f7 100644 --- a/sound/soc/codecs/wm8523.c +++ b/sound/soc/codecs/wm8523.c | |||
@@ -20,6 +20,7 @@ | |||
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 <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -84,7 +85,7 @@ static const char *wm8523_zd_count_text[] = { | |||
84 | static const struct soc_enum wm8523_zc_count = | 85 | static const struct soc_enum wm8523_zc_count = |
85 | SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); | 86 | SOC_ENUM_SINGLE(WM8523_ZERO_DETECT, 0, 2, wm8523_zd_count_text); |
86 | 87 | ||
87 | static const struct snd_kcontrol_new wm8523_snd_controls[] = { | 88 | static const struct snd_kcontrol_new wm8523_controls[] = { |
88 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, | 89 | SOC_DOUBLE_R_TLV("Playback Volume", WM8523_DAC_GAINL, WM8523_DAC_GAINR, |
89 | 0, 448, 0, dac_tlv), | 90 | 0, 448, 0, dac_tlv), |
90 | SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), | 91 | SOC_SINGLE("ZC Switch", WM8523_DAC_CTRL3, 4, 1, 0), |
@@ -101,22 +102,11 @@ SND_SOC_DAPM_OUTPUT("LINEVOUTL"), | |||
101 | SND_SOC_DAPM_OUTPUT("LINEVOUTR"), | 102 | SND_SOC_DAPM_OUTPUT("LINEVOUTR"), |
102 | }; | 103 | }; |
103 | 104 | ||
104 | static const struct snd_soc_dapm_route intercon[] = { | 105 | static const struct snd_soc_dapm_route wm8523_dapm_routes[] = { |
105 | { "LINEVOUTL", NULL, "DAC" }, | 106 | { "LINEVOUTL", NULL, "DAC" }, |
106 | { "LINEVOUTR", NULL, "DAC" }, | 107 | { "LINEVOUTR", NULL, "DAC" }, |
107 | }; | 108 | }; |
108 | 109 | ||
109 | static int wm8523_add_widgets(struct snd_soc_codec *codec) | ||
110 | { | ||
111 | struct snd_soc_dapm_context *dapm = &codec->dapm; | ||
112 | |||
113 | snd_soc_dapm_new_controls(dapm, wm8523_dapm_widgets, | ||
114 | ARRAY_SIZE(wm8523_dapm_widgets)); | ||
115 | snd_soc_dapm_add_routes(dapm, intercon, ARRAY_SIZE(intercon)); | ||
116 | |||
117 | return 0; | ||
118 | } | ||
119 | |||
120 | static struct { | 110 | static struct { |
121 | int value; | 111 | int value; |
122 | int ratio; | 112 | int ratio; |
@@ -479,10 +469,6 @@ static int wm8523_probe(struct snd_soc_codec *codec) | |||
479 | /* Bias level configuration will have done an extra enable */ | 469 | /* Bias level configuration will have done an extra enable */ |
480 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); | 470 | regulator_bulk_disable(ARRAY_SIZE(wm8523->supplies), wm8523->supplies); |
481 | 471 | ||
482 | snd_soc_add_controls(codec, wm8523_snd_controls, | ||
483 | ARRAY_SIZE(wm8523_snd_controls)); | ||
484 | wm8523_add_widgets(codec); | ||
485 | |||
486 | return 0; | 472 | return 0; |
487 | 473 | ||
488 | err_enable: | 474 | err_enable: |
@@ -512,6 +498,18 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8523 = { | |||
512 | .reg_word_size = sizeof(u16), | 498 | .reg_word_size = sizeof(u16), |
513 | .reg_cache_default = wm8523_reg, | 499 | .reg_cache_default = wm8523_reg, |
514 | .volatile_register = wm8523_volatile_register, | 500 | .volatile_register = wm8523_volatile_register, |
501 | |||
502 | .controls = wm8523_controls, | ||
503 | .num_controls = ARRAY_SIZE(wm8523_controls), | ||
504 | .dapm_widgets = wm8523_dapm_widgets, | ||
505 | .num_dapm_widgets = ARRAY_SIZE(wm8523_dapm_widgets), | ||
506 | .dapm_routes = wm8523_dapm_routes, | ||
507 | .num_dapm_routes = ARRAY_SIZE(wm8523_dapm_routes), | ||
508 | }; | ||
509 | |||
510 | static const struct of_device_id wm8523_of_match[] = { | ||
511 | { .compatible = "wlf,wm8523" }, | ||
512 | { }, | ||
515 | }; | 513 | }; |
516 | 514 | ||
517 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 515 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
@@ -551,8 +549,9 @@ MODULE_DEVICE_TABLE(i2c, wm8523_i2c_id); | |||
551 | 549 | ||
552 | static struct i2c_driver wm8523_i2c_driver = { | 550 | static struct i2c_driver wm8523_i2c_driver = { |
553 | .driver = { | 551 | .driver = { |
554 | .name = "wm8523-codec", | 552 | .name = "wm8523", |
555 | .owner = THIS_MODULE, | 553 | .owner = THIS_MODULE, |
554 | .of_match_table = wm8523_of_match, | ||
556 | }, | 555 | }, |
557 | .probe = wm8523_i2c_probe, | 556 | .probe = wm8523_i2c_probe, |
558 | .remove = __devexit_p(wm8523_i2c_remove), | 557 | .remove = __devexit_p(wm8523_i2c_remove), |
diff --git a/sound/soc/codecs/wm8580.c b/sound/soc/codecs/wm8580.c index 4bbc0a79f01e..4664c3a76c78 100644 --- a/sound/soc/codecs/wm8580.c +++ b/sound/soc/codecs/wm8580.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/regulator/consumer.h> | 27 | #include <linux/regulator/consumer.h> |
28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
29 | #include <linux/of_device.h> | ||
29 | 30 | ||
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -907,6 +908,11 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8580 = { | |||
907 | .reg_cache_default = wm8580_reg, | 908 | .reg_cache_default = wm8580_reg, |
908 | }; | 909 | }; |
909 | 910 | ||
911 | static const struct of_device_id wm8580_of_match[] = { | ||
912 | { .compatible = "wlf,wm8580" }, | ||
913 | { }, | ||
914 | }; | ||
915 | |||
910 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 916 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
911 | static int wm8580_i2c_probe(struct i2c_client *i2c, | 917 | static int wm8580_i2c_probe(struct i2c_client *i2c, |
912 | const struct i2c_device_id *id) | 918 | const struct i2c_device_id *id) |
@@ -943,8 +949,9 @@ MODULE_DEVICE_TABLE(i2c, wm8580_i2c_id); | |||
943 | 949 | ||
944 | static struct i2c_driver wm8580_i2c_driver = { | 950 | static struct i2c_driver wm8580_i2c_driver = { |
945 | .driver = { | 951 | .driver = { |
946 | .name = "wm8580-codec", | 952 | .name = "wm8580", |
947 | .owner = THIS_MODULE, | 953 | .owner = THIS_MODULE, |
954 | .of_match_table = wm8580_of_match, | ||
948 | }, | 955 | }, |
949 | .probe = wm8580_i2c_probe, | 956 | .probe = wm8580_i2c_probe, |
950 | .remove = wm8580_i2c_remove, | 957 | .remove = wm8580_i2c_remove, |
diff --git a/sound/soc/codecs/wm8711.c b/sound/soc/codecs/wm8711.c index a537e4af6ae7..8457d3cb5962 100644 --- a/sound/soc/codecs/wm8711.c +++ b/sound/soc/codecs/wm8711.c | |||
@@ -21,6 +21,7 @@ | |||
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 <linux/of_device.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -414,6 +415,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8711 = { | |||
414 | .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), | 415 | .num_dapm_routes = ARRAY_SIZE(wm8711_intercon), |
415 | }; | 416 | }; |
416 | 417 | ||
418 | static const struct of_device_id wm8711_of_match[] = { | ||
419 | { .compatible = "wlf,wm8711", }, | ||
420 | { } | ||
421 | }; | ||
422 | MODULE_DEVICE_TABLE(of, wm8711_of_match); | ||
423 | |||
417 | #if defined(CONFIG_SPI_MASTER) | 424 | #if defined(CONFIG_SPI_MASTER) |
418 | static int __devinit wm8711_spi_probe(struct spi_device *spi) | 425 | static int __devinit wm8711_spi_probe(struct spi_device *spi) |
419 | { | 426 | { |
@@ -443,8 +450,9 @@ static int __devexit wm8711_spi_remove(struct spi_device *spi) | |||
443 | 450 | ||
444 | static struct spi_driver wm8711_spi_driver = { | 451 | static struct spi_driver wm8711_spi_driver = { |
445 | .driver = { | 452 | .driver = { |
446 | .name = "wm8711-codec", | 453 | .name = "wm8711", |
447 | .owner = THIS_MODULE, | 454 | .owner = THIS_MODULE, |
455 | .of_match_table = wm8711_of_match, | ||
448 | }, | 456 | }, |
449 | .probe = wm8711_spi_probe, | 457 | .probe = wm8711_spi_probe, |
450 | .remove = __devexit_p(wm8711_spi_remove), | 458 | .remove = __devexit_p(wm8711_spi_remove), |
@@ -487,8 +495,9 @@ MODULE_DEVICE_TABLE(i2c, wm8711_i2c_id); | |||
487 | 495 | ||
488 | static struct i2c_driver wm8711_i2c_driver = { | 496 | static struct i2c_driver wm8711_i2c_driver = { |
489 | .driver = { | 497 | .driver = { |
490 | .name = "wm8711-codec", | 498 | .name = "wm8711", |
491 | .owner = THIS_MODULE, | 499 | .owner = THIS_MODULE, |
500 | .of_match_table = wm8711_of_match, | ||
492 | }, | 501 | }, |
493 | .probe = wm8711_i2c_probe, | 502 | .probe = wm8711_i2c_probe, |
494 | .remove = __devexit_p(wm8711_i2c_remove), | 503 | .remove = __devexit_p(wm8711_i2c_remove), |
diff --git a/sound/soc/codecs/wm8728.c b/sound/soc/codecs/wm8728.c index 86d4718d3a76..04b027efd5c0 100644 --- a/sound/soc/codecs/wm8728.c +++ b/sound/soc/codecs/wm8728.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
20 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/of_device.h> | ||
22 | #include <sound/core.h> | 23 | #include <sound/core.h> |
23 | #include <sound/pcm.h> | 24 | #include <sound/pcm.h> |
24 | #include <sound/pcm_params.h> | 25 | #include <sound/pcm_params.h> |
@@ -269,6 +270,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8728 = { | |||
269 | .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), | 270 | .num_dapm_routes = ARRAY_SIZE(wm8728_intercon), |
270 | }; | 271 | }; |
271 | 272 | ||
273 | static const struct of_device_id wm8728_of_match[] = { | ||
274 | { .compatible = "wlf,wm8728", }, | ||
275 | { } | ||
276 | }; | ||
277 | MODULE_DEVICE_TABLE(of, wm8728_of_match); | ||
278 | |||
272 | #if defined(CONFIG_SPI_MASTER) | 279 | #if defined(CONFIG_SPI_MASTER) |
273 | static int __devinit wm8728_spi_probe(struct spi_device *spi) | 280 | static int __devinit wm8728_spi_probe(struct spi_device *spi) |
274 | { | 281 | { |
@@ -298,8 +305,9 @@ static int __devexit wm8728_spi_remove(struct spi_device *spi) | |||
298 | 305 | ||
299 | static struct spi_driver wm8728_spi_driver = { | 306 | static struct spi_driver wm8728_spi_driver = { |
300 | .driver = { | 307 | .driver = { |
301 | .name = "wm8728-codec", | 308 | .name = "wm8728", |
302 | .owner = THIS_MODULE, | 309 | .owner = THIS_MODULE, |
310 | .of_match_table = wm8728_of_match, | ||
303 | }, | 311 | }, |
304 | .probe = wm8728_spi_probe, | 312 | .probe = wm8728_spi_probe, |
305 | .remove = __devexit_p(wm8728_spi_remove), | 313 | .remove = __devexit_p(wm8728_spi_remove), |
@@ -342,8 +350,9 @@ MODULE_DEVICE_TABLE(i2c, wm8728_i2c_id); | |||
342 | 350 | ||
343 | static struct i2c_driver wm8728_i2c_driver = { | 351 | static struct i2c_driver wm8728_i2c_driver = { |
344 | .driver = { | 352 | .driver = { |
345 | .name = "wm8728-codec", | 353 | .name = "wm8728", |
346 | .owner = THIS_MODULE, | 354 | .owner = THIS_MODULE, |
355 | .of_match_table = wm8728_of_match, | ||
347 | }, | 356 | }, |
348 | .probe = wm8728_i2c_probe, | 357 | .probe = wm8728_i2c_probe, |
349 | .remove = __devexit_p(wm8728_i2c_remove), | 358 | .remove = __devexit_p(wm8728_i2c_remove), |
diff --git a/sound/soc/codecs/wm8731.c b/sound/soc/codecs/wm8731.c index 76b4361e9b80..f76b6fc6766a 100644 --- a/sound/soc/codecs/wm8731.c +++ b/sound/soc/codecs/wm8731.c | |||
@@ -22,6 +22,7 @@ | |||
22 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
23 | #include <linux/regulator/consumer.h> | 23 | #include <linux/regulator/consumer.h> |
24 | #include <linux/spi/spi.h> | 24 | #include <linux/spi/spi.h> |
25 | #include <linux/of_device.h> | ||
25 | #include <sound/core.h> | 26 | #include <sound/core.h> |
26 | #include <sound/pcm.h> | 27 | #include <sound/pcm.h> |
27 | #include <sound/pcm_params.h> | 28 | #include <sound/pcm_params.h> |
@@ -607,6 +608,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8731 = { | |||
607 | .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), | 608 | .num_dapm_routes = ARRAY_SIZE(wm8731_intercon), |
608 | }; | 609 | }; |
609 | 610 | ||
611 | static const struct of_device_id wm8731_of_match[] = { | ||
612 | { .compatible = "wlf,wm8731", }, | ||
613 | { } | ||
614 | }; | ||
615 | |||
616 | MODULE_DEVICE_TABLE(of, wm8731_of_match); | ||
617 | |||
610 | #if defined(CONFIG_SPI_MASTER) | 618 | #if defined(CONFIG_SPI_MASTER) |
611 | static int __devinit wm8731_spi_probe(struct spi_device *spi) | 619 | static int __devinit wm8731_spi_probe(struct spi_device *spi) |
612 | { | 620 | { |
@@ -638,6 +646,7 @@ static struct spi_driver wm8731_spi_driver = { | |||
638 | .driver = { | 646 | .driver = { |
639 | .name = "wm8731", | 647 | .name = "wm8731", |
640 | .owner = THIS_MODULE, | 648 | .owner = THIS_MODULE, |
649 | .of_match_table = wm8731_of_match, | ||
641 | }, | 650 | }, |
642 | .probe = wm8731_spi_probe, | 651 | .probe = wm8731_spi_probe, |
643 | .remove = __devexit_p(wm8731_spi_remove), | 652 | .remove = __devexit_p(wm8731_spi_remove), |
@@ -682,6 +691,7 @@ static struct i2c_driver wm8731_i2c_driver = { | |||
682 | .driver = { | 691 | .driver = { |
683 | .name = "wm8731", | 692 | .name = "wm8731", |
684 | .owner = THIS_MODULE, | 693 | .owner = THIS_MODULE, |
694 | .of_match_table = wm8731_of_match, | ||
685 | }, | 695 | }, |
686 | .probe = wm8731_i2c_probe, | 696 | .probe = wm8731_i2c_probe, |
687 | .remove = __devexit_p(wm8731_i2c_remove), | 697 | .remove = __devexit_p(wm8731_i2c_remove), |
diff --git a/sound/soc/codecs/wm8737.c b/sound/soc/codecs/wm8737.c index 30c67d06a904..f6aef58845c2 100644 --- a/sound/soc/codecs/wm8737.c +++ b/sound/soc/codecs/wm8737.c | |||
@@ -20,6 +20,7 @@ | |||
20 | #include <linux/regulator/consumer.h> | 20 | #include <linux/regulator/consumer.h> |
21 | #include <linux/spi/spi.h> | 21 | #include <linux/spi/spi.h> |
22 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
23 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 24 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 25 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 26 | #include <sound/pcm_params.h> |
@@ -634,6 +635,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8737 = { | |||
634 | .reg_cache_default = wm8737_reg, | 635 | .reg_cache_default = wm8737_reg, |
635 | }; | 636 | }; |
636 | 637 | ||
638 | static const struct of_device_id wm8737_of_match[] = { | ||
639 | { .compatible = "wlf,wm8737", }, | ||
640 | { } | ||
641 | }; | ||
642 | |||
643 | MODULE_DEVICE_TABLE(of, wm8737_of_match); | ||
644 | |||
637 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 645 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
638 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, | 646 | static __devinit int wm8737_i2c_probe(struct i2c_client *i2c, |
639 | const struct i2c_device_id *id) | 647 | const struct i2c_device_id *id) |
@@ -673,6 +681,7 @@ static struct i2c_driver wm8737_i2c_driver = { | |||
673 | .driver = { | 681 | .driver = { |
674 | .name = "wm8737", | 682 | .name = "wm8737", |
675 | .owner = THIS_MODULE, | 683 | .owner = THIS_MODULE, |
684 | .of_match_table = wm8737_of_match, | ||
676 | }, | 685 | }, |
677 | .probe = wm8737_i2c_probe, | 686 | .probe = wm8737_i2c_probe, |
678 | .remove = __devexit_p(wm8737_i2c_remove), | 687 | .remove = __devexit_p(wm8737_i2c_remove), |
@@ -711,6 +720,7 @@ static struct spi_driver wm8737_spi_driver = { | |||
711 | .driver = { | 720 | .driver = { |
712 | .name = "wm8737", | 721 | .name = "wm8737", |
713 | .owner = THIS_MODULE, | 722 | .owner = THIS_MODULE, |
723 | .of_match_table = wm8737_of_match, | ||
714 | }, | 724 | }, |
715 | .probe = wm8737_spi_probe, | 725 | .probe = wm8737_spi_probe, |
716 | .remove = __devexit_p(wm8737_spi_remove), | 726 | .remove = __devexit_p(wm8737_spi_remove), |
diff --git a/sound/soc/codecs/wm8741.c b/sound/soc/codecs/wm8741.c index 25af901fe813..78c9e5ab3fa5 100644 --- a/sound/soc/codecs/wm8741.c +++ b/sound/soc/codecs/wm8741.c | |||
@@ -17,9 +17,11 @@ | |||
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/spi/spi.h> | ||
20 | #include <linux/platform_device.h> | 21 | #include <linux/platform_device.h> |
21 | #include <linux/regulator/consumer.h> | 22 | #include <linux/regulator/consumer.h> |
22 | #include <linux/slab.h> | 23 | #include <linux/slab.h> |
24 | #include <linux/of_device.h> | ||
23 | #include <sound/core.h> | 25 | #include <sound/core.h> |
24 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
25 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -422,17 +424,35 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
422 | { | 424 | { |
423 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | 425 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); |
424 | int ret = 0; | 426 | int ret = 0; |
427 | int i; | ||
428 | |||
429 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
430 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
431 | |||
432 | ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(wm8741->supplies), | ||
433 | wm8741->supplies); | ||
434 | if (ret != 0) { | ||
435 | dev_err(codec->dev, "Failed to request supplies: %d\n", ret); | ||
436 | goto err; | ||
437 | } | ||
438 | |||
439 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | ||
440 | wm8741->supplies); | ||
441 | if (ret != 0) { | ||
442 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | ||
443 | goto err_get; | ||
444 | } | ||
425 | 445 | ||
426 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); | 446 | ret = snd_soc_codec_set_cache_io(codec, 7, 9, wm8741->control_type); |
427 | if (ret != 0) { | 447 | if (ret != 0) { |
428 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); | 448 | dev_err(codec->dev, "Failed to set cache I/O: %d\n", ret); |
429 | return ret; | 449 | goto err_enable; |
430 | } | 450 | } |
431 | 451 | ||
432 | ret = wm8741_reset(codec); | 452 | ret = wm8741_reset(codec); |
433 | if (ret < 0) { | 453 | if (ret < 0) { |
434 | dev_err(codec->dev, "Failed to issue reset\n"); | 454 | dev_err(codec->dev, "Failed to issue reset\n"); |
435 | return ret; | 455 | goto err_enable; |
436 | } | 456 | } |
437 | 457 | ||
438 | /* Change some default settings - latch VU */ | 458 | /* Change some default settings - latch VU */ |
@@ -451,58 +471,61 @@ static int wm8741_probe(struct snd_soc_codec *codec) | |||
451 | 471 | ||
452 | dev_dbg(codec->dev, "Successful registration\n"); | 472 | dev_dbg(codec->dev, "Successful registration\n"); |
453 | return ret; | 473 | return ret; |
474 | |||
475 | err_enable: | ||
476 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
477 | err_get: | ||
478 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
479 | err: | ||
480 | return ret; | ||
481 | } | ||
482 | |||
483 | static int wm8741_remove(struct snd_soc_codec *codec) | ||
484 | { | ||
485 | struct wm8741_priv *wm8741 = snd_soc_codec_get_drvdata(codec); | ||
486 | |||
487 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
488 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
489 | |||
490 | return 0; | ||
454 | } | 491 | } |
455 | 492 | ||
456 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { | 493 | static struct snd_soc_codec_driver soc_codec_dev_wm8741 = { |
457 | .probe = wm8741_probe, | 494 | .probe = wm8741_probe, |
495 | .remove = wm8741_remove, | ||
458 | .resume = wm8741_resume, | 496 | .resume = wm8741_resume, |
459 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), | 497 | .reg_cache_size = ARRAY_SIZE(wm8741_reg_defaults), |
460 | .reg_word_size = sizeof(u16), | 498 | .reg_word_size = sizeof(u16), |
461 | .reg_cache_default = wm8741_reg_defaults, | 499 | .reg_cache_default = wm8741_reg_defaults, |
462 | }; | 500 | }; |
463 | 501 | ||
502 | static const struct of_device_id wm8741_of_match[] = { | ||
503 | { .compatible = "wlf,wm8741", }, | ||
504 | { } | ||
505 | }; | ||
506 | MODULE_DEVICE_TABLE(of, wm8741_of_match); | ||
507 | |||
464 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 508 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
465 | static int wm8741_i2c_probe(struct i2c_client *i2c, | 509 | static int wm8741_i2c_probe(struct i2c_client *i2c, |
466 | const struct i2c_device_id *id) | 510 | const struct i2c_device_id *id) |
467 | { | 511 | { |
468 | struct wm8741_priv *wm8741; | 512 | struct wm8741_priv *wm8741; |
469 | int ret, i; | 513 | int ret; |
470 | 514 | ||
471 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | 515 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); |
472 | if (wm8741 == NULL) | 516 | if (wm8741 == NULL) |
473 | return -ENOMEM; | 517 | return -ENOMEM; |
474 | 518 | ||
475 | for (i = 0; i < ARRAY_SIZE(wm8741->supplies); i++) | ||
476 | wm8741->supplies[i].supply = wm8741_supply_names[i]; | ||
477 | |||
478 | ret = regulator_bulk_get(&i2c->dev, ARRAY_SIZE(wm8741->supplies), | ||
479 | wm8741->supplies); | ||
480 | if (ret != 0) { | ||
481 | dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); | ||
482 | goto err; | ||
483 | } | ||
484 | |||
485 | ret = regulator_bulk_enable(ARRAY_SIZE(wm8741->supplies), | ||
486 | wm8741->supplies); | ||
487 | if (ret != 0) { | ||
488 | dev_err(&i2c->dev, "Failed to enable supplies: %d\n", ret); | ||
489 | goto err_get; | ||
490 | } | ||
491 | |||
492 | i2c_set_clientdata(i2c, wm8741); | 519 | i2c_set_clientdata(i2c, wm8741); |
493 | wm8741->control_type = SND_SOC_I2C; | 520 | wm8741->control_type = SND_SOC_I2C; |
494 | 521 | ||
495 | ret = snd_soc_register_codec(&i2c->dev, | 522 | ret = snd_soc_register_codec(&i2c->dev, |
496 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | 523 | &soc_codec_dev_wm8741, &wm8741_dai, 1); |
497 | if (ret < 0) | 524 | if (ret != 0) |
498 | goto err_enable; | 525 | goto err; |
499 | return ret; | ||
500 | 526 | ||
501 | err_enable: | 527 | return ret; |
502 | regulator_bulk_disable(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
503 | 528 | ||
504 | err_get: | ||
505 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
506 | err: | 529 | err: |
507 | kfree(wm8741); | 530 | kfree(wm8741); |
508 | return ret; | 531 | return ret; |
@@ -510,10 +533,7 @@ err: | |||
510 | 533 | ||
511 | static int wm8741_i2c_remove(struct i2c_client *client) | 534 | static int wm8741_i2c_remove(struct i2c_client *client) |
512 | { | 535 | { |
513 | struct wm8741_priv *wm8741 = i2c_get_clientdata(client); | ||
514 | |||
515 | snd_soc_unregister_codec(&client->dev); | 536 | snd_soc_unregister_codec(&client->dev); |
516 | regulator_bulk_free(ARRAY_SIZE(wm8741->supplies), wm8741->supplies); | ||
517 | kfree(i2c_get_clientdata(client)); | 537 | kfree(i2c_get_clientdata(client)); |
518 | return 0; | 538 | return 0; |
519 | } | 539 | } |
@@ -526,8 +546,9 @@ MODULE_DEVICE_TABLE(i2c, wm8741_i2c_id); | |||
526 | 546 | ||
527 | static struct i2c_driver wm8741_i2c_driver = { | 547 | static struct i2c_driver wm8741_i2c_driver = { |
528 | .driver = { | 548 | .driver = { |
529 | .name = "wm8741-codec", | 549 | .name = "wm8741", |
530 | .owner = THIS_MODULE, | 550 | .owner = THIS_MODULE, |
551 | .of_match_table = wm8741_of_match, | ||
531 | }, | 552 | }, |
532 | .probe = wm8741_i2c_probe, | 553 | .probe = wm8741_i2c_probe, |
533 | .remove = wm8741_i2c_remove, | 554 | .remove = wm8741_i2c_remove, |
@@ -535,6 +556,44 @@ static struct i2c_driver wm8741_i2c_driver = { | |||
535 | }; | 556 | }; |
536 | #endif | 557 | #endif |
537 | 558 | ||
559 | #if defined(CONFIG_SPI_MASTER) | ||
560 | static int __devinit wm8741_spi_probe(struct spi_device *spi) | ||
561 | { | ||
562 | struct wm8741_priv *wm8741; | ||
563 | int ret; | ||
564 | |||
565 | wm8741 = kzalloc(sizeof(struct wm8741_priv), GFP_KERNEL); | ||
566 | if (wm8741 == NULL) | ||
567 | return -ENOMEM; | ||
568 | |||
569 | wm8741->control_type = SND_SOC_SPI; | ||
570 | spi_set_drvdata(spi, wm8741); | ||
571 | |||
572 | ret = snd_soc_register_codec(&spi->dev, | ||
573 | &soc_codec_dev_wm8741, &wm8741_dai, 1); | ||
574 | if (ret < 0) | ||
575 | kfree(wm8741); | ||
576 | return ret; | ||
577 | } | ||
578 | |||
579 | static int __devexit wm8741_spi_remove(struct spi_device *spi) | ||
580 | { | ||
581 | snd_soc_unregister_codec(&spi->dev); | ||
582 | kfree(spi_get_drvdata(spi)); | ||
583 | return 0; | ||
584 | } | ||
585 | |||
586 | static struct spi_driver wm8741_spi_driver = { | ||
587 | .driver = { | ||
588 | .name = "wm8741", | ||
589 | .owner = THIS_MODULE, | ||
590 | .of_match_table = wm8741_of_match, | ||
591 | }, | ||
592 | .probe = wm8741_spi_probe, | ||
593 | .remove = __devexit_p(wm8741_spi_remove), | ||
594 | }; | ||
595 | #endif /* CONFIG_SPI_MASTER */ | ||
596 | |||
538 | static int __init wm8741_modinit(void) | 597 | static int __init wm8741_modinit(void) |
539 | { | 598 | { |
540 | int ret = 0; | 599 | int ret = 0; |
@@ -544,6 +603,13 @@ static int __init wm8741_modinit(void) | |||
544 | if (ret != 0) | 603 | if (ret != 0) |
545 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); | 604 | pr_err("Failed to register WM8741 I2C driver: %d\n", ret); |
546 | #endif | 605 | #endif |
606 | #if defined(CONFIG_SPI_MASTER) | ||
607 | ret = spi_register_driver(&wm8741_spi_driver); | ||
608 | if (ret != 0) { | ||
609 | printk(KERN_ERR "Failed to register wm8741 SPI driver: %d\n", | ||
610 | ret); | ||
611 | } | ||
612 | #endif | ||
547 | 613 | ||
548 | return ret; | 614 | return ret; |
549 | } | 615 | } |
@@ -551,6 +617,9 @@ module_init(wm8741_modinit); | |||
551 | 617 | ||
552 | static void __exit wm8741_exit(void) | 618 | static void __exit wm8741_exit(void) |
553 | { | 619 | { |
620 | #if defined(CONFIG_SPI_MASTER) | ||
621 | spi_unregister_driver(&wm8741_spi_driver); | ||
622 | #endif | ||
554 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) | 623 | #if defined(CONFIG_I2C) || defined(CONFIG_I2C_MODULE) |
555 | i2c_del_driver(&wm8741_i2c_driver); | 624 | i2c_del_driver(&wm8741_i2c_driver); |
556 | #endif | 625 | #endif |
diff --git a/sound/soc/codecs/wm8750.c b/sound/soc/codecs/wm8750.c index d0003cc3bcd6..15f03721ec6f 100644 --- a/sound/soc/codecs/wm8750.c +++ b/sound/soc/codecs/wm8750.c | |||
@@ -21,6 +21,7 @@ | |||
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 <linux/of_device.h> | ||
24 | #include <sound/core.h> | 25 | #include <sound/core.h> |
25 | #include <sound/pcm.h> | 26 | #include <sound/pcm.h> |
26 | #include <sound/pcm_params.h> | 27 | #include <sound/pcm_params.h> |
@@ -751,6 +752,13 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8750 = { | |||
751 | .reg_cache_default = wm8750_reg, | 752 | .reg_cache_default = wm8750_reg, |
752 | }; | 753 | }; |
753 | 754 | ||
755 | static const struct of_device_id wm8750_of_match[] = { | ||
756 | { .compatible = "wlf,wm8750", }, | ||
757 | { .compatible = "wlf,wm8987", }, | ||
758 | { } | ||
759 | }; | ||
760 | MODULE_DEVICE_TABLE(of, wm8750_of_match); | ||
761 | |||
754 | #if defined(CONFIG_SPI_MASTER) | 762 | #if defined(CONFIG_SPI_MASTER) |
755 | static int __devinit wm8750_spi_probe(struct spi_device *spi) | 763 | static int __devinit wm8750_spi_probe(struct spi_device *spi) |
756 | { | 764 | { |
@@ -787,8 +795,9 @@ MODULE_DEVICE_TABLE(spi, wm8750_spi_ids); | |||
787 | 795 | ||
788 | static struct spi_driver wm8750_spi_driver = { | 796 | static struct spi_driver wm8750_spi_driver = { |
789 | .driver = { | 797 | .driver = { |
790 | .name = "wm8750-codec", | 798 | .name = "wm8750", |
791 | .owner = THIS_MODULE, | 799 | .owner = THIS_MODULE, |
800 | .of_match_table = wm8750_of_match, | ||
792 | }, | 801 | }, |
793 | .id_table = wm8750_spi_ids, | 802 | .id_table = wm8750_spi_ids, |
794 | .probe = wm8750_spi_probe, | 803 | .probe = wm8750_spi_probe, |
@@ -833,8 +842,9 @@ MODULE_DEVICE_TABLE(i2c, wm8750_i2c_id); | |||
833 | 842 | ||
834 | static struct i2c_driver wm8750_i2c_driver = { | 843 | static struct i2c_driver wm8750_i2c_driver = { |
835 | .driver = { | 844 | .driver = { |
836 | .name = "wm8750-codec", | 845 | .name = "wm8750", |
837 | .owner = THIS_MODULE, | 846 | .owner = THIS_MODULE, |
847 | .of_match_table = wm8750_of_match, | ||
838 | }, | 848 | }, |
839 | .probe = wm8750_i2c_probe, | 849 | .probe = wm8750_i2c_probe, |
840 | .remove = __devexit_p(wm8750_i2c_remove), | 850 | .remove = __devexit_p(wm8750_i2c_remove), |
diff --git a/sound/soc/codecs/wm8753.c b/sound/soc/codecs/wm8753.c index ffa2ffe5ec11..fe04a101d657 100644 --- a/sound/soc/codecs/wm8753.c +++ b/sound/soc/codecs/wm8753.c | |||
@@ -38,6 +38,7 @@ | |||
38 | #include <linux/delay.h> | 38 | #include <linux/delay.h> |
39 | #include <linux/pm.h> | 39 | #include <linux/pm.h> |
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/of_device.h> | ||
41 | #include <linux/platform_device.h> | 42 | #include <linux/platform_device.h> |
42 | #include <linux/spi/spi.h> | 43 | #include <linux/spi/spi.h> |
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
@@ -1490,6 +1491,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8753 = { | |||
1490 | .reg_cache_default = wm8753_reg, | 1491 | .reg_cache_default = wm8753_reg, |
1491 | }; | 1492 | }; |
1492 | 1493 | ||
1494 | static const struct of_device_id wm8753_of_match[] = { | ||
1495 | { .compatible = "wlf,wm8753", }, | ||
1496 | { } | ||
1497 | }; | ||
1498 | MODULE_DEVICE_TABLE(of, wm8753_of_match); | ||
1499 | |||
1493 | #if defined(CONFIG_SPI_MASTER) | 1500 | #if defined(CONFIG_SPI_MASTER) |
1494 | static int __devinit wm8753_spi_probe(struct spi_device *spi) | 1501 | static int __devinit wm8753_spi_probe(struct spi_device *spi) |
1495 | { | 1502 | { |
@@ -1519,8 +1526,9 @@ static int __devexit wm8753_spi_remove(struct spi_device *spi) | |||
1519 | 1526 | ||
1520 | static struct spi_driver wm8753_spi_driver = { | 1527 | static struct spi_driver wm8753_spi_driver = { |
1521 | .driver = { | 1528 | .driver = { |
1522 | .name = "wm8753-codec", | 1529 | .name = "wm8753", |
1523 | .owner = THIS_MODULE, | 1530 | .owner = THIS_MODULE, |
1531 | .of_match_table = wm8753_of_match, | ||
1524 | }, | 1532 | }, |
1525 | .probe = wm8753_spi_probe, | 1533 | .probe = wm8753_spi_probe, |
1526 | .remove = __devexit_p(wm8753_spi_remove), | 1534 | .remove = __devexit_p(wm8753_spi_remove), |
@@ -1563,8 +1571,9 @@ MODULE_DEVICE_TABLE(i2c, wm8753_i2c_id); | |||
1563 | 1571 | ||
1564 | static struct i2c_driver wm8753_i2c_driver = { | 1572 | static struct i2c_driver wm8753_i2c_driver = { |
1565 | .driver = { | 1573 | .driver = { |
1566 | .name = "wm8753-codec", | 1574 | .name = "wm8753", |
1567 | .owner = THIS_MODULE, | 1575 | .owner = THIS_MODULE, |
1576 | .of_match_table = wm8753_of_match, | ||
1568 | }, | 1577 | }, |
1569 | .probe = wm8753_i2c_probe, | 1578 | .probe = wm8753_i2c_probe, |
1570 | .remove = __devexit_p(wm8753_i2c_remove), | 1579 | .remove = __devexit_p(wm8753_i2c_remove), |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index 19b92baa9e8c..aa05e6507f84 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -14,6 +14,7 @@ | |||
14 | #include <linux/moduleparam.h> | 14 | #include <linux/moduleparam.h> |
15 | #include <linux/init.h> | 15 | #include <linux/init.h> |
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/of_device.h> | ||
17 | #include <linux/pm.h> | 18 | #include <linux/pm.h> |
18 | #include <linux/platform_device.h> | 19 | #include <linux/platform_device.h> |
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
@@ -684,6 +685,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8770 = { | |||
684 | .reg_cache_default = wm8770_reg_defs | 685 | .reg_cache_default = wm8770_reg_defs |
685 | }; | 686 | }; |
686 | 687 | ||
688 | static const struct of_device_id wm8770_of_match[] = { | ||
689 | { .compatible = "wlf,wm8770", }, | ||
690 | { } | ||
691 | }; | ||
692 | MODULE_DEVICE_TABLE(of, wm8770_of_match); | ||
693 | |||
687 | #if defined(CONFIG_SPI_MASTER) | 694 | #if defined(CONFIG_SPI_MASTER) |
688 | static int __devinit wm8770_spi_probe(struct spi_device *spi) | 695 | static int __devinit wm8770_spi_probe(struct spi_device *spi) |
689 | { | 696 | { |
@@ -715,6 +722,7 @@ static struct spi_driver wm8770_spi_driver = { | |||
715 | .driver = { | 722 | .driver = { |
716 | .name = "wm8770", | 723 | .name = "wm8770", |
717 | .owner = THIS_MODULE, | 724 | .owner = THIS_MODULE, |
725 | .of_match_table = wm8770_of_match, | ||
718 | }, | 726 | }, |
719 | .probe = wm8770_spi_probe, | 727 | .probe = wm8770_spi_probe, |
720 | .remove = __devexit_p(wm8770_spi_remove) | 728 | .remove = __devexit_p(wm8770_spi_remove) |
diff --git a/sound/soc/codecs/wm8776.c b/sound/soc/codecs/wm8776.c index 8e7953b1b790..00d8846fae8a 100644 --- a/sound/soc/codecs/wm8776.c +++ b/sound/soc/codecs/wm8776.c | |||
@@ -18,6 +18,7 @@ | |||
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/of_device.h> | ||
21 | #include <linux/platform_device.h> | 22 | #include <linux/platform_device.h> |
22 | #include <linux/spi/spi.h> | 23 | #include <linux/spi/spi.h> |
23 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
@@ -215,8 +216,6 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
215 | int ratio_shift, master; | 216 | int ratio_shift, master; |
216 | int i; | 217 | int i; |
217 | 218 | ||
218 | iface = 0; | ||
219 | |||
220 | switch (dai->driver->id) { | 219 | switch (dai->driver->id) { |
221 | case WM8776_DAI_DAC: | 220 | case WM8776_DAI_DAC: |
222 | iface_reg = WM8776_DACIFCTRL; | 221 | iface_reg = WM8776_DACIFCTRL; |
@@ -232,20 +231,23 @@ static int wm8776_hw_params(struct snd_pcm_substream *substream, | |||
232 | return -EINVAL; | 231 | return -EINVAL; |
233 | } | 232 | } |
234 | 233 | ||
235 | |||
236 | /* Set word length */ | 234 | /* Set word length */ |
237 | switch (params_format(params)) { | 235 | switch (snd_pcm_format_width(params_format(params))) { |
238 | case SNDRV_PCM_FORMAT_S16_LE: | 236 | case 16: |
237 | iface = 0; | ||
238 | case 20: | ||
239 | iface = 0x10; | ||
239 | break; | 240 | break; |
240 | case SNDRV_PCM_FORMAT_S20_3LE: | 241 | case 24: |
241 | iface |= 0x10; | 242 | iface = 0x20; |
242 | break; | 243 | break; |
243 | case SNDRV_PCM_FORMAT_S24_LE: | 244 | case 32: |
244 | iface |= 0x20; | 245 | iface = 0x30; |
245 | break; | ||
246 | case SNDRV_PCM_FORMAT_S32_LE: | ||
247 | iface |= 0x30; | ||
248 | break; | 246 | break; |
247 | default: | ||
248 | dev_err(codec->dev, "Unsupported sample size: %i\n", | ||
249 | snd_pcm_format_width(params_format(params))); | ||
250 | return -EINVAL; | ||
249 | } | 251 | } |
250 | 252 | ||
251 | /* Only need to set MCLK/LRCLK ratio if we're master */ | 253 | /* Only need to set MCLK/LRCLK ratio if we're master */ |
@@ -320,11 +322,6 @@ static int wm8776_set_bias_level(struct snd_soc_codec *codec, | |||
320 | return 0; | 322 | return 0; |
321 | } | 323 | } |
322 | 324 | ||
323 | #define WM8776_RATES (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 |\ | ||
324 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_88200 |\ | ||
325 | SNDRV_PCM_RATE_96000) | ||
326 | |||
327 | |||
328 | #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 325 | #define WM8776_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
329 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) | 326 | SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S32_LE) |
330 | 327 | ||
@@ -349,7 +346,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { | |||
349 | .stream_name = "Playback", | 346 | .stream_name = "Playback", |
350 | .channels_min = 2, | 347 | .channels_min = 2, |
351 | .channels_max = 2, | 348 | .channels_max = 2, |
352 | .rates = WM8776_RATES, | 349 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
350 | .rate_min = 32000, | ||
351 | .rate_max = 192000, | ||
353 | .formats = WM8776_FORMATS, | 352 | .formats = WM8776_FORMATS, |
354 | }, | 353 | }, |
355 | .ops = &wm8776_dac_ops, | 354 | .ops = &wm8776_dac_ops, |
@@ -361,7 +360,9 @@ static struct snd_soc_dai_driver wm8776_dai[] = { | |||
361 | .stream_name = "Capture", | 360 | .stream_name = "Capture", |
362 | .channels_min = 2, | 361 | .channels_min = 2, |
363 | .channels_max = 2, | 362 | .channels_max = 2, |
364 | .rates = WM8776_RATES, | 363 | .rates = SNDRV_PCM_RATE_CONTINUOUS, |
364 | .rate_min = 32000, | ||
365 | .rate_max = 96000, | ||
365 | .formats = WM8776_FORMATS, | 366 | .formats = WM8776_FORMATS, |
366 | }, | 367 | }, |
367 | .ops = &wm8776_adc_ops, | 368 | .ops = &wm8776_adc_ops, |
@@ -452,6 +453,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8776 = { | |||
452 | .reg_cache_default = wm8776_reg, | 453 | .reg_cache_default = wm8776_reg, |
453 | }; | 454 | }; |
454 | 455 | ||
456 | static const struct of_device_id wm8776_of_match[] = { | ||
457 | { .compatible = "wlf,wm8776", }, | ||
458 | { } | ||
459 | }; | ||
460 | MODULE_DEVICE_TABLE(of, wm8776_of_match); | ||
461 | |||
455 | #if defined(CONFIG_SPI_MASTER) | 462 | #if defined(CONFIG_SPI_MASTER) |
456 | static int __devinit wm8776_spi_probe(struct spi_device *spi) | 463 | static int __devinit wm8776_spi_probe(struct spi_device *spi) |
457 | { | 464 | { |
@@ -481,8 +488,9 @@ static int __devexit wm8776_spi_remove(struct spi_device *spi) | |||
481 | 488 | ||
482 | static struct spi_driver wm8776_spi_driver = { | 489 | static struct spi_driver wm8776_spi_driver = { |
483 | .driver = { | 490 | .driver = { |
484 | .name = "wm8776-codec", | 491 | .name = "wm8776", |
485 | .owner = THIS_MODULE, | 492 | .owner = THIS_MODULE, |
493 | .of_match_table = wm8776_of_match, | ||
486 | }, | 494 | }, |
487 | .probe = wm8776_spi_probe, | 495 | .probe = wm8776_spi_probe, |
488 | .remove = __devexit_p(wm8776_spi_remove), | 496 | .remove = __devexit_p(wm8776_spi_remove), |
@@ -525,8 +533,9 @@ MODULE_DEVICE_TABLE(i2c, wm8776_i2c_id); | |||
525 | 533 | ||
526 | static struct i2c_driver wm8776_i2c_driver = { | 534 | static struct i2c_driver wm8776_i2c_driver = { |
527 | .driver = { | 535 | .driver = { |
528 | .name = "wm8776-codec", | 536 | .name = "wm8776", |
529 | .owner = THIS_MODULE, | 537 | .owner = THIS_MODULE, |
538 | .of_match_table = wm8776_of_match, | ||
530 | }, | 539 | }, |
531 | .probe = wm8776_i2c_probe, | 540 | .probe = wm8776_i2c_probe, |
532 | .remove = __devexit_p(wm8776_i2c_remove), | 541 | .remove = __devexit_p(wm8776_i2c_remove), |
diff --git a/sound/soc/codecs/wm8804.c b/sound/soc/codecs/wm8804.c index 9a5e67c5a6bd..9ee072b85975 100644 --- a/sound/soc/codecs/wm8804.c +++ b/sound/soc/codecs/wm8804.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/pm.h> | 17 | #include <linux/pm.h> |
18 | #include <linux/i2c.h> | 18 | #include <linux/i2c.h> |
19 | #include <linux/of_device.h> | ||
19 | #include <linux/spi/spi.h> | 20 | #include <linux/spi/spi.h> |
20 | #include <linux/regulator/consumer.h> | 21 | #include <linux/regulator/consumer.h> |
21 | #include <linux/slab.h> | 22 | #include <linux/slab.h> |
@@ -717,6 +718,12 @@ static struct snd_soc_codec_driver soc_codec_dev_wm8804 = { | |||
717 | .volatile_register = wm8804_volatile | 718 | .volatile_register = wm8804_volatile |
718 | }; | 719 | }; |
719 | 720 | ||
721 | static const struct of_device_id wm8804_of_match[] = { | ||
722 | { .compatible = "wlf,wm8804", }, | ||
723 | { } | ||
724 | }; | ||
725 | MODULE_DEVICE_TABLE(of, wm8804_of_match); | ||
726 | |||
720 | #if defined(CONFIG_SPI_MASTER) | 727 | #if defined(CONFIG_SPI_MASTER) |
721 | static int __devinit wm8804_spi_probe(struct spi_device *spi) | 728 | static int __devinit wm8804_spi_probe(struct spi_device *spi) |
722 | { | 729 | { |
@@ -748,6 +755,7 @@ static struct spi_driver wm8804_spi_driver = { | |||
748 | .driver = { | 755 | .driver = { |
749 | .name = "wm8804", | 756 | .name = "wm8804", |
750 | .owner = THIS_MODULE, | 757 | .owner = THIS_MODULE, |
758 | .of_match_table = wm8804_of_match, | ||
751 | }, | 759 | }, |
752 | .probe = wm8804_spi_probe, | 760 | .probe = wm8804_spi_probe, |
753 | .remove = __devexit_p(wm8804_spi_remove) | 761 | .remove = __devexit_p(wm8804_spi_remove) |
@@ -792,6 +800,7 @@ static struct i2c_driver wm8804_i2c_driver = { | |||
792 | .driver = { | 800 | .driver = { |
793 | .name = "wm8804", | 801 | .name = "wm8804", |
794 | .owner = THIS_MODULE, | 802 | .owner = THIS_MODULE, |
803 | .of_match_table = wm8804_of_match, | ||
795 | }, | 804 | }, |
796 | .probe = wm8804_i2c_probe, | 805 | .probe = wm8804_i2c_probe, |
797 | .remove = __devexit_p(wm8804_i2c_remove), | 806 | .remove = __devexit_p(wm8804_i2c_remove), |
diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index 1725550c293e..3676b38838d8 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c | |||
@@ -63,6 +63,8 @@ struct wm8962_priv { | |||
63 | int fll_fref; | 63 | int fll_fref; |
64 | int fll_fout; | 64 | int fll_fout; |
65 | 65 | ||
66 | u16 dsp2_ena; | ||
67 | |||
66 | struct delayed_work mic_work; | 68 | struct delayed_work mic_work; |
67 | struct snd_soc_jack *jack; | 69 | struct snd_soc_jack *jack; |
68 | 70 | ||
@@ -837,7 +839,7 @@ static const struct wm8962_reg_access { | |||
837 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ | 839 | [40] = { 0x00FF, 0x01FF, 0x0000 }, /* R40 - SPKOUTL volume */ |
838 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ | 840 | [41] = { 0x00FF, 0x01FF, 0x0000 }, /* R41 - SPKOUTR volume */ |
839 | 841 | ||
840 | [47] = { 0x000F, 0x0000, 0x0000 }, /* R47 - Thermal Shutdown Status */ | 842 | [47] = { 0x000F, 0x0000, 0xFFFF }, /* R47 - Thermal Shutdown Status */ |
841 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ | 843 | [48] = { 0x7EC7, 0x7E07, 0xFFFF }, /* R48 - Additional Control (4) */ |
842 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ | 844 | [49] = { 0x00D3, 0x00D7, 0xFFFF }, /* R49 - Class D Control 1 */ |
843 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ | 845 | [51] = { 0x0047, 0x0047, 0x0000 }, /* R51 - Class D Control 2 */ |
@@ -965,7 +967,7 @@ static const struct wm8962_reg_access { | |||
965 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ | 967 | [584] = { 0x002D, 0x002D, 0x0000 }, /* R584 - IRQ Debounce */ |
966 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ | 968 | [586] = { 0xC000, 0xC000, 0x0000 }, /* R586 - MICINT Source Pol */ |
967 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ | 969 | [768] = { 0x0001, 0x0001, 0x0000 }, /* R768 - DSP2 Power Management */ |
968 | [1037] = { 0x0000, 0x003F, 0x0000 }, /* R1037 - DSP2_ExecControl */ | 970 | [1037] = { 0x0000, 0x003F, 0xFFFF }, /* R1037 - DSP2_ExecControl */ |
969 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ | 971 | [4096] = { 0x3FFF, 0x3FFF, 0x0000 }, /* R4096 - Write Sequencer 0 */ |
970 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ | 972 | [4097] = { 0x00FF, 0x00FF, 0x0000 }, /* R4097 - Write Sequencer 1 */ |
971 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ | 973 | [4098] = { 0x070F, 0x070F, 0x0000 }, /* R4098 - Write Sequencer 2 */ |
@@ -1986,6 +1988,122 @@ static const unsigned int classd_tlv[] = { | |||
1986 | }; | 1988 | }; |
1987 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 1989 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
1988 | 1990 | ||
1991 | static int wm8962_dsp2_write_config(struct snd_soc_codec *codec) | ||
1992 | { | ||
1993 | return 0; | ||
1994 | } | ||
1995 | |||
1996 | static int wm8962_dsp2_set_enable(struct snd_soc_codec *codec, u16 val) | ||
1997 | { | ||
1998 | u16 adcl = snd_soc_read(codec, WM8962_LEFT_ADC_VOLUME); | ||
1999 | u16 adcr = snd_soc_read(codec, WM8962_RIGHT_ADC_VOLUME); | ||
2000 | u16 dac = snd_soc_read(codec, WM8962_ADC_DAC_CONTROL_1); | ||
2001 | |||
2002 | /* Mute the ADCs and DACs */ | ||
2003 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, 0); | ||
2004 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, WM8962_ADC_VU); | ||
2005 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2006 | WM8962_DAC_MUTE, WM8962_DAC_MUTE); | ||
2007 | |||
2008 | snd_soc_write(codec, WM8962_SOUNDSTAGE_ENABLES_0, val); | ||
2009 | |||
2010 | /* Restore the ADCs and DACs */ | ||
2011 | snd_soc_write(codec, WM8962_LEFT_ADC_VOLUME, adcl); | ||
2012 | snd_soc_write(codec, WM8962_RIGHT_ADC_VOLUME, adcr); | ||
2013 | snd_soc_update_bits(codec, WM8962_ADC_DAC_CONTROL_1, | ||
2014 | WM8962_DAC_MUTE, dac); | ||
2015 | |||
2016 | return 0; | ||
2017 | } | ||
2018 | |||
2019 | static int wm8962_dsp2_start(struct snd_soc_codec *codec) | ||
2020 | { | ||
2021 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2022 | |||
2023 | wm8962_dsp2_write_config(codec); | ||
2024 | |||
2025 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_RUNR); | ||
2026 | |||
2027 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2028 | |||
2029 | return 0; | ||
2030 | } | ||
2031 | |||
2032 | static int wm8962_dsp2_stop(struct snd_soc_codec *codec) | ||
2033 | { | ||
2034 | wm8962_dsp2_set_enable(codec, 0); | ||
2035 | |||
2036 | snd_soc_write(codec, WM8962_DSP2_EXECCONTROL, WM8962_DSP2_STOP); | ||
2037 | |||
2038 | return 0; | ||
2039 | } | ||
2040 | |||
2041 | #define WM8962_DSP2_ENABLE(xname, xshift) \ | ||
2042 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
2043 | .info = wm8962_dsp2_ena_info, \ | ||
2044 | .get = wm8962_dsp2_ena_get, .put = wm8962_dsp2_ena_put, \ | ||
2045 | .private_value = xshift } | ||
2046 | |||
2047 | static int wm8962_dsp2_ena_info(struct snd_kcontrol *kcontrol, | ||
2048 | struct snd_ctl_elem_info *uinfo) | ||
2049 | { | ||
2050 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; | ||
2051 | |||
2052 | uinfo->count = 1; | ||
2053 | uinfo->value.integer.min = 0; | ||
2054 | uinfo->value.integer.max = 1; | ||
2055 | |||
2056 | return 0; | ||
2057 | } | ||
2058 | |||
2059 | static int wm8962_dsp2_ena_get(struct snd_kcontrol *kcontrol, | ||
2060 | struct snd_ctl_elem_value *ucontrol) | ||
2061 | { | ||
2062 | int shift = kcontrol->private_value; | ||
2063 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2064 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2065 | |||
2066 | ucontrol->value.integer.value[0] = !!(wm8962->dsp2_ena & 1 << shift); | ||
2067 | |||
2068 | return 0; | ||
2069 | } | ||
2070 | |||
2071 | static int wm8962_dsp2_ena_put(struct snd_kcontrol *kcontrol, | ||
2072 | struct snd_ctl_elem_value *ucontrol) | ||
2073 | { | ||
2074 | int shift = kcontrol->private_value; | ||
2075 | struct snd_soc_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2076 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2077 | int old = wm8962->dsp2_ena; | ||
2078 | int ret = 0; | ||
2079 | int dsp2_running = snd_soc_read(codec, WM8962_DSP2_POWER_MANAGEMENT) & | ||
2080 | WM8962_DSP2_ENA; | ||
2081 | |||
2082 | mutex_lock(&codec->mutex); | ||
2083 | |||
2084 | if (ucontrol->value.integer.value[0]) | ||
2085 | wm8962->dsp2_ena |= 1 << shift; | ||
2086 | else | ||
2087 | wm8962->dsp2_ena &= ~(1 << shift); | ||
2088 | |||
2089 | if (wm8962->dsp2_ena == old) | ||
2090 | goto out; | ||
2091 | |||
2092 | ret = 1; | ||
2093 | |||
2094 | if (dsp2_running) { | ||
2095 | if (wm8962->dsp2_ena) | ||
2096 | wm8962_dsp2_set_enable(codec, wm8962->dsp2_ena); | ||
2097 | else | ||
2098 | wm8962_dsp2_stop(codec); | ||
2099 | } | ||
2100 | |||
2101 | out: | ||
2102 | mutex_unlock(&codec->mutex); | ||
2103 | |||
2104 | return ret; | ||
2105 | } | ||
2106 | |||
1989 | /* The VU bits for the headphones are in a different register to the mute | 2107 | /* The VU bits for the headphones are in a different register to the mute |
1990 | * bits and only take effect on the PGA if it is actually powered. | 2108 | * bits and only take effect on the PGA if it is actually powered. |
1991 | */ | 2109 | */ |
@@ -2049,6 +2167,14 @@ static const char *cap_hpf_mode_text[] = { | |||
2049 | static const struct soc_enum cap_hpf_mode = | 2167 | static const struct soc_enum cap_hpf_mode = |
2050 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); | 2168 | SOC_ENUM_SINGLE(WM8962_ADC_DAC_CONTROL_2, 10, 2, cap_hpf_mode_text); |
2051 | 2169 | ||
2170 | |||
2171 | static const char *cap_lhpf_mode_text[] = { | ||
2172 | "LPF", "HPF" | ||
2173 | }; | ||
2174 | |||
2175 | static const struct soc_enum cap_lhpf_mode = | ||
2176 | SOC_ENUM_SINGLE(WM8962_LHPF1, 1, 2, cap_lhpf_mode_text); | ||
2177 | |||
2052 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { | 2178 | static const struct snd_kcontrol_new wm8962_snd_controls[] = { |
2053 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), | 2179 | SOC_DOUBLE("Input Mixer Switch", WM8962_INPUT_MIXER_CONTROL_1, 3, 2, 1, 1), |
2054 | 2180 | ||
@@ -2077,6 +2203,8 @@ SOC_DOUBLE_R("Capture ZC Switch", WM8962_LEFT_INPUT_VOLUME, | |||
2077 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), | 2203 | SOC_SINGLE("Capture HPF Switch", WM8962_ADC_DAC_CONTROL_1, 0, 1, 1), |
2078 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), | 2204 | SOC_ENUM("Capture HPF Mode", cap_hpf_mode), |
2079 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), | 2205 | SOC_SINGLE("Capture HPF Cutoff", WM8962_ADC_DAC_CONTROL_2, 7, 7, 0), |
2206 | SOC_SINGLE("Capture LHPF Switch", WM8962_LHPF1, 0, 1, 0), | ||
2207 | SOC_ENUM("Capture LHPF Mode", cap_lhpf_mode), | ||
2080 | 2208 | ||
2081 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, | 2209 | SOC_DOUBLE_R_TLV("Sidetone Volume", WM8962_DAC_DSP_MIXING_1, |
2082 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), | 2210 | WM8962_DAC_DSP_MIXING_2, 4, 12, 0, st_tlv), |
@@ -2134,6 +2262,11 @@ SOC_DOUBLE_R_TLV("EQ4 Volume", WM8962_EQ3, WM8962_EQ23, | |||
2134 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), | 2262 | WM8962_EQL_B4_GAIN_SHIFT, 31, 0, eq_tlv), |
2135 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, | 2263 | SOC_DOUBLE_R_TLV("EQ5 Volume", WM8962_EQ3, WM8962_EQ23, |
2136 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), | 2264 | WM8962_EQL_B5_GAIN_SHIFT, 31, 0, eq_tlv), |
2265 | |||
2266 | WM8962_DSP2_ENABLE("VSS Switch", WM8962_VSS_ENA_SHIFT), | ||
2267 | WM8962_DSP2_ENABLE("HPF1 Switch", WM8962_HPF1_ENA_SHIFT), | ||
2268 | WM8962_DSP2_ENABLE("HPF2 Switch", WM8962_HPF2_ENA_SHIFT), | ||
2269 | WM8962_DSP2_ENABLE("HD Bass Switch", WM8962_HDBASS_ENA_SHIFT), | ||
2137 | }; | 2270 | }; |
2138 | 2271 | ||
2139 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { | 2272 | static const struct snd_kcontrol_new wm8962_spk_mono_controls[] = { |
@@ -2395,6 +2528,31 @@ static int out_pga_event(struct snd_soc_dapm_widget *w, | |||
2395 | } | 2528 | } |
2396 | } | 2529 | } |
2397 | 2530 | ||
2531 | static int dsp2_event(struct snd_soc_dapm_widget *w, | ||
2532 | struct snd_kcontrol *kcontrol, int event) | ||
2533 | { | ||
2534 | struct snd_soc_codec *codec = w->codec; | ||
2535 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | ||
2536 | |||
2537 | switch (event) { | ||
2538 | case SND_SOC_DAPM_POST_PMU: | ||
2539 | if (wm8962->dsp2_ena) | ||
2540 | wm8962_dsp2_start(codec); | ||
2541 | break; | ||
2542 | |||
2543 | case SND_SOC_DAPM_PRE_PMD: | ||
2544 | if (wm8962->dsp2_ena) | ||
2545 | wm8962_dsp2_stop(codec); | ||
2546 | break; | ||
2547 | |||
2548 | default: | ||
2549 | BUG(); | ||
2550 | return -EINVAL; | ||
2551 | } | ||
2552 | |||
2553 | return 0; | ||
2554 | } | ||
2555 | |||
2398 | static const char *st_text[] = { "None", "Right", "Left" }; | 2556 | static const char *st_text[] = { "None", "Right", "Left" }; |
2399 | 2557 | ||
2400 | static const struct soc_enum str_enum = | 2558 | static const struct soc_enum str_enum = |
@@ -2517,6 +2675,9 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", WM8962_CLOCKING2, 5, 0, sysclk_event, | |||
2517 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, | 2675 | SND_SOC_DAPM_SUPPLY("Charge Pump", WM8962_CHARGE_PUMP_1, 0, 0, cp_event, |
2518 | SND_SOC_DAPM_POST_PMU), | 2676 | SND_SOC_DAPM_POST_PMU), |
2519 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), | 2677 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8962_ADDITIONAL_CONTROL_1, 0, 0, NULL, 0), |
2678 | SND_SOC_DAPM_SUPPLY_S("DSP2", 1, WM8962_DSP2_POWER_MANAGEMENT, | ||
2679 | WM8962_DSP2_ENA_SHIFT, 0, dsp2_event, | ||
2680 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | ||
2520 | 2681 | ||
2521 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, | 2682 | SND_SOC_DAPM_MIXER("INPGAL", WM8962_LEFT_INPUT_PGA_CONTROL, 4, 0, |
2522 | inpgal, ARRAY_SIZE(inpgal)), | 2683 | inpgal, ARRAY_SIZE(inpgal)), |
@@ -2612,11 +2773,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2612 | { "ADCL", NULL, "TOCLK" }, | 2773 | { "ADCL", NULL, "TOCLK" }, |
2613 | { "ADCL", NULL, "MIXINL" }, | 2774 | { "ADCL", NULL, "MIXINL" }, |
2614 | { "ADCL", NULL, "DMIC" }, | 2775 | { "ADCL", NULL, "DMIC" }, |
2776 | { "ADCL", NULL, "DSP2" }, | ||
2615 | 2777 | ||
2616 | { "ADCR", NULL, "SYSCLK" }, | 2778 | { "ADCR", NULL, "SYSCLK" }, |
2617 | { "ADCR", NULL, "TOCLK" }, | 2779 | { "ADCR", NULL, "TOCLK" }, |
2618 | { "ADCR", NULL, "MIXINR" }, | 2780 | { "ADCR", NULL, "MIXINR" }, |
2619 | { "ADCR", NULL, "DMIC" }, | 2781 | { "ADCR", NULL, "DMIC" }, |
2782 | { "ADCR", NULL, "DSP2" }, | ||
2620 | 2783 | ||
2621 | { "STL", "Left", "ADCL" }, | 2784 | { "STL", "Left", "ADCL" }, |
2622 | { "STL", "Right", "ADCR" }, | 2785 | { "STL", "Right", "ADCR" }, |
@@ -2628,11 +2791,13 @@ static const struct snd_soc_dapm_route wm8962_intercon[] = { | |||
2628 | { "DACL", NULL, "TOCLK" }, | 2791 | { "DACL", NULL, "TOCLK" }, |
2629 | { "DACL", NULL, "Beep" }, | 2792 | { "DACL", NULL, "Beep" }, |
2630 | { "DACL", NULL, "STL" }, | 2793 | { "DACL", NULL, "STL" }, |
2794 | { "DACL", NULL, "DSP2" }, | ||
2631 | 2795 | ||
2632 | { "DACR", NULL, "SYSCLK" }, | 2796 | { "DACR", NULL, "SYSCLK" }, |
2633 | { "DACR", NULL, "TOCLK" }, | 2797 | { "DACR", NULL, "TOCLK" }, |
2634 | { "DACR", NULL, "Beep" }, | 2798 | { "DACR", NULL, "Beep" }, |
2635 | { "DACR", NULL, "STR" }, | 2799 | { "DACR", NULL, "STR" }, |
2800 | { "DACR", NULL, "DSP2" }, | ||
2636 | 2801 | ||
2637 | { "HPMIXL", "IN4L Switch", "IN4L" }, | 2802 | { "HPMIXL", "IN4L Switch", "IN4L" }, |
2638 | { "HPMIXL", "IN4R Switch", "IN4R" }, | 2803 | { "HPMIXL", "IN4R Switch", "IN4R" }, |
@@ -3403,12 +3568,16 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3403 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); | 3568 | struct wm8962_priv *wm8962 = snd_soc_codec_get_drvdata(codec); |
3404 | int mask; | 3569 | int mask; |
3405 | int active; | 3570 | int active; |
3571 | int reg; | ||
3406 | 3572 | ||
3407 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); | 3573 | mask = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2_MASK); |
3408 | 3574 | ||
3409 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); | 3575 | active = snd_soc_read(codec, WM8962_INTERRUPT_STATUS_2); |
3410 | active &= ~mask; | 3576 | active &= ~mask; |
3411 | 3577 | ||
3578 | if (!active) | ||
3579 | return IRQ_NONE; | ||
3580 | |||
3412 | /* Acknowledge the interrupts */ | 3581 | /* Acknowledge the interrupts */ |
3413 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); | 3582 | snd_soc_write(codec, WM8962_INTERRUPT_STATUS_2, active); |
3414 | 3583 | ||
@@ -3420,9 +3589,21 @@ static irqreturn_t wm8962_irq(int irq, void *data) | |||
3420 | if (active & WM8962_FIFOS_ERR_EINT) | 3589 | if (active & WM8962_FIFOS_ERR_EINT) |
3421 | dev_err(codec->dev, "FIFO error\n"); | 3590 | dev_err(codec->dev, "FIFO error\n"); |
3422 | 3591 | ||
3423 | if (active & WM8962_TEMP_SHUT_EINT) | 3592 | if (active & WM8962_TEMP_SHUT_EINT) { |
3424 | dev_crit(codec->dev, "Thermal shutdown\n"); | 3593 | dev_crit(codec->dev, "Thermal shutdown\n"); |
3425 | 3594 | ||
3595 | reg = snd_soc_read(codec, WM8962_THERMAL_SHUTDOWN_STATUS); | ||
3596 | |||
3597 | if (reg & WM8962_TEMP_ERR_HP) | ||
3598 | dev_crit(codec->dev, "Headphone thermal error\n"); | ||
3599 | if (reg & WM8962_TEMP_WARN_HP) | ||
3600 | dev_crit(codec->dev, "Headphone thermal warning\n"); | ||
3601 | if (reg & WM8962_TEMP_ERR_SPK) | ||
3602 | dev_crit(codec->dev, "Speaker thermal error\n"); | ||
3603 | if (reg & WM8962_TEMP_WARN_SPK) | ||
3604 | dev_crit(codec->dev, "Speaker thermal warning\n"); | ||
3605 | } | ||
3606 | |||
3426 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { | 3607 | if (active & (WM8962_MICSCD_EINT | WM8962_MICD_EINT)) { |
3427 | dev_dbg(codec->dev, "Microphone event detected\n"); | 3608 | dev_dbg(codec->dev, "Microphone event detected\n"); |
3428 | 3609 | ||
@@ -3479,31 +3660,6 @@ int wm8962_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack) | |||
3479 | } | 3660 | } |
3480 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); | 3661 | EXPORT_SYMBOL_GPL(wm8962_mic_detect); |
3481 | 3662 | ||
3482 | #ifdef CONFIG_PM | ||
3483 | static int wm8962_resume(struct snd_soc_codec *codec) | ||
3484 | { | ||
3485 | u16 *reg_cache = codec->reg_cache; | ||
3486 | int i; | ||
3487 | |||
3488 | /* Restore the registers */ | ||
3489 | for (i = 1; i < codec->driver->reg_cache_size; i++) { | ||
3490 | switch (i) { | ||
3491 | case WM8962_SOFTWARE_RESET: | ||
3492 | continue; | ||
3493 | default: | ||
3494 | break; | ||
3495 | } | ||
3496 | |||
3497 | if (reg_cache[i] != wm8962_reg[i]) | ||
3498 | snd_soc_write(codec, i, reg_cache[i]); | ||
3499 | } | ||
3500 | |||
3501 | return 0; | ||
3502 | } | ||
3503 | #else | ||
3504 | #define wm8962_resume NULL | ||
3505 | #endif | ||
3506 | |||
3507 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) | 3663 | #if defined(CONFIG_INPUT) || defined(CONFIG_INPUT_MODULE) |
3508 | static int beep_rates[] = { | 3664 | static int beep_rates[] = { |
3509 | 500, 1000, 2000, 4000, | 3665 | 500, 1000, 2000, 4000, |
@@ -4015,7 +4171,6 @@ static int wm8962_remove(struct snd_soc_codec *codec) | |||
4015 | static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { | 4171 | static struct snd_soc_codec_driver soc_codec_dev_wm8962 = { |
4016 | .probe = wm8962_probe, | 4172 | .probe = wm8962_probe, |
4017 | .remove = wm8962_remove, | 4173 | .remove = wm8962_remove, |
4018 | .resume = wm8962_resume, | ||
4019 | .set_bias_level = wm8962_set_bias_level, | 4174 | .set_bias_level = wm8962_set_bias_level, |
4020 | .reg_cache_size = WM8962_MAX_REGISTER + 1, | 4175 | .reg_cache_size = WM8962_MAX_REGISTER + 1, |
4021 | .reg_word_size = sizeof(u16), | 4176 | .reg_word_size = sizeof(u16), |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 6e85b8869af7..eec8e1435116 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -847,6 +847,7 @@ SND_SOC_DAPM_SUPPLY("CLK_SYS", WM8993_BUS_CONTROL_1, 1, 0, clk_sys_event, | |||
847 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 847 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
848 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), | 848 | SND_SOC_DAPM_SUPPLY("TOCLK", WM8993_CLOCKING_1, 14, 0, NULL, 0), |
849 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), | 849 | SND_SOC_DAPM_SUPPLY("CLK_DSP", WM8993_CLOCKING_3, 0, 0, NULL, 0), |
850 | SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
850 | 851 | ||
851 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), | 852 | SND_SOC_DAPM_ADC("ADCL", NULL, WM8993_POWER_MANAGEMENT_2, 1, 0), |
852 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), | 853 | SND_SOC_DAPM_ADC("ADCR", NULL, WM8993_POWER_MANAGEMENT_2, 0, 0), |
@@ -880,6 +881,9 @@ SND_SOC_DAPM_PGA("Direct Voice", SND_SOC_NOPM, 0, 0, NULL, 0), | |||
880 | }; | 881 | }; |
881 | 882 | ||
882 | static const struct snd_soc_dapm_route routes[] = { | 883 | static const struct snd_soc_dapm_route routes[] = { |
884 | { "MICBIAS1", NULL, "VMID" }, | ||
885 | { "MICBIAS2", NULL, "VMID" }, | ||
886 | |||
883 | { "ADCL", NULL, "CLK_SYS" }, | 887 | { "ADCL", NULL, "CLK_SYS" }, |
884 | { "ADCL", NULL, "CLK_DSP" }, | 888 | { "ADCL", NULL, "CLK_DSP" }, |
885 | { "ADCR", NULL, "CLK_SYS" }, | 889 | { "ADCR", NULL, "CLK_SYS" }, |
@@ -1433,7 +1437,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1433 | int ret, i, val; | 1437 | int ret, i, val; |
1434 | 1438 | ||
1435 | wm8993->hubs_data.hp_startup_mode = 1; | 1439 | wm8993->hubs_data.hp_startup_mode = 1; |
1436 | wm8993->hubs_data.dcs_codes = -2; | 1440 | wm8993->hubs_data.dcs_codes_l = -2; |
1441 | wm8993->hubs_data.dcs_codes_r = -2; | ||
1437 | wm8993->hubs_data.series_startup = 1; | 1442 | wm8993->hubs_data.series_startup = 1; |
1438 | 1443 | ||
1439 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); | 1444 | ret = snd_soc_codec_set_cache_io(codec, 8, 16, SND_SOC_I2C); |
diff --git a/sound/soc/codecs/wm8994-tables.c b/sound/soc/codecs/wm8994-tables.c index a87adbd05ee1..df5a8b9a250f 100644 --- a/sound/soc/codecs/wm8994-tables.c +++ b/sound/soc/codecs/wm8994-tables.c | |||
@@ -1073,8 +1073,8 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
1073 | { 0x0000, 0x0000 }, /* R1069 */ | 1073 | { 0x0000, 0x0000 }, /* R1069 */ |
1074 | { 0x0000, 0x0000 }, /* R1070 */ | 1074 | { 0x0000, 0x0000 }, /* R1070 */ |
1075 | { 0x0000, 0x0000 }, /* R1071 */ | 1075 | { 0x0000, 0x0000 }, /* R1071 */ |
1076 | { 0x0000, 0x0000 }, /* R1072 */ | 1076 | { 0x006F, 0x006F }, /* R1072 - AIF1 DAC1 Noise Gate */ |
1077 | { 0x0000, 0x0000 }, /* R1073 */ | 1077 | { 0x006F, 0x006F }, /* R1073 - AIF1 DAC2 Noise Gate */ |
1078 | { 0x0000, 0x0000 }, /* R1074 */ | 1078 | { 0x0000, 0x0000 }, /* R1074 */ |
1079 | { 0x0000, 0x0000 }, /* R1075 */ | 1079 | { 0x0000, 0x0000 }, /* R1075 */ |
1080 | { 0x0000, 0x0000 }, /* R1076 */ | 1080 | { 0x0000, 0x0000 }, /* R1076 */ |
@@ -1329,7 +1329,7 @@ const struct wm8994_access_mask wm8994_access_masks[WM8994_CACHE_SIZE] = { | |||
1329 | { 0x0000, 0x0000 }, /* R1325 */ | 1329 | { 0x0000, 0x0000 }, /* R1325 */ |
1330 | { 0x0000, 0x0000 }, /* R1326 */ | 1330 | { 0x0000, 0x0000 }, /* R1326 */ |
1331 | { 0x0000, 0x0000 }, /* R1327 */ | 1331 | { 0x0000, 0x0000 }, /* R1327 */ |
1332 | { 0x0000, 0x0000 }, /* R1328 */ | 1332 | { 0x006F, 0x006F }, /* R1328 - AIF2 DAC Noise Gate */ |
1333 | { 0x0000, 0x0000 }, /* R1329 */ | 1333 | { 0x0000, 0x0000 }, /* R1329 */ |
1334 | { 0x0000, 0x0000 }, /* R1330 */ | 1334 | { 0x0000, 0x0000 }, /* R1330 */ |
1335 | { 0x0000, 0x0000 }, /* R1331 */ | 1335 | { 0x0000, 0x0000 }, /* R1331 */ |
@@ -1635,8 +1635,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
1635 | 0x0000, /* R58 - MICBIAS */ | 1635 | 0x0000, /* R58 - MICBIAS */ |
1636 | 0x000D, /* R59 - LDO 1 */ | 1636 | 0x000D, /* R59 - LDO 1 */ |
1637 | 0x0003, /* R60 - LDO 2 */ | 1637 | 0x0003, /* R60 - LDO 2 */ |
1638 | 0x0000, /* R61 */ | 1638 | 0x0039, /* R61 - MICBIAS1 */ |
1639 | 0x0000, /* R62 */ | 1639 | 0x0039, /* R62 - MICBIAS2 */ |
1640 | 0x0000, /* R63 */ | 1640 | 0x0000, /* R63 */ |
1641 | 0x0000, /* R64 */ | 1641 | 0x0000, /* R64 */ |
1642 | 0x0000, /* R65 */ | 1642 | 0x0000, /* R65 */ |
@@ -2646,8 +2646,8 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
2646 | 0x0000, /* R1069 */ | 2646 | 0x0000, /* R1069 */ |
2647 | 0x0000, /* R1070 */ | 2647 | 0x0000, /* R1070 */ |
2648 | 0x0000, /* R1071 */ | 2648 | 0x0000, /* R1071 */ |
2649 | 0x0000, /* R1072 */ | 2649 | 0x0068, /* R1072 - AIF1 DAC1 Noise Gate */ |
2650 | 0x0000, /* R1073 */ | 2650 | 0x0068, /* R1073 - AIF1 DAC2 Noise Gate */ |
2651 | 0x0000, /* R1074 */ | 2651 | 0x0000, /* R1074 */ |
2652 | 0x0000, /* R1075 */ | 2652 | 0x0000, /* R1075 */ |
2653 | 0x0000, /* R1076 */ | 2653 | 0x0000, /* R1076 */ |
@@ -2902,7 +2902,7 @@ const u16 wm8994_reg_defaults[WM8994_CACHE_SIZE] = { | |||
2902 | 0x0000, /* R1325 */ | 2902 | 0x0000, /* R1325 */ |
2903 | 0x0000, /* R1326 */ | 2903 | 0x0000, /* R1326 */ |
2904 | 0x0000, /* R1327 */ | 2904 | 0x0000, /* R1327 */ |
2905 | 0x0000, /* R1328 */ | 2905 | 0x0068, /* R1328 - AIF2 DAC Noise Gate */ |
2906 | 0x0000, /* R1329 */ | 2906 | 0x0000, /* R1329 */ |
2907 | 0x0000, /* R1330 */ | 2907 | 0x0000, /* R1330 */ |
2908 | 0x0000, /* R1331 */ | 2908 | 0x0000, /* R1331 */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index b393f9fac97a..e5372675123d 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -107,6 +107,7 @@ static int wm8994_volatile(struct snd_soc_codec *codec, unsigned int reg) | |||
107 | case WM8994_LDO_2: | 107 | case WM8994_LDO_2: |
108 | case WM8958_DSP2_EXECCONTROL: | 108 | case WM8958_DSP2_EXECCONTROL: |
109 | case WM8958_MIC_DETECT_3: | 109 | case WM8958_MIC_DETECT_3: |
110 | case WM8994_DC_SERVO_4E: | ||
110 | return 1; | 111 | return 1; |
111 | default: | 112 | default: |
112 | return 0; | 113 | return 0; |
@@ -281,6 +282,7 @@ static const DECLARE_TLV_DB_SCALE(digital_tlv, -7200, 75, 1); | |||
281 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); | 282 | static const DECLARE_TLV_DB_SCALE(st_tlv, -3600, 300, 0); |
282 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); | 283 | static const DECLARE_TLV_DB_SCALE(wm8994_3d_tlv, -1600, 183, 0); |
283 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 284 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
285 | static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | ||
284 | 286 | ||
285 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | 287 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
286 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 288 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ |
@@ -660,8 +662,45 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
660 | eq_tlv), | 662 | eq_tlv), |
661 | }; | 663 | }; |
662 | 664 | ||
665 | static const char *wm8958_ng_text[] = { | ||
666 | "30ms", "125ms", "250ms", "500ms", | ||
667 | }; | ||
668 | |||
669 | static const struct soc_enum wm8958_aif1dac1_ng_hold = | ||
670 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC1_NOISE_GATE, | ||
671 | WM8958_AIF1DAC1_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
672 | |||
673 | static const struct soc_enum wm8958_aif1dac2_ng_hold = | ||
674 | SOC_ENUM_SINGLE(WM8958_AIF1_DAC2_NOISE_GATE, | ||
675 | WM8958_AIF1DAC2_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
676 | |||
677 | static const struct soc_enum wm8958_aif2dac_ng_hold = | ||
678 | SOC_ENUM_SINGLE(WM8958_AIF2_DAC_NOISE_GATE, | ||
679 | WM8958_AIF2DAC_NG_THR_SHIFT, 4, wm8958_ng_text); | ||
680 | |||
663 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { | 681 | static const struct snd_kcontrol_new wm8958_snd_controls[] = { |
664 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), | 682 | SOC_SINGLE_TLV("AIF3 Boost Volume", WM8958_AIF3_CONTROL_2, 10, 3, 0, aif_tlv), |
683 | |||
684 | SOC_SINGLE("AIF1DAC1 Noise Gate Switch", WM8958_AIF1_DAC1_NOISE_GATE, | ||
685 | WM8958_AIF1DAC1_NG_ENA_SHIFT, 1, 0), | ||
686 | SOC_ENUM("AIF1DAC1 Noise Gate Hold Time", wm8958_aif1dac1_ng_hold), | ||
687 | SOC_SINGLE_TLV("AIF1DAC1 Noise Gate Threshold Volume", | ||
688 | WM8958_AIF1_DAC1_NOISE_GATE, WM8958_AIF1DAC1_NG_THR_SHIFT, | ||
689 | 7, 1, ng_tlv), | ||
690 | |||
691 | SOC_SINGLE("AIF1DAC2 Noise Gate Switch", WM8958_AIF1_DAC2_NOISE_GATE, | ||
692 | WM8958_AIF1DAC2_NG_ENA_SHIFT, 1, 0), | ||
693 | SOC_ENUM("AIF1DAC2 Noise Gate Hold Time", wm8958_aif1dac2_ng_hold), | ||
694 | SOC_SINGLE_TLV("AIF1DAC2 Noise Gate Threshold Volume", | ||
695 | WM8958_AIF1_DAC2_NOISE_GATE, WM8958_AIF1DAC2_NG_THR_SHIFT, | ||
696 | 7, 1, ng_tlv), | ||
697 | |||
698 | SOC_SINGLE("AIF2DAC Noise Gate Switch", WM8958_AIF2_DAC_NOISE_GATE, | ||
699 | WM8958_AIF2DAC_NG_ENA_SHIFT, 1, 0), | ||
700 | SOC_ENUM("AIF2DAC Noise Gate Hold Time", wm8958_aif2dac_ng_hold), | ||
701 | SOC_SINGLE_TLV("AIF2DAC Noise Gate Threshold Volume", | ||
702 | WM8958_AIF2_DAC_NOISE_GATE, WM8958_AIF2DAC_NG_THR_SHIFT, | ||
703 | 7, 1, ng_tlv), | ||
665 | }; | 704 | }; |
666 | 705 | ||
667 | static int clk_sys_event(struct snd_soc_dapm_widget *w, | 706 | static int clk_sys_event(struct snd_soc_dapm_widget *w, |
@@ -681,6 +720,97 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
681 | return 0; | 720 | return 0; |
682 | } | 721 | } |
683 | 722 | ||
723 | static void vmid_reference(struct snd_soc_codec *codec) | ||
724 | { | ||
725 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
726 | |||
727 | wm8994->vmid_refcount++; | ||
728 | |||
729 | dev_dbg(codec->dev, "Referencing VMID, refcount is now %d\n", | ||
730 | wm8994->vmid_refcount); | ||
731 | |||
732 | if (wm8994->vmid_refcount == 1) { | ||
733 | /* Startup bias, VMID ramp & buffer */ | ||
734 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
735 | WM8994_STARTUP_BIAS_ENA | | ||
736 | WM8994_VMID_BUF_ENA | | ||
737 | WM8994_VMID_RAMP_MASK, | ||
738 | WM8994_STARTUP_BIAS_ENA | | ||
739 | WM8994_VMID_BUF_ENA | | ||
740 | (0x11 << WM8994_VMID_RAMP_SHIFT)); | ||
741 | |||
742 | /* Main bias enable, VMID=2x40k */ | ||
743 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
744 | WM8994_BIAS_ENA | | ||
745 | WM8994_VMID_SEL_MASK, | ||
746 | WM8994_BIAS_ENA | 0x2); | ||
747 | |||
748 | msleep(20); | ||
749 | } | ||
750 | } | ||
751 | |||
752 | static void vmid_dereference(struct snd_soc_codec *codec) | ||
753 | { | ||
754 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
755 | |||
756 | wm8994->vmid_refcount--; | ||
757 | |||
758 | dev_dbg(codec->dev, "Dereferencing VMID, refcount is now %d\n", | ||
759 | wm8994->vmid_refcount); | ||
760 | |||
761 | if (wm8994->vmid_refcount == 0) { | ||
762 | /* Switch over to startup biases */ | ||
763 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
764 | WM8994_BIAS_SRC | | ||
765 | WM8994_STARTUP_BIAS_ENA | | ||
766 | WM8994_VMID_BUF_ENA | | ||
767 | WM8994_VMID_RAMP_MASK, | ||
768 | WM8994_BIAS_SRC | | ||
769 | WM8994_STARTUP_BIAS_ENA | | ||
770 | WM8994_VMID_BUF_ENA | | ||
771 | (1 << WM8994_VMID_RAMP_SHIFT)); | ||
772 | |||
773 | /* Disable main biases */ | ||
774 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
775 | WM8994_BIAS_ENA | | ||
776 | WM8994_VMID_SEL_MASK, 0); | ||
777 | |||
778 | /* Discharge line */ | ||
779 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
780 | WM8994_LINEOUT1_DISCH | | ||
781 | WM8994_LINEOUT2_DISCH, | ||
782 | WM8994_LINEOUT1_DISCH | | ||
783 | WM8994_LINEOUT2_DISCH); | ||
784 | |||
785 | msleep(5); | ||
786 | |||
787 | /* Switch off startup biases */ | ||
788 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
789 | WM8994_BIAS_SRC | | ||
790 | WM8994_STARTUP_BIAS_ENA | | ||
791 | WM8994_VMID_BUF_ENA | | ||
792 | WM8994_VMID_RAMP_MASK, 0); | ||
793 | } | ||
794 | } | ||
795 | |||
796 | static int vmid_event(struct snd_soc_dapm_widget *w, | ||
797 | struct snd_kcontrol *kcontrol, int event) | ||
798 | { | ||
799 | struct snd_soc_codec *codec = w->codec; | ||
800 | |||
801 | switch (event) { | ||
802 | case SND_SOC_DAPM_PRE_PMU: | ||
803 | vmid_reference(codec); | ||
804 | break; | ||
805 | |||
806 | case SND_SOC_DAPM_POST_PMD: | ||
807 | vmid_dereference(codec); | ||
808 | break; | ||
809 | } | ||
810 | |||
811 | return 0; | ||
812 | } | ||
813 | |||
684 | static void wm8994_update_class_w(struct snd_soc_codec *codec) | 814 | static void wm8994_update_class_w(struct snd_soc_codec *codec) |
685 | { | 815 | { |
686 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 816 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
@@ -1208,6 +1338,8 @@ SND_SOC_DAPM_INPUT("Clock"), | |||
1208 | 1338 | ||
1209 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, | 1339 | SND_SOC_DAPM_SUPPLY_S("MICBIAS Supply", 1, SND_SOC_NOPM, 0, 0, micbias_ev, |
1210 | SND_SOC_DAPM_PRE_PMU), | 1340 | SND_SOC_DAPM_PRE_PMU), |
1341 | SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | ||
1342 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
1211 | 1343 | ||
1212 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1344 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1213 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1345 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), |
@@ -1525,6 +1657,8 @@ static const struct snd_soc_dapm_route wm8994_revd_intercon[] = { | |||
1525 | static const struct snd_soc_dapm_route wm8994_intercon[] = { | 1657 | static const struct snd_soc_dapm_route wm8994_intercon[] = { |
1526 | { "AIF2DACL", NULL, "AIF2DAC Mux" }, | 1658 | { "AIF2DACL", NULL, "AIF2DAC Mux" }, |
1527 | { "AIF2DACR", NULL, "AIF2DAC Mux" }, | 1659 | { "AIF2DACR", NULL, "AIF2DAC Mux" }, |
1660 | { "MICBIAS1", NULL, "VMID" }, | ||
1661 | { "MICBIAS2", NULL, "VMID" }, | ||
1528 | }; | 1662 | }; |
1529 | 1663 | ||
1530 | static const struct snd_soc_dapm_route wm8958_intercon[] = { | 1664 | static const struct snd_soc_dapm_route wm8958_intercon[] = { |
@@ -1629,10 +1763,12 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1629 | unsigned int freq_in, unsigned int freq_out) | 1763 | unsigned int freq_in, unsigned int freq_out) |
1630 | { | 1764 | { |
1631 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | 1765 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); |
1766 | struct wm8994 *control = codec->control_data; | ||
1632 | int reg_offset, ret; | 1767 | int reg_offset, ret; |
1633 | struct fll_div fll; | 1768 | struct fll_div fll; |
1634 | u16 reg, aif1, aif2; | 1769 | u16 reg, aif1, aif2; |
1635 | unsigned long timeout; | 1770 | unsigned long timeout; |
1771 | bool was_enabled; | ||
1636 | 1772 | ||
1637 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) | 1773 | aif1 = snd_soc_read(codec, WM8994_AIF1_CLOCKING_1) |
1638 | & WM8994_AIF1CLK_ENA; | 1774 | & WM8994_AIF1CLK_ENA; |
@@ -1653,6 +1789,9 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1653 | return -EINVAL; | 1789 | return -EINVAL; |
1654 | } | 1790 | } |
1655 | 1791 | ||
1792 | reg = snd_soc_read(codec, WM8994_FLL1_CONTROL_1 + reg_offset); | ||
1793 | was_enabled = reg & WM8994_FLL1_ENA; | ||
1794 | |||
1656 | switch (src) { | 1795 | switch (src) { |
1657 | case 0: | 1796 | case 0: |
1658 | /* Allow no source specification when stopping */ | 1797 | /* Allow no source specification when stopping */ |
@@ -1719,6 +1858,21 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1719 | 1858 | ||
1720 | /* Enable (with fractional mode if required) */ | 1859 | /* Enable (with fractional mode if required) */ |
1721 | if (freq_out) { | 1860 | if (freq_out) { |
1861 | /* Enable VMID if we need it */ | ||
1862 | if (!was_enabled) { | ||
1863 | switch (control->type) { | ||
1864 | case WM8994: | ||
1865 | vmid_reference(codec); | ||
1866 | break; | ||
1867 | case WM8958: | ||
1868 | if (wm8994->revision < 1) | ||
1869 | vmid_reference(codec); | ||
1870 | break; | ||
1871 | default: | ||
1872 | break; | ||
1873 | } | ||
1874 | } | ||
1875 | |||
1722 | if (fll.k) | 1876 | if (fll.k) |
1723 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | 1877 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; |
1724 | else | 1878 | else |
@@ -1736,6 +1890,20 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
1736 | } else { | 1890 | } else { |
1737 | msleep(5); | 1891 | msleep(5); |
1738 | } | 1892 | } |
1893 | } else { | ||
1894 | if (was_enabled) { | ||
1895 | switch (control->type) { | ||
1896 | case WM8994: | ||
1897 | vmid_dereference(codec); | ||
1898 | break; | ||
1899 | case WM8958: | ||
1900 | if (wm8994->revision < 1) | ||
1901 | vmid_dereference(codec); | ||
1902 | break; | ||
1903 | default: | ||
1904 | break; | ||
1905 | } | ||
1906 | } | ||
1739 | } | 1907 | } |
1740 | 1908 | ||
1741 | wm8994->fll[id].in = freq_in; | 1909 | wm8994->fll[id].in = freq_in; |
@@ -1852,9 +2020,6 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
1852 | break; | 2020 | break; |
1853 | 2021 | ||
1854 | case SND_SOC_BIAS_PREPARE: | 2022 | case SND_SOC_BIAS_PREPARE: |
1855 | /* VMID=2x40k */ | ||
1856 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1857 | WM8994_VMID_SEL_MASK, 0x2); | ||
1858 | break; | 2023 | break; |
1859 | 2024 | ||
1860 | case SND_SOC_BIAS_STANDBY: | 2025 | case SND_SOC_BIAS_STANDBY: |
@@ -1896,65 +2061,13 @@ static int wm8994_set_bias_level(struct snd_soc_codec *codec, | |||
1896 | WM8994_LINEOUT2_DISCH, | 2061 | WM8994_LINEOUT2_DISCH, |
1897 | WM8994_LINEOUT1_DISCH | | 2062 | WM8994_LINEOUT1_DISCH | |
1898 | WM8994_LINEOUT2_DISCH); | 2063 | WM8994_LINEOUT2_DISCH); |
1899 | |||
1900 | /* Startup bias, VMID ramp & buffer */ | ||
1901 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1902 | WM8994_STARTUP_BIAS_ENA | | ||
1903 | WM8994_VMID_BUF_ENA | | ||
1904 | WM8994_VMID_RAMP_MASK, | ||
1905 | WM8994_STARTUP_BIAS_ENA | | ||
1906 | WM8994_VMID_BUF_ENA | | ||
1907 | (0x11 << WM8994_VMID_RAMP_SHIFT)); | ||
1908 | |||
1909 | /* Main bias enable, VMID=2x40k */ | ||
1910 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1911 | WM8994_BIAS_ENA | | ||
1912 | WM8994_VMID_SEL_MASK, | ||
1913 | WM8994_BIAS_ENA | 0x2); | ||
1914 | |||
1915 | msleep(20); | ||
1916 | } | 2064 | } |
1917 | 2065 | ||
1918 | /* VMID=2x500k */ | ||
1919 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1920 | WM8994_VMID_SEL_MASK, 0x4); | ||
1921 | 2066 | ||
1922 | break; | 2067 | break; |
1923 | 2068 | ||
1924 | case SND_SOC_BIAS_OFF: | 2069 | case SND_SOC_BIAS_OFF: |
1925 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | 2070 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { |
1926 | /* Switch over to startup biases */ | ||
1927 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1928 | WM8994_BIAS_SRC | | ||
1929 | WM8994_STARTUP_BIAS_ENA | | ||
1930 | WM8994_VMID_BUF_ENA | | ||
1931 | WM8994_VMID_RAMP_MASK, | ||
1932 | WM8994_BIAS_SRC | | ||
1933 | WM8994_STARTUP_BIAS_ENA | | ||
1934 | WM8994_VMID_BUF_ENA | | ||
1935 | (1 << WM8994_VMID_RAMP_SHIFT)); | ||
1936 | |||
1937 | /* Disable main biases */ | ||
1938 | snd_soc_update_bits(codec, WM8994_POWER_MANAGEMENT_1, | ||
1939 | WM8994_BIAS_ENA | | ||
1940 | WM8994_VMID_SEL_MASK, 0); | ||
1941 | |||
1942 | /* Discharge line */ | ||
1943 | snd_soc_update_bits(codec, WM8994_ANTIPOP_1, | ||
1944 | WM8994_LINEOUT1_DISCH | | ||
1945 | WM8994_LINEOUT2_DISCH, | ||
1946 | WM8994_LINEOUT1_DISCH | | ||
1947 | WM8994_LINEOUT2_DISCH); | ||
1948 | |||
1949 | msleep(5); | ||
1950 | |||
1951 | /* Switch off startup biases */ | ||
1952 | snd_soc_update_bits(codec, WM8994_ANTIPOP_2, | ||
1953 | WM8994_BIAS_SRC | | ||
1954 | WM8994_STARTUP_BIAS_ENA | | ||
1955 | WM8994_VMID_BUF_ENA | | ||
1956 | WM8994_VMID_RAMP_MASK, 0); | ||
1957 | |||
1958 | wm8994->cur_fw = NULL; | 2071 | wm8994->cur_fw = NULL; |
1959 | 2072 | ||
1960 | pm_runtime_put(codec->dev); | 2073 | pm_runtime_put(codec->dev); |
@@ -2384,6 +2497,21 @@ static int wm8994_set_tristate(struct snd_soc_dai *codec_dai, int tristate) | |||
2384 | return snd_soc_update_bits(codec, reg, mask, val); | 2497 | return snd_soc_update_bits(codec, reg, mask, val); |
2385 | } | 2498 | } |
2386 | 2499 | ||
2500 | static int wm8994_aif2_probe(struct snd_soc_dai *dai) | ||
2501 | { | ||
2502 | struct snd_soc_codec *codec = dai->codec; | ||
2503 | |||
2504 | /* Disable the pulls on the AIF if we're using it to save power. */ | ||
2505 | snd_soc_update_bits(codec, WM8994_GPIO_3, | ||
2506 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2507 | snd_soc_update_bits(codec, WM8994_GPIO_4, | ||
2508 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2509 | snd_soc_update_bits(codec, WM8994_GPIO_5, | ||
2510 | WM8994_GPN_PU | WM8994_GPN_PD, 0); | ||
2511 | |||
2512 | return 0; | ||
2513 | } | ||
2514 | |||
2387 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 | 2515 | #define WM8994_RATES SNDRV_PCM_RATE_8000_96000 |
2388 | 2516 | ||
2389 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ | 2517 | #define WM8994_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE |\ |
@@ -2451,6 +2579,7 @@ static struct snd_soc_dai_driver wm8994_dai[] = { | |||
2451 | .rates = WM8994_RATES, | 2579 | .rates = WM8994_RATES, |
2452 | .formats = WM8994_FORMATS, | 2580 | .formats = WM8994_FORMATS, |
2453 | }, | 2581 | }, |
2582 | .probe = wm8994_aif2_probe, | ||
2454 | .ops = &wm8994_aif2_dai_ops, | 2583 | .ops = &wm8994_aif2_dai_ops, |
2455 | }, | 2584 | }, |
2456 | { | 2585 | { |
@@ -2916,6 +3045,24 @@ static irqreturn_t wm8994_fifo_error(int irq, void *data) | |||
2916 | return IRQ_HANDLED; | 3045 | return IRQ_HANDLED; |
2917 | } | 3046 | } |
2918 | 3047 | ||
3048 | static irqreturn_t wm8994_temp_warn(int irq, void *data) | ||
3049 | { | ||
3050 | struct snd_soc_codec *codec = data; | ||
3051 | |||
3052 | dev_err(codec->dev, "Thermal warning\n"); | ||
3053 | |||
3054 | return IRQ_HANDLED; | ||
3055 | } | ||
3056 | |||
3057 | static irqreturn_t wm8994_temp_shut(int irq, void *data) | ||
3058 | { | ||
3059 | struct snd_soc_codec *codec = data; | ||
3060 | |||
3061 | dev_crit(codec->dev, "Thermal shutdown\n"); | ||
3062 | |||
3063 | return IRQ_HANDLED; | ||
3064 | } | ||
3065 | |||
2919 | static int wm8994_codec_probe(struct snd_soc_codec *codec) | 3066 | static int wm8994_codec_probe(struct snd_soc_codec *codec) |
2920 | { | 3067 | { |
2921 | struct wm8994 *control; | 3068 | struct wm8994 *control; |
@@ -2972,13 +3119,14 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2972 | switch (wm8994->revision) { | 3119 | switch (wm8994->revision) { |
2973 | case 2: | 3120 | case 2: |
2974 | case 3: | 3121 | case 3: |
2975 | wm8994->hubs.dcs_codes = -5; | 3122 | wm8994->hubs.dcs_codes_l = -5; |
3123 | wm8994->hubs.dcs_codes_r = -5; | ||
2976 | wm8994->hubs.hp_startup_mode = 1; | 3124 | wm8994->hubs.hp_startup_mode = 1; |
2977 | wm8994->hubs.dcs_readback_mode = 1; | 3125 | wm8994->hubs.dcs_readback_mode = 1; |
2978 | wm8994->hubs.series_startup = 1; | 3126 | wm8994->hubs.series_startup = 1; |
2979 | break; | 3127 | break; |
2980 | default: | 3128 | default: |
2981 | wm8994->hubs.dcs_readback_mode = 1; | 3129 | wm8994->hubs.dcs_readback_mode = 2; |
2982 | break; | 3130 | break; |
2983 | } | 3131 | } |
2984 | break; | 3132 | break; |
@@ -2993,6 +3141,10 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
2993 | 3141 | ||
2994 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, | 3142 | wm8994_request_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, |
2995 | wm8994_fifo_error, "FIFO error", codec); | 3143 | wm8994_fifo_error, "FIFO error", codec); |
3144 | wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_WARN, | ||
3145 | wm8994_temp_warn, "Thermal warning", codec); | ||
3146 | wm8994_request_irq(wm8994->control_data, WM8994_IRQ_TEMP_SHUT, | ||
3147 | wm8994_temp_shut, "Thermal shutdown", codec); | ||
2996 | 3148 | ||
2997 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3149 | ret = wm8994_request_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
2998 | wm_hubs_dcs_done, "DC servo done", | 3150 | wm_hubs_dcs_done, "DC servo done", |
@@ -3257,6 +3409,8 @@ err_irq: | |||
3257 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3409 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
3258 | &wm8994->hubs); | 3410 | &wm8994->hubs); |
3259 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | 3411 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); |
3412 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); | ||
3413 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); | ||
3260 | err: | 3414 | err: |
3261 | kfree(wm8994); | 3415 | kfree(wm8994); |
3262 | return ret; | 3416 | return ret; |
@@ -3279,6 +3433,8 @@ static int wm8994_codec_remove(struct snd_soc_codec *codec) | |||
3279 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, | 3433 | wm8994_free_irq(codec->control_data, WM8994_IRQ_DCS_DONE, |
3280 | &wm8994->hubs); | 3434 | &wm8994->hubs); |
3281 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); | 3435 | wm8994_free_irq(codec->control_data, WM8994_IRQ_FIFOS_ERR, codec); |
3436 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_SHUT, codec); | ||
3437 | wm8994_free_irq(codec->control_data, WM8994_IRQ_TEMP_WARN, codec); | ||
3282 | 3438 | ||
3283 | switch (control->type) { | 3439 | switch (control->type) { |
3284 | case WM8994: | 3440 | case WM8994: |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 1ab2266039f7..f4f1355efc82 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -83,6 +83,8 @@ struct wm8994_priv { | |||
83 | struct completion fll_locked[2]; | 83 | struct completion fll_locked[2]; |
84 | bool fll_locked_irq; | 84 | bool fll_locked_irq; |
85 | 85 | ||
86 | int vmid_refcount; | ||
87 | |||
86 | int dac_rates[2]; | 88 | int dac_rates[2]; |
87 | int lrclk_shared[2]; | 89 | int lrclk_shared[2]; |
88 | 90 | ||
diff --git a/sound/soc/codecs/wm8995.c b/sound/soc/codecs/wm8995.c index 5ad873fda814..74ae5995a786 100644 --- a/sound/soc/codecs/wm8995.c +++ b/sound/soc/codecs/wm8995.c | |||
@@ -1573,9 +1573,7 @@ static int wm8995_resume(struct snd_soc_codec *codec) | |||
1573 | static int wm8995_remove(struct snd_soc_codec *codec) | 1573 | static int wm8995_remove(struct snd_soc_codec *codec) |
1574 | { | 1574 | { |
1575 | struct wm8995_priv *wm8995; | 1575 | struct wm8995_priv *wm8995; |
1576 | struct i2c_client *i2c; | ||
1577 | 1576 | ||
1578 | i2c = container_of(codec->dev, struct i2c_client, dev); | ||
1579 | wm8995 = snd_soc_codec_get_drvdata(codec); | 1577 | wm8995 = snd_soc_codec_get_drvdata(codec); |
1580 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1578 | wm8995_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1581 | return 0; | 1579 | return 0; |
@@ -1642,6 +1640,7 @@ static int wm8995_probe(struct snd_soc_codec *codec) | |||
1642 | 1640 | ||
1643 | if (ret != 0x8995) { | 1641 | if (ret != 0x8995) { |
1644 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); | 1642 | dev_err(codec->dev, "Invalid device ID: %#x\n", ret); |
1643 | ret = -EINVAL; | ||
1645 | goto err_reg_enable; | 1644 | goto err_reg_enable; |
1646 | } | 1645 | } |
1647 | 1646 | ||
diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index 0cdb9d105671..833df74c5584 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c | |||
@@ -41,12 +41,11 @@ | |||
41 | #define HPOUT2L 4 | 41 | #define HPOUT2L 4 |
42 | #define HPOUT2R 8 | 42 | #define HPOUT2R 8 |
43 | 43 | ||
44 | #define WM8996_NUM_SUPPLIES 4 | 44 | #define WM8996_NUM_SUPPLIES 3 |
45 | static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { | 45 | static const char *wm8996_supply_names[WM8996_NUM_SUPPLIES] = { |
46 | "DBVDD", | 46 | "DBVDD", |
47 | "AVDD1", | 47 | "AVDD1", |
48 | "AVDD2", | 48 | "AVDD2", |
49 | "CPVDD", | ||
50 | }; | 49 | }; |
51 | 50 | ||
52 | struct wm8996_priv { | 51 | struct wm8996_priv { |
@@ -71,6 +70,8 @@ struct wm8996_priv { | |||
71 | 70 | ||
72 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; | 71 | struct regulator_bulk_data supplies[WM8996_NUM_SUPPLIES]; |
73 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; | 72 | struct notifier_block disable_nb[WM8996_NUM_SUPPLIES]; |
73 | struct regulator *cpvdd; | ||
74 | int bg_ena; | ||
74 | 75 | ||
75 | struct wm8996_pdata pdata; | 76 | struct wm8996_pdata pdata; |
76 | 77 | ||
@@ -112,7 +113,6 @@ static int wm8996_regulator_event_##n(struct notifier_block *nb, \ | |||
112 | WM8996_REGULATOR_EVENT(0) | 113 | WM8996_REGULATOR_EVENT(0) |
113 | WM8996_REGULATOR_EVENT(1) | 114 | WM8996_REGULATOR_EVENT(1) |
114 | WM8996_REGULATOR_EVENT(2) | 115 | WM8996_REGULATOR_EVENT(2) |
115 | WM8996_REGULATOR_EVENT(3) | ||
116 | 116 | ||
117 | static const u16 wm8996_reg[WM8996_MAX_REGISTER] = { | 117 | static const u16 wm8996_reg[WM8996_MAX_REGISTER] = { |
118 | [WM8996_SOFTWARE_RESET] = 0x8996, | 118 | [WM8996_SOFTWARE_RESET] = 0x8996, |
@@ -414,6 +414,7 @@ static const DECLARE_TLV_DB_SCALE(out_digital_tlv, -1200, 150, 0); | |||
414 | static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); | 414 | static const DECLARE_TLV_DB_SCALE(out_tlv, -900, 75, 0); |
415 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); | 415 | static const DECLARE_TLV_DB_SCALE(spk_tlv, -900, 150, 0); |
416 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); | 416 | static const DECLARE_TLV_DB_SCALE(eq_tlv, -1200, 100, 0); |
417 | static const DECLARE_TLV_DB_SCALE(threedstereo_tlv, -1600, 183, 1); | ||
417 | 418 | ||
418 | static const char *sidetone_hpf_text[] = { | 419 | static const char *sidetone_hpf_text[] = { |
419 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" | 420 | "2.9kHz", "1.5kHz", "735Hz", "403Hz", "196Hz", "98Hz", "49Hz" |
@@ -608,6 +609,14 @@ SOC_SINGLE("DAC High Performance Switch", WM8996_OVERSAMPLING, 0, 1, 0), | |||
608 | SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), | 609 | SOC_SINGLE("DAC Soft Mute Switch", WM8996_DAC_SOFTMUTE, 1, 1, 0), |
609 | SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), | 610 | SOC_SINGLE("DAC Slow Soft Mute Switch", WM8996_DAC_SOFTMUTE, 0, 1, 0), |
610 | 611 | ||
612 | SOC_SINGLE("DSP1 3D Stereo Switch", WM8996_DSP1_RX_FILTERS_2, 8, 1, 0), | ||
613 | SOC_SINGLE("DSP2 3D Stereo Switch", WM8996_DSP2_RX_FILTERS_2, 8, 1, 0), | ||
614 | |||
615 | SOC_SINGLE_TLV("DSP1 3D Stereo Volume", WM8996_DSP1_RX_FILTERS_2, 10, 15, | ||
616 | 0, threedstereo_tlv), | ||
617 | SOC_SINGLE_TLV("DSP2 3D Stereo Volume", WM8996_DSP2_RX_FILTERS_2, 10, 15, | ||
618 | 0, threedstereo_tlv), | ||
619 | |||
611 | SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, | 620 | SOC_DOUBLE_TLV("Digital Output 1 Volume", WM8996_DAC1_HPOUT1_VOLUME, 0, 4, |
612 | 8, 0, out_digital_tlv), | 621 | 8, 0, out_digital_tlv), |
613 | SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, | 622 | SOC_DOUBLE_TLV("Digital Output 2 Volume", WM8996_DAC2_HPOUT2_VOLUME, 0, 4, |
@@ -658,19 +667,75 @@ SOC_SINGLE_TLV("DSP2 EQ B5 Volume", WM8996_DSP2_RX_EQ_GAINS_2, 6, 31, 0, | |||
658 | eq_tlv), | 667 | eq_tlv), |
659 | }; | 668 | }; |
660 | 669 | ||
670 | static void wm8996_bg_enable(struct snd_soc_codec *codec) | ||
671 | { | ||
672 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
673 | |||
674 | wm8996->bg_ena++; | ||
675 | if (wm8996->bg_ena == 1) { | ||
676 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
677 | WM8996_BG_ENA, WM8996_BG_ENA); | ||
678 | msleep(2); | ||
679 | } | ||
680 | } | ||
681 | |||
682 | static void wm8996_bg_disable(struct snd_soc_codec *codec) | ||
683 | { | ||
684 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
685 | |||
686 | wm8996->bg_ena--; | ||
687 | if (!wm8996->bg_ena) | ||
688 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
689 | WM8996_BG_ENA, 0); | ||
690 | } | ||
691 | |||
692 | static int bg_event(struct snd_soc_dapm_widget *w, | ||
693 | struct snd_kcontrol *kcontrol, int event) | ||
694 | { | ||
695 | struct snd_soc_codec *codec = w->codec; | ||
696 | int ret = 0; | ||
697 | |||
698 | switch (event) { | ||
699 | case SND_SOC_DAPM_PRE_PMU: | ||
700 | wm8996_bg_enable(codec); | ||
701 | break; | ||
702 | case SND_SOC_DAPM_POST_PMD: | ||
703 | wm8996_bg_disable(codec); | ||
704 | break; | ||
705 | default: | ||
706 | BUG(); | ||
707 | ret = -EINVAL; | ||
708 | } | ||
709 | |||
710 | return ret; | ||
711 | } | ||
712 | |||
661 | static int cp_event(struct snd_soc_dapm_widget *w, | 713 | static int cp_event(struct snd_soc_dapm_widget *w, |
662 | struct snd_kcontrol *kcontrol, int event) | 714 | struct snd_kcontrol *kcontrol, int event) |
663 | { | 715 | { |
716 | struct snd_soc_codec *codec = w->codec; | ||
717 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
718 | int ret = 0; | ||
719 | |||
664 | switch (event) { | 720 | switch (event) { |
721 | case SND_SOC_DAPM_PRE_PMU: | ||
722 | ret = regulator_enable(wm8996->cpvdd); | ||
723 | if (ret != 0) | ||
724 | dev_err(codec->dev, "Failed to enable CPVDD: %d\n", | ||
725 | ret); | ||
726 | break; | ||
665 | case SND_SOC_DAPM_POST_PMU: | 727 | case SND_SOC_DAPM_POST_PMU: |
666 | msleep(5); | 728 | msleep(5); |
667 | break; | 729 | break; |
730 | case SND_SOC_DAPM_POST_PMD: | ||
731 | regulator_disable_deferred(wm8996->cpvdd, 20); | ||
732 | break; | ||
668 | default: | 733 | default: |
669 | BUG(); | 734 | BUG(); |
670 | return -EINVAL; | 735 | ret = -EINVAL; |
671 | } | 736 | } |
672 | 737 | ||
673 | return 0; | 738 | return ret; |
674 | } | 739 | } |
675 | 740 | ||
676 | static int rmv_short_event(struct snd_soc_dapm_widget *w, | 741 | static int rmv_short_event(struct snd_soc_dapm_widget *w, |
@@ -698,7 +763,7 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
698 | { | 763 | { |
699 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 764 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
700 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 765 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
701 | int i, ret; | 766 | int ret; |
702 | unsigned long timeout = 200; | 767 | unsigned long timeout = 200; |
703 | 768 | ||
704 | snd_soc_write(codec, WM8996_DC_SERVO_2, mask); | 769 | snd_soc_write(codec, WM8996_DC_SERVO_2, mask); |
@@ -713,15 +778,12 @@ static void wait_for_dc_servo(struct snd_soc_codec *codec, u16 mask) | |||
713 | 778 | ||
714 | } else { | 779 | } else { |
715 | msleep(1); | 780 | msleep(1); |
716 | if (--i) { | 781 | timeout--; |
717 | timeout = 0; | ||
718 | break; | ||
719 | } | ||
720 | } | 782 | } |
721 | 783 | ||
722 | ret = snd_soc_read(codec, WM8996_DC_SERVO_2); | 784 | ret = snd_soc_read(codec, WM8996_DC_SERVO_2); |
723 | dev_dbg(codec->dev, "DC servo state: %x\n", ret); | 785 | dev_dbg(codec->dev, "DC servo state: %x\n", ret); |
724 | } while (ret & mask); | 786 | } while (timeout && ret & mask); |
725 | 787 | ||
726 | if (timeout == 0) | 788 | if (timeout == 0) |
727 | dev_err(codec->dev, "DC servo timed out for %x\n", mask); | 789 | dev_err(codec->dev, "DC servo timed out for %x\n", mask); |
@@ -979,9 +1041,12 @@ SND_SOC_DAPM_SUPPLY_S("SYSCLK", 1, WM8996_AIF_CLOCKING_1, 0, 0, NULL, 0), | |||
979 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), | 1041 | SND_SOC_DAPM_SUPPLY_S("SYSDSPCLK", 2, WM8996_CLOCKING_1, 1, 0, NULL, 0), |
980 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), | 1042 | SND_SOC_DAPM_SUPPLY_S("AIFCLK", 2, WM8996_CLOCKING_1, 2, 0, NULL, 0), |
981 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, | 1043 | SND_SOC_DAPM_SUPPLY_S("Charge Pump", 2, WM8996_CHARGE_PUMP_1, 15, 0, cp_event, |
982 | SND_SOC_DAPM_POST_PMU), | 1044 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
983 | 1045 | SND_SOC_DAPM_SUPPLY("Bandgap", SND_SOC_NOPM, 0, 0, bg_event, | |
1046 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | ||
984 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), | 1047 | SND_SOC_DAPM_SUPPLY("LDO2", WM8996_POWER_MANAGEMENT_2, 1, 0, NULL, 0), |
1048 | SND_SOC_DAPM_SUPPLY("MICB1 Audio", WM8996_MICBIAS_1, 4, 1, NULL, 0), | ||
1049 | SND_SOC_DAPM_SUPPLY("MICB2 Audio", WM8996_MICBIAS_2, 4, 1, NULL, 0), | ||
985 | SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), | 1050 | SND_SOC_DAPM_MICBIAS("MICB2", WM8996_POWER_MANAGEMENT_1, 9, 0), |
986 | SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), | 1051 | SND_SOC_DAPM_MICBIAS("MICB1", WM8996_POWER_MANAGEMENT_1, 8, 0), |
987 | 1052 | ||
@@ -1035,14 +1100,14 @@ SND_SOC_DAPM_DAC("DAC2R", NULL, WM8996_POWER_MANAGEMENT_5, 2, 0), | |||
1035 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), | 1100 | SND_SOC_DAPM_DAC("DAC1L", NULL, WM8996_POWER_MANAGEMENT_5, 1, 0), |
1036 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), | 1101 | SND_SOC_DAPM_DAC("DAC1R", NULL, WM8996_POWER_MANAGEMENT_5, 0, 0), |
1037 | 1102 | ||
1038 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 1, | 1103 | SND_SOC_DAPM_AIF_IN("AIF2RX1", "AIF2 Playback", 0, |
1039 | WM8996_POWER_MANAGEMENT_4, 9, 0), | 1104 | WM8996_POWER_MANAGEMENT_4, 9, 0), |
1040 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 2, | 1105 | SND_SOC_DAPM_AIF_IN("AIF2RX0", "AIF2 Playback", 1, |
1041 | WM8996_POWER_MANAGEMENT_4, 8, 0), | 1106 | WM8996_POWER_MANAGEMENT_4, 8, 0), |
1042 | 1107 | ||
1043 | SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 1, | 1108 | SND_SOC_DAPM_AIF_IN("AIF2TX1", "AIF2 Capture", 0, |
1044 | WM8996_POWER_MANAGEMENT_6, 9, 0), | 1109 | WM8996_POWER_MANAGEMENT_6, 9, 0), |
1045 | SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 2, | 1110 | SND_SOC_DAPM_AIF_IN("AIF2TX0", "AIF2 Capture", 1, |
1046 | WM8996_POWER_MANAGEMENT_6, 8, 0), | 1111 | WM8996_POWER_MANAGEMENT_6, 8, 0), |
1047 | 1112 | ||
1048 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, | 1113 | SND_SOC_DAPM_AIF_IN("AIF1RX5", "AIF1 Playback", 5, |
@@ -1137,17 +1202,23 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1137 | { "Charge Pump", NULL, "SYSCLK" }, | 1202 | { "Charge Pump", NULL, "SYSCLK" }, |
1138 | 1203 | ||
1139 | { "MICB1", NULL, "LDO2" }, | 1204 | { "MICB1", NULL, "LDO2" }, |
1205 | { "MICB1", NULL, "MICB1 Audio" }, | ||
1206 | { "MICB1", NULL, "Bandgap" }, | ||
1140 | { "MICB2", NULL, "LDO2" }, | 1207 | { "MICB2", NULL, "LDO2" }, |
1208 | { "MICB2", NULL, "MICB2 Audio" }, | ||
1209 | { "MICB2", NULL, "Bandgap" }, | ||
1141 | 1210 | ||
1142 | { "IN1L PGA", NULL, "IN2LN" }, | 1211 | { "IN1L PGA", NULL, "IN2LN" }, |
1143 | { "IN1L PGA", NULL, "IN2LP" }, | 1212 | { "IN1L PGA", NULL, "IN2LP" }, |
1144 | { "IN1L PGA", NULL, "IN1LN" }, | 1213 | { "IN1L PGA", NULL, "IN1LN" }, |
1145 | { "IN1L PGA", NULL, "IN1LP" }, | 1214 | { "IN1L PGA", NULL, "IN1LP" }, |
1215 | { "IN1L PGA", NULL, "Bandgap" }, | ||
1146 | 1216 | ||
1147 | { "IN1R PGA", NULL, "IN2RN" }, | 1217 | { "IN1R PGA", NULL, "IN2RN" }, |
1148 | { "IN1R PGA", NULL, "IN2RP" }, | 1218 | { "IN1R PGA", NULL, "IN2RP" }, |
1149 | { "IN1R PGA", NULL, "IN1RN" }, | 1219 | { "IN1R PGA", NULL, "IN1RN" }, |
1150 | { "IN1R PGA", NULL, "IN1RP" }, | 1220 | { "IN1R PGA", NULL, "IN1RP" }, |
1221 | { "IN1R PGA", NULL, "Bandgap" }, | ||
1151 | 1222 | ||
1152 | { "ADCL", NULL, "IN1L PGA" }, | 1223 | { "ADCL", NULL, "IN1L PGA" }, |
1153 | 1224 | ||
@@ -1281,6 +1352,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1281 | { "DAC2R", NULL, "DAC2R Mixer" }, | 1352 | { "DAC2R", NULL, "DAC2R Mixer" }, |
1282 | 1353 | ||
1283 | { "HPOUT2L PGA", NULL, "Charge Pump" }, | 1354 | { "HPOUT2L PGA", NULL, "Charge Pump" }, |
1355 | { "HPOUT2L PGA", NULL, "Bandgap" }, | ||
1284 | { "HPOUT2L PGA", NULL, "DAC2L" }, | 1356 | { "HPOUT2L PGA", NULL, "DAC2L" }, |
1285 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, | 1357 | { "HPOUT2L_DLY", NULL, "HPOUT2L PGA" }, |
1286 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, | 1358 | { "HPOUT2L_DCS", NULL, "HPOUT2L_DLY" }, |
@@ -1288,6 +1360,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1288 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, | 1360 | { "HPOUT2L_RMV_SHORT", NULL, "HPOUT2L_OUTP" }, |
1289 | 1361 | ||
1290 | { "HPOUT2R PGA", NULL, "Charge Pump" }, | 1362 | { "HPOUT2R PGA", NULL, "Charge Pump" }, |
1363 | { "HPOUT2R PGA", NULL, "Bandgap" }, | ||
1291 | { "HPOUT2R PGA", NULL, "DAC2R" }, | 1364 | { "HPOUT2R PGA", NULL, "DAC2R" }, |
1292 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, | 1365 | { "HPOUT2R_DLY", NULL, "HPOUT2R PGA" }, |
1293 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, | 1366 | { "HPOUT2R_DCS", NULL, "HPOUT2R_DLY" }, |
@@ -1295,6 +1368,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1295 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, | 1368 | { "HPOUT2R_RMV_SHORT", NULL, "HPOUT2R_OUTP" }, |
1296 | 1369 | ||
1297 | { "HPOUT1L PGA", NULL, "Charge Pump" }, | 1370 | { "HPOUT1L PGA", NULL, "Charge Pump" }, |
1371 | { "HPOUT1L PGA", NULL, "Bandgap" }, | ||
1298 | { "HPOUT1L PGA", NULL, "DAC1L" }, | 1372 | { "HPOUT1L PGA", NULL, "DAC1L" }, |
1299 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, | 1373 | { "HPOUT1L_DLY", NULL, "HPOUT1L PGA" }, |
1300 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, | 1374 | { "HPOUT1L_DCS", NULL, "HPOUT1L_DLY" }, |
@@ -1302,6 +1376,7 @@ static const struct snd_soc_dapm_route wm8996_dapm_routes[] = { | |||
1302 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, | 1376 | { "HPOUT1L_RMV_SHORT", NULL, "HPOUT1L_OUTP" }, |
1303 | 1377 | ||
1304 | { "HPOUT1R PGA", NULL, "Charge Pump" }, | 1378 | { "HPOUT1R PGA", NULL, "Charge Pump" }, |
1379 | { "HPOUT1R PGA", NULL, "Bandgap" }, | ||
1305 | { "HPOUT1R PGA", NULL, "DAC1R" }, | 1380 | { "HPOUT1R PGA", NULL, "DAC1R" }, |
1306 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, | 1381 | { "HPOUT1R_DLY", NULL, "HPOUT1R PGA" }, |
1307 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, | 1382 | { "HPOUT1R_DCS", NULL, "HPOUT1R_DLY" }, |
@@ -1620,14 +1695,7 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1620 | 1695 | ||
1621 | switch (level) { | 1696 | switch (level) { |
1622 | case SND_SOC_BIAS_ON: | 1697 | case SND_SOC_BIAS_ON: |
1623 | break; | ||
1624 | |||
1625 | case SND_SOC_BIAS_PREPARE: | 1698 | case SND_SOC_BIAS_PREPARE: |
1626 | if (codec->dapm.bias_level == SND_SOC_BIAS_STANDBY) { | ||
1627 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
1628 | WM8996_BG_ENA, WM8996_BG_ENA); | ||
1629 | msleep(2); | ||
1630 | } | ||
1631 | break; | 1699 | break; |
1632 | 1700 | ||
1633 | case SND_SOC_BIAS_STANDBY: | 1701 | case SND_SOC_BIAS_STANDBY: |
@@ -1650,9 +1718,6 @@ static int wm8996_set_bias_level(struct snd_soc_codec *codec, | |||
1650 | codec->cache_only = false; | 1718 | codec->cache_only = false; |
1651 | snd_soc_cache_sync(codec); | 1719 | snd_soc_cache_sync(codec); |
1652 | } | 1720 | } |
1653 | |||
1654 | snd_soc_update_bits(codec, WM8996_POWER_MANAGEMENT_1, | ||
1655 | WM8996_BG_ENA, 0); | ||
1656 | break; | 1721 | break; |
1657 | 1722 | ||
1658 | case SND_SOC_BIAS_OFF: | 1723 | case SND_SOC_BIAS_OFF: |
@@ -2041,7 +2106,7 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2041 | struct i2c_client *i2c = to_i2c_client(codec->dev); | 2106 | struct i2c_client *i2c = to_i2c_client(codec->dev); |
2042 | struct _fll_div fll_div; | 2107 | struct _fll_div fll_div; |
2043 | unsigned long timeout; | 2108 | unsigned long timeout; |
2044 | int ret, reg; | 2109 | int ret, reg, retry; |
2045 | 2110 | ||
2046 | /* Any change? */ | 2111 | /* Any change? */ |
2047 | if (source == wm8996->fll_src && Fref == wm8996->fll_fref && | 2112 | if (source == wm8996->fll_src && Fref == wm8996->fll_fref && |
@@ -2057,6 +2122,8 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2057 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, | 2122 | snd_soc_update_bits(codec, WM8996_FLL_CONTROL_1, |
2058 | WM8996_FLL_ENA, 0); | 2123 | WM8996_FLL_ENA, 0); |
2059 | 2124 | ||
2125 | wm8996_bg_disable(codec); | ||
2126 | |||
2060 | return 0; | 2127 | return 0; |
2061 | } | 2128 | } |
2062 | 2129 | ||
@@ -2111,6 +2178,11 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2111 | 2178 | ||
2112 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); | 2179 | snd_soc_write(codec, WM8996_FLL_EFS_1, fll_div.lambda); |
2113 | 2180 | ||
2181 | /* Enable the bandgap if it's not already enabled */ | ||
2182 | ret = snd_soc_read(codec, WM8996_FLL_CONTROL_1); | ||
2183 | if (!(ret & WM8996_FLL_ENA)) | ||
2184 | wm8996_bg_enable(codec); | ||
2185 | |||
2114 | /* Clear any pending completions (eg, from failed startups) */ | 2186 | /* Clear any pending completions (eg, from failed startups) */ |
2115 | try_wait_for_completion(&wm8996->fll_lock); | 2187 | try_wait_for_completion(&wm8996->fll_lock); |
2116 | 2188 | ||
@@ -2128,17 +2200,29 @@ static int wm8996_set_fll(struct snd_soc_codec *codec, int fll_id, int source, | |||
2128 | else | 2200 | else |
2129 | timeout = msecs_to_jiffies(2); | 2201 | timeout = msecs_to_jiffies(2); |
2130 | 2202 | ||
2131 | /* Allow substantially longer if we've actually got the IRQ */ | 2203 | /* Allow substantially longer if we've actually got the IRQ, poll |
2204 | * at a slightly higher rate if we don't. | ||
2205 | */ | ||
2132 | if (i2c->irq) | 2206 | if (i2c->irq) |
2133 | timeout *= 1000; | 2207 | timeout *= 10; |
2208 | else | ||
2209 | timeout /= 2; | ||
2134 | 2210 | ||
2135 | ret = wait_for_completion_timeout(&wm8996->fll_lock, timeout); | 2211 | for (retry = 0; retry < 10; retry++) { |
2212 | ret = wait_for_completion_timeout(&wm8996->fll_lock, | ||
2213 | timeout); | ||
2214 | if (ret != 0) { | ||
2215 | WARN_ON(!i2c->irq); | ||
2216 | break; | ||
2217 | } | ||
2136 | 2218 | ||
2137 | if (ret == 0 && i2c->irq) { | 2219 | ret = snd_soc_read(codec, WM8996_INTERRUPT_RAW_STATUS_2); |
2220 | if (ret & WM8996_FLL_LOCK_STS) | ||
2221 | break; | ||
2222 | } | ||
2223 | if (retry == 10) { | ||
2138 | dev_err(codec->dev, "Timed out waiting for FLL\n"); | 2224 | dev_err(codec->dev, "Timed out waiting for FLL\n"); |
2139 | ret = -ETIMEDOUT; | 2225 | ret = -ETIMEDOUT; |
2140 | } else { | ||
2141 | ret = 0; | ||
2142 | } | 2226 | } |
2143 | 2227 | ||
2144 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); | 2228 | dev_dbg(codec->dev, "FLL configured for %dHz->%dHz\n", Fref, Fout); |
@@ -2297,12 +2381,94 @@ int wm8996_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
2297 | 2381 | ||
2298 | /* Enable interrupts and we're off */ | 2382 | /* Enable interrupts and we're off */ |
2299 | snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, | 2383 | snd_soc_update_bits(codec, WM8996_INTERRUPT_STATUS_2_MASK, |
2300 | WM8996_IM_MICD_EINT, 0); | 2384 | WM8996_IM_MICD_EINT | WM8996_HP_DONE_EINT, 0); |
2301 | 2385 | ||
2302 | return 0; | 2386 | return 0; |
2303 | } | 2387 | } |
2304 | EXPORT_SYMBOL_GPL(wm8996_detect); | 2388 | EXPORT_SYMBOL_GPL(wm8996_detect); |
2305 | 2389 | ||
2390 | static void wm8996_hpdet_irq(struct snd_soc_codec *codec) | ||
2391 | { | ||
2392 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | ||
2393 | int val, reg, report; | ||
2394 | |||
2395 | /* Assume headphone in error conditions; we need to report | ||
2396 | * something or we stall our state machine. | ||
2397 | */ | ||
2398 | report = SND_JACK_HEADPHONE; | ||
2399 | |||
2400 | reg = snd_soc_read(codec, WM8996_HEADPHONE_DETECT_2); | ||
2401 | if (reg < 0) { | ||
2402 | dev_err(codec->dev, "Failed to read HPDET status\n"); | ||
2403 | goto out; | ||
2404 | } | ||
2405 | |||
2406 | if (!(reg & WM8996_HP_DONE)) { | ||
2407 | dev_err(codec->dev, "Got HPDET IRQ but HPDET is busy\n"); | ||
2408 | goto out; | ||
2409 | } | ||
2410 | |||
2411 | val = reg & WM8996_HP_LVL_MASK; | ||
2412 | |||
2413 | dev_dbg(codec->dev, "HPDET measured %d ohms\n", val); | ||
2414 | |||
2415 | /* If we've got high enough impedence then report as line, | ||
2416 | * otherwise assume headphone. | ||
2417 | */ | ||
2418 | if (val >= 126) | ||
2419 | report = SND_JACK_LINEOUT; | ||
2420 | else | ||
2421 | report = SND_JACK_HEADPHONE; | ||
2422 | |||
2423 | out: | ||
2424 | if (wm8996->jack_mic) | ||
2425 | report |= SND_JACK_MICROPHONE; | ||
2426 | |||
2427 | snd_soc_jack_report(wm8996->jack, report, | ||
2428 | SND_JACK_LINEOUT | SND_JACK_HEADSET); | ||
2429 | |||
2430 | wm8996->detecting = false; | ||
2431 | |||
2432 | /* If the output isn't running re-clamp it */ | ||
2433 | if (!(snd_soc_read(codec, WM8996_POWER_MANAGEMENT_1) & | ||
2434 | (WM8996_HPOUT1L_ENA | WM8996_HPOUT1R_RMV_SHORT))) | ||
2435 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, | ||
2436 | WM8996_HPOUT1L_RMV_SHORT | | ||
2437 | WM8996_HPOUT1R_RMV_SHORT, 0); | ||
2438 | |||
2439 | /* Go back to looking at the microphone */ | ||
2440 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, | ||
2441 | WM8996_JD_MODE_MASK, 0); | ||
2442 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, | ||
2443 | WM8996_MICD_ENA); | ||
2444 | |||
2445 | snd_soc_dapm_disable_pin(&codec->dapm, "Bandgap"); | ||
2446 | snd_soc_dapm_sync(&codec->dapm); | ||
2447 | } | ||
2448 | |||
2449 | static void wm8996_hpdet_start(struct snd_soc_codec *codec) | ||
2450 | { | ||
2451 | /* Unclamp the output, we can't measure while we're shorting it */ | ||
2452 | snd_soc_update_bits(codec, WM8996_ANALOGUE_HP_1, | ||
2453 | WM8996_HPOUT1L_RMV_SHORT | | ||
2454 | WM8996_HPOUT1R_RMV_SHORT, | ||
2455 | WM8996_HPOUT1L_RMV_SHORT | | ||
2456 | WM8996_HPOUT1R_RMV_SHORT); | ||
2457 | |||
2458 | /* We need bandgap for HPDET */ | ||
2459 | snd_soc_dapm_force_enable_pin(&codec->dapm, "Bandgap"); | ||
2460 | snd_soc_dapm_sync(&codec->dapm); | ||
2461 | |||
2462 | /* Go into headphone detect left mode */ | ||
2463 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, WM8996_MICD_ENA, 0); | ||
2464 | snd_soc_update_bits(codec, WM8996_ACCESSORY_DETECT_MODE_1, | ||
2465 | WM8996_JD_MODE_MASK, 1); | ||
2466 | |||
2467 | /* Trigger a measurement */ | ||
2468 | snd_soc_update_bits(codec, WM8996_HEADPHONE_DETECT_1, | ||
2469 | WM8996_HP_POLL, WM8996_HP_POLL); | ||
2470 | } | ||
2471 | |||
2306 | static void wm8996_micd(struct snd_soc_codec *codec) | 2472 | static void wm8996_micd(struct snd_soc_codec *codec) |
2307 | { | 2473 | { |
2308 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); | 2474 | struct wm8996_priv *wm8996 = snd_soc_codec_get_drvdata(codec); |
@@ -2323,28 +2489,36 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2323 | wm8996->jack_mic = false; | 2489 | wm8996->jack_mic = false; |
2324 | wm8996->detecting = true; | 2490 | wm8996->detecting = true; |
2325 | snd_soc_jack_report(wm8996->jack, 0, | 2491 | snd_soc_jack_report(wm8996->jack, 0, |
2326 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2492 | SND_JACK_LINEOUT | SND_JACK_HEADSET | |
2493 | SND_JACK_BTN_0); | ||
2494 | |||
2327 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2495 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2328 | WM8996_MICD_RATE_MASK, | 2496 | WM8996_MICD_RATE_MASK, |
2329 | WM8996_MICD_RATE_MASK); | 2497 | WM8996_MICD_RATE_MASK); |
2330 | return; | 2498 | return; |
2331 | } | 2499 | } |
2332 | 2500 | ||
2333 | /* If the measurement is very high we've got a microphone but | 2501 | /* If the measurement is very high we've got a microphone, |
2334 | * do a little debounce to account for mechanical issues. | 2502 | * either we just detected one or if we already reported then |
2503 | * we've got a button release event. | ||
2335 | */ | 2504 | */ |
2336 | if (val & 0x400) { | 2505 | if (val & 0x400) { |
2337 | dev_dbg(codec->dev, "Microphone detected\n"); | 2506 | if (wm8996->detecting) { |
2338 | snd_soc_jack_report(wm8996->jack, SND_JACK_HEADSET, | 2507 | dev_dbg(codec->dev, "Microphone detected\n"); |
2339 | SND_JACK_HEADSET | SND_JACK_BTN_0); | 2508 | wm8996->jack_mic = true; |
2340 | wm8996->jack_mic = true; | 2509 | wm8996_hpdet_start(codec); |
2341 | wm8996->detecting = false; | 2510 | |
2342 | 2511 | /* Increase poll rate to give better responsiveness | |
2343 | /* Increase poll rate to give better responsiveness | 2512 | * for buttons */ |
2344 | * for buttons */ | 2513 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2345 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2514 | WM8996_MICD_RATE_MASK, |
2346 | WM8996_MICD_RATE_MASK, | 2515 | 5 << WM8996_MICD_RATE_SHIFT); |
2347 | 5 << WM8996_MICD_RATE_SHIFT); | 2516 | } else { |
2517 | dev_dbg(codec->dev, "Mic button up\n"); | ||
2518 | snd_soc_jack_report(wm8996->jack, 0, SND_JACK_BTN_0); | ||
2519 | } | ||
2520 | |||
2521 | return; | ||
2348 | } | 2522 | } |
2349 | 2523 | ||
2350 | /* If we detected a lower impedence during initial startup | 2524 | /* If we detected a lower impedence during initial startup |
@@ -2376,15 +2550,11 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2376 | if (val & 0x3fc) { | 2550 | if (val & 0x3fc) { |
2377 | if (wm8996->jack_mic) { | 2551 | if (wm8996->jack_mic) { |
2378 | dev_dbg(codec->dev, "Mic button detected\n"); | 2552 | dev_dbg(codec->dev, "Mic button detected\n"); |
2379 | snd_soc_jack_report(wm8996->jack, | 2553 | snd_soc_jack_report(wm8996->jack, SND_JACK_BTN_0, |
2380 | SND_JACK_HEADSET | SND_JACK_BTN_0, | ||
2381 | SND_JACK_HEADSET | SND_JACK_BTN_0); | ||
2382 | } else { | ||
2383 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2384 | snd_soc_jack_report(wm8996->jack, | ||
2385 | SND_JACK_HEADPHONE, | ||
2386 | SND_JACK_HEADSET | | ||
2387 | SND_JACK_BTN_0); | 2554 | SND_JACK_BTN_0); |
2555 | } else if (wm8996->detecting) { | ||
2556 | dev_dbg(codec->dev, "Headphone detected\n"); | ||
2557 | wm8996_hpdet_start(codec); | ||
2388 | 2558 | ||
2389 | /* Increase the detection rate a bit for | 2559 | /* Increase the detection rate a bit for |
2390 | * responsiveness. | 2560 | * responsiveness. |
@@ -2392,8 +2562,6 @@ static void wm8996_micd(struct snd_soc_codec *codec) | |||
2392 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, | 2562 | snd_soc_update_bits(codec, WM8996_MIC_DETECT_1, |
2393 | WM8996_MICD_RATE_MASK, | 2563 | WM8996_MICD_RATE_MASK, |
2394 | 7 << WM8996_MICD_RATE_SHIFT); | 2564 | 7 << WM8996_MICD_RATE_SHIFT); |
2395 | |||
2396 | wm8996->detecting = false; | ||
2397 | } | 2565 | } |
2398 | } | 2566 | } |
2399 | } | 2567 | } |
@@ -2412,6 +2580,9 @@ static irqreturn_t wm8996_irq(int irq, void *data) | |||
2412 | } | 2580 | } |
2413 | irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); | 2581 | irq_val &= ~snd_soc_read(codec, WM8996_INTERRUPT_STATUS_2_MASK); |
2414 | 2582 | ||
2583 | if (!irq_val) | ||
2584 | return IRQ_NONE; | ||
2585 | |||
2415 | snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); | 2586 | snd_soc_write(codec, WM8996_INTERRUPT_STATUS_2, irq_val); |
2416 | 2587 | ||
2417 | if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { | 2588 | if (irq_val & (WM8996_DCS_DONE_01_EINT | WM8996_DCS_DONE_23_EINT)) { |
@@ -2430,10 +2601,10 @@ static irqreturn_t wm8996_irq(int irq, void *data) | |||
2430 | if (irq_val & WM8996_MICD_EINT) | 2601 | if (irq_val & WM8996_MICD_EINT) |
2431 | wm8996_micd(codec); | 2602 | wm8996_micd(codec); |
2432 | 2603 | ||
2433 | if (irq_val) | 2604 | if (irq_val & WM8996_HP_DONE_EINT) |
2434 | return IRQ_HANDLED; | 2605 | wm8996_hpdet_irq(codec); |
2435 | else | 2606 | |
2436 | return IRQ_NONE; | 2607 | return IRQ_HANDLED; |
2437 | } | 2608 | } |
2438 | 2609 | ||
2439 | static irqreturn_t wm8996_edge_irq(int irq, void *data) | 2610 | static irqreturn_t wm8996_edge_irq(int irq, void *data) |
@@ -2548,7 +2719,13 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2548 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; | 2719 | wm8996->disable_nb[0].notifier_call = wm8996_regulator_event_0; |
2549 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; | 2720 | wm8996->disable_nb[1].notifier_call = wm8996_regulator_event_1; |
2550 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; | 2721 | wm8996->disable_nb[2].notifier_call = wm8996_regulator_event_2; |
2551 | wm8996->disable_nb[3].notifier_call = wm8996_regulator_event_3; | 2722 | |
2723 | wm8996->cpvdd = regulator_get(&i2c->dev, "CPVDD"); | ||
2724 | if (IS_ERR(wm8996->cpvdd)) { | ||
2725 | ret = PTR_ERR(wm8996->cpvdd); | ||
2726 | dev_err(&i2c->dev, "Failed to get CPVDD: %d\n", ret); | ||
2727 | goto err_get; | ||
2728 | } | ||
2552 | 2729 | ||
2553 | /* This should really be moved into the regulator core */ | 2730 | /* This should really be moved into the regulator core */ |
2554 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { | 2731 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) { |
@@ -2565,7 +2742,7 @@ static int wm8996_probe(struct snd_soc_codec *codec) | |||
2565 | wm8996->supplies); | 2742 | wm8996->supplies); |
2566 | if (ret != 0) { | 2743 | if (ret != 0) { |
2567 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); | 2744 | dev_err(codec->dev, "Failed to enable supplies: %d\n", ret); |
2568 | goto err_get; | 2745 | goto err_cpvdd; |
2569 | } | 2746 | } |
2570 | 2747 | ||
2571 | if (wm8996->pdata.ldo_ena >= 0) { | 2748 | if (wm8996->pdata.ldo_ena >= 0) { |
@@ -2808,6 +2985,8 @@ err_enable: | |||
2808 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); | 2985 | gpio_set_value_cansleep(wm8996->pdata.ldo_ena, 0); |
2809 | 2986 | ||
2810 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2987 | regulator_bulk_disable(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2988 | err_cpvdd: | ||
2989 | regulator_put(wm8996->cpvdd); | ||
2811 | err_get: | 2990 | err_get: |
2812 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 2991 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2813 | err: | 2992 | err: |
@@ -2831,6 +3010,7 @@ static int wm8996_remove(struct snd_soc_codec *codec) | |||
2831 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) | 3010 | for (i = 0; i < ARRAY_SIZE(wm8996->supplies); i++) |
2832 | regulator_unregister_notifier(wm8996->supplies[i].consumer, | 3011 | regulator_unregister_notifier(wm8996->supplies[i].consumer, |
2833 | &wm8996->disable_nb[i]); | 3012 | &wm8996->disable_nb[i]); |
3013 | regulator_put(wm8996->cpvdd); | ||
2834 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); | 3014 | regulator_bulk_free(ARRAY_SIZE(wm8996->supplies), wm8996->supplies); |
2835 | 3015 | ||
2836 | return 0; | 3016 | return 0; |
diff --git a/sound/soc/codecs/wm9081.c b/sound/soc/codecs/wm9081.c index a4691321f9b3..f32ab1ee9647 100644 --- a/sound/soc/codecs/wm9081.c +++ b/sound/soc/codecs/wm9081.c | |||
@@ -1120,8 +1120,8 @@ static int wm9081_digital_mute(struct snd_soc_dai *codec_dai, int mute) | |||
1120 | return 0; | 1120 | return 0; |
1121 | } | 1121 | } |
1122 | 1122 | ||
1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, | 1123 | static int wm9081_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
1124 | int clk_id, unsigned int freq, int dir) | 1124 | int source, unsigned int freq, int dir) |
1125 | { | 1125 | { |
1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); | 1126 | struct wm9081_priv *wm9081 = snd_soc_codec_get_drvdata(codec); |
1127 | 1127 | ||
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 4de12203e611..f2f3077928da 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -139,7 +139,6 @@ static const u16 wm9090_reg_defaults[] = { | |||
139 | 139 | ||
140 | /* This struct is used to save the context */ | 140 | /* This struct is used to save the context */ |
141 | struct wm9090_priv { | 141 | struct wm9090_priv { |
142 | struct mutex mutex; | ||
143 | struct wm9090_platform_data pdata; | 142 | struct wm9090_platform_data pdata; |
144 | void *control_data; | 143 | void *control_data; |
145 | }; | 144 | }; |
@@ -663,7 +662,6 @@ static int wm9090_i2c_probe(struct i2c_client *i2c, | |||
663 | 662 | ||
664 | i2c_set_clientdata(i2c, wm9090); | 663 | i2c_set_clientdata(i2c, wm9090); |
665 | wm9090->control_data = i2c; | 664 | wm9090->control_data = i2c; |
666 | mutex_init(&wm9090->mutex); | ||
667 | 665 | ||
668 | ret = snd_soc_register_codec(&i2c->dev, | 666 | ret = snd_soc_register_codec(&i2c->dev, |
669 | &soc_codec_dev_wm9090, NULL, 0); | 667 | &soc_codec_dev_wm9090, NULL, 0); |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index e763c54c55dc..ca8ce03510f4 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -18,6 +18,7 @@ | |||
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/mfd/wm8994/registers.h> | ||
21 | #include <sound/core.h> | 22 | #include <sound/core.h> |
22 | #include <sound/pcm.h> | 23 | #include <sound/pcm.h> |
23 | #include <sound/pcm_params.h> | 24 | #include <sound/pcm_params.h> |
@@ -116,14 +117,23 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
116 | { | 117 | { |
117 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 118 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
118 | s8 offset; | 119 | s8 offset; |
119 | u16 reg, reg_l, reg_r, dcs_cfg; | 120 | u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; |
121 | |||
122 | switch (hubs->dcs_readback_mode) { | ||
123 | case 2: | ||
124 | dcs_reg = WM8994_DC_SERVO_4E; | ||
125 | break; | ||
126 | default: | ||
127 | dcs_reg = WM8993_DC_SERVO_3; | ||
128 | break; | ||
129 | } | ||
120 | 130 | ||
121 | /* If we're using a digital only path and have a previously | 131 | /* If we're using a digital only path and have a previously |
122 | * callibrated DC servo offset stored then use that. */ | 132 | * callibrated DC servo offset stored then use that. */ |
123 | if (hubs->class_w && hubs->class_w_dcs) { | 133 | if (hubs->class_w && hubs->class_w_dcs) { |
124 | dev_dbg(codec->dev, "Using cached DC servo offset %x\n", | 134 | dev_dbg(codec->dev, "Using cached DC servo offset %x\n", |
125 | hubs->class_w_dcs); | 135 | hubs->class_w_dcs); |
126 | snd_soc_write(codec, WM8993_DC_SERVO_3, hubs->class_w_dcs); | 136 | snd_soc_write(codec, dcs_reg, hubs->class_w_dcs); |
127 | wait_for_dc_servo(codec, | 137 | wait_for_dc_servo(codec, |
128 | WM8993_DCS_TRIG_DAC_WR_0 | | 138 | WM8993_DCS_TRIG_DAC_WR_0 | |
129 | WM8993_DCS_TRIG_DAC_WR_1); | 139 | WM8993_DCS_TRIG_DAC_WR_1); |
@@ -154,8 +164,9 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
154 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | 164 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) |
155 | & WM8993_DCS_INTEG_CHAN_1_MASK; | 165 | & WM8993_DCS_INTEG_CHAN_1_MASK; |
156 | break; | 166 | break; |
167 | case 2: | ||
157 | case 1: | 168 | case 1: |
158 | reg = snd_soc_read(codec, WM8993_DC_SERVO_3); | 169 | reg = snd_soc_read(codec, dcs_reg); |
159 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | 170 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) |
160 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 171 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
161 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | 172 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; |
@@ -168,24 +179,25 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
168 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 179 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
169 | 180 | ||
170 | /* Apply correction to DC servo result */ | 181 | /* Apply correction to DC servo result */ |
171 | if (hubs->dcs_codes) { | 182 | if (hubs->dcs_codes_l || hubs->dcs_codes_r) { |
172 | dev_dbg(codec->dev, "Applying %d code DC servo correction\n", | 183 | dev_dbg(codec->dev, |
173 | hubs->dcs_codes); | 184 | "Applying %d/%d code DC servo correction\n", |
185 | hubs->dcs_codes_l, hubs->dcs_codes_r); | ||
174 | 186 | ||
175 | /* HPOUT1R */ | 187 | /* HPOUT1R */ |
176 | offset = reg_r; | 188 | offset = reg_r; |
177 | offset += hubs->dcs_codes; | 189 | offset += hubs->dcs_codes_r; |
178 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 190 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
179 | 191 | ||
180 | /* HPOUT1L */ | 192 | /* HPOUT1L */ |
181 | offset = reg_l; | 193 | offset = reg_l; |
182 | offset += hubs->dcs_codes; | 194 | offset += hubs->dcs_codes_l; |
183 | dcs_cfg |= (u8)offset; | 195 | dcs_cfg |= (u8)offset; |
184 | 196 | ||
185 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); | 197 | dev_dbg(codec->dev, "DCS result: %x\n", dcs_cfg); |
186 | 198 | ||
187 | /* Do it */ | 199 | /* Do it */ |
188 | snd_soc_write(codec, WM8993_DC_SERVO_3, dcs_cfg); | 200 | snd_soc_write(codec, dcs_reg, dcs_cfg); |
189 | wait_for_dc_servo(codec, | 201 | wait_for_dc_servo(codec, |
190 | WM8993_DCS_TRIG_DAC_WR_0 | | 202 | WM8993_DCS_TRIG_DAC_WR_0 | |
191 | WM8993_DCS_TRIG_DAC_WR_1); | 203 | WM8993_DCS_TRIG_DAC_WR_1); |
@@ -217,7 +229,7 @@ static int wm8993_put_dc_servo(struct snd_kcontrol *kcontrol, | |||
217 | 229 | ||
218 | /* If we're applying an offset correction then updating the | 230 | /* If we're applying an offset correction then updating the |
219 | * callibration would be likely to introduce further offsets. */ | 231 | * callibration would be likely to introduce further offsets. */ |
220 | if (hubs->dcs_codes || hubs->no_series_update) | 232 | if (hubs->dcs_codes_l || hubs->dcs_codes_r || hubs->no_series_update) |
221 | return ret; | 233 | return ret; |
222 | 234 | ||
223 | /* Only need to do this if the outputs are active */ | 235 | /* Only need to do this if the outputs are active */ |
@@ -699,6 +711,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
699 | { "IN1L PGA", "IN1LP Switch", "IN1LP" }, | 711 | { "IN1L PGA", "IN1LP Switch", "IN1LP" }, |
700 | { "IN1L PGA", "IN1LN Switch", "IN1LN" }, | 712 | { "IN1L PGA", "IN1LN Switch", "IN1LN" }, |
701 | 713 | ||
714 | { "IN1L PGA", NULL, "VMID" }, | ||
715 | { "IN1R PGA", NULL, "VMID" }, | ||
716 | { "IN2L PGA", NULL, "VMID" }, | ||
717 | { "IN2R PGA", NULL, "VMID" }, | ||
718 | |||
702 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, | 719 | { "IN1R PGA", "IN1RP Switch", "IN1RP" }, |
703 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, | 720 | { "IN1R PGA", "IN1RN Switch", "IN1RN" }, |
704 | 721 | ||
@@ -716,12 +733,14 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
716 | { "MIXINL", NULL, "Direct Voice" }, | 733 | { "MIXINL", NULL, "Direct Voice" }, |
717 | { "MIXINL", NULL, "IN1LP" }, | 734 | { "MIXINL", NULL, "IN1LP" }, |
718 | { "MIXINL", NULL, "Left Output Mixer" }, | 735 | { "MIXINL", NULL, "Left Output Mixer" }, |
736 | { "MIXINL", NULL, "VMID" }, | ||
719 | 737 | ||
720 | { "MIXINR", "IN1R Switch", "IN1R PGA" }, | 738 | { "MIXINR", "IN1R Switch", "IN1R PGA" }, |
721 | { "MIXINR", "IN2R Switch", "IN2R PGA" }, | 739 | { "MIXINR", "IN2R Switch", "IN2R PGA" }, |
722 | { "MIXINR", NULL, "Direct Voice" }, | 740 | { "MIXINR", NULL, "Direct Voice" }, |
723 | { "MIXINR", NULL, "IN1RP" }, | 741 | { "MIXINR", NULL, "IN1RP" }, |
724 | { "MIXINR", NULL, "Right Output Mixer" }, | 742 | { "MIXINR", NULL, "Right Output Mixer" }, |
743 | { "MIXINR", NULL, "VMID" }, | ||
725 | 744 | ||
726 | { "ADCL", NULL, "MIXINL" }, | 745 | { "ADCL", NULL, "MIXINL" }, |
727 | { "ADCR", NULL, "MIXINR" }, | 746 | { "ADCR", NULL, "MIXINR" }, |
@@ -752,6 +771,7 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
752 | { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, | 771 | { "Earpiece Mixer", "Left Output Switch", "Left Output PGA" }, |
753 | { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, | 772 | { "Earpiece Mixer", "Right Output Switch", "Right Output PGA" }, |
754 | 773 | ||
774 | { "Earpiece Driver", NULL, "VMID" }, | ||
755 | { "Earpiece Driver", NULL, "Earpiece Mixer" }, | 775 | { "Earpiece Driver", NULL, "Earpiece Mixer" }, |
756 | { "HPOUT2N", NULL, "Earpiece Driver" }, | 776 | { "HPOUT2N", NULL, "Earpiece Driver" }, |
757 | { "HPOUT2P", NULL, "Earpiece Driver" }, | 777 | { "HPOUT2P", NULL, "Earpiece Driver" }, |
@@ -774,9 +794,11 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
774 | { "SPKR Boost", "SPKR Switch", "SPKR" }, | 794 | { "SPKR Boost", "SPKR Switch", "SPKR" }, |
775 | { "SPKR Boost", "SPKL Switch", "SPKL" }, | 795 | { "SPKR Boost", "SPKL Switch", "SPKL" }, |
776 | 796 | ||
797 | { "SPKL Driver", NULL, "VMID" }, | ||
777 | { "SPKL Driver", NULL, "SPKL Boost" }, | 798 | { "SPKL Driver", NULL, "SPKL Boost" }, |
778 | { "SPKL Driver", NULL, "CLK_SYS" }, | 799 | { "SPKL Driver", NULL, "CLK_SYS" }, |
779 | 800 | ||
801 | { "SPKR Driver", NULL, "VMID" }, | ||
780 | { "SPKR Driver", NULL, "SPKR Boost" }, | 802 | { "SPKR Driver", NULL, "SPKR Boost" }, |
781 | { "SPKR Driver", NULL, "CLK_SYS" }, | 803 | { "SPKR Driver", NULL, "CLK_SYS" }, |
782 | 804 | ||
@@ -790,12 +812,18 @@ static const struct snd_soc_dapm_route analogue_routes[] = { | |||
790 | 812 | ||
791 | { "Headphone PGA", NULL, "Left Headphone Mux" }, | 813 | { "Headphone PGA", NULL, "Left Headphone Mux" }, |
792 | { "Headphone PGA", NULL, "Right Headphone Mux" }, | 814 | { "Headphone PGA", NULL, "Right Headphone Mux" }, |
815 | { "Headphone PGA", NULL, "VMID" }, | ||
793 | { "Headphone PGA", NULL, "CLK_SYS" }, | 816 | { "Headphone PGA", NULL, "CLK_SYS" }, |
794 | { "Headphone PGA", NULL, "Headphone Supply" }, | 817 | { "Headphone PGA", NULL, "Headphone Supply" }, |
795 | 818 | ||
796 | { "HPOUT1L", NULL, "Headphone PGA" }, | 819 | { "HPOUT1L", NULL, "Headphone PGA" }, |
797 | { "HPOUT1R", NULL, "Headphone PGA" }, | 820 | { "HPOUT1R", NULL, "Headphone PGA" }, |
798 | 821 | ||
822 | { "LINEOUT1N Driver", NULL, "VMID" }, | ||
823 | { "LINEOUT1P Driver", NULL, "VMID" }, | ||
824 | { "LINEOUT2N Driver", NULL, "VMID" }, | ||
825 | { "LINEOUT2P Driver", NULL, "VMID" }, | ||
826 | |||
799 | { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, | 827 | { "LINEOUT1N", NULL, "LINEOUT1N Driver" }, |
800 | { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, | 828 | { "LINEOUT1P", NULL, "LINEOUT1P Driver" }, |
801 | { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, | 829 | { "LINEOUT2N", NULL, "LINEOUT2N Driver" }, |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index 676b1252ab91..c674c7a502a6 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -23,7 +23,8 @@ extern const unsigned int wm_hubs_spkmix_tlv[]; | |||
23 | 23 | ||
24 | /* This *must* be the first element of the codec->private_data struct */ | 24 | /* This *must* be the first element of the codec->private_data struct */ |
25 | struct wm_hubs_data { | 25 | struct wm_hubs_data { |
26 | int dcs_codes; | 26 | int dcs_codes_l; |
27 | int dcs_codes_r; | ||
27 | int dcs_readback_mode; | 28 | int dcs_readback_mode; |
28 | int hp_startup_mode; | 29 | int hp_startup_mode; |
29 | int series_startup; | 30 | int series_startup; |