Loading drivers/soc/qcom/qdsp6v2/msm_audio_ion.c +83 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -29,6 +29,7 @@ #include <linux/export.h> #include <linux/qcom_iommu.h> #include <asm/dma-iommu.h> #include <soc/qcom/secure_buffer.h> #define MSM_AUDIO_ION_PROBED (1 << 0) Loading Loading @@ -178,6 +179,87 @@ err: } EXPORT_SYMBOL(msm_audio_ion_alloc); static int msm_audio_hyp_assign(ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type) { int srcVM[1] = {VMID_HLOS}; int destVM[1] = {VMID_CP_ADSP_SHARED}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; int ret = 0; switch (assign_type) { case HLOS_TO_ADSP: srcVM[0] = VMID_HLOS; destVM[0] = VMID_CP_ADSP_SHARED; break; case ADSP_TO_HLOS: srcVM[0] = VMID_CP_ADSP_SHARED; destVM[0] = VMID_HLOS; break; default: pr_err("%s: Invalid assign type = %d\n", __func__, assign_type); ret = -EINVAL; goto done; } ret = hyp_assign_phys(*paddr, *pa_len, srcVM, 1, destVM, destVMperm, 1); if (ret) pr_err("%s: hyp_assign_phys failed for type %d, rc = %d\n", __func__, assign_type, ret); done: return ret; } int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type) { struct ion_client *client; struct ion_handle *handle; int ret; if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) { pr_debug("%s:probe is not done, deferred\n", __func__); return -EPROBE_DEFER; } if (!name || !paddr || !pa_len) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } client = msm_audio_ion_client_create(name); if (IS_ERR_OR_NULL((void *)(client))) { pr_err("%s: ION create client failed\n", __func__); return -EINVAL; } handle = ion_import_dma_buf(client, fd); if (IS_ERR_OR_NULL((void *) (handle))) { pr_err("%s: ion import dma buffer failed\n", __func__); ret = -EINVAL; goto err_destroy_client; } ret = ion_phys(client, handle, paddr, pa_len); if (ret) { pr_err("%s: could not get physical address for handle, ret = %d\n", __func__, ret); goto err_ion_handle; } pr_debug("%s: ION Physical address is %x\n", __func__, (u32)*paddr); ret = msm_audio_hyp_assign(paddr, pa_len, assign_type); err_ion_handle: ion_free(client, handle); err_destroy_client: ion_client_destroy(client); return ret; } int msm_audio_ion_import(const char *name, struct ion_client **client, struct ion_handle **handle, int fd, unsigned long *ionflag, size_t bufsz, Loading include/linux/msm_audio_ion.h +11 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,12 @@ #include <sound/pcm.h> #include <linux/msm_ion.h> enum { HLOS_TO_ADSP = 1, ADSP_TO_HLOS, }; #define VMID_CP_ADSP_SHARED 33 int msm_audio_ion_alloc(const char *name, struct ion_client **client, struct ion_handle **handle, size_t bufsz, Loading @@ -26,6 +32,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, struct ion_handle **handle, int fd, unsigned long *ionflag, size_t bufsz, ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr); int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle); int msm_audio_ion_mmap(struct audio_buffer *substream, struct vm_area_struct *vma); Loading @@ -42,4 +49,7 @@ int msm_audio_ion_import_legacy(const char *name, struct ion_client *client, int msm_audio_ion_free_legacy(struct ion_client *client, struct ion_handle *handle); u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa); int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type); #endif /* _LINUX_MSM_AUDIO_ION_H */ include/sound/q6asm-v2.h +1 −1 Original line number Diff line number Diff line Loading @@ -639,7 +639,7 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params, int q6asm_send_stream_cmd(struct audio_client *ac, struct msm_adsp_event_data *data); int q6asm_send_ion_fd(struct audio_client *ac, int fd); int q6asm_audio_map_shm_fd(struct audio_client *ac, int fd); int q6asm_send_rtic_event_ack(struct audio_client *ac, void *param, uint32_t params_length); Loading include/sound/q6core.h +15 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -20,6 +20,8 @@ #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D bool q6core_is_adsp_ready(void); int q6core_add_remove_pool_pages(phys_addr_t buf_add, uint32_t bufsz, uint32_t mempool_id, bool add_pages); #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919 #define DTS_EAGLE_LICENSE_ID 0x00028346 Loading Loading @@ -153,4 +155,16 @@ struct avcs_cmd_deregister_topologies { int32_t core_set_license(uint32_t key, uint32_t module_id); int32_t core_get_license_status(uint32_t module_id); #define ADSP_MEMORY_MAP_HLOS_PHYSPOOL 4 #define AVCS_CMD_ADD_POOL_PAGES 0x0001292E #define AVCS_CMD_REMOVE_POOL_PAGES 0x0001292F struct avs_mem_assign_region { struct apr_hdr hdr; u32 pool_id; u32 size; u32 addr_lsw; u32 addr_msw; } __packed; #endif /* __Q6CORE_H__ */ sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +155 −22 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include <sound/apr_audio-v2.h> #include <sound/q6asm-v2.h> #include <sound/q6core.h> #include <sound/compress_params.h> #include <sound/compress_offload.h> #include <sound/compress_driver.h> Loading Loading @@ -103,6 +104,7 @@ struct msm_compr_pdata { bool use_legacy_api; /* indicates use older asm apis*/ struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX]; struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX]; int32_t ion_fd[MSM_FRONTEND_DAI_MAX]; }; struct msm_compr_audio { Loading Loading @@ -156,6 +158,8 @@ struct msm_compr_audio { uint32_t start_delay_lsw; uint32_t start_delay_msw; int32_t shm_ion_fd; uint64_t marker_timestamp; struct msm_compr_gapless_state gapless_state; Loading Loading @@ -1506,6 +1510,40 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) return ret; } static int msm_compr_map_unmap_fd(int fd, bool add_pages) { ion_phys_addr_t paddr; size_t pa_len = 0; int ret = 0; u8 assign_type; if (add_pages) assign_type = HLOS_TO_ADSP; else assign_type = ADSP_TO_HLOS; ret = msm_audio_ion_phys_assign("audio_lib_mem_client", fd, &paddr, &pa_len, assign_type); if (ret) { pr_err("%s: audio lib ION phys failed, rc = %d\n", __func__, ret); goto done; } ret = q6core_add_remove_pool_pages(paddr, pa_len, ADSP_MEMORY_MAP_HLOS_PHYSPOOL, add_pages); if (ret) { pr_err("%s: add remove pages failed, rc = %d\n", __func__, ret); /* Assign back to HLOS if add pages cmd failed */ if (add_pages) msm_audio_ion_phys_assign("audio_lib_mem_client", fd, &paddr, &pa_len, ADSP_TO_HLOS); } done: return ret; } static int msm_compr_playback_open(struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; Loading @@ -1513,6 +1551,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) struct msm_compr_audio *prtd; struct msm_compr_pdata *pdata = snd_soc_platform_get_drvdata(rtd->platform); int ret = 0; pr_debug("%s\n", __func__); prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL); Loading @@ -1528,19 +1567,16 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL); if (!pdata->audio_effects[rtd->dai_link->be_id]) { pr_err("%s: Could not allocate memory for effects\n", __func__); pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto effect_err; } pdata->dec_params[rtd->dai_link->be_id] = kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL); if (!pdata->dec_params[rtd->dai_link->be_id]) { pr_err("%s: Could not allocate memory for dec params\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto param_err; } prtd->codec = FORMAT_MP3; prtd->bytes_received = 0; Loading Loading @@ -1584,19 +1620,32 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) (app_cb)compr_event_handler, prtd); if (!prtd->audio_client) { pr_err("%s: Could not allocate memory for client\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); kfree(pdata->dec_params[rtd->dai_link->be_id]); pdata->cstream[rtd->dai_link->be_id] = NULL; runtime->private_data = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto ac_err; } pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session); prtd->audio_client->perf_mode = false; prtd->session_id = prtd->audio_client->session; msm_adsp_init_mixer_ctl_pp_event_queue(rtd); if (pdata->ion_fd[rtd->dai_link->be_id] > 0) { ret = msm_compr_map_unmap_fd( pdata->ion_fd[rtd->dai_link->be_id], true); if (ret < 0) goto map_err; } return 0; map_err: q6asm_audio_client_free(prtd->audio_client); ac_err: kfree(pdata->dec_params[rtd->dai_link->be_id]); param_err: kfree(pdata->audio_effects[rtd->dai_link->be_id]); effect_err: pdata->cstream[rtd->dai_link->be_id] = NULL; runtime->private_data = NULL; kfree(prtd); return ret; } static int msm_compr_capture_open(struct snd_compr_stream *cstream) Loading Loading @@ -1675,6 +1724,8 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) int dir = IN, ret = 0, stream_id; unsigned long flags; uint32_t stream_index; ion_phys_addr_t paddr; size_t pa_len = 0; pr_debug("%s\n", __func__); Loading Loading @@ -1748,6 +1799,15 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) } q6asm_audio_client_buf_free_contiguous(dir, ac); if (prtd->shm_ion_fd > 0) msm_audio_ion_phys_assign("audio_shm_mem_client", prtd->shm_ion_fd, &paddr, &pa_len, ADSP_TO_HLOS); if (pdata->ion_fd[soc_prtd->dai_link->be_id] > 0) { msm_compr_map_unmap_fd(pdata->ion_fd[soc_prtd->dai_link->be_id], false); pdata->ion_fd[soc_prtd->dai_link->be_id] = 0; } q6asm_audio_client_free(ac); msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd); Loading Loading @@ -3655,7 +3715,7 @@ done: return ret; } static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, static int msm_compr_shm_ion_fd_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); Loading @@ -3664,7 +3724,6 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, snd_soc_component_get_drvdata(comp); struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd; int fd; int ret = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { Loading Loading @@ -3694,10 +3753,34 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, goto done; } memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd)); ret = q6asm_send_ion_fd(prtd->audio_client, fd); memcpy(&prtd->shm_ion_fd, ucontrol->value.bytes.data, sizeof(prtd->shm_ion_fd)); ret = q6asm_audio_map_shm_fd(prtd->audio_client, prtd->shm_ion_fd); if (ret < 0) pr_err("%s: failed to register ion fd\n", __func__); pr_err("%s: failed to map shm mem\n", __func__); done: return ret; } static int msm_compr_lib_ion_fd_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); unsigned long fe_id = kcontrol->private_value; struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) snd_soc_component_get_drvdata(comp); int ret = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds invalid fe_id %lu\n", __func__, fe_id); ret = -EINVAL; goto done; } memcpy(&pdata->ion_fd[fe_id], ucontrol->value.bytes.data, sizeof(pdata->ion_fd[fe_id])); done: return ret; } Loading Loading @@ -4329,7 +4412,7 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd) return 0; } static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) static int msm_compr_add_shm_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = "Playback ION FD"; const char *deviceNo = "NN"; Loading @@ -4341,7 +4424,52 @@ static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_ion_fd_map_put, .put = msm_compr_shm_ion_fd_map_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_ion_fd_config_control[0].name = mixer_str; fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_ion_fd_config_control, ARRAY_SIZE(fe_ion_fd_config_control)); if (ret < 0) pr_err("%s: failed to add ctl %s\n", __func__, mixer_str); kfree(mixer_str); done: return ret; } static int msm_compr_add_lib_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = "Playback ION LIB FD"; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_ion_fd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_lib_ion_fd_map_put, .private_value = 0, } }; Loading Loading @@ -4442,11 +4570,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add Compr ADSP Stream Callback Control\n", __func__); rc = msm_compr_add_io_fd_cmd_control(rtd); rc = msm_compr_add_shm_ion_fd_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ion fd Control\n", __func__); rc = msm_compr_add_lib_ion_fd_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ion lib fd Control\n", __func__); rc = msm_compr_add_event_ack_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr event ack Control\n", Loading Loading
drivers/soc/qcom/qdsp6v2/msm_audio_ion.c +83 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2016, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2017, The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading Loading @@ -29,6 +29,7 @@ #include <linux/export.h> #include <linux/qcom_iommu.h> #include <asm/dma-iommu.h> #include <soc/qcom/secure_buffer.h> #define MSM_AUDIO_ION_PROBED (1 << 0) Loading Loading @@ -178,6 +179,87 @@ err: } EXPORT_SYMBOL(msm_audio_ion_alloc); static int msm_audio_hyp_assign(ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type) { int srcVM[1] = {VMID_HLOS}; int destVM[1] = {VMID_CP_ADSP_SHARED}; int destVMperm[1] = {PERM_READ | PERM_WRITE | PERM_EXEC}; int ret = 0; switch (assign_type) { case HLOS_TO_ADSP: srcVM[0] = VMID_HLOS; destVM[0] = VMID_CP_ADSP_SHARED; break; case ADSP_TO_HLOS: srcVM[0] = VMID_CP_ADSP_SHARED; destVM[0] = VMID_HLOS; break; default: pr_err("%s: Invalid assign type = %d\n", __func__, assign_type); ret = -EINVAL; goto done; } ret = hyp_assign_phys(*paddr, *pa_len, srcVM, 1, destVM, destVMperm, 1); if (ret) pr_err("%s: hyp_assign_phys failed for type %d, rc = %d\n", __func__, assign_type, ret); done: return ret; } int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type) { struct ion_client *client; struct ion_handle *handle; int ret; if (!(msm_audio_ion_data.device_status & MSM_AUDIO_ION_PROBED)) { pr_debug("%s:probe is not done, deferred\n", __func__); return -EPROBE_DEFER; } if (!name || !paddr || !pa_len) { pr_err("%s: Invalid params\n", __func__); return -EINVAL; } client = msm_audio_ion_client_create(name); if (IS_ERR_OR_NULL((void *)(client))) { pr_err("%s: ION create client failed\n", __func__); return -EINVAL; } handle = ion_import_dma_buf(client, fd); if (IS_ERR_OR_NULL((void *) (handle))) { pr_err("%s: ion import dma buffer failed\n", __func__); ret = -EINVAL; goto err_destroy_client; } ret = ion_phys(client, handle, paddr, pa_len); if (ret) { pr_err("%s: could not get physical address for handle, ret = %d\n", __func__, ret); goto err_ion_handle; } pr_debug("%s: ION Physical address is %x\n", __func__, (u32)*paddr); ret = msm_audio_hyp_assign(paddr, pa_len, assign_type); err_ion_handle: ion_free(client, handle); err_destroy_client: ion_client_destroy(client); return ret; } int msm_audio_ion_import(const char *name, struct ion_client **client, struct ion_handle **handle, int fd, unsigned long *ionflag, size_t bufsz, Loading
include/linux/msm_audio_ion.h +11 −1 Original line number Diff line number Diff line /* * Copyright (c) 2013-2015, The Linux Foundation. All rights reserved. * Copyright (c) 2013-2015, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -17,6 +17,12 @@ #include <sound/pcm.h> #include <linux/msm_ion.h> enum { HLOS_TO_ADSP = 1, ADSP_TO_HLOS, }; #define VMID_CP_ADSP_SHARED 33 int msm_audio_ion_alloc(const char *name, struct ion_client **client, struct ion_handle **handle, size_t bufsz, Loading @@ -26,6 +32,7 @@ int msm_audio_ion_import(const char *name, struct ion_client **client, struct ion_handle **handle, int fd, unsigned long *ionflag, size_t bufsz, ion_phys_addr_t *paddr, size_t *pa_len, void **vaddr); int msm_audio_ion_free(struct ion_client *client, struct ion_handle *handle); int msm_audio_ion_mmap(struct audio_buffer *substream, struct vm_area_struct *vma); Loading @@ -42,4 +49,7 @@ int msm_audio_ion_import_legacy(const char *name, struct ion_client *client, int msm_audio_ion_free_legacy(struct ion_client *client, struct ion_handle *handle); u32 msm_audio_populate_upper_32_bits(ion_phys_addr_t pa); int msm_audio_ion_phys_assign(const char *name, int fd, ion_phys_addr_t *paddr, size_t *pa_len, u8 assign_type); #endif /* _LINUX_MSM_AUDIO_ION_H */
include/sound/q6asm-v2.h +1 −1 Original line number Diff line number Diff line Loading @@ -639,7 +639,7 @@ int q6asm_send_audio_effects_params(struct audio_client *ac, char *params, int q6asm_send_stream_cmd(struct audio_client *ac, struct msm_adsp_event_data *data); int q6asm_send_ion_fd(struct audio_client *ac, int fd); int q6asm_audio_map_shm_fd(struct audio_client *ac, int fd); int q6asm_send_rtic_event_ack(struct audio_client *ac, void *param, uint32_t params_length); Loading
include/sound/q6core.h +15 −1 Original line number Diff line number Diff line /* Copyright (c) 2012-2016, The Linux Foundation. All rights reserved. /* Copyright (c) 2012-2016, 2017 The Linux Foundation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and Loading @@ -20,6 +20,8 @@ #define AVCS_CMDRSP_ADSP_EVENT_GET_STATE 0x0001290D bool q6core_is_adsp_ready(void); int q6core_add_remove_pool_pages(phys_addr_t buf_add, uint32_t bufsz, uint32_t mempool_id, bool add_pages); #define ADSP_CMD_SET_DTS_EAGLE_DATA_ID 0x00012919 #define DTS_EAGLE_LICENSE_ID 0x00028346 Loading Loading @@ -153,4 +155,16 @@ struct avcs_cmd_deregister_topologies { int32_t core_set_license(uint32_t key, uint32_t module_id); int32_t core_get_license_status(uint32_t module_id); #define ADSP_MEMORY_MAP_HLOS_PHYSPOOL 4 #define AVCS_CMD_ADD_POOL_PAGES 0x0001292E #define AVCS_CMD_REMOVE_POOL_PAGES 0x0001292F struct avs_mem_assign_region { struct apr_hdr hdr; u32 pool_id; u32 size; u32 addr_lsw; u32 addr_msw; } __packed; #endif /* __Q6CORE_H__ */
sound/soc/msm/qdsp6v2/msm-compress-q6-v2.c +155 −22 Original line number Diff line number Diff line Loading @@ -39,6 +39,7 @@ #include <sound/apr_audio-v2.h> #include <sound/q6asm-v2.h> #include <sound/q6core.h> #include <sound/compress_params.h> #include <sound/compress_offload.h> #include <sound/compress_driver.h> Loading Loading @@ -103,6 +104,7 @@ struct msm_compr_pdata { bool use_legacy_api; /* indicates use older asm apis*/ struct msm_compr_dec_params *dec_params[MSM_FRONTEND_DAI_MAX]; struct msm_compr_ch_map *ch_map[MSM_FRONTEND_DAI_MAX]; int32_t ion_fd[MSM_FRONTEND_DAI_MAX]; }; struct msm_compr_audio { Loading Loading @@ -156,6 +158,8 @@ struct msm_compr_audio { uint32_t start_delay_lsw; uint32_t start_delay_msw; int32_t shm_ion_fd; uint64_t marker_timestamp; struct msm_compr_gapless_state gapless_state; Loading Loading @@ -1506,6 +1510,40 @@ static int msm_compr_configure_dsp_for_capture(struct snd_compr_stream *cstream) return ret; } static int msm_compr_map_unmap_fd(int fd, bool add_pages) { ion_phys_addr_t paddr; size_t pa_len = 0; int ret = 0; u8 assign_type; if (add_pages) assign_type = HLOS_TO_ADSP; else assign_type = ADSP_TO_HLOS; ret = msm_audio_ion_phys_assign("audio_lib_mem_client", fd, &paddr, &pa_len, assign_type); if (ret) { pr_err("%s: audio lib ION phys failed, rc = %d\n", __func__, ret); goto done; } ret = q6core_add_remove_pool_pages(paddr, pa_len, ADSP_MEMORY_MAP_HLOS_PHYSPOOL, add_pages); if (ret) { pr_err("%s: add remove pages failed, rc = %d\n", __func__, ret); /* Assign back to HLOS if add pages cmd failed */ if (add_pages) msm_audio_ion_phys_assign("audio_lib_mem_client", fd, &paddr, &pa_len, ADSP_TO_HLOS); } done: return ret; } static int msm_compr_playback_open(struct snd_compr_stream *cstream) { struct snd_compr_runtime *runtime = cstream->runtime; Loading @@ -1513,6 +1551,7 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) struct msm_compr_audio *prtd; struct msm_compr_pdata *pdata = snd_soc_platform_get_drvdata(rtd->platform); int ret = 0; pr_debug("%s\n", __func__); prtd = kzalloc(sizeof(struct msm_compr_audio), GFP_KERNEL); Loading @@ -1528,19 +1567,16 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) kzalloc(sizeof(struct msm_compr_audio_effects), GFP_KERNEL); if (!pdata->audio_effects[rtd->dai_link->be_id]) { pr_err("%s: Could not allocate memory for effects\n", __func__); pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto effect_err; } pdata->dec_params[rtd->dai_link->be_id] = kzalloc(sizeof(struct msm_compr_dec_params), GFP_KERNEL); if (!pdata->dec_params[rtd->dai_link->be_id]) { pr_err("%s: Could not allocate memory for dec params\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); pdata->cstream[rtd->dai_link->be_id] = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto param_err; } prtd->codec = FORMAT_MP3; prtd->bytes_received = 0; Loading Loading @@ -1584,19 +1620,32 @@ static int msm_compr_playback_open(struct snd_compr_stream *cstream) (app_cb)compr_event_handler, prtd); if (!prtd->audio_client) { pr_err("%s: Could not allocate memory for client\n", __func__); kfree(pdata->audio_effects[rtd->dai_link->be_id]); kfree(pdata->dec_params[rtd->dai_link->be_id]); pdata->cstream[rtd->dai_link->be_id] = NULL; runtime->private_data = NULL; kfree(prtd); return -ENOMEM; ret = -ENOMEM; goto ac_err; } pr_debug("%s: session ID %d\n", __func__, prtd->audio_client->session); prtd->audio_client->perf_mode = false; prtd->session_id = prtd->audio_client->session; msm_adsp_init_mixer_ctl_pp_event_queue(rtd); if (pdata->ion_fd[rtd->dai_link->be_id] > 0) { ret = msm_compr_map_unmap_fd( pdata->ion_fd[rtd->dai_link->be_id], true); if (ret < 0) goto map_err; } return 0; map_err: q6asm_audio_client_free(prtd->audio_client); ac_err: kfree(pdata->dec_params[rtd->dai_link->be_id]); param_err: kfree(pdata->audio_effects[rtd->dai_link->be_id]); effect_err: pdata->cstream[rtd->dai_link->be_id] = NULL; runtime->private_data = NULL; kfree(prtd); return ret; } static int msm_compr_capture_open(struct snd_compr_stream *cstream) Loading Loading @@ -1675,6 +1724,8 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) int dir = IN, ret = 0, stream_id; unsigned long flags; uint32_t stream_index; ion_phys_addr_t paddr; size_t pa_len = 0; pr_debug("%s\n", __func__); Loading Loading @@ -1748,6 +1799,15 @@ static int msm_compr_playback_free(struct snd_compr_stream *cstream) } q6asm_audio_client_buf_free_contiguous(dir, ac); if (prtd->shm_ion_fd > 0) msm_audio_ion_phys_assign("audio_shm_mem_client", prtd->shm_ion_fd, &paddr, &pa_len, ADSP_TO_HLOS); if (pdata->ion_fd[soc_prtd->dai_link->be_id] > 0) { msm_compr_map_unmap_fd(pdata->ion_fd[soc_prtd->dai_link->be_id], false); pdata->ion_fd[soc_prtd->dai_link->be_id] = 0; } q6asm_audio_client_free(ac); msm_adsp_clean_mixer_ctl_pp_event_queue(soc_prtd); Loading Loading @@ -3655,7 +3715,7 @@ done: return ret; } static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, static int msm_compr_shm_ion_fd_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); Loading @@ -3664,7 +3724,6 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, snd_soc_component_get_drvdata(comp); struct snd_compr_stream *cstream = NULL; struct msm_compr_audio *prtd; int fd; int ret = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { Loading Loading @@ -3694,10 +3753,34 @@ static int msm_compr_ion_fd_map_put(struct snd_kcontrol *kcontrol, goto done; } memcpy(&fd, ucontrol->value.bytes.data, sizeof(fd)); ret = q6asm_send_ion_fd(prtd->audio_client, fd); memcpy(&prtd->shm_ion_fd, ucontrol->value.bytes.data, sizeof(prtd->shm_ion_fd)); ret = q6asm_audio_map_shm_fd(prtd->audio_client, prtd->shm_ion_fd); if (ret < 0) pr_err("%s: failed to register ion fd\n", __func__); pr_err("%s: failed to map shm mem\n", __func__); done: return ret; } static int msm_compr_lib_ion_fd_map_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) { struct snd_soc_component *comp = snd_kcontrol_chip(kcontrol); unsigned long fe_id = kcontrol->private_value; struct msm_compr_pdata *pdata = (struct msm_compr_pdata *) snd_soc_component_get_drvdata(comp); int ret = 0; if (fe_id >= MSM_FRONTEND_DAI_MAX) { pr_err("%s Received out of bounds invalid fe_id %lu\n", __func__, fe_id); ret = -EINVAL; goto done; } memcpy(&pdata->ion_fd[fe_id], ucontrol->value.bytes.data, sizeof(pdata->ion_fd[fe_id])); done: return ret; } Loading Loading @@ -4329,7 +4412,7 @@ static int msm_compr_add_channel_map_control(struct snd_soc_pcm_runtime *rtd) return 0; } static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) static int msm_compr_add_shm_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = "Playback ION FD"; const char *deviceNo = "NN"; Loading @@ -4341,7 +4424,52 @@ static int msm_compr_add_io_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_ion_fd_map_put, .put = msm_compr_shm_ion_fd_map_put, .private_value = 0, } }; if (!rtd) { pr_err("%s NULL rtd\n", __func__); ret = -EINVAL; goto done; } ctl_len = strlen(mixer_ctl_name) + 1 + strlen(deviceNo) + 1; mixer_str = kzalloc(ctl_len, GFP_KERNEL); if (!mixer_str) { ret = -ENOMEM; goto done; } snprintf(mixer_str, ctl_len, "%s %d", mixer_ctl_name, rtd->pcm->device); fe_ion_fd_config_control[0].name = mixer_str; fe_ion_fd_config_control[0].private_value = rtd->dai_link->be_id; pr_debug("%s: Registering new mixer ctl %s\n", __func__, mixer_str); ret = snd_soc_add_platform_controls(rtd->platform, fe_ion_fd_config_control, ARRAY_SIZE(fe_ion_fd_config_control)); if (ret < 0) pr_err("%s: failed to add ctl %s\n", __func__, mixer_str); kfree(mixer_str); done: return ret; } static int msm_compr_add_lib_ion_fd_cmd_control(struct snd_soc_pcm_runtime *rtd) { const char *mixer_ctl_name = "Playback ION LIB FD"; const char *deviceNo = "NN"; char *mixer_str = NULL; int ctl_len = 0, ret = 0; struct snd_kcontrol_new fe_ion_fd_config_control[1] = { { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = "?", .access = SNDRV_CTL_ELEM_ACCESS_READWRITE, .info = msm_adsp_stream_cmd_info, .put = msm_compr_lib_ion_fd_map_put, .private_value = 0, } }; Loading Loading @@ -4442,11 +4570,16 @@ static int msm_compr_new(struct snd_soc_pcm_runtime *rtd) pr_err("%s: Could not add Compr ADSP Stream Callback Control\n", __func__); rc = msm_compr_add_io_fd_cmd_control(rtd); rc = msm_compr_add_shm_ion_fd_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ion fd Control\n", __func__); rc = msm_compr_add_lib_ion_fd_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr ion lib fd Control\n", __func__); rc = msm_compr_add_event_ack_cmd_control(rtd); if (rc) pr_err("%s: Could not add Compr event ack Control\n", Loading