mirror of
https://github.com/torvalds/linux.git
synced 2026-07-28 01:55:51 +02:00
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:
parent
7c1ac23b17
commit
ed56ac9e5e
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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__ */
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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_ */
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user