diff options
-rw-r--r-- | sound/soc/codecs/wm_adsp.c | 181 | ||||
-rw-r--r-- | sound/soc/codecs/wm_adsp.h | 2 |
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 | ||
1495 | int wm_adsp2_event(struct snd_soc_dapm_widget *w, | 1495 | void 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, | 1589 | err: |
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 | |||
1594 | int 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) \ |