diff options
author | Shreyas NC <shreyas.nc@intel.com> | 2016-08-12 02:59:51 -0400 |
---|---|---|
committer | Mark Brown <broonie@kernel.org> | 2016-08-22 13:44:11 -0400 |
commit | 6277e83292a2d4d88d150c0eb3004bd714ad8728 (patch) | |
tree | 63b9ddf85a9677f4efb397e1c719dc7cd6442d6c /sound | |
parent | 15f0d4f531d84015511dbdc2512e5a77c0173d49 (diff) |
ASoC: Intel: Skylake: Parse vendor tokens to build module data
Skl topology data is preceded by a descriptor for number of data
blocks, the size of the data block and type of data block. The
type of the data block can be either a tuple or a binary blob.
Private data is parsed based on data block type and module data
is filled accordingly.
Signed-off-by: Shreyas NC <shreyas.nc@intel.com>
Signed-off-by: Vinod Koul <vinod.koul@intel.com>
Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'sound')
-rw-r--r-- | sound/soc/intel/skylake/skl-topology.c | 645 | ||||
-rw-r--r-- | sound/soc/intel/skylake/skl-tplg-interface.h | 10 |
2 files changed, 545 insertions, 110 deletions
diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index 4bc8f9c269db..000482e6e2f7 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c | |||
@@ -21,6 +21,7 @@ | |||
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
22 | #include <sound/soc.h> | 22 | #include <sound/soc.h> |
23 | #include <sound/soc-topology.h> | 23 | #include <sound/soc-topology.h> |
24 | #include <uapi/sound/snd_sst_tokens.h> | ||
24 | #include "skl-sst-dsp.h" | 25 | #include "skl-sst-dsp.h" |
25 | #include "skl-sst-ipc.h" | 26 | #include "skl-sst-ipc.h" |
26 | #include "skl-topology.h" | 27 | #include "skl-topology.h" |
@@ -32,6 +33,8 @@ | |||
32 | #define SKL_CH_FIXUP_MASK (1 << 0) | 33 | #define SKL_CH_FIXUP_MASK (1 << 0) |
33 | #define SKL_RATE_FIXUP_MASK (1 << 1) | 34 | #define SKL_RATE_FIXUP_MASK (1 << 1) |
34 | #define SKL_FMT_FIXUP_MASK (1 << 2) | 35 | #define SKL_FMT_FIXUP_MASK (1 << 2) |
36 | #define SKL_IN_DIR_BIT_MASK BIT(0) | ||
37 | #define SKL_PIN_COUNT_MASK GENMASK(7, 4) | ||
35 | 38 | ||
36 | /* | 39 | /* |
37 | * SKL DSP driver modelling uses only few DAPM widgets so for rest we will | 40 | * SKL DSP driver modelling uses only few DAPM widgets so for rest we will |
@@ -1468,85 +1471,570 @@ static const struct snd_soc_tplg_bytes_ext_ops skl_tlv_ops[] = { | |||
1468 | skl_tplg_tlv_control_set}, | 1471 | skl_tplg_tlv_control_set}, |
1469 | }; | 1472 | }; |
1470 | 1473 | ||
1471 | /* | 1474 | static int skl_tplg_fill_pipe_tkn(struct device *dev, |
1472 | * The topology binary passes the pin info for a module so initialize the pin | 1475 | struct skl_pipe *pipe, u32 tkn, |
1473 | * info passed into module instance | 1476 | u32 tkn_val) |
1474 | */ | ||
1475 | static void skl_fill_module_pin_info(struct skl_dfw_module_pin *dfw_pin, | ||
1476 | struct skl_module_pin *m_pin, | ||
1477 | bool is_dynamic, int max_pin) | ||
1478 | { | 1477 | { |
1479 | int i; | ||
1480 | 1478 | ||
1481 | for (i = 0; i < max_pin; i++) { | 1479 | switch (tkn) { |
1482 | m_pin[i].id.module_id = dfw_pin[i].module_id; | 1480 | case SKL_TKN_U32_PIPE_CONN_TYPE: |
1483 | m_pin[i].id.instance_id = dfw_pin[i].instance_id; | 1481 | pipe->conn_type = tkn_val; |
1484 | m_pin[i].in_use = false; | 1482 | break; |
1485 | m_pin[i].is_dynamic = is_dynamic; | 1483 | |
1486 | m_pin[i].pin_state = SKL_PIN_UNBIND; | 1484 | case SKL_TKN_U32_PIPE_PRIORITY: |
1485 | pipe->pipe_priority = tkn_val; | ||
1486 | break; | ||
1487 | |||
1488 | case SKL_TKN_U32_PIPE_MEM_PGS: | ||
1489 | pipe->memory_pages = tkn_val; | ||
1490 | break; | ||
1491 | |||
1492 | default: | ||
1493 | dev_err(dev, "Token not handled %d\n", tkn); | ||
1494 | return -EINVAL; | ||
1487 | } | 1495 | } |
1496 | |||
1497 | return 0; | ||
1488 | } | 1498 | } |
1489 | 1499 | ||
1490 | /* | 1500 | /* |
1491 | * Add pipeline from topology binary into driver pipeline list | 1501 | * Add pipeline by parsing the relevant tokens |
1492 | * | 1502 | * Return an existing pipe if the pipe already exists. |
1493 | * If already added we return that instance | ||
1494 | * Otherwise we create a new instance and add into driver list | ||
1495 | */ | 1503 | */ |
1496 | static struct skl_pipe *skl_tplg_add_pipe(struct device *dev, | 1504 | static int skl_tplg_add_pipe(struct device *dev, |
1497 | struct skl *skl, struct skl_dfw_pipe *dfw_pipe) | 1505 | struct skl_module_cfg *mconfig, struct skl *skl, |
1506 | struct snd_soc_tplg_vendor_value_elem *tkn_elem) | ||
1498 | { | 1507 | { |
1499 | struct skl_pipeline *ppl; | 1508 | struct skl_pipeline *ppl; |
1500 | struct skl_pipe *pipe; | 1509 | struct skl_pipe *pipe; |
1501 | struct skl_pipe_params *params; | 1510 | struct skl_pipe_params *params; |
1502 | 1511 | ||
1503 | list_for_each_entry(ppl, &skl->ppl_list, node) { | 1512 | list_for_each_entry(ppl, &skl->ppl_list, node) { |
1504 | if (ppl->pipe->ppl_id == dfw_pipe->pipe_id) | 1513 | if (ppl->pipe->ppl_id == tkn_elem->value) { |
1505 | return ppl->pipe; | 1514 | mconfig->pipe = ppl->pipe; |
1515 | return EEXIST; | ||
1516 | } | ||
1506 | } | 1517 | } |
1507 | 1518 | ||
1508 | ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); | 1519 | ppl = devm_kzalloc(dev, sizeof(*ppl), GFP_KERNEL); |
1509 | if (!ppl) | 1520 | if (!ppl) |
1510 | return NULL; | 1521 | return -ENOMEM; |
1511 | 1522 | ||
1512 | pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); | 1523 | pipe = devm_kzalloc(dev, sizeof(*pipe), GFP_KERNEL); |
1513 | if (!pipe) | 1524 | if (!pipe) |
1514 | return NULL; | 1525 | return -ENOMEM; |
1515 | 1526 | ||
1516 | params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); | 1527 | params = devm_kzalloc(dev, sizeof(*params), GFP_KERNEL); |
1517 | if (!params) | 1528 | if (!params) |
1518 | return NULL; | 1529 | return -ENOMEM; |
1519 | 1530 | ||
1520 | pipe->ppl_id = dfw_pipe->pipe_id; | ||
1521 | pipe->memory_pages = dfw_pipe->memory_pages; | ||
1522 | pipe->pipe_priority = dfw_pipe->pipe_priority; | ||
1523 | pipe->conn_type = dfw_pipe->conn_type; | ||
1524 | pipe->state = SKL_PIPE_INVALID; | ||
1525 | pipe->p_params = params; | 1531 | pipe->p_params = params; |
1532 | pipe->ppl_id = tkn_elem->value; | ||
1526 | INIT_LIST_HEAD(&pipe->w_list); | 1533 | INIT_LIST_HEAD(&pipe->w_list); |
1527 | 1534 | ||
1528 | ppl->pipe = pipe; | 1535 | ppl->pipe = pipe; |
1529 | list_add(&ppl->node, &skl->ppl_list); | 1536 | list_add(&ppl->node, &skl->ppl_list); |
1530 | 1537 | ||
1531 | return ppl->pipe; | 1538 | mconfig->pipe = pipe; |
1539 | mconfig->pipe->state = SKL_PIPE_INVALID; | ||
1540 | |||
1541 | return 0; | ||
1542 | } | ||
1543 | |||
1544 | static int skl_tplg_fill_pin(struct device *dev, u32 tkn, | ||
1545 | struct skl_module_pin *m_pin, | ||
1546 | int pin_index, u32 value) | ||
1547 | { | ||
1548 | switch (tkn) { | ||
1549 | case SKL_TKN_U32_PIN_MOD_ID: | ||
1550 | m_pin[pin_index].id.module_id = value; | ||
1551 | break; | ||
1552 | |||
1553 | case SKL_TKN_U32_PIN_INST_ID: | ||
1554 | m_pin[pin_index].id.instance_id = value; | ||
1555 | break; | ||
1556 | |||
1557 | default: | ||
1558 | dev_err(dev, "%d Not a pin token\n", value); | ||
1559 | return -EINVAL; | ||
1560 | } | ||
1561 | |||
1562 | return 0; | ||
1563 | } | ||
1564 | |||
1565 | /* | ||
1566 | * Parse for pin config specific tokens to fill up the | ||
1567 | * module private data | ||
1568 | */ | ||
1569 | static int skl_tplg_fill_pins_info(struct device *dev, | ||
1570 | struct skl_module_cfg *mconfig, | ||
1571 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, | ||
1572 | int dir, int pin_count) | ||
1573 | { | ||
1574 | int ret; | ||
1575 | struct skl_module_pin *m_pin; | ||
1576 | |||
1577 | switch (dir) { | ||
1578 | case SKL_DIR_IN: | ||
1579 | m_pin = mconfig->m_in_pin; | ||
1580 | break; | ||
1581 | |||
1582 | case SKL_DIR_OUT: | ||
1583 | m_pin = mconfig->m_out_pin; | ||
1584 | break; | ||
1585 | |||
1586 | default: | ||
1587 | dev_err(dev, "Invalid direction value"); | ||
1588 | return -EINVAL; | ||
1589 | } | ||
1590 | |||
1591 | ret = skl_tplg_fill_pin(dev, tkn_elem->token, | ||
1592 | m_pin, pin_count, tkn_elem->value); | ||
1593 | |||
1594 | if (ret < 0) | ||
1595 | return ret; | ||
1596 | |||
1597 | m_pin[pin_count].in_use = false; | ||
1598 | m_pin[pin_count].pin_state = SKL_PIN_UNBIND; | ||
1599 | |||
1600 | return 0; | ||
1532 | } | 1601 | } |
1533 | 1602 | ||
1534 | static void skl_tplg_fill_fmt(struct skl_module_fmt *dst_fmt, | 1603 | /* |
1535 | struct skl_dfw_module_fmt *src_fmt, | 1604 | * Fill up input/output module config format based |
1536 | int pins) | 1605 | * on the direction |
1606 | */ | ||
1607 | static int skl_tplg_fill_fmt(struct device *dev, | ||
1608 | struct skl_module_cfg *mconfig, u32 tkn, | ||
1609 | u32 value, u32 dir, u32 pin_count) | ||
1610 | { | ||
1611 | struct skl_module_fmt *dst_fmt; | ||
1612 | |||
1613 | switch (dir) { | ||
1614 | case SKL_DIR_IN: | ||
1615 | dst_fmt = mconfig->in_fmt; | ||
1616 | dst_fmt += pin_count; | ||
1617 | break; | ||
1618 | |||
1619 | case SKL_DIR_OUT: | ||
1620 | dst_fmt = mconfig->out_fmt; | ||
1621 | dst_fmt += pin_count; | ||
1622 | break; | ||
1623 | |||
1624 | default: | ||
1625 | dev_err(dev, "Invalid direction value"); | ||
1626 | return -EINVAL; | ||
1627 | } | ||
1628 | |||
1629 | switch (tkn) { | ||
1630 | case SKL_TKN_U32_FMT_CH: | ||
1631 | dst_fmt->channels = value; | ||
1632 | break; | ||
1633 | |||
1634 | case SKL_TKN_U32_FMT_FREQ: | ||
1635 | dst_fmt->s_freq = value; | ||
1636 | break; | ||
1637 | |||
1638 | case SKL_TKN_U32_FMT_BIT_DEPTH: | ||
1639 | dst_fmt->bit_depth = value; | ||
1640 | break; | ||
1641 | |||
1642 | case SKL_TKN_U32_FMT_SAMPLE_SIZE: | ||
1643 | dst_fmt->valid_bit_depth = value; | ||
1644 | break; | ||
1645 | |||
1646 | case SKL_TKN_U32_FMT_CH_CONFIG: | ||
1647 | dst_fmt->ch_cfg = value; | ||
1648 | break; | ||
1649 | |||
1650 | case SKL_TKN_U32_FMT_INTERLEAVE: | ||
1651 | dst_fmt->interleaving_style = value; | ||
1652 | break; | ||
1653 | |||
1654 | case SKL_TKN_U32_FMT_SAMPLE_TYPE: | ||
1655 | dst_fmt->sample_type = value; | ||
1656 | break; | ||
1657 | |||
1658 | case SKL_TKN_U32_FMT_CH_MAP: | ||
1659 | dst_fmt->ch_map = value; | ||
1660 | break; | ||
1661 | |||
1662 | default: | ||
1663 | dev_err(dev, "Invalid token %d", tkn); | ||
1664 | return -EINVAL; | ||
1665 | } | ||
1666 | |||
1667 | return 0; | ||
1668 | } | ||
1669 | |||
1670 | static int skl_tplg_get_uuid(struct device *dev, struct skl_module_cfg *mconfig, | ||
1671 | struct snd_soc_tplg_vendor_uuid_elem *uuid_tkn) | ||
1672 | { | ||
1673 | if (uuid_tkn->token == SKL_TKN_UUID) | ||
1674 | memcpy(&mconfig->guid, &uuid_tkn->uuid, 16); | ||
1675 | else { | ||
1676 | dev_err(dev, "Not an UUID token tkn %d", uuid_tkn->token); | ||
1677 | return -EINVAL; | ||
1678 | } | ||
1679 | |||
1680 | return 0; | ||
1681 | } | ||
1682 | |||
1683 | static void skl_tplg_fill_pin_dynamic_val( | ||
1684 | struct skl_module_pin *mpin, u32 pin_count, u32 value) | ||
1537 | { | 1685 | { |
1538 | int i; | 1686 | int i; |
1539 | 1687 | ||
1540 | for (i = 0; i < pins; i++) { | 1688 | for (i = 0; i < pin_count; i++) |
1541 | dst_fmt[i].channels = src_fmt[i].channels; | 1689 | mpin[i].is_dynamic = value; |
1542 | dst_fmt[i].s_freq = src_fmt[i].freq; | 1690 | } |
1543 | dst_fmt[i].bit_depth = src_fmt[i].bit_depth; | 1691 | |
1544 | dst_fmt[i].valid_bit_depth = src_fmt[i].valid_bit_depth; | 1692 | /* |
1545 | dst_fmt[i].ch_cfg = src_fmt[i].ch_cfg; | 1693 | * Parse tokens to fill up the module private data |
1546 | dst_fmt[i].ch_map = src_fmt[i].ch_map; | 1694 | */ |
1547 | dst_fmt[i].interleaving_style = src_fmt[i].interleaving_style; | 1695 | static int skl_tplg_get_token(struct device *dev, |
1548 | dst_fmt[i].sample_type = src_fmt[i].sample_type; | 1696 | struct snd_soc_tplg_vendor_value_elem *tkn_elem, |
1697 | struct skl *skl, struct skl_module_cfg *mconfig) | ||
1698 | { | ||
1699 | int tkn_count = 0; | ||
1700 | int ret; | ||
1701 | static int is_pipe_exists; | ||
1702 | static int pin_index, dir; | ||
1703 | |||
1704 | if (tkn_elem->token > SKL_TKN_MAX) | ||
1705 | return -EINVAL; | ||
1706 | |||
1707 | switch (tkn_elem->token) { | ||
1708 | case SKL_TKN_U8_IN_QUEUE_COUNT: | ||
1709 | mconfig->max_in_queue = tkn_elem->value; | ||
1710 | mconfig->m_in_pin = devm_kzalloc(dev, mconfig->max_in_queue * | ||
1711 | sizeof(*mconfig->m_in_pin), | ||
1712 | GFP_KERNEL); | ||
1713 | if (!mconfig->m_in_pin) | ||
1714 | return -ENOMEM; | ||
1715 | |||
1716 | break; | ||
1717 | |||
1718 | case SKL_TKN_U8_OUT_QUEUE_COUNT: | ||
1719 | mconfig->max_out_queue = tkn_elem->value; | ||
1720 | mconfig->m_out_pin = devm_kzalloc(dev, mconfig->max_out_queue * | ||
1721 | sizeof(*mconfig->m_out_pin), | ||
1722 | GFP_KERNEL); | ||
1723 | |||
1724 | if (!mconfig->m_out_pin) | ||
1725 | return -ENOMEM; | ||
1726 | |||
1727 | break; | ||
1728 | |||
1729 | case SKL_TKN_U8_DYN_IN_PIN: | ||
1730 | if (!mconfig->m_in_pin) | ||
1731 | return -ENOMEM; | ||
1732 | |||
1733 | skl_tplg_fill_pin_dynamic_val(mconfig->m_in_pin, | ||
1734 | mconfig->max_in_queue, tkn_elem->value); | ||
1735 | |||
1736 | break; | ||
1737 | |||
1738 | case SKL_TKN_U8_DYN_OUT_PIN: | ||
1739 | if (!mconfig->m_out_pin) | ||
1740 | return -ENOMEM; | ||
1741 | |||
1742 | skl_tplg_fill_pin_dynamic_val(mconfig->m_out_pin, | ||
1743 | mconfig->max_out_queue, tkn_elem->value); | ||
1744 | |||
1745 | break; | ||
1746 | |||
1747 | case SKL_TKN_U8_TIME_SLOT: | ||
1748 | mconfig->time_slot = tkn_elem->value; | ||
1749 | break; | ||
1750 | |||
1751 | case SKL_TKN_U8_CORE_ID: | ||
1752 | mconfig->core_id = tkn_elem->value; | ||
1753 | |||
1754 | case SKL_TKN_U8_MOD_TYPE: | ||
1755 | mconfig->m_type = tkn_elem->value; | ||
1756 | break; | ||
1757 | |||
1758 | case SKL_TKN_U8_DEV_TYPE: | ||
1759 | mconfig->dev_type = tkn_elem->value; | ||
1760 | break; | ||
1761 | |||
1762 | case SKL_TKN_U8_HW_CONN_TYPE: | ||
1763 | mconfig->hw_conn_type = tkn_elem->value; | ||
1764 | break; | ||
1765 | |||
1766 | case SKL_TKN_U16_MOD_INST_ID: | ||
1767 | mconfig->id.instance_id = | ||
1768 | tkn_elem->value; | ||
1769 | break; | ||
1770 | |||
1771 | case SKL_TKN_U32_MEM_PAGES: | ||
1772 | mconfig->mem_pages = tkn_elem->value; | ||
1773 | break; | ||
1774 | |||
1775 | case SKL_TKN_U32_MAX_MCPS: | ||
1776 | mconfig->mcps = tkn_elem->value; | ||
1777 | break; | ||
1778 | |||
1779 | case SKL_TKN_U32_OBS: | ||
1780 | mconfig->obs = tkn_elem->value; | ||
1781 | break; | ||
1782 | |||
1783 | case SKL_TKN_U32_IBS: | ||
1784 | mconfig->ibs = tkn_elem->value; | ||
1785 | break; | ||
1786 | |||
1787 | case SKL_TKN_U32_VBUS_ID: | ||
1788 | mconfig->vbus_id = tkn_elem->value; | ||
1789 | break; | ||
1790 | |||
1791 | case SKL_TKN_U32_PARAMS_FIXUP: | ||
1792 | mconfig->params_fixup = tkn_elem->value; | ||
1793 | break; | ||
1794 | |||
1795 | case SKL_TKN_U32_CONVERTER: | ||
1796 | mconfig->converter = tkn_elem->value; | ||
1797 | break; | ||
1798 | |||
1799 | case SKL_TKN_U32_PIPE_ID: | ||
1800 | ret = skl_tplg_add_pipe(dev, | ||
1801 | mconfig, skl, tkn_elem); | ||
1802 | |||
1803 | if (ret < 0) | ||
1804 | return is_pipe_exists; | ||
1805 | |||
1806 | if (ret == EEXIST) | ||
1807 | is_pipe_exists = 1; | ||
1808 | |||
1809 | break; | ||
1810 | |||
1811 | case SKL_TKN_U32_PIPE_CONN_TYPE: | ||
1812 | case SKL_TKN_U32_PIPE_PRIORITY: | ||
1813 | case SKL_TKN_U32_PIPE_MEM_PGS: | ||
1814 | if (is_pipe_exists) { | ||
1815 | ret = skl_tplg_fill_pipe_tkn(dev, mconfig->pipe, | ||
1816 | tkn_elem->token, tkn_elem->value); | ||
1817 | if (ret < 0) | ||
1818 | return ret; | ||
1819 | } | ||
1820 | |||
1821 | break; | ||
1822 | |||
1823 | /* | ||
1824 | * SKL_TKN_U32_DIR_PIN_COUNT token has the value for both | ||
1825 | * direction and the pin count. The first four bits represent | ||
1826 | * direction and next four the pin count. | ||
1827 | */ | ||
1828 | case SKL_TKN_U32_DIR_PIN_COUNT: | ||
1829 | dir = tkn_elem->value & SKL_IN_DIR_BIT_MASK; | ||
1830 | pin_index = (tkn_elem->value & | ||
1831 | SKL_PIN_COUNT_MASK) >> 4; | ||
1832 | |||
1833 | break; | ||
1834 | |||
1835 | case SKL_TKN_U32_FMT_CH: | ||
1836 | case SKL_TKN_U32_FMT_FREQ: | ||
1837 | case SKL_TKN_U32_FMT_BIT_DEPTH: | ||
1838 | case SKL_TKN_U32_FMT_SAMPLE_SIZE: | ||
1839 | case SKL_TKN_U32_FMT_CH_CONFIG: | ||
1840 | case SKL_TKN_U32_FMT_INTERLEAVE: | ||
1841 | case SKL_TKN_U32_FMT_SAMPLE_TYPE: | ||
1842 | case SKL_TKN_U32_FMT_CH_MAP: | ||
1843 | ret = skl_tplg_fill_fmt(dev, mconfig, tkn_elem->token, | ||
1844 | tkn_elem->value, dir, pin_index); | ||
1845 | |||
1846 | if (ret < 0) | ||
1847 | return ret; | ||
1848 | |||
1849 | break; | ||
1850 | |||
1851 | case SKL_TKN_U32_PIN_MOD_ID: | ||
1852 | case SKL_TKN_U32_PIN_INST_ID: | ||
1853 | ret = skl_tplg_fill_pins_info(dev, | ||
1854 | mconfig, tkn_elem, dir, | ||
1855 | pin_index); | ||
1856 | if (ret < 0) | ||
1857 | return ret; | ||
1858 | |||
1859 | break; | ||
1860 | |||
1861 | case SKL_TKN_U32_CAPS_SIZE: | ||
1862 | mconfig->formats_config.caps_size = | ||
1863 | tkn_elem->value; | ||
1864 | |||
1865 | break; | ||
1866 | |||
1867 | case SKL_TKN_U32_PROC_DOMAIN: | ||
1868 | mconfig->domain = | ||
1869 | tkn_elem->value; | ||
1870 | |||
1871 | break; | ||
1872 | |||
1873 | case SKL_TKN_U8_IN_PIN_TYPE: | ||
1874 | case SKL_TKN_U8_OUT_PIN_TYPE: | ||
1875 | case SKL_TKN_U8_CONN_TYPE: | ||
1876 | break; | ||
1877 | |||
1878 | default: | ||
1879 | dev_err(dev, "Token %d not handled\n", | ||
1880 | tkn_elem->token); | ||
1881 | return -EINVAL; | ||
1549 | } | 1882 | } |
1883 | |||
1884 | tkn_count++; | ||
1885 | |||
1886 | return tkn_count; | ||
1887 | } | ||
1888 | |||
1889 | /* | ||
1890 | * Parse the vendor array for specific tokens to construct | ||
1891 | * module private data | ||
1892 | */ | ||
1893 | static int skl_tplg_get_tokens(struct device *dev, | ||
1894 | char *pvt_data, struct skl *skl, | ||
1895 | struct skl_module_cfg *mconfig, int block_size) | ||
1896 | { | ||
1897 | struct snd_soc_tplg_vendor_array *array; | ||
1898 | struct snd_soc_tplg_vendor_value_elem *tkn_elem; | ||
1899 | int tkn_count = 0, ret; | ||
1900 | int off = 0, tuple_size = 0; | ||
1901 | |||
1902 | if (block_size <= 0) | ||
1903 | return -EINVAL; | ||
1904 | |||
1905 | while (tuple_size < block_size) { | ||
1906 | array = (struct snd_soc_tplg_vendor_array *)(pvt_data + off); | ||
1907 | |||
1908 | off += array->size; | ||
1909 | |||
1910 | switch (array->type) { | ||
1911 | case SND_SOC_TPLG_TUPLE_TYPE_STRING: | ||
1912 | dev_warn(dev, "no string tokens expected for skl tplg"); | ||
1913 | continue; | ||
1914 | |||
1915 | case SND_SOC_TPLG_TUPLE_TYPE_UUID: | ||
1916 | ret = skl_tplg_get_uuid(dev, mconfig, array->uuid); | ||
1917 | if (ret < 0) | ||
1918 | return ret; | ||
1919 | |||
1920 | tuple_size += sizeof(*array->uuid); | ||
1921 | |||
1922 | continue; | ||
1923 | |||
1924 | default: | ||
1925 | tkn_elem = array->value; | ||
1926 | tkn_count = 0; | ||
1927 | break; | ||
1928 | } | ||
1929 | |||
1930 | while (tkn_count <= (array->num_elems - 1)) { | ||
1931 | ret = skl_tplg_get_token(dev, tkn_elem, | ||
1932 | skl, mconfig); | ||
1933 | |||
1934 | if (ret < 0) | ||
1935 | return ret; | ||
1936 | |||
1937 | tkn_count = tkn_count + ret; | ||
1938 | tkn_elem++; | ||
1939 | } | ||
1940 | |||
1941 | tuple_size += tkn_count * sizeof(*tkn_elem); | ||
1942 | } | ||
1943 | |||
1944 | return 0; | ||
1945 | } | ||
1946 | |||
1947 | /* | ||
1948 | * Every data block is preceded by a descriptor to read the number | ||
1949 | * of data blocks, they type of the block and it's size | ||
1950 | */ | ||
1951 | static int skl_tplg_get_desc_blocks(struct device *dev, | ||
1952 | struct snd_soc_tplg_vendor_array *array) | ||
1953 | { | ||
1954 | struct snd_soc_tplg_vendor_value_elem *tkn_elem; | ||
1955 | |||
1956 | tkn_elem = array->value; | ||
1957 | |||
1958 | switch (tkn_elem->token) { | ||
1959 | case SKL_TKN_U8_NUM_BLOCKS: | ||
1960 | case SKL_TKN_U8_BLOCK_TYPE: | ||
1961 | case SKL_TKN_U16_BLOCK_SIZE: | ||
1962 | return tkn_elem->value; | ||
1963 | |||
1964 | default: | ||
1965 | dev_err(dev, "Invalid descriptor token %d", tkn_elem->token); | ||
1966 | break; | ||
1967 | } | ||
1968 | |||
1969 | return -EINVAL; | ||
1970 | } | ||
1971 | |||
1972 | /* | ||
1973 | * Parse the private data for the token and corresponding value. | ||
1974 | * The private data can have multiple data blocks. So, a data block | ||
1975 | * is preceded by a descriptor for number of blocks and a descriptor | ||
1976 | * for the type and size of the suceeding data block. | ||
1977 | */ | ||
1978 | static int skl_tplg_get_pvt_data(struct snd_soc_tplg_dapm_widget *tplg_w, | ||
1979 | struct skl *skl, struct device *dev, | ||
1980 | struct skl_module_cfg *mconfig) | ||
1981 | { | ||
1982 | struct snd_soc_tplg_vendor_array *array; | ||
1983 | int num_blocks, block_size = 0, block_type, off = 0; | ||
1984 | char *data; | ||
1985 | int ret; | ||
1986 | |||
1987 | /* Read the NUM_DATA_BLOCKS descriptor */ | ||
1988 | array = (struct snd_soc_tplg_vendor_array *)tplg_w->priv.data; | ||
1989 | ret = skl_tplg_get_desc_blocks(dev, array); | ||
1990 | if (ret < 0) | ||
1991 | return ret; | ||
1992 | num_blocks = ret; | ||
1993 | |||
1994 | off += array->size; | ||
1995 | array = (struct snd_soc_tplg_vendor_array *)(tplg_w->priv.data + off); | ||
1996 | |||
1997 | /* Read the BLOCK_TYPE and BLOCK_SIZE descriptor */ | ||
1998 | while (num_blocks > 0) { | ||
1999 | ret = skl_tplg_get_desc_blocks(dev, array); | ||
2000 | |||
2001 | if (ret < 0) | ||
2002 | return ret; | ||
2003 | block_type = ret; | ||
2004 | off += array->size; | ||
2005 | |||
2006 | array = (struct snd_soc_tplg_vendor_array *) | ||
2007 | (tplg_w->priv.data + off); | ||
2008 | |||
2009 | ret = skl_tplg_get_desc_blocks(dev, array); | ||
2010 | |||
2011 | if (ret < 0) | ||
2012 | return ret; | ||
2013 | block_size = ret; | ||
2014 | off += array->size; | ||
2015 | |||
2016 | array = (struct snd_soc_tplg_vendor_array *) | ||
2017 | (tplg_w->priv.data + off); | ||
2018 | |||
2019 | data = (tplg_w->priv.data + off); | ||
2020 | |||
2021 | if (block_type == SKL_TYPE_TUPLE) { | ||
2022 | ret = skl_tplg_get_tokens(dev, data, | ||
2023 | skl, mconfig, block_size); | ||
2024 | |||
2025 | if (ret < 0) | ||
2026 | return ret; | ||
2027 | |||
2028 | --num_blocks; | ||
2029 | } else { | ||
2030 | if (mconfig->formats_config.caps_size > 0) | ||
2031 | memcpy(mconfig->formats_config.caps, data, | ||
2032 | mconfig->formats_config.caps_size); | ||
2033 | --num_blocks; | ||
2034 | } | ||
2035 | } | ||
2036 | |||
2037 | return 0; | ||
1550 | } | 2038 | } |
1551 | 2039 | ||
1552 | static void skl_clear_pin_config(struct snd_soc_platform *platform, | 2040 | static void skl_clear_pin_config(struct snd_soc_platform *platform, |
@@ -1614,9 +2102,6 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, | |||
1614 | struct skl *skl = ebus_to_skl(ebus); | 2102 | struct skl *skl = ebus_to_skl(ebus); |
1615 | struct hdac_bus *bus = ebus_to_hbus(ebus); | 2103 | struct hdac_bus *bus = ebus_to_hbus(ebus); |
1616 | struct skl_module_cfg *mconfig; | 2104 | struct skl_module_cfg *mconfig; |
1617 | struct skl_pipe *pipe; | ||
1618 | struct skl_dfw_module *dfw_config = | ||
1619 | (struct skl_dfw_module *)tplg_w->priv.data; | ||
1620 | 2105 | ||
1621 | if (!tplg_w->priv.size) | 2106 | if (!tplg_w->priv.size) |
1622 | goto bind_event; | 2107 | goto bind_event; |
@@ -1627,77 +2112,17 @@ static int skl_tplg_widget_load(struct snd_soc_component *cmpnt, | |||
1627 | return -ENOMEM; | 2112 | return -ENOMEM; |
1628 | 2113 | ||
1629 | w->priv = mconfig; | 2114 | w->priv = mconfig; |
1630 | memcpy(&mconfig->guid, &dfw_config->uuid, 16); | ||
1631 | 2115 | ||
1632 | /* | 2116 | /* |
1633 | * module binary can be loaded later, so set it to query when | 2117 | * module binary can be loaded later, so set it to query when |
1634 | * module is load for a use case | 2118 | * module is load for a use case |
1635 | */ | 2119 | */ |
1636 | mconfig->id.module_id = -1; | 2120 | mconfig->id.module_id = -1; |
1637 | mconfig->id.instance_id = dfw_config->instance_id; | ||
1638 | mconfig->mcps = dfw_config->max_mcps; | ||
1639 | mconfig->ibs = dfw_config->ibs; | ||
1640 | mconfig->obs = dfw_config->obs; | ||
1641 | mconfig->core_id = dfw_config->core_id; | ||
1642 | mconfig->max_in_queue = dfw_config->max_in_queue; | ||
1643 | mconfig->max_out_queue = dfw_config->max_out_queue; | ||
1644 | mconfig->is_loadable = dfw_config->is_loadable; | ||
1645 | mconfig->domain = dfw_config->proc_domain; | ||
1646 | skl_tplg_fill_fmt(mconfig->in_fmt, dfw_config->in_fmt, | ||
1647 | MODULE_MAX_IN_PINS); | ||
1648 | skl_tplg_fill_fmt(mconfig->out_fmt, dfw_config->out_fmt, | ||
1649 | MODULE_MAX_OUT_PINS); | ||
1650 | |||
1651 | mconfig->params_fixup = dfw_config->params_fixup; | ||
1652 | mconfig->converter = dfw_config->converter; | ||
1653 | mconfig->m_type = dfw_config->module_type; | ||
1654 | mconfig->vbus_id = dfw_config->vbus_id; | ||
1655 | mconfig->mem_pages = dfw_config->mem_pages; | ||
1656 | |||
1657 | pipe = skl_tplg_add_pipe(bus->dev, skl, &dfw_config->pipe); | ||
1658 | if (pipe) | ||
1659 | mconfig->pipe = pipe; | ||
1660 | |||
1661 | mconfig->dev_type = dfw_config->dev_type; | ||
1662 | mconfig->hw_conn_type = dfw_config->hw_conn_type; | ||
1663 | mconfig->time_slot = dfw_config->time_slot; | ||
1664 | mconfig->formats_config.caps_size = dfw_config->caps.caps_size; | ||
1665 | |||
1666 | mconfig->m_in_pin = devm_kzalloc(bus->dev, (mconfig->max_in_queue) * | ||
1667 | sizeof(*mconfig->m_in_pin), | ||
1668 | GFP_KERNEL); | ||
1669 | if (!mconfig->m_in_pin) | ||
1670 | return -ENOMEM; | ||
1671 | |||
1672 | mconfig->m_out_pin = devm_kzalloc(bus->dev, (mconfig->max_out_queue) * | ||
1673 | sizeof(*mconfig->m_out_pin), | ||
1674 | GFP_KERNEL); | ||
1675 | if (!mconfig->m_out_pin) | ||
1676 | return -ENOMEM; | ||
1677 | |||
1678 | skl_fill_module_pin_info(dfw_config->in_pin, mconfig->m_in_pin, | ||
1679 | dfw_config->is_dynamic_in_pin, | ||
1680 | mconfig->max_in_queue); | ||
1681 | |||
1682 | skl_fill_module_pin_info(dfw_config->out_pin, mconfig->m_out_pin, | ||
1683 | dfw_config->is_dynamic_out_pin, | ||
1684 | mconfig->max_out_queue); | ||
1685 | |||
1686 | |||
1687 | if (mconfig->formats_config.caps_size == 0) | ||
1688 | goto bind_event; | ||
1689 | |||
1690 | mconfig->formats_config.caps = (u32 *)devm_kzalloc(bus->dev, | ||
1691 | mconfig->formats_config.caps_size, GFP_KERNEL); | ||
1692 | |||
1693 | if (mconfig->formats_config.caps == NULL) | ||
1694 | return -ENOMEM; | ||
1695 | |||
1696 | memcpy(mconfig->formats_config.caps, dfw_config->caps.caps, | ||
1697 | dfw_config->caps.caps_size); | ||
1698 | mconfig->formats_config.param_id = dfw_config->caps.param_id; | ||
1699 | mconfig->formats_config.set_params = dfw_config->caps.set_params; | ||
1700 | 2121 | ||
2122 | /* Parse private data for tuples */ | ||
2123 | ret = skl_tplg_get_pvt_data(tplg_w, skl, bus->dev, mconfig); | ||
2124 | if (ret < 0) | ||
2125 | return ret; | ||
1701 | bind_event: | 2126 | bind_event: |
1702 | if (tplg_w->event_type == 0) { | 2127 | if (tplg_w->event_type == 0) { |
1703 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); | 2128 | dev_dbg(bus->dev, "ASoC: No event handler required\n"); |
diff --git a/sound/soc/intel/skylake/skl-tplg-interface.h b/sound/soc/intel/skylake/skl-tplg-interface.h index bd8b4ae43557..281762eca0ab 100644 --- a/sound/soc/intel/skylake/skl-tplg-interface.h +++ b/sound/soc/intel/skylake/skl-tplg-interface.h | |||
@@ -241,4 +241,14 @@ struct skl_dfw_manifest { | |||
241 | struct lib_info lib[HDA_MAX_LIB]; | 241 | struct lib_info lib[HDA_MAX_LIB]; |
242 | } __packed; | 242 | } __packed; |
243 | 243 | ||
244 | enum skl_tkn_dir { | ||
245 | SKL_DIR_IN, | ||
246 | SKL_DIR_OUT | ||
247 | }; | ||
248 | |||
249 | enum skl_tuple_type { | ||
250 | SKL_TYPE_TUPLE, | ||
251 | SKL_TYPE_DATA | ||
252 | }; | ||
253 | |||
244 | #endif | 254 | #endif |