diff options
-rw-r--r-- | include/sound/soc.h | 27 | ||||
-rw-r--r-- | sound/soc/soc-core.c | 335 | ||||
-rw-r--r-- | sound/soc/soc-generic-dmaengine-pcm.c | 4 |
3 files changed, 194 insertions, 172 deletions
diff --git a/include/sound/soc.h b/include/sound/soc.h index 0ab8b1e4a5d2..22543acfae4b 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h | |||
@@ -697,6 +697,10 @@ struct snd_soc_component_driver { | |||
697 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, | 697 | void (*seq_notifier)(struct snd_soc_component *, enum snd_soc_dapm_type, |
698 | int subseq); | 698 | int subseq); |
699 | int (*stream_event)(struct snd_soc_component *, int event); | 699 | int (*stream_event)(struct snd_soc_component *, int event); |
700 | |||
701 | /* probe ordering - for components with runtime dependencies */ | ||
702 | int probe_order; | ||
703 | int remove_order; | ||
700 | }; | 704 | }; |
701 | 705 | ||
702 | struct snd_soc_component { | 706 | struct snd_soc_component { |
@@ -710,6 +714,7 @@ struct snd_soc_component { | |||
710 | 714 | ||
711 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ | 715 | unsigned int ignore_pmdown_time:1; /* pmdown_time is ignored at stop */ |
712 | unsigned int registered_as_component:1; | 716 | unsigned int registered_as_component:1; |
717 | unsigned int probed:1; | ||
713 | 718 | ||
714 | struct list_head list; | 719 | struct list_head list; |
715 | 720 | ||
@@ -742,6 +747,18 @@ struct snd_soc_component { | |||
742 | struct snd_soc_dapm_context dapm; | 747 | struct snd_soc_dapm_context dapm; |
743 | struct snd_soc_dapm_context *dapm_ptr; | 748 | struct snd_soc_dapm_context *dapm_ptr; |
744 | 749 | ||
750 | const struct snd_kcontrol_new *controls; | ||
751 | unsigned int num_controls; | ||
752 | const struct snd_soc_dapm_widget *dapm_widgets; | ||
753 | unsigned int num_dapm_widgets; | ||
754 | const struct snd_soc_dapm_route *dapm_routes; | ||
755 | unsigned int num_dapm_routes; | ||
756 | bool steal_sibling_dai_widgets; | ||
757 | struct snd_soc_codec *codec; | ||
758 | |||
759 | int (*probe)(struct snd_soc_component *); | ||
760 | void (*remove)(struct snd_soc_component *); | ||
761 | |||
745 | #ifdef CONFIG_DEBUG_FS | 762 | #ifdef CONFIG_DEBUG_FS |
746 | void (*init_debugfs)(struct snd_soc_component *component); | 763 | void (*init_debugfs)(struct snd_soc_component *component); |
747 | const char *debugfs_prefix; | 764 | const char *debugfs_prefix; |
@@ -761,7 +778,6 @@ struct snd_soc_codec { | |||
761 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ | 778 | struct snd_ac97 *ac97; /* for ad-hoc ac97 devices */ |
762 | unsigned int cache_bypass:1; /* Suppress access to the cache */ | 779 | unsigned int cache_bypass:1; /* Suppress access to the cache */ |
763 | unsigned int suspended:1; /* Codec is in suspend PM state */ | 780 | unsigned int suspended:1; /* Codec is in suspend PM state */ |
764 | unsigned int probed:1; /* Codec has been probed */ | ||
765 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ | 781 | unsigned int ac97_registered:1; /* Codec has been AC97 registered */ |
766 | unsigned int ac97_created:1; /* Codec has been created by SoC */ | 782 | unsigned int ac97_created:1; /* Codec has been created by SoC */ |
767 | unsigned int cache_init:1; /* codec cache has been initialized */ | 783 | unsigned int cache_init:1; /* codec cache has been initialized */ |
@@ -827,10 +843,6 @@ struct snd_soc_codec_driver { | |||
827 | enum snd_soc_dapm_type, int); | 843 | enum snd_soc_dapm_type, int); |
828 | 844 | ||
829 | bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */ | 845 | bool ignore_pmdown_time; /* Doesn't benefit from pmdown delay */ |
830 | |||
831 | /* probe ordering - for components with runtime dependencies */ | ||
832 | int probe_order; | ||
833 | int remove_order; | ||
834 | }; | 846 | }; |
835 | 847 | ||
836 | /* SoC platform interface */ | 848 | /* SoC platform interface */ |
@@ -867,10 +879,6 @@ struct snd_soc_platform_driver { | |||
867 | /* platform stream compress ops */ | 879 | /* platform stream compress ops */ |
868 | const struct snd_compr_ops *compr_ops; | 880 | const struct snd_compr_ops *compr_ops; |
869 | 881 | ||
870 | /* probe ordering - for components with runtime dependencies */ | ||
871 | int probe_order; | ||
872 | int remove_order; | ||
873 | |||
874 | /* platform IO - used for platform DAPM */ | 882 | /* platform IO - used for platform DAPM */ |
875 | unsigned int (*read)(struct snd_soc_platform *, unsigned int); | 883 | unsigned int (*read)(struct snd_soc_platform *, unsigned int); |
876 | int (*write)(struct snd_soc_platform *, unsigned int, unsigned int); | 884 | int (*write)(struct snd_soc_platform *, unsigned int, unsigned int); |
@@ -888,7 +896,6 @@ struct snd_soc_platform { | |||
888 | const struct snd_soc_platform_driver *driver; | 896 | const struct snd_soc_platform_driver *driver; |
889 | 897 | ||
890 | unsigned int suspended:1; /* platform is suspended */ | 898 | unsigned int suspended:1; /* platform is suspended */ |
891 | unsigned int probed:1; | ||
892 | 899 | ||
893 | struct list_head list; | 900 | struct list_head list; |
894 | 901 | ||
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 79371a77f324..b833cc6fd86d 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c | |||
@@ -985,44 +985,20 @@ static int soc_bind_dai_link(struct snd_soc_card *card, int num) | |||
985 | return 0; | 985 | return 0; |
986 | } | 986 | } |
987 | 987 | ||
988 | static int soc_remove_platform(struct snd_soc_platform *platform) | 988 | static void soc_remove_component(struct snd_soc_component *component) |
989 | { | 989 | { |
990 | int ret; | 990 | /* This is a HACK and will be removed soon */ |
991 | 991 | if (component->codec) | |
992 | if (platform->driver->remove) { | 992 | list_del(&component->codec->card_list); |
993 | ret = platform->driver->remove(platform); | ||
994 | if (ret < 0) | ||
995 | dev_err(platform->dev, "ASoC: failed to remove %d\n", | ||
996 | ret); | ||
997 | } | ||
998 | |||
999 | /* Make sure all DAPM widgets are freed */ | ||
1000 | snd_soc_dapm_free(&platform->component.dapm); | ||
1001 | |||
1002 | soc_cleanup_component_debugfs(&platform->component); | ||
1003 | platform->probed = 0; | ||
1004 | module_put(platform->dev->driver->owner); | ||
1005 | |||
1006 | return 0; | ||
1007 | } | ||
1008 | |||
1009 | static void soc_remove_codec(struct snd_soc_codec *codec) | ||
1010 | { | ||
1011 | int err; | ||
1012 | 993 | ||
1013 | if (codec->driver->remove) { | 994 | if (component->remove) |
1014 | err = codec->driver->remove(codec); | 995 | component->remove(component); |
1015 | if (err < 0) | ||
1016 | dev_err(codec->dev, "ASoC: failed to remove %d\n", err); | ||
1017 | } | ||
1018 | 996 | ||
1019 | /* Make sure all DAPM widgets are freed */ | 997 | snd_soc_dapm_free(snd_soc_component_get_dapm(component)); |
1020 | snd_soc_dapm_free(&codec->dapm); | ||
1021 | 998 | ||
1022 | soc_cleanup_component_debugfs(&codec->component); | 999 | soc_cleanup_component_debugfs(component); |
1023 | codec->probed = 0; | 1000 | component->probed = 0; |
1024 | list_del(&codec->card_list); | 1001 | module_put(component->dev->driver->owner); |
1025 | module_put(codec->dev->driver->owner); | ||
1026 | } | 1002 | } |
1027 | 1003 | ||
1028 | static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) | 1004 | static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) |
@@ -1086,25 +1062,24 @@ static void soc_remove_link_components(struct snd_soc_card *card, int num, | |||
1086 | int i; | 1062 | int i; |
1087 | 1063 | ||
1088 | /* remove the platform */ | 1064 | /* remove the platform */ |
1089 | if (platform && platform->probed && | 1065 | if (platform && platform->component.probed && |
1090 | platform->driver->remove_order == order) { | 1066 | platform->component.driver->remove_order == order) |
1091 | soc_remove_platform(platform); | 1067 | soc_remove_component(&platform->component); |
1092 | } | ||
1093 | 1068 | ||
1094 | /* remove the CODEC-side CODEC */ | 1069 | /* remove the CODEC-side CODEC */ |
1095 | for (i = 0; i < rtd->num_codecs; i++) { | 1070 | for (i = 0; i < rtd->num_codecs; i++) { |
1096 | codec = rtd->codec_dais[i]->codec; | 1071 | codec = rtd->codec_dais[i]->codec; |
1097 | if (codec && codec->probed && | 1072 | if (codec && codec->component.probed && |
1098 | codec->driver->remove_order == order) | 1073 | codec->component.driver->remove_order == order) |
1099 | soc_remove_codec(codec); | 1074 | soc_remove_component(&codec->component); |
1100 | } | 1075 | } |
1101 | 1076 | ||
1102 | /* remove any CPU-side CODEC */ | 1077 | /* remove any CPU-side CODEC */ |
1103 | if (cpu_dai) { | 1078 | if (cpu_dai) { |
1104 | codec = cpu_dai->codec; | 1079 | codec = cpu_dai->codec; |
1105 | if (codec && codec->probed && | 1080 | if (codec && codec->component.probed && |
1106 | codec->driver->remove_order == order) | 1081 | codec->component.driver->remove_order == order) |
1107 | soc_remove_codec(codec); | 1082 | soc_remove_component(&codec->component); |
1108 | } | 1083 | } |
1109 | } | 1084 | } |
1110 | 1085 | ||
@@ -1146,137 +1121,108 @@ static void soc_set_name_prefix(struct snd_soc_card *card, | |||
1146 | } | 1121 | } |
1147 | } | 1122 | } |
1148 | 1123 | ||
1149 | static int soc_probe_codec(struct snd_soc_card *card, | 1124 | static int soc_probe_component(struct snd_soc_card *card, |
1150 | struct snd_soc_codec *codec) | 1125 | struct snd_soc_component *component) |
1151 | { | 1126 | { |
1152 | int ret = 0; | 1127 | struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); |
1153 | const struct snd_soc_codec_driver *driver = codec->driver; | 1128 | struct snd_soc_component *dai_component, *component2; |
1154 | struct snd_soc_dai *dai; | 1129 | struct snd_soc_dai *dai; |
1130 | int ret; | ||
1155 | 1131 | ||
1156 | codec->component.card = card; | 1132 | component->card = card; |
1157 | codec->dapm.card = card; | 1133 | dapm->card = card; |
1158 | soc_set_name_prefix(card, &codec->component); | 1134 | soc_set_name_prefix(card, component); |
1159 | 1135 | ||
1160 | if (!try_module_get(codec->dev->driver->owner)) | 1136 | if (!try_module_get(component->dev->driver->owner)) |
1161 | return -ENODEV; | 1137 | return -ENODEV; |
1162 | 1138 | ||
1163 | soc_init_component_debugfs(&codec->component); | 1139 | soc_init_component_debugfs(component); |
1164 | 1140 | ||
1165 | if (driver->dapm_widgets) { | 1141 | if (component->dapm_widgets) { |
1166 | ret = snd_soc_dapm_new_controls(&codec->dapm, | 1142 | ret = snd_soc_dapm_new_controls(dapm, component->dapm_widgets, |
1167 | driver->dapm_widgets, | 1143 | component->num_dapm_widgets); |
1168 | driver->num_dapm_widgets); | ||
1169 | 1144 | ||
1170 | if (ret != 0) { | 1145 | if (ret != 0) { |
1171 | dev_err(codec->dev, | 1146 | dev_err(component->dev, |
1172 | "Failed to create new controls %d\n", ret); | 1147 | "Failed to create new controls %d\n", ret); |
1173 | goto err_probe; | 1148 | goto err_probe; |
1174 | } | 1149 | } |
1175 | } | 1150 | } |
1176 | 1151 | ||
1177 | /* Create DAPM widgets for each DAI stream */ | 1152 | /* |
1178 | list_for_each_entry(dai, &codec->component.dai_list, list) { | 1153 | * This is rather ugly, but certain platforms expect that the DAPM |
1179 | ret = snd_soc_dapm_new_dai_widgets(&codec->dapm, dai); | 1154 | * widgets for the DAIs for components with the same parent device are |
1155 | * created in the platforms DAPM context. Until that is fixed we need to | ||
1156 | * keep this. | ||
1157 | */ | ||
1158 | if (component->steal_sibling_dai_widgets) { | ||
1159 | dai_component = NULL; | ||
1160 | list_for_each_entry(component2, &component_list, list) { | ||
1161 | if (component == component2) | ||
1162 | continue; | ||
1180 | 1163 | ||
1181 | if (ret != 0) { | 1164 | if (component2->dev == component->dev && |
1182 | dev_err(codec->dev, | 1165 | !list_empty(&component2->dai_list)) { |
1183 | "Failed to create DAI widgets %d\n", ret); | 1166 | dai_component = component2; |
1184 | goto err_probe; | 1167 | break; |
1168 | } | ||
1185 | } | 1169 | } |
1186 | } | 1170 | } else { |
1187 | 1171 | dai_component = component; | |
1188 | codec->dapm.idle_bias_off = driver->idle_bias_off; | 1172 | list_for_each_entry(component2, &component_list, list) { |
1189 | 1173 | if (component2->dev == component->dev && | |
1190 | if (driver->probe) { | 1174 | component2->steal_sibling_dai_widgets) { |
1191 | ret = driver->probe(codec); | 1175 | dai_component = NULL; |
1192 | if (ret < 0) { | 1176 | break; |
1193 | dev_err(codec->dev, | 1177 | } |
1194 | "ASoC: failed to probe CODEC %d\n", ret); | ||
1195 | goto err_probe; | ||
1196 | } | 1178 | } |
1197 | WARN(codec->dapm.idle_bias_off && | ||
1198 | codec->dapm.bias_level != SND_SOC_BIAS_OFF, | ||
1199 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | ||
1200 | codec->component.name); | ||
1201 | } | 1179 | } |
1202 | 1180 | ||
1203 | if (driver->controls) | 1181 | if (dai_component) { |
1204 | snd_soc_add_codec_controls(codec, driver->controls, | 1182 | list_for_each_entry(dai, &dai_component->dai_list, list) { |
1205 | driver->num_controls); | 1183 | snd_soc_dapm_new_dai_widgets(dapm, dai); |
1206 | if (driver->dapm_routes) | 1184 | if (ret != 0) { |
1207 | snd_soc_dapm_add_routes(&codec->dapm, driver->dapm_routes, | 1185 | dev_err(component->dev, |
1208 | driver->num_dapm_routes); | 1186 | "Failed to create DAI widgets %d\n", |
1209 | 1187 | ret); | |
1210 | /* mark codec as probed and add to card codec list */ | 1188 | goto err_probe; |
1211 | codec->probed = 1; | 1189 | } |
1212 | list_add(&codec->card_list, &card->codec_dev_list); | 1190 | } |
1213 | list_add(&codec->dapm.list, &card->dapm_list); | ||
1214 | |||
1215 | return 0; | ||
1216 | |||
1217 | err_probe: | ||
1218 | soc_cleanup_component_debugfs(&codec->component); | ||
1219 | module_put(codec->dev->driver->owner); | ||
1220 | |||
1221 | return ret; | ||
1222 | } | ||
1223 | |||
1224 | static int soc_probe_platform(struct snd_soc_card *card, | ||
1225 | struct snd_soc_platform *platform) | ||
1226 | { | ||
1227 | int ret = 0; | ||
1228 | const struct snd_soc_platform_driver *driver = platform->driver; | ||
1229 | struct snd_soc_component *component; | ||
1230 | struct snd_soc_dai *dai; | ||
1231 | |||
1232 | platform->component.card = card; | ||
1233 | platform->component.dapm.card = card; | ||
1234 | |||
1235 | if (!try_module_get(platform->dev->driver->owner)) | ||
1236 | return -ENODEV; | ||
1237 | |||
1238 | soc_init_component_debugfs(&platform->component); | ||
1239 | |||
1240 | if (driver->dapm_widgets) | ||
1241 | snd_soc_dapm_new_controls(&platform->component.dapm, | ||
1242 | driver->dapm_widgets, driver->num_dapm_widgets); | ||
1243 | |||
1244 | /* Create DAPM widgets for each DAI stream */ | ||
1245 | list_for_each_entry(component, &component_list, list) { | ||
1246 | if (component->dev != platform->dev) | ||
1247 | continue; | ||
1248 | list_for_each_entry(dai, &component->dai_list, list) | ||
1249 | snd_soc_dapm_new_dai_widgets(&platform->component.dapm, | ||
1250 | dai); | ||
1251 | } | 1191 | } |
1252 | 1192 | ||
1253 | platform->component.dapm.idle_bias_off = 1; | 1193 | if (component->probe) { |
1254 | 1194 | ret = component->probe(component); | |
1255 | if (driver->probe) { | ||
1256 | ret = driver->probe(platform); | ||
1257 | if (ret < 0) { | 1195 | if (ret < 0) { |
1258 | dev_err(platform->dev, | 1196 | dev_err(component->dev, |
1259 | "ASoC: failed to probe platform %d\n", ret); | 1197 | "ASoC: failed to probe component %d\n", ret); |
1260 | goto err_probe; | 1198 | goto err_probe; |
1261 | } | 1199 | } |
1200 | |||
1201 | WARN(dapm->idle_bias_off && | ||
1202 | dapm->bias_level != SND_SOC_BIAS_OFF, | ||
1203 | "codec %s can not start from non-off bias with idle_bias_off==1\n", | ||
1204 | component->name); | ||
1262 | } | 1205 | } |
1263 | 1206 | ||
1264 | if (driver->controls) | 1207 | if (component->controls) |
1265 | snd_soc_add_platform_controls(platform, driver->controls, | 1208 | snd_soc_add_component_controls(component, component->controls, |
1266 | driver->num_controls); | 1209 | component->num_controls); |
1267 | if (driver->dapm_routes) | 1210 | if (component->dapm_routes) |
1268 | snd_soc_dapm_add_routes(&platform->component.dapm, | 1211 | snd_soc_dapm_add_routes(dapm, component->dapm_routes, |
1269 | driver->dapm_routes, driver->num_dapm_routes); | 1212 | component->num_dapm_routes); |
1270 | 1213 | ||
1271 | /* mark platform as probed and add to card platform list */ | 1214 | component->probed = 1; |
1272 | platform->probed = 1; | 1215 | list_add(&dapm->list, &card->dapm_list); |
1273 | list_add(&platform->component.dapm.list, &card->dapm_list); | 1216 | |
1217 | /* This is a HACK and will be removed soon */ | ||
1218 | if (component->codec) | ||
1219 | list_add(&component->codec->card_list, &card->codec_dev_list); | ||
1274 | 1220 | ||
1275 | return 0; | 1221 | return 0; |
1276 | 1222 | ||
1277 | err_probe: | 1223 | err_probe: |
1278 | soc_cleanup_component_debugfs(&platform->component); | 1224 | soc_cleanup_component_debugfs(component); |
1279 | module_put(platform->dev->driver->owner); | 1225 | module_put(component->dev->driver->owner); |
1280 | 1226 | ||
1281 | return ret; | 1227 | return ret; |
1282 | } | 1228 | } |
@@ -1334,33 +1280,36 @@ static int soc_probe_link_components(struct snd_soc_card *card, int num, | |||
1334 | int order) | 1280 | int order) |
1335 | { | 1281 | { |
1336 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; | 1282 | struct snd_soc_pcm_runtime *rtd = &card->rtd[num]; |
1337 | struct snd_soc_dai *cpu_dai = rtd->cpu_dai; | ||
1338 | struct snd_soc_platform *platform = rtd->platform; | 1283 | struct snd_soc_platform *platform = rtd->platform; |
1284 | struct snd_soc_component *component; | ||
1339 | int i, ret; | 1285 | int i, ret; |
1340 | 1286 | ||
1341 | /* probe the CPU-side component, if it is a CODEC */ | 1287 | /* probe the CPU-side component, if it is a CODEC */ |
1342 | if (cpu_dai->codec && | 1288 | if (rtd->cpu_dai->codec) { |
1343 | !cpu_dai->codec->probed && | 1289 | component = &rtd->cpu_dai->codec->component; |
1344 | cpu_dai->codec->driver->probe_order == order) { | 1290 | if (!component->probed && |
1345 | ret = soc_probe_codec(card, cpu_dai->codec); | 1291 | component->driver->probe_order == order) { |
1346 | if (ret < 0) | 1292 | ret = soc_probe_component(card, component); |
1347 | return ret; | 1293 | if (ret < 0) |
1294 | return ret; | ||
1295 | } | ||
1348 | } | 1296 | } |
1349 | 1297 | ||
1350 | /* probe the CODEC-side components */ | 1298 | /* probe the CODEC-side components */ |
1351 | for (i = 0; i < rtd->num_codecs; i++) { | 1299 | for (i = 0; i < rtd->num_codecs; i++) { |
1352 | if (!rtd->codec_dais[i]->codec->probed && | 1300 | component = &rtd->codec_dais[i]->codec->component; |
1353 | rtd->codec_dais[i]->codec->driver->probe_order == order) { | 1301 | if (!component->probed && |
1354 | ret = soc_probe_codec(card, rtd->codec_dais[i]->codec); | 1302 | component->driver->probe_order == order) { |
1303 | ret = soc_probe_component(card, component); | ||
1355 | if (ret < 0) | 1304 | if (ret < 0) |
1356 | return ret; | 1305 | return ret; |
1357 | } | 1306 | } |
1358 | } | 1307 | } |
1359 | 1308 | ||
1360 | /* probe the platform */ | 1309 | /* probe the platform */ |
1361 | if (!platform->probed && | 1310 | if (!platform->component.probed && |
1362 | platform->driver->probe_order == order) { | 1311 | platform->component.driver->probe_order == order) { |
1363 | ret = soc_probe_platform(card, platform); | 1312 | ret = soc_probe_component(card, &platform->component); |
1364 | if (ret < 0) | 1313 | if (ret < 0) |
1365 | return ret; | 1314 | return ret; |
1366 | } | 1315 | } |
@@ -1647,12 +1596,12 @@ static int soc_probe_aux_dev(struct snd_soc_card *card, int num) | |||
1647 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; | 1596 | struct snd_soc_aux_dev *aux_dev = &card->aux_dev[num]; |
1648 | int ret; | 1597 | int ret; |
1649 | 1598 | ||
1650 | if (rtd->codec->probed) { | 1599 | if (rtd->codec->component.probed) { |
1651 | dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); | 1600 | dev_err(rtd->codec->dev, "ASoC: codec already probed\n"); |
1652 | return -EBUSY; | 1601 | return -EBUSY; |
1653 | } | 1602 | } |
1654 | 1603 | ||
1655 | ret = soc_probe_codec(card, rtd->codec); | 1604 | ret = soc_probe_component(card, &rtd->codec->component); |
1656 | if (ret < 0) | 1605 | if (ret < 0) |
1657 | return ret; | 1606 | return ret; |
1658 | 1607 | ||
@@ -1681,8 +1630,8 @@ static void soc_remove_aux_dev(struct snd_soc_card *card, int num) | |||
1681 | rtd->dev_registered = 0; | 1630 | rtd->dev_registered = 0; |
1682 | } | 1631 | } |
1683 | 1632 | ||
1684 | if (codec && codec->probed) | 1633 | if (codec && codec->component.probed) |
1685 | soc_remove_codec(codec); | 1634 | soc_remove_component(&codec->component); |
1686 | } | 1635 | } |
1687 | 1636 | ||
1688 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) | 1637 | static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) |
@@ -4198,6 +4147,20 @@ found: | |||
4198 | } | 4147 | } |
4199 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); | 4148 | EXPORT_SYMBOL_GPL(snd_soc_unregister_component); |
4200 | 4149 | ||
4150 | static int snd_soc_platform_drv_probe(struct snd_soc_component *component) | ||
4151 | { | ||
4152 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); | ||
4153 | |||
4154 | return platform->driver->probe(platform); | ||
4155 | } | ||
4156 | |||
4157 | static void snd_soc_platform_drv_remove(struct snd_soc_component *component) | ||
4158 | { | ||
4159 | struct snd_soc_platform *platform = snd_soc_component_to_platform(component); | ||
4160 | |||
4161 | platform->driver->remove(platform); | ||
4162 | } | ||
4163 | |||
4201 | static int snd_soc_platform_drv_write(struct snd_soc_component *component, | 4164 | static int snd_soc_platform_drv_write(struct snd_soc_component *component, |
4202 | unsigned int reg, unsigned int val) | 4165 | unsigned int reg, unsigned int val) |
4203 | { | 4166 | { |
@@ -4234,6 +4197,24 @@ int snd_soc_add_platform(struct device *dev, struct snd_soc_platform *platform, | |||
4234 | 4197 | ||
4235 | platform->dev = dev; | 4198 | platform->dev = dev; |
4236 | platform->driver = platform_drv; | 4199 | platform->driver = platform_drv; |
4200 | if (platform_drv->controls) { | ||
4201 | platform->component.controls = platform_drv->controls; | ||
4202 | platform->component.num_controls = platform_drv->num_controls; | ||
4203 | } | ||
4204 | if (platform_drv->dapm_widgets) { | ||
4205 | platform->component.dapm_widgets = platform_drv->dapm_widgets; | ||
4206 | platform->component.num_dapm_widgets = platform_drv->num_dapm_widgets; | ||
4207 | platform->component.steal_sibling_dai_widgets = true; | ||
4208 | } | ||
4209 | if (platform_drv->dapm_routes) { | ||
4210 | platform->component.dapm_routes = platform_drv->dapm_routes; | ||
4211 | platform->component.num_dapm_routes = platform_drv->num_dapm_routes; | ||
4212 | } | ||
4213 | |||
4214 | if (platform_drv->probe) | ||
4215 | platform->component.probe = snd_soc_platform_drv_probe; | ||
4216 | if (platform_drv->remove) | ||
4217 | platform->component.remove = snd_soc_platform_drv_remove; | ||
4237 | if (platform_drv->write) | 4218 | if (platform_drv->write) |
4238 | platform->component.write = snd_soc_platform_drv_write; | 4219 | platform->component.write = snd_soc_platform_drv_write; |
4239 | if (platform_drv->read) | 4220 | if (platform_drv->read) |
@@ -4363,6 +4344,20 @@ static void fixup_codec_formats(struct snd_soc_pcm_stream *stream) | |||
4363 | stream->formats |= codec_format_map[i]; | 4344 | stream->formats |= codec_format_map[i]; |
4364 | } | 4345 | } |
4365 | 4346 | ||
4347 | static int snd_soc_codec_drv_probe(struct snd_soc_component *component) | ||
4348 | { | ||
4349 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
4350 | |||
4351 | return codec->driver->probe(codec); | ||
4352 | } | ||
4353 | |||
4354 | static void snd_soc_codec_drv_remove(struct snd_soc_component *component) | ||
4355 | { | ||
4356 | struct snd_soc_codec *codec = snd_soc_component_to_codec(component); | ||
4357 | |||
4358 | codec->driver->remove(codec); | ||
4359 | } | ||
4360 | |||
4366 | static int snd_soc_codec_drv_write(struct snd_soc_component *component, | 4361 | static int snd_soc_codec_drv_write(struct snd_soc_component *component, |
4367 | unsigned int reg, unsigned int val) | 4362 | unsigned int reg, unsigned int val) |
4368 | { | 4363 | { |
@@ -4411,12 +4406,30 @@ int snd_soc_register_codec(struct device *dev, | |||
4411 | return -ENOMEM; | 4406 | return -ENOMEM; |
4412 | 4407 | ||
4413 | codec->component.dapm_ptr = &codec->dapm; | 4408 | codec->component.dapm_ptr = &codec->dapm; |
4409 | codec->component.codec = codec; | ||
4414 | 4410 | ||
4415 | ret = snd_soc_component_initialize(&codec->component, | 4411 | ret = snd_soc_component_initialize(&codec->component, |
4416 | &codec_drv->component_driver, dev); | 4412 | &codec_drv->component_driver, dev); |
4417 | if (ret) | 4413 | if (ret) |
4418 | goto err_free; | 4414 | goto err_free; |
4419 | 4415 | ||
4416 | if (codec_drv->controls) { | ||
4417 | codec->component.controls = codec_drv->controls; | ||
4418 | codec->component.num_controls = codec_drv->num_controls; | ||
4419 | } | ||
4420 | if (codec_drv->dapm_widgets) { | ||
4421 | codec->component.dapm_widgets = codec_drv->dapm_widgets; | ||
4422 | codec->component.num_dapm_widgets = codec_drv->num_dapm_widgets; | ||
4423 | } | ||
4424 | if (codec_drv->dapm_routes) { | ||
4425 | codec->component.dapm_routes = codec_drv->dapm_routes; | ||
4426 | codec->component.num_dapm_routes = codec_drv->num_dapm_routes; | ||
4427 | } | ||
4428 | |||
4429 | if (codec_drv->probe) | ||
4430 | codec->component.probe = snd_soc_codec_drv_probe; | ||
4431 | if (codec_drv->remove) | ||
4432 | codec->component.remove = snd_soc_codec_drv_remove; | ||
4420 | if (codec_drv->write) | 4433 | if (codec_drv->write) |
4421 | codec->component.write = snd_soc_codec_drv_write; | 4434 | codec->component.write = snd_soc_codec_drv_write; |
4422 | if (codec_drv->read) | 4435 | if (codec_drv->read) |
diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 6307f85e871b..b329b84bc5af 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c | |||
@@ -336,10 +336,12 @@ static const struct snd_pcm_ops dmaengine_pcm_ops = { | |||
336 | }; | 336 | }; |
337 | 337 | ||
338 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { | 338 | static const struct snd_soc_platform_driver dmaengine_pcm_platform = { |
339 | .component_driver = { | ||
340 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
341 | }, | ||
339 | .ops = &dmaengine_pcm_ops, | 342 | .ops = &dmaengine_pcm_ops, |
340 | .pcm_new = dmaengine_pcm_new, | 343 | .pcm_new = dmaengine_pcm_new, |
341 | .pcm_free = dmaengine_pcm_free, | 344 | .pcm_free = dmaengine_pcm_free, |
342 | .probe_order = SND_SOC_COMP_ORDER_LATE, | ||
343 | }; | 345 | }; |
344 | 346 | ||
345 | static const char * const dmaengine_pcm_dma_channel_names[] = { | 347 | static const char * const dmaengine_pcm_dma_channel_names[] = { |