[RESEND PATCH v3 0/5] soundwire: add static port map support
Resending this as I realized that alsa-devel list was missing in cc!
In some cases, SoundWire device ports are statically mapped to Controller ports during design, however there is no way to expose this information to the controller. Controllers like Qualcomm ones use this info to setup static bandwidth parameters for those ports.
A generic port allocation is not possible in this cases! This patch adds a new member m_port_map to SoundWire device so that it can populate the static master port map and share it with controller to be able to setup correct bandwidth parameters.
As a user of this feature this patchset also adds new bindings for wsa881x smart speaker which has 4 ports which are statically mapped to the 3 output and 1 input port of the controller.
Tested it on DB845c and SM8250 MTP.
thanks, srini
Changes since v2: - fixed dt_binding_check error and kernel test robot reported errors - updated comments as suggested by Pierre - updated wsa881x to populate m_ports from valid index.
Srinivas Kandagatla (5): soundwire: add static port mapping support soundwire: qcom: update port map allocation bit mask soundwire: qcom: add static port map support ASoC: dt-bindings: wsa881x: add bindings for port mapping ASoC: codecs: wsa881x: add static port map support
.../bindings/sound/qcom,wsa881x.yaml | 9 ++++++ drivers/soundwire/qcom.c | 31 +++++++++++++++---- include/linux/soundwire/sdw.h | 2 ++ sound/soc/codecs/wsa881x.c | 7 +++++ 4 files changed, 43 insertions(+), 6 deletions(-)
Some of the SoundWire device ports are statically mapped to Controller ports during design, however there is no way to expose this information to the controller. Controllers like Qualcomm ones use this info to setup static bandwith parameters for those ports.
A generic port allocation is not possible in this cases! So this patch adds a new member m_port_map to struct sdw_slave to expose this static map.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- include/linux/soundwire/sdw.h | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/include/linux/soundwire/sdw.h b/include/linux/soundwire/sdw.h index d08039d65825..b032d6ac0b39 100644 --- a/include/linux/soundwire/sdw.h +++ b/include/linux/soundwire/sdw.h @@ -614,6 +614,7 @@ struct sdw_slave_ops { * @debugfs: Slave debugfs * @node: node for bus list * @port_ready: Port ready completion flag for each Slave port + * @m_port_map: static Master port map for each Slave port0 to port14 * @dev_num: Current Device Number, values can be 0 or dev_num_sticky * @dev_num_sticky: one-time static Device Number assigned by Bus * @probed: boolean tracking driver state @@ -645,6 +646,7 @@ struct sdw_slave { #endif struct list_head node; struct completion port_ready[SDW_MAX_PORTS]; + unsigned int m_port_map[SDW_MAX_PORTS]; enum sdw_clk_stop_mode curr_clk_stop_mode; u16 dev_num; u16 dev_num_sticky;
currently the internal bitmask used for allocating ports starts with offset 0. This is bit confusing as data port numbers on Qualcomm controller are valid from 1 to 14. So adjust this bit mask accordingly, this will also help while adding static port map support.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- drivers/soundwire/qcom.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 6d22df01f354..9e70c53e2c7b 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -519,7 +519,7 @@ static void qcom_swrm_stream_free_ports(struct qcom_swrm_ctrl *ctrl, port_mask = &ctrl->din_port_mask;
list_for_each_entry(p_rt, &m_rt->port_list, port_node) - clear_bit(p_rt->num - 1, port_mask); + clear_bit(p_rt->num, port_mask); }
mutex_unlock(&ctrl->port_lock); @@ -552,13 +552,13 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, list_for_each_entry(p_rt, &s_rt->port_list, port_node) { /* Port numbers start from 1 - 14*/ pn = find_first_zero_bit(port_mask, maxport); - if (pn > (maxport - 1)) { + if (pn > maxport) { dev_err(ctrl->dev, "All ports busy\n"); ret = -EBUSY; goto err; } set_bit(pn, port_mask); - pconfig[nports].num = pn + 1; + pconfig[nports].num = pn; pconfig[nports].ch_mask = p_rt->ch_mask; nports++; } @@ -580,7 +580,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, err: if (ret) { for (i = 0; i < nports; i++) - clear_bit(pconfig[i].num - 1, port_mask); + clear_bit(pconfig[i].num, port_mask); }
mutex_unlock(&ctrl->port_lock); @@ -754,6 +754,9 @@ static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl) ctrl->num_dout_ports = val;
nports = ctrl->num_dout_ports + ctrl->num_din_ports; + /* Valid port numbers are from 1-14, so mask out port 0 explicitly */ + set_bit(0, &ctrl->dout_port_mask); + set_bit(0, &ctrl->din_port_mask);
ret = of_property_read_u8_array(np, "qcom,ports-offset1", off1, nports);
SoundWire device ports are statically mapped to Controller ports during design. Add support to read these from SoundWire devices. This controller uses static port map info to setup bandwidth parameters for those ports.
A generic port allocation is not possible in this cases!
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- drivers/soundwire/qcom.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c index 9e70c53e2c7b..39222b04a2e0 100644 --- a/drivers/soundwire/qcom.c +++ b/drivers/soundwire/qcom.c @@ -460,6 +460,8 @@ static int qcom_swrm_compute_params(struct sdw_bus *bus) struct sdw_slave_runtime *s_rt; struct sdw_port_runtime *p_rt; struct qcom_swrm_port_config *pcfg; + struct sdw_slave *slave; + unsigned int m_port; int i = 0;
list_for_each_entry(m_rt, &bus->m_rt_list, bus_node) { @@ -473,8 +475,14 @@ static int qcom_swrm_compute_params(struct sdw_bus *bus) }
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { + slave = s_rt->slave; list_for_each_entry(p_rt, &s_rt->port_list, port_node) { - pcfg = &ctrl->pconfig[i]; + m_port = slave->m_port_map[p_rt->num]; + /* port config starts at offset 0 so -1 from actual port number */ + if (m_port) + pcfg = &ctrl->pconfig[m_port - 1]; + else + pcfg = &ctrl->pconfig[i]; p_rt->transport_params.port_num = p_rt->num; p_rt->transport_params.sample_interval = pcfg->si + 1; @@ -535,8 +543,10 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, struct sdw_master_runtime *m_rt; struct sdw_slave_runtime *s_rt; struct sdw_port_runtime *p_rt; + struct sdw_slave *slave; unsigned long *port_mask; int i, maxport, pn, nports = 0, ret = 0; + unsigned int m_port;
mutex_lock(&ctrl->port_lock); list_for_each_entry(m_rt, &stream->master_list, stream_node) { @@ -549,9 +559,15 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl, }
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) { + slave = s_rt->slave; list_for_each_entry(p_rt, &s_rt->port_list, port_node) { + m_port = slave->m_port_map[p_rt->num]; /* Port numbers start from 1 - 14*/ - pn = find_first_zero_bit(port_mask, maxport); + if (m_port) + pn = m_port; + else + pn = find_first_zero_bit(port_mask, maxport); + if (pn > maxport) { dev_err(ctrl->dev, "All ports busy\n"); ret = -EBUSY;
WSA881x SoundWire device ports are statically assigned to master ports at design time. So add bindings required to specify these mappings!
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- .../devicetree/bindings/sound/qcom,wsa881x.yaml | 9 +++++++++ 1 file changed, 9 insertions(+)
diff --git a/Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml b/Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml index ea44d03e58ca..491ce1270cb5 100644 --- a/Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml +++ b/Documentation/devicetree/bindings/sound/qcom,wsa881x.yaml @@ -26,6 +26,13 @@ properties: description: GPIO spec for Powerdown/Shutdown line to use maxItems: 1
+ qcom,port-mapping: + description: | + Specifies static port mapping between slave and master ports. + In the order of slave port index. + maxItems: 4 + $ref: /schemas/types.yaml#/definitions/uint32-array + '#thermal-sensor-cells': const: 0
@@ -54,6 +61,7 @@ examples: powerdown-gpios = <&wcdpinctrl 2 0>; #thermal-sensor-cells = <0>; #sound-dai-cells = <0>; + qcom,port-mapping = <1 2 3 7>; };
speaker@0,2 { @@ -62,6 +70,7 @@ examples: powerdown-gpios = <&wcdpinctrl 2 0>; #thermal-sensor-cells = <0>; #sound-dai-cells = <0>; + qcom,port-mapping = <4 5 6 8>; }; };
Two instances of WSA881x(Speaker Right, Speaker Left) ports are statically mapped to master ports. Allow the driver to parse those mappings from device tree.
Signed-off-by: Srinivas Kandagatla srinivas.kandagatla@linaro.org --- sound/soc/codecs/wsa881x.c | 7 +++++++ 1 file changed, 7 insertions(+)
diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index db87e07b11c9..b3568aec0cd0 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1093,6 +1093,7 @@ static int wsa881x_probe(struct sdw_slave *pdev, const struct sdw_device_id *id) { struct wsa881x_priv *wsa881x; + struct device *dev = &pdev->dev;
wsa881x = devm_kzalloc(&pdev->dev, sizeof(*wsa881x), GFP_KERNEL); if (!wsa881x) @@ -1105,6 +1106,12 @@ static int wsa881x_probe(struct sdw_slave *pdev, return PTR_ERR(wsa881x->sd_n); }
+ /* valid port numbers on this codec starts from 1, so skip 0th index */ + if (of_property_read_u32_array(dev->of_node, "qcom,port-mapping", + &pdev->m_port_map[1], + WSA881X_MAX_SWR_PORTS)) + dev_info(dev, "Static Port mapping not specified\n"); + dev_set_drvdata(&pdev->dev, wsa881x); wsa881x->slave = pdev; wsa881x->dev = &pdev->dev;
participants (1)
-
Srinivas Kandagatla