aboutsummaryrefslogtreecommitdiffstats
path: root/sound/soc/codecs/wm_adsp.c
diff options
context:
space:
mode:
Diffstat (limited to 'sound/soc/codecs/wm_adsp.c')
-rw-r--r--sound/soc/codecs/wm_adsp.c201
1 files changed, 122 insertions, 79 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 4fbcab63e61f..444626fcab40 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1286,6 +1286,7 @@ static int wm_adsp_load_coeff(struct wm_adsp *dsp)
1286 reg = wm_adsp_region_to_reg(mem, 1286 reg = wm_adsp_region_to_reg(mem,
1287 reg); 1287 reg);
1288 reg += offset; 1288 reg += offset;
1289 break;
1289 } 1290 }
1290 } 1291 }
1291 1292
@@ -1468,8 +1469,8 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
1468 unsigned int val; 1469 unsigned int val;
1469 int ret, count; 1470 int ret, count;
1470 1471
1471 ret = regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL, 1472 ret = regmap_update_bits_async(dsp->regmap, dsp->base + ADSP2_CONTROL,
1472 ADSP2_SYS_ENA, ADSP2_SYS_ENA); 1473 ADSP2_SYS_ENA, ADSP2_SYS_ENA);
1473 if (ret != 0) 1474 if (ret != 0)
1474 return ret; 1475 return ret;
1475 1476
@@ -1492,112 +1493,153 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
1492 } 1493 }
1493 1494
1494 adsp_dbg(dsp, "RAM ready after %d polls\n", count); 1495 adsp_dbg(dsp, "RAM ready after %d polls\n", count);
1495 adsp_info(dsp, "RAM ready after %d polls\n", count);
1496 1496
1497 return 0; 1497 return 0;
1498} 1498}
1499 1499
1500int wm_adsp2_event(struct snd_soc_dapm_widget *w, 1500static void wm_adsp2_boot_work(struct work_struct *work)
1501 struct snd_kcontrol *kcontrol, int event)
1502{ 1501{
1503 struct snd_soc_codec *codec = w->codec; 1502 struct wm_adsp *dsp = container_of(work,
1504 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1503 struct wm_adsp,
1505 struct wm_adsp *dsp = &dsps[w->shift]; 1504 boot_work);
1506 struct wm_adsp_alg_region *alg_region;
1507 struct wm_coeff_ctl *ctl;
1508 unsigned int val;
1509 int ret; 1505 int ret;
1506 unsigned int val;
1510 1507
1511 dsp->card = codec->card; 1508 /*
1509 * For simplicity set the DSP clock rate to be the
1510 * SYSCLK rate rather than making it configurable.
1511 */
1512 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
1513 if (ret != 0) {
1514 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
1515 return;
1516 }
1517 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1518 >> ARIZONA_SYSCLK_FREQ_SHIFT;
1512 1519
1513 switch (event) { 1520 ret = regmap_update_bits_async(dsp->regmap,
1514 case SND_SOC_DAPM_POST_PMU: 1521 dsp->base + ADSP2_CLOCKING,
1515 /* 1522 ADSP2_CLK_SEL_MASK, val);
1516 * For simplicity set the DSP clock rate to be the 1523 if (ret != 0) {
1517 * SYSCLK rate rather than making it configurable. 1524 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
1518 */ 1525 return;
1519 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); 1526 }
1520 if (ret != 0) {
1521 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
1522 ret);
1523 return ret;
1524 }
1525 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1526 >> ARIZONA_SYSCLK_FREQ_SHIFT;
1527 1527
1528 ret = regmap_update_bits(dsp->regmap, 1528 if (dsp->dvfs) {
1529 dsp->base + ADSP2_CLOCKING, 1529 ret = regmap_read(dsp->regmap,
1530 ADSP2_CLK_SEL_MASK, val); 1530 dsp->base + ADSP2_CLOCKING, &val);
1531 if (ret != 0) { 1531 if (ret != 0) {
1532 adsp_err(dsp, "Failed to set clock rate: %d\n", 1532 dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
1533 ret); 1533 return;
1534 return ret;
1535 } 1534 }
1536 1535
1537 if (dsp->dvfs) { 1536 if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
1538 ret = regmap_read(dsp->regmap, 1537 ret = regulator_enable(dsp->dvfs);
1539 dsp->base + ADSP2_CLOCKING, &val);
1540 if (ret != 0) { 1538 if (ret != 0) {
1541 dev_err(dsp->dev, 1539 dev_err(dsp->dev,
1542 "Failed to read clocking: %d\n", ret); 1540 "Failed to enable supply: %d\n",
1543 return ret; 1541 ret);
1542 return;
1544 } 1543 }
1545 1544
1546 if ((val & ADSP2_CLK_SEL_MASK) >= 3) { 1545 ret = regulator_set_voltage(dsp->dvfs,
1547 ret = regulator_enable(dsp->dvfs); 1546 1800000,
1548 if (ret != 0) { 1547 1800000);
1549 dev_err(dsp->dev, 1548 if (ret != 0) {
1550 "Failed to enable supply: %d\n", 1549 dev_err(dsp->dev,
1551 ret); 1550 "Failed to raise supply: %d\n",
1552 return ret; 1551 ret);
1553 } 1552 return;
1554
1555 ret = regulator_set_voltage(dsp->dvfs,
1556 1800000,
1557 1800000);
1558 if (ret != 0) {
1559 dev_err(dsp->dev,
1560 "Failed to raise supply: %d\n",
1561 ret);
1562 return ret;
1563 }
1564 } 1553 }
1565 } 1554 }
1555 }
1566 1556
1567 ret = wm_adsp2_ena(dsp); 1557 ret = wm_adsp2_ena(dsp);
1568 if (ret != 0) 1558 if (ret != 0)
1569 return ret; 1559 return;
1570 1560
1571 ret = wm_adsp_load(dsp); 1561 ret = wm_adsp_load(dsp);
1572 if (ret != 0) 1562 if (ret != 0)
1573 goto err; 1563 goto err;
1574 1564
1575 ret = wm_adsp_setup_algs(dsp); 1565 ret = wm_adsp_setup_algs(dsp);
1576 if (ret != 0) 1566 if (ret != 0)
1577 goto err; 1567 goto err;
1578 1568
1579 ret = wm_adsp_load_coeff(dsp); 1569 ret = wm_adsp_load_coeff(dsp);
1580 if (ret != 0) 1570 if (ret != 0)
1581 goto err; 1571 goto err;
1582 1572
1583 /* Initialize caches for enabled and unset controls */ 1573 /* Initialize caches for enabled and unset controls */
1584 ret = wm_coeff_init_control_caches(dsp); 1574 ret = wm_coeff_init_control_caches(dsp);
1585 if (ret != 0) 1575 if (ret != 0)
1586 goto err; 1576 goto err;
1587 1577
1588 /* Sync set controls */ 1578 /* Sync set controls */
1589 ret = wm_coeff_sync_controls(dsp); 1579 ret = wm_coeff_sync_controls(dsp);
1590 if (ret != 0) 1580 if (ret != 0)
1591 goto err; 1581 goto err;
1582
1583 ret = regmap_update_bits_async(dsp->regmap,
1584 dsp->base + ADSP2_CONTROL,
1585 ADSP2_CORE_ENA,
1586 ADSP2_CORE_ENA);
1587 if (ret != 0)
1588 goto err;
1589
1590 dsp->running = true;
1591
1592 return;
1593
1594err:
1595 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1596 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
1597}
1598
1599int wm_adsp2_early_event(struct snd_soc_dapm_widget *w,
1600 struct snd_kcontrol *kcontrol, int event)
1601{
1602 struct snd_soc_codec *codec = w->codec;
1603 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1604 struct wm_adsp *dsp = &dsps[w->shift];
1605
1606 dsp->card = codec->card;
1607
1608 switch (event) {
1609 case SND_SOC_DAPM_PRE_PMU:
1610 queue_work(system_unbound_wq, &dsp->boot_work);
1611 break;
1612 default:
1613 break;
1614 };
1615
1616 return 0;
1617}
1618EXPORT_SYMBOL_GPL(wm_adsp2_early_event);
1619
1620int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1621 struct snd_kcontrol *kcontrol, int event)
1622{
1623 struct snd_soc_codec *codec = w->codec;
1624 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1625 struct wm_adsp *dsp = &dsps[w->shift];
1626 struct wm_adsp_alg_region *alg_region;
1627 struct wm_coeff_ctl *ctl;
1628 int ret;
1629
1630 switch (event) {
1631 case SND_SOC_DAPM_POST_PMU:
1632 flush_work(&dsp->boot_work);
1633
1634 if (!dsp->running)
1635 return -EIO;
1592 1636
1593 ret = regmap_update_bits(dsp->regmap, 1637 ret = regmap_update_bits(dsp->regmap,
1594 dsp->base + ADSP2_CONTROL, 1638 dsp->base + ADSP2_CONTROL,
1595 ADSP2_CORE_ENA | ADSP2_START, 1639 ADSP2_START,
1596 ADSP2_CORE_ENA | ADSP2_START); 1640 ADSP2_START);
1597 if (ret != 0) 1641 if (ret != 0)
1598 goto err; 1642 goto err;
1599
1600 dsp->running = true;
1601 break; 1643 break;
1602 1644
1603 case SND_SOC_DAPM_PRE_PMD: 1645 case SND_SOC_DAPM_PRE_PMD:
@@ -1668,6 +1710,7 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1668 1710
1669 INIT_LIST_HEAD(&adsp->alg_regions); 1711 INIT_LIST_HEAD(&adsp->alg_regions);
1670 INIT_LIST_HEAD(&adsp->ctl_list); 1712 INIT_LIST_HEAD(&adsp->ctl_list);
1713 INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
1671 1714
1672 if (dvfs) { 1715 if (dvfs) {
1673 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1716 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");