ASoC: qcom: q6apm: add watermark event support

Push-pull shared memory modules can report watermark events when the DSP
read/write index reaches configured circular buffer levels.

Add support for registering watermark levels with the shared memory module
and route the resulting module event to q6apm clients using a new
APM_CLIENT_EVENT_WATERMARK_EVENT event.

Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com>
Link: https://patch.msgid.link/20260528185806.6316-6-srinivas.kandagatla@oss.qualcomm.com
Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
Srinivas Kandagatla 2026-05-28 19:58:04 +01:00 committed by Mark Brown
parent 7c1ac23b17
commit ed56ac9e5e
No known key found for this signature in database
GPG Key ID: 24D68B725D5487D0
4 changed files with 102 additions and 0 deletions

View File

@ -1118,6 +1118,42 @@ static int audioreach_pcm_set_media_format(struct q6apm_graph *graph,
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
}
int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels)
{
struct apm_module_register_events *event;
struct event_cfg_sh_mem_pull_push_mode_watermark_t *level;
int i, payload_size;
struct gpr_pkt *pkt __free(kfree) = NULL;
void *p;
if (num_levels <= 0 || bytes <= 0)
return -EINVAL;
payload_size = sizeof(*event) + sizeof(*level) + num_levels * sizeof(uint32_t);
pkt = audioreach_alloc_cmd_pkt(payload_size, APM_CMD_REGISTER_MODULE_EVENTS, 0,
graph->port->id, graph->shm_iid);
if (IS_ERR(pkt))
return PTR_ERR(pkt);
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
event = p;
event->module_instance_id = graph->shm_iid;
event->event_id = EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK;
event->is_register = 1;
event->event_config_payload_size = sizeof(*level) + num_levels * sizeof(uint32_t);
p += sizeof(*event);
level = p;
level->num_water_mark_levels = num_levels;
for (i = 0; i < num_levels; i++)
level->level[i] = (i + 1) * bytes;
return audioreach_graph_send_cmd_sync(graph, pkt, 0);
}
EXPORT_SYMBOL_GPL(audioreach_shmem_register_event);
static int audioreach_shmem_set_media_format(struct q6apm_graph *graph,
const struct audioreach_module *module,
const struct audioreach_module_config *mcfg)

View File

@ -62,6 +62,8 @@ struct q6apm_graph;
#define APM_CMD_GET_CFG 0x01001007
#define APM_CMD_SHARED_MEM_MAP_REGIONS 0x0100100C
#define APM_CMD_SHARED_MEM_UNMAP_REGIONS 0x0100100D
#define APM_CMD_REGISTER_MODULE_EVENTS 0x0100100E
#define APM_EVENT_MODULE_TO_CLIENT 0x03001000
#define APM_CMD_RSP_SHARED_MEM_MAP_REGIONS 0x02001001
#define APM_MMAP_TOKEN_GID_MASK GENMASK(15, 0)
#define APM_MMAP_TOKEN_MAP_TYPE_POS_BUF BIT(16)
@ -69,6 +71,48 @@ struct q6apm_graph;
#define APM_CMD_RSP_GET_CFG 0x02001000
#define APM_CMD_CLOSE_ALL 0x01001013
#define APM_CMD_REGISTER_SHARED_CFG 0x0100100A
#define EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK 0x0800101C
/**
* struct event_cfg_sh_mem_pull_push_mode_watermark_t - Watermark config
* @num_water_mark_levels: Number of watermark levels.
* @level: Watermark levels.
*
* If @num_water_mark_levels is zero, no watermark levels are specified
* and watermark events are not supported.
*/
struct event_cfg_sh_mem_pull_push_mode_watermark_t {
uint32_t num_water_mark_levels;
uint32_t level[];
} __packed;
/**
* struct apm_module_register_events - Register or unregister module events
* @module_instance_id: Module instance identifier.
* @event_id: Module event identifier.
* @is_register: 1 to register the event, 0 to unregister it.
* @error_code: Error code for out-of-band command mode.
* @event_config_payload_size: Event configuration payload size in bytes.
* @reserved: Reserved for alignment; must be zero.
*/
struct apm_module_register_events {
uint32_t module_instance_id;
uint32_t event_id;
uint32_t is_register;
uint32_t error_code;
uint32_t event_config_payload_size;
uint32_t reserved;
} __packed;
/**
* struct apm_module_event - Module event descriptor
* @event_id: Module event identifier.
* @event_payload_size: Event payload size in bytes.
*/
struct apm_module_event {
uint32_t event_id;
uint32_t event_payload_size;
} __packed;
#define APM_MEMORY_MAP_SHMEM8_4K_POOL 3
@ -907,4 +951,5 @@ int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys,
uint32_t pos_buf_mem_map_handle, uint32_t size);
int audioreach_map_memory_position_buffer(struct q6apm_graph *graph, unsigned int dir);
int audioreach_shmem_register_event(struct q6apm_graph *graph, int bytes, int num_levels);
#endif /* __AUDIOREACH_H__ */

View File

@ -557,6 +557,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
{
struct data_cmd_rsp_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done;
struct apm_module_event *event;
const struct gpr_ibasic_rsp_result_t *result;
struct q6apm_graph *graph = priv;
const struct gpr_hdr *hdr = &data->hdr;
@ -568,6 +569,16 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
result = data->payload;
switch (hdr->opcode) {
case APM_EVENT_MODULE_TO_CLIENT:
event = data->payload;
switch (event->event_id) {
case EVENT_ID_SH_MEM_PULL_PUSH_MODE_WATERMARK:
client_event = APM_CLIENT_EVENT_WATERMARK_EVENT;
graph->cb(client_event, hdr->token, data->payload, graph->priv);
break;
}
break;
case DATA_CMD_RSP_WR_SH_MEM_EP_DATA_BUFFER_DONE_V2:
if (!graph->ar_graph)
break;
@ -623,6 +634,7 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
switch (result->opcode) {
case APM_CMD_SHARED_MEM_MAP_REGIONS:
case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT:
case APM_CMD_REGISTER_MODULE_EVENTS:
case APM_CMD_SET_CFG:
graph->result.opcode = result->opcode;
graph->result.status = result->status;
@ -641,6 +653,13 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
return 0;
}
int q6apm_register_watermark_event(struct q6apm_graph *graph, int water_mark_level_bytes,
int num_levels)
{
return audioreach_shmem_register_event(graph, water_mark_level_bytes, num_levels);
}
EXPORT_SYMBOL_GPL(q6apm_register_watermark_event);
int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys,
phys_addr_t pphys, uint32_t size)
{

View File

@ -41,6 +41,7 @@
#define APM_CLIENT_EVENT_CMD_RUN_DONE 0x1008
#define APM_CLIENT_EVENT_DATA_WRITE_DONE 0x1009
#define APM_CLIENT_EVENT_DATA_READ_DONE 0x100a
#define APM_CLIENT_EVENT_WATERMARK_EVENT 0x100b
#define APM_WRITE_TOKEN_MASK GENMASK(15, 0)
#define APM_WRITE_TOKEN_LEN_MASK GENMASK(31, 16)
#define APM_WRITE_TOKEN_LEN_SHIFT 16
@ -164,4 +165,5 @@ bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int g
int q6apm_push_pull_config(struct q6apm_graph *graph, phys_addr_t bphys,
phys_addr_t pphys, uint32_t size);
int q6apm_register_watermark_event(struct q6apm_graph *graph, int watermark_bytes, int num_levels);
#endif /* __APM_GRAPH_ */