[PATCH v1 4/4] ASoC: codecs: wcd937x: Add static channel mapping support in wcd937x-sdw

From: Mohammad Rafi Shaik
Date: Mon Sep 09 2024 - 06:58:10 EST


Add static channel mapping between master and slave ports in
wcd937x-sdw. This patch will resolve the channel mask mismatch
between master and slave.

Signed-off-by: Mohammad Rafi Shaik <quic_mohs@xxxxxxxxxxx>
---
sound/soc/codecs/wcd937x-sdw.c | 52 ++++++++++++++++++++++++++++------
sound/soc/codecs/wcd937x.c | 12 ++++++--
sound/soc/codecs/wcd937x.h | 6 +++-
3 files changed, 59 insertions(+), 11 deletions(-)

diff --git a/sound/soc/codecs/wcd937x-sdw.c b/sound/soc/codecs/wcd937x-sdw.c
index 0c33f7f3dc25..f59068ddc26f 100644
--- a/sound/soc/codecs/wcd937x-sdw.c
+++ b/sound/soc/codecs/wcd937x-sdw.c
@@ -19,7 +19,7 @@
#include <sound/soc.h>
#include "wcd937x.h"

-static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
+static struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
WCD_SDW_CH(WCD937X_HPH_L, WCD937X_HPH_PORT, BIT(0)),
WCD_SDW_CH(WCD937X_HPH_R, WCD937X_HPH_PORT, BIT(1)),
WCD_SDW_CH(WCD937X_CLSH, WCD937X_CLSH_PORT, BIT(0)),
@@ -30,7 +30,7 @@ static const struct wcd937x_sdw_ch_info wcd937x_sdw_rx_ch_info[] = {
WCD_SDW_CH(WCD937X_DSD_R, WCD937X_DSD_PORT, BIT(1)),
};

-static const struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = {
+static struct wcd937x_sdw_ch_info wcd937x_sdw_tx_ch_info[] = {
WCD_SDW_CH(WCD937X_ADC1, WCD937X_ADC_1_PORT, BIT(0)),
WCD_SDW_CH(WCD937X_ADC2, WCD937X_ADC_2_3_PORT, BIT(0)),
WCD_SDW_CH(WCD937X_ADC3, WCD937X_ADC_2_3_PORT, BIT(0)),
@@ -91,7 +91,7 @@ int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd,
{
struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS];
unsigned long ch_mask;
- int i, j;
+ int i, j, ret = 0;

wcd->sconfig.ch_count = 1;
wcd->active_ports = 0;
@@ -112,9 +112,15 @@ int wcd937x_sdw_hw_params(struct wcd937x_sdw_priv *wcd,
wcd->sconfig.direction = wcd->is_tx ? SDW_DATA_DIR_TX : SDW_DATA_DIR_RX;
wcd->sconfig.type = SDW_STREAM_PCM;

- return sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
- &port_config[0], wcd->active_ports,
- wcd->sruntime);
+ ret = sdw_stream_add_slave(wcd->sdev, &wcd->sconfig,
+ &port_config[0], wcd->active_ports,
+ wcd->sruntime);
+ if (!ret)
+ sdw_set_channel_map_stream(wcd->sruntime,
+ wcd->master_channel_map,
+ wcd->active_ports);
+
+ return ret;
}
EXPORT_SYMBOL_GPL(wcd937x_sdw_hw_params);

@@ -1019,7 +1025,9 @@ static int wcd9370_probe(struct sdw_slave *pdev,
{
struct device *dev = &pdev->dev;
struct wcd937x_sdw_priv *wcd;
- int ret;
+ u8 master_ch_mask[WCD937X_MAX_SWR_CH_IDS];
+ int master_ch_mask_size = 0;
+ int ret, i;

wcd = devm_kzalloc(dev, sizeof(*wcd), GFP_KERNEL);
if (!wcd)
@@ -1048,10 +1056,36 @@ static int wcd9370_probe(struct sdw_slave *pdev,
SDW_SCP_INT1_PARITY;
pdev->prop.lane_control_support = true;
pdev->prop.simple_clk_stop_capable = true;
+
+ memset(master_ch_mask, 0, WCD937X_MAX_SWR_CH_IDS);
+
if (wcd->is_tx) {
- pdev->prop.source_ports = GENMASK(WCD937X_MAX_TX_SWR_PORTS - 1, 0);
+ master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
+ "qcom,tx-channel-mapping");
+
+ if (master_ch_mask_size)
+ ret = of_property_read_u8_array(dev->of_node, "qcom,tx-channel-mapping",
+ master_ch_mask, master_ch_mask_size);
+ } else {
+ master_ch_mask_size = of_property_count_u8_elems(dev->of_node,
+ "qcom,rx-channel-mapping");
+
+ if (master_ch_mask_size)
+ ret = of_property_read_u8_array(dev->of_node, "qcom,rx-channel-mapping",
+ master_ch_mask, master_ch_mask_size);
+ }
+
+ if (ret < 0)
+ dev_info(dev, "Static channel mapping not specified using device channel maps\n");
+
+ if (wcd->is_tx) {
+ pdev->prop.source_ports = GENMASK(WCD937X_MAX_TX_SWR_PORTS, 0);
pdev->prop.src_dpn_prop = wcd937x_dpn_prop;
wcd->ch_info = &wcd937x_sdw_tx_ch_info[0];
+
+ for (i = 0; i < master_ch_mask_size; i++)
+ wcd->ch_info[i].master_ch_mask = master_ch_mask[i];
+
pdev->prop.wake_capable = true;

wcd->regmap = devm_regmap_init_sdw(pdev, &wcd937x_regmap_config);
@@ -1065,6 +1099,8 @@ static int wcd9370_probe(struct sdw_slave *pdev,
pdev->prop.sink_ports = GENMASK(WCD937X_MAX_SWR_PORTS - 1, 0);
pdev->prop.sink_dpn_prop = wcd937x_dpn_prop;
wcd->ch_info = &wcd937x_sdw_rx_ch_info[0];
+ for (i = 0; i < master_ch_mask_size; i++)
+ wcd->ch_info[i].master_ch_mask = master_ch_mask[i];
}


diff --git a/sound/soc/codecs/wcd937x.c b/sound/soc/codecs/wcd937x.c
index af296b77a723..404effb8c31f 100644
--- a/sound/soc/codecs/wcd937x.c
+++ b/sound/soc/codecs/wcd937x.c
@@ -1192,13 +1192,21 @@ static int wcd937x_connect_port(struct wcd937x_sdw_priv *wcd, u8 port_idx, u8 ch
const struct wcd937x_sdw_ch_info *ch_info = &wcd->ch_info[ch_id];
u8 port_num = ch_info->port_num;
u8 ch_mask = ch_info->ch_mask;
+ u8 mstr_port_num, mstr_ch_mask;
+ struct sdw_slave *sdev = wcd->sdev;

port_config->num = port_num;

- if (enable)
+ mstr_port_num = sdev->m_port_map[port_num];
+ mstr_ch_mask = ch_info->master_ch_mask;
+
+ if (enable) {
port_config->ch_mask |= ch_mask;
- else
+ wcd->master_channel_map[mstr_port_num] |= mstr_ch_mask;
+ } else {
port_config->ch_mask &= ~ch_mask;
+ wcd->master_channel_map[mstr_port_num] &= ~mstr_ch_mask;
+ }

return 0;
}
diff --git a/sound/soc/codecs/wcd937x.h b/sound/soc/codecs/wcd937x.h
index 35f3d48bd7dd..850aa943b7ab 100644
--- a/sound/soc/codecs/wcd937x.h
+++ b/sound/soc/codecs/wcd937x.h
@@ -506,12 +506,14 @@ enum wcd937x_rx_sdw_ports {
struct wcd937x_sdw_ch_info {
int port_num;
unsigned int ch_mask;
+ unsigned int master_ch_mask;
};

#define WCD_SDW_CH(id, pn, cmask) \
[id] = { \
.port_num = pn, \
.ch_mask = cmask, \
+ .master_ch_mask = cmask, \
}

struct wcd937x_priv;
@@ -520,9 +522,11 @@ struct wcd937x_sdw_priv {
struct sdw_stream_config sconfig;
struct sdw_stream_runtime *sruntime;
struct sdw_port_config port_config[WCD937X_MAX_SWR_PORTS];
- const struct wcd937x_sdw_ch_info *ch_info;
+ struct wcd937x_sdw_ch_info *ch_info;
bool port_enable[WCD937X_MAX_SWR_CH_IDS];
+ unsigned int master_channel_map[SDW_MAX_PORTS];
int active_ports;
+ int num_ports;
bool is_tx;
struct wcd937x_priv *wcd937x;
struct irq_domain *slave_irq;
--
2.25.1