Skip to content

Commit 96e539b

Browse files
committed
soundwire: send multi sections in one BPT stream
Bard Liao <yung-chuan.liao@linux.intel.com> says: 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. Link: https://patch.msgid.link/20251021094355.132943-1-yung-chuan.liao@linux.intel.com Signed-off-by: Vinod Koul <vkoul@kernel.org>
2 parents 04878e8 + 3368590 commit 96e539b

6 files changed

Lines changed: 189 additions & 102 deletions

File tree

drivers/soundwire/bus.c

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2052,8 +2052,14 @@ EXPORT_SYMBOL(sdw_clear_slave_status);
20522052

20532053
int sdw_bpt_send_async(struct sdw_bus *bus, struct sdw_slave *slave, struct sdw_bpt_msg *msg)
20542054
{
2055-
if (msg->len > SDW_BPT_MSG_MAX_BYTES) {
2056-
dev_err(bus->dev, "Invalid BPT message length %d\n", msg->len);
2055+
int len = 0;
2056+
int i;
2057+
2058+
for (i = 0; i < msg->sections; i++)
2059+
len += msg->sec[i].len;
2060+
2061+
if (len > SDW_BPT_MSG_MAX_BYTES) {
2062+
dev_err(bus->dev, "Invalid BPT message length %d\n", len);
20572063
return -EINVAL;
20582064
}
20592065

drivers/soundwire/bus.h

Lines changed: 16 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -73,21 +73,31 @@ struct sdw_msg {
7373
};
7474

7575
/**
76-
* struct sdw_btp_msg - Message structure
76+
* struct sdw_btp_section - Message section structure
7777
* @addr: Start Register address accessed in the Slave
7878
* @len: number of bytes to transfer. More than 64Kb can be transferred
7979
* but a practical limit of SDW_BPT_MSG_MAX_BYTES is enforced.
80-
* @dev_num: Slave device number
81-
* @flags: transfer flags, indicate if xfer is read or write
82-
* @buf: message data buffer (filled by host for write, filled
80+
* @buf: section data buffer (filled by host for write, filled
8381
* by Peripheral hardware for reads)
8482
*/
85-
struct sdw_bpt_msg {
83+
struct sdw_bpt_section {
8684
u32 addr;
8785
u32 len;
86+
u8 *buf;
87+
};
88+
89+
/**
90+
* struct sdw_btp_msg - Message structure
91+
* @sec: Pointer to array of sections
92+
* @sections: Number of sections in the array
93+
* @dev_num: Slave device number
94+
* @flags: transfer flags, indicate if xfer is read or write
95+
*/
96+
struct sdw_bpt_msg {
97+
struct sdw_bpt_section *sec;
98+
int sections;
8899
u8 dev_num;
89100
u8 flags;
90-
u8 *buf;
91101
};
92102

93103
#define SDW_DOUBLE_RATE_FACTOR 2

drivers/soundwire/cadence_master.c

Lines changed: 112 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -2324,65 +2324,78 @@ static int sdw_cdns_prepare_read_pd0_buffer(u8 *header, unsigned int header_size
23242324

23252325
#define CDNS_BPT_ROLLING_COUNTER_START 1
23262326

2327-
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
2328-
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
2329-
int *dma_buffer_total_bytes)
2327+
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
2328+
int data_per_frame, u8 *dma_buffer,
2329+
int dma_buffer_size, int *dma_buffer_total_bytes)
23302330
{
23312331
int total_dma_data_written = 0;
23322332
u8 *p_dma_buffer = dma_buffer;
23332333
u8 header[SDW_CDNS_BRA_HDR];
2334+
unsigned int start_register;
2335+
unsigned int section_size;
23342336
int dma_data_written;
2335-
u8 *p_data = data;
2337+
u8 *p_data;
23362338
u8 counter;
23372339
int ret;
2340+
int i;
23382341

23392342
counter = CDNS_BPT_ROLLING_COUNTER_START;
23402343

23412344
header[0] = BIT(1); /* write command: BIT(1) set */
23422345
header[0] |= GENMASK(7, 6); /* header is active */
23432346
header[0] |= (dev_num << 2);
23442347

2345-
while (data_size >= data_per_frame) {
2346-
header[1] = data_per_frame;
2347-
header[2] = start_register >> 24 & 0xFF;
2348-
header[3] = start_register >> 16 & 0xFF;
2349-
header[4] = start_register >> 8 & 0xFF;
2350-
header[5] = start_register >> 0 & 0xFF;
2351-
2352-
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2353-
p_data, data_per_frame,
2354-
p_dma_buffer, dma_buffer_size,
2355-
&dma_data_written, counter);
2356-
if (ret < 0)
2357-
return ret;
2348+
for (i = 0; i < num_sec; i++) {
2349+
start_register = sec[i].addr;
2350+
section_size = sec[i].len;
2351+
p_data = sec[i].buf;
23582352

2359-
counter++;
2353+
while (section_size >= data_per_frame) {
2354+
header[1] = data_per_frame;
2355+
header[2] = start_register >> 24 & 0xFF;
2356+
header[3] = start_register >> 16 & 0xFF;
2357+
header[4] = start_register >> 8 & 0xFF;
2358+
header[5] = start_register >> 0 & 0xFF;
23602359

2361-
p_data += data_per_frame;
2362-
data_size -= data_per_frame;
2360+
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2361+
p_data, data_per_frame,
2362+
p_dma_buffer, dma_buffer_size,
2363+
&dma_data_written, counter);
2364+
if (ret < 0)
2365+
return ret;
23632366

2364-
p_dma_buffer += dma_data_written;
2365-
dma_buffer_size -= dma_data_written;
2366-
total_dma_data_written += dma_data_written;
2367+
counter++;
23672368

2368-
start_register += data_per_frame;
2369-
}
2369+
p_data += data_per_frame;
2370+
section_size -= data_per_frame;
23702371

2371-
if (data_size) {
2372-
header[1] = data_size;
2373-
header[2] = start_register >> 24 & 0xFF;
2374-
header[3] = start_register >> 16 & 0xFF;
2375-
header[4] = start_register >> 8 & 0xFF;
2376-
header[5] = start_register >> 0 & 0xFF;
2372+
p_dma_buffer += dma_data_written;
2373+
dma_buffer_size -= dma_data_written;
2374+
total_dma_data_written += dma_data_written;
23772375

2378-
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2379-
p_data, data_size,
2380-
p_dma_buffer, dma_buffer_size,
2381-
&dma_data_written, counter);
2382-
if (ret < 0)
2383-
return ret;
2376+
start_register += data_per_frame;
2377+
}
23842378

2385-
total_dma_data_written += dma_data_written;
2379+
if (section_size) {
2380+
header[1] = section_size;
2381+
header[2] = start_register >> 24 & 0xFF;
2382+
header[3] = start_register >> 16 & 0xFF;
2383+
header[4] = start_register >> 8 & 0xFF;
2384+
header[5] = start_register >> 0 & 0xFF;
2385+
2386+
ret = sdw_cdns_prepare_write_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2387+
p_data, section_size,
2388+
p_dma_buffer, dma_buffer_size,
2389+
&dma_data_written, counter);
2390+
if (ret < 0)
2391+
return ret;
2392+
2393+
counter++;
2394+
2395+
p_dma_buffer += dma_data_written;
2396+
dma_buffer_size -= dma_data_written;
2397+
total_dma_data_written += dma_data_written;
2398+
}
23862399
}
23872400

23882401
*dma_buffer_total_bytes = total_dma_data_written;
@@ -2391,65 +2404,72 @@ int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data,
23912404
}
23922405
EXPORT_SYMBOL(sdw_cdns_prepare_write_dma_buffer);
23932406

2394-
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
2407+
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
23952408
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
23962409
int *dma_buffer_total_bytes, unsigned int fake_size)
23972410
{
23982411
int total_dma_data_written = 0;
23992412
u8 *p_dma_buffer = dma_buffer;
24002413
u8 header[SDW_CDNS_BRA_HDR];
2414+
unsigned int start_register;
2415+
unsigned int data_size;
24012416
int dma_data_written;
24022417
u8 counter;
24032418
int ret;
2419+
int i;
24042420

24052421
counter = CDNS_BPT_ROLLING_COUNTER_START;
24062422

24072423
header[0] = 0; /* read command: BIT(1) cleared */
24082424
header[0] |= GENMASK(7, 6); /* header is active */
24092425
header[0] |= (dev_num << 2);
24102426

2411-
while (data_size >= data_per_frame) {
2412-
header[1] = data_per_frame;
2413-
header[2] = start_register >> 24 & 0xFF;
2414-
header[3] = start_register >> 16 & 0xFF;
2415-
header[4] = start_register >> 8 & 0xFF;
2416-
header[5] = start_register >> 0 & 0xFF;
2427+
for (i = 0; i < num_sec; i++) {
2428+
start_register = sec[i].addr;
2429+
data_size = sec[i].len;
2430+
while (data_size >= data_per_frame) {
2431+
header[1] = data_per_frame;
2432+
header[2] = start_register >> 24 & 0xFF;
2433+
header[3] = start_register >> 16 & 0xFF;
2434+
header[4] = start_register >> 8 & 0xFF;
2435+
header[5] = start_register >> 0 & 0xFF;
24172436

2418-
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
2419-
dma_buffer_size, &dma_data_written,
2420-
counter);
2421-
if (ret < 0)
2422-
return ret;
2437+
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2438+
p_dma_buffer, dma_buffer_size,
2439+
&dma_data_written, counter);
2440+
if (ret < 0)
2441+
return ret;
24232442

2424-
counter++;
2443+
counter++;
24252444

2426-
data_size -= data_per_frame;
2445+
data_size -= data_per_frame;
24272446

2428-
p_dma_buffer += dma_data_written;
2429-
dma_buffer_size -= dma_data_written;
2430-
total_dma_data_written += dma_data_written;
2447+
p_dma_buffer += dma_data_written;
2448+
dma_buffer_size -= dma_data_written;
2449+
total_dma_data_written += dma_data_written;
24312450

2432-
start_register += data_per_frame;
2433-
}
2451+
start_register += data_per_frame;
2452+
}
24342453

2435-
if (data_size) {
2436-
header[1] = data_size;
2437-
header[2] = start_register >> 24 & 0xFF;
2438-
header[3] = start_register >> 16 & 0xFF;
2439-
header[4] = start_register >> 8 & 0xFF;
2440-
header[5] = start_register >> 0 & 0xFF;
2454+
if (data_size) {
2455+
header[1] = data_size;
2456+
header[2] = start_register >> 24 & 0xFF;
2457+
header[3] = start_register >> 16 & 0xFF;
2458+
header[4] = start_register >> 8 & 0xFF;
2459+
header[5] = start_register >> 0 & 0xFF;
24412460

2442-
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR, p_dma_buffer,
2443-
dma_buffer_size, &dma_data_written,
2444-
counter);
2445-
if (ret < 0)
2446-
return ret;
2461+
ret = sdw_cdns_prepare_read_pd0_buffer(header, SDW_CDNS_BRA_HDR,
2462+
p_dma_buffer, dma_buffer_size,
2463+
&dma_data_written, counter);
2464+
if (ret < 0)
2465+
return ret;
24472466

2448-
counter++;
2467+
counter++;
24492468

2450-
p_dma_buffer += dma_data_written;
2451-
dma_buffer_size -= dma_data_written;
2452-
total_dma_data_written += dma_data_written;
2469+
p_dma_buffer += dma_data_written;
2470+
dma_buffer_size -= dma_data_written;
2471+
total_dma_data_written += dma_data_written;
2472+
}
24532473
}
24542474

24552475
/* Add fake frame */
@@ -2616,9 +2636,12 @@ static u8 extract_read_data(u32 *data, int num_bytes, u8 *buffer)
26162636
}
26172637

26182638
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
2619-
u8 *buffer, int buffer_size, int num_frames, int data_per_frame)
2639+
struct sdw_bpt_section *sec, int num_sec, int num_frames,
2640+
int data_per_frame)
26202641
{
26212642
int total_num_bytes = 0;
2643+
int buffer_size = 0;
2644+
int sec_index;
26222645
u32 *p_data;
26232646
u8 *p_buf;
26242647
int counter;
@@ -2632,7 +2655,10 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
26322655

26332656
counter = CDNS_BPT_ROLLING_COUNTER_START;
26342657
p_data = (u32 *)dma_buffer;
2635-
p_buf = buffer;
2658+
2659+
sec_index = 0;
2660+
p_buf = sec[sec_index].buf;
2661+
buffer_size = sec[sec_index].len;
26362662

26372663
for (i = 0; i < num_frames; i++) {
26382664
header = *p_data++;
@@ -2672,6 +2698,18 @@ int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buf
26722698

26732699
counter++;
26742700
counter &= GENMASK(3, 0);
2701+
2702+
if (buffer_size == total_num_bytes && (i + 1) < num_frames) {
2703+
sec_index++;
2704+
if (sec_index >= num_sec) {
2705+
dev_err(dev, "%s: incorrect section index %d i %d\n",
2706+
__func__, sec_index, i);
2707+
return -EINVAL;
2708+
}
2709+
p_buf = sec[sec_index].buf;
2710+
buffer_size = sec[sec_index].len;
2711+
total_num_bytes = 0;
2712+
}
26752713
}
26762714
return 0;
26772715
}

drivers/soundwire/cadence_master.h

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/* SPDX-License-Identifier: (GPL-2.0 OR BSD-3-Clause) */
22
/* Copyright(c) 2015-17 Intel Corporation. */
33
#include <sound/soc.h>
4+
#include "bus.h"
45

56
#ifndef __SDW_CADENCE_H
67
#define __SDW_CADENCE_H
@@ -220,17 +221,18 @@ int sdw_cdns_bpt_find_buffer_sizes(int command, /* 0: write, 1: read */
220221
unsigned int *data_per_frame, unsigned int *pdi0_buffer_size,
221222
unsigned int *pdi1_buffer_size, unsigned int *num_frames);
222223

223-
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, u32 start_register, u8 *data, int data_size,
224-
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
225-
int *dma_buffer_total_bytes);
224+
int sdw_cdns_prepare_write_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
225+
int data_per_frame, u8 *dma_buffer,
226+
int dma_buffer_size, int *dma_buffer_total_bytes);
226227

227-
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, u32 start_register, int data_size,
228+
int sdw_cdns_prepare_read_dma_buffer(u8 dev_num, struct sdw_bpt_section *sec, int num_sec,
228229
int data_per_frame, u8 *dma_buffer, int dma_buffer_size,
229230
int *dma_buffer_total_bytes, unsigned int fake_size);
230231

231232
int sdw_cdns_check_write_response(struct device *dev, u8 *dma_buffer,
232233
int dma_buffer_size, int num_frames);
233234

234235
int sdw_cdns_check_read_response(struct device *dev, u8 *dma_buffer, int dma_buffer_size,
235-
u8 *buffer, int buffer_size, int num_frames, int data_per_frame);
236+
struct sdw_bpt_section *sec, int num_sec, int num_frames,
237+
int data_per_frame);
236238
#endif /* __SDW_CADENCE_H */

drivers/soundwire/debugfs.c

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,15 +222,23 @@ DEFINE_DEBUGFS_ATTRIBUTE(set_num_bytes_fops, NULL,
222222
static int do_bpt_sequence(struct sdw_slave *slave, bool write, u8 *buffer)
223223
{
224224
struct sdw_bpt_msg msg = {0};
225+
struct sdw_bpt_section *sec;
225226

226-
msg.addr = start_addr;
227-
msg.len = num_bytes;
227+
sec = kcalloc(1, sizeof(*sec), GFP_KERNEL);
228+
if (!sec)
229+
return -ENOMEM;
230+
msg.sections = 1;
231+
232+
sec[0].addr = start_addr;
233+
sec[0].len = num_bytes;
234+
235+
msg.sec = sec;
228236
msg.dev_num = slave->dev_num;
229237
if (write)
230238
msg.flags = SDW_MSG_FLAG_WRITE;
231239
else
232240
msg.flags = SDW_MSG_FLAG_READ;
233-
msg.buf = buffer;
241+
sec[0].buf = buffer;
234242

235243
return sdw_bpt_send_sync(slave->bus, slave, &msg);
236244
}

0 commit comments

Comments
 (0)