All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/3] soundwire: send multi sections in one BPT stream
@ 2025-10-21  9:43 Bard Liao
  2025-10-21  9:43 ` [PATCH 1/3] soundwire: introduce BPT section Bard Liao
                   ` (4 more replies)
  0 siblings, 5 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. 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.

Bard Liao (3):
  soundwire: introduce BPT section
  soundwire: pass sdw_bpt_section to cdns BPT helpers
  soundwire: intel_ace2x: handle multi BPT sections

 drivers/soundwire/bus.c            |  10 +-
 drivers/soundwire/bus.h            |  22 ++-
 drivers/soundwire/cadence_master.c | 218 +++++++++++++++++------------
 drivers/soundwire/cadence_master.h |  12 +-
 drivers/soundwire/debugfs.c        |  14 +-
 drivers/soundwire/intel_ace2x.c    |  47 +++++--
 6 files changed, 205 insertions(+), 118 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [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-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

* 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

end of thread, other threads:[~2025-11-12  8:46 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
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 ` [PATCH 3/3] soundwire: intel_ace2x: handle multi BPT sections Bard Liao
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
2025-11-12  8:45 ` Vinod Koul

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.