aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars-Peter Clausen <lars@metafoo.de>2014-08-19 09:51:19 -0400
committerMark Brown <broonie@linaro.org>2014-08-19 11:59:45 -0400
commitf1d45cc3ae96a6173129b2c164c216272faa5fc0 (patch)
treed59bf61023e1fe970639016909b1e1550b129d7a
parent81c7cfd1b22a0ee5e40efef72ec2cd17dbf12e6d (diff)
ASoC: Consolidate platform and CODEC probe/remove
The platform and CODEC probe and remove code is now largely identical. This patch consolidates it at the component level. The resulting code is slightly larger due to all the boiler plate code setting up the indirection for the table based control and DAPM registration. Once all drivers have been update to no longer use the snd_soc_codec_driver and snd_soc_platform_driver specific fields for this the indirection can be removed again. This patch contains two noteworthy hacks that are only meant to be temporary to be able to update drivers and the core in separate incremental patches. The first hack is related to that some DPCM platforms expect that the DAPM widgets for the DAIs of a snd_soc_component are created in the DAPM context of the snd_soc_platform that has the same parent device. For handling this the steal_sibling_dai_widgets attribute is introduced. It gets set for snd_soc_platforms that register DAPM elements. When creating the DAI widgets for a component this flag is checked and if it is found on one of the siblings the component will not create any DAI widgets in its own DAPM context. If the attribute is set on a platform it will look for siblings components and create DAI widgets for them in its own context. The fix for this will be to update the offending drivers to only register a single component rather than two. The second hack deals with the fact that the ASoC card suspend and resume code still needs a list of CODECs that have been registered for the card. To handle this the generic probe and remove path have a check to see if the component is CODEC and if yes add/remove it to the card's CODEC list. While it is possible to clean up the suspend/resume code to not need the CODEC list anymore this is a bit of a chicken and egg problem since it will become easier to clean up the suspend/resume code once there is a unified component layer. Signed-off-by: Lars-Peter Clausen <lars@metafoo.de> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--include/sound/soc.h27
-rw-r--r--sound/soc/soc-core.c335
-rw-r--r--sound/soc/soc-generic-dmaengine-pcm.c4
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
702struct snd_soc_component { 706struct 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
988static int soc_remove_platform(struct snd_soc_platform *platform) 988static 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
1009static 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
1028static void soc_remove_codec_dai(struct snd_soc_dai *codec_dai, int order) 1004static 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
1149static int soc_probe_codec(struct snd_soc_card *card, 1124static 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
1217err_probe:
1218 soc_cleanup_component_debugfs(&codec->component);
1219 module_put(codec->dev->driver->owner);
1220
1221 return ret;
1222}
1223
1224static 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
1277err_probe: 1223err_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
1688static int snd_soc_init_codec_cache(struct snd_soc_codec *codec) 1637static int snd_soc_init_codec_cache(struct snd_soc_codec *codec)
@@ -4198,6 +4147,20 @@ found:
4198} 4147}
4199EXPORT_SYMBOL_GPL(snd_soc_unregister_component); 4148EXPORT_SYMBOL_GPL(snd_soc_unregister_component);
4200 4149
4150static 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
4157static 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
4201static int snd_soc_platform_drv_write(struct snd_soc_component *component, 4164static 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
4347static 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
4354static 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
4366static int snd_soc_codec_drv_write(struct snd_soc_component *component, 4361static 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
338static const struct snd_soc_platform_driver dmaengine_pcm_platform = { 338static 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
345static const char * const dmaengine_pcm_dma_channel_names[] = { 347static const char * const dmaengine_pcm_dma_channel_names[] = {