diff options
Diffstat (limited to 'sound/soc')
85 files changed, 2856 insertions, 766 deletions
diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index c5de0a84566f..5da8ca7aee05 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig | |||
@@ -9,6 +9,7 @@ menuconfig SND_SOC | |||
9 | select SND_JACK if INPUT=y || INPUT=SND | 9 | select SND_JACK if INPUT=y || INPUT=SND |
10 | select REGMAP_I2C if I2C | 10 | select REGMAP_I2C if I2C |
11 | select REGMAP_SPI if SPI_MASTER | 11 | select REGMAP_SPI if SPI_MASTER |
12 | select SND_COMPRESS_OFFLOAD | ||
12 | ---help--- | 13 | ---help--- |
13 | 14 | ||
14 | If you want ASoC support, you should say Y here and also to the | 15 | If you want ASoC support, you should say Y here and also to the |
@@ -32,9 +33,9 @@ config SND_SOC_DMAENGINE_PCM | |||
32 | source "sound/soc/atmel/Kconfig" | 33 | source "sound/soc/atmel/Kconfig" |
33 | source "sound/soc/au1x/Kconfig" | 34 | source "sound/soc/au1x/Kconfig" |
34 | source "sound/soc/blackfin/Kconfig" | 35 | source "sound/soc/blackfin/Kconfig" |
36 | source "sound/soc/cirrus/Kconfig" | ||
35 | source "sound/soc/davinci/Kconfig" | 37 | source "sound/soc/davinci/Kconfig" |
36 | source "sound/soc/dwc/Kconfig" | 38 | source "sound/soc/dwc/Kconfig" |
37 | source "sound/soc/ep93xx/Kconfig" | ||
38 | source "sound/soc/fsl/Kconfig" | 39 | source "sound/soc/fsl/Kconfig" |
39 | source "sound/soc/jz4740/Kconfig" | 40 | source "sound/soc/jz4740/Kconfig" |
40 | source "sound/soc/nuc900/Kconfig" | 41 | source "sound/soc/nuc900/Kconfig" |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 00a555a743b6..bcbf1d00aa85 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -1,5 +1,5 @@ | |||
1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o | 1 | snd-soc-core-objs := soc-core.o soc-dapm.o soc-jack.o soc-cache.o soc-utils.o |
2 | snd-soc-core-objs += soc-pcm.o soc-io.o | 2 | snd-soc-core-objs += soc-pcm.o soc-compress.o soc-io.o |
3 | 3 | ||
4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o | 4 | snd-soc-dmaengine-pcm-objs := soc-dmaengine-pcm.o |
5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o | 5 | obj-$(CONFIG_SND_SOC_DMAENGINE_PCM) += snd-soc-dmaengine-pcm.o |
@@ -10,9 +10,9 @@ obj-$(CONFIG_SND_SOC) += generic/ | |||
10 | obj-$(CONFIG_SND_SOC) += atmel/ | 10 | obj-$(CONFIG_SND_SOC) += atmel/ |
11 | obj-$(CONFIG_SND_SOC) += au1x/ | 11 | obj-$(CONFIG_SND_SOC) += au1x/ |
12 | obj-$(CONFIG_SND_SOC) += blackfin/ | 12 | obj-$(CONFIG_SND_SOC) += blackfin/ |
13 | obj-$(CONFIG_SND_SOC) += cirrus/ | ||
13 | obj-$(CONFIG_SND_SOC) += davinci/ | 14 | obj-$(CONFIG_SND_SOC) += davinci/ |
14 | obj-$(CONFIG_SND_SOC) += dwc/ | 15 | obj-$(CONFIG_SND_SOC) += dwc/ |
15 | obj-$(CONFIG_SND_SOC) += ep93xx/ | ||
16 | obj-$(CONFIG_SND_SOC) += fsl/ | 16 | obj-$(CONFIG_SND_SOC) += fsl/ |
17 | obj-$(CONFIG_SND_SOC) += jz4740/ | 17 | obj-$(CONFIG_SND_SOC) += jz4740/ |
18 | obj-$(CONFIG_SND_SOC) += mid-x86/ | 18 | obj-$(CONFIG_SND_SOC) += mid-x86/ |
diff --git a/sound/soc/blackfin/bf5xx-ad1836.c b/sound/soc/blackfin/bf5xx-ad1836.c index d542d4063771..16b9c9efd19a 100644 --- a/sound/soc/blackfin/bf5xx-ad1836.c +++ b/sound/soc/blackfin/bf5xx-ad1836.c | |||
@@ -59,62 +59,63 @@ static struct snd_soc_ops bf5xx_ad1836_ops = { | |||
59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ | 59 | #define BF5XX_AD1836_DAIFMT (SND_SOC_DAIFMT_DSP_A | SND_SOC_DAIFMT_IB_IF | \ |
60 | SND_SOC_DAIFMT_CBM_CFM) | 60 | SND_SOC_DAIFMT_CBM_CFM) |
61 | 61 | ||
62 | static struct snd_soc_dai_link bf5xx_ad1836_dai[] = { | 62 | static struct snd_soc_dai_link bf5xx_ad1836_dai = { |
63 | { | 63 | .name = "ad1836", |
64 | .name = "ad1836", | 64 | .stream_name = "AD1836", |
65 | .stream_name = "AD1836", | 65 | .codec_dai_name = "ad1836-hifi", |
66 | .cpu_dai_name = "bfin-tdm.0", | 66 | .platform_name = "bfin-tdm-pcm-audio", |
67 | .codec_dai_name = "ad1836-hifi", | 67 | .ops = &bf5xx_ad1836_ops, |
68 | .platform_name = "bfin-tdm-pcm-audio", | 68 | .dai_fmt = BF5XX_AD1836_DAIFMT, |
69 | .codec_name = "spi0.4", | ||
70 | .ops = &bf5xx_ad1836_ops, | ||
71 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
72 | }, | ||
73 | { | ||
74 | .name = "ad1836", | ||
75 | .stream_name = "AD1836", | ||
76 | .cpu_dai_name = "bfin-tdm.1", | ||
77 | .codec_dai_name = "ad1836-hifi", | ||
78 | .platform_name = "bfin-tdm-pcm-audio", | ||
79 | .codec_name = "spi0.4", | ||
80 | .ops = &bf5xx_ad1836_ops, | ||
81 | .dai_fmt = BF5XX_AD1836_DAIFMT, | ||
82 | }, | ||
83 | }; | 69 | }; |
84 | 70 | ||
85 | static struct snd_soc_card bf5xx_ad1836 = { | 71 | static struct snd_soc_card bf5xx_ad1836 = { |
86 | .name = "bfin-ad1836", | 72 | .name = "bfin-ad1836", |
87 | .owner = THIS_MODULE, | 73 | .owner = THIS_MODULE, |
88 | .dai_link = &bf5xx_ad1836_dai[CONFIG_SND_BF5XX_SPORT_NUM], | 74 | .dai_link = &bf5xx_ad1836_dai, |
89 | .num_links = 1, | 75 | .num_links = 1, |
90 | }; | 76 | }; |
91 | 77 | ||
92 | static struct platform_device *bfxx_ad1836_snd_device; | 78 | static __devinit int bf5xx_ad1836_driver_probe(struct platform_device *pdev) |
93 | |||
94 | static int __init bf5xx_ad1836_init(void) | ||
95 | { | 79 | { |
80 | struct snd_soc_card *card = &bf5xx_ad1836; | ||
81 | const char **link_name; | ||
96 | int ret; | 82 | int ret; |
97 | 83 | ||
98 | bfxx_ad1836_snd_device = platform_device_alloc("soc-audio", -1); | 84 | link_name = pdev->dev.platform_data; |
99 | if (!bfxx_ad1836_snd_device) | 85 | if (!link_name) { |
100 | return -ENOMEM; | 86 | dev_err(&pdev->dev, "No platform data supplied\n"); |
87 | return -EINVAL; | ||
88 | } | ||
89 | bf5xx_ad1836_dai.cpu_dai_name = link_name[0]; | ||
90 | bf5xx_ad1836_dai.codec_name = link_name[1]; | ||
101 | 91 | ||
102 | platform_set_drvdata(bfxx_ad1836_snd_device, &bf5xx_ad1836); | 92 | card->dev = &pdev->dev; |
103 | ret = platform_device_add(bfxx_ad1836_snd_device); | 93 | platform_set_drvdata(pdev, card); |
104 | 94 | ||
95 | ret = snd_soc_register_card(card); | ||
105 | if (ret) | 96 | if (ret) |
106 | platform_device_put(bfxx_ad1836_snd_device); | 97 | dev_err(&pdev->dev, "Failed to register card\n"); |
107 | |||
108 | return ret; | 98 | return ret; |
109 | } | 99 | } |
110 | 100 | ||
111 | static void __exit bf5xx_ad1836_exit(void) | 101 | static int __devexit bf5xx_ad1836_driver_remove(struct platform_device *pdev) |
112 | { | 102 | { |
113 | platform_device_unregister(bfxx_ad1836_snd_device); | 103 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
104 | |||
105 | snd_soc_unregister_card(card); | ||
106 | return 0; | ||
114 | } | 107 | } |
115 | 108 | ||
116 | module_init(bf5xx_ad1836_init); | 109 | static struct platform_driver bf5xx_ad1836_driver = { |
117 | module_exit(bf5xx_ad1836_exit); | 110 | .driver = { |
111 | .name = "bfin-snd-ad1836", | ||
112 | .owner = THIS_MODULE, | ||
113 | .pm = &snd_soc_pm_ops, | ||
114 | }, | ||
115 | .probe = bf5xx_ad1836_driver_probe, | ||
116 | .remove = __devexit_p(bf5xx_ad1836_driver_remove), | ||
117 | }; | ||
118 | module_platform_driver(bf5xx_ad1836_driver); | ||
118 | 119 | ||
119 | /* Module information */ | 120 | /* Module information */ |
120 | MODULE_AUTHOR("Barry Song"); | 121 | MODULE_AUTHOR("Barry Song"); |
diff --git a/sound/soc/ep93xx/Kconfig b/sound/soc/cirrus/Kconfig index 88143db7e753..88143db7e753 100644 --- a/sound/soc/ep93xx/Kconfig +++ b/sound/soc/cirrus/Kconfig | |||
diff --git a/sound/soc/ep93xx/Makefile b/sound/soc/cirrus/Makefile index 5514146cbdf0..5514146cbdf0 100644 --- a/sound/soc/ep93xx/Makefile +++ b/sound/soc/cirrus/Makefile | |||
diff --git a/sound/soc/ep93xx/edb93xx.c b/sound/soc/cirrus/edb93xx.c index e01cb02abd3a..e01cb02abd3a 100644 --- a/sound/soc/ep93xx/edb93xx.c +++ b/sound/soc/cirrus/edb93xx.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index bdffab33e160..bdffab33e160 100644 --- a/sound/soc/ep93xx/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-i2s.c b/sound/soc/cirrus/ep93xx-i2s.c index 8df8f6dc474f..8df8f6dc474f 100644 --- a/sound/soc/ep93xx/ep93xx-i2s.c +++ b/sound/soc/cirrus/ep93xx-i2s.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.c b/sound/soc/cirrus/ep93xx-pcm.c index 4eea98b42bc8..4eea98b42bc8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.c +++ b/sound/soc/cirrus/ep93xx-pcm.c | |||
diff --git a/sound/soc/ep93xx/ep93xx-pcm.h b/sound/soc/cirrus/ep93xx-pcm.h index 111e1121ecb8..111e1121ecb8 100644 --- a/sound/soc/ep93xx/ep93xx-pcm.h +++ b/sound/soc/cirrus/ep93xx-pcm.h | |||
diff --git a/sound/soc/ep93xx/simone.c b/sound/soc/cirrus/simone.c index dd997094eb30..dd997094eb30 100644 --- a/sound/soc/ep93xx/simone.c +++ b/sound/soc/cirrus/simone.c | |||
diff --git a/sound/soc/ep93xx/snappercl15.c b/sound/soc/cirrus/snappercl15.c index a193cea3cf3c..a193cea3cf3c 100644 --- a/sound/soc/ep93xx/snappercl15.c +++ b/sound/soc/cirrus/snappercl15.c | |||
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 9f8e8594aeb9..3684255e5fba 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -70,6 +70,7 @@ config SND_SOC_ALL_CODECS | |||
70 | select SND_SOC_UDA134X | 70 | select SND_SOC_UDA134X |
71 | select SND_SOC_UDA1380 if I2C | 71 | select SND_SOC_UDA1380 if I2C |
72 | select SND_SOC_WL1273 if MFD_WL1273_CORE | 72 | select SND_SOC_WL1273 if MFD_WL1273_CORE |
73 | select SND_SOC_WM0010 if SPI_MASTER | ||
73 | select SND_SOC_WM1250_EV1 if I2C | 74 | select SND_SOC_WM1250_EV1 if I2C |
74 | select SND_SOC_WM2000 if I2C | 75 | select SND_SOC_WM2000 if I2C |
75 | select SND_SOC_WM2200 if I2C | 76 | select SND_SOC_WM2200 if I2C |
@@ -326,6 +327,9 @@ config SND_SOC_UDA1380 | |||
326 | config SND_SOC_WL1273 | 327 | config SND_SOC_WL1273 |
327 | tristate | 328 | tristate |
328 | 329 | ||
330 | config SND_SOC_WM0010 | ||
331 | tristate | ||
332 | |||
329 | config SND_SOC_WM1250_EV1 | 333 | config SND_SOC_WM1250_EV1 |
330 | tristate | 334 | tristate |
331 | 335 | ||
diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 34148bb59c68..ca508b251df7 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile | |||
@@ -61,6 +61,7 @@ snd-soc-twl6040-objs := twl6040.o | |||
61 | snd-soc-uda134x-objs := uda134x.o | 61 | snd-soc-uda134x-objs := uda134x.o |
62 | snd-soc-uda1380-objs := uda1380.o | 62 | snd-soc-uda1380-objs := uda1380.o |
63 | snd-soc-wl1273-objs := wl1273.o | 63 | snd-soc-wl1273-objs := wl1273.o |
64 | snd-soc-wm0010-objs := wm0010.o | ||
64 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o | 65 | snd-soc-wm1250-ev1-objs := wm1250-ev1.o |
65 | snd-soc-wm2000-objs := wm2000.o | 66 | snd-soc-wm2000-objs := wm2000.o |
66 | snd-soc-wm2200-objs := wm2200.o | 67 | snd-soc-wm2200-objs := wm2200.o |
@@ -177,6 +178,7 @@ obj-$(CONFIG_SND_SOC_TWL6040) += snd-soc-twl6040.o | |||
177 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o | 178 | obj-$(CONFIG_SND_SOC_UDA134X) += snd-soc-uda134x.o |
178 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o | 179 | obj-$(CONFIG_SND_SOC_UDA1380) += snd-soc-uda1380.o |
179 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o | 180 | obj-$(CONFIG_SND_SOC_WL1273) += snd-soc-wl1273.o |
181 | obj-$(CONFIG_SND_SOC_WM0010) += snd-soc-wm0010.o | ||
180 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o | 182 | obj-$(CONFIG_SND_SOC_WM1250_EV1) += snd-soc-wm1250-ev1.o |
181 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o | 183 | obj-$(CONFIG_SND_SOC_WM2000) += snd-soc-wm2000.o |
182 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o | 184 | obj-$(CONFIG_SND_SOC_WM2200) += snd-soc-wm2200.o |
diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index 23b40186f9b8..b7836503dc69 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c | |||
@@ -2404,12 +2404,12 @@ static int ab8500_codec_probe(struct snd_soc_codec *codec) | |||
2404 | 2404 | ||
2405 | dev_dbg(dev, "%s: Enter.\n", __func__); | 2405 | dev_dbg(dev, "%s: Enter.\n", __func__); |
2406 | 2406 | ||
2407 | /* Setup AB8500 according to board-settings */ | ||
2408 | pdata = (struct ab8500_platform_data *)dev_get_platdata(dev->parent); | ||
2409 | |||
2410 | /* Inform SoC Core that we have our own I/O arrangements. */ | 2407 | /* Inform SoC Core that we have our own I/O arrangements. */ |
2411 | codec->control_data = (void *)true; | 2408 | codec->control_data = (void *)true; |
2412 | 2409 | ||
2410 | /* Setup AB8500 according to board-settings */ | ||
2411 | pdata = dev_get_platdata(dev->parent); | ||
2412 | |||
2413 | status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); | 2413 | status = ab8500_audio_setup_mics(codec, &pdata->codec->amics); |
2414 | if (status < 0) { | 2414 | if (status < 0) { |
2415 | pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); | 2415 | pr_err("%s: Failed to setup mics (%d)!\n", __func__, status); |
diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index c67b50d8b317..ae1eb51bc9da 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c | |||
@@ -379,17 +379,7 @@ static struct spi_driver ad1836_spi_driver = { | |||
379 | .id_table = ad1836_ids, | 379 | .id_table = ad1836_ids, |
380 | }; | 380 | }; |
381 | 381 | ||
382 | static int __init ad1836_init(void) | 382 | module_spi_driver(ad1836_spi_driver); |
383 | { | ||
384 | return spi_register_driver(&ad1836_spi_driver); | ||
385 | } | ||
386 | module_init(ad1836_init); | ||
387 | |||
388 | static void __exit ad1836_exit(void) | ||
389 | { | ||
390 | spi_unregister_driver(&ad1836_spi_driver); | ||
391 | } | ||
392 | module_exit(ad1836_exit); | ||
393 | 383 | ||
394 | MODULE_DESCRIPTION("ASoC ad1836 driver"); | 384 | MODULE_DESCRIPTION("ASoC ad1836 driver"); |
395 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); | 385 | MODULE_AUTHOR("Barry Song <21cnbao@gmail.com>"); |
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 44f59064d8de..704544bfc90d 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -1392,17 +1392,7 @@ static struct i2c_driver adau1373_i2c_driver = { | |||
1392 | .id_table = adau1373_i2c_id, | 1392 | .id_table = adau1373_i2c_id, |
1393 | }; | 1393 | }; |
1394 | 1394 | ||
1395 | static int __init adau1373_init(void) | 1395 | module_i2c_driver(adau1373_i2c_driver); |
1396 | { | ||
1397 | return i2c_add_driver(&adau1373_i2c_driver); | ||
1398 | } | ||
1399 | module_init(adau1373_init); | ||
1400 | |||
1401 | static void __exit adau1373_exit(void) | ||
1402 | { | ||
1403 | i2c_del_driver(&adau1373_i2c_driver); | ||
1404 | } | ||
1405 | module_exit(adau1373_exit); | ||
1406 | 1396 | ||
1407 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); | 1397 | MODULE_DESCRIPTION("ASoC ADAU1373 driver"); |
1408 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 1398 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index 3d50fc8646b6..51f2f3cd8136 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -527,17 +527,7 @@ static struct i2c_driver adau1701_i2c_driver = { | |||
527 | .id_table = adau1701_i2c_id, | 527 | .id_table = adau1701_i2c_id, |
528 | }; | 528 | }; |
529 | 529 | ||
530 | static int __init adau1701_init(void) | 530 | module_i2c_driver(adau1701_i2c_driver); |
531 | { | ||
532 | return i2c_add_driver(&adau1701_i2c_driver); | ||
533 | } | ||
534 | module_init(adau1701_init); | ||
535 | |||
536 | static void __exit adau1701_exit(void) | ||
537 | { | ||
538 | i2c_del_driver(&adau1701_i2c_driver); | ||
539 | } | ||
540 | module_exit(adau1701_exit); | ||
541 | 531 | ||
542 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); | 532 | MODULE_DESCRIPTION("ASoC ADAU1701 SigmaDSP driver"); |
543 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); | 533 | MODULE_AUTHOR("Cliff Cai <cliff.cai@analog.com>"); |
diff --git a/sound/soc/codecs/ak4671.c b/sound/soc/codecs/ak4671.c index 5fb7c2a80e6d..2b457976a7bf 100644 --- a/sound/soc/codecs/ak4671.c +++ b/sound/soc/codecs/ak4671.c | |||
@@ -696,17 +696,7 @@ static struct i2c_driver ak4671_i2c_driver = { | |||
696 | .id_table = ak4671_i2c_id, | 696 | .id_table = ak4671_i2c_id, |
697 | }; | 697 | }; |
698 | 698 | ||
699 | static int __init ak4671_modinit(void) | 699 | module_i2c_driver(ak4671_i2c_driver); |
700 | { | ||
701 | return i2c_add_driver(&ak4671_i2c_driver); | ||
702 | } | ||
703 | module_init(ak4671_modinit); | ||
704 | |||
705 | static void __exit ak4671_exit(void) | ||
706 | { | ||
707 | i2c_del_driver(&ak4671_i2c_driver); | ||
708 | } | ||
709 | module_exit(ak4671_exit); | ||
710 | 700 | ||
711 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); | 701 | MODULE_DESCRIPTION("ASoC AK4671 codec driver"); |
712 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 702 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c index 5c9cacaf2d52..5e96a0a1669c 100644 --- a/sound/soc/codecs/arizona.c +++ b/sound/soc/codecs/arizona.c | |||
@@ -229,6 +229,69 @@ int arizona_out_ev(struct snd_soc_dapm_widget *w, | |||
229 | } | 229 | } |
230 | EXPORT_SYMBOL_GPL(arizona_out_ev); | 230 | EXPORT_SYMBOL_GPL(arizona_out_ev); |
231 | 231 | ||
232 | static unsigned int arizona_sysclk_48k_rates[] = { | ||
233 | 6144000, | ||
234 | 12288000, | ||
235 | 22579200, | ||
236 | 49152000, | ||
237 | }; | ||
238 | |||
239 | static unsigned int arizona_sysclk_44k1_rates[] = { | ||
240 | 5644800, | ||
241 | 11289600, | ||
242 | 24576000, | ||
243 | 45158400, | ||
244 | }; | ||
245 | |||
246 | static int arizona_set_opclk(struct snd_soc_codec *codec, unsigned int clk, | ||
247 | unsigned int freq) | ||
248 | { | ||
249 | struct arizona_priv *priv = snd_soc_codec_get_drvdata(codec); | ||
250 | unsigned int reg; | ||
251 | unsigned int *rates; | ||
252 | int ref, div, refclk; | ||
253 | |||
254 | switch (clk) { | ||
255 | case ARIZONA_CLK_OPCLK: | ||
256 | reg = ARIZONA_OUTPUT_SYSTEM_CLOCK; | ||
257 | refclk = priv->sysclk; | ||
258 | break; | ||
259 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
260 | reg = ARIZONA_OUTPUT_ASYNC_CLOCK; | ||
261 | refclk = priv->asyncclk; | ||
262 | break; | ||
263 | default: | ||
264 | return -EINVAL; | ||
265 | } | ||
266 | |||
267 | if (refclk % 8000) | ||
268 | rates = arizona_sysclk_44k1_rates; | ||
269 | else | ||
270 | rates = arizona_sysclk_48k_rates; | ||
271 | |||
272 | for (ref = 0; ref < ARRAY_SIZE(arizona_sysclk_48k_rates) && | ||
273 | rates[ref] <= refclk; ref++) { | ||
274 | div = 1; | ||
275 | while (rates[ref] / div >= freq && div < 32) { | ||
276 | if (rates[ref] / div == freq) { | ||
277 | dev_dbg(codec->dev, "Configured %dHz OPCLK\n", | ||
278 | freq); | ||
279 | snd_soc_update_bits(codec, reg, | ||
280 | ARIZONA_OPCLK_DIV_MASK | | ||
281 | ARIZONA_OPCLK_SEL_MASK, | ||
282 | (div << | ||
283 | ARIZONA_OPCLK_DIV_SHIFT) | | ||
284 | ref); | ||
285 | return 0; | ||
286 | } | ||
287 | div++; | ||
288 | } | ||
289 | } | ||
290 | |||
291 | dev_err(codec->dev, "Unable to generate %dHz OPCLK\n", freq); | ||
292 | return -EINVAL; | ||
293 | } | ||
294 | |||
232 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | 295 | int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, |
233 | int source, unsigned int freq, int dir) | 296 | int source, unsigned int freq, int dir) |
234 | { | 297 | { |
@@ -252,6 +315,9 @@ int arizona_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
252 | reg = ARIZONA_ASYNC_CLOCK_1; | 315 | reg = ARIZONA_ASYNC_CLOCK_1; |
253 | clk = &priv->asyncclk; | 316 | clk = &priv->asyncclk; |
254 | break; | 317 | break; |
318 | case ARIZONA_CLK_OPCLK: | ||
319 | case ARIZONA_CLK_ASYNC_OPCLK: | ||
320 | return arizona_set_opclk(codec, clk_id, freq); | ||
255 | default: | 321 | default: |
256 | return -EINVAL; | 322 | return -EINVAL; |
257 | } | 323 | } |
diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index 59caca8865e8..eb66b52777c9 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h | |||
@@ -17,8 +17,10 @@ | |||
17 | 17 | ||
18 | #include <sound/soc.h> | 18 | #include <sound/soc.h> |
19 | 19 | ||
20 | #define ARIZONA_CLK_SYSCLK 1 | 20 | #define ARIZONA_CLK_SYSCLK 1 |
21 | #define ARIZONA_CLK_ASYNCCLK 2 | 21 | #define ARIZONA_CLK_ASYNCCLK 2 |
22 | #define ARIZONA_CLK_OPCLK 3 | ||
23 | #define ARIZONA_CLK_ASYNC_OPCLK 4 | ||
22 | 24 | ||
23 | #define ARIZONA_CLK_SRC_MCLK1 0x0 | 25 | #define ARIZONA_CLK_SRC_MCLK1 0x0 |
24 | #define ARIZONA_CLK_SRC_MCLK2 0x1 | 26 | #define ARIZONA_CLK_SRC_MCLK2 0x1 |
diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index 047917f0b8ae..44a176f74170 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c | |||
@@ -29,6 +29,8 @@ | |||
29 | #include <linux/i2c.h> | 29 | #include <linux/i2c.h> |
30 | #include <linux/delay.h> | 30 | #include <linux/delay.h> |
31 | #include <linux/regulator/consumer.h> | 31 | #include <linux/regulator/consumer.h> |
32 | #include <linux/of_device.h> | ||
33 | #include <linux/of_gpio.h> | ||
32 | 34 | ||
33 | /* | 35 | /* |
34 | * The codec isn't really big-endian or little-endian, since the I2S | 36 | * The codec isn't really big-endian or little-endian, since the I2S |
@@ -639,6 +641,15 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
639 | .reg_cache_default = cs4270_default_reg_cache, | 641 | .reg_cache_default = cs4270_default_reg_cache, |
640 | }; | 642 | }; |
641 | 643 | ||
644 | /* | ||
645 | * cs4270_of_match - the device tree bindings | ||
646 | */ | ||
647 | static const struct of_device_id cs4270_of_match[] = { | ||
648 | { .compatible = "cirrus,cs4270", }, | ||
649 | { } | ||
650 | }; | ||
651 | MODULE_DEVICE_TABLE(of, cs4270_of_match); | ||
652 | |||
642 | /** | 653 | /** |
643 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 | 654 | * cs4270_i2c_probe - initialize the I2C interface of the CS4270 |
644 | * @i2c_client: the I2C client object | 655 | * @i2c_client: the I2C client object |
@@ -650,9 +661,25 @@ static const struct snd_soc_codec_driver soc_codec_device_cs4270 = { | |||
650 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, | 661 | static int cs4270_i2c_probe(struct i2c_client *i2c_client, |
651 | const struct i2c_device_id *id) | 662 | const struct i2c_device_id *id) |
652 | { | 663 | { |
664 | struct device_node *np = i2c_client->dev.of_node; | ||
653 | struct cs4270_private *cs4270; | 665 | struct cs4270_private *cs4270; |
654 | int ret; | 666 | int ret; |
655 | 667 | ||
668 | /* See if we have a way to bring the codec out of reset */ | ||
669 | if (np) { | ||
670 | enum of_gpio_flags flags; | ||
671 | int gpio = of_get_named_gpio_flags(np, "reset-gpio", 0, &flags); | ||
672 | |||
673 | if (gpio_is_valid(gpio)) { | ||
674 | ret = devm_gpio_request_one(&i2c_client->dev, gpio, | ||
675 | flags & OF_GPIO_ACTIVE_LOW ? | ||
676 | GPIOF_OUT_INIT_LOW : GPIOF_OUT_INIT_HIGH, | ||
677 | "cs4270 reset"); | ||
678 | if (ret < 0) | ||
679 | return ret; | ||
680 | } | ||
681 | } | ||
682 | |||
656 | /* Verify that we have a CS4270 */ | 683 | /* Verify that we have a CS4270 */ |
657 | 684 | ||
658 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); | 685 | ret = i2c_smbus_read_byte_data(i2c_client, CS4270_CHIPID); |
@@ -718,23 +745,14 @@ static struct i2c_driver cs4270_i2c_driver = { | |||
718 | .driver = { | 745 | .driver = { |
719 | .name = "cs4270", | 746 | .name = "cs4270", |
720 | .owner = THIS_MODULE, | 747 | .owner = THIS_MODULE, |
748 | .of_match_table = cs4270_of_match, | ||
721 | }, | 749 | }, |
722 | .id_table = cs4270_id, | 750 | .id_table = cs4270_id, |
723 | .probe = cs4270_i2c_probe, | 751 | .probe = cs4270_i2c_probe, |
724 | .remove = cs4270_i2c_remove, | 752 | .remove = cs4270_i2c_remove, |
725 | }; | 753 | }; |
726 | 754 | ||
727 | static int __init cs4270_init(void) | 755 | module_i2c_driver(cs4270_i2c_driver); |
728 | { | ||
729 | return i2c_add_driver(&cs4270_i2c_driver); | ||
730 | } | ||
731 | module_init(cs4270_init); | ||
732 | |||
733 | static void __exit cs4270_exit(void) | ||
734 | { | ||
735 | i2c_del_driver(&cs4270_i2c_driver); | ||
736 | } | ||
737 | module_exit(cs4270_exit); | ||
738 | 756 | ||
739 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); | 757 | MODULE_AUTHOR("Timur Tabi <timur@freescale.com>"); |
740 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); | 758 | MODULE_DESCRIPTION("Cirrus Logic CS4270 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs42l51.c b/sound/soc/codecs/cs42l51.c index 091d0193f507..1e0fa3b5f79a 100644 --- a/sound/soc/codecs/cs42l51.c +++ b/sound/soc/codecs/cs42l51.c | |||
@@ -614,24 +614,7 @@ static struct i2c_driver cs42l51_i2c_driver = { | |||
614 | .remove = cs42l51_i2c_remove, | 614 | .remove = cs42l51_i2c_remove, |
615 | }; | 615 | }; |
616 | 616 | ||
617 | static int __init cs42l51_init(void) | 617 | module_i2c_driver(cs42l51_i2c_driver); |
618 | { | ||
619 | int ret; | ||
620 | |||
621 | ret = i2c_add_driver(&cs42l51_i2c_driver); | ||
622 | if (ret != 0) { | ||
623 | printk(KERN_ERR "%s: can't add i2c driver\n", __func__); | ||
624 | return ret; | ||
625 | } | ||
626 | return 0; | ||
627 | } | ||
628 | module_init(cs42l51_init); | ||
629 | |||
630 | static void __exit cs42l51_exit(void) | ||
631 | { | ||
632 | i2c_del_driver(&cs42l51_i2c_driver); | ||
633 | } | ||
634 | module_exit(cs42l51_exit); | ||
635 | 618 | ||
636 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); | 619 | MODULE_AUTHOR("Arnaud Patard <arnaud.patard@rtp-net.org>"); |
637 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); | 620 | MODULE_DESCRIPTION("Cirrus Logic CS42L51 ALSA SoC Codec Driver"); |
diff --git a/sound/soc/codecs/cs42l52.c b/sound/soc/codecs/cs42l52.c index 628daf6a1d97..61599298fb26 100644 --- a/sound/soc/codecs/cs42l52.c +++ b/sound/soc/codecs/cs42l52.c | |||
@@ -24,7 +24,6 @@ | |||
24 | #include <linux/slab.h> | 24 | #include <linux/slab.h> |
25 | #include <linux/workqueue.h> | 25 | #include <linux/workqueue.h> |
26 | #include <linux/platform_device.h> | 26 | #include <linux/platform_device.h> |
27 | #include <linux/slab.h> | ||
28 | #include <sound/core.h> | 27 | #include <sound/core.h> |
29 | #include <sound/pcm.h> | 28 | #include <sound/pcm.h> |
30 | #include <sound/pcm_params.h> | 29 | #include <sound/pcm_params.h> |
diff --git a/sound/soc/codecs/isabelle.c b/sound/soc/codecs/isabelle.c index 5d8f39e32978..1bf55602c9eb 100644 --- a/sound/soc/codecs/isabelle.c +++ b/sound/soc/codecs/isabelle.c | |||
@@ -13,7 +13,6 @@ | |||
13 | */ | 13 | */ |
14 | #include <linux/module.h> | 14 | #include <linux/module.h> |
15 | #include <linux/moduleparam.h> | 15 | #include <linux/moduleparam.h> |
16 | #include <linux/version.h> | ||
17 | #include <linux/kernel.h> | 16 | #include <linux/kernel.h> |
18 | #include <linux/init.h> | 17 | #include <linux/init.h> |
19 | #include <linux/delay.h> | 18 | #include <linux/delay.h> |
diff --git a/sound/soc/codecs/lm4857.c b/sound/soc/codecs/lm4857.c index ba4fafb93e56..81a328c78838 100644 --- a/sound/soc/codecs/lm4857.c +++ b/sound/soc/codecs/lm4857.c | |||
@@ -250,17 +250,7 @@ static struct i2c_driver lm4857_i2c_driver = { | |||
250 | .id_table = lm4857_i2c_id, | 250 | .id_table = lm4857_i2c_id, |
251 | }; | 251 | }; |
252 | 252 | ||
253 | static int __init lm4857_init(void) | 253 | module_i2c_driver(lm4857_i2c_driver); |
254 | { | ||
255 | return i2c_add_driver(&lm4857_i2c_driver); | ||
256 | } | ||
257 | module_init(lm4857_init); | ||
258 | |||
259 | static void __exit lm4857_exit(void) | ||
260 | { | ||
261 | i2c_del_driver(&lm4857_i2c_driver); | ||
262 | } | ||
263 | module_exit(lm4857_exit); | ||
264 | 254 | ||
265 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); | 255 | MODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>"); |
266 | MODULE_DESCRIPTION("LM4857 amplifier driver"); | 256 | MODULE_DESCRIPTION("LM4857 amplifier driver"); |
diff --git a/sound/soc/codecs/max98088.c b/sound/soc/codecs/max98088.c index af7324b79dd0..3264a5169306 100644 --- a/sound/soc/codecs/max98088.c +++ b/sound/soc/codecs/max98088.c | |||
@@ -2107,23 +2107,7 @@ static struct i2c_driver max98088_i2c_driver = { | |||
2107 | .id_table = max98088_i2c_id, | 2107 | .id_table = max98088_i2c_id, |
2108 | }; | 2108 | }; |
2109 | 2109 | ||
2110 | static int __init max98088_init(void) | 2110 | module_i2c_driver(max98088_i2c_driver); |
2111 | { | ||
2112 | int ret; | ||
2113 | |||
2114 | ret = i2c_add_driver(&max98088_i2c_driver); | ||
2115 | if (ret) | ||
2116 | pr_err("Failed to register max98088 I2C driver: %d\n", ret); | ||
2117 | |||
2118 | return ret; | ||
2119 | } | ||
2120 | module_init(max98088_init); | ||
2121 | |||
2122 | static void __exit max98088_exit(void) | ||
2123 | { | ||
2124 | i2c_del_driver(&max98088_i2c_driver); | ||
2125 | } | ||
2126 | module_exit(max98088_exit); | ||
2127 | 2111 | ||
2128 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); | 2112 | MODULE_DESCRIPTION("ALSA SoC MAX98088 driver"); |
2129 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); | 2113 | MODULE_AUTHOR("Peter Hsiang, Jesse Marroquin"); |
diff --git a/sound/soc/codecs/max98095.c b/sound/soc/codecs/max98095.c index 7cd508e16a5c..38d43c59d3f4 100644 --- a/sound/soc/codecs/max98095.c +++ b/sound/soc/codecs/max98095.c | |||
@@ -2533,23 +2533,7 @@ static struct i2c_driver max98095_i2c_driver = { | |||
2533 | .id_table = max98095_i2c_id, | 2533 | .id_table = max98095_i2c_id, |
2534 | }; | 2534 | }; |
2535 | 2535 | ||
2536 | static int __init max98095_init(void) | 2536 | module_i2c_driver(max98095_i2c_driver); |
2537 | { | ||
2538 | int ret; | ||
2539 | |||
2540 | ret = i2c_add_driver(&max98095_i2c_driver); | ||
2541 | if (ret) | ||
2542 | pr_err("Failed to register max98095 I2C driver: %d\n", ret); | ||
2543 | |||
2544 | return ret; | ||
2545 | } | ||
2546 | module_init(max98095_init); | ||
2547 | |||
2548 | static void __exit max98095_exit(void) | ||
2549 | { | ||
2550 | i2c_del_driver(&max98095_i2c_driver); | ||
2551 | } | ||
2552 | module_exit(max98095_exit); | ||
2553 | 2537 | ||
2554 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); | 2538 | MODULE_DESCRIPTION("ALSA SoC MAX98095 driver"); |
2555 | MODULE_AUTHOR("Peter Hsiang"); | 2539 | MODULE_AUTHOR("Peter Hsiang"); |
diff --git a/sound/soc/codecs/max9850.c b/sound/soc/codecs/max9850.c index a1913091f56c..efe535c37b39 100644 --- a/sound/soc/codecs/max9850.c +++ b/sound/soc/codecs/max9850.c | |||
@@ -369,17 +369,7 @@ static struct i2c_driver max9850_i2c_driver = { | |||
369 | .id_table = max9850_i2c_id, | 369 | .id_table = max9850_i2c_id, |
370 | }; | 370 | }; |
371 | 371 | ||
372 | static int __init max9850_init(void) | 372 | module_i2c_driver(max9850_i2c_driver); |
373 | { | ||
374 | return i2c_add_driver(&max9850_i2c_driver); | ||
375 | } | ||
376 | module_init(max9850_init); | ||
377 | |||
378 | static void __exit max9850_exit(void) | ||
379 | { | ||
380 | i2c_del_driver(&max9850_i2c_driver); | ||
381 | } | ||
382 | module_exit(max9850_exit); | ||
383 | 373 | ||
384 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); | 374 | MODULE_AUTHOR("Christian Glindkamp <christian.glindkamp@taskit.de>"); |
385 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); | 375 | MODULE_DESCRIPTION("ASoC MAX9850 codec driver"); |
diff --git a/sound/soc/codecs/max9877.c b/sound/soc/codecs/max9877.c index 3a2ba3d8fd6d..d15e5943c85e 100644 --- a/sound/soc/codecs/max9877.c +++ b/sound/soc/codecs/max9877.c | |||
@@ -291,17 +291,7 @@ static struct i2c_driver max9877_i2c_driver = { | |||
291 | .id_table = max9877_i2c_id, | 291 | .id_table = max9877_i2c_id, |
292 | }; | 292 | }; |
293 | 293 | ||
294 | static int __init max9877_init(void) | 294 | module_i2c_driver(max9877_i2c_driver); |
295 | { | ||
296 | return i2c_add_driver(&max9877_i2c_driver); | ||
297 | } | ||
298 | module_init(max9877_init); | ||
299 | |||
300 | static void __exit max9877_exit(void) | ||
301 | { | ||
302 | i2c_del_driver(&max9877_i2c_driver); | ||
303 | } | ||
304 | module_exit(max9877_exit); | ||
305 | 295 | ||
306 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); | 296 | MODULE_DESCRIPTION("ASoC MAX9877 amp driver"); |
307 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); | 297 | MODULE_AUTHOR("Joonyoung Shim <jy0922.shim@samsung.com>"); |
diff --git a/sound/soc/codecs/sta32x.c b/sound/soc/codecs/sta32x.c index 8d717f4b5a87..51b7313a4c14 100644 --- a/sound/soc/codecs/sta32x.c +++ b/sound/soc/codecs/sta32x.c | |||
@@ -1006,17 +1006,7 @@ static struct i2c_driver sta32x_i2c_driver = { | |||
1006 | .id_table = sta32x_i2c_id, | 1006 | .id_table = sta32x_i2c_id, |
1007 | }; | 1007 | }; |
1008 | 1008 | ||
1009 | static int __init sta32x_init(void) | 1009 | module_i2c_driver(sta32x_i2c_driver); |
1010 | { | ||
1011 | return i2c_add_driver(&sta32x_i2c_driver); | ||
1012 | } | ||
1013 | module_init(sta32x_init); | ||
1014 | |||
1015 | static void __exit sta32x_exit(void) | ||
1016 | { | ||
1017 | i2c_del_driver(&sta32x_i2c_driver); | ||
1018 | } | ||
1019 | module_exit(sta32x_exit); | ||
1020 | 1010 | ||
1021 | MODULE_DESCRIPTION("ASoC STA32X driver"); | 1011 | MODULE_DESCRIPTION("ASoC STA32X driver"); |
1022 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); | 1012 | MODULE_AUTHOR("Johannes Stezenbach <js@sig21.net>"); |
diff --git a/sound/soc/codecs/sta529.c b/sound/soc/codecs/sta529.c index 0c225cd569d2..9e3144862386 100644 --- a/sound/soc/codecs/sta529.c +++ b/sound/soc/codecs/sta529.c | |||
@@ -358,7 +358,7 @@ static int sta529_resume(struct snd_soc_codec *codec) | |||
358 | return 0; | 358 | return 0; |
359 | } | 359 | } |
360 | 360 | ||
361 | struct snd_soc_codec_driver sta529_codec_driver = { | 361 | static const struct snd_soc_codec_driver sta529_codec_driver = { |
362 | .probe = sta529_probe, | 362 | .probe = sta529_probe, |
363 | .remove = sta529_remove, | 363 | .remove = sta529_remove, |
364 | .set_bias_level = sta529_set_bias_level, | 364 | .set_bias_level = sta529_set_bias_level, |
diff --git a/sound/soc/codecs/tlv320aic26.c b/sound/soc/codecs/tlv320aic26.c index 85944e953578..b1f6982c7c9c 100644 --- a/sound/soc/codecs/tlv320aic26.c +++ b/sound/soc/codecs/tlv320aic26.c | |||
@@ -444,14 +444,4 @@ static struct spi_driver aic26_spi = { | |||
444 | .remove = aic26_spi_remove, | 444 | .remove = aic26_spi_remove, |
445 | }; | 445 | }; |
446 | 446 | ||
447 | static int __init aic26_init(void) | 447 | module_spi_driver(aic26_spi); |
448 | { | ||
449 | return spi_register_driver(&aic26_spi); | ||
450 | } | ||
451 | module_init(aic26_init); | ||
452 | |||
453 | static void __exit aic26_exit(void) | ||
454 | { | ||
455 | spi_unregister_driver(&aic26_spi); | ||
456 | } | ||
457 | module_exit(aic26_exit); | ||
diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index b0a73d37ed52..f230292ba96b 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c | |||
@@ -746,24 +746,7 @@ static struct i2c_driver aic32x4_i2c_driver = { | |||
746 | .id_table = aic32x4_i2c_id, | 746 | .id_table = aic32x4_i2c_id, |
747 | }; | 747 | }; |
748 | 748 | ||
749 | static int __init aic32x4_modinit(void) | 749 | module_i2c_driver(aic32x4_i2c_driver); |
750 | { | ||
751 | int ret = 0; | ||
752 | |||
753 | ret = i2c_add_driver(&aic32x4_i2c_driver); | ||
754 | if (ret != 0) { | ||
755 | printk(KERN_ERR "Failed to register aic32x4 I2C driver: %d\n", | ||
756 | ret); | ||
757 | } | ||
758 | return ret; | ||
759 | } | ||
760 | module_init(aic32x4_modinit); | ||
761 | |||
762 | static void __exit aic32x4_exit(void) | ||
763 | { | ||
764 | i2c_del_driver(&aic32x4_i2c_driver); | ||
765 | } | ||
766 | module_exit(aic32x4_exit); | ||
767 | 750 | ||
768 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); | 751 | MODULE_DESCRIPTION("ASoC tlv320aic32x4 codec driver"); |
769 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); | 752 | MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>"); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index dc78f5a4bcbf..5708a973a776 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -40,6 +40,7 @@ | |||
40 | #include <linux/i2c.h> | 40 | #include <linux/i2c.h> |
41 | #include <linux/gpio.h> | 41 | #include <linux/gpio.h> |
42 | #include <linux/regulator/consumer.h> | 42 | #include <linux/regulator/consumer.h> |
43 | #include <linux/of_gpio.h> | ||
43 | #include <linux/slab.h> | 44 | #include <linux/slab.h> |
44 | #include <sound/core.h> | 45 | #include <sound/core.h> |
45 | #include <sound/pcm.h> | 46 | #include <sound/pcm.h> |
@@ -1457,6 +1458,8 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1457 | { | 1458 | { |
1458 | struct aic3x_pdata *pdata = i2c->dev.platform_data; | 1459 | struct aic3x_pdata *pdata = i2c->dev.platform_data; |
1459 | struct aic3x_priv *aic3x; | 1460 | struct aic3x_priv *aic3x; |
1461 | struct aic3x_setup_data *ai3x_setup; | ||
1462 | struct device_node *np = i2c->dev.of_node; | ||
1460 | int ret; | 1463 | int ret; |
1461 | 1464 | ||
1462 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); | 1465 | aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); |
@@ -1471,6 +1474,25 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, | |||
1471 | if (pdata) { | 1474 | if (pdata) { |
1472 | aic3x->gpio_reset = pdata->gpio_reset; | 1475 | aic3x->gpio_reset = pdata->gpio_reset; |
1473 | aic3x->setup = pdata->setup; | 1476 | aic3x->setup = pdata->setup; |
1477 | } else if (np) { | ||
1478 | ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), | ||
1479 | GFP_KERNEL); | ||
1480 | if (ai3x_setup == NULL) { | ||
1481 | dev_err(&i2c->dev, "failed to create private data\n"); | ||
1482 | return -ENOMEM; | ||
1483 | } | ||
1484 | |||
1485 | ret = of_get_named_gpio(np, "gpio-reset", 0); | ||
1486 | if (ret >= 0) | ||
1487 | aic3x->gpio_reset = ret; | ||
1488 | else | ||
1489 | aic3x->gpio_reset = -1; | ||
1490 | |||
1491 | if (of_property_read_u32_array(np, "ai3x-gpio-func", | ||
1492 | ai3x_setup->gpio_func, 2) >= 0) { | ||
1493 | aic3x->setup = ai3x_setup; | ||
1494 | } | ||
1495 | |||
1474 | } else { | 1496 | } else { |
1475 | aic3x->gpio_reset = -1; | 1497 | aic3x->gpio_reset = -1; |
1476 | } | 1498 | } |
@@ -1488,34 +1510,27 @@ static int aic3x_i2c_remove(struct i2c_client *client) | |||
1488 | return 0; | 1510 | return 0; |
1489 | } | 1511 | } |
1490 | 1512 | ||
1513 | #if defined(CONFIG_OF) | ||
1514 | static const struct of_device_id tlv320aic3x_of_match[] = { | ||
1515 | { .compatible = "ti,tlv320aic3x", }, | ||
1516 | {}, | ||
1517 | }; | ||
1518 | MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); | ||
1519 | #endif | ||
1520 | |||
1491 | /* machine i2c codec control layer */ | 1521 | /* machine i2c codec control layer */ |
1492 | static struct i2c_driver aic3x_i2c_driver = { | 1522 | static struct i2c_driver aic3x_i2c_driver = { |
1493 | .driver = { | 1523 | .driver = { |
1494 | .name = "tlv320aic3x-codec", | 1524 | .name = "tlv320aic3x-codec", |
1495 | .owner = THIS_MODULE, | 1525 | .owner = THIS_MODULE, |
1526 | .of_match_table = of_match_ptr(tlv320aic3x_of_match), | ||
1496 | }, | 1527 | }, |
1497 | .probe = aic3x_i2c_probe, | 1528 | .probe = aic3x_i2c_probe, |
1498 | .remove = aic3x_i2c_remove, | 1529 | .remove = aic3x_i2c_remove, |
1499 | .id_table = aic3x_i2c_id, | 1530 | .id_table = aic3x_i2c_id, |
1500 | }; | 1531 | }; |
1501 | 1532 | ||
1502 | static int __init aic3x_modinit(void) | 1533 | module_i2c_driver(aic3x_i2c_driver); |
1503 | { | ||
1504 | int ret = 0; | ||
1505 | ret = i2c_add_driver(&aic3x_i2c_driver); | ||
1506 | if (ret != 0) { | ||
1507 | printk(KERN_ERR "Failed to register TLV320AIC3x I2C driver: %d\n", | ||
1508 | ret); | ||
1509 | } | ||
1510 | return ret; | ||
1511 | } | ||
1512 | module_init(aic3x_modinit); | ||
1513 | |||
1514 | static void __exit aic3x_exit(void) | ||
1515 | { | ||
1516 | i2c_del_driver(&aic3x_i2c_driver); | ||
1517 | } | ||
1518 | module_exit(aic3x_exit); | ||
1519 | 1534 | ||
1520 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); | 1535 | MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); |
1521 | MODULE_AUTHOR("Vladimir Barinov"); | 1536 | MODULE_AUTHOR("Vladimir Barinov"); |
diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index 0dd41077ab79..d2e16c5d7d1f 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c | |||
@@ -1621,24 +1621,7 @@ static struct i2c_driver tlv320dac33_i2c_driver = { | |||
1621 | .id_table = tlv320dac33_i2c_id, | 1621 | .id_table = tlv320dac33_i2c_id, |
1622 | }; | 1622 | }; |
1623 | 1623 | ||
1624 | static int __init dac33_module_init(void) | 1624 | module_i2c_driver(tlv320dac33_i2c_driver); |
1625 | { | ||
1626 | int r; | ||
1627 | r = i2c_add_driver(&tlv320dac33_i2c_driver); | ||
1628 | if (r < 0) { | ||
1629 | printk(KERN_ERR "DAC33: driver registration failed\n"); | ||
1630 | return r; | ||
1631 | } | ||
1632 | return 0; | ||
1633 | } | ||
1634 | module_init(dac33_module_init); | ||
1635 | |||
1636 | static void __exit dac33_module_exit(void) | ||
1637 | { | ||
1638 | i2c_del_driver(&tlv320dac33_i2c_driver); | ||
1639 | } | ||
1640 | module_exit(dac33_module_exit); | ||
1641 | |||
1642 | 1625 | ||
1643 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); | 1626 | MODULE_DESCRIPTION("ASoC TLV320DAC33 codec driver"); |
1644 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 1627 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
diff --git a/sound/soc/codecs/tpa6130a2.c b/sound/soc/codecs/tpa6130a2.c index 6fe4aa3ac544..565ff39ad3a3 100644 --- a/sound/soc/codecs/tpa6130a2.c +++ b/sound/soc/codecs/tpa6130a2.c | |||
@@ -487,19 +487,8 @@ static struct i2c_driver tpa6130a2_i2c_driver = { | |||
487 | .id_table = tpa6130a2_id, | 487 | .id_table = tpa6130a2_id, |
488 | }; | 488 | }; |
489 | 489 | ||
490 | static int __init tpa6130a2_init(void) | 490 | module_i2c_driver(tpa6130a2_i2c_driver); |
491 | { | ||
492 | return i2c_add_driver(&tpa6130a2_i2c_driver); | ||
493 | } | ||
494 | |||
495 | static void __exit tpa6130a2_exit(void) | ||
496 | { | ||
497 | i2c_del_driver(&tpa6130a2_i2c_driver); | ||
498 | } | ||
499 | 491 | ||
500 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); | 492 | MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>"); |
501 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); | 493 | MODULE_DESCRIPTION("TPA6130A2 Headphone amplifier driver"); |
502 | MODULE_LICENSE("GPL"); | 494 | MODULE_LICENSE("GPL"); |
503 | |||
504 | module_init(tpa6130a2_init); | ||
505 | module_exit(tpa6130a2_exit); | ||
diff --git a/sound/soc/codecs/wm0010.c b/sound/soc/codecs/wm0010.c new file mode 100644 index 000000000000..5f99148447e1 --- /dev/null +++ b/sound/soc/codecs/wm0010.c | |||
@@ -0,0 +1,942 @@ | |||
1 | /* | ||
2 | * wm0010.c -- WM0010 DSP Driver | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics PLC. | ||
5 | * | ||
6 | * Authors: Mark Brown <broonie@opensource.wolfsonmicro.com> | ||
7 | * Dimitris Papastamos <dp@opensource.wolfsonmicro.com> | ||
8 | * Scott Ling <sl@opensource.wolfsonmicro.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License version 2 as | ||
12 | * published by the Free Software Foundation. | ||
13 | */ | ||
14 | |||
15 | #include <linux/module.h> | ||
16 | #include <linux/moduleparam.h> | ||
17 | #include <linux/irqreturn.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/spi/spi.h> | ||
20 | #include <linux/firmware.h> | ||
21 | #include <linux/delay.h> | ||
22 | #include <linux/fs.h> | ||
23 | #include <linux/miscdevice.h> | ||
24 | #include <linux/gpio.h> | ||
25 | #include <linux/regulator/consumer.h> | ||
26 | #include <linux/mutex.h> | ||
27 | #include <linux/workqueue.h> | ||
28 | |||
29 | #include <sound/soc.h> | ||
30 | #include <sound/wm0010.h> | ||
31 | |||
32 | #define DEVICE_ID_WM0010 10 | ||
33 | |||
34 | enum dfw_cmd { | ||
35 | DFW_CMD_FUSE = 0x01, | ||
36 | DFW_CMD_CODE_HDR, | ||
37 | DFW_CMD_CODE_DATA, | ||
38 | DFW_CMD_PLL, | ||
39 | DFW_CMD_INFO = 0xff | ||
40 | }; | ||
41 | |||
42 | struct dfw_binrec { | ||
43 | u8 command; | ||
44 | u32 length:24; | ||
45 | u32 address; | ||
46 | uint8_t data[0]; | ||
47 | } __packed; | ||
48 | |||
49 | struct dfw_pllrec { | ||
50 | u8 command; | ||
51 | u32 length:24; | ||
52 | u32 address; | ||
53 | u32 clkctrl1; | ||
54 | u32 clkctrl2; | ||
55 | u32 clkctrl3; | ||
56 | u32 ldetctrl; | ||
57 | u32 uart_div; | ||
58 | u32 spi_div; | ||
59 | } __packed; | ||
60 | |||
61 | static struct pll_clock_map { | ||
62 | int max_sysclk; | ||
63 | int max_pll_spi_speed; | ||
64 | u32 pll_clkctrl1; | ||
65 | } pll_clock_map[] = { /* Dividers */ | ||
66 | { 22000000, 26000000, 0x00201f11 }, /* 2,32,2 */ | ||
67 | { 18000000, 26000000, 0x00203f21 }, /* 2,64,4 */ | ||
68 | { 14000000, 26000000, 0x00202620 }, /* 1,39,4 */ | ||
69 | { 10000000, 22000000, 0x00203120 }, /* 1,50,4 */ | ||
70 | { 6500000, 22000000, 0x00204520 }, /* 1,70,4 */ | ||
71 | { 5500000, 22000000, 0x00103f10 }, /* 1,64,2 */ | ||
72 | }; | ||
73 | |||
74 | enum wm0010_state { | ||
75 | WM0010_POWER_OFF, | ||
76 | WM0010_OUT_OF_RESET, | ||
77 | WM0010_BOOTROM, | ||
78 | WM0010_STAGE2, | ||
79 | WM0010_FIRMWARE, | ||
80 | }; | ||
81 | |||
82 | struct wm0010_priv { | ||
83 | struct snd_soc_codec *codec; | ||
84 | |||
85 | struct mutex lock; | ||
86 | struct device *dev; | ||
87 | |||
88 | struct wm0010_pdata pdata; | ||
89 | |||
90 | int gpio_reset; | ||
91 | int gpio_reset_value; | ||
92 | |||
93 | struct regulator_bulk_data core_supplies[2]; | ||
94 | struct regulator *dbvdd; | ||
95 | |||
96 | int sysclk; | ||
97 | |||
98 | enum wm0010_state state; | ||
99 | bool boot_failed; | ||
100 | int boot_done; | ||
101 | bool ready; | ||
102 | bool pll_running; | ||
103 | int max_spi_freq; | ||
104 | int board_max_spi_speed; | ||
105 | u32 pll_clkctrl1; | ||
106 | |||
107 | spinlock_t irq_lock; | ||
108 | int irq; | ||
109 | |||
110 | struct completion boot_completion; | ||
111 | }; | ||
112 | |||
113 | struct wm0010_spi_msg { | ||
114 | struct spi_message m; | ||
115 | struct spi_transfer t; | ||
116 | u8 *tx_buf; | ||
117 | u8 *rx_buf; | ||
118 | size_t len; | ||
119 | }; | ||
120 | |||
121 | static const struct snd_soc_dapm_widget wm0010_dapm_widgets[] = { | ||
122 | SND_SOC_DAPM_SUPPLY("CLKIN", SND_SOC_NOPM, 0, 0, NULL, 0), | ||
123 | }; | ||
124 | |||
125 | static const struct snd_soc_dapm_route wm0010_dapm_routes[] = { | ||
126 | { "SDI2 Capture", NULL, "SDI1 Playback" }, | ||
127 | { "SDI1 Capture", NULL, "SDI2 Playback" }, | ||
128 | |||
129 | { "SDI1 Capture", NULL, "CLKIN" }, | ||
130 | { "SDI2 Capture", NULL, "CLKIN" }, | ||
131 | { "SDI1 Playback", NULL, "CLKIN" }, | ||
132 | { "SDI2 Playback", NULL, "CLKIN" }, | ||
133 | }; | ||
134 | |||
135 | static const char *wm0010_state_to_str(enum wm0010_state state) | ||
136 | { | ||
137 | const char *state_to_str[] = { | ||
138 | "Power off", | ||
139 | "Out of reset", | ||
140 | "Boot ROM", | ||
141 | "Stage2", | ||
142 | "Firmware" | ||
143 | }; | ||
144 | |||
145 | if (state < 0 || state >= ARRAY_SIZE(state_to_str)) | ||
146 | return "null"; | ||
147 | return state_to_str[state]; | ||
148 | } | ||
149 | |||
150 | /* Called with wm0010->lock held */ | ||
151 | static void wm0010_halt(struct snd_soc_codec *codec) | ||
152 | { | ||
153 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
154 | unsigned long flags; | ||
155 | enum wm0010_state state; | ||
156 | |||
157 | /* Fetch the wm0010 state */ | ||
158 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
159 | state = wm0010->state; | ||
160 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
161 | |||
162 | switch (state) { | ||
163 | case WM0010_POWER_OFF: | ||
164 | /* If there's nothing to do, bail out */ | ||
165 | return; | ||
166 | case WM0010_OUT_OF_RESET: | ||
167 | case WM0010_BOOTROM: | ||
168 | case WM0010_STAGE2: | ||
169 | case WM0010_FIRMWARE: | ||
170 | /* Remember to put chip back into reset */ | ||
171 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | ||
172 | /* Disable the regulators */ | ||
173 | regulator_disable(wm0010->dbvdd); | ||
174 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
175 | wm0010->core_supplies); | ||
176 | break; | ||
177 | } | ||
178 | |||
179 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
180 | wm0010->state = WM0010_POWER_OFF; | ||
181 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
182 | } | ||
183 | |||
184 | struct wm0010_boot_xfer { | ||
185 | struct list_head list; | ||
186 | struct snd_soc_codec *codec; | ||
187 | struct completion *done; | ||
188 | struct spi_message m; | ||
189 | struct spi_transfer t; | ||
190 | }; | ||
191 | |||
192 | /* Called with wm0010->lock held */ | ||
193 | static void wm0010_mark_boot_failure(struct wm0010_priv *wm0010) | ||
194 | { | ||
195 | enum wm0010_state state; | ||
196 | unsigned long flags; | ||
197 | |||
198 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
199 | state = wm0010->state; | ||
200 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
201 | |||
202 | dev_err(wm0010->dev, "Failed to transition from `%s' state to `%s' state\n", | ||
203 | wm0010_state_to_str(state), wm0010_state_to_str(state + 1)); | ||
204 | |||
205 | wm0010->boot_failed = true; | ||
206 | } | ||
207 | |||
208 | static void wm0010_boot_xfer_complete(void *data) | ||
209 | { | ||
210 | struct wm0010_boot_xfer *xfer = data; | ||
211 | struct snd_soc_codec *codec = xfer->codec; | ||
212 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
213 | u32 *out32 = xfer->t.rx_buf; | ||
214 | int i; | ||
215 | |||
216 | if (xfer->m.status != 0) { | ||
217 | dev_err(codec->dev, "SPI transfer failed: %d\n", | ||
218 | xfer->m.status); | ||
219 | wm0010_mark_boot_failure(wm0010); | ||
220 | if (xfer->done) | ||
221 | complete(xfer->done); | ||
222 | return; | ||
223 | } | ||
224 | |||
225 | for (i = 0; i < xfer->t.len / 4; i++) { | ||
226 | dev_dbg(codec->dev, "%d: %04x\n", i, out32[i]); | ||
227 | |||
228 | switch (be32_to_cpu(out32[i])) { | ||
229 | case 0xe0e0e0e0: | ||
230 | dev_err(codec->dev, | ||
231 | "%d: ROM error reported in stage 2\n", i); | ||
232 | wm0010_mark_boot_failure(wm0010); | ||
233 | break; | ||
234 | |||
235 | case 0x55555555: | ||
236 | if (wm0010->boot_done == 0) | ||
237 | break; | ||
238 | dev_err(codec->dev, | ||
239 | "%d: ROM bootloader running in stage 2\n", i); | ||
240 | wm0010_mark_boot_failure(wm0010); | ||
241 | break; | ||
242 | |||
243 | case 0x0fed0000: | ||
244 | dev_dbg(codec->dev, "Stage2 loader running\n"); | ||
245 | break; | ||
246 | |||
247 | case 0x0fed0007: | ||
248 | dev_dbg(codec->dev, "CODE_HDR packet received\n"); | ||
249 | break; | ||
250 | |||
251 | case 0x0fed0008: | ||
252 | dev_dbg(codec->dev, "CODE_DATA packet received\n"); | ||
253 | break; | ||
254 | |||
255 | case 0x0fed0009: | ||
256 | dev_dbg(codec->dev, "Download complete\n"); | ||
257 | break; | ||
258 | |||
259 | case 0x0fed000c: | ||
260 | dev_dbg(codec->dev, "Application start\n"); | ||
261 | break; | ||
262 | |||
263 | case 0x0fed000e: | ||
264 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
265 | wm0010->pll_running = true; | ||
266 | break; | ||
267 | |||
268 | case 0x0fed0025: | ||
269 | dev_err(codec->dev, "Device reports image too long\n"); | ||
270 | wm0010_mark_boot_failure(wm0010); | ||
271 | break; | ||
272 | |||
273 | case 0x0fed002c: | ||
274 | dev_err(codec->dev, "Device reports bad SPI packet\n"); | ||
275 | wm0010_mark_boot_failure(wm0010); | ||
276 | break; | ||
277 | |||
278 | case 0x0fed0031: | ||
279 | dev_err(codec->dev, "Device reports SPI read overflow\n"); | ||
280 | wm0010_mark_boot_failure(wm0010); | ||
281 | break; | ||
282 | |||
283 | case 0x0fed0032: | ||
284 | dev_err(codec->dev, "Device reports SPI underclock\n"); | ||
285 | wm0010_mark_boot_failure(wm0010); | ||
286 | break; | ||
287 | |||
288 | case 0x0fed0033: | ||
289 | dev_err(codec->dev, "Device reports bad header packet\n"); | ||
290 | wm0010_mark_boot_failure(wm0010); | ||
291 | break; | ||
292 | |||
293 | case 0x0fed0034: | ||
294 | dev_err(codec->dev, "Device reports invalid packet type\n"); | ||
295 | wm0010_mark_boot_failure(wm0010); | ||
296 | break; | ||
297 | |||
298 | case 0x0fed0035: | ||
299 | dev_err(codec->dev, "Device reports data before header error\n"); | ||
300 | wm0010_mark_boot_failure(wm0010); | ||
301 | break; | ||
302 | |||
303 | case 0x0fed0038: | ||
304 | dev_err(codec->dev, "Device reports invalid PLL packet\n"); | ||
305 | break; | ||
306 | |||
307 | case 0x0fed003a: | ||
308 | dev_err(codec->dev, "Device reports packet alignment error\n"); | ||
309 | wm0010_mark_boot_failure(wm0010); | ||
310 | break; | ||
311 | |||
312 | default: | ||
313 | dev_err(codec->dev, "Unrecognised return 0x%x\n", | ||
314 | be32_to_cpu(out32[i])); | ||
315 | wm0010_mark_boot_failure(wm0010); | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | if (wm0010->boot_failed) | ||
320 | break; | ||
321 | } | ||
322 | |||
323 | wm0010->boot_done++; | ||
324 | if (xfer->done) | ||
325 | complete(xfer->done); | ||
326 | } | ||
327 | |||
328 | static void byte_swap_64(u64 *data_in, u64 *data_out, u32 len) | ||
329 | { | ||
330 | int i; | ||
331 | |||
332 | for (i = 0; i < len / 8; i++) | ||
333 | data_out[i] = cpu_to_be64(le64_to_cpu(data_in[i])); | ||
334 | } | ||
335 | |||
336 | static int wm0010_boot(struct snd_soc_codec *codec) | ||
337 | { | ||
338 | struct spi_device *spi = to_spi_device(codec->dev); | ||
339 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
340 | unsigned long flags; | ||
341 | struct list_head xfer_list; | ||
342 | struct wm0010_boot_xfer *xfer; | ||
343 | int ret; | ||
344 | struct completion done; | ||
345 | const struct firmware *fw; | ||
346 | const struct dfw_binrec *rec; | ||
347 | struct spi_message m; | ||
348 | struct spi_transfer t; | ||
349 | struct dfw_pllrec pll_rec; | ||
350 | u32 *img, *p; | ||
351 | u64 *img_swap; | ||
352 | u8 *out; | ||
353 | u32 len, offset; | ||
354 | int i; | ||
355 | |||
356 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
357 | if (wm0010->state != WM0010_POWER_OFF) | ||
358 | dev_warn(wm0010->dev, "DSP already powered up!\n"); | ||
359 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
360 | |||
361 | if (wm0010->sysclk > 26000000) { | ||
362 | dev_err(codec->dev, "Max DSP clock frequency is 26MHz\n"); | ||
363 | ret = -ECANCELED; | ||
364 | goto err; | ||
365 | } | ||
366 | |||
367 | INIT_LIST_HEAD(&xfer_list); | ||
368 | |||
369 | mutex_lock(&wm0010->lock); | ||
370 | wm0010->pll_running = false; | ||
371 | |||
372 | dev_dbg(codec->dev, "max_spi_freq: %d\n", wm0010->max_spi_freq); | ||
373 | |||
374 | ret = regulator_bulk_enable(ARRAY_SIZE(wm0010->core_supplies), | ||
375 | wm0010->core_supplies); | ||
376 | if (ret != 0) { | ||
377 | dev_err(&spi->dev, "Failed to enable core supplies: %d\n", | ||
378 | ret); | ||
379 | mutex_unlock(&wm0010->lock); | ||
380 | goto err; | ||
381 | } | ||
382 | |||
383 | ret = regulator_enable(wm0010->dbvdd); | ||
384 | if (ret != 0) { | ||
385 | dev_err(&spi->dev, "Failed to enable DBVDD: %d\n", ret); | ||
386 | goto err_core; | ||
387 | } | ||
388 | |||
389 | /* Release reset */ | ||
390 | gpio_set_value(wm0010->gpio_reset, !wm0010->gpio_reset_value); | ||
391 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
392 | wm0010->state = WM0010_OUT_OF_RESET; | ||
393 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
394 | |||
395 | /* First the bootloader */ | ||
396 | ret = request_firmware(&fw, "wm0010_stage2.bin", codec->dev); | ||
397 | if (ret != 0) { | ||
398 | dev_err(codec->dev, "Failed to request stage2 loader: %d\n", | ||
399 | ret); | ||
400 | goto abort; | ||
401 | } | ||
402 | |||
403 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
404 | msecs_to_jiffies(10))) | ||
405 | dev_err(codec->dev, "Failed to get interrupt from DSP\n"); | ||
406 | |||
407 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
408 | wm0010->state = WM0010_BOOTROM; | ||
409 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
410 | |||
411 | dev_dbg(codec->dev, "Downloading %d byte stage 2 loader\n", fw->size); | ||
412 | |||
413 | /* Copy to local buffer first as vmalloc causes problems for dma */ | ||
414 | img = kzalloc(fw->size, GFP_KERNEL); | ||
415 | if (!img) { | ||
416 | dev_err(codec->dev, "Failed to allocate image buffer\n"); | ||
417 | goto abort; | ||
418 | } | ||
419 | |||
420 | out = kzalloc(fw->size, GFP_KERNEL); | ||
421 | if (!out) { | ||
422 | dev_err(codec->dev, "Failed to allocate output buffer\n"); | ||
423 | goto abort; | ||
424 | } | ||
425 | |||
426 | memcpy(img, &fw->data[0], fw->size); | ||
427 | |||
428 | spi_message_init(&m); | ||
429 | memset(&t, 0, sizeof(t)); | ||
430 | t.rx_buf = out; | ||
431 | t.tx_buf = img; | ||
432 | t.len = fw->size; | ||
433 | t.bits_per_word = 8; | ||
434 | t.speed_hz = wm0010->sysclk / 10; | ||
435 | spi_message_add_tail(&t, &m); | ||
436 | |||
437 | dev_dbg(codec->dev, "Starting initial download at %dHz\n", | ||
438 | t.speed_hz); | ||
439 | |||
440 | ret = spi_sync(spi, &m); | ||
441 | if (ret != 0) { | ||
442 | dev_err(codec->dev, "Initial download failed: %d\n", ret); | ||
443 | goto abort; | ||
444 | } | ||
445 | |||
446 | /* Look for errors from the boot ROM */ | ||
447 | for (i = 0; i < fw->size; i++) { | ||
448 | if (out[i] != 0x55) { | ||
449 | ret = -EBUSY; | ||
450 | dev_err(codec->dev, "Boot ROM error: %x in %d\n", | ||
451 | out[i], i); | ||
452 | wm0010_mark_boot_failure(wm0010); | ||
453 | goto abort; | ||
454 | } | ||
455 | } | ||
456 | |||
457 | release_firmware(fw); | ||
458 | kfree(img); | ||
459 | kfree(out); | ||
460 | |||
461 | if (!wait_for_completion_timeout(&wm0010->boot_completion, | ||
462 | msecs_to_jiffies(10))) | ||
463 | dev_err(codec->dev, "Failed to get interrupt from DSP loader.\n"); | ||
464 | |||
465 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
466 | wm0010->state = WM0010_STAGE2; | ||
467 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
468 | |||
469 | /* Only initialise PLL if max_spi_freq initialised */ | ||
470 | if (wm0010->max_spi_freq) { | ||
471 | |||
472 | /* Initialise a PLL record */ | ||
473 | memset(&pll_rec, 0, sizeof(pll_rec)); | ||
474 | pll_rec.command = DFW_CMD_PLL; | ||
475 | pll_rec.length = (sizeof(pll_rec) - 8); | ||
476 | |||
477 | /* On wm0010 only the CLKCTRL1 value is used */ | ||
478 | pll_rec.clkctrl1 = wm0010->pll_clkctrl1; | ||
479 | |||
480 | len = pll_rec.length + 8; | ||
481 | out = kzalloc(len, GFP_KERNEL); | ||
482 | if (!out) { | ||
483 | dev_err(codec->dev, | ||
484 | "Failed to allocate RX buffer\n"); | ||
485 | goto abort; | ||
486 | } | ||
487 | |||
488 | img_swap = kzalloc(len, GFP_KERNEL); | ||
489 | if (!img_swap) { | ||
490 | dev_err(codec->dev, | ||
491 | "Failed to allocate image buffer\n"); | ||
492 | goto abort; | ||
493 | } | ||
494 | |||
495 | /* We need to re-order for 0010 */ | ||
496 | byte_swap_64((u64 *)&pll_rec, img_swap, len); | ||
497 | |||
498 | spi_message_init(&m); | ||
499 | memset(&t, 0, sizeof(t)); | ||
500 | t.rx_buf = out; | ||
501 | t.tx_buf = img_swap; | ||
502 | t.len = len; | ||
503 | t.bits_per_word = 8; | ||
504 | t.speed_hz = wm0010->sysclk / 6; | ||
505 | spi_message_add_tail(&t, &m); | ||
506 | |||
507 | ret = spi_sync(spi, &m); | ||
508 | if (ret != 0) { | ||
509 | dev_err(codec->dev, "First PLL write failed: %d\n", ret); | ||
510 | goto abort; | ||
511 | } | ||
512 | |||
513 | /* Use a second send of the message to get the return status */ | ||
514 | ret = spi_sync(spi, &m); | ||
515 | if (ret != 0) { | ||
516 | dev_err(codec->dev, "Second PLL write failed: %d\n", ret); | ||
517 | goto abort; | ||
518 | } | ||
519 | |||
520 | p = (u32 *)out; | ||
521 | |||
522 | /* Look for PLL active code from the DSP */ | ||
523 | for (i = 0; i < len / 4; i++) { | ||
524 | if (*p == 0x0e00ed0f) { | ||
525 | dev_dbg(codec->dev, "PLL packet received\n"); | ||
526 | wm0010->pll_running = true; | ||
527 | break; | ||
528 | } | ||
529 | p++; | ||
530 | } | ||
531 | |||
532 | kfree(img_swap); | ||
533 | kfree(out); | ||
534 | } else | ||
535 | dev_dbg(codec->dev, "Not enabling DSP PLL."); | ||
536 | |||
537 | ret = request_firmware(&fw, "wm0010.dfw", codec->dev); | ||
538 | if (ret != 0) { | ||
539 | dev_err(codec->dev, "Failed to request application: %d\n", | ||
540 | ret); | ||
541 | goto abort; | ||
542 | } | ||
543 | |||
544 | rec = (const struct dfw_binrec *)fw->data; | ||
545 | offset = 0; | ||
546 | wm0010->boot_done = 0; | ||
547 | wm0010->boot_failed = false; | ||
548 | BUG_ON(!list_empty(&xfer_list)); | ||
549 | init_completion(&done); | ||
550 | |||
551 | /* First record should be INFO */ | ||
552 | if (rec->command != DFW_CMD_INFO) { | ||
553 | dev_err(codec->dev, "First record not INFO\r\n"); | ||
554 | goto abort; | ||
555 | } | ||
556 | |||
557 | /* Check it's a 0010 file */ | ||
558 | if (rec->data[0] != DEVICE_ID_WM0010) { | ||
559 | dev_err(codec->dev, "Not a WM0010 firmware file.\r\n"); | ||
560 | goto abort; | ||
561 | } | ||
562 | |||
563 | /* Skip the info record as we don't need to send it */ | ||
564 | offset += ((rec->length) + 8); | ||
565 | rec = (void *)&rec->data[rec->length]; | ||
566 | |||
567 | while (offset < fw->size) { | ||
568 | dev_dbg(codec->dev, | ||
569 | "Packet: command %d, data length = 0x%x\r\n", | ||
570 | rec->command, rec->length); | ||
571 | len = rec->length + 8; | ||
572 | |||
573 | out = kzalloc(len, GFP_KERNEL); | ||
574 | if (!out) { | ||
575 | dev_err(codec->dev, | ||
576 | "Failed to allocate RX buffer\n"); | ||
577 | goto abort; | ||
578 | } | ||
579 | |||
580 | img_swap = kzalloc(len, GFP_KERNEL); | ||
581 | if (!img_swap) { | ||
582 | dev_err(codec->dev, | ||
583 | "Failed to allocate image buffer\n"); | ||
584 | goto abort; | ||
585 | } | ||
586 | |||
587 | /* We need to re-order for 0010 */ | ||
588 | byte_swap_64((u64 *)&rec->command, img_swap, len); | ||
589 | |||
590 | xfer = kzalloc(sizeof(*xfer), GFP_KERNEL); | ||
591 | if (!xfer) { | ||
592 | dev_err(codec->dev, "Failed to allocate xfer\n"); | ||
593 | goto abort; | ||
594 | } | ||
595 | |||
596 | xfer->codec = codec; | ||
597 | list_add_tail(&xfer->list, &xfer_list); | ||
598 | |||
599 | spi_message_init(&xfer->m); | ||
600 | xfer->m.complete = wm0010_boot_xfer_complete; | ||
601 | xfer->m.context = xfer; | ||
602 | xfer->t.tx_buf = img_swap; | ||
603 | xfer->t.rx_buf = out; | ||
604 | xfer->t.len = len; | ||
605 | xfer->t.bits_per_word = 8; | ||
606 | |||
607 | if (!wm0010->pll_running) { | ||
608 | xfer->t.speed_hz = wm0010->sysclk / 6; | ||
609 | } else { | ||
610 | xfer->t.speed_hz = wm0010->max_spi_freq; | ||
611 | |||
612 | if (wm0010->board_max_spi_speed && | ||
613 | (wm0010->board_max_spi_speed < wm0010->max_spi_freq)) | ||
614 | xfer->t.speed_hz = wm0010->board_max_spi_speed; | ||
615 | } | ||
616 | |||
617 | /* Store max usable spi frequency for later use */ | ||
618 | wm0010->max_spi_freq = xfer->t.speed_hz; | ||
619 | |||
620 | spi_message_add_tail(&xfer->t, &xfer->m); | ||
621 | |||
622 | offset += ((rec->length) + 8); | ||
623 | rec = (void *)&rec->data[rec->length]; | ||
624 | |||
625 | if (offset >= fw->size) { | ||
626 | dev_dbg(codec->dev, "All transfers scheduled\n"); | ||
627 | xfer->done = &done; | ||
628 | } | ||
629 | |||
630 | ret = spi_async(spi, &xfer->m); | ||
631 | if (ret != 0) { | ||
632 | dev_err(codec->dev, "Write failed: %d\n", ret); | ||
633 | goto abort; | ||
634 | } | ||
635 | |||
636 | if (wm0010->boot_failed) | ||
637 | goto abort; | ||
638 | } | ||
639 | |||
640 | wait_for_completion(&done); | ||
641 | |||
642 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
643 | wm0010->state = WM0010_FIRMWARE; | ||
644 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
645 | |||
646 | mutex_unlock(&wm0010->lock); | ||
647 | |||
648 | release_firmware(fw); | ||
649 | |||
650 | while (!list_empty(&xfer_list)) { | ||
651 | xfer = list_first_entry(&xfer_list, struct wm0010_boot_xfer, | ||
652 | list); | ||
653 | kfree(xfer->t.rx_buf); | ||
654 | kfree(xfer->t.tx_buf); | ||
655 | list_del(&xfer->list); | ||
656 | kfree(xfer); | ||
657 | } | ||
658 | |||
659 | return 0; | ||
660 | |||
661 | abort: | ||
662 | /* Put the chip back into reset */ | ||
663 | wm0010_halt(codec); | ||
664 | mutex_unlock(&wm0010->lock); | ||
665 | return ret; | ||
666 | err_core: | ||
667 | regulator_bulk_disable(ARRAY_SIZE(wm0010->core_supplies), | ||
668 | wm0010->core_supplies); | ||
669 | err: | ||
670 | return ret; | ||
671 | } | ||
672 | |||
673 | static int wm0010_set_bias_level(struct snd_soc_codec *codec, | ||
674 | enum snd_soc_bias_level level) | ||
675 | { | ||
676 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
677 | |||
678 | switch (level) { | ||
679 | case SND_SOC_BIAS_ON: | ||
680 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) | ||
681 | wm0010_boot(codec); | ||
682 | break; | ||
683 | case SND_SOC_BIAS_PREPARE: | ||
684 | break; | ||
685 | case SND_SOC_BIAS_STANDBY: | ||
686 | if (codec->dapm.bias_level == SND_SOC_BIAS_PREPARE) { | ||
687 | mutex_lock(&wm0010->lock); | ||
688 | wm0010_halt(codec); | ||
689 | mutex_unlock(&wm0010->lock); | ||
690 | } | ||
691 | break; | ||
692 | case SND_SOC_BIAS_OFF: | ||
693 | break; | ||
694 | } | ||
695 | |||
696 | codec->dapm.bias_level = level; | ||
697 | |||
698 | return 0; | ||
699 | } | ||
700 | |||
701 | static int wm0010_set_sysclk(struct snd_soc_codec *codec, int source, | ||
702 | int clk_id, unsigned int freq, int dir) | ||
703 | { | ||
704 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
705 | unsigned int i; | ||
706 | |||
707 | wm0010->sysclk = freq; | ||
708 | |||
709 | if (freq < pll_clock_map[ARRAY_SIZE(pll_clock_map)-1].max_sysclk) { | ||
710 | wm0010->max_spi_freq = 0; | ||
711 | } else { | ||
712 | for (i = 0; i < ARRAY_SIZE(pll_clock_map); i++) | ||
713 | if (freq >= pll_clock_map[i].max_sysclk) | ||
714 | break; | ||
715 | |||
716 | wm0010->max_spi_freq = pll_clock_map[i].max_pll_spi_speed; | ||
717 | wm0010->pll_clkctrl1 = pll_clock_map[i].pll_clkctrl1; | ||
718 | } | ||
719 | |||
720 | return 0; | ||
721 | } | ||
722 | |||
723 | static int wm0010_probe(struct snd_soc_codec *codec); | ||
724 | |||
725 | static struct snd_soc_codec_driver soc_codec_dev_wm0010 = { | ||
726 | .probe = wm0010_probe, | ||
727 | .set_bias_level = wm0010_set_bias_level, | ||
728 | .set_sysclk = wm0010_set_sysclk, | ||
729 | .idle_bias_off = true, | ||
730 | |||
731 | .dapm_widgets = wm0010_dapm_widgets, | ||
732 | .num_dapm_widgets = ARRAY_SIZE(wm0010_dapm_widgets), | ||
733 | .dapm_routes = wm0010_dapm_routes, | ||
734 | .num_dapm_routes = ARRAY_SIZE(wm0010_dapm_routes), | ||
735 | }; | ||
736 | |||
737 | #define WM0010_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) | ||
738 | #define WM0010_FORMATS (SNDRV_PCM_FMTBIT_S8 | SNDRV_PCM_FMTBIT_S16_LE |\ | ||
739 | SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE |\ | ||
740 | SNDRV_PCM_FMTBIT_S32_LE) | ||
741 | |||
742 | static struct snd_soc_dai_driver wm0010_dai[] = { | ||
743 | { | ||
744 | .name = "wm0010-sdi1", | ||
745 | .playback = { | ||
746 | .stream_name = "SDI1 Playback", | ||
747 | .channels_min = 1, | ||
748 | .channels_max = 2, | ||
749 | .rates = WM0010_RATES, | ||
750 | .formats = WM0010_FORMATS, | ||
751 | }, | ||
752 | .capture = { | ||
753 | .stream_name = "SDI1 Capture", | ||
754 | .channels_min = 1, | ||
755 | .channels_max = 2, | ||
756 | .rates = WM0010_RATES, | ||
757 | .formats = WM0010_FORMATS, | ||
758 | }, | ||
759 | }, | ||
760 | { | ||
761 | .name = "wm0010-sdi2", | ||
762 | .playback = { | ||
763 | .stream_name = "SDI2 Playback", | ||
764 | .channels_min = 1, | ||
765 | .channels_max = 2, | ||
766 | .rates = WM0010_RATES, | ||
767 | .formats = WM0010_FORMATS, | ||
768 | }, | ||
769 | .capture = { | ||
770 | .stream_name = "SDI2 Capture", | ||
771 | .channels_min = 1, | ||
772 | .channels_max = 2, | ||
773 | .rates = WM0010_RATES, | ||
774 | .formats = WM0010_FORMATS, | ||
775 | }, | ||
776 | }, | ||
777 | }; | ||
778 | |||
779 | static irqreturn_t wm0010_irq(int irq, void *data) | ||
780 | { | ||
781 | struct wm0010_priv *wm0010 = data; | ||
782 | |||
783 | switch (wm0010->state) { | ||
784 | case WM0010_POWER_OFF: | ||
785 | case WM0010_OUT_OF_RESET: | ||
786 | case WM0010_BOOTROM: | ||
787 | case WM0010_STAGE2: | ||
788 | spin_lock(&wm0010->irq_lock); | ||
789 | complete(&wm0010->boot_completion); | ||
790 | spin_unlock(&wm0010->irq_lock); | ||
791 | return IRQ_HANDLED; | ||
792 | default: | ||
793 | return IRQ_NONE; | ||
794 | } | ||
795 | |||
796 | return IRQ_NONE; | ||
797 | } | ||
798 | |||
799 | static int wm0010_probe(struct snd_soc_codec *codec) | ||
800 | { | ||
801 | struct wm0010_priv *wm0010 = snd_soc_codec_get_drvdata(codec); | ||
802 | |||
803 | wm0010->codec = codec; | ||
804 | |||
805 | return 0; | ||
806 | } | ||
807 | |||
808 | static int __devinit wm0010_spi_probe(struct spi_device *spi) | ||
809 | { | ||
810 | unsigned long flags; | ||
811 | unsigned long gpio_flags; | ||
812 | int ret; | ||
813 | int trigger; | ||
814 | int irq; | ||
815 | struct wm0010_priv *wm0010; | ||
816 | |||
817 | wm0010 = devm_kzalloc(&spi->dev, sizeof(*wm0010), | ||
818 | GFP_KERNEL); | ||
819 | if (!wm0010) | ||
820 | return -ENOMEM; | ||
821 | |||
822 | mutex_init(&wm0010->lock); | ||
823 | spin_lock_init(&wm0010->irq_lock); | ||
824 | |||
825 | spi_set_drvdata(spi, wm0010); | ||
826 | wm0010->dev = &spi->dev; | ||
827 | |||
828 | if (dev_get_platdata(&spi->dev)) | ||
829 | memcpy(&wm0010->pdata, dev_get_platdata(&spi->dev), | ||
830 | sizeof(wm0010->pdata)); | ||
831 | |||
832 | init_completion(&wm0010->boot_completion); | ||
833 | |||
834 | wm0010->core_supplies[0].supply = "AVDD"; | ||
835 | wm0010->core_supplies[1].supply = "DCVDD"; | ||
836 | ret = devm_regulator_bulk_get(wm0010->dev, ARRAY_SIZE(wm0010->core_supplies), | ||
837 | wm0010->core_supplies); | ||
838 | if (ret != 0) { | ||
839 | dev_err(wm0010->dev, "Failed to obtain core supplies: %d\n", | ||
840 | ret); | ||
841 | return ret; | ||
842 | } | ||
843 | |||
844 | wm0010->dbvdd = devm_regulator_get(wm0010->dev, "DBVDD"); | ||
845 | if (IS_ERR(wm0010->dbvdd)) { | ||
846 | ret = PTR_ERR(wm0010->dbvdd); | ||
847 | dev_err(wm0010->dev, "Failed to obtain DBVDD: %d\n", ret); | ||
848 | return ret; | ||
849 | } | ||
850 | |||
851 | if (wm0010->pdata.gpio_reset) { | ||
852 | wm0010->gpio_reset = wm0010->pdata.gpio_reset; | ||
853 | |||
854 | if (wm0010->pdata.reset_active_high) | ||
855 | wm0010->gpio_reset_value = 1; | ||
856 | else | ||
857 | wm0010->gpio_reset_value = 0; | ||
858 | |||
859 | if (wm0010->gpio_reset_value) | ||
860 | gpio_flags = GPIOF_OUT_INIT_HIGH; | ||
861 | else | ||
862 | gpio_flags = GPIOF_OUT_INIT_LOW; | ||
863 | |||
864 | ret = devm_gpio_request_one(wm0010->dev, wm0010->gpio_reset, | ||
865 | gpio_flags, "wm0010 reset"); | ||
866 | if (ret < 0) { | ||
867 | dev_err(wm0010->dev, | ||
868 | "Failed to request GPIO for DSP reset: %d\n", | ||
869 | ret); | ||
870 | return ret; | ||
871 | } | ||
872 | } else { | ||
873 | dev_err(wm0010->dev, "No reset GPIO configured\n"); | ||
874 | return -EINVAL; | ||
875 | } | ||
876 | |||
877 | irq = spi->irq; | ||
878 | if (wm0010->pdata.irq_flags) | ||
879 | trigger = wm0010->pdata.irq_flags; | ||
880 | else | ||
881 | trigger = IRQF_TRIGGER_FALLING; | ||
882 | trigger |= IRQF_ONESHOT; | ||
883 | |||
884 | ret = request_threaded_irq(irq, NULL, wm0010_irq, trigger, | ||
885 | "wm0010", wm0010); | ||
886 | if (ret) { | ||
887 | dev_err(wm0010->dev, "Failed to request IRQ %d: %d\n", | ||
888 | irq, ret); | ||
889 | return ret; | ||
890 | } | ||
891 | wm0010->irq = irq; | ||
892 | |||
893 | if (spi->max_speed_hz) | ||
894 | wm0010->board_max_spi_speed = spi->max_speed_hz; | ||
895 | else | ||
896 | wm0010->board_max_spi_speed = 0; | ||
897 | |||
898 | spin_lock_irqsave(&wm0010->irq_lock, flags); | ||
899 | wm0010->state = WM0010_POWER_OFF; | ||
900 | spin_unlock_irqrestore(&wm0010->irq_lock, flags); | ||
901 | |||
902 | ret = snd_soc_register_codec(&spi->dev, | ||
903 | &soc_codec_dev_wm0010, wm0010_dai, | ||
904 | ARRAY_SIZE(wm0010_dai)); | ||
905 | if (ret < 0) | ||
906 | return ret; | ||
907 | |||
908 | return 0; | ||
909 | } | ||
910 | |||
911 | static int __devexit wm0010_spi_remove(struct spi_device *spi) | ||
912 | { | ||
913 | struct wm0010_priv *wm0010 = spi_get_drvdata(spi); | ||
914 | |||
915 | snd_soc_unregister_codec(&spi->dev); | ||
916 | |||
917 | if (wm0010->gpio_reset) { | ||
918 | /* Remember to put chip back into reset */ | ||
919 | gpio_set_value(wm0010->gpio_reset, wm0010->gpio_reset_value); | ||
920 | } | ||
921 | |||
922 | if (wm0010->irq) | ||
923 | free_irq(wm0010->irq, wm0010); | ||
924 | |||
925 | return 0; | ||
926 | } | ||
927 | |||
928 | static struct spi_driver wm0010_spi_driver = { | ||
929 | .driver = { | ||
930 | .name = "wm0010", | ||
931 | .bus = &spi_bus_type, | ||
932 | .owner = THIS_MODULE, | ||
933 | }, | ||
934 | .probe = wm0010_spi_probe, | ||
935 | .remove = __devexit_p(wm0010_spi_remove), | ||
936 | }; | ||
937 | |||
938 | module_spi_driver(wm0010_spi_driver); | ||
939 | |||
940 | MODULE_DESCRIPTION("ASoC WM0010 driver"); | ||
941 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
942 | MODULE_LICENSE("GPL"); | ||
diff --git a/sound/soc/codecs/wm2000.c b/sound/soc/codecs/wm2000.c index 3fd5b29dc933..89cd6fcad015 100644 --- a/sound/soc/codecs/wm2000.c +++ b/sound/soc/codecs/wm2000.c | |||
@@ -858,17 +858,7 @@ static struct i2c_driver wm2000_i2c_driver = { | |||
858 | .id_table = wm2000_i2c_id, | 858 | .id_table = wm2000_i2c_id, |
859 | }; | 859 | }; |
860 | 860 | ||
861 | static int __init wm2000_init(void) | 861 | module_i2c_driver(wm2000_i2c_driver); |
862 | { | ||
863 | return i2c_add_driver(&wm2000_i2c_driver); | ||
864 | } | ||
865 | module_init(wm2000_init); | ||
866 | |||
867 | static void __exit wm2000_exit(void) | ||
868 | { | ||
869 | i2c_del_driver(&wm2000_i2c_driver); | ||
870 | } | ||
871 | module_exit(wm2000_exit); | ||
872 | 862 | ||
873 | MODULE_DESCRIPTION("ASoC WM2000 driver"); | 863 | MODULE_DESCRIPTION("ASoC WM2000 driver"); |
874 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); | 864 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfonmicro.com>"); |
diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index 32682c1b7cde..71debd0a3822 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c | |||
@@ -2270,17 +2270,7 @@ static struct i2c_driver wm2200_i2c_driver = { | |||
2270 | .id_table = wm2200_i2c_id, | 2270 | .id_table = wm2200_i2c_id, |
2271 | }; | 2271 | }; |
2272 | 2272 | ||
2273 | static int __init wm2200_modinit(void) | 2273 | module_i2c_driver(wm2200_i2c_driver); |
2274 | { | ||
2275 | return i2c_add_driver(&wm2200_i2c_driver); | ||
2276 | } | ||
2277 | module_init(wm2200_modinit); | ||
2278 | |||
2279 | static void __exit wm2200_exit(void) | ||
2280 | { | ||
2281 | i2c_del_driver(&wm2200_i2c_driver); | ||
2282 | } | ||
2283 | module_exit(wm2200_exit); | ||
2284 | 2274 | ||
2285 | MODULE_DESCRIPTION("ASoC WM2200 driver"); | 2275 | MODULE_DESCRIPTION("ASoC WM2200 driver"); |
2286 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 2276 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index e33d327396ad..e2fb07ee68a7 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c | |||
@@ -274,11 +274,36 @@ ARIZONA_MIXER_ENUMS(ASRC1R, ARIZONA_ASRC1RMIX_INPUT_1_SOURCE); | |||
274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); | 274 | ARIZONA_MIXER_ENUMS(ASRC2L, ARIZONA_ASRC2LMIX_INPUT_1_SOURCE); |
275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); | 275 | ARIZONA_MIXER_ENUMS(ASRC2R, ARIZONA_ASRC2RMIX_INPUT_1_SOURCE); |
276 | 276 | ||
277 | |||
278 | static const char *wm5102_aec_loopback_texts[] = { | ||
279 | "HPOUT1L", "HPOUT1R", "HPOUT2L", "HPOUT2R", "EPOUT", | ||
280 | "SPKOUTL", "SPKOUTR", "SPKDAT1L", "SPKDAT1R", | ||
281 | }; | ||
282 | |||
283 | static const unsigned int wm5102_aec_loopback_values[] = { | ||
284 | 0, 1, 2, 3, 4, 6, 7, 8, 9, | ||
285 | }; | ||
286 | |||
287 | static const struct soc_enum wm5102_aec_loopback = | ||
288 | SOC_VALUE_ENUM_SINGLE(ARIZONA_DAC_AEC_CONTROL_1, | ||
289 | ARIZONA_AEC_LOOPBACK_SRC_SHIFT, | ||
290 | ARIZONA_AEC_LOOPBACK_SRC_MASK, | ||
291 | ARRAY_SIZE(wm5102_aec_loopback_texts), | ||
292 | wm5102_aec_loopback_texts, | ||
293 | wm5102_aec_loopback_values); | ||
294 | |||
295 | static const struct snd_kcontrol_new wm5102_aec_loopback_mux = | ||
296 | SOC_DAPM_VALUE_ENUM("AEC Loopback", wm5102_aec_loopback); | ||
297 | |||
277 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { | 298 | static const struct snd_soc_dapm_widget wm5102_dapm_widgets[] = { |
278 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | 299 | SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, |
279 | 0, NULL, 0), | 300 | 0, NULL, 0), |
280 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 301 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
281 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 302 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
303 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | ||
304 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), | ||
305 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, | ||
306 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), | ||
282 | 307 | ||
283 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 308 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), |
284 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), |
@@ -421,6 +446,9 @@ SND_SOC_DAPM_AIF_IN("AIF3RX1", NULL, 0, | |||
421 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, | 446 | SND_SOC_DAPM_AIF_IN("AIF3RX2", NULL, 0, |
422 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), | 447 | ARIZONA_AIF3_RX_ENABLES, ARIZONA_AIF3RX2_ENA_SHIFT, 0), |
423 | 448 | ||
449 | SND_SOC_DAPM_VALUE_MUX("AEC Loopback", ARIZONA_DAC_AEC_CONTROL_1, | ||
450 | ARIZONA_AEC_LOOPBACK_ENA, 0, &wm5102_aec_loopback_mux), | ||
451 | |||
424 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, | 452 | SND_SOC_DAPM_PGA_E("OUT1L", ARIZONA_OUTPUT_ENABLES_1, |
425 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, | 453 | ARIZONA_OUT1L_ENA_SHIFT, 0, NULL, 0, arizona_out_ev, |
426 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), | 454 | SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), |
@@ -516,6 +544,7 @@ SND_SOC_DAPM_OUTPUT("SPKDAT1R"), | |||
516 | { name, "Noise Generator", "Noise Generator" }, \ | 544 | { name, "Noise Generator", "Noise Generator" }, \ |
517 | { name, "Tone Generator 1", "Tone Generator 1" }, \ | 545 | { name, "Tone Generator 1", "Tone Generator 1" }, \ |
518 | { name, "Tone Generator 2", "Tone Generator 2" }, \ | 546 | { name, "Tone Generator 2", "Tone Generator 2" }, \ |
547 | { name, "AEC", "AEC Loopback" }, \ | ||
519 | { name, "IN1L", "IN1L PGA" }, \ | 548 | { name, "IN1L", "IN1L PGA" }, \ |
520 | { name, "IN1R", "IN1R PGA" }, \ | 549 | { name, "IN1R", "IN1R PGA" }, \ |
521 | { name, "IN2L", "IN2L PGA" }, \ | 550 | { name, "IN2L", "IN2L PGA" }, \ |
@@ -681,21 +710,30 @@ static const struct snd_soc_dapm_route wm5102_dapm_routes[] = { | |||
681 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), | 710 | ARIZONA_MIXER_ROUTES("ASRC2L", "ASRC2L"), |
682 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), | 711 | ARIZONA_MIXER_ROUTES("ASRC2R", "ASRC2R"), |
683 | 712 | ||
713 | { "AEC Loopback", "HPOUT1L", "OUT1L" }, | ||
714 | { "AEC Loopback", "HPOUT1R", "OUT1R" }, | ||
684 | { "HPOUT1L", NULL, "OUT1L" }, | 715 | { "HPOUT1L", NULL, "OUT1L" }, |
685 | { "HPOUT1R", NULL, "OUT1R" }, | 716 | { "HPOUT1R", NULL, "OUT1R" }, |
686 | 717 | ||
718 | { "AEC Loopback", "HPOUT2L", "OUT2L" }, | ||
719 | { "AEC Loopback", "HPOUT2R", "OUT2R" }, | ||
687 | { "HPOUT2L", NULL, "OUT2L" }, | 720 | { "HPOUT2L", NULL, "OUT2L" }, |
688 | { "HPOUT2R", NULL, "OUT2R" }, | 721 | { "HPOUT2R", NULL, "OUT2R" }, |
689 | 722 | ||
723 | { "AEC Loopback", "EPOUT", "OUT3L" }, | ||
690 | { "EPOUTN", NULL, "OUT3L" }, | 724 | { "EPOUTN", NULL, "OUT3L" }, |
691 | { "EPOUTP", NULL, "OUT3L" }, | 725 | { "EPOUTP", NULL, "OUT3L" }, |
692 | 726 | ||
727 | { "AEC Loopback", "SPKOUTL", "OUT4L" }, | ||
693 | { "SPKOUTLN", NULL, "OUT4L" }, | 728 | { "SPKOUTLN", NULL, "OUT4L" }, |
694 | { "SPKOUTLP", NULL, "OUT4L" }, | 729 | { "SPKOUTLP", NULL, "OUT4L" }, |
695 | 730 | ||
731 | { "AEC Loopback", "SPKOUTR", "OUT4R" }, | ||
696 | { "SPKOUTRN", NULL, "OUT4R" }, | 732 | { "SPKOUTRN", NULL, "OUT4R" }, |
697 | { "SPKOUTRP", NULL, "OUT4R" }, | 733 | { "SPKOUTRP", NULL, "OUT4R" }, |
698 | 734 | ||
735 | { "AEC Loopback", "SPKDAT1L", "OUT5L" }, | ||
736 | { "AEC Loopback", "SPKDAT1R", "OUT5R" }, | ||
699 | { "SPKDAT1L", NULL, "OUT5L" }, | 737 | { "SPKDAT1L", NULL, "OUT5L" }, |
700 | { "SPKDAT1R", NULL, "OUT5R" }, | 738 | { "SPKDAT1R", NULL, "OUT5R" }, |
701 | }; | 739 | }; |
diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 01ebbcc5c6a4..57c7d9c0aadb 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c | |||
@@ -305,6 +305,10 @@ SND_SOC_DAPM_SUPPLY("SYSCLK", ARIZONA_SYSTEM_CLOCK_1, ARIZONA_SYSCLK_ENA_SHIFT, | |||
305 | 0, NULL, 0), | 305 | 0, NULL, 0), |
306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, | 306 | SND_SOC_DAPM_SUPPLY("ASYNCCLK", ARIZONA_ASYNC_CLOCK_1, |
307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), | 307 | ARIZONA_ASYNC_CLK_ENA_SHIFT, 0, NULL, 0), |
308 | SND_SOC_DAPM_SUPPLY("OPCLK", ARIZONA_OUTPUT_SYSTEM_CLOCK, | ||
309 | ARIZONA_OPCLK_ENA_SHIFT, 0, NULL, 0), | ||
310 | SND_SOC_DAPM_SUPPLY("ASYNCOPCLK", ARIZONA_OUTPUT_ASYNC_CLOCK, | ||
311 | ARIZONA_OPCLK_ASYNC_ENA_SHIFT, 0, NULL, 0), | ||
308 | 312 | ||
309 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), | 313 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD2", 0), |
310 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), | 314 | SND_SOC_DAPM_REGULATOR_SUPPLY("DBVDD3", 0), |
diff --git a/sound/soc/codecs/wm8770.c b/sound/soc/codecs/wm8770.c index a5127b4ff9e1..c7c0034d3966 100644 --- a/sound/soc/codecs/wm8770.c +++ b/sound/soc/codecs/wm8770.c | |||
@@ -724,24 +724,7 @@ static struct spi_driver wm8770_spi_driver = { | |||
724 | .remove = __devexit_p(wm8770_spi_remove) | 724 | .remove = __devexit_p(wm8770_spi_remove) |
725 | }; | 725 | }; |
726 | 726 | ||
727 | static int __init wm8770_modinit(void) | 727 | module_spi_driver(wm8770_spi_driver); |
728 | { | ||
729 | int ret = 0; | ||
730 | |||
731 | ret = spi_register_driver(&wm8770_spi_driver); | ||
732 | if (ret) { | ||
733 | printk(KERN_ERR "Failed to register wm8770 SPI driver: %d\n", | ||
734 | ret); | ||
735 | } | ||
736 | return ret; | ||
737 | } | ||
738 | module_init(wm8770_modinit); | ||
739 | |||
740 | static void __exit wm8770_exit(void) | ||
741 | { | ||
742 | spi_unregister_driver(&wm8770_spi_driver); | ||
743 | } | ||
744 | module_exit(wm8770_exit); | ||
745 | 728 | ||
746 | MODULE_DESCRIPTION("ASoC WM8770 driver"); | 729 | MODULE_DESCRIPTION("ASoC WM8770 driver"); |
747 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); | 730 | MODULE_AUTHOR("Dimitris Papastamos <dp@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 73f1c8d7bafb..839414f9e2ed 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -2241,23 +2241,7 @@ static struct i2c_driver wm8903_i2c_driver = { | |||
2241 | .id_table = wm8903_i2c_id, | 2241 | .id_table = wm8903_i2c_id, |
2242 | }; | 2242 | }; |
2243 | 2243 | ||
2244 | static int __init wm8903_modinit(void) | 2244 | module_i2c_driver(wm8903_i2c_driver); |
2245 | { | ||
2246 | int ret = 0; | ||
2247 | ret = i2c_add_driver(&wm8903_i2c_driver); | ||
2248 | if (ret != 0) { | ||
2249 | printk(KERN_ERR "Failed to register wm8903 I2C driver: %d\n", | ||
2250 | ret); | ||
2251 | } | ||
2252 | return ret; | ||
2253 | } | ||
2254 | module_init(wm8903_modinit); | ||
2255 | |||
2256 | static void __exit wm8903_exit(void) | ||
2257 | { | ||
2258 | i2c_del_driver(&wm8903_i2c_driver); | ||
2259 | } | ||
2260 | module_exit(wm8903_exit); | ||
2261 | 2245 | ||
2262 | MODULE_DESCRIPTION("ASoC WM8903 driver"); | 2246 | MODULE_DESCRIPTION("ASoC WM8903 driver"); |
2263 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); | 2247 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.cm>"); |
diff --git a/sound/soc/codecs/wm8940.c b/sound/soc/codecs/wm8940.c index 481a3d9cfe48..b20aa4e7c3f9 100644 --- a/sound/soc/codecs/wm8940.c +++ b/sound/soc/codecs/wm8940.c | |||
@@ -785,23 +785,7 @@ static struct i2c_driver wm8940_i2c_driver = { | |||
785 | .id_table = wm8940_i2c_id, | 785 | .id_table = wm8940_i2c_id, |
786 | }; | 786 | }; |
787 | 787 | ||
788 | static int __init wm8940_modinit(void) | 788 | module_i2c_driver(wm8940_i2c_driver); |
789 | { | ||
790 | int ret = 0; | ||
791 | ret = i2c_add_driver(&wm8940_i2c_driver); | ||
792 | if (ret != 0) { | ||
793 | printk(KERN_ERR "Failed to register wm8940 I2C driver: %d\n", | ||
794 | ret); | ||
795 | } | ||
796 | return ret; | ||
797 | } | ||
798 | module_init(wm8940_modinit); | ||
799 | |||
800 | static void __exit wm8940_exit(void) | ||
801 | { | ||
802 | i2c_del_driver(&wm8940_i2c_driver); | ||
803 | } | ||
804 | module_exit(wm8940_exit); | ||
805 | 789 | ||
806 | MODULE_DESCRIPTION("ASoC WM8940 driver"); | 790 | MODULE_DESCRIPTION("ASoC WM8940 driver"); |
807 | MODULE_AUTHOR("Jonathan Cameron"); | 791 | MODULE_AUTHOR("Jonathan Cameron"); |
diff --git a/sound/soc/codecs/wm8955.c b/sound/soc/codecs/wm8955.c index 61fe97433e73..2f1c075755b1 100644 --- a/sound/soc/codecs/wm8955.c +++ b/sound/soc/codecs/wm8955.c | |||
@@ -1071,23 +1071,7 @@ static struct i2c_driver wm8955_i2c_driver = { | |||
1071 | .id_table = wm8955_i2c_id, | 1071 | .id_table = wm8955_i2c_id, |
1072 | }; | 1072 | }; |
1073 | 1073 | ||
1074 | static int __init wm8955_modinit(void) | 1074 | module_i2c_driver(wm8955_i2c_driver); |
1075 | { | ||
1076 | int ret = 0; | ||
1077 | ret = i2c_add_driver(&wm8955_i2c_driver); | ||
1078 | if (ret != 0) { | ||
1079 | printk(KERN_ERR "Failed to register WM8955 I2C driver: %d\n", | ||
1080 | ret); | ||
1081 | } | ||
1082 | return ret; | ||
1083 | } | ||
1084 | module_init(wm8955_modinit); | ||
1085 | |||
1086 | static void __exit wm8955_exit(void) | ||
1087 | { | ||
1088 | i2c_del_driver(&wm8955_i2c_driver); | ||
1089 | } | ||
1090 | module_exit(wm8955_exit); | ||
1091 | 1075 | ||
1092 | MODULE_DESCRIPTION("ASoC WM8955 driver"); | 1076 | MODULE_DESCRIPTION("ASoC WM8955 driver"); |
1093 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1077 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 1332692ef81b..00121ba36597 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c | |||
@@ -946,7 +946,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
946 | wm8994->mbc_texts = kmalloc(sizeof(char *) | 946 | wm8994->mbc_texts = kmalloc(sizeof(char *) |
947 | * pdata->num_mbc_cfgs, GFP_KERNEL); | 947 | * pdata->num_mbc_cfgs, GFP_KERNEL); |
948 | if (!wm8994->mbc_texts) { | 948 | if (!wm8994->mbc_texts) { |
949 | dev_err(wm8994->codec->dev, | 949 | dev_err(wm8994->hubs.codec->dev, |
950 | "Failed to allocate %d MBC config texts\n", | 950 | "Failed to allocate %d MBC config texts\n", |
951 | pdata->num_mbc_cfgs); | 951 | pdata->num_mbc_cfgs); |
952 | return; | 952 | return; |
@@ -958,9 +958,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; | 958 | wm8994->mbc_enum.max = pdata->num_mbc_cfgs; |
959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; | 959 | wm8994->mbc_enum.texts = wm8994->mbc_texts; |
960 | 960 | ||
961 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 961 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
962 | control, 1); | ||
962 | if (ret != 0) | 963 | if (ret != 0) |
963 | dev_err(wm8994->codec->dev, | 964 | dev_err(wm8994->hubs.codec->dev, |
964 | "Failed to add MBC mode controls: %d\n", ret); | 965 | "Failed to add MBC mode controls: %d\n", ret); |
965 | } | 966 | } |
966 | 967 | ||
@@ -974,7 +975,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
974 | wm8994->vss_texts = kmalloc(sizeof(char *) | 975 | wm8994->vss_texts = kmalloc(sizeof(char *) |
975 | * pdata->num_vss_cfgs, GFP_KERNEL); | 976 | * pdata->num_vss_cfgs, GFP_KERNEL); |
976 | if (!wm8994->vss_texts) { | 977 | if (!wm8994->vss_texts) { |
977 | dev_err(wm8994->codec->dev, | 978 | dev_err(wm8994->hubs.codec->dev, |
978 | "Failed to allocate %d VSS config texts\n", | 979 | "Failed to allocate %d VSS config texts\n", |
979 | pdata->num_vss_cfgs); | 980 | pdata->num_vss_cfgs); |
980 | return; | 981 | return; |
@@ -986,9 +987,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
986 | wm8994->vss_enum.max = pdata->num_vss_cfgs; | 987 | wm8994->vss_enum.max = pdata->num_vss_cfgs; |
987 | wm8994->vss_enum.texts = wm8994->vss_texts; | 988 | wm8994->vss_enum.texts = wm8994->vss_texts; |
988 | 989 | ||
989 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 990 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
991 | control, 1); | ||
990 | if (ret != 0) | 992 | if (ret != 0) |
991 | dev_err(wm8994->codec->dev, | 993 | dev_err(wm8994->hubs.codec->dev, |
992 | "Failed to add VSS mode controls: %d\n", ret); | 994 | "Failed to add VSS mode controls: %d\n", ret); |
993 | } | 995 | } |
994 | 996 | ||
@@ -1003,7 +1005,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1003 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) | 1005 | wm8994->vss_hpf_texts = kmalloc(sizeof(char *) |
1004 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); | 1006 | * pdata->num_vss_hpf_cfgs, GFP_KERNEL); |
1005 | if (!wm8994->vss_hpf_texts) { | 1007 | if (!wm8994->vss_hpf_texts) { |
1006 | dev_err(wm8994->codec->dev, | 1008 | dev_err(wm8994->hubs.codec->dev, |
1007 | "Failed to allocate %d VSS HPF config texts\n", | 1009 | "Failed to allocate %d VSS HPF config texts\n", |
1008 | pdata->num_vss_hpf_cfgs); | 1010 | pdata->num_vss_hpf_cfgs); |
1009 | return; | 1011 | return; |
@@ -1015,9 +1017,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1015 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; | 1017 | wm8994->vss_hpf_enum.max = pdata->num_vss_hpf_cfgs; |
1016 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; | 1018 | wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; |
1017 | 1019 | ||
1018 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1020 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
1021 | control, 1); | ||
1019 | if (ret != 0) | 1022 | if (ret != 0) |
1020 | dev_err(wm8994->codec->dev, | 1023 | dev_err(wm8994->hubs.codec->dev, |
1021 | "Failed to add VSS HPFmode controls: %d\n", | 1024 | "Failed to add VSS HPFmode controls: %d\n", |
1022 | ret); | 1025 | ret); |
1023 | } | 1026 | } |
@@ -1033,7 +1036,7 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1033 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) | 1036 | wm8994->enh_eq_texts = kmalloc(sizeof(char *) |
1034 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); | 1037 | * pdata->num_enh_eq_cfgs, GFP_KERNEL); |
1035 | if (!wm8994->enh_eq_texts) { | 1038 | if (!wm8994->enh_eq_texts) { |
1036 | dev_err(wm8994->codec->dev, | 1039 | dev_err(wm8994->hubs.codec->dev, |
1037 | "Failed to allocate %d enhanced EQ config texts\n", | 1040 | "Failed to allocate %d enhanced EQ config texts\n", |
1038 | pdata->num_enh_eq_cfgs); | 1041 | pdata->num_enh_eq_cfgs); |
1039 | return; | 1042 | return; |
@@ -1045,9 +1048,10 @@ void wm8958_dsp2_init(struct snd_soc_codec *codec) | |||
1045 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; | 1048 | wm8994->enh_eq_enum.max = pdata->num_enh_eq_cfgs; |
1046 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; | 1049 | wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; |
1047 | 1050 | ||
1048 | ret = snd_soc_add_codec_controls(wm8994->codec, control, 1); | 1051 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, |
1052 | control, 1); | ||
1049 | if (ret != 0) | 1053 | if (ret != 0) |
1050 | dev_err(wm8994->codec->dev, | 1054 | dev_err(wm8994->hubs.codec->dev, |
1051 | "Failed to add enhanced EQ controls: %d\n", | 1055 | "Failed to add enhanced EQ controls: %d\n", |
1052 | ret); | 1056 | ret); |
1053 | } | 1057 | } |
diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index 96518ac8e24c..804f4116912f 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c | |||
@@ -1010,23 +1010,7 @@ static struct i2c_driver wm8960_i2c_driver = { | |||
1010 | .id_table = wm8960_i2c_id, | 1010 | .id_table = wm8960_i2c_id, |
1011 | }; | 1011 | }; |
1012 | 1012 | ||
1013 | static int __init wm8960_modinit(void) | 1013 | module_i2c_driver(wm8960_i2c_driver); |
1014 | { | ||
1015 | int ret = 0; | ||
1016 | ret = i2c_add_driver(&wm8960_i2c_driver); | ||
1017 | if (ret != 0) { | ||
1018 | printk(KERN_ERR "Failed to register WM8960 I2C driver: %d\n", | ||
1019 | ret); | ||
1020 | } | ||
1021 | return ret; | ||
1022 | } | ||
1023 | module_init(wm8960_modinit); | ||
1024 | |||
1025 | static void __exit wm8960_exit(void) | ||
1026 | { | ||
1027 | i2c_del_driver(&wm8960_i2c_driver); | ||
1028 | } | ||
1029 | module_exit(wm8960_exit); | ||
1030 | 1014 | ||
1031 | MODULE_DESCRIPTION("ASoC WM8960 driver"); | 1015 | MODULE_DESCRIPTION("ASoC WM8960 driver"); |
1032 | MODULE_AUTHOR("Liam Girdwood"); | 1016 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8961.c b/sound/soc/codecs/wm8961.c index 01edbcc754d2..719fb69a17c8 100644 --- a/sound/soc/codecs/wm8961.c +++ b/sound/soc/codecs/wm8961.c | |||
@@ -1114,23 +1114,7 @@ static struct i2c_driver wm8961_i2c_driver = { | |||
1114 | .id_table = wm8961_i2c_id, | 1114 | .id_table = wm8961_i2c_id, |
1115 | }; | 1115 | }; |
1116 | 1116 | ||
1117 | static int __init wm8961_modinit(void) | 1117 | module_i2c_driver(wm8961_i2c_driver); |
1118 | { | ||
1119 | int ret = 0; | ||
1120 | ret = i2c_add_driver(&wm8961_i2c_driver); | ||
1121 | if (ret != 0) { | ||
1122 | printk(KERN_ERR "Failed to register wm8961 I2C driver: %d\n", | ||
1123 | ret); | ||
1124 | } | ||
1125 | return ret; | ||
1126 | } | ||
1127 | module_init(wm8961_modinit); | ||
1128 | |||
1129 | static void __exit wm8961_exit(void) | ||
1130 | { | ||
1131 | i2c_del_driver(&wm8961_i2c_driver); | ||
1132 | } | ||
1133 | module_exit(wm8961_exit); | ||
1134 | 1118 | ||
1135 | MODULE_DESCRIPTION("ASoC WM8961 driver"); | 1119 | MODULE_DESCRIPTION("ASoC WM8961 driver"); |
1136 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 1120 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
diff --git a/sound/soc/codecs/wm8971.c b/sound/soc/codecs/wm8971.c index eef783f6b6d6..5ce647758443 100644 --- a/sound/soc/codecs/wm8971.c +++ b/sound/soc/codecs/wm8971.c | |||
@@ -721,23 +721,7 @@ static struct i2c_driver wm8971_i2c_driver = { | |||
721 | .id_table = wm8971_i2c_id, | 721 | .id_table = wm8971_i2c_id, |
722 | }; | 722 | }; |
723 | 723 | ||
724 | static int __init wm8971_modinit(void) | 724 | module_i2c_driver(wm8971_i2c_driver); |
725 | { | ||
726 | int ret = 0; | ||
727 | ret = i2c_add_driver(&wm8971_i2c_driver); | ||
728 | if (ret != 0) { | ||
729 | printk(KERN_ERR "Failed to register WM8971 I2C driver: %d\n", | ||
730 | ret); | ||
731 | } | ||
732 | return ret; | ||
733 | } | ||
734 | module_init(wm8971_modinit); | ||
735 | |||
736 | static void __exit wm8971_exit(void) | ||
737 | { | ||
738 | i2c_del_driver(&wm8971_i2c_driver); | ||
739 | } | ||
740 | module_exit(wm8971_exit); | ||
741 | 725 | ||
742 | MODULE_DESCRIPTION("ASoC WM8971 driver"); | 726 | MODULE_DESCRIPTION("ASoC WM8971 driver"); |
743 | MODULE_AUTHOR("Lab126"); | 727 | MODULE_AUTHOR("Lab126"); |
diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index d93c03f820c9..9a39511af52a 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c | |||
@@ -659,23 +659,7 @@ static struct i2c_driver wm8974_i2c_driver = { | |||
659 | .id_table = wm8974_i2c_id, | 659 | .id_table = wm8974_i2c_id, |
660 | }; | 660 | }; |
661 | 661 | ||
662 | static int __init wm8974_modinit(void) | 662 | module_i2c_driver(wm8974_i2c_driver); |
663 | { | ||
664 | int ret = 0; | ||
665 | ret = i2c_add_driver(&wm8974_i2c_driver); | ||
666 | if (ret != 0) { | ||
667 | printk(KERN_ERR "Failed to register wm8974 I2C driver: %d\n", | ||
668 | ret); | ||
669 | } | ||
670 | return ret; | ||
671 | } | ||
672 | module_init(wm8974_modinit); | ||
673 | |||
674 | static void __exit wm8974_exit(void) | ||
675 | { | ||
676 | i2c_del_driver(&wm8974_i2c_driver); | ||
677 | } | ||
678 | module_exit(wm8974_exit); | ||
679 | 663 | ||
680 | MODULE_DESCRIPTION("ASoC WM8974 driver"); | 664 | MODULE_DESCRIPTION("ASoC WM8974 driver"); |
681 | MODULE_AUTHOR("Liam Girdwood"); | 665 | MODULE_AUTHOR("Liam Girdwood"); |
diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index a5be3adecf75..5421fd9fbcb5 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c | |||
@@ -1105,23 +1105,7 @@ static struct i2c_driver wm8978_i2c_driver = { | |||
1105 | .id_table = wm8978_i2c_id, | 1105 | .id_table = wm8978_i2c_id, |
1106 | }; | 1106 | }; |
1107 | 1107 | ||
1108 | static int __init wm8978_modinit(void) | 1108 | module_i2c_driver(wm8978_i2c_driver); |
1109 | { | ||
1110 | int ret = 0; | ||
1111 | ret = i2c_add_driver(&wm8978_i2c_driver); | ||
1112 | if (ret != 0) { | ||
1113 | printk(KERN_ERR "Failed to register WM8978 I2C driver: %d\n", | ||
1114 | ret); | ||
1115 | } | ||
1116 | return ret; | ||
1117 | } | ||
1118 | module_init(wm8978_modinit); | ||
1119 | |||
1120 | static void __exit wm8978_exit(void) | ||
1121 | { | ||
1122 | i2c_del_driver(&wm8978_i2c_driver); | ||
1123 | } | ||
1124 | module_exit(wm8978_exit); | ||
1125 | 1109 | ||
1126 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); | 1110 | MODULE_DESCRIPTION("ASoC WM8978 codec driver"); |
1127 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); | 1111 | MODULE_AUTHOR("Guennadi Liakhovetski <g.liakhovetski@gmx.de>"); |
diff --git a/sound/soc/codecs/wm8991.c b/sound/soc/codecs/wm8991.c index 9ac31ba9b82e..b9dbfebbda13 100644 --- a/sound/soc/codecs/wm8991.c +++ b/sound/soc/codecs/wm8991.c | |||
@@ -1400,23 +1400,7 @@ static struct i2c_driver wm8991_i2c_driver = { | |||
1400 | .id_table = wm8991_i2c_id, | 1400 | .id_table = wm8991_i2c_id, |
1401 | }; | 1401 | }; |
1402 | 1402 | ||
1403 | static int __init wm8991_modinit(void) | 1403 | module_i2c_driver(wm8991_i2c_driver); |
1404 | { | ||
1405 | int ret; | ||
1406 | ret = i2c_add_driver(&wm8991_i2c_driver); | ||
1407 | if (ret != 0) { | ||
1408 | printk(KERN_ERR "Failed to register WM8991 I2C driver: %d\n", | ||
1409 | ret); | ||
1410 | } | ||
1411 | return 0; | ||
1412 | } | ||
1413 | module_init(wm8991_modinit); | ||
1414 | |||
1415 | static void __exit wm8991_exit(void) | ||
1416 | { | ||
1417 | i2c_del_driver(&wm8991_i2c_driver); | ||
1418 | } | ||
1419 | module_exit(wm8991_exit); | ||
1420 | 1404 | ||
1421 | MODULE_DESCRIPTION("ASoC WM8991 driver"); | 1405 | MODULE_DESCRIPTION("ASoC WM8991 driver"); |
1422 | MODULE_AUTHOR("Graeme Gregory"); | 1406 | MODULE_AUTHOR("Graeme Gregory"); |
diff --git a/sound/soc/codecs/wm8993.c b/sound/soc/codecs/wm8993.c index 9fd80d688979..94737a30716b 100644 --- a/sound/soc/codecs/wm8993.c +++ b/sound/soc/codecs/wm8993.c | |||
@@ -1520,6 +1520,8 @@ static int wm8993_probe(struct snd_soc_codec *codec) | |||
1520 | wm8993->pdata.lineout2fb, | 1520 | wm8993->pdata.lineout2fb, |
1521 | wm8993->pdata.jd_scthr, | 1521 | wm8993->pdata.jd_scthr, |
1522 | wm8993->pdata.jd_thr, | 1522 | wm8993->pdata.jd_thr, |
1523 | wm8993->pdata.micbias1_delay, | ||
1524 | wm8993->pdata.micbias2_delay, | ||
1523 | wm8993->pdata.micbias1_lvl, | 1525 | wm8993->pdata.micbias1_lvl, |
1524 | wm8993->pdata.micbias2_lvl); | 1526 | wm8993->pdata.micbias2_lvl); |
1525 | 1527 | ||
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 6c9eeca85b95..2b2dadc54dac 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -671,6 +671,18 @@ SOC_SINGLE_TLV("AIF2 EQ5 Volume", WM8994_AIF2_EQ_GAINS_2, 6, 31, 0, | |||
671 | eq_tlv), | 671 | eq_tlv), |
672 | }; | 672 | }; |
673 | 673 | ||
674 | static const struct snd_kcontrol_new wm8994_drc_controls[] = { | ||
675 | SND_SOC_BYTES_MASK("AIF1.1 DRC", WM8994_AIF1_DRC1_1, 5, | ||
676 | WM8994_AIF1DAC1_DRC_ENA | WM8994_AIF1ADC1L_DRC_ENA | | ||
677 | WM8994_AIF1ADC1R_DRC_ENA), | ||
678 | SND_SOC_BYTES_MASK("AIF1.2 DRC", WM8994_AIF1_DRC2_1, 5, | ||
679 | WM8994_AIF1DAC2_DRC_ENA | WM8994_AIF1ADC2L_DRC_ENA | | ||
680 | WM8994_AIF1ADC2R_DRC_ENA), | ||
681 | SND_SOC_BYTES_MASK("AIF2 DRC", WM8994_AIF2_DRC_1, 5, | ||
682 | WM8994_AIF2DAC_DRC_ENA | WM8994_AIF2ADCL_DRC_ENA | | ||
683 | WM8994_AIF2ADCR_DRC_ENA), | ||
684 | }; | ||
685 | |||
674 | static const char *wm8958_ng_text[] = { | 686 | static const char *wm8958_ng_text[] = { |
675 | "30ms", "125ms", "250ms", "500ms", | 687 | "30ms", "125ms", "250ms", "500ms", |
676 | }; | 688 | }; |
@@ -789,11 +801,27 @@ static int clk_sys_event(struct snd_soc_dapm_widget *w, | |||
789 | struct snd_kcontrol *kcontrol, int event) | 801 | struct snd_kcontrol *kcontrol, int event) |
790 | { | 802 | { |
791 | struct snd_soc_codec *codec = w->codec; | 803 | struct snd_soc_codec *codec = w->codec; |
804 | struct wm8994_priv *wm8994 = snd_soc_codec_get_drvdata(codec); | ||
792 | 805 | ||
793 | switch (event) { | 806 | switch (event) { |
794 | case SND_SOC_DAPM_PRE_PMU: | 807 | case SND_SOC_DAPM_PRE_PMU: |
795 | return configure_clock(codec); | 808 | return configure_clock(codec); |
796 | 809 | ||
810 | case SND_SOC_DAPM_POST_PMU: | ||
811 | /* | ||
812 | * JACKDET won't run until we start the clock and it | ||
813 | * only reports deltas, make sure we notify the state | ||
814 | * up the stack on startup. Use a *very* generous | ||
815 | * timeout for paranoia, there's no urgency and we | ||
816 | * don't want false reports. | ||
817 | */ | ||
818 | if (wm8994->jackdet && !wm8994->clk_has_run) { | ||
819 | schedule_delayed_work(&wm8994->jackdet_bootstrap, | ||
820 | msecs_to_jiffies(1000)); | ||
821 | wm8994->clk_has_run = true; | ||
822 | } | ||
823 | break; | ||
824 | |||
797 | case SND_SOC_DAPM_POST_PMD: | 825 | case SND_SOC_DAPM_POST_PMD: |
798 | configure_clock(codec); | 826 | configure_clock(codec); |
799 | break; | 827 | break; |
@@ -1632,7 +1660,8 @@ SND_SOC_DAPM_SUPPLY("VMID", SND_SOC_NOPM, 0, 0, vmid_event, | |||
1632 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), | 1660 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), |
1633 | 1661 | ||
1634 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, | 1662 | SND_SOC_DAPM_SUPPLY("CLK_SYS", SND_SOC_NOPM, 0, 0, clk_sys_event, |
1635 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), | 1663 | SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | |
1664 | SND_SOC_DAPM_PRE_PMD), | ||
1636 | 1665 | ||
1637 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), | 1666 | SND_SOC_DAPM_SUPPLY("DSP1CLK", SND_SOC_NOPM, 3, 0, NULL, 0), |
1638 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), | 1667 | SND_SOC_DAPM_SUPPLY("DSP2CLK", SND_SOC_NOPM, 2, 0, NULL, 0), |
@@ -2102,6 +2131,10 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2102 | case WM8994_FLL_SRC_LRCLK: | 2131 | case WM8994_FLL_SRC_LRCLK: |
2103 | case WM8994_FLL_SRC_BCLK: | 2132 | case WM8994_FLL_SRC_BCLK: |
2104 | break; | 2133 | break; |
2134 | case WM8994_FLL_SRC_INTERNAL: | ||
2135 | freq_in = 12000000; | ||
2136 | freq_out = 12000000; | ||
2137 | break; | ||
2105 | default: | 2138 | default: |
2106 | return -EINVAL; | 2139 | return -EINVAL; |
2107 | } | 2140 | } |
@@ -2161,12 +2194,14 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2161 | 2194 | ||
2162 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, | 2195 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_4 + reg_offset, |
2163 | WM8994_FLL1_N_MASK, | 2196 | WM8994_FLL1_N_MASK, |
2164 | fll.n << WM8994_FLL1_N_SHIFT); | 2197 | fll.n << WM8994_FLL1_N_SHIFT); |
2165 | 2198 | ||
2166 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, | 2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_5 + reg_offset, |
2167 | WM8958_FLL1_BYP | | 2200 | WM8994_FLL1_FRC_NCO | WM8958_FLL1_BYP | |
2168 | WM8994_FLL1_REFCLK_DIV_MASK | | 2201 | WM8994_FLL1_REFCLK_DIV_MASK | |
2169 | WM8994_FLL1_REFCLK_SRC_MASK, | 2202 | WM8994_FLL1_REFCLK_SRC_MASK, |
2203 | ((src == WM8994_FLL_SRC_INTERNAL) | ||
2204 | << WM8994_FLL1_FRC_NCO_SHIFT) | | ||
2170 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | | 2205 | (fll.clk_ref_div << WM8994_FLL1_REFCLK_DIV_SHIFT) | |
2171 | (src - 1)); | 2206 | (src - 1)); |
2172 | 2207 | ||
@@ -2192,13 +2227,16 @@ static int _wm8994_set_fll(struct snd_soc_codec *codec, int id, int src, | |||
2192 | } | 2227 | } |
2193 | } | 2228 | } |
2194 | 2229 | ||
2230 | reg = WM8994_FLL1_ENA; | ||
2231 | |||
2195 | if (fll.k) | 2232 | if (fll.k) |
2196 | reg = WM8994_FLL1_ENA | WM8994_FLL1_FRAC; | 2233 | reg |= WM8994_FLL1_FRAC; |
2197 | else | 2234 | if (src == WM8994_FLL_SRC_INTERNAL) |
2198 | reg = WM8994_FLL1_ENA; | 2235 | reg |= WM8994_FLL1_OSC_ENA; |
2236 | |||
2199 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, | 2237 | snd_soc_update_bits(codec, WM8994_FLL1_CONTROL_1 + reg_offset, |
2200 | WM8994_FLL1_ENA | WM8994_FLL1_FRAC, | 2238 | WM8994_FLL1_ENA | WM8994_FLL1_OSC_ENA | |
2201 | reg); | 2239 | WM8994_FLL1_FRAC, reg); |
2202 | 2240 | ||
2203 | if (wm8994->fll_locked_irq) { | 2241 | if (wm8994->fll_locked_irq) { |
2204 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], | 2242 | timeout = wait_for_completion_timeout(&wm8994->fll_locked[id], |
@@ -3027,7 +3065,7 @@ static int wm8994_codec_resume(struct snd_soc_codec *codec) | |||
3027 | 3065 | ||
3028 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | 3066 | static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) |
3029 | { | 3067 | { |
3030 | struct snd_soc_codec *codec = wm8994->codec; | 3068 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3031 | struct wm8994_pdata *pdata = wm8994->pdata; | 3069 | struct wm8994_pdata *pdata = wm8994->pdata; |
3032 | struct snd_kcontrol_new controls[] = { | 3070 | struct snd_kcontrol_new controls[] = { |
3033 | SOC_ENUM_EXT("AIF1.1 EQ Mode", | 3071 | SOC_ENUM_EXT("AIF1.1 EQ Mode", |
@@ -3085,16 +3123,16 @@ static void wm8994_handle_retune_mobile_pdata(struct wm8994_priv *wm8994) | |||
3085 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; | 3123 | wm8994->retune_mobile_enum.max = wm8994->num_retune_mobile_texts; |
3086 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; | 3124 | wm8994->retune_mobile_enum.texts = wm8994->retune_mobile_texts; |
3087 | 3125 | ||
3088 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3126 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
3089 | ARRAY_SIZE(controls)); | 3127 | ARRAY_SIZE(controls)); |
3090 | if (ret != 0) | 3128 | if (ret != 0) |
3091 | dev_err(wm8994->codec->dev, | 3129 | dev_err(wm8994->hubs.codec->dev, |
3092 | "Failed to add ReTune Mobile controls: %d\n", ret); | 3130 | "Failed to add ReTune Mobile controls: %d\n", ret); |
3093 | } | 3131 | } |
3094 | 3132 | ||
3095 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | 3133 | static void wm8994_handle_pdata(struct wm8994_priv *wm8994) |
3096 | { | 3134 | { |
3097 | struct snd_soc_codec *codec = wm8994->codec; | 3135 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3098 | struct wm8994_pdata *pdata = wm8994->pdata; | 3136 | struct wm8994_pdata *pdata = wm8994->pdata; |
3099 | int ret, i; | 3137 | int ret, i; |
3100 | 3138 | ||
@@ -3107,6 +3145,8 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3107 | pdata->lineout2fb, | 3145 | pdata->lineout2fb, |
3108 | pdata->jd_scthr, | 3146 | pdata->jd_scthr, |
3109 | pdata->jd_thr, | 3147 | pdata->jd_thr, |
3148 | pdata->micb1_delay, | ||
3149 | pdata->micb2_delay, | ||
3110 | pdata->micbias1_lvl, | 3150 | pdata->micbias1_lvl, |
3111 | pdata->micbias2_lvl); | 3151 | pdata->micbias2_lvl); |
3112 | 3152 | ||
@@ -3123,10 +3163,10 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3123 | }; | 3163 | }; |
3124 | 3164 | ||
3125 | /* We need an array of texts for the enum API */ | 3165 | /* We need an array of texts for the enum API */ |
3126 | wm8994->drc_texts = devm_kzalloc(wm8994->codec->dev, | 3166 | wm8994->drc_texts = devm_kzalloc(wm8994->hubs.codec->dev, |
3127 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); | 3167 | sizeof(char *) * pdata->num_drc_cfgs, GFP_KERNEL); |
3128 | if (!wm8994->drc_texts) { | 3168 | if (!wm8994->drc_texts) { |
3129 | dev_err(wm8994->codec->dev, | 3169 | dev_err(wm8994->hubs.codec->dev, |
3130 | "Failed to allocate %d DRC config texts\n", | 3170 | "Failed to allocate %d DRC config texts\n", |
3131 | pdata->num_drc_cfgs); | 3171 | pdata->num_drc_cfgs); |
3132 | return; | 3172 | return; |
@@ -3138,23 +3178,28 @@ static void wm8994_handle_pdata(struct wm8994_priv *wm8994) | |||
3138 | wm8994->drc_enum.max = pdata->num_drc_cfgs; | 3178 | wm8994->drc_enum.max = pdata->num_drc_cfgs; |
3139 | wm8994->drc_enum.texts = wm8994->drc_texts; | 3179 | wm8994->drc_enum.texts = wm8994->drc_texts; |
3140 | 3180 | ||
3141 | ret = snd_soc_add_codec_controls(wm8994->codec, controls, | 3181 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, controls, |
3142 | ARRAY_SIZE(controls)); | 3182 | ARRAY_SIZE(controls)); |
3143 | if (ret != 0) | ||
3144 | dev_err(wm8994->codec->dev, | ||
3145 | "Failed to add DRC mode controls: %d\n", ret); | ||
3146 | |||
3147 | for (i = 0; i < WM8994_NUM_DRC; i++) | 3183 | for (i = 0; i < WM8994_NUM_DRC; i++) |
3148 | wm8994_set_drc(codec, i); | 3184 | wm8994_set_drc(codec, i); |
3185 | } else { | ||
3186 | ret = snd_soc_add_codec_controls(wm8994->hubs.codec, | ||
3187 | wm8994_drc_controls, | ||
3188 | ARRAY_SIZE(wm8994_drc_controls)); | ||
3149 | } | 3189 | } |
3150 | 3190 | ||
3191 | if (ret != 0) | ||
3192 | dev_err(wm8994->hubs.codec->dev, | ||
3193 | "Failed to add DRC mode controls: %d\n", ret); | ||
3194 | |||
3195 | |||
3151 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", | 3196 | dev_dbg(codec->dev, "%d ReTune Mobile configurations\n", |
3152 | pdata->num_retune_mobile_cfgs); | 3197 | pdata->num_retune_mobile_cfgs); |
3153 | 3198 | ||
3154 | if (pdata->num_retune_mobile_cfgs) | 3199 | if (pdata->num_retune_mobile_cfgs) |
3155 | wm8994_handle_retune_mobile_pdata(wm8994); | 3200 | wm8994_handle_retune_mobile_pdata(wm8994); |
3156 | else | 3201 | else |
3157 | snd_soc_add_codec_controls(wm8994->codec, wm8994_eq_controls, | 3202 | snd_soc_add_codec_controls(wm8994->hubs.codec, wm8994_eq_controls, |
3158 | ARRAY_SIZE(wm8994_eq_controls)); | 3203 | ARRAY_SIZE(wm8994_eq_controls)); |
3159 | 3204 | ||
3160 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { | 3205 | for (i = 0; i < ARRAY_SIZE(pdata->micbias); i++) { |
@@ -3236,6 +3281,12 @@ int wm8994_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3236 | 3281 | ||
3237 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); | 3282 | snd_soc_update_bits(codec, WM8994_MICBIAS, WM8994_MICD_ENA, reg); |
3238 | 3283 | ||
3284 | /* enable MICDET and MICSHRT deboune */ | ||
3285 | snd_soc_update_bits(codec, WM8994_IRQ_DEBOUNCE, | ||
3286 | WM8994_MIC1_DET_DB_MASK | WM8994_MIC1_SHRT_DB_MASK | | ||
3287 | WM8994_MIC2_DET_DB_MASK | WM8994_MIC2_SHRT_DB_MASK, | ||
3288 | WM8994_MIC1_DET_DB | WM8994_MIC1_SHRT_DB); | ||
3289 | |||
3239 | snd_soc_dapm_sync(&codec->dapm); | 3290 | snd_soc_dapm_sync(&codec->dapm); |
3240 | 3291 | ||
3241 | return 0; | 3292 | return 0; |
@@ -3309,7 +3360,7 @@ static void wm8994_mic_work(struct work_struct *work) | |||
3309 | static irqreturn_t wm8994_mic_irq(int irq, void *data) | 3360 | static irqreturn_t wm8994_mic_irq(int irq, void *data) |
3310 | { | 3361 | { |
3311 | struct wm8994_priv *priv = data; | 3362 | struct wm8994_priv *priv = data; |
3312 | struct snd_soc_codec *codec = priv->codec; | 3363 | struct snd_soc_codec *codec = priv->hubs.codec; |
3313 | 3364 | ||
3314 | #ifndef CONFIG_SND_SOC_WM8994_MODULE | 3365 | #ifndef CONFIG_SND_SOC_WM8994_MODULE |
3315 | trace_snd_soc_jack_irq(dev_name(codec->dev)); | 3366 | trace_snd_soc_jack_irq(dev_name(codec->dev)); |
@@ -3345,7 +3396,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3345 | 3396 | ||
3346 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, | 3397 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, |
3347 | wm8994->btn_mask | | 3398 | wm8994->btn_mask | |
3348 | SND_JACK_HEADSET); | 3399 | SND_JACK_HEADSET); |
3349 | } | 3400 | } |
3350 | return; | 3401 | return; |
3351 | } | 3402 | } |
@@ -3422,7 +3473,7 @@ static void wm8958_default_micdet(u16 status, void *data) | |||
3422 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | 3473 | static irqreturn_t wm1811_jackdet_irq(int irq, void *data) |
3423 | { | 3474 | { |
3424 | struct wm8994_priv *wm8994 = data; | 3475 | struct wm8994_priv *wm8994 = data; |
3425 | struct snd_soc_codec *codec = wm8994->codec; | 3476 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3426 | int reg; | 3477 | int reg; |
3427 | bool present; | 3478 | bool present; |
3428 | 3479 | ||
@@ -3499,10 +3550,22 @@ static irqreturn_t wm1811_jackdet_irq(int irq, void *data) | |||
3499 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | | 3550 | SND_JACK_MECHANICAL | SND_JACK_HEADSET | |
3500 | wm8994->btn_mask); | 3551 | wm8994->btn_mask); |
3501 | 3552 | ||
3553 | /* Since we only report deltas force an update, ensures we | ||
3554 | * avoid bootstrapping issues with the core. */ | ||
3555 | snd_soc_jack_report(wm8994->micdet[0].jack, 0, 0); | ||
3556 | |||
3502 | pm_runtime_put(codec->dev); | 3557 | pm_runtime_put(codec->dev); |
3503 | return IRQ_HANDLED; | 3558 | return IRQ_HANDLED; |
3504 | } | 3559 | } |
3505 | 3560 | ||
3561 | static void wm1811_jackdet_bootstrap(struct work_struct *work) | ||
3562 | { | ||
3563 | struct wm8994_priv *wm8994 = container_of(work, | ||
3564 | struct wm8994_priv, | ||
3565 | jackdet_bootstrap.work); | ||
3566 | wm1811_jackdet_irq(0, wm8994); | ||
3567 | } | ||
3568 | |||
3506 | /** | 3569 | /** |
3507 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ | 3570 | * wm8958_mic_detect - Enable microphone detection via the WM8958 IRQ |
3508 | * | 3571 | * |
@@ -3573,6 +3636,10 @@ int wm8958_mic_detect(struct snd_soc_codec *codec, struct snd_soc_jack *jack, | |||
3573 | * otherwise jump straight to microphone detection. | 3636 | * otherwise jump straight to microphone detection. |
3574 | */ | 3637 | */ |
3575 | if (wm8994->jackdet) { | 3638 | if (wm8994->jackdet) { |
3639 | /* Disable debounce for the initial detect */ | ||
3640 | snd_soc_update_bits(codec, WM1811_JACKDET_CTRL, | ||
3641 | WM1811_JACKDET_DB, 0); | ||
3642 | |||
3576 | snd_soc_update_bits(codec, WM8958_MICBIAS2, | 3643 | snd_soc_update_bits(codec, WM8958_MICBIAS2, |
3577 | WM8958_MICB2_DISCH, | 3644 | WM8958_MICB2_DISCH, |
3578 | WM8958_MICB2_DISCH); | 3645 | WM8958_MICB2_DISCH); |
@@ -3600,7 +3667,7 @@ EXPORT_SYMBOL_GPL(wm8958_mic_detect); | |||
3600 | static irqreturn_t wm8958_mic_irq(int irq, void *data) | 3667 | static irqreturn_t wm8958_mic_irq(int irq, void *data) |
3601 | { | 3668 | { |
3602 | struct wm8994_priv *wm8994 = data; | 3669 | struct wm8994_priv *wm8994 = data; |
3603 | struct snd_soc_codec *codec = wm8994->codec; | 3670 | struct snd_soc_codec *codec = wm8994->hubs.codec; |
3604 | int reg, count; | 3671 | int reg, count; |
3605 | 3672 | ||
3606 | /* | 3673 | /* |
@@ -3690,15 +3757,15 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3690 | unsigned int reg; | 3757 | unsigned int reg; |
3691 | int ret, i; | 3758 | int ret, i; |
3692 | 3759 | ||
3693 | wm8994->codec = codec; | 3760 | wm8994->hubs.codec = codec; |
3694 | codec->control_data = control->regmap; | 3761 | codec->control_data = control->regmap; |
3695 | 3762 | ||
3696 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); | 3763 | snd_soc_codec_set_cache_io(codec, 16, 16, SND_SOC_REGMAP); |
3697 | 3764 | ||
3698 | wm8994->codec = codec; | ||
3699 | |||
3700 | mutex_init(&wm8994->accdet_lock); | 3765 | mutex_init(&wm8994->accdet_lock); |
3701 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); | 3766 | INIT_DELAYED_WORK(&wm8994->mic_work, wm8994_mic_work); |
3767 | INIT_DELAYED_WORK(&wm8994->jackdet_bootstrap, | ||
3768 | wm1811_jackdet_bootstrap); | ||
3702 | 3769 | ||
3703 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) | 3770 | for (i = 0; i < ARRAY_SIZE(wm8994->fll_locked); i++) |
3704 | init_completion(&wm8994->fll_locked[i]); | 3771 | init_completion(&wm8994->fll_locked[i]); |
@@ -3756,14 +3823,17 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3756 | wm8994->hubs.no_cache_dac_hp_direct = true; | 3823 | wm8994->hubs.no_cache_dac_hp_direct = true; |
3757 | wm8994->fll_byp = true; | 3824 | wm8994->fll_byp = true; |
3758 | 3825 | ||
3759 | switch (wm8994->revision) { | 3826 | switch (control->cust_id) { |
3760 | case 0: | 3827 | case 0: |
3761 | case 1: | ||
3762 | case 2: | 3828 | case 2: |
3763 | case 3: | ||
3764 | wm8994->hubs.dcs_codes_l = -9; | 3829 | wm8994->hubs.dcs_codes_l = -9; |
3765 | wm8994->hubs.dcs_codes_r = -7; | 3830 | wm8994->hubs.dcs_codes_r = -7; |
3766 | break; | 3831 | break; |
3832 | case 1: | ||
3833 | case 3: | ||
3834 | wm8994->hubs.dcs_codes_l = -8; | ||
3835 | wm8994->hubs.dcs_codes_r = -7; | ||
3836 | break; | ||
3767 | default: | 3837 | default: |
3768 | break; | 3838 | break; |
3769 | } | 3839 | } |
@@ -3852,7 +3922,7 @@ static int wm8994_codec_probe(struct snd_soc_codec *codec) | |||
3852 | 3922 | ||
3853 | switch (control->type) { | 3923 | switch (control->type) { |
3854 | case WM1811: | 3924 | case WM1811: |
3855 | if (wm8994->revision > 1) { | 3925 | if (control->cust_id > 1 || wm8994->revision > 1) { |
3856 | ret = wm8994_request_irq(wm8994->wm8994, | 3926 | ret = wm8994_request_irq(wm8994->wm8994, |
3857 | WM8994_IRQ_GPIO(6), | 3927 | WM8994_IRQ_GPIO(6), |
3858 | wm1811_jackdet_irq, "JACKDET", | 3928 | wm1811_jackdet_irq, "JACKDET", |
diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index d77e06f0a675..f142ec198db3 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h | |||
@@ -28,10 +28,11 @@ | |||
28 | #define WM8994_FLL1 1 | 28 | #define WM8994_FLL1 1 |
29 | #define WM8994_FLL2 2 | 29 | #define WM8994_FLL2 2 |
30 | 30 | ||
31 | #define WM8994_FLL_SRC_MCLK1 1 | 31 | #define WM8994_FLL_SRC_MCLK1 1 |
32 | #define WM8994_FLL_SRC_MCLK2 2 | 32 | #define WM8994_FLL_SRC_MCLK2 2 |
33 | #define WM8994_FLL_SRC_LRCLK 3 | 33 | #define WM8994_FLL_SRC_LRCLK 3 |
34 | #define WM8994_FLL_SRC_BCLK 4 | 34 | #define WM8994_FLL_SRC_BCLK 4 |
35 | #define WM8994_FLL_SRC_INTERNAL 5 | ||
35 | 36 | ||
36 | enum wm8994_vmid_mode { | 37 | enum wm8994_vmid_mode { |
37 | WM8994_VMID_NORMAL, | 38 | WM8994_VMID_NORMAL, |
@@ -72,7 +73,6 @@ struct wm8994; | |||
72 | struct wm8994_priv { | 73 | struct wm8994_priv { |
73 | struct wm_hubs_data hubs; | 74 | struct wm_hubs_data hubs; |
74 | struct wm8994 *wm8994; | 75 | struct wm8994 *wm8994; |
75 | struct snd_soc_codec *codec; | ||
76 | int sysclk[2]; | 76 | int sysclk[2]; |
77 | int sysclk_rate[2]; | 77 | int sysclk_rate[2]; |
78 | int mclk[2]; | 78 | int mclk[2]; |
@@ -81,6 +81,7 @@ struct wm8994_priv { | |||
81 | struct completion fll_locked[2]; | 81 | struct completion fll_locked[2]; |
82 | bool fll_locked_irq; | 82 | bool fll_locked_irq; |
83 | bool fll_byp; | 83 | bool fll_byp; |
84 | bool clk_has_run; | ||
84 | 85 | ||
85 | int vmid_refcount; | 86 | int vmid_refcount; |
86 | int active_refcount; | 87 | int active_refcount; |
@@ -134,6 +135,7 @@ struct wm8994_priv { | |||
134 | int btn_mask; | 135 | int btn_mask; |
135 | bool jackdet; | 136 | bool jackdet; |
136 | int jackdet_mode; | 137 | int jackdet_mode; |
138 | struct delayed_work jackdet_bootstrap; | ||
137 | 139 | ||
138 | wm8958_micdet_cb jack_cb; | 140 | wm8958_micdet_cb jack_cb; |
139 | void *jack_cb_data; | 141 | void *jack_cb_data; |
diff --git a/sound/soc/codecs/wm9090.c b/sound/soc/codecs/wm9090.c index 2c2346fdd637..c7ddc56175d1 100644 --- a/sound/soc/codecs/wm9090.c +++ b/sound/soc/codecs/wm9090.c | |||
@@ -695,17 +695,7 @@ static struct i2c_driver wm9090_i2c_driver = { | |||
695 | .id_table = wm9090_id, | 695 | .id_table = wm9090_id, |
696 | }; | 696 | }; |
697 | 697 | ||
698 | static int __init wm9090_init(void) | 698 | module_i2c_driver(wm9090_i2c_driver); |
699 | { | ||
700 | return i2c_add_driver(&wm9090_i2c_driver); | ||
701 | } | ||
702 | module_init(wm9090_init); | ||
703 | |||
704 | static void __exit wm9090_exit(void) | ||
705 | { | ||
706 | i2c_del_driver(&wm9090_i2c_driver); | ||
707 | } | ||
708 | module_exit(wm9090_exit); | ||
709 | 699 | ||
710 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | 700 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); |
711 | MODULE_DESCRIPTION("WM9090 ASoC driver"); | 701 | MODULE_DESCRIPTION("WM9090 ASoC driver"); |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c6d2076a796b..1992a6295a16 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -132,8 +132,9 @@ SOC_SINGLE("Aux Playback Phone Volume", AC97_CD, 4, 7, 1), | |||
132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), | 132 | SOC_SINGLE("Phone Volume", AC97_PHONE, 0, 15, 1), |
133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), | 133 | SOC_DOUBLE("Line Capture Volume", AC97_LINE, 8, 0, 31, 1), |
134 | 134 | ||
135 | SOC_SINGLE("Capture 20dB Boost Switch", AC97_REC_SEL, 14, 1, 0), | 135 | SOC_SINGLE_TLV("Capture Boost Switch", AC97_REC_SEL, 14, 1, 0, boost_tlv), |
136 | SOC_SINGLE("Capture to Phone 20dB Boost Switch", AC97_REC_SEL, 11, 1, 1), | 136 | SOC_SINGLE_TLV("Capture to Phone Boost Switch", AC97_REC_SEL, 11, 1, 1, |
137 | boost_tlv), | ||
137 | 138 | ||
138 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), | 139 | SOC_SINGLE("3D Upper Cut-off Switch", AC97_3D_CONTROL, 5, 1, 1), |
139 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), | 140 | SOC_SINGLE("3D Lower Cut-off Switch", AC97_3D_CONTROL, 4, 1, 1), |
@@ -146,7 +147,7 @@ SOC_SINGLE("Playback Attenuate (-6dB) Switch", AC97_MASTER_TONE, 6, 1, 0), | |||
146 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), | 147 | SOC_SINGLE("Bass Volume", AC97_MASTER_TONE, 8, 15, 1), |
147 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), | 148 | SOC_SINGLE("Treble Volume", AC97_MASTER_TONE, 0, 15, 1), |
148 | 149 | ||
149 | SOC_SINGLE("Capture ADC Switch", AC97_REC_GAIN, 15, 1, 1), | 150 | SOC_SINGLE("Capture Switch", AC97_REC_GAIN, 15, 1, 1), |
150 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), | 151 | SOC_ENUM("Capture Volume Steps", wm9712_enum[6]), |
151 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), | 152 | SOC_DOUBLE("Capture Volume", AC97_REC_GAIN, 8, 0, 63, 0), |
152 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), | 153 | SOC_SINGLE("Capture ZC Switch", AC97_REC_GAIN, 7, 1, 0), |
@@ -699,8 +700,8 @@ static int __devexit wm9712_remove(struct platform_device *pdev) | |||
699 | 700 | ||
700 | static struct platform_driver wm9712_codec_driver = { | 701 | static struct platform_driver wm9712_codec_driver = { |
701 | .driver = { | 702 | .driver = { |
702 | .name = "wm9712-codec", | 703 | .name = "wm9712-codec", |
703 | .owner = THIS_MODULE, | 704 | .owner = THIS_MODULE, |
704 | }, | 705 | }, |
705 | 706 | ||
706 | .probe = wm9712_probe, | 707 | .probe = wm9712_probe, |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index 61baa48823cb..7a773a835b8e 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -199,15 +199,56 @@ static void wm_hubs_dcs_cache_set(struct snd_soc_codec *codec, u16 dcs_cfg) | |||
199 | list_add_tail(&cache->list, &hubs->dcs_cache); | 199 | list_add_tail(&cache->list, &hubs->dcs_cache); |
200 | } | 200 | } |
201 | 201 | ||
202 | static void wm_hubs_read_dc_servo(struct snd_soc_codec *codec, | ||
203 | u16 *reg_l, u16 *reg_r) | ||
204 | { | ||
205 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
206 | u16 dcs_reg, reg; | ||
207 | |||
208 | switch (hubs->dcs_readback_mode) { | ||
209 | case 2: | ||
210 | dcs_reg = WM8994_DC_SERVO_4E; | ||
211 | break; | ||
212 | case 1: | ||
213 | dcs_reg = WM8994_DC_SERVO_READBACK; | ||
214 | break; | ||
215 | default: | ||
216 | dcs_reg = WM8993_DC_SERVO_3; | ||
217 | break; | ||
218 | } | ||
219 | |||
220 | /* Different chips in the family support different readback | ||
221 | * methods. | ||
222 | */ | ||
223 | switch (hubs->dcs_readback_mode) { | ||
224 | case 0: | ||
225 | *reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
226 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
227 | *reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
228 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
229 | break; | ||
230 | case 2: | ||
231 | case 1: | ||
232 | reg = snd_soc_read(codec, dcs_reg); | ||
233 | *reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
234 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
235 | *reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
236 | break; | ||
237 | default: | ||
238 | WARN(1, "Unknown DCS readback method\n"); | ||
239 | return; | ||
240 | } | ||
241 | } | ||
242 | |||
202 | /* | 243 | /* |
203 | * Startup calibration of the DC servo | 244 | * Startup calibration of the DC servo |
204 | */ | 245 | */ |
205 | static void calibrate_dc_servo(struct snd_soc_codec *codec) | 246 | static void enable_dc_servo(struct snd_soc_codec *codec) |
206 | { | 247 | { |
207 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 248 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
208 | struct wm_hubs_dcs_cache *cache; | 249 | struct wm_hubs_dcs_cache *cache; |
209 | s8 offset; | 250 | s8 offset; |
210 | u16 reg, reg_l, reg_r, dcs_cfg, dcs_reg; | 251 | u16 reg_l, reg_r, dcs_cfg, dcs_reg; |
211 | 252 | ||
212 | switch (hubs->dcs_readback_mode) { | 253 | switch (hubs->dcs_readback_mode) { |
213 | case 2: | 254 | case 2: |
@@ -245,27 +286,7 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
245 | WM8993_DCS_TRIG_STARTUP_1); | 286 | WM8993_DCS_TRIG_STARTUP_1); |
246 | } | 287 | } |
247 | 288 | ||
248 | /* Different chips in the family support different readback | 289 | wm_hubs_read_dc_servo(codec, ®_l, ®_r); |
249 | * methods. | ||
250 | */ | ||
251 | switch (hubs->dcs_readback_mode) { | ||
252 | case 0: | ||
253 | reg_l = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_1) | ||
254 | & WM8993_DCS_INTEG_CHAN_0_MASK; | ||
255 | reg_r = snd_soc_read(codec, WM8993_DC_SERVO_READBACK_2) | ||
256 | & WM8993_DCS_INTEG_CHAN_1_MASK; | ||
257 | break; | ||
258 | case 2: | ||
259 | case 1: | ||
260 | reg = snd_soc_read(codec, dcs_reg); | ||
261 | reg_r = (reg & WM8993_DCS_DAC_WR_VAL_1_MASK) | ||
262 | >> WM8993_DCS_DAC_WR_VAL_1_SHIFT; | ||
263 | reg_l = reg & WM8993_DCS_DAC_WR_VAL_0_MASK; | ||
264 | break; | ||
265 | default: | ||
266 | WARN(1, "Unknown DCS readback method\n"); | ||
267 | return; | ||
268 | } | ||
269 | 290 | ||
270 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); | 291 | dev_dbg(codec->dev, "DCS input: %x %x\n", reg_l, reg_r); |
271 | 292 | ||
@@ -276,12 +297,16 @@ static void calibrate_dc_servo(struct snd_soc_codec *codec) | |||
276 | hubs->dcs_codes_l, hubs->dcs_codes_r); | 297 | hubs->dcs_codes_l, hubs->dcs_codes_r); |
277 | 298 | ||
278 | /* HPOUT1R */ | 299 | /* HPOUT1R */ |
279 | offset = reg_r; | 300 | offset = (s8)reg_r; |
301 | dev_dbg(codec->dev, "DCS right %d->%d\n", offset, | ||
302 | offset + hubs->dcs_codes_r); | ||
280 | offset += hubs->dcs_codes_r; | 303 | offset += hubs->dcs_codes_r; |
281 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; | 304 | dcs_cfg = (u8)offset << WM8993_DCS_DAC_WR_VAL_1_SHIFT; |
282 | 305 | ||
283 | /* HPOUT1L */ | 306 | /* HPOUT1L */ |
284 | offset = reg_l; | 307 | offset = (s8)reg_l; |
308 | dev_dbg(codec->dev, "DCS left %d->%d\n", offset, | ||
309 | offset + hubs->dcs_codes_l); | ||
285 | offset += hubs->dcs_codes_l; | 310 | offset += hubs->dcs_codes_l; |
286 | dcs_cfg |= (u8)offset; | 311 | dcs_cfg |= (u8)offset; |
287 | 312 | ||
@@ -535,7 +560,7 @@ static int hp_event(struct snd_soc_dapm_widget *w, | |||
535 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, | 560 | snd_soc_update_bits(codec, WM8993_DC_SERVO_1, |
536 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); | 561 | WM8993_DCS_TIMER_PERIOD_01_MASK, 0); |
537 | 562 | ||
538 | calibrate_dc_servo(codec); | 563 | enable_dc_servo(codec); |
539 | 564 | ||
540 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | | 565 | reg |= WM8993_HPOUT1R_OUTP | WM8993_HPOUT1R_RMV_SHORT | |
541 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; | 566 | WM8993_HPOUT1L_OUTP | WM8993_HPOUT1L_RMV_SHORT; |
@@ -619,6 +644,28 @@ static int lineout_event(struct snd_soc_dapm_widget *w, | |||
619 | return 0; | 644 | return 0; |
620 | } | 645 | } |
621 | 646 | ||
647 | static int micbias_event(struct snd_soc_dapm_widget *w, | ||
648 | struct snd_kcontrol *kcontrol, int event) | ||
649 | { | ||
650 | struct snd_soc_codec *codec = w->codec; | ||
651 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | ||
652 | |||
653 | switch (w->shift) { | ||
654 | case WM8993_MICB1_ENA_SHIFT: | ||
655 | if (hubs->micb1_delay) | ||
656 | msleep(hubs->micb1_delay); | ||
657 | break; | ||
658 | case WM8993_MICB2_ENA_SHIFT: | ||
659 | if (hubs->micb2_delay) | ||
660 | msleep(hubs->micb2_delay); | ||
661 | break; | ||
662 | default: | ||
663 | return -EINVAL; | ||
664 | } | ||
665 | |||
666 | return 0; | ||
667 | } | ||
668 | |||
622 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) | 669 | void wm_hubs_update_class_w(struct snd_soc_codec *codec) |
623 | { | 670 | { |
624 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 671 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
@@ -809,8 +856,10 @@ SND_SOC_DAPM_INPUT("IN1RP"), | |||
809 | SND_SOC_DAPM_INPUT("IN2RN"), | 856 | SND_SOC_DAPM_INPUT("IN2RN"), |
810 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), | 857 | SND_SOC_DAPM_INPUT("IN2RP:VXRP"), |
811 | 858 | ||
812 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, NULL, 0), | 859 | SND_SOC_DAPM_SUPPLY("MICBIAS2", WM8993_POWER_MANAGEMENT_1, 5, 0, |
813 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, NULL, 0), | 860 | micbias_event, SND_SOC_DAPM_POST_PMU), |
861 | SND_SOC_DAPM_SUPPLY("MICBIAS1", WM8993_POWER_MANAGEMENT_1, 4, 0, | ||
862 | micbias_event, SND_SOC_DAPM_POST_PMU), | ||
814 | 863 | ||
815 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, | 864 | SND_SOC_DAPM_MIXER("IN1L PGA", WM8993_POWER_MANAGEMENT_2, 6, 0, |
816 | in1l_pga, ARRAY_SIZE(in1l_pga)), | 865 | in1l_pga, ARRAY_SIZE(in1l_pga)), |
@@ -1112,6 +1161,8 @@ int wm_hubs_add_analogue_routes(struct snd_soc_codec *codec, | |||
1112 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1161 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
1113 | struct snd_soc_dapm_context *dapm = &codec->dapm; | 1162 | struct snd_soc_dapm_context *dapm = &codec->dapm; |
1114 | 1163 | ||
1164 | hubs->codec = codec; | ||
1165 | |||
1115 | INIT_LIST_HEAD(&hubs->dcs_cache); | 1166 | INIT_LIST_HEAD(&hubs->dcs_cache); |
1116 | init_completion(&hubs->dcs_done); | 1167 | init_completion(&hubs->dcs_done); |
1117 | 1168 | ||
@@ -1143,13 +1194,16 @@ EXPORT_SYMBOL_GPL(wm_hubs_add_analogue_routes); | |||
1143 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, | 1194 | int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *codec, |
1144 | int lineout1_diff, int lineout2_diff, | 1195 | int lineout1_diff, int lineout2_diff, |
1145 | int lineout1fb, int lineout2fb, | 1196 | int lineout1fb, int lineout2fb, |
1146 | int jd_scthr, int jd_thr, int micbias1_lvl, | 1197 | int jd_scthr, int jd_thr, |
1147 | int micbias2_lvl) | 1198 | int micbias1_delay, int micbias2_delay, |
1199 | int micbias1_lvl, int micbias2_lvl) | ||
1148 | { | 1200 | { |
1149 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); | 1201 | struct wm_hubs_data *hubs = snd_soc_codec_get_drvdata(codec); |
1150 | 1202 | ||
1151 | hubs->lineout1_se = !lineout1_diff; | 1203 | hubs->lineout1_se = !lineout1_diff; |
1152 | hubs->lineout2_se = !lineout2_diff; | 1204 | hubs->lineout2_se = !lineout2_diff; |
1205 | hubs->micb1_delay = micbias1_delay; | ||
1206 | hubs->micb2_delay = micbias2_delay; | ||
1153 | 1207 | ||
1154 | if (!lineout1_diff) | 1208 | if (!lineout1_diff) |
1155 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, | 1209 | snd_soc_update_bits(codec, WM8993_LINE_MIXER1, |
diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index da2dc899ce6d..24c763df21f9 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h | |||
@@ -36,6 +36,9 @@ struct wm_hubs_data { | |||
36 | struct list_head dcs_cache; | 36 | struct list_head dcs_cache; |
37 | bool (*check_class_w_digital)(struct snd_soc_codec *); | 37 | bool (*check_class_w_digital)(struct snd_soc_codec *); |
38 | 38 | ||
39 | int micb1_delay; | ||
40 | int micb2_delay; | ||
41 | |||
39 | bool lineout1_se; | 42 | bool lineout1_se; |
40 | bool lineout1n_ena; | 43 | bool lineout1n_ena; |
41 | bool lineout1p_ena; | 44 | bool lineout1p_ena; |
@@ -46,6 +49,8 @@ struct wm_hubs_data { | |||
46 | 49 | ||
47 | bool dcs_done_irq; | 50 | bool dcs_done_irq; |
48 | struct completion dcs_done; | 51 | struct completion dcs_done; |
52 | |||
53 | struct snd_soc_codec *codec; | ||
49 | }; | 54 | }; |
50 | 55 | ||
51 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); | 56 | extern int wm_hubs_add_analogue_controls(struct snd_soc_codec *); |
@@ -54,6 +59,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_codec *, | |||
54 | int lineout1_diff, int lineout2_diff, | 59 | int lineout1_diff, int lineout2_diff, |
55 | int lineout1fb, int lineout2fb, | 60 | int lineout1fb, int lineout2fb, |
56 | int jd_scthr, int jd_thr, | 61 | int jd_scthr, int jd_thr, |
62 | int micbias1_dly, int micbias2_dly, | ||
57 | int micbias1_lvl, int micbias2_lvl); | 63 | int micbias1_lvl, int micbias2_lvl); |
58 | 64 | ||
59 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); | 65 | extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); |
diff --git a/sound/soc/davinci/davinci-evm.c b/sound/soc/davinci/davinci-evm.c index 10a2d8c788b7..6fac5af13298 100644 --- a/sound/soc/davinci/davinci-evm.c +++ b/sound/soc/davinci/davinci-evm.c | |||
@@ -22,10 +22,6 @@ | |||
22 | #include <asm/dma.h> | 22 | #include <asm/dma.h> |
23 | #include <asm/mach-types.h> | 23 | #include <asm/mach-types.h> |
24 | 24 | ||
25 | #include <mach/asp.h> | ||
26 | #include <mach/edma.h> | ||
27 | #include <mach/mux.h> | ||
28 | |||
29 | #include "davinci-pcm.h" | 25 | #include "davinci-pcm.h" |
30 | #include "davinci-i2s.h" | 26 | #include "davinci-i2s.h" |
31 | #include "davinci-mcasp.h" | 27 | #include "davinci-mcasp.h" |
@@ -160,7 +156,7 @@ static struct snd_soc_dai_link dm6446_evm_dai = { | |||
160 | .cpu_dai_name = "davinci-mcbsp", | 156 | .cpu_dai_name = "davinci-mcbsp", |
161 | .codec_dai_name = "tlv320aic3x-hifi", | 157 | .codec_dai_name = "tlv320aic3x-hifi", |
162 | .codec_name = "tlv320aic3x-codec.1-001b", | 158 | .codec_name = "tlv320aic3x-codec.1-001b", |
163 | .platform_name = "davinci-pcm-audio", | 159 | .platform_name = "davinci-mcbsp", |
164 | .init = evm_aic3x_init, | 160 | .init = evm_aic3x_init, |
165 | .ops = &evm_ops, | 161 | .ops = &evm_ops, |
166 | }; | 162 | }; |
@@ -171,7 +167,7 @@ static struct snd_soc_dai_link dm355_evm_dai = { | |||
171 | .cpu_dai_name = "davinci-mcbsp.1", | 167 | .cpu_dai_name = "davinci-mcbsp.1", |
172 | .codec_dai_name = "tlv320aic3x-hifi", | 168 | .codec_dai_name = "tlv320aic3x-hifi", |
173 | .codec_name = "tlv320aic3x-codec.1-001b", | 169 | .codec_name = "tlv320aic3x-codec.1-001b", |
174 | .platform_name = "davinci-pcm-audio", | 170 | .platform_name = "davinci-mcbsp.1", |
175 | .init = evm_aic3x_init, | 171 | .init = evm_aic3x_init, |
176 | .ops = &evm_ops, | 172 | .ops = &evm_ops, |
177 | }; | 173 | }; |
@@ -185,14 +181,15 @@ static struct snd_soc_dai_link dm365_evm_dai = { | |||
185 | .init = evm_aic3x_init, | 181 | .init = evm_aic3x_init, |
186 | .codec_name = "tlv320aic3x-codec.1-0018", | 182 | .codec_name = "tlv320aic3x-codec.1-0018", |
187 | .ops = &evm_ops, | 183 | .ops = &evm_ops, |
184 | .platform_name = "davinci-mcbsp", | ||
188 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) | 185 | #elif defined(CONFIG_SND_DM365_VOICE_CODEC) |
189 | .name = "Voice Codec - CQ93VC", | 186 | .name = "Voice Codec - CQ93VC", |
190 | .stream_name = "CQ93", | 187 | .stream_name = "CQ93", |
191 | .cpu_dai_name = "davinci-vcif", | 188 | .cpu_dai_name = "davinci-vcif", |
192 | .codec_dai_name = "cq93vc-hifi", | 189 | .codec_dai_name = "cq93vc-hifi", |
193 | .codec_name = "cq93vc-codec", | 190 | .codec_name = "cq93vc-codec", |
191 | .platform_name = "davinci-vcif", | ||
194 | #endif | 192 | #endif |
195 | .platform_name = "davinci-pcm-audio", | ||
196 | }; | 193 | }; |
197 | 194 | ||
198 | static struct snd_soc_dai_link dm6467_evm_dai[] = { | 195 | static struct snd_soc_dai_link dm6467_evm_dai[] = { |
@@ -201,7 +198,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
201 | .stream_name = "AIC3X", | 198 | .stream_name = "AIC3X", |
202 | .cpu_dai_name= "davinci-mcasp.0", | 199 | .cpu_dai_name= "davinci-mcasp.0", |
203 | .codec_dai_name = "tlv320aic3x-hifi", | 200 | .codec_dai_name = "tlv320aic3x-hifi", |
204 | .platform_name ="davinci-pcm-audio", | 201 | .platform_name = "davinci-mcasp.0", |
205 | .codec_name = "tlv320aic3x-codec.0-001a", | 202 | .codec_name = "tlv320aic3x-codec.0-001a", |
206 | .init = evm_aic3x_init, | 203 | .init = evm_aic3x_init, |
207 | .ops = &evm_ops, | 204 | .ops = &evm_ops, |
@@ -212,7 +209,7 @@ static struct snd_soc_dai_link dm6467_evm_dai[] = { | |||
212 | .cpu_dai_name= "davinci-mcasp.1", | 209 | .cpu_dai_name= "davinci-mcasp.1", |
213 | .codec_dai_name = "dit-hifi", | 210 | .codec_dai_name = "dit-hifi", |
214 | .codec_name = "spdif_dit", | 211 | .codec_name = "spdif_dit", |
215 | .platform_name = "davinci-pcm-audio", | 212 | .platform_name = "davinci-mcasp.1", |
216 | .ops = &evm_spdif_ops, | 213 | .ops = &evm_spdif_ops, |
217 | }, | 214 | }, |
218 | }; | 215 | }; |
@@ -223,7 +220,7 @@ static struct snd_soc_dai_link da830_evm_dai = { | |||
223 | .cpu_dai_name = "davinci-mcasp.1", | 220 | .cpu_dai_name = "davinci-mcasp.1", |
224 | .codec_dai_name = "tlv320aic3x-hifi", | 221 | .codec_dai_name = "tlv320aic3x-hifi", |
225 | .codec_name = "tlv320aic3x-codec.1-0018", | 222 | .codec_name = "tlv320aic3x-codec.1-0018", |
226 | .platform_name = "davinci-pcm-audio", | 223 | .platform_name = "davinci-mcasp.1", |
227 | .init = evm_aic3x_init, | 224 | .init = evm_aic3x_init, |
228 | .ops = &evm_ops, | 225 | .ops = &evm_ops, |
229 | }; | 226 | }; |
@@ -234,7 +231,7 @@ static struct snd_soc_dai_link da850_evm_dai = { | |||
234 | .cpu_dai_name= "davinci-mcasp.0", | 231 | .cpu_dai_name= "davinci-mcasp.0", |
235 | .codec_dai_name = "tlv320aic3x-hifi", | 232 | .codec_dai_name = "tlv320aic3x-hifi", |
236 | .codec_name = "tlv320aic3x-codec.1-0018", | 233 | .codec_name = "tlv320aic3x-codec.1-0018", |
237 | .platform_name = "davinci-pcm-audio", | 234 | .platform_name = "davinci-mcasp.0", |
238 | .init = evm_aic3x_init, | 235 | .init = evm_aic3x_init, |
239 | .ops = &evm_ops, | 236 | .ops = &evm_ops, |
240 | }; | 237 | }; |
diff --git a/sound/soc/davinci/davinci-i2s.c b/sound/soc/davinci/davinci-i2s.c index 0a74b9587a2c..821831207180 100644 --- a/sound/soc/davinci/davinci-i2s.c +++ b/sound/soc/davinci/davinci-i2s.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/delay.h> | 16 | #include <linux/delay.h> |
17 | #include <linux/io.h> | 17 | #include <linux/io.h> |
18 | #include <linux/clk.h> | 18 | #include <linux/clk.h> |
19 | #include <linux/platform_data/davinci_asp.h> | ||
19 | 20 | ||
20 | #include <sound/core.h> | 21 | #include <sound/core.h> |
21 | #include <sound/pcm.h> | 22 | #include <sound/pcm.h> |
@@ -23,8 +24,6 @@ | |||
23 | #include <sound/initval.h> | 24 | #include <sound/initval.h> |
24 | #include <sound/soc.h> | 25 | #include <sound/soc.h> |
25 | 26 | ||
26 | #include <mach/asp.h> | ||
27 | |||
28 | #include "davinci-pcm.h" | 27 | #include "davinci-pcm.h" |
29 | #include "davinci-i2s.h" | 28 | #include "davinci-i2s.h" |
30 | 29 | ||
@@ -732,8 +731,16 @@ static int davinci_i2s_probe(struct platform_device *pdev) | |||
732 | if (ret != 0) | 731 | if (ret != 0) |
733 | goto err_release_clk; | 732 | goto err_release_clk; |
734 | 733 | ||
734 | ret = davinci_soc_platform_register(&pdev->dev); | ||
735 | if (ret) { | ||
736 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
737 | goto err_unregister_dai; | ||
738 | } | ||
739 | |||
735 | return 0; | 740 | return 0; |
736 | 741 | ||
742 | err_unregister_dai: | ||
743 | snd_soc_unregister_dai(&pdev->dev); | ||
737 | err_release_clk: | 744 | err_release_clk: |
738 | clk_disable(dev->clk); | 745 | clk_disable(dev->clk); |
739 | clk_put(dev->clk); | 746 | clk_put(dev->clk); |
@@ -745,6 +752,8 @@ static int davinci_i2s_remove(struct platform_device *pdev) | |||
745 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); | 752 | struct davinci_mcbsp_dev *dev = dev_get_drvdata(&pdev->dev); |
746 | 753 | ||
747 | snd_soc_unregister_dai(&pdev->dev); | 754 | snd_soc_unregister_dai(&pdev->dev); |
755 | davinci_soc_platform_unregister(&pdev->dev); | ||
756 | |||
748 | clk_disable(dev->clk); | 757 | clk_disable(dev->clk); |
749 | clk_put(dev->clk); | 758 | clk_put(dev->clk); |
750 | dev->clk = NULL; | 759 | dev->clk = NULL; |
diff --git a/sound/soc/davinci/davinci-mcasp.c b/sound/soc/davinci/davinci-mcasp.c index ce5e5cd254dd..c3eae1d8e077 100644 --- a/sound/soc/davinci/davinci-mcasp.c +++ b/sound/soc/davinci/davinci-mcasp.c | |||
@@ -21,7 +21,10 @@ | |||
21 | #include <linux/slab.h> | 21 | #include <linux/slab.h> |
22 | #include <linux/delay.h> | 22 | #include <linux/delay.h> |
23 | #include <linux/io.h> | 23 | #include <linux/io.h> |
24 | #include <linux/clk.h> | 24 | #include <linux/pm_runtime.h> |
25 | #include <linux/of.h> | ||
26 | #include <linux/of_platform.h> | ||
27 | #include <linux/of_device.h> | ||
25 | 28 | ||
26 | #include <sound/core.h> | 29 | #include <sound/core.h> |
27 | #include <sound/pcm.h> | 30 | #include <sound/pcm.h> |
@@ -782,20 +785,17 @@ static int davinci_mcasp_trigger(struct snd_pcm_substream *substream, | |||
782 | case SNDRV_PCM_TRIGGER_RESUME: | 785 | case SNDRV_PCM_TRIGGER_RESUME: |
783 | case SNDRV_PCM_TRIGGER_START: | 786 | case SNDRV_PCM_TRIGGER_START: |
784 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: | 787 | case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: |
785 | if (!dev->clk_active) { | 788 | ret = pm_runtime_get_sync(dev->dev); |
786 | clk_enable(dev->clk); | 789 | if (IS_ERR_VALUE(ret)) |
787 | dev->clk_active = 1; | 790 | dev_err(dev->dev, "pm_runtime_get_sync() failed\n"); |
788 | } | ||
789 | davinci_mcasp_start(dev, substream->stream); | 791 | davinci_mcasp_start(dev, substream->stream); |
790 | break; | 792 | break; |
791 | 793 | ||
792 | case SNDRV_PCM_TRIGGER_SUSPEND: | 794 | case SNDRV_PCM_TRIGGER_SUSPEND: |
793 | davinci_mcasp_stop(dev, substream->stream); | 795 | davinci_mcasp_stop(dev, substream->stream); |
794 | if (dev->clk_active) { | 796 | ret = pm_runtime_put_sync(dev->dev); |
795 | clk_disable(dev->clk); | 797 | if (IS_ERR_VALUE(ret)) |
796 | dev->clk_active = 0; | 798 | dev_err(dev->dev, "pm_runtime_put_sync() failed\n"); |
797 | } | ||
798 | |||
799 | break; | 799 | break; |
800 | 800 | ||
801 | case SNDRV_PCM_TRIGGER_STOP: | 801 | case SNDRV_PCM_TRIGGER_STOP: |
@@ -865,6 +865,114 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = { | |||
865 | 865 | ||
866 | }; | 866 | }; |
867 | 867 | ||
868 | static const struct of_device_id mcasp_dt_ids[] = { | ||
869 | { | ||
870 | .compatible = "ti,dm646x-mcasp-audio", | ||
871 | .data = (void *)MCASP_VERSION_1, | ||
872 | }, | ||
873 | { | ||
874 | .compatible = "ti,da830-mcasp-audio", | ||
875 | .data = (void *)MCASP_VERSION_2, | ||
876 | }, | ||
877 | { /* sentinel */ } | ||
878 | }; | ||
879 | MODULE_DEVICE_TABLE(of, mcasp_dt_ids); | ||
880 | |||
881 | static struct snd_platform_data *davinci_mcasp_set_pdata_from_of( | ||
882 | struct platform_device *pdev) | ||
883 | { | ||
884 | struct device_node *np = pdev->dev.of_node; | ||
885 | struct snd_platform_data *pdata = NULL; | ||
886 | const struct of_device_id *match = | ||
887 | of_match_device(of_match_ptr(mcasp_dt_ids), &pdev->dev); | ||
888 | |||
889 | const u32 *of_serial_dir32; | ||
890 | u8 *of_serial_dir; | ||
891 | u32 val; | ||
892 | int i, ret = 0; | ||
893 | |||
894 | if (pdev->dev.platform_data) { | ||
895 | pdata = pdev->dev.platform_data; | ||
896 | return pdata; | ||
897 | } else if (match) { | ||
898 | pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL); | ||
899 | if (!pdata) { | ||
900 | ret = -ENOMEM; | ||
901 | goto nodata; | ||
902 | } | ||
903 | } else { | ||
904 | /* control shouldn't reach here. something is wrong */ | ||
905 | ret = -EINVAL; | ||
906 | goto nodata; | ||
907 | } | ||
908 | |||
909 | if (match->data) | ||
910 | pdata->version = (u8)((int)match->data); | ||
911 | |||
912 | ret = of_property_read_u32(np, "op-mode", &val); | ||
913 | if (ret >= 0) | ||
914 | pdata->op_mode = val; | ||
915 | |||
916 | ret = of_property_read_u32(np, "tdm-slots", &val); | ||
917 | if (ret >= 0) | ||
918 | pdata->tdm_slots = val; | ||
919 | |||
920 | ret = of_property_read_u32(np, "num-serializer", &val); | ||
921 | if (ret >= 0) | ||
922 | pdata->num_serializer = val; | ||
923 | |||
924 | of_serial_dir32 = of_get_property(np, "serial-dir", &val); | ||
925 | val /= sizeof(u32); | ||
926 | if (val != pdata->num_serializer) { | ||
927 | dev_err(&pdev->dev, | ||
928 | "num-serializer(%d) != serial-dir size(%d)\n", | ||
929 | pdata->num_serializer, val); | ||
930 | ret = -EINVAL; | ||
931 | goto nodata; | ||
932 | } | ||
933 | |||
934 | if (of_serial_dir32) { | ||
935 | of_serial_dir = devm_kzalloc(&pdev->dev, | ||
936 | (sizeof(*of_serial_dir) * val), | ||
937 | GFP_KERNEL); | ||
938 | if (!of_serial_dir) { | ||
939 | ret = -ENOMEM; | ||
940 | goto nodata; | ||
941 | } | ||
942 | |||
943 | for (i = 0; i < pdata->num_serializer; i++) | ||
944 | of_serial_dir[i] = be32_to_cpup(&of_serial_dir32[i]); | ||
945 | |||
946 | pdata->serial_dir = of_serial_dir; | ||
947 | } | ||
948 | |||
949 | ret = of_property_read_u32(np, "tx-num-evt", &val); | ||
950 | if (ret >= 0) | ||
951 | pdata->txnumevt = val; | ||
952 | |||
953 | ret = of_property_read_u32(np, "rx-num-evt", &val); | ||
954 | if (ret >= 0) | ||
955 | pdata->rxnumevt = val; | ||
956 | |||
957 | ret = of_property_read_u32(np, "sram-size-playback", &val); | ||
958 | if (ret >= 0) | ||
959 | pdata->sram_size_playback = val; | ||
960 | |||
961 | ret = of_property_read_u32(np, "sram-size-capture", &val); | ||
962 | if (ret >= 0) | ||
963 | pdata->sram_size_capture = val; | ||
964 | |||
965 | return pdata; | ||
966 | |||
967 | nodata: | ||
968 | if (ret < 0) { | ||
969 | dev_err(&pdev->dev, "Error populating platform data, err %d\n", | ||
970 | ret); | ||
971 | pdata = NULL; | ||
972 | } | ||
973 | return pdata; | ||
974 | } | ||
975 | |||
868 | static int davinci_mcasp_probe(struct platform_device *pdev) | 976 | static int davinci_mcasp_probe(struct platform_device *pdev) |
869 | { | 977 | { |
870 | struct davinci_pcm_dma_params *dma_data; | 978 | struct davinci_pcm_dma_params *dma_data; |
@@ -873,11 +981,22 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
873 | struct davinci_audio_dev *dev; | 981 | struct davinci_audio_dev *dev; |
874 | int ret; | 982 | int ret; |
875 | 983 | ||
984 | if (!pdev->dev.platform_data && !pdev->dev.of_node) { | ||
985 | dev_err(&pdev->dev, "No platform data supplied\n"); | ||
986 | return -EINVAL; | ||
987 | } | ||
988 | |||
876 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), | 989 | dev = devm_kzalloc(&pdev->dev, sizeof(struct davinci_audio_dev), |
877 | GFP_KERNEL); | 990 | GFP_KERNEL); |
878 | if (!dev) | 991 | if (!dev) |
879 | return -ENOMEM; | 992 | return -ENOMEM; |
880 | 993 | ||
994 | pdata = davinci_mcasp_set_pdata_from_of(pdev); | ||
995 | if (!pdata) { | ||
996 | dev_err(&pdev->dev, "no platform data\n"); | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
881 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 1000 | mem = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
882 | if (!mem) { | 1001 | if (!mem) { |
883 | dev_err(&pdev->dev, "no mem resource?\n"); | 1002 | dev_err(&pdev->dev, "no mem resource?\n"); |
@@ -891,13 +1010,13 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
891 | return -EBUSY; | 1010 | return -EBUSY; |
892 | } | 1011 | } |
893 | 1012 | ||
894 | pdata = pdev->dev.platform_data; | 1013 | pm_runtime_enable(&pdev->dev); |
895 | dev->clk = clk_get(&pdev->dev, NULL); | ||
896 | if (IS_ERR(dev->clk)) | ||
897 | return -ENODEV; | ||
898 | 1014 | ||
899 | clk_enable(dev->clk); | 1015 | ret = pm_runtime_get_sync(&pdev->dev); |
900 | dev->clk_active = 1; | 1016 | if (IS_ERR_VALUE(ret)) { |
1017 | dev_err(&pdev->dev, "pm_runtime_get_sync() failed\n"); | ||
1018 | return ret; | ||
1019 | } | ||
901 | 1020 | ||
902 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | 1021 | dev->base = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); |
903 | if (!dev->base) { | 1022 | if (!dev->base) { |
@@ -914,6 +1033,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
914 | dev->version = pdata->version; | 1033 | dev->version = pdata->version; |
915 | dev->txnumevt = pdata->txnumevt; | 1034 | dev->txnumevt = pdata->txnumevt; |
916 | dev->rxnumevt = pdata->rxnumevt; | 1035 | dev->rxnumevt = pdata->rxnumevt; |
1036 | dev->dev = &pdev->dev; | ||
917 | 1037 | ||
918 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; | 1038 | dma_data = &dev->dma_params[SNDRV_PCM_STREAM_PLAYBACK]; |
919 | dma_data->asp_chan_q = pdata->asp_chan_q; | 1039 | dma_data->asp_chan_q = pdata->asp_chan_q; |
@@ -952,22 +1072,31 @@ static int davinci_mcasp_probe(struct platform_device *pdev) | |||
952 | 1072 | ||
953 | if (ret != 0) | 1073 | if (ret != 0) |
954 | goto err_release_clk; | 1074 | goto err_release_clk; |
1075 | |||
1076 | ret = davinci_soc_platform_register(&pdev->dev); | ||
1077 | if (ret) { | ||
1078 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
1079 | goto err_unregister_dai; | ||
1080 | } | ||
1081 | |||
955 | return 0; | 1082 | return 0; |
956 | 1083 | ||
1084 | err_unregister_dai: | ||
1085 | snd_soc_unregister_dai(&pdev->dev); | ||
957 | err_release_clk: | 1086 | err_release_clk: |
958 | clk_disable(dev->clk); | 1087 | pm_runtime_put_sync(&pdev->dev); |
959 | clk_put(dev->clk); | 1088 | pm_runtime_disable(&pdev->dev); |
960 | return ret; | 1089 | return ret; |
961 | } | 1090 | } |
962 | 1091 | ||
963 | static int davinci_mcasp_remove(struct platform_device *pdev) | 1092 | static int davinci_mcasp_remove(struct platform_device *pdev) |
964 | { | 1093 | { |
965 | struct davinci_audio_dev *dev = dev_get_drvdata(&pdev->dev); | ||
966 | 1094 | ||
967 | snd_soc_unregister_dai(&pdev->dev); | 1095 | snd_soc_unregister_dai(&pdev->dev); |
968 | clk_disable(dev->clk); | 1096 | davinci_soc_platform_unregister(&pdev->dev); |
969 | clk_put(dev->clk); | 1097 | |
970 | dev->clk = NULL; | 1098 | pm_runtime_put_sync(&pdev->dev); |
1099 | pm_runtime_disable(&pdev->dev); | ||
971 | 1100 | ||
972 | return 0; | 1101 | return 0; |
973 | } | 1102 | } |
@@ -978,6 +1107,7 @@ static struct platform_driver davinci_mcasp_driver = { | |||
978 | .driver = { | 1107 | .driver = { |
979 | .name = "davinci-mcasp", | 1108 | .name = "davinci-mcasp", |
980 | .owner = THIS_MODULE, | 1109 | .owner = THIS_MODULE, |
1110 | .of_match_table = of_match_ptr(mcasp_dt_ids), | ||
981 | }, | 1111 | }, |
982 | }; | 1112 | }; |
983 | 1113 | ||
diff --git a/sound/soc/davinci/davinci-mcasp.h b/sound/soc/davinci/davinci-mcasp.h index 4681acc63606..0de9ed6ce038 100644 --- a/sound/soc/davinci/davinci-mcasp.h +++ b/sound/soc/davinci/davinci-mcasp.h | |||
@@ -19,7 +19,8 @@ | |||
19 | #define DAVINCI_MCASP_H | 19 | #define DAVINCI_MCASP_H |
20 | 20 | ||
21 | #include <linux/io.h> | 21 | #include <linux/io.h> |
22 | #include <mach/asp.h> | 22 | #include <linux/platform_data/davinci_asp.h> |
23 | |||
23 | #include "davinci-pcm.h" | 24 | #include "davinci-pcm.h" |
24 | 25 | ||
25 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 | 26 | #define DAVINCI_MCASP_RATES SNDRV_PCM_RATE_8000_96000 |
@@ -40,9 +41,8 @@ struct davinci_audio_dev { | |||
40 | struct davinci_pcm_dma_params dma_params[2]; | 41 | struct davinci_pcm_dma_params dma_params[2]; |
41 | void __iomem *base; | 42 | void __iomem *base; |
42 | int sample_rate; | 43 | int sample_rate; |
43 | struct clk *clk; | 44 | struct device *dev; |
44 | unsigned int codec_fmt; | 45 | unsigned int codec_fmt; |
45 | u8 clk_active; | ||
46 | 46 | ||
47 | /* McASP specific data */ | 47 | /* McASP specific data */ |
48 | int tdm_slots; | 48 | int tdm_slots; |
diff --git a/sound/soc/davinci/davinci-pcm.c b/sound/soc/davinci/davinci-pcm.c index 97d77b298968..93ea3bf567e1 100644 --- a/sound/soc/davinci/davinci-pcm.c +++ b/sound/soc/davinci/davinci-pcm.c | |||
@@ -23,7 +23,6 @@ | |||
23 | #include <sound/soc.h> | 23 | #include <sound/soc.h> |
24 | 24 | ||
25 | #include <asm/dma.h> | 25 | #include <asm/dma.h> |
26 | #include <mach/edma.h> | ||
27 | #include <mach/sram.h> | 26 | #include <mach/sram.h> |
28 | 27 | ||
29 | #include "davinci-pcm.h" | 28 | #include "davinci-pcm.h" |
@@ -864,28 +863,17 @@ static struct snd_soc_platform_driver davinci_soc_platform = { | |||
864 | .pcm_free = davinci_pcm_free, | 863 | .pcm_free = davinci_pcm_free, |
865 | }; | 864 | }; |
866 | 865 | ||
867 | static int __devinit davinci_soc_platform_probe(struct platform_device *pdev) | 866 | int davinci_soc_platform_register(struct device *dev) |
868 | { | 867 | { |
869 | return snd_soc_register_platform(&pdev->dev, &davinci_soc_platform); | 868 | return snd_soc_register_platform(dev, &davinci_soc_platform); |
870 | } | 869 | } |
870 | EXPORT_SYMBOL_GPL(davinci_soc_platform_register); | ||
871 | 871 | ||
872 | static int __devexit davinci_soc_platform_remove(struct platform_device *pdev) | 872 | void davinci_soc_platform_unregister(struct device *dev) |
873 | { | 873 | { |
874 | snd_soc_unregister_platform(&pdev->dev); | 874 | snd_soc_unregister_platform(dev); |
875 | return 0; | ||
876 | } | 875 | } |
877 | 876 | EXPORT_SYMBOL_GPL(davinci_soc_platform_unregister); | |
878 | static struct platform_driver davinci_pcm_driver = { | ||
879 | .driver = { | ||
880 | .name = "davinci-pcm-audio", | ||
881 | .owner = THIS_MODULE, | ||
882 | }, | ||
883 | |||
884 | .probe = davinci_soc_platform_probe, | ||
885 | .remove = __devexit_p(davinci_soc_platform_remove), | ||
886 | }; | ||
887 | |||
888 | module_platform_driver(davinci_pcm_driver); | ||
889 | 877 | ||
890 | MODULE_AUTHOR("Vladimir Barinov"); | 878 | MODULE_AUTHOR("Vladimir Barinov"); |
891 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); | 879 | MODULE_DESCRIPTION("TI DAVINCI PCM DMA module"); |
diff --git a/sound/soc/davinci/davinci-pcm.h b/sound/soc/davinci/davinci-pcm.h index c0d6c9be4b4d..fc4d01cdd8c9 100644 --- a/sound/soc/davinci/davinci-pcm.h +++ b/sound/soc/davinci/davinci-pcm.h | |||
@@ -12,9 +12,8 @@ | |||
12 | #ifndef _DAVINCI_PCM_H | 12 | #ifndef _DAVINCI_PCM_H |
13 | #define _DAVINCI_PCM_H | 13 | #define _DAVINCI_PCM_H |
14 | 14 | ||
15 | #include <linux/platform_data/davinci_asp.h> | ||
15 | #include <mach/edma.h> | 16 | #include <mach/edma.h> |
16 | #include <mach/asp.h> | ||
17 | |||
18 | 17 | ||
19 | struct davinci_pcm_dma_params { | 18 | struct davinci_pcm_dma_params { |
20 | int channel; /* sync dma channel ID */ | 19 | int channel; /* sync dma channel ID */ |
@@ -28,4 +27,7 @@ struct davinci_pcm_dma_params { | |||
28 | unsigned int fifo_level; | 27 | unsigned int fifo_level; |
29 | }; | 28 | }; |
30 | 29 | ||
30 | int davinci_soc_platform_register(struct device *dev); | ||
31 | void davinci_soc_platform_unregister(struct device *dev); | ||
32 | |||
31 | #endif | 33 | #endif |
diff --git a/sound/soc/davinci/davinci-sffsdr.c b/sound/soc/davinci/davinci-sffsdr.c index f71175b29e38..5be65aae7e0e 100644 --- a/sound/soc/davinci/davinci-sffsdr.c +++ b/sound/soc/davinci/davinci-sffsdr.c | |||
@@ -86,7 +86,7 @@ static struct snd_soc_dai_link sffsdr_dai = { | |||
86 | .cpu_dai_name = "davinci-mcbsp", | 86 | .cpu_dai_name = "davinci-mcbsp", |
87 | .codec_dai_name = "pcm3008-hifi", | 87 | .codec_dai_name = "pcm3008-hifi", |
88 | .codec_name = "pcm3008-codec", | 88 | .codec_name = "pcm3008-codec", |
89 | .platform_name = "davinci-pcm-audio", | 89 | .platform_name = "davinci-mcbsp", |
90 | .ops = &sffsdr_ops, | 90 | .ops = &sffsdr_ops, |
91 | }; | 91 | }; |
92 | 92 | ||
diff --git a/sound/soc/davinci/davinci-vcif.c b/sound/soc/davinci/davinci-vcif.c index da030ff883d5..07bde2e6f84e 100644 --- a/sound/soc/davinci/davinci-vcif.c +++ b/sound/soc/davinci/davinci-vcif.c | |||
@@ -240,12 +240,20 @@ static int davinci_vcif_probe(struct platform_device *pdev) | |||
240 | return ret; | 240 | return ret; |
241 | } | 241 | } |
242 | 242 | ||
243 | ret = davinci_soc_platform_register(&pdev->dev); | ||
244 | if (ret) { | ||
245 | dev_err(&pdev->dev, "register PCM failed: %d\n", ret); | ||
246 | snd_soc_unregister_dai(&pdev->dev); | ||
247 | return ret; | ||
248 | } | ||
249 | |||
243 | return 0; | 250 | return 0; |
244 | } | 251 | } |
245 | 252 | ||
246 | static int davinci_vcif_remove(struct platform_device *pdev) | 253 | static int davinci_vcif_remove(struct platform_device *pdev) |
247 | { | 254 | { |
248 | snd_soc_unregister_dai(&pdev->dev); | 255 | snd_soc_unregister_dai(&pdev->dev); |
256 | davinci_soc_platform_unregister(&pdev->dev); | ||
249 | 257 | ||
250 | return 0; | 258 | return 0; |
251 | } | 259 | } |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index 81d7728cf67f..7074ae689984 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -524,7 +524,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
524 | int ret = 0; | 524 | int ret = 0; |
525 | struct snd_soc_dai_driver *dai; | 525 | struct snd_soc_dai_driver *dai; |
526 | 526 | ||
527 | ssi = kzalloc(sizeof(*ssi), GFP_KERNEL); | 527 | ssi = devm_kzalloc(&pdev->dev, sizeof(*ssi), GFP_KERNEL); |
528 | if (!ssi) | 528 | if (!ssi) |
529 | return -ENOMEM; | 529 | return -ENOMEM; |
530 | dev_set_drvdata(&pdev->dev, ssi); | 530 | dev_set_drvdata(&pdev->dev, ssi); |
@@ -537,7 +537,7 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
537 | 537 | ||
538 | ssi->irq = platform_get_irq(pdev, 0); | 538 | ssi->irq = platform_get_irq(pdev, 0); |
539 | 539 | ||
540 | ssi->clk = clk_get(&pdev->dev, NULL); | 540 | ssi->clk = devm_clk_get(&pdev->dev, NULL); |
541 | if (IS_ERR(ssi->clk)) { | 541 | if (IS_ERR(ssi->clk)) { |
542 | ret = PTR_ERR(ssi->clk); | 542 | ret = PTR_ERR(ssi->clk); |
543 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 543 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
@@ -552,23 +552,18 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
552 | goto failed_get_resource; | 552 | goto failed_get_resource; |
553 | } | 553 | } |
554 | 554 | ||
555 | if (!request_mem_region(res->start, resource_size(res), DRV_NAME)) { | 555 | ssi->base = devm_request_and_ioremap(&pdev->dev, res); |
556 | dev_err(&pdev->dev, "request_mem_region failed\n"); | ||
557 | ret = -EBUSY; | ||
558 | goto failed_get_resource; | ||
559 | } | ||
560 | |||
561 | ssi->base = ioremap(res->start, resource_size(res)); | ||
562 | if (!ssi->base) { | 556 | if (!ssi->base) { |
563 | dev_err(&pdev->dev, "ioremap failed\n"); | 557 | dev_err(&pdev->dev, "ioremap failed\n"); |
564 | ret = -ENODEV; | 558 | ret = -ENODEV; |
565 | goto failed_ioremap; | 559 | goto failed_register; |
566 | } | 560 | } |
567 | 561 | ||
568 | if (ssi->flags & IMX_SSI_USE_AC97) { | 562 | if (ssi->flags & IMX_SSI_USE_AC97) { |
569 | if (ac97_ssi) { | 563 | if (ac97_ssi) { |
564 | dev_err(&pdev->dev, "AC'97 SSI already registered\n"); | ||
570 | ret = -EBUSY; | 565 | ret = -EBUSY; |
571 | goto failed_ac97; | 566 | goto failed_register; |
572 | } | 567 | } |
573 | ac97_ssi = ssi; | 568 | ac97_ssi = ssi; |
574 | setup_channel_to_ac97(ssi); | 569 | setup_channel_to_ac97(ssi); |
@@ -637,15 +632,10 @@ failed_pdev_fiq_add: | |||
637 | failed_pdev_fiq_alloc: | 632 | failed_pdev_fiq_alloc: |
638 | snd_soc_unregister_dai(&pdev->dev); | 633 | snd_soc_unregister_dai(&pdev->dev); |
639 | failed_register: | 634 | failed_register: |
640 | failed_ac97: | ||
641 | iounmap(ssi->base); | ||
642 | failed_ioremap: | ||
643 | release_mem_region(res->start, resource_size(res)); | 635 | release_mem_region(res->start, resource_size(res)); |
644 | failed_get_resource: | 636 | failed_get_resource: |
645 | clk_disable_unprepare(ssi->clk); | 637 | clk_disable_unprepare(ssi->clk); |
646 | clk_put(ssi->clk); | ||
647 | failed_clk: | 638 | failed_clk: |
648 | kfree(ssi); | ||
649 | 639 | ||
650 | return ret; | 640 | return ret; |
651 | } | 641 | } |
@@ -663,11 +653,8 @@ static int __devexit imx_ssi_remove(struct platform_device *pdev) | |||
663 | if (ssi->flags & IMX_SSI_USE_AC97) | 653 | if (ssi->flags & IMX_SSI_USE_AC97) |
664 | ac97_ssi = NULL; | 654 | ac97_ssi = NULL; |
665 | 655 | ||
666 | iounmap(ssi->base); | ||
667 | release_mem_region(res->start, resource_size(res)); | 656 | release_mem_region(res->start, resource_size(res)); |
668 | clk_disable_unprepare(ssi->clk); | 657 | clk_disable_unprepare(ssi->clk); |
669 | clk_put(ssi->clk); | ||
670 | kfree(ssi); | ||
671 | 658 | ||
672 | return 0; | 659 | return 0; |
673 | } | 660 | } |
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 2937e54da49e..2cc7782714b5 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
@@ -318,6 +318,15 @@ static struct snd_soc_dai_link mfld_msic_dailink[] = { | |||
318 | .platform_name = "sst-platform", | 318 | .platform_name = "sst-platform", |
319 | .init = NULL, | 319 | .init = NULL, |
320 | }, | 320 | }, |
321 | { | ||
322 | .name = "Medfield Compress", | ||
323 | .stream_name = "Speaker", | ||
324 | .cpu_dai_name = "Compress-cpu-dai", | ||
325 | .codec_dai_name = "SN95031 Speaker", | ||
326 | .codec_name = "sn95031", | ||
327 | .platform_name = "sst-platform", | ||
328 | .init = NULL, | ||
329 | }, | ||
321 | }; | 330 | }; |
322 | 331 | ||
323 | /* SoC card */ | 332 | /* SoC card */ |
diff --git a/sound/soc/mid-x86/sst_dsp.h b/sound/soc/mid-x86/sst_dsp.h new file mode 100644 index 000000000000..0fce1de284ff --- /dev/null +++ b/sound/soc/mid-x86/sst_dsp.h | |||
@@ -0,0 +1,134 @@ | |||
1 | #ifndef __SST_DSP_H__ | ||
2 | #define __SST_DSP_H__ | ||
3 | /* | ||
4 | * sst_dsp.h - Intel SST Driver for audio engine | ||
5 | * | ||
6 | * Copyright (C) 2008-12 Intel Corporation | ||
7 | * Authors: Vinod Koul <vinod.koul@linux.intel.com> | ||
8 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify | ||
11 | * it under the terms of the GNU General Public License as published by | ||
12 | * the Free Software Foundation; version 2 of the License. | ||
13 | * | ||
14 | * This program is distributed in the hope that it will be useful, but | ||
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of | ||
16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
17 | * General Public License for more details. | ||
18 | * | ||
19 | * You should have received a copy of the GNU General Public License along | ||
20 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
21 | * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | ||
22 | * | ||
23 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
24 | */ | ||
25 | |||
26 | enum sst_codec_types { | ||
27 | /* AUDIO/MUSIC CODEC Type Definitions */ | ||
28 | SST_CODEC_TYPE_UNKNOWN = 0, | ||
29 | SST_CODEC_TYPE_PCM, /* Pass through Audio codec */ | ||
30 | SST_CODEC_TYPE_MP3, | ||
31 | SST_CODEC_TYPE_MP24, | ||
32 | SST_CODEC_TYPE_AAC, | ||
33 | SST_CODEC_TYPE_AACP, | ||
34 | SST_CODEC_TYPE_eAACP, | ||
35 | }; | ||
36 | |||
37 | enum stream_type { | ||
38 | SST_STREAM_TYPE_NONE = 0, | ||
39 | SST_STREAM_TYPE_MUSIC = 1, | ||
40 | }; | ||
41 | |||
42 | struct snd_pcm_params { | ||
43 | u16 codec; /* codec type */ | ||
44 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
45 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
46 | u32 reserved; /* Bitrate in bits per second */ | ||
47 | u32 sfreq; /* Sampling rate in Hz */ | ||
48 | u8 use_offload_path; | ||
49 | u8 reserved2; | ||
50 | u16 reserved3; | ||
51 | u8 channel_map[8]; | ||
52 | } __packed; | ||
53 | |||
54 | /* MP3 Music Parameters Message */ | ||
55 | struct snd_mp3_params { | ||
56 | u16 codec; | ||
57 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
58 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
59 | u8 crc_check; /* crc_check - disable (0) or enable (1) */ | ||
60 | u8 reserved1; /* unused*/ | ||
61 | u16 reserved2; /* Unused */ | ||
62 | } __packed; | ||
63 | |||
64 | #define AAC_BIT_STREAM_ADTS 0 | ||
65 | #define AAC_BIT_STREAM_ADIF 1 | ||
66 | #define AAC_BIT_STREAM_RAW 2 | ||
67 | |||
68 | /* AAC Music Parameters Message */ | ||
69 | struct snd_aac_params { | ||
70 | u16 codec; | ||
71 | u8 num_chan; /* 1=Mono, 2=Stereo*/ | ||
72 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
73 | u8 bdownsample; /*SBR downsampling 0 - disable 1 -enabled AAC+ only */ | ||
74 | u8 bs_format; /* input bit stream format adts=0, adif=1, raw=2 */ | ||
75 | u16 reser2; | ||
76 | u32 externalsr; /*sampling rate of basic AAC raw bit stream*/ | ||
77 | u8 sbr_signalling;/*disable/enable/set automode the SBR tool.AAC+*/ | ||
78 | u8 reser1; | ||
79 | u16 reser3; | ||
80 | } __packed; | ||
81 | |||
82 | /* WMA Music Parameters Message */ | ||
83 | struct snd_wma_params { | ||
84 | u16 codec; | ||
85 | u8 num_chan; /* 1=Mono, 2=Stereo */ | ||
86 | u8 pcm_wd_sz; /* 16/24 - bit*/ | ||
87 | u32 brate; /* Use the hard coded value. */ | ||
88 | u32 sfreq; /* Sampling freq eg. 8000, 441000, 48000 */ | ||
89 | u32 channel_mask; /* Channel Mask */ | ||
90 | u16 format_tag; /* Format Tag */ | ||
91 | u16 block_align; /* packet size */ | ||
92 | u16 wma_encode_opt;/* Encoder option */ | ||
93 | u8 op_align; /* op align 0- 16 bit, 1- MSB, 2 LSB */ | ||
94 | u8 reserved; /* reserved */ | ||
95 | } __packed; | ||
96 | |||
97 | /* Codec params struture */ | ||
98 | union snd_sst_codec_params { | ||
99 | struct snd_pcm_params pcm_params; | ||
100 | struct snd_mp3_params mp3_params; | ||
101 | struct snd_aac_params aac_params; | ||
102 | struct snd_wma_params wma_params; | ||
103 | } __packed; | ||
104 | |||
105 | /* Address and size info of a frame buffer */ | ||
106 | struct sst_address_info { | ||
107 | u32 addr; /* Address at IA */ | ||
108 | u32 size; /* Size of the buffer */ | ||
109 | }; | ||
110 | |||
111 | struct snd_sst_alloc_params_ext { | ||
112 | struct sst_address_info ring_buf_info[8]; | ||
113 | u8 sg_count; | ||
114 | u8 reserved; | ||
115 | u16 reserved2; | ||
116 | u32 frag_size; /*Number of samples after which period elapsed | ||
117 | message is sent valid only if path = 0*/ | ||
118 | } __packed; | ||
119 | |||
120 | struct snd_sst_stream_params { | ||
121 | union snd_sst_codec_params uc; | ||
122 | } __packed; | ||
123 | |||
124 | struct snd_sst_params { | ||
125 | u32 stream_id; | ||
126 | u8 codec; | ||
127 | u8 ops; | ||
128 | u8 stream_type; | ||
129 | u8 device_type; | ||
130 | struct snd_sst_stream_params sparams; | ||
131 | struct snd_sst_alloc_params_ext aparams; | ||
132 | }; | ||
133 | |||
134 | #endif /* __SST_DSP_H__ */ | ||
diff --git a/sound/soc/mid-x86/sst_platform.c b/sound/soc/mid-x86/sst_platform.c index d34563b12c3b..a263cbed8624 100644 --- a/sound/soc/mid-x86/sst_platform.c +++ b/sound/soc/mid-x86/sst_platform.c | |||
@@ -1,7 +1,7 @@ | |||
1 | /* | 1 | /* |
2 | * sst_platform.c - Intel MID Platform driver | 2 | * sst_platform.c - Intel MID Platform driver |
3 | * | 3 | * |
4 | * Copyright (C) 2010 Intel Corp | 4 | * Copyright (C) 2010-2012 Intel Corp |
5 | * Author: Vinod Koul <vinod.koul@intel.com> | 5 | * Author: Vinod Koul <vinod.koul@intel.com> |
6 | * Author: Harsha Priya <priya.harsha@intel.com> | 6 | * Author: Harsha Priya <priya.harsha@intel.com> |
7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | 7 | * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ |
@@ -32,6 +32,7 @@ | |||
32 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
33 | #include <sound/pcm_params.h> | 33 | #include <sound/pcm_params.h> |
34 | #include <sound/soc.h> | 34 | #include <sound/soc.h> |
35 | #include <sound/compress_driver.h> | ||
35 | #include "sst_platform.h" | 36 | #include "sst_platform.h" |
36 | 37 | ||
37 | static struct sst_device *sst; | 38 | static struct sst_device *sst; |
@@ -152,6 +153,16 @@ static struct snd_soc_dai_driver sst_platform_dai[] = { | |||
152 | .formats = SNDRV_PCM_FMTBIT_S24_LE, | 153 | .formats = SNDRV_PCM_FMTBIT_S24_LE, |
153 | }, | 154 | }, |
154 | }, | 155 | }, |
156 | { | ||
157 | .name = "Compress-cpu-dai", | ||
158 | .compress_dai = 1, | ||
159 | .playback = { | ||
160 | .channels_min = SST_STEREO, | ||
161 | .channels_max = SST_STEREO, | ||
162 | .rates = SNDRV_PCM_RATE_44100|SNDRV_PCM_RATE_48000, | ||
163 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | ||
164 | }, | ||
165 | }, | ||
155 | }; | 166 | }; |
156 | 167 | ||
157 | /* helper functions */ | 168 | /* helper functions */ |
@@ -463,8 +474,199 @@ static int sst_pcm_new(struct snd_soc_pcm_runtime *rtd) | |||
463 | } | 474 | } |
464 | return retval; | 475 | return retval; |
465 | } | 476 | } |
477 | |||
478 | /* compress stream operations */ | ||
479 | static void sst_compr_fragment_elapsed(void *arg) | ||
480 | { | ||
481 | struct snd_compr_stream *cstream = (struct snd_compr_stream *)arg; | ||
482 | |||
483 | pr_debug("fragment elapsed by driver\n"); | ||
484 | if (cstream) | ||
485 | snd_compr_fragment_elapsed(cstream); | ||
486 | } | ||
487 | |||
488 | static int sst_platform_compr_open(struct snd_compr_stream *cstream) | ||
489 | { | ||
490 | |||
491 | int ret_val = 0; | ||
492 | struct snd_compr_runtime *runtime = cstream->runtime; | ||
493 | struct sst_runtime_stream *stream; | ||
494 | |||
495 | stream = kzalloc(sizeof(*stream), GFP_KERNEL); | ||
496 | if (!stream) | ||
497 | return -ENOMEM; | ||
498 | |||
499 | spin_lock_init(&stream->status_lock); | ||
500 | |||
501 | /* get the sst ops */ | ||
502 | if (!sst || !try_module_get(sst->dev->driver->owner)) { | ||
503 | pr_err("no device available to run\n"); | ||
504 | ret_val = -ENODEV; | ||
505 | goto out_ops; | ||
506 | } | ||
507 | stream->compr_ops = sst->compr_ops; | ||
508 | |||
509 | stream->id = 0; | ||
510 | sst_set_stream_status(stream, SST_PLATFORM_INIT); | ||
511 | runtime->private_data = stream; | ||
512 | return 0; | ||
513 | out_ops: | ||
514 | kfree(stream); | ||
515 | return ret_val; | ||
516 | } | ||
517 | |||
518 | static int sst_platform_compr_free(struct snd_compr_stream *cstream) | ||
519 | { | ||
520 | struct sst_runtime_stream *stream; | ||
521 | int ret_val = 0, str_id; | ||
522 | |||
523 | stream = cstream->runtime->private_data; | ||
524 | /*need to check*/ | ||
525 | str_id = stream->id; | ||
526 | if (str_id) | ||
527 | ret_val = stream->compr_ops->close(str_id); | ||
528 | module_put(sst->dev->driver->owner); | ||
529 | kfree(stream); | ||
530 | pr_debug("%s: %d\n", __func__, ret_val); | ||
531 | return 0; | ||
532 | } | ||
533 | |||
534 | static int sst_platform_compr_set_params(struct snd_compr_stream *cstream, | ||
535 | struct snd_compr_params *params) | ||
536 | { | ||
537 | struct sst_runtime_stream *stream; | ||
538 | int retval; | ||
539 | struct snd_sst_params str_params; | ||
540 | struct sst_compress_cb cb; | ||
541 | |||
542 | stream = cstream->runtime->private_data; | ||
543 | /* construct fw structure for this*/ | ||
544 | memset(&str_params, 0, sizeof(str_params)); | ||
545 | |||
546 | str_params.ops = STREAM_OPS_PLAYBACK; | ||
547 | str_params.stream_type = SST_STREAM_TYPE_MUSIC; | ||
548 | str_params.device_type = SND_SST_DEVICE_COMPRESS; | ||
549 | |||
550 | switch (params->codec.id) { | ||
551 | case SND_AUDIOCODEC_MP3: { | ||
552 | str_params.codec = SST_CODEC_TYPE_MP3; | ||
553 | str_params.sparams.uc.mp3_params.codec = SST_CODEC_TYPE_MP3; | ||
554 | str_params.sparams.uc.mp3_params.num_chan = params->codec.ch_in; | ||
555 | str_params.sparams.uc.mp3_params.pcm_wd_sz = 16; | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | case SND_AUDIOCODEC_AAC: { | ||
560 | str_params.codec = SST_CODEC_TYPE_AAC; | ||
561 | str_params.sparams.uc.aac_params.codec = SST_CODEC_TYPE_AAC; | ||
562 | str_params.sparams.uc.aac_params.num_chan = params->codec.ch_in; | ||
563 | str_params.sparams.uc.aac_params.pcm_wd_sz = 16; | ||
564 | if (params->codec.format == SND_AUDIOSTREAMFORMAT_MP4ADTS) | ||
565 | str_params.sparams.uc.aac_params.bs_format = | ||
566 | AAC_BIT_STREAM_ADTS; | ||
567 | else if (params->codec.format == SND_AUDIOSTREAMFORMAT_RAW) | ||
568 | str_params.sparams.uc.aac_params.bs_format = | ||
569 | AAC_BIT_STREAM_RAW; | ||
570 | else { | ||
571 | pr_err("Undefined format%d\n", params->codec.format); | ||
572 | return -EINVAL; | ||
573 | } | ||
574 | str_params.sparams.uc.aac_params.externalsr = | ||
575 | params->codec.sample_rate; | ||
576 | break; | ||
577 | } | ||
578 | |||
579 | default: | ||
580 | pr_err("codec not supported, id =%d\n", params->codec.id); | ||
581 | return -EINVAL; | ||
582 | } | ||
583 | |||
584 | str_params.aparams.ring_buf_info[0].addr = | ||
585 | virt_to_phys(cstream->runtime->buffer); | ||
586 | str_params.aparams.ring_buf_info[0].size = | ||
587 | cstream->runtime->buffer_size; | ||
588 | str_params.aparams.sg_count = 1; | ||
589 | str_params.aparams.frag_size = cstream->runtime->fragment_size; | ||
590 | |||
591 | cb.param = cstream; | ||
592 | cb.compr_cb = sst_compr_fragment_elapsed; | ||
593 | |||
594 | retval = stream->compr_ops->open(&str_params, &cb); | ||
595 | if (retval < 0) { | ||
596 | pr_err("stream allocation failed %d\n", retval); | ||
597 | return retval; | ||
598 | } | ||
599 | |||
600 | stream->id = retval; | ||
601 | return 0; | ||
602 | } | ||
603 | |||
604 | static int sst_platform_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
605 | { | ||
606 | struct sst_runtime_stream *stream = | ||
607 | cstream->runtime->private_data; | ||
608 | |||
609 | return stream->compr_ops->control(cmd, stream->id); | ||
610 | } | ||
611 | |||
612 | static int sst_platform_compr_pointer(struct snd_compr_stream *cstream, | ||
613 | struct snd_compr_tstamp *tstamp) | ||
614 | { | ||
615 | struct sst_runtime_stream *stream; | ||
616 | |||
617 | stream = cstream->runtime->private_data; | ||
618 | stream->compr_ops->tstamp(stream->id, tstamp); | ||
619 | tstamp->byte_offset = tstamp->copied_total % | ||
620 | (u32)cstream->runtime->buffer_size; | ||
621 | pr_debug("calc bytes offset/copied bytes as %d\n", tstamp->byte_offset); | ||
622 | return 0; | ||
623 | } | ||
624 | |||
625 | static int sst_platform_compr_ack(struct snd_compr_stream *cstream, | ||
626 | size_t bytes) | ||
627 | { | ||
628 | struct sst_runtime_stream *stream; | ||
629 | |||
630 | stream = cstream->runtime->private_data; | ||
631 | stream->compr_ops->ack(stream->id, (unsigned long)bytes); | ||
632 | stream->bytes_written += bytes; | ||
633 | |||
634 | return 0; | ||
635 | } | ||
636 | |||
637 | static int sst_platform_compr_get_caps(struct snd_compr_stream *cstream, | ||
638 | struct snd_compr_caps *caps) | ||
639 | { | ||
640 | struct sst_runtime_stream *stream = | ||
641 | cstream->runtime->private_data; | ||
642 | |||
643 | return stream->compr_ops->get_caps(caps); | ||
644 | } | ||
645 | |||
646 | static int sst_platform_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
647 | struct snd_compr_codec_caps *codec) | ||
648 | { | ||
649 | struct sst_runtime_stream *stream = | ||
650 | cstream->runtime->private_data; | ||
651 | |||
652 | return stream->compr_ops->get_codec_caps(codec); | ||
653 | } | ||
654 | |||
655 | static struct snd_compr_ops sst_platform_compr_ops = { | ||
656 | |||
657 | .open = sst_platform_compr_open, | ||
658 | .free = sst_platform_compr_free, | ||
659 | .set_params = sst_platform_compr_set_params, | ||
660 | .trigger = sst_platform_compr_trigger, | ||
661 | .pointer = sst_platform_compr_pointer, | ||
662 | .ack = sst_platform_compr_ack, | ||
663 | .get_caps = sst_platform_compr_get_caps, | ||
664 | .get_codec_caps = sst_platform_compr_get_codec_caps, | ||
665 | }; | ||
666 | |||
466 | static struct snd_soc_platform_driver sst_soc_platform_drv = { | 667 | static struct snd_soc_platform_driver sst_soc_platform_drv = { |
467 | .ops = &sst_platform_ops, | 668 | .ops = &sst_platform_ops, |
669 | .compr_ops = &sst_platform_compr_ops, | ||
468 | .pcm_new = sst_pcm_new, | 670 | .pcm_new = sst_pcm_new, |
469 | .pcm_free = sst_pcm_free, | 671 | .pcm_free = sst_pcm_free, |
470 | }; | 672 | }; |
diff --git a/sound/soc/mid-x86/sst_platform.h b/sound/soc/mid-x86/sst_platform.h index f04f4f72daa0..d61c5d514ffa 100644 --- a/sound/soc/mid-x86/sst_platform.h +++ b/sound/soc/mid-x86/sst_platform.h | |||
@@ -27,6 +27,8 @@ | |||
27 | #ifndef __SST_PLATFORMDRV_H__ | 27 | #ifndef __SST_PLATFORMDRV_H__ |
28 | #define __SST_PLATFORMDRV_H__ | 28 | #define __SST_PLATFORMDRV_H__ |
29 | 29 | ||
30 | #include "sst_dsp.h" | ||
31 | |||
30 | #define SST_MONO 1 | 32 | #define SST_MONO 1 |
31 | #define SST_STEREO 2 | 33 | #define SST_STEREO 2 |
32 | #define SST_MAX_CAP 5 | 34 | #define SST_MAX_CAP 5 |
@@ -42,7 +44,6 @@ | |||
42 | #define SST_MIN_PERIODS 2 | 44 | #define SST_MIN_PERIODS 2 |
43 | #define SST_MAX_PERIODS (1024*2) | 45 | #define SST_MAX_PERIODS (1024*2) |
44 | #define SST_FIFO_SIZE 0 | 46 | #define SST_FIFO_SIZE 0 |
45 | #define SST_CODEC_TYPE_PCM 1 | ||
46 | 47 | ||
47 | struct pcm_stream_info { | 48 | struct pcm_stream_info { |
48 | int str_id; | 49 | int str_id; |
@@ -83,6 +84,7 @@ enum sst_audio_device_type { | |||
83 | SND_SST_DEVICE_VIBRA, | 84 | SND_SST_DEVICE_VIBRA, |
84 | SND_SST_DEVICE_HAPTIC, | 85 | SND_SST_DEVICE_HAPTIC, |
85 | SND_SST_DEVICE_CAPTURE, | 86 | SND_SST_DEVICE_CAPTURE, |
87 | SND_SST_DEVICE_COMPRESS, | ||
86 | }; | 88 | }; |
87 | 89 | ||
88 | /* PCM Parameters */ | 90 | /* PCM Parameters */ |
@@ -107,6 +109,24 @@ struct sst_stream_params { | |||
107 | struct sst_pcm_params sparams; | 109 | struct sst_pcm_params sparams; |
108 | }; | 110 | }; |
109 | 111 | ||
112 | struct sst_compress_cb { | ||
113 | void *param; | ||
114 | void (*compr_cb)(void *param); | ||
115 | }; | ||
116 | |||
117 | struct compress_sst_ops { | ||
118 | const char *name; | ||
119 | int (*open) (struct snd_sst_params *str_params, | ||
120 | struct sst_compress_cb *cb); | ||
121 | int (*control) (unsigned int cmd, unsigned int str_id); | ||
122 | int (*tstamp) (unsigned int str_id, struct snd_compr_tstamp *tstamp); | ||
123 | int (*ack) (unsigned int str_id, unsigned long bytes); | ||
124 | int (*close) (unsigned int str_id); | ||
125 | int (*get_caps) (struct snd_compr_caps *caps); | ||
126 | int (*get_codec_caps) (struct snd_compr_codec_caps *codec); | ||
127 | |||
128 | }; | ||
129 | |||
110 | struct sst_ops { | 130 | struct sst_ops { |
111 | int (*open) (struct sst_stream_params *str_param); | 131 | int (*open) (struct sst_stream_params *str_param); |
112 | int (*device_control) (int cmd, void *arg); | 132 | int (*device_control) (int cmd, void *arg); |
@@ -115,8 +135,11 @@ struct sst_ops { | |||
115 | 135 | ||
116 | struct sst_runtime_stream { | 136 | struct sst_runtime_stream { |
117 | int stream_status; | 137 | int stream_status; |
138 | unsigned int id; | ||
139 | size_t bytes_written; | ||
118 | struct pcm_stream_info stream_info; | 140 | struct pcm_stream_info stream_info; |
119 | struct sst_ops *ops; | 141 | struct sst_ops *ops; |
142 | struct compress_sst_ops *compr_ops; | ||
120 | spinlock_t status_lock; | 143 | spinlock_t status_lock; |
121 | }; | 144 | }; |
122 | 145 | ||
@@ -124,6 +147,7 @@ struct sst_device { | |||
124 | char *name; | 147 | char *name; |
125 | struct device *dev; | 148 | struct device *dev; |
126 | struct sst_ops *ops; | 149 | struct sst_ops *ops; |
150 | struct compress_sst_ops *compr_ops; | ||
127 | }; | 151 | }; |
128 | 152 | ||
129 | int sst_register_dsp(struct sst_device *sst); | 153 | int sst_register_dsp(struct sst_device *sst); |
diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index b3030718c228..aa037b292f3d 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c | |||
@@ -704,7 +704,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
704 | return ret; | 704 | return ret; |
705 | } | 705 | } |
706 | 706 | ||
707 | saif->clk = clk_get(&pdev->dev, NULL); | 707 | saif->clk = devm_clk_get(&pdev->dev, NULL); |
708 | if (IS_ERR(saif->clk)) { | 708 | if (IS_ERR(saif->clk)) { |
709 | ret = PTR_ERR(saif->clk); | 709 | ret = PTR_ERR(saif->clk); |
710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", | 710 | dev_err(&pdev->dev, "Cannot get the clock: %d\n", |
@@ -717,8 +717,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); | 717 | saif->base = devm_request_and_ioremap(&pdev->dev, iores); |
718 | if (!saif->base) { | 718 | if (!saif->base) { |
719 | dev_err(&pdev->dev, "ioremap failed\n"); | 719 | dev_err(&pdev->dev, "ioremap failed\n"); |
720 | ret = -ENODEV; | 720 | return -ENODEV; |
721 | goto failed_get_resource; | ||
722 | } | 721 | } |
723 | 722 | ||
724 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 723 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
@@ -731,7 +730,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
731 | &saif->dma_param.chan_num); | 730 | &saif->dma_param.chan_num); |
732 | if (ret) { | 731 | if (ret) { |
733 | dev_err(&pdev->dev, "failed to get dma channel\n"); | 732 | dev_err(&pdev->dev, "failed to get dma channel\n"); |
734 | goto failed_get_resource; | 733 | return ret; |
735 | } | 734 | } |
736 | } else { | 735 | } else { |
737 | saif->dma_param.chan_num = dmares->start; | 736 | saif->dma_param.chan_num = dmares->start; |
@@ -742,7 +741,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
742 | ret = saif->irq; | 741 | ret = saif->irq; |
743 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", | 742 | dev_err(&pdev->dev, "failed to get irq resource: %d\n", |
744 | ret); | 743 | ret); |
745 | goto failed_get_resource; | 744 | return ret; |
746 | } | 745 | } |
747 | 746 | ||
748 | saif->dev = &pdev->dev; | 747 | saif->dev = &pdev->dev; |
@@ -750,7 +749,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
750 | "mxs-saif", saif); | 749 | "mxs-saif", saif); |
751 | if (ret) { | 750 | if (ret) { |
752 | dev_err(&pdev->dev, "failed to request irq\n"); | 751 | dev_err(&pdev->dev, "failed to request irq\n"); |
753 | goto failed_get_resource; | 752 | return ret; |
754 | } | 753 | } |
755 | 754 | ||
756 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); | 755 | saif->dma_param.chan_irq = platform_get_irq(pdev, 1); |
@@ -758,7 +757,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
758 | ret = saif->dma_param.chan_irq; | 757 | ret = saif->dma_param.chan_irq; |
759 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", | 758 | dev_err(&pdev->dev, "failed to get dma irq resource: %d\n", |
760 | ret); | 759 | ret); |
761 | goto failed_get_resource; | 760 | return ret; |
762 | } | 761 | } |
763 | 762 | ||
764 | platform_set_drvdata(pdev, saif); | 763 | platform_set_drvdata(pdev, saif); |
@@ -766,7 +765,7 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
766 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); | 765 | ret = snd_soc_register_dai(&pdev->dev, &mxs_saif_dai); |
767 | if (ret) { | 766 | if (ret) { |
768 | dev_err(&pdev->dev, "register DAI failed\n"); | 767 | dev_err(&pdev->dev, "register DAI failed\n"); |
769 | goto failed_get_resource; | 768 | return ret; |
770 | } | 769 | } |
771 | 770 | ||
772 | ret = mxs_pcm_platform_register(&pdev->dev); | 771 | ret = mxs_pcm_platform_register(&pdev->dev); |
@@ -779,19 +778,14 @@ static int __devinit mxs_saif_probe(struct platform_device *pdev) | |||
779 | 778 | ||
780 | failed_pdev_alloc: | 779 | failed_pdev_alloc: |
781 | snd_soc_unregister_dai(&pdev->dev); | 780 | snd_soc_unregister_dai(&pdev->dev); |
782 | failed_get_resource: | ||
783 | clk_put(saif->clk); | ||
784 | 781 | ||
785 | return ret; | 782 | return ret; |
786 | } | 783 | } |
787 | 784 | ||
788 | static int __devexit mxs_saif_remove(struct platform_device *pdev) | 785 | static int __devexit mxs_saif_remove(struct platform_device *pdev) |
789 | { | 786 | { |
790 | struct mxs_saif *saif = platform_get_drvdata(pdev); | ||
791 | |||
792 | mxs_pcm_platform_unregister(&pdev->dev); | 787 | mxs_pcm_platform_unregister(&pdev->dev); |
793 | snd_soc_unregister_dai(&pdev->dev); | 788 | snd_soc_unregister_dai(&pdev->dev); |
794 | clk_put(saif->clk); | ||
795 | 789 | ||
796 | return 0; | 790 | return 0; |
797 | } | 791 | } |
diff --git a/sound/soc/omap/omap-abe-twl6040.c b/sound/soc/omap/omap-abe-twl6040.c index 9d93793d3077..be525dfe9faa 100644 --- a/sound/soc/omap/omap-abe-twl6040.c +++ b/sound/soc/omap/omap-abe-twl6040.c | |||
@@ -25,6 +25,7 @@ | |||
25 | #include <linux/mfd/twl6040.h> | 25 | #include <linux/mfd/twl6040.h> |
26 | #include <linux/platform_data/omap-abe-twl6040.h> | 26 | #include <linux/platform_data/omap-abe-twl6040.h> |
27 | #include <linux/module.h> | 27 | #include <linux/module.h> |
28 | #include <linux/of.h> | ||
28 | 29 | ||
29 | #include <sound/core.h> | 30 | #include <sound/core.h> |
30 | #include <sound/pcm.h> | 31 | #include <sound/pcm.h> |
@@ -43,6 +44,8 @@ | |||
43 | struct abe_twl6040 { | 44 | struct abe_twl6040 { |
44 | int jack_detection; /* board can detect jack events */ | 45 | int jack_detection; /* board can detect jack events */ |
45 | int mclk_freq; /* MCLK frequency speed for twl6040 */ | 46 | int mclk_freq; /* MCLK frequency speed for twl6040 */ |
47 | |||
48 | struct platform_device *dmic_codec_dev; | ||
46 | }; | 49 | }; |
47 | 50 | ||
48 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, | 51 | static int omap_abe_hw_params(struct snd_pcm_substream *substream, |
@@ -185,17 +188,6 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
185 | int hs_trim; | 188 | int hs_trim; |
186 | int ret = 0; | 189 | int ret = 0; |
187 | 190 | ||
188 | /* Disable not connected paths if not used */ | ||
189 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
190 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
191 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
192 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
193 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
194 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
195 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
196 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
197 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
198 | |||
199 | /* | 191 | /* |
200 | * Configure McPDM offset cancellation based on the HSOTRIM value from | 192 | * Configure McPDM offset cancellation based on the HSOTRIM value from |
201 | * twl6040. | 193 | * twl6040. |
@@ -216,6 +208,24 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) | |||
216 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); | 208 | twl6040_hs_jack_detect(codec, &hs_jack, SND_JACK_HEADSET); |
217 | } | 209 | } |
218 | 210 | ||
211 | /* | ||
212 | * NULL pdata means we booted with DT. In this case the routing is | ||
213 | * provided and the card is fully routed, no need to mark pins. | ||
214 | */ | ||
215 | if (!pdata) | ||
216 | return ret; | ||
217 | |||
218 | /* Disable not connected paths if not used */ | ||
219 | twl6040_disconnect_pin(dapm, pdata->has_hs, "Headset Stereophone"); | ||
220 | twl6040_disconnect_pin(dapm, pdata->has_hf, "Ext Spk"); | ||
221 | twl6040_disconnect_pin(dapm, pdata->has_ep, "Earphone Spk"); | ||
222 | twl6040_disconnect_pin(dapm, pdata->has_aux, "Line Out"); | ||
223 | twl6040_disconnect_pin(dapm, pdata->has_vibra, "Vinrator"); | ||
224 | twl6040_disconnect_pin(dapm, pdata->has_hsmic, "Headset Mic"); | ||
225 | twl6040_disconnect_pin(dapm, pdata->has_mainmic, "Main Handset Mic"); | ||
226 | twl6040_disconnect_pin(dapm, pdata->has_submic, "Sub Handset Mic"); | ||
227 | twl6040_disconnect_pin(dapm, pdata->has_afm, "Line In"); | ||
228 | |||
219 | return ret; | 229 | return ret; |
220 | } | 230 | } |
221 | 231 | ||
@@ -270,52 +280,116 @@ static struct snd_soc_card omap_abe_card = { | |||
270 | static __devinit int omap_abe_probe(struct platform_device *pdev) | 280 | static __devinit int omap_abe_probe(struct platform_device *pdev) |
271 | { | 281 | { |
272 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); | 282 | struct omap_abe_twl6040_data *pdata = dev_get_platdata(&pdev->dev); |
283 | struct device_node *node = pdev->dev.of_node; | ||
273 | struct snd_soc_card *card = &omap_abe_card; | 284 | struct snd_soc_card *card = &omap_abe_card; |
274 | struct abe_twl6040 *priv; | 285 | struct abe_twl6040 *priv; |
275 | int num_links = 0; | 286 | int num_links = 0; |
276 | int ret; | 287 | int ret = 0; |
277 | 288 | ||
278 | card->dev = &pdev->dev; | 289 | card->dev = &pdev->dev; |
279 | 290 | ||
280 | if (!pdata) { | ||
281 | dev_err(&pdev->dev, "Missing pdata\n"); | ||
282 | return -ENODEV; | ||
283 | } | ||
284 | |||
285 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); | 291 | priv = devm_kzalloc(&pdev->dev, sizeof(struct abe_twl6040), GFP_KERNEL); |
286 | if (priv == NULL) | 292 | if (priv == NULL) |
287 | return -ENOMEM; | 293 | return -ENOMEM; |
288 | 294 | ||
289 | if (pdata->card_name) { | 295 | priv->dmic_codec_dev = ERR_PTR(-EINVAL); |
290 | card->name = pdata->card_name; | 296 | |
297 | if (node) { | ||
298 | struct device_node *dai_node; | ||
299 | |||
300 | if (snd_soc_of_parse_card_name(card, "ti,model")) { | ||
301 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
302 | return -ENODEV; | ||
303 | } | ||
304 | |||
305 | ret = snd_soc_of_parse_audio_routing(card, | ||
306 | "ti,audio-routing"); | ||
307 | if (ret) { | ||
308 | dev_err(&pdev->dev, | ||
309 | "Error while parsing DAPM routing\n"); | ||
310 | return ret; | ||
311 | } | ||
312 | |||
313 | dai_node = of_parse_phandle(node, "ti,mcpdm", 0); | ||
314 | if (!dai_node) { | ||
315 | dev_err(&pdev->dev, "McPDM node is not provided\n"); | ||
316 | return -EINVAL; | ||
317 | } | ||
318 | abe_twl6040_dai_links[0].cpu_dai_name = NULL; | ||
319 | abe_twl6040_dai_links[0].cpu_of_node = dai_node; | ||
320 | |||
321 | dai_node = of_parse_phandle(node, "ti,dmic", 0); | ||
322 | if (dai_node) { | ||
323 | num_links = 2; | ||
324 | abe_twl6040_dai_links[1].cpu_dai_name = NULL; | ||
325 | abe_twl6040_dai_links[1].cpu_of_node = dai_node; | ||
326 | |||
327 | priv->dmic_codec_dev = platform_device_register_simple( | ||
328 | "dmic-codec", -1, NULL, 0); | ||
329 | if (IS_ERR(priv->dmic_codec_dev)) { | ||
330 | dev_err(&pdev->dev, | ||
331 | "Can't instantiate dmic-codec\n"); | ||
332 | return PTR_ERR(priv->dmic_codec_dev); | ||
333 | } | ||
334 | } else { | ||
335 | num_links = 1; | ||
336 | } | ||
337 | |||
338 | of_property_read_u32(node, "ti,jack-detection", | ||
339 | &priv->jack_detection); | ||
340 | of_property_read_u32(node, "ti,mclk-freq", | ||
341 | &priv->mclk_freq); | ||
342 | if (!priv->mclk_freq) { | ||
343 | dev_err(&pdev->dev, "MCLK frequency not provided\n"); | ||
344 | ret = -EINVAL; | ||
345 | goto err_unregister; | ||
346 | } | ||
347 | |||
348 | omap_abe_card.fully_routed = 1; | ||
349 | } else if (pdata) { | ||
350 | if (pdata->card_name) { | ||
351 | card->name = pdata->card_name; | ||
352 | } else { | ||
353 | dev_err(&pdev->dev, "Card name is not provided\n"); | ||
354 | return -ENODEV; | ||
355 | } | ||
356 | |||
357 | if (pdata->has_dmic) | ||
358 | num_links = 2; | ||
359 | else | ||
360 | num_links = 1; | ||
361 | |||
362 | priv->jack_detection = pdata->jack_detection; | ||
363 | priv->mclk_freq = pdata->mclk_freq; | ||
291 | } else { | 364 | } else { |
292 | dev_err(&pdev->dev, "Card name is not provided\n"); | 365 | dev_err(&pdev->dev, "Missing pdata\n"); |
293 | return -ENODEV; | 366 | return -ENODEV; |
294 | } | 367 | } |
295 | 368 | ||
296 | priv->jack_detection = pdata->jack_detection; | ||
297 | priv->mclk_freq = pdata->mclk_freq; | ||
298 | |||
299 | 369 | ||
300 | if (!priv->mclk_freq) { | 370 | if (!priv->mclk_freq) { |
301 | dev_err(&pdev->dev, "MCLK frequency missing\n"); | 371 | dev_err(&pdev->dev, "MCLK frequency missing\n"); |
302 | return -ENODEV; | 372 | ret = -ENODEV; |
373 | goto err_unregister; | ||
303 | } | 374 | } |
304 | 375 | ||
305 | if (pdata->has_dmic) | ||
306 | num_links = 2; | ||
307 | else | ||
308 | num_links = 1; | ||
309 | |||
310 | card->dai_link = abe_twl6040_dai_links; | 376 | card->dai_link = abe_twl6040_dai_links; |
311 | card->num_links = num_links; | 377 | card->num_links = num_links; |
312 | 378 | ||
313 | snd_soc_card_set_drvdata(card, priv); | 379 | snd_soc_card_set_drvdata(card, priv); |
314 | 380 | ||
315 | ret = snd_soc_register_card(card); | 381 | ret = snd_soc_register_card(card); |
316 | if (ret) | 382 | if (ret) { |
317 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", | 383 | dev_err(&pdev->dev, "snd_soc_register_card() failed: %d\n", |
318 | ret); | 384 | ret); |
385 | goto err_unregister; | ||
386 | } | ||
387 | |||
388 | return 0; | ||
389 | |||
390 | err_unregister: | ||
391 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
392 | platform_device_unregister(priv->dmic_codec_dev); | ||
319 | 393 | ||
320 | return ret; | 394 | return ret; |
321 | } | 395 | } |
@@ -323,17 +397,28 @@ static __devinit int omap_abe_probe(struct platform_device *pdev) | |||
323 | static int __devexit omap_abe_remove(struct platform_device *pdev) | 397 | static int __devexit omap_abe_remove(struct platform_device *pdev) |
324 | { | 398 | { |
325 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 399 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
400 | struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); | ||
326 | 401 | ||
327 | snd_soc_unregister_card(card); | 402 | snd_soc_unregister_card(card); |
328 | 403 | ||
404 | if (!IS_ERR(priv->dmic_codec_dev)) | ||
405 | platform_device_unregister(priv->dmic_codec_dev); | ||
406 | |||
329 | return 0; | 407 | return 0; |
330 | } | 408 | } |
331 | 409 | ||
410 | static const struct of_device_id omap_abe_of_match[] = { | ||
411 | {.compatible = "ti,abe-twl6040", }, | ||
412 | { }, | ||
413 | }; | ||
414 | MODULE_DEVICE_TABLE(of, omap_abe_of_match); | ||
415 | |||
332 | static struct platform_driver omap_abe_driver = { | 416 | static struct platform_driver omap_abe_driver = { |
333 | .driver = { | 417 | .driver = { |
334 | .name = "omap-abe-twl6040", | 418 | .name = "omap-abe-twl6040", |
335 | .owner = THIS_MODULE, | 419 | .owner = THIS_MODULE, |
336 | .pm = &snd_soc_pm_ops, | 420 | .pm = &snd_soc_pm_ops, |
421 | .of_match_table = omap_abe_of_match, | ||
337 | }, | 422 | }, |
338 | .probe = omap_abe_probe, | 423 | .probe = omap_abe_probe, |
339 | .remove = __devexit_p(omap_abe_remove), | 424 | .remove = __devexit_p(omap_abe_remove), |
diff --git a/sound/soc/omap/omap-mcpdm.c b/sound/soc/omap/omap-mcpdm.c index 2c66e2498a45..f7babb374a37 100644 --- a/sound/soc/omap/omap-mcpdm.c +++ b/sound/soc/omap/omap-mcpdm.c | |||
@@ -445,9 +445,8 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
445 | { | 445 | { |
446 | struct omap_mcpdm *mcpdm; | 446 | struct omap_mcpdm *mcpdm; |
447 | struct resource *res; | 447 | struct resource *res; |
448 | int ret = 0; | ||
449 | 448 | ||
450 | mcpdm = kzalloc(sizeof(struct omap_mcpdm), GFP_KERNEL); | 449 | mcpdm = devm_kzalloc(&pdev->dev, sizeof(struct omap_mcpdm), GFP_KERNEL); |
451 | if (!mcpdm) | 450 | if (!mcpdm) |
452 | return -ENOMEM; | 451 | return -ENOMEM; |
453 | 452 | ||
@@ -456,55 +455,30 @@ static __devinit int asoc_mcpdm_probe(struct platform_device *pdev) | |||
456 | mutex_init(&mcpdm->mutex); | 455 | mutex_init(&mcpdm->mutex); |
457 | 456 | ||
458 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 457 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
459 | if (res == NULL) { | 458 | if (res == NULL) |
460 | dev_err(&pdev->dev, "no resource\n"); | 459 | return -ENOMEM; |
461 | goto err_res; | ||
462 | } | ||
463 | 460 | ||
464 | if (!request_mem_region(res->start, resource_size(res), "McPDM")) { | 461 | if (!devm_request_mem_region(&pdev->dev, res->start, |
465 | ret = -EBUSY; | 462 | resource_size(res), "McPDM")) |
466 | goto err_res; | 463 | return -EBUSY; |
467 | } | ||
468 | 464 | ||
469 | mcpdm->io_base = ioremap(res->start, resource_size(res)); | 465 | mcpdm->io_base = devm_ioremap(&pdev->dev, res->start, |
470 | if (!mcpdm->io_base) { | 466 | resource_size(res)); |
471 | ret = -ENOMEM; | 467 | if (!mcpdm->io_base) |
472 | goto err_iomap; | 468 | return -ENOMEM; |
473 | } | ||
474 | 469 | ||
475 | mcpdm->irq = platform_get_irq(pdev, 0); | 470 | mcpdm->irq = platform_get_irq(pdev, 0); |
476 | if (mcpdm->irq < 0) { | 471 | if (mcpdm->irq < 0) |
477 | ret = mcpdm->irq; | 472 | return mcpdm->irq; |
478 | goto err_irq; | ||
479 | } | ||
480 | 473 | ||
481 | mcpdm->dev = &pdev->dev; | 474 | mcpdm->dev = &pdev->dev; |
482 | 475 | ||
483 | ret = snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); | 476 | return snd_soc_register_dai(&pdev->dev, &omap_mcpdm_dai); |
484 | if (!ret) | ||
485 | return 0; | ||
486 | |||
487 | err_irq: | ||
488 | iounmap(mcpdm->io_base); | ||
489 | err_iomap: | ||
490 | release_mem_region(res->start, resource_size(res)); | ||
491 | err_res: | ||
492 | kfree(mcpdm); | ||
493 | return ret; | ||
494 | } | 477 | } |
495 | 478 | ||
496 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) | 479 | static int __devexit asoc_mcpdm_remove(struct platform_device *pdev) |
497 | { | 480 | { |
498 | struct omap_mcpdm *mcpdm = platform_get_drvdata(pdev); | ||
499 | struct resource *res; | ||
500 | |||
501 | snd_soc_unregister_dai(&pdev->dev); | 481 | snd_soc_unregister_dai(&pdev->dev); |
502 | |||
503 | res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
504 | iounmap(mcpdm->io_base); | ||
505 | release_mem_region(res->start, resource_size(res)); | ||
506 | |||
507 | kfree(mcpdm); | ||
508 | return 0; | 482 | return 0; |
509 | } | 483 | } |
510 | 484 | ||
diff --git a/sound/soc/samsung/Kconfig b/sound/soc/samsung/Kconfig index fe3995ce9b38..e7b83179aca2 100644 --- a/sound/soc/samsung/Kconfig +++ b/sound/soc/samsung/Kconfig | |||
@@ -1,6 +1,6 @@ | |||
1 | config SND_SOC_SAMSUNG | 1 | config SND_SOC_SAMSUNG |
2 | tristate "ASoC support for Samsung" | 2 | tristate "ASoC support for Samsung" |
3 | depends on ARCH_S3C24XX || ARCH_S3C64XX || ARCH_S5PC100 || ARCH_S5PV210 || ARCH_S5P64X0 || ARCH_EXYNOS4 | 3 | depends on PLAT_SAMSUNG |
4 | select S3C64XX_DMA if ARCH_S3C64XX | 4 | select S3C64XX_DMA if ARCH_S3C64XX |
5 | select S3C2410_DMA if ARCH_S3C24XX | 5 | select S3C2410_DMA if ARCH_S3C24XX |
6 | help | 6 | help |
@@ -191,6 +191,7 @@ config SND_SOC_SPEYSIDE | |||
191 | select SND_SAMSUNG_I2S | 191 | select SND_SAMSUNG_I2S |
192 | select SND_SOC_WM8996 | 192 | select SND_SOC_WM8996 |
193 | select SND_SOC_WM9081 | 193 | select SND_SOC_WM9081 |
194 | select SND_SOC_WM0010 | ||
194 | select SND_SOC_WM1250_EV1 | 195 | select SND_SOC_WM1250_EV1 |
195 | 196 | ||
196 | config SND_SOC_TOBERMORY | 197 | config SND_SOC_TOBERMORY |
@@ -199,6 +200,14 @@ config SND_SOC_TOBERMORY | |||
199 | select SND_SAMSUNG_I2S | 200 | select SND_SAMSUNG_I2S |
200 | select SND_SOC_WM8962 | 201 | select SND_SOC_WM8962 |
201 | 202 | ||
203 | config SND_SOC_BELLS | ||
204 | tristate "Audio support for Wolfson Bells" | ||
205 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | ||
206 | select SND_SAMSUNG_I2S | ||
207 | select SND_SOC_WM5102 | ||
208 | select SND_SOC_WM5110 | ||
209 | select SND_SOC_WM9081 | ||
210 | |||
202 | config SND_SOC_LOWLAND | 211 | config SND_SOC_LOWLAND |
203 | tristate "Audio support for Wolfson Lowland" | 212 | tristate "Audio support for Wolfson Lowland" |
204 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 | 213 | depends on SND_SOC_SAMSUNG && MACH_WLF_CRAGG_6410 |
diff --git a/sound/soc/samsung/Makefile b/sound/soc/samsung/Makefile index 9d03beb40c86..709f6059ad67 100644 --- a/sound/soc/samsung/Makefile +++ b/sound/soc/samsung/Makefile | |||
@@ -42,6 +42,7 @@ snd-soc-speyside-objs := speyside.o | |||
42 | snd-soc-tobermory-objs := tobermory.o | 42 | snd-soc-tobermory-objs := tobermory.o |
43 | snd-soc-lowland-objs := lowland.o | 43 | snd-soc-lowland-objs := lowland.o |
44 | snd-soc-littlemill-objs := littlemill.o | 44 | snd-soc-littlemill-objs := littlemill.o |
45 | snd-soc-bells-objs := bells.o | ||
45 | 46 | ||
46 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o | 47 | obj-$(CONFIG_SND_SOC_SAMSUNG_JIVE_WM8750) += snd-soc-jive-wm8750.o |
47 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o | 48 | obj-$(CONFIG_SND_SOC_SAMSUNG_NEO1973_WM8753) += snd-soc-neo1973-wm8753.o |
@@ -65,3 +66,4 @@ obj-$(CONFIG_SND_SOC_SPEYSIDE) += snd-soc-speyside.o | |||
65 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o | 66 | obj-$(CONFIG_SND_SOC_TOBERMORY) += snd-soc-tobermory.o |
66 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o | 67 | obj-$(CONFIG_SND_SOC_LOWLAND) += snd-soc-lowland.o |
67 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o | 68 | obj-$(CONFIG_SND_SOC_LITTLEMILL) += snd-soc-littlemill.o |
69 | obj-$(CONFIG_SND_SOC_BELLS) += snd-soc-bells.o | ||
diff --git a/sound/soc/samsung/bells.c b/sound/soc/samsung/bells.c new file mode 100644 index 000000000000..5dc10dfc0d42 --- /dev/null +++ b/sound/soc/samsung/bells.c | |||
@@ -0,0 +1,346 @@ | |||
1 | /* | ||
2 | * Bells audio support | ||
3 | * | ||
4 | * Copyright 2012 Wolfson Microelectronics | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms of the GNU General Public License as published by the | ||
8 | * Free Software Foundation; either version 2 of the License, or (at your | ||
9 | * option) any later version. | ||
10 | */ | ||
11 | |||
12 | #include <sound/soc.h> | ||
13 | #include <sound/soc-dapm.h> | ||
14 | #include <sound/jack.h> | ||
15 | #include <linux/gpio.h> | ||
16 | #include <linux/module.h> | ||
17 | |||
18 | #include "../codecs/wm5102.h" | ||
19 | #include "../codecs/wm9081.h" | ||
20 | |||
21 | /* | ||
22 | * 44.1kHz based clocks for the SYSCLK domain, use a very high clock | ||
23 | * to allow all the DSP functionality to be enabled if desired. | ||
24 | */ | ||
25 | #define SYSCLK_RATE (44100 * 1024) | ||
26 | |||
27 | /* 48kHz based clocks for the ASYNC domain */ | ||
28 | #define ASYNCCLK_RATE (48000 * 512) | ||
29 | |||
30 | /* BCLK2 is fixed at this currently */ | ||
31 | #define BCLK2_RATE (64 * 8000) | ||
32 | |||
33 | /* | ||
34 | * Expect a 24.576MHz crystal if one is fitted (the driver will function | ||
35 | * if this is not fitted). | ||
36 | */ | ||
37 | #define MCLK_RATE 24576000 | ||
38 | |||
39 | #define WM9081_AUDIO_RATE 44100 | ||
40 | #define WM9081_MCLK_RATE (WM9081_AUDIO_RATE * 256) | ||
41 | |||
42 | static int bells_set_bias_level(struct snd_soc_card *card, | ||
43 | struct snd_soc_dapm_context *dapm, | ||
44 | enum snd_soc_bias_level level) | ||
45 | { | ||
46 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
47 | struct snd_soc_codec *codec = codec_dai->codec; | ||
48 | int ret; | ||
49 | |||
50 | if (dapm->dev != codec_dai->dev) | ||
51 | return 0; | ||
52 | |||
53 | switch (level) { | ||
54 | case SND_SOC_BIAS_PREPARE: | ||
55 | if (dapm->bias_level == SND_SOC_BIAS_STANDBY) { | ||
56 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, | ||
57 | ARIZONA_FLL_SRC_MCLK1, | ||
58 | MCLK_RATE, | ||
59 | SYSCLK_RATE); | ||
60 | if (ret < 0) | ||
61 | pr_err("Failed to start FLL: %d\n", ret); | ||
62 | |||
63 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, | ||
64 | ARIZONA_FLL_SRC_AIF2BCLK, | ||
65 | BCLK2_RATE, | ||
66 | ASYNCCLK_RATE); | ||
67 | if (ret < 0) | ||
68 | pr_err("Failed to start FLL: %d\n", ret); | ||
69 | } | ||
70 | break; | ||
71 | |||
72 | default: | ||
73 | break; | ||
74 | } | ||
75 | |||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int bells_set_bias_level_post(struct snd_soc_card *card, | ||
80 | struct snd_soc_dapm_context *dapm, | ||
81 | enum snd_soc_bias_level level) | ||
82 | { | ||
83 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | ||
84 | struct snd_soc_codec *codec = codec_dai->codec; | ||
85 | int ret; | ||
86 | |||
87 | if (dapm->dev != codec_dai->dev) | ||
88 | return 0; | ||
89 | |||
90 | switch (level) { | ||
91 | case SND_SOC_BIAS_STANDBY: | ||
92 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL1, 0, 0, 0); | ||
93 | if (ret < 0) { | ||
94 | pr_err("Failed to stop FLL: %d\n", ret); | ||
95 | return ret; | ||
96 | } | ||
97 | |||
98 | ret = snd_soc_codec_set_pll(codec, WM5102_FLL2, 0, 0, 0); | ||
99 | if (ret < 0) { | ||
100 | pr_err("Failed to stop FLL: %d\n", ret); | ||
101 | return ret; | ||
102 | } | ||
103 | break; | ||
104 | |||
105 | default: | ||
106 | break; | ||
107 | } | ||
108 | |||
109 | dapm->bias_level = level; | ||
110 | |||
111 | return 0; | ||
112 | } | ||
113 | |||
114 | static int bells_late_probe(struct snd_soc_card *card) | ||
115 | { | ||
116 | struct snd_soc_codec *codec = card->rtd[0].codec; | ||
117 | struct snd_soc_dai *aif1_dai = card->rtd[0].codec_dai; | ||
118 | struct snd_soc_dai *aif2_dai = card->rtd[1].cpu_dai; | ||
119 | struct snd_soc_dai *aif3_dai = card->rtd[2].cpu_dai; | ||
120 | struct snd_soc_dai *wm9081_dai = card->rtd[2].codec_dai; | ||
121 | int ret; | ||
122 | |||
123 | ret = snd_soc_dai_set_sysclk(aif1_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
124 | if (ret != 0) { | ||
125 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
126 | return ret; | ||
127 | } | ||
128 | |||
129 | ret = snd_soc_dai_set_sysclk(aif2_dai, ARIZONA_CLK_ASYNCCLK, 0, 0); | ||
130 | if (ret != 0) { | ||
131 | dev_err(aif2_dai->dev, "Failed to set AIF2 clock: %d\n", ret); | ||
132 | return ret; | ||
133 | } | ||
134 | |||
135 | ret = snd_soc_dai_set_sysclk(aif3_dai, ARIZONA_CLK_SYSCLK, 0, 0); | ||
136 | if (ret != 0) { | ||
137 | dev_err(aif1_dai->dev, "Failed to set AIF1 clock: %d\n", ret); | ||
138 | return ret; | ||
139 | } | ||
140 | |||
141 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_SYSCLK, | ||
142 | ARIZONA_CLK_SRC_FLL1, SYSCLK_RATE, | ||
143 | SND_SOC_CLOCK_IN); | ||
144 | if (ret != 0) { | ||
145 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
146 | return ret; | ||
147 | } | ||
148 | |||
149 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_OPCLK, 0, | ||
150 | WM9081_MCLK_RATE, SND_SOC_CLOCK_OUT); | ||
151 | if (ret != 0) { | ||
152 | dev_err(codec->dev, "Failed to set OPCLK: %d\n", ret); | ||
153 | return ret; | ||
154 | } | ||
155 | |||
156 | ret = snd_soc_codec_set_sysclk(codec, ARIZONA_CLK_ASYNCCLK, | ||
157 | ARIZONA_CLK_SRC_FLL2, ASYNCCLK_RATE, | ||
158 | SND_SOC_CLOCK_IN); | ||
159 | if (ret != 0) { | ||
160 | dev_err(codec->dev, "Failed to set SYSCLK: %d\n", ret); | ||
161 | return ret; | ||
162 | } | ||
163 | |||
164 | ret = snd_soc_codec_set_sysclk(wm9081_dai->codec, WM9081_SYSCLK_MCLK, | ||
165 | 0, WM9081_MCLK_RATE, 0); | ||
166 | if (ret != 0) { | ||
167 | dev_err(wm9081_dai->dev, "Failed to set MCLK: %d\n", ret); | ||
168 | return ret; | ||
169 | } | ||
170 | |||
171 | return 0; | ||
172 | } | ||
173 | |||
174 | static const struct snd_soc_pcm_stream baseband_params = { | ||
175 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
176 | .rate_min = 8000, | ||
177 | .rate_max = 8000, | ||
178 | .channels_min = 2, | ||
179 | .channels_max = 2, | ||
180 | }; | ||
181 | |||
182 | static const struct snd_soc_pcm_stream sub_params = { | ||
183 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
184 | .rate_min = WM9081_AUDIO_RATE, | ||
185 | .rate_max = WM9081_AUDIO_RATE, | ||
186 | .channels_min = 2, | ||
187 | .channels_max = 2, | ||
188 | }; | ||
189 | |||
190 | static struct snd_soc_dai_link bells_dai_wm5102[] = { | ||
191 | { | ||
192 | .name = "CPU", | ||
193 | .stream_name = "CPU", | ||
194 | .cpu_dai_name = "samsung-i2s.0", | ||
195 | .codec_dai_name = "wm5102-aif1", | ||
196 | .platform_name = "samsung-audio", | ||
197 | .codec_name = "wm5102-codec", | ||
198 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
199 | | SND_SOC_DAIFMT_CBM_CFM, | ||
200 | }, | ||
201 | { | ||
202 | .name = "Baseband", | ||
203 | .stream_name = "Baseband", | ||
204 | .cpu_dai_name = "wm5102-aif2", | ||
205 | .codec_dai_name = "wm1250-ev1", | ||
206 | .codec_name = "wm1250-ev1.1-0027", | ||
207 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
208 | | SND_SOC_DAIFMT_CBM_CFM, | ||
209 | .ignore_suspend = 1, | ||
210 | .params = &baseband_params, | ||
211 | }, | ||
212 | { | ||
213 | .name = "Sub", | ||
214 | .stream_name = "Sub", | ||
215 | .cpu_dai_name = "wm5102-aif3", | ||
216 | .codec_dai_name = "wm9081-hifi", | ||
217 | .codec_name = "wm9081.1-006c", | ||
218 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
219 | | SND_SOC_DAIFMT_CBS_CFS, | ||
220 | .ignore_suspend = 1, | ||
221 | .params = &sub_params, | ||
222 | }, | ||
223 | }; | ||
224 | |||
225 | static struct snd_soc_dai_link bells_dai_wm5110[] = { | ||
226 | { | ||
227 | .name = "CPU", | ||
228 | .stream_name = "CPU", | ||
229 | .cpu_dai_name = "samsung-i2s.0", | ||
230 | .codec_dai_name = "wm5110-aif1", | ||
231 | .platform_name = "samsung-audio", | ||
232 | .codec_name = "wm5110-codec", | ||
233 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
234 | | SND_SOC_DAIFMT_CBM_CFM, | ||
235 | }, | ||
236 | { | ||
237 | .name = "Baseband", | ||
238 | .stream_name = "Baseband", | ||
239 | .cpu_dai_name = "wm5110-aif2", | ||
240 | .codec_dai_name = "wm1250-ev1", | ||
241 | .codec_name = "wm1250-ev1.1-0027", | ||
242 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
243 | | SND_SOC_DAIFMT_CBM_CFM, | ||
244 | .ignore_suspend = 1, | ||
245 | .params = &baseband_params, | ||
246 | }, | ||
247 | { | ||
248 | .name = "Sub", | ||
249 | .stream_name = "Sub", | ||
250 | .cpu_dai_name = "wm5102-aif3", | ||
251 | .codec_dai_name = "wm9081-hifi", | ||
252 | .codec_name = "wm9081.1-006c", | ||
253 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
254 | | SND_SOC_DAIFMT_CBS_CFS, | ||
255 | .ignore_suspend = 1, | ||
256 | .params = &sub_params, | ||
257 | }, | ||
258 | }; | ||
259 | |||
260 | static struct snd_soc_codec_conf bells_codec_conf[] = { | ||
261 | { | ||
262 | .dev_name = "wm9081.1-006c", | ||
263 | .name_prefix = "Sub", | ||
264 | }, | ||
265 | }; | ||
266 | |||
267 | static struct snd_soc_dapm_route bells_routes[] = { | ||
268 | { "Sub CLK_SYS", NULL, "OPCLK" }, | ||
269 | }; | ||
270 | |||
271 | static struct snd_soc_card bells_cards[] = { | ||
272 | { | ||
273 | .name = "Bells WM5102", | ||
274 | .owner = THIS_MODULE, | ||
275 | .dai_link = bells_dai_wm5102, | ||
276 | .num_links = ARRAY_SIZE(bells_dai_wm5102), | ||
277 | .codec_conf = bells_codec_conf, | ||
278 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
279 | |||
280 | .late_probe = bells_late_probe, | ||
281 | |||
282 | .dapm_routes = bells_routes, | ||
283 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
284 | |||
285 | .set_bias_level = bells_set_bias_level, | ||
286 | .set_bias_level_post = bells_set_bias_level_post, | ||
287 | }, | ||
288 | { | ||
289 | .name = "Bells WM5110", | ||
290 | .owner = THIS_MODULE, | ||
291 | .dai_link = bells_dai_wm5110, | ||
292 | .num_links = ARRAY_SIZE(bells_dai_wm5110), | ||
293 | .codec_conf = bells_codec_conf, | ||
294 | .num_configs = ARRAY_SIZE(bells_codec_conf), | ||
295 | |||
296 | .late_probe = bells_late_probe, | ||
297 | |||
298 | .dapm_routes = bells_routes, | ||
299 | .num_dapm_routes = ARRAY_SIZE(bells_routes), | ||
300 | |||
301 | .set_bias_level = bells_set_bias_level, | ||
302 | .set_bias_level_post = bells_set_bias_level_post, | ||
303 | }, | ||
304 | }; | ||
305 | |||
306 | |||
307 | static __devinit int bells_probe(struct platform_device *pdev) | ||
308 | { | ||
309 | int ret; | ||
310 | |||
311 | bells_cards[pdev->id].dev = &pdev->dev; | ||
312 | |||
313 | ret = snd_soc_register_card(&bells_cards[pdev->id]); | ||
314 | if (ret) { | ||
315 | dev_err(&pdev->dev, | ||
316 | "snd_soc_register_card(%s) failed: %d\n", | ||
317 | bells_cards[pdev->id].name, ret); | ||
318 | return ret; | ||
319 | } | ||
320 | |||
321 | return 0; | ||
322 | } | ||
323 | |||
324 | static int __devexit bells_remove(struct platform_device *pdev) | ||
325 | { | ||
326 | snd_soc_unregister_card(&bells_cards[pdev->id]); | ||
327 | |||
328 | return 0; | ||
329 | } | ||
330 | |||
331 | static struct platform_driver bells_driver = { | ||
332 | .driver = { | ||
333 | .name = "bells", | ||
334 | .owner = THIS_MODULE, | ||
335 | .pm = &snd_soc_pm_ops, | ||
336 | }, | ||
337 | .probe = bells_probe, | ||
338 | .remove = __devexit_p(bells_remove), | ||
339 | }; | ||
340 | |||
341 | module_platform_driver(bells_driver); | ||
342 | |||
343 | MODULE_DESCRIPTION("Bells audio support"); | ||
344 | MODULE_AUTHOR("Mark Brown <broonie@opensource.wolfsonmicro.com>"); | ||
345 | MODULE_LICENSE("GPL"); | ||
346 | MODULE_ALIAS("platform:bells"); | ||
diff --git a/sound/soc/samsung/speyside.c b/sound/soc/samsung/speyside.c index a4a9fc7e8c76..c7e1c28528a4 100644 --- a/sound/soc/samsung/speyside.c +++ b/sound/soc/samsung/speyside.c | |||
@@ -25,7 +25,7 @@ static int speyside_set_bias_level(struct snd_soc_card *card, | |||
25 | struct snd_soc_dapm_context *dapm, | 25 | struct snd_soc_dapm_context *dapm, |
26 | enum snd_soc_bias_level level) | 26 | enum snd_soc_bias_level level) |
27 | { | 27 | { |
28 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 28 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
29 | int ret; | 29 | int ret; |
30 | 30 | ||
31 | if (dapm->dev != codec_dai->dev) | 31 | if (dapm->dev != codec_dai->dev) |
@@ -57,7 +57,7 @@ static int speyside_set_bias_level_post(struct snd_soc_card *card, | |||
57 | struct snd_soc_dapm_context *dapm, | 57 | struct snd_soc_dapm_context *dapm, |
58 | enum snd_soc_bias_level level) | 58 | enum snd_soc_bias_level level) |
59 | { | 59 | { |
60 | struct snd_soc_dai *codec_dai = card->rtd[0].codec_dai; | 60 | struct snd_soc_dai *codec_dai = card->rtd[1].codec_dai; |
61 | int ret; | 61 | int ret; |
62 | 62 | ||
63 | if (dapm->dev != codec_dai->dev) | 63 | if (dapm->dev != codec_dai->dev) |
@@ -126,6 +126,18 @@ static void speyside_set_polarity(struct snd_soc_codec *codec, | |||
126 | snd_soc_dapm_sync(&codec->dapm); | 126 | snd_soc_dapm_sync(&codec->dapm); |
127 | } | 127 | } |
128 | 128 | ||
129 | static int speyside_wm0010_init(struct snd_soc_pcm_runtime *rtd) | ||
130 | { | ||
131 | struct snd_soc_dai *dai = rtd->codec_dai; | ||
132 | int ret; | ||
133 | |||
134 | ret = snd_soc_dai_set_sysclk(dai, 0, MCLK_AUDIO_RATE, 0); | ||
135 | if (ret < 0) | ||
136 | return ret; | ||
137 | |||
138 | return 0; | ||
139 | } | ||
140 | |||
129 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) | 141 | static int speyside_wm8996_init(struct snd_soc_pcm_runtime *rtd) |
130 | { | 142 | { |
131 | struct snd_soc_dai *dai = rtd->codec_dai; | 143 | struct snd_soc_dai *dai = rtd->codec_dai; |
@@ -172,17 +184,37 @@ static int speyside_late_probe(struct snd_soc_card *card) | |||
172 | return 0; | 184 | return 0; |
173 | } | 185 | } |
174 | 186 | ||
187 | static const struct snd_soc_pcm_stream dsp_codec_params = { | ||
188 | .formats = SNDRV_PCM_FMTBIT_S32_LE, | ||
189 | .rate_min = 48000, | ||
190 | .rate_max = 48000, | ||
191 | .channels_min = 2, | ||
192 | .channels_max = 2, | ||
193 | }; | ||
194 | |||
175 | static struct snd_soc_dai_link speyside_dai[] = { | 195 | static struct snd_soc_dai_link speyside_dai[] = { |
176 | { | 196 | { |
177 | .name = "CPU", | 197 | .name = "CPU-DSP", |
178 | .stream_name = "CPU", | 198 | .stream_name = "CPU-DSP", |
179 | .cpu_dai_name = "samsung-i2s.0", | 199 | .cpu_dai_name = "samsung-i2s.0", |
180 | .codec_dai_name = "wm8996-aif1", | 200 | .codec_dai_name = "wm0010-sdi1", |
181 | .platform_name = "samsung-audio", | 201 | .platform_name = "samsung-audio", |
202 | .codec_name = "spi0.0", | ||
203 | .init = speyside_wm0010_init, | ||
204 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | ||
205 | | SND_SOC_DAIFMT_CBM_CFM, | ||
206 | }, | ||
207 | { | ||
208 | .name = "DSP-CODEC", | ||
209 | .stream_name = "DSP-CODEC", | ||
210 | .cpu_dai_name = "wm0010-sdi2", | ||
211 | .codec_dai_name = "wm8996-aif1", | ||
182 | .codec_name = "wm8996.1-001a", | 212 | .codec_name = "wm8996.1-001a", |
183 | .init = speyside_wm8996_init, | 213 | .init = speyside_wm8996_init, |
184 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF | 214 | .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF |
185 | | SND_SOC_DAIFMT_CBM_CFM, | 215 | | SND_SOC_DAIFMT_CBM_CFM, |
216 | .params = &dsp_codec_params, | ||
217 | .ignore_suspend = 1, | ||
186 | }, | 218 | }, |
187 | { | 219 | { |
188 | .name = "Baseband", | 220 | .name = "Baseband", |
diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c new file mode 100644 index 000000000000..967d0e173e1b --- /dev/null +++ b/sound/soc/soc-compress.c | |||
@@ -0,0 +1,294 @@ | |||
1 | /* | ||
2 | * soc-compress.c -- ALSA SoC Compress | ||
3 | * | ||
4 | * Copyright (C) 2012 Intel Corp. | ||
5 | * | ||
6 | * Authors: Namarta Kohli <namartax.kohli@intel.com> | ||
7 | * Ramesh Babu K V <ramesh.babu@linux.intel.com> | ||
8 | * Vinod Koul <vinod.koul@linux.intel.com> | ||
9 | * | ||
10 | * This program is free software; you can redistribute it and/or modify it | ||
11 | * under the terms of the GNU General Public License as published by the | ||
12 | * Free Software Foundation; either version 2 of the License, or (at your | ||
13 | * option) any later version. | ||
14 | * | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/init.h> | ||
19 | #include <linux/delay.h> | ||
20 | #include <linux/slab.h> | ||
21 | #include <linux/workqueue.h> | ||
22 | #include <sound/core.h> | ||
23 | #include <sound/compress_params.h> | ||
24 | #include <sound/compress_driver.h> | ||
25 | #include <sound/soc.h> | ||
26 | #include <sound/initval.h> | ||
27 | |||
28 | static int soc_compr_open(struct snd_compr_stream *cstream) | ||
29 | { | ||
30 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
31 | struct snd_soc_platform *platform = rtd->platform; | ||
32 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
33 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
34 | int ret = 0; | ||
35 | |||
36 | if (platform->driver->compr_ops && platform->driver->compr_ops->open) { | ||
37 | ret = platform->driver->compr_ops->open(cstream); | ||
38 | if (ret < 0) { | ||
39 | pr_err("compress asoc: can't open platform %s\n", platform->name); | ||
40 | goto out; | ||
41 | } | ||
42 | } | ||
43 | |||
44 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->startup) { | ||
45 | ret = rtd->dai_link->compr_ops->startup(cstream); | ||
46 | if (ret < 0) { | ||
47 | pr_err("compress asoc: %s startup failed\n", rtd->dai_link->name); | ||
48 | goto machine_err; | ||
49 | } | ||
50 | } | ||
51 | |||
52 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
53 | cpu_dai->playback_active++; | ||
54 | codec_dai->playback_active++; | ||
55 | } else { | ||
56 | cpu_dai->capture_active++; | ||
57 | codec_dai->capture_active++; | ||
58 | } | ||
59 | |||
60 | cpu_dai->active++; | ||
61 | codec_dai->active++; | ||
62 | rtd->codec->active++; | ||
63 | |||
64 | return 0; | ||
65 | |||
66 | machine_err: | ||
67 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
68 | platform->driver->compr_ops->free(cstream); | ||
69 | out: | ||
70 | return ret; | ||
71 | } | ||
72 | |||
73 | static int soc_compr_free(struct snd_compr_stream *cstream) | ||
74 | { | ||
75 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
76 | struct snd_soc_platform *platform = rtd->platform; | ||
77 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
78 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
79 | struct snd_soc_codec *codec = rtd->codec; | ||
80 | |||
81 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
82 | cpu_dai->playback_active--; | ||
83 | codec_dai->playback_active--; | ||
84 | } else { | ||
85 | cpu_dai->capture_active--; | ||
86 | codec_dai->capture_active--; | ||
87 | } | ||
88 | |||
89 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
90 | |||
91 | cpu_dai->active--; | ||
92 | codec_dai->active--; | ||
93 | codec->active--; | ||
94 | |||
95 | if (!cpu_dai->active) | ||
96 | cpu_dai->rate = 0; | ||
97 | |||
98 | if (!codec_dai->active) | ||
99 | codec_dai->rate = 0; | ||
100 | |||
101 | |||
102 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->shutdown) | ||
103 | rtd->dai_link->compr_ops->shutdown(cstream); | ||
104 | |||
105 | if (platform->driver->compr_ops && platform->driver->compr_ops->free) | ||
106 | platform->driver->compr_ops->free(cstream); | ||
107 | cpu_dai->runtime = NULL; | ||
108 | |||
109 | if (cstream->direction == SND_COMPRESS_PLAYBACK) { | ||
110 | if (!rtd->pmdown_time || codec->ignore_pmdown_time || | ||
111 | rtd->dai_link->ignore_pmdown_time) { | ||
112 | snd_soc_dapm_stream_event(rtd, | ||
113 | SNDRV_PCM_STREAM_PLAYBACK, | ||
114 | SND_SOC_DAPM_STREAM_STOP); | ||
115 | } else | ||
116 | codec_dai->pop_wait = 1; | ||
117 | schedule_delayed_work(&rtd->delayed_work, | ||
118 | msecs_to_jiffies(rtd->pmdown_time)); | ||
119 | } else { | ||
120 | /* capture streams can be powered down now */ | ||
121 | snd_soc_dapm_stream_event(rtd, | ||
122 | SNDRV_PCM_STREAM_CAPTURE, | ||
123 | SND_SOC_DAPM_STREAM_STOP); | ||
124 | } | ||
125 | |||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int soc_compr_trigger(struct snd_compr_stream *cstream, int cmd) | ||
130 | { | ||
131 | |||
132 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
133 | struct snd_soc_platform *platform = rtd->platform; | ||
134 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
135 | int ret = 0; | ||
136 | |||
137 | if (platform->driver->compr_ops && platform->driver->compr_ops->trigger) { | ||
138 | ret = platform->driver->compr_ops->trigger(cstream, cmd); | ||
139 | if (ret < 0) | ||
140 | return ret; | ||
141 | } | ||
142 | |||
143 | if (cmd == SNDRV_PCM_TRIGGER_START) | ||
144 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
145 | else if (cmd == SNDRV_PCM_TRIGGER_STOP) | ||
146 | snd_soc_dai_digital_mute(codec_dai, 1); | ||
147 | |||
148 | return ret; | ||
149 | } | ||
150 | |||
151 | static int soc_compr_set_params(struct snd_compr_stream *cstream, | ||
152 | struct snd_compr_params *params) | ||
153 | { | ||
154 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
155 | struct snd_soc_platform *platform = rtd->platform; | ||
156 | int ret = 0; | ||
157 | |||
158 | /* first we call set_params for the platform driver | ||
159 | * this should configure the soc side | ||
160 | * if the machine has compressed ops then we call that as well | ||
161 | * expectation is that platform and machine will configure everything | ||
162 | * for this compress path, like configuring pcm port for codec | ||
163 | */ | ||
164 | if (platform->driver->compr_ops && platform->driver->compr_ops->set_params) { | ||
165 | ret = platform->driver->compr_ops->set_params(cstream, params); | ||
166 | if (ret < 0) | ||
167 | return ret; | ||
168 | } | ||
169 | |||
170 | if (rtd->dai_link->compr_ops && rtd->dai_link->compr_ops->set_params) { | ||
171 | ret = rtd->dai_link->compr_ops->set_params(cstream); | ||
172 | if (ret < 0) | ||
173 | return ret; | ||
174 | } | ||
175 | |||
176 | snd_soc_dapm_stream_event(rtd, SNDRV_PCM_STREAM_PLAYBACK, | ||
177 | SND_SOC_DAPM_STREAM_START); | ||
178 | |||
179 | return ret; | ||
180 | } | ||
181 | |||
182 | static int soc_compr_get_params(struct snd_compr_stream *cstream, | ||
183 | struct snd_codec *params) | ||
184 | { | ||
185 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
186 | struct snd_soc_platform *platform = rtd->platform; | ||
187 | int ret = 0; | ||
188 | |||
189 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_params) | ||
190 | ret = platform->driver->compr_ops->get_params(cstream, params); | ||
191 | |||
192 | return ret; | ||
193 | } | ||
194 | |||
195 | static int soc_compr_get_caps(struct snd_compr_stream *cstream, | ||
196 | struct snd_compr_caps *caps) | ||
197 | { | ||
198 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
199 | struct snd_soc_platform *platform = rtd->platform; | ||
200 | int ret = 0; | ||
201 | |||
202 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_caps) | ||
203 | ret = platform->driver->compr_ops->get_caps(cstream, caps); | ||
204 | |||
205 | return ret; | ||
206 | } | ||
207 | |||
208 | static int soc_compr_get_codec_caps(struct snd_compr_stream *cstream, | ||
209 | struct snd_compr_codec_caps *codec) | ||
210 | { | ||
211 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
212 | struct snd_soc_platform *platform = rtd->platform; | ||
213 | int ret = 0; | ||
214 | |||
215 | if (platform->driver->compr_ops && platform->driver->compr_ops->get_codec_caps) | ||
216 | ret = platform->driver->compr_ops->get_codec_caps(cstream, codec); | ||
217 | |||
218 | return ret; | ||
219 | } | ||
220 | |||
221 | static int soc_compr_ack(struct snd_compr_stream *cstream, size_t bytes) | ||
222 | { | ||
223 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
224 | struct snd_soc_platform *platform = rtd->platform; | ||
225 | int ret = 0; | ||
226 | |||
227 | if (platform->driver->compr_ops && platform->driver->compr_ops->ack) | ||
228 | ret = platform->driver->compr_ops->ack(cstream, bytes); | ||
229 | |||
230 | return ret; | ||
231 | } | ||
232 | |||
233 | static int soc_compr_pointer(struct snd_compr_stream *cstream, | ||
234 | struct snd_compr_tstamp *tstamp) | ||
235 | { | ||
236 | struct snd_soc_pcm_runtime *rtd = cstream->private_data; | ||
237 | struct snd_soc_platform *platform = rtd->platform; | ||
238 | |||
239 | if (platform->driver->compr_ops && platform->driver->compr_ops->pointer) | ||
240 | platform->driver->compr_ops->pointer(cstream, tstamp); | ||
241 | |||
242 | return 0; | ||
243 | } | ||
244 | |||
245 | /* ASoC Compress operations */ | ||
246 | static struct snd_compr_ops soc_compr_ops = { | ||
247 | .open = soc_compr_open, | ||
248 | .free = soc_compr_free, | ||
249 | .set_params = soc_compr_set_params, | ||
250 | .get_params = soc_compr_get_params, | ||
251 | .trigger = soc_compr_trigger, | ||
252 | .pointer = soc_compr_pointer, | ||
253 | .ack = soc_compr_ack, | ||
254 | .get_caps = soc_compr_get_caps, | ||
255 | .get_codec_caps = soc_compr_get_codec_caps | ||
256 | }; | ||
257 | |||
258 | /* create a new compress */ | ||
259 | int soc_new_compress(struct snd_soc_pcm_runtime *rtd, int num) | ||
260 | { | ||
261 | struct snd_soc_codec *codec = rtd->codec; | ||
262 | struct snd_soc_dai *codec_dai = rtd->codec_dai; | ||
263 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
264 | struct snd_compr *compr; | ||
265 | char new_name[64]; | ||
266 | int ret = 0, direction = 0; | ||
267 | |||
268 | /* check client and interface hw capabilities */ | ||
269 | snprintf(new_name, sizeof(new_name), "%s %s-%d", | ||
270 | rtd->dai_link->stream_name, codec_dai->name, num); | ||
271 | direction = SND_COMPRESS_PLAYBACK; | ||
272 | compr = kzalloc(sizeof(*compr), GFP_KERNEL); | ||
273 | if (compr == NULL) { | ||
274 | snd_printk(KERN_ERR "Cannot allocate compr\n"); | ||
275 | return -ENOMEM; | ||
276 | } | ||
277 | |||
278 | compr->ops = &soc_compr_ops; | ||
279 | mutex_init(&compr->lock); | ||
280 | ret = snd_compress_new(rtd->card->snd_card, num, direction, compr); | ||
281 | if (ret < 0) { | ||
282 | pr_err("compress asoc: can't create compress for codec %s\n", | ||
283 | codec->name); | ||
284 | kfree(compr); | ||
285 | return ret; | ||
286 | } | ||
287 | |||
288 | rtd->compr = compr; | ||
289 | compr->private_data = rtd; | ||
290 | |||
291 | printk(KERN_INFO "compress asoc: %s <-> %s mapping ok\n", codec_dai->name, | ||
292 | cpu_dai->name); | ||
293 | return ret; | ||
294 | } | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c501af6d8dbe..b95d1fb388a1 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -1388,37 +1388,48 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1388 | if (ret < 0) | 1388 | if (ret < 0) |
1389 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); | 1389 | pr_warn("asoc: failed to add pmdown_time sysfs:%d\n", ret); |
1390 | 1390 | ||
1391 | if (!dai_link->params) { | 1391 | if (cpu_dai->driver->compress_dai) { |
1392 | /* create the pcm */ | 1392 | /*create compress_device"*/ |
1393 | ret = soc_new_pcm(rtd, num); | 1393 | ret = soc_new_compress(rtd, num); |
1394 | if (ret < 0) { | 1394 | if (ret < 0) { |
1395 | pr_err("asoc: can't create pcm %s :%d\n", | 1395 | pr_err("asoc: can't create compress %s\n", |
1396 | dai_link->stream_name, ret); | 1396 | dai_link->stream_name); |
1397 | return ret; | 1397 | return ret; |
1398 | } | 1398 | } |
1399 | } else { | 1399 | } else { |
1400 | /* link the DAI widgets */ | 1400 | |
1401 | play_w = codec_dai->playback_widget; | 1401 | if (!dai_link->params) { |
1402 | capture_w = cpu_dai->capture_widget; | 1402 | /* create the pcm */ |
1403 | if (play_w && capture_w) { | 1403 | ret = soc_new_pcm(rtd, num); |
1404 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1404 | if (ret < 0) { |
1405 | capture_w, play_w); | 1405 | pr_err("asoc: can't create pcm %s :%d\n", |
1406 | if (ret != 0) { | 1406 | dai_link->stream_name, ret); |
1407 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
1408 | play_w->name, capture_w->name, ret); | ||
1409 | return ret; | 1407 | return ret; |
1410 | } | 1408 | } |
1411 | } | 1409 | } else { |
1410 | /* link the DAI widgets */ | ||
1411 | play_w = codec_dai->playback_widget; | ||
1412 | capture_w = cpu_dai->capture_widget; | ||
1413 | if (play_w && capture_w) { | ||
1414 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | ||
1415 | capture_w, play_w); | ||
1416 | if (ret != 0) { | ||
1417 | dev_err(card->dev, "Can't link %s to %s: %d\n", | ||
1418 | play_w->name, capture_w->name, ret); | ||
1419 | return ret; | ||
1420 | } | ||
1421 | } | ||
1412 | 1422 | ||
1413 | play_w = cpu_dai->playback_widget; | 1423 | play_w = cpu_dai->playback_widget; |
1414 | capture_w = codec_dai->capture_widget; | 1424 | capture_w = codec_dai->capture_widget; |
1415 | if (play_w && capture_w) { | 1425 | if (play_w && capture_w) { |
1416 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, | 1426 | ret = snd_soc_dapm_new_pcm(card, dai_link->params, |
1417 | capture_w, play_w); | 1427 | capture_w, play_w); |
1418 | if (ret != 0) { | 1428 | if (ret != 0) { |
1419 | dev_err(card->dev, "Can't link %s to %s: %d\n", | 1429 | dev_err(card->dev, "Can't link %s to %s: %d\n", |
1420 | play_w->name, capture_w->name, ret); | 1430 | play_w->name, capture_w->name, ret); |
1421 | return ret; | 1431 | return ret; |
1432 | } | ||
1422 | } | 1433 | } |
1423 | } | 1434 | } |
1424 | } | 1435 | } |
@@ -1816,7 +1827,6 @@ base_error: | |||
1816 | static int soc_probe(struct platform_device *pdev) | 1827 | static int soc_probe(struct platform_device *pdev) |
1817 | { | 1828 | { |
1818 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 1829 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
1819 | int ret = 0; | ||
1820 | 1830 | ||
1821 | /* | 1831 | /* |
1822 | * no card, so machine driver should be registering card | 1832 | * no card, so machine driver should be registering card |
@@ -1832,13 +1842,7 @@ static int soc_probe(struct platform_device *pdev) | |||
1832 | /* Bodge while we unpick instantiation */ | 1842 | /* Bodge while we unpick instantiation */ |
1833 | card->dev = &pdev->dev; | 1843 | card->dev = &pdev->dev; |
1834 | 1844 | ||
1835 | ret = snd_soc_register_card(card); | 1845 | return snd_soc_register_card(card); |
1836 | if (ret != 0) { | ||
1837 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
1838 | return ret; | ||
1839 | } | ||
1840 | |||
1841 | return 0; | ||
1842 | } | 1846 | } |
1843 | 1847 | ||
1844 | static int soc_cleanup_card_resources(struct snd_soc_card *card) | 1848 | static int soc_cleanup_card_resources(struct snd_soc_card *card) |
@@ -3717,6 +3721,9 @@ int snd_soc_register_dai(struct device *dev, | |||
3717 | } | 3721 | } |
3718 | } | 3722 | } |
3719 | 3723 | ||
3724 | if (!dai->codec) | ||
3725 | dai->dapm.idle_bias_off = 1; | ||
3726 | |||
3720 | list_add(&dai->list, &dai_list); | 3727 | list_add(&dai->list, &dai_list); |
3721 | 3728 | ||
3722 | mutex_unlock(&client_mutex); | 3729 | mutex_unlock(&client_mutex); |
@@ -3805,6 +3812,9 @@ int snd_soc_register_dais(struct device *dev, | |||
3805 | } | 3812 | } |
3806 | } | 3813 | } |
3807 | 3814 | ||
3815 | if (!dai->codec) | ||
3816 | dai->dapm.idle_bias_off = 1; | ||
3817 | |||
3808 | list_add(&dai->list, &dai_list); | 3818 | list_add(&dai->list, &dai_list); |
3809 | 3819 | ||
3810 | mutex_unlock(&client_mutex); | 3820 | mutex_unlock(&client_mutex); |
diff --git a/sound/soc/soc-jack.c b/sound/soc/soc-jack.c index 0c172938b82a..fa0fd8ddae90 100644 --- a/sound/soc/soc-jack.c +++ b/sound/soc/soc-jack.c | |||
@@ -83,11 +83,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
83 | jack->status &= ~mask; | 83 | jack->status &= ~mask; |
84 | jack->status |= status & mask; | 84 | jack->status |= status & mask; |
85 | 85 | ||
86 | /* The DAPM sync is expensive enough to be worth skipping. | ||
87 | * However, empty mask means pin synchronization is desired. */ | ||
88 | if (mask && (jack->status == oldstatus)) | ||
89 | goto out; | ||
90 | |||
91 | trace_snd_soc_jack_notify(jack, status); | 86 | trace_snd_soc_jack_notify(jack, status); |
92 | 87 | ||
93 | list_for_each_entry(pin, &jack->pins, list) { | 88 | list_for_each_entry(pin, &jack->pins, list) { |
@@ -109,7 +104,6 @@ void snd_soc_jack_report(struct snd_soc_jack *jack, int status, int mask) | |||
109 | 104 | ||
110 | snd_jack_report(jack->jack, jack->status); | 105 | snd_jack_report(jack->jack, jack->status); |
111 | 106 | ||
112 | out: | ||
113 | mutex_unlock(&jack->mutex); | 107 | mutex_unlock(&jack->mutex); |
114 | } | 108 | } |
115 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); | 109 | EXPORT_SYMBOL_GPL(snd_soc_jack_report); |
diff --git a/sound/soc/ux500/ux500_msp_dai.c b/sound/soc/ux500/ux500_msp_dai.c index 057e28ef770e..772cb19d2fb3 100644 --- a/sound/soc/ux500/ux500_msp_dai.c +++ b/sound/soc/ux500/ux500_msp_dai.c | |||
@@ -760,6 +760,9 @@ static int __devinit ux500_msp_drv_probe(struct platform_device *pdev) | |||
760 | drvdata = devm_kzalloc(&pdev->dev, | 760 | drvdata = devm_kzalloc(&pdev->dev, |
761 | sizeof(struct ux500_msp_i2s_drvdata), | 761 | sizeof(struct ux500_msp_i2s_drvdata), |
762 | GFP_KERNEL); | 762 | GFP_KERNEL); |
763 | if (!drvdata) | ||
764 | return -ENOMEM; | ||
765 | |||
763 | drvdata->fmt = 0; | 766 | drvdata->fmt = 0; |
764 | drvdata->slots = 1; | 767 | drvdata->slots = 1; |
765 | drvdata->tx_mask = 0x01; | 768 | drvdata->tx_mask = 0x01; |
diff --git a/sound/soc/ux500/ux500_msp_i2s.c b/sound/soc/ux500/ux500_msp_i2s.c index 5c472f335a64..36be11e47ad6 100644 --- a/sound/soc/ux500/ux500_msp_i2s.c +++ b/sound/soc/ux500/ux500_msp_i2s.c | |||
@@ -673,6 +673,8 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev, | |||
673 | 673 | ||
674 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); | 674 | *msp_p = devm_kzalloc(&pdev->dev, sizeof(struct ux500_msp), GFP_KERNEL); |
675 | msp = *msp_p; | 675 | msp = *msp_p; |
676 | if (!msp) | ||
677 | return -ENOMEM; | ||
676 | 678 | ||
677 | msp->id = platform_data->id; | 679 | msp->id = platform_data->id; |
678 | msp->dev = &pdev->dev; | 680 | msp->dev = &pdev->dev; |