Skip to content

Commit 8707df5

Browse files
committed
soundwire: intel_ace2x: add fake frame to BRA read command
Intel DMA buffer size need to be a mutiple of data block size. Find the minimal fake data size and extra buffer size to meet the requirement. Signed-off-by: Bard Liao <yung-chuan.liao@linux.intel.com>
1 parent 71cf9e2 commit 8707df5

File tree

1 file changed

+56
-5
lines changed

1 file changed

+56
-5
lines changed

drivers/soundwire/intel_ace2x.c

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,8 @@ static int sdw_slave_bpt_stream_add(struct sdw_slave *slave, struct sdw_stream_r
4444
return ret;
4545
}
4646

47+
#define READ_PDI1_MIN_SIZE 12
48+
4749
static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *slave,
4850
struct sdw_bpt_msg *msg)
4951
{
@@ -53,15 +55,23 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
5355
struct sdw_stream_runtime *stream;
5456
struct sdw_stream_config sconfig;
5557
struct sdw_port_config *pconfig;
58+
unsigned int pdi0_buf_size_pre_frame;
59+
unsigned int pdi1_buf_size_pre_frame;
5660
unsigned int pdi0_buffer_size;
5761
unsigned int tx_dma_bandwidth;
5862
unsigned int pdi1_buffer_size;
5963
unsigned int rx_dma_bandwidth;
64+
unsigned int fake_num_frames;
6065
unsigned int data_per_frame;
6166
unsigned int tx_total_bytes;
6267
struct sdw_cdns_pdi *pdi0;
6368
struct sdw_cdns_pdi *pdi1;
69+
unsigned int rx_alignment;
70+
unsigned int tx_alignment;
6471
unsigned int num_frames;
72+
unsigned int fake_size;
73+
unsigned int tx_pad;
74+
unsigned int rx_pad;
6575
int command;
6676
int ret1;
6777
int ret;
@@ -138,6 +148,13 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
138148

139149
command = (msg->flags & SDW_MSG_FLAG_WRITE) ? 0 : 1;
140150

151+
ret = sdw_cdns_bpt_find_bandwidth(command, cdns->bus.params.row,
152+
cdns->bus.params.col,
153+
prop->default_frame_rate,
154+
&tx_dma_bandwidth, &rx_dma_bandwidth);
155+
if (ret < 0)
156+
goto deprepare_stream;
157+
141158
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row, cdns->bus.params.col,
142159
msg->len, SDW_BPT_MSG_MAX_BYTES, &data_per_frame,
143160
&pdi0_buffer_size, &pdi1_buffer_size, &num_frames);
@@ -148,10 +165,44 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
148165
sdw->bpt_ctx.pdi1_buffer_size = pdi1_buffer_size;
149166
sdw->bpt_ctx.num_frames = num_frames;
150167
sdw->bpt_ctx.data_per_frame = data_per_frame;
151-
tx_dma_bandwidth = div_u64((u64)pdi0_buffer_size * 8 * (u64)prop->default_frame_rate,
152-
num_frames);
153-
rx_dma_bandwidth = div_u64((u64)pdi1_buffer_size * 8 * (u64)prop->default_frame_rate,
154-
num_frames);
168+
169+
rx_alignment = hda_sdw_bpt_get_buf_size_alignment(rx_dma_bandwidth);
170+
tx_alignment = hda_sdw_bpt_get_buf_size_alignment(tx_dma_bandwidth);
171+
172+
if (command) { /* read */
173+
/* Get buffer size of a full frame */
174+
ret = sdw_cdns_bpt_find_buffer_sizes(command, cdns->bus.params.row,
175+
cdns->bus.params.col,
176+
data_per_frame, SDW_BPT_MSG_MAX_BYTES,
177+
&data_per_frame, &pdi0_buf_size_pre_frame,
178+
&pdi1_buf_size_pre_frame, &fake_num_frames);
179+
if (ret < 0)
180+
goto deprepare_stream;
181+
182+
/* find fake pdi1 buffer size */
183+
rx_pad = rx_alignment - (pdi1_buffer_size % rx_alignment);
184+
while (rx_pad <= READ_PDI1_MIN_SIZE) {
185+
rx_pad += rx_alignment;
186+
}
187+
pdi1_buffer_size += rx_pad;
188+
/* It is fine if we request more than enough byte to read */
189+
fake_num_frames = DIV_ROUND_UP(rx_pad, pdi1_buf_size_pre_frame);
190+
fake_size = fake_num_frames * data_per_frame;
191+
192+
/* find fake pdi0 buffer size */
193+
pdi0_buffer_size += (fake_num_frames * pdi0_buf_size_pre_frame);
194+
tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment);
195+
pdi0_buffer_size += tx_pad;
196+
} else { /* write */
197+
/*
198+
* For the write command, the rx data block is 4, and the rx buffer size of a frame
199+
* is 8. So the rx buffer size (pdi0_buffer_size) is always a mutiple of rx
200+
* alignment.
201+
*/
202+
tx_pad = tx_alignment - (pdi0_buffer_size % tx_alignment);
203+
pdi0_buffer_size += tx_pad;
204+
205+
}
155206

156207
dev_dbg(cdns->dev, "Message len %d transferred in %d frames (%d per frame)\n",
157208
msg->len, num_frames, data_per_frame);
@@ -177,7 +228,7 @@ static int intel_ace2x_bpt_open_stream(struct sdw_intel *sdw, struct sdw_slave *
177228
ret = sdw_cdns_prepare_read_dma_buffer(msg->dev_num, msg->addr, msg->len,
178229
data_per_frame,
179230
sdw->bpt_ctx.dmab_tx_bdl.area,
180-
pdi0_buffer_size, &tx_total_bytes, 0);
231+
pdi0_buffer_size, &tx_total_bytes, fake_size);
181232
}
182233

183234
if (!ret)

0 commit comments

Comments
 (0)