aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCharles Keepax <ckeepax@opensource.wolfsonmicro.com>2014-03-07 11:34:20 -0500
committerMark Brown <broonie@linaro.org>2014-03-09 04:28:06 -0400
commit23f785a8bc33a98c4c384a653b9bff9c0cc3591d (patch)
treeaf6793ec409d88b878d12492379eefaef5163a7f
parent61719db8141acde1a6293bbbddc733655defcc3c (diff)
ASoC: arizona: Move calculation of FLL configuration
Currently the FLL configuration is calculated before it is known which FLL path the configuration will be applied to. Newer versions of the IP have differences in the configuration required for each FLL path, which makes it complicated to calculate the FLL configuration in advance. This patch simply checks the validity of a requested input and output frequency before we know which FLL path they will be applied to and saves the actual calculation of the configuration until we know where the settings will be applied. Signed-off-by: Charles Keepax <ckeepax@opensource.wolfsonmicro.com> Signed-off-by: Mark Brown <broonie@linaro.org>
-rw-r--r--sound/soc/codecs/arizona.c79
1 files changed, 44 insertions, 35 deletions
diff --git a/sound/soc/codecs/arizona.c b/sound/soc/codecs/arizona.c
index 9afd8c41d143..7398c69192cb 100644
--- a/sound/soc/codecs/arizona.c
+++ b/sound/soc/codecs/arizona.c
@@ -1383,6 +1383,29 @@ struct arizona_fll_cfg {
1383 int gain; 1383 int gain;
1384}; 1384};
1385 1385
1386static int arizona_validate_fll(struct arizona_fll *fll,
1387 unsigned int Fref,
1388 unsigned int Fout)
1389{
1390 unsigned int Fvco_min;
1391
1392 if (Fref / ARIZONA_FLL_MAX_REFDIV > ARIZONA_FLL_MAX_FREF) {
1393 arizona_fll_err(fll,
1394 "Can't scale %dMHz in to <=13.5MHz\n",
1395 Fref);
1396 return -EINVAL;
1397 }
1398
1399 Fvco_min = ARIZONA_FLL_MIN_FVCO * fll->vco_mult;
1400 if (Fout * ARIZONA_FLL_MAX_OUTDIV < Fvco_min) {
1401 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1402 Fout);
1403 return -EINVAL;
1404 }
1405
1406 return 0;
1407}
1408
1386static int arizona_calc_fll(struct arizona_fll *fll, 1409static int arizona_calc_fll(struct arizona_fll *fll,
1387 struct arizona_fll_cfg *cfg, 1410 struct arizona_fll_cfg *cfg,
1388 unsigned int Fref, 1411 unsigned int Fref,
@@ -1400,12 +1423,8 @@ static int arizona_calc_fll(struct arizona_fll *fll,
1400 div *= 2; 1423 div *= 2;
1401 cfg->refdiv++; 1424 cfg->refdiv++;
1402 1425
1403 if (div > ARIZONA_FLL_MAX_REFDIV) { 1426 if (div > ARIZONA_FLL_MAX_REFDIV)
1404 arizona_fll_err(fll,
1405 "Can't scale %dMHz in to <=13.5MHz\n",
1406 Fref);
1407 return -EINVAL; 1427 return -EINVAL;
1408 }
1409 } 1428 }
1410 1429
1411 /* Apply the division for our remaining calculations */ 1430 /* Apply the division for our remaining calculations */
@@ -1415,11 +1434,8 @@ static int arizona_calc_fll(struct arizona_fll *fll,
1415 div = ARIZONA_FLL_MIN_OUTDIV; 1434 div = ARIZONA_FLL_MIN_OUTDIV;
1416 while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) { 1435 while (Fout * div < ARIZONA_FLL_MIN_FVCO * fll->vco_mult) {
1417 div++; 1436 div++;
1418 if (div > ARIZONA_FLL_MAX_OUTDIV) { 1437 if (div > ARIZONA_FLL_MAX_OUTDIV)
1419 arizona_fll_err(fll, "No FLL_OUTDIV for Fout=%uHz\n",
1420 Fout);
1421 return -EINVAL; 1438 return -EINVAL;
1422 }
1423 } 1439 }
1424 target = Fout * div / fll->vco_mult; 1440 target = Fout * div / fll->vco_mult;
1425 cfg->outdiv = div; 1441 cfg->outdiv = div;
@@ -1536,13 +1552,12 @@ static bool arizona_is_enabled_fll(struct arizona_fll *fll)
1536 return reg & ARIZONA_FLL1_ENA; 1552 return reg & ARIZONA_FLL1_ENA;
1537} 1553}
1538 1554
1539static void arizona_enable_fll(struct arizona_fll *fll, 1555static void arizona_enable_fll(struct arizona_fll *fll)
1540 struct arizona_fll_cfg *ref,
1541 struct arizona_fll_cfg *sync)
1542{ 1556{
1543 struct arizona *arizona = fll->arizona; 1557 struct arizona *arizona = fll->arizona;
1544 int ret; 1558 int ret;
1545 bool use_sync = false; 1559 bool use_sync = false;
1560 struct arizona_fll_cfg cfg;
1546 1561
1547 /* 1562 /*
1548 * If we have both REFCLK and SYNCCLK then enable both, 1563 * If we have both REFCLK and SYNCCLK then enable both,
@@ -1550,15 +1565,21 @@ static void arizona_enable_fll(struct arizona_fll *fll,
1550 */ 1565 */
1551 if (fll->ref_src >= 0 && fll->ref_freq && 1566 if (fll->ref_src >= 0 && fll->ref_freq &&
1552 fll->ref_src != fll->sync_src) { 1567 fll->ref_src != fll->sync_src) {
1553 arizona_apply_fll(arizona, fll->base, ref, fll->ref_src, 1568 arizona_calc_fll(fll, &cfg, fll->ref_freq, fll->fout);
1569
1570 arizona_apply_fll(arizona, fll->base, &cfg, fll->ref_src,
1554 false); 1571 false);
1555 if (fll->sync_src >= 0) { 1572 if (fll->sync_src >= 0) {
1556 arizona_apply_fll(arizona, fll->base + 0x10, sync, 1573 arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout);
1574
1575 arizona_apply_fll(arizona, fll->base + 0x10, &cfg,
1557 fll->sync_src, true); 1576 fll->sync_src, true);
1558 use_sync = true; 1577 use_sync = true;
1559 } 1578 }
1560 } else if (fll->sync_src >= 0) { 1579 } else if (fll->sync_src >= 0) {
1561 arizona_apply_fll(arizona, fll->base, sync, 1580 arizona_calc_fll(fll, &cfg, fll->sync_freq, fll->fout);
1581
1582 arizona_apply_fll(arizona, fll->base, &cfg,
1562 fll->sync_src, false); 1583 fll->sync_src, false);
1563 1584
1564 regmap_update_bits_async(arizona->regmap, fll->base + 0x11, 1585 regmap_update_bits_async(arizona->regmap, fll->base + 0x11,
@@ -1620,32 +1641,22 @@ static void arizona_disable_fll(struct arizona_fll *fll)
1620int arizona_set_fll_refclk(struct arizona_fll *fll, int source, 1641int arizona_set_fll_refclk(struct arizona_fll *fll, int source,
1621 unsigned int Fref, unsigned int Fout) 1642 unsigned int Fref, unsigned int Fout)
1622{ 1643{
1623 struct arizona_fll_cfg ref, sync;
1624 int ret; 1644 int ret;
1625 1645
1626 if (fll->ref_src == source && fll->ref_freq == Fref) 1646 if (fll->ref_src == source && fll->ref_freq == Fref)
1627 return 0; 1647 return 0;
1628 1648
1629 if (fll->fout) { 1649 if (fll->fout && Fref > 0) {
1630 if (Fref > 0) { 1650 ret = arizona_validate_fll(fll, Fref, fll->fout);
1631 ret = arizona_calc_fll(fll, &ref, Fref, fll->fout); 1651 if (ret != 0)
1632 if (ret != 0) 1652 return ret;
1633 return ret;
1634 }
1635
1636 if (fll->sync_src >= 0) {
1637 ret = arizona_calc_fll(fll, &sync, fll->sync_freq,
1638 fll->fout);
1639 if (ret != 0)
1640 return ret;
1641 }
1642 } 1653 }
1643 1654
1644 fll->ref_src = source; 1655 fll->ref_src = source;
1645 fll->ref_freq = Fref; 1656 fll->ref_freq = Fref;
1646 1657
1647 if (fll->fout && Fref > 0) { 1658 if (fll->fout && Fref > 0) {
1648 arizona_enable_fll(fll, &ref, &sync); 1659 arizona_enable_fll(fll);
1649 } 1660 }
1650 1661
1651 return 0; 1662 return 0;
@@ -1655,7 +1666,6 @@ EXPORT_SYMBOL_GPL(arizona_set_fll_refclk);
1655int arizona_set_fll(struct arizona_fll *fll, int source, 1666int arizona_set_fll(struct arizona_fll *fll, int source,
1656 unsigned int Fref, unsigned int Fout) 1667 unsigned int Fref, unsigned int Fout)
1657{ 1668{
1658 struct arizona_fll_cfg ref, sync;
1659 int ret; 1669 int ret;
1660 1670
1661 if (fll->sync_src == source && 1671 if (fll->sync_src == source &&
@@ -1664,13 +1674,12 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
1664 1674
1665 if (Fout) { 1675 if (Fout) {
1666 if (fll->ref_src >= 0) { 1676 if (fll->ref_src >= 0) {
1667 ret = arizona_calc_fll(fll, &ref, fll->ref_freq, 1677 ret = arizona_validate_fll(fll, fll->ref_freq, Fout);
1668 Fout);
1669 if (ret != 0) 1678 if (ret != 0)
1670 return ret; 1679 return ret;
1671 } 1680 }
1672 1681
1673 ret = arizona_calc_fll(fll, &sync, Fref, Fout); 1682 ret = arizona_validate_fll(fll, Fref, Fout);
1674 if (ret != 0) 1683 if (ret != 0)
1675 return ret; 1684 return ret;
1676 } 1685 }
@@ -1680,7 +1689,7 @@ int arizona_set_fll(struct arizona_fll *fll, int source,
1680 fll->fout = Fout; 1689 fll->fout = Fout;
1681 1690
1682 if (Fout) { 1691 if (Fout) {
1683 arizona_enable_fll(fll, &ref, &sync); 1692 arizona_enable_fll(fll);
1684 } else { 1693 } else {
1685 arizona_disable_fll(fll); 1694 arizona_disable_fll(fll);
1686 } 1695 }