diff options
Diffstat (limited to 'sound/soc/soc-core.c')
-rw-r--r-- | sound/soc/soc-core.c | 575 |
1 files changed, 419 insertions, 156 deletions
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 85b7d548f16..bac7291b6ff 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -33,12 +33,15 @@ | |||
33 | #include <linux/slab.h> | 33 | #include <linux/slab.h> |
34 | #include <sound/ac97_codec.h> | 34 | #include <sound/ac97_codec.h> |
35 | #include <sound/core.h> | 35 | #include <sound/core.h> |
36 | #include <sound/jack.h> | ||
36 | #include <sound/pcm.h> | 37 | #include <sound/pcm.h> |
37 | #include <sound/pcm_params.h> | 38 | #include <sound/pcm_params.h> |
38 | #include <sound/soc.h> | 39 | #include <sound/soc.h> |
39 | #include <sound/soc-dapm.h> | ||
40 | #include <sound/initval.h> | 40 | #include <sound/initval.h> |
41 | 41 | ||
42 | #define CREATE_TRACE_POINTS | ||
43 | #include <trace/events/asoc.h> | ||
44 | |||
42 | #define NAME_SIZE 32 | 45 | #define NAME_SIZE 32 |
43 | 46 | ||
44 | static DEFINE_MUTEX(pcm_mutex); | 47 | static DEFINE_MUTEX(pcm_mutex); |
@@ -67,25 +70,6 @@ static int pmdown_time = 5000; | |||
67 | module_param(pmdown_time, int, 0); | 70 | module_param(pmdown_time, int, 0); |
68 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); | 71 | MODULE_PARM_DESC(pmdown_time, "DAPM stream powerdown time (msecs)"); |
69 | 72 | ||
70 | /* | ||
71 | * This function forces any delayed work to be queued and run. | ||
72 | */ | ||
73 | static int run_delayed_work(struct delayed_work *dwork) | ||
74 | { | ||
75 | int ret; | ||
76 | |||
77 | /* cancel any work waiting to be queued. */ | ||
78 | ret = cancel_delayed_work(dwork); | ||
79 | |||
80 | /* if there was any work waiting then we run it now and | ||
81 | * wait for it's completion */ | ||
82 | if (ret) { | ||
83 | schedule_delayed_work(dwork, 0); | ||
84 | flush_scheduled_work(); | ||
85 | } | ||
86 | return ret; | ||
87 | } | ||
88 | |||
89 | /* codec register dump */ | 73 | /* codec register dump */ |
90 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | 74 | static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) |
91 | { | 75 | { |
@@ -114,7 +98,7 @@ static ssize_t soc_codec_reg_show(struct snd_soc_codec *codec, char *buf) | |||
114 | * the register being volatile and the device being | 98 | * the register being volatile and the device being |
115 | * powered off. | 99 | * powered off. |
116 | */ | 100 | */ |
117 | ret = codec->driver->read(codec, i); | 101 | ret = snd_soc_read(codec, i); |
118 | if (ret >= 0) | 102 | if (ret >= 0) |
119 | count += snprintf(buf + count, | 103 | count += snprintf(buf + count, |
120 | PAGE_SIZE - count, | 104 | PAGE_SIZE - count, |
@@ -225,7 +209,7 @@ static ssize_t codec_reg_write_file(struct file *file, | |||
225 | start++; | 209 | start++; |
226 | if (strict_strtoul(start, 16, &value)) | 210 | if (strict_strtoul(start, 16, &value)) |
227 | return -EINVAL; | 211 | return -EINVAL; |
228 | codec->driver->write(codec, reg, value); | 212 | snd_soc_write(codec, reg, value); |
229 | return buf_size; | 213 | return buf_size; |
230 | } | 214 | } |
231 | 215 | ||
@@ -238,8 +222,10 @@ static const struct file_operations codec_reg_fops = { | |||
238 | 222 | ||
239 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 223 | static void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
240 | { | 224 | { |
241 | codec->debugfs_codec_root = debugfs_create_dir(codec->name , | 225 | struct dentry *debugfs_card_root = codec->card->debugfs_card_root; |
242 | debugfs_root); | 226 | |
227 | codec->debugfs_codec_root = debugfs_create_dir(codec->name, | ||
228 | debugfs_card_root); | ||
243 | if (!codec->debugfs_codec_root) { | 229 | if (!codec->debugfs_codec_root) { |
244 | printk(KERN_WARNING | 230 | printk(KERN_WARNING |
245 | "ASoC: Failed to create codec debugfs directory\n"); | 231 | "ASoC: Failed to create codec debugfs directory\n"); |
@@ -253,20 +239,13 @@ static void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
253 | printk(KERN_WARNING | 239 | printk(KERN_WARNING |
254 | "ASoC: Failed to create codec register debugfs file\n"); | 240 | "ASoC: Failed to create codec register debugfs file\n"); |
255 | 241 | ||
256 | codec->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, | 242 | codec->dapm.debugfs_dapm = debugfs_create_dir("dapm", |
257 | codec->debugfs_codec_root, | ||
258 | &codec->pop_time); | ||
259 | if (!codec->debugfs_pop_time) | ||
260 | printk(KERN_WARNING | ||
261 | "Failed to create pop time debugfs file\n"); | ||
262 | |||
263 | codec->debugfs_dapm = debugfs_create_dir("dapm", | ||
264 | codec->debugfs_codec_root); | 243 | codec->debugfs_codec_root); |
265 | if (!codec->debugfs_dapm) | 244 | if (!codec->dapm.debugfs_dapm) |
266 | printk(KERN_WARNING | 245 | printk(KERN_WARNING |
267 | "Failed to create DAPM debugfs directory\n"); | 246 | "Failed to create DAPM debugfs directory\n"); |
268 | 247 | ||
269 | snd_soc_dapm_debugfs_init(codec); | 248 | snd_soc_dapm_debugfs_init(&codec->dapm); |
270 | } | 249 | } |
271 | 250 | ||
272 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 251 | static void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) |
@@ -374,6 +353,29 @@ static const struct file_operations platform_list_fops = { | |||
374 | .llseek = default_llseek,/* read accesses f_pos */ | 353 | .llseek = default_llseek,/* read accesses f_pos */ |
375 | }; | 354 | }; |
376 | 355 | ||
356 | static void soc_init_card_debugfs(struct snd_soc_card *card) | ||
357 | { | ||
358 | card->debugfs_card_root = debugfs_create_dir(card->name, | ||
359 | debugfs_root); | ||
360 | if (!card->debugfs_card_root) { | ||
361 | dev_warn(card->dev, | ||
362 | "ASoC: Failed to create codec debugfs directory\n"); | ||
363 | return; | ||
364 | } | ||
365 | |||
366 | card->debugfs_pop_time = debugfs_create_u32("dapm_pop_time", 0644, | ||
367 | card->debugfs_card_root, | ||
368 | &card->pop_time); | ||
369 | if (!card->debugfs_pop_time) | ||
370 | dev_warn(card->dev, | ||
371 | "Failed to create pop time debugfs file\n"); | ||
372 | } | ||
373 | |||
374 | static void soc_cleanup_card_debugfs(struct snd_soc_card *card) | ||
375 | { | ||
376 | debugfs_remove_recursive(card->debugfs_card_root); | ||
377 | } | ||
378 | |||
377 | #else | 379 | #else |
378 | 380 | ||
379 | static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | 381 | static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) |
@@ -383,6 +385,14 @@ static inline void soc_init_codec_debugfs(struct snd_soc_codec *codec) | |||
383 | static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) | 385 | static inline void soc_cleanup_codec_debugfs(struct snd_soc_codec *codec) |
384 | { | 386 | { |
385 | } | 387 | } |
388 | |||
389 | static inline void soc_init_card_debugfs(struct snd_soc_card *card) | ||
390 | { | ||
391 | } | ||
392 | |||
393 | static inline void soc_cleanup_card_debugfs(struct snd_soc_card *card) | ||
394 | { | ||
395 | } | ||
386 | #endif | 396 | #endif |
387 | 397 | ||
388 | #ifdef CONFIG_SND_SOC_AC97_BUS | 398 | #ifdef CONFIG_SND_SOC_AC97_BUS |
@@ -497,7 +507,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) | |||
497 | } | 507 | } |
498 | } | 508 | } |
499 | 509 | ||
500 | /* Check that the codec and cpu DAI's are compatible */ | 510 | /* Check that the codec and cpu DAIs are compatible */ |
501 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { | 511 | if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { |
502 | runtime->hw.rate_min = | 512 | runtime->hw.rate_min = |
503 | max(codec_dai_drv->playback.rate_min, | 513 | max(codec_dai_drv->playback.rate_min, |
@@ -846,7 +856,7 @@ codec_err: | |||
846 | } | 856 | } |
847 | 857 | ||
848 | /* | 858 | /* |
849 | * Free's resources allocated by hw_params, can be called multiple times | 859 | * Frees resources allocated by hw_params, can be called multiple times |
850 | */ | 860 | */ |
851 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | 861 | static int soc_pcm_hw_free(struct snd_pcm_substream *substream) |
852 | { | 862 | { |
@@ -870,7 +880,7 @@ static int soc_pcm_hw_free(struct snd_pcm_substream *substream) | |||
870 | if (platform->driver->ops->hw_free) | 880 | if (platform->driver->ops->hw_free) |
871 | platform->driver->ops->hw_free(substream); | 881 | platform->driver->ops->hw_free(substream); |
872 | 882 | ||
873 | /* now free hw params for the DAI's */ | 883 | /* now free hw params for the DAIs */ |
874 | if (codec_dai->driver->ops->hw_free) | 884 | if (codec_dai->driver->ops->hw_free) |
875 | codec_dai->driver->ops->hw_free(substream, codec_dai); | 885 | codec_dai->driver->ops->hw_free(substream, codec_dai); |
876 | 886 | ||
@@ -958,6 +968,7 @@ static int soc_suspend(struct device *dev) | |||
958 | { | 968 | { |
959 | struct platform_device *pdev = to_platform_device(dev); | 969 | struct platform_device *pdev = to_platform_device(dev); |
960 | struct snd_soc_card *card = platform_get_drvdata(pdev); | 970 | struct snd_soc_card *card = platform_get_drvdata(pdev); |
971 | struct snd_soc_codec *codec; | ||
961 | int i; | 972 | int i; |
962 | 973 | ||
963 | /* If the initialization of this soc device failed, there is no codec | 974 | /* If the initialization of this soc device failed, there is no codec |
@@ -976,7 +987,7 @@ static int soc_suspend(struct device *dev) | |||
976 | /* we're going to block userspace touching us until resume completes */ | 987 | /* we're going to block userspace touching us until resume completes */ |
977 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); | 988 | snd_power_change_state(card->snd_card, SNDRV_CTL_POWER_D3hot); |
978 | 989 | ||
979 | /* mute any active DAC's */ | 990 | /* mute any active DACs */ |
980 | for (i = 0; i < card->num_rtd; i++) { | 991 | for (i = 0; i < card->num_rtd; i++) { |
981 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; | 992 | struct snd_soc_dai *dai = card->rtd[i].codec_dai; |
982 | struct snd_soc_dai_driver *drv = dai->driver; | 993 | struct snd_soc_dai_driver *drv = dai->driver; |
@@ -1016,8 +1027,8 @@ static int soc_suspend(struct device *dev) | |||
1016 | 1027 | ||
1017 | /* close any waiting streams and save state */ | 1028 | /* close any waiting streams and save state */ |
1018 | for (i = 0; i < card->num_rtd; i++) { | 1029 | for (i = 0; i < card->num_rtd; i++) { |
1019 | run_delayed_work(&card->rtd[i].delayed_work); | 1030 | flush_delayed_work_sync(&card->rtd[i].delayed_work); |
1020 | card->rtd[i].codec->suspend_bias_level = card->rtd[i].codec->bias_level; | 1031 | card->rtd[i].codec->dapm.suspend_bias_level = card->rtd[i].codec->dapm.bias_level; |
1021 | } | 1032 | } |
1022 | 1033 | ||
1023 | for (i = 0; i < card->num_rtd; i++) { | 1034 | for (i = 0; i < card->num_rtd; i++) { |
@@ -1036,12 +1047,11 @@ static int soc_suspend(struct device *dev) | |||
1036 | } | 1047 | } |
1037 | 1048 | ||
1038 | /* suspend all CODECs */ | 1049 | /* suspend all CODECs */ |
1039 | for (i = 0; i < card->num_rtd; i++) { | 1050 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
1040 | struct snd_soc_codec *codec = card->rtd[i].codec; | ||
1041 | /* If there are paths active then the CODEC will be held with | 1051 | /* If there are paths active then the CODEC will be held with |
1042 | * bias _ON and should not be suspended. */ | 1052 | * bias _ON and should not be suspended. */ |
1043 | if (!codec->suspended && codec->driver->suspend) { | 1053 | if (!codec->suspended && codec->driver->suspend) { |
1044 | switch (codec->bias_level) { | 1054 | switch (codec->dapm.bias_level) { |
1045 | case SND_SOC_BIAS_STANDBY: | 1055 | case SND_SOC_BIAS_STANDBY: |
1046 | case SND_SOC_BIAS_OFF: | 1056 | case SND_SOC_BIAS_OFF: |
1047 | codec->driver->suspend(codec, PMSG_SUSPEND); | 1057 | codec->driver->suspend(codec, PMSG_SUSPEND); |
@@ -1078,6 +1088,7 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1078 | struct snd_soc_card *card = | 1088 | struct snd_soc_card *card = |
1079 | container_of(work, struct snd_soc_card, deferred_resume_work); | 1089 | container_of(work, struct snd_soc_card, deferred_resume_work); |
1080 | struct platform_device *pdev = to_platform_device(card->dev); | 1090 | struct platform_device *pdev = to_platform_device(card->dev); |
1091 | struct snd_soc_codec *codec; | ||
1081 | int i; | 1092 | int i; |
1082 | 1093 | ||
1083 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, | 1094 | /* our power state is still SNDRV_CTL_POWER_D3hot from suspend time, |
@@ -1103,14 +1114,13 @@ static void soc_resume_deferred(struct work_struct *work) | |||
1103 | cpu_dai->driver->resume(cpu_dai); | 1114 | cpu_dai->driver->resume(cpu_dai); |
1104 | } | 1115 | } |
1105 | 1116 | ||
1106 | for (i = 0; i < card->num_rtd; i++) { | 1117 | list_for_each_entry(codec, &card->codec_dev_list, card_list) { |
1107 | struct snd_soc_codec *codec = card->rtd[i].codec; | ||
1108 | /* If the CODEC was idle over suspend then it will have been | 1118 | /* If the CODEC was idle over suspend then it will have been |
1109 | * left with bias OFF or STANDBY and suspended so we must now | 1119 | * left with bias OFF or STANDBY and suspended so we must now |
1110 | * resume. Otherwise the suspend was suppressed. | 1120 | * resume. Otherwise the suspend was suppressed. |
1111 | */ | 1121 | */ |
1112 | if (codec->driver->resume && codec->suspended) { | 1122 | if (codec->driver->resume && codec->suspended) { |
1113 | switch (codec->bias_level) { | 1123 | switch (codec->dapm.bias_level) { |
1114 | case SND_SOC_BIAS_STANDBY: | 1124 | case SND_SOC_BIAS_STANDBY: |
1115 | case SND_SOC_BIAS_OFF: | 1125 | case SND_SOC_BIAS_OFF: |
1116 | codec->driver->resume(codec); | 1126 | codec->driver->resume(codec); |
@@ -1249,9 +1259,6 @@ find_codec: | |||
1249 | if (!strcmp(codec->name, dai_link->codec_name)) { | 1259 | if (!strcmp(codec->name, dai_link->codec_name)) { |
1250 | rtd->codec = codec; | 1260 | rtd->codec = codec; |
1251 | 1261 | ||
1252 | if (!try_module_get(codec->dev->driver->owner)) | ||
1253 | return -ENODEV; | ||
1254 | |||
1255 | /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ | 1262 | /* CODEC found, so find CODEC DAI from registered DAIs from this CODEC*/ |
1256 | list_for_each_entry(codec_dai, &dai_list, list) { | 1263 | list_for_each_entry(codec_dai, &dai_list, list) { |
1257 | if (codec->dev == codec_dai->dev && | 1264 | if (codec->dev == codec_dai->dev && |
@@ -1277,10 +1284,6 @@ find_platform: | |||
1277 | /* no, then find CPU DAI from registered DAIs*/ | 1284 | /* no, then find CPU DAI from registered DAIs*/ |
1278 | list_for_each_entry(platform, &platform_list, list) { | 1285 | list_for_each_entry(platform, &platform_list, list) { |
1279 | if (!strcmp(platform->name, dai_link->platform_name)) { | 1286 | if (!strcmp(platform->name, dai_link->platform_name)) { |
1280 | |||
1281 | if (!try_module_get(platform->dev->driver->owner)) | ||
1282 | return -ENODEV; | ||
1283 | |||
1284 | rtd->platform = platform; | 1287 | rtd->platform = platform; |
1285 | goto out; | 1288 | goto out; |
1286 | } | 1289 | } |
@@ -1299,6 +1302,27 @@ out: | |||
1299 | return 1; | 1302 | return 1; |
1300 | } | 1303 | } |
1301 | 1304 | ||
1305 | static void soc_remove_codec(struct snd_soc_codec *codec) | ||
1306 | { | ||
1307 | int err; | ||
1308 | |||
1309 | if (codec->driver->remove) { | ||
1310 | err = codec->driver->remove(codec); | ||
1311 | if (err < 0) | ||
1312 | dev_err(codec->dev, | ||
1313 | "asoc: failed to remove %s: %d\n", | ||
1314 | codec->name, err); | ||
1315 | } | ||
1316 | |||
1317 | /* Make sure all DAPM widgets are freed */ | ||
1318 | snd_soc_dapm_free(&codec->dapm); | ||
1319 | |||
1320 | soc_cleanup_codec_debugfs(codec); | ||
1321 | codec->probed = 0; | ||
1322 | list_del(&codec->card_list); | ||
1323 | module_put(codec->dev->driver->owner); | ||
1324 | } | ||
1325 | |||
1302 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) | 1326 | static void soc_remove_dai_link(struct snd_soc_card *card, int num) |
1303 | { | 1327 | { |
1304 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1328 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
@@ -1310,6 +1334,7 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1310 | /* unregister the rtd device */ | 1334 | /* unregister the rtd device */ |
1311 | if (rtd->dev_registered) { | 1335 | if (rtd->dev_registered) { |
1312 | device_remove_file(&rtd->dev, &dev_attr_pmdown_time); | 1336 | device_remove_file(&rtd->dev, &dev_attr_pmdown_time); |
1337 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1313 | device_unregister(&rtd->dev); | 1338 | device_unregister(&rtd->dev); |
1314 | rtd->dev_registered = 0; | 1339 | rtd->dev_registered = 0; |
1315 | } | 1340 | } |
@@ -1338,22 +1363,8 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1338 | } | 1363 | } |
1339 | 1364 | ||
1340 | /* remove the CODEC */ | 1365 | /* remove the CODEC */ |
1341 | if (codec && codec->probed) { | 1366 | if (codec && codec->probed) |
1342 | if (codec->driver->remove) { | 1367 | soc_remove_codec(codec); |
1343 | err = codec->driver->remove(codec); | ||
1344 | if (err < 0) | ||
1345 | printk(KERN_ERR "asoc: failed to remove %s\n", codec->name); | ||
1346 | } | ||
1347 | |||
1348 | /* Make sure all DAPM widgets are freed */ | ||
1349 | snd_soc_dapm_free(codec); | ||
1350 | |||
1351 | soc_cleanup_codec_debugfs(codec); | ||
1352 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1353 | codec->probed = 0; | ||
1354 | list_del(&codec->card_list); | ||
1355 | module_put(codec->dev->driver->owner); | ||
1356 | } | ||
1357 | 1368 | ||
1358 | /* remove the cpu_dai */ | 1369 | /* remove the cpu_dai */ |
1359 | if (cpu_dai && cpu_dai->probed) { | 1370 | if (cpu_dai && cpu_dai->probed) { |
@@ -1368,8 +1379,126 @@ static void soc_remove_dai_link(struct snd_soc_card *card, int num) | |||
1368 | } | 1379 | } |
1369 | } | 1380 | } |
1370 | 1381 | ||
1382 | static void soc_set_name_prefix(struct snd_soc_card *card, | ||
1383 | struct snd_soc_codec *codec) | ||
1384 | { | ||
1385 | int i; | ||
1386 | |||
1387 | if (card->codec_conf == NULL) | ||
1388 | return; | ||
1389 | |||
1390 | for (i = 0; i < card->num_configs; i++) { | ||
1391 | struct snd_soc_codec_conf *map = &card->codec_conf[i]; | ||
1392 | if (map->dev_name && !strcmp(codec->name, map->dev_name)) { | ||
1393 | codec->name_prefix = map->name_prefix; | ||
1394 | break; | ||
1395 | } | ||
1396 | } | ||
1397 | } | ||
1398 | |||
1399 | static int soc_probe_codec(struct snd_soc_card *card, | ||
1400 | struct snd_soc_codec *codec) | ||
1401 | { | ||
1402 | int ret = 0; | ||
1403 | |||
1404 | codec->card = card; | ||
1405 | codec->dapm.card = card; | ||
1406 | soc_set_name_prefix(card, codec); | ||
1407 | |||
1408 | if (codec->driver->probe) { | ||
1409 | ret = codec->driver->probe(codec); | ||
1410 | if (ret < 0) { | ||
1411 | dev_err(codec->dev, | ||
1412 | "asoc: failed to probe CODEC %s: %d\n", | ||
1413 | codec->name, ret); | ||
1414 | return ret; | ||
1415 | } | ||
1416 | } | ||
1417 | |||
1418 | soc_init_codec_debugfs(codec); | ||
1419 | |||
1420 | /* mark codec as probed and add to card codec list */ | ||
1421 | if (!try_module_get(codec->dev->driver->owner)) | ||
1422 | return -ENODEV; | ||
1423 | |||
1424 | codec->probed = 1; | ||
1425 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1426 | list_add(&codec->dapm.list, &card->dapm_list); | ||
1427 | |||
1428 | return ret; | ||
1429 | } | ||
1430 | |||
1371 | static void rtd_release(struct device *dev) {} | 1431 | static void rtd_release(struct device *dev) {} |
1372 | 1432 | ||
1433 | static int soc_post_component_init(struct snd_soc_card *card, | ||
1434 | struct snd_soc_codec *codec, | ||
1435 | int num, int dailess) | ||
1436 | { | ||
1437 | struct snd_soc_dai_link *dai_link = NULL; | ||
1438 | struct snd_soc_aux_dev *aux_dev = NULL; | ||
1439 | struct snd_soc_pcm_runtime *rtd; | ||
1440 | const char *temp, *name; | ||
1441 | int ret = 0; | ||
1442 | |||
1443 | if (!dailess) { | ||
1444 | dai_link = &card->dai_link[num]; | ||
1445 | rtd = &card->rtd[num]; | ||
1446 | name = dai_link->name; | ||
1447 | } else { | ||
1448 | aux_dev = &card->aux_dev[num]; | ||
1449 | rtd = &card->rtd_aux[num]; | ||
1450 | name = aux_dev->name; | ||
1451 | } | ||
1452 | |||
1453 | /* machine controls, routes and widgets are not prefixed */ | ||
1454 | temp = codec->name_prefix; | ||
1455 | codec->name_prefix = NULL; | ||
1456 | |||
1457 | /* do machine specific initialization */ | ||
1458 | if (!dailess && dai_link->init) | ||
1459 | ret = dai_link->init(rtd); | ||
1460 | else if (dailess && aux_dev->init) | ||
1461 | ret = aux_dev->init(&codec->dapm); | ||
1462 | if (ret < 0) { | ||
1463 | dev_err(card->dev, "asoc: failed to init %s: %d\n", name, ret); | ||
1464 | return ret; | ||
1465 | } | ||
1466 | codec->name_prefix = temp; | ||
1467 | |||
1468 | /* Make sure all DAPM widgets are instantiated */ | ||
1469 | snd_soc_dapm_new_widgets(&codec->dapm); | ||
1470 | snd_soc_dapm_sync(&codec->dapm); | ||
1471 | |||
1472 | /* register the rtd device */ | ||
1473 | rtd->codec = codec; | ||
1474 | rtd->card = card; | ||
1475 | rtd->dev.parent = card->dev; | ||
1476 | rtd->dev.release = rtd_release; | ||
1477 | rtd->dev.init_name = name; | ||
1478 | ret = device_register(&rtd->dev); | ||
1479 | if (ret < 0) { | ||
1480 | dev_err(card->dev, | ||
1481 | "asoc: failed to register runtime device: %d\n", ret); | ||
1482 | return ret; | ||
1483 | } | ||
1484 | rtd->dev_registered = 1; | ||
1485 | |||
1486 | /* add DAPM sysfs entries for this codec */ | ||
1487 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1488 | if (ret < 0) | ||
1489 | dev_err(codec->dev, | ||
1490 | "asoc: failed to add codec dapm sysfs entries: %d\n", | ||
1491 | ret); | ||
1492 | |||
1493 | /* add codec sysfs entries */ | ||
1494 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1495 | if (ret < 0) | ||
1496 | dev_err(codec->dev, | ||
1497 | "asoc: failed to add codec sysfs files: %d\n", ret); | ||
1498 | |||
1499 | return 0; | ||
1500 | } | ||
1501 | |||
1373 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) | 1502 | static int soc_probe_dai_link(struct snd_soc_card *card, int num) |
1374 | { | 1503 | { |
1375 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; | 1504 | struct snd_soc_dai_link *dai_link = &card->dai_link[num]; |
@@ -1383,10 +1512,7 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1383 | 1512 | ||
1384 | /* config components */ | 1513 | /* config components */ |
1385 | codec_dai->codec = codec; | 1514 | codec_dai->codec = codec; |
1386 | codec->card = card; | ||
1387 | cpu_dai->platform = platform; | 1515 | cpu_dai->platform = platform; |
1388 | rtd->card = card; | ||
1389 | rtd->dev.parent = card->dev; | ||
1390 | codec_dai->card = card; | 1516 | codec_dai->card = card; |
1391 | cpu_dai->card = card; | 1517 | cpu_dai->card = card; |
1392 | 1518 | ||
@@ -1410,20 +1536,9 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1410 | 1536 | ||
1411 | /* probe the CODEC */ | 1537 | /* probe the CODEC */ |
1412 | if (!codec->probed) { | 1538 | if (!codec->probed) { |
1413 | if (codec->driver->probe) { | 1539 | ret = soc_probe_codec(card, codec); |
1414 | ret = codec->driver->probe(codec); | 1540 | if (ret < 0) |
1415 | if (ret < 0) { | 1541 | return ret; |
1416 | printk(KERN_ERR "asoc: failed to probe CODEC %s\n", | ||
1417 | codec->name); | ||
1418 | return ret; | ||
1419 | } | ||
1420 | } | ||
1421 | |||
1422 | soc_init_codec_debugfs(codec); | ||
1423 | |||
1424 | /* mark codec as probed and add to card codec list */ | ||
1425 | codec->probed = 1; | ||
1426 | list_add(&codec->card_list, &card->codec_dev_list); | ||
1427 | } | 1542 | } |
1428 | 1543 | ||
1429 | /* probe the platform */ | 1544 | /* probe the platform */ |
@@ -1437,6 +1552,10 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1437 | } | 1552 | } |
1438 | } | 1553 | } |
1439 | /* mark platform as probed and add to card platform list */ | 1554 | /* mark platform as probed and add to card platform list */ |
1555 | |||
1556 | if (!try_module_get(platform->dev->driver->owner)) | ||
1557 | return -ENODEV; | ||
1558 | |||
1440 | platform->probed = 1; | 1559 | platform->probed = 1; |
1441 | list_add(&platform->card_list, &card->platform_dev_list); | 1560 | list_add(&platform->card_list, &card->platform_dev_list); |
1442 | } | 1561 | } |
@@ -1460,43 +1579,14 @@ static int soc_probe_dai_link(struct snd_soc_card *card, int num) | |||
1460 | /* DAPM dai link stream work */ | 1579 | /* DAPM dai link stream work */ |
1461 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); | 1580 | INIT_DELAYED_WORK(&rtd->delayed_work, close_delayed_work); |
1462 | 1581 | ||
1463 | /* now that all clients have probed, initialise the DAI link */ | 1582 | ret = soc_post_component_init(card, codec, num, 0); |
1464 | if (dai_link->init) { | 1583 | if (ret) |
1465 | ret = dai_link->init(rtd); | ||
1466 | if (ret < 0) { | ||
1467 | printk(KERN_ERR "asoc: failed to init %s\n", dai_link->stream_name); | ||
1468 | return ret; | ||
1469 | } | ||
1470 | } | ||
1471 | |||
1472 | /* Make sure all DAPM widgets are instantiated */ | ||
1473 | snd_soc_dapm_new_widgets(codec); | ||
1474 | snd_soc_dapm_sync(codec); | ||
1475 | |||
1476 | /* register the rtd device */ | ||
1477 | rtd->dev.release = rtd_release; | ||
1478 | rtd->dev.init_name = dai_link->name; | ||
1479 | ret = device_register(&rtd->dev); | ||
1480 | if (ret < 0) { | ||
1481 | printk(KERN_ERR "asoc: failed to register DAI runtime device %d\n", ret); | ||
1482 | return ret; | 1584 | return ret; |
1483 | } | ||
1484 | 1585 | ||
1485 | rtd->dev_registered = 1; | ||
1486 | ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); | 1586 | ret = device_create_file(&rtd->dev, &dev_attr_pmdown_time); |
1487 | if (ret < 0) | 1587 | if (ret < 0) |
1488 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); | 1588 | printk(KERN_WARNING "asoc: failed to add pmdown_time sysfs\n"); |
1489 | 1589 | ||
1490 | /* add DAPM sysfs entries for this codec */ | ||
1491 | ret = snd_soc_dapm_sys_add(&rtd->dev); | ||
1492 | if (ret < 0) | ||
1493 | printk(KERN_WARNING "asoc: failed to add codec dapm sysfs entries\n"); | ||
1494 | |||
1495 | /* add codec sysfs entries */ | ||
1496 | ret = device_create_file(&rtd->dev, &dev_attr_codec_reg); | ||
1497 | if (ret < 0) | ||
1498 | printk(KERN_WARNING "asoc: failed to add codec sysfs files\n"); | ||
1499 | |||
1500 | /* create the pcm */ | 1590 | /* create the pcm */ |
1501 | ret = soc_new_pcm(rtd, num); | 1591 | ret = soc_new_pcm(rtd, num); |
1502 | if (ret < 0) { | 1592 | if (ret < 0) { |
@@ -1551,9 +1641,85 @@ static void soc_unregister_ac97_dai_link(struct snd_soc_codec *codec) | |||
1551 | } | 1641 | } |
1552 | #endif | 1642 | #endif |
1553 | 1643 | ||
1644 | static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | ||
1645 | { | ||
1646 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | ||
1647 | struct snd_soc_codec *codec; | ||
1648 | int ret = -ENODEV; | ||
1649 | |||
1650 | /* find CODEC from registered CODECs*/ | ||
1651 | list_for_each_entry(codec, &codec_list, list) { | ||
1652 | if (!strcmp(codec->name, aux_dev->codec_name)) { | ||
1653 | if (codec->probed) { | ||
1654 | dev_err(codec->dev, | ||
1655 | "asoc: codec already probed"); | ||
1656 | ret = -EBUSY; | ||
1657 | goto out; | ||
1658 | } | ||
1659 | goto found; | ||
1660 | } | ||
1661 | } | ||
1662 | /* codec not found */ | ||
1663 | dev_err(card->dev, "asoc: codec %s not found", aux_dev->codec_name); | ||
1664 | goto out; | ||
1665 | |||
1666 | found: | ||
1667 | if (!try_module_get(codec->dev->driver->owner)) | ||
1668 | return -ENODEV; | ||
1669 | |||
1670 | ret = soc_probe_codec(card, codec); | ||
1671 | if (ret < 0) | ||
1672 | return ret; | ||
1673 | |||
1674 | ret = soc_post_component_init(card, codec, num, 1); | ||
1675 | |||
1676 | out: | ||
1677 | return ret; | ||
1678 | } | ||
1679 | |||
1680 | static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | ||
1681 | { | ||
1682 | struct snd_soc_pcm_runtime *rtd = &card->rtd_aux[num]; | ||
1683 | struct snd_soc_codec *codec = rtd->codec; | ||
1684 | |||
1685 | /* unregister the rtd device */ | ||
1686 | if (rtd->dev_registered) { | ||
1687 | device_remove_file(&rtd->dev, &dev_attr_codec_reg); | ||
1688 | device_unregister(&rtd->dev); | ||
1689 | rtd->dev_registered = 0; | ||
1690 | } | ||
1691 | |||
1692 | if (codec && codec->probed) | ||
1693 | soc_remove_codec(codec); | ||
1694 | } | ||
1695 | |||
1696 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec, | ||
1697 | enum snd_soc_compress_type compress_type) | ||
1698 | { | ||
1699 | int ret; | ||
1700 | |||
1701 | if (codec->cache_init) | ||
1702 | return 0; | ||
1703 | |||
1704 | /* override the compress_type if necessary */ | ||
1705 | if (compress_type && codec->compress_type != compress_type) | ||
1706 | codec->compress_type = compress_type; | ||
1707 | ret = snd_soc_cache_init(codec); | ||
1708 | if (ret < 0) { | ||
1709 | dev_err(codec->dev, "Failed to set cache compression type: %d\n", | ||
1710 | ret); | ||
1711 | return ret; | ||
1712 | } | ||
1713 | codec->cache_init = 1; | ||
1714 | return 0; | ||
1715 | } | ||
1716 | |||
1554 | static void snd_soc_instantiate_card(struct snd_soc_card *card) | 1717 | static void snd_soc_instantiate_card(struct snd_soc_card *card) |
1555 | { | 1718 | { |
1556 | struct platform_device *pdev = to_platform_device(card->dev); | 1719 | struct platform_device *pdev = to_platform_device(card->dev); |
1720 | struct snd_soc_codec *codec; | ||
1721 | struct snd_soc_codec_conf *codec_conf; | ||
1722 | enum snd_soc_compress_type compress_type; | ||
1557 | int ret, i; | 1723 | int ret, i; |
1558 | 1724 | ||
1559 | mutex_lock(&card->mutex); | 1725 | mutex_lock(&card->mutex); |
@@ -1573,6 +1739,39 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1573 | return; | 1739 | return; |
1574 | } | 1740 | } |
1575 | 1741 | ||
1742 | /* initialize the register cache for each available codec */ | ||
1743 | list_for_each_entry(codec, &codec_list, list) { | ||
1744 | if (codec->cache_init) | ||
1745 | continue; | ||
1746 | /* check to see if we need to override the compress_type */ | ||
1747 | for (i = 0; i < card->num_configs; ++i) { | ||
1748 | codec_conf = &card->codec_conf[i]; | ||
1749 | if (!strcmp(codec->name, codec_conf->dev_name)) { | ||
1750 | compress_type = codec_conf->compress_type; | ||
1751 | if (compress_type && compress_type | ||
1752 | != codec->compress_type) | ||
1753 | break; | ||
1754 | } | ||
1755 | } | ||
1756 | if (i == card->num_configs) { | ||
1757 | /* no need to override the compress_type so | ||
1758 | * go ahead and do the standard thing */ | ||
1759 | ret = snd_soc_init_codec_cache(codec, 0); | ||
1760 | if (ret < 0) { | ||
1761 | mutex_unlock(&card->mutex); | ||
1762 | return; | ||
1763 | } | ||
1764 | continue; | ||
1765 | } | ||
1766 | /* override the compress_type with the one supplied in | ||
1767 | * the machine driver */ | ||
1768 | ret = snd_soc_init_codec_cache(codec, compress_type); | ||
1769 | if (ret < 0) { | ||
1770 | mutex_unlock(&card->mutex); | ||
1771 | return; | ||
1772 | } | ||
1773 | } | ||
1774 | |||
1576 | /* card bind complete so register a sound card */ | 1775 | /* card bind complete so register a sound card */ |
1577 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, | 1776 | ret = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1, |
1578 | card->owner, 0, &card->snd_card); | 1777 | card->owner, 0, &card->snd_card); |
@@ -1605,6 +1804,15 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1605 | } | 1804 | } |
1606 | } | 1805 | } |
1607 | 1806 | ||
1807 | for (i = 0; i < card->num_aux_devs; i++) { | ||
1808 | ret = soc_probe_aux_dev(card, i); | ||
1809 | if (ret < 0) { | ||
1810 | pr_err("asoc: failed to add auxiliary devices %s: %d\n", | ||
1811 | card->name, ret); | ||
1812 | goto probe_aux_dev_err; | ||
1813 | } | ||
1814 | } | ||
1815 | |||
1608 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), | 1816 | snprintf(card->snd_card->shortname, sizeof(card->snd_card->shortname), |
1609 | "%s", card->name); | 1817 | "%s", card->name); |
1610 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), | 1818 | snprintf(card->snd_card->longname, sizeof(card->snd_card->longname), |
@@ -1613,7 +1821,7 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1613 | ret = snd_card_register(card->snd_card); | 1821 | ret = snd_card_register(card->snd_card); |
1614 | if (ret < 0) { | 1822 | if (ret < 0) { |
1615 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); | 1823 | printk(KERN_ERR "asoc: failed to register soundcard for %s\n", card->name); |
1616 | goto probe_dai_err; | 1824 | goto probe_aux_dev_err; |
1617 | } | 1825 | } |
1618 | 1826 | ||
1619 | #ifdef CONFIG_SND_SOC_AC97_BUS | 1827 | #ifdef CONFIG_SND_SOC_AC97_BUS |
@@ -1623,8 +1831,8 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1623 | if (ret < 0) { | 1831 | if (ret < 0) { |
1624 | printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); | 1832 | printk(KERN_ERR "asoc: failed to register AC97 %s\n", card->name); |
1625 | while (--i >= 0) | 1833 | while (--i >= 0) |
1626 | soc_unregister_ac97_dai_link(&card->rtd[i]); | 1834 | soc_unregister_ac97_dai_link(card->rtd[i].codec); |
1627 | goto probe_dai_err; | 1835 | goto probe_aux_dev_err; |
1628 | } | 1836 | } |
1629 | } | 1837 | } |
1630 | #endif | 1838 | #endif |
@@ -1633,6 +1841,10 @@ static void snd_soc_instantiate_card(struct snd_soc_card *card) | |||
1633 | mutex_unlock(&card->mutex); | 1841 | mutex_unlock(&card->mutex); |
1634 | return; | 1842 | return; |
1635 | 1843 | ||
1844 | probe_aux_dev_err: | ||
1845 | for (i = 0; i < card->num_aux_devs; i++) | ||
1846 | soc_remove_aux_dev(card, i); | ||
1847 | |||
1636 | probe_dai_err: | 1848 | probe_dai_err: |
1637 | for (i = 0; i < card->num_links; i++) | 1849 | for (i = 0; i < card->num_links; i++) |
1638 | soc_remove_dai_link(card, i); | 1850 | soc_remove_dai_link(card, i); |
@@ -1668,6 +1880,11 @@ static int soc_probe(struct platform_device *pdev) | |||
1668 | INIT_LIST_HEAD(&card->dai_dev_list); | 1880 | INIT_LIST_HEAD(&card->dai_dev_list); |
1669 | INIT_LIST_HEAD(&card->codec_dev_list); | 1881 | INIT_LIST_HEAD(&card->codec_dev_list); |
1670 | INIT_LIST_HEAD(&card->platform_dev_list); | 1882 | INIT_LIST_HEAD(&card->platform_dev_list); |
1883 | INIT_LIST_HEAD(&card->widgets); | ||
1884 | INIT_LIST_HEAD(&card->paths); | ||
1885 | INIT_LIST_HEAD(&card->dapm_list); | ||
1886 | |||
1887 | soc_init_card_debugfs(card); | ||
1671 | 1888 | ||
1672 | ret = snd_soc_register_card(card); | 1889 | ret = snd_soc_register_card(card); |
1673 | if (ret != 0) { | 1890 | if (ret != 0) { |
@@ -1689,13 +1906,19 @@ static int soc_remove(struct platform_device *pdev) | |||
1689 | /* make sure any delayed work runs */ | 1906 | /* make sure any delayed work runs */ |
1690 | for (i = 0; i < card->num_rtd; i++) { | 1907 | for (i = 0; i < card->num_rtd; i++) { |
1691 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | 1908 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
1692 | run_delayed_work(&rtd->delayed_work); | 1909 | flush_delayed_work_sync(&rtd->delayed_work); |
1693 | } | 1910 | } |
1694 | 1911 | ||
1912 | /* remove auxiliary devices */ | ||
1913 | for (i = 0; i < card->num_aux_devs; i++) | ||
1914 | soc_remove_aux_dev(card, i); | ||
1915 | |||
1695 | /* remove and free each DAI */ | 1916 | /* remove and free each DAI */ |
1696 | for (i = 0; i < card->num_rtd; i++) | 1917 | for (i = 0; i < card->num_rtd; i++) |
1697 | soc_remove_dai_link(card, i); | 1918 | soc_remove_dai_link(card, i); |
1698 | 1919 | ||
1920 | soc_cleanup_card_debugfs(card); | ||
1921 | |||
1699 | /* remove the card */ | 1922 | /* remove the card */ |
1700 | if (card->remove) | 1923 | if (card->remove) |
1701 | card->remove(pdev); | 1924 | card->remove(pdev); |
@@ -1720,7 +1943,7 @@ static int soc_poweroff(struct device *dev) | |||
1720 | * now, we're shutting down so no imminent restart. */ | 1943 | * now, we're shutting down so no imminent restart. */ |
1721 | for (i = 0; i < card->num_rtd; i++) { | 1944 | for (i = 0; i < card->num_rtd; i++) { |
1722 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; | 1945 | struct snd_soc_pcm_runtime *rtd = &card->rtd[i]; |
1723 | run_delayed_work(&rtd->delayed_work); | 1946 | flush_delayed_work_sync(&rtd->delayed_work); |
1724 | } | 1947 | } |
1725 | 1948 | ||
1726 | snd_soc_dapm_shutdown(card); | 1949 | snd_soc_dapm_shutdown(card); |
@@ -1879,6 +2102,27 @@ void snd_soc_free_ac97_codec(struct snd_soc_codec *codec) | |||
1879 | } | 2102 | } |
1880 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); | 2103 | EXPORT_SYMBOL_GPL(snd_soc_free_ac97_codec); |
1881 | 2104 | ||
2105 | unsigned int snd_soc_read(struct snd_soc_codec *codec, unsigned int reg) | ||
2106 | { | ||
2107 | unsigned int ret; | ||
2108 | |||
2109 | ret = codec->read(codec, reg); | ||
2110 | dev_dbg(codec->dev, "read %x => %x\n", reg, ret); | ||
2111 | trace_snd_soc_reg_read(codec, reg, ret); | ||
2112 | |||
2113 | return ret; | ||
2114 | } | ||
2115 | EXPORT_SYMBOL_GPL(snd_soc_read); | ||
2116 | |||
2117 | unsigned int snd_soc_write(struct snd_soc_codec *codec, | ||
2118 | unsigned int reg, unsigned int val) | ||
2119 | { | ||
2120 | dev_dbg(codec->dev, "write %x = %x\n", reg, val); | ||
2121 | trace_snd_soc_reg_write(codec, reg, val); | ||
2122 | return codec->write(codec, reg, val); | ||
2123 | } | ||
2124 | EXPORT_SYMBOL_GPL(snd_soc_write); | ||
2125 | |||
1882 | /** | 2126 | /** |
1883 | * snd_soc_update_bits - update codec register bits | 2127 | * snd_soc_update_bits - update codec register bits |
1884 | * @codec: audio codec | 2128 | * @codec: audio codec |
@@ -2019,14 +2263,22 @@ int snd_soc_add_controls(struct snd_soc_codec *codec, | |||
2019 | const struct snd_kcontrol_new *controls, int num_controls) | 2263 | const struct snd_kcontrol_new *controls, int num_controls) |
2020 | { | 2264 | { |
2021 | struct snd_card *card = codec->card->snd_card; | 2265 | struct snd_card *card = codec->card->snd_card; |
2266 | char prefixed_name[44], *name; | ||
2022 | int err, i; | 2267 | int err, i; |
2023 | 2268 | ||
2024 | for (i = 0; i < num_controls; i++) { | 2269 | for (i = 0; i < num_controls; i++) { |
2025 | const struct snd_kcontrol_new *control = &controls[i]; | 2270 | const struct snd_kcontrol_new *control = &controls[i]; |
2026 | err = snd_ctl_add(card, snd_soc_cnew(control, codec, NULL)); | 2271 | if (codec->name_prefix) { |
2272 | snprintf(prefixed_name, sizeof(prefixed_name), "%s %s", | ||
2273 | codec->name_prefix, control->name); | ||
2274 | name = prefixed_name; | ||
2275 | } else { | ||
2276 | name = control->name; | ||
2277 | } | ||
2278 | err = snd_ctl_add(card, snd_soc_cnew(control, codec, name)); | ||
2027 | if (err < 0) { | 2279 | if (err < 0) { |
2028 | dev_err(codec->dev, "%s: Failed to add %s: %d\n", | 2280 | dev_err(codec->dev, "%s: Failed to add %s: %d\n", |
2029 | codec->name, control->name, err); | 2281 | codec->name, name, err); |
2030 | return err; | 2282 | return err; |
2031 | } | 2283 | } |
2032 | } | 2284 | } |
@@ -2863,10 +3115,12 @@ static int snd_soc_register_card(struct snd_soc_card *card) | |||
2863 | if (!card->name || !card->dev) | 3115 | if (!card->name || !card->dev) |
2864 | return -EINVAL; | 3116 | return -EINVAL; |
2865 | 3117 | ||
2866 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * card->num_links, | 3118 | card->rtd = kzalloc(sizeof(struct snd_soc_pcm_runtime) * |
2867 | GFP_KERNEL); | 3119 | (card->num_links + card->num_aux_devs), |
3120 | GFP_KERNEL); | ||
2868 | if (card->rtd == NULL) | 3121 | if (card->rtd == NULL) |
2869 | return -ENOMEM; | 3122 | return -ENOMEM; |
3123 | card->rtd_aux = &card->rtd[card->num_links]; | ||
2870 | 3124 | ||
2871 | for (i = 0; i < card->num_links; i++) | 3125 | for (i = 0; i < card->num_links; i++) |
2872 | card->rtd[i].dai_link = &card->dai_link[i]; | 3126 | card->rtd[i].dai_link = &card->dai_link[i]; |
@@ -2908,7 +3162,7 @@ static int snd_soc_unregister_card(struct snd_soc_card *card) | |||
2908 | * Simplify DAI link configuration by removing ".-1" from device names | 3162 | * Simplify DAI link configuration by removing ".-1" from device names |
2909 | * and sanitizing names. | 3163 | * and sanitizing names. |
2910 | */ | 3164 | */ |
2911 | static inline char *fmt_single_name(struct device *dev, int *id) | 3165 | static char *fmt_single_name(struct device *dev, int *id) |
2912 | { | 3166 | { |
2913 | char *found, name[NAME_SIZE]; | 3167 | char *found, name[NAME_SIZE]; |
2914 | int id1, id2; | 3168 | int id1, id2; |
@@ -2916,7 +3170,7 @@ static inline char *fmt_single_name(struct device *dev, int *id) | |||
2916 | if (dev_name(dev) == NULL) | 3170 | if (dev_name(dev) == NULL) |
2917 | return NULL; | 3171 | return NULL; |
2918 | 3172 | ||
2919 | strncpy(name, dev_name(dev), NAME_SIZE); | 3173 | strlcpy(name, dev_name(dev), NAME_SIZE); |
2920 | 3174 | ||
2921 | /* are we a "%s.%d" name (platform and SPI components) */ | 3175 | /* are we a "%s.%d" name (platform and SPI components) */ |
2922 | found = strstr(name, dev->driver->name); | 3176 | found = strstr(name, dev->driver->name); |
@@ -2939,7 +3193,7 @@ static inline char *fmt_single_name(struct device *dev, int *id) | |||
2939 | 3193 | ||
2940 | /* sanitize component name for DAI link creation */ | 3194 | /* sanitize component name for DAI link creation */ |
2941 | snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); | 3195 | snprintf(tmp, NAME_SIZE, "%s.%s", dev->driver->name, name); |
2942 | strncpy(name, tmp, NAME_SIZE); | 3196 | strlcpy(name, tmp, NAME_SIZE); |
2943 | } else | 3197 | } else |
2944 | *id = 0; | 3198 | *id = 0; |
2945 | } | 3199 | } |
@@ -3204,9 +3458,11 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) | |||
3204 | * @codec: codec to register | 3458 | * @codec: codec to register |
3205 | */ | 3459 | */ |
3206 | int snd_soc_register_codec(struct device *dev, | 3460 | int snd_soc_register_codec(struct device *dev, |
3207 | struct snd_soc_codec_driver *codec_drv, | 3461 | const struct snd_soc_codec_driver *codec_drv, |
3208 | struct snd_soc_dai_driver *dai_drv, int num_dai) | 3462 | struct snd_soc_dai_driver *dai_drv, |
3463 | int num_dai) | ||
3209 | { | 3464 | { |
3465 | size_t reg_size; | ||
3210 | struct snd_soc_codec *codec; | 3466 | struct snd_soc_codec *codec; |
3211 | int ret, i; | 3467 | int ret, i; |
3212 | 3468 | ||
@@ -3223,30 +3479,37 @@ int snd_soc_register_codec(struct device *dev, | |||
3223 | return -ENOMEM; | 3479 | return -ENOMEM; |
3224 | } | 3480 | } |
3225 | 3481 | ||
3226 | /* allocate CODEC register cache */ | 3482 | if (codec_drv->compress_type) |
3227 | if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { | 3483 | codec->compress_type = codec_drv->compress_type; |
3228 | 3484 | else | |
3229 | if (codec_drv->reg_cache_default) | 3485 | codec->compress_type = SND_SOC_FLAT_COMPRESSION; |
3230 | codec->reg_cache = kmemdup(codec_drv->reg_cache_default, | ||
3231 | codec_drv->reg_cache_size * codec_drv->reg_word_size, GFP_KERNEL); | ||
3232 | else | ||
3233 | codec->reg_cache = kzalloc(codec_drv->reg_cache_size * | ||
3234 | codec_drv->reg_word_size, GFP_KERNEL); | ||
3235 | |||
3236 | if (codec->reg_cache == NULL) { | ||
3237 | kfree(codec->name); | ||
3238 | kfree(codec); | ||
3239 | return -ENOMEM; | ||
3240 | } | ||
3241 | } | ||
3242 | 3486 | ||
3487 | codec->write = codec_drv->write; | ||
3488 | codec->read = codec_drv->read; | ||
3489 | codec->dapm.bias_level = SND_SOC_BIAS_OFF; | ||
3490 | codec->dapm.dev = dev; | ||
3491 | codec->dapm.codec = codec; | ||
3243 | codec->dev = dev; | 3492 | codec->dev = dev; |
3244 | codec->driver = codec_drv; | 3493 | codec->driver = codec_drv; |
3245 | codec->bias_level = SND_SOC_BIAS_OFF; | ||
3246 | codec->num_dai = num_dai; | 3494 | codec->num_dai = num_dai; |
3247 | mutex_init(&codec->mutex); | 3495 | mutex_init(&codec->mutex); |
3248 | INIT_LIST_HEAD(&codec->dapm_widgets); | 3496 | |
3249 | INIT_LIST_HEAD(&codec->dapm_paths); | 3497 | /* allocate CODEC register cache */ |
3498 | if (codec_drv->reg_cache_size && codec_drv->reg_word_size) { | ||
3499 | reg_size = codec_drv->reg_cache_size * codec_drv->reg_word_size; | ||
3500 | /* it is necessary to make a copy of the default register cache | ||
3501 | * because in the case of using a compression type that requires | ||
3502 | * the default register cache to be marked as __devinitconst the | ||
3503 | * kernel might have freed the array by the time we initialize | ||
3504 | * the cache. | ||
3505 | */ | ||
3506 | codec->reg_def_copy = kmemdup(codec_drv->reg_cache_default, | ||
3507 | reg_size, GFP_KERNEL); | ||
3508 | if (!codec->reg_def_copy) { | ||
3509 | ret = -ENOMEM; | ||
3510 | goto fail; | ||
3511 | } | ||
3512 | } | ||
3250 | 3513 | ||
3251 | for (i = 0; i < num_dai; i++) { | 3514 | for (i = 0; i < num_dai; i++) { |
3252 | fixup_codec_formats(&dai_drv[i].playback); | 3515 | fixup_codec_formats(&dai_drv[i].playback); |
@@ -3257,7 +3520,7 @@ int snd_soc_register_codec(struct device *dev, | |||
3257 | if (num_dai) { | 3520 | if (num_dai) { |
3258 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); | 3521 | ret = snd_soc_register_dais(dev, dai_drv, num_dai); |
3259 | if (ret < 0) | 3522 | if (ret < 0) |
3260 | goto error; | 3523 | goto fail; |
3261 | } | 3524 | } |
3262 | 3525 | ||
3263 | mutex_lock(&client_mutex); | 3526 | mutex_lock(&client_mutex); |
@@ -3268,9 +3531,9 @@ int snd_soc_register_codec(struct device *dev, | |||
3268 | pr_debug("Registered codec '%s'\n", codec->name); | 3531 | pr_debug("Registered codec '%s'\n", codec->name); |
3269 | return 0; | 3532 | return 0; |
3270 | 3533 | ||
3271 | error: | 3534 | fail: |
3272 | if (codec->reg_cache) | 3535 | kfree(codec->reg_def_copy); |
3273 | kfree(codec->reg_cache); | 3536 | codec->reg_def_copy = NULL; |
3274 | kfree(codec->name); | 3537 | kfree(codec->name); |
3275 | kfree(codec); | 3538 | kfree(codec); |
3276 | return ret; | 3539 | return ret; |
@@ -3304,8 +3567,8 @@ found: | |||
3304 | 3567 | ||
3305 | pr_debug("Unregistered codec '%s'\n", codec->name); | 3568 | pr_debug("Unregistered codec '%s'\n", codec->name); |
3306 | 3569 | ||
3307 | if (codec->reg_cache) | 3570 | snd_soc_cache_exit(codec); |
3308 | kfree(codec->reg_cache); | 3571 | kfree(codec->reg_def_copy); |
3309 | kfree(codec->name); | 3572 | kfree(codec->name); |
3310 | kfree(codec); | 3573 | kfree(codec); |
3311 | } | 3574 | } |