diff options
Diffstat (limited to 'sound')
34 files changed, 895 insertions, 373 deletions
diff --git a/sound/soc/au1x/ac97c.c b/sound/soc/au1x/ac97c.c index 44b8dcecf571..d6f7694fcad4 100644 --- a/sound/soc/au1x/ac97c.c +++ b/sound/soc/au1x/ac97c.c | |||
@@ -179,13 +179,12 @@ static void au1xac97c_ac97_cold_reset(struct snd_ac97 *ac97) | |||
179 | } | 179 | } |
180 | 180 | ||
181 | /* AC97 controller operations */ | 181 | /* AC97 controller operations */ |
182 | struct snd_ac97_bus_ops soc_ac97_ops = { | 182 | static struct snd_ac97_bus_ops ac97c_bus_ops = { |
183 | .read = au1xac97c_ac97_read, | 183 | .read = au1xac97c_ac97_read, |
184 | .write = au1xac97c_ac97_write, | 184 | .write = au1xac97c_ac97_write, |
185 | .reset = au1xac97c_ac97_cold_reset, | 185 | .reset = au1xac97c_ac97_cold_reset, |
186 | .warm_reset = au1xac97c_ac97_warm_reset, | 186 | .warm_reset = au1xac97c_ac97_warm_reset, |
187 | }; | 187 | }; |
188 | EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ | ||
189 | 188 | ||
190 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, | 189 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, |
191 | struct snd_soc_dai *dai) | 190 | struct snd_soc_dai *dai) |
@@ -272,6 +271,10 @@ static int au1xac97c_drvprobe(struct platform_device *pdev) | |||
272 | 271 | ||
273 | platform_set_drvdata(pdev, ctx); | 272 | platform_set_drvdata(pdev, ctx); |
274 | 273 | ||
274 | ret = snd_soc_set_ac97_ops(&ac97c_bus_ops); | ||
275 | if (ret) | ||
276 | return ret; | ||
277 | |||
275 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, | 278 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, |
276 | &au1xac97c_dai_driver, 1); | 279 | &au1xac97c_dai_driver, 1); |
277 | if (ret) | 280 | if (ret) |
@@ -338,19 +341,7 @@ static struct platform_driver au1xac97c_driver = { | |||
338 | .remove = au1xac97c_drvremove, | 341 | .remove = au1xac97c_drvremove, |
339 | }; | 342 | }; |
340 | 343 | ||
341 | static int __init au1xac97c_load(void) | 344 | module_platform_driver(&au1xac97c_driver); |
342 | { | ||
343 | ac97c_workdata = NULL; | ||
344 | return platform_driver_register(&au1xac97c_driver); | ||
345 | } | ||
346 | |||
347 | static void __exit au1xac97c_unload(void) | ||
348 | { | ||
349 | platform_driver_unregister(&au1xac97c_driver); | ||
350 | } | ||
351 | |||
352 | module_init(au1xac97c_load); | ||
353 | module_exit(au1xac97c_unload); | ||
354 | 345 | ||
355 | MODULE_LICENSE("GPL"); | 346 | MODULE_LICENSE("GPL"); |
356 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); | 347 | MODULE_DESCRIPTION("Au1000/1500/1100 AC97C ASoC driver"); |
diff --git a/sound/soc/au1x/psc-ac97.c b/sound/soc/au1x/psc-ac97.c index 8f1862aa7333..a822ab822bb7 100644 --- a/sound/soc/au1x/psc-ac97.c +++ b/sound/soc/au1x/psc-ac97.c | |||
@@ -201,13 +201,12 @@ static void au1xpsc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
201 | } | 201 | } |
202 | 202 | ||
203 | /* AC97 controller operations */ | 203 | /* AC97 controller operations */ |
204 | struct snd_ac97_bus_ops soc_ac97_ops = { | 204 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
205 | .read = au1xpsc_ac97_read, | 205 | .read = au1xpsc_ac97_read, |
206 | .write = au1xpsc_ac97_write, | 206 | .write = au1xpsc_ac97_write, |
207 | .reset = au1xpsc_ac97_cold_reset, | 207 | .reset = au1xpsc_ac97_cold_reset, |
208 | .warm_reset = au1xpsc_ac97_warm_reset, | 208 | .warm_reset = au1xpsc_ac97_warm_reset, |
209 | }; | 209 | }; |
210 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
211 | 210 | ||
212 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, | 211 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, |
213 | struct snd_pcm_hw_params *params, | 212 | struct snd_pcm_hw_params *params, |
@@ -383,15 +382,9 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
383 | if (!iores) | 382 | if (!iores) |
384 | return -ENODEV; | 383 | return -ENODEV; |
385 | 384 | ||
386 | if (!devm_request_mem_region(&pdev->dev, iores->start, | 385 | wd->mmio = devm_ioremap_resource(&pdev->dev, iores); |
387 | resource_size(iores), | 386 | if (IS_ERR(wd->mmio)) |
388 | pdev->name)) | 387 | return PTR_ERR(wd->mmio); |
389 | return -EBUSY; | ||
390 | |||
391 | wd->mmio = devm_ioremap(&pdev->dev, iores->start, | ||
392 | resource_size(iores)); | ||
393 | if (!wd->mmio) | ||
394 | return -EBUSY; | ||
395 | 388 | ||
396 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); | 389 | dmares = platform_get_resource(pdev, IORESOURCE_DMA, 0); |
397 | if (!dmares) | 390 | if (!dmares) |
@@ -423,6 +416,10 @@ static int au1xpsc_ac97_drvprobe(struct platform_device *pdev) | |||
423 | 416 | ||
424 | platform_set_drvdata(pdev, wd); | 417 | platform_set_drvdata(pdev, wd); |
425 | 418 | ||
419 | ret = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
420 | if (ret) | ||
421 | return ret; | ||
422 | |||
426 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, | 423 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, |
427 | &wd->dai_drv, 1); | 424 | &wd->dai_drv, 1); |
428 | if (ret) | 425 | if (ret) |
@@ -503,19 +500,7 @@ static struct platform_driver au1xpsc_ac97_driver = { | |||
503 | .remove = au1xpsc_ac97_drvremove, | 500 | .remove = au1xpsc_ac97_drvremove, |
504 | }; | 501 | }; |
505 | 502 | ||
506 | static int __init au1xpsc_ac97_load(void) | 503 | module_platform_driver(au1xpsc_ac97_driver); |
507 | { | ||
508 | au1xpsc_ac97_workdata = NULL; | ||
509 | return platform_driver_register(&au1xpsc_ac97_driver); | ||
510 | } | ||
511 | |||
512 | static void __exit au1xpsc_ac97_unload(void) | ||
513 | { | ||
514 | platform_driver_unregister(&au1xpsc_ac97_driver); | ||
515 | } | ||
516 | |||
517 | module_init(au1xpsc_ac97_load); | ||
518 | module_exit(au1xpsc_ac97_unload); | ||
519 | 504 | ||
520 | MODULE_LICENSE("GPL"); | 505 | MODULE_LICENSE("GPL"); |
521 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); | 506 | MODULE_DESCRIPTION("Au12x0/Au1550 PSC AC97 ALSA ASoC audio driver"); |
diff --git a/sound/soc/blackfin/bf5xx-ac97.c b/sound/soc/blackfin/bf5xx-ac97.c index c66bef826ac5..efb1daecd0dd 100644 --- a/sound/soc/blackfin/bf5xx-ac97.c +++ b/sound/soc/blackfin/bf5xx-ac97.c | |||
@@ -198,13 +198,12 @@ static void bf5xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
198 | #endif | 198 | #endif |
199 | } | 199 | } |
200 | 200 | ||
201 | struct snd_ac97_bus_ops soc_ac97_ops = { | 201 | static struct snd_ac97_bus_ops bf5xx_ac97_ops = { |
202 | .read = bf5xx_ac97_read, | 202 | .read = bf5xx_ac97_read, |
203 | .write = bf5xx_ac97_write, | 203 | .write = bf5xx_ac97_write, |
204 | .warm_reset = bf5xx_ac97_warm_reset, | 204 | .warm_reset = bf5xx_ac97_warm_reset, |
205 | .reset = bf5xx_ac97_cold_reset, | 205 | .reset = bf5xx_ac97_cold_reset, |
206 | }; | 206 | }; |
207 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
208 | 207 | ||
209 | #ifdef CONFIG_PM | 208 | #ifdef CONFIG_PM |
210 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) | 209 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
@@ -293,13 +292,14 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
293 | 292 | ||
294 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 293 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET |
295 | /* Request PB3 as reset pin */ | 294 | /* Request PB3 as reset pin */ |
296 | if (gpio_request(CONFIG_SND_BF5XX_RESET_GPIO_NUM, "SND_AD198x RESET")) { | 295 | ret = devm_gpio_request_one(&pdev->dev, |
297 | pr_err("Failed to request GPIO_%d for reset\n", | 296 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, |
298 | CONFIG_SND_BF5XX_RESET_GPIO_NUM); | 297 | GPIOF_OUT_INIT_HIGH, "SND_AD198x RESET") { |
299 | ret = -1; | 298 | dev_err(&pdev->dev, |
299 | "Failed to request GPIO_%d for reset: %d\n", | ||
300 | CONFIG_SND_BF5XX_RESET_GPIO_NUM, ret); | ||
300 | goto gpio_err; | 301 | goto gpio_err; |
301 | } | 302 | } |
302 | gpio_direction_output(CONFIG_SND_BF5XX_RESET_GPIO_NUM, 1); | ||
303 | #endif | 303 | #endif |
304 | 304 | ||
305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), | 305 | sport_handle = sport_init(pdev, 2, sizeof(struct ac97_frame), |
@@ -335,6 +335,12 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
335 | goto sport_config_err; | 335 | goto sport_config_err; |
336 | } | 336 | } |
337 | 337 | ||
338 | ret = snd_soc_set_ac97_ops(&bf5xx_ac97_ops); | ||
339 | if (ret != 0) { | ||
340 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
341 | goto sport_config_err; | ||
342 | } | ||
343 | |||
338 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, | 344 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, |
339 | &bfin_ac97_dai, 1); | 345 | &bfin_ac97_dai, 1); |
340 | if (ret) { | 346 | if (ret) { |
@@ -349,10 +355,7 @@ static int asoc_bfin_ac97_probe(struct platform_device *pdev) | |||
349 | sport_config_err: | 355 | sport_config_err: |
350 | sport_done(sport_handle); | 356 | sport_done(sport_handle); |
351 | sport_err: | 357 | sport_err: |
352 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 358 | snd_soc_set_ac97_ops(NULL); |
353 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
354 | gpio_err: | ||
355 | #endif | ||
356 | 359 | ||
357 | return ret; | 360 | return ret; |
358 | } | 361 | } |
@@ -363,9 +366,7 @@ static int asoc_bfin_ac97_remove(struct platform_device *pdev) | |||
363 | 366 | ||
364 | snd_soc_unregister_component(&pdev->dev); | 367 | snd_soc_unregister_component(&pdev->dev); |
365 | sport_done(sport_handle); | 368 | sport_done(sport_handle); |
366 | #ifdef CONFIG_SND_BF5XX_HAVE_COLD_RESET | 369 | snd_soc_set_ac97_ops(NULL); |
367 | gpio_free(CONFIG_SND_BF5XX_RESET_GPIO_NUM); | ||
368 | #endif | ||
369 | 370 | ||
370 | return 0; | 371 | return 0; |
371 | } | 372 | } |
diff --git a/sound/soc/cirrus/ep93xx-ac97.c b/sound/soc/cirrus/ep93xx-ac97.c index 3f4f88877c84..ac73c607410a 100644 --- a/sound/soc/cirrus/ep93xx-ac97.c +++ b/sound/soc/cirrus/ep93xx-ac97.c | |||
@@ -237,13 +237,12 @@ static irqreturn_t ep93xx_ac97_interrupt(int irq, void *dev_id) | |||
237 | return IRQ_HANDLED; | 237 | return IRQ_HANDLED; |
238 | } | 238 | } |
239 | 239 | ||
240 | struct snd_ac97_bus_ops soc_ac97_ops = { | 240 | static struct snd_ac97_bus_ops ep93xx_ac97_ops = { |
241 | .read = ep93xx_ac97_read, | 241 | .read = ep93xx_ac97_read, |
242 | .write = ep93xx_ac97_write, | 242 | .write = ep93xx_ac97_write, |
243 | .reset = ep93xx_ac97_cold_reset, | 243 | .reset = ep93xx_ac97_cold_reset, |
244 | .warm_reset = ep93xx_ac97_warm_reset, | 244 | .warm_reset = ep93xx_ac97_warm_reset, |
245 | }; | 245 | }; |
246 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
247 | 246 | ||
248 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, | 247 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, |
249 | int cmd, struct snd_soc_dai *dai) | 248 | int cmd, struct snd_soc_dai *dai) |
@@ -389,6 +388,10 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
389 | ep93xx_ac97_info = info; | 388 | ep93xx_ac97_info = info; |
390 | platform_set_drvdata(pdev, info); | 389 | platform_set_drvdata(pdev, info); |
391 | 390 | ||
391 | ret = snd_soc_set_ac97_ops(&ep93xx_ac97_ops); | ||
392 | if (ret) | ||
393 | goto fail; | ||
394 | |||
392 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, | 395 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, |
393 | &ep93xx_ac97_dai, 1); | 396 | &ep93xx_ac97_dai, 1); |
394 | if (ret) | 397 | if (ret) |
@@ -398,7 +401,7 @@ static int ep93xx_ac97_probe(struct platform_device *pdev) | |||
398 | 401 | ||
399 | fail: | 402 | fail: |
400 | ep93xx_ac97_info = NULL; | 403 | ep93xx_ac97_info = NULL; |
401 | dev_set_drvdata(&pdev->dev, NULL); | 404 | snd_soc_set_ac97_ops(NULL); |
402 | return ret; | 405 | return ret; |
403 | } | 406 | } |
404 | 407 | ||
@@ -412,7 +415,8 @@ static int ep93xx_ac97_remove(struct platform_device *pdev) | |||
412 | ep93xx_ac97_write_reg(info, AC97GCR, 0); | 415 | ep93xx_ac97_write_reg(info, AC97GCR, 0); |
413 | 416 | ||
414 | ep93xx_ac97_info = NULL; | 417 | ep93xx_ac97_info = NULL; |
415 | dev_set_drvdata(&pdev->dev, NULL); | 418 | |
419 | snd_soc_set_ac97_ops(NULL); | ||
416 | 420 | ||
417 | return 0; | 421 | return 0; |
418 | } | 422 | } |
diff --git a/sound/soc/codecs/88pm860x-codec.c b/sound/soc/codecs/88pm860x-codec.c index 1382f3f3f4bf..8af04343cc1a 100644 --- a/sound/soc/codecs/88pm860x-codec.c +++ b/sound/soc/codecs/88pm860x-codec.c | |||
@@ -120,10 +120,8 @@ | |||
120 | * before DAC & PGA in DAPM power-off sequence. | 120 | * before DAC & PGA in DAPM power-off sequence. |
121 | */ | 121 | */ |
122 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ | 122 | #define PM860X_DAPM_OUTPUT(wname, wevent) \ |
123 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 123 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, 0, 0, NULL, 0, wevent, \ |
124 | .shift = 0, .invert = 0, .kcontrol_news = NULL, \ | 124 | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD) |
125 | .num_kcontrols = 0, .event = wevent, \ | ||
126 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD, } | ||
127 | 125 | ||
128 | struct pm860x_det { | 126 | struct pm860x_det { |
129 | struct snd_soc_jack *hp_jack; | 127 | struct snd_soc_jack *hp_jack; |
diff --git a/sound/soc/codecs/ac97.c b/sound/soc/codecs/ac97.c index ef2ae32ffc66..ec7351803c24 100644 --- a/sound/soc/codecs/ac97.c +++ b/sound/soc/codecs/ac97.c | |||
@@ -62,13 +62,13 @@ static struct snd_soc_dai_driver ac97_dai = { | |||
62 | static unsigned int ac97_read(struct snd_soc_codec *codec, | 62 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
63 | unsigned int reg) | 63 | unsigned int reg) |
64 | { | 64 | { |
65 | return soc_ac97_ops.read(codec->ac97, reg); | 65 | return soc_ac97_ops->read(codec->ac97, reg); |
66 | } | 66 | } |
67 | 67 | ||
68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | 68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
69 | unsigned int val) | 69 | unsigned int val) |
70 | { | 70 | { |
71 | soc_ac97_ops.write(codec->ac97, reg, val); | 71 | soc_ac97_ops->write(codec->ac97, reg, val); |
72 | return 0; | 72 | return 0; |
73 | } | 73 | } |
74 | 74 | ||
@@ -79,7 +79,8 @@ static int ac97_soc_probe(struct snd_soc_codec *codec) | |||
79 | int ret; | 79 | int ret; |
80 | 80 | ||
81 | /* add codec as bus device for standard ac97 */ | 81 | /* add codec as bus device for standard ac97 */ |
82 | ret = snd_ac97_bus(codec->card->snd_card, 0, &soc_ac97_ops, NULL, &ac97_bus); | 82 | ret = snd_ac97_bus(codec->card->snd_card, 0, soc_ac97_ops, NULL, |
83 | &ac97_bus); | ||
83 | if (ret < 0) | 84 | if (ret < 0) |
84 | return ret; | 85 | return ret; |
85 | 86 | ||
diff --git a/sound/soc/codecs/ad1980.c b/sound/soc/codecs/ad1980.c index f385342947d3..89fcf7d6e7b8 100644 --- a/sound/soc/codecs/ad1980.c +++ b/sound/soc/codecs/ad1980.c | |||
@@ -108,7 +108,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
108 | case AC97_EXTENDED_STATUS: | 108 | case AC97_EXTENDED_STATUS: |
109 | case AC97_VENDOR_ID1: | 109 | case AC97_VENDOR_ID1: |
110 | case AC97_VENDOR_ID2: | 110 | case AC97_VENDOR_ID2: |
111 | return soc_ac97_ops.read(codec->ac97, reg); | 111 | return soc_ac97_ops->read(codec->ac97, reg); |
112 | default: | 112 | default: |
113 | reg = reg >> 1; | 113 | reg = reg >> 1; |
114 | 114 | ||
@@ -124,7 +124,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
124 | { | 124 | { |
125 | u16 *cache = codec->reg_cache; | 125 | u16 *cache = codec->reg_cache; |
126 | 126 | ||
127 | soc_ac97_ops.write(codec->ac97, reg, val); | 127 | soc_ac97_ops->write(codec->ac97, reg, val); |
128 | reg = reg >> 1; | 128 | reg = reg >> 1; |
129 | if (reg < ARRAY_SIZE(ad1980_reg)) | 129 | if (reg < ARRAY_SIZE(ad1980_reg)) |
130 | cache[reg] = val; | 130 | cache[reg] = val; |
@@ -154,13 +154,13 @@ static int ad1980_reset(struct snd_soc_codec *codec, int try_warm) | |||
154 | u16 retry_cnt = 0; | 154 | u16 retry_cnt = 0; |
155 | 155 | ||
156 | retry: | 156 | retry: |
157 | if (try_warm && soc_ac97_ops.warm_reset) { | 157 | if (try_warm && soc_ac97_ops->warm_reset) { |
158 | soc_ac97_ops.warm_reset(codec->ac97); | 158 | soc_ac97_ops->warm_reset(codec->ac97); |
159 | if (ac97_read(codec, AC97_RESET) == 0x0090) | 159 | if (ac97_read(codec, AC97_RESET) == 0x0090) |
160 | return 1; | 160 | return 1; |
161 | } | 161 | } |
162 | 162 | ||
163 | soc_ac97_ops.reset(codec->ac97); | 163 | soc_ac97_ops->reset(codec->ac97); |
164 | /* Set bit 16slot in register 74h, then every slot will has only 16 | 164 | /* Set bit 16slot in register 74h, then every slot will has only 16 |
165 | * bits. This command is sent out in 20bit mode, in which case the | 165 | * bits. This command is sent out in 20bit mode, in which case the |
166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ | 166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ |
@@ -186,7 +186,7 @@ static int ad1980_soc_probe(struct snd_soc_codec *codec) | |||
186 | 186 | ||
187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); | 187 | printk(KERN_INFO "AD1980 SoC Audio Codec\n"); |
188 | 188 | ||
189 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 189 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
190 | if (ret < 0) { | 190 | if (ret < 0) { |
191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
192 | return ret; | 192 | return ret; |
diff --git a/sound/soc/codecs/adau1701.c b/sound/soc/codecs/adau1701.c index b6b1a773bd37..0e250f118c0e 100644 --- a/sound/soc/codecs/adau1701.c +++ b/sound/soc/codecs/adau1701.c | |||
@@ -16,6 +16,7 @@ | |||
16 | #include <linux/of.h> | 16 | #include <linux/of.h> |
17 | #include <linux/of_gpio.h> | 17 | #include <linux/of_gpio.h> |
18 | #include <linux/of_device.h> | 18 | #include <linux/of_device.h> |
19 | #include <linux/regmap.h> | ||
19 | #include <sound/core.h> | 20 | #include <sound/core.h> |
20 | #include <sound/pcm.h> | 21 | #include <sound/pcm.h> |
21 | #include <sound/pcm_params.h> | 22 | #include <sound/pcm_params.h> |
@@ -24,16 +25,19 @@ | |||
24 | #include "sigmadsp.h" | 25 | #include "sigmadsp.h" |
25 | #include "adau1701.h" | 26 | #include "adau1701.h" |
26 | 27 | ||
27 | #define ADAU1701_DSPCTRL 0x1c | 28 | #define ADAU1701_DSPCTRL 0x081c |
28 | #define ADAU1701_SEROCTL 0x1e | 29 | #define ADAU1701_SEROCTL 0x081e |
29 | #define ADAU1701_SERICTL 0x1f | 30 | #define ADAU1701_SERICTL 0x081f |
30 | 31 | ||
31 | #define ADAU1701_AUXNPOW 0x22 | 32 | #define ADAU1701_AUXNPOW 0x0822 |
33 | #define ADAU1701_PINCONF_0 0x0820 | ||
34 | #define ADAU1701_PINCONF_1 0x0821 | ||
35 | #define ADAU1701_AUXNPOW 0x0822 | ||
32 | 36 | ||
33 | #define ADAU1701_OSCIPOW 0x26 | 37 | #define ADAU1701_OSCIPOW 0x0826 |
34 | #define ADAU1701_DACSET 0x27 | 38 | #define ADAU1701_DACSET 0x0827 |
35 | 39 | ||
36 | #define ADAU1701_NUM_REGS 0x28 | 40 | #define ADAU1701_MAX_REGISTER 0x0828 |
37 | 41 | ||
38 | #define ADAU1701_DSPCTRL_CR (1 << 2) | 42 | #define ADAU1701_DSPCTRL_CR (1 << 2) |
39 | #define ADAU1701_DSPCTRL_DAM (1 << 3) | 43 | #define ADAU1701_DSPCTRL_DAM (1 << 3) |
@@ -87,11 +91,18 @@ | |||
87 | #define ADAU1701_OSCIPOW_OPD 0x04 | 91 | #define ADAU1701_OSCIPOW_OPD 0x04 |
88 | #define ADAU1701_DACSET_DACINIT 1 | 92 | #define ADAU1701_DACSET_DACINIT 1 |
89 | 93 | ||
94 | #define ADAU1707_CLKDIV_UNSET (-1UL) | ||
95 | |||
90 | #define ADAU1701_FIRMWARE "adau1701.bin" | 96 | #define ADAU1701_FIRMWARE "adau1701.bin" |
91 | 97 | ||
92 | struct adau1701 { | 98 | struct adau1701 { |
93 | int gpio_nreset; | 99 | int gpio_nreset; |
100 | int gpio_pll_mode[2]; | ||
94 | unsigned int dai_fmt; | 101 | unsigned int dai_fmt; |
102 | unsigned int pll_clkdiv; | ||
103 | unsigned int sysclk; | ||
104 | struct regmap *regmap; | ||
105 | u8 pin_config[12]; | ||
95 | }; | 106 | }; |
96 | 107 | ||
97 | static const struct snd_kcontrol_new adau1701_controls[] = { | 108 | static const struct snd_kcontrol_new adau1701_controls[] = { |
@@ -123,10 +134,13 @@ static const struct snd_soc_dapm_route adau1701_dapm_routes[] = { | |||
123 | { "ADC", NULL, "IN1" }, | 134 | { "ADC", NULL, "IN1" }, |
124 | }; | 135 | }; |
125 | 136 | ||
126 | static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | 137 | static unsigned int adau1701_register_size(struct device *dev, |
127 | unsigned int reg) | 138 | unsigned int reg) |
128 | { | 139 | { |
129 | switch (reg) { | 140 | switch (reg) { |
141 | case ADAU1701_PINCONF_0: | ||
142 | case ADAU1701_PINCONF_1: | ||
143 | return 3; | ||
130 | case ADAU1701_DSPCTRL: | 144 | case ADAU1701_DSPCTRL: |
131 | case ADAU1701_SEROCTL: | 145 | case ADAU1701_SEROCTL: |
132 | case ADAU1701_AUXNPOW: | 146 | case ADAU1701_AUXNPOW: |
@@ -137,33 +151,42 @@ static unsigned int adau1701_register_size(struct snd_soc_codec *codec, | |||
137 | return 1; | 151 | return 1; |
138 | } | 152 | } |
139 | 153 | ||
140 | dev_err(codec->dev, "Unsupported register address: %d\n", reg); | 154 | dev_err(dev, "Unsupported register address: %d\n", reg); |
141 | return 0; | 155 | return 0; |
142 | } | 156 | } |
143 | 157 | ||
144 | static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | 158 | static bool adau1701_volatile_reg(struct device *dev, unsigned int reg) |
145 | unsigned int value) | ||
146 | { | 159 | { |
160 | switch (reg) { | ||
161 | case ADAU1701_DACSET: | ||
162 | return true; | ||
163 | default: | ||
164 | return false; | ||
165 | } | ||
166 | } | ||
167 | |||
168 | static int adau1701_reg_write(void *context, unsigned int reg, | ||
169 | unsigned int value) | ||
170 | { | ||
171 | struct i2c_client *client = context; | ||
147 | unsigned int i; | 172 | unsigned int i; |
148 | unsigned int size; | 173 | unsigned int size; |
149 | uint8_t buf[4]; | 174 | uint8_t buf[5]; |
150 | int ret; | 175 | int ret; |
151 | 176 | ||
152 | size = adau1701_register_size(codec, reg); | 177 | size = adau1701_register_size(&client->dev, reg); |
153 | if (size == 0) | 178 | if (size == 0) |
154 | return -EINVAL; | 179 | return -EINVAL; |
155 | 180 | ||
156 | snd_soc_cache_write(codec, reg, value); | 181 | buf[0] = reg >> 8; |
157 | 182 | buf[1] = reg & 0xff; | |
158 | buf[0] = 0x08; | ||
159 | buf[1] = reg; | ||
160 | 183 | ||
161 | for (i = size + 1; i >= 2; --i) { | 184 | for (i = size + 1; i >= 2; --i) { |
162 | buf[i] = value; | 185 | buf[i] = value; |
163 | value >>= 8; | 186 | value >>= 8; |
164 | } | 187 | } |
165 | 188 | ||
166 | ret = i2c_master_send(to_i2c_client(codec->dev), buf, size + 2); | 189 | ret = i2c_master_send(client, buf, size + 2); |
167 | if (ret == size + 2) | 190 | if (ret == size + 2) |
168 | return 0; | 191 | return 0; |
169 | else if (ret < 0) | 192 | else if (ret < 0) |
@@ -172,47 +195,105 @@ static int adau1701_write(struct snd_soc_codec *codec, unsigned int reg, | |||
172 | return -EIO; | 195 | return -EIO; |
173 | } | 196 | } |
174 | 197 | ||
175 | static unsigned int adau1701_read(struct snd_soc_codec *codec, unsigned int reg) | 198 | static int adau1701_reg_read(void *context, unsigned int reg, |
199 | unsigned int *value) | ||
176 | { | 200 | { |
177 | unsigned int value; | 201 | int ret; |
178 | unsigned int ret; | 202 | unsigned int i; |
203 | unsigned int size; | ||
204 | uint8_t send_buf[2], recv_buf[3]; | ||
205 | struct i2c_client *client = context; | ||
206 | struct i2c_msg msgs[2]; | ||
179 | 207 | ||
180 | ret = snd_soc_cache_read(codec, reg, &value); | 208 | size = adau1701_register_size(&client->dev, reg); |
181 | if (ret) | 209 | if (size == 0) |
182 | return ret; | 210 | return -EINVAL; |
183 | 211 | ||
184 | return value; | 212 | send_buf[0] = reg >> 8; |
185 | } | 213 | send_buf[1] = reg & 0xff; |
186 | 214 | ||
187 | static void adau1701_reset(struct snd_soc_codec *codec) | 215 | msgs[0].addr = client->addr; |
188 | { | 216 | msgs[0].len = sizeof(send_buf); |
189 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | 217 | msgs[0].buf = send_buf; |
218 | msgs[0].flags = 0; | ||
190 | 219 | ||
191 | if (!gpio_is_valid(adau1701->gpio_nreset)) | 220 | msgs[1].addr = client->addr; |
192 | return; | 221 | msgs[1].len = size; |
222 | msgs[1].buf = recv_buf; | ||
223 | msgs[1].flags = I2C_M_RD; | ||
193 | 224 | ||
194 | gpio_set_value(adau1701->gpio_nreset, 0); | 225 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); |
195 | /* minimum reset time is 20ns */ | 226 | if (ret < 0) |
196 | udelay(1); | 227 | return ret; |
197 | gpio_set_value(adau1701->gpio_nreset, 1); | 228 | else if (ret != ARRAY_SIZE(msgs)) |
198 | /* power-up time may be as long as 85ms */ | 229 | return -EIO; |
199 | mdelay(85); | 230 | |
231 | *value = 0; | ||
232 | |||
233 | for (i = 0; i < size; i++) | ||
234 | *value |= recv_buf[i] << (i * 8); | ||
235 | |||
236 | return 0; | ||
200 | } | 237 | } |
201 | 238 | ||
202 | static int adau1701_init(struct snd_soc_codec *codec) | 239 | static int adau1701_reset(struct snd_soc_codec *codec, unsigned int clkdiv) |
203 | { | 240 | { |
204 | int ret; | 241 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); |
205 | struct i2c_client *client = to_i2c_client(codec->dev); | 242 | struct i2c_client *client = to_i2c_client(codec->dev); |
243 | int ret; | ||
206 | 244 | ||
207 | adau1701_reset(codec); | 245 | if (clkdiv != ADAU1707_CLKDIV_UNSET && |
246 | gpio_is_valid(adau1701->gpio_pll_mode[0]) && | ||
247 | gpio_is_valid(adau1701->gpio_pll_mode[1])) { | ||
248 | switch (clkdiv) { | ||
249 | case 64: | ||
250 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
251 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
252 | break; | ||
253 | case 256: | ||
254 | gpio_set_value(adau1701->gpio_pll_mode[0], 0); | ||
255 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
256 | break; | ||
257 | case 384: | ||
258 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
259 | gpio_set_value(adau1701->gpio_pll_mode[1], 0); | ||
260 | break; | ||
261 | case 0: /* fallback */ | ||
262 | case 512: | ||
263 | gpio_set_value(adau1701->gpio_pll_mode[0], 1); | ||
264 | gpio_set_value(adau1701->gpio_pll_mode[1], 1); | ||
265 | break; | ||
266 | } | ||
267 | } | ||
208 | 268 | ||
209 | ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); | 269 | adau1701->pll_clkdiv = clkdiv; |
210 | if (ret) { | 270 | |
211 | dev_warn(codec->dev, "Failed to load firmware\n"); | 271 | if (gpio_is_valid(adau1701->gpio_nreset)) { |
212 | return ret; | 272 | gpio_set_value(adau1701->gpio_nreset, 0); |
273 | /* minimum reset time is 20ns */ | ||
274 | udelay(1); | ||
275 | gpio_set_value(adau1701->gpio_nreset, 1); | ||
276 | /* power-up time may be as long as 85ms */ | ||
277 | mdelay(85); | ||
213 | } | 278 | } |
214 | 279 | ||
215 | snd_soc_write(codec, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | 280 | /* |
281 | * Postpone the firmware download to a point in time when we | ||
282 | * know the correct PLL setup | ||
283 | */ | ||
284 | if (clkdiv != ADAU1707_CLKDIV_UNSET) { | ||
285 | ret = process_sigma_firmware(client, ADAU1701_FIRMWARE); | ||
286 | if (ret) { | ||
287 | dev_warn(codec->dev, "Failed to load firmware\n"); | ||
288 | return ret; | ||
289 | } | ||
290 | } | ||
291 | |||
292 | regmap_write(adau1701->regmap, ADAU1701_DACSET, ADAU1701_DACSET_DACINIT); | ||
293 | regmap_write(adau1701->regmap, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | ||
294 | |||
295 | regcache_mark_dirty(adau1701->regmap); | ||
296 | regcache_sync(adau1701->regmap); | ||
216 | 297 | ||
217 | return 0; | 298 | return 0; |
218 | } | 299 | } |
@@ -291,8 +372,22 @@ static int adau1701_hw_params(struct snd_pcm_substream *substream, | |||
291 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) | 372 | struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) |
292 | { | 373 | { |
293 | struct snd_soc_codec *codec = dai->codec; | 374 | struct snd_soc_codec *codec = dai->codec; |
375 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
376 | unsigned int clkdiv = adau1701->sysclk / params_rate(params); | ||
294 | snd_pcm_format_t format; | 377 | snd_pcm_format_t format; |
295 | unsigned int val; | 378 | unsigned int val; |
379 | int ret; | ||
380 | |||
381 | /* | ||
382 | * If the mclk/lrclk ratio changes, the chip needs updated PLL | ||
383 | * mode GPIO settings, and a full reset cycle, including a new | ||
384 | * firmware upload. | ||
385 | */ | ||
386 | if (clkdiv != adau1701->pll_clkdiv) { | ||
387 | ret = adau1701_reset(codec, clkdiv); | ||
388 | if (ret < 0) | ||
389 | return ret; | ||
390 | } | ||
296 | 391 | ||
297 | switch (params_rate(params)) { | 392 | switch (params_rate(params)) { |
298 | case 192000: | 393 | case 192000: |
@@ -384,8 +479,8 @@ static int adau1701_set_dai_fmt(struct snd_soc_dai *codec_dai, | |||
384 | 479 | ||
385 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; | 480 | adau1701->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; |
386 | 481 | ||
387 | snd_soc_write(codec, ADAU1701_SERICTL, serictl); | 482 | regmap_write(adau1701->regmap, ADAU1701_SERICTL, serictl); |
388 | snd_soc_update_bits(codec, ADAU1701_SEROCTL, | 483 | regmap_update_bits(adau1701->regmap, ADAU1701_SEROCTL, |
389 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); | 484 | ~ADAU1701_SEROCTL_WORD_LEN_MASK, seroctl); |
390 | 485 | ||
391 | return 0; | 486 | return 0; |
@@ -435,6 +530,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
435 | int source, unsigned int freq, int dir) | 530 | int source, unsigned int freq, int dir) |
436 | { | 531 | { |
437 | unsigned int val; | 532 | unsigned int val; |
533 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
438 | 534 | ||
439 | switch (clk_id) { | 535 | switch (clk_id) { |
440 | case ADAU1701_CLK_SRC_OSC: | 536 | case ADAU1701_CLK_SRC_OSC: |
@@ -448,6 +544,7 @@ static int adau1701_set_sysclk(struct snd_soc_codec *codec, int clk_id, | |||
448 | } | 544 | } |
449 | 545 | ||
450 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); | 546 | snd_soc_update_bits(codec, ADAU1701_OSCIPOW, ADAU1701_OSCIPOW_OPD, val); |
547 | adau1701->sysclk = freq; | ||
451 | 548 | ||
452 | return 0; | 549 | return 0; |
453 | } | 550 | } |
@@ -494,15 +591,37 @@ MODULE_DEVICE_TABLE(of, adau1701_dt_ids); | |||
494 | 591 | ||
495 | static int adau1701_probe(struct snd_soc_codec *codec) | 592 | static int adau1701_probe(struct snd_soc_codec *codec) |
496 | { | 593 | { |
497 | int ret; | 594 | int i, ret; |
595 | unsigned int val; | ||
596 | struct adau1701 *adau1701 = snd_soc_codec_get_drvdata(codec); | ||
498 | 597 | ||
499 | codec->control_data = to_i2c_client(codec->dev); | 598 | codec->control_data = to_i2c_client(codec->dev); |
500 | 599 | ||
501 | ret = adau1701_init(codec); | 600 | /* |
502 | if (ret) | 601 | * Let the pll_clkdiv variable default to something that won't happen |
602 | * at runtime. That way, we can postpone the firmware download from | ||
603 | * adau1701_reset() to a point in time when we know the correct PLL | ||
604 | * mode parameters. | ||
605 | */ | ||
606 | adau1701->pll_clkdiv = ADAU1707_CLKDIV_UNSET; | ||
607 | |||
608 | /* initalize with pre-configured pll mode settings */ | ||
609 | ret = adau1701_reset(codec, adau1701->pll_clkdiv); | ||
610 | if (ret < 0) | ||
503 | return ret; | 611 | return ret; |
504 | 612 | ||
505 | snd_soc_write(codec, ADAU1701_DSPCTRL, ADAU1701_DSPCTRL_CR); | 613 | /* set up pin config */ |
614 | val = 0; | ||
615 | for (i = 0; i < 6; i++) | ||
616 | val |= adau1701->pin_config[i] << (i * 4); | ||
617 | |||
618 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_0, val); | ||
619 | |||
620 | val = 0; | ||
621 | for (i = 0; i < 6; i++) | ||
622 | val |= adau1701->pin_config[i + 6] << (i * 4); | ||
623 | |||
624 | regmap_write(adau1701->regmap, ADAU1701_PINCONF_1, val); | ||
506 | 625 | ||
507 | return 0; | 626 | return 0; |
508 | } | 627 | } |
@@ -512,9 +631,6 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
512 | .set_bias_level = adau1701_set_bias_level, | 631 | .set_bias_level = adau1701_set_bias_level, |
513 | .idle_bias_off = true, | 632 | .idle_bias_off = true, |
514 | 633 | ||
515 | .reg_cache_size = ADAU1701_NUM_REGS, | ||
516 | .reg_word_size = sizeof(u16), | ||
517 | |||
518 | .controls = adau1701_controls, | 634 | .controls = adau1701_controls, |
519 | .num_controls = ARRAY_SIZE(adau1701_controls), | 635 | .num_controls = ARRAY_SIZE(adau1701_controls), |
520 | .dapm_widgets = adau1701_dapm_widgets, | 636 | .dapm_widgets = adau1701_dapm_widgets, |
@@ -522,28 +638,58 @@ static struct snd_soc_codec_driver adau1701_codec_drv = { | |||
522 | .dapm_routes = adau1701_dapm_routes, | 638 | .dapm_routes = adau1701_dapm_routes, |
523 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), | 639 | .num_dapm_routes = ARRAY_SIZE(adau1701_dapm_routes), |
524 | 640 | ||
525 | .write = adau1701_write, | ||
526 | .read = adau1701_read, | ||
527 | |||
528 | .set_sysclk = adau1701_set_sysclk, | 641 | .set_sysclk = adau1701_set_sysclk, |
529 | }; | 642 | }; |
530 | 643 | ||
644 | static const struct regmap_config adau1701_regmap = { | ||
645 | .reg_bits = 16, | ||
646 | .val_bits = 32, | ||
647 | .max_register = ADAU1701_MAX_REGISTER, | ||
648 | .cache_type = REGCACHE_RBTREE, | ||
649 | .volatile_reg = adau1701_volatile_reg, | ||
650 | .reg_write = adau1701_reg_write, | ||
651 | .reg_read = adau1701_reg_read, | ||
652 | }; | ||
653 | |||
531 | static int adau1701_i2c_probe(struct i2c_client *client, | 654 | static int adau1701_i2c_probe(struct i2c_client *client, |
532 | const struct i2c_device_id *id) | 655 | const struct i2c_device_id *id) |
533 | { | 656 | { |
534 | struct adau1701 *adau1701; | 657 | struct adau1701 *adau1701; |
535 | struct device *dev = &client->dev; | 658 | struct device *dev = &client->dev; |
536 | int gpio_nreset = -EINVAL; | 659 | int gpio_nreset = -EINVAL; |
660 | int gpio_pll_mode[2] = { -EINVAL, -EINVAL }; | ||
537 | int ret; | 661 | int ret; |
538 | 662 | ||
539 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); | 663 | adau1701 = devm_kzalloc(dev, sizeof(*adau1701), GFP_KERNEL); |
540 | if (!adau1701) | 664 | if (!adau1701) |
541 | return -ENOMEM; | 665 | return -ENOMEM; |
542 | 666 | ||
667 | adau1701->regmap = devm_regmap_init(dev, NULL, client, | ||
668 | &adau1701_regmap); | ||
669 | if (IS_ERR(adau1701->regmap)) | ||
670 | return PTR_ERR(adau1701->regmap); | ||
671 | |||
543 | if (dev->of_node) { | 672 | if (dev->of_node) { |
544 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); | 673 | gpio_nreset = of_get_named_gpio(dev->of_node, "reset-gpio", 0); |
545 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) | 674 | if (gpio_nreset < 0 && gpio_nreset != -ENOENT) |
546 | return gpio_nreset; | 675 | return gpio_nreset; |
676 | |||
677 | gpio_pll_mode[0] = of_get_named_gpio(dev->of_node, | ||
678 | "adi,pll-mode-gpios", 0); | ||
679 | if (gpio_pll_mode[0] < 0 && gpio_pll_mode[0] != -ENOENT) | ||
680 | return gpio_pll_mode[0]; | ||
681 | |||
682 | gpio_pll_mode[1] = of_get_named_gpio(dev->of_node, | ||
683 | "adi,pll-mode-gpios", 1); | ||
684 | if (gpio_pll_mode[1] < 0 && gpio_pll_mode[1] != -ENOENT) | ||
685 | return gpio_pll_mode[1]; | ||
686 | |||
687 | of_property_read_u32(dev->of_node, "adi,pll-clkdiv", | ||
688 | &adau1701->pll_clkdiv); | ||
689 | |||
690 | of_property_read_u8_array(dev->of_node, "adi,pin-config", | ||
691 | adau1701->pin_config, | ||
692 | ARRAY_SIZE(adau1701->pin_config)); | ||
547 | } | 693 | } |
548 | 694 | ||
549 | if (gpio_is_valid(gpio_nreset)) { | 695 | if (gpio_is_valid(gpio_nreset)) { |
@@ -553,7 +699,24 @@ static int adau1701_i2c_probe(struct i2c_client *client, | |||
553 | return ret; | 699 | return ret; |
554 | } | 700 | } |
555 | 701 | ||
702 | if (gpio_is_valid(gpio_pll_mode[0]) && | ||
703 | gpio_is_valid(gpio_pll_mode[1])) { | ||
704 | ret = devm_gpio_request_one(dev, gpio_pll_mode[0], | ||
705 | GPIOF_OUT_INIT_LOW, | ||
706 | "ADAU1701 PLL mode 0"); | ||
707 | if (ret < 0) | ||
708 | return ret; | ||
709 | |||
710 | ret = devm_gpio_request_one(dev, gpio_pll_mode[1], | ||
711 | GPIOF_OUT_INIT_LOW, | ||
712 | "ADAU1701 PLL mode 1"); | ||
713 | if (ret < 0) | ||
714 | return ret; | ||
715 | } | ||
716 | |||
556 | adau1701->gpio_nreset = gpio_nreset; | 717 | adau1701->gpio_nreset = gpio_nreset; |
718 | adau1701->gpio_pll_mode[0] = gpio_pll_mode[0]; | ||
719 | adau1701->gpio_pll_mode[1] = gpio_pll_mode[1]; | ||
557 | 720 | ||
558 | i2c_set_clientdata(client, adau1701); | 721 | i2c_set_clientdata(client, adau1701); |
559 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, | 722 | ret = snd_soc_register_codec(&client->dev, &adau1701_codec_drv, |
diff --git a/sound/soc/codecs/stac9766.c b/sound/soc/codecs/stac9766.c index 2eda85ba79ac..a5455c1aea42 100644 --- a/sound/soc/codecs/stac9766.c +++ b/sound/soc/codecs/stac9766.c | |||
@@ -28,8 +28,6 @@ | |||
28 | 28 | ||
29 | #include "stac9766.h" | 29 | #include "stac9766.h" |
30 | 30 | ||
31 | #define STAC9766_VERSION "0.10" | ||
32 | |||
33 | /* | 31 | /* |
34 | * STAC9766 register cache | 32 | * STAC9766 register cache |
35 | */ | 33 | */ |
@@ -145,14 +143,14 @@ static int stac9766_ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
145 | 143 | ||
146 | if (reg > AC97_STAC_PAGE0) { | 144 | if (reg > AC97_STAC_PAGE0) { |
147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
148 | soc_ac97_ops.write(codec->ac97, reg, val); | 146 | soc_ac97_ops->write(codec->ac97, reg, val); |
149 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
150 | return 0; | 148 | return 0; |
151 | } | 149 | } |
152 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) | 150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
153 | return -EIO; | 151 | return -EIO; |
154 | 152 | ||
155 | soc_ac97_ops.write(codec->ac97, reg, val); | 153 | soc_ac97_ops->write(codec->ac97, reg, val); |
156 | cache[reg / 2] = val; | 154 | cache[reg / 2] = val; |
157 | return 0; | 155 | return 0; |
158 | } | 156 | } |
@@ -164,7 +162,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
164 | 162 | ||
165 | if (reg > AC97_STAC_PAGE0) { | 163 | if (reg > AC97_STAC_PAGE0) { |
166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); | 164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
167 | val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); | 165 | val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); |
168 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
169 | return val; | 167 | return val; |
170 | } | 168 | } |
@@ -175,7 +173,7 @@ static unsigned int stac9766_ac97_read(struct snd_soc_codec *codec, | |||
175 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || | 173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
176 | reg == AC97_VENDOR_ID2) { | 174 | reg == AC97_VENDOR_ID2) { |
177 | 175 | ||
178 | val = soc_ac97_ops.read(codec->ac97, reg); | 176 | val = soc_ac97_ops->read(codec->ac97, reg); |
179 | return val; | 177 | return val; |
180 | } | 178 | } |
181 | return cache[reg / 2]; | 179 | return cache[reg / 2]; |
@@ -242,15 +240,15 @@ static int stac9766_set_bias_level(struct snd_soc_codec *codec, | |||
242 | 240 | ||
243 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) | 241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
244 | { | 242 | { |
245 | if (try_warm && soc_ac97_ops.warm_reset) { | 243 | if (try_warm && soc_ac97_ops->warm_reset) { |
246 | soc_ac97_ops.warm_reset(codec->ac97); | 244 | soc_ac97_ops->warm_reset(codec->ac97); |
247 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) | 245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
248 | return 1; | 246 | return 1; |
249 | } | 247 | } |
250 | 248 | ||
251 | soc_ac97_ops.reset(codec->ac97); | 249 | soc_ac97_ops->reset(codec->ac97); |
252 | if (soc_ac97_ops.warm_reset) | 250 | if (soc_ac97_ops->warm_reset) |
253 | soc_ac97_ops.warm_reset(codec->ac97); | 251 | soc_ac97_ops->warm_reset(codec->ac97); |
254 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) | 252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
255 | return -EIO; | 253 | return -EIO; |
256 | return 0; | 254 | return 0; |
@@ -274,7 +272,7 @@ reset: | |||
274 | return -EIO; | 272 | return -EIO; |
275 | } | 273 | } |
276 | codec->ac97->bus->ops->warm_reset(codec->ac97); | 274 | codec->ac97->bus->ops->warm_reset(codec->ac97); |
277 | id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2); | 275 | id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); |
278 | if (id != 0x4c13) { | 276 | if (id != 0x4c13) { |
279 | stac9766_reset(codec, 0); | 277 | stac9766_reset(codec, 0); |
280 | reset++; | 278 | reset++; |
@@ -338,9 +336,7 @@ static int stac9766_codec_probe(struct snd_soc_codec *codec) | |||
338 | { | 336 | { |
339 | int ret = 0; | 337 | int ret = 0; |
340 | 338 | ||
341 | printk(KERN_INFO "STAC9766 SoC Audio Codec %s\n", STAC9766_VERSION); | 339 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
342 | |||
343 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
344 | if (ret < 0) | 340 | if (ret < 0) |
345 | goto codec_err; | 341 | goto codec_err; |
346 | 342 | ||
diff --git a/sound/soc/codecs/tas5086.c b/sound/soc/codecs/tas5086.c index d447c4aa1d5e..6d31d88f7204 100644 --- a/sound/soc/codecs/tas5086.c +++ b/sound/soc/codecs/tas5086.c | |||
@@ -83,6 +83,14 @@ | |||
83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ | 83 | #define TAS5086_SPLIT_CAP_CHARGE 0x1a /* Split cap charge period register */ |
84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ | 84 | #define TAS5086_OSC_TRIM 0x1b /* Oscillator trim register */ |
85 | #define TAS5086_BKNDERR 0x1c | 85 | #define TAS5086_BKNDERR 0x1c |
86 | #define TAS5086_INPUT_MUX 0x20 | ||
87 | #define TAS5086_PWM_OUTPUT_MUX 0x25 | ||
88 | |||
89 | #define TAS5086_MAX_REGISTER TAS5086_PWM_OUTPUT_MUX | ||
90 | |||
91 | #define TAS5086_PWM_START_MIDZ_FOR_START_1 (1 << 7) | ||
92 | #define TAS5086_PWM_START_MIDZ_FOR_START_2 (1 << 6) | ||
93 | #define TAS5086_PWM_START_CHANNEL_MASK (0x3f) | ||
86 | 94 | ||
87 | /* | 95 | /* |
88 | * Default TAS5086 power-up configuration | 96 | * Default TAS5086 power-up configuration |
@@ -119,9 +127,30 @@ static const struct reg_default tas5086_reg_defaults[] = { | |||
119 | { 0x1c, 0x05 }, | 127 | { 0x1c, 0x05 }, |
120 | }; | 128 | }; |
121 | 129 | ||
130 | static int tas5086_register_size(struct device *dev, unsigned int reg) | ||
131 | { | ||
132 | switch (reg) { | ||
133 | case TAS5086_CLOCK_CONTROL ... TAS5086_BKNDERR: | ||
134 | return 1; | ||
135 | case TAS5086_INPUT_MUX: | ||
136 | case TAS5086_PWM_OUTPUT_MUX: | ||
137 | return 4; | ||
138 | } | ||
139 | |||
140 | dev_err(dev, "Unsupported register address: %d\n", reg); | ||
141 | return 0; | ||
142 | } | ||
143 | |||
122 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) | 144 | static bool tas5086_accessible_reg(struct device *dev, unsigned int reg) |
123 | { | 145 | { |
124 | return !((reg == 0x0f) || (reg >= 0x11 && reg <= 0x17)); | 146 | switch (reg) { |
147 | case 0x0f: | ||
148 | case 0x11 ... 0x17: | ||
149 | case 0x1d ... 0x1f: | ||
150 | return false; | ||
151 | default: | ||
152 | return true; | ||
153 | } | ||
125 | } | 154 | } |
126 | 155 | ||
127 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) | 156 | static bool tas5086_volatile_reg(struct device *dev, unsigned int reg) |
@@ -140,6 +169,76 @@ static bool tas5086_writeable_reg(struct device *dev, unsigned int reg) | |||
140 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); | 169 | return tas5086_accessible_reg(dev, reg) && (reg != TAS5086_DEV_ID); |
141 | } | 170 | } |
142 | 171 | ||
172 | static int tas5086_reg_write(void *context, unsigned int reg, | ||
173 | unsigned int value) | ||
174 | { | ||
175 | struct i2c_client *client = context; | ||
176 | unsigned int i, size; | ||
177 | uint8_t buf[5]; | ||
178 | int ret; | ||
179 | |||
180 | size = tas5086_register_size(&client->dev, reg); | ||
181 | if (size == 0) | ||
182 | return -EINVAL; | ||
183 | |||
184 | buf[0] = reg; | ||
185 | |||
186 | for (i = size; i >= 1; --i) { | ||
187 | buf[i] = value; | ||
188 | value >>= 8; | ||
189 | } | ||
190 | |||
191 | ret = i2c_master_send(client, buf, size + 1); | ||
192 | if (ret == size + 1) | ||
193 | return 0; | ||
194 | else if (ret < 0) | ||
195 | return ret; | ||
196 | else | ||
197 | return -EIO; | ||
198 | } | ||
199 | |||
200 | static int tas5086_reg_read(void *context, unsigned int reg, | ||
201 | unsigned int *value) | ||
202 | { | ||
203 | struct i2c_client *client = context; | ||
204 | uint8_t send_buf, recv_buf[4]; | ||
205 | struct i2c_msg msgs[2]; | ||
206 | unsigned int size; | ||
207 | unsigned int i; | ||
208 | int ret; | ||
209 | |||
210 | size = tas5086_register_size(&client->dev, reg); | ||
211 | if (size == 0) | ||
212 | return -EINVAL; | ||
213 | |||
214 | send_buf = reg; | ||
215 | |||
216 | msgs[0].addr = client->addr; | ||
217 | msgs[0].len = sizeof(send_buf); | ||
218 | msgs[0].buf = &send_buf; | ||
219 | msgs[0].flags = 0; | ||
220 | |||
221 | msgs[1].addr = client->addr; | ||
222 | msgs[1].len = size; | ||
223 | msgs[1].buf = recv_buf; | ||
224 | msgs[1].flags = I2C_M_RD; | ||
225 | |||
226 | ret = i2c_transfer(client->adapter, msgs, ARRAY_SIZE(msgs)); | ||
227 | if (ret < 0) | ||
228 | return ret; | ||
229 | else if (ret != ARRAY_SIZE(msgs)) | ||
230 | return -EIO; | ||
231 | |||
232 | *value = 0; | ||
233 | |||
234 | for (i = 0; i < size; i++) { | ||
235 | *value <<= 8; | ||
236 | *value |= recv_buf[i]; | ||
237 | } | ||
238 | |||
239 | return 0; | ||
240 | } | ||
241 | |||
143 | struct tas5086_private { | 242 | struct tas5086_private { |
144 | struct regmap *regmap; | 243 | struct regmap *regmap; |
145 | unsigned int mclk, sclk; | 244 | unsigned int mclk, sclk; |
@@ -376,6 +475,202 @@ static const struct snd_kcontrol_new tas5086_controls[] = { | |||
376 | tas5086_get_deemph, tas5086_put_deemph), | 475 | tas5086_get_deemph, tas5086_put_deemph), |
377 | }; | 476 | }; |
378 | 477 | ||
478 | /* Input mux controls */ | ||
479 | static const char *tas5086_dapm_sdin_texts[] = | ||
480 | { | ||
481 | "SDIN1-L", "SDIN1-R", "SDIN2-L", "SDIN2-R", | ||
482 | "SDIN3-L", "SDIN3-R", "Ground (0)", "nc" | ||
483 | }; | ||
484 | |||
485 | static const struct soc_enum tas5086_dapm_input_mux_enum[] = { | ||
486 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 20, 8, tas5086_dapm_sdin_texts), | ||
487 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 16, 8, tas5086_dapm_sdin_texts), | ||
488 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 12, 8, tas5086_dapm_sdin_texts), | ||
489 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 8, 8, tas5086_dapm_sdin_texts), | ||
490 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 4, 8, tas5086_dapm_sdin_texts), | ||
491 | SOC_ENUM_SINGLE(TAS5086_INPUT_MUX, 0, 8, tas5086_dapm_sdin_texts), | ||
492 | }; | ||
493 | |||
494 | static const struct snd_kcontrol_new tas5086_dapm_input_mux_controls[] = { | ||
495 | SOC_DAPM_ENUM("Channel 1 input", tas5086_dapm_input_mux_enum[0]), | ||
496 | SOC_DAPM_ENUM("Channel 2 input", tas5086_dapm_input_mux_enum[1]), | ||
497 | SOC_DAPM_ENUM("Channel 3 input", tas5086_dapm_input_mux_enum[2]), | ||
498 | SOC_DAPM_ENUM("Channel 4 input", tas5086_dapm_input_mux_enum[3]), | ||
499 | SOC_DAPM_ENUM("Channel 5 input", tas5086_dapm_input_mux_enum[4]), | ||
500 | SOC_DAPM_ENUM("Channel 6 input", tas5086_dapm_input_mux_enum[5]), | ||
501 | }; | ||
502 | |||
503 | /* Output mux controls */ | ||
504 | static const char *tas5086_dapm_channel_texts[] = | ||
505 | { "Channel 1 Mux", "Channel 2 Mux", "Channel 3 Mux", | ||
506 | "Channel 4 Mux", "Channel 5 Mux", "Channel 6 Mux" }; | ||
507 | |||
508 | static const struct soc_enum tas5086_dapm_output_mux_enum[] = { | ||
509 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 20, 6, tas5086_dapm_channel_texts), | ||
510 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 16, 6, tas5086_dapm_channel_texts), | ||
511 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 12, 6, tas5086_dapm_channel_texts), | ||
512 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 8, 6, tas5086_dapm_channel_texts), | ||
513 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 4, 6, tas5086_dapm_channel_texts), | ||
514 | SOC_ENUM_SINGLE(TAS5086_PWM_OUTPUT_MUX, 0, 6, tas5086_dapm_channel_texts), | ||
515 | }; | ||
516 | |||
517 | static const struct snd_kcontrol_new tas5086_dapm_output_mux_controls[] = { | ||
518 | SOC_DAPM_ENUM("PWM1 Output", tas5086_dapm_output_mux_enum[0]), | ||
519 | SOC_DAPM_ENUM("PWM2 Output", tas5086_dapm_output_mux_enum[1]), | ||
520 | SOC_DAPM_ENUM("PWM3 Output", tas5086_dapm_output_mux_enum[2]), | ||
521 | SOC_DAPM_ENUM("PWM4 Output", tas5086_dapm_output_mux_enum[3]), | ||
522 | SOC_DAPM_ENUM("PWM5 Output", tas5086_dapm_output_mux_enum[4]), | ||
523 | SOC_DAPM_ENUM("PWM6 Output", tas5086_dapm_output_mux_enum[5]), | ||
524 | }; | ||
525 | |||
526 | static const struct snd_soc_dapm_widget tas5086_dapm_widgets[] = { | ||
527 | SND_SOC_DAPM_INPUT("SDIN1-L"), | ||
528 | SND_SOC_DAPM_INPUT("SDIN1-R"), | ||
529 | SND_SOC_DAPM_INPUT("SDIN2-L"), | ||
530 | SND_SOC_DAPM_INPUT("SDIN2-R"), | ||
531 | SND_SOC_DAPM_INPUT("SDIN3-L"), | ||
532 | SND_SOC_DAPM_INPUT("SDIN3-R"), | ||
533 | SND_SOC_DAPM_INPUT("SDIN4-L"), | ||
534 | SND_SOC_DAPM_INPUT("SDIN4-R"), | ||
535 | |||
536 | SND_SOC_DAPM_OUTPUT("PWM1"), | ||
537 | SND_SOC_DAPM_OUTPUT("PWM2"), | ||
538 | SND_SOC_DAPM_OUTPUT("PWM3"), | ||
539 | SND_SOC_DAPM_OUTPUT("PWM4"), | ||
540 | SND_SOC_DAPM_OUTPUT("PWM5"), | ||
541 | SND_SOC_DAPM_OUTPUT("PWM6"), | ||
542 | |||
543 | SND_SOC_DAPM_MUX("Channel 1 Mux", SND_SOC_NOPM, 0, 0, | ||
544 | &tas5086_dapm_input_mux_controls[0]), | ||
545 | SND_SOC_DAPM_MUX("Channel 2 Mux", SND_SOC_NOPM, 0, 0, | ||
546 | &tas5086_dapm_input_mux_controls[1]), | ||
547 | SND_SOC_DAPM_MUX("Channel 3 Mux", SND_SOC_NOPM, 0, 0, | ||
548 | &tas5086_dapm_input_mux_controls[2]), | ||
549 | SND_SOC_DAPM_MUX("Channel 4 Mux", SND_SOC_NOPM, 0, 0, | ||
550 | &tas5086_dapm_input_mux_controls[3]), | ||
551 | SND_SOC_DAPM_MUX("Channel 5 Mux", SND_SOC_NOPM, 0, 0, | ||
552 | &tas5086_dapm_input_mux_controls[4]), | ||
553 | SND_SOC_DAPM_MUX("Channel 6 Mux", SND_SOC_NOPM, 0, 0, | ||
554 | &tas5086_dapm_input_mux_controls[5]), | ||
555 | |||
556 | SND_SOC_DAPM_MUX("PWM1 Mux", SND_SOC_NOPM, 0, 0, | ||
557 | &tas5086_dapm_output_mux_controls[0]), | ||
558 | SND_SOC_DAPM_MUX("PWM2 Mux", SND_SOC_NOPM, 0, 0, | ||
559 | &tas5086_dapm_output_mux_controls[1]), | ||
560 | SND_SOC_DAPM_MUX("PWM3 Mux", SND_SOC_NOPM, 0, 0, | ||
561 | &tas5086_dapm_output_mux_controls[2]), | ||
562 | SND_SOC_DAPM_MUX("PWM4 Mux", SND_SOC_NOPM, 0, 0, | ||
563 | &tas5086_dapm_output_mux_controls[3]), | ||
564 | SND_SOC_DAPM_MUX("PWM5 Mux", SND_SOC_NOPM, 0, 0, | ||
565 | &tas5086_dapm_output_mux_controls[4]), | ||
566 | SND_SOC_DAPM_MUX("PWM6 Mux", SND_SOC_NOPM, 0, 0, | ||
567 | &tas5086_dapm_output_mux_controls[5]), | ||
568 | }; | ||
569 | |||
570 | static const struct snd_soc_dapm_route tas5086_dapm_routes[] = { | ||
571 | /* SDIN inputs -> channel muxes */ | ||
572 | { "Channel 1 Mux", "SDIN1-L", "SDIN1-L" }, | ||
573 | { "Channel 1 Mux", "SDIN1-R", "SDIN1-R" }, | ||
574 | { "Channel 1 Mux", "SDIN2-L", "SDIN2-L" }, | ||
575 | { "Channel 1 Mux", "SDIN2-R", "SDIN2-R" }, | ||
576 | { "Channel 1 Mux", "SDIN3-L", "SDIN3-L" }, | ||
577 | { "Channel 1 Mux", "SDIN3-R", "SDIN3-R" }, | ||
578 | |||
579 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
580 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
581 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
582 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
583 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
584 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
585 | |||
586 | { "Channel 2 Mux", "SDIN1-L", "SDIN1-L" }, | ||
587 | { "Channel 2 Mux", "SDIN1-R", "SDIN1-R" }, | ||
588 | { "Channel 2 Mux", "SDIN2-L", "SDIN2-L" }, | ||
589 | { "Channel 2 Mux", "SDIN2-R", "SDIN2-R" }, | ||
590 | { "Channel 2 Mux", "SDIN3-L", "SDIN3-L" }, | ||
591 | { "Channel 2 Mux", "SDIN3-R", "SDIN3-R" }, | ||
592 | |||
593 | { "Channel 3 Mux", "SDIN1-L", "SDIN1-L" }, | ||
594 | { "Channel 3 Mux", "SDIN1-R", "SDIN1-R" }, | ||
595 | { "Channel 3 Mux", "SDIN2-L", "SDIN2-L" }, | ||
596 | { "Channel 3 Mux", "SDIN2-R", "SDIN2-R" }, | ||
597 | { "Channel 3 Mux", "SDIN3-L", "SDIN3-L" }, | ||
598 | { "Channel 3 Mux", "SDIN3-R", "SDIN3-R" }, | ||
599 | |||
600 | { "Channel 4 Mux", "SDIN1-L", "SDIN1-L" }, | ||
601 | { "Channel 4 Mux", "SDIN1-R", "SDIN1-R" }, | ||
602 | { "Channel 4 Mux", "SDIN2-L", "SDIN2-L" }, | ||
603 | { "Channel 4 Mux", "SDIN2-R", "SDIN2-R" }, | ||
604 | { "Channel 4 Mux", "SDIN3-L", "SDIN3-L" }, | ||
605 | { "Channel 4 Mux", "SDIN3-R", "SDIN3-R" }, | ||
606 | |||
607 | { "Channel 5 Mux", "SDIN1-L", "SDIN1-L" }, | ||
608 | { "Channel 5 Mux", "SDIN1-R", "SDIN1-R" }, | ||
609 | { "Channel 5 Mux", "SDIN2-L", "SDIN2-L" }, | ||
610 | { "Channel 5 Mux", "SDIN2-R", "SDIN2-R" }, | ||
611 | { "Channel 5 Mux", "SDIN3-L", "SDIN3-L" }, | ||
612 | { "Channel 5 Mux", "SDIN3-R", "SDIN3-R" }, | ||
613 | |||
614 | { "Channel 6 Mux", "SDIN1-L", "SDIN1-L" }, | ||
615 | { "Channel 6 Mux", "SDIN1-R", "SDIN1-R" }, | ||
616 | { "Channel 6 Mux", "SDIN2-L", "SDIN2-L" }, | ||
617 | { "Channel 6 Mux", "SDIN2-R", "SDIN2-R" }, | ||
618 | { "Channel 6 Mux", "SDIN3-L", "SDIN3-L" }, | ||
619 | { "Channel 6 Mux", "SDIN3-R", "SDIN3-R" }, | ||
620 | |||
621 | /* Channel muxes -> PWM muxes */ | ||
622 | { "PWM1 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
623 | { "PWM2 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
624 | { "PWM3 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
625 | { "PWM4 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
626 | { "PWM5 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
627 | { "PWM6 Mux", "Channel 1 Mux", "Channel 1 Mux" }, | ||
628 | |||
629 | { "PWM1 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
630 | { "PWM2 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
631 | { "PWM3 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
632 | { "PWM4 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
633 | { "PWM5 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
634 | { "PWM6 Mux", "Channel 2 Mux", "Channel 2 Mux" }, | ||
635 | |||
636 | { "PWM1 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
637 | { "PWM2 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
638 | { "PWM3 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
639 | { "PWM4 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
640 | { "PWM5 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
641 | { "PWM6 Mux", "Channel 3 Mux", "Channel 3 Mux" }, | ||
642 | |||
643 | { "PWM1 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
644 | { "PWM2 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
645 | { "PWM3 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
646 | { "PWM4 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
647 | { "PWM5 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
648 | { "PWM6 Mux", "Channel 4 Mux", "Channel 4 Mux" }, | ||
649 | |||
650 | { "PWM1 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
651 | { "PWM2 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
652 | { "PWM3 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
653 | { "PWM4 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
654 | { "PWM5 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
655 | { "PWM6 Mux", "Channel 5 Mux", "Channel 5 Mux" }, | ||
656 | |||
657 | { "PWM1 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
658 | { "PWM2 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
659 | { "PWM3 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
660 | { "PWM4 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
661 | { "PWM5 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
662 | { "PWM6 Mux", "Channel 6 Mux", "Channel 6 Mux" }, | ||
663 | |||
664 | /* The PWM muxes are directly connected to the PWM outputs */ | ||
665 | { "PWM1", NULL, "PWM1 Mux" }, | ||
666 | { "PWM2", NULL, "PWM2 Mux" }, | ||
667 | { "PWM3", NULL, "PWM3 Mux" }, | ||
668 | { "PWM4", NULL, "PWM4 Mux" }, | ||
669 | { "PWM5", NULL, "PWM5 Mux" }, | ||
670 | { "PWM6", NULL, "PWM6 Mux" }, | ||
671 | |||
672 | }; | ||
673 | |||
379 | static const struct snd_soc_dai_ops tas5086_dai_ops = { | 674 | static const struct snd_soc_dai_ops tas5086_dai_ops = { |
380 | .hw_params = tas5086_hw_params, | 675 | .hw_params = tas5086_hw_params, |
381 | .set_sysclk = tas5086_set_dai_sysclk, | 676 | .set_sysclk = tas5086_set_dai_sysclk, |
@@ -426,13 +721,34 @@ static int tas5086_probe(struct snd_soc_codec *codec) | |||
426 | { | 721 | { |
427 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); | 722 | struct tas5086_private *priv = snd_soc_codec_get_drvdata(codec); |
428 | int charge_period = 1300000; /* hardware default is 1300 ms */ | 723 | int charge_period = 1300000; /* hardware default is 1300 ms */ |
724 | u8 pwm_start_mid_z = 0; | ||
429 | int i, ret; | 725 | int i, ret; |
430 | 726 | ||
431 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { | 727 | if (of_match_device(of_match_ptr(tas5086_dt_ids), codec->dev)) { |
432 | struct device_node *of_node = codec->dev->of_node; | 728 | struct device_node *of_node = codec->dev->of_node; |
433 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); | 729 | of_property_read_u32(of_node, "ti,charge-period", &charge_period); |
730 | |||
731 | for (i = 0; i < 6; i++) { | ||
732 | char name[25]; | ||
733 | |||
734 | snprintf(name, sizeof(name), | ||
735 | "ti,mid-z-channel-%d", i + 1); | ||
736 | |||
737 | if (of_get_property(of_node, name, NULL) != NULL) | ||
738 | pwm_start_mid_z |= 1 << i; | ||
739 | } | ||
434 | } | 740 | } |
435 | 741 | ||
742 | /* | ||
743 | * If any of the channels is configured to start in Mid-Z mode, | ||
744 | * configure 'part 1' of the PWM starts to use Mid-Z, and tell | ||
745 | * all configured mid-z channels to start start under 'part 1'. | ||
746 | */ | ||
747 | if (pwm_start_mid_z) | ||
748 | regmap_write(priv->regmap, TAS5086_PWM_START, | ||
749 | TAS5086_PWM_START_MIDZ_FOR_START_1 | | ||
750 | pwm_start_mid_z); | ||
751 | |||
436 | /* lookup and set split-capacitor charge period */ | 752 | /* lookup and set split-capacitor charge period */ |
437 | if (charge_period == 0) { | 753 | if (charge_period == 0) { |
438 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); | 754 | regmap_write(priv->regmap, TAS5086_SPLIT_CAP_CHARGE, 0); |
@@ -490,6 +806,10 @@ static struct snd_soc_codec_driver soc_codec_dev_tas5086 = { | |||
490 | .resume = tas5086_soc_resume, | 806 | .resume = tas5086_soc_resume, |
491 | .controls = tas5086_controls, | 807 | .controls = tas5086_controls, |
492 | .num_controls = ARRAY_SIZE(tas5086_controls), | 808 | .num_controls = ARRAY_SIZE(tas5086_controls), |
809 | .dapm_widgets = tas5086_dapm_widgets, | ||
810 | .num_dapm_widgets = ARRAY_SIZE(tas5086_dapm_widgets), | ||
811 | .dapm_routes = tas5086_dapm_routes, | ||
812 | .num_dapm_routes = ARRAY_SIZE(tas5086_dapm_routes), | ||
493 | }; | 813 | }; |
494 | 814 | ||
495 | static const struct i2c_device_id tas5086_i2c_id[] = { | 815 | static const struct i2c_device_id tas5086_i2c_id[] = { |
@@ -500,14 +820,16 @@ MODULE_DEVICE_TABLE(i2c, tas5086_i2c_id); | |||
500 | 820 | ||
501 | static const struct regmap_config tas5086_regmap = { | 821 | static const struct regmap_config tas5086_regmap = { |
502 | .reg_bits = 8, | 822 | .reg_bits = 8, |
503 | .val_bits = 8, | 823 | .val_bits = 32, |
504 | .max_register = ARRAY_SIZE(tas5086_reg_defaults), | 824 | .max_register = TAS5086_MAX_REGISTER, |
505 | .reg_defaults = tas5086_reg_defaults, | 825 | .reg_defaults = tas5086_reg_defaults, |
506 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), | 826 | .num_reg_defaults = ARRAY_SIZE(tas5086_reg_defaults), |
507 | .cache_type = REGCACHE_RBTREE, | 827 | .cache_type = REGCACHE_RBTREE, |
508 | .volatile_reg = tas5086_volatile_reg, | 828 | .volatile_reg = tas5086_volatile_reg, |
509 | .writeable_reg = tas5086_writeable_reg, | 829 | .writeable_reg = tas5086_writeable_reg, |
510 | .readable_reg = tas5086_accessible_reg, | 830 | .readable_reg = tas5086_accessible_reg, |
831 | .reg_read = tas5086_reg_read, | ||
832 | .reg_write = tas5086_reg_write, | ||
511 | }; | 833 | }; |
512 | 834 | ||
513 | static int tas5086_i2c_probe(struct i2c_client *i2c, | 835 | static int tas5086_i2c_probe(struct i2c_client *i2c, |
@@ -522,7 +844,7 @@ static int tas5086_i2c_probe(struct i2c_client *i2c, | |||
522 | if (!priv) | 844 | if (!priv) |
523 | return -ENOMEM; | 845 | return -ENOMEM; |
524 | 846 | ||
525 | priv->regmap = devm_regmap_init_i2c(i2c, &tas5086_regmap); | 847 | priv->regmap = devm_regmap_init(dev, NULL, i2c, &tas5086_regmap); |
526 | if (IS_ERR(priv->regmap)) { | 848 | if (IS_ERR(priv->regmap)) { |
527 | ret = PTR_ERR(priv->regmap); | 849 | ret = PTR_ERR(priv->regmap); |
528 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); | 850 | dev_err(&i2c->dev, "Failed to create regmap: %d\n", ret); |
diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 1514bf845e4b..e5b926883131 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c | |||
@@ -128,10 +128,8 @@ static const u8 aic3x_reg[AIC3X_CACHEREGNUM] = { | |||
128 | }; | 128 | }; |
129 | 129 | ||
130 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ | 130 | #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ |
131 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 131 | SOC_SINGLE_EXT(xname, reg, shift, mask, invert, \ |
132 | .info = snd_soc_info_volsw, \ | 132 | snd_soc_dapm_get_volsw, snd_soc_dapm_put_volsw_aic3x) |
133 | .get = snd_soc_dapm_get_volsw, .put = snd_soc_dapm_put_volsw_aic3x, \ | ||
134 | .private_value = SOC_SINGLE_VALUE(reg, shift, mask, invert) } | ||
135 | 133 | ||
136 | /* | 134 | /* |
137 | * All input lines are connected when !0xf and disconnected with 0xf bit field, | 135 | * All input lines are connected when !0xf and disconnected with 0xf bit field, |
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c index 9b9a6e587610..44621ddc332d 100644 --- a/sound/soc/codecs/twl6040.c +++ b/sound/soc/codecs/twl6040.c | |||
@@ -38,6 +38,14 @@ | |||
38 | 38 | ||
39 | #include "twl6040.h" | 39 | #include "twl6040.h" |
40 | 40 | ||
41 | enum twl6040_dai_id { | ||
42 | TWL6040_DAI_LEGACY = 0, | ||
43 | TWL6040_DAI_UL, | ||
44 | TWL6040_DAI_DL1, | ||
45 | TWL6040_DAI_DL2, | ||
46 | TWL6040_DAI_VIB, | ||
47 | }; | ||
48 | |||
41 | #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 | 49 | #define TWL6040_RATES SNDRV_PCM_RATE_8000_96000 |
42 | #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) | 50 | #define TWL6040_FORMATS (SNDRV_PCM_FMTBIT_S32_LE) |
43 | 51 | ||
@@ -67,6 +75,8 @@ struct twl6040_data { | |||
67 | int pll_power_mode; | 75 | int pll_power_mode; |
68 | int hs_power_mode; | 76 | int hs_power_mode; |
69 | int hs_power_mode_locked; | 77 | int hs_power_mode_locked; |
78 | bool dl1_unmuted; | ||
79 | bool dl2_unmuted; | ||
70 | unsigned int clk_in; | 80 | unsigned int clk_in; |
71 | unsigned int sysclk; | 81 | unsigned int sysclk; |
72 | struct twl6040_jack_data hs_jack; | 82 | struct twl6040_jack_data hs_jack; |
@@ -220,6 +230,25 @@ static int twl6040_read_reg_volatile(struct snd_soc_codec *codec, | |||
220 | return value; | 230 | return value; |
221 | } | 231 | } |
222 | 232 | ||
233 | static bool twl6040_is_path_unmuted(struct snd_soc_codec *codec, | ||
234 | unsigned int reg) | ||
235 | { | ||
236 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
237 | |||
238 | switch (reg) { | ||
239 | case TWL6040_REG_HSLCTL: | ||
240 | case TWL6040_REG_HSRCTL: | ||
241 | case TWL6040_REG_EARCTL: | ||
242 | /* DL1 path */ | ||
243 | return priv->dl1_unmuted; | ||
244 | case TWL6040_REG_HFLCTL: | ||
245 | case TWL6040_REG_HFRCTL: | ||
246 | return priv->dl2_unmuted; | ||
247 | default: | ||
248 | return 1; | ||
249 | }; | ||
250 | } | ||
251 | |||
223 | /* | 252 | /* |
224 | * write to the twl6040 register space | 253 | * write to the twl6040 register space |
225 | */ | 254 | */ |
@@ -232,7 +261,8 @@ static int twl6040_write(struct snd_soc_codec *codec, | |||
232 | return -EIO; | 261 | return -EIO; |
233 | 262 | ||
234 | twl6040_write_reg_cache(codec, reg, value); | 263 | twl6040_write_reg_cache(codec, reg, value); |
235 | if (likely(reg < TWL6040_REG_SW_SHADOW)) | 264 | if (likely(reg < TWL6040_REG_SW_SHADOW) && |
265 | twl6040_is_path_unmuted(codec, reg)) | ||
236 | return twl6040_reg_write(twl6040, reg, value); | 266 | return twl6040_reg_write(twl6040, reg, value); |
237 | else | 267 | else |
238 | return 0; | 268 | return 0; |
@@ -1026,16 +1056,84 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai, | |||
1026 | return 0; | 1056 | return 0; |
1027 | } | 1057 | } |
1028 | 1058 | ||
1059 | static void twl6040_mute_path(struct snd_soc_codec *codec, enum twl6040_dai_id id, | ||
1060 | int mute) | ||
1061 | { | ||
1062 | struct twl6040 *twl6040 = codec->control_data; | ||
1063 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1064 | int hslctl, hsrctl, earctl; | ||
1065 | int hflctl, hfrctl; | ||
1066 | |||
1067 | switch (id) { | ||
1068 | case TWL6040_DAI_DL1: | ||
1069 | hslctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSLCTL); | ||
1070 | hsrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HSRCTL); | ||
1071 | earctl = twl6040_read_reg_cache(codec, TWL6040_REG_EARCTL); | ||
1072 | |||
1073 | if (mute) { | ||
1074 | /* Power down drivers and DACs */ | ||
1075 | earctl &= ~0x01; | ||
1076 | hslctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); | ||
1077 | hsrctl &= ~(TWL6040_HSDRVENA | TWL6040_HSDACENA); | ||
1078 | |||
1079 | } | ||
1080 | |||
1081 | twl6040_reg_write(twl6040, TWL6040_REG_EARCTL, earctl); | ||
1082 | twl6040_reg_write(twl6040, TWL6040_REG_HSLCTL, hslctl); | ||
1083 | twl6040_reg_write(twl6040, TWL6040_REG_HSRCTL, hsrctl); | ||
1084 | priv->dl1_unmuted = !mute; | ||
1085 | break; | ||
1086 | case TWL6040_DAI_DL2: | ||
1087 | hflctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFLCTL); | ||
1088 | hfrctl = twl6040_read_reg_cache(codec, TWL6040_REG_HFRCTL); | ||
1089 | |||
1090 | if (mute) { | ||
1091 | /* Power down drivers and DACs */ | ||
1092 | hflctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | | ||
1093 | TWL6040_HFDRVENA); | ||
1094 | hfrctl &= ~(TWL6040_HFDACENA | TWL6040_HFPGAENA | | ||
1095 | TWL6040_HFDRVENA); | ||
1096 | } | ||
1097 | |||
1098 | twl6040_reg_write(twl6040, TWL6040_REG_HFLCTL, hflctl); | ||
1099 | twl6040_reg_write(twl6040, TWL6040_REG_HFRCTL, hfrctl); | ||
1100 | priv->dl2_unmuted = !mute; | ||
1101 | break; | ||
1102 | default: | ||
1103 | break; | ||
1104 | }; | ||
1105 | } | ||
1106 | |||
1107 | static int twl6040_digital_mute(struct snd_soc_dai *dai, int mute) | ||
1108 | { | ||
1109 | switch (dai->id) { | ||
1110 | case TWL6040_DAI_LEGACY: | ||
1111 | twl6040_mute_path(dai->codec, TWL6040_DAI_DL1, mute); | ||
1112 | twl6040_mute_path(dai->codec, TWL6040_DAI_DL2, mute); | ||
1113 | break; | ||
1114 | case TWL6040_DAI_DL1: | ||
1115 | case TWL6040_DAI_DL2: | ||
1116 | twl6040_mute_path(dai->codec, dai->id, mute); | ||
1117 | break; | ||
1118 | default: | ||
1119 | break; | ||
1120 | } | ||
1121 | |||
1122 | return 0; | ||
1123 | } | ||
1124 | |||
1029 | static const struct snd_soc_dai_ops twl6040_dai_ops = { | 1125 | static const struct snd_soc_dai_ops twl6040_dai_ops = { |
1030 | .startup = twl6040_startup, | 1126 | .startup = twl6040_startup, |
1031 | .hw_params = twl6040_hw_params, | 1127 | .hw_params = twl6040_hw_params, |
1032 | .prepare = twl6040_prepare, | 1128 | .prepare = twl6040_prepare, |
1033 | .set_sysclk = twl6040_set_dai_sysclk, | 1129 | .set_sysclk = twl6040_set_dai_sysclk, |
1130 | .digital_mute = twl6040_digital_mute, | ||
1034 | }; | 1131 | }; |
1035 | 1132 | ||
1036 | static struct snd_soc_dai_driver twl6040_dai[] = { | 1133 | static struct snd_soc_dai_driver twl6040_dai[] = { |
1037 | { | 1134 | { |
1038 | .name = "twl6040-legacy", | 1135 | .name = "twl6040-legacy", |
1136 | .id = TWL6040_DAI_LEGACY, | ||
1039 | .playback = { | 1137 | .playback = { |
1040 | .stream_name = "Legacy Playback", | 1138 | .stream_name = "Legacy Playback", |
1041 | .channels_min = 1, | 1139 | .channels_min = 1, |
@@ -1054,6 +1152,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1054 | }, | 1152 | }, |
1055 | { | 1153 | { |
1056 | .name = "twl6040-ul", | 1154 | .name = "twl6040-ul", |
1155 | .id = TWL6040_DAI_UL, | ||
1057 | .capture = { | 1156 | .capture = { |
1058 | .stream_name = "Capture", | 1157 | .stream_name = "Capture", |
1059 | .channels_min = 1, | 1158 | .channels_min = 1, |
@@ -1065,6 +1164,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1065 | }, | 1164 | }, |
1066 | { | 1165 | { |
1067 | .name = "twl6040-dl1", | 1166 | .name = "twl6040-dl1", |
1167 | .id = TWL6040_DAI_DL1, | ||
1068 | .playback = { | 1168 | .playback = { |
1069 | .stream_name = "Headset Playback", | 1169 | .stream_name = "Headset Playback", |
1070 | .channels_min = 1, | 1170 | .channels_min = 1, |
@@ -1076,6 +1176,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1076 | }, | 1176 | }, |
1077 | { | 1177 | { |
1078 | .name = "twl6040-dl2", | 1178 | .name = "twl6040-dl2", |
1179 | .id = TWL6040_DAI_DL2, | ||
1079 | .playback = { | 1180 | .playback = { |
1080 | .stream_name = "Handsfree Playback", | 1181 | .stream_name = "Handsfree Playback", |
1081 | .channels_min = 1, | 1182 | .channels_min = 1, |
@@ -1087,6 +1188,7 @@ static struct snd_soc_dai_driver twl6040_dai[] = { | |||
1087 | }, | 1188 | }, |
1088 | { | 1189 | { |
1089 | .name = "twl6040-vib", | 1190 | .name = "twl6040-vib", |
1191 | .id = TWL6040_DAI_VIB, | ||
1090 | .playback = { | 1192 | .playback = { |
1091 | .stream_name = "Vibra Playback", | 1193 | .stream_name = "Vibra Playback", |
1092 | .channels_min = 1, | 1194 | .channels_min = 1, |
@@ -1143,7 +1245,7 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1143 | 1245 | ||
1144 | mutex_init(&priv->mutex); | 1246 | mutex_init(&priv->mutex); |
1145 | 1247 | ||
1146 | ret = devm_request_threaded_irq(codec->dev, priv->plug_irq, NULL, | 1248 | ret = request_threaded_irq(priv->plug_irq, NULL, |
1147 | twl6040_audio_handler, IRQF_NO_SUSPEND, | 1249 | twl6040_audio_handler, IRQF_NO_SUSPEND, |
1148 | "twl6040_irq_plug", codec); | 1250 | "twl6040_irq_plug", codec); |
1149 | if (ret) { | 1251 | if (ret) { |
@@ -1159,6 +1261,9 @@ static int twl6040_probe(struct snd_soc_codec *codec) | |||
1159 | 1261 | ||
1160 | static int twl6040_remove(struct snd_soc_codec *codec) | 1262 | static int twl6040_remove(struct snd_soc_codec *codec) |
1161 | { | 1263 | { |
1264 | struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); | ||
1265 | |||
1266 | free_irq(priv->plug_irq, codec); | ||
1162 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); | 1267 | twl6040_set_bias_level(codec, SND_SOC_BIAS_OFF); |
1163 | 1268 | ||
1164 | return 0; | 1269 | return 0; |
diff --git a/sound/soc/codecs/wm8400.c b/sound/soc/codecs/wm8400.c index af6d227e67be..d2a092850283 100644 --- a/sound/soc/codecs/wm8400.c +++ b/sound/soc/codecs/wm8400.c | |||
@@ -143,13 +143,8 @@ static int wm8400_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
143 | } | 143 | } |
144 | 144 | ||
145 | #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ | 145 | #define WM8400_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert, tlv_array) \ |
146 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 146 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
147 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 147 | snd_soc_get_volsw, wm8400_outpga_put_volsw_vu, tlv_array) |
148 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
149 | .tlv.p = (tlv_array), \ | ||
150 | .info = snd_soc_info_volsw, \ | ||
151 | .get = snd_soc_get_volsw, .put = wm8400_outpga_put_volsw_vu, \ | ||
152 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
153 | 148 | ||
154 | 149 | ||
155 | static const char *wm8400_digital_sidetone[] = | 150 | static const char *wm8400_digital_sidetone[] = |
diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 9d88437cdcd1..fa24cedee687 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c | |||
@@ -403,10 +403,8 @@ static int wm8903_class_w_put(struct snd_kcontrol *kcontrol, | |||
403 | } | 403 | } |
404 | 404 | ||
405 | #define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ | 405 | #define SOC_DAPM_SINGLE_W(xname, reg, shift, max, invert) \ |
406 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 406 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
407 | .info = snd_soc_info_volsw, \ | 407 | snd_soc_dapm_get_volsw, wm8903_class_w_put) |
408 | .get = snd_soc_dapm_get_volsw, .put = wm8903_class_w_put, \ | ||
409 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
410 | 408 | ||
411 | 409 | ||
412 | static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; | 410 | static int wm8903_deemph[] = { 0, 32000, 44100, 48000 }; |
diff --git a/sound/soc/codecs/wm8904.c b/sound/soc/codecs/wm8904.c index 3ff195c541db..4c9fb142cb2d 100644 --- a/sound/soc/codecs/wm8904.c +++ b/sound/soc/codecs/wm8904.c | |||
@@ -603,13 +603,8 @@ SOC_DOUBLE_R("Capture Switch", WM8904_ANALOGUE_LEFT_INPUT_0, | |||
603 | 603 | ||
604 | SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), | 604 | SOC_SINGLE("High Pass Filter Switch", WM8904_ADC_DIGITAL_0, 4, 1, 0), |
605 | SOC_ENUM("High Pass Filter Mode", hpf_mode), | 605 | SOC_ENUM("High Pass Filter Mode", hpf_mode), |
606 | 606 | SOC_SINGLE_EXT("ADC 128x OSR Switch", WM8904_ANALOGUE_ADC_0, 0, 1, 0, | |
607 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, | 607 | snd_soc_get_volsw, wm8904_adc_osr_put), |
608 | .name = "ADC 128x OSR Switch", | ||
609 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw, | ||
610 | .put = wm8904_adc_osr_put, | ||
611 | .private_value = SOC_SINGLE_VALUE(WM8904_ANALOGUE_ADC_0, 0, 1, 0), | ||
612 | }, | ||
613 | }; | 608 | }; |
614 | 609 | ||
615 | static const char *drc_path_text[] = { | 610 | static const char *drc_path_text[] = { |
diff --git a/sound/soc/codecs/wm8990.c b/sound/soc/codecs/wm8990.c index 837978e16e9d..253c88bb7a4c 100644 --- a/sound/soc/codecs/wm8990.c +++ b/sound/soc/codecs/wm8990.c | |||
@@ -151,14 +151,9 @@ static int wm899x_outpga_put_volsw_vu(struct snd_kcontrol *kcontrol, | |||
151 | } | 151 | } |
152 | 152 | ||
153 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ | 153 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ |
154 | tlv_array) {\ | 154 | tlv_array) \ |
155 | .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 155 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
156 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 156 | snd_soc_get_volsw, wm899x_outpga_put_volsw_vu, tlv_array) |
157 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
158 | .tlv.p = (tlv_array), \ | ||
159 | .info = snd_soc_info_volsw, \ | ||
160 | .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ | ||
161 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
162 | 157 | ||
163 | 158 | ||
164 | static const char *wm8990_digital_sidetone[] = | 159 | static const char *wm8990_digital_sidetone[] = |
diff --git a/sound/soc/codecs/wm8991.h b/sound/soc/codecs/wm8991.h index 8a942efd18a5..07707d8d7e20 100644 --- a/sound/soc/codecs/wm8991.h +++ b/sound/soc/codecs/wm8991.h | |||
@@ -822,12 +822,7 @@ | |||
822 | 822 | ||
823 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ | 823 | #define SOC_WM899X_OUTPGA_SINGLE_R_TLV(xname, reg, shift, max, invert,\ |
824 | tlv_array) \ | 824 | tlv_array) \ |
825 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ | 825 | SOC_SINGLE_EXT_TLV(xname, reg, shift, max, invert, \ |
826 | .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ |\ | 826 | snd_soc_get_volsw, wm899x_outpga_put_volsw_vu, tlv_array) |
827 | SNDRV_CTL_ELEM_ACCESS_READWRITE,\ | ||
828 | .tlv.p = (tlv_array), \ | ||
829 | .info = snd_soc_info_volsw, \ | ||
830 | .get = snd_soc_get_volsw, .put = wm899x_outpga_put_volsw_vu, \ | ||
831 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
832 | 827 | ||
833 | #endif /* _WM8991_H */ | 828 | #endif /* _WM8991_H */ |
diff --git a/sound/soc/codecs/wm8994.c b/sound/soc/codecs/wm8994.c index 25580b5a853f..1d4b1ec66e36 100644 --- a/sound/soc/codecs/wm8994.c +++ b/sound/soc/codecs/wm8994.c | |||
@@ -290,10 +290,8 @@ static const DECLARE_TLV_DB_SCALE(ng_tlv, -10200, 600, 0); | |||
290 | static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); | 290 | static const DECLARE_TLV_DB_SCALE(mixin_boost_tlv, 0, 900, 0); |
291 | 291 | ||
292 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ | 292 | #define WM8994_DRC_SWITCH(xname, reg, shift) \ |
293 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 293 | SOC_SINGLE_EXT(xname, reg, shift, 1, 0, \ |
294 | .info = snd_soc_info_volsw, .get = snd_soc_get_volsw,\ | 294 | snd_soc_get_volsw, wm8994_put_drc_sw) |
295 | .put = wm8994_put_drc_sw, \ | ||
296 | .private_value = SOC_SINGLE_VALUE(reg, shift, 1, 0) } | ||
297 | 295 | ||
298 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, | 296 | static int wm8994_put_drc_sw(struct snd_kcontrol *kcontrol, |
299 | struct snd_ctl_elem_value *ucontrol) | 297 | struct snd_ctl_elem_value *ucontrol) |
@@ -1433,10 +1431,8 @@ SOC_DAPM_SINGLE("AIF1.1 Switch", WM8994_DAC2_RIGHT_MIXER_ROUTING, | |||
1433 | }; | 1431 | }; |
1434 | 1432 | ||
1435 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ | 1433 | #define WM8994_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ |
1436 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 1434 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
1437 | .info = snd_soc_info_volsw, \ | 1435 | snd_soc_get_volsw, wm8994_put_class_w) |
1438 | .get = snd_soc_dapm_get_volsw, .put = wm8994_put_class_w, \ | ||
1439 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
1440 | 1436 | ||
1441 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, | 1437 | static int wm8994_put_class_w(struct snd_kcontrol *kcontrol, |
1442 | struct snd_ctl_elem_value *ucontrol) | 1438 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/soc/codecs/wm8995.h b/sound/soc/codecs/wm8995.h index 5642121c4977..508ad27fe2bb 100644 --- a/sound/soc/codecs/wm8995.h +++ b/sound/soc/codecs/wm8995.h | |||
@@ -4237,11 +4237,8 @@ | |||
4237 | #define WM8995_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ | 4237 | #define WM8995_SPK2_MUTE_SEQ1_WIDTH 8 /* SPK2_MUTE_SEQ1 - [7:0] */ |
4238 | 4238 | ||
4239 | #define WM8995_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ | 4239 | #define WM8995_CLASS_W_SWITCH(xname, reg, shift, max, invert) \ |
4240 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 4240 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
4241 | .info = snd_soc_info_volsw, \ | 4241 | snd_soc_dapm_get_volsw, wm8995_put_class_w) |
4242 | .get = snd_soc_dapm_get_volsw, .put = wm8995_put_class_w, \ | ||
4243 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) \ | ||
4244 | } | ||
4245 | 4242 | ||
4246 | struct wm8995_reg_access { | 4243 | struct wm8995_reg_access { |
4247 | u16 read; | 4244 | u16 read; |
diff --git a/sound/soc/codecs/wm9705.c b/sound/soc/codecs/wm9705.c index 05b1f346695b..70ce6793c5bd 100644 --- a/sound/soc/codecs/wm9705.c +++ b/sound/soc/codecs/wm9705.c | |||
@@ -209,7 +209,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, unsigned int reg) | |||
209 | case AC97_RESET: | 209 | case AC97_RESET: |
210 | case AC97_VENDOR_ID1: | 210 | case AC97_VENDOR_ID1: |
211 | case AC97_VENDOR_ID2: | 211 | case AC97_VENDOR_ID2: |
212 | return soc_ac97_ops.read(codec->ac97, reg); | 212 | return soc_ac97_ops->read(codec->ac97, reg); |
213 | default: | 213 | default: |
214 | reg = reg >> 1; | 214 | reg = reg >> 1; |
215 | 215 | ||
@@ -225,7 +225,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
225 | { | 225 | { |
226 | u16 *cache = codec->reg_cache; | 226 | u16 *cache = codec->reg_cache; |
227 | 227 | ||
228 | soc_ac97_ops.write(codec->ac97, reg, val); | 228 | soc_ac97_ops->write(codec->ac97, reg, val); |
229 | reg = reg >> 1; | 229 | reg = reg >> 1; |
230 | if (reg < (ARRAY_SIZE(wm9705_reg))) | 230 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | cache[reg] = val; | 231 | cache[reg] = val; |
@@ -294,8 +294,8 @@ static struct snd_soc_dai_driver wm9705_dai[] = { | |||
294 | 294 | ||
295 | static int wm9705_reset(struct snd_soc_codec *codec) | 295 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | { | 296 | { |
297 | if (soc_ac97_ops.reset) { | 297 | if (soc_ac97_ops->reset) { |
298 | soc_ac97_ops.reset(codec->ac97); | 298 | soc_ac97_ops->reset(codec->ac97); |
299 | if (ac97_read(codec, 0) == wm9705_reg[0]) | 299 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | return 0; /* Success */ | 300 | return 0; /* Success */ |
301 | } | 301 | } |
@@ -306,7 +306,7 @@ static int wm9705_reset(struct snd_soc_codec *codec) | |||
306 | #ifdef CONFIG_PM | 306 | #ifdef CONFIG_PM |
307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) | 307 | static int wm9705_soc_suspend(struct snd_soc_codec *codec) |
308 | { | 308 | { |
309 | soc_ac97_ops.write(codec->ac97, AC97_POWERDOWN, 0xffff); | 309 | soc_ac97_ops->write(codec->ac97, AC97_POWERDOWN, 0xffff); |
310 | 310 | ||
311 | return 0; | 311 | return 0; |
312 | } | 312 | } |
@@ -323,7 +323,7 @@ static int wm9705_soc_resume(struct snd_soc_codec *codec) | |||
323 | } | 323 | } |
324 | 324 | ||
325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { | 325 | for (i = 2; i < ARRAY_SIZE(wm9705_reg) << 1; i += 2) { |
326 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 326 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
327 | } | 327 | } |
328 | 328 | ||
329 | return 0; | 329 | return 0; |
@@ -337,9 +337,7 @@ static int wm9705_soc_probe(struct snd_soc_codec *codec) | |||
337 | { | 337 | { |
338 | int ret = 0; | 338 | int ret = 0; |
339 | 339 | ||
340 | printk(KERN_INFO "WM9705 SoC Audio Codec\n"); | 340 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
341 | |||
342 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | ||
343 | if (ret < 0) { | 341 | if (ret < 0) { |
344 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); | 342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
345 | return ret; | 343 | return ret; |
diff --git a/sound/soc/codecs/wm9712.c b/sound/soc/codecs/wm9712.c index 8e9a6a3eeb1a..c5eb746087b4 100644 --- a/sound/soc/codecs/wm9712.c +++ b/sound/soc/codecs/wm9712.c | |||
@@ -455,7 +455,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | reg == AC97_REC_GAIN) | 457 | reg == AC97_REC_GAIN) |
458 | return soc_ac97_ops.read(codec->ac97, reg); | 458 | return soc_ac97_ops->read(codec->ac97, reg); |
459 | else { | 459 | else { |
460 | reg = reg >> 1; | 460 | reg = reg >> 1; |
461 | 461 | ||
@@ -472,7 +472,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
472 | u16 *cache = codec->reg_cache; | 472 | u16 *cache = codec->reg_cache; |
473 | 473 | ||
474 | if (reg < 0x7c) | 474 | if (reg < 0x7c) |
475 | soc_ac97_ops.write(codec->ac97, reg, val); | 475 | soc_ac97_ops->write(codec->ac97, reg, val); |
476 | reg = reg >> 1; | 476 | reg = reg >> 1; |
477 | if (reg < (ARRAY_SIZE(wm9712_reg))) | 477 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | cache[reg] = val; | 478 | cache[reg] = val; |
@@ -581,15 +581,15 @@ static int wm9712_set_bias_level(struct snd_soc_codec *codec, | |||
581 | 581 | ||
582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) | 582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | { | 583 | { |
584 | if (try_warm && soc_ac97_ops.warm_reset) { | 584 | if (try_warm && soc_ac97_ops->warm_reset) { |
585 | soc_ac97_ops.warm_reset(codec->ac97); | 585 | soc_ac97_ops->warm_reset(codec->ac97); |
586 | if (ac97_read(codec, 0) == wm9712_reg[0]) | 586 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | return 1; | 587 | return 1; |
588 | } | 588 | } |
589 | 589 | ||
590 | soc_ac97_ops.reset(codec->ac97); | 590 | soc_ac97_ops->reset(codec->ac97); |
591 | if (soc_ac97_ops.warm_reset) | 591 | if (soc_ac97_ops->warm_reset) |
592 | soc_ac97_ops.warm_reset(codec->ac97); | 592 | soc_ac97_ops->warm_reset(codec->ac97); |
593 | if (ac97_read(codec, 0) != wm9712_reg[0]) | 593 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | goto err; | 594 | goto err; |
595 | return 0; | 595 | return 0; |
@@ -624,7 +624,7 @@ static int wm9712_soc_resume(struct snd_soc_codec *codec) | |||
624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || | 624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | (i > 0x58 && i != 0x5c)) | 625 | (i > 0x58 && i != 0x5c)) |
626 | continue; | 626 | continue; |
627 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 627 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
628 | } | 628 | } |
629 | } | 629 | } |
630 | 630 | ||
@@ -635,7 +635,7 @@ static int wm9712_soc_probe(struct snd_soc_codec *codec) | |||
635 | { | 635 | { |
636 | int ret = 0; | 636 | int ret = 0; |
637 | 637 | ||
638 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 638 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
639 | if (ret < 0) { | 639 | if (ret < 0) { |
640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
641 | return ret; | 641 | return ret; |
diff --git a/sound/soc/codecs/wm9713.c b/sound/soc/codecs/wm9713.c index f7afa68d8c7f..a53e175c015a 100644 --- a/sound/soc/codecs/wm9713.c +++ b/sound/soc/codecs/wm9713.c | |||
@@ -652,7 +652,7 @@ static unsigned int ac97_read(struct snd_soc_codec *codec, | |||
652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || | 652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || | 653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | reg == AC97_CD) | 654 | reg == AC97_CD) |
655 | return soc_ac97_ops.read(codec->ac97, reg); | 655 | return soc_ac97_ops->read(codec->ac97, reg); |
656 | else { | 656 | else { |
657 | reg = reg >> 1; | 657 | reg = reg >> 1; |
658 | 658 | ||
@@ -668,7 +668,7 @@ static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, | |||
668 | { | 668 | { |
669 | u16 *cache = codec->reg_cache; | 669 | u16 *cache = codec->reg_cache; |
670 | if (reg < 0x7c) | 670 | if (reg < 0x7c) |
671 | soc_ac97_ops.write(codec->ac97, reg, val); | 671 | soc_ac97_ops->write(codec->ac97, reg, val); |
672 | reg = reg >> 1; | 672 | reg = reg >> 1; |
673 | if (reg < (ARRAY_SIZE(wm9713_reg))) | 673 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | cache[reg] = val; | 674 | cache[reg] = val; |
@@ -1095,15 +1095,15 @@ static struct snd_soc_dai_driver wm9713_dai[] = { | |||
1095 | 1095 | ||
1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) | 1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | { | 1097 | { |
1098 | if (try_warm && soc_ac97_ops.warm_reset) { | 1098 | if (try_warm && soc_ac97_ops->warm_reset) { |
1099 | soc_ac97_ops.warm_reset(codec->ac97); | 1099 | soc_ac97_ops->warm_reset(codec->ac97); |
1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) | 1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | return 1; | 1101 | return 1; |
1102 | } | 1102 | } |
1103 | 1103 | ||
1104 | soc_ac97_ops.reset(codec->ac97); | 1104 | soc_ac97_ops->reset(codec->ac97); |
1105 | if (soc_ac97_ops.warm_reset) | 1105 | if (soc_ac97_ops->warm_reset) |
1106 | soc_ac97_ops.warm_reset(codec->ac97); | 1106 | soc_ac97_ops->warm_reset(codec->ac97); |
1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) | 1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) |
1108 | return -EIO; | 1108 | return -EIO; |
1109 | return 0; | 1109 | return 0; |
@@ -1180,7 +1180,7 @@ static int wm9713_soc_resume(struct snd_soc_codec *codec) | |||
1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || | 1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) | 1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | continue; | 1182 | continue; |
1183 | soc_ac97_ops.write(codec->ac97, i, cache[i>>1]); | 1183 | soc_ac97_ops->write(codec->ac97, i, cache[i>>1]); |
1184 | } | 1184 | } |
1185 | } | 1185 | } |
1186 | 1186 | ||
@@ -1197,7 +1197,7 @@ static int wm9713_soc_probe(struct snd_soc_codec *codec) | |||
1197 | return -ENOMEM; | 1197 | return -ENOMEM; |
1198 | snd_soc_codec_set_drvdata(codec, wm9713); | 1198 | snd_soc_codec_set_drvdata(codec, wm9713); |
1199 | 1199 | ||
1200 | ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | 1200 | ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); |
1201 | if (ret < 0) | 1201 | if (ret < 0) |
1202 | goto codec_err; | 1202 | goto codec_err; |
1203 | 1203 | ||
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h index 6e890b916592..9f922c82536c 100644 --- a/sound/soc/codecs/wm_adsp.h +++ b/sound/soc/codecs/wm_adsp.h | |||
@@ -61,14 +61,12 @@ struct wm_adsp { | |||
61 | }; | 61 | }; |
62 | 62 | ||
63 | #define WM_ADSP1(wname, num) \ | 63 | #define WM_ADSP1(wname, num) \ |
64 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 64 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
65 | .shift = num, .event = wm_adsp1_event, \ | 65 | wm_adsp1_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
66 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
67 | 66 | ||
68 | #define WM_ADSP2(wname, num) \ | 67 | #define WM_ADSP2(wname, num) \ |
69 | { .id = snd_soc_dapm_pga, .name = wname, .reg = SND_SOC_NOPM, \ | 68 | SND_SOC_DAPM_PGA_E(wname, SND_SOC_NOPM, num, 0, NULL, 0, \ |
70 | .shift = num, .event = wm_adsp2_event, \ | 69 | wm_adsp2_event, SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD) |
71 | .event_flags = SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD } | ||
72 | 70 | ||
73 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; | 71 | extern const struct snd_kcontrol_new wm_adsp1_fw_controls[]; |
74 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; | 72 | extern const struct snd_kcontrol_new wm_adsp2_fw_controls[]; |
diff --git a/sound/soc/codecs/wm_hubs.c b/sound/soc/codecs/wm_hubs.c index f5d81b948759..2d9e099415a5 100644 --- a/sound/soc/codecs/wm_hubs.c +++ b/sound/soc/codecs/wm_hubs.c | |||
@@ -693,10 +693,8 @@ void wm_hubs_update_class_w(struct snd_soc_codec *codec) | |||
693 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); | 693 | EXPORT_SYMBOL_GPL(wm_hubs_update_class_w); |
694 | 694 | ||
695 | #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \ | 695 | #define WM_HUBS_SINGLE_W(xname, reg, shift, max, invert) \ |
696 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, \ | 696 | SOC_SINGLE_EXT(xname, reg, shift, max, invert, \ |
697 | .info = snd_soc_info_volsw, \ | 697 | snd_soc_dapm_get_volsw, class_w_put_volsw) |
698 | .get = snd_soc_dapm_get_volsw, .put = class_w_put_volsw, \ | ||
699 | .private_value = SOC_SINGLE_VALUE(reg, shift, max, invert) } | ||
700 | 698 | ||
701 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, | 699 | static int class_w_put_volsw(struct snd_kcontrol *kcontrol, |
702 | struct snd_ctl_elem_value *ucontrol) | 700 | struct snd_ctl_elem_value *ucontrol) |
diff --git a/sound/soc/fsl/imx-ssi.c b/sound/soc/fsl/imx-ssi.c index a8362be3cd18..51be3772cba9 100644 --- a/sound/soc/fsl/imx-ssi.c +++ b/sound/soc/fsl/imx-ssi.c | |||
@@ -501,13 +501,12 @@ static void imx_ssi_ac97_warm_reset(struct snd_ac97 *ac97) | |||
501 | imx_ssi_ac97_read(ac97, 0); | 501 | imx_ssi_ac97_read(ac97, 0); |
502 | } | 502 | } |
503 | 503 | ||
504 | struct snd_ac97_bus_ops soc_ac97_ops = { | 504 | static struct snd_ac97_bus_ops imx_ssi_ac97_ops = { |
505 | .read = imx_ssi_ac97_read, | 505 | .read = imx_ssi_ac97_read, |
506 | .write = imx_ssi_ac97_write, | 506 | .write = imx_ssi_ac97_write, |
507 | .reset = imx_ssi_ac97_reset, | 507 | .reset = imx_ssi_ac97_reset, |
508 | .warm_reset = imx_ssi_ac97_warm_reset | 508 | .warm_reset = imx_ssi_ac97_warm_reset |
509 | }; | 509 | }; |
510 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
511 | 510 | ||
512 | static int imx_ssi_probe(struct platform_device *pdev) | 511 | static int imx_ssi_probe(struct platform_device *pdev) |
513 | { | 512 | { |
@@ -583,6 +582,12 @@ static int imx_ssi_probe(struct platform_device *pdev) | |||
583 | 582 | ||
584 | platform_set_drvdata(pdev, ssi); | 583 | platform_set_drvdata(pdev, ssi); |
585 | 584 | ||
585 | ret = snd_soc_set_ac97_ops(&imx_ssi_ac97_ops); | ||
586 | if (ret != 0) { | ||
587 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
588 | goto failed_register; | ||
589 | } | ||
590 | |||
586 | ret = snd_soc_register_component(&pdev->dev, &imx_component, | 591 | ret = snd_soc_register_component(&pdev->dev, &imx_component, |
587 | dai, 1); | 592 | dai, 1); |
588 | if (ret) { | 593 | if (ret) { |
@@ -608,6 +613,7 @@ failed_register: | |||
608 | release_mem_region(res->start, resource_size(res)); | 613 | release_mem_region(res->start, resource_size(res)); |
609 | clk_disable_unprepare(ssi->clk); | 614 | clk_disable_unprepare(ssi->clk); |
610 | failed_clk: | 615 | failed_clk: |
616 | snd_soc_set_ac97_ops(NULL); | ||
611 | 617 | ||
612 | return ret; | 618 | return ret; |
613 | } | 619 | } |
@@ -627,6 +633,7 @@ static int imx_ssi_remove(struct platform_device *pdev) | |||
627 | 633 | ||
628 | release_mem_region(res->start, resource_size(res)); | 634 | release_mem_region(res->start, resource_size(res)); |
629 | clk_disable_unprepare(ssi->clk); | 635 | clk_disable_unprepare(ssi->clk); |
636 | snd_soc_set_ac97_ops(NULL); | ||
630 | 637 | ||
631 | return 0; | 638 | return 0; |
632 | } | 639 | } |
diff --git a/sound/soc/fsl/mpc5200_psc_ac97.c b/sound/soc/fsl/mpc5200_psc_ac97.c index 4141b35ef0bb..3ef7a0c92efa 100644 --- a/sound/soc/fsl/mpc5200_psc_ac97.c +++ b/sound/soc/fsl/mpc5200_psc_ac97.c | |||
@@ -131,13 +131,12 @@ static void psc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
131 | psc_ac97_warm_reset(ac97); | 131 | psc_ac97_warm_reset(ac97); |
132 | } | 132 | } |
133 | 133 | ||
134 | struct snd_ac97_bus_ops soc_ac97_ops = { | 134 | static struct snd_ac97_bus_ops psc_ac97_ops = { |
135 | .read = psc_ac97_read, | 135 | .read = psc_ac97_read, |
136 | .write = psc_ac97_write, | 136 | .write = psc_ac97_write, |
137 | .reset = psc_ac97_cold_reset, | 137 | .reset = psc_ac97_cold_reset, |
138 | .warm_reset = psc_ac97_warm_reset, | 138 | .warm_reset = psc_ac97_warm_reset, |
139 | }; | 139 | }; |
140 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
141 | 140 | ||
142 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, | 141 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, |
143 | struct snd_pcm_hw_params *params, | 142 | struct snd_pcm_hw_params *params, |
@@ -290,6 +289,12 @@ static int psc_ac97_of_probe(struct platform_device *op) | |||
290 | if (rc != 0) | 289 | if (rc != 0) |
291 | return rc; | 290 | return rc; |
292 | 291 | ||
292 | rc = snd_soc_set_ac97_ops(&psc_ac97_ops); | ||
293 | if (rc != 0) { | ||
294 | dev_err(&op->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
295 | return rc; | ||
296 | } | ||
297 | |||
293 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, | 298 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, |
294 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); | 299 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
295 | if (rc != 0) { | 300 | if (rc != 0) { |
@@ -318,6 +323,7 @@ static int psc_ac97_of_remove(struct platform_device *op) | |||
318 | { | 323 | { |
319 | mpc5200_audio_dma_destroy(op); | 324 | mpc5200_audio_dma_destroy(op); |
320 | snd_soc_unregister_component(&op->dev); | 325 | snd_soc_unregister_component(&op->dev); |
326 | snd_soc_set_ac97_ops(NULL); | ||
321 | return 0; | 327 | return 0; |
322 | } | 328 | } |
323 | 329 | ||
diff --git a/sound/soc/mid-x86/mfld_machine.c b/sound/soc/mid-x86/mfld_machine.c index 78d582519891..ee363845759e 100644 --- a/sound/soc/mid-x86/mfld_machine.c +++ b/sound/soc/mid-x86/mfld_machine.c | |||
@@ -371,7 +371,7 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) | |||
371 | 371 | ||
372 | /* audio interrupt base of SRAM location where | 372 | /* audio interrupt base of SRAM location where |
373 | * interrupts are stored by System FW */ | 373 | * interrupts are stored by System FW */ |
374 | mc_drv_ctx = kzalloc(sizeof(*mc_drv_ctx), GFP_ATOMIC); | 374 | mc_drv_ctx = devm_kzalloc(&pdev->dev, sizeof(*mc_drv_ctx), GFP_ATOMIC); |
375 | if (!mc_drv_ctx) { | 375 | if (!mc_drv_ctx) { |
376 | pr_err("allocation failed\n"); | 376 | pr_err("allocation failed\n"); |
377 | return -ENOMEM; | 377 | return -ENOMEM; |
@@ -381,50 +381,39 @@ static int snd_mfld_mc_probe(struct platform_device *pdev) | |||
381 | pdev, IORESOURCE_MEM, "IRQ_BASE"); | 381 | pdev, IORESOURCE_MEM, "IRQ_BASE"); |
382 | if (!irq_mem) { | 382 | if (!irq_mem) { |
383 | pr_err("no mem resource given\n"); | 383 | pr_err("no mem resource given\n"); |
384 | ret_val = -ENODEV; | 384 | return -ENODEV; |
385 | goto unalloc; | ||
386 | } | 385 | } |
387 | mc_drv_ctx->int_base = ioremap_nocache(irq_mem->start, | 386 | mc_drv_ctx->int_base = devm_ioremap_nocache(&pdev->dev, irq_mem->start, |
388 | resource_size(irq_mem)); | 387 | resource_size(irq_mem)); |
389 | if (!mc_drv_ctx->int_base) { | 388 | if (!mc_drv_ctx->int_base) { |
390 | pr_err("Mapping of cache failed\n"); | 389 | pr_err("Mapping of cache failed\n"); |
391 | ret_val = -ENOMEM; | 390 | return -ENOMEM; |
392 | goto unalloc; | ||
393 | } | 391 | } |
394 | /* register for interrupt */ | 392 | /* register for interrupt */ |
395 | ret_val = request_threaded_irq(irq, snd_mfld_jack_intr_handler, | 393 | ret_val = devm_request_threaded_irq(&pdev->dev, irq, |
394 | snd_mfld_jack_intr_handler, | ||
396 | snd_mfld_jack_detection, | 395 | snd_mfld_jack_detection, |
397 | IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); | 396 | IRQF_SHARED, pdev->dev.driver->name, mc_drv_ctx); |
398 | if (ret_val) { | 397 | if (ret_val) { |
399 | pr_err("cannot register IRQ\n"); | 398 | pr_err("cannot register IRQ\n"); |
400 | goto unalloc; | 399 | return ret_val; |
401 | } | 400 | } |
402 | /* register the soc card */ | 401 | /* register the soc card */ |
403 | snd_soc_card_mfld.dev = &pdev->dev; | 402 | snd_soc_card_mfld.dev = &pdev->dev; |
404 | ret_val = snd_soc_register_card(&snd_soc_card_mfld); | 403 | ret_val = snd_soc_register_card(&snd_soc_card_mfld); |
405 | if (ret_val) { | 404 | if (ret_val) { |
406 | pr_debug("snd_soc_register_card failed %d\n", ret_val); | 405 | pr_debug("snd_soc_register_card failed %d\n", ret_val); |
407 | goto freeirq; | 406 | return ret_val; |
408 | } | 407 | } |
409 | platform_set_drvdata(pdev, mc_drv_ctx); | 408 | platform_set_drvdata(pdev, mc_drv_ctx); |
410 | pr_debug("successfully exited probe\n"); | 409 | pr_debug("successfully exited probe\n"); |
411 | return ret_val; | 410 | return 0; |
412 | |||
413 | freeirq: | ||
414 | free_irq(irq, mc_drv_ctx); | ||
415 | unalloc: | ||
416 | kfree(mc_drv_ctx); | ||
417 | return ret_val; | ||
418 | } | 411 | } |
419 | 412 | ||
420 | static int snd_mfld_mc_remove(struct platform_device *pdev) | 413 | static int snd_mfld_mc_remove(struct platform_device *pdev) |
421 | { | 414 | { |
422 | struct mfld_mc_private *mc_drv_ctx = platform_get_drvdata(pdev); | ||
423 | |||
424 | pr_debug("snd_mfld_mc_remove called\n"); | 415 | pr_debug("snd_mfld_mc_remove called\n"); |
425 | free_irq(platform_get_irq(pdev, 0), mc_drv_ctx); | ||
426 | snd_soc_unregister_card(&snd_soc_card_mfld); | 416 | snd_soc_unregister_card(&snd_soc_card_mfld); |
427 | kfree(mc_drv_ctx); | ||
428 | return 0; | 417 | return 0; |
429 | } | 418 | } |
430 | 419 | ||
diff --git a/sound/soc/nuc900/nuc900-ac97.c b/sound/soc/nuc900/nuc900-ac97.c index fe3285ceaf5b..f4c2417a8730 100644 --- a/sound/soc/nuc900/nuc900-ac97.c +++ b/sound/soc/nuc900/nuc900-ac97.c | |||
@@ -197,13 +197,12 @@ static void nuc900_ac97_cold_reset(struct snd_ac97 *ac97) | |||
197 | } | 197 | } |
198 | 198 | ||
199 | /* AC97 controller operations */ | 199 | /* AC97 controller operations */ |
200 | struct snd_ac97_bus_ops soc_ac97_ops = { | 200 | static struct snd_ac97_bus_ops nuc900_ac97_ops = { |
201 | .read = nuc900_ac97_read, | 201 | .read = nuc900_ac97_read, |
202 | .write = nuc900_ac97_write, | 202 | .write = nuc900_ac97_write, |
203 | .reset = nuc900_ac97_cold_reset, | 203 | .reset = nuc900_ac97_cold_reset, |
204 | .warm_reset = nuc900_ac97_warm_reset, | 204 | .warm_reset = nuc900_ac97_warm_reset, |
205 | } | 205 | }; |
206 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
207 | 206 | ||
208 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, | 207 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, |
209 | int cmd, struct snd_soc_dai *dai) | 208 | int cmd, struct snd_soc_dai *dai) |
@@ -326,64 +325,52 @@ static int nuc900_ac97_drvprobe(struct platform_device *pdev) | |||
326 | if (nuc900_ac97_data) | 325 | if (nuc900_ac97_data) |
327 | return -EBUSY; | 326 | return -EBUSY; |
328 | 327 | ||
329 | nuc900_audio = kzalloc(sizeof(struct nuc900_audio), GFP_KERNEL); | 328 | nuc900_audio = devm_kzalloc(&pdev->dev, sizeof(struct nuc900_audio), |
329 | GFP_KERNEL); | ||
330 | if (!nuc900_audio) | 330 | if (!nuc900_audio) |
331 | return -ENOMEM; | 331 | return -ENOMEM; |
332 | 332 | ||
333 | spin_lock_init(&nuc900_audio->lock); | 333 | spin_lock_init(&nuc900_audio->lock); |
334 | 334 | ||
335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | 335 | nuc900_audio->res = platform_get_resource(pdev, IORESOURCE_MEM, 0); |
336 | if (!nuc900_audio->res) { | 336 | if (!nuc900_audio->res) |
337 | ret = -ENODEV; | 337 | return ret; |
338 | goto out0; | ||
339 | } | ||
340 | |||
341 | if (!request_mem_region(nuc900_audio->res->start, | ||
342 | resource_size(nuc900_audio->res), pdev->name)) { | ||
343 | ret = -EBUSY; | ||
344 | goto out0; | ||
345 | } | ||
346 | 338 | ||
347 | nuc900_audio->mmio = ioremap(nuc900_audio->res->start, | 339 | nuc900_audio->mmio = devm_ioremap_resource(&pdev->dev, |
348 | resource_size(nuc900_audio->res)); | 340 | nuc900_audio->res); |
349 | if (!nuc900_audio->mmio) { | 341 | if (IS_ERR(nuc900_audio->mmio)) |
350 | ret = -ENOMEM; | 342 | return PTR_ERR(nuc900_audio->mmio); |
351 | goto out1; | ||
352 | } | ||
353 | 343 | ||
354 | nuc900_audio->clk = clk_get(&pdev->dev, NULL); | 344 | nuc900_audio->clk = devm_clk_get(&pdev->dev, NULL); |
355 | if (IS_ERR(nuc900_audio->clk)) { | 345 | if (IS_ERR(nuc900_audio->clk)) { |
356 | ret = PTR_ERR(nuc900_audio->clk); | 346 | ret = PTR_ERR(nuc900_audio->clk); |
357 | goto out2; | 347 | goto out; |
358 | } | 348 | } |
359 | 349 | ||
360 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); | 350 | nuc900_audio->irq_num = platform_get_irq(pdev, 0); |
361 | if (!nuc900_audio->irq_num) { | 351 | if (!nuc900_audio->irq_num) { |
362 | ret = -EBUSY; | 352 | ret = -EBUSY; |
363 | goto out3; | 353 | goto out; |
364 | } | 354 | } |
365 | 355 | ||
366 | nuc900_ac97_data = nuc900_audio; | 356 | nuc900_ac97_data = nuc900_audio; |
367 | 357 | ||
358 | ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); | ||
359 | if (ret) | ||
360 | goto out; | ||
361 | |||
368 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, | 362 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, |
369 | &nuc900_ac97_dai, 1); | 363 | &nuc900_ac97_dai, 1); |
370 | if (ret) | 364 | if (ret) |
371 | goto out3; | 365 | goto out; |
372 | 366 | ||
373 | /* enbale ac97 multifunction pin */ | 367 | /* enbale ac97 multifunction pin */ |
374 | mfp_set_groupg(nuc900_audio->dev, NULL); | 368 | mfp_set_groupg(nuc900_audio->dev, NULL); |
375 | 369 | ||
376 | return 0; | 370 | return 0; |
377 | 371 | ||
378 | out3: | 372 | out: |
379 | clk_put(nuc900_audio->clk); | 373 | snd_soc_set_ac97_ops(NULL); |
380 | out2: | ||
381 | iounmap(nuc900_audio->mmio); | ||
382 | out1: | ||
383 | release_mem_region(nuc900_audio->res->start, | ||
384 | resource_size(nuc900_audio->res)); | ||
385 | out0: | ||
386 | kfree(nuc900_audio); | ||
387 | return ret; | 374 | return ret; |
388 | } | 375 | } |
389 | 376 | ||
@@ -391,13 +378,8 @@ static int nuc900_ac97_drvremove(struct platform_device *pdev) | |||
391 | { | 378 | { |
392 | snd_soc_unregister_component(&pdev->dev); | 379 | snd_soc_unregister_component(&pdev->dev); |
393 | 380 | ||
394 | clk_put(nuc900_ac97_data->clk); | ||
395 | iounmap(nuc900_ac97_data->mmio); | ||
396 | release_mem_region(nuc900_ac97_data->res->start, | ||
397 | resource_size(nuc900_ac97_data->res)); | ||
398 | |||
399 | kfree(nuc900_ac97_data); | ||
400 | nuc900_ac97_data = NULL; | 381 | nuc900_ac97_data = NULL; |
382 | snd_soc_set_ac97_ops(NULL); | ||
401 | 383 | ||
402 | return 0; | 384 | return 0; |
403 | } | 385 | } |
diff --git a/sound/soc/pxa/pxa2xx-ac97.c b/sound/soc/pxa/pxa2xx-ac97.c index 57ea8e6c5488..a3c22ba25f08 100644 --- a/sound/soc/pxa/pxa2xx-ac97.c +++ b/sound/soc/pxa/pxa2xx-ac97.c | |||
@@ -41,13 +41,12 @@ static void pxa2xx_ac97_cold_reset(struct snd_ac97 *ac97) | |||
41 | pxa2xx_ac97_finish_reset(ac97); | 41 | pxa2xx_ac97_finish_reset(ac97); |
42 | } | 42 | } |
43 | 43 | ||
44 | struct snd_ac97_bus_ops soc_ac97_ops = { | 44 | static struct snd_ac97_bus_ops pxa2xx_ac97_ops = { |
45 | .read = pxa2xx_ac97_read, | 45 | .read = pxa2xx_ac97_read, |
46 | .write = pxa2xx_ac97_write, | 46 | .write = pxa2xx_ac97_write, |
47 | .warm_reset = pxa2xx_ac97_warm_reset, | 47 | .warm_reset = pxa2xx_ac97_warm_reset, |
48 | .reset = pxa2xx_ac97_cold_reset, | 48 | .reset = pxa2xx_ac97_cold_reset, |
49 | }; | 49 | }; |
50 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
51 | 50 | ||
52 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { | 51 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { |
53 | .name = "AC97 PCM Stereo out", | 52 | .name = "AC97 PCM Stereo out", |
@@ -244,6 +243,10 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
244 | return -ENXIO; | 243 | return -ENXIO; |
245 | } | 244 | } |
246 | 245 | ||
246 | ret = snd_soc_set_ac97_ops(&pxa2xx_ac97_ops); | ||
247 | if (ret != 0) | ||
248 | return ret; | ||
249 | |||
247 | /* Punt most of the init to the SoC probe; we may need the machine | 250 | /* Punt most of the init to the SoC probe; we may need the machine |
248 | * driver to do interesting things with the clocking to get us up | 251 | * driver to do interesting things with the clocking to get us up |
249 | * and running. | 252 | * and running. |
@@ -255,6 +258,7 @@ static int pxa2xx_ac97_dev_probe(struct platform_device *pdev) | |||
255 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) | 258 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
256 | { | 259 | { |
257 | snd_soc_unregister_component(&pdev->dev); | 260 | snd_soc_unregister_component(&pdev->dev); |
261 | snd_soc_set_ac97_ops(NULL); | ||
258 | return 0; | 262 | return 0; |
259 | } | 263 | } |
260 | 264 | ||
diff --git a/sound/soc/samsung/ac97.c b/sound/soc/samsung/ac97.c index cb88ead98917..2dd623fa3882 100644 --- a/sound/soc/samsung/ac97.c +++ b/sound/soc/samsung/ac97.c | |||
@@ -214,13 +214,12 @@ static irqreturn_t s3c_ac97_irq(int irq, void *dev_id) | |||
214 | return IRQ_HANDLED; | 214 | return IRQ_HANDLED; |
215 | } | 215 | } |
216 | 216 | ||
217 | struct snd_ac97_bus_ops soc_ac97_ops = { | 217 | static struct snd_ac97_bus_ops s3c_ac97_ops = { |
218 | .read = s3c_ac97_read, | 218 | .read = s3c_ac97_read, |
219 | .write = s3c_ac97_write, | 219 | .write = s3c_ac97_write, |
220 | .warm_reset = s3c_ac97_warm_reset, | 220 | .warm_reset = s3c_ac97_warm_reset, |
221 | .reset = s3c_ac97_cold_reset, | 221 | .reset = s3c_ac97_cold_reset, |
222 | }; | 222 | }; |
223 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
224 | 223 | ||
225 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, | 224 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, |
226 | struct snd_pcm_hw_params *params, | 225 | struct snd_pcm_hw_params *params, |
@@ -417,11 +416,9 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
417 | return -ENXIO; | 416 | return -ENXIO; |
418 | } | 417 | } |
419 | 418 | ||
420 | if (!request_mem_region(mem_res->start, | 419 | s3c_ac97.regs = devm_ioremap_resource(&pdev->dev, mem_res); |
421 | resource_size(mem_res), "ac97")) { | 420 | if (IS_ERR(s3c_ac97.regs)) |
422 | dev_err(&pdev->dev, "Unable to request register region\n"); | 421 | return PTR_ERR(s3c_ac97.regs); |
423 | return -EBUSY; | ||
424 | } | ||
425 | 422 | ||
426 | s3c_ac97_pcm_out.channel = dmatx_res->start; | 423 | s3c_ac97_pcm_out.channel = dmatx_res->start; |
427 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; | 424 | s3c_ac97_pcm_out.dma_addr = mem_res->start + S3C_AC97_PCM_DATA; |
@@ -433,14 +430,7 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
433 | init_completion(&s3c_ac97.done); | 430 | init_completion(&s3c_ac97.done); |
434 | mutex_init(&s3c_ac97.lock); | 431 | mutex_init(&s3c_ac97.lock); |
435 | 432 | ||
436 | s3c_ac97.regs = ioremap(mem_res->start, resource_size(mem_res)); | 433 | s3c_ac97.ac97_clk = devm_clk_get(&pdev->dev, "ac97"); |
437 | if (s3c_ac97.regs == NULL) { | ||
438 | dev_err(&pdev->dev, "Unable to ioremap register region\n"); | ||
439 | ret = -ENXIO; | ||
440 | goto err1; | ||
441 | } | ||
442 | |||
443 | s3c_ac97.ac97_clk = clk_get(&pdev->dev, "ac97"); | ||
444 | if (IS_ERR(s3c_ac97.ac97_clk)) { | 434 | if (IS_ERR(s3c_ac97.ac97_clk)) { |
445 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); | 435 | dev_err(&pdev->dev, "ac97 failed to get ac97_clock\n"); |
446 | ret = -ENODEV; | 436 | ret = -ENODEV; |
@@ -461,6 +451,12 @@ static int s3c_ac97_probe(struct platform_device *pdev) | |||
461 | goto err4; | 451 | goto err4; |
462 | } | 452 | } |
463 | 453 | ||
454 | ret = snd_soc_set_ac97_ops(&s3c_ac97_ops); | ||
455 | if (ret != 0) { | ||
456 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
457 | goto err4; | ||
458 | } | ||
459 | |||
464 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, | 460 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, |
465 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); | 461 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); |
466 | if (ret) | 462 | if (ret) |
@@ -480,18 +476,14 @@ err5: | |||
480 | err4: | 476 | err4: |
481 | err3: | 477 | err3: |
482 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 478 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
483 | clk_put(s3c_ac97.ac97_clk); | ||
484 | err2: | 479 | err2: |
485 | iounmap(s3c_ac97.regs); | 480 | snd_soc_set_ac97_ops(NULL); |
486 | err1: | ||
487 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
488 | |||
489 | return ret; | 481 | return ret; |
490 | } | 482 | } |
491 | 483 | ||
492 | static int s3c_ac97_remove(struct platform_device *pdev) | 484 | static int s3c_ac97_remove(struct platform_device *pdev) |
493 | { | 485 | { |
494 | struct resource *mem_res, *irq_res; | 486 | struct resource *irq_res; |
495 | 487 | ||
496 | asoc_dma_platform_unregister(&pdev->dev); | 488 | asoc_dma_platform_unregister(&pdev->dev); |
497 | snd_soc_unregister_component(&pdev->dev); | 489 | snd_soc_unregister_component(&pdev->dev); |
@@ -501,13 +493,7 @@ static int s3c_ac97_remove(struct platform_device *pdev) | |||
501 | free_irq(irq_res->start, NULL); | 493 | free_irq(irq_res->start, NULL); |
502 | 494 | ||
503 | clk_disable_unprepare(s3c_ac97.ac97_clk); | 495 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
504 | clk_put(s3c_ac97.ac97_clk); | 496 | snd_soc_set_ac97_ops(NULL); |
505 | |||
506 | iounmap(s3c_ac97.regs); | ||
507 | |||
508 | mem_res = platform_get_resource(pdev, IORESOURCE_MEM, 0); | ||
509 | if (mem_res) | ||
510 | release_mem_region(mem_res->start, resource_size(mem_res)); | ||
511 | 497 | ||
512 | return 0; | 498 | return 0; |
513 | } | 499 | } |
diff --git a/sound/soc/sh/hac.c b/sound/soc/sh/hac.c index af19f77b7bf0..0af2e4dfd139 100644 --- a/sound/soc/sh/hac.c +++ b/sound/soc/sh/hac.c | |||
@@ -227,13 +227,12 @@ static void hac_ac97_coldrst(struct snd_ac97 *ac97) | |||
227 | hac_ac97_warmrst(ac97); | 227 | hac_ac97_warmrst(ac97); |
228 | } | 228 | } |
229 | 229 | ||
230 | struct snd_ac97_bus_ops soc_ac97_ops = { | 230 | static struct snd_ac97_bus_ops hac_ac97_ops = { |
231 | .read = hac_ac97_read, | 231 | .read = hac_ac97_read, |
232 | .write = hac_ac97_write, | 232 | .write = hac_ac97_write, |
233 | .reset = hac_ac97_coldrst, | 233 | .reset = hac_ac97_coldrst, |
234 | .warm_reset = hac_ac97_warmrst, | 234 | .warm_reset = hac_ac97_warmrst, |
235 | }; | 235 | }; |
236 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
237 | 236 | ||
238 | static int hac_hw_params(struct snd_pcm_substream *substream, | 237 | static int hac_hw_params(struct snd_pcm_substream *substream, |
239 | struct snd_pcm_hw_params *params, | 238 | struct snd_pcm_hw_params *params, |
@@ -316,6 +315,10 @@ static const struct snd_soc_component_driver sh4_hac_component = { | |||
316 | 315 | ||
317 | static int hac_soc_platform_probe(struct platform_device *pdev) | 316 | static int hac_soc_platform_probe(struct platform_device *pdev) |
318 | { | 317 | { |
318 | ret = snd_soc_set_ac97_ops(&hac_ac97_ops); | ||
319 | if (ret != 0) | ||
320 | return ret; | ||
321 | |||
319 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, | 322 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, |
320 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); | 323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); |
321 | } | 324 | } |
@@ -323,6 +326,7 @@ static int hac_soc_platform_probe(struct platform_device *pdev) | |||
323 | static int hac_soc_platform_remove(struct platform_device *pdev) | 326 | static int hac_soc_platform_remove(struct platform_device *pdev) |
324 | { | 327 | { |
325 | snd_soc_unregister_component(&pdev->dev); | 328 | snd_soc_unregister_component(&pdev->dev); |
329 | snd_soc_set_ac97_ops(NULL); | ||
326 | return 0; | 330 | return 0; |
327 | } | 331 | } |
328 | 332 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 4489c5b7b53a..309e5c91167b 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -2080,6 +2080,22 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
2080 | } | 2080 | } |
2081 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); | 2081 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
2082 | 2082 | ||
2083 | struct snd_ac97_bus_ops *soc_ac97_ops; | ||
2084 | |||
2085 | int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | ||
2086 | { | ||
2087 | if (ops == soc_ac97_ops) | ||
2088 | return 0; | ||
2089 | |||
2090 | if (soc_ac97_ops && ops) | ||
2091 | return -EBUSY; | ||
2092 | |||
2093 | soc_ac97_ops = ops; | ||
2094 | |||
2095 | return 0; | ||
2096 | } | ||
2097 | EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | ||
2098 | |||
2083 | /** | 2099 | /** |
2084 | * snd_soc_free_ac97_codec - free AC97 codec device | 2100 | * snd_soc_free_ac97_codec - free AC97 codec device |
2085 | * @codec: audio codec | 2101 | * @codec: audio codec |
diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 2f70ea7f6618..f52eab6d2231 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c | |||
@@ -142,13 +142,12 @@ static void tegra20_ac97_codec_write(struct snd_ac97 *ac97_snd, | |||
142 | } while (!time_after(jiffies, timeout)); | 142 | } while (!time_after(jiffies, timeout)); |
143 | } | 143 | } |
144 | 144 | ||
145 | struct snd_ac97_bus_ops soc_ac97_ops = { | 145 | static struct snd_ac97_bus_ops tegra20_ac97_ops = { |
146 | .read = tegra20_ac97_codec_read, | 146 | .read = tegra20_ac97_codec_read, |
147 | .write = tegra20_ac97_codec_write, | 147 | .write = tegra20_ac97_codec_write, |
148 | .reset = tegra20_ac97_codec_reset, | 148 | .reset = tegra20_ac97_codec_reset, |
149 | .warm_reset = tegra20_ac97_codec_warm_reset, | 149 | .warm_reset = tegra20_ac97_codec_warm_reset, |
150 | }; | 150 | }; |
151 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
152 | 151 | ||
153 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) | 152 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) |
154 | { | 153 | { |
@@ -327,7 +326,7 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
327 | } | 326 | } |
328 | dev_set_drvdata(&pdev->dev, ac97); | 327 | dev_set_drvdata(&pdev->dev, ac97); |
329 | 328 | ||
330 | ac97->clk_ac97 = clk_get(&pdev->dev, NULL); | 329 | ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); |
331 | if (IS_ERR(ac97->clk_ac97)) { | 330 | if (IS_ERR(ac97->clk_ac97)) { |
332 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); | 331 | dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); |
333 | ret = PTR_ERR(ac97->clk_ac97); | 332 | ret = PTR_ERR(ac97->clk_ac97); |
@@ -341,18 +340,10 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
341 | goto err_clk_put; | 340 | goto err_clk_put; |
342 | } | 341 | } |
343 | 342 | ||
344 | memregion = devm_request_mem_region(&pdev->dev, mem->start, | 343 | regs = devm_ioremap_resource(&pdev->dev, mem); |
345 | resource_size(mem), DRV_NAME); | 344 | if (IS_ERR(regs)) { |
346 | if (!memregion) { | 345 | ret = PTR_ERR(regs); |
347 | dev_err(&pdev->dev, "Memory region already claimed\n"); | 346 | dev_err(&pdev->dev, "ioremap failed: %d\n", ret); |
348 | ret = -EBUSY; | ||
349 | goto err_clk_put; | ||
350 | } | ||
351 | |||
352 | regs = devm_ioremap(&pdev->dev, mem->start, resource_size(mem)); | ||
353 | if (!regs) { | ||
354 | dev_err(&pdev->dev, "ioremap failed\n"); | ||
355 | ret = -ENOMEM; | ||
356 | goto err_clk_put; | 347 | goto err_clk_put; |
357 | } | 348 | } |
358 | 349 | ||
@@ -403,23 +394,9 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
403 | ac97->capture_dma_data.maxburst = 4; | 394 | ac97->capture_dma_data.maxburst = 4; |
404 | ac97->capture_dma_data.slave_id = of_dma[0]; | 395 | ac97->capture_dma_data.slave_id = of_dma[0]; |
405 | 396 | ||
406 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
407 | &tegra20_ac97_dai, 1); | ||
408 | if (ret) { | ||
409 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
410 | ret = -ENOMEM; | ||
411 | goto err_clk_put; | ||
412 | } | ||
413 | |||
414 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
415 | if (ret) { | ||
416 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
417 | goto err_unregister_component; | ||
418 | } | ||
419 | |||
420 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); | 397 | ret = tegra_asoc_utils_init(&ac97->util_data, &pdev->dev); |
421 | if (ret) | 398 | if (ret) |
422 | goto err_unregister_pcm; | 399 | goto err_clk_put; |
423 | 400 | ||
424 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); | 401 | ret = tegra_asoc_utils_set_ac97_rate(&ac97->util_data); |
425 | if (ret) | 402 | if (ret) |
@@ -431,20 +408,40 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) | |||
431 | goto err_asoc_utils_fini; | 408 | goto err_asoc_utils_fini; |
432 | } | 409 | } |
433 | 410 | ||
411 | ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); | ||
412 | if (ret) { | ||
413 | dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); | ||
414 | goto err_asoc_utils_fini; | ||
415 | } | ||
416 | |||
417 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, | ||
418 | &tegra20_ac97_dai, 1); | ||
419 | if (ret) { | ||
420 | dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); | ||
421 | ret = -ENOMEM; | ||
422 | goto err_asoc_utils_fini; | ||
423 | } | ||
424 | |||
425 | ret = tegra_pcm_platform_register(&pdev->dev); | ||
426 | if (ret) { | ||
427 | dev_err(&pdev->dev, "Could not register PCM: %d\n", ret); | ||
428 | goto err_unregister_component; | ||
429 | } | ||
430 | |||
434 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ | 431 | /* XXX: crufty ASoC AC97 API - only one AC97 codec allowed */ |
435 | workdata = ac97; | 432 | workdata = ac97; |
436 | 433 | ||
437 | return 0; | 434 | return 0; |
438 | 435 | ||
439 | err_asoc_utils_fini: | ||
440 | tegra_asoc_utils_fini(&ac97->util_data); | ||
441 | err_unregister_pcm: | 436 | err_unregister_pcm: |
442 | tegra_pcm_platform_unregister(&pdev->dev); | 437 | tegra_pcm_platform_unregister(&pdev->dev); |
443 | err_unregister_component: | 438 | err_unregister_component: |
444 | snd_soc_unregister_component(&pdev->dev); | 439 | snd_soc_unregister_component(&pdev->dev); |
440 | err_asoc_utils_fini: | ||
441 | tegra_asoc_utils_fini(&ac97->util_data); | ||
445 | err_clk_put: | 442 | err_clk_put: |
446 | clk_put(ac97->clk_ac97); | ||
447 | err: | 443 | err: |
444 | snd_soc_set_ac97_ops(NULL); | ||
448 | return ret; | 445 | return ret; |
449 | } | 446 | } |
450 | 447 | ||
@@ -458,7 +455,8 @@ static int tegra20_ac97_platform_remove(struct platform_device *pdev) | |||
458 | tegra_asoc_utils_fini(&ac97->util_data); | 455 | tegra_asoc_utils_fini(&ac97->util_data); |
459 | 456 | ||
460 | clk_disable_unprepare(ac97->clk_ac97); | 457 | clk_disable_unprepare(ac97->clk_ac97); |
461 | clk_put(ac97->clk_ac97); | 458 | |
459 | snd_soc_set_ac97_ops(NULL); | ||
462 | 460 | ||
463 | return 0; | 461 | return 0; |
464 | } | 462 | } |
diff --git a/sound/soc/txx9/txx9aclc-ac97.c b/sound/soc/txx9/txx9aclc-ac97.c index 8a2840304d28..4bcce8a3cded 100644 --- a/sound/soc/txx9/txx9aclc-ac97.c +++ b/sound/soc/txx9/txx9aclc-ac97.c | |||
@@ -119,12 +119,11 @@ static void txx9aclc_ac97_cold_reset(struct snd_ac97 *ac97) | |||
119 | } | 119 | } |
120 | 120 | ||
121 | /* AC97 controller operations */ | 121 | /* AC97 controller operations */ |
122 | struct snd_ac97_bus_ops soc_ac97_ops = { | 122 | static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { |
123 | .read = txx9aclc_ac97_read, | 123 | .read = txx9aclc_ac97_read, |
124 | .write = txx9aclc_ac97_write, | 124 | .write = txx9aclc_ac97_write, |
125 | .reset = txx9aclc_ac97_cold_reset, | 125 | .reset = txx9aclc_ac97_cold_reset, |
126 | }; | 126 | }; |
127 | EXPORT_SYMBOL_GPL(soc_ac97_ops); | ||
128 | 127 | ||
129 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) | 128 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) |
130 | { | 129 | { |
@@ -188,9 +187,9 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
188 | if (!r) | 187 | if (!r) |
189 | return -EBUSY; | 188 | return -EBUSY; |
190 | 189 | ||
191 | if (!devm_request_mem_region(&pdev->dev, r->start, resource_size(r), | 190 | drvdata->base = devm_ioremap_resource(&pdev->dev, r); |
192 | dev_name(&pdev->dev))) | 191 | if (IS_ERR(drvdata->base)) |
193 | return -EBUSY; | 192 | return PTR_ERR(drvdata->base); |
194 | 193 | ||
195 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); | 194 | drvdata = devm_kzalloc(&pdev->dev, sizeof(*drvdata), GFP_KERNEL); |
196 | if (!drvdata) | 195 | if (!drvdata) |
@@ -201,14 +200,15 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
201 | r->start >= TXX9_DIRECTMAP_BASE && | 200 | r->start >= TXX9_DIRECTMAP_BASE && |
202 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) | 201 | r->start < TXX9_DIRECTMAP_BASE + 0x400000) |
203 | drvdata->physbase |= 0xf00000000ull; | 202 | drvdata->physbase |= 0xf00000000ull; |
204 | drvdata->base = devm_ioremap(&pdev->dev, r->start, resource_size(r)); | ||
205 | if (!drvdata->base) | ||
206 | return -EBUSY; | ||
207 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, | 203 | err = devm_request_irq(&pdev->dev, irq, txx9aclc_ac97_irq, |
208 | 0, dev_name(&pdev->dev), drvdata); | 204 | 0, dev_name(&pdev->dev), drvdata); |
209 | if (err < 0) | 205 | if (err < 0) |
210 | return err; | 206 | return err; |
211 | 207 | ||
208 | err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); | ||
209 | if (err < 0) | ||
210 | return err; | ||
211 | |||
212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, | 212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, |
213 | &txx9aclc_ac97_dai, 1); | 213 | &txx9aclc_ac97_dai, 1); |
214 | } | 214 | } |
@@ -216,6 +216,7 @@ static int txx9aclc_ac97_dev_probe(struct platform_device *pdev) | |||
216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) | 216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
217 | { | 217 | { |
218 | snd_soc_unregister_component(&pdev->dev); | 218 | snd_soc_unregister_component(&pdev->dev); |
219 | snd_soc_set_ac97_ops(NULL); | ||
219 | return 0; | 220 | return 0; |
220 | } | 221 | } |
221 | 222 | ||