audio: host: update position every period to improve precision

The position is currently updated by the host component when a
period was consumed. The granularity of this position is too large,
applications relying on timer-based scheduling may query the
position at any time and conformance test suites fail.

This patch introduce another field "cont_update_posn" in
sof_ipc_stream_params which suggests a more precise position
reporting, by storing the latest position in a memory window
when the host component completes a transfer. This will increase
the traffic to memory windows, but allow for a much smaller
granularity in position updates.

In hindsight, this solution should have been the default behavior
but to avoid backwards compatibility issues is added as a new
capability controlled by an ABI check. Only with a recent-enough
Linux kernel will this behavior be enabled.

Signed-off-by: YC Hung <yc.hung@mediatek.com>
This commit is contained in:
YC Hung 2021-12-28 20:05:54 +08:00 committed by Liam Girdwood
parent c42ede6a97
commit 6a18e5a8c9
3 changed files with 20 additions and 7 deletions

View File

@ -76,6 +76,7 @@ struct host_data {
uint32_t host_period_bytes;
uint16_t stream_tag;
uint16_t no_stream_position; /**< 1 means don't send stream position */
uint8_t cont_update_posn; /**< 1 means continuous update stream position */
/* host component attributes */
enum comp_copy_type copy_type; /**< Current host copy type */
@ -307,6 +308,8 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes)
struct comp_buffer *source;
struct comp_buffer *sink;
int ret;
bool update_mailbox = false;
bool send_ipc = false;
if (dev->direction == SOF_IPC_STREAM_PLAYBACK)
@ -345,6 +348,8 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes)
#else
hd->local_pos = 0;
#endif
if (hd->cont_update_posn)
update_mailbox = true;
/* Don't send stream position if no_stream_position == 1 */
if (!hd->no_stream_position) {
@ -361,12 +366,18 @@ static void host_update_position(struct comp_dev *dev, uint32_t bytes)
/* send timestamped position to host
* (updates position first, by calling ops.position())
*/
pipeline_get_timestamp(dev->pipeline, dev, &hd->posn);
mailbox_stream_write(dev->pipeline->posn_offset,
&hd->posn, sizeof(hd->posn));
ipc_msg_send(hd->msg, &hd->posn, false);
update_mailbox = true;
send_ipc = true;
}
}
if (update_mailbox) {
pipeline_get_timestamp(dev->pipeline, dev, &hd->posn);
mailbox_stream_write(dev->pipeline->posn_offset,
&hd->posn, sizeof(hd->posn));
if (send_ipc)
ipc_msg_send(hd->msg, &hd->posn, false);
}
}
/* The host memory is not guaranteed to be continuous and also not guaranteed
@ -761,6 +772,7 @@ static int host_params(struct comp_dev *dev,
hd->stream_tag = params->stream_tag;
hd->no_stream_position = params->no_stream_position;
hd->host_period_bytes = params->host_period_bytes;
hd->cont_update_posn = params->cont_update_posn;
/* retrieve DMA buffer address alignment */
err = dma_get_attribute(hd->dma, DMA_ATTR_BUFFER_ADDRESS_ALIGNMENT,

View File

@ -94,8 +94,9 @@ struct sof_ipc_stream_params {
uint32_t host_period_bytes;
uint16_t no_stream_position; /**< 1 means don't send stream position */
uint8_t cont_update_posn; /**< 1 means continuous update stream position */
uint16_t reserved[3];
uint8_t reserved[5];
uint16_t chmap[SOF_IPC_MAX_CHANNELS]; /**< channel map - SOF_CHMAP_ */
} __attribute__((packed, aligned(4)));

View File

@ -29,8 +29,8 @@
/** \brief SOF ABI version major, minor and patch numbers */
#define SOF_ABI_MAJOR 3
#define SOF_ABI_MINOR 20
#define SOF_ABI_PATCH 1
#define SOF_ABI_MINOR 21
#define SOF_ABI_PATCH 0
/** \brief SOF ABI version number. Format within 32bit word is MMmmmppp */
#define SOF_ABI_MAJOR_SHIFT 24