aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/soc/codecs/wm_adsp.c181
-rw-r--r--sound/soc/codecs/wm_adsp.h2
2 files changed, 105 insertions, 78 deletions
diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c
index 8f720ded27c4..2087ae2eb323 100644
--- a/sound/soc/codecs/wm_adsp.c
+++ b/sound/soc/codecs/wm_adsp.c
@@ -1492,107 +1492,131 @@ static int wm_adsp2_ena(struct wm_adsp *dsp)
1492 return 0; 1492 return 0;
1493} 1493}
1494 1494
1495int wm_adsp2_event(struct snd_soc_dapm_widget *w, 1495void wm_adsp2_boot_work(struct work_struct *work)
1496 struct snd_kcontrol *kcontrol, int event)
1497{ 1496{
1498 struct snd_soc_codec *codec = w->codec; 1497 struct wm_adsp *dsp = container_of(work,
1499 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec); 1498 struct wm_adsp,
1500 struct wm_adsp *dsp = &dsps[w->shift]; 1499 boot_work);
1501 struct wm_adsp_alg_region *alg_region;
1502 struct wm_coeff_ctl *ctl;
1503 unsigned int val;
1504 int ret; 1500 int ret;
1501 unsigned int val;
1505 1502
1506 dsp->card = codec->card; 1503 /*
1504 * For simplicity set the DSP clock rate to be the
1505 * SYSCLK rate rather than making it configurable.
1506 */
1507 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val);
1508 if (ret != 0) {
1509 adsp_err(dsp, "Failed to read SYSCLK state: %d\n", ret);
1510 return;
1511 }
1512 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1513 >> ARIZONA_SYSCLK_FREQ_SHIFT;
1507 1514
1508 switch (event) { 1515 ret = regmap_update_bits_async(dsp->regmap,
1509 case SND_SOC_DAPM_POST_PMU: 1516 dsp->base + ADSP2_CLOCKING,
1510 /* 1517 ADSP2_CLK_SEL_MASK, val);
1511 * For simplicity set the DSP clock rate to be the 1518 if (ret != 0) {
1512 * SYSCLK rate rather than making it configurable. 1519 adsp_err(dsp, "Failed to set clock rate: %d\n", ret);
1513 */ 1520 return;
1514 ret = regmap_read(dsp->regmap, ARIZONA_SYSTEM_CLOCK_1, &val); 1521 }
1515 if (ret != 0) {
1516 adsp_err(dsp, "Failed to read SYSCLK state: %d\n",
1517 ret);
1518 return ret;
1519 }
1520 val = (val & ARIZONA_SYSCLK_FREQ_MASK)
1521 >> ARIZONA_SYSCLK_FREQ_SHIFT;
1522 1522
1523 ret = regmap_update_bits_async(dsp->regmap, 1523 if (dsp->dvfs) {
1524 dsp->base + ADSP2_CLOCKING, 1524 ret = regmap_read(dsp->regmap,
1525 ADSP2_CLK_SEL_MASK, val); 1525 dsp->base + ADSP2_CLOCKING, &val);
1526 if (ret != 0) { 1526 if (ret != 0) {
1527 adsp_err(dsp, "Failed to set clock rate: %d\n", 1527 dev_err(dsp->dev, "Failed to read clocking: %d\n", ret);
1528 ret); 1528 return;
1529 return ret;
1530 } 1529 }
1531 1530
1532 if (dsp->dvfs) { 1531 if ((val & ADSP2_CLK_SEL_MASK) >= 3) {
1533 ret = regmap_read(dsp->regmap, 1532 ret = regulator_enable(dsp->dvfs);
1534 dsp->base + ADSP2_CLOCKING, &val);
1535 if (ret != 0) { 1533 if (ret != 0) {
1536 dev_err(dsp->dev, 1534 dev_err(dsp->dev,
1537 "Failed to read clocking: %d\n", ret); 1535 "Failed to enable supply: %d\n",
1538 return ret; 1536 ret);
1537 return;
1539 } 1538 }
1540 1539
1541 if ((val & ADSP2_CLK_SEL_MASK) >= 3) { 1540 ret = regulator_set_voltage(dsp->dvfs,
1542 ret = regulator_enable(dsp->dvfs); 1541 1800000,
1543 if (ret != 0) { 1542 1800000);
1544 dev_err(dsp->dev, 1543 if (ret != 0) {
1545 "Failed to enable supply: %d\n", 1544 dev_err(dsp->dev,
1546 ret); 1545 "Failed to raise supply: %d\n",
1547 return ret; 1546 ret);
1548 } 1547 return;
1549
1550 ret = regulator_set_voltage(dsp->dvfs,
1551 1800000,
1552 1800000);
1553 if (ret != 0) {
1554 dev_err(dsp->dev,
1555 "Failed to raise supply: %d\n",
1556 ret);
1557 return ret;
1558 }
1559 } 1548 }
1560 } 1549 }
1550 }
1561 1551
1562 ret = wm_adsp2_ena(dsp); 1552 ret = wm_adsp2_ena(dsp);
1563 if (ret != 0) 1553 if (ret != 0)
1564 return ret; 1554 return;
1565 1555
1566 ret = wm_adsp_load(dsp); 1556 ret = wm_adsp_load(dsp);
1567 if (ret != 0) 1557 if (ret != 0)
1568 goto err; 1558 goto err;
1569 1559
1570 ret = wm_adsp_setup_algs(dsp); 1560 ret = wm_adsp_setup_algs(dsp);
1571 if (ret != 0) 1561 if (ret != 0)
1572 goto err; 1562 goto err;
1573 1563
1574 ret = wm_adsp_load_coeff(dsp); 1564 ret = wm_adsp_load_coeff(dsp);
1575 if (ret != 0) 1565 if (ret != 0)
1576 goto err; 1566 goto err;
1577 1567
1578 /* Initialize caches for enabled and unset controls */ 1568 /* Initialize caches for enabled and unset controls */
1579 ret = wm_coeff_init_control_caches(dsp); 1569 ret = wm_coeff_init_control_caches(dsp);
1580 if (ret != 0) 1570 if (ret != 0)
1581 goto err; 1571 goto err;
1582 1572
1583 /* Sync set controls */ 1573 /* Sync set controls */
1584 ret = wm_coeff_sync_controls(dsp); 1574 ret = wm_coeff_sync_controls(dsp);
1585 if (ret != 0) 1575 if (ret != 0)
1586 goto err; 1576 goto err;
1577
1578 ret = regmap_update_bits_async(dsp->regmap,
1579 dsp->base + ADSP2_CONTROL,
1580 ADSP2_CORE_ENA,
1581 ADSP2_CORE_ENA);
1582 if (ret != 0)
1583 goto err;
1584
1585 dsp->running = true;
1586
1587 return;
1587 1588
1588 ret = regmap_update_bits_async(dsp->regmap, 1589err:
1589 dsp->base + ADSP2_CONTROL, 1590 regmap_update_bits(dsp->regmap, dsp->base + ADSP2_CONTROL,
1590 ADSP2_CORE_ENA | ADSP2_START, 1591 ADSP2_SYS_ENA | ADSP2_CORE_ENA | ADSP2_START, 0);
1591 ADSP2_CORE_ENA | ADSP2_START); 1592}
1593
1594int wm_adsp2_event(struct snd_soc_dapm_widget *w,
1595 struct snd_kcontrol *kcontrol, int event)
1596{
1597 struct snd_soc_codec *codec = w->codec;
1598 struct wm_adsp *dsps = snd_soc_codec_get_drvdata(codec);
1599 struct wm_adsp *dsp = &dsps[w->shift];
1600 struct wm_adsp_alg_region *alg_region;
1601 struct wm_coeff_ctl *ctl;
1602 int ret;
1603
1604 dsp->card = codec->card;
1605
1606 switch (event) {
1607 case SND_SOC_DAPM_POST_PMU:
1608 queue_work(system_unbound_wq, &dsp->boot_work);
1609 flush_work(&dsp->boot_work);
1610
1611 if (!dsp->running)
1612 return -EIO;
1613
1614 ret = regmap_update_bits(dsp->regmap,
1615 dsp->base + ADSP2_CONTROL,
1616 ADSP2_START,
1617 ADSP2_START);
1592 if (ret != 0) 1618 if (ret != 0)
1593 goto err; 1619 goto err;
1594
1595 dsp->running = true;
1596 break; 1620 break;
1597 1621
1598 case SND_SOC_DAPM_PRE_PMD: 1622 case SND_SOC_DAPM_PRE_PMD:
@@ -1663,6 +1687,7 @@ int wm_adsp2_init(struct wm_adsp *adsp, bool dvfs)
1663 1687
1664 INIT_LIST_HEAD(&adsp->alg_regions); 1688 INIT_LIST_HEAD(&adsp->alg_regions);
1665 INIT_LIST_HEAD(&adsp->ctl_list); 1689 INIT_LIST_HEAD(&adsp->ctl_list);
1690 INIT_WORK(&adsp->boot_work, wm_adsp2_boot_work);
1666 1691
1667 if (dvfs) { 1692 if (dvfs) {
1668 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD"); 1693 adsp->dvfs = devm_regulator_get(adsp->dev, "DCVDD");
diff --git a/sound/soc/codecs/wm_adsp.h b/sound/soc/codecs/wm_adsp.h
index d018dea6254d..b172c1df9159 100644
--- a/sound/soc/codecs/wm_adsp.h
+++ b/sound/soc/codecs/wm_adsp.h
@@ -59,6 +59,8 @@ struct wm_adsp {
59 struct regulator *dvfs; 59 struct regulator *dvfs;
60 60
61 struct list_head ctl_list; 61 struct list_head ctl_list;
62
63 struct work_struct boot_work;
62}; 64};
63 65
64#define WM_ADSP1(wname, num) \ 66#define WM_ADSP1(wname, num) \