mirror of
https://github.com/torvalds/linux.git
synced 2026-07-27 17:47:41 +02:00
ASoC: qcom: qdsp6: add push/pull module support
Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> says: This patchset adds support for Push/Pull mode modules. Push-pull mode uses dedicated shared-memory modules that allow the DSP to access the PCM circular buffer directly. In addition to reducing fragment queueing and ACK handling in the host driver, This mode exposes a DSP-maintained position buffer that provides fine-grained hardware pointer updates. Unlike the Read/Write Shared Memory endpoitn modules, which are period based, where the reported pointer advances only at period boundaries, where as push-pull mode allows .pointer() to reflect sub-period progress, improving pointer accuracy. Also the driver now can queue buffers which are less than period size, which makes tests like alsa_conformance_test happy. Now the pointer update visibility is around 1ms, compared to min of 10ms with read/write shared memory endpoints. Along with the circular buffer support, this patchset also adds watermark event support to provide a period level event from dsp to notify about period progress. Tested this on T14s, Arduino VENTUNO-Q platforms. Tplg related changes are available at: https://github.com/Srinivas-Kandagatla/audioreach-topology/tree/push/pull Link: https://patch.msgid.link/20260528185806.6316-1-srinivas.kandagatla@oss.qualcomm.com
This commit is contained in:
commit
3ef902c960
|
|
@ -955,7 +955,7 @@ int audioreach_compr_set_param(struct q6apm_graph *graph,
|
|||
struct media_format *header;
|
||||
int rc;
|
||||
void *p;
|
||||
int iid = q6apm_graph_get_rx_shmem_module_iid(graph);
|
||||
int iid = graph->shm_iid;
|
||||
int payload_size = sizeof(struct apm_sh_module_media_fmt_cmd);
|
||||
|
||||
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(payload_size,
|
||||
|
|
@ -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)
|
||||
|
|
@ -1342,6 +1378,7 @@ int audioreach_set_media_format(struct q6apm_graph *graph,
|
|||
rc = audioreach_i2s_set_media_format(graph, module, cfg);
|
||||
break;
|
||||
case MODULE_ID_WR_SHARED_MEM_EP:
|
||||
case MODULE_ID_SH_MEM_PULL_MODE:
|
||||
rc = audioreach_shmem_set_media_format(graph, module, cfg);
|
||||
break;
|
||||
case MODULE_ID_GAIN:
|
||||
|
|
@ -1401,10 +1438,48 @@ void audioreach_graph_free_buf(struct q6apm_graph *graph)
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
|
||||
|
||||
int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys,
|
||||
phys_addr_t pphys, uint32_t mem_map_handle,
|
||||
uint32_t pos_buf_mem_map_handle, uint32_t size)
|
||||
{
|
||||
struct param_id_sh_mem_pull_push_mode_cfg *cfg;
|
||||
struct apm_module_param_data *param_data;
|
||||
int payload_size;
|
||||
struct gpr_pkt *pkt __free(kfree) = NULL;
|
||||
void *p;
|
||||
|
||||
payload_size = sizeof(*cfg) + APM_MODULE_PARAM_DATA_SIZE;
|
||||
pkt = audioreach_alloc_apm_cmd_pkt(payload_size, APM_CMD_SET_CFG, 0);
|
||||
if (IS_ERR(pkt))
|
||||
return PTR_ERR(pkt);
|
||||
|
||||
p = (void *)pkt + GPR_HDR_SIZE + APM_CMD_HDR_SIZE;
|
||||
|
||||
param_data = p;
|
||||
param_data->module_instance_id = graph->shm_iid;
|
||||
param_data->error_code = 0;
|
||||
param_data->param_id = PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG;
|
||||
param_data->param_size = payload_size - APM_MODULE_PARAM_DATA_SIZE;
|
||||
|
||||
p = p + APM_MODULE_PARAM_DATA_SIZE;
|
||||
cfg = p;
|
||||
|
||||
cfg->shared_circ_buf_addr_lsw = lower_32_bits(bphys);
|
||||
cfg->shared_circ_buf_addr_msw = upper_32_bits(bphys);
|
||||
cfg->shared_circ_buf_size = size;
|
||||
cfg->circ_buf_mem_map_handle = mem_map_handle;
|
||||
cfg->shared_pos_buf_addr_lsw = lower_32_bits(pphys);
|
||||
cfg->shared_pos_buf_addr_msw = upper_32_bits(pphys);
|
||||
cfg->pos_buf_mem_map_handle = pos_buf_mem_map_handle;
|
||||
|
||||
return q6apm_send_cmd_sync(graph->apm, pkt, 0);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(audioreach_setup_push_pull);
|
||||
|
||||
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
|
||||
{
|
||||
struct data_cmd_wr_sh_mem_ep_eos *eos;
|
||||
int iid = q6apm_graph_get_rx_shmem_module_iid(graph);
|
||||
int iid = graph->shm_iid;
|
||||
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_cmd_pkt(sizeof(*eos),
|
||||
DATA_CMD_WR_SH_MEM_EP_EOS, 0, graph->port->id, iid);
|
||||
if (IS_ERR(pkt))
|
||||
|
|
|
|||
|
|
@ -16,6 +16,8 @@ struct q6apm_graph;
|
|||
#define MODULE_ID_PCM_CNV 0x07001003
|
||||
#define MODULE_ID_PCM_ENC 0x07001004
|
||||
#define MODULE_ID_PCM_DEC 0x07001005
|
||||
#define MODULE_ID_SH_MEM_PULL_MODE 0x07001006
|
||||
#define MODULE_ID_SH_MEM_PUSH_MODE 0x07001007
|
||||
#define MODULE_ID_PLACEHOLDER_ENCODER 0x07001008
|
||||
#define MODULE_ID_PLACEHOLDER_DECODER 0x07001009
|
||||
#define MODULE_ID_I2S_SINK 0x0700100A
|
||||
|
|
@ -60,10 +62,57 @@ 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)
|
||||
#define APM_MMAP_TOKEN_MAP_TYPE_SHIFT 16
|
||||
#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
|
||||
|
||||
|
|
@ -710,6 +759,46 @@ struct param_id_placeholder_real_module_id {
|
|||
uint32_t real_module_id;
|
||||
} __packed;
|
||||
|
||||
|
||||
#define PARAM_ID_SH_MEM_PULL_PUSH_MODE_CFG 0x0800100A
|
||||
|
||||
/**
|
||||
* struct param_id_sh_mem_pull_push_mode_cfg - Shared memory push/pull config
|
||||
* @shared_circ_buf_addr_lsw: Lower 32 bits of the circular buffer address.
|
||||
* @shared_circ_buf_addr_msw: Upper 32 bits of the circular buffer address.
|
||||
* @shared_circ_buf_size: Circular buffer size in bytes.
|
||||
* @circ_buf_mem_map_handle: Circular buffer memory map handle.
|
||||
* @shared_pos_buf_addr_lsw: Lower 32 bits of the position buffer address.
|
||||
* @shared_pos_buf_addr_msw: Upper 32 bits of the position buffer address.
|
||||
* @pos_buf_mem_map_handle: Position buffer memory map handle.
|
||||
*/
|
||||
struct param_id_sh_mem_pull_push_mode_cfg {
|
||||
uint32_t shared_circ_buf_addr_lsw;
|
||||
uint32_t shared_circ_buf_addr_msw;
|
||||
uint32_t shared_circ_buf_size;
|
||||
uint32_t circ_buf_mem_map_handle;
|
||||
uint32_t shared_pos_buf_addr_lsw;
|
||||
uint32_t shared_pos_buf_addr_msw;
|
||||
uint32_t pos_buf_mem_map_handle;
|
||||
} __packed;
|
||||
|
||||
/**
|
||||
* struct sh_mem_pull_push_mode_position_buffer - Shared position buffer
|
||||
* @frame_counter: Synchronization counter.
|
||||
* @index: Current read/write index in bytes.
|
||||
* @timestamp_us_lsw: Lower 32 bits of the timestamp in microseconds.
|
||||
* @timestamp_us_msw: Upper 32 bits of the timestamp in microseconds.
|
||||
*
|
||||
* The frame counter should be read before and after the other fields to
|
||||
* ensure the DSP did not update them while they were being read.
|
||||
*/
|
||||
struct sh_mem_pull_push_mode_position_buffer {
|
||||
uint32_t frame_counter;
|
||||
uint32_t index;
|
||||
uint32_t timestamp_us_lsw;
|
||||
uint32_t timestamp_us_msw;
|
||||
} __packed;
|
||||
|
||||
/* Graph */
|
||||
struct audioreach_connection {
|
||||
/* Connections */
|
||||
|
|
@ -723,8 +812,10 @@ struct audioreach_connection {
|
|||
struct audioreach_graph_info {
|
||||
int id;
|
||||
uint32_t mem_map_handle;
|
||||
uint32_t pos_buf_mem_map_handle;
|
||||
uint32_t num_sub_graphs;
|
||||
struct list_head sg_list;
|
||||
bool is_push_pull_mode;
|
||||
/* DPCM connection from FE Graph to BE graph */
|
||||
uint32_t src_mod_inst_id;
|
||||
uint32_t src_mod_op_port_id;
|
||||
|
|
@ -855,5 +946,10 @@ int audioreach_send_u32_param(struct q6apm_graph *graph,
|
|||
uint32_t param_id, uint32_t param_val);
|
||||
int audioreach_compr_set_param(struct q6apm_graph *graph,
|
||||
const struct audioreach_module_config *mcfg);
|
||||
int audioreach_setup_push_pull(struct q6apm_graph *graph, phys_addr_t bphys,
|
||||
phys_addr_t pphys, uint32_t mem_map_handle,
|
||||
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__ */
|
||||
|
|
|
|||
|
|
@ -18,6 +18,7 @@
|
|||
#include "q6apm.h"
|
||||
|
||||
#define DRV_NAME "q6apm-dai"
|
||||
#define POS_BUFFER_BYTES 4096
|
||||
|
||||
#define PLAYBACK_MIN_NUM_PERIODS 2
|
||||
#define PLAYBACK_MAX_NUM_PERIODS 8
|
||||
|
|
@ -62,8 +63,12 @@ struct q6apm_dai_rtd {
|
|||
struct snd_codec codec;
|
||||
struct snd_compr_params codec_param;
|
||||
struct snd_dma_buffer dma_buffer;
|
||||
struct sh_mem_pull_push_mode_position_buffer *pos_buffer;
|
||||
uint32_t last_pos_index;
|
||||
phys_addr_t phys;
|
||||
phys_addr_t pos_phys;
|
||||
unsigned int pcm_size;
|
||||
unsigned int push_pull_size;
|
||||
unsigned int pcm_count;
|
||||
unsigned int periods;
|
||||
uint64_t bytes_sent;
|
||||
|
|
@ -128,6 +133,9 @@ static void event_handler(uint32_t opcode, uint32_t token, void *payload, void *
|
|||
struct snd_pcm_substream *substream = prtd->substream;
|
||||
|
||||
switch (opcode) {
|
||||
case APM_CLIENT_EVENT_WATERMARK_EVENT:
|
||||
snd_pcm_period_elapsed(substream);
|
||||
break;
|
||||
case APM_CLIENT_EVENT_CMD_EOS_DONE:
|
||||
prtd->state = Q6APM_STREAM_STOPPED;
|
||||
break;
|
||||
|
|
@ -234,24 +242,47 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
|||
q6apm_free_fragments(prtd->graph, substream->stream);
|
||||
}
|
||||
|
||||
prtd->last_pos_index = 0;
|
||||
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
||||
/* rate and channels are sent to audio driver */
|
||||
ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s: q6apm_open_write failed\n", __func__);
|
||||
return ret;
|
||||
if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
|
||||
if (prtd->pcm_size != prtd->push_pull_size) {
|
||||
ret = q6apm_push_pull_config(prtd->graph, prtd->phys, prtd->pos_phys,
|
||||
prtd->pcm_size);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Push/Pull config failed rc = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = q6apm_register_watermark_event(prtd->graph,
|
||||
prtd->pcm_size / prtd->periods,
|
||||
prtd->periods);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "WaterMark event config failed rc = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
prtd->push_pull_size = prtd->pcm_size;
|
||||
}
|
||||
} else {
|
||||
ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
|
||||
(prtd->pcm_size / prtd->periods), prtd->periods);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ret = q6apm_graph_media_format_pcm(prtd->graph, &cfg);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "%s: CMD Format block failed\n", __func__);
|
||||
|
||||
ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
|
||||
(prtd->pcm_size / prtd->periods), prtd->periods);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||
return -ENOMEM;
|
||||
dev_err(dev, "%s: CMD Format block failed\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* rate and channels are sent to audio driver */
|
||||
ret = q6apm_graph_media_format_shmem(prtd->graph, &cfg);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "Failed to set media format %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = q6apm_graph_prepare(prtd->graph);
|
||||
|
|
@ -265,13 +296,13 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
|||
dev_err(dev, "Failed to Start Graph %d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
int i;
|
||||
/* Queue the buffers for Capture ONLY after graph is started */
|
||||
for (i = 0; i < runtime->periods; i++)
|
||||
q6apm_read(prtd->graph);
|
||||
|
||||
if (!q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
|
||||
if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
int i;
|
||||
/* Queue the buffers for Capture ONLY after graph is started */
|
||||
for (i = 0; i < runtime->periods; i++)
|
||||
q6apm_read(prtd->graph);
|
||||
}
|
||||
}
|
||||
|
||||
/* Now that graph as been prepared and started update the internal state accordingly */
|
||||
|
|
@ -286,6 +317,9 @@ static int q6apm_dai_ack(struct snd_soc_component *component, struct snd_pcm_sub
|
|||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||
int i, ret = 0, avail_periods;
|
||||
|
||||
if (q6apm_is_graph_in_push_pull_mode(prtd->graph))
|
||||
return 0;
|
||||
|
||||
if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
avail_periods = (runtime->control->appl_ptr - prtd->queue_ptr)/runtime->period_size;
|
||||
for (i = 0; i < avail_periods; i++) {
|
||||
|
|
@ -317,6 +351,7 @@ static int q6apm_dai_trigger(struct snd_soc_component *component,
|
|||
/* TODO support be handled via SoftPause Module */
|
||||
prtd->state = Q6APM_STREAM_STOPPED;
|
||||
prtd->queue_ptr = 0;
|
||||
prtd->last_pos_index = 0;
|
||||
break;
|
||||
case SNDRV_PCM_TRIGGER_SUSPEND:
|
||||
case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
|
||||
|
|
@ -402,6 +437,14 @@ static int q6apm_dai_open(struct snd_soc_component *component,
|
|||
else
|
||||
prtd->phys = substream->dma_buffer.addr | (pdata->sid << 32);
|
||||
|
||||
if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
|
||||
void *pos_buffer;
|
||||
|
||||
prtd->pos_phys = prtd->phys + BUFFER_BYTES_MAX;
|
||||
pos_buffer = (void *)(substream->dma_buffer.area + BUFFER_BYTES_MAX);
|
||||
prtd->pos_buffer = (struct sh_mem_pull_push_mode_position_buffer *)(pos_buffer);
|
||||
}
|
||||
|
||||
return 0;
|
||||
err:
|
||||
kfree(prtd);
|
||||
|
|
@ -436,6 +479,25 @@ static snd_pcm_uframes_t q6apm_dai_pointer(struct snd_soc_component *component,
|
|||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||
snd_pcm_uframes_t ptr;
|
||||
|
||||
if (q6apm_is_graph_in_push_pull_mode(prtd->graph)) {
|
||||
int retries = 10;
|
||||
uint32_t index, fc1, fc2;
|
||||
|
||||
/* index is valid if frame_counter does not change while reading. */
|
||||
do {
|
||||
fc1 = READ_ONCE(prtd->pos_buffer->frame_counter);
|
||||
index = READ_ONCE(prtd->pos_buffer->index);
|
||||
fc2 = READ_ONCE(prtd->pos_buffer->frame_counter);
|
||||
} while (fc1 != fc2 && --retries);
|
||||
|
||||
if (fc1 != fc2)
|
||||
index = prtd->last_pos_index;
|
||||
else
|
||||
prtd->last_pos_index = index;
|
||||
|
||||
ptr = bytes_to_frames(runtime, index);
|
||||
return ptr;
|
||||
}
|
||||
ptr = q6apm_get_hw_pointer(prtd->graph, substream->stream) * runtime->period_size;
|
||||
if (ptr)
|
||||
return ptr - 1;
|
||||
|
|
@ -468,7 +530,8 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component,
|
|||
}
|
||||
|
||||
static int q6apm_dai_memory_map(struct snd_soc_component *component,
|
||||
struct snd_pcm_substream *substream, int graph_id)
|
||||
struct snd_pcm_substream *substream,
|
||||
int graph_id, bool is_push_pull)
|
||||
{
|
||||
struct q6apm_dai_data *pdata;
|
||||
struct device *dev = component->dev;
|
||||
|
|
@ -490,6 +553,19 @@ static int q6apm_dai_memory_map(struct snd_soc_component *component,
|
|||
if (ret < 0)
|
||||
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||
|
||||
if (is_push_pull) {
|
||||
if (pdata->sid < 0)
|
||||
phys = substream->dma_buffer.addr + BUFFER_BYTES_MAX;
|
||||
else
|
||||
phys = (substream->dma_buffer.addr + BUFFER_BYTES_MAX) | (pdata->sid << 32);
|
||||
|
||||
ret = q6apm_map_pos_buffer(dev, graph_id, phys, POS_BUFFER_BYTES);
|
||||
if (ret < 0)
|
||||
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||
} else {
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
@ -504,25 +580,30 @@ static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc
|
|||
*/
|
||||
int size = BUFFER_BYTES_MAX + PAGE_SIZE;
|
||||
int graph_id, ret;
|
||||
struct snd_pcm_substream *substream;
|
||||
bool is_push_pull;
|
||||
struct snd_pcm_substream *substream = NULL;
|
||||
|
||||
graph_id = cpu_dai->driver->id;
|
||||
|
||||
ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Note: DSP backend dais are uni-directional ONLY(either playback or capture) */
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) {
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream)
|
||||
substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
||||
ret = q6apm_dai_memory_map(component, substream, graph_id);
|
||||
else if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream)
|
||||
substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
|
||||
|
||||
|
||||
if (substream) {
|
||||
is_push_pull = q6apm_is_graph_in_push_pull_mode_from_id(component->dev,
|
||||
graph_id,
|
||||
substream->stream);
|
||||
if (is_push_pull)
|
||||
size += POS_BUFFER_BYTES;
|
||||
|
||||
ret = snd_pcm_set_fixed_buffer_all(pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) {
|
||||
substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
|
||||
ret = q6apm_dai_memory_map(component, substream, graph_id);
|
||||
ret = q6apm_dai_memory_map(component, substream, graph_id, is_push_pull);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
|
@ -547,6 +628,9 @@ static void q6apm_dai_memory_unmap(struct snd_soc_component *component,
|
|||
|
||||
graph_id = cpu_dai->driver->id;
|
||||
q6apm_unmap_memory_fixed_region(component->dev, graph_id);
|
||||
|
||||
if (q6apm_is_graph_in_push_pull_mode_from_id(component->dev, graph_id, substream->stream))
|
||||
q6apm_unmap_pos_buffer(component->dev, graph_id);
|
||||
}
|
||||
|
||||
static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
|
||||
|
|
|
|||
|
|
@ -186,23 +186,27 @@ int q6apm_graph_media_format_shmem(struct q6apm_graph *graph,
|
|||
{
|
||||
struct audioreach_module *module;
|
||||
|
||||
if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE)
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
|
||||
else
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
|
||||
if (cfg->direction == SNDRV_PCM_STREAM_CAPTURE) {
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PUSH_MODE);
|
||||
if (!module)
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
|
||||
} else {
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_SH_MEM_PULL_MODE);
|
||||
if (!module)
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
|
||||
}
|
||||
|
||||
if (!module)
|
||||
if (!module) {
|
||||
dev_err(graph->dev, "No SHMEM module found in graph\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
audioreach_set_media_format(graph, module, cfg);
|
||||
|
||||
return 0;
|
||||
|
||||
return audioreach_set_media_format(graph, module, cfg);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem);
|
||||
|
||||
int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
|
||||
size_t sz)
|
||||
static int __q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id,
|
||||
phys_addr_t phys, size_t sz, bool is_pos_buf)
|
||||
{
|
||||
struct audioreach_graph_info *info;
|
||||
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||
|
|
@ -211,8 +215,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
|
|||
int payload_size = sizeof(*cmd) + (sizeof(*mregions));
|
||||
uint32_t buf_sz;
|
||||
void *p;
|
||||
uint32_t pos_mask = is_pos_buf ? APM_MMAP_TOKEN_MAP_TYPE_POS_BUF : 0;
|
||||
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size,
|
||||
APM_CMD_SHARED_MEM_MAP_REGIONS, graph_id);
|
||||
APM_CMD_SHARED_MEM_MAP_REGIONS, (graph_id | pos_mask));
|
||||
|
||||
if (IS_ERR(pkt))
|
||||
return PTR_ERR(pkt);
|
||||
|
||||
|
|
@ -220,8 +226,13 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
|
|||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
if (info->mem_map_handle)
|
||||
return 0;
|
||||
if (is_pos_buf) {
|
||||
if (info->pos_buf_mem_map_handle)
|
||||
return 0;
|
||||
} else {
|
||||
if (info->mem_map_handle)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* DSP expects size should be aligned to 4K */
|
||||
buf_sz = ALIGN(sz, 4096);
|
||||
|
|
@ -230,7 +241,10 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
|
|||
cmd = p;
|
||||
cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
|
||||
cmd->num_regions = 1;
|
||||
cmd->property_flag = 0x0;
|
||||
if (is_pos_buf)
|
||||
cmd->property_flag = 0x2;
|
||||
else
|
||||
cmd->property_flag = 0x0;
|
||||
|
||||
mregions = p + sizeof(*cmd);
|
||||
|
||||
|
|
@ -240,6 +254,18 @@ int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phy
|
|||
|
||||
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
|
||||
}
|
||||
|
||||
int q6apm_map_pos_buffer(struct device *dev, unsigned int graph_id, phys_addr_t phys, size_t sz)
|
||||
{
|
||||
return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_map_pos_buffer);
|
||||
|
||||
int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id,
|
||||
phys_addr_t phys, size_t sz)
|
||||
{
|
||||
return __q6apm_map_memory_fixed_region(dev, graph_id, phys, sz, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_map_memory_fixed_region);
|
||||
|
||||
int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
|
||||
|
|
@ -293,11 +319,13 @@ int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_alloc_fragments);
|
||||
|
||||
int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
|
||||
static int __q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id,
|
||||
bool is_pos_buf)
|
||||
{
|
||||
struct apm_cmd_shared_mem_unmap_regions *cmd;
|
||||
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||
struct audioreach_graph_info *info;
|
||||
uint32_t mem_map_handle;
|
||||
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd),
|
||||
APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id);
|
||||
if (IS_ERR(pkt))
|
||||
|
|
@ -307,16 +335,35 @@ int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
|
|||
if (!info)
|
||||
return -ENODEV;
|
||||
|
||||
if (!info->mem_map_handle)
|
||||
return 0;
|
||||
if (is_pos_buf) {
|
||||
if (!info->pos_buf_mem_map_handle)
|
||||
return 0;
|
||||
mem_map_handle = info->pos_buf_mem_map_handle;
|
||||
} else {
|
||||
|
||||
if (!info->mem_map_handle)
|
||||
return 0;
|
||||
mem_map_handle = info->mem_map_handle;
|
||||
}
|
||||
|
||||
cmd = (void *)pkt + GPR_HDR_SIZE;
|
||||
cmd->mem_map_handle = info->mem_map_handle;
|
||||
cmd->mem_map_handle = mem_map_handle;
|
||||
|
||||
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
|
||||
}
|
||||
|
||||
int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
|
||||
{
|
||||
return __q6apm_unmap_memory_fixed_region(dev, graph_id, false);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_unmap_memory_fixed_region);
|
||||
|
||||
int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id)
|
||||
{
|
||||
return __q6apm_unmap_memory_fixed_region(dev, graph_id, true);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_unmap_pos_buffer);
|
||||
|
||||
int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
|
||||
{
|
||||
audioreach_graph_free_buf(graph);
|
||||
|
|
@ -399,15 +446,20 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo
|
|||
struct audioreach_sub_graph *sgs;
|
||||
struct audioreach_container *container;
|
||||
struct audioreach_module *module;
|
||||
int ret;
|
||||
|
||||
list_for_each_entry(sgs, &info->sg_list, node) {
|
||||
list_for_each_entry(container, &sgs->container_list, node) {
|
||||
list_for_each_entry(module, &container->modules_list, node) {
|
||||
if ((module->module_id == MODULE_ID_WR_SHARED_MEM_EP) ||
|
||||
(module->module_id == MODULE_ID_RD_SHARED_MEM_EP))
|
||||
(module->module_id == MODULE_ID_RD_SHARED_MEM_EP) ||
|
||||
(module->module_id == MODULE_ID_SH_MEM_PULL_MODE) ||
|
||||
(module->module_id == MODULE_ID_SH_MEM_PUSH_MODE))
|
||||
continue;
|
||||
|
||||
audioreach_set_media_format(graph, module, cfg);
|
||||
ret = audioreach_set_media_format(graph, module, cfg);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -417,31 +469,6 @@ int q6apm_graph_media_format_pcm(struct q6apm_graph *graph, struct audioreach_mo
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_pcm);
|
||||
|
||||
static int q6apm_graph_get_tx_shmem_module_iid(struct q6apm_graph *graph)
|
||||
{
|
||||
struct audioreach_module *module;
|
||||
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_RD_SHARED_MEM_EP);
|
||||
if (!module)
|
||||
return -ENODEV;
|
||||
|
||||
return module->instance_id;
|
||||
|
||||
}
|
||||
|
||||
int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph)
|
||||
{
|
||||
struct audioreach_module *module;
|
||||
|
||||
module = q6apm_find_module_by_mid(graph, MODULE_ID_WR_SHARED_MEM_EP);
|
||||
if (!module)
|
||||
return -ENODEV;
|
||||
|
||||
return module->instance_id;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_graph_get_rx_shmem_module_iid);
|
||||
|
||||
int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
|
||||
uint32_t lsw_ts, uint32_t wflags)
|
||||
{
|
||||
|
|
@ -530,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;
|
||||
|
|
@ -541,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;
|
||||
|
|
@ -596,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;
|
||||
|
|
@ -614,13 +653,67 @@ 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)
|
||||
{
|
||||
struct audioreach_graph_info *info = graph->info;
|
||||
|
||||
return audioreach_setup_push_pull(graph, bphys, pphys, info->mem_map_handle,
|
||||
info->pos_buf_mem_map_handle, size);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_push_pull_config);
|
||||
|
||||
bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir)
|
||||
{
|
||||
struct audioreach_graph_info *info;
|
||||
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||
struct audioreach_module *module;
|
||||
|
||||
info = idr_find(&apm->graph_info_idr, graph_id);
|
||||
if (!info)
|
||||
return false;
|
||||
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PULL_MODE);
|
||||
else
|
||||
module = __q6apm_find_module_by_mid(apm, info, MODULE_ID_SH_MEM_PUSH_MODE);
|
||||
|
||||
return !!module;
|
||||
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode_from_id);
|
||||
|
||||
bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph)
|
||||
{
|
||||
return graph->info->is_push_pull_mode;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(q6apm_is_graph_in_push_pull_mode);
|
||||
|
||||
static int q6apm_graph_get_module_iid(struct q6apm_graph *graph, uint32_t mid)
|
||||
{
|
||||
struct audioreach_module *module;
|
||||
|
||||
module = q6apm_find_module_by_mid(graph, mid);
|
||||
if (!module)
|
||||
return -ENODEV;
|
||||
|
||||
return module->instance_id;
|
||||
}
|
||||
|
||||
struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
|
||||
void *priv, int graph_id, int dir)
|
||||
{
|
||||
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||
struct audioreach_graph *ar_graph;
|
||||
struct q6apm_graph *graph;
|
||||
int ret;
|
||||
int ret, iid = 0;
|
||||
|
||||
ar_graph = q6apm_get_audioreach_graph(apm, graph_id);
|
||||
if (IS_ERR(ar_graph)) {
|
||||
|
|
@ -642,11 +735,23 @@ struct q6apm_graph *q6apm_graph_open(struct device *dev, q6apm_cb cb,
|
|||
graph->id = ar_graph->id;
|
||||
graph->dev = dev;
|
||||
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||
graph->shm_iid = q6apm_graph_get_rx_shmem_module_iid(graph);
|
||||
else
|
||||
graph->shm_iid = q6apm_graph_get_tx_shmem_module_iid(graph);
|
||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK) {
|
||||
iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PULL_MODE);
|
||||
if (iid < 0)
|
||||
iid = q6apm_graph_get_module_iid(graph, MODULE_ID_WR_SHARED_MEM_EP);
|
||||
else
|
||||
graph->info->is_push_pull_mode = true;
|
||||
|
||||
} else {
|
||||
iid = q6apm_graph_get_module_iid(graph, MODULE_ID_SH_MEM_PUSH_MODE);
|
||||
if (iid < 0)
|
||||
iid = q6apm_graph_get_module_iid(graph, MODULE_ID_RD_SHARED_MEM_EP);
|
||||
else
|
||||
graph->info->is_push_pull_mode = true;
|
||||
}
|
||||
|
||||
if (iid > 0)
|
||||
graph->shm_iid = iid;
|
||||
|
||||
mutex_init(&graph->lock);
|
||||
init_waitqueue_head(&graph->cmd_wait);
|
||||
|
|
@ -803,6 +908,7 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
|||
struct device *dev = &gdev->dev;
|
||||
struct gpr_ibasic_rsp_result_t *result;
|
||||
const struct gpr_hdr *hdr = &data->hdr;
|
||||
int graph_id, is_pos_buf;
|
||||
|
||||
result = data->payload;
|
||||
|
||||
|
|
@ -853,13 +959,19 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
|||
apm->result.opcode = hdr->opcode;
|
||||
apm->result.status = 0;
|
||||
rsp = data->payload;
|
||||
graph_id = hdr->token & APM_MMAP_TOKEN_GID_MASK;
|
||||
is_pos_buf = hdr->token & APM_MMAP_TOKEN_MAP_TYPE_POS_BUF;
|
||||
|
||||
info = idr_find(&apm->graph_info_idr, hdr->token);
|
||||
if (info)
|
||||
info->mem_map_handle = rsp->mem_map_handle;
|
||||
else
|
||||
info = idr_find(&apm->graph_info_idr, graph_id);
|
||||
if (info) {
|
||||
if (is_pos_buf)
|
||||
info->pos_buf_mem_map_handle = rsp->mem_map_handle;
|
||||
else
|
||||
info->mem_map_handle = rsp->mem_map_handle;
|
||||
} else {
|
||||
dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status,
|
||||
result->opcode);
|
||||
}
|
||||
|
||||
wake_up(&apm->wait);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -136,6 +137,10 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
|
|||
int q6apm_map_memory_fixed_region(struct device *dev,
|
||||
unsigned int graph_id, phys_addr_t phys,
|
||||
size_t sz);
|
||||
int q6apm_map_pos_buffer(struct device *dev,
|
||||
unsigned int graph_id, phys_addr_t phys,
|
||||
size_t sz);
|
||||
int q6apm_unmap_pos_buffer(struct device *dev, unsigned int graph_id);
|
||||
int q6apm_alloc_fragments(struct q6apm_graph *graph,
|
||||
unsigned int dir, phys_addr_t phys,
|
||||
size_t period_sz, unsigned int periods);
|
||||
|
|
@ -148,8 +153,6 @@ int q6apm_send_cmd_sync(struct q6apm *apm, const struct gpr_pkt *pkt,
|
|||
/* Callback for graph specific */
|
||||
struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph,
|
||||
uint32_t mid);
|
||||
int q6apm_graph_get_rx_shmem_module_iid(struct q6apm_graph *graph);
|
||||
|
||||
bool q6apm_is_adsp_ready(void);
|
||||
|
||||
int q6apm_enable_compress_module(struct device *dev, struct q6apm_graph *graph, bool en);
|
||||
|
|
@ -157,4 +160,10 @@ int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph,
|
|||
int q6apm_remove_trailing_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples);
|
||||
int q6apm_set_real_module_id(struct device *dev, struct q6apm_graph *graph, uint32_t codec_id);
|
||||
int q6apm_get_hw_pointer(struct q6apm_graph *graph, int dir);
|
||||
bool q6apm_is_graph_in_push_pull_mode(struct q6apm_graph *graph);
|
||||
bool q6apm_is_graph_in_push_pull_mode_from_id(struct device *dev, unsigned int graph_id, int dir);
|
||||
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