* [PATCH 1/3] soundwire: introduce BPT section
2025-10-21 9:43 [PATCH 0/3] soundwire: send multi sections in one BPT stream Bard Liao
@ 2025-10-21 9:43 ` Bard Liao
2025-10-21 9:43 ` [PATCH 2/3] soundwire: pass sdw_bpt_section to cdns BPT helpers Bard Liao
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Bard Liao @ 2025-10-21 9:43 UTC (permalink / raw)
To: linux-sound, vkoul
Cc: vinod.koul, linux-kernel, pierre-louis.bossart, bard.liao
Currently we send a BRA message with a start address with continuous
registers in a BPT stream. However, a codec may need to write different
register sections shortly. Introduce a register section in struct
sdw_btp_msg which contain register start address, length, and buffer.
This commit uses only 1 section for each BPT message. And we need to add
up all BPT section length and check if it reach maximum BPT bytes.
No function changes.
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: Shuming Fan <shumingf@realtek.com>
---
drivers/soundwire/bus.c | 10 ++++++++--
drivers/soundwire/bus.h | 22 ++++++++++++++++------
drivers/soundwire/debugfs.c | 14 +++++++++++---
drivers/soundwire/intel_ace2x.c | 22 +++++++++++++---------
4 files changed, 48 insertions(+), 20 deletions(-)
diff --git a/drivers/soundwire/bus.c b/drivers/soundwire/bus.c
index 55c1db816534..fb68738dfb9b 100644
--- a/drivers/soundwire/bus.c
+++ b/drivers/soundwire/bus.c
@@ -2052,8 +2052,14 @@ EXPORT_SYMBOL(sdw_clear_slave_status);
int sdw_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg)
{
- if (msg->len > SDW_BPT_MSG_MAX_BYTES) {
- dev_err(bus->dev, "Invalid BPT message length %d\n", msg->len);
+ int len = 0;
+ int i;
+
+ for (i = 0; i < msg->sections; i++)
+ len += msg->sec[i].len;
+
+ if (len > SDW_BPT_MSG_MAX_BYTES) {
+ dev_err(bus->dev, "Invalid BPT message length %d\n", len);
return -EINVAL;
}
diff --git a/drivers/soundwire/bus.h b/drivers/soundwire/bus.h
index 02651fbb683a..8115c64dd48e 100644
--- a/drivers/soundwire/bus.h
+++ b/drivers/soundwire/bus.h
@@ -73,21 +73,31 @@ struct sdw_msg {
};
/**
- * struct sdw_btp_msg - Message structure
+ * struct sdw_btp_section - Message section structure
* @addr: Start Register address accessed in the Slave
* @len: number of bytes to transfer. More than 64Kb can be transferred
* but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced.
- * @dev_num: Slave device number
- * @flags: transfer flags, indicate if xfer is read or write
- * @buf: message data buffer (filled by host for write, filled
+ * @buf: section data buffer (filled by host for write, filled
* by Peripheral hardware for reads)
*/
-struct sdw_bpt_msg {
+struct sdw_bpt_section {
u32 addr;
u32 len;
+ u8 *buf;
+};
+
+/**
+ * struct sdw_btp_msg - Message structure
+ * @sec: Pointer to array of sections
+ * @sections: Number of sections in the array
+ * @dev_num: Slave device number
+ * @flags: transfer flags, indicate if xfer is read or write
+ */
+struct sdw_bpt_msg {
+ struct sdw_bpt_section *sec;
+ int sections;
u8 dev_num;
u8 flags;
- u8 *buf;
};
#define SDW_DOUBLE_RATE_FACTOR 2
diff --git a/drivers/soundwire/debugfs.c b/drivers/soundwire/debugfs.c
index 1e0f9318b616..6068011dd0d9 100644
--- a/drivers/soundwire/debugfs.c
+++ b/drivers/soundwire/debugfs.c
@@ -222,15 +222,23 @@ DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL,
static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer)
{
struct sdw_bpt_msg msg = {0};
+ struct sdw_bpt_section *sec;
- msg.addr = start_addr;
- msg.len = num_bytes;
+ sec = kcalloc(1, sizeof(*sec), GFP_KERNEL);
+ if (!sec)
+ return -ENOMEM;
+ msg.sections = 1;
+
+ sec[0].addr = start_addr;
+ sec[0].len = num_bytes;
+
+ msg.sec = sec;
msg.dev_num = slave->dev_num;
if (write)
msg.flags = SDW_MSG_FLAG_WRITE;
else
msg.flags = SDW_MSG_FLAG_READ;
- msg.buf = buffer;
+ sec[0].buf = buffer;
return sdw_bpt_send_sync(slave->bus, slave, &msg);
}
diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c
index e11a0cf77193..a0f708a7cdff 100644
--- a/drivers/soundwire/intel_ace2x.c
+++ b/drivers/soundwire/intel_ace2x.c
@@ -156,8 +156,9 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
goto deprepare_stream;
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col,
- msg->len, SDW_BPT_MSG_MAX_BYTES, &data_per_frame,
- &pdi0_buffer_size, &pdi1_buffer_size, &num_frames);
+ msg->sec[0].len, SDW_BPT_MSG_MAX_BYTES,
+ &data_per_frame, &pdi0_buffer_size, &pdi1_buffer_size,
+ &num_frames);
if (ret < 0)
goto deprepare_stream;
@@ -204,7 +205,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
}
dev_dbg(cdns->dev, "Message len %d transferred in %d frames (%d per frame)\n",
- msg->len, num_frames, data_per_frame);
+ msg->sec[0].len, num_frames, data_per_frame);
dev_dbg(cdns->dev, "sizes pdi0 %d pdi1 %d tx_bandwidth %d rx_bandwidth %d\n",
pdi0_buffer_size, pdi1_buffer_size, tx_dma_bandwidth, rx_dma_bandwidth);
@@ -219,12 +220,14 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
}
if (!command) {
- ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->addr, msg->buf,
- msg->len, data_per_frame,
+ ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec[0].addr,
+ msg->sec[0].buf,
+ msg->sec[0].len, data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes);
} else {
- ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->addr, msg->len,
+ ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec[0].addr,
+ msg->sec[0].len,
data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes,
@@ -305,9 +308,9 @@ static int intel_ace2x_bpt_send_async(struct sdw_intel *sdw, struct sdw_slave *s
struct sdw_cdns *cdns = &sdw->cdns;
int ret;
- if (msg->len < INTEL_BPT_MSG_BYTE_MIN) {
+ if (msg->sec[0].len < INTEL_BPT_MSG_BYTE_MIN) {
dev_err(cdns->dev, "BPT message length %d is less than the minimum bytes %d\n",
- msg->len, INTEL_BPT_MSG_BYTE_MIN);
+ msg->sec[0].len, INTEL_BPT_MSG_BYTE_MIN);
return -EINVAL;
}
@@ -367,7 +370,8 @@ static int intel_ace2x_bpt_wait(struct sdw_intel *sdw, struct sdw_slave *slave,
} else {
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
sdw->bpt_ctx.pdi1_buffer_size,
- msg->buf, msg->len, sdw->bpt_ctx.num_frames,
+ msg->sec[0].buf, msg->sec[0].len,
+ sdw->bpt_ctx.num_frames,
sdw->bpt_ctx.data_per_frame);
if (ret < 0)
dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 2/3] soundwire: pass sdw_bpt_section to cdns BPT helpers
2025-10-21 9:43 [PATCH 0/3] soundwire: send multi sections in one BPT stream Bard Liao
2025-10-21 9:43 ` [PATCH 1/3] soundwire: introduce BPT section Bard Liao
@ 2025-10-21 9:43 ` Bard Liao
2025-10-21 9:43 ` [PATCH 3/3] soundwire: intel_ace2x: handle multi BPT sections Bard Liao
` (2 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Bard Liao @ 2025-10-21 9:43 UTC (permalink / raw)
To: linux-sound, vkoul
Cc: vinod.koul, linux-kernel, pierre-louis.bossart, bard.liao
We can get start_register, data_size, and buffer data from the new
sdw_bpt_section parameter. Also, handle all register sections in the
cdns BRA helpers. No function changes as section number is 1.
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: Shuming Fan <shumingf@realtek.com>
---
drivers/soundwire/cadence_master.c | 218 +++++++++++++++++------------
drivers/soundwire/cadence_master.h | 12 +-
drivers/soundwire/intel_ace2x.c | 11 +-
3 files changed, 139 insertions(+), 102 deletions(-)
diff --git a/drivers/soundwire/cadence_master.c b/drivers/soundwire/cadence_master.c
index 4e94da28d8ad..a106e5e482c8 100644
--- a/drivers/soundwire/cadence_master.c
+++ b/drivers/soundwire/cadence_master.c
@@ -2324,17 +2324,20 @@ static int sdw_cdns_prepare_read_pd0_buffer(u8 *header, unsigned int header_size
#define CDNS_BPT_ROLLING_COUNTER_START 1
-int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
- int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
- int *dma_buffer_total_bytes)
+int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
+ int data_per_frame, u8 *dma_buffer,
+ int dma_buffer_size, int *dma_buffer_total_bytes)
{
int total_dma_data_written = 0;
u8 *p_dma_buffer = dma_buffer;
u8 header[SDW_CDNS_BRA_HDR];
+ unsigned int start_register;
+ unsigned int section_size;
int dma_data_written;
- u8 *p_data = data;
+ u8 *p_data;
u8 counter;
int ret;
+ int i;
counter = CDNS_BPT_ROLLING_COUNTER_START;
@@ -2342,47 +2345,57 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
header[0] |= GENMASK(7, 6); /* header is active */
header[0] |= (dev_num << 2);
- while (data_size >= data_per_frame) {
- header[1] = data_per_frame;
- header[2] = start_register >> 24 & 0xFF;
- header[3] = start_register >> 16 & 0xFF;
- header[4] = start_register >> 8 & 0xFF;
- header[5] = start_register >> 0 & 0xFF;
-
- ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
- p_data, data_per_frame,
- p_dma_buffer, dma_buffer_size,
- &dma_data_written, counter);
- if (ret < 0)
- return ret;
-
- counter++;
-
- p_data += data_per_frame;
- data_size -= data_per_frame;
-
- p_dma_buffer += dma_data_written;
- dma_buffer_size -= dma_data_written;
- total_dma_data_written += dma_data_written;
-
- start_register += data_per_frame;
- }
-
- if (data_size) {
- header[1] = data_size;
- header[2] = start_register >> 24 & 0xFF;
- header[3] = start_register >> 16 & 0xFF;
- header[4] = start_register >> 8 & 0xFF;
- header[5] = start_register >> 0 & 0xFF;
-
- ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
- p_data, data_size,
- p_dma_buffer, dma_buffer_size,
- &dma_data_written, counter);
- if (ret < 0)
- return ret;
-
- total_dma_data_written += dma_data_written;
+ for (i = 0; i < num_sec; i++) {
+ start_register = sec[i].addr;
+ section_size = sec[i].len;
+ p_data = sec[i].buf;
+
+ while (section_size >= data_per_frame) {
+ header[1] = data_per_frame;
+ header[2] = start_register >> 24 & 0xFF;
+ header[3] = start_register >> 16 & 0xFF;
+ header[4] = start_register >> 8 & 0xFF;
+ header[5] = start_register >> 0 & 0xFF;
+
+ ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
+ p_data, data_per_frame,
+ p_dma_buffer, dma_buffer_size,
+ &dma_data_written, counter);
+ if (ret < 0)
+ return ret;
+
+ counter++;
+
+ p_data += data_per_frame;
+ section_size -= data_per_frame;
+
+ p_dma_buffer += dma_data_written;
+ dma_buffer_size -= dma_data_written;
+ total_dma_data_written += dma_data_written;
+
+ start_register += data_per_frame;
+ }
+
+ if (section_size) {
+ header[1] = section_size;
+ header[2] = start_register >> 24 & 0xFF;
+ header[3] = start_register >> 16 & 0xFF;
+ header[4] = start_register >> 8 & 0xFF;
+ header[5] = start_register >> 0 & 0xFF;
+
+ ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
+ p_data, section_size,
+ p_dma_buffer, dma_buffer_size,
+ &dma_data_written, counter);
+ if (ret < 0)
+ return ret;
+
+ counter++;
+
+ p_dma_buffer += dma_data_written;
+ dma_buffer_size -= dma_data_written;
+ total_dma_data_written += dma_data_written;
+ }
}
*dma_buffer_total_bytes = total_dma_data_written;
@@ -2391,16 +2404,19 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
}
EXPORT_SYMBOL(sdw_cdns_prepare_write_dma_buffer);
-int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
+int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
int *dma_buffer_total_bytes, unsigned int fake_size)
{
int total_dma_data_written = 0;
u8 *p_dma_buffer = dma_buffer;
u8 header[SDW_CDNS_BRA_HDR];
+ unsigned int start_register;
+ unsigned int data_size;
int dma_data_written;
u8 counter;
int ret;
+ int i;
counter = CDNS_BPT_ROLLING_COUNTER_START;
@@ -2408,48 +2424,52 @@ int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_si
header[0] |= GENMASK(7, 6); /* header is active */
header[0] |= (dev_num << 2);
- while (data_size >= data_per_frame) {
- header[1] = data_per_frame;
- header[2] = start_register >> 24 & 0xFF;
- header[3] = start_register >> 16 & 0xFF;
- header[4] = start_register >> 8 & 0xFF;
- header[5] = start_register >> 0 & 0xFF;
-
- ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
- dma_buffer_size, &dma_data_written,
- counter);
- if (ret < 0)
- return ret;
-
- counter++;
-
- data_size -= data_per_frame;
-
- p_dma_buffer += dma_data_written;
- dma_buffer_size -= dma_data_written;
- total_dma_data_written += dma_data_written;
-
- start_register += data_per_frame;
- }
-
- if (data_size) {
- header[1] = data_size;
- header[2] = start_register >> 24 & 0xFF;
- header[3] = start_register >> 16 & 0xFF;
- header[4] = start_register >> 8 & 0xFF;
- header[5] = start_register >> 0 & 0xFF;
-
- ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
- dma_buffer_size, &dma_data_written,
- counter);
- if (ret < 0)
- return ret;
-
- counter++;
-
- p_dma_buffer += dma_data_written;
- dma_buffer_size -= dma_data_written;
- total_dma_data_written += dma_data_written;
+ for (i = 0; i < num_sec; i++) {
+ start_register = sec[i].addr;
+ data_size = sec[i].len;
+ while (data_size >= data_per_frame) {
+ header[1] = data_per_frame;
+ header[2] = start_register >> 24 & 0xFF;
+ header[3] = start_register >> 16 & 0xFF;
+ header[4] = start_register >> 8 & 0xFF;
+ header[5] = start_register >> 0 & 0xFF;
+
+ ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
+ p_dma_buffer, dma_buffer_size,
+ &dma_data_written, counter);
+ if (ret < 0)
+ return ret;
+
+ counter++;
+
+ data_size -= data_per_frame;
+
+ p_dma_buffer += dma_data_written;
+ dma_buffer_size -= dma_data_written;
+ total_dma_data_written += dma_data_written;
+
+ start_register += data_per_frame;
+ }
+
+ if (data_size) {
+ header[1] = data_size;
+ header[2] = start_register >> 24 & 0xFF;
+ header[3] = start_register >> 16 & 0xFF;
+ header[4] = start_register >> 8 & 0xFF;
+ header[5] = start_register >> 0 & 0xFF;
+
+ ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
+ p_dma_buffer, dma_buffer_size,
+ &dma_data_written, counter);
+ if (ret < 0)
+ return ret;
+
+ counter++;
+
+ p_dma_buffer += dma_data_written;
+ dma_buffer_size -= dma_data_written;
+ total_dma_data_written += dma_data_written;
+ }
}
/* Add fake frame */
@@ -2616,9 +2636,12 @@ static u8 extract_read_data(u32 *data, int num_bytes, u8 *buffer)
}
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
- u8 *buffer, int buffer_size, int num_frames, int data_per_frame)
+ struct sdw_bpt_section *sec, int num_sec, int num_frames,
+ int data_per_frame)
{
int total_num_bytes = 0;
+ int buffer_size = 0;
+ int sec_index;
u32 *p_data;
u8 *p_buf;
int counter;
@@ -2632,7 +2655,10 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
counter = CDNS_BPT_ROLLING_COUNTER_START;
p_data = (u32 *)dma_buffer;
- p_buf = buffer;
+
+ sec_index = 0;
+ p_buf = sec[sec_index].buf;
+ buffer_size = sec[sec_index].len;
for (i = 0; i < num_frames; i++) {
header = *p_data++;
@@ -2672,6 +2698,18 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
counter++;
counter &= GENMASK(3, 0);
+
+ if (buffer_size == total_num_bytes && (i + 1) < num_frames) {
+ sec_index++;
+ if (sec_index >= num_sec) {
+ dev_err(dev, "%s: incorrect section index %d i %d\n",
+ __func__, sec_index, i);
+ return -EINVAL;
+ }
+ p_buf = sec[sec_index].buf;
+ buffer_size = sec[sec_index].len;
+ total_num_bytes = 0;
+ }
}
return 0;
}
diff --git a/drivers/soundwire/cadence_master.h b/drivers/soundwire/cadence_master.h
index a269a87486fc..668f807cff4b 100644
--- a/drivers/soundwire/cadence_master.h
+++ b/drivers/soundwire/cadence_master.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
/* Copyright(c) 2015-17 Intel Corporation. */
#include <sound/soc.h>
+#include "bus.h"
#ifndef __SDW_CADENCE_H
#define __SDW_CADENCE_H
@@ -220,11 +221,11 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
unsigned int *pdi1_buffer_size, unsigned int *num_frames);
-int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
- int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
- int *dma_buffer_total_bytes);
+int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
+ int data_per_frame, u8 *dma_buffer,
+ int dma_buffer_size, int *dma_buffer_total_bytes);
-int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
+int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
int *dma_buffer_total_bytes, unsigned int fake_size);
@@ -232,5 +233,6 @@ int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer,
int dma_buffer_size, int num_frames);
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
- u8 *buffer, int buffer_size, int num_frames, int data_per_frame);
+ struct sdw_bpt_section *sec, int num_sec, int num_frames,
+ int data_per_frame);
#endif /* __SDW_CADENCE_H */
diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c
index a0f708a7cdff..300ede6bc7f1 100644
--- a/drivers/soundwire/intel_ace2x.c
+++ b/drivers/soundwire/intel_ace2x.c
@@ -220,14 +220,12 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
}
if (!command) {
- ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec[0].addr,
- msg->sec[0].buf,
- msg->sec[0].len, data_per_frame,
+ ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, 1,
+ data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes);
} else {
- ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec[0].addr,
- msg->sec[0].len,
+ ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, 1,
data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes,
@@ -370,8 +368,7 @@ static int intel_ace2x_bpt_wait(struct sdw_intel *sdw, struct sdw_slave *slave,
} else {
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
sdw->bpt_ctx.pdi1_buffer_size,
- msg->sec[0].buf, msg->sec[0].len,
- sdw->bpt_ctx.num_frames,
+ msg->sec, 1, sdw->bpt_ctx.num_frames,
sdw->bpt_ctx.data_per_frame);
if (ret < 0)
dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* [PATCH 3/3] soundwire: intel_ace2x: handle multi BPT sections
2025-10-21 9:43 [PATCH 0/3] soundwire: send multi sections in one BPT stream Bard Liao
2025-10-21 9:43 ` [PATCH 1/3] soundwire: introduce BPT section Bard Liao
2025-10-21 9:43 ` [PATCH 2/3] soundwire: pass sdw_bpt_section to cdns BPT helpers Bard Liao
@ 2025-10-21 9:43 ` Bard Liao
2025-11-12 5:12 ` [PATCH 0/3] soundwire: send multi sections in one BPT stream Vinod Koul
2025-11-12 8:45 ` Vinod Koul
4 siblings, 0 replies; 8+ messages in thread
From: Bard Liao @ 2025-10-21 9:43 UTC (permalink / raw)
To: linux-sound, vkoul
Cc: vinod.koul, linux-kernel, pierre-louis.bossart, bard.liao
Calculate required PDI buffer and pass the section number to the cdns
BPT helpers.
Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
Reviewed-by: Ranjani Sridharan <ranjani.sridharan@linux.intel.com>
Tested-by: Shuming Fan <shumingf@realtek.com>
---
drivers/soundwire/intel_ace2x.c | 46 ++++++++++++++++++++++++---------
1 file changed, 34 insertions(+), 12 deletions(-)
diff --git a/drivers/soundwire/intel_ace2x.c b/drivers/soundwire/intel_ace2x.c
index 300ede6bc7f1..1ed0251d2592 100644
--- a/drivers/soundwire/intel_ace2x.c
+++ b/drivers/soundwire/intel_ace2x.c
@@ -57,6 +57,8 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
struct sdw_port_config *pconfig;
unsigned int pdi0_buf_size_pre_frame;
unsigned int pdi1_buf_size_pre_frame;
+ unsigned int pdi0_buffer_size_;
+ unsigned int pdi1_buffer_size_;
unsigned int pdi0_buffer_size;
unsigned int tx_dma_bandwidth;
unsigned int pdi1_buffer_size;
@@ -68,6 +70,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
struct sdw_cdns_pdi *pdi1;
unsigned int rx_alignment;
unsigned int tx_alignment;
+ unsigned int num_frames_;
unsigned int num_frames;
unsigned int fake_size;
unsigned int tx_pad;
@@ -76,6 +79,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
int ret1;
int ret;
int dir;
+ int len;
int i;
stream = sdw_alloc_stream("BPT", SDW_STREAM_BPT);
@@ -155,12 +159,25 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
if (ret < 0)
goto deprepare_stream;
- ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col,
- msg->sec[0].len, SDW_BPT_MSG_MAX_BYTES,
- &data_per_frame, &pdi0_buffer_size, &pdi1_buffer_size,
- &num_frames);
- if (ret < 0)
- goto deprepare_stream;
+ len = 0;
+ pdi0_buffer_size = 0;
+ pdi1_buffer_size = 0;
+ num_frames = 0;
+ /* Add up pdi buffer size and frame numbers of each BPT sections */
+ for (i = 0; i < msg->sections; i++) {
+ ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row,
+ cdns->bus.params.col,
+ msg->sec[i].len, SDW_BPT_MSG_MAX_BYTES,
+ &data_per_frame, &pdi0_buffer_size_,
+ &pdi1_buffer_size_, &num_frames_);
+ if (ret < 0)
+ goto deprepare_stream;
+
+ len += msg->sec[i].len;
+ pdi0_buffer_size += pdi0_buffer_size_;
+ pdi1_buffer_size += pdi1_buffer_size_;
+ num_frames += num_frames_;
+ }
sdw->bpt_ctx.pdi0_buffer_size = pdi0_buffer_size;
sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size;
@@ -205,7 +222,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
}
dev_dbg(cdns->dev, "Message len %d transferred in %d frames (%d per frame)\n",
- msg->sec[0].len, num_frames, data_per_frame);
+ len, num_frames, data_per_frame);
dev_dbg(cdns->dev, "sizes pdi0 %d pdi1 %d tx_bandwidth %d rx_bandwidth %d\n",
pdi0_buffer_size, pdi1_buffer_size, tx_dma_bandwidth, rx_dma_bandwidth);
@@ -220,12 +237,12 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
}
if (!command) {
- ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, 1,
+ ret = sdw_cdns_prepare_write_dma_buffer(msg->dev_num, msg->sec, msg->sections,
data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes);
} else {
- ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, 1,
+ ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->sec, msg->sections,
data_per_frame,
sdw->bpt_ctx.dmab_tx_bdl.area,
pdi0_buffer_size, &tx_total_bytes,
@@ -304,11 +321,16 @@ static int intel_ace2x_bpt_send_async(struct sdw_intel *sdw, struct sdw_slave *s
struct sdw_bpt_msg *msg)
{
struct sdw_cdns *cdns = &sdw->cdns;
+ int len = 0;
int ret;
+ int i;
- if (msg->sec[0].len < INTEL_BPT_MSG_BYTE_MIN) {
+ for (i = 0; i < msg->sections; i++)
+ len += msg->sec[i].len;
+
+ if (len < INTEL_BPT_MSG_BYTE_MIN) {
dev_err(cdns->dev, "BPT message length %d is less than the minimum bytes %d\n",
- msg->sec[0].len, INTEL_BPT_MSG_BYTE_MIN);
+ len, INTEL_BPT_MSG_BYTE_MIN);
return -EINVAL;
}
@@ -368,7 +390,7 @@ static int intel_ace2x_bpt_wait(struct sdw_intel *sdw, struct sdw_slave *slave,
} else {
ret = sdw_cdns_check_read_response(cdns->dev, sdw->bpt_ctx.dmab_rx_bdl.area,
sdw->bpt_ctx.pdi1_buffer_size,
- msg->sec, 1, sdw->bpt_ctx.num_frames,
+ msg->sec, msg->sections, sdw->bpt_ctx.num_frames,
sdw->bpt_ctx.data_per_frame);
if (ret < 0)
dev_err(cdns->dev, "%s: BPT Read failed %d\n", __func__, ret);
--
2.43.0
^ permalink raw reply related [flat|nested] 8+ messages in thread* Re: [PATCH 0/3] soundwire: send multi sections in one BPT stream
2025-10-21 9:43 [PATCH 0/3] soundwire: send multi sections in one BPT stream Bard Liao
` (2 preceding siblings ...)
2025-10-21 9:43 ` [PATCH 3/3] soundwire: intel_ace2x: handle multi BPT sections Bard Liao
@ 2025-11-12 5:12 ` Vinod Koul
2025-11-12 6:13 ` Liao, Bard
2025-11-12 8:45 ` Vinod Koul
4 siblings, 1 reply; 8+ messages in thread
From: Vinod Koul @ 2025-11-12 5:12 UTC (permalink / raw)
To: Bard Liao; +Cc: linux-sound, linux-kernel, pierre-louis.bossart, bard.liao
On 21-10-25, 17:43, Bard Liao wrote:
> Currently we send a BRA message with a start address with continuous
> registers in a BPT stream. However, a codec may need to write different
> register sections shortly. It makes more sense to send different
> register sections in a BPT stream and no need to close/open the BPT
> stream repeatedly.
>
> This series depends on the "ASoC/soundwire: add fake BPT frame to align
> Intel DMA buffer size" series. Sending it now to get more review time.
I have applied it on top of above series, pls check why it is not
applying in :
error: patch failed: drivers/soundwire/intel_ace2x.c:156
error: drivers/soundwire/intel_ace2x.c: patch does not apply
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 0/3] soundwire: send multi sections in one BPT stream
2025-11-12 5:12 ` [PATCH 0/3] soundwire: send multi sections in one BPT stream Vinod Koul
@ 2025-11-12 6:13 ` Liao, Bard
2025-11-12 8:46 ` Vinod Koul
0 siblings, 1 reply; 8+ messages in thread
From: Liao, Bard @ 2025-11-12 6:13 UTC (permalink / raw)
To: Vinod Koul; +Cc: linux-sound, linux-kernel, pierre-louis.bossart, bard.liao
On 11/12/2025 1:12 PM, Vinod Koul wrote:
> On 21-10-25, 17:43, Bard Liao wrote:
>> Currently we send a BRA message with a start address with continuous
>> registers in a BPT stream. However, a codec may need to write different
>> register sections shortly. It makes more sense to send different
>> register sections in a BPT stream and no need to close/open the BPT
>> stream repeatedly.
>>
>> This series depends on the "ASoC/soundwire: add fake BPT frame to align
>> Intel DMA buffer size" series. Sending it now to get more review time.
>
> I have applied it on top of above series, pls check why it is not
> applying in :
> error: patch failed: drivers/soundwire/intel_ace2x.c:156
> error: drivers/soundwire/intel_ace2x.c: patch does not apply
>
Hi Vinod,
I just tried "git am" this series again and it can apply on top of
04878e873d94 ("ASoC/soundwire: add fake BPT frame to align Intel DMA
buffer size").
Also, I checked drivers/soundwire/intel_ace2x.c line 156 and it has the
same content as the "soundwire: introduce BPT section" patch.
Sorry, I have no idea why it didn't apply. Could you please try again?
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [PATCH 0/3] soundwire: send multi sections in one BPT stream
2025-11-12 6:13 ` Liao, Bard
@ 2025-11-12 8:46 ` Vinod Koul
0 siblings, 0 replies; 8+ messages in thread
From: Vinod Koul @ 2025-11-12 8:46 UTC (permalink / raw)
To: Liao, Bard; +Cc: linux-sound, linux-kernel, pierre-louis.bossart, bard.liao
On 12-11-25, 14:13, Liao, Bard wrote:
>
>
> On 11/12/2025 1:12 PM, Vinod Koul wrote:
> > On 21-10-25, 17:43, Bard Liao wrote:
> >> Currently we send a BRA message with a start address with continuous
> >> registers in a BPT stream. However, a codec may need to write different
> >> register sections shortly. It makes more sense to send different
> >> register sections in a BPT stream and no need to close/open the BPT
> >> stream repeatedly.
> >>
> >> This series depends on the "ASoC/soundwire: add fake BPT frame to align
> >> Intel DMA buffer size" series. Sending it now to get more review time.
> >
> > I have applied it on top of above series, pls check why it is not
> > applying in :
> > error: patch failed: drivers/soundwire/intel_ace2x.c:156
> > error: drivers/soundwire/intel_ace2x.c: patch does not apply
> >
>
> Hi Vinod,
>
> I just tried "git am" this series again and it can apply on top of
> 04878e873d94 ("ASoC/soundwire: add fake BPT frame to align Intel DMA
> buffer size").
> Also, I checked drivers/soundwire/intel_ace2x.c line 156 and it has the
> same content as the "soundwire: introduce BPT section" patch.
> Sorry, I have no idea why it didn't apply. Could you please try again?
Yeah I fixed the commit base and it worked, thanks
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [PATCH 0/3] soundwire: send multi sections in one BPT stream
2025-10-21 9:43 [PATCH 0/3] soundwire: send multi sections in one BPT stream Bard Liao
` (3 preceding siblings ...)
2025-11-12 5:12 ` [PATCH 0/3] soundwire: send multi sections in one BPT stream Vinod Koul
@ 2025-11-12 8:45 ` Vinod Koul
4 siblings, 0 replies; 8+ messages in thread
From: Vinod Koul @ 2025-11-12 8:45 UTC (permalink / raw)
To: linux-sound, Bard Liao
Cc: vinod.koul, linux-kernel, pierre-louis.bossart, bard.liao
On Tue, 21 Oct 2025 17:43:51 +0800, Bard Liao wrote:
> Currently we send a BRA message with a start address with continuous
> registers in a BPT stream. However, a codec may need to write different
> register sections shortly. It makes more sense to send different
> register sections in a BPT stream and no need to close/open the BPT
> stream repeatedly.
>
> This series depends on the "ASoC/soundwire: add fake BPT frame to align
> Intel DMA buffer size" series. Sending it now to get more review time.
>
> [...]
Applied, thanks!
[1/3] soundwire: introduce BPT section
commit: 96755433031e426353cee230abd0e6170d386787
[2/3] soundwire: pass sdw_bpt_section to cdns BPT helpers
commit: 1fdffb2012767f12bba6bb5646a6967e5607caec
[3/3] soundwire: intel_ace2x: handle multi BPT sections
commit: 336859050e5844b2e8b601dd126d5dc46f6c00f4
Best regards,
--
~Vinod
^ permalink raw reply [flat|nested] 8+ messages in thread