aboutsummaryrefslogtreecommitdiffstats
path: root/sound
diff options
context:
space:
mode:
authorPeter Ujfalusi <peter.ujfalusi@ti.com>2011-07-02 19:06:07 -0400
committerPeter Ujfalusi <peter.ujfalusi@ti.com>2011-07-07 07:23:45 -0400
commit753621c2155bd49bff7d5d3844b3ddc203e44a06 (patch)
treede6e77bf22a784b5662a0ab1a19bb18c7b73c680 /sound
parentf53c346c08425b6448cf9729e882e4057ea505f0 (diff)
ASoC: twl6040: Configure PLL only once
Avoid configuring the PLL several times during audio startup. We can configure the PLL at prepare time with parameters collected earlier hw_param, and set_dai_sysclk calls. Signed-off-by: Peter Ujfalusi <peter.ujfalusi@ti.com> Acked-by: Mark Brown <broonie@opensource.wolfsonmicro.com>
Diffstat (limited to 'sound')
-rw-r--r--sound/soc/codecs/twl6040.c72
1 files changed, 27 insertions, 45 deletions
diff --git a/sound/soc/codecs/twl6040.c b/sound/soc/codecs/twl6040.c
index c72268bf663a..bd364c3a97c8 100644
--- a/sound/soc/codecs/twl6040.c
+++ b/sound/soc/codecs/twl6040.c
@@ -1343,9 +1343,6 @@ static int twl6040_set_bias_level(struct snd_soc_codec *codec,
1343 break; 1343 break;
1344 } 1344 }
1345 1345
1346 /* get PLL and sysclk after power transition */
1347 priv->pll = twl6040_get_pll(twl6040);
1348 priv->sysclk = twl6040_get_sysclk(twl6040);
1349 codec->dapm.bias_level = level; 1346 codec->dapm.bias_level = level;
1350 1347
1351 return 0; 1348 return 0;
@@ -1371,14 +1368,8 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
1371{ 1368{
1372 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1369 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1373 struct snd_soc_codec *codec = rtd->codec; 1370 struct snd_soc_codec *codec = rtd->codec;
1374 struct twl6040 *twl6040 = codec->control_data;
1375 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1371 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1376 unsigned int sysclk; 1372 int rate;
1377 int rate, ret;
1378
1379 /* nothing to do for high-perf pll, it supports only 48 kHz */
1380 if (priv->pll == TWL6040_HPPLL_ID)
1381 return 0;
1382 1373
1383 rate = params_rate(params); 1374 rate = params_rate(params);
1384 switch (rate) { 1375 switch (rate) {
@@ -1386,26 +1377,33 @@ static int twl6040_hw_params(struct snd_pcm_substream *substream,
1386 case 22500: 1377 case 22500:
1387 case 44100: 1378 case 44100:
1388 case 88200: 1379 case 88200:
1389 sysclk = 17640000; 1380 /* These rates are not supported when HPPLL is in use */
1381 if (unlikely(priv->pll == TWL6040_SYSCLK_SEL_HPPLL)) {
1382 dev_err(codec->dev, "HPPLL does not support rate %d\n",
1383 rate);
1384 return -EINVAL;
1385 }
1386 /* Capture is not supported with 17.64MHz sysclk */
1387 if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1388 dev_err(codec->dev,
1389 "capture mode is not supported at %dHz\n",
1390 rate);
1391 return -EINVAL;
1392 }
1393 priv->sysclk = 17640000;
1390 break; 1394 break;
1391 case 8000: 1395 case 8000:
1392 case 16000: 1396 case 16000:
1393 case 32000: 1397 case 32000:
1394 case 48000: 1398 case 48000:
1395 case 96000: 1399 case 96000:
1396 sysclk = 19200000; 1400 priv->sysclk = 19200000;
1397 break; 1401 break;
1398 default: 1402 default:
1399 dev_err(codec->dev, "unsupported rate %d\n", rate); 1403 dev_err(codec->dev, "unsupported rate %d\n", rate);
1400 return -EINVAL; 1404 return -EINVAL;
1401 } 1405 }
1402 1406
1403 ret = twl6040_set_pll(twl6040, TWL6040_LPPLL_ID, priv->clk_in, sysclk);
1404 if (ret)
1405 return ret;
1406
1407 priv->sysclk = twl6040_get_sysclk(twl6040);
1408
1409 return 0; 1407 return 0;
1410} 1408}
1411 1409
@@ -1414,7 +1412,9 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
1414{ 1412{
1415 struct snd_soc_pcm_runtime *rtd = substream->private_data; 1413 struct snd_soc_pcm_runtime *rtd = substream->private_data;
1416 struct snd_soc_codec *codec = rtd->codec; 1414 struct snd_soc_codec *codec = rtd->codec;
1415 struct twl6040 *twl6040 = codec->control_data;
1417 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1416 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1417 int ret;
1418 1418
1419 if (!priv->sysclk) { 1419 if (!priv->sysclk) {
1420 dev_err(codec->dev, 1420 dev_err(codec->dev,
@@ -1422,24 +1422,19 @@ static int twl6040_prepare(struct snd_pcm_substream *substream,
1422 return -EINVAL; 1422 return -EINVAL;
1423 } 1423 }
1424 1424
1425 /*
1426 * capture is not supported at 17.64 MHz,
1427 * it's reserved for headset low-power playback scenario
1428 */
1429 if ((priv->sysclk == 17640000) &&
1430 substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
1431 dev_err(codec->dev,
1432 "capture mode is not supported at %dHz\n",
1433 priv->sysclk);
1434 return -EINVAL;
1435 }
1436
1437 if ((priv->sysclk == 17640000) && priv->non_lp) { 1425 if ((priv->sysclk == 17640000) && priv->non_lp) {
1438 dev_err(codec->dev, 1426 dev_err(codec->dev,
1439 "some enabled paths aren't supported at %dHz\n", 1427 "some enabled paths aren't supported at %dHz\n",
1440 priv->sysclk); 1428 priv->sysclk);
1441 return -EPERM; 1429 return -EPERM;
1442 } 1430 }
1431
1432 ret = twl6040_set_pll(twl6040, priv->pll, priv->clk_in, priv->sysclk);
1433 if (ret) {
1434 dev_err(codec->dev, "Can not set PLL (%d)\n", ret);
1435 return -EPERM;
1436 }
1437
1443 return 0; 1438 return 0;
1444} 1439}
1445 1440
@@ -1447,32 +1442,19 @@ static int twl6040_set_dai_sysclk(struct snd_soc_dai *codec_dai,
1447 int clk_id, unsigned int freq, int dir) 1442 int clk_id, unsigned int freq, int dir)
1448{ 1443{
1449 struct snd_soc_codec *codec = codec_dai->codec; 1444 struct snd_soc_codec *codec = codec_dai->codec;
1450 struct twl6040 *twl6040 = codec->control_data;
1451 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec); 1445 struct twl6040_data *priv = snd_soc_codec_get_drvdata(codec);
1452 int ret = 0;
1453 1446
1454 switch (clk_id) { 1447 switch (clk_id) {
1455 case TWL6040_SYSCLK_SEL_LPPLL: 1448 case TWL6040_SYSCLK_SEL_LPPLL:
1456 ret = twl6040_set_pll(twl6040, TWL6040_LPPLL_ID,
1457 freq, priv->sysclk);
1458 if (ret)
1459 return ret;
1460 break;
1461 case TWL6040_SYSCLK_SEL_HPPLL: 1449 case TWL6040_SYSCLK_SEL_HPPLL:
1462 ret = twl6040_set_pll(twl6040, TWL6040_HPPLL_ID, 1450 priv->pll = clk_id;
1463 freq, priv->sysclk); 1451 priv->clk_in = freq;
1464 if (ret)
1465 return ret;
1466 break; 1452 break;
1467 default: 1453 default:
1468 dev_err(codec->dev, "unknown clk_id %d\n", clk_id); 1454 dev_err(codec->dev, "unknown clk_id %d\n", clk_id);
1469 return -EINVAL; 1455 return -EINVAL;
1470 } 1456 }
1471 1457
1472 priv->pll = twl6040_get_pll(twl6040);
1473 priv->clk_in = freq;
1474 priv->sysclk = twl6040_get_sysclk(twl6040);
1475
1476 return 0; 1458 return 0;
1477} 1459}
1478 1460