* [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller
@ 2025-09-02 16:11 Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 1/7] of: base: Add of_property_read_u8_index Srinivas Kandagatla
` (6 more replies)
0 siblings, 7 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla
This patch series adds support for Qualcomm Soundwire Controller
version v3.1.0.
As part for adding this support, a new macro of_property_read_u8_index()
is added so that we can remove the qcom,din-ports and qcom,dout-ports.
As v3.1.0 supports more than 17 soundwire ports. Also due to change in
the register offsets, new entries are added to the variant data.
Tested this patchset on X14s and Glymur reference platform.
Thanks,
Srini
Changes since v1:
- fixed typo in non OF config of of_property_read_u8_index
- adjusted scoped-based cleanup initalization.
- remove unused macros.
Srinivas Kandagatla (7):
of: base: Add of_property_read_u8_index
soundwire: qcom: remove unused rd_fifo_depth
dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports
soundwire: qcom: deprecate qcom,din/out-ports
soundwire: qcom: prepare for v3.x
dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block
soundwire: qcom: adding support for v3.1.0
.../bindings/soundwire/qcom,soundwire.yaml | 8 +-
drivers/of/property.c | 33 +++
drivers/soundwire/qcom.c | 249 ++++++++++--------
include/linux/of.h | 9 +
4 files changed, 185 insertions(+), 114 deletions(-)
--
2.50.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v2 1/7] of: base: Add of_property_read_u8_index
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 18:04 ` Rob Herring
2025-09-02 16:11 ` [PATCH v2 2/7] soundwire: qcom: remove unused rd_fifo_depth Srinivas Kandagatla
` (5 subsequent siblings)
6 siblings, 1 reply; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla
Add support for of_property_read_u8_index(), simillar to others
u16 and u32 variants. Having this helper makes the code more tidy in
isome cases, specially when we are parsing multiple of these into
data structures.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
drivers/of/property.c | 33 +++++++++++++++++++++++++++++++++
include/linux/of.h | 9 +++++++++
2 files changed, 42 insertions(+)
diff --git a/drivers/of/property.c b/drivers/of/property.c
index c1feb631e383..a644b24d5b75 100644
--- a/drivers/of/property.c
+++ b/drivers/of/property.c
@@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np,
return prop->value;
}
+/**
+ * of_property_read_u8_index - Find and read a u8 from a multi-value property.
+ *
+ * @np: device node from which the property value is to be read.
+ * @propname: name of the property to be searched.
+ * @index: index of the u8 in the list of values
+ * @out_value: pointer to return value, modified only if no error.
+ *
+ * Search for a property in a device node and read nth 8-bit value from
+ * it.
+ *
+ * Return: 0 on success, -EINVAL if the property does not exist,
+ * -ENODATA if property does not have a value, and -EOVERFLOW if the
+ * property data isn't large enough.
+ *
+ * The out_value is modified only if a valid u8 value can be decoded.
+ */
+int of_property_read_u8_index(const struct device_node *np,
+ const char *propname,
+ u32 index, u8 *out_value)
+{
+ const u8 *val = of_find_property_value_of_size(np, propname,
+ ((index + 1) * sizeof(*out_value)),
+ 0, NULL);
+
+ if (IS_ERR(val))
+ return PTR_ERR(val);
+
+ *out_value = *(val + index);
+ return 0;
+}
+EXPORT_SYMBOL_GPL(of_property_read_u8_index);
+
/**
* of_property_read_u16_index - Find and read a u16 from a multi-value property.
*
diff --git a/include/linux/of.h b/include/linux/of.h
index a62154aeda1b..0c95e26c7191 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -316,6 +316,9 @@ extern struct property *of_find_property(const struct device_node *np,
extern bool of_property_read_bool(const struct device_node *np, const char *propname);
extern int of_property_count_elems_of_size(const struct device_node *np,
const char *propname, int elem_size);
+extern int of_property_read_u8_index(const struct device_node *np,
+ const char *propname,
+ u32 index, u8 *out_value);
extern int of_property_read_u16_index(const struct device_node *np,
const char *propname,
u32 index, u16 *out_value);
@@ -639,6 +642,12 @@ static inline int of_property_count_elems_of_size(const struct device_node *np,
return -ENOSYS;
}
+static inline int of_property_read_u8_index(const struct device_node *np,
+ const char *propname, u32 index, u8 *out_value)
+{
+ return -ENOSYS;
+}
+
static inline int of_property_read_u16_index(const struct device_node *np,
const char *propname, u32 index, u16 *out_value)
{
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 2/7] soundwire: qcom: remove unused rd_fifo_depth
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 1/7] of: base: Add of_property_read_u8_index Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 3/7] dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports Srinivas Kandagatla
` (4 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla,
Konrad Dybcio
remove read fifo depth field parsing logic, as rd_fifo_depth is never
used in the driver. Cleaning this up would benefit when adding new
variant support which includes adding variant fields for rd_fifo_depth.
ex: Glymur has this rd_fifo_depth register fields changed from v2.x
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Konrad Dybcio <konrad.dybcio@oss.qualcomm.com>
---
drivers/soundwire/qcom.c | 2 --
1 file changed, 2 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 5b3078220189..f3ad53ec6e76 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -209,7 +209,6 @@ struct qcom_swrm_ctrl {
int (*reg_write)(struct qcom_swrm_ctrl *ctrl, int reg, int val);
u32 slave_status;
u32 wr_fifo_depth;
- u32 rd_fifo_depth;
bool clock_stop_not_supported;
};
@@ -898,7 +897,6 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
swrm_wait_for_frame_gen_enabled(ctrl);
ctrl->slave_status = 0;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
- ctrl->rd_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_RD_FIFO_DEPTH, val);
ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val);
return 0;
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 3/7] dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 1/7] of: base: Add of_property_read_u8_index Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 2/7] soundwire: qcom: remove unused rd_fifo_depth Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 4/7] " Srinivas Kandagatla
` (3 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla,
Krzysztof Kozlowski
Number of input and output ports can be dynamically read from the
controller registers, getting this value from Device Tree is redundant
and potentially lead to bugs.
Mark these two properties as deprecated in device tree bindings.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
.../devicetree/bindings/soundwire/qcom,soundwire.yaml | 7 ++-----
1 file changed, 2 insertions(+), 5 deletions(-)
diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
index 95d947fda6a7..7ea491f7e828 100644
--- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
+++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
@@ -73,10 +73,12 @@ properties:
qcom,din-ports:
$ref: /schemas/types.yaml#/definitions/uint32
description: count of data in ports
+ deprecated: true
qcom,dout-ports:
$ref: /schemas/types.yaml#/definitions/uint32
description: count of data out ports
+ deprecated: true
qcom,ports-word-length:
$ref: /schemas/types.yaml#/definitions/uint8-array
@@ -223,8 +225,6 @@ required:
- '#sound-dai-cells'
- '#address-cells'
- '#size-cells'
- - qcom,dout-ports
- - qcom,din-ports
- qcom,ports-offset1
- qcom,ports-offset2
@@ -257,9 +257,6 @@ examples:
clocks = <&lpass_rx_macro>;
clock-names = "iface";
- qcom,din-ports = <0>;
- qcom,dout-ports = <5>;
-
resets = <&lpass_audiocc LPASS_AUDIO_SWR_RX_CGCR>;
reset-names = "swr_audio_cgcr";
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 4/7] soundwire: qcom: deprecate qcom,din/out-ports
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
` (2 preceding siblings ...)
2025-09-02 16:11 ` [PATCH v2 3/7] dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 5/7] soundwire: qcom: prepare for v3.x Srinivas Kandagatla
` (2 subsequent siblings)
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla
Number of input and output ports can be dynamically read from the
controller registers, getting this value from Device Tree is redundant
and potentially lead to bugs.
Remove the code parsing this property along with marking this as
deprecated in device tree bindings.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
drivers/soundwire/qcom.c | 133 ++++++++++++++-------------------------
1 file changed, 48 insertions(+), 85 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index f3ad53ec6e76..34d4e2c2dd0a 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -128,7 +128,6 @@
#define MAX_FREQ_NUM 1
#define TIMEOUT_MS 100
#define QCOM_SWRM_MAX_RD_LEN 0x1
-#define QCOM_SDW_MAX_PORTS 14
#define DEFAULT_CLK_FREQ 9600000
#define SWRM_MAX_DAIS 0xF
#define SWR_INVALID_PARAM 0xFF
@@ -195,6 +194,7 @@ struct qcom_swrm_ctrl {
int wake_irq;
int num_din_ports;
int num_dout_ports;
+ int nports;
int cols_index;
int rows_index;
unsigned long port_mask;
@@ -202,7 +202,7 @@ struct qcom_swrm_ctrl {
u8 rcmd_id;
u8 wcmd_id;
/* Port numbers are 1 - 14 */
- struct qcom_swrm_port_config pconfig[QCOM_SDW_MAX_PORTS + 1];
+ struct qcom_swrm_port_config *pconfig;
struct sdw_stream_runtime *sruntime[SWRM_MAX_DAIS];
enum sdw_slave_status status[SDW_MAX_DEVICES + 1];
int (*reg_read)(struct qcom_swrm_ctrl *ctrl, int reg, u32 *val);
@@ -1153,7 +1153,6 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
struct snd_pcm_hw_params *params,
int direction)
{
- struct sdw_port_config pconfig[QCOM_SDW_MAX_PORTS];
struct sdw_stream_config sconfig;
struct sdw_master_runtime *m_rt;
struct sdw_slave_runtime *s_rt;
@@ -1162,6 +1161,10 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
unsigned long *port_mask;
int maxport, pn, nports = 0, ret = 0;
unsigned int m_port;
+ struct sdw_port_config *pconfig __free(kfree) = kcalloc(ctrl->nports,
+ sizeof(*pconfig), GFP_KERNEL);
+ if (!pconfig)
+ return -ENOMEM;
if (direction == SNDRV_PCM_STREAM_CAPTURE)
sconfig.direction = SDW_DATA_DIR_TX;
@@ -1186,8 +1189,7 @@ static int qcom_swrm_stream_alloc_ports(struct qcom_swrm_ctrl *ctrl,
continue;
port_mask = &ctrl->port_mask;
- maxport = ctrl->num_dout_ports + ctrl->num_din_ports;
-
+ maxport = ctrl->nports;
list_for_each_entry(s_rt, &m_rt->slave_rt_list, m_rt_node) {
slave = s_rt->slave;
@@ -1347,106 +1349,67 @@ static int qcom_swrm_register_dais(struct qcom_swrm_ctrl *ctrl)
static int qcom_swrm_get_port_config(struct qcom_swrm_ctrl *ctrl)
{
struct device_node *np = ctrl->dev->of_node;
- u8 off1[QCOM_SDW_MAX_PORTS];
- u8 off2[QCOM_SDW_MAX_PORTS];
- u16 si[QCOM_SDW_MAX_PORTS];
- u8 bp_mode[QCOM_SDW_MAX_PORTS] = { 0, };
- u8 hstart[QCOM_SDW_MAX_PORTS];
- u8 hstop[QCOM_SDW_MAX_PORTS];
- u8 word_length[QCOM_SDW_MAX_PORTS];
- u8 blk_group_count[QCOM_SDW_MAX_PORTS];
- u8 lane_control[QCOM_SDW_MAX_PORTS];
- int i, ret, nports, val;
- bool si_16 = false;
+ struct qcom_swrm_port_config *pcfg;
+ int i, ret, val;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
ctrl->num_dout_ports = FIELD_GET(SWRM_COMP_PARAMS_DOUT_PORTS_MASK, val);
ctrl->num_din_ports = FIELD_GET(SWRM_COMP_PARAMS_DIN_PORTS_MASK, val);
- ret = of_property_read_u32(np, "qcom,din-ports", &val);
- if (ret)
- return ret;
-
- if (val > ctrl->num_din_ports)
- return -EINVAL;
-
- ctrl->num_din_ports = val;
-
- ret = of_property_read_u32(np, "qcom,dout-ports", &val);
- if (ret)
- return ret;
-
- if (val > ctrl->num_dout_ports)
- return -EINVAL;
-
- ctrl->num_dout_ports = val;
+ ctrl->nports = ctrl->num_dout_ports + ctrl->num_din_ports;
- nports = ctrl->num_dout_ports + ctrl->num_din_ports;
- if (nports > QCOM_SDW_MAX_PORTS)
- return -EINVAL;
+ ctrl->pconfig = devm_kcalloc(ctrl->dev, ctrl->nports + 1,
+ sizeof(*ctrl->pconfig), GFP_KERNEL);
+ if (!ctrl->pconfig)
+ return -ENOMEM;
- /* Valid port numbers are from 1-14, so mask out port 0 explicitly */
set_bit(0, &ctrl->port_mask);
+ /* Valid port numbers are from 1, so mask out port 0 explicitly */
+ for (i = 0; i < ctrl->nports; i++) {
+ pcfg = &ctrl->pconfig[i + 1];
- ret = of_property_read_u8_array(np, "qcom,ports-offset1",
- off1, nports);
- if (ret)
- return ret;
-
- ret = of_property_read_u8_array(np, "qcom,ports-offset2",
- off2, nports);
- if (ret)
- return ret;
-
- ret = of_property_read_u8_array(np, "qcom,ports-sinterval-low",
- (u8 *)si, nports);
- if (ret) {
- ret = of_property_read_u16_array(np, "qcom,ports-sinterval",
- si, nports);
+ ret = of_property_read_u8_index(np, "qcom,ports-offset1", i, &pcfg->off1);
if (ret)
return ret;
- si_16 = true;
- }
- ret = of_property_read_u8_array(np, "qcom,ports-block-pack-mode",
- bp_mode, nports);
- if (ret) {
- if (ctrl->version <= SWRM_VERSION_1_3_0)
- memset(bp_mode, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- else
+ ret = of_property_read_u8_index(np, "qcom,ports-offset2", i, &pcfg->off2);
+ if (ret)
return ret;
- }
- memset(hstart, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- of_property_read_u8_array(np, "qcom,ports-hstart", hstart, nports);
+ ret = of_property_read_u8_index(np, "qcom,ports-sinterval-low", i, (u8 *)&pcfg->si);
+ if (ret) {
+ ret = of_property_read_u16_index(np, "qcom,ports-sinterval", i, &pcfg->si);
+ if (ret)
+ return ret;
+ }
+
+ ret = of_property_read_u8_index(np, "qcom,ports-block-pack-mode",
+ i, &pcfg->bp_mode);
+ if (ret) {
+ if (ctrl->version <= SWRM_VERSION_1_3_0)
+ pcfg->bp_mode = SWR_INVALID_PARAM;
+ else
+ return ret;
+ }
- memset(hstop, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- of_property_read_u8_array(np, "qcom,ports-hstop", hstop, nports);
+ /* Optional properties */
+ pcfg->hstart = SWR_INVALID_PARAM;
+ pcfg->hstop = SWR_INVALID_PARAM;
+ pcfg->word_length = SWR_INVALID_PARAM;
+ pcfg->blk_group_count = SWR_INVALID_PARAM;
+ pcfg->lane_control = SWR_INVALID_PARAM;
- memset(word_length, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- of_property_read_u8_array(np, "qcom,ports-word-length", word_length, nports);
+ of_property_read_u8_index(np, "qcom,ports-hstart", i, &pcfg->hstart);
- memset(blk_group_count, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- of_property_read_u8_array(np, "qcom,ports-block-group-count", blk_group_count, nports);
+ of_property_read_u8_index(np, "qcom,ports-hstop", i, &pcfg->hstop);
- memset(lane_control, SWR_INVALID_PARAM, QCOM_SDW_MAX_PORTS);
- of_property_read_u8_array(np, "qcom,ports-lane-control", lane_control, nports);
+ of_property_read_u8_index(np, "qcom,ports-word-length", i, &pcfg->word_length);
- for (i = 0; i < nports; i++) {
- /* Valid port number range is from 1-14 */
- if (si_16)
- ctrl->pconfig[i + 1].si = si[i];
- else
- ctrl->pconfig[i + 1].si = ((u8 *)si)[i];
- ctrl->pconfig[i + 1].off1 = off1[i];
- ctrl->pconfig[i + 1].off2 = off2[i];
- ctrl->pconfig[i + 1].bp_mode = bp_mode[i];
- ctrl->pconfig[i + 1].hstart = hstart[i];
- ctrl->pconfig[i + 1].hstop = hstop[i];
- ctrl->pconfig[i + 1].word_length = word_length[i];
- ctrl->pconfig[i + 1].blk_group_count = blk_group_count[i];
- ctrl->pconfig[i + 1].lane_control = lane_control[i];
+ of_property_read_u8_index(np, "qcom,ports-block-group-count",
+ i, &pcfg->blk_group_count);
+
+ of_property_read_u8_index(np, "qcom,ports-lane-control", i, &pcfg->lane_control);
}
return 0;
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 5/7] soundwire: qcom: prepare for v3.x
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
` (3 preceding siblings ...)
2025-09-02 16:11 ` [PATCH v2 4/7] " Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 6/7] dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 7/7] soundwire: qcom: adding support for v3.1.0 Srinivas Kandagatla
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla
cleanup the register layout structs to prepare for adding new 3.x
controller support.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
drivers/soundwire/qcom.c | 77 +++++++++++++++++++++++++++++-----------
1 file changed, 56 insertions(+), 21 deletions(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 34d4e2c2dd0a..3d4d0c443977 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -99,14 +99,15 @@
#define SWRM_MCP_SLV_STATUS 0x1090
#define SWRM_MCP_SLV_STATUS_MASK GENMASK(1, 0)
#define SWRM_MCP_SLV_STATUS_SZ 2
-#define SWRM_DP_PORT_CTRL_BANK(n, m) (0x1124 + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DP_PORT_CTRL_2_BANK(n, m) (0x1128 + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DP_BLOCK_CTRL_1(n) (0x112C + 0x100 * (n - 1))
-#define SWRM_DP_BLOCK_CTRL2_BANK(n, m) (0x1130 + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DP_PORT_HCTRL_BANK(n, m) (0x1134 + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DP_BLOCK_CTRL3_BANK(n, m) (0x1138 + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DP_SAMPLECTRL2_BANK(n, m) (0x113C + 0x100 * (n - 1) + 0x40 * m)
-#define SWRM_DIN_DPn_PCM_PORT_CTRL(n) (0x1054 + 0x100 * (n - 1))
+
+#define SWRM_DPn_PORT_CTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DPn_PORT_CTRL_2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DPn_BLOCK_CTRL_1(offset, n) (offset + 0x100 * (n - 1))
+#define SWRM_DPn_BLOCK_CTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DPn_PORT_HCTRL_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DPn_BLOCK_CTRL3_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+#define SWRM_DPn_SAMPLECTRL2_BANK(offset, n, m) (offset + 0x100 * (n - 1) + 0x40 * m)
+
#define SWR_V1_3_MSTR_MAX_REG_ADDR 0x1740
#define SWR_V2_0_MSTR_MAX_REG_ADDR 0x50ac
@@ -171,6 +172,13 @@ enum {
SWRM_REG_CMD_FIFO_RD_CMD,
SWRM_REG_CMD_FIFO_STATUS,
SWRM_REG_CMD_FIFO_RD_FIFO_ADDR,
+ SWRM_OFFSET_DP_PORT_CTRL_BANK,
+ SWRM_OFFSET_DP_PORT_CTRL_2_BANK,
+ SWRM_OFFSET_DP_BLOCK_CTRL_1,
+ SWRM_OFFSET_DP_BLOCK_CTRL2_BANK,
+ SWRM_OFFSET_DP_PORT_HCTRL_BANK,
+ SWRM_OFFSET_DP_BLOCK_CTRL3_BANK,
+ SWRM_OFFSET_DP_SAMPLECTRL2_BANK,
};
struct qcom_swrm_ctrl {
@@ -230,6 +238,13 @@ static const unsigned int swrm_v1_3_reg_layout[] = {
[SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V1_3_CMD_FIFO_RD_CMD,
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V1_3_CMD_FIFO_STATUS,
[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V1_3_CMD_FIFO_RD_FIFO_ADDR,
+ [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124,
+ [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128,
+ [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c,
+ [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130,
+ [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134,
+ [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138,
+ [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c,
};
static const struct qcom_swrm_data swrm_v1_3_data = {
@@ -264,6 +279,13 @@ static const unsigned int swrm_v2_0_reg_layout[] = {
[SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
[SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
[SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR,
+ [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1124,
+ [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1128,
+ [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x112c,
+ [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1130,
+ [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1134,
+ [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1138,
+ [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x113c,
};
static const struct qcom_swrm_data swrm_v2_0_data = {
@@ -964,10 +986,10 @@ static int qcom_swrm_port_params(struct sdw_bus *bus,
unsigned int bank)
{
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
+ u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL_1];
- return ctrl->reg_write(ctrl, SWRM_DP_BLOCK_CTRL_1(p_params->num),
- p_params->bps - 1);
-
+ return ctrl->reg_write(ctrl, SWRM_DPn_BLOCK_CTRL_1(offset, p_params->num),
+ p_params->bps - 1);
}
static int qcom_swrm_transport_params(struct sdw_bus *bus,
@@ -977,9 +999,11 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
struct qcom_swrm_port_config *pcfg;
u32 value;
- int reg = SWRM_DP_PORT_CTRL_BANK((params->port_num), bank);
+ int reg, offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK];
int ret;
+ reg = SWRM_DPn_PORT_CTRL_BANK(offset, params->port_num, bank);
+
pcfg = &ctrl->pconfig[params->port_num];
value = pcfg->off1 << SWRM_DP_PORT_CTRL_OFFSET1_SHFT;
@@ -991,15 +1015,19 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
goto err;
if (pcfg->si > 0xff) {
+ offset = ctrl->reg_layout[SWRM_OFFSET_DP_SAMPLECTRL2_BANK];
value = (pcfg->si >> 8) & 0xff;
- reg = SWRM_DP_SAMPLECTRL2_BANK(params->port_num, bank);
+ reg = SWRM_DPn_SAMPLECTRL2_BANK(offset, params->port_num, bank);
+
ret = ctrl->reg_write(ctrl, reg, value);
if (ret)
goto err;
}
if (pcfg->lane_control != SWR_INVALID_PARAM) {
- reg = SWRM_DP_PORT_CTRL_2_BANK(params->port_num, bank);
+ offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_2_BANK];
+ reg = SWRM_DPn_PORT_CTRL_2_BANK(offset, params->port_num, bank);
+
value = pcfg->lane_control;
ret = ctrl->reg_write(ctrl, reg, value);
if (ret)
@@ -1007,20 +1035,23 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
}
if (pcfg->blk_group_count != SWR_INVALID_PARAM) {
- reg = SWRM_DP_BLOCK_CTRL2_BANK(params->port_num, bank);
+ offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL2_BANK];
+
+ reg = SWRM_DPn_BLOCK_CTRL2_BANK(offset, params->port_num, bank);
+
value = pcfg->blk_group_count;
ret = ctrl->reg_write(ctrl, reg, value);
if (ret)
goto err;
}
- if (pcfg->hstart != SWR_INVALID_PARAM
- && pcfg->hstop != SWR_INVALID_PARAM) {
- reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
+ offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_HCTRL_BANK];
+ reg = SWRM_DPn_PORT_HCTRL_BANK(offset, params->port_num, bank);
+
+ if (pcfg->hstart != SWR_INVALID_PARAM && pcfg->hstop != SWR_INVALID_PARAM) {
value = (pcfg->hstop << 4) | pcfg->hstart;
ret = ctrl->reg_write(ctrl, reg, value);
} else {
- reg = SWRM_DP_PORT_HCTRL_BANK(params->port_num, bank);
value = (SWR_HSTOP_MAX_VAL << 4) | SWR_HSTART_MIN_VAL;
ret = ctrl->reg_write(ctrl, reg, value);
}
@@ -1029,7 +1060,8 @@ static int qcom_swrm_transport_params(struct sdw_bus *bus,
goto err;
if (pcfg->bp_mode != SWR_INVALID_PARAM) {
- reg = SWRM_DP_BLOCK_CTRL3_BANK(params->port_num, bank);
+ offset = ctrl->reg_layout[SWRM_OFFSET_DP_BLOCK_CTRL3_BANK];
+ reg = SWRM_DPn_BLOCK_CTRL3_BANK(offset, params->port_num, bank);
ret = ctrl->reg_write(ctrl, reg, pcfg->bp_mode);
}
@@ -1041,9 +1073,12 @@ static int qcom_swrm_port_enable(struct sdw_bus *bus,
struct sdw_enable_ch *enable_ch,
unsigned int bank)
{
- u32 reg = SWRM_DP_PORT_CTRL_BANK(enable_ch->port_num, bank);
+ u32 reg;
struct qcom_swrm_ctrl *ctrl = to_qcom_sdw(bus);
u32 val;
+ u32 offset = ctrl->reg_layout[SWRM_OFFSET_DP_PORT_CTRL_BANK];
+
+ reg = SWRM_DPn_PORT_CTRL_BANK(offset, enable_ch->port_num, bank);
ctrl->reg_read(ctrl, reg, &val);
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 6/7] dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
` (4 preceding siblings ...)
2025-09-02 16:11 ` [PATCH v2 5/7] soundwire: qcom: prepare for v3.x Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 7/7] soundwire: qcom: adding support for v3.1.0 Srinivas Kandagatla
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla,
Krzysztof Kozlowski
Add bindings for Soundwire controllers v3.1.0, which is available on
Qualcomm Glymur SoC.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Reviewed-by: Krzysztof Kozlowski <krzysztof.kozlowski@linaro.org>
---
Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml | 1 +
1 file changed, 1 insertion(+)
diff --git a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
index 7ea491f7e828..003023729fb8 100644
--- a/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
+++ b/Documentation/devicetree/bindings/soundwire/qcom,soundwire.yaml
@@ -23,6 +23,7 @@ properties:
- qcom,soundwire-v1.6.0
- qcom,soundwire-v1.7.0
- qcom,soundwire-v2.0.0
+ - qcom,soundwire-v3.1.0
- items:
- enum:
- qcom,soundwire-v2.1.0
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v2 7/7] soundwire: qcom: adding support for v3.1.0
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
` (5 preceding siblings ...)
2025-09-02 16:11 ` [PATCH v2 6/7] dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block Srinivas Kandagatla
@ 2025-09-02 16:11 ` Srinivas Kandagatla
6 siblings, 0 replies; 9+ messages in thread
From: Srinivas Kandagatla @ 2025-09-02 16:11 UTC (permalink / raw)
To: robh, krzk+dt, vkoul
Cc: conor+dt, srini, yung-chuan.liao, pierre-louis.bossart,
linux-arm-msm, devicetree, linux-sound, Srinivas Kandagatla
Add support for controller version v3.1.0, which has changes in
register layout and some register fields compared to v2.0.
Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
---
drivers/soundwire/qcom.c | 37 ++++++++++++++++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/soundwire/qcom.c b/drivers/soundwire/qcom.c
index 3d4d0c443977..a7b6d9ecc3ba 100644
--- a/drivers/soundwire/qcom.c
+++ b/drivers/soundwire/qcom.c
@@ -31,6 +31,7 @@
#define SWRM_VERSION_1_5_1 0x01050001
#define SWRM_VERSION_1_7_0 0x01070000
#define SWRM_VERSION_2_0_0 0x02000000
+#define SWRM_VERSION_3_1_0 0x03010000
#define SWRM_COMP_HW_VERSION 0x00
#define SWRM_COMP_CFG_ADDR 0x04
#define SWRM_COMP_CFG_IRQ_LEVEL_OR_PULSE_MSK BIT(1)
@@ -40,6 +41,9 @@
#define SWRM_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(19, 15)
#define SWRM_COMP_PARAMS_DOUT_PORTS_MASK GENMASK(4, 0)
#define SWRM_COMP_PARAMS_DIN_PORTS_MASK GENMASK(9, 5)
+#define SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH GENMASK(17, 10)
+#define SWRM_V3_COMP_PARAMS_RD_FIFO_DEPTH GENMASK(23, 18)
+
#define SWRM_COMP_MASTER_ID 0x104
#define SWRM_V1_3_INTERRUPT_STATUS 0x200
#define SWRM_V2_0_INTERRUPT_STATUS 0x5000
@@ -296,6 +300,32 @@ static const struct qcom_swrm_data swrm_v2_0_data = {
.reg_layout = swrm_v2_0_reg_layout,
};
+static const unsigned int swrm_v3_0_reg_layout[] = {
+ [SWRM_REG_FRAME_GEN_ENABLED] = SWRM_V2_0_LINK_STATUS,
+ [SWRM_REG_INTERRUPT_STATUS] = SWRM_V2_0_INTERRUPT_STATUS,
+ [SWRM_REG_INTERRUPT_MASK_ADDR] = 0, /* Not present */
+ [SWRM_REG_INTERRUPT_CLEAR] = SWRM_V2_0_INTERRUPT_CLEAR,
+ [SWRM_REG_INTERRUPT_CPU_EN] = SWRM_V2_0_INTERRUPT_CPU_EN,
+ [SWRM_REG_CMD_FIFO_WR_CMD] = SWRM_V2_0_CMD_FIFO_WR_CMD,
+ [SWRM_REG_CMD_FIFO_RD_CMD] = SWRM_V2_0_CMD_FIFO_RD_CMD,
+ [SWRM_REG_CMD_FIFO_STATUS] = SWRM_V2_0_CMD_FIFO_STATUS,
+ [SWRM_REG_CMD_FIFO_RD_FIFO_ADDR] = SWRM_V2_0_CMD_FIFO_RD_FIFO_ADDR,
+ [SWRM_OFFSET_DP_PORT_CTRL_BANK] = 0x1224,
+ [SWRM_OFFSET_DP_PORT_CTRL_2_BANK] = 0x1228,
+ [SWRM_OFFSET_DP_BLOCK_CTRL_1] = 0x122c,
+ [SWRM_OFFSET_DP_BLOCK_CTRL2_BANK] = 0x1230,
+ [SWRM_OFFSET_DP_PORT_HCTRL_BANK] = 0x1234,
+ [SWRM_OFFSET_DP_BLOCK_CTRL3_BANK] = 0x1238,
+ [SWRM_OFFSET_DP_SAMPLECTRL2_BANK] = 0x123c,
+};
+
+static const struct qcom_swrm_data swrm_v3_0_data = {
+ .default_rows = 50,
+ .default_cols = 16,
+ .sw_clk_gate_required = true,
+ .max_reg = SWR_V2_0_MSTR_MAX_REG_ADDR,
+ .reg_layout = swrm_v3_0_reg_layout,
+};
#define to_qcom_sdw(b) container_of(b, struct qcom_swrm_ctrl, bus)
static int qcom_swrm_ahb_reg_read(struct qcom_swrm_ctrl *ctrl, int reg,
@@ -919,7 +949,11 @@ static int qcom_swrm_init(struct qcom_swrm_ctrl *ctrl)
swrm_wait_for_frame_gen_enabled(ctrl);
ctrl->slave_status = 0;
ctrl->reg_read(ctrl, SWRM_COMP_PARAMS, &val);
- ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val);
+
+ if (ctrl->version >= SWRM_VERSION_3_1_0)
+ ctrl->wr_fifo_depth = FIELD_GET(SWRM_V3_COMP_PARAMS_WR_FIFO_DEPTH, val);
+ else
+ ctrl->wr_fifo_depth = FIELD_GET(SWRM_COMP_PARAMS_WR_FIFO_DEPTH, val);
return 0;
}
@@ -1765,6 +1799,7 @@ static const struct of_device_id qcom_swrm_of_match[] = {
{ .compatible = "qcom,soundwire-v1.6.0", .data = &swrm_v1_6_data },
{ .compatible = "qcom,soundwire-v1.7.0", .data = &swrm_v1_5_data },
{ .compatible = "qcom,soundwire-v2.0.0", .data = &swrm_v2_0_data },
+ { .compatible = "qcom,soundwire-v3.1.0", .data = &swrm_v3_0_data },
{/* sentinel */},
};
--
2.50.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v2 1/7] of: base: Add of_property_read_u8_index
2025-09-02 16:11 ` [PATCH v2 1/7] of: base: Add of_property_read_u8_index Srinivas Kandagatla
@ 2025-09-02 18:04 ` Rob Herring
0 siblings, 0 replies; 9+ messages in thread
From: Rob Herring @ 2025-09-02 18:04 UTC (permalink / raw)
To: Srinivas Kandagatla
Cc: krzk+dt, vkoul, conor+dt, srini, yung-chuan.liao,
pierre-louis.bossart, linux-arm-msm, devicetree, linux-sound
On Tue, Sep 2, 2025 at 11:12 AM Srinivas Kandagatla
<srinivas.kandagatla@oss.qualcomm.com> wrote:
>
> Add support for of_property_read_u8_index(), simillar to others
> u16 and u32 variants. Having this helper makes the code more tidy in
> isome cases, specially when we are parsing multiple of these into
> data structures.
>
> Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
> ---
> drivers/of/property.c | 33 +++++++++++++++++++++++++++++++++
> include/linux/of.h | 9 +++++++++
> 2 files changed, 42 insertions(+)
>
> diff --git a/drivers/of/property.c b/drivers/of/property.c
> index c1feb631e383..a644b24d5b75 100644
> --- a/drivers/of/property.c
> +++ b/drivers/of/property.c
> @@ -147,6 +147,39 @@ static void *of_find_property_value_of_size(const struct device_node *np,
> return prop->value;
> }
>
> +/**
> + * of_property_read_u8_index - Find and read a u8 from a multi-value property.
> + *
> + * @np: device node from which the property value is to be read.
> + * @propname: name of the property to be searched.
> + * @index: index of the u8 in the list of values
> + * @out_value: pointer to return value, modified only if no error.
> + *
> + * Search for a property in a device node and read nth 8-bit value from
> + * it.
> + *
> + * Return: 0 on success, -EINVAL if the property does not exist,
> + * -ENODATA if property does not have a value, and -EOVERFLOW if the
> + * property data isn't large enough.
> + *
> + * The out_value is modified only if a valid u8 value can be decoded.
> + */
> +int of_property_read_u8_index(const struct device_node *np,
> + const char *propname,
> + u32 index, u8 *out_value)
> +{
> + const u8 *val = of_find_property_value_of_size(np, propname,
> + ((index + 1) * sizeof(*out_value)),
> + 0, NULL);
> +
> + if (IS_ERR(val))
> + return PTR_ERR(val);
> +
> + *out_value = *(val + index);
val[index]
Otherwise,
Reviewed-by: Rob Herring (Arm) <robh@kernel.org>
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2025-09-02 18:04 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-09-02 16:11 [PATCH v2 0/7] soundwire: qcom: add support for v3.1.0 controller Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 1/7] of: base: Add of_property_read_u8_index Srinivas Kandagatla
2025-09-02 18:04 ` Rob Herring
2025-09-02 16:11 ` [PATCH v2 2/7] soundwire: qcom: remove unused rd_fifo_depth Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 3/7] dt-bindings: soundwire: qcom: deprecate qcom,din/out-ports Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 4/7] " Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 5/7] soundwire: qcom: prepare for v3.x Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 6/7] dt-bindings: soundwire: qcom: Document v3.1.0 version of IP block Srinivas Kandagatla
2025-09-02 16:11 ` [PATCH v2 7/7] soundwire: qcom: adding support for v3.1.0 Srinivas Kandagatla
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).