diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 840 |
1 files changed, 624 insertions, 216 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16c7453f4946..b098c0b4c584 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <linux/delay.h> | 26 | #include <linux/delay.h> |
27 | #include <linux/pm.h> | 27 | #include <linux/pm.h> |
28 | #include <linux/bitops.h> | 28 | #include <linux/bitops.h> |
29 | #include <linux/debugfs.h> | ||
29 | #include <linux/platform_device.h> | 30 | #include <linux/platform_device.h> |
30 | #include <sound/core.h> | 31 | #include <sound/core.h> |
31 | #include <sound/pcm.h> | 32 | #include <sound/pcm.h> |
@@ -34,18 +35,23 @@ | |||
34 | #include <sound/soc-dapm.h> | 35 | #include <sound/soc-dapm.h> |
35 | #include <sound/initval.h> | 36 | #include <sound/initval.h> |
36 | 37 | ||
37 | /* debug */ | ||
38 | #define SOC_DEBUG 0 | ||
39 | #if SOC_DEBUG | ||
40 | #define dbg(format, arg...) printk(format, ## arg) | ||
41 | #else | ||
42 | #define dbg(format, arg...) | ||
43 | #endif | ||
44 | |||
45 | static DEFINE_MUTEX(pcm_mutex); | 38 | static DEFINE_MUTEX(pcm_mutex); |
46 | static DEFINE_MUTEX(io_mutex); | 39 | static DEFINE_MUTEX(io_mutex); |
47 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); | 40 | static DECLARE_WAIT_QUEUE_HEAD(soc_pm_waitq); |
48 | 41 | ||
42 | #ifdef CONFIG_DEBUG_FS | ||
43 | static struct dentry *debugfs_root; | ||
44 | #endif | ||
45 | |||
46 | static DEFINE_MUTEX(client_mutex); | ||
47 | static LIST_HEAD(card_list); | ||
48 | static LIST_HEAD(dai_list); | ||
49 | static LIST_HEAD(platform_list); | ||
50 | static LIST_HEAD(codec_list); | ||
51 | |||
52 | static int snd_soc_register_card(struct snd_soc_card *card); | ||
53 | static int snd_soc_unregister_card(struct snd_soc_card *card); | ||
54 | |||
49 | /* | 55 | /* |
50 | * This is a timeout to do a DAPM powerdown after a stream is closed(). | 56 | * This is a timeout to do a DAPM powerdown after a stream is closed(). |
51 | * It can be used to eliminate pops between different playback streams, e.g. | 57 | * It can be used to eliminate pops between different playback streams, e.g. |
@@ -107,20 +113,6 @@ static int soc_ac97_dev_register(struct snd_soc_codec *codec) | |||
107 | } | 113 | } |
108 | #endif | 114 | #endif |
109 | 115 | ||
110 | static inline const char *get_dai_name(int type) | ||
111 | { | ||
112 | switch (type) { | ||
113 | case SND_SOC_DAI_AC97_BUS: | ||
114 | case SND_SOC_DAI_AC97: | ||
115 | return "AC97"; | ||
116 | case SND_SOC_DAI_I2S: | ||
117 | return "I2S"; | ||
118 | case SND_SOC_DAI_PCM: | ||
119 | return "PCM"; | ||
120 | } | ||
121 | return NULL; | ||
122 | } | ||
123 | |||
124 | /* | 116 | /* |
125 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is | 117 | * Called by ALSA when a PCM substream is opened, the runtime->hw record is |
126 | * then initialized and any private data can be allocated. This also calls | 118 | * then initialized and any private data can be allocated. This also calls |
@@ -130,9 +122,10 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
130 | { | 122 | { |
131 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 123 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
132 | struct snd_soc_device *socdev = rtd->socdev; | 124 | struct snd_soc_device *socdev = rtd->socdev; |
125 | struct snd_soc_card *card = socdev->card; | ||
133 | struct snd_pcm_runtime *runtime = substream->runtime; | 126 | struct snd_pcm_runtime *runtime = substream->runtime; |
134 | struct snd_soc_dai_link *machine = rtd->dai; | 127 | struct snd_soc_dai_link *machine = rtd->dai; |
135 | struct snd_soc_platform *platform = socdev->platform; | 128 | struct snd_soc_platform *platform = card->platform; |
136 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 129 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
137 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 130 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
138 | int ret = 0; | 131 | int ret = 0; |
@@ -141,7 +134,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
141 | 134 | ||
142 | /* startup the audio subsystem */ | 135 | /* startup the audio subsystem */ |
143 | if (cpu_dai->ops.startup) { | 136 | if (cpu_dai->ops.startup) { |
144 | ret = cpu_dai->ops.startup(substream); | 137 | ret = cpu_dai->ops.startup(substream, cpu_dai); |
145 | if (ret < 0) { | 138 | if (ret < 0) { |
146 | printk(KERN_ERR "asoc: can't open interface %s\n", | 139 | printk(KERN_ERR "asoc: can't open interface %s\n", |
147 | cpu_dai->name); | 140 | cpu_dai->name); |
@@ -158,7 +151,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
158 | } | 151 | } |
159 | 152 | ||
160 | if (codec_dai->ops.startup) { | 153 | if (codec_dai->ops.startup) { |
161 | ret = codec_dai->ops.startup(substream); | 154 | ret = codec_dai->ops.startup(substream, codec_dai); |
162 | if (ret < 0) { | 155 | if (ret < 0) { |
163 | printk(KERN_ERR "asoc: can't open codec %s\n", | 156 | printk(KERN_ERR "asoc: can't open codec %s\n", |
164 | codec_dai->name); | 157 | codec_dai->name); |
@@ -228,12 +221,12 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
228 | goto machine_err; | 221 | goto machine_err; |
229 | } | 222 | } |
230 | 223 | ||
231 | dbg("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); | 224 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); |
232 | dbg("asoc: rate mask 0x%x\n", runtime->hw.rates); | 225 | pr_debug("asoc: rate mask 0x%x\n", runtime->hw.rates); |
233 | dbg("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, | 226 | pr_debug("asoc: min ch %d max ch %d\n", runtime->hw.channels_min, |
234 | runtime->hw.channels_max); | 227 | runtime->hw.channels_max); |
235 | dbg("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, | 228 | pr_debug("asoc: min rate %d max rate %d\n", runtime->hw.rate_min, |
236 | runtime->hw.rate_max); | 229 | runtime->hw.rate_max); |
237 | 230 | ||
238 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 231 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
239 | cpu_dai->playback.active = codec_dai->playback.active = 1; | 232 | cpu_dai->playback.active = codec_dai->playback.active = 1; |
@@ -255,7 +248,7 @@ codec_dai_err: | |||
255 | 248 | ||
256 | platform_err: | 249 | platform_err: |
257 | if (cpu_dai->ops.shutdown) | 250 | if (cpu_dai->ops.shutdown) |
258 | cpu_dai->ops.shutdown(substream); | 251 | cpu_dai->ops.shutdown(substream, cpu_dai); |
259 | out: | 252 | out: |
260 | mutex_unlock(&pcm_mutex); | 253 | mutex_unlock(&pcm_mutex); |
261 | return ret; | 254 | return ret; |
@@ -268,8 +261,9 @@ out: | |||
268 | */ | 261 | */ |
269 | static void close_delayed_work(struct work_struct *work) | 262 | static void close_delayed_work(struct work_struct *work) |
270 | { | 263 | { |
271 | struct snd_soc_device *socdev = | 264 | struct snd_soc_card *card = container_of(work, struct snd_soc_card, |
272 | container_of(work, struct snd_soc_device, delayed_work.work); | 265 | delayed_work.work); |
266 | struct snd_soc_device *socdev = card->socdev; | ||
273 | struct snd_soc_codec *codec = socdev->codec; | 267 | struct snd_soc_codec *codec = socdev->codec; |
274 | struct snd_soc_dai *codec_dai; | 268 | struct snd_soc_dai *codec_dai; |
275 | int i; | 269 | int i; |
@@ -278,18 +272,18 @@ static void close_delayed_work(struct work_struct *work) | |||
278 | for (i = 0; i < codec->num_dai; i++) { | 272 | for (i = 0; i < codec->num_dai; i++) { |
279 | codec_dai = &codec->dai[i]; | 273 | codec_dai = &codec->dai[i]; |
280 | 274 | ||
281 | dbg("pop wq checking: %s status: %s waiting: %s\n", | 275 | pr_debug("pop wq checking: %s status: %s waiting: %s\n", |
282 | codec_dai->playback.stream_name, | 276 | codec_dai->playback.stream_name, |
283 | codec_dai->playback.active ? "active" : "inactive", | 277 | codec_dai->playback.active ? "active" : "inactive", |
284 | codec_dai->pop_wait ? "yes" : "no"); | 278 | codec_dai->pop_wait ? "yes" : "no"); |
285 | 279 | ||
286 | /* are we waiting on this codec DAI stream */ | 280 | /* are we waiting on this codec DAI stream */ |
287 | if (codec_dai->pop_wait == 1) { | 281 | if (codec_dai->pop_wait == 1) { |
288 | 282 | ||
289 | /* Reduce power if no longer active */ | 283 | /* Reduce power if no longer active */ |
290 | if (codec->active == 0) { | 284 | if (codec->active == 0) { |
291 | dbg("pop wq D1 %s %s\n", codec->name, | 285 | pr_debug("pop wq D1 %s %s\n", codec->name, |
292 | codec_dai->playback.stream_name); | 286 | codec_dai->playback.stream_name); |
293 | snd_soc_dapm_set_bias_level(socdev, | 287 | snd_soc_dapm_set_bias_level(socdev, |
294 | SND_SOC_BIAS_PREPARE); | 288 | SND_SOC_BIAS_PREPARE); |
295 | } | 289 | } |
@@ -301,8 +295,8 @@ static void close_delayed_work(struct work_struct *work) | |||
301 | 295 | ||
302 | /* Fall into standby if no longer active */ | 296 | /* Fall into standby if no longer active */ |
303 | if (codec->active == 0) { | 297 | if (codec->active == 0) { |
304 | dbg("pop wq D3 %s %s\n", codec->name, | 298 | pr_debug("pop wq D3 %s %s\n", codec->name, |
305 | codec_dai->playback.stream_name); | 299 | codec_dai->playback.stream_name); |
306 | snd_soc_dapm_set_bias_level(socdev, | 300 | snd_soc_dapm_set_bias_level(socdev, |
307 | SND_SOC_BIAS_STANDBY); | 301 | SND_SOC_BIAS_STANDBY); |
308 | } | 302 | } |
@@ -320,8 +314,9 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
320 | { | 314 | { |
321 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 315 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
322 | struct snd_soc_device *socdev = rtd->socdev; | 316 | struct snd_soc_device *socdev = rtd->socdev; |
317 | struct snd_soc_card *card = socdev->card; | ||
323 | struct snd_soc_dai_link *machine = rtd->dai; | 318 | struct snd_soc_dai_link *machine = rtd->dai; |
324 | struct snd_soc_platform *platform = socdev->platform; | 319 | struct snd_soc_platform *platform = card->platform; |
325 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 320 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
326 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 321 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
327 | struct snd_soc_codec *codec = socdev->codec; | 322 | struct snd_soc_codec *codec = socdev->codec; |
@@ -346,10 +341,10 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
346 | snd_soc_dai_digital_mute(codec_dai, 1); | 341 | snd_soc_dai_digital_mute(codec_dai, 1); |
347 | 342 | ||
348 | if (cpu_dai->ops.shutdown) | 343 | if (cpu_dai->ops.shutdown) |
349 | cpu_dai->ops.shutdown(substream); | 344 | cpu_dai->ops.shutdown(substream, cpu_dai); |
350 | 345 | ||
351 | if (codec_dai->ops.shutdown) | 346 | if (codec_dai->ops.shutdown) |
352 | codec_dai->ops.shutdown(substream); | 347 | codec_dai->ops.shutdown(substream, codec_dai); |
353 | 348 | ||
354 | if (machine->ops && machine->ops->shutdown) | 349 | if (machine->ops && machine->ops->shutdown) |
355 | machine->ops->shutdown(substream); | 350 | machine->ops->shutdown(substream); |
@@ -361,7 +356,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
361 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 356 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
362 | /* start delayed pop wq here for playback streams */ | 357 | /* start delayed pop wq here for playback streams */ |
363 | codec_dai->pop_wait = 1; | 358 | codec_dai->pop_wait = 1; |
364 | schedule_delayed_work(&socdev->delayed_work, | 359 | schedule_delayed_work(&card->delayed_work, |
365 | msecs_to_jiffies(pmdown_time)); | 360 | msecs_to_jiffies(pmdown_time)); |
366 | } else { | 361 | } else { |
367 | /* capture streams can be powered down now */ | 362 | /* capture streams can be powered down now */ |
@@ -387,8 +382,9 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
387 | { | 382 | { |
388 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 383 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
389 | struct snd_soc_device *socdev = rtd->socdev; | 384 | struct snd_soc_device *socdev = rtd->socdev; |
385 | struct snd_soc_card *card = socdev->card; | ||
390 | struct snd_soc_dai_link *machine = rtd->dai; | 386 | struct snd_soc_dai_link *machine = rtd->dai; |
391 | struct snd_soc_platform *platform = socdev->platform; | 387 | struct snd_soc_platform *platform = card->platform; |
392 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 388 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
393 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 389 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
394 | struct snd_soc_codec *codec = socdev->codec; | 390 | struct snd_soc_codec *codec = socdev->codec; |
@@ -413,7 +409,7 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
413 | } | 409 | } |
414 | 410 | ||
415 | if (codec_dai->ops.prepare) { | 411 | if (codec_dai->ops.prepare) { |
416 | ret = codec_dai->ops.prepare(substream); | 412 | ret = codec_dai->ops.prepare(substream, codec_dai); |
417 | if (ret < 0) { | 413 | if (ret < 0) { |
418 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); | 414 | printk(KERN_ERR "asoc: codec DAI prepare error\n"); |
419 | goto out; | 415 | goto out; |
@@ -421,58 +417,49 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) | |||
421 | } | 417 | } |
422 | 418 | ||
423 | if (cpu_dai->ops.prepare) { | 419 | if (cpu_dai->ops.prepare) { |
424 | ret = cpu_dai->ops.prepare(substream); | 420 | ret = cpu_dai->ops.prepare(substream, cpu_dai); |
425 | if (ret < 0) { | 421 | if (ret < 0) { |
426 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); | 422 | printk(KERN_ERR "asoc: cpu DAI prepare error\n"); |
427 | goto out; | 423 | goto out; |
428 | } | 424 | } |
429 | } | 425 | } |
430 | 426 | ||
431 | /* we only want to start a DAPM playback stream if we are not waiting | 427 | /* cancel any delayed stream shutdown that is pending */ |
432 | * on an existing one stopping */ | 428 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && |
433 | if (codec_dai->pop_wait) { | 429 | codec_dai->pop_wait) { |
434 | /* we are waiting for the delayed work to start */ | 430 | codec_dai->pop_wait = 0; |
435 | if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) | 431 | cancel_delayed_work(&card->delayed_work); |
436 | snd_soc_dapm_stream_event(socdev->codec, | 432 | } |
437 | codec_dai->capture.stream_name, | ||
438 | SND_SOC_DAPM_STREAM_START); | ||
439 | else { | ||
440 | codec_dai->pop_wait = 0; | ||
441 | cancel_delayed_work(&socdev->delayed_work); | ||
442 | snd_soc_dai_digital_mute(codec_dai, 0); | ||
443 | } | ||
444 | } else { | ||
445 | /* no delayed work - do we need to power up codec */ | ||
446 | if (codec->bias_level != SND_SOC_BIAS_ON) { | ||
447 | 433 | ||
448 | snd_soc_dapm_set_bias_level(socdev, | 434 | /* do we need to power up codec */ |
449 | SND_SOC_BIAS_PREPARE); | 435 | if (codec->bias_level != SND_SOC_BIAS_ON) { |
436 | snd_soc_dapm_set_bias_level(socdev, | ||
437 | SND_SOC_BIAS_PREPARE); | ||
450 | 438 | ||
451 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 439 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
452 | snd_soc_dapm_stream_event(codec, | 440 | snd_soc_dapm_stream_event(codec, |
453 | codec_dai->playback.stream_name, | 441 | codec_dai->playback.stream_name, |
454 | SND_SOC_DAPM_STREAM_START); | 442 | SND_SOC_DAPM_STREAM_START); |
455 | else | 443 | else |
456 | snd_soc_dapm_stream_event(codec, | 444 | snd_soc_dapm_stream_event(codec, |
457 | codec_dai->capture.stream_name, | 445 | codec_dai->capture.stream_name, |
458 | SND_SOC_DAPM_STREAM_START); | 446 | SND_SOC_DAPM_STREAM_START); |
459 | 447 | ||
460 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON); | 448 | snd_soc_dapm_set_bias_level(socdev, SND_SOC_BIAS_ON); |
461 | snd_soc_dai_digital_mute(codec_dai, 0); | 449 | snd_soc_dai_digital_mute(codec_dai, 0); |
462 | 450 | ||
463 | } else { | 451 | } else { |
464 | /* codec already powered - power on widgets */ | 452 | /* codec already powered - power on widgets */ |
465 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) | 453 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) |
466 | snd_soc_dapm_stream_event(codec, | 454 | snd_soc_dapm_stream_event(codec, |
467 | codec_dai->playback.stream_name, | 455 | codec_dai->playback.stream_name, |
468 | SND_SOC_DAPM_STREAM_START); | 456 | SND_SOC_DAPM_STREAM_START); |
469 | else | 457 | else |
470 | snd_soc_dapm_stream_event(codec, | 458 | snd_soc_dapm_stream_event(codec, |
471 | codec_dai->capture.stream_name, | 459 | codec_dai->capture.stream_name, |
472 | SND_SOC_DAPM_STREAM_START); | 460 | SND_SOC_DAPM_STREAM_START); |
473 | 461 | ||
474 | snd_soc_dai_digital_mute(codec_dai, 0); | 462 | snd_soc_dai_digital_mute(codec_dai, 0); |
475 | } | ||
476 | } | 463 | } |
477 | 464 | ||
478 | out: | 465 | out: |
@@ -491,7 +478,8 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
491 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 478 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
492 | struct snd_soc_device *socdev = rtd->socdev; | 479 | struct snd_soc_device *socdev = rtd->socdev; |
493 | struct snd_soc_dai_link *machine = rtd->dai; | 480 | struct snd_soc_dai_link *machine = rtd->dai; |
494 | struct snd_soc_platform *platform = socdev->platform; | 481 | struct snd_soc_card *card = socdev->card; |
482 | struct snd_soc_platform *platform = card->platform; | ||
495 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 483 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
496 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 484 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
497 | int ret = 0; | 485 | int ret = 0; |
@@ -507,7 +495,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
507 | } | 495 | } |
508 | 496 | ||
509 | if (codec_dai->ops.hw_params) { | 497 | if (codec_dai->ops.hw_params) { |
510 | ret = codec_dai->ops.hw_params(substream, params); | 498 | ret = codec_dai->ops.hw_params(substream, params, codec_dai); |
511 | if (ret < 0) { | 499 | if (ret < 0) { |
512 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", | 500 | printk(KERN_ERR "asoc: can't set codec %s hw params\n", |
513 | codec_dai->name); | 501 | codec_dai->name); |
@@ -516,7 +504,7 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, | |||
516 | } | 504 | } |
517 | 505 | ||
518 | if (cpu_dai->ops.hw_params) { | 506 | if (cpu_dai->ops.hw_params) { |
519 | ret = cpu_dai->ops.hw_params(substream, params); | 507 | ret = cpu_dai->ops.hw_params(substream, params, cpu_dai); |
520 | if (ret < 0) { | 508 | if (ret < 0) { |
521 | printk(KERN_ERR "asoc: interface %s hw params failed\n", | 509 | printk(KERN_ERR "asoc: interface %s hw params failed\n", |
522 | cpu_dai->name); | 510 | cpu_dai->name); |
@@ -539,11 +527,11 @@ out: | |||
539 | 527 | ||
540 | platform_err: | 528 | platform_err: |
541 | if (cpu_dai->ops.hw_free) | 529 | if (cpu_dai->ops.hw_free) |
542 | cpu_dai->ops.hw_free(substream); | 530 | cpu_dai->ops.hw_free(substream, cpu_dai); |
543 | 531 | ||
544 | interface_err: | 532 | interface_err: |
545 | if (codec_dai->ops.hw_free) | 533 | if (codec_dai->ops.hw_free) |
546 | codec_dai->ops.hw_free(substream); | 534 | codec_dai->ops.hw_free(substream, codec_dai); |
547 | 535 | ||
548 | codec_err: | 536 | codec_err: |
549 | if (machine->ops && machine->ops->hw_free) | 537 | if (machine->ops && machine->ops->hw_free) |
@@ -561,7 +549,8 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
561 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 549 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
562 | struct snd_soc_device *socdev = rtd->socdev; | 550 | struct snd_soc_device *socdev = rtd->socdev; |
563 | struct snd_soc_dai_link *machine = rtd->dai; | 551 | struct snd_soc_dai_link *machine = rtd->dai; |
564 | struct snd_soc_platform *platform = socdev->platform; | 552 | struct snd_soc_card *card = socdev->card; |
553 | struct snd_soc_platform *platform = card->platform; | ||
565 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 554 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
566 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 555 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
567 | struct snd_soc_codec *codec = socdev->codec; | 556 | struct snd_soc_codec *codec = socdev->codec; |
@@ -582,10 +571,10 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
582 | 571 | ||
583 | /* now free hw params for the DAI's */ | 572 | /* now free hw params for the DAI's */ |
584 | if (codec_dai->ops.hw_free) | 573 | if (codec_dai->ops.hw_free) |
585 | codec_dai->ops.hw_free(substream); | 574 | codec_dai->ops.hw_free(substream, codec_dai); |
586 | 575 | ||
587 | if (cpu_dai->ops.hw_free) | 576 | if (cpu_dai->ops.hw_free) |
588 | cpu_dai->ops.hw_free(substream); | 577 | cpu_dai->ops.hw_free(substream, cpu_dai); |
589 | 578 | ||
590 | mutex_unlock(&pcm_mutex); | 579 | mutex_unlock(&pcm_mutex); |
591 | return 0; | 580 | return 0; |
@@ -595,14 +584,15 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
595 | { | 584 | { |
596 | struct snd_soc_pcm_runtime *rtd = substream->private_data; | 585 | struct snd_soc_pcm_runtime *rtd = substream->private_data; |
597 | struct snd_soc_device *socdev = rtd->socdev; | 586 | struct snd_soc_device *socdev = rtd->socdev; |
587 | struct snd_soc_card *card= socdev->card; | ||
598 | struct snd_soc_dai_link *machine = rtd->dai; | 588 | struct snd_soc_dai_link *machine = rtd->dai; |
599 | struct snd_soc_platform *platform = socdev->platform; | 589 | struct snd_soc_platform *platform = card->platform; |
600 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; | 590 | struct snd_soc_dai *cpu_dai = machine->cpu_dai; |
601 | struct snd_soc_dai *codec_dai = machine->codec_dai; | 591 | struct snd_soc_dai *codec_dai = machine->codec_dai; |
602 | int ret; | 592 | int ret; |
603 | 593 | ||
604 | if (codec_dai->ops.trigger) { | 594 | if (codec_dai->ops.trigger) { |
605 | ret = codec_dai->ops.trigger(substream, cmd); | 595 | ret = codec_dai->ops.trigger(substream, cmd, codec_dai); |
606 | if (ret < 0) | 596 | if (ret < 0) |
607 | return ret; | 597 | return ret; |
608 | } | 598 | } |
@@ -614,7 +604,7 @@ static int soc_pcm_trigger(struct snd_pcm_substream *substream, int cmd) | |||
614 | } | 604 | } |
615 | 605 | ||
616 | if (cpu_dai->ops.trigger) { | 606 | if (cpu_dai->ops.trigger) { |
617 | ret = cpu_dai->ops.trigger(substream, cmd); | 607 | ret = cpu_dai->ops.trigger(substream, cmd, cpu_dai); |
618 | if (ret < 0) | 608 | if (ret < 0) |
619 | return ret; | 609 | return ret; |
620 | } | 610 | } |
@@ -636,8 +626,8 @@ static struct snd_pcm_ops soc_pcm_ops = { | |||
636 | static int soc_suspend(struct platform_device *pdev, pm_message_t state) | 626 | static int soc_suspend(struct platform_device *pdev, pm_message_t state) |
637 | { | 627 | { |
638 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 628 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
639 | struct snd_soc_machine *machine = socdev->machine; | 629 | struct snd_soc_card *card = socdev->card; |
640 | struct snd_soc_platform *platform = socdev->platform; | 630 | struct snd_soc_platform *platform = card->platform; |
641 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 631 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
642 | struct snd_soc_codec *codec = socdev->codec; | 632 | struct snd_soc_codec *codec = socdev->codec; |
643 | int i; | 633 | int i; |
@@ -653,29 +643,29 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
653 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); | 643 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D3hot); |
654 | 644 | ||
655 | /* mute any active DAC's */ | 645 | /* mute any active DAC's */ |
656 | for (i = 0; i < machine->num_links; i++) { | 646 | for (i = 0; i < card->num_links; i++) { |
657 | struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; | 647 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
658 | if (dai->dai_ops.digital_mute && dai->playback.active) | 648 | if (dai->ops.digital_mute && dai->playback.active) |
659 | dai->dai_ops.digital_mute(dai, 1); | 649 | dai->ops.digital_mute(dai, 1); |
660 | } | 650 | } |
661 | 651 | ||
662 | /* suspend all pcms */ | 652 | /* suspend all pcms */ |
663 | for (i = 0; i < machine->num_links; i++) | 653 | for (i = 0; i < card->num_links; i++) |
664 | snd_pcm_suspend_all(machine->dai_link[i].pcm); | 654 | snd_pcm_suspend_all(card->dai_link[i].pcm); |
665 | 655 | ||
666 | if (machine->suspend_pre) | 656 | if (card->suspend_pre) |
667 | machine->suspend_pre(pdev, state); | 657 | card->suspend_pre(pdev, state); |
668 | 658 | ||
669 | for (i = 0; i < machine->num_links; i++) { | 659 | for (i = 0; i < card->num_links; i++) { |
670 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 660 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
671 | if (cpu_dai->suspend && cpu_dai->type != SND_SOC_DAI_AC97) | 661 | if (cpu_dai->suspend && !cpu_dai->ac97_control) |
672 | cpu_dai->suspend(pdev, cpu_dai); | 662 | cpu_dai->suspend(cpu_dai); |
673 | if (platform->suspend) | 663 | if (platform->suspend) |
674 | platform->suspend(pdev, cpu_dai); | 664 | platform->suspend(cpu_dai); |
675 | } | 665 | } |
676 | 666 | ||
677 | /* close any waiting streams and save state */ | 667 | /* close any waiting streams and save state */ |
678 | run_delayed_work(&socdev->delayed_work); | 668 | run_delayed_work(&card->delayed_work); |
679 | codec->suspend_bias_level = codec->bias_level; | 669 | codec->suspend_bias_level = codec->bias_level; |
680 | 670 | ||
681 | for (i = 0; i < codec->num_dai; i++) { | 671 | for (i = 0; i < codec->num_dai; i++) { |
@@ -692,14 +682,14 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
692 | if (codec_dev->suspend) | 682 | if (codec_dev->suspend) |
693 | codec_dev->suspend(pdev, state); | 683 | codec_dev->suspend(pdev, state); |
694 | 684 | ||
695 | for (i = 0; i < machine->num_links; i++) { | 685 | for (i = 0; i < card->num_links; i++) { |
696 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 686 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
697 | if (cpu_dai->suspend && cpu_dai->type == SND_SOC_DAI_AC97) | 687 | if (cpu_dai->suspend && cpu_dai->ac97_control) |
698 | cpu_dai->suspend(pdev, cpu_dai); | 688 | cpu_dai->suspend(cpu_dai); |
699 | } | 689 | } |
700 | 690 | ||
701 | if (machine->suspend_post) | 691 | if (card->suspend_post) |
702 | machine->suspend_post(pdev, state); | 692 | card->suspend_post(pdev, state); |
703 | 693 | ||
704 | return 0; | 694 | return 0; |
705 | } | 695 | } |
@@ -709,11 +699,11 @@ static int soc_suspend(struct platform_device *pdev, pm_message_t state) | |||
709 | */ | 699 | */ |
710 | static void soc_resume_deferred(struct work_struct *work) | 700 | static void soc_resume_deferred(struct work_struct *work) |
711 | { | 701 | { |
712 | struct snd_soc_device *socdev = container_of(work, | 702 | struct snd_soc_card *card = container_of(work, |
713 | struct snd_soc_device, | 703 | struct snd_soc_card, |
714 | deferred_resume_work); | 704 | deferred_resume_work); |
715 | struct snd_soc_machine *machine = socdev->machine; | 705 | struct snd_soc_device *socdev = card->socdev; |
716 | struct snd_soc_platform *platform = socdev->platform; | 706 | struct snd_soc_platform *platform = card->platform; |
717 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 707 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
718 | struct snd_soc_codec *codec = socdev->codec; | 708 | struct snd_soc_codec *codec = socdev->codec; |
719 | struct platform_device *pdev = to_platform_device(socdev->dev); | 709 | struct platform_device *pdev = to_platform_device(socdev->dev); |
@@ -723,15 +713,15 @@ static void soc_resume_deferred(struct work_struct *work) | |||
723 | * so userspace apps are blocked from touching us | 713 | * so userspace apps are blocked from touching us |
724 | */ | 714 | */ |
725 | 715 | ||
726 | dev_info(socdev->dev, "starting resume work\n"); | 716 | dev_dbg(socdev->dev, "starting resume work\n"); |
727 | 717 | ||
728 | if (machine->resume_pre) | 718 | if (card->resume_pre) |
729 | machine->resume_pre(pdev); | 719 | card->resume_pre(pdev); |
730 | 720 | ||
731 | for (i = 0; i < machine->num_links; i++) { | 721 | for (i = 0; i < card->num_links; i++) { |
732 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 722 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
733 | if (cpu_dai->resume && cpu_dai->type == SND_SOC_DAI_AC97) | 723 | if (cpu_dai->resume && cpu_dai->ac97_control) |
734 | cpu_dai->resume(pdev, cpu_dai); | 724 | cpu_dai->resume(cpu_dai); |
735 | } | 725 | } |
736 | 726 | ||
737 | if (codec_dev->resume) | 727 | if (codec_dev->resume) |
@@ -749,24 +739,24 @@ static void soc_resume_deferred(struct work_struct *work) | |||
749 | } | 739 | } |
750 | 740 | ||
751 | /* unmute any active DACs */ | 741 | /* unmute any active DACs */ |
752 | for (i = 0; i < machine->num_links; i++) { | 742 | for (i = 0; i < card->num_links; i++) { |
753 | struct snd_soc_dai *dai = machine->dai_link[i].codec_dai; | 743 | struct snd_soc_dai *dai = card->dai_link[i].codec_dai; |
754 | if (dai->dai_ops.digital_mute && dai->playback.active) | 744 | if (dai->ops.digital_mute && dai->playback.active) |
755 | dai->dai_ops.digital_mute(dai, 0); | 745 | dai->ops.digital_mute(dai, 0); |
756 | } | 746 | } |
757 | 747 | ||
758 | for (i = 0; i < machine->num_links; i++) { | 748 | for (i = 0; i < card->num_links; i++) { |
759 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 749 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
760 | if (cpu_dai->resume && cpu_dai->type != SND_SOC_DAI_AC97) | 750 | if (cpu_dai->resume && !cpu_dai->ac97_control) |
761 | cpu_dai->resume(pdev, cpu_dai); | 751 | cpu_dai->resume(cpu_dai); |
762 | if (platform->resume) | 752 | if (platform->resume) |
763 | platform->resume(pdev, cpu_dai); | 753 | platform->resume(cpu_dai); |
764 | } | 754 | } |
765 | 755 | ||
766 | if (machine->resume_post) | 756 | if (card->resume_post) |
767 | machine->resume_post(pdev); | 757 | card->resume_post(pdev); |
768 | 758 | ||
769 | dev_info(socdev->dev, "resume work completed\n"); | 759 | dev_dbg(socdev->dev, "resume work completed\n"); |
770 | 760 | ||
771 | /* userspace can access us now we are back as we were before */ | 761 | /* userspace can access us now we are back as we were before */ |
772 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); | 762 | snd_power_change_state(codec->card, SNDRV_CTL_POWER_D0); |
@@ -776,11 +766,12 @@ static void soc_resume_deferred(struct work_struct *work) | |||
776 | static int soc_resume(struct platform_device *pdev) | 766 | static int soc_resume(struct platform_device *pdev) |
777 | { | 767 | { |
778 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 768 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
769 | struct snd_soc_card *card = socdev->card; | ||
779 | 770 | ||
780 | dev_info(socdev->dev, "scheduling resume work\n"); | 771 | dev_dbg(socdev->dev, "scheduling resume work\n"); |
781 | 772 | ||
782 | if (!schedule_work(&socdev->deferred_resume_work)) | 773 | if (!schedule_work(&card->deferred_resume_work)) |
783 | dev_err(socdev->dev, "work item may be lost\n"); | 774 | dev_err(socdev->dev, "resume work item may be lost\n"); |
784 | 775 | ||
785 | return 0; | 776 | return 0; |
786 | } | 777 | } |
@@ -790,23 +781,83 @@ static int soc_resume(struct platform_device *pdev) | |||
790 | #define soc_resume NULL | 781 | #define soc_resume NULL |
791 | #endif | 782 | #endif |
792 | 783 | ||
793 | /* probes a new socdev */ | 784 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
794 | static int soc_probe(struct platform_device *pdev) | ||
795 | { | 785 | { |
796 | int ret = 0, i; | 786 | struct platform_device *pdev = container_of(card->dev, |
797 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 787 | struct platform_device, |
798 | struct snd_soc_machine *machine = socdev->machine; | 788 | dev); |
799 | struct snd_soc_platform *platform = socdev->platform; | 789 | struct snd_soc_codec_device *codec_dev = card->socdev->codec_dev; |
800 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 790 | struct snd_soc_platform *platform; |
791 | struct snd_soc_dai *dai; | ||
792 | int i, found, ret, ac97; | ||
793 | |||
794 | if (card->instantiated) | ||
795 | return; | ||
796 | |||
797 | found = 0; | ||
798 | list_for_each_entry(platform, &platform_list, list) | ||
799 | if (card->platform == platform) { | ||
800 | found = 1; | ||
801 | break; | ||
802 | } | ||
803 | if (!found) { | ||
804 | dev_dbg(card->dev, "Platform %s not registered\n", | ||
805 | card->platform->name); | ||
806 | return; | ||
807 | } | ||
808 | |||
809 | ac97 = 0; | ||
810 | for (i = 0; i < card->num_links; i++) { | ||
811 | found = 0; | ||
812 | list_for_each_entry(dai, &dai_list, list) | ||
813 | if (card->dai_link[i].cpu_dai == dai) { | ||
814 | found = 1; | ||
815 | break; | ||
816 | } | ||
817 | if (!found) { | ||
818 | dev_dbg(card->dev, "DAI %s not registered\n", | ||
819 | card->dai_link[i].cpu_dai->name); | ||
820 | return; | ||
821 | } | ||
801 | 822 | ||
802 | if (machine->probe) { | 823 | if (card->dai_link[i].cpu_dai->ac97_control) |
803 | ret = machine->probe(pdev); | 824 | ac97 = 1; |
825 | } | ||
826 | |||
827 | /* If we have AC97 in the system then don't wait for the | ||
828 | * codec. This will need revisiting if we have to handle | ||
829 | * systems with mixed AC97 and non-AC97 parts. Only check for | ||
830 | * DAIs currently; we can't do this per link since some AC97 | ||
831 | * codecs have non-AC97 DAIs. | ||
832 | */ | ||
833 | if (!ac97) | ||
834 | for (i = 0; i < card->num_links; i++) { | ||
835 | found = 0; | ||
836 | list_for_each_entry(dai, &dai_list, list) | ||
837 | if (card->dai_link[i].codec_dai == dai) { | ||
838 | found = 1; | ||
839 | break; | ||
840 | } | ||
841 | if (!found) { | ||
842 | dev_dbg(card->dev, "DAI %s not registered\n", | ||
843 | card->dai_link[i].codec_dai->name); | ||
844 | return; | ||
845 | } | ||
846 | } | ||
847 | |||
848 | /* Note that we do not current check for codec components */ | ||
849 | |||
850 | dev_dbg(card->dev, "All components present, instantiating\n"); | ||
851 | |||
852 | /* Found everything, bring it up */ | ||
853 | if (card->probe) { | ||
854 | ret = card->probe(pdev); | ||
804 | if (ret < 0) | 855 | if (ret < 0) |
805 | return ret; | 856 | return; |
806 | } | 857 | } |
807 | 858 | ||
808 | for (i = 0; i < machine->num_links; i++) { | 859 | for (i = 0; i < card->num_links; i++) { |
809 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 860 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
810 | if (cpu_dai->probe) { | 861 | if (cpu_dai->probe) { |
811 | ret = cpu_dai->probe(pdev, cpu_dai); | 862 | ret = cpu_dai->probe(pdev, cpu_dai); |
812 | if (ret < 0) | 863 | if (ret < 0) |
@@ -827,13 +878,15 @@ static int soc_probe(struct platform_device *pdev) | |||
827 | } | 878 | } |
828 | 879 | ||
829 | /* DAPM stream work */ | 880 | /* DAPM stream work */ |
830 | INIT_DELAYED_WORK(&socdev->delayed_work, close_delayed_work); | 881 | INIT_DELAYED_WORK(&card->delayed_work, close_delayed_work); |
831 | #ifdef CONFIG_PM | 882 | #ifdef CONFIG_PM |
832 | /* deferred resume work */ | 883 | /* deferred resume work */ |
833 | INIT_WORK(&socdev->deferred_resume_work, soc_resume_deferred); | 884 | INIT_WORK(&card->deferred_resume_work, soc_resume_deferred); |
834 | #endif | 885 | #endif |
835 | 886 | ||
836 | return 0; | 887 | card->instantiated = 1; |
888 | |||
889 | return; | ||
837 | 890 | ||
838 | platform_err: | 891 | platform_err: |
839 | if (codec_dev->remove) | 892 | if (codec_dev->remove) |
@@ -841,15 +894,45 @@ platform_err: | |||
841 | 894 | ||
842 | cpu_dai_err: | 895 | cpu_dai_err: |
843 | for (i--; i >= 0; i--) { | 896 | for (i--; i >= 0; i--) { |
844 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 897 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
845 | if (cpu_dai->remove) | 898 | if (cpu_dai->remove) |
846 | cpu_dai->remove(pdev, cpu_dai); | 899 | cpu_dai->remove(pdev, cpu_dai); |
847 | } | 900 | } |
848 | 901 | ||
849 | if (machine->remove) | 902 | if (card->remove) |
850 | machine->remove(pdev); | 903 | card->remove(pdev); |
904 | } | ||
851 | 905 | ||
852 | return ret; | 906 | /* |
907 | * Attempt to initialise any uninitalised cards. Must be called with | ||
908 | * client_mutex. | ||
909 | */ | ||
910 | static void snd_soc_instantiate_cards(void) | ||
911 | { | ||
912 | struct snd_soc_card *card; | ||
913 | list_for_each_entry(card, &card_list, list) | ||
914 | snd_soc_instantiate_card(card); | ||
915 | } | ||
916 | |||
917 | /* probes a new socdev */ | ||
918 | static int soc_probe(struct platform_device *pdev) | ||
919 | { | ||
920 | int ret = 0; | ||
921 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | ||
922 | struct snd_soc_card *card = socdev->card; | ||
923 | |||
924 | /* Bodge while we push things out of socdev */ | ||
925 | card->socdev = socdev; | ||
926 | |||
927 | /* Bodge while we unpick instantiation */ | ||
928 | card->dev = &pdev->dev; | ||
929 | ret = snd_soc_register_card(card); | ||
930 | if (ret != 0) { | ||
931 | dev_err(&pdev->dev, "Failed to register card\n"); | ||
932 | return ret; | ||
933 | } | ||
934 | |||
935 | return 0; | ||
853 | } | 936 | } |
854 | 937 | ||
855 | /* removes a socdev */ | 938 | /* removes a socdev */ |
@@ -857,11 +940,11 @@ static int soc_remove(struct platform_device *pdev) | |||
857 | { | 940 | { |
858 | int i; | 941 | int i; |
859 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); | 942 | struct snd_soc_device *socdev = platform_get_drvdata(pdev); |
860 | struct snd_soc_machine *machine = socdev->machine; | 943 | struct snd_soc_card *card = socdev->card; |
861 | struct snd_soc_platform *platform = socdev->platform; | 944 | struct snd_soc_platform *platform = card->platform; |
862 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; | 945 | struct snd_soc_codec_device *codec_dev = socdev->codec_dev; |
863 | 946 | ||
864 | run_delayed_work(&socdev->delayed_work); | 947 | run_delayed_work(&card->delayed_work); |
865 | 948 | ||
866 | if (platform->remove) | 949 | if (platform->remove) |
867 | platform->remove(pdev); | 950 | platform->remove(pdev); |
@@ -869,14 +952,16 @@ static int soc_remove(struct platform_device *pdev) | |||
869 | if (codec_dev->remove) | 952 | if (codec_dev->remove) |
870 | codec_dev->remove(pdev); | 953 | codec_dev->remove(pdev); |
871 | 954 | ||
872 | for (i = 0; i < machine->num_links; i++) { | 955 | for (i = 0; i < card->num_links; i++) { |
873 | struct snd_soc_dai *cpu_dai = machine->dai_link[i].cpu_dai; | 956 | struct snd_soc_dai *cpu_dai = card->dai_link[i].cpu_dai; |
874 | if (cpu_dai->remove) | 957 | if (cpu_dai->remove) |
875 | cpu_dai->remove(pdev, cpu_dai); | 958 | cpu_dai->remove(pdev, cpu_dai); |
876 | } | 959 | } |
877 | 960 | ||
878 | if (machine->remove) | 961 | if (card->remove) |
879 | machine->remove(pdev); | 962 | card->remove(pdev); |
963 | |||
964 | snd_soc_unregister_card(card); | ||
880 | 965 | ||
881 | return 0; | 966 | return 0; |
882 | } | 967 | } |
@@ -898,6 +983,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
898 | struct snd_soc_dai_link *dai_link, int num) | 983 | struct snd_soc_dai_link *dai_link, int num) |
899 | { | 984 | { |
900 | struct snd_soc_codec *codec = socdev->codec; | 985 | struct snd_soc_codec *codec = socdev->codec; |
986 | struct snd_soc_card *card = socdev->card; | ||
987 | struct snd_soc_platform *platform = card->platform; | ||
901 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; | 988 | struct snd_soc_dai *codec_dai = dai_link->codec_dai; |
902 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; | 989 | struct snd_soc_dai *cpu_dai = dai_link->cpu_dai; |
903 | struct snd_soc_pcm_runtime *rtd; | 990 | struct snd_soc_pcm_runtime *rtd; |
@@ -914,8 +1001,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
914 | codec_dai->codec = socdev->codec; | 1001 | codec_dai->codec = socdev->codec; |
915 | 1002 | ||
916 | /* check client and interface hw capabilities */ | 1003 | /* check client and interface hw capabilities */ |
917 | sprintf(new_name, "%s %s-%s-%d", dai_link->stream_name, codec_dai->name, | 1004 | sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, |
918 | get_dai_name(cpu_dai->type), num); | 1005 | num); |
919 | 1006 | ||
920 | if (codec_dai->playback.channels_min) | 1007 | if (codec_dai->playback.channels_min) |
921 | playback = 1; | 1008 | playback = 1; |
@@ -933,13 +1020,13 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
933 | 1020 | ||
934 | dai_link->pcm = pcm; | 1021 | dai_link->pcm = pcm; |
935 | pcm->private_data = rtd; | 1022 | pcm->private_data = rtd; |
936 | soc_pcm_ops.mmap = socdev->platform->pcm_ops->mmap; | 1023 | soc_pcm_ops.mmap = platform->pcm_ops->mmap; |
937 | soc_pcm_ops.pointer = socdev->platform->pcm_ops->pointer; | 1024 | soc_pcm_ops.pointer = platform->pcm_ops->pointer; |
938 | soc_pcm_ops.ioctl = socdev->platform->pcm_ops->ioctl; | 1025 | soc_pcm_ops.ioctl = platform->pcm_ops->ioctl; |
939 | soc_pcm_ops.copy = socdev->platform->pcm_ops->copy; | 1026 | soc_pcm_ops.copy = platform->pcm_ops->copy; |
940 | soc_pcm_ops.silence = socdev->platform->pcm_ops->silence; | 1027 | soc_pcm_ops.silence = platform->pcm_ops->silence; |
941 | soc_pcm_ops.ack = socdev->platform->pcm_ops->ack; | 1028 | soc_pcm_ops.ack = platform->pcm_ops->ack; |
942 | soc_pcm_ops.page = socdev->platform->pcm_ops->page; | 1029 | soc_pcm_ops.page = platform->pcm_ops->page; |
943 | 1030 | ||
944 | if (playback) | 1031 | if (playback) |
945 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); | 1032 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_PLAYBACK, &soc_pcm_ops); |
@@ -947,24 +1034,22 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
947 | if (capture) | 1034 | if (capture) |
948 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); | 1035 | snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &soc_pcm_ops); |
949 | 1036 | ||
950 | ret = socdev->platform->pcm_new(codec->card, codec_dai, pcm); | 1037 | ret = platform->pcm_new(codec->card, codec_dai, pcm); |
951 | if (ret < 0) { | 1038 | if (ret < 0) { |
952 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); | 1039 | printk(KERN_ERR "asoc: platform pcm constructor failed\n"); |
953 | kfree(rtd); | 1040 | kfree(rtd); |
954 | return ret; | 1041 | return ret; |
955 | } | 1042 | } |
956 | 1043 | ||
957 | pcm->private_free = socdev->platform->pcm_free; | 1044 | pcm->private_free = platform->pcm_free; |
958 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, | 1045 | printk(KERN_INFO "asoc: %s <-> %s mapping ok\n", codec_dai->name, |
959 | cpu_dai->name); | 1046 | cpu_dai->name); |
960 | return ret; | 1047 | return ret; |
961 | } | 1048 | } |
962 | 1049 | ||
963 | /* codec register dump */ | 1050 | /* codec register dump */ |
964 | static ssize_t codec_reg_show(struct device *dev, | 1051 | static ssize_t soc_codec_reg_show(struct snd_soc_device *devdata, char *buf) |
965 | struct device_attribute *attr, char *buf) | ||
966 | { | 1052 | { |
967 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
968 | struct snd_soc_codec *codec = devdata->codec; | 1053 | struct snd_soc_codec *codec = devdata->codec; |
969 | int i, step = 1, count = 0; | 1054 | int i, step = 1, count = 0; |
970 | 1055 | ||
@@ -1001,8 +1086,110 @@ static ssize_t codec_reg_show(struct device *dev, | |||
1001 | 1086 | ||
1002 | return count; | 1087 | return count; |
1003 | } | 1088 | } |
1089 | static ssize_t codec_reg_show(struct device *dev, | ||
1090 | struct device_attribute *attr, char *buf) | ||
1091 | { | ||
1092 | struct snd_soc_device *devdata = dev_get_drvdata(dev); | ||
1093 | return soc_codec_reg_show(devdata, buf); | ||
1094 | } | ||
1095 | |||
1004 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 1096 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
1005 | 1097 | ||
1098 | #ifdef CONFIG_DEBUG_FS | ||
1099 | static int codec_reg_open_file(struct inode *inode, struct file *file) | ||
1100 | { | ||
1101 | file->private_data = inode->i_private; | ||
1102 | return 0; | ||
1103 | } | ||
1104 | |||
1105 | static ssize_t codec_reg_read_file(struct file *file, char __user *user_buf, | ||
1106 | size_t count, loff_t *ppos) | ||
1107 | { | ||
1108 | ssize_t ret; | ||
1109 | struct snd_soc_codec *codec = file->private_data; | ||
1110 | struct device *card_dev = codec->card->dev; | ||
1111 | struct snd_soc_device *devdata = card_dev->driver_data; | ||
1112 | char *buf = kmalloc(PAGE_SIZE, GFP_KERNEL); | ||
1113 | if (!buf) | ||
1114 | return -ENOMEM; | ||
1115 | ret = soc_codec_reg_show(devdata, buf); | ||
1116 | if (ret >= 0) | ||
1117 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, ret); | ||
1118 | kfree(buf); | ||
1119 | return ret; | ||
1120 | } | ||
1121 | |||
1122 | static ssize_t codec_reg_write_file(struct file *file, | ||
1123 | const char __user *user_buf, size_t count, loff_t *ppos) | ||
1124 | { | ||
1125 | char buf[32]; | ||
1126 | int buf_size; | ||
1127 | char *start = buf; | ||
1128 | unsigned long reg, value; | ||
1129 | int step = 1; | ||
1130 | struct snd_soc_codec *codec = file->private_data; | ||
1131 | |||
1132 | buf_size = min(count, (sizeof(buf)-1)); | ||
1133 | if (copy_from_user(buf, user_buf, buf_size)) | ||
1134 | return -EFAULT; | ||
1135 | buf[buf_size] = 0; | ||
1136 | |||
1137 | if (codec->reg_cache_step) | ||
1138 | step = codec->reg_cache_step; | ||
1139 | |||
1140 | while (*start == ' ') | ||
1141 | start++; | ||
1142 | reg = simple_strtoul(start, &start, 16); | ||
1143 | if ((reg >= codec->reg_cache_size) || (reg % step)) | ||
1144 | return -EINVAL; | ||
1145 | while (*start == ' ') | ||
1146 | start++; | ||
1147 | if (strict_strtoul(start, 16, &value)) | ||
1148 | return -EINVAL; | ||
1149 | codec->write(codec, reg, value); | ||
1150 | return buf_size; | ||
1151 | } | ||
1152 | |||
1153 | static const struct file_operations codec_reg_fops = { | ||
1154 | .open = codec_reg_open_file, | ||
1155 | .read = codec_reg_read_file, | ||
1156 | .write = codec_reg_write_file, | ||
1157 | }; | ||
1158 | |||
1159 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | ||
1160 | { | ||
1161 | codec->debugfs_reg = debugfs_create_file("codec_reg", 0644, | ||
1162 | debugfs_root, codec, | ||
1163 | &codec_reg_fops); | ||
1164 | if (!codec->debugfs_reg) | ||
1165 | printk(KERN_WARNING | ||
1166 | "ASoC: Failed to create codec register debugfs file\n"); | ||
1167 | |||
1168 | codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0744, | ||
1169 | debugfs_root, | ||
1170 | &codec->pop_time); | ||
1171 | if (!codec->debugfs_pop_time) | ||
1172 | printk(KERN_WARNING | ||
1173 | "Failed to create pop time debugfs file\n"); | ||
1174 | } | ||
1175 | |||
1176 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | ||
1177 | { | ||
1178 | debugfs_remove(codec->debugfs_pop_time); | ||
1179 | debugfs_remove(codec->debugfs_reg); | ||
1180 | } | ||
1181 | |||
1182 | #else | ||
1183 | |||
1184 | static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | ||
1185 | { | ||
1186 | } | ||
1187 | |||
1188 | static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | ||
1189 | { | ||
1190 | } | ||
1191 | #endif | ||
1192 | |||
1006 | /** | 1193 | /** |
1007 | * snd_soc_new_ac97_codec - initailise AC97 device | 1194 | * snd_soc_new_ac97_codec - initailise AC97 device |
1008 | * @codec: audio codec | 1195 | * @codec: audio codec |
@@ -1121,7 +1308,7 @@ EXPORT_SYMBOL_GPL(snd_soc_test_bits); | |||
1121 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | 1308 | int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) |
1122 | { | 1309 | { |
1123 | struct snd_soc_codec *codec = socdev->codec; | 1310 | struct snd_soc_codec *codec = socdev->codec; |
1124 | struct snd_soc_machine *machine = socdev->machine; | 1311 | struct snd_soc_card *card = socdev->card; |
1125 | int ret = 0, i; | 1312 | int ret = 0, i; |
1126 | 1313 | ||
1127 | mutex_lock(&codec->mutex); | 1314 | mutex_lock(&codec->mutex); |
@@ -1140,11 +1327,11 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | |||
1140 | strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); | 1327 | strncpy(codec->card->driver, codec->name, sizeof(codec->card->driver)); |
1141 | 1328 | ||
1142 | /* create the pcms */ | 1329 | /* create the pcms */ |
1143 | for (i = 0; i < machine->num_links; i++) { | 1330 | for (i = 0; i < card->num_links; i++) { |
1144 | ret = soc_new_pcm(socdev, &machine->dai_link[i], i); | 1331 | ret = soc_new_pcm(socdev, &card->dai_link[i], i); |
1145 | if (ret < 0) { | 1332 | if (ret < 0) { |
1146 | printk(KERN_ERR "asoc: can't create pcm %s\n", | 1333 | printk(KERN_ERR "asoc: can't create pcm %s\n", |
1147 | machine->dai_link[i].stream_name); | 1334 | card->dai_link[i].stream_name); |
1148 | mutex_unlock(&codec->mutex); | 1335 | mutex_unlock(&codec->mutex); |
1149 | return ret; | 1336 | return ret; |
1150 | } | 1337 | } |
@@ -1156,7 +1343,7 @@ int snd_soc_new_pcms(struct snd_soc_device *socdev, int idx, const char *xid) | |||
1156 | EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | 1343 | EXPORT_SYMBOL_GPL(snd_soc_new_pcms); |
1157 | 1344 | ||
1158 | /** | 1345 | /** |
1159 | * snd_soc_register_card - register sound card | 1346 | * snd_soc_init_card - register sound card |
1160 | * @socdev: the SoC audio device | 1347 | * @socdev: the SoC audio device |
1161 | * | 1348 | * |
1162 | * Register a SoC sound card. Also registers an AC97 device if the | 1349 | * Register a SoC sound card. Also registers an AC97 device if the |
@@ -1164,29 +1351,28 @@ EXPORT_SYMBOL_GPL(snd_soc_new_pcms); | |||
1164 | * | 1351 | * |
1165 | * Returns 0 for success, else error. | 1352 | * Returns 0 for success, else error. |
1166 | */ | 1353 | */ |
1167 | int snd_soc_register_card(struct snd_soc_device *socdev) | 1354 | int snd_soc_init_card(struct snd_soc_device *socdev) |
1168 | { | 1355 | { |
1169 | struct snd_soc_codec *codec = socdev->codec; | 1356 | struct snd_soc_codec *codec = socdev->codec; |
1170 | struct snd_soc_machine *machine = socdev->machine; | 1357 | struct snd_soc_card *card = socdev->card; |
1171 | int ret = 0, i, ac97 = 0, err = 0; | 1358 | int ret = 0, i, ac97 = 0, err = 0; |
1172 | 1359 | ||
1173 | for (i = 0; i < machine->num_links; i++) { | 1360 | for (i = 0; i < card->num_links; i++) { |
1174 | if (socdev->machine->dai_link[i].init) { | 1361 | if (card->dai_link[i].init) { |
1175 | err = socdev->machine->dai_link[i].init(codec); | 1362 | err = card->dai_link[i].init(codec); |
1176 | if (err < 0) { | 1363 | if (err < 0) { |
1177 | printk(KERN_ERR "asoc: failed to init %s\n", | 1364 | printk(KERN_ERR "asoc: failed to init %s\n", |
1178 | socdev->machine->dai_link[i].stream_name); | 1365 | card->dai_link[i].stream_name); |
1179 | continue; | 1366 | continue; |
1180 | } | 1367 | } |
1181 | } | 1368 | } |
1182 | if (socdev->machine->dai_link[i].codec_dai->type == | 1369 | if (card->dai_link[i].codec_dai->ac97_control) |
1183 | SND_SOC_DAI_AC97_BUS) | ||
1184 | ac97 = 1; | 1370 | ac97 = 1; |
1185 | } | 1371 | } |
1186 | snprintf(codec->card->shortname, sizeof(codec->card->shortname), | 1372 | snprintf(codec->card->shortname, sizeof(codec->card->shortname), |
1187 | "%s", machine->name); | 1373 | "%s", card->name); |
1188 | snprintf(codec->card->longname, sizeof(codec->card->longname), | 1374 | snprintf(codec->card->longname, sizeof(codec->card->longname), |
1189 | "%s (%s)", machine->name, codec->name); | 1375 | "%s (%s)", card->name, codec->name); |
1190 | 1376 | ||
1191 | ret = snd_card_register(codec->card); | 1377 | ret = snd_card_register(codec->card); |
1192 | if (ret < 0) { | 1378 | if (ret < 0) { |
@@ -1216,12 +1402,13 @@ int snd_soc_register_card(struct snd_soc_device *socdev) | |||
1216 | if (err < 0) | 1402 | if (err < 0) |
1217 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1403 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); |
1218 | 1404 | ||
1405 | soc_init_codec_debugfs(socdev->codec); | ||
1219 | mutex_unlock(&codec->mutex); | 1406 | mutex_unlock(&codec->mutex); |
1220 | 1407 | ||
1221 | out: | 1408 | out: |
1222 | return ret; | 1409 | return ret; |
1223 | } | 1410 | } |
1224 | EXPORT_SYMBOL_GPL(snd_soc_register_card); | 1411 | EXPORT_SYMBOL_GPL(snd_soc_init_card); |
1225 | 1412 | ||
1226 | /** | 1413 | /** |
1227 | * snd_soc_free_pcms - free sound card and pcms | 1414 | * snd_soc_free_pcms - free sound card and pcms |
@@ -1239,10 +1426,11 @@ void snd_soc_free_pcms(struct snd_soc_device *socdev) | |||
1239 | #endif | 1426 | #endif |
1240 | 1427 | ||
1241 | mutex_lock(&codec->mutex); | 1428 | mutex_lock(&codec->mutex); |
1429 | soc_cleanup_codec_debugfs(socdev->codec); | ||
1242 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1430 | #ifdef CONFIG_SND_SOC_AC97_BUS |
1243 | for (i = 0; i < codec->num_dai; i++) { | 1431 | for (i = 0; i < codec->num_dai; i++) { |
1244 | codec_dai = &codec->dai[i]; | 1432 | codec_dai = &codec->dai[i]; |
1245 | if (codec_dai->type == SND_SOC_DAI_AC97_BUS && codec->ac97) { | 1433 | if (codec_dai->ac97_control && codec->ac97) { |
1246 | soc_ac97_dev_unregister(codec); | 1434 | soc_ac97_dev_unregister(codec); |
1247 | goto free_card; | 1435 | goto free_card; |
1248 | } | 1436 | } |
@@ -1756,8 +1944,8 @@ EXPORT_SYMBOL_GPL(snd_soc_put_volsw_s8); | |||
1756 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, | 1944 | int snd_soc_dai_set_sysclk(struct snd_soc_dai *dai, int clk_id, |
1757 | unsigned int freq, int dir) | 1945 | unsigned int freq, int dir) |
1758 | { | 1946 | { |
1759 | if (dai->dai_ops.set_sysclk) | 1947 | if (dai->ops.set_sysclk) |
1760 | return dai->dai_ops.set_sysclk(dai, clk_id, freq, dir); | 1948 | return dai->ops.set_sysclk(dai, clk_id, freq, dir); |
1761 | else | 1949 | else |
1762 | return -EINVAL; | 1950 | return -EINVAL; |
1763 | } | 1951 | } |
@@ -1776,8 +1964,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_sysclk); | |||
1776 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, | 1964 | int snd_soc_dai_set_clkdiv(struct snd_soc_dai *dai, |
1777 | int div_id, int div) | 1965 | int div_id, int div) |
1778 | { | 1966 | { |
1779 | if (dai->dai_ops.set_clkdiv) | 1967 | if (dai->ops.set_clkdiv) |
1780 | return dai->dai_ops.set_clkdiv(dai, div_id, div); | 1968 | return dai->ops.set_clkdiv(dai, div_id, div); |
1781 | else | 1969 | else |
1782 | return -EINVAL; | 1970 | return -EINVAL; |
1783 | } | 1971 | } |
@@ -1795,8 +1983,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_clkdiv); | |||
1795 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, | 1983 | int snd_soc_dai_set_pll(struct snd_soc_dai *dai, |
1796 | int pll_id, unsigned int freq_in, unsigned int freq_out) | 1984 | int pll_id, unsigned int freq_in, unsigned int freq_out) |
1797 | { | 1985 | { |
1798 | if (dai->dai_ops.set_pll) | 1986 | if (dai->ops.set_pll) |
1799 | return dai->dai_ops.set_pll(dai, pll_id, freq_in, freq_out); | 1987 | return dai->ops.set_pll(dai, pll_id, freq_in, freq_out); |
1800 | else | 1988 | else |
1801 | return -EINVAL; | 1989 | return -EINVAL; |
1802 | } | 1990 | } |
@@ -1805,15 +1993,14 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_pll); | |||
1805 | /** | 1993 | /** |
1806 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. | 1994 | * snd_soc_dai_set_fmt - configure DAI hardware audio format. |
1807 | * @dai: DAI | 1995 | * @dai: DAI |
1808 | * @clk_id: DAI specific clock ID | ||
1809 | * @fmt: SND_SOC_DAIFMT_ format value. | 1996 | * @fmt: SND_SOC_DAIFMT_ format value. |
1810 | * | 1997 | * |
1811 | * Configures the DAI hardware format and clocking. | 1998 | * Configures the DAI hardware format and clocking. |
1812 | */ | 1999 | */ |
1813 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) | 2000 | int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) |
1814 | { | 2001 | { |
1815 | if (dai->dai_ops.set_fmt) | 2002 | if (dai->ops.set_fmt) |
1816 | return dai->dai_ops.set_fmt(dai, fmt); | 2003 | return dai->ops.set_fmt(dai, fmt); |
1817 | else | 2004 | else |
1818 | return -EINVAL; | 2005 | return -EINVAL; |
1819 | } | 2006 | } |
@@ -1831,8 +2018,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); | |||
1831 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, | 2018 | int snd_soc_dai_set_tdm_slot(struct snd_soc_dai *dai, |
1832 | unsigned int mask, int slots) | 2019 | unsigned int mask, int slots) |
1833 | { | 2020 | { |
1834 | if (dai->dai_ops.set_sysclk) | 2021 | if (dai->ops.set_sysclk) |
1835 | return dai->dai_ops.set_tdm_slot(dai, mask, slots); | 2022 | return dai->ops.set_tdm_slot(dai, mask, slots); |
1836 | else | 2023 | else |
1837 | return -EINVAL; | 2024 | return -EINVAL; |
1838 | } | 2025 | } |
@@ -1847,8 +2034,8 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tdm_slot); | |||
1847 | */ | 2034 | */ |
1848 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) | 2035 | int snd_soc_dai_set_tristate(struct snd_soc_dai *dai, int tristate) |
1849 | { | 2036 | { |
1850 | if (dai->dai_ops.set_sysclk) | 2037 | if (dai->ops.set_sysclk) |
1851 | return dai->dai_ops.set_tristate(dai, tristate); | 2038 | return dai->ops.set_tristate(dai, tristate); |
1852 | else | 2039 | else |
1853 | return -EINVAL; | 2040 | return -EINVAL; |
1854 | } | 2041 | } |
@@ -1863,21 +2050,242 @@ EXPORT_SYMBOL_GPL(snd_soc_dai_set_tristate); | |||
1863 | */ | 2050 | */ |
1864 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) | 2051 | int snd_soc_dai_digital_mute(struct snd_soc_dai *dai, int mute) |
1865 | { | 2052 | { |
1866 | if (dai->dai_ops.digital_mute) | 2053 | if (dai->ops.digital_mute) |
1867 | return dai->dai_ops.digital_mute(dai, mute); | 2054 | return dai->ops.digital_mute(dai, mute); |
1868 | else | 2055 | else |
1869 | return -EINVAL; | 2056 | return -EINVAL; |
1870 | } | 2057 | } |
1871 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); | 2058 | EXPORT_SYMBOL_GPL(snd_soc_dai_digital_mute); |
1872 | 2059 | ||
1873 | static int __devinit snd_soc_init(void) | 2060 | /** |
2061 | * snd_soc_register_card - Register a card with the ASoC core | ||
2062 | * | ||
2063 | * @param card Card to register | ||
2064 | * | ||
2065 | * Note that currently this is an internal only function: it will be | ||
2066 | * exposed to machine drivers after further backporting of ASoC v2 | ||
2067 | * registration APIs. | ||
2068 | */ | ||
2069 | static int snd_soc_register_card(struct snd_soc_card *card) | ||
2070 | { | ||
2071 | if (!card->name || !card->dev) | ||
2072 | return -EINVAL; | ||
2073 | |||
2074 | INIT_LIST_HEAD(&card->list); | ||
2075 | card->instantiated = 0; | ||
2076 | |||
2077 | mutex_lock(&client_mutex); | ||
2078 | list_add(&card->list, &card_list); | ||
2079 | snd_soc_instantiate_cards(); | ||
2080 | mutex_unlock(&client_mutex); | ||
2081 | |||
2082 | dev_dbg(card->dev, "Registered card '%s'\n", card->name); | ||
2083 | |||
2084 | return 0; | ||
2085 | } | ||
2086 | |||
2087 | /** | ||
2088 | * snd_soc_unregister_card - Unregister a card with the ASoC core | ||
2089 | * | ||
2090 | * @param card Card to unregister | ||
2091 | * | ||
2092 | * Note that currently this is an internal only function: it will be | ||
2093 | * exposed to machine drivers after further backporting of ASoC v2 | ||
2094 | * registration APIs. | ||
2095 | */ | ||
2096 | static int snd_soc_unregister_card(struct snd_soc_card *card) | ||
2097 | { | ||
2098 | mutex_lock(&client_mutex); | ||
2099 | list_del(&card->list); | ||
2100 | mutex_unlock(&client_mutex); | ||
2101 | |||
2102 | dev_dbg(card->dev, "Unregistered card '%s'\n", card->name); | ||
2103 | |||
2104 | return 0; | ||
2105 | } | ||
2106 | |||
2107 | /** | ||
2108 | * snd_soc_register_dai - Register a DAI with the ASoC core | ||
2109 | * | ||
2110 | * @param dai DAI to register | ||
2111 | */ | ||
2112 | int snd_soc_register_dai(struct snd_soc_dai *dai) | ||
2113 | { | ||
2114 | if (!dai->name) | ||
2115 | return -EINVAL; | ||
2116 | |||
2117 | /* The device should become mandatory over time */ | ||
2118 | if (!dai->dev) | ||
2119 | printk(KERN_WARNING "No device for DAI %s\n", dai->name); | ||
2120 | |||
2121 | INIT_LIST_HEAD(&dai->list); | ||
2122 | |||
2123 | mutex_lock(&client_mutex); | ||
2124 | list_add(&dai->list, &dai_list); | ||
2125 | snd_soc_instantiate_cards(); | ||
2126 | mutex_unlock(&client_mutex); | ||
2127 | |||
2128 | pr_debug("Registered DAI '%s'\n", dai->name); | ||
2129 | |||
2130 | return 0; | ||
2131 | } | ||
2132 | EXPORT_SYMBOL_GPL(snd_soc_register_dai); | ||
2133 | |||
2134 | /** | ||
2135 | * snd_soc_unregister_dai - Unregister a DAI from the ASoC core | ||
2136 | * | ||
2137 | * @param dai DAI to unregister | ||
2138 | */ | ||
2139 | void snd_soc_unregister_dai(struct snd_soc_dai *dai) | ||
2140 | { | ||
2141 | mutex_lock(&client_mutex); | ||
2142 | list_del(&dai->list); | ||
2143 | mutex_unlock(&client_mutex); | ||
2144 | |||
2145 | pr_debug("Unregistered DAI '%s'\n", dai->name); | ||
2146 | } | ||
2147 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dai); | ||
2148 | |||
2149 | /** | ||
2150 | * snd_soc_register_dais - Register multiple DAIs with the ASoC core | ||
2151 | * | ||
2152 | * @param dai Array of DAIs to register | ||
2153 | * @param count Number of DAIs | ||
2154 | */ | ||
2155 | int snd_soc_register_dais(struct snd_soc_dai *dai, size_t count) | ||
2156 | { | ||
2157 | int i, ret; | ||
2158 | |||
2159 | for (i = 0; i < count; i++) { | ||
2160 | ret = snd_soc_register_dai(&dai[i]); | ||
2161 | if (ret != 0) | ||
2162 | goto err; | ||
2163 | } | ||
2164 | |||
2165 | return 0; | ||
2166 | |||
2167 | err: | ||
2168 | for (i--; i >= 0; i--) | ||
2169 | snd_soc_unregister_dai(&dai[i]); | ||
2170 | |||
2171 | return ret; | ||
2172 | } | ||
2173 | EXPORT_SYMBOL_GPL(snd_soc_register_dais); | ||
2174 | |||
2175 | /** | ||
2176 | * snd_soc_unregister_dais - Unregister multiple DAIs from the ASoC core | ||
2177 | * | ||
2178 | * @param dai Array of DAIs to unregister | ||
2179 | * @param count Number of DAIs | ||
2180 | */ | ||
2181 | void snd_soc_unregister_dais(struct snd_soc_dai *dai, size_t count) | ||
2182 | { | ||
2183 | int i; | ||
2184 | |||
2185 | for (i = 0; i < count; i++) | ||
2186 | snd_soc_unregister_dai(&dai[i]); | ||
2187 | } | ||
2188 | EXPORT_SYMBOL_GPL(snd_soc_unregister_dais); | ||
2189 | |||
2190 | /** | ||
2191 | * snd_soc_register_platform - Register a platform with the ASoC core | ||
2192 | * | ||
2193 | * @param platform platform to register | ||
2194 | */ | ||
2195 | int snd_soc_register_platform(struct snd_soc_platform *platform) | ||
2196 | { | ||
2197 | if (!platform->name) | ||
2198 | return -EINVAL; | ||
2199 | |||
2200 | INIT_LIST_HEAD(&platform->list); | ||
2201 | |||
2202 | mutex_lock(&client_mutex); | ||
2203 | list_add(&platform->list, &platform_list); | ||
2204 | snd_soc_instantiate_cards(); | ||
2205 | mutex_unlock(&client_mutex); | ||
2206 | |||
2207 | pr_debug("Registered platform '%s'\n", platform->name); | ||
2208 | |||
2209 | return 0; | ||
2210 | } | ||
2211 | EXPORT_SYMBOL_GPL(snd_soc_register_platform); | ||
2212 | |||
2213 | /** | ||
2214 | * snd_soc_unregister_platform - Unregister a platform from the ASoC core | ||
2215 | * | ||
2216 | * @param platform platform to unregister | ||
2217 | */ | ||
2218 | void snd_soc_unregister_platform(struct snd_soc_platform *platform) | ||
1874 | { | 2219 | { |
1875 | printk(KERN_INFO "ASoC version %s\n", SND_SOC_VERSION); | 2220 | mutex_lock(&client_mutex); |
2221 | list_del(&platform->list); | ||
2222 | mutex_unlock(&client_mutex); | ||
2223 | |||
2224 | pr_debug("Unregistered platform '%s'\n", platform->name); | ||
2225 | } | ||
2226 | EXPORT_SYMBOL_GPL(snd_soc_unregister_platform); | ||
2227 | |||
2228 | /** | ||
2229 | * snd_soc_register_codec - Register a codec with the ASoC core | ||
2230 | * | ||
2231 | * @param codec codec to register | ||
2232 | */ | ||
2233 | int snd_soc_register_codec(struct snd_soc_codec *codec) | ||
2234 | { | ||
2235 | if (!codec->name) | ||
2236 | return -EINVAL; | ||
2237 | |||
2238 | /* The device should become mandatory over time */ | ||
2239 | if (!codec->dev) | ||
2240 | printk(KERN_WARNING "No device for codec %s\n", codec->name); | ||
2241 | |||
2242 | INIT_LIST_HEAD(&codec->list); | ||
2243 | |||
2244 | mutex_lock(&client_mutex); | ||
2245 | list_add(&codec->list, &codec_list); | ||
2246 | snd_soc_instantiate_cards(); | ||
2247 | mutex_unlock(&client_mutex); | ||
2248 | |||
2249 | pr_debug("Registered codec '%s'\n", codec->name); | ||
2250 | |||
2251 | return 0; | ||
2252 | } | ||
2253 | EXPORT_SYMBOL_GPL(snd_soc_register_codec); | ||
2254 | |||
2255 | /** | ||
2256 | * snd_soc_unregister_codec - Unregister a codec from the ASoC core | ||
2257 | * | ||
2258 | * @param codec codec to unregister | ||
2259 | */ | ||
2260 | void snd_soc_unregister_codec(struct snd_soc_codec *codec) | ||
2261 | { | ||
2262 | mutex_lock(&client_mutex); | ||
2263 | list_del(&codec->list); | ||
2264 | mutex_unlock(&client_mutex); | ||
2265 | |||
2266 | pr_debug("Unregistered codec '%s'\n", codec->name); | ||
2267 | } | ||
2268 | EXPORT_SYMBOL_GPL(snd_soc_unregister_codec); | ||
2269 | |||
2270 | static int __init snd_soc_init(void) | ||
2271 | { | ||
2272 | #ifdef CONFIG_DEBUG_FS | ||
2273 | debugfs_root = debugfs_create_dir("asoc", NULL); | ||
2274 | if (IS_ERR(debugfs_root) || !debugfs_root) { | ||
2275 | printk(KERN_WARNING | ||
2276 | "ASoC: Failed to create debugfs directory\n"); | ||
2277 | debugfs_root = NULL; | ||
2278 | } | ||
2279 | #endif | ||
2280 | |||
1876 | return platform_driver_register(&soc_driver); | 2281 | return platform_driver_register(&soc_driver); |
1877 | } | 2282 | } |
1878 | 2283 | ||
1879 | static void snd_soc_exit(void) | 2284 | static void __exit snd_soc_exit(void) |
1880 | { | 2285 | { |
2286 | #ifdef CONFIG_DEBUG_FS | ||
2287 | debugfs_remove_recursive(debugfs_root); | ||
2288 | #endif | ||
1881 | platform_driver_unregister(&soc_driver); | 2289 | platform_driver_unregister(&soc_driver); |
1882 | } | 2290 | } |
1883 | 2291 | ||