Commit b047e1cce8fe32475ab61846772943a5e4c0a908
1 parent
b49dff8cb6
Exists in
smarc-imx_3.14.28_1.0.0_ga
and in
1 other branch
ASoC: ac97: Support multi-platform AC'97
Currently we can only have a single platform built in with AC'97 support due to the use of a global variable to provide the bus operations. Fix this by making that variable a pointer and having the bus drivers set the operations prior to registering. This is not a particularly good or nice approach but it avoids blocking multiplatform and a real fix involves fixing the fairly deep problems with AC'97 support - we should be converting it to a real bus. Acked-by: Arnd Bergmann <arnd@arndb.de> Reviewed-by: Stephen Warren <swarren@nvidia.com> Signed-off-by: Mark Brown <broonie@linaro.org>
Showing 20 changed files with 154 additions and 72 deletions Side-by-side Diff
- include/sound/soc.h
- sound/soc/au1x/ac97c.c
- sound/soc/au1x/psc-ac97.c
- sound/soc/blackfin/bf5xx-ac97.c
- sound/soc/cirrus/ep93xx-ac97.c
- sound/soc/codecs/ac97.c
- sound/soc/codecs/ad1980.c
- sound/soc/codecs/stac9766.c
- sound/soc/codecs/wm9705.c
- sound/soc/codecs/wm9712.c
- sound/soc/codecs/wm9713.c
- sound/soc/fsl/imx-ssi.c
- sound/soc/fsl/mpc5200_psc_ac97.c
- sound/soc/nuc900/nuc900-ac97.c
- sound/soc/pxa/pxa2xx-ac97.c
- sound/soc/samsung/ac97.c
- sound/soc/sh/hac.c
- sound/soc/soc-core.c
- sound/soc/tegra/tegra20_ac97.c
- sound/soc/txx9/txx9aclc-ac97.c
include/sound/soc.h
... | ... | @@ -340,7 +340,7 @@ |
340 | 340 | |
341 | 341 | typedef int (*hw_write_t)(void *,const char* ,int); |
342 | 342 | |
343 | -extern struct snd_ac97_bus_ops soc_ac97_ops; | |
343 | +extern struct snd_ac97_bus_ops *soc_ac97_ops; | |
344 | 344 | |
345 | 345 | enum snd_soc_control_type { |
346 | 346 | SND_SOC_I2C = 1, |
... | ... | @@ -466,6 +466,8 @@ |
466 | 466 | int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, |
467 | 467 | struct snd_ac97_bus_ops *ops, int num); |
468 | 468 | void snd_soc_free_ac97_codec(struct snd_soc_codec *codec); |
469 | + | |
470 | +int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops); | |
469 | 471 | |
470 | 472 | /* |
471 | 473 | *Controls |
sound/soc/au1x/ac97c.c
... | ... | @@ -179,13 +179,12 @@ |
179 | 179 | } |
180 | 180 | |
181 | 181 | /* AC97 controller operations */ |
182 | -struct snd_ac97_bus_ops soc_ac97_ops = { | |
182 | +static struct snd_ac97_bus_ops ac97c_bus_ops = { | |
183 | 183 | .read = au1xac97c_ac97_read, |
184 | 184 | .write = au1xac97c_ac97_write, |
185 | 185 | .reset = au1xac97c_ac97_cold_reset, |
186 | 186 | .warm_reset = au1xac97c_ac97_warm_reset, |
187 | 187 | }; |
188 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); /* globals be gone! */ | |
189 | 188 | |
190 | 189 | static int alchemy_ac97c_startup(struct snd_pcm_substream *substream, |
191 | 190 | struct snd_soc_dai *dai) |
... | ... | @@ -271,6 +270,10 @@ |
271 | 270 | WR(ctx, AC97_CONFIG, ctx->cfg); |
272 | 271 | |
273 | 272 | platform_set_drvdata(pdev, ctx); |
273 | + | |
274 | + ret = snd_soc_set_ac97_ops(&ac97c_bus_ops); | |
275 | + if (ret) | |
276 | + return ret; | |
274 | 277 | |
275 | 278 | ret = snd_soc_register_component(&pdev->dev, &au1xac97c_component, |
276 | 279 | &au1xac97c_dai_driver, 1); |
sound/soc/au1x/psc-ac97.c
... | ... | @@ -201,13 +201,12 @@ |
201 | 201 | } |
202 | 202 | |
203 | 203 | /* AC97 controller operations */ |
204 | -struct snd_ac97_bus_ops soc_ac97_ops = { | |
204 | +static struct snd_ac97_bus_ops psc_ac97_ops = { | |
205 | 205 | .read = au1xpsc_ac97_read, |
206 | 206 | .write = au1xpsc_ac97_write, |
207 | 207 | .reset = au1xpsc_ac97_cold_reset, |
208 | 208 | .warm_reset = au1xpsc_ac97_warm_reset, |
209 | 209 | }; |
210 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
211 | 210 | |
212 | 211 | static int au1xpsc_ac97_hw_params(struct snd_pcm_substream *substream, |
213 | 212 | struct snd_pcm_hw_params *params, |
... | ... | @@ -416,6 +415,10 @@ |
416 | 415 | wd->dai_drv.name = dev_name(&pdev->dev); |
417 | 416 | |
418 | 417 | platform_set_drvdata(pdev, wd); |
418 | + | |
419 | + ret = snd_soc_set_ac97_ops(&psc_ac97_ops); | |
420 | + if (ret) | |
421 | + return ret; | |
419 | 422 | |
420 | 423 | ret = snd_soc_register_component(&pdev->dev, &au1xpsc_ac97_component, |
421 | 424 | &wd->dai_drv, 1); |
sound/soc/blackfin/bf5xx-ac97.c
... | ... | @@ -198,13 +198,12 @@ |
198 | 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 | 202 | .read = bf5xx_ac97_read, |
203 | 203 | .write = bf5xx_ac97_write, |
204 | 204 | .warm_reset = bf5xx_ac97_warm_reset, |
205 | 205 | .reset = bf5xx_ac97_cold_reset, |
206 | 206 | }; |
207 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
208 | 207 | |
209 | 208 | #ifdef CONFIG_PM |
210 | 209 | static int bf5xx_ac97_suspend(struct snd_soc_dai *dai) |
... | ... | @@ -336,6 +335,12 @@ |
336 | 335 | goto sport_config_err; |
337 | 336 | } |
338 | 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 | + | |
339 | 344 | ret = snd_soc_register_component(&pdev->dev, &bfin_ac97_component, |
340 | 345 | &bfin_ac97_dai, 1); |
341 | 346 | if (ret) { |
... | ... | @@ -350,6 +355,7 @@ |
350 | 355 | sport_config_err: |
351 | 356 | sport_done(sport_handle); |
352 | 357 | sport_err: |
358 | + snd_soc_set_ac97_ops(NULL); | |
353 | 359 | |
354 | 360 | return ret; |
355 | 361 | } |
... | ... | @@ -360,6 +366,7 @@ |
360 | 366 | |
361 | 367 | snd_soc_unregister_component(&pdev->dev); |
362 | 368 | sport_done(sport_handle); |
369 | + snd_soc_set_ac97_ops(NULL); | |
363 | 370 | |
364 | 371 | return 0; |
365 | 372 | } |
sound/soc/cirrus/ep93xx-ac97.c
... | ... | @@ -237,13 +237,12 @@ |
237 | 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 | 241 | .read = ep93xx_ac97_read, |
242 | 242 | .write = ep93xx_ac97_write, |
243 | 243 | .reset = ep93xx_ac97_cold_reset, |
244 | 244 | .warm_reset = ep93xx_ac97_warm_reset, |
245 | 245 | }; |
246 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
247 | 246 | |
248 | 247 | static int ep93xx_ac97_trigger(struct snd_pcm_substream *substream, |
249 | 248 | int cmd, struct snd_soc_dai *dai) |
... | ... | @@ -395,6 +394,10 @@ |
395 | 394 | ep93xx_ac97_info = info; |
396 | 395 | platform_set_drvdata(pdev, info); |
397 | 396 | |
397 | + ret = snd_soc_set_ac97_ops(&ep93xx_ac97_ops); | |
398 | + if (ret) | |
399 | + goto fail; | |
400 | + | |
398 | 401 | ret = snd_soc_register_component(&pdev->dev, &ep93xx_ac97_component, |
399 | 402 | &ep93xx_ac97_dai, 1); |
400 | 403 | if (ret) |
... | ... | @@ -405,6 +408,7 @@ |
405 | 408 | fail: |
406 | 409 | platform_set_drvdata(pdev, NULL); |
407 | 410 | ep93xx_ac97_info = NULL; |
411 | + snd_soc_set_ac97_ops(NULL); | |
408 | 412 | return ret; |
409 | 413 | } |
410 | 414 | |
... | ... | @@ -419,6 +423,8 @@ |
419 | 423 | |
420 | 424 | platform_set_drvdata(pdev, NULL); |
421 | 425 | ep93xx_ac97_info = NULL; |
426 | + | |
427 | + snd_soc_set_ac97_ops(NULL); | |
422 | 428 | |
423 | 429 | return 0; |
424 | 430 | } |
sound/soc/codecs/ac97.c
... | ... | @@ -62,13 +62,13 @@ |
62 | 62 | static unsigned int ac97_read(struct snd_soc_codec *codec, |
63 | 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 | 68 | static int ac97_write(struct snd_soc_codec *codec, unsigned int reg, |
69 | 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 | 72 | return 0; |
73 | 73 | } |
74 | 74 | |
... | ... | @@ -79,7 +79,8 @@ |
79 | 79 | int ret; |
80 | 80 | |
81 | 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 | 84 | if (ret < 0) |
84 | 85 | return ret; |
85 | 86 |
sound/soc/codecs/ad1980.c
... | ... | @@ -108,7 +108,7 @@ |
108 | 108 | case AC97_EXTENDED_STATUS: |
109 | 109 | case AC97_VENDOR_ID1: |
110 | 110 | case AC97_VENDOR_ID2: |
111 | - return soc_ac97_ops.read(codec->ac97, reg); | |
111 | + return soc_ac97_ops->read(codec->ac97, reg); | |
112 | 112 | default: |
113 | 113 | reg = reg >> 1; |
114 | 114 | |
... | ... | @@ -124,7 +124,7 @@ |
124 | 124 | { |
125 | 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 | 128 | reg = reg >> 1; |
129 | 129 | if (reg < ARRAY_SIZE(ad1980_reg)) |
130 | 130 | cache[reg] = val; |
131 | 131 | |
... | ... | @@ -154,13 +154,13 @@ |
154 | 154 | u16 retry_cnt = 0; |
155 | 155 | |
156 | 156 | retry: |
157 | - if (try_warm && soc_ac97_ops.warm_reset) { | |
158 | - soc_ac97_ops.warm_reset(codec->ac97); | |
157 | + if (try_warm && soc_ac97_ops->warm_reset) { | |
158 | + soc_ac97_ops->warm_reset(codec->ac97); | |
159 | 159 | if (ac97_read(codec, AC97_RESET) == 0x0090) |
160 | 160 | return 1; |
161 | 161 | } |
162 | 162 | |
163 | - soc_ac97_ops.reset(codec->ac97); | |
163 | + soc_ac97_ops->reset(codec->ac97); | |
164 | 164 | /* Set bit 16slot in register 74h, then every slot will has only 16 |
165 | 165 | * bits. This command is sent out in 20bit mode, in which case the |
166 | 166 | * first nibble of data is eaten by the addr. (Tag is always 16 bit)*/ |
... | ... | @@ -186,7 +186,7 @@ |
186 | 186 | |
187 | 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 | 190 | if (ret < 0) { |
191 | 191 | printk(KERN_ERR "ad1980: failed to register AC97 codec\n"); |
192 | 192 | return ret; |
sound/soc/codecs/stac9766.c
... | ... | @@ -143,14 +143,14 @@ |
143 | 143 | |
144 | 144 | if (reg > AC97_STAC_PAGE0) { |
145 | 145 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
146 | - soc_ac97_ops.write(codec->ac97, reg, val); | |
146 | + soc_ac97_ops->write(codec->ac97, reg, val); | |
147 | 147 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
148 | 148 | return 0; |
149 | 149 | } |
150 | 150 | if (reg / 2 >= ARRAY_SIZE(stac9766_reg)) |
151 | 151 | return -EIO; |
152 | 152 | |
153 | - soc_ac97_ops.write(codec->ac97, reg, val); | |
153 | + soc_ac97_ops->write(codec->ac97, reg, val); | |
154 | 154 | cache[reg / 2] = val; |
155 | 155 | return 0; |
156 | 156 | } |
... | ... | @@ -162,7 +162,7 @@ |
162 | 162 | |
163 | 163 | if (reg > AC97_STAC_PAGE0) { |
164 | 164 | stac9766_ac97_write(codec, AC97_INT_PAGING, 0); |
165 | - val = soc_ac97_ops.read(codec->ac97, reg - AC97_STAC_PAGE0); | |
165 | + val = soc_ac97_ops->read(codec->ac97, reg - AC97_STAC_PAGE0); | |
166 | 166 | stac9766_ac97_write(codec, AC97_INT_PAGING, 1); |
167 | 167 | return val; |
168 | 168 | } |
... | ... | @@ -173,7 +173,7 @@ |
173 | 173 | reg == AC97_INT_PAGING || reg == AC97_VENDOR_ID1 || |
174 | 174 | reg == AC97_VENDOR_ID2) { |
175 | 175 | |
176 | - val = soc_ac97_ops.read(codec->ac97, reg); | |
176 | + val = soc_ac97_ops->read(codec->ac97, reg); | |
177 | 177 | return val; |
178 | 178 | } |
179 | 179 | return cache[reg / 2]; |
180 | 180 | |
... | ... | @@ -240,15 +240,15 @@ |
240 | 240 | |
241 | 241 | static int stac9766_reset(struct snd_soc_codec *codec, int try_warm) |
242 | 242 | { |
243 | - if (try_warm && soc_ac97_ops.warm_reset) { | |
244 | - soc_ac97_ops.warm_reset(codec->ac97); | |
243 | + if (try_warm && soc_ac97_ops->warm_reset) { | |
244 | + soc_ac97_ops->warm_reset(codec->ac97); | |
245 | 245 | if (stac9766_ac97_read(codec, 0) == stac9766_reg[0]) |
246 | 246 | return 1; |
247 | 247 | } |
248 | 248 | |
249 | - soc_ac97_ops.reset(codec->ac97); | |
250 | - if (soc_ac97_ops.warm_reset) | |
251 | - soc_ac97_ops.warm_reset(codec->ac97); | |
249 | + soc_ac97_ops->reset(codec->ac97); | |
250 | + if (soc_ac97_ops->warm_reset) | |
251 | + soc_ac97_ops->warm_reset(codec->ac97); | |
252 | 252 | if (stac9766_ac97_read(codec, 0) != stac9766_reg[0]) |
253 | 253 | return -EIO; |
254 | 254 | return 0; |
... | ... | @@ -272,7 +272,7 @@ |
272 | 272 | return -EIO; |
273 | 273 | } |
274 | 274 | codec->ac97->bus->ops->warm_reset(codec->ac97); |
275 | - id = soc_ac97_ops.read(codec->ac97, AC97_VENDOR_ID2); | |
275 | + id = soc_ac97_ops->read(codec->ac97, AC97_VENDOR_ID2); | |
276 | 276 | if (id != 0x4c13) { |
277 | 277 | stac9766_reset(codec, 0); |
278 | 278 | reset++; |
... | ... | @@ -336,7 +336,7 @@ |
336 | 336 | { |
337 | 337 | int ret = 0; |
338 | 338 | |
339 | - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | |
339 | + ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | |
340 | 340 | if (ret < 0) |
341 | 341 | goto codec_err; |
342 | 342 |
sound/soc/codecs/wm9705.c
... | ... | @@ -209,7 +209,7 @@ |
209 | 209 | case AC97_RESET: |
210 | 210 | case AC97_VENDOR_ID1: |
211 | 211 | case AC97_VENDOR_ID2: |
212 | - return soc_ac97_ops.read(codec->ac97, reg); | |
212 | + return soc_ac97_ops->read(codec->ac97, reg); | |
213 | 213 | default: |
214 | 214 | reg = reg >> 1; |
215 | 215 | |
... | ... | @@ -225,7 +225,7 @@ |
225 | 225 | { |
226 | 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 | 229 | reg = reg >> 1; |
230 | 230 | if (reg < (ARRAY_SIZE(wm9705_reg))) |
231 | 231 | cache[reg] = val; |
... | ... | @@ -294,8 +294,8 @@ |
294 | 294 | |
295 | 295 | static int wm9705_reset(struct snd_soc_codec *codec) |
296 | 296 | { |
297 | - if (soc_ac97_ops.reset) { | |
298 | - soc_ac97_ops.reset(codec->ac97); | |
297 | + if (soc_ac97_ops->reset) { | |
298 | + soc_ac97_ops->reset(codec->ac97); | |
299 | 299 | if (ac97_read(codec, 0) == wm9705_reg[0]) |
300 | 300 | return 0; /* Success */ |
301 | 301 | } |
... | ... | @@ -306,7 +306,7 @@ |
306 | 306 | #ifdef CONFIG_PM |
307 | 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 | 311 | return 0; |
312 | 312 | } |
... | ... | @@ -323,7 +323,7 @@ |
323 | 323 | } |
324 | 324 | |
325 | 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 | 329 | return 0; |
... | ... | @@ -337,7 +337,7 @@ |
337 | 337 | { |
338 | 338 | int ret = 0; |
339 | 339 | |
340 | - ret = snd_soc_new_ac97_codec(codec, &soc_ac97_ops, 0); | |
340 | + ret = snd_soc_new_ac97_codec(codec, soc_ac97_ops, 0); | |
341 | 341 | if (ret < 0) { |
342 | 342 | printk(KERN_ERR "wm9705: failed to register AC97 codec\n"); |
343 | 343 | return ret; |
sound/soc/codecs/wm9712.c
... | ... | @@ -455,7 +455,7 @@ |
455 | 455 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
456 | 456 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
457 | 457 | reg == AC97_REC_GAIN) |
458 | - return soc_ac97_ops.read(codec->ac97, reg); | |
458 | + return soc_ac97_ops->read(codec->ac97, reg); | |
459 | 459 | else { |
460 | 460 | reg = reg >> 1; |
461 | 461 | |
... | ... | @@ -472,7 +472,7 @@ |
472 | 472 | u16 *cache = codec->reg_cache; |
473 | 473 | |
474 | 474 | if (reg < 0x7c) |
475 | - soc_ac97_ops.write(codec->ac97, reg, val); | |
475 | + soc_ac97_ops->write(codec->ac97, reg, val); | |
476 | 476 | reg = reg >> 1; |
477 | 477 | if (reg < (ARRAY_SIZE(wm9712_reg))) |
478 | 478 | cache[reg] = val; |
479 | 479 | |
... | ... | @@ -581,15 +581,15 @@ |
581 | 581 | |
582 | 582 | static int wm9712_reset(struct snd_soc_codec *codec, int try_warm) |
583 | 583 | { |
584 | - if (try_warm && soc_ac97_ops.warm_reset) { | |
585 | - soc_ac97_ops.warm_reset(codec->ac97); | |
584 | + if (try_warm && soc_ac97_ops->warm_reset) { | |
585 | + soc_ac97_ops->warm_reset(codec->ac97); | |
586 | 586 | if (ac97_read(codec, 0) == wm9712_reg[0]) |
587 | 587 | return 1; |
588 | 588 | } |
589 | 589 | |
590 | - soc_ac97_ops.reset(codec->ac97); | |
591 | - if (soc_ac97_ops.warm_reset) | |
592 | - soc_ac97_ops.warm_reset(codec->ac97); | |
590 | + soc_ac97_ops->reset(codec->ac97); | |
591 | + if (soc_ac97_ops->warm_reset) | |
592 | + soc_ac97_ops->warm_reset(codec->ac97); | |
593 | 593 | if (ac97_read(codec, 0) != wm9712_reg[0]) |
594 | 594 | goto err; |
595 | 595 | return 0; |
... | ... | @@ -624,7 +624,7 @@ |
624 | 624 | if (i == AC97_INT_PAGING || i == AC97_POWERDOWN || |
625 | 625 | (i > 0x58 && i != 0x5c)) |
626 | 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 @@ |
635 | 635 | { |
636 | 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 | 639 | if (ret < 0) { |
640 | 640 | printk(KERN_ERR "wm9712: failed to register AC97 codec\n"); |
641 | 641 | return ret; |
sound/soc/codecs/wm9713.c
... | ... | @@ -652,7 +652,7 @@ |
652 | 652 | if (reg == AC97_RESET || reg == AC97_GPIO_STATUS || |
653 | 653 | reg == AC97_VENDOR_ID1 || reg == AC97_VENDOR_ID2 || |
654 | 654 | reg == AC97_CD) |
655 | - return soc_ac97_ops.read(codec->ac97, reg); | |
655 | + return soc_ac97_ops->read(codec->ac97, reg); | |
656 | 656 | else { |
657 | 657 | reg = reg >> 1; |
658 | 658 | |
... | ... | @@ -668,7 +668,7 @@ |
668 | 668 | { |
669 | 669 | u16 *cache = codec->reg_cache; |
670 | 670 | if (reg < 0x7c) |
671 | - soc_ac97_ops.write(codec->ac97, reg, val); | |
671 | + soc_ac97_ops->write(codec->ac97, reg, val); | |
672 | 672 | reg = reg >> 1; |
673 | 673 | if (reg < (ARRAY_SIZE(wm9713_reg))) |
674 | 674 | cache[reg] = val; |
675 | 675 | |
... | ... | @@ -1095,15 +1095,15 @@ |
1095 | 1095 | |
1096 | 1096 | int wm9713_reset(struct snd_soc_codec *codec, int try_warm) |
1097 | 1097 | { |
1098 | - if (try_warm && soc_ac97_ops.warm_reset) { | |
1099 | - soc_ac97_ops.warm_reset(codec->ac97); | |
1098 | + if (try_warm && soc_ac97_ops->warm_reset) { | |
1099 | + soc_ac97_ops->warm_reset(codec->ac97); | |
1100 | 1100 | if (ac97_read(codec, 0) == wm9713_reg[0]) |
1101 | 1101 | return 1; |
1102 | 1102 | } |
1103 | 1103 | |
1104 | - soc_ac97_ops.reset(codec->ac97); | |
1105 | - if (soc_ac97_ops.warm_reset) | |
1106 | - soc_ac97_ops.warm_reset(codec->ac97); | |
1104 | + soc_ac97_ops->reset(codec->ac97); | |
1105 | + if (soc_ac97_ops->warm_reset) | |
1106 | + soc_ac97_ops->warm_reset(codec->ac97); | |
1107 | 1107 | if (ac97_read(codec, 0) != wm9713_reg[0]) |
1108 | 1108 | return -EIO; |
1109 | 1109 | return 0; |
... | ... | @@ -1180,7 +1180,7 @@ |
1180 | 1180 | if (i == AC97_POWERDOWN || i == AC97_EXTENDED_MID || |
1181 | 1181 | i == AC97_EXTENDED_MSTATUS || i > 0x66) |
1182 | 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 @@ |
1197 | 1197 | return -ENOMEM; |
1198 | 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 | 1201 | if (ret < 0) |
1202 | 1202 | goto codec_err; |
1203 | 1203 |
sound/soc/fsl/imx-ssi.c
... | ... | @@ -501,13 +501,12 @@ |
501 | 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 | 505 | .read = imx_ssi_ac97_read, |
506 | 506 | .write = imx_ssi_ac97_write, |
507 | 507 | .reset = imx_ssi_ac97_reset, |
508 | 508 | .warm_reset = imx_ssi_ac97_warm_reset |
509 | 509 | }; |
510 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
511 | 510 | |
512 | 511 | static int imx_ssi_probe(struct platform_device *pdev) |
513 | 512 | { |
... | ... | @@ -583,6 +582,12 @@ |
583 | 582 | |
584 | 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 | 591 | ret = snd_soc_register_component(&pdev->dev, &imx_component, |
587 | 592 | dai, 1); |
588 | 593 | if (ret) { |
... | ... | @@ -630,6 +635,7 @@ |
630 | 635 | release_mem_region(res->start, resource_size(res)); |
631 | 636 | clk_disable_unprepare(ssi->clk); |
632 | 637 | failed_clk: |
638 | + snd_soc_set_ac97_ops(NULL); | |
633 | 639 | |
634 | 640 | return ret; |
635 | 641 | } |
... | ... | @@ -649,6 +655,7 @@ |
649 | 655 | |
650 | 656 | release_mem_region(res->start, resource_size(res)); |
651 | 657 | clk_disable_unprepare(ssi->clk); |
658 | + snd_soc_set_ac97_ops(NULL); | |
652 | 659 | |
653 | 660 | return 0; |
654 | 661 | } |
sound/soc/fsl/mpc5200_psc_ac97.c
... | ... | @@ -131,13 +131,12 @@ |
131 | 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 | 135 | .read = psc_ac97_read, |
136 | 136 | .write = psc_ac97_write, |
137 | 137 | .reset = psc_ac97_cold_reset, |
138 | 138 | .warm_reset = psc_ac97_warm_reset, |
139 | 139 | }; |
140 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
141 | 140 | |
142 | 141 | static int psc_ac97_hw_analog_params(struct snd_pcm_substream *substream, |
143 | 142 | struct snd_pcm_hw_params *params, |
... | ... | @@ -290,6 +289,12 @@ |
290 | 289 | if (rc != 0) |
291 | 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 | 298 | rc = snd_soc_register_component(&op->dev, &psc_ac97_component, |
294 | 299 | psc_ac97_dai, ARRAY_SIZE(psc_ac97_dai)); |
295 | 300 | if (rc != 0) { |
... | ... | @@ -318,6 +323,7 @@ |
318 | 323 | { |
319 | 324 | mpc5200_audio_dma_destroy(op); |
320 | 325 | snd_soc_unregister_component(&op->dev); |
326 | + snd_soc_set_ac97_ops(NULL); | |
321 | 327 | return 0; |
322 | 328 | } |
323 | 329 |
sound/soc/nuc900/nuc900-ac97.c
... | ... | @@ -197,13 +197,12 @@ |
197 | 197 | } |
198 | 198 | |
199 | 199 | /* AC97 controller operations */ |
200 | -struct snd_ac97_bus_ops soc_ac97_ops = { | |
200 | +static struct snd_ac97_bus_ops nuc900_ac97_ops = { | |
201 | 201 | .read = nuc900_ac97_read, |
202 | 202 | .write = nuc900_ac97_write, |
203 | 203 | .reset = nuc900_ac97_cold_reset, |
204 | 204 | .warm_reset = nuc900_ac97_warm_reset, |
205 | -} | |
206 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
205 | +}; | |
207 | 206 | |
208 | 207 | static int nuc900_ac97_trigger(struct snd_pcm_substream *substream, |
209 | 208 | int cmd, struct snd_soc_dai *dai) |
... | ... | @@ -356,6 +355,10 @@ |
356 | 355 | |
357 | 356 | nuc900_ac97_data = nuc900_audio; |
358 | 357 | |
358 | + ret = snd_soc_set_ac97_ops(&nuc900_ac97_ops); | |
359 | + if (ret) | |
360 | + goto out; | |
361 | + | |
359 | 362 | ret = snd_soc_register_component(&pdev->dev, &nuc900_ac97_component, |
360 | 363 | &nuc900_ac97_dai, 1); |
361 | 364 | if (ret) |
... | ... | @@ -367,6 +370,7 @@ |
367 | 370 | return 0; |
368 | 371 | |
369 | 372 | out: |
373 | + snd_soc_set_ac97_ops(NULL); | |
370 | 374 | return ret; |
371 | 375 | } |
372 | 376 | |
... | ... | @@ -375,6 +379,7 @@ |
375 | 379 | snd_soc_unregister_component(&pdev->dev); |
376 | 380 | |
377 | 381 | nuc900_ac97_data = NULL; |
382 | + snd_soc_set_ac97_ops(NULL); | |
378 | 383 | |
379 | 384 | return 0; |
380 | 385 | } |
sound/soc/pxa/pxa2xx-ac97.c
... | ... | @@ -41,13 +41,12 @@ |
41 | 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 | 45 | .read = pxa2xx_ac97_read, |
46 | 46 | .write = pxa2xx_ac97_write, |
47 | 47 | .warm_reset = pxa2xx_ac97_warm_reset, |
48 | 48 | .reset = pxa2xx_ac97_cold_reset, |
49 | 49 | }; |
50 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
51 | 50 | |
52 | 51 | static struct pxa2xx_pcm_dma_params pxa2xx_ac97_pcm_stereo_out = { |
53 | 52 | .name = "AC97 PCM Stereo out", |
... | ... | @@ -244,6 +243,10 @@ |
244 | 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 | 250 | /* Punt most of the init to the SoC probe; we may need the machine |
248 | 251 | * driver to do interesting things with the clocking to get us up |
249 | 252 | * and running. |
... | ... | @@ -255,6 +258,7 @@ |
255 | 258 | static int pxa2xx_ac97_dev_remove(struct platform_device *pdev) |
256 | 259 | { |
257 | 260 | snd_soc_unregister_component(&pdev->dev); |
261 | + snd_soc_set_ac97_ops(NULL); | |
258 | 262 | return 0; |
259 | 263 | } |
260 | 264 |
sound/soc/samsung/ac97.c
... | ... | @@ -214,13 +214,12 @@ |
214 | 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 | 218 | .read = s3c_ac97_read, |
219 | 219 | .write = s3c_ac97_write, |
220 | 220 | .warm_reset = s3c_ac97_warm_reset, |
221 | 221 | .reset = s3c_ac97_cold_reset, |
222 | 222 | }; |
223 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
224 | 223 | |
225 | 224 | static int s3c_ac97_hw_params(struct snd_pcm_substream *substream, |
226 | 225 | struct snd_pcm_hw_params *params, |
... | ... | @@ -452,6 +451,12 @@ |
452 | 451 | goto err4; |
453 | 452 | } |
454 | 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 | + | |
455 | 460 | ret = snd_soc_register_component(&pdev->dev, &s3c_ac97_component, |
456 | 461 | s3c_ac97_dai, ARRAY_SIZE(s3c_ac97_dai)); |
457 | 462 | if (ret) |
... | ... | @@ -472,7 +477,7 @@ |
472 | 477 | err3: |
473 | 478 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
474 | 479 | err2: |
475 | - | |
480 | + snd_soc_set_ac97_ops(NULL); | |
476 | 481 | return ret; |
477 | 482 | } |
478 | 483 | |
... | ... | @@ -488,6 +493,7 @@ |
488 | 493 | free_irq(irq_res->start, NULL); |
489 | 494 | |
490 | 495 | clk_disable_unprepare(s3c_ac97.ac97_clk); |
496 | + snd_soc_set_ac97_ops(NULL); | |
491 | 497 | |
492 | 498 | return 0; |
493 | 499 | } |
sound/soc/sh/hac.c
... | ... | @@ -227,13 +227,12 @@ |
227 | 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 | 231 | .read = hac_ac97_read, |
232 | 232 | .write = hac_ac97_write, |
233 | 233 | .reset = hac_ac97_coldrst, |
234 | 234 | .warm_reset = hac_ac97_warmrst, |
235 | 235 | }; |
236 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
237 | 236 | |
238 | 237 | static int hac_hw_params(struct snd_pcm_substream *substream, |
239 | 238 | struct snd_pcm_hw_params *params, |
... | ... | @@ -316,6 +315,10 @@ |
316 | 315 | |
317 | 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 | 322 | return snd_soc_register_component(&pdev->dev, &sh4_hac_component, |
320 | 323 | sh4_hac_dai, ARRAY_SIZE(sh4_hac_dai)); |
321 | 324 | } |
... | ... | @@ -323,6 +326,7 @@ |
323 | 326 | static int hac_soc_platform_remove(struct platform_device *pdev) |
324 | 327 | { |
325 | 328 | snd_soc_unregister_component(&pdev->dev); |
329 | + snd_soc_set_ac97_ops(NULL); | |
326 | 330 | return 0; |
327 | 331 | } |
328 | 332 |
sound/soc/soc-core.c
... | ... | @@ -2079,6 +2079,22 @@ |
2079 | 2079 | } |
2080 | 2080 | EXPORT_SYMBOL_GPL(snd_soc_new_ac97_codec); |
2081 | 2081 | |
2082 | +struct snd_ac97_bus_ops *soc_ac97_ops; | |
2083 | + | |
2084 | +int snd_soc_set_ac97_ops(struct snd_ac97_bus_ops *ops) | |
2085 | +{ | |
2086 | + if (ops == soc_ac97_ops) | |
2087 | + return 0; | |
2088 | + | |
2089 | + if (soc_ac97_ops && ops) | |
2090 | + return -EBUSY; | |
2091 | + | |
2092 | + soc_ac97_ops = ops; | |
2093 | + | |
2094 | + return 0; | |
2095 | +} | |
2096 | +EXPORT_SYMBOL_GPL(snd_soc_set_ac97_ops); | |
2097 | + | |
2082 | 2098 | /** |
2083 | 2099 | * snd_soc_free_ac97_codec - free AC97 codec device |
2084 | 2100 | * @codec: audio codec |
sound/soc/tegra/tegra20_ac97.c
... | ... | @@ -142,13 +142,12 @@ |
142 | 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 | 146 | .read = tegra20_ac97_codec_read, |
147 | 147 | .write = tegra20_ac97_codec_write, |
148 | 148 | .reset = tegra20_ac97_codec_reset, |
149 | 149 | .warm_reset = tegra20_ac97_codec_warm_reset, |
150 | 150 | }; |
151 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
152 | 151 | |
153 | 152 | static inline void tegra20_ac97_start_playback(struct tegra20_ac97 *ac97) |
154 | 153 | { |
... | ... | @@ -409,6 +408,12 @@ |
409 | 408 | goto err_asoc_utils_fini; |
410 | 409 | } |
411 | 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 | + | |
412 | 417 | ret = snd_soc_register_component(&pdev->dev, &tegra20_ac97_component, |
413 | 418 | &tegra20_ac97_dai, 1); |
414 | 419 | if (ret) { |
... | ... | @@ -436,6 +441,7 @@ |
436 | 441 | tegra_asoc_utils_fini(&ac97->util_data); |
437 | 442 | err_clk_put: |
438 | 443 | err: |
444 | + snd_soc_set_ac97_ops(NULL); | |
439 | 445 | return ret; |
440 | 446 | } |
441 | 447 | |
... | ... | @@ -449,6 +455,8 @@ |
449 | 455 | tegra_asoc_utils_fini(&ac97->util_data); |
450 | 456 | |
451 | 457 | clk_disable_unprepare(ac97->clk_ac97); |
458 | + | |
459 | + snd_soc_set_ac97_ops(NULL); | |
452 | 460 | |
453 | 461 | return 0; |
454 | 462 | } |
sound/soc/txx9/txx9aclc-ac97.c
... | ... | @@ -119,12 +119,11 @@ |
119 | 119 | } |
120 | 120 | |
121 | 121 | /* AC97 controller operations */ |
122 | -struct snd_ac97_bus_ops soc_ac97_ops = { | |
122 | +static struct snd_ac97_bus_ops txx9aclc_ac97_ops = { | |
123 | 123 | .read = txx9aclc_ac97_read, |
124 | 124 | .write = txx9aclc_ac97_write, |
125 | 125 | .reset = txx9aclc_ac97_cold_reset, |
126 | 126 | }; |
127 | -EXPORT_SYMBOL_GPL(soc_ac97_ops); | |
128 | 127 | |
129 | 128 | static irqreturn_t txx9aclc_ac97_irq(int irq, void *dev_id) |
130 | 129 | { |
... | ... | @@ -206,6 +205,10 @@ |
206 | 205 | if (err < 0) |
207 | 206 | return err; |
208 | 207 | |
208 | + err = snd_soc_set_ac97_ops(&txx9aclc_ac97_ops); | |
209 | + if (err < 0) | |
210 | + return err; | |
211 | + | |
209 | 212 | return snd_soc_register_component(&pdev->dev, &txx9aclc_ac97_component, |
210 | 213 | &txx9aclc_ac97_dai, 1); |
211 | 214 | } |
... | ... | @@ -213,6 +216,7 @@ |
213 | 216 | static int txx9aclc_ac97_dev_remove(struct platform_device *pdev) |
214 | 217 | { |
215 | 218 | snd_soc_unregister_component(&pdev->dev); |
219 | + snd_soc_set_ac97_ops(NULL); | |
216 | 220 | return 0; |
217 | 221 | } |
218 | 222 |