mirror of
https://github.com/torvalds/linux.git
synced 2026-05-27 00:22:00 +02:00
ASoC: qcom: q6apm: Add support for early buffer mapping on DSP
Buffers are allocated on pcm_new and mapped in the dsp on every prepare call, which is inefficient and unnecessary. Add new functions q6apm_[un]map_memory_fixed_region to map it on to dsp only once after allocation. Signed-off-by: Srinivas Kandagatla <srinivas.kandagatla@oss.qualcomm.com> Link: https://patch.msgid.link/20260402081118.348071-14-srinivas.kandagatla@oss.qualcomm.com Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
parent
d8b4163038
commit
8ea6e25c85
|
|
@ -1396,66 +1396,6 @@ void audioreach_graph_free_buf(struct q6apm_graph *graph)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
|
EXPORT_SYMBOL_GPL(audioreach_graph_free_buf);
|
||||||
|
|
||||||
int audioreach_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, size_t period_sz,
|
|
||||||
unsigned int periods, bool is_contiguous)
|
|
||||||
{
|
|
||||||
struct apm_shared_map_region_payload *mregions;
|
|
||||||
struct apm_cmd_shared_mem_map_regions *cmd;
|
|
||||||
uint32_t num_regions, buf_sz, payload_size;
|
|
||||||
struct audioreach_graph_data *data;
|
|
||||||
struct gpr_pkt *pkt __free(kfree) = NULL;
|
|
||||||
void *p;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
|
||||||
data = &graph->rx_data;
|
|
||||||
else
|
|
||||||
data = &graph->tx_data;
|
|
||||||
|
|
||||||
if (is_contiguous) {
|
|
||||||
num_regions = 1;
|
|
||||||
buf_sz = period_sz * periods;
|
|
||||||
} else {
|
|
||||||
buf_sz = period_sz;
|
|
||||||
num_regions = periods;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* DSP expects size should be aligned to 4K */
|
|
||||||
buf_sz = ALIGN(buf_sz, 4096);
|
|
||||||
|
|
||||||
payload_size = sizeof(*cmd) + (sizeof(*mregions) * num_regions);
|
|
||||||
|
|
||||||
pkt = audioreach_alloc_apm_pkt(payload_size, APM_CMD_SHARED_MEM_MAP_REGIONS, dir,
|
|
||||||
graph->port->id);
|
|
||||||
if (IS_ERR(pkt))
|
|
||||||
return PTR_ERR(pkt);
|
|
||||||
|
|
||||||
p = (void *)pkt + GPR_HDR_SIZE;
|
|
||||||
cmd = p;
|
|
||||||
cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
|
|
||||||
cmd->num_regions = num_regions;
|
|
||||||
|
|
||||||
cmd->property_flag = 0x0;
|
|
||||||
|
|
||||||
mregions = p + sizeof(*cmd);
|
|
||||||
|
|
||||||
mutex_lock(&graph->lock);
|
|
||||||
|
|
||||||
for (i = 0; i < num_regions; i++) {
|
|
||||||
struct audio_buffer *ab;
|
|
||||||
|
|
||||||
ab = &data->buf[i];
|
|
||||||
mregions->shm_addr_lsw = lower_32_bits(ab->phys);
|
|
||||||
mregions->shm_addr_msw = upper_32_bits(ab->phys);
|
|
||||||
mregions->mem_size_bytes = buf_sz;
|
|
||||||
++mregions;
|
|
||||||
}
|
|
||||||
mutex_unlock(&graph->lock);
|
|
||||||
|
|
||||||
return audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
|
|
||||||
}
|
|
||||||
EXPORT_SYMBOL_GPL(audioreach_map_memory_regions);
|
|
||||||
|
|
||||||
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
|
int audioreach_shared_memory_send_eos(struct q6apm_graph *graph)
|
||||||
{
|
{
|
||||||
struct data_cmd_wr_sh_mem_ep_eos *eos;
|
struct data_cmd_wr_sh_mem_ep_eos *eos;
|
||||||
|
|
|
||||||
|
|
@ -722,6 +722,7 @@ struct audioreach_connection {
|
||||||
|
|
||||||
struct audioreach_graph_info {
|
struct audioreach_graph_info {
|
||||||
int id;
|
int id;
|
||||||
|
uint32_t mem_map_handle;
|
||||||
uint32_t num_sub_graphs;
|
uint32_t num_sub_graphs;
|
||||||
struct list_head sg_list;
|
struct list_head sg_list;
|
||||||
/* DPCM connection from FE Graph to BE graph */
|
/* DPCM connection from FE Graph to BE graph */
|
||||||
|
|
@ -838,10 +839,6 @@ int audioreach_tplg_init(struct snd_soc_component *component);
|
||||||
|
|
||||||
/* Module specific */
|
/* Module specific */
|
||||||
void audioreach_graph_free_buf(struct q6apm_graph *graph);
|
void audioreach_graph_free_buf(struct q6apm_graph *graph);
|
||||||
int audioreach_map_memory_regions(struct q6apm_graph *graph,
|
|
||||||
unsigned int dir, size_t period_sz,
|
|
||||||
unsigned int periods,
|
|
||||||
bool is_contiguous);
|
|
||||||
int audioreach_send_cmd_sync(struct device *dev, gpr_device_t *gdev, struct gpr_ibasic_rsp_result_t *result,
|
int audioreach_send_cmd_sync(struct device *dev, gpr_device_t *gdev, struct gpr_ibasic_rsp_result_t *result,
|
||||||
struct mutex *cmd_lock, gpr_port_t *port, wait_queue_head_t *cmd_wait,
|
struct mutex *cmd_lock, gpr_port_t *port, wait_queue_head_t *cmd_wait,
|
||||||
struct gpr_pkt *pkt, uint32_t rsp_opcode);
|
struct gpr_pkt *pkt, uint32_t rsp_opcode);
|
||||||
|
|
|
||||||
|
|
@ -228,11 +228,10 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
||||||
cfg.bit_width = prtd->bits_per_sample;
|
cfg.bit_width = prtd->bits_per_sample;
|
||||||
cfg.fmt = SND_AUDIOCODEC_PCM;
|
cfg.fmt = SND_AUDIOCODEC_PCM;
|
||||||
audioreach_set_default_channel_mapping(cfg.channel_map, runtime->channels);
|
audioreach_set_default_channel_mapping(cfg.channel_map, runtime->channels);
|
||||||
|
|
||||||
if (prtd->state) {
|
if (prtd->state) {
|
||||||
/* clear the previous setup if any */
|
/* clear the previous setup if any */
|
||||||
q6apm_graph_stop(prtd->graph);
|
q6apm_graph_stop(prtd->graph);
|
||||||
q6apm_unmap_memory_regions(prtd->graph, substream->stream);
|
q6apm_free_fragments(prtd->graph, substream->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
prtd->pcm_count = snd_pcm_lib_period_bytes(substream);
|
||||||
|
|
@ -247,8 +246,8 @@ static int q6apm_dai_prepare(struct snd_soc_component *component,
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
dev_err(dev, "%s: CMD Format block failed\n", __func__);
|
dev_err(dev, "%s: CMD Format block failed\n", __func__);
|
||||||
|
|
||||||
ret = q6apm_map_memory_regions(prtd->graph, substream->stream, prtd->phys,
|
ret = q6apm_alloc_fragments(prtd->graph, substream->stream, prtd->phys,
|
||||||
(prtd->pcm_size / prtd->periods), prtd->periods);
|
(prtd->pcm_size / prtd->periods), prtd->periods);
|
||||||
|
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||||
|
|
@ -416,9 +415,10 @@ static int q6apm_dai_close(struct snd_soc_component *component,
|
||||||
struct snd_pcm_runtime *runtime = substream->runtime;
|
struct snd_pcm_runtime *runtime = substream->runtime;
|
||||||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||||
|
|
||||||
if (prtd->state) { /* only stop graph that is started */
|
if (prtd->state) {
|
||||||
|
/* only stop graph that is started */
|
||||||
q6apm_graph_stop(prtd->graph);
|
q6apm_graph_stop(prtd->graph);
|
||||||
q6apm_unmap_memory_regions(prtd->graph, substream->stream);
|
q6apm_free_fragments(prtd->graph, substream->stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
q6apm_graph_close(prtd->graph);
|
q6apm_graph_close(prtd->graph);
|
||||||
|
|
@ -467,11 +467,94 @@ static int q6apm_dai_hw_params(struct snd_soc_component *component,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int q6apm_dai_memory_map(struct snd_soc_component *component,
|
||||||
|
struct snd_pcm_substream *substream, int graph_id)
|
||||||
|
{
|
||||||
|
struct q6apm_dai_data *pdata;
|
||||||
|
struct device *dev = component->dev;
|
||||||
|
phys_addr_t phys;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
pdata = snd_soc_component_get_drvdata(component);
|
||||||
|
if (!pdata) {
|
||||||
|
dev_err(component->dev, "Drv data not found ..\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pdata->sid < 0)
|
||||||
|
phys = substream->dma_buffer.addr;
|
||||||
|
else
|
||||||
|
phys = substream->dma_buffer.addr | (pdata->sid << 32);
|
||||||
|
|
||||||
|
ret = q6apm_map_memory_fixed_region(dev, graph_id, phys, BUFFER_BYTES_MAX);
|
||||||
|
if (ret < 0)
|
||||||
|
dev_err(dev, "Audio Start: Buffer Allocation failed rc = %d\n", ret);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
|
static int q6apm_dai_pcm_new(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd)
|
||||||
{
|
{
|
||||||
|
struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0);
|
||||||
|
struct snd_pcm *pcm = rtd->pcm;
|
||||||
int size = BUFFER_BYTES_MAX;
|
int size = BUFFER_BYTES_MAX;
|
||||||
|
int graph_id, ret;
|
||||||
|
struct snd_pcm_substream *substream;
|
||||||
|
|
||||||
return snd_pcm_set_fixed_buffer_all(rtd->pcm, SNDRV_DMA_TYPE_DEV, component->dev, size);
|
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) {
|
||||||
|
substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
||||||
|
ret = q6apm_dai_memory_map(component, substream, graph_id);
|
||||||
|
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);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void q6apm_dai_memory_unmap(struct snd_soc_component *component,
|
||||||
|
struct snd_pcm_substream *substream)
|
||||||
|
{
|
||||||
|
struct snd_soc_pcm_runtime *soc_prtd;
|
||||||
|
struct snd_soc_dai *cpu_dai;
|
||||||
|
int graph_id;
|
||||||
|
|
||||||
|
soc_prtd = snd_soc_substream_to_rtd(substream);
|
||||||
|
if (!soc_prtd)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cpu_dai = snd_soc_rtd_to_cpu(soc_prtd, 0);
|
||||||
|
if (!cpu_dai)
|
||||||
|
return;
|
||||||
|
|
||||||
|
graph_id = cpu_dai->driver->id;
|
||||||
|
q6apm_unmap_memory_fixed_region(component->dev, graph_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void q6apm_dai_pcm_free(struct snd_soc_component *component, struct snd_pcm *pcm)
|
||||||
|
{
|
||||||
|
struct snd_pcm_substream *substream;
|
||||||
|
|
||||||
|
substream = pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream;
|
||||||
|
if (substream)
|
||||||
|
q6apm_dai_memory_unmap(component, substream);
|
||||||
|
|
||||||
|
substream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream;
|
||||||
|
if (substream)
|
||||||
|
q6apm_dai_memory_unmap(component, substream);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int q6apm_dai_compr_open(struct snd_soc_component *component,
|
static int q6apm_dai_compr_open(struct snd_soc_component *component,
|
||||||
|
|
@ -530,7 +613,8 @@ static int q6apm_dai_compr_free(struct snd_soc_component *component,
|
||||||
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
struct q6apm_dai_rtd *prtd = runtime->private_data;
|
||||||
|
|
||||||
q6apm_graph_stop(prtd->graph);
|
q6apm_graph_stop(prtd->graph);
|
||||||
q6apm_unmap_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK);
|
q6apm_free_fragments(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK);
|
||||||
|
q6apm_unmap_memory_fixed_region(component->dev, prtd->graph->id);
|
||||||
q6apm_graph_close(prtd->graph);
|
q6apm_graph_close(prtd->graph);
|
||||||
snd_dma_free_pages(&prtd->dma_buffer);
|
snd_dma_free_pages(&prtd->dma_buffer);
|
||||||
prtd->graph = NULL;
|
prtd->graph = NULL;
|
||||||
|
|
@ -679,9 +763,9 @@ static int q6apm_dai_compr_set_params(struct snd_soc_component *component,
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = q6apm_map_memory_regions(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
|
ret = q6apm_alloc_fragments(prtd->graph, SNDRV_PCM_STREAM_PLAYBACK,
|
||||||
prtd->phys, (prtd->pcm_size / prtd->periods),
|
prtd->phys, (prtd->pcm_size / prtd->periods),
|
||||||
prtd->periods);
|
prtd->periods);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
|
|
@ -834,6 +918,7 @@ static const struct snd_soc_component_driver q6apm_fe_dai_component = {
|
||||||
.close = q6apm_dai_close,
|
.close = q6apm_dai_close,
|
||||||
.prepare = q6apm_dai_prepare,
|
.prepare = q6apm_dai_prepare,
|
||||||
.pcm_new = q6apm_dai_pcm_new,
|
.pcm_new = q6apm_dai_pcm_new,
|
||||||
|
.pcm_free = q6apm_dai_pcm_free,
|
||||||
.hw_params = q6apm_dai_hw_params,
|
.hw_params = q6apm_dai_hw_params,
|
||||||
.pointer = q6apm_dai_pointer,
|
.pointer = q6apm_dai_pointer,
|
||||||
.trigger = q6apm_dai_trigger,
|
.trigger = q6apm_dai_trigger,
|
||||||
|
|
|
||||||
|
|
@ -200,13 +200,53 @@ int q6apm_graph_media_format_shmem(struct q6apm_graph *graph,
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem);
|
EXPORT_SYMBOL_GPL(q6apm_graph_media_format_shmem);
|
||||||
|
|
||||||
int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
|
int q6apm_map_memory_fixed_region(struct device *dev, unsigned int graph_id, phys_addr_t phys,
|
||||||
size_t period_sz, unsigned int periods)
|
size_t sz)
|
||||||
|
{
|
||||||
|
struct audioreach_graph_info *info;
|
||||||
|
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||||
|
struct apm_shared_map_region_payload *mregions;
|
||||||
|
struct apm_cmd_shared_mem_map_regions *cmd;
|
||||||
|
int payload_size = sizeof(*cmd) + (sizeof(*mregions));
|
||||||
|
uint32_t buf_sz;
|
||||||
|
void *p;
|
||||||
|
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(payload_size,
|
||||||
|
APM_CMD_SHARED_MEM_MAP_REGIONS, graph_id);
|
||||||
|
if (IS_ERR(pkt))
|
||||||
|
return PTR_ERR(pkt);
|
||||||
|
|
||||||
|
info = idr_find(&apm->graph_info_idr, graph_id);
|
||||||
|
if (!info)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (info->mem_map_handle)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* DSP expects size should be aligned to 4K */
|
||||||
|
buf_sz = ALIGN(sz, 4096);
|
||||||
|
|
||||||
|
p = (void *)pkt + GPR_HDR_SIZE;
|
||||||
|
cmd = p;
|
||||||
|
cmd->mem_pool_id = APM_MEMORY_MAP_SHMEM8_4K_POOL;
|
||||||
|
cmd->num_regions = 1;
|
||||||
|
cmd->property_flag = 0x0;
|
||||||
|
|
||||||
|
mregions = p + sizeof(*cmd);
|
||||||
|
|
||||||
|
mregions->shm_addr_lsw = lower_32_bits(phys);
|
||||||
|
mregions->shm_addr_msw = upper_32_bits(phys);
|
||||||
|
mregions->mem_size_bytes = buf_sz;
|
||||||
|
|
||||||
|
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_RSP_SHARED_MEM_MAP_REGIONS);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(q6apm_map_memory_fixed_region);
|
||||||
|
|
||||||
|
int q6apm_alloc_fragments(struct q6apm_graph *graph, unsigned int dir, phys_addr_t phys,
|
||||||
|
size_t period_sz, unsigned int periods)
|
||||||
{
|
{
|
||||||
struct audioreach_graph_data *data;
|
struct audioreach_graph_data *data;
|
||||||
struct audio_buffer *buf;
|
struct audio_buffer *buf;
|
||||||
int cnt;
|
int cnt;
|
||||||
int rc;
|
|
||||||
|
|
||||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
||||||
data = &graph->rx_data;
|
data = &graph->rx_data;
|
||||||
|
|
@ -248,46 +288,41 @@ int q6apm_map_memory_regions(struct q6apm_graph *graph, unsigned int dir, phys_a
|
||||||
|
|
||||||
mutex_unlock(&graph->lock);
|
mutex_unlock(&graph->lock);
|
||||||
|
|
||||||
rc = audioreach_map_memory_regions(graph, dir, period_sz, periods, 1);
|
return 0;
|
||||||
if (rc < 0) {
|
|
||||||
dev_err(graph->dev, "Memory_map_regions failed\n");
|
|
||||||
audioreach_graph_free_buf(graph);
|
|
||||||
}
|
|
||||||
|
|
||||||
return rc;
|
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(q6apm_map_memory_regions);
|
EXPORT_SYMBOL_GPL(q6apm_alloc_fragments);
|
||||||
|
|
||||||
int q6apm_unmap_memory_regions(struct q6apm_graph *graph, unsigned int dir)
|
int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id)
|
||||||
{
|
{
|
||||||
struct apm_cmd_shared_mem_unmap_regions *cmd;
|
struct apm_cmd_shared_mem_unmap_regions *cmd;
|
||||||
struct audioreach_graph_data *data;
|
struct q6apm *apm = dev_get_drvdata(dev->parent);
|
||||||
int rc;
|
struct audioreach_graph_info *info;
|
||||||
|
struct gpr_pkt *pkt __free(kfree) = audioreach_alloc_apm_cmd_pkt(sizeof(*cmd),
|
||||||
if (dir == SNDRV_PCM_STREAM_PLAYBACK)
|
APM_CMD_SHARED_MEM_UNMAP_REGIONS, graph_id);
|
||||||
data = &graph->rx_data;
|
|
||||||
else
|
|
||||||
data = &graph->tx_data;
|
|
||||||
|
|
||||||
if (!data->mem_map_handle)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
struct gpr_pkt *pkt __free(kfree) =
|
|
||||||
audioreach_alloc_apm_pkt(sizeof(*cmd), APM_CMD_SHARED_MEM_UNMAP_REGIONS,
|
|
||||||
dir, graph->port->id);
|
|
||||||
if (IS_ERR(pkt))
|
if (IS_ERR(pkt))
|
||||||
return PTR_ERR(pkt);
|
return PTR_ERR(pkt);
|
||||||
|
|
||||||
|
info = idr_find(&apm->graph_info_idr, graph_id);
|
||||||
|
if (!info)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
if (!info->mem_map_handle)
|
||||||
|
return 0;
|
||||||
|
|
||||||
cmd = (void *)pkt + GPR_HDR_SIZE;
|
cmd = (void *)pkt + GPR_HDR_SIZE;
|
||||||
cmd->mem_map_handle = data->mem_map_handle;
|
cmd->mem_map_handle = info->mem_map_handle;
|
||||||
|
|
||||||
rc = audioreach_graph_send_cmd_sync(graph, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
|
return q6apm_send_cmd_sync(apm, pkt, APM_CMD_SHARED_MEM_UNMAP_REGIONS);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(q6apm_unmap_memory_fixed_region);
|
||||||
|
|
||||||
|
int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir)
|
||||||
|
{
|
||||||
audioreach_graph_free_buf(graph);
|
audioreach_graph_free_buf(graph);
|
||||||
|
|
||||||
return rc;
|
return 0;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(q6apm_unmap_memory_regions);
|
EXPORT_SYMBOL_GPL(q6apm_free_fragments);
|
||||||
|
|
||||||
int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples)
|
int q6apm_remove_initial_silence(struct device *dev, struct q6apm_graph *graph, uint32_t samples)
|
||||||
{
|
{
|
||||||
|
|
@ -429,7 +464,7 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
|
||||||
write_buffer->buf_size = len;
|
write_buffer->buf_size = len;
|
||||||
write_buffer->timestamp_lsw = lsw_ts;
|
write_buffer->timestamp_lsw = lsw_ts;
|
||||||
write_buffer->timestamp_msw = msw_ts;
|
write_buffer->timestamp_msw = msw_ts;
|
||||||
write_buffer->mem_map_handle = graph->rx_data.mem_map_handle;
|
write_buffer->mem_map_handle = graph->info->mem_map_handle;
|
||||||
write_buffer->flags = wflags;
|
write_buffer->flags = wflags;
|
||||||
|
|
||||||
graph->rx_data.dsp_buf++;
|
graph->rx_data.dsp_buf++;
|
||||||
|
|
@ -463,7 +498,7 @@ int q6apm_read(struct q6apm_graph *graph)
|
||||||
|
|
||||||
read_buffer->buf_addr_lsw = lower_32_bits(ab->phys);
|
read_buffer->buf_addr_lsw = lower_32_bits(ab->phys);
|
||||||
read_buffer->buf_addr_msw = upper_32_bits(ab->phys);
|
read_buffer->buf_addr_msw = upper_32_bits(ab->phys);
|
||||||
read_buffer->mem_map_handle = port->mem_map_handle;
|
read_buffer->mem_map_handle = graph->info->mem_map_handle;
|
||||||
read_buffer->buf_size = ab->size;
|
read_buffer->buf_size = ab->size;
|
||||||
|
|
||||||
port->dsp_buf++;
|
port->dsp_buf++;
|
||||||
|
|
@ -494,7 +529,6 @@ 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_rd_sh_mem_ep_data_buffer_done_v2 *rd_done;
|
||||||
struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done;
|
struct data_cmd_rsp_wr_sh_mem_ep_data_buffer_done_v2 *done;
|
||||||
struct apm_cmd_rsp_shared_mem_map_regions *rsp;
|
|
||||||
const struct gpr_ibasic_rsp_result_t *result;
|
const struct gpr_ibasic_rsp_result_t *result;
|
||||||
struct q6apm_graph *graph = priv;
|
struct q6apm_graph *graph = priv;
|
||||||
const struct gpr_hdr *hdr = &data->hdr;
|
const struct gpr_hdr *hdr = &data->hdr;
|
||||||
|
|
@ -529,18 +563,6 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
||||||
done->buf_addr_msw);
|
done->buf_addr_msw);
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
|
||||||
case APM_CMD_RSP_SHARED_MEM_MAP_REGIONS:
|
|
||||||
graph->result.opcode = hdr->opcode;
|
|
||||||
graph->result.status = 0;
|
|
||||||
rsp = data->payload;
|
|
||||||
|
|
||||||
if (hdr->token == SNDRV_PCM_STREAM_PLAYBACK)
|
|
||||||
graph->rx_data.mem_map_handle = rsp->mem_map_handle;
|
|
||||||
else
|
|
||||||
graph->tx_data.mem_map_handle = rsp->mem_map_handle;
|
|
||||||
|
|
||||||
wake_up(&graph->cmd_wait);
|
|
||||||
break;
|
break;
|
||||||
case DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2:
|
case DATA_CMD_RSP_RD_SH_MEM_EP_DATA_BUFFER_V2:
|
||||||
if (!graph->ar_graph)
|
if (!graph->ar_graph)
|
||||||
|
|
@ -571,16 +593,6 @@ static int graph_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
||||||
break;
|
break;
|
||||||
case GPR_BASIC_RSP_RESULT:
|
case GPR_BASIC_RSP_RESULT:
|
||||||
switch (result->opcode) {
|
switch (result->opcode) {
|
||||||
case APM_CMD_SHARED_MEM_UNMAP_REGIONS:
|
|
||||||
graph->result.opcode = result->opcode;
|
|
||||||
graph->result.status = 0;
|
|
||||||
if (hdr->token == SNDRV_PCM_STREAM_PLAYBACK)
|
|
||||||
graph->rx_data.mem_map_handle = 0;
|
|
||||||
else
|
|
||||||
graph->tx_data.mem_map_handle = 0;
|
|
||||||
|
|
||||||
wake_up(&graph->cmd_wait);
|
|
||||||
break;
|
|
||||||
case APM_CMD_SHARED_MEM_MAP_REGIONS:
|
case APM_CMD_SHARED_MEM_MAP_REGIONS:
|
||||||
case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT:
|
case DATA_CMD_WR_SH_MEM_EP_MEDIA_FORMAT:
|
||||||
case APM_CMD_SET_CFG:
|
case APM_CMD_SET_CFG:
|
||||||
|
|
@ -784,7 +796,9 @@ struct audioreach_module *q6apm_find_module_by_mid(struct q6apm_graph *graph, ui
|
||||||
static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
||||||
{
|
{
|
||||||
gpr_device_t *gdev = priv;
|
gpr_device_t *gdev = priv;
|
||||||
|
struct audioreach_graph_info *info;
|
||||||
struct q6apm *apm = dev_get_drvdata(&gdev->dev);
|
struct q6apm *apm = dev_get_drvdata(&gdev->dev);
|
||||||
|
struct apm_cmd_rsp_shared_mem_map_regions *rsp;
|
||||||
struct device *dev = &gdev->dev;
|
struct device *dev = &gdev->dev;
|
||||||
struct gpr_ibasic_rsp_result_t *result;
|
struct gpr_ibasic_rsp_result_t *result;
|
||||||
const struct gpr_hdr *hdr = &data->hdr;
|
const struct gpr_hdr *hdr = &data->hdr;
|
||||||
|
|
@ -801,6 +815,7 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
||||||
break;
|
break;
|
||||||
case GPR_BASIC_RSP_RESULT:
|
case GPR_BASIC_RSP_RESULT:
|
||||||
switch (result->opcode) {
|
switch (result->opcode) {
|
||||||
|
case APM_CMD_SHARED_MEM_MAP_REGIONS:
|
||||||
case APM_CMD_GRAPH_START:
|
case APM_CMD_GRAPH_START:
|
||||||
case APM_CMD_GRAPH_OPEN:
|
case APM_CMD_GRAPH_OPEN:
|
||||||
case APM_CMD_GRAPH_PREPARE:
|
case APM_CMD_GRAPH_PREPARE:
|
||||||
|
|
@ -815,10 +830,38 @@ static int apm_callback(const struct gpr_resp_pkt *data, void *priv, int op)
|
||||||
result->opcode);
|
result->opcode);
|
||||||
wake_up(&apm->wait);
|
wake_up(&apm->wait);
|
||||||
break;
|
break;
|
||||||
|
case APM_CMD_SHARED_MEM_UNMAP_REGIONS:
|
||||||
|
apm->result.opcode = hdr->opcode;
|
||||||
|
apm->result.status = 0;
|
||||||
|
rsp = data->payload;
|
||||||
|
|
||||||
|
info = idr_find(&apm->graph_info_idr, hdr->token);
|
||||||
|
if (info)
|
||||||
|
info->mem_map_handle = 0;
|
||||||
|
else
|
||||||
|
dev_err(dev, "Error (%d) Processing 0x%08x cmd\n", result->status,
|
||||||
|
result->opcode);
|
||||||
|
|
||||||
|
wake_up(&apm->wait);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case APM_CMD_RSP_SHARED_MEM_MAP_REGIONS:
|
||||||
|
apm->result.opcode = hdr->opcode;
|
||||||
|
apm->result.status = 0;
|
||||||
|
rsp = data->payload;
|
||||||
|
|
||||||
|
info = idr_find(&apm->graph_info_idr, hdr->token);
|
||||||
|
if (info)
|
||||||
|
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;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -78,7 +78,6 @@ struct audioreach_graph_data {
|
||||||
struct audio_buffer *buf;
|
struct audio_buffer *buf;
|
||||||
uint32_t num_periods;
|
uint32_t num_periods;
|
||||||
uint32_t dsp_buf;
|
uint32_t dsp_buf;
|
||||||
uint32_t mem_map_handle;
|
|
||||||
atomic_t hw_ptr;
|
atomic_t hw_ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -134,11 +133,14 @@ int q6apm_write_async(struct q6apm_graph *graph, uint32_t len, uint32_t msw_ts,
|
||||||
uint32_t lsw_ts, uint32_t wflags);
|
uint32_t lsw_ts, uint32_t wflags);
|
||||||
|
|
||||||
/* Memory Map related */
|
/* Memory Map related */
|
||||||
int q6apm_map_memory_regions(struct q6apm_graph *graph,
|
int q6apm_map_memory_fixed_region(struct device *dev,
|
||||||
unsigned int dir, phys_addr_t phys,
|
unsigned int graph_id, phys_addr_t phys,
|
||||||
size_t period_sz, unsigned int periods);
|
size_t sz);
|
||||||
int q6apm_unmap_memory_regions(struct q6apm_graph *graph,
|
int q6apm_alloc_fragments(struct q6apm_graph *graph,
|
||||||
unsigned int dir);
|
unsigned int dir, phys_addr_t phys,
|
||||||
|
size_t period_sz, unsigned int periods);
|
||||||
|
int q6apm_free_fragments(struct q6apm_graph *graph, unsigned int dir);
|
||||||
|
int q6apm_unmap_memory_fixed_region(struct device *dev, unsigned int graph_id);
|
||||||
/* Helpers */
|
/* Helpers */
|
||||||
int q6apm_send_cmd_sync(struct q6apm *apm, struct gpr_pkt *pkt,
|
int q6apm_send_cmd_sync(struct q6apm *apm, struct gpr_pkt *pkt,
|
||||||
uint32_t rsp_opcode);
|
uint32_t rsp_opcode);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user