aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorShawn Guo <shawn.guo@linaro.org>2013-12-13 01:43:03 -0500
committerMark Brown <broonie@linaro.org>2013-12-18 13:49:17 -0500
commit11db0da831b1e6ae3c1f8743599434281db294db (patch)
treef71ee7cb739714ef6553fa8e6560bb3c0fa555f5
parent252e91ff1094eefacd25b401c3b77e549803cae6 (diff)
ASoC: sgtl5000: clean up sgtl5000_enable_regulators()
Function sgtl5000_enable_regulators() is somehow odd in handling the optional external VDDD supply. The driver can only enable this supply on SGTL5000 chip before revision 0x11, and of course when this external VDDD is present. It currently does something like below. 1. Check if regulator_bulk_get() on VDDA, VDDIO and VDDD will fail. If it fails, VDDD must be absent and it falls on internal LDO by calling sgtl5000_replace_vddd_with_ldo(). Otherwise, VDDD is used. And in either case, regulator_bulk_enable() will be called to enable 3 supplies. 2. In case that SGTL5000 revision is later than 0x11, even if external VDDD is present, it has to roll back the 'enable' and 'get' calls with regulator_bulk_disable() and regulator_bulk_free(), and starts over again by calling sgtl5000_replace_vddd_with_ldo() and regulator_bulk_enable(). Such back and forth calls sequence is complicated and unnecessary. Also, since commit 4ddfebd (regulator: core: Provide a dummy regulator with full constraints), regulator_bulk_get() will always succeeds because of the dummy regulator. Thus the VDDD detection is broken. The patch changes the flow to something like the following, which should be more reasonable and clear, and also fix the VDDD detection breakage. 1. Check if we're running a chip before revision 0x11, on which an external VDDD can possibly be an option. 2. If it is an early revision, call regulator_get_optional() to detect whether an external VDDD supply is available. 3. If external VDDD is present, call sgtl5000_replace_vddd_with_ldo() to update sgtl5000->supplies info. 4. Drop regulator_bulk_get() call in sgtl5000_replace_vddd_with_ldo(), and call it in sgtl5000_enable_regulators() no matter it's an external VDDD or internal LDO. 5. Call regulator_bulk_enable() to enable these 3 regulators. Signed-off-by: Shawn Guo <shawn.guo@linaro.org> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/codecs/sgtl5000.c62
1 files changed, 22 insertions, 40 deletions
diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c
index bd291d2b327d..0fcbe90f3ef2 100644
--- a/sound/soc/codecs/sgtl5000.c
+++ b/sound/soc/codecs/sgtl5000.c
@@ -1286,15 +1286,6 @@ static int sgtl5000_replace_vddd_with_ldo(struct snd_soc_codec *codec)
1286 1286
1287 sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME; 1287 sgtl5000->supplies[VDDD].supply = LDO_CONSUMER_NAME;
1288 1288
1289 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
1290 sgtl5000->supplies);
1291
1292 if (ret) {
1293 ldo_regulator_remove(codec);
1294 dev_err(codec->dev, "Failed to request supplies: %d\n", ret);
1295 return ret;
1296 }
1297
1298 dev_info(codec->dev, "Using internal LDO instead of VDDD\n"); 1289 dev_info(codec->dev, "Using internal LDO instead of VDDD\n");
1299 return 0; 1290 return 0;
1300} 1291}
@@ -1305,20 +1296,35 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
1305 int i; 1296 int i;
1306 int external_vddd = 0; 1297 int external_vddd = 0;
1307 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec); 1298 struct sgtl5000_priv *sgtl5000 = snd_soc_codec_get_drvdata(codec);
1299 struct regulator *vddd;
1308 1300
1309 for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++) 1301 for (i = 0; i < ARRAY_SIZE(sgtl5000->supplies); i++)
1310 sgtl5000->supplies[i].supply = supply_names[i]; 1302 sgtl5000->supplies[i].supply = supply_names[i];
1311 1303
1312 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies), 1304 /* External VDDD only works before revision 0x11 */
1313 sgtl5000->supplies); 1305 if (sgtl5000->revision < 0x11) {
1314 if (!ret) 1306 vddd = regulator_get_optional(codec->dev, "VDDD");
1315 external_vddd = 1; 1307 if (IS_ERR(vddd)) {
1316 else { 1308 /* See if it's just not registered yet */
1309 if (PTR_ERR(vddd) == -EPROBE_DEFER)
1310 return -EPROBE_DEFER;
1311 } else {
1312 external_vddd = 1;
1313 regulator_put(vddd);
1314 }
1315 }
1316
1317 if (!external_vddd) {
1317 ret = sgtl5000_replace_vddd_with_ldo(codec); 1318 ret = sgtl5000_replace_vddd_with_ldo(codec);
1318 if (ret) 1319 if (ret)
1319 return ret; 1320 return ret;
1320 } 1321 }
1321 1322
1323 ret = regulator_bulk_get(codec->dev, ARRAY_SIZE(sgtl5000->supplies),
1324 sgtl5000->supplies);
1325 if (ret)
1326 goto err_ldo_remove;
1327
1322 ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies), 1328 ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
1323 sgtl5000->supplies); 1329 sgtl5000->supplies);
1324 if (ret) 1330 if (ret)
@@ -1327,37 +1333,13 @@ static int sgtl5000_enable_regulators(struct snd_soc_codec *codec)
1327 /* wait for all power rails bring up */ 1333 /* wait for all power rails bring up */
1328 udelay(10); 1334 udelay(10);
1329 1335
1330 /*
1331 * workaround for revision 0x11 and later,
1332 * roll back to use internal LDO
1333 */
1334 if (external_vddd && sgtl5000->revision >= 0x11) {
1335 /* disable all regulator first */
1336 regulator_bulk_disable(ARRAY_SIZE(sgtl5000->supplies),
1337 sgtl5000->supplies);
1338 /* free VDDD regulator */
1339 regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
1340 sgtl5000->supplies);
1341
1342 ret = sgtl5000_replace_vddd_with_ldo(codec);
1343 if (ret)
1344 return ret;
1345
1346 ret = regulator_bulk_enable(ARRAY_SIZE(sgtl5000->supplies),
1347 sgtl5000->supplies);
1348 if (ret)
1349 goto err_regulator_free;
1350
1351 /* wait for all power rails bring up */
1352 udelay(10);
1353 }
1354
1355 return 0; 1336 return 0;
1356 1337
1357err_regulator_free: 1338err_regulator_free:
1358 regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies), 1339 regulator_bulk_free(ARRAY_SIZE(sgtl5000->supplies),
1359 sgtl5000->supplies); 1340 sgtl5000->supplies);
1360 if (external_vddd) 1341err_ldo_remove:
1342 if (!external_vddd)
1361 ldo_regulator_remove(codec); 1343 ldo_regulator_remove(codec);
1362 return ret; 1344 return ret;
1363 1345