diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 63 |
1 files changed, 52 insertions, 11 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0a6440c6f54a..c8b0556ef431 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -130,6 +130,29 @@ static ssize_t codec_reg_show(struct device *dev, | |||
130 | 130 | ||
131 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); | 131 | static DEVICE_ATTR(codec_reg, 0444, codec_reg_show, NULL); |
132 | 132 | ||
133 | static ssize_t pmdown_time_show(struct device *dev, | ||
134 | struct device_attribute *attr, char *buf) | ||
135 | { | ||
136 | struct snd_soc_device *socdev = dev_get_drvdata(dev); | ||
137 | struct snd_soc_card *card = socdev->card; | ||
138 | |||
139 | return sprintf(buf, "%ld\n", card->pmdown_time); | ||
140 | } | ||
141 | |||
142 | static ssize_t pmdown_time_set(struct device *dev, | ||
143 | struct device_attribute *attr, | ||
144 | const char *buf, size_t count) | ||
145 | { | ||
146 | struct snd_soc_device *socdev = dev_get_drvdata(dev); | ||
147 | struct snd_soc_card *card = socdev->card; | ||
148 | |||
149 | strict_strtol(buf, 10, &card->pmdown_time); | ||
150 | |||
151 | return count; | ||
152 | } | ||
153 | |||
154 | static DEVICE_ATTR(pmdown_time, 0644, pmdown_time_show, pmdown_time_set); | ||
155 | |||
133 | #ifdef CONFIG_DEBUG_FS | 156 | #ifdef CONFIG_DEBUG_FS |
134 | static int codec_reg_open_file(struct inode *inode, struct file *file) | 157 | static int codec_reg_open_file(struct inode *inode, struct file *file) |
135 | { | 158 | { |
@@ -404,24 +427,24 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
404 | if (!runtime->hw.rates) { | 427 | if (!runtime->hw.rates) { |
405 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", | 428 | printk(KERN_ERR "asoc: %s <-> %s No matching rates\n", |
406 | codec_dai->name, cpu_dai->name); | 429 | codec_dai->name, cpu_dai->name); |
407 | goto machine_err; | 430 | goto config_err; |
408 | } | 431 | } |
409 | if (!runtime->hw.formats) { | 432 | if (!runtime->hw.formats) { |
410 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", | 433 | printk(KERN_ERR "asoc: %s <-> %s No matching formats\n", |
411 | codec_dai->name, cpu_dai->name); | 434 | codec_dai->name, cpu_dai->name); |
412 | goto machine_err; | 435 | goto config_err; |
413 | } | 436 | } |
414 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { | 437 | if (!runtime->hw.channels_min || !runtime->hw.channels_max) { |
415 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", | 438 | printk(KERN_ERR "asoc: %s <-> %s No matching channels\n", |
416 | codec_dai->name, cpu_dai->name); | 439 | codec_dai->name, cpu_dai->name); |
417 | goto machine_err; | 440 | goto config_err; |
418 | } | 441 | } |
419 | 442 | ||
420 | /* Symmetry only applies if we've already got an active stream. */ | 443 | /* Symmetry only applies if we've already got an active stream. */ |
421 | if (cpu_dai->active || codec_dai->active) { | 444 | if (cpu_dai->active || codec_dai->active) { |
422 | ret = soc_pcm_apply_symmetry(substream); | 445 | ret = soc_pcm_apply_symmetry(substream); |
423 | if (ret != 0) | 446 | if (ret != 0) |
424 | goto machine_err; | 447 | goto config_err; |
425 | } | 448 | } |
426 | 449 | ||
427 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); | 450 | pr_debug("asoc: %s <-> %s info:\n", codec_dai->name, cpu_dai->name); |
@@ -441,10 +464,14 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
441 | mutex_unlock(&pcm_mutex); | 464 | mutex_unlock(&pcm_mutex); |
442 | return 0; | 465 | return 0; |
443 | 466 | ||
444 | machine_err: | 467 | config_err: |
445 | if (machine->ops && machine->ops->shutdown) | 468 | if (machine->ops && machine->ops->shutdown) |
446 | machine->ops->shutdown(substream); | 469 | machine->ops->shutdown(substream); |
447 | 470 | ||
471 | machine_err: | ||
472 | if (codec_dai->ops->shutdown) | ||
473 | codec_dai->ops->shutdown(substream, codec_dai); | ||
474 | |||
448 | codec_dai_err: | 475 | codec_dai_err: |
449 | if (platform->pcm_ops->close) | 476 | if (platform->pcm_ops->close) |
450 | platform->pcm_ops->close(substream); | 477 | platform->pcm_ops->close(substream); |
@@ -542,7 +569,7 @@ static int soc_codec_close(struct snd_pcm_substream *substream) | |||
542 | /* start delayed pop wq here for playback streams */ | 569 | /* start delayed pop wq here for playback streams */ |
543 | codec_dai->pop_wait = 1; | 570 | codec_dai->pop_wait = 1; |
544 | schedule_delayed_work(&card->delayed_work, | 571 | schedule_delayed_work(&card->delayed_work, |
545 | msecs_to_jiffies(pmdown_time)); | 572 | msecs_to_jiffies(card->pmdown_time)); |
546 | } else { | 573 | } else { |
547 | /* capture streams can be powered down now */ | 574 | /* capture streams can be powered down now */ |
548 | snd_soc_dapm_stream_event(codec, | 575 | snd_soc_dapm_stream_event(codec, |
@@ -940,6 +967,12 @@ static int soc_resume(struct device *dev) | |||
940 | struct snd_soc_card *card = socdev->card; | 967 | struct snd_soc_card *card = socdev->card; |
941 | struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; | 968 | struct snd_soc_dai *cpu_dai = card->dai_link[0].cpu_dai; |
942 | 969 | ||
970 | /* If the initialization of this soc device failed, there is no codec | ||
971 | * associated with it. Just bail out in this case. | ||
972 | */ | ||
973 | if (!card->codec) | ||
974 | return 0; | ||
975 | |||
943 | /* AC97 devices might have other drivers hanging off them so | 976 | /* AC97 devices might have other drivers hanging off them so |
944 | * need to resume immediately. Other drivers don't have that | 977 | * need to resume immediately. Other drivers don't have that |
945 | * problem and may take a substantial amount of time to resume | 978 | * problem and may take a substantial amount of time to resume |
@@ -1039,6 +1072,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1039 | dev_dbg(card->dev, "All components present, instantiating\n"); | 1072 | dev_dbg(card->dev, "All components present, instantiating\n"); |
1040 | 1073 | ||
1041 | /* Found everything, bring it up */ | 1074 | /* Found everything, bring it up */ |
1075 | card->pmdown_time = pmdown_time; | ||
1076 | |||
1042 | if (card->probe) { | 1077 | if (card->probe) { |
1043 | ret = card->probe(pdev); | 1078 | ret = card->probe(pdev); |
1044 | if (ret < 0) | 1079 | if (ret < 0) |
@@ -1122,6 +1157,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1122 | if (ret < 0) | 1157 | if (ret < 0) |
1123 | printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); | 1158 | printk(KERN_WARNING "asoc: failed to add dapm sysfs entries\n"); |
1124 | 1159 | ||
1160 | ret = device_create_file(card->socdev->dev, &dev_attr_pmdown_time); | ||
1161 | if (ret < 0) | ||
1162 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | ||
1163 | |||
1125 | ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); | 1164 | ret = device_create_file(card->socdev->dev, &dev_attr_codec_reg); |
1126 | if (ret < 0) | 1165 | if (ret < 0) |
1127 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | 1166 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); |
@@ -1276,8 +1315,8 @@ static int soc_new_pcm(struct snd_soc_device *socdev, | |||
1276 | codec_dai->codec = card->codec; | 1315 | codec_dai->codec = card->codec; |
1277 | 1316 | ||
1278 | /* check client and interface hw capabilities */ | 1317 | /* check client and interface hw capabilities */ |
1279 | sprintf(new_name, "%s %s-%d", dai_link->stream_name, codec_dai->name, | 1318 | snprintf(new_name, sizeof(new_name), "%s %s-%d", |
1280 | num); | 1319 | dai_link->stream_name, codec_dai->name, num); |
1281 | 1320 | ||
1282 | if (codec_dai->playback.channels_min) | 1321 | if (codec_dai->playback.channels_min) |
1283 | playback = 1; | 1322 | playback = 1; |
@@ -1368,6 +1407,7 @@ int snd_soc_new_ac97_codec(struct snd_soc_codec *codec, | |||
1368 | 1407 | ||
1369 | codec->ac97->bus->ops = ops; | 1408 | codec->ac97->bus->ops = ops; |
1370 | codec->ac97->num = num; | 1409 | codec->ac97->num = num; |
1410 | codec->dev = &codec->ac97->dev; | ||
1371 | mutex_unlock(&codec->mutex); | 1411 | mutex_unlock(&codec->mutex); |
1372 | return 0; | 1412 | return 0; |
1373 | } | 1413 | } |
@@ -1427,9 +1467,9 @@ EXPORT_SYMBOL_GPL(snd_soc_update_bits); | |||
1427 | * | 1467 | * |
1428 | * Returns 1 for change else 0. | 1468 | * Returns 1 for change else 0. |
1429 | */ | 1469 | */ |
1430 | static int snd_soc_update_bits_locked(struct snd_soc_codec *codec, | 1470 | int snd_soc_update_bits_locked(struct snd_soc_codec *codec, |
1431 | unsigned short reg, unsigned int mask, | 1471 | unsigned short reg, unsigned int mask, |
1432 | unsigned int value) | 1472 | unsigned int value) |
1433 | { | 1473 | { |
1434 | int change; | 1474 | int change; |
1435 | 1475 | ||
@@ -1439,6 +1479,7 @@ static int snd_soc_update_bits_locked(struct snd_soc_codec *codec, | |||
1439 | 1479 | ||
1440 | return change; | 1480 | return change; |
1441 | } | 1481 | } |
1482 | EXPORT_SYMBOL_GPL(snd_soc_update_bits_locked); | ||
1442 | 1483 | ||
1443 | /** | 1484 | /** |
1444 | * snd_soc_test_bits - test register for change | 1485 | * snd_soc_test_bits - test register for change |