diff options
37 files changed, 987 insertions, 751 deletions
diff --git a/drivers/base/regmap/Kconfig b/drivers/base/regmap/Kconfig index 8a3f51f7b1b9..db9d00c36a3e 100644 --- a/drivers/base/regmap/Kconfig +++ b/drivers/base/regmap/Kconfig | |||
@@ -3,12 +3,15 @@ | |||
3 | # subsystems should select the appropriate symbols. | 3 | # subsystems should select the appropriate symbols. |
4 | 4 | ||
5 | config REGMAP | 5 | config REGMAP |
6 | default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_MMIO || REGMAP_IRQ) | 6 | default y if (REGMAP_I2C || REGMAP_SPI || REGMAP_SPMI || REGMAP_AC97 || REGMAP_MMIO || REGMAP_IRQ) |
7 | select LZO_COMPRESS | 7 | select LZO_COMPRESS |
8 | select LZO_DECOMPRESS | 8 | select LZO_DECOMPRESS |
9 | select IRQ_DOMAIN if REGMAP_IRQ | 9 | select IRQ_DOMAIN if REGMAP_IRQ |
10 | bool | 10 | bool |
11 | 11 | ||
12 | config REGMAP_AC97 | ||
13 | tristate | ||
14 | |||
12 | config REGMAP_I2C | 15 | config REGMAP_I2C |
13 | tristate | 16 | tristate |
14 | depends on I2C | 17 | depends on I2C |
diff --git a/drivers/base/regmap/Makefile b/drivers/base/regmap/Makefile index a7c670b4123a..0a533653ef3b 100644 --- a/drivers/base/regmap/Makefile +++ b/drivers/base/regmap/Makefile | |||
@@ -1,6 +1,7 @@ | |||
1 | obj-$(CONFIG_REGMAP) += regmap.o regcache.o | 1 | obj-$(CONFIG_REGMAP) += regmap.o regcache.o |
2 | obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o | 2 | obj-$(CONFIG_REGMAP) += regcache-rbtree.o regcache-lzo.o regcache-flat.o |
3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o | 3 | obj-$(CONFIG_DEBUG_FS) += regmap-debugfs.o |
4 | obj-$(CONFIG_REGMAP_AC97) += regmap-ac97.o | ||
4 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o | 5 | obj-$(CONFIG_REGMAP_I2C) += regmap-i2c.o |
5 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o | 6 | obj-$(CONFIG_REGMAP_SPI) += regmap-spi.o |
6 | obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o | 7 | obj-$(CONFIG_REGMAP_SPMI) += regmap-spmi.o |
diff --git a/drivers/base/regmap/regmap-ac97.c b/drivers/base/regmap/regmap-ac97.c new file mode 100644 index 000000000000..e4c45d2299c1 --- /dev/null +++ b/drivers/base/regmap/regmap-ac97.c | |||
@@ -0,0 +1,114 @@ | |||
1 | /* | ||
2 | * Register map access API - AC'97 support | ||
3 | * | ||
4 | * Copyright 2013 Linaro Ltd. All rights reserved. | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify it | ||
7 | * under the terms and conditions of the GNU General Public License, | ||
8 | * version 2, as published by the Free Software Foundation. | ||
9 | * | ||
10 | * This program is distributed in the hope it will be useful, but WITHOUT | ||
11 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | ||
12 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | ||
13 | * more details. | ||
14 | * | ||
15 | * You should have received a copy of the GNU General Public License | ||
16 | * along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
17 | */ | ||
18 | |||
19 | #include <linux/clk.h> | ||
20 | #include <linux/err.h> | ||
21 | #include <linux/init.h> | ||
22 | #include <linux/io.h> | ||
23 | #include <linux/module.h> | ||
24 | #include <linux/regmap.h> | ||
25 | #include <linux/slab.h> | ||
26 | |||
27 | #include <sound/ac97_codec.h> | ||
28 | |||
29 | bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg) | ||
30 | { | ||
31 | switch (reg) { | ||
32 | case AC97_RESET: | ||
33 | case AC97_POWERDOWN: | ||
34 | case AC97_INT_PAGING: | ||
35 | case AC97_EXTENDED_ID: | ||
36 | case AC97_EXTENDED_STATUS: | ||
37 | case AC97_EXTENDED_MID: | ||
38 | case AC97_EXTENDED_MSTATUS: | ||
39 | case AC97_GPIO_STATUS: | ||
40 | case AC97_MISC_AFE: | ||
41 | case AC97_VENDOR_ID1: | ||
42 | case AC97_VENDOR_ID2: | ||
43 | case AC97_CODEC_CLASS_REV: | ||
44 | case AC97_PCI_SVID: | ||
45 | case AC97_PCI_SID: | ||
46 | case AC97_FUNC_SELECT: | ||
47 | case AC97_FUNC_INFO: | ||
48 | case AC97_SENSE_INFO: | ||
49 | return true; | ||
50 | default: | ||
51 | return false; | ||
52 | } | ||
53 | } | ||
54 | EXPORT_SYMBOL_GPL(regmap_ac97_default_volatile); | ||
55 | |||
56 | static int regmap_ac97_reg_read(void *context, unsigned int reg, | ||
57 | unsigned int *val) | ||
58 | { | ||
59 | struct snd_ac97 *ac97 = context; | ||
60 | |||
61 | *val = ac97->bus->ops->read(ac97, reg); | ||
62 | |||
63 | return 0; | ||
64 | } | ||
65 | |||
66 | static int regmap_ac97_reg_write(void *context, unsigned int reg, | ||
67 | unsigned int val) | ||
68 | { | ||
69 | struct snd_ac97 *ac97 = context; | ||
70 | |||
71 | ac97->bus->ops->write(ac97, reg, val); | ||
72 | |||
73 | return 0; | ||
74 | } | ||
75 | |||
76 | static const struct regmap_bus ac97_regmap_bus = { | ||
77 | .reg_write = regmap_ac97_reg_write, | ||
78 | .reg_read = regmap_ac97_reg_read, | ||
79 | }; | ||
80 | |||
81 | /** | ||
82 | * regmap_init_ac97(): Initialise AC'97 register map | ||
83 | * | ||
84 | * @ac97: Device that will be interacted with | ||
85 | * @config: Configuration for register map | ||
86 | * | ||
87 | * The return value will be an ERR_PTR() on error or a valid pointer to | ||
88 | * a struct regmap. | ||
89 | */ | ||
90 | struct regmap *regmap_init_ac97(struct snd_ac97 *ac97, | ||
91 | const struct regmap_config *config) | ||
92 | { | ||
93 | return regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config); | ||
94 | } | ||
95 | EXPORT_SYMBOL_GPL(regmap_init_ac97); | ||
96 | |||
97 | /** | ||
98 | * devm_regmap_init_ac97(): Initialise AC'97 register map | ||
99 | * | ||
100 | * @ac97: Device that will be interacted with | ||
101 | * @config: Configuration for register map | ||
102 | * | ||
103 | * The return value will be an ERR_PTR() on error or a valid pointer | ||
104 | * to a struct regmap. The regmap will be automatically freed by the | ||
105 | * device management code. | ||
106 | */ | ||
107 | struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97, | ||
108 | const struct regmap_config *config) | ||
109 | { | ||
110 | return devm_regmap_init(&ac97->dev, &ac97_regmap_bus, ac97, config); | ||
111 | } | ||
112 | EXPORT_SYMBOL_GPL(devm_regmap_init_ac97); | ||
113 | |||
114 | MODULE_LICENSE("GPL v2"); | ||
diff --git a/include/linux/regmap.h b/include/linux/regmap.h index c5ed83f49c4e..4419b99d8d6e 100644 --- a/include/linux/regmap.h +++ b/include/linux/regmap.h | |||
@@ -27,6 +27,7 @@ struct spmi_device; | |||
27 | struct regmap; | 27 | struct regmap; |
28 | struct regmap_range_cfg; | 28 | struct regmap_range_cfg; |
29 | struct regmap_field; | 29 | struct regmap_field; |
30 | struct snd_ac97; | ||
30 | 31 | ||
31 | /* An enum of all the supported cache types */ | 32 | /* An enum of all the supported cache types */ |
32 | enum regcache_type { | 33 | enum regcache_type { |
@@ -340,6 +341,8 @@ struct regmap *regmap_init_spmi_ext(struct spmi_device *dev, | |||
340 | struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, | 341 | struct regmap *regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
341 | void __iomem *regs, | 342 | void __iomem *regs, |
342 | const struct regmap_config *config); | 343 | const struct regmap_config *config); |
344 | struct regmap *regmap_init_ac97(struct snd_ac97 *ac97, | ||
345 | const struct regmap_config *config); | ||
343 | 346 | ||
344 | struct regmap *devm_regmap_init(struct device *dev, | 347 | struct regmap *devm_regmap_init(struct device *dev, |
345 | const struct regmap_bus *bus, | 348 | const struct regmap_bus *bus, |
@@ -356,6 +359,10 @@ struct regmap *devm_regmap_init_spmi_ext(struct spmi_device *dev, | |||
356 | struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, | 359 | struct regmap *devm_regmap_init_mmio_clk(struct device *dev, const char *clk_id, |
357 | void __iomem *regs, | 360 | void __iomem *regs, |
358 | const struct regmap_config *config); | 361 | const struct regmap_config *config); |
362 | struct regmap *devm_regmap_init_ac97(struct snd_ac97 *ac97, | ||
363 | const struct regmap_config *config); | ||
364 | |||
365 | bool regmap_ac97_default_volatile(struct device *dev, unsigned int reg); | ||
359 | 366 | ||
360 | /** | 367 | /** |
361 | * regmap_init_mmio(): Initialise register map | 368 | * regmap_init_mmio(): Initialise register map |
diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 373d1775ecba..2df96b1384c7 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h | |||
@@ -206,7 +206,6 @@ struct snd_soc_dai_driver { | |||
206 | /* DAI description */ | 206 | /* DAI description */ |
207 | const char *name; | 207 | const char *name; |
208 | unsigned int id; | 208 | unsigned int id; |
209 | int ac97_control; | ||
210 | unsigned int base; | 209 | unsigned int base; |
211 | 210 | ||
212 | /* DAI driver callbacks */ | 211 | /* DAI driver callbacks */ |
@@ -216,6 +215,8 @@ struct snd_soc_dai_driver { | |||
216 | int (*resume)(struct snd_soc_dai *dai); | 215 | int (*resume)(struct snd_soc_dai *dai); |
217 | /* compress dai */ | 216 | /* compress dai */ |
218 | bool compress_dai; | 217 | bool compress_dai; |
218 | /* DAI is also used for the control bus */ | ||
219 | bool bus_control; | ||
219 | 220 | ||
220 | /* ops */ | 221 | /* ops */ |
221 | const struct snd_soc_dai_ops *ops; | 222 | const struct snd_soc_dai_ops *ops; |
@@ -241,7 +242,6 @@ struct snd_soc_dai { | |||
241 | const char *name; | 242 | const char *name; |
242 | int id; | 243 | int id; |
243 | struct device *dev; | 244 | struct device *dev; |
244 | void *ac97_pdata; /* platform_data for the ac97 codec */ | ||
245 | 245 | ||
246 | /* driver ops */ | 246 | /* driver ops */ |
247 | struct snd_soc_dai_driver *driver; | 247 | struct snd_soc_dai_driver *driver; |
diff --git a/include/sound/soc.h b/include/sound/soc.h index 38769cc900c9..a765c684bd7b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -369,8 +369,6 @@ struct snd_soc_jack_gpio; | |||
369 | 369 | ||
370 | typedef int (*hw_write_t)(void *,const char* ,int); | 370 | typedef int (*hw_write_t)(void *,const char* ,int); |
371 | 371 | ||
372 | extern struct snd_ac97_bus_ops *soc_ac97_ops; | ||
373 | |||
374 | enum snd_soc_pcm_subclass { | 372 | enum snd_soc_pcm_subclass { |
375 | SND_SOC_PCM_CLASS_PCM = 0, | 373 | SND_SOC_PCM_CLASS_PCM = 0, |
376 | SND_SOC_PCM_CLASS_BE = 1, | 374 | SND_SOC_PCM_CLASS_BE = 1, |
@@ -499,14 +497,28 @@ int snd_soc_update_bits_locked(struct snd_soc_codec *codec, | |||
499 | int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, | 497 | int snd_soc_test_bits(struct snd_soc_codec *codec, unsigned int reg, |
500 | unsigned int mask, unsigned int value); | 498 | unsigned int mask, unsigned int value); |
501 | 499 | ||
502 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | 500 | #ifdef CONFIG_SND_SOC_AC97_BUS |
503 | struct snd_ac97_bus_ops *ops, int num); | 501 | struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec); |
504 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); | 502 | void snd_soc_free_ac97_codec(struct snd_ac97 *ac97); |
505 | 503 | ||
506 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); | 504 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); |
507 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | 505 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, |
508 | struct platform_device *pdev); | 506 | struct platform_device *pdev); |
509 | 507 | ||
508 | extern struct snd_ac97_bus_ops *soc_ac97_ops; | ||
509 | #else | ||
510 | static inline int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
511 | struct platform_device *pdev) | ||
512 | { | ||
513 | return 0; | ||
514 | } | ||
515 | |||
516 | static inline int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
517 | { | ||
518 | return 0; | ||
519 | } | ||
520 | #endif | ||
521 | |||
510 | /* | 522 | /* |
511 | *Controls | 523 | *Controls |
512 | */ | 524 | */ |
@@ -778,11 +790,8 @@ struct snd_soc_codec { | |||
778 | struct list_head card_list; | 790 | struct list_head card_list; |
779 | 791 | ||
780 | /* runtime */ | 792 | /* runtime */ |
781 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ | ||
782 | unsigned int cache_bypass:1; /* Suppress access to the cache */ | 793 | unsigned int cache_bypass:1; /* Suppress access to the cache */ |
783 | unsigned int suspended:1; /* Codec is in suspend PM state */ | 794 | unsigned int suspended:1; /* Codec is in suspend PM state */ |
784 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | ||
785 | unsigned int ac97_created:1; /* Codec has been created by SoC */ | ||
786 | unsigned int cache_init:1; /* codec cache has been initialized */ | 795 | unsigned int cache_init:1; /* codec cache has been initialized */ |
787 | 796 | ||
788 | /* codec IO */ | 797 | /* codec IO */ |
@@ -1275,6 +1284,45 @@ void snd_soc_component_async_complete(struct snd_soc_component *component); | |||
1275 | int snd_soc_component_test_bits(struct snd_soc_component *component, | 1284 | int snd_soc_component_test_bits(struct snd_soc_component *component, |
1276 | unsigned int reg, unsigned int mask, unsigned int value); | 1285 | unsigned int reg, unsigned int mask, unsigned int value); |
1277 | 1286 | ||
1287 | #ifdef CONFIG_REGMAP | ||
1288 | |||
1289 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
1290 | struct regmap *regmap); | ||
1291 | void snd_soc_component_exit_regmap(struct snd_soc_component *component); | ||
1292 | |||
1293 | /** | ||
1294 | * snd_soc_codec_init_regmap() - Initialize regmap instance for the CODEC | ||
1295 | * @codec: The CODEC for which to initialize the regmap instance | ||
1296 | * @regmap: The regmap instance that should be used by the CODEC | ||
1297 | * | ||
1298 | * This function allows deferred assignment of the regmap instance that is | ||
1299 | * associated with the CODEC. Only use this if the regmap instance is not yet | ||
1300 | * ready when the CODEC is registered. The function must also be called before | ||
1301 | * the first IO attempt of the CODEC. | ||
1302 | */ | ||
1303 | static inline void snd_soc_codec_init_regmap(struct snd_soc_codec *codec, | ||
1304 | struct regmap *regmap) | ||
1305 | { | ||
1306 | snd_soc_component_init_regmap(&codec->component, regmap); | ||
1307 | } | ||
1308 | |||
1309 | /** | ||
1310 | * snd_soc_codec_exit_regmap() - De-initialize regmap instance for the CODEC | ||
1311 | * @codec: The CODEC for which to de-initialize the regmap instance | ||
1312 | * | ||
1313 | * Calls regmap_exit() on the regmap instance associated to the CODEC and | ||
1314 | * removes the regmap instance from the CODEC. | ||
1315 | * | ||
1316 | * This function should only be used if snd_soc_codec_init_regmap() was used to | ||
1317 | * initialize the regmap instance. | ||
1318 | */ | ||
1319 | static inline void snd_soc_codec_exit_regmap(struct snd_soc_codec *codec) | ||
1320 | { | ||
1321 | snd_soc_component_exit_regmap(&codec->component); | ||
1322 | } | ||
1323 | |||
1324 | #endif | ||
1325 | |||
1278 | /* device driver data */ | 1326 | /* device driver data */ |
1279 | 1327 | ||
1280 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, | 1328 | static inline void snd_soc_card_set_drvdata(struct snd_soc_card *card, |
diff --git a/sound/soc/Makefile b/sound/soc/Makefile index 2a043804a2bc..865e090c8061 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile | |||
@@ -5,6 +5,10 @@ ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) | |||
5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o | 5 | snd-soc-core-objs += soc-generic-dmaengine-pcm.o |
6 | endif | 6 | endif |
7 | 7 | ||
8 | ifneq ($(CONFIG_SND_SOC_AC97_BUS),) | ||
9 | snd-soc-core-objs += soc-ac97.o | ||
10 | endif | ||
11 | |||
8 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o | 12 | obj-$(CONFIG_SND_SOC) += snd-soc-core.o |
9 | obj-$(CONFIG_SND_SOC) += codecs/ | 13 | obj-$(CONFIG_SND_SOC) += codecs/ |
10 | obj-$(CONFIG_SND_SOC) += generic/ | 14 | obj-$(CONFIG_SND_SOC) += generic/ |
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index c8a2de103c5f..5159a50a45a6 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c | |||
@@ -205,7 +205,7 @@ static int au1xac97c_dai_probe(struct snd_soc_dai *dai) | |||
205 | 205 | ||
206 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { | 206 | static struct snd_soc_dai_driver au1xac97c_dai_driver = { |
207 | .name = "alchemy-ac97c", | 207 | .name = "alchemy-ac97c", |
208 | .ac97_control = 1, | 208 | .bus_control = true, |
209 | .probe = au1xac97c_dai_probe, | 209 | .probe = au1xac97c_dai_probe, |
210 | .playback = { | 210 | .playback = { |
211 | .rates = AC97_RATES, | 211 | .rates = AC97_RATES, |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 84f31e1f9d24..c6daec98ff89 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -343,7 +343,7 @@ static const struct snd_soc_dai_ops au1xpsc_ac97_dai_ops = { | |||
343 | }; | 343 | }; |
344 | 344 | ||
345 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { | 345 | static const struct snd_soc_dai_driver au1xpsc_ac97_dai_template = { |
346 | .ac97_control = 1, | 346 | .bus_control = true, |
347 | .probe = au1xpsc_ac97_probe, | 347 | .probe = au1xpsc_ac97_probe, |
348 | .playback = { | 348 | .playback = { |
349 | .rates = AC97_RATES, | 349 | .rates = AC97_RATES, |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index e82eb373a731..6bf21a6c02e4 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -260,7 +260,7 @@ static int bf5xx_ac97_resume(struct snd_soc_dai *dai) | |||
260 | #endif | 260 | #endif |
261 | 261 | ||
262 | static struct snd_soc_dai_driver bfin_ac97_dai = { | 262 | static struct snd_soc_dai_driver bfin_ac97_dai = { |
263 | .ac97_control = 1, | 263 | .bus_control = true, |
264 | .suspend = bf5xx_ac97_suspend, | 264 | .suspend = bf5xx_ac97_suspend, |
265 | .resume = bf5xx_ac97_resume, | 265 | .resume = bf5xx_ac97_resume, |
266 | .playback = { | 266 | .playback = { |
diff --git a/sound/soc/blackfin/bf5xx-ad1980.c b/sound/soc/blackfin/bf5xx-ad1980.c index 3450e8f9080d..0fa81a523b8a 100644 --- a/sound/soc/blackfin/bf5xx-ad1980.c +++ b/sound/soc/blackfin/bf5xx-ad1980.c | |||
@@ -46,8 +46,6 @@ | |||
46 | #include <linux/gpio.h> | 46 | #include <linux/gpio.h> |
47 | #include <asm/portmux.h> | 47 | #include <asm/portmux.h> |
48 | 48 | ||
49 | #include "../codecs/ad1980.h" | ||
50 | |||
51 | #include "bf5xx-ac97.h" | 49 | #include "bf5xx-ac97.h" |
52 | 50 | ||
53 | static struct snd_soc_card bf5xx_board; | 51 | static struct snd_soc_card bf5xx_board; |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index f30dadf85b99..6b8a366b0211 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -338,7 +338,7 @@ static const struct snd_soc_dai_ops ep93xx_ac97_dai_ops = { | |||
338 | static struct snd_soc_dai_driver ep93xx_ac97_dai = { | 338 | static struct snd_soc_dai_driver ep93xx_ac97_dai = { |
339 | .name = "ep93xx-ac97", | 339 | .name = "ep93xx-ac97", |
340 | .id = 0, | 340 | .id = 0, |
341 | .ac97_control = 1, | 341 | .bus_control = true, |
342 | .probe = ep93xx_ac97_dai_probe, | 342 | .probe = ep93xx_ac97_dai_probe, |
343 | .playback = { | 343 | .playback = { |
344 | .stream_name = "AC97 Playback", | 344 | .stream_name = "AC97 Playback", |
diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index a68d1731a8fd..6a66216a9c0f 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig | |||
@@ -223,6 +223,7 @@ config SND_SOC_AD193X_I2C | |||
223 | select SND_SOC_AD193X | 223 | select SND_SOC_AD193X |
224 | 224 | ||
225 | config SND_SOC_AD1980 | 225 | config SND_SOC_AD1980 |
226 | select REGMAP_AC97 | ||
226 | tristate | 227 | tristate |
227 | 228 | ||
228 | config SND_SOC_AD73311 | 229 | config SND_SOC_AD73311 |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index bd9b1839c8b0..c6e5a313ebf4 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -37,10 +37,11 @@ static int ac97_prepare(struct snd_pcm_substream *substream, | |||
37 | struct snd_soc_dai *dai) | 37 | struct snd_soc_dai *dai) |
38 | { | 38 | { |
39 | struct snd_soc_codec *codec = dai->codec; | 39 | struct snd_soc_codec *codec = dai->codec; |
40 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
40 | 41 | ||
41 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? | 42 | int reg = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ? |
42 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; | 43 | AC97_PCM_FRONT_DAC_RATE : AC97_PCM_LR_ADC_RATE; |
43 | return snd_ac97_set_rate(codec->ac97, reg, substream->runtime->rate); | 44 | return snd_ac97_set_rate(ac97, reg, substream->runtime->rate); |
44 | } | 45 | } |
45 | 46 | ||
46 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ | 47 | #define STD_AC97_RATES (SNDRV_PCM_RATE_8000 | SNDRV_PCM_RATE_11025 |\ |
@@ -53,7 +54,6 @@ static const struct snd_soc_dai_ops ac97_dai_ops = { | |||
53 | 54 | ||
54 | static struct snd_soc_dai_driver ac97_dai = { | 55 | static struct snd_soc_dai_driver ac97_dai = { |
55 | .name = "ac97-hifi", | 56 | .name = "ac97-hifi", |
56 | .ac97_control = 1, | ||
57 | .playback = { | 57 | .playback = { |
58 | .stream_name = "AC97 Playback", | 58 | .stream_name = "AC97 Playback", |
59 | .channels_min = 1, | 59 | .channels_min = 1, |
@@ -71,6 +71,7 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
71 | 71 | ||
72 | static int ac97_soc_probe(struct snd_soc_codec *codec) | 72 | static int ac97_soc_probe(struct snd_soc_codec *codec) |
73 | { | 73 | { |
74 | struct snd_ac97 *ac97; | ||
74 | struct snd_ac97_bus *ac97_bus; | 75 | struct snd_ac97_bus *ac97_bus; |
75 | struct snd_ac97_template ac97_template; | 76 | struct snd_ac97_template ac97_template; |
76 | int ret; | 77 | int ret; |
@@ -82,24 +83,31 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
82 | return ret; | 83 | return ret; |
83 | 84 | ||
84 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); | 85 | memset(&ac97_template, 0, sizeof(struct snd_ac97_template)); |
85 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &codec->ac97); | 86 | ret = snd_ac97_mixer(ac97_bus, &ac97_template, &ac97); |
86 | if (ret < 0) | 87 | if (ret < 0) |
87 | return ret; | 88 | return ret; |
88 | 89 | ||
90 | snd_soc_codec_set_drvdata(codec, ac97); | ||
91 | |||
89 | return 0; | 92 | return 0; |
90 | } | 93 | } |
91 | 94 | ||
92 | #ifdef CONFIG_PM | 95 | #ifdef CONFIG_PM |
93 | static int ac97_soc_suspend(struct snd_soc_codec *codec) | 96 | static int ac97_soc_suspend(struct snd_soc_codec *codec) |
94 | { | 97 | { |
95 | snd_ac97_suspend(codec->ac97); | 98 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
99 | |||
100 | snd_ac97_suspend(ac97); | ||
96 | 101 | ||
97 | return 0; | 102 | return 0; |
98 | } | 103 | } |
99 | 104 | ||
100 | static int ac97_soc_resume(struct snd_soc_codec *codec) | 105 | static int ac97_soc_resume(struct snd_soc_codec *codec) |
101 | { | 106 | { |
102 | snd_ac97_resume(codec->ac97); | 107 | |
108 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
109 | |||
110 | snd_ac97_resume(ac97); | ||
103 | 111 | ||
104 | return 0; | 112 | return 0; |
105 | } | 113 | } |
diff --git a/sound/soc/codecs/ad193x.c b/sound/soc/codecs/ad193x.c index 6844d0b2af68..387530b0b0fd 100644 --- a/sound/soc/codecs/ad193x.c +++ b/sound/soc/codecs/ad193x.c | |||
@@ -72,11 +72,13 @@ static const struct snd_kcontrol_new ad193x_snd_controls[] = { | |||
72 | }; | 72 | }; |
73 | 73 | ||
74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | 74 | static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { |
75 | SND_SOC_DAPM_DAC("DAC", "Playback", AD193X_DAC_CTRL0, 0, 1), | 75 | SND_SOC_DAPM_DAC("DAC", "Playback", SND_SOC_NOPM, 0, 0), |
76 | SND_SOC_DAPM_PGA("DAC Output", AD193X_DAC_CTRL0, 0, 1, NULL, 0), | ||
76 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), | 77 | SND_SOC_DAPM_ADC("ADC", "Capture", SND_SOC_NOPM, 0, 0), |
77 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), | 78 | SND_SOC_DAPM_SUPPLY("PLL_PWR", AD193X_PLL_CLK_CTRL0, 0, 1, NULL, 0), |
78 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), | 79 | SND_SOC_DAPM_SUPPLY("ADC_PWR", AD193X_ADC_CTRL0, 0, 1, NULL, 0), |
79 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), | 80 | SND_SOC_DAPM_SUPPLY("SYSCLK", AD193X_PLL_CLK_CTRL0, 7, 0, NULL, 0), |
81 | SND_SOC_DAPM_VMID("VMID"), | ||
80 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), | 82 | SND_SOC_DAPM_OUTPUT("DAC1OUT"), |
81 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), | 83 | SND_SOC_DAPM_OUTPUT("DAC2OUT"), |
82 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), | 84 | SND_SOC_DAPM_OUTPUT("DAC3OUT"), |
@@ -87,13 +89,15 @@ static const struct snd_soc_dapm_widget ad193x_dapm_widgets[] = { | |||
87 | 89 | ||
88 | static const struct snd_soc_dapm_route audio_paths[] = { | 90 | static const struct snd_soc_dapm_route audio_paths[] = { |
89 | { "DAC", NULL, "SYSCLK" }, | 91 | { "DAC", NULL, "SYSCLK" }, |
92 | { "DAC Output", NULL, "DAC" }, | ||
93 | { "DAC Output", NULL, "VMID" }, | ||
90 | { "ADC", NULL, "SYSCLK" }, | 94 | { "ADC", NULL, "SYSCLK" }, |
91 | { "DAC", NULL, "ADC_PWR" }, | 95 | { "DAC", NULL, "ADC_PWR" }, |
92 | { "ADC", NULL, "ADC_PWR" }, | 96 | { "ADC", NULL, "ADC_PWR" }, |
93 | { "DAC1OUT", NULL, "DAC" }, | 97 | { "DAC1OUT", NULL, "DAC Output" }, |
94 | { "DAC2OUT", NULL, "DAC" }, | 98 | { "DAC2OUT", NULL, "DAC Output" }, |
95 | { "DAC3OUT", NULL, "DAC" }, | 99 | { "DAC3OUT", NULL, "DAC Output" }, |
96 | { "DAC4OUT", NULL, "DAC" }, | 100 | { "DAC4OUT", NULL, "DAC Output" }, |
97 | { "ADC", NULL, "ADC1IN" }, | 101 | { "ADC", NULL, "ADC1IN" }, |
98 | { "ADC", NULL, "ADC2IN" }, | 102 | { "ADC", NULL, "ADC2IN" }, |
99 | { "SYSCLK", NULL, "PLL_PWR" }, | 103 | { "SYSCLK", NULL, "PLL_PWR" }, |
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index 304d3003339a..2860eef8610c 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -24,34 +24,86 @@ | |||
24 | #include <linux/module.h> | 24 | #include <linux/module.h> |
25 | #include <linux/kernel.h> | 25 | #include <linux/kernel.h> |
26 | #include <linux/device.h> | 26 | #include <linux/device.h> |
27 | #include <linux/regmap.h> | ||
27 | #include <sound/core.h> | 28 | #include <sound/core.h> |
28 | #include <sound/pcm.h> | 29 | #include <sound/pcm.h> |
29 | #include <sound/ac97_codec.h> | 30 | #include <sound/ac97_codec.h> |
30 | #include <sound/initval.h> | 31 | #include <sound/initval.h> |
31 | #include <sound/soc.h> | 32 | #include <sound/soc.h> |
32 | 33 | ||
33 | #include "ad1980.h" | 34 | static const struct reg_default ad1980_reg_defaults[] = { |
35 | { 0x02, 0x8000 }, | ||
36 | { 0x04, 0x8000 }, | ||
37 | { 0x06, 0x8000 }, | ||
38 | { 0x0c, 0x8008 }, | ||
39 | { 0x0e, 0x8008 }, | ||
40 | { 0x10, 0x8808 }, | ||
41 | { 0x12, 0x8808 }, | ||
42 | { 0x16, 0x8808 }, | ||
43 | { 0x18, 0x8808 }, | ||
44 | { 0x1a, 0x0000 }, | ||
45 | { 0x1c, 0x8000 }, | ||
46 | { 0x20, 0x0000 }, | ||
47 | { 0x28, 0x03c7 }, | ||
48 | { 0x2c, 0xbb80 }, | ||
49 | { 0x2e, 0xbb80 }, | ||
50 | { 0x30, 0xbb80 }, | ||
51 | { 0x32, 0xbb80 }, | ||
52 | { 0x36, 0x8080 }, | ||
53 | { 0x38, 0x8080 }, | ||
54 | { 0x3a, 0x2000 }, | ||
55 | { 0x60, 0x0000 }, | ||
56 | { 0x62, 0x0000 }, | ||
57 | { 0x72, 0x0000 }, | ||
58 | { 0x74, 0x1001 }, | ||
59 | { 0x76, 0x0000 }, | ||
60 | }; | ||
34 | 61 | ||
35 | /* | 62 | static bool ad1980_readable_reg(struct device *dev, unsigned int reg) |
36 | * AD1980 register cache | 63 | { |
37 | */ | 64 | switch (reg) { |
38 | static const u16 ad1980_reg[] = { | 65 | case AC97_RESET ... AC97_MASTER_MONO: |
39 | 0x0090, 0x8000, 0x8000, 0x8000, /* 0 - 6 */ | 66 | case AC97_PHONE ... AC97_CD: |
40 | 0x0000, 0x0000, 0x8008, 0x8008, /* 8 - e */ | 67 | case AC97_AUX ... AC97_GENERAL_PURPOSE: |
41 | 0x8808, 0x8808, 0x0000, 0x8808, /* 10 - 16 */ | 68 | case AC97_POWERDOWN ... AC97_PCM_LR_ADC_RATE: |
42 | 0x8808, 0x0000, 0x8000, 0x0000, /* 18 - 1e */ | 69 | case AC97_SPDIF: |
43 | 0x0000, 0x0000, 0x0000, 0x0000, /* 20 - 26 */ | 70 | case AC97_CODEC_CLASS_REV: |
44 | 0x03c7, 0x0000, 0xbb80, 0xbb80, /* 28 - 2e */ | 71 | case AC97_PCI_SVID: |
45 | 0xbb80, 0xbb80, 0x0000, 0x8080, /* 30 - 36 */ | 72 | case AC97_AD_CODEC_CFG: |
46 | 0x8080, 0x2000, 0x0000, 0x0000, /* 38 - 3e */ | 73 | case AC97_AD_JACK_SPDIF: |
47 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 74 | case AC97_AD_SERIAL_CFG: |
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 75 | case AC97_VENDOR_ID1: |
49 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 76 | case AC97_VENDOR_ID2: |
50 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 77 | return true; |
51 | 0x8080, 0x0000, 0x0000, 0x0000, /* 60 - 66 */ | 78 | default: |
52 | 0x0000, 0x0000, 0x0000, 0x0000, /* reserved */ | 79 | return false; |
53 | 0x0000, 0x0000, 0x1001, 0x0000, /* 70 - 76 */ | 80 | } |
54 | 0x0000, 0x0000, 0x4144, 0x5370 /* 78 - 7e */ | 81 | } |
82 | |||
83 | static bool ad1980_writeable_reg(struct device *dev, unsigned int reg) | ||
84 | { | ||
85 | switch (reg) { | ||
86 | case AC97_VENDOR_ID1: | ||
87 | case AC97_VENDOR_ID2: | ||
88 | return false; | ||
89 | default: | ||
90 | return ad1980_readable_reg(dev, reg); | ||
91 | } | ||
92 | } | ||
93 | |||
94 | static const struct regmap_config ad1980_regmap_config = { | ||
95 | .reg_bits = 16, | ||
96 | .reg_stride = 2, | ||
97 | .val_bits = 16, | ||
98 | .max_register = 0x7e, | ||
99 | .cache_type = REGCACHE_RBTREE, | ||
100 | |||
101 | .volatile_reg = regmap_ac97_default_volatile, | ||
102 | .readable_reg = ad1980_readable_reg, | ||
103 | .writeable_reg = ad1980_writeable_reg, | ||
104 | |||
105 | .reg_defaults = ad1980_reg_defaults, | ||
106 | .num_reg_defaults = ARRAY_SIZE(ad1980_reg_defaults), | ||
55 | }; | 107 | }; |
56 | 108 | ||
57 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", | 109 | static const char *ad1980_rec_sel[] = {"Mic", "CD", "NC", "AUX", "Line", |
@@ -134,45 +186,8 @@ static const struct snd_soc_dapm_route ad1980_dapm_routes[] = { | |||
134 | { "HP_OUT_R", NULL, "Playback" }, | 186 | { "HP_OUT_R", NULL, "Playback" }, |
135 | }; | 187 | }; |
136 | 188 | ||
137 | static unsigned int ac97_read(struct snd_soc_codec *codec, | ||
138 | unsigned int reg) | ||
139 | { | ||
140 | u16 *cache = codec->reg_cache; | ||
141 | |||
142 | switch (reg) { | ||
143 | case AC97_RESET: | ||
144 | case AC97_INT_PAGING: | ||
145 | case AC97_POWERDOWN: | ||
146 | case AC97_EXTENDED_STATUS: | ||
147 | case AC97_VENDOR_ID1: | ||
148 | case AC97_VENDOR_ID2: | ||
149 | return soc_ac97_ops->read(codec->ac97, reg); | ||
150 | default: | ||
151 | reg = reg >> 1; | ||
152 | |||
153 | if (reg >= ARRAY_SIZE(ad1980_reg)) | ||
154 | return -EINVAL; | ||
155 | |||
156 | return cache[reg]; | ||
157 | } | ||
158 | } | ||
159 | |||
160 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | ||
161 | unsigned int val) | ||
162 | { | ||
163 | u16 *cache = codec->reg_cache; | ||
164 | |||
165 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
166 | reg = reg >> 1; | ||
167 | if (reg < ARRAY_SIZE(ad1980_reg)) | ||
168 | cache[reg] = val; | ||
169 | |||
170 | return 0; | ||
171 | } | ||
172 | |||
173 | static struct snd_soc_dai_driver ad1980_dai = { | 189 | static struct snd_soc_dai_driver ad1980_dai = { |
174 | .name = "ad1980-hifi", | 190 | .name = "ad1980-hifi", |
175 | .ac97_control = 1, | ||
176 | .playback = { | 191 | .playback = { |
177 | .stream_name = "Playback", | 192 | .stream_name = "Playback", |
178 | .channels_min = 2, | 193 | .channels_min = 2, |
@@ -189,108 +204,115 @@ static struct snd_soc_dai_driver ad1980_dai = { | |||
189 | 204 | ||
190 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | 205 | static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) |
191 | { | 206 | { |
207 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
192 | unsigned int retry_cnt = 0; | 208 | unsigned int retry_cnt = 0; |
193 | 209 | ||
194 | do { | 210 | do { |
195 | if (try_warm && soc_ac97_ops->warm_reset) { | 211 | if (try_warm && soc_ac97_ops->warm_reset) { |
196 | soc_ac97_ops->warm_reset(codec->ac97); | 212 | soc_ac97_ops->warm_reset(ac97); |
197 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 213 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
198 | return 1; | 214 | return 1; |
199 | } | 215 | } |
200 | 216 | ||
201 | soc_ac97_ops->reset(codec->ac97); | 217 | soc_ac97_ops->reset(ac97); |
202 | /* | 218 | /* |
203 | * Set bit 16slot in register 74h, then every slot will has only | 219 | * Set bit 16slot in register 74h, then every slot will has only |
204 | * 16 bits. This command is sent out in 20bit mode, in which | 220 | * 16 bits. This command is sent out in 20bit mode, in which |
205 | * case the first nibble of data is eaten by the addr. (Tag is | 221 | * case the first nibble of data is eaten by the addr. (Tag is |
206 | * always 16 bit) | 222 | * always 16 bit) |
207 | */ | 223 | */ |
208 | ac97_write(codec, AC97_AD_SERIAL_CFG, 0x9900); | 224 | snd_soc_write(codec, AC97_AD_SERIAL_CFG, 0x9900); |
209 | 225 | ||
210 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 226 | if (snd_soc_read(codec, AC97_RESET) == 0x0090) |
211 | return 0; | 227 | return 0; |
212 | } while (retry_cnt++ < 10); | 228 | } while (retry_cnt++ < 10); |
213 | 229 | ||
214 | printk(KERN_ERR "AD1980 AC97 reset failed\n"); | 230 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
231 | |||
215 | return -EIO; | 232 | return -EIO; |
216 | } | 233 | } |
217 | 234 | ||
218 | static int ad1980_soc_probe(struct snd_soc_codec *codec) | 235 | static int ad1980_soc_probe(struct snd_soc_codec *codec) |
219 | { | 236 | { |
237 | struct snd_ac97 *ac97; | ||
238 | struct regmap *regmap; | ||
220 | int ret; | 239 | int ret; |
221 | u16 vendor_id2; | 240 | u16 vendor_id2; |
222 | u16 ext_status; | 241 | u16 ext_status; |
223 | 242 | ||
224 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 243 | ac97 = snd_soc_new_ac97_codec(codec); |
225 | 244 | if (IS_ERR(ac97)) { | |
226 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 245 | ret = PTR_ERR(ac97); |
227 | if (ret < 0) { | 246 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); |
228 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | ||
229 | return ret; | 247 | return ret; |
230 | } | 248 | } |
231 | 249 | ||
250 | regmap = regmap_init_ac97(ac97, &ad1980_regmap_config); | ||
251 | if (IS_ERR(regmap)) { | ||
252 | ret = PTR_ERR(regmap); | ||
253 | goto err_free_ac97; | ||
254 | } | ||
255 | |||
256 | snd_soc_codec_init_regmap(codec, regmap); | ||
257 | snd_soc_codec_set_drvdata(codec, ac97); | ||
258 | |||
232 | ret = ad1980_reset(codec, 0); | 259 | ret = ad1980_reset(codec, 0); |
233 | if (ret < 0) { | 260 | if (ret < 0) |
234 | printk(KERN_ERR "Failed to reset AD1980: AC97 link error\n"); | ||
235 | goto reset_err; | 261 | goto reset_err; |
236 | } | ||
237 | 262 | ||
238 | /* Read out vendor ID to make sure it is ad1980 */ | 263 | /* Read out vendor ID to make sure it is ad1980 */ |
239 | if (ac97_read(codec, AC97_VENDOR_ID1) != 0x4144) { | 264 | if (snd_soc_read(codec, AC97_VENDOR_ID1) != 0x4144) { |
240 | ret = -ENODEV; | 265 | ret = -ENODEV; |
241 | goto reset_err; | 266 | goto reset_err; |
242 | } | 267 | } |
243 | 268 | ||
244 | vendor_id2 = ac97_read(codec, AC97_VENDOR_ID2); | 269 | vendor_id2 = snd_soc_read(codec, AC97_VENDOR_ID2); |
245 | 270 | ||
246 | if (vendor_id2 != 0x5370) { | 271 | if (vendor_id2 != 0x5370) { |
247 | if (vendor_id2 != 0x5374) { | 272 | if (vendor_id2 != 0x5374) { |
248 | ret = -ENODEV; | 273 | ret = -ENODEV; |
249 | goto reset_err; | 274 | goto reset_err; |
250 | } else { | 275 | } else { |
251 | printk(KERN_WARNING "ad1980: " | 276 | dev_warn(codec->dev, |
252 | "Found AD1981 - only 2/2 IN/OUT Channels " | 277 | "Found AD1981 - only 2/2 IN/OUT Channels supported\n"); |
253 | "supported\n"); | ||
254 | } | 278 | } |
255 | } | 279 | } |
256 | 280 | ||
257 | /* unmute captures and playbacks volume */ | 281 | /* unmute captures and playbacks volume */ |
258 | ac97_write(codec, AC97_MASTER, 0x0000); | 282 | snd_soc_write(codec, AC97_MASTER, 0x0000); |
259 | ac97_write(codec, AC97_PCM, 0x0000); | 283 | snd_soc_write(codec, AC97_PCM, 0x0000); |
260 | ac97_write(codec, AC97_REC_GAIN, 0x0000); | 284 | snd_soc_write(codec, AC97_REC_GAIN, 0x0000); |
261 | ac97_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); | 285 | snd_soc_write(codec, AC97_CENTER_LFE_MASTER, 0x0000); |
262 | ac97_write(codec, AC97_SURROUND_MASTER, 0x0000); | 286 | snd_soc_write(codec, AC97_SURROUND_MASTER, 0x0000); |
263 | 287 | ||
264 | /*power on LFE/CENTER/Surround DACs*/ | 288 | /*power on LFE/CENTER/Surround DACs*/ |
265 | ext_status = ac97_read(codec, AC97_EXTENDED_STATUS); | 289 | ext_status = snd_soc_read(codec, AC97_EXTENDED_STATUS); |
266 | ac97_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); | 290 | snd_soc_write(codec, AC97_EXTENDED_STATUS, ext_status&~0x3800); |
267 | |||
268 | snd_soc_add_codec_controls(codec, ad1980_snd_ac97_controls, | ||
269 | ARRAY_SIZE(ad1980_snd_ac97_controls)); | ||
270 | 291 | ||
271 | return 0; | 292 | return 0; |
272 | 293 | ||
273 | reset_err: | 294 | reset_err: |
274 | snd_soc_free_ac97_codec(codec); | 295 | snd_soc_codec_exit_regmap(codec); |
296 | err_free_ac97: | ||
297 | snd_soc_free_ac97_codec(ac97); | ||
275 | return ret; | 298 | return ret; |
276 | } | 299 | } |
277 | 300 | ||
278 | static int ad1980_soc_remove(struct snd_soc_codec *codec) | 301 | static int ad1980_soc_remove(struct snd_soc_codec *codec) |
279 | { | 302 | { |
280 | snd_soc_free_ac97_codec(codec); | 303 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
304 | |||
305 | snd_soc_codec_exit_regmap(codec); | ||
306 | snd_soc_free_ac97_codec(ac97); | ||
281 | return 0; | 307 | return 0; |
282 | } | 308 | } |
283 | 309 | ||
284 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { | 310 | static struct snd_soc_codec_driver soc_codec_dev_ad1980 = { |
285 | .probe = ad1980_soc_probe, | 311 | .probe = ad1980_soc_probe, |
286 | .remove = ad1980_soc_remove, | 312 | .remove = ad1980_soc_remove, |
287 | .reg_cache_size = ARRAY_SIZE(ad1980_reg), | ||
288 | .reg_word_size = sizeof(u16), | ||
289 | .reg_cache_default = ad1980_reg, | ||
290 | .reg_cache_step = 2, | ||
291 | .write = ac97_write, | ||
292 | .read = ac97_read, | ||
293 | 313 | ||
314 | .controls = ad1980_snd_ac97_controls, | ||
315 | .num_controls = ARRAY_SIZE(ad1980_snd_ac97_controls), | ||
294 | .dapm_widgets = ad1980_dapm_widgets, | 316 | .dapm_widgets = ad1980_dapm_widgets, |
295 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), | 317 | .num_dapm_widgets = ARRAY_SIZE(ad1980_dapm_widgets), |
296 | .dapm_routes = ad1980_dapm_routes, | 318 | .dapm_routes = ad1980_dapm_routes, |
diff --git a/sound/soc/codecs/ad1980.h b/sound/soc/codecs/ad1980.h deleted file mode 100644 index eb0af44ad3df..000000000000 --- a/sound/soc/codecs/ad1980.h +++ /dev/null | |||
@@ -1,26 +0,0 @@ | |||
1 | /* | ||
2 | * ad1980.h -- ad1980 Soc Audio driver | ||
3 | * | ||
4 | * WARNING: | ||
5 | * | ||
6 | * Because Analog Devices Inc. discontinued the ad1980 sound chip since | ||
7 | * Sep. 2009, this ad1980 driver is not maintained, tested and supported | ||
8 | * by ADI now. | ||
9 | */ | ||
10 | |||
11 | #ifndef _AD1980_H | ||
12 | #define _AD1980_H | ||
13 | /* Bit definition of Power-Down Control/Status Register */ | ||
14 | #define ADC 0x0001 | ||
15 | #define DAC 0x0002 | ||
16 | #define ANL 0x0004 | ||
17 | #define REF 0x0008 | ||
18 | #define PR0 0x0100 | ||
19 | #define PR1 0x0200 | ||
20 | #define PR2 0x0400 | ||
21 | #define PR3 0x0800 | ||
22 | #define PR4 0x1000 | ||
23 | #define PR5 0x2000 | ||
24 | #define PR6 0x4000 | ||
25 | |||
26 | #endif | ||
diff --git a/sound/soc/codecs/adau1373.c b/sound/soc/codecs/adau1373.c index 7c784ad3e8b2..783dcb57043a 100644 --- a/sound/soc/codecs/adau1373.c +++ b/sound/soc/codecs/adau1373.c | |||
@@ -551,7 +551,7 @@ static const struct snd_kcontrol_new adau1373_drc_controls[] = { | |||
551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, | 551 | static int adau1373_pll_event(struct snd_soc_dapm_widget *w, |
552 | struct snd_kcontrol *kcontrol, int event) | 552 | struct snd_kcontrol *kcontrol, int event) |
553 | { | 553 | { |
554 | struct snd_soc_codec *codec = w->codec; | 554 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 555 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
556 | unsigned int pll_id = w->name[3] - '1'; | 556 | unsigned int pll_id = w->name[3] - '1'; |
557 | unsigned int val; | 557 | unsigned int val; |
@@ -823,7 +823,7 @@ static const struct snd_soc_dapm_widget adau1373_dapm_widgets[] = { | |||
823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | 823 | static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, |
824 | struct snd_soc_dapm_widget *sink) | 824 | struct snd_soc_dapm_widget *sink) |
825 | { | 825 | { |
826 | struct snd_soc_codec *codec = source->codec; | 826 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 827 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
828 | unsigned int dai; | 828 | unsigned int dai; |
829 | const char *clk; | 829 | const char *clk; |
@@ -844,7 +844,7 @@ static int adau1373_check_aif_clk(struct snd_soc_dapm_widget *source, | |||
844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, | 844 | static int adau1373_check_src(struct snd_soc_dapm_widget *source, |
845 | struct snd_soc_dapm_widget *sink) | 845 | struct snd_soc_dapm_widget *sink) |
846 | { | 846 | { |
847 | struct snd_soc_codec *codec = source->codec; | 847 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(source->dapm); |
848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); | 848 | struct adau1373 *adau1373 = snd_soc_codec_get_drvdata(codec); |
849 | unsigned int dai; | 849 | unsigned int dai; |
850 | 850 | ||
diff --git a/sound/soc/codecs/adau1761.c b/sound/soc/codecs/adau1761.c index 91f60282fd2f..16093dc89441 100644 --- a/sound/soc/codecs/adau1761.c +++ b/sound/soc/codecs/adau1761.c | |||
@@ -255,7 +255,8 @@ static const struct snd_kcontrol_new adau1761_input_mux_control = | |||
255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, | 255 | static int adau1761_dejitter_fixup(struct snd_soc_dapm_widget *w, |
256 | struct snd_kcontrol *kcontrol, int event) | 256 | struct snd_kcontrol *kcontrol, int event) |
257 | { | 257 | { |
258 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 258 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
259 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
259 | 260 | ||
260 | /* After any power changes have been made the dejitter circuit | 261 | /* After any power changes have been made the dejitter circuit |
261 | * has to be reinitialized. */ | 262 | * has to be reinitialized. */ |
diff --git a/sound/soc/codecs/adau1781.c b/sound/soc/codecs/adau1781.c index e9fc00fb13dd..aa6a37cc44b7 100644 --- a/sound/soc/codecs/adau1781.c +++ b/sound/soc/codecs/adau1781.c | |||
@@ -174,7 +174,7 @@ static const struct snd_kcontrol_new adau1781_mono_mixer_controls[] = { | |||
174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, | 174 | static int adau1781_dejitter_fixup(struct snd_soc_dapm_widget *w, |
175 | struct snd_kcontrol *kcontrol, int event) | 175 | struct snd_kcontrol *kcontrol, int event) |
176 | { | 176 | { |
177 | struct snd_soc_codec *codec = w->codec; | 177 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | 178 | struct adau *adau = snd_soc_codec_get_drvdata(codec); |
179 | 179 | ||
180 | /* After any power changes have been made the dejitter circuit | 180 | /* After any power changes have been made the dejitter circuit |
diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 3e16c1c64115..427ad77bfe56 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c | |||
@@ -61,7 +61,8 @@ static const struct snd_kcontrol_new adau17x1_controls[] = { | |||
61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, | 61 | static int adau17x1_pll_event(struct snd_soc_dapm_widget *w, |
62 | struct snd_kcontrol *kcontrol, int event) | 62 | struct snd_kcontrol *kcontrol, int event) |
63 | { | 63 | { |
64 | struct adau *adau = snd_soc_codec_get_drvdata(w->codec); | 64 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm); |
65 | struct adau *adau = snd_soc_codec_get_drvdata(codec); | ||
65 | int ret; | 66 | int ret; |
66 | 67 | ||
67 | if (SND_SOC_DAPM_EVENT_ON(event)) { | 68 | if (SND_SOC_DAPM_EVENT_ON(event)) { |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 53b810d23fea..f37a79ec45e6 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -139,18 +139,19 @@ static const struct snd_kcontrol_new stac9766_snd_ac97_controls[] = { | |||
139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 139 | static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
140 | unsigned int val) | 140 | unsigned int val) |
141 | { | 141 | { |
142 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
142 | u16 *cache = codec->reg_cache; | 143 | u16 *cache = codec->reg_cache; |
143 | 144 | ||
144 | if (reg > AC97_STAC_PAGE0) { | 145 | if (reg > AC97_STAC_PAGE0) { |
145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 146 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
146 | soc_ac97_ops->write(codec->ac97, reg, val); | 147 | soc_ac97_ops->write(ac97, reg, val); |
147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 148 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
148 | return 0; | 149 | return 0; |
149 | } | 150 | } |
150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 151 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
151 | return -EIO; | 152 | return -EIO; |
152 | 153 | ||
153 | soc_ac97_ops->write(codec->ac97, reg, val); | 154 | soc_ac97_ops->write(ac97, reg, val); |
154 | cache[reg / 2] = val; | 155 | cache[reg / 2] = val; |
155 | return 0; | 156 | return 0; |
156 | } | 157 | } |
@@ -158,11 +159,12 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
158 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | 159 | static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, |
159 | unsigned int reg) | 160 | unsigned int reg) |
160 | { | 161 | { |
162 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
161 | u16 val = 0, *cache = codec->reg_cache; | 163 | u16 val = 0, *cache = codec->reg_cache; |
162 | 164 | ||
163 | if (reg > AC97_STAC_PAGE0) { | 165 | if (reg > AC97_STAC_PAGE0) { |
164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); | 167 | val = soc_ac97_ops->read(ac97, reg - AC97_STAC_PAGE0); |
166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
167 | return val; | 169 | return val; |
168 | } | 170 | } |
@@ -173,7 +175,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
174 | reg == AC97_VENDOR_ID2) { | 176 | reg == AC97_VENDOR_ID2) { |
175 | 177 | ||
176 | val = soc_ac97_ops->read(codec->ac97, reg); | 178 | val = soc_ac97_ops->read(ac97, reg); |
177 | return val; | 179 | return val; |
178 | } | 180 | } |
179 | return cache[reg / 2]; | 181 | return cache[reg / 2]; |
@@ -240,15 +242,17 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
240 | 242 | ||
241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
242 | { | 244 | { |
245 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
246 | |||
243 | if (try_warm && soc_ac97_ops->warm_reset) { | 247 | if (try_warm && soc_ac97_ops->warm_reset) { |
244 | soc_ac97_ops->warm_reset(codec->ac97); | 248 | soc_ac97_ops->warm_reset(ac97); |
245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 249 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
246 | return 1; | 250 | return 1; |
247 | } | 251 | } |
248 | 252 | ||
249 | soc_ac97_ops->reset(codec->ac97); | 253 | soc_ac97_ops->reset(ac97); |
250 | if (soc_ac97_ops->warm_reset) | 254 | if (soc_ac97_ops->warm_reset) |
251 | soc_ac97_ops->warm_reset(codec->ac97); | 255 | soc_ac97_ops->warm_reset(ac97); |
252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 256 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
253 | return -EIO; | 257 | return -EIO; |
254 | return 0; | 258 | return 0; |
@@ -262,6 +266,7 @@ static int stac9766_codec_suspend(struct snd_soc_codec *codec) | |||
262 | 266 | ||
263 | static int stac9766_codec_resume(struct snd_soc_codec *codec) | 267 | static int stac9766_codec_resume(struct snd_soc_codec *codec) |
264 | { | 268 | { |
269 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
265 | u16 id, reset; | 270 | u16 id, reset; |
266 | 271 | ||
267 | reset = 0; | 272 | reset = 0; |
@@ -271,8 +276,8 @@ reset: | |||
271 | printk(KERN_ERR "stac9766 failed to resume"); | 276 | printk(KERN_ERR "stac9766 failed to resume"); |
272 | return -EIO; | 277 | return -EIO; |
273 | } | 278 | } |
274 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 279 | ac97->bus->ops->warm_reset(ac97); |
275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); | 280 | id = soc_ac97_ops->read(ac97, AC97_VENDOR_ID2); |
276 | if (id != 0x4c13) { | 281 | if (id != 0x4c13) { |
277 | stac9766_reset(codec, 0); | 282 | stac9766_reset(codec, 0); |
278 | reset++; | 283 | reset++; |
@@ -294,7 +299,6 @@ static const struct snd_soc_dai_ops stac9766_dai_ops_digital = { | |||
294 | static struct snd_soc_dai_driver stac9766_dai[] = { | 299 | static struct snd_soc_dai_driver stac9766_dai[] = { |
295 | { | 300 | { |
296 | .name = "stac9766-hifi-analog", | 301 | .name = "stac9766-hifi-analog", |
297 | .ac97_control = 1, | ||
298 | 302 | ||
299 | /* stream cababilities */ | 303 | /* stream cababilities */ |
300 | .playback = { | 304 | .playback = { |
@@ -316,7 +320,6 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
316 | }, | 320 | }, |
317 | { | 321 | { |
318 | .name = "stac9766-hifi-IEC958", | 322 | .name = "stac9766-hifi-IEC958", |
319 | .ac97_control = 1, | ||
320 | 323 | ||
321 | /* stream cababilities */ | 324 | /* stream cababilities */ |
322 | .playback = { | 325 | .playback = { |
@@ -334,11 +337,14 @@ static struct snd_soc_dai_driver stac9766_dai[] = { | |||
334 | 337 | ||
335 | static int stac9766_codec_probe(struct snd_soc_codec *codec) | 338 | static int stac9766_codec_probe(struct snd_soc_codec *codec) |
336 | { | 339 | { |
340 | struct snd_ac97 *ac97; | ||
337 | int ret = 0; | 341 | int ret = 0; |
338 | 342 | ||
339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 343 | ac97 = snd_soc_new_ac97_codec(codec); |
340 | if (ret < 0) | 344 | if (IS_ERR(ac97)) |
341 | goto codec_err; | 345 | return PTR_ERR(ac97); |
346 | |||
347 | snd_soc_codec_set_drvdata(codec, ac97); | ||
342 | 348 | ||
343 | /* do a cold reset for the controller and then try | 349 | /* do a cold reset for the controller and then try |
344 | * a warm reset followed by an optional cold reset for codec */ | 350 | * a warm reset followed by an optional cold reset for codec */ |
@@ -357,13 +363,15 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
357 | return 0; | 363 | return 0; |
358 | 364 | ||
359 | codec_err: | 365 | codec_err: |
360 | snd_soc_free_ac97_codec(codec); | 366 | snd_soc_free_ac97_codec(ac97); |
361 | return ret; | 367 | return ret; |
362 | } | 368 | } |
363 | 369 | ||
364 | static int stac9766_codec_remove(struct snd_soc_codec *codec) | 370 | static int stac9766_codec_remove(struct snd_soc_codec *codec) |
365 | { | 371 | { |
366 | snd_soc_free_ac97_codec(codec); | 372 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
373 | |||
374 | snd_soc_free_ac97_codec(ac97); | ||
367 | return 0; | 375 | return 0; |
368 | } | 376 | } |
369 | 377 | ||
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index c0b7f45dfa37..d3a800fa6f06 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -203,13 +203,14 @@ static const struct snd_soc_dapm_route wm9705_audio_map[] = { | |||
203 | /* We use a register cache to enhance read performance. */ | 203 | /* We use a register cache to enhance read performance. */ |
204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | 204 | static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) |
205 | { | 205 | { |
206 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
206 | u16 *cache = codec->reg_cache; | 207 | u16 *cache = codec->reg_cache; |
207 | 208 | ||
208 | switch (reg) { | 209 | switch (reg) { |
209 | case AC97_RESET: | 210 | case AC97_RESET: |
210 | case AC97_VENDOR_ID1: | 211 | case AC97_VENDOR_ID1: |
211 | case AC97_VENDOR_ID2: | 212 | case AC97_VENDOR_ID2: |
212 | return soc_ac97_ops->read(codec->ac97, reg); | 213 | return soc_ac97_ops->read(ac97, reg); |
213 | default: | 214 | default: |
214 | reg = reg >> 1; | 215 | reg = reg >> 1; |
215 | 216 | ||
@@ -223,9 +224,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
223 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 224 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
224 | unsigned int val) | 225 | unsigned int val) |
225 | { | 226 | { |
227 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
226 | u16 *cache = codec->reg_cache; | 228 | u16 *cache = codec->reg_cache; |
227 | 229 | ||
228 | soc_ac97_ops->write(codec->ac97, reg, val); | 230 | soc_ac97_ops->write(ac97, reg, val); |
229 | reg = reg >> 1; | 231 | reg = reg >> 1; |
230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 232 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | cache[reg] = val; | 233 | cache[reg] = val; |
@@ -263,7 +265,6 @@ static const struct snd_soc_dai_ops wm9705_dai_ops = { | |||
263 | static struct snd_soc_dai_driver wm9705_dai[] = { | 265 | static struct snd_soc_dai_driver wm9705_dai[] = { |
264 | { | 266 | { |
265 | .name = "wm9705-hifi", | 267 | .name = "wm9705-hifi", |
266 | .ac97_control = 1, | ||
267 | .playback = { | 268 | .playback = { |
268 | .stream_name = "HiFi Playback", | 269 | .stream_name = "HiFi Playback", |
269 | .channels_min = 1, | 270 | .channels_min = 1, |
@@ -294,36 +295,41 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
294 | 295 | ||
295 | static int wm9705_reset(struct snd_soc_codec *codec) | 296 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | { | 297 | { |
298 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
299 | |||
297 | if (soc_ac97_ops->reset) { | 300 | if (soc_ac97_ops->reset) { |
298 | soc_ac97_ops->reset(codec->ac97); | 301 | soc_ac97_ops->reset(ac97); |
299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 302 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | return 0; /* Success */ | 303 | return 0; /* Success */ |
301 | } | 304 | } |
302 | 305 | ||
306 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
307 | |||
303 | return -EIO; | 308 | return -EIO; |
304 | } | 309 | } |
305 | 310 | ||
306 | #ifdef CONFIG_PM | 311 | #ifdef CONFIG_PM |
307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 312 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
308 | { | 313 | { |
309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); | 314 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
315 | |||
316 | soc_ac97_ops->write(ac97, AC97_POWERDOWN, 0xffff); | ||
310 | 317 | ||
311 | return 0; | 318 | return 0; |
312 | } | 319 | } |
313 | 320 | ||
314 | static int wm9705_soc_resume(struct snd_soc_codec *codec) | 321 | static int wm9705_soc_resume(struct snd_soc_codec *codec) |
315 | { | 322 | { |
323 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); | ||
316 | int i, ret; | 324 | int i, ret; |
317 | u16 *cache = codec->reg_cache; | 325 | u16 *cache = codec->reg_cache; |
318 | 326 | ||
319 | ret = wm9705_reset(codec); | 327 | ret = wm9705_reset(codec); |
320 | if (ret < 0) { | 328 | if (ret < 0) |
321 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
322 | return ret; | 329 | return ret; |
323 | } | ||
324 | 330 | ||
325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 331 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 332 | soc_ac97_ops->write(ac97, i, cache[i>>1]); |
327 | } | 333 | } |
328 | 334 | ||
329 | return 0; | 335 | return 0; |
@@ -335,31 +341,34 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
335 | 341 | ||
336 | static int wm9705_soc_probe(struct snd_soc_codec *codec) | 342 | static int wm9705_soc_probe(struct snd_soc_codec *codec) |
337 | { | 343 | { |
344 | struct snd_ac97 *ac97; | ||
338 | int ret = 0; | 345 | int ret = 0; |
339 | 346 | ||
340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 347 | ac97 = snd_soc_new_ac97_codec(codec); |
341 | if (ret < 0) { | 348 | if (IS_ERR(ac97)) { |
342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 349 | ret = PTR_ERR(ac97); |
350 | dev_err(codec->dev, "Failed to register AC97 codec\n"); | ||
343 | return ret; | 351 | return ret; |
344 | } | 352 | } |
345 | 353 | ||
354 | snd_soc_codec_set_drvdata(codec, ac97); | ||
355 | |||
346 | ret = wm9705_reset(codec); | 356 | ret = wm9705_reset(codec); |
347 | if (ret) | 357 | if (ret) |
348 | goto reset_err; | 358 | goto reset_err; |
349 | 359 | ||
350 | snd_soc_add_codec_controls(codec, wm9705_snd_ac97_controls, | ||
351 | ARRAY_SIZE(wm9705_snd_ac97_controls)); | ||
352 | |||
353 | return 0; | 360 | return 0; |
354 | 361 | ||
355 | reset_err: | 362 | reset_err: |
356 | snd_soc_free_ac97_codec(codec); | 363 | snd_soc_free_ac97_codec(ac97); |
357 | return ret; | 364 | return ret; |
358 | } | 365 | } |
359 | 366 | ||
360 | static int wm9705_soc_remove(struct snd_soc_codec *codec) | 367 | static int wm9705_soc_remove(struct snd_soc_codec *codec) |
361 | { | 368 | { |
362 | snd_soc_free_ac97_codec(codec); | 369 | struct snd_ac97 *ac97 = snd_soc_codec_get_drvdata(codec); |
370 | |||
371 | snd_soc_free_ac97_codec(ac97); | ||
363 | return 0; | 372 | return 0; |
364 | } | 373 | } |
365 | 374 | ||
@@ -374,6 +383,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9705 = { | |||
374 | .reg_word_size = sizeof(u16), | 383 | .reg_word_size = sizeof(u16), |
375 | .reg_cache_step = 2, | 384 | .reg_cache_step = 2, |
376 | .reg_cache_default = wm9705_reg, | 385 | .reg_cache_default = wm9705_reg, |
386 | |||
387 | .controls = wm9705_snd_ac97_controls, | ||
388 | .num_controls = ARRAY_SIZE(wm9705_snd_ac97_controls), | ||
377 | .dapm_widgets = wm9705_dapm_widgets, | 389 | .dapm_widgets = wm9705_dapm_widgets, |
378 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), | 390 | .num_dapm_widgets = ARRAY_SIZE(wm9705_dapm_widgets), |
379 | .dapm_routes = wm9705_audio_map, | 391 | .dapm_routes = wm9705_audio_map, |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index c5eb746087b4..52a211be5b47 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -23,6 +23,12 @@ | |||
23 | #include <sound/tlv.h> | 23 | #include <sound/tlv.h> |
24 | #include "wm9712.h" | 24 | #include "wm9712.h" |
25 | 25 | ||
26 | struct wm9712_priv { | ||
27 | struct snd_ac97 *ac97; | ||
28 | unsigned int hp_mixer[2]; | ||
29 | struct mutex lock; | ||
30 | }; | ||
31 | |||
26 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 32 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
27 | unsigned int reg); | 33 | unsigned int reg); |
28 | static int ac97_write(struct snd_soc_codec *codec, | 34 | static int ac97_write(struct snd_soc_codec *codec, |
@@ -48,12 +54,10 @@ static const u16 wm9712_reg[] = { | |||
48 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ | 54 | 0x0000, 0x0000, 0x0000, 0x0000, /* 6e */ |
49 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ | 55 | 0x0000, 0x0000, 0x0000, 0x0006, /* 76 */ |
50 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ | 56 | 0x0001, 0x0000, 0x574d, 0x4c12, /* 7e */ |
51 | 0x0000, 0x0000 /* virtual hp mixers */ | ||
52 | }; | 57 | }; |
53 | 58 | ||
54 | /* virtual HP mixers regs */ | 59 | #define HPL_MIXER 0x0 |
55 | #define HPL_MIXER 0x80 | 60 | #define HPR_MIXER 0x1 |
56 | #define HPR_MIXER 0x82 | ||
57 | 61 | ||
58 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; | 62 | static const char *wm9712_alc_select[] = {"None", "Left", "Right", "Stereo"}; |
59 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; | 63 | static const char *wm9712_alc_mux[] = {"Stereo", "Left", "Right", "None"}; |
@@ -157,75 +161,108 @@ SOC_SINGLE_TLV("Mic 2 Volume", AC97_MIC, 0, 31, 1, main_tlv), | |||
157 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), | 161 | SOC_SINGLE_TLV("Mic Boost Volume", AC97_MIC, 7, 1, 0, boost_tlv), |
158 | }; | 162 | }; |
159 | 163 | ||
164 | static const unsigned int wm9712_mixer_mute_regs[] = { | ||
165 | AC97_VIDEO, | ||
166 | AC97_PCM, | ||
167 | AC97_LINE, | ||
168 | AC97_PHONE, | ||
169 | AC97_CD, | ||
170 | AC97_PC_BEEP, | ||
171 | }; | ||
172 | |||
160 | /* We have to create a fake left and right HP mixers because | 173 | /* We have to create a fake left and right HP mixers because |
161 | * the codec only has a single control that is shared by both channels. | 174 | * the codec only has a single control that is shared by both channels. |
162 | * This makes it impossible to determine the audio path. | 175 | * This makes it impossible to determine the audio path. |
163 | */ | 176 | */ |
164 | static int mixer_event(struct snd_soc_dapm_widget *w, | 177 | static int wm9712_hp_mixer_put(struct snd_kcontrol *kcontrol, |
165 | struct snd_kcontrol *k, int event) | 178 | struct snd_ctl_elem_value *ucontrol) |
166 | { | 179 | { |
167 | u16 l, r, beep, line, phone, mic, pcm, aux; | 180 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
168 | 181 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
169 | l = ac97_read(w->codec, HPL_MIXER); | 182 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
170 | r = ac97_read(w->codec, HPR_MIXER); | 183 | unsigned int val = ucontrol->value.enumerated.item[0]; |
171 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 184 | struct soc_mixer_control *mc = |
172 | mic = ac97_read(w->codec, AC97_VIDEO); | 185 | (struct soc_mixer_control *)kcontrol->private_value; |
173 | phone = ac97_read(w->codec, AC97_PHONE); | 186 | unsigned int mixer, mask, shift, old; |
174 | line = ac97_read(w->codec, AC97_LINE); | 187 | struct snd_soc_dapm_update update; |
175 | pcm = ac97_read(w->codec, AC97_PCM); | 188 | bool change; |
176 | aux = ac97_read(w->codec, AC97_CD); | 189 | |
177 | 190 | mixer = mc->shift >> 8; | |
178 | if (l & 0x1 || r & 0x1) | 191 | shift = mc->shift & 0xff; |
179 | ac97_write(w->codec, AC97_VIDEO, mic & 0x7fff); | 192 | mask = 1 << shift; |
193 | |||
194 | mutex_lock(&wm9712->lock); | ||
195 | old = wm9712->hp_mixer[mixer]; | ||
196 | if (ucontrol->value.enumerated.item[0]) | ||
197 | wm9712->hp_mixer[mixer] |= mask; | ||
180 | else | 198 | else |
181 | ac97_write(w->codec, AC97_VIDEO, mic | 0x8000); | 199 | wm9712->hp_mixer[mixer] &= ~mask; |
200 | |||
201 | change = old != wm9712->hp_mixer[mixer]; | ||
202 | if (change) { | ||
203 | update.kcontrol = kcontrol; | ||
204 | update.reg = wm9712_mixer_mute_regs[shift]; | ||
205 | update.mask = 0x8000; | ||
206 | if ((wm9712->hp_mixer[0] & mask) || | ||
207 | (wm9712->hp_mixer[1] & mask)) | ||
208 | update.val = 0x0; | ||
209 | else | ||
210 | update.val = 0x8000; | ||
211 | |||
212 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
213 | &update); | ||
214 | } | ||
182 | 215 | ||
183 | if (l & 0x2 || r & 0x2) | 216 | mutex_unlock(&wm9712->lock); |
184 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | ||
185 | else | ||
186 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
187 | 217 | ||
188 | if (l & 0x4 || r & 0x4) | 218 | return change; |
189 | ac97_write(w->codec, AC97_LINE, line & 0x7fff); | 219 | } |
190 | else | ||
191 | ac97_write(w->codec, AC97_LINE, line | 0x8000); | ||
192 | 220 | ||
193 | if (l & 0x8 || r & 0x8) | 221 | static int wm9712_hp_mixer_get(struct snd_kcontrol *kcontrol, |
194 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 222 | struct snd_ctl_elem_value *ucontrol) |
195 | else | 223 | { |
196 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | 224 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
225 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
226 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
227 | struct soc_mixer_control *mc = | ||
228 | (struct soc_mixer_control *)kcontrol->private_value; | ||
229 | unsigned int shift, mixer; | ||
197 | 230 | ||
198 | if (l & 0x10 || r & 0x10) | 231 | mixer = mc->shift >> 8; |
199 | ac97_write(w->codec, AC97_CD, aux & 0x7fff); | 232 | shift = mc->shift & 0xff; |
200 | else | ||
201 | ac97_write(w->codec, AC97_CD, aux | 0x8000); | ||
202 | 233 | ||
203 | if (l & 0x20 || r & 0x20) | 234 | ucontrol->value.enumerated.item[0] = |
204 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 235 | (wm9712->hp_mixer[mixer] >> shift) & 1; |
205 | else | ||
206 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | ||
207 | 236 | ||
208 | return 0; | 237 | return 0; |
209 | } | 238 | } |
210 | 239 | ||
240 | #define WM9712_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
241 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
242 | .info = snd_soc_info_volsw, \ | ||
243 | .get = wm9712_hp_mixer_get, .put = wm9712_hp_mixer_put, \ | ||
244 | .private_value = SOC_SINGLE_VALUE(SND_SOC_NOPM, \ | ||
245 | (xmixer << 8) | xshift, 1, 0, 0) \ | ||
246 | } | ||
247 | |||
211 | /* Left Headphone Mixers */ | 248 | /* Left Headphone Mixers */ |
212 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { | 249 | static const struct snd_kcontrol_new wm9712_hpl_mixer_controls[] = { |
213 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPL_MIXER, 5, 1, 0), | 250 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPL_MIXER, 5), |
214 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 4, 1, 0), | 251 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 4), |
215 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPL_MIXER, 3, 1, 0), | 252 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPL_MIXER, 3), |
216 | SOC_DAPM_SINGLE("Line Bypass Switch", HPL_MIXER, 2, 1, 0), | 253 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPL_MIXER, 2), |
217 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 1, 1, 0), | 254 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 1), |
218 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPL_MIXER, 0, 1, 0), | 255 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPL_MIXER, 0), |
219 | }; | 256 | }; |
220 | 257 | ||
221 | /* Right Headphone Mixers */ | 258 | /* Right Headphone Mixers */ |
222 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { | 259 | static const struct snd_kcontrol_new wm9712_hpr_mixer_controls[] = { |
223 | SOC_DAPM_SINGLE("PCBeep Bypass Switch", HPR_MIXER, 5, 1, 0), | 260 | WM9712_HP_MIXER_CTRL("PCBeep Bypass Switch", HPR_MIXER, 5), |
224 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 4, 1, 0), | 261 | WM9712_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 4), |
225 | SOC_DAPM_SINGLE("Phone Bypass Switch", HPR_MIXER, 3, 1, 0), | 262 | WM9712_HP_MIXER_CTRL("Phone Bypass Switch", HPR_MIXER, 3), |
226 | SOC_DAPM_SINGLE("Line Bypass Switch", HPR_MIXER, 2, 1, 0), | 263 | WM9712_HP_MIXER_CTRL("Line Bypass Switch", HPR_MIXER, 2), |
227 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 1, 1, 0), | 264 | WM9712_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 1), |
228 | SOC_DAPM_SINGLE("Mic Sidetone Switch", HPR_MIXER, 0, 1, 0), | 265 | WM9712_HP_MIXER_CTRL("Mic Sidetone Switch", HPR_MIXER, 0), |
229 | }; | 266 | }; |
230 | 267 | ||
231 | /* Speaker Mixer */ | 268 | /* Speaker Mixer */ |
@@ -299,12 +336,10 @@ SND_SOC_DAPM_MUX("Right Mic Select Source", SND_SOC_NOPM, 0, 0, | |||
299 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, | 336 | SND_SOC_DAPM_MUX("Differential Source", SND_SOC_NOPM, 0, 0, |
300 | &wm9712_diff_sel_controls), | 337 | &wm9712_diff_sel_controls), |
301 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), | 338 | SND_SOC_DAPM_MIXER("AC97 Mixer", SND_SOC_NOPM, 0, 0, NULL, 0), |
302 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_INT_PAGING, 9, 1, | 339 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_INT_PAGING, 9, 1, |
303 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls), | 340 | &wm9712_hpl_mixer_controls[0], ARRAY_SIZE(wm9712_hpl_mixer_controls)), |
304 | mixer_event, SND_SOC_DAPM_POST_REG), | 341 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_INT_PAGING, 8, 1, |
305 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_INT_PAGING, 8, 1, | 342 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls)), |
306 | &wm9712_hpr_mixer_controls[0], ARRAY_SIZE(wm9712_hpr_mixer_controls), | ||
307 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
308 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, | 343 | SND_SOC_DAPM_MIXER("Phone Mixer", AC97_INT_PAGING, 6, 1, |
309 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), | 344 | &wm9712_phone_mixer_controls[0], ARRAY_SIZE(wm9712_phone_mixer_controls)), |
310 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, | 345 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_INT_PAGING, 7, 1, |
@@ -450,12 +485,13 @@ static const struct snd_soc_dapm_route wm9712_audio_map[] = { | |||
450 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 485 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
451 | unsigned int reg) | 486 | unsigned int reg) |
452 | { | 487 | { |
488 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
453 | u16 *cache = codec->reg_cache; | 489 | u16 *cache = codec->reg_cache; |
454 | 490 | ||
455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 491 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 492 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | reg == AC97_REC_GAIN) | 493 | reg == AC97_REC_GAIN) |
458 | return soc_ac97_ops->read(codec->ac97, reg); | 494 | return soc_ac97_ops->read(wm9712->ac97, reg); |
459 | else { | 495 | else { |
460 | reg = reg >> 1; | 496 | reg = reg >> 1; |
461 | 497 | ||
@@ -469,10 +505,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
469 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 505 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
470 | unsigned int val) | 506 | unsigned int val) |
471 | { | 507 | { |
508 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
472 | u16 *cache = codec->reg_cache; | 509 | u16 *cache = codec->reg_cache; |
473 | 510 | ||
474 | if (reg < 0x7c) | 511 | soc_ac97_ops->write(wm9712->ac97, reg, val); |
475 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
476 | reg = reg >> 1; | 512 | reg = reg >> 1; |
477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 513 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | cache[reg] = val; | 514 | cache[reg] = val; |
@@ -532,7 +568,6 @@ static const struct snd_soc_dai_ops wm9712_dai_ops_aux = { | |||
532 | static struct snd_soc_dai_driver wm9712_dai[] = { | 568 | static struct snd_soc_dai_driver wm9712_dai[] = { |
533 | { | 569 | { |
534 | .name = "wm9712-hifi", | 570 | .name = "wm9712-hifi", |
535 | .ac97_control = 1, | ||
536 | .playback = { | 571 | .playback = { |
537 | .stream_name = "HiFi Playback", | 572 | .stream_name = "HiFi Playback", |
538 | .channels_min = 1, | 573 | .channels_min = 1, |
@@ -581,21 +616,23 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
581 | 616 | ||
582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 617 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | { | 618 | { |
619 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
620 | |||
584 | if (try_warm && soc_ac97_ops->warm_reset) { | 621 | if (try_warm && soc_ac97_ops->warm_reset) { |
585 | soc_ac97_ops->warm_reset(codec->ac97); | 622 | soc_ac97_ops->warm_reset(wm9712->ac97); |
586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 623 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | return 1; | 624 | return 1; |
588 | } | 625 | } |
589 | 626 | ||
590 | soc_ac97_ops->reset(codec->ac97); | 627 | soc_ac97_ops->reset(wm9712->ac97); |
591 | if (soc_ac97_ops->warm_reset) | 628 | if (soc_ac97_ops->warm_reset) |
592 | soc_ac97_ops->warm_reset(codec->ac97); | 629 | soc_ac97_ops->warm_reset(wm9712->ac97); |
593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 630 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | goto err; | 631 | goto err; |
595 | return 0; | 632 | return 0; |
596 | 633 | ||
597 | err: | 634 | err: |
598 | printk(KERN_ERR "WM9712 AC97 reset failed\n"); | 635 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); |
599 | return -EIO; | 636 | return -EIO; |
600 | } | 637 | } |
601 | 638 | ||
@@ -607,14 +644,13 @@ static int wm9712_soc_suspend(struct snd_soc_codec *codec) | |||
607 | 644 | ||
608 | static int wm9712_soc_resume(struct snd_soc_codec *codec) | 645 | static int wm9712_soc_resume(struct snd_soc_codec *codec) |
609 | { | 646 | { |
647 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
610 | int i, ret; | 648 | int i, ret; |
611 | u16 *cache = codec->reg_cache; | 649 | u16 *cache = codec->reg_cache; |
612 | 650 | ||
613 | ret = wm9712_reset(codec, 1); | 651 | ret = wm9712_reset(codec, 1); |
614 | if (ret < 0) { | 652 | if (ret < 0) |
615 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
616 | return ret; | 653 | return ret; |
617 | } | ||
618 | 654 | ||
619 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 655 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
620 | 656 | ||
@@ -624,7 +660,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 660 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | (i > 0x58 && i != 0x5c)) | 661 | (i > 0x58 && i != 0x5c)) |
626 | continue; | 662 | continue; |
627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 663 | soc_ac97_ops->write(wm9712->ac97, i, cache[i>>1]); |
628 | } | 664 | } |
629 | } | 665 | } |
630 | 666 | ||
@@ -633,37 +669,37 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
633 | 669 | ||
634 | static int wm9712_soc_probe(struct snd_soc_codec *codec) | 670 | static int wm9712_soc_probe(struct snd_soc_codec *codec) |
635 | { | 671 | { |
672 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); | ||
636 | int ret = 0; | 673 | int ret = 0; |
637 | 674 | ||
638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | 675 | wm9712->ac97 = snd_soc_new_ac97_codec(codec); |
639 | if (ret < 0) { | 676 | if (IS_ERR(wm9712->ac97)) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 677 | ret = PTR_ERR(wm9712->ac97); |
678 | dev_err(codec->dev, "Failed to register AC97 codec: %d\n", ret); | ||
641 | return ret; | 679 | return ret; |
642 | } | 680 | } |
643 | 681 | ||
644 | ret = wm9712_reset(codec, 0); | 682 | ret = wm9712_reset(codec, 0); |
645 | if (ret < 0) { | 683 | if (ret < 0) |
646 | printk(KERN_ERR "Failed to reset WM9712: AC97 link error\n"); | ||
647 | goto reset_err; | 684 | goto reset_err; |
648 | } | ||
649 | 685 | ||
650 | /* set alc mux to none */ | 686 | /* set alc mux to none */ |
651 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); | 687 | ac97_write(codec, AC97_VIDEO, ac97_read(codec, AC97_VIDEO) | 0x3000); |
652 | 688 | ||
653 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 689 | wm9712_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
654 | snd_soc_add_codec_controls(codec, wm9712_snd_ac97_controls, | ||
655 | ARRAY_SIZE(wm9712_snd_ac97_controls)); | ||
656 | 690 | ||
657 | return 0; | 691 | return 0; |
658 | 692 | ||
659 | reset_err: | 693 | reset_err: |
660 | snd_soc_free_ac97_codec(codec); | 694 | snd_soc_free_ac97_codec(wm9712->ac97); |
661 | return ret; | 695 | return ret; |
662 | } | 696 | } |
663 | 697 | ||
664 | static int wm9712_soc_remove(struct snd_soc_codec *codec) | 698 | static int wm9712_soc_remove(struct snd_soc_codec *codec) |
665 | { | 699 | { |
666 | snd_soc_free_ac97_codec(codec); | 700 | struct wm9712_priv *wm9712 = snd_soc_codec_get_drvdata(codec); |
701 | |||
702 | snd_soc_free_ac97_codec(wm9712->ac97); | ||
667 | return 0; | 703 | return 0; |
668 | } | 704 | } |
669 | 705 | ||
@@ -679,6 +715,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
679 | .reg_word_size = sizeof(u16), | 715 | .reg_word_size = sizeof(u16), |
680 | .reg_cache_step = 2, | 716 | .reg_cache_step = 2, |
681 | .reg_cache_default = wm9712_reg, | 717 | .reg_cache_default = wm9712_reg, |
718 | |||
719 | .controls = wm9712_snd_ac97_controls, | ||
720 | .num_controls = ARRAY_SIZE(wm9712_snd_ac97_controls), | ||
682 | .dapm_widgets = wm9712_dapm_widgets, | 721 | .dapm_widgets = wm9712_dapm_widgets, |
683 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), | 722 | .num_dapm_widgets = ARRAY_SIZE(wm9712_dapm_widgets), |
684 | .dapm_routes = wm9712_audio_map, | 723 | .dapm_routes = wm9712_audio_map, |
@@ -687,6 +726,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9712 = { | |||
687 | 726 | ||
688 | static int wm9712_probe(struct platform_device *pdev) | 727 | static int wm9712_probe(struct platform_device *pdev) |
689 | { | 728 | { |
729 | struct wm9712_priv *wm9712; | ||
730 | |||
731 | wm9712 = devm_kzalloc(&pdev->dev, sizeof(*wm9712), GFP_KERNEL); | ||
732 | if (wm9712 == NULL) | ||
733 | return -ENOMEM; | ||
734 | |||
735 | mutex_init(&wm9712->lock); | ||
736 | |||
737 | platform_set_drvdata(pdev, wm9712); | ||
738 | |||
690 | return snd_soc_register_codec(&pdev->dev, | 739 | return snd_soc_register_codec(&pdev->dev, |
691 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); | 740 | &soc_codec_dev_wm9712, wm9712_dai, ARRAY_SIZE(wm9712_dai)); |
692 | } | 741 | } |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index bddee30a4bc7..6c95d98b0eb1 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -30,7 +30,10 @@ | |||
30 | #include "wm9713.h" | 30 | #include "wm9713.h" |
31 | 31 | ||
32 | struct wm9713_priv { | 32 | struct wm9713_priv { |
33 | struct snd_ac97 *ac97; | ||
33 | u32 pll_in; /* PLL input frequency */ | 34 | u32 pll_in; /* PLL input frequency */ |
35 | unsigned int hp_mixer[2]; | ||
36 | struct mutex lock; | ||
34 | }; | 37 | }; |
35 | 38 | ||
36 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 39 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
@@ -59,13 +62,10 @@ static const u16 wm9713_reg[] = { | |||
59 | 0x0000, 0x0000, 0x0000, 0x0000, | 62 | 0x0000, 0x0000, 0x0000, 0x0000, |
60 | 0x0000, 0x0000, 0x0000, 0x0006, | 63 | 0x0000, 0x0000, 0x0000, 0x0006, |
61 | 0x0001, 0x0000, 0x574d, 0x4c13, | 64 | 0x0001, 0x0000, 0x574d, 0x4c13, |
62 | 0x0000, 0x0000, 0x0000 | ||
63 | }; | 65 | }; |
64 | 66 | ||
65 | /* virtual HP mixers regs */ | 67 | #define HPL_MIXER 0 |
66 | #define HPL_MIXER 0x80 | 68 | #define HPR_MIXER 1 |
67 | #define HPR_MIXER 0x82 | ||
68 | #define MICB_MUX 0x82 | ||
69 | 69 | ||
70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; | 70 | static const char *wm9713_mic_mixer[] = {"Stereo", "Mic 1", "Mic 2", "Mute"}; |
71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; | 71 | static const char *wm9713_rec_mux[] = {"Stereo", "Left", "Right", "Mute"}; |
@@ -110,7 +110,7 @@ SOC_ENUM_SINGLE(AC97_REC_GAIN_MIC, 10, 8, wm9713_dac_inv), /* dac invert 2 15 */ | |||
110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ | 110 | SOC_ENUM_SINGLE(AC97_GENERAL_PURPOSE, 15, 2, wm9713_bass), /* bass control 16 */ |
111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ | 111 | SOC_ENUM_SINGLE(AC97_PCI_SVID, 5, 2, wm9713_ng_type), /* noise gate type 17 */ |
112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ | 112 | SOC_ENUM_SINGLE(AC97_3D_CONTROL, 12, 3, wm9713_mic_select), /* mic selection 18 */ |
113 | SOC_ENUM_SINGLE(MICB_MUX, 0, 2, wm9713_micb_select), /* mic selection 19 */ | 113 | SOC_ENUM_SINGLE_VIRT(2, wm9713_micb_select), /* mic selection 19 */ |
114 | }; | 114 | }; |
115 | 115 | ||
116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); | 116 | static const DECLARE_TLV_DB_SCALE(out_tlv, -4650, 150, 0); |
@@ -234,6 +234,14 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
234 | return 0; | 234 | return 0; |
235 | } | 235 | } |
236 | 236 | ||
237 | static const unsigned int wm9713_mixer_mute_regs[] = { | ||
238 | AC97_PC_BEEP, | ||
239 | AC97_MASTER_TONE, | ||
240 | AC97_PHONE, | ||
241 | AC97_REC_SEL, | ||
242 | AC97_PCM, | ||
243 | AC97_AUX, | ||
244 | }; | ||
237 | 245 | ||
238 | /* We have to create a fake left and right HP mixers because | 246 | /* We have to create a fake left and right HP mixers because |
239 | * the codec only has a single control that is shared by both channels. | 247 | * the codec only has a single control that is shared by both channels. |
@@ -241,73 +249,95 @@ static int wm9713_voice_shutdown(struct snd_soc_dapm_widget *w, | |||
241 | * register map, thus we add a new (virtual) register to help determine the | 249 | * register map, thus we add a new (virtual) register to help determine the |
242 | * audio route within the device. | 250 | * audio route within the device. |
243 | */ | 251 | */ |
244 | static int mixer_event(struct snd_soc_dapm_widget *w, | 252 | static int wm9713_hp_mixer_put(struct snd_kcontrol *kcontrol, |
245 | struct snd_kcontrol *kcontrol, int event) | 253 | struct snd_ctl_elem_value *ucontrol) |
246 | { | 254 | { |
247 | u16 l, r, beep, tone, phone, rec, pcm, aux; | 255 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
248 | 256 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | |
249 | l = ac97_read(w->codec, HPL_MIXER); | 257 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
250 | r = ac97_read(w->codec, HPR_MIXER); | 258 | unsigned int val = ucontrol->value.enumerated.item[0]; |
251 | beep = ac97_read(w->codec, AC97_PC_BEEP); | 259 | struct soc_mixer_control *mc = |
252 | tone = ac97_read(w->codec, AC97_MASTER_TONE); | 260 | (struct soc_mixer_control *)kcontrol->private_value; |
253 | phone = ac97_read(w->codec, AC97_PHONE); | 261 | unsigned int mixer, mask, shift, old; |
254 | rec = ac97_read(w->codec, AC97_REC_SEL); | 262 | struct snd_soc_dapm_update update; |
255 | pcm = ac97_read(w->codec, AC97_PCM); | 263 | bool change; |
256 | aux = ac97_read(w->codec, AC97_AUX); | 264 | |
257 | 265 | mixer = mc->shift >> 8; | |
258 | if (event & SND_SOC_DAPM_PRE_REG) | 266 | shift = mc->shift & 0xff; |
259 | return 0; | 267 | mask = (1 << shift); |
260 | if ((l & 0x1) || (r & 0x1)) | 268 | |
261 | ac97_write(w->codec, AC97_PC_BEEP, beep & 0x7fff); | 269 | mutex_lock(&wm9713->lock); |
270 | old = wm9713->hp_mixer[mixer]; | ||
271 | if (ucontrol->value.enumerated.item[0]) | ||
272 | wm9713->hp_mixer[mixer] |= mask; | ||
262 | else | 273 | else |
263 | ac97_write(w->codec, AC97_PC_BEEP, beep | 0x8000); | 274 | wm9713->hp_mixer[mixer] &= ~mask; |
275 | |||
276 | change = old != wm9713->hp_mixer[mixer]; | ||
277 | if (change) { | ||
278 | update.kcontrol = kcontrol; | ||
279 | update.reg = wm9713_mixer_mute_regs[shift]; | ||
280 | update.mask = 0x8000; | ||
281 | if ((wm9713->hp_mixer[0] & mask) || | ||
282 | (wm9713->hp_mixer[1] & mask)) | ||
283 | update.val = 0x0; | ||
284 | else | ||
285 | update.val = 0x8000; | ||
286 | |||
287 | snd_soc_dapm_mixer_update_power(dapm, kcontrol, val, | ||
288 | &update); | ||
289 | } | ||
264 | 290 | ||
265 | if ((l & 0x2) || (r & 0x2)) | 291 | mutex_unlock(&wm9713->lock); |
266 | ac97_write(w->codec, AC97_MASTER_TONE, tone & 0x7fff); | ||
267 | else | ||
268 | ac97_write(w->codec, AC97_MASTER_TONE, tone | 0x8000); | ||
269 | 292 | ||
270 | if ((l & 0x4) || (r & 0x4)) | 293 | return change; |
271 | ac97_write(w->codec, AC97_PHONE, phone & 0x7fff); | 294 | } |
272 | else | ||
273 | ac97_write(w->codec, AC97_PHONE, phone | 0x8000); | ||
274 | 295 | ||
275 | if ((l & 0x8) || (r & 0x8)) | 296 | static int wm9713_hp_mixer_get(struct snd_kcontrol *kcontrol, |
276 | ac97_write(w->codec, AC97_REC_SEL, rec & 0x7fff); | 297 | struct snd_ctl_elem_value *ucontrol) |
277 | else | 298 | { |
278 | ac97_write(w->codec, AC97_REC_SEL, rec | 0x8000); | 299 | struct snd_soc_dapm_context *dapm = snd_soc_dapm_kcontrol_dapm(kcontrol); |
300 | struct snd_soc_codec *codec = snd_soc_dapm_to_codec(dapm); | ||
301 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
302 | struct soc_mixer_control *mc = | ||
303 | (struct soc_mixer_control *)kcontrol->private_value; | ||
304 | unsigned int mixer, shift; | ||
279 | 305 | ||
280 | if ((l & 0x10) || (r & 0x10)) | 306 | mixer = mc->shift >> 8; |
281 | ac97_write(w->codec, AC97_PCM, pcm & 0x7fff); | 307 | shift = mc->shift & 0xff; |
282 | else | ||
283 | ac97_write(w->codec, AC97_PCM, pcm | 0x8000); | ||
284 | 308 | ||
285 | if ((l & 0x20) || (r & 0x20)) | 309 | ucontrol->value.enumerated.item[0] = |
286 | ac97_write(w->codec, AC97_AUX, aux & 0x7fff); | 310 | (wm9713->hp_mixer[mixer] >> shift) & 1; |
287 | else | ||
288 | ac97_write(w->codec, AC97_AUX, aux | 0x8000); | ||
289 | 311 | ||
290 | return 0; | 312 | return 0; |
291 | } | 313 | } |
292 | 314 | ||
315 | #define WM9713_HP_MIXER_CTRL(xname, xmixer, xshift) { \ | ||
316 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | ||
317 | .info = snd_soc_info_volsw, \ | ||
318 | .get = wm9713_hp_mixer_get, .put = wm9713_hp_mixer_put, \ | ||
319 | .private_value = SOC_DOUBLE_VALUE(SND_SOC_NOPM, \ | ||
320 | xshift, xmixer, 1, 0, 0) \ | ||
321 | } | ||
322 | |||
293 | /* Left Headphone Mixers */ | 323 | /* Left Headphone Mixers */ |
294 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { | 324 | static const struct snd_kcontrol_new wm9713_hpl_mixer_controls[] = { |
295 | SOC_DAPM_SINGLE("Beep Playback Switch", HPL_MIXER, 5, 1, 0), | 325 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPL_MIXER, 5), |
296 | SOC_DAPM_SINGLE("Voice Playback Switch", HPL_MIXER, 4, 1, 0), | 326 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPL_MIXER, 4), |
297 | SOC_DAPM_SINGLE("Aux Playback Switch", HPL_MIXER, 3, 1, 0), | 327 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPL_MIXER, 3), |
298 | SOC_DAPM_SINGLE("PCM Playback Switch", HPL_MIXER, 2, 1, 0), | 328 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPL_MIXER, 2), |
299 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPL_MIXER, 1, 1, 0), | 329 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPL_MIXER, 1), |
300 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPL_MIXER, 0, 1, 0), | 330 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPL_MIXER, 0), |
301 | }; | 331 | }; |
302 | 332 | ||
303 | /* Right Headphone Mixers */ | 333 | /* Right Headphone Mixers */ |
304 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { | 334 | static const struct snd_kcontrol_new wm9713_hpr_mixer_controls[] = { |
305 | SOC_DAPM_SINGLE("Beep Playback Switch", HPR_MIXER, 5, 1, 0), | 335 | WM9713_HP_MIXER_CTRL("Beep Playback Switch", HPR_MIXER, 5), |
306 | SOC_DAPM_SINGLE("Voice Playback Switch", HPR_MIXER, 4, 1, 0), | 336 | WM9713_HP_MIXER_CTRL("Voice Playback Switch", HPR_MIXER, 4), |
307 | SOC_DAPM_SINGLE("Aux Playback Switch", HPR_MIXER, 3, 1, 0), | 337 | WM9713_HP_MIXER_CTRL("Aux Playback Switch", HPR_MIXER, 3), |
308 | SOC_DAPM_SINGLE("PCM Playback Switch", HPR_MIXER, 2, 1, 0), | 338 | WM9713_HP_MIXER_CTRL("PCM Playback Switch", HPR_MIXER, 2), |
309 | SOC_DAPM_SINGLE("MonoIn Playback Switch", HPR_MIXER, 1, 1, 0), | 339 | WM9713_HP_MIXER_CTRL("MonoIn Playback Switch", HPR_MIXER, 1), |
310 | SOC_DAPM_SINGLE("Bypass Playback Switch", HPR_MIXER, 0, 1, 0), | 340 | WM9713_HP_MIXER_CTRL("Bypass Playback Switch", HPR_MIXER, 0), |
311 | }; | 341 | }; |
312 | 342 | ||
313 | /* headphone capture mux */ | 343 | /* headphone capture mux */ |
@@ -429,12 +459,10 @@ SND_SOC_DAPM_MUX("Mic A Source", SND_SOC_NOPM, 0, 0, | |||
429 | &wm9713_mic_sel_mux_controls), | 459 | &wm9713_mic_sel_mux_controls), |
430 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, | 460 | SND_SOC_DAPM_MUX("Mic B Source", SND_SOC_NOPM, 0, 0, |
431 | &wm9713_micb_sel_mux_controls), | 461 | &wm9713_micb_sel_mux_controls), |
432 | SND_SOC_DAPM_MIXER_E("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, | 462 | SND_SOC_DAPM_MIXER("Left HP Mixer", AC97_EXTENDED_MID, 3, 1, |
433 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls), | 463 | &wm9713_hpl_mixer_controls[0], ARRAY_SIZE(wm9713_hpl_mixer_controls)), |
434 | mixer_event, SND_SOC_DAPM_POST_REG), | 464 | SND_SOC_DAPM_MIXER("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, |
435 | SND_SOC_DAPM_MIXER_E("Right HP Mixer", AC97_EXTENDED_MID, 2, 1, | 465 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls)), |
436 | &wm9713_hpr_mixer_controls[0], ARRAY_SIZE(wm9713_hpr_mixer_controls), | ||
437 | mixer_event, SND_SOC_DAPM_POST_REG), | ||
438 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, | 466 | SND_SOC_DAPM_MIXER("Mono Mixer", AC97_EXTENDED_MID, 0, 1, |
439 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), | 467 | &wm9713_mono_mixer_controls[0], ARRAY_SIZE(wm9713_mono_mixer_controls)), |
440 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, | 468 | SND_SOC_DAPM_MIXER("Speaker Mixer", AC97_EXTENDED_MID, 1, 1, |
@@ -647,12 +675,13 @@ static const struct snd_soc_dapm_route wm9713_audio_map[] = { | |||
647 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 675 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
648 | unsigned int reg) | 676 | unsigned int reg) |
649 | { | 677 | { |
678 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
650 | u16 *cache = codec->reg_cache; | 679 | u16 *cache = codec->reg_cache; |
651 | 680 | ||
652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 681 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 682 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | reg == AC97_CD) | 683 | reg == AC97_CD) |
655 | return soc_ac97_ops->read(codec->ac97, reg); | 684 | return soc_ac97_ops->read(wm9713->ac97, reg); |
656 | else { | 685 | else { |
657 | reg = reg >> 1; | 686 | reg = reg >> 1; |
658 | 687 | ||
@@ -666,9 +695,10 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
666 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 695 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
667 | unsigned int val) | 696 | unsigned int val) |
668 | { | 697 | { |
698 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
699 | |||
669 | u16 *cache = codec->reg_cache; | 700 | u16 *cache = codec->reg_cache; |
670 | if (reg < 0x7c) | 701 | soc_ac97_ops->write(wm9713->ac97, reg, val); |
671 | soc_ac97_ops->write(codec->ac97, reg, val); | ||
672 | reg = reg >> 1; | 702 | reg = reg >> 1; |
673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 703 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | cache[reg] = val; | 704 | cache[reg] = val; |
@@ -689,7 +719,8 @@ struct _pll_div { | |||
689 | * to allow rounding later */ | 719 | * to allow rounding later */ |
690 | #define FIXED_PLL_SIZE ((1 << 22) * 10) | 720 | #define FIXED_PLL_SIZE ((1 << 22) * 10) |
691 | 721 | ||
692 | static void pll_factors(struct _pll_div *pll_div, unsigned int source) | 722 | static void pll_factors(struct snd_soc_codec *codec, |
723 | struct _pll_div *pll_div, unsigned int source) | ||
693 | { | 724 | { |
694 | u64 Kpart; | 725 | u64 Kpart; |
695 | unsigned int K, Ndiv, Nmod, target; | 726 | unsigned int K, Ndiv, Nmod, target; |
@@ -724,7 +755,7 @@ static void pll_factors(struct _pll_div *pll_div, unsigned int source) | |||
724 | 755 | ||
725 | Ndiv = target / source; | 756 | Ndiv = target / source; |
726 | if ((Ndiv < 5) || (Ndiv > 12)) | 757 | if ((Ndiv < 5) || (Ndiv > 12)) |
727 | printk(KERN_WARNING | 758 | dev_warn(codec->dev, |
728 | "WM9713 PLL N value %u out of recommended range!\n", | 759 | "WM9713 PLL N value %u out of recommended range!\n", |
729 | Ndiv); | 760 | Ndiv); |
730 | 761 | ||
@@ -768,7 +799,7 @@ static int wm9713_set_pll(struct snd_soc_codec *codec, | |||
768 | return 0; | 799 | return 0; |
769 | } | 800 | } |
770 | 801 | ||
771 | pll_factors(&pll_div, freq_in); | 802 | pll_factors(codec, &pll_div, freq_in); |
772 | 803 | ||
773 | if (pll_div.k == 0) { | 804 | if (pll_div.k == 0) { |
774 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | | 805 | reg = (pll_div.n << 12) | (pll_div.lf << 11) | |
@@ -1049,7 +1080,6 @@ static const struct snd_soc_dai_ops wm9713_dai_ops_voice = { | |||
1049 | static struct snd_soc_dai_driver wm9713_dai[] = { | 1080 | static struct snd_soc_dai_driver wm9713_dai[] = { |
1050 | { | 1081 | { |
1051 | .name = "wm9713-hifi", | 1082 | .name = "wm9713-hifi", |
1052 | .ac97_control = 1, | ||
1053 | .playback = { | 1083 | .playback = { |
1054 | .stream_name = "HiFi Playback", | 1084 | .stream_name = "HiFi Playback", |
1055 | .channels_min = 1, | 1085 | .channels_min = 1, |
@@ -1095,17 +1125,22 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1095 | 1125 | ||
1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1126 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | { | 1127 | { |
1128 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | ||
1129 | |||
1098 | if (try_warm && soc_ac97_ops->warm_reset) { | 1130 | if (try_warm && soc_ac97_ops->warm_reset) { |
1099 | soc_ac97_ops->warm_reset(codec->ac97); | 1131 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1132 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | return 1; | 1133 | return 1; |
1102 | } | 1134 | } |
1103 | 1135 | ||
1104 | soc_ac97_ops->reset(codec->ac97); | 1136 | soc_ac97_ops->reset(wm9713->ac97); |
1105 | if (soc_ac97_ops->warm_reset) | 1137 | if (soc_ac97_ops->warm_reset) |
1106 | soc_ac97_ops->warm_reset(codec->ac97); | 1138 | soc_ac97_ops->warm_reset(wm9713->ac97); |
1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1139 | if (ac97_read(codec, 0) != wm9713_reg[0]) { |
1140 | dev_err(codec->dev, "Failed to reset: AC97 link error\n"); | ||
1108 | return -EIO; | 1141 | return -EIO; |
1142 | } | ||
1143 | |||
1109 | return 0; | 1144 | return 0; |
1110 | } | 1145 | } |
1111 | EXPORT_SYMBOL_GPL(wm9713_reset); | 1146 | EXPORT_SYMBOL_GPL(wm9713_reset); |
@@ -1163,10 +1198,8 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1163 | u16 *cache = codec->reg_cache; | 1198 | u16 *cache = codec->reg_cache; |
1164 | 1199 | ||
1165 | ret = wm9713_reset(codec, 1); | 1200 | ret = wm9713_reset(codec, 1); |
1166 | if (ret < 0) { | 1201 | if (ret < 0) |
1167 | printk(KERN_ERR "could not reset AC97 codec\n"); | ||
1168 | return ret; | 1202 | return ret; |
1169 | } | ||
1170 | 1203 | ||
1171 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1204 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1172 | 1205 | ||
@@ -1180,7 +1213,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1213 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1214 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | continue; | 1215 | continue; |
1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); | 1216 | soc_ac97_ops->write(wm9713->ac97, i, cache[i>>1]); |
1184 | } | 1217 | } |
1185 | } | 1218 | } |
1186 | 1219 | ||
@@ -1189,26 +1222,19 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1189 | 1222 | ||
1190 | static int wm9713_soc_probe(struct snd_soc_codec *codec) | 1223 | static int wm9713_soc_probe(struct snd_soc_codec *codec) |
1191 | { | 1224 | { |
1192 | struct wm9713_priv *wm9713; | 1225 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1193 | int ret = 0, reg; | 1226 | int ret = 0, reg; |
1194 | 1227 | ||
1195 | wm9713 = kzalloc(sizeof(struct wm9713_priv), GFP_KERNEL); | 1228 | wm9713->ac97 = snd_soc_new_ac97_codec(codec); |
1196 | if (wm9713 == NULL) | 1229 | if (IS_ERR(wm9713->ac97)) |
1197 | return -ENOMEM; | 1230 | return PTR_ERR(wm9713->ac97); |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | ||
1199 | |||
1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | ||
1201 | if (ret < 0) | ||
1202 | goto codec_err; | ||
1203 | 1231 | ||
1204 | /* do a cold reset for the controller and then try | 1232 | /* do a cold reset for the controller and then try |
1205 | * a warm reset followed by an optional cold reset for codec */ | 1233 | * a warm reset followed by an optional cold reset for codec */ |
1206 | wm9713_reset(codec, 0); | 1234 | wm9713_reset(codec, 0); |
1207 | ret = wm9713_reset(codec, 1); | 1235 | ret = wm9713_reset(codec, 1); |
1208 | if (ret < 0) { | 1236 | if (ret < 0) |
1209 | printk(KERN_ERR "Failed to reset WM9713: AC97 link error\n"); | ||
1210 | goto reset_err; | 1237 | goto reset_err; |
1211 | } | ||
1212 | 1238 | ||
1213 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); | 1239 | wm9713_set_bias_level(codec, SND_SOC_BIAS_STANDBY); |
1214 | 1240 | ||
@@ -1216,23 +1242,18 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1216 | reg = ac97_read(codec, AC97_CD) & 0x7fff; | 1242 | reg = ac97_read(codec, AC97_CD) & 0x7fff; |
1217 | ac97_write(codec, AC97_CD, reg); | 1243 | ac97_write(codec, AC97_CD, reg); |
1218 | 1244 | ||
1219 | snd_soc_add_codec_controls(codec, wm9713_snd_ac97_controls, | ||
1220 | ARRAY_SIZE(wm9713_snd_ac97_controls)); | ||
1221 | |||
1222 | return 0; | 1245 | return 0; |
1223 | 1246 | ||
1224 | reset_err: | 1247 | reset_err: |
1225 | snd_soc_free_ac97_codec(codec); | 1248 | snd_soc_free_ac97_codec(wm9713->ac97); |
1226 | codec_err: | ||
1227 | kfree(wm9713); | ||
1228 | return ret; | 1249 | return ret; |
1229 | } | 1250 | } |
1230 | 1251 | ||
1231 | static int wm9713_soc_remove(struct snd_soc_codec *codec) | 1252 | static int wm9713_soc_remove(struct snd_soc_codec *codec) |
1232 | { | 1253 | { |
1233 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); | 1254 | struct wm9713_priv *wm9713 = snd_soc_codec_get_drvdata(codec); |
1234 | snd_soc_free_ac97_codec(codec); | 1255 | |
1235 | kfree(wm9713); | 1256 | snd_soc_free_ac97_codec(wm9713->ac97); |
1236 | return 0; | 1257 | return 0; |
1237 | } | 1258 | } |
1238 | 1259 | ||
@@ -1248,6 +1269,9 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1248 | .reg_word_size = sizeof(u16), | 1269 | .reg_word_size = sizeof(u16), |
1249 | .reg_cache_step = 2, | 1270 | .reg_cache_step = 2, |
1250 | .reg_cache_default = wm9713_reg, | 1271 | .reg_cache_default = wm9713_reg, |
1272 | |||
1273 | .controls = wm9713_snd_ac97_controls, | ||
1274 | .num_controls = ARRAY_SIZE(wm9713_snd_ac97_controls), | ||
1251 | .dapm_widgets = wm9713_dapm_widgets, | 1275 | .dapm_widgets = wm9713_dapm_widgets, |
1252 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), | 1276 | .num_dapm_widgets = ARRAY_SIZE(wm9713_dapm_widgets), |
1253 | .dapm_routes = wm9713_audio_map, | 1277 | .dapm_routes = wm9713_audio_map, |
@@ -1256,6 +1280,16 @@ static struct snd_soc_codec_driver soc_codec_dev_wm9713 = { | |||
1256 | 1280 | ||
1257 | static int wm9713_probe(struct platform_device *pdev) | 1281 | static int wm9713_probe(struct platform_device *pdev) |
1258 | { | 1282 | { |
1283 | struct wm9713_priv *wm9713; | ||
1284 | |||
1285 | wm9713 = devm_kzalloc(&pdev->dev, sizeof(*wm9713), GFP_KERNEL); | ||
1286 | if (wm9713 == NULL) | ||
1287 | return -ENOMEM; | ||
1288 | |||
1289 | mutex_init(&wm9713->lock); | ||
1290 | |||
1291 | platform_set_drvdata(pdev, wm9713); | ||
1292 | |||
1259 | return snd_soc_register_codec(&pdev->dev, | 1293 | return snd_soc_register_codec(&pdev->dev, |
1260 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); | 1294 | &soc_codec_dev_wm9713, wm9713_dai, ARRAY_SIZE(wm9713_dai)); |
1261 | } | 1295 | } |
diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index e6955170dc42..7fd3cbcd74c0 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c | |||
@@ -1099,7 +1099,7 @@ static const struct snd_soc_component_driver fsl_ssi_component = { | |||
1099 | }; | 1099 | }; |
1100 | 1100 | ||
1101 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { | 1101 | static struct snd_soc_dai_driver fsl_ssi_ac97_dai = { |
1102 | .ac97_control = 1, | 1102 | .bus_control = true, |
1103 | .playback = { | 1103 | .playback = { |
1104 | .stream_name = "AC97 Playback", | 1104 | .stream_name = "AC97 Playback", |
1105 | .channels_min = 2, | 1105 | .channels_min = 2, |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index ab2fdd76b693..60b0a5b1f1f1 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -382,7 +382,7 @@ static struct snd_soc_dai_driver imx_ssi_dai = { | |||
382 | 382 | ||
383 | static struct snd_soc_dai_driver imx_ac97_dai = { | 383 | static struct snd_soc_dai_driver imx_ac97_dai = { |
384 | .probe = imx_ssi_dai_probe, | 384 | .probe = imx_ssi_dai_probe, |
385 | .ac97_control = 1, | 385 | .bus_control = true, |
386 | .playback = { | 386 | .playback = { |
387 | .stream_name = "AC97 Playback", | 387 | .stream_name = "AC97 Playback", |
388 | .channels_min = 2, | 388 | .channels_min = 2, |
diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index f2b5d756b1f3..0b82e209b6e3 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c | |||
@@ -327,9 +327,6 @@ static int psc_dma_new(struct snd_soc_pcm_runtime *rtd) | |||
327 | goto capture_alloc_err; | 327 | goto capture_alloc_err; |
328 | } | 328 | } |
329 | 329 | ||
330 | if (rtd->codec->ac97) | ||
331 | rtd->codec->ac97->private_data = psc_dma; | ||
332 | |||
333 | return 0; | 330 | return 0; |
334 | 331 | ||
335 | capture_alloc_err: | 332 | capture_alloc_err: |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 24eafa2cfbf4..c6ed6ba965a9 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -237,7 +237,7 @@ static const struct snd_soc_dai_ops psc_ac97_digital_ops = { | |||
237 | static struct snd_soc_dai_driver psc_ac97_dai[] = { | 237 | static struct snd_soc_dai_driver psc_ac97_dai[] = { |
238 | { | 238 | { |
239 | .name = "mpc5200-psc-ac97.0", | 239 | .name = "mpc5200-psc-ac97.0", |
240 | .ac97_control = 1, | 240 | .bus_control = true, |
241 | .probe = psc_ac97_probe, | 241 | .probe = psc_ac97_probe, |
242 | .playback = { | 242 | .playback = { |
243 | .stream_name = "AC97 Playback", | 243 | .stream_name = "AC97 Playback", |
@@ -257,7 +257,7 @@ static struct snd_soc_dai_driver psc_ac97_dai[] = { | |||
257 | }, | 257 | }, |
258 | { | 258 | { |
259 | .name = "mpc5200-psc-ac97.1", | 259 | .name = "mpc5200-psc-ac97.1", |
260 | .ac97_control = 1, | 260 | .bus_control = true, |
261 | .playback = { | 261 | .playback = { |
262 | .stream_name = "AC97 SPDIF", | 262 | .stream_name = "AC97 SPDIF", |
263 | .channels_min = 1, | 263 | .channels_min = 1, |
@@ -282,7 +282,6 @@ static const struct snd_soc_component_driver psc_ac97_component = { | |||
282 | static int psc_ac97_of_probe(struct platform_device *op) | 282 | static int psc_ac97_of_probe(struct platform_device *op) |
283 | { | 283 | { |
284 | int rc; | 284 | int rc; |
285 | struct snd_ac97 ac97; | ||
286 | struct mpc52xx_psc __iomem *regs; | 285 | struct mpc52xx_psc __iomem *regs; |
287 | 286 | ||
288 | rc = mpc5200_audio_dma_create(op); | 287 | rc = mpc5200_audio_dma_create(op); |
@@ -304,7 +303,6 @@ static int psc_ac97_of_probe(struct platform_device *op) | |||
304 | 303 | ||
305 | psc_dma = dev_get_drvdata(&op->dev); | 304 | psc_dma = dev_get_drvdata(&op->dev); |
306 | regs = psc_dma->psc_regs; | 305 | regs = psc_dma->psc_regs; |
307 | ac97.private_data = psc_dma; | ||
308 | 306 | ||
309 | psc_dma->imr = 0; | 307 | psc_dma->imr = 0; |
310 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); | 308 | out_be16(&psc_dma->psc_regs->isr_imr.imr, psc_dma->imr); |
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index f2f67942b229..dff443e4b657 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -298,7 +298,7 @@ static const struct snd_soc_dai_ops nuc900_ac97_dai_ops = { | |||
298 | static struct snd_soc_dai_driver nuc900_ac97_dai = { | 298 | static struct snd_soc_dai_driver nuc900_ac97_dai = { |
299 | .probe = nuc900_ac97_probe, | 299 | .probe = nuc900_ac97_probe, |
300 | .remove = nuc900_ac97_remove, | 300 | .remove = nuc900_ac97_remove, |
301 | .ac97_control = 1, | 301 | .bus_control = true, |
302 | .playback = { | 302 | .playback = { |
303 | .rates = SNDRV_PCM_RATE_8000_48000, | 303 | .rates = SNDRV_PCM_RATE_8000_48000, |
304 | .formats = SNDRV_PCM_FMTBIT_S16_LE, | 304 | .formats = SNDRV_PCM_FMTBIT_S16_LE, |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index ae956e3f4b9d..73ca2820c08c 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -157,7 +157,7 @@ static const struct snd_soc_dai_ops pxa_ac97_mic_dai_ops = { | |||
157 | static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | 157 | static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { |
158 | { | 158 | { |
159 | .name = "pxa2xx-ac97", | 159 | .name = "pxa2xx-ac97", |
160 | .ac97_control = 1, | 160 | .bus_control = true, |
161 | .playback = { | 161 | .playback = { |
162 | .stream_name = "AC97 Playback", | 162 | .stream_name = "AC97 Playback", |
163 | .channels_min = 2, | 163 | .channels_min = 2, |
@@ -174,7 +174,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | |||
174 | }, | 174 | }, |
175 | { | 175 | { |
176 | .name = "pxa2xx-ac97-aux", | 176 | .name = "pxa2xx-ac97-aux", |
177 | .ac97_control = 1, | 177 | .bus_control = true, |
178 | .playback = { | 178 | .playback = { |
179 | .stream_name = "AC97 Aux Playback", | 179 | .stream_name = "AC97 Aux Playback", |
180 | .channels_min = 1, | 180 | .channels_min = 1, |
@@ -191,7 +191,7 @@ static struct snd_soc_dai_driver pxa_ac97_dai_driver[] = { | |||
191 | }, | 191 | }, |
192 | { | 192 | { |
193 | .name = "pxa2xx-ac97-mic", | 193 | .name = "pxa2xx-ac97-mic", |
194 | .ac97_control = 1, | 194 | .bus_control = true, |
195 | .capture = { | 195 | .capture = { |
196 | .stream_name = "AC97 Mic Capture", | 196 | .stream_name = "AC97 Mic Capture", |
197 | .channels_min = 1, | 197 | .channels_min = 1, |
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index e1615113fd84..7952a625669d 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -288,7 +288,7 @@ static int s3c_ac97_mic_dai_probe(struct snd_soc_dai *dai) | |||
288 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { | 288 | static struct snd_soc_dai_driver s3c_ac97_dai[] = { |
289 | [S3C_AC97_DAI_PCM] = { | 289 | [S3C_AC97_DAI_PCM] = { |
290 | .name = "samsung-ac97", | 290 | .name = "samsung-ac97", |
291 | .ac97_control = 1, | 291 | .bus_control = true, |
292 | .playback = { | 292 | .playback = { |
293 | .stream_name = "AC97 Playback", | 293 | .stream_name = "AC97 Playback", |
294 | .channels_min = 2, | 294 | .channels_min = 2, |
@@ -306,7 +306,7 @@ static struct snd_soc_dai_driver s3c_ac97_dai[] = { | |||
306 | }, | 306 | }, |
307 | [S3C_AC97_DAI_MIC] = { | 307 | [S3C_AC97_DAI_MIC] = { |
308 | .name = "samsung-ac97-mic", | 308 | .name = "samsung-ac97-mic", |
309 | .ac97_control = 1, | 309 | .bus_control = true, |
310 | .capture = { | 310 | .capture = { |
311 | .stream_name = "AC97 Mic Capture", | 311 | .stream_name = "AC97 Mic Capture", |
312 | .channels_min = 1, | 312 | .channels_min = 1, |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index 0af2e4dfd139..d5f567e085ff 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -272,7 +272,7 @@ static const struct snd_soc_dai_ops hac_dai_ops = { | |||
272 | static struct snd_soc_dai_driver sh4_hac_dai[] = { | 272 | static struct snd_soc_dai_driver sh4_hac_dai[] = { |
273 | { | 273 | { |
274 | .name = "hac-dai.0", | 274 | .name = "hac-dai.0", |
275 | .ac97_control = 1, | 275 | .bus_control = true, |
276 | .playback = { | 276 | .playback = { |
277 | .rates = AC97_RATES, | 277 | .rates = AC97_RATES, |
278 | .formats = AC97_FMTS, | 278 | .formats = AC97_FMTS, |
diff --git a/sound/soc/soc-ac97.c b/sound/soc/soc-ac97.c new file mode 100644 index 000000000000..2e10e9a38376 --- /dev/null +++ b/sound/soc/soc-ac97.c | |||
@@ -0,0 +1,256 @@ | |||
1 | /* | ||
2 | * soc-ac97.c -- ALSA SoC Audio Layer AC97 support | ||
3 | * | ||
4 | * Copyright 2005 Wolfson Microelectronics PLC. | ||
5 | * Copyright 2005 Openedhand Ltd. | ||
6 | * Copyright (C) 2010 Slimlogic Ltd. | ||
7 | * Copyright (C) 2010 Texas Instruments Inc. | ||
8 | * | ||
9 | * Author: Liam Girdwood <lrg@slimlogic.co.uk> | ||
10 | * with code, comments and ideas from :- | ||
11 | * Richard Purdie <richard@openedhand.com> | ||
12 | * | ||
13 | * This program is free software; you can redistribute it and/or modify it | ||
14 | * under the terms of the GNU General Public License as published by the | ||
15 | * Free Software Foundation; either version 2 of the License, or (at your | ||
16 | * option) any later version. | ||
17 | */ | ||
18 | |||
19 | #include <linux/ctype.h> | ||
20 | #include <linux/delay.h> | ||
21 | #include <linux/export.h> | ||
22 | #include <linux/gpio.h> | ||
23 | #include <linux/init.h> | ||
24 | #include <linux/of_gpio.h> | ||
25 | #include <linux/of.h> | ||
26 | #include <linux/pinctrl/consumer.h> | ||
27 | #include <linux/slab.h> | ||
28 | #include <sound/ac97_codec.h> | ||
29 | #include <sound/soc.h> | ||
30 | |||
31 | struct snd_ac97_reset_cfg { | ||
32 | struct pinctrl *pctl; | ||
33 | struct pinctrl_state *pstate_reset; | ||
34 | struct pinctrl_state *pstate_warm_reset; | ||
35 | struct pinctrl_state *pstate_run; | ||
36 | int gpio_sdata; | ||
37 | int gpio_sync; | ||
38 | int gpio_reset; | ||
39 | }; | ||
40 | |||
41 | static struct snd_ac97_bus soc_ac97_bus = { | ||
42 | .ops = NULL, /* Gets initialized in snd_soc_set_ac97_ops() */ | ||
43 | }; | ||
44 | |||
45 | static void soc_ac97_device_release(struct device *dev) | ||
46 | { | ||
47 | kfree(to_ac97_t(dev)); | ||
48 | } | ||
49 | |||
50 | /** | ||
51 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
52 | * @codec: audio codec | ||
53 | * | ||
54 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
55 | */ | ||
56 | struct snd_ac97 *snd_soc_new_ac97_codec(struct snd_soc_codec *codec) | ||
57 | { | ||
58 | struct snd_ac97 *ac97; | ||
59 | int ret; | ||
60 | |||
61 | ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
62 | if (ac97 == NULL) | ||
63 | return ERR_PTR(-ENOMEM); | ||
64 | |||
65 | ac97->bus = &soc_ac97_bus; | ||
66 | ac97->num = 0; | ||
67 | |||
68 | ac97->dev.bus = &ac97_bus_type; | ||
69 | ac97->dev.parent = codec->component.card->dev; | ||
70 | ac97->dev.release = soc_ac97_device_release; | ||
71 | |||
72 | dev_set_name(&ac97->dev, "%d-%d:%s", | ||
73 | codec->component.card->snd_card->number, 0, | ||
74 | codec->component.name); | ||
75 | |||
76 | ret = device_register(&ac97->dev); | ||
77 | if (ret) { | ||
78 | put_device(&ac97->dev); | ||
79 | return ERR_PTR(ret); | ||
80 | } | ||
81 | |||
82 | return ac97; | ||
83 | } | ||
84 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
85 | |||
86 | /** | ||
87 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
88 | * @codec: audio codec | ||
89 | * | ||
90 | * Frees AC97 codec device resources. | ||
91 | */ | ||
92 | void snd_soc_free_ac97_codec(struct snd_ac97 *ac97) | ||
93 | { | ||
94 | device_del(&ac97->dev); | ||
95 | ac97->bus = NULL; | ||
96 | put_device(&ac97->dev); | ||
97 | } | ||
98 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
99 | |||
100 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
101 | |||
102 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
103 | { | ||
104 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
105 | |||
106 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
107 | |||
108 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
109 | |||
110 | udelay(10); | ||
111 | |||
112 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
113 | |||
114 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
115 | msleep(2); | ||
116 | } | ||
117 | |||
118 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
119 | { | ||
120 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
121 | |||
122 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
123 | |||
124 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
125 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
126 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
127 | |||
128 | udelay(10); | ||
129 | |||
130 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
131 | |||
132 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
133 | msleep(2); | ||
134 | } | ||
135 | |||
136 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
137 | struct snd_ac97_reset_cfg *cfg) | ||
138 | { | ||
139 | struct pinctrl *p; | ||
140 | struct pinctrl_state *state; | ||
141 | int gpio; | ||
142 | int ret; | ||
143 | |||
144 | p = devm_pinctrl_get(dev); | ||
145 | if (IS_ERR(p)) { | ||
146 | dev_err(dev, "Failed to get pinctrl\n"); | ||
147 | return PTR_ERR(p); | ||
148 | } | ||
149 | cfg->pctl = p; | ||
150 | |||
151 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
152 | if (IS_ERR(state)) { | ||
153 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
154 | return PTR_ERR(state); | ||
155 | } | ||
156 | cfg->pstate_reset = state; | ||
157 | |||
158 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
159 | if (IS_ERR(state)) { | ||
160 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
161 | return PTR_ERR(state); | ||
162 | } | ||
163 | cfg->pstate_warm_reset = state; | ||
164 | |||
165 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
166 | if (IS_ERR(state)) { | ||
167 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
168 | return PTR_ERR(state); | ||
169 | } | ||
170 | cfg->pstate_run = state; | ||
171 | |||
172 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
173 | if (gpio < 0) { | ||
174 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
175 | return gpio; | ||
176 | } | ||
177 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
178 | if (ret) { | ||
179 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
180 | return ret; | ||
181 | } | ||
182 | cfg->gpio_sync = gpio; | ||
183 | |||
184 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
185 | if (gpio < 0) { | ||
186 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
187 | return gpio; | ||
188 | } | ||
189 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
190 | if (ret) { | ||
191 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
192 | return ret; | ||
193 | } | ||
194 | cfg->gpio_sdata = gpio; | ||
195 | |||
196 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
197 | if (gpio < 0) { | ||
198 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
199 | return gpio; | ||
200 | } | ||
201 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
202 | if (ret) { | ||
203 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
204 | return ret; | ||
205 | } | ||
206 | cfg->gpio_reset = gpio; | ||
207 | |||
208 | return 0; | ||
209 | } | ||
210 | |||
211 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
212 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
213 | |||
214 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
215 | { | ||
216 | if (ops == soc_ac97_ops) | ||
217 | return 0; | ||
218 | |||
219 | if (soc_ac97_ops && ops) | ||
220 | return -EBUSY; | ||
221 | |||
222 | soc_ac97_ops = ops; | ||
223 | soc_ac97_bus.ops = ops; | ||
224 | |||
225 | return 0; | ||
226 | } | ||
227 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
228 | |||
229 | /** | ||
230 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
231 | * | ||
232 | * This function sets the reset and warm_reset properties of ops and parses | ||
233 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
234 | */ | ||
235 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
236 | struct platform_device *pdev) | ||
237 | { | ||
238 | struct device *dev = &pdev->dev; | ||
239 | struct snd_ac97_reset_cfg cfg; | ||
240 | int ret; | ||
241 | |||
242 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
243 | if (ret) | ||
244 | return ret; | ||
245 | |||
246 | ret = snd_soc_set_ac97_ops(ops); | ||
247 | if (ret) | ||
248 | return ret; | ||
249 | |||
250 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
251 | ops->reset = snd_soc_ac97_reset; | ||
252 | |||
253 | snd_ac97_rst_cfg = cfg; | ||
254 | return 0; | ||
255 | } | ||
256 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index d8d5449cc48e..e0d3b6f109c4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -34,9 +34,6 @@ | |||
34 | #include <linux/ctype.h> | 34 | #include <linux/ctype.h> |
35 | #include <linux/slab.h> | 35 | #include <linux/slab.h> |
36 | #include <linux/of.h> | 36 | #include <linux/of.h> |
37 | #include <linux/gpio.h> | ||
38 | #include <linux/of_gpio.h> | ||
39 | #include <sound/ac97_codec.h> | ||
40 | #include <sound/core.h> | 37 | #include <sound/core.h> |
41 | #include <sound/jack.h> | 38 | #include <sound/jack.h> |
42 | #include <sound/pcm.h> | 39 | #include <sound/pcm.h> |
@@ -69,16 +66,6 @@ static int pmdown_time = 5000; | |||
69 | module_param(pmdown_time, int, 0); | 66 | module_param(pmdown_time, int, 0); |
70 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 67 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
71 | 68 | ||
72 | struct snd_ac97_reset_cfg { | ||
73 | struct pinctrl *pctl; | ||
74 | struct pinctrl_state *pstate_reset; | ||
75 | struct pinctrl_state *pstate_warm_reset; | ||
76 | struct pinctrl_state *pstate_run; | ||
77 | int gpio_sdata; | ||
78 | int gpio_sync; | ||
79 | int gpio_reset; | ||
80 | }; | ||
81 | |||
82 | /* returns the minimum number of bytes needed to represent | 69 | /* returns the minimum number of bytes needed to represent |
83 | * a particular given value */ | 70 | * a particular given value */ |
84 | static int min_bytes_needed(unsigned long val) | 71 | static int min_bytes_needed(unsigned long val) |
@@ -496,40 +483,6 @@ struct snd_soc_pcm_runtime *snd_soc_get_pcm_runtime(struct snd_soc_card *card, | |||
496 | } | 483 | } |
497 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); | 484 | EXPORT_SYMBOL_GPL(snd_soc_get_pcm_runtime); |
498 | 485 | ||
499 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
500 | /* unregister ac97 codec */ | ||
501 | static int soc_ac97_dev_unregister(struct snd_soc_codec *codec) | ||
502 | { | ||
503 | if (codec->ac97->dev.bus) | ||
504 | device_unregister(&codec->ac97->dev); | ||
505 | return 0; | ||
506 | } | ||
507 | |||
508 | /* stop no dev release warning */ | ||
509 | static void soc_ac97_device_release(struct device *dev){} | ||
510 | |||
511 | /* register ac97 codec to bus */ | ||
512 | static int soc_ac97_dev_register(struct snd_soc_codec *codec) | ||
513 | { | ||
514 | int err; | ||
515 | |||
516 | codec->ac97->dev.bus = &ac97_bus_type; | ||
517 | codec->ac97->dev.parent = codec->component.card->dev; | ||
518 | codec->ac97->dev.release = soc_ac97_device_release; | ||
519 | |||
520 | dev_set_name(&codec->ac97->dev, "%d-%d:%s", | ||
521 | codec->component.card->snd_card->number, 0, | ||
522 | codec->component.name); | ||
523 | err = device_register(&codec->ac97->dev); | ||
524 | if (err < 0) { | ||
525 | dev_err(codec->dev, "ASoC: Can't register ac97 bus\n"); | ||
526 | codec->ac97->dev.bus = NULL; | ||
527 | return err; | ||
528 | } | ||
529 | return 0; | ||
530 | } | ||
531 | #endif | ||
532 | |||
533 | static void codec2codec_close_delayed_work(struct work_struct *work) | 486 | static void codec2codec_close_delayed_work(struct work_struct *work) |
534 | { | 487 | { |
535 | /* Currently nothing to do for c2c links | 488 | /* Currently nothing to do for c2c links |
@@ -593,7 +546,7 @@ int snd_soc_suspend(struct device *dev) | |||
593 | if (card->rtd[i].dai_link->ignore_suspend) | 546 | if (card->rtd[i].dai_link->ignore_suspend) |
594 | continue; | 547 | continue; |
595 | 548 | ||
596 | if (cpu_dai->driver->suspend && !cpu_dai->driver->ac97_control) | 549 | if (cpu_dai->driver->suspend && !cpu_dai->driver->bus_control) |
597 | cpu_dai->driver->suspend(cpu_dai); | 550 | cpu_dai->driver->suspend(cpu_dai); |
598 | } | 551 | } |
599 | 552 | ||
@@ -667,7 +620,7 @@ int snd_soc_suspend(struct device *dev) | |||
667 | if (card->rtd[i].dai_link->ignore_suspend) | 620 | if (card->rtd[i].dai_link->ignore_suspend) |
668 | continue; | 621 | continue; |
669 | 622 | ||
670 | if (cpu_dai->driver->suspend && cpu_dai->driver->ac97_control) | 623 | if (cpu_dai->driver->suspend && cpu_dai->driver->bus_control) |
671 | cpu_dai->driver->suspend(cpu_dai); | 624 | cpu_dai->driver->suspend(cpu_dai); |
672 | 625 | ||
673 | /* deactivate pins to sleep state */ | 626 | /* deactivate pins to sleep state */ |
@@ -703,14 +656,14 @@ static void soc_resume_deferred(struct work_struct *work) | |||
703 | if (card->resume_pre) | 656 | if (card->resume_pre) |
704 | card->resume_pre(card); | 657 | card->resume_pre(card); |
705 | 658 | ||
706 | /* resume AC97 DAIs */ | 659 | /* resume control bus DAIs */ |
707 | for (i = 0; i < card->num_rtd; i++) { | 660 | for (i = 0; i < card->num_rtd; i++) { |
708 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 661 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
709 | 662 | ||
710 | if (card->rtd[i].dai_link->ignore_suspend) | 663 | if (card->rtd[i].dai_link->ignore_suspend) |
711 | continue; | 664 | continue; |
712 | 665 | ||
713 | if (cpu_dai->driver->resume && cpu_dai->driver->ac97_control) | 666 | if (cpu_dai->driver->resume && cpu_dai->driver->bus_control) |
714 | cpu_dai->driver->resume(cpu_dai); | 667 | cpu_dai->driver->resume(cpu_dai); |
715 | } | 668 | } |
716 | 669 | ||
@@ -770,7 +723,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
770 | if (card->rtd[i].dai_link->ignore_suspend) | 723 | if (card->rtd[i].dai_link->ignore_suspend) |
771 | continue; | 724 | continue; |
772 | 725 | ||
773 | if (cpu_dai->driver->resume && !cpu_dai->driver->ac97_control) | 726 | if (cpu_dai->driver->resume && !cpu_dai->driver->bus_control) |
774 | cpu_dai->driver->resume(cpu_dai); | 727 | cpu_dai->driver->resume(cpu_dai); |
775 | } | 728 | } |
776 | 729 | ||
@@ -791,7 +744,8 @@ static void soc_resume_deferred(struct work_struct *work) | |||
791 | int snd_soc_resume(struct device *dev) | 744 | int snd_soc_resume(struct device *dev) |
792 | { | 745 | { |
793 | struct snd_soc_card *card = dev_get_drvdata(dev); | 746 | struct snd_soc_card *card = dev_get_drvdata(dev); |
794 | int i, ac97_control = 0; | 747 | bool bus_control = false; |
748 | int i; | ||
795 | 749 | ||
796 | /* If the card is not initialized yet there is nothing to do */ | 750 | /* If the card is not initialized yet there is nothing to do */ |
797 | if (!card->instantiated) | 751 | if (!card->instantiated) |
@@ -814,17 +768,18 @@ int snd_soc_resume(struct device *dev) | |||
814 | } | 768 | } |
815 | } | 769 | } |
816 | 770 | ||
817 | /* AC97 devices might have other drivers hanging off them so | 771 | /* |
818 | * need to resume immediately. Other drivers don't have that | 772 | * DAIs that also act as the control bus master might have other drivers |
819 | * problem and may take a substantial amount of time to resume | 773 | * hanging off them so need to resume immediately. Other drivers don't |
774 | * have that problem and may take a substantial amount of time to resume | ||
820 | * due to I/O costs and anti-pop so handle them out of line. | 775 | * due to I/O costs and anti-pop so handle them out of line. |
821 | */ | 776 | */ |
822 | for (i = 0; i < card->num_rtd; i++) { | 777 | for (i = 0; i < card->num_rtd; i++) { |
823 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; | 778 | struct snd_soc_dai *cpu_dai = card->rtd[i].cpu_dai; |
824 | ac97_control |= cpu_dai->driver->ac97_control; | 779 | bus_control |= cpu_dai->driver->bus_control; |
825 | } | 780 | } |
826 | if (ac97_control) { | 781 | if (bus_control) { |
827 | dev_dbg(dev, "ASoC: Resuming AC97 immediately\n"); | 782 | dev_dbg(dev, "ASoC: Resuming control bus master immediately\n"); |
828 | soc_resume_deferred(&card->deferred_resume_work); | 783 | soc_resume_deferred(&card->deferred_resume_work); |
829 | } else { | 784 | } else { |
830 | dev_dbg(dev, "ASoC: Scheduling resume work\n"); | 785 | dev_dbg(dev, "ASoC: Scheduling resume work\n"); |
@@ -1387,84 +1342,9 @@ static int soc_probe_link_dais(struct snd_soc_card *card, int num, int order) | |||
1387 | } | 1342 | } |
1388 | } | 1343 | } |
1389 | 1344 | ||
1390 | /* add platform data for AC97 devices */ | ||
1391 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1392 | if (rtd->codec_dais[i]->driver->ac97_control) | ||
1393 | snd_ac97_dev_add_pdata(rtd->codec_dais[i]->codec->ac97, | ||
1394 | rtd->cpu_dai->ac97_pdata); | ||
1395 | } | ||
1396 | |||
1397 | return 0; | 1345 | return 0; |
1398 | } | 1346 | } |
1399 | 1347 | ||
1400 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1401 | static int soc_register_ac97_codec(struct snd_soc_codec *codec, | ||
1402 | struct snd_soc_dai *codec_dai) | ||
1403 | { | ||
1404 | int ret; | ||
1405 | |||
1406 | /* Only instantiate AC97 if not already done by the adaptor | ||
1407 | * for the generic AC97 subsystem. | ||
1408 | */ | ||
1409 | if (codec_dai->driver->ac97_control && !codec->ac97_registered) { | ||
1410 | /* | ||
1411 | * It is possible that the AC97 device is already registered to | ||
1412 | * the device subsystem. This happens when the device is created | ||
1413 | * via snd_ac97_mixer(). Currently only SoC codec that does so | ||
1414 | * is the generic AC97 glue but others migh emerge. | ||
1415 | * | ||
1416 | * In those cases we don't try to register the device again. | ||
1417 | */ | ||
1418 | if (!codec->ac97_created) | ||
1419 | return 0; | ||
1420 | |||
1421 | ret = soc_ac97_dev_register(codec); | ||
1422 | if (ret < 0) { | ||
1423 | dev_err(codec->dev, | ||
1424 | "ASoC: AC97 device register failed: %d\n", ret); | ||
1425 | return ret; | ||
1426 | } | ||
1427 | |||
1428 | codec->ac97_registered = 1; | ||
1429 | } | ||
1430 | return 0; | ||
1431 | } | ||
1432 | |||
1433 | static void soc_unregister_ac97_codec(struct snd_soc_codec *codec) | ||
1434 | { | ||
1435 | if (codec->ac97_registered) { | ||
1436 | soc_ac97_dev_unregister(codec); | ||
1437 | codec->ac97_registered = 0; | ||
1438 | } | ||
1439 | } | ||
1440 | |||
1441 | static int soc_register_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1442 | { | ||
1443 | int i, ret; | ||
1444 | |||
1445 | for (i = 0; i < rtd->num_codecs; i++) { | ||
1446 | struct snd_soc_dai *codec_dai = rtd->codec_dais[i]; | ||
1447 | |||
1448 | ret = soc_register_ac97_codec(codec_dai->codec, codec_dai); | ||
1449 | if (ret) { | ||
1450 | while (--i >= 0) | ||
1451 | soc_unregister_ac97_codec(codec_dai->codec); | ||
1452 | return ret; | ||
1453 | } | ||
1454 | } | ||
1455 | |||
1456 | return 0; | ||
1457 | } | ||
1458 | |||
1459 | static void soc_unregister_ac97_dai_link(struct snd_soc_pcm_runtime *rtd) | ||
1460 | { | ||
1461 | int i; | ||
1462 | |||
1463 | for (i = 0; i < rtd->num_codecs; i++) | ||
1464 | soc_unregister_ac97_codec(rtd->codec_dais[i]->codec); | ||
1465 | } | ||
1466 | #endif | ||
1467 | |||
1468 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) | 1348 | static int soc_bind_aux_dev(struct snd_soc_card *card, int num) |
1469 | { | 1349 | { |
1470 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | 1350 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; |
@@ -1758,20 +1638,6 @@ static int snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1758 | goto probe_aux_dev_err; | 1638 | goto probe_aux_dev_err; |
1759 | } | 1639 | } |
1760 | 1640 | ||
1761 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
1762 | /* register any AC97 codecs */ | ||
1763 | for (i = 0; i < card->num_rtd; i++) { | ||
1764 | ret = soc_register_ac97_dai_link(&card->rtd[i]); | ||
1765 | if (ret < 0) { | ||
1766 | dev_err(card->dev, | ||
1767 | "ASoC: failed to register AC97: %d\n", ret); | ||
1768 | while (--i >= 0) | ||
1769 | soc_unregister_ac97_dai_link(&card->rtd[i]); | ||
1770 | goto probe_aux_dev_err; | ||
1771 | } | ||
1772 | } | ||
1773 | #endif | ||
1774 | |||
1775 | card->instantiated = 1; | 1641 | card->instantiated = 1; |
1776 | snd_soc_dapm_sync(&card->dapm); | 1642 | snd_soc_dapm_sync(&card->dapm); |
1777 | mutex_unlock(&card->mutex); | 1643 | mutex_unlock(&card->mutex); |
@@ -1914,216 +1780,6 @@ static struct platform_driver soc_driver = { | |||
1914 | }; | 1780 | }; |
1915 | 1781 | ||
1916 | /** | 1782 | /** |
1917 | * snd_soc_new_ac97_codec - initailise AC97 device | ||
1918 | * @codec: audio codec | ||
1919 | * @ops: AC97 bus operations | ||
1920 | * @num: AC97 codec number | ||
1921 | * | ||
1922 | * Initialises AC97 codec resources for use by ad-hoc devices only. | ||
1923 | */ | ||
1924 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | ||
1925 | struct snd_ac97_bus_ops *ops, int num) | ||
1926 | { | ||
1927 | codec->ac97 = kzalloc(sizeof(struct snd_ac97), GFP_KERNEL); | ||
1928 | if (codec->ac97 == NULL) | ||
1929 | return -ENOMEM; | ||
1930 | |||
1931 | codec->ac97->bus = kzalloc(sizeof(struct snd_ac97_bus), GFP_KERNEL); | ||
1932 | if (codec->ac97->bus == NULL) { | ||
1933 | kfree(codec->ac97); | ||
1934 | codec->ac97 = NULL; | ||
1935 | return -ENOMEM; | ||
1936 | } | ||
1937 | |||
1938 | codec->ac97->bus->ops = ops; | ||
1939 | codec->ac97->num = num; | ||
1940 | |||
1941 | /* | ||
1942 | * Mark the AC97 device to be created by us. This way we ensure that the | ||
1943 | * device will be registered with the device subsystem later on. | ||
1944 | */ | ||
1945 | codec->ac97_created = 1; | ||
1946 | |||
1947 | return 0; | ||
1948 | } | ||
1949 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | ||
1950 | |||
1951 | static struct snd_ac97_reset_cfg snd_ac97_rst_cfg; | ||
1952 | |||
1953 | static void snd_soc_ac97_warm_reset(struct snd_ac97 *ac97) | ||
1954 | { | ||
1955 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
1956 | |||
1957 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_warm_reset); | ||
1958 | |||
1959 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 1); | ||
1960 | |||
1961 | udelay(10); | ||
1962 | |||
1963 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
1964 | |||
1965 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
1966 | msleep(2); | ||
1967 | } | ||
1968 | |||
1969 | static void snd_soc_ac97_reset(struct snd_ac97 *ac97) | ||
1970 | { | ||
1971 | struct pinctrl *pctl = snd_ac97_rst_cfg.pctl; | ||
1972 | |||
1973 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_reset); | ||
1974 | |||
1975 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sync, 0); | ||
1976 | gpio_direction_output(snd_ac97_rst_cfg.gpio_sdata, 0); | ||
1977 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 0); | ||
1978 | |||
1979 | udelay(10); | ||
1980 | |||
1981 | gpio_direction_output(snd_ac97_rst_cfg.gpio_reset, 1); | ||
1982 | |||
1983 | pinctrl_select_state(pctl, snd_ac97_rst_cfg.pstate_run); | ||
1984 | msleep(2); | ||
1985 | } | ||
1986 | |||
1987 | static int snd_soc_ac97_parse_pinctl(struct device *dev, | ||
1988 | struct snd_ac97_reset_cfg *cfg) | ||
1989 | { | ||
1990 | struct pinctrl *p; | ||
1991 | struct pinctrl_state *state; | ||
1992 | int gpio; | ||
1993 | int ret; | ||
1994 | |||
1995 | p = devm_pinctrl_get(dev); | ||
1996 | if (IS_ERR(p)) { | ||
1997 | dev_err(dev, "Failed to get pinctrl\n"); | ||
1998 | return PTR_ERR(p); | ||
1999 | } | ||
2000 | cfg->pctl = p; | ||
2001 | |||
2002 | state = pinctrl_lookup_state(p, "ac97-reset"); | ||
2003 | if (IS_ERR(state)) { | ||
2004 | dev_err(dev, "Can't find pinctrl state ac97-reset\n"); | ||
2005 | return PTR_ERR(state); | ||
2006 | } | ||
2007 | cfg->pstate_reset = state; | ||
2008 | |||
2009 | state = pinctrl_lookup_state(p, "ac97-warm-reset"); | ||
2010 | if (IS_ERR(state)) { | ||
2011 | dev_err(dev, "Can't find pinctrl state ac97-warm-reset\n"); | ||
2012 | return PTR_ERR(state); | ||
2013 | } | ||
2014 | cfg->pstate_warm_reset = state; | ||
2015 | |||
2016 | state = pinctrl_lookup_state(p, "ac97-running"); | ||
2017 | if (IS_ERR(state)) { | ||
2018 | dev_err(dev, "Can't find pinctrl state ac97-running\n"); | ||
2019 | return PTR_ERR(state); | ||
2020 | } | ||
2021 | cfg->pstate_run = state; | ||
2022 | |||
2023 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 0); | ||
2024 | if (gpio < 0) { | ||
2025 | dev_err(dev, "Can't find ac97-sync gpio\n"); | ||
2026 | return gpio; | ||
2027 | } | ||
2028 | ret = devm_gpio_request(dev, gpio, "AC97 link sync"); | ||
2029 | if (ret) { | ||
2030 | dev_err(dev, "Failed requesting ac97-sync gpio\n"); | ||
2031 | return ret; | ||
2032 | } | ||
2033 | cfg->gpio_sync = gpio; | ||
2034 | |||
2035 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 1); | ||
2036 | if (gpio < 0) { | ||
2037 | dev_err(dev, "Can't find ac97-sdata gpio %d\n", gpio); | ||
2038 | return gpio; | ||
2039 | } | ||
2040 | ret = devm_gpio_request(dev, gpio, "AC97 link sdata"); | ||
2041 | if (ret) { | ||
2042 | dev_err(dev, "Failed requesting ac97-sdata gpio\n"); | ||
2043 | return ret; | ||
2044 | } | ||
2045 | cfg->gpio_sdata = gpio; | ||
2046 | |||
2047 | gpio = of_get_named_gpio(dev->of_node, "ac97-gpios", 2); | ||
2048 | if (gpio < 0) { | ||
2049 | dev_err(dev, "Can't find ac97-reset gpio\n"); | ||
2050 | return gpio; | ||
2051 | } | ||
2052 | ret = devm_gpio_request(dev, gpio, "AC97 link reset"); | ||
2053 | if (ret) { | ||
2054 | dev_err(dev, "Failed requesting ac97-reset gpio\n"); | ||
2055 | return ret; | ||
2056 | } | ||
2057 | cfg->gpio_reset = gpio; | ||
2058 | |||
2059 | return 0; | ||
2060 | } | ||
2061 | |||
2062 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
2063 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
2064 | |||
2065 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
2066 | { | ||
2067 | if (ops == soc_ac97_ops) | ||
2068 | return 0; | ||
2069 | |||
2070 | if (soc_ac97_ops && ops) | ||
2071 | return -EBUSY; | ||
2072 | |||
2073 | soc_ac97_ops = ops; | ||
2074 | |||
2075 | return 0; | ||
2076 | } | ||
2077 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
2078 | |||
2079 | /** | ||
2080 | * snd_soc_set_ac97_ops_of_reset - Set ac97 ops with generic ac97 reset functions | ||
2081 | * | ||
2082 | * This function sets the reset and warm_reset properties of ops and parses | ||
2083 | * the device node of pdev to get pinctrl states and gpio numbers to use. | ||
2084 | */ | ||
2085 | int snd_soc_set_ac97_ops_of_reset(struct snd_ac97_bus_ops *ops, | ||
2086 | struct platform_device *pdev) | ||
2087 | { | ||
2088 | struct device *dev = &pdev->dev; | ||
2089 | struct snd_ac97_reset_cfg cfg; | ||
2090 | int ret; | ||
2091 | |||
2092 | ret = snd_soc_ac97_parse_pinctl(dev, &cfg); | ||
2093 | if (ret) | ||
2094 | return ret; | ||
2095 | |||
2096 | ret = snd_soc_set_ac97_ops(ops); | ||
2097 | if (ret) | ||
2098 | return ret; | ||
2099 | |||
2100 | ops->warm_reset = snd_soc_ac97_warm_reset; | ||
2101 | ops->reset = snd_soc_ac97_reset; | ||
2102 | |||
2103 | snd_ac97_rst_cfg = cfg; | ||
2104 | return 0; | ||
2105 | } | ||
2106 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops_of_reset); | ||
2107 | |||
2108 | /** | ||
2109 | * snd_soc_free_ac97_codec - free AC97 codec device | ||
2110 | * @codec: audio codec | ||
2111 | * | ||
2112 | * Frees AC97 codec device resources. | ||
2113 | */ | ||
2114 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | ||
2115 | { | ||
2116 | #ifdef CONFIG_SND_SOC_AC97_BUS | ||
2117 | soc_unregister_ac97_codec(codec); | ||
2118 | #endif | ||
2119 | kfree(codec->ac97->bus); | ||
2120 | kfree(codec->ac97); | ||
2121 | codec->ac97 = NULL; | ||
2122 | codec->ac97_created = 0; | ||
2123 | } | ||
2124 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | ||
2125 | |||
2126 | /** | ||
2127 | * snd_soc_cnew - create new control | 1783 | * snd_soc_cnew - create new control |
2128 | * @_template: control template | 1784 | * @_template: control template |
2129 | * @data: control private data | 1785 | * @data: control private data |
@@ -2947,22 +2603,62 @@ static int snd_soc_component_initialize(struct snd_soc_component *component, | |||
2947 | return 0; | 2603 | return 0; |
2948 | } | 2604 | } |
2949 | 2605 | ||
2950 | static void snd_soc_component_init_regmap(struct snd_soc_component *component) | 2606 | static void snd_soc_component_setup_regmap(struct snd_soc_component *component) |
2951 | { | 2607 | { |
2952 | if (!component->regmap) | 2608 | int val_bytes = regmap_get_val_bytes(component->regmap); |
2953 | component->regmap = dev_get_regmap(component->dev, NULL); | 2609 | |
2954 | if (component->regmap) { | 2610 | /* Errors are legitimate for non-integer byte multiples */ |
2955 | int val_bytes = regmap_get_val_bytes(component->regmap); | 2611 | if (val_bytes > 0) |
2956 | /* Errors are legitimate for non-integer byte multiples */ | 2612 | component->val_bytes = val_bytes; |
2957 | if (val_bytes > 0) | 2613 | } |
2958 | component->val_bytes = val_bytes; | 2614 | |
2959 | } | 2615 | #ifdef CONFIG_REGMAP |
2616 | |||
2617 | /** | ||
2618 | * snd_soc_component_init_regmap() - Initialize regmap instance for the component | ||
2619 | * @component: The component for which to initialize the regmap instance | ||
2620 | * @regmap: The regmap instance that should be used by the component | ||
2621 | * | ||
2622 | * This function allows deferred assignment of the regmap instance that is | ||
2623 | * associated with the component. Only use this if the regmap instance is not | ||
2624 | * yet ready when the component is registered. The function must also be called | ||
2625 | * before the first IO attempt of the component. | ||
2626 | */ | ||
2627 | void snd_soc_component_init_regmap(struct snd_soc_component *component, | ||
2628 | struct regmap *regmap) | ||
2629 | { | ||
2630 | component->regmap = regmap; | ||
2631 | snd_soc_component_setup_regmap(component); | ||
2960 | } | 2632 | } |
2633 | EXPORT_SYMBOL_GPL(snd_soc_component_init_regmap); | ||
2634 | |||
2635 | /** | ||
2636 | * snd_soc_component_exit_regmap() - De-initialize regmap instance for the component | ||
2637 | * @component: The component for which to de-initialize the regmap instance | ||
2638 | * | ||
2639 | * Calls regmap_exit() on the regmap instance associated to the component and | ||
2640 | * removes the regmap instance from the component. | ||
2641 | * | ||
2642 | * This function should only be used if snd_soc_component_init_regmap() was used | ||
2643 | * to initialize the regmap instance. | ||
2644 | */ | ||
2645 | void snd_soc_component_exit_regmap(struct snd_soc_component *component) | ||
2646 | { | ||
2647 | regmap_exit(component->regmap); | ||
2648 | component->regmap = NULL; | ||
2649 | } | ||
2650 | EXPORT_SYMBOL_GPL(snd_soc_component_exit_regmap); | ||
2651 | |||
2652 | #endif | ||
2961 | 2653 | ||
2962 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) | 2654 | static void snd_soc_component_add_unlocked(struct snd_soc_component *component) |
2963 | { | 2655 | { |
2964 | if (!component->write && !component->read) | 2656 | if (!component->write && !component->read) { |
2965 | snd_soc_component_init_regmap(component); | 2657 | if (!component->regmap) |
2658 | component->regmap = dev_get_regmap(component->dev, NULL); | ||
2659 | if (component->regmap) | ||
2660 | snd_soc_component_setup_regmap(component); | ||
2661 | } | ||
2966 | 2662 | ||
2967 | list_add(&component->list, &component_list); | 2663 | list_add(&component->list, &component_list); |
2968 | } | 2664 | } |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 3b0fa12dbff7..29a9957d335a 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -228,7 +228,7 @@ static int tegra20_ac97_probe(struct snd_soc_dai *dai) | |||
228 | 228 | ||
229 | static struct snd_soc_dai_driver tegra20_ac97_dai = { | 229 | static struct snd_soc_dai_driver tegra20_ac97_dai = { |
230 | .name = "tegra-ac97-pcm", | 230 | .name = "tegra-ac97-pcm", |
231 | .ac97_control = 1, | 231 | .bus_control = true, |
232 | .probe = tegra20_ac97_probe, | 232 | .probe = tegra20_ac97_probe, |
233 | .playback = { | 233 | .playback = { |
234 | .stream_name = "PCM Playback", | 234 | .stream_name = "PCM Playback", |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 9edd68db9f48..f7135cdaa2ca 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -152,7 +152,7 @@ static int txx9aclc_ac97_remove(struct snd_soc_dai *dai) | |||
152 | } | 152 | } |
153 | 153 | ||
154 | static struct snd_soc_dai_driver txx9aclc_ac97_dai = { | 154 | static struct snd_soc_dai_driver txx9aclc_ac97_dai = { |
155 | .ac97_control = 1, | 155 | .bus_control = true, |
156 | .probe = txx9aclc_ac97_probe, | 156 | .probe = txx9aclc_ac97_probe, |
157 | .remove = txx9aclc_ac97_remove, | 157 | .remove = txx9aclc_ac97_remove, |
158 | .playback = { | 158 | .playback = { |