diff --git a/audioreach-driver/audioreach_common.c b/audioreach-driver/audioreach_common.c index aa37289..a4ba2e5 100644 --- a/audioreach-driver/audioreach_common.c +++ b/audioreach-driver/audioreach_common.c @@ -4,7 +4,9 @@ #include #include +#include #include +#include #include #include #include @@ -25,6 +27,9 @@ #define I2S_BIT_RATE(rate, channels, format) \ ((rate) * (channels) * (format)) +#define SHIKRA_IQS_MCLK_RATE 12288000 +#define SHIKRA_CQS_BCLK_RATE 3072000 + struct snd_soc_common { const char *driver_name; const struct snd_soc_dapm_widget *dapm_widgets; @@ -34,11 +39,21 @@ struct snd_soc_common { const struct snd_kcontrol_new *controls; int num_controls; unsigned int codec_dai_fmt; + unsigned int codec_sysclk_rate; int num_wsa_spkr; bool codec_sysclk_set; bool mi2s_mclk_enable; bool mi2s_bclk_enable; + bool qaif_backend_names; + const char *primary_mi2s_rx_backend_name; bool wcd_jack; + /* Shikra-style: stereo channel fixup in be_hw_params_fixup */ + bool stereo_fixup; + /* bclk derived from params and set as CLOCK_IN on cpu dai */ + bool bclk_from_params; + /* fixed bclk rate for TDM cpu dai + codec sysclk */ + unsigned int tdm_bclk_rate; + }; struct qcs6490_snd_data { @@ -165,6 +180,25 @@ static const struct snd_soc_dapm_route qcs6490_dapm_routes[] = { { "SpkrRight Speaker", NULL, "SpkrRight SPKR" }, }; +static const struct snd_soc_dapm_widget shikra_cqs_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), +}; + +static const struct snd_soc_dapm_widget shikra_iqs_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MIC("Int Mic", NULL), + SND_SOC_DAPM_SPK("Speaker", NULL), +}; + +static const struct snd_kcontrol_new shikra_iqs_controls[] = { + SOC_DAPM_PIN_SWITCH("Headset Mic"), + SOC_DAPM_PIN_SWITCH("Headphone"), + SOC_DAPM_PIN_SWITCH("Int Mic"), + SOC_DAPM_PIN_SWITCH("Speaker"), +}; + static struct snd_soc_dapm_widget glymur_dapm_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Mic Jack", NULL), @@ -481,14 +515,18 @@ static int qcs6490_snd_wcd_jack_setup(struct snd_soc_pcm_runtime *rtd, } -static void audioreach_get_link_name(const char **link_name, int dai_id) +static void audioreach_get_link_name(const char **link_name, int dai_id, + const struct snd_soc_common *common) { switch (dai_id) { case WSA_CODEC_DMA_RX_0: *link_name = "CODEC_DMA-LPAIF_WSA-RX-0"; break; case VA_CODEC_DMA_TX_0: - *link_name = "CODEC_DMA-LPAIF_VA-TX-0"; + if (common && common->qaif_backend_names) + *link_name = "CODEC_DMA-QAIF-TX-0"; + else + *link_name = "CODEC_DMA-LPAIF_VA-TX-0"; break; case RX_CODEC_DMA_RX_0: *link_name = "CODEC_DMA-LPAIF_RXTX-RX-0"; @@ -500,7 +538,11 @@ static void audioreach_get_link_name(const char **link_name, int dai_id) *link_name = "CODEC_DMA-LPAIF_RXTX-TX-3"; break; case PRIMARY_MI2S_RX: - if (strstr(*link_name, "HS") != NULL) + if (common && common->primary_mi2s_rx_backend_name) + *link_name = common->primary_mi2s_rx_backend_name; + else if (common && common->qaif_backend_names) + *link_name = "QAIF-QAIF_AUD-RX-2"; + else if (strstr(*link_name, "HS") != NULL) *link_name = "MI2S-LPAIF_SDR-RX-PRIMARY"; else *link_name = "MI2S-LPAIF-RX-PRIMARY"; @@ -550,6 +592,8 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card) struct snd_soc_dai_link *link; struct of_phandle_args args; struct snd_soc_dai_link_component *dlc; + struct qcs6490_snd_data *data = snd_soc_card_get_drvdata(card); + const struct snd_soc_common *common = data ? data->snd_soc_common_priv : NULL; int ret, num_links; ret = snd_soc_of_parse_card_name(card, "model"); @@ -634,7 +678,7 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card) goto err; } - link->id = args.args[0]; + link->id = args.args[0]; link->platforms->of_node = link->cpus->of_node; if (codec) { @@ -663,7 +707,7 @@ static int qcs6490_snd_parse_of(struct snd_soc_card *card) link->nonatomic = 1; } - audioreach_get_link_name(&link->name, link->id); + audioreach_get_link_name(&link->name, link->id, common); link->stream_name = link->name; link++; @@ -747,6 +791,7 @@ static int qcs6490_snd_init(struct snd_soc_pcm_runtime *rtd) static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { + struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); @@ -754,6 +799,11 @@ static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, SNDRV_PCM_HW_PARAM_CHANNELS); rate->min = rate->max = 48000; + if (pdata->snd_soc_common_priv->stereo_fixup) { + channels->min = 2; + channels->max = 2; + } + switch (cpu_dai->id) { case TX_CODEC_DMA_TX_0: case TX_CODEC_DMA_TX_1: @@ -769,13 +819,46 @@ static int qcs6490_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, return 0; } +static int qcs6490_snd_set_codecs_fmt(struct snd_soc_pcm_runtime *rtd, + unsigned int fmt) +{ + struct snd_soc_dai *codec_dai; + int ret; + int i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_fmt(codec_dai, fmt); + if (ret && ret != -ENOTSUPP) + return ret; + } + + return 0; +} + +static int qcs6490_snd_set_codecs_sysclk(struct snd_soc_pcm_runtime *rtd, + unsigned int freq) +{ + struct snd_soc_dai *codec_dai; + int ret; + int i; + + for_each_rtd_codec_dais(rtd, i, codec_dai) { + ret = snd_soc_dai_set_sysclk(codec_dai, 0, freq, + SND_SOC_CLOCK_IN); + if (ret) + return ret; + } + + return 0; +} + static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = snd_soc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = snd_soc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = snd_soc_rtd_to_cpu(rtd, 0); struct qcs6490_snd_data *pdata = snd_soc_card_get_drvdata(rtd->card); + const struct snd_soc_common *common = pdata->snd_soc_common_priv; int mclk_freq = qcs6490_get_mclk_freq(params); int bclk_freq = qcs6490_get_bclk_freq(params); int ret = 0; @@ -787,14 +870,13 @@ static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream, if (ret && ret != -ENOTSUPP) return ret; - if (pdata->snd_soc_common_priv->codec_dai_fmt) { - ret = snd_soc_dai_set_fmt(codec_dai, - pdata->snd_soc_common_priv->codec_dai_fmt); - if (ret && ret != -ENOTSUPP) + if (common->codec_dai_fmt) { + ret = qcs6490_snd_set_codecs_fmt(rtd, common->codec_dai_fmt); + if (ret) return ret; } - if (pdata->snd_soc_common_priv->mi2s_mclk_enable) { + if (common->mi2s_mclk_enable) { ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_MCLK, mclk_freq, SND_SOC_CLOCK_OUT); @@ -802,7 +884,16 @@ static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream, return ret; } - if (pdata->snd_soc_common_priv->mi2s_bclk_enable) { + if (common->bclk_from_params) { + int bclk = snd_soc_params_to_bclk(params); + + if (bclk <= 0) + return -EINVAL; + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, + bclk, SND_SOC_CLOCK_IN); + if (ret) + return ret; + } else if (common->mi2s_bclk_enable) { ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, bclk_freq, SND_SOC_CLOCK_OUT); @@ -810,12 +901,24 @@ static int qcs6490_snd_hw_params(struct snd_pcm_substream *substream, return ret; } - if (pdata->snd_soc_common_priv->codec_sysclk_set) { - ret = snd_soc_dai_set_sysclk(codec_dai, - 0, mclk_freq, + if (common->codec_sysclk_set || common->codec_sysclk_rate) { + ret = qcs6490_snd_set_codecs_sysclk(rtd, + common->codec_sysclk_rate ?: mclk_freq); + if (ret) + return ret; + } + break; + case SECONDARY_TDM_RX_0: + if (common->tdm_bclk_rate) { + ret = snd_soc_dai_set_sysclk(cpu_dai, LPAIF_MI2S_BCLK, + common->tdm_bclk_rate, SND_SOC_CLOCK_IN); if (ret) return ret; + ret = qcs6490_snd_set_codecs_sysclk(rtd, + common->tdm_bclk_rate); + if (ret) + return ret; } break; default: @@ -867,6 +970,29 @@ static void qcs6490_add_be_ops(struct snd_soc_card *card) } } +static struct snd_soc_common shikra_cqs_priv_data = { + .driver_name = "shikra-cqs", + .dapm_widgets = shikra_cqs_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_cqs_dapm_widgets), + .qaif_backend_names = true, + .stereo_fixup = true, + .tdm_bclk_rate = SHIKRA_CQS_BCLK_RATE, +}; + +static struct snd_soc_common shikra_iqs_priv_data = { + .driver_name = "shikra-iqs", + .dapm_widgets = shikra_iqs_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(shikra_iqs_dapm_widgets), + .controls = shikra_iqs_controls, + .num_controls = ARRAY_SIZE(shikra_iqs_controls), + .qaif_backend_names = true, + .primary_mi2s_rx_backend_name = "QAIF-QAIF_AUD-RX-0", + .codec_dai_fmt = SND_SOC_DAIFMT_CBP_CFP | SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_I2S, + .codec_sysclk_rate = SHIKRA_IQS_MCLK_RATE, + .bclk_from_params = true, + .stereo_fixup = true, +}; + static int qcs6490_platform_probe(struct platform_device *pdev) { struct snd_soc_card *card; @@ -903,7 +1029,11 @@ static int qcs6490_platform_probe(struct platform_device *pdev) card->driver_name = data->snd_soc_common_priv->driver_name; qcs6490_add_be_ops(card); - return devm_snd_soc_register_card(dev, card); + ret = devm_snd_soc_register_card(dev, card); + if (ret) + return dev_err_probe(dev, ret, "sound card registration failed\n"); + + return 0; } static struct snd_soc_common glymur_priv_data = { @@ -1039,6 +1169,8 @@ static const struct of_device_id snd_qcs6490_dt_match[] = { {.compatible = "qcom,sm8650-sndcard", .data = &sm8650_priv_data}, {.compatible = "qcom,sm8750-sndcard", .data = &sm8750_priv_data}, {.compatible = "qcom,x1e80100-sndcard", .data = &x1e80100_priv_data}, + {.compatible = "qcom,shikra-cqs-sndcard", .data = &shikra_cqs_priv_data}, + {.compatible = "qcom,shikra-iqs-sndcard", .data = &shikra_iqs_priv_data}, {} }; diff --git a/audioreach-driver/q6apm_audio_mem.c b/audioreach-driver/q6apm_audio_mem.c index 98f32ec..fe2d385 100644 --- a/audioreach-driver/q6apm_audio_mem.c +++ b/audioreach-driver/q6apm_audio_mem.c @@ -18,12 +18,18 @@ #include #include #include +#include +#include +#include #include +#include +#include #include #include #include #include #include +#include #include #include #include @@ -45,6 +51,7 @@ int msm_audio_cma_get_phy_addr(int fd, dma_addr_t *paddr, size_t *pa_len); #define MSM_AUDIO_SMMU_SID_OFFSET 32 #define MINOR_NUMBER_COUNT 1 #define QCOM_SMMU_SID_MASK 0xF +#define MSM_AUDIO_HEAP_NAME "qcom,audio" #if LINUX_VERSION_CODE >= KERNEL_VERSION(6, 12, 0) #define AR_USE_VOID_RETURN_TYPE 1 @@ -67,6 +74,34 @@ struct msm_audio_mem_private { struct class *mem_class; struct device *chardev; struct cdev cdev; + bool use_mss_msa_vmid; + struct gen_pool *audio_heap_pool; + struct dma_heap *audio_heap; + phys_addr_t audio_heap_base; + size_t audio_heap_size; + bool audio_heap_hyp_assigned; + u64 audio_heap_perms; + phys_addr_t audio_aux_region_base; + size_t audio_aux_region_size; + bool audio_aux_region_hyp_assigned; + u64 audio_aux_region_perms; +}; + +struct msm_audio_heap_buffer { + struct msm_audio_mem_private *mem_data; + struct list_head attachments; + struct mutex lock; + unsigned long len; + phys_addr_t phys; + void *vaddr; + int vmap_cnt; +}; + +struct msm_audio_heap_attachment { + struct device *dev; + struct sg_table table; + struct list_head list; + bool mapped; }; struct msm_audio_alloc_data { @@ -96,8 +131,557 @@ struct msm_audio_fd_data { struct device *dev; struct list_head list; bool hyp_assign; + bool use_mss_msa_vmid; +}; + +static bool msm_audio_mem_range_in_audio_heap( + struct msm_audio_mem_private *mem_data, dma_addr_t paddr, size_t len); +static void msm_audio_mem_unassign_audio_heap(struct device *dev, + struct msm_audio_mem_private *mem_data); + +static int msm_audio_heap_attach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + struct msm_audio_heap_attachment *attach; + struct page *page; + int ret; + + attach = kzalloc(sizeof(*attach), GFP_KERNEL); + if (!attach) + return -ENOMEM; + + ret = sg_alloc_table(&attach->table, 1, GFP_KERNEL); + if (ret) { + kfree(attach); + return ret; + } + + page = pfn_to_page(PHYS_PFN(buffer->phys)); + sg_set_page(attach->table.sgl, page, buffer->len, 0); + sg_dma_address(attach->table.sgl) = buffer->phys; + sg_dma_len(attach->table.sgl) = buffer->len; + attach->dev = attachment->dev; + attach->mapped = false; + INIT_LIST_HEAD(&attach->list); + attachment->priv = attach; + + mutex_lock(&buffer->lock); + list_add(&attach->list, &buffer->attachments); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void msm_audio_heap_detach(struct dma_buf *dmabuf, + struct dma_buf_attachment *attachment) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + struct msm_audio_heap_attachment *attach = attachment->priv; + + mutex_lock(&buffer->lock); + list_del(&attach->list); + mutex_unlock(&buffer->lock); + + sg_free_table(&attach->table); + kfree(attach); +} + +static struct sg_table *msm_audio_heap_map_dma_buf(struct dma_buf_attachment *attachment, + enum dma_data_direction direction) +{ + struct msm_audio_heap_attachment *attach = attachment->priv; + + attach->mapped = true; + + return &attach->table; +} + +static void msm_audio_heap_unmap_dma_buf(struct dma_buf_attachment *attachment, + struct sg_table *table, + enum dma_data_direction direction) +{ + struct msm_audio_heap_attachment *attach = attachment->priv; + + attach->mapped = false; +} + +static int msm_audio_heap_dma_buf_begin_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + struct msm_audio_heap_attachment *attach; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt && buffer->vaddr) + invalidate_kernel_vmap_range(buffer->vaddr, buffer->len); + + list_for_each_entry(attach, &buffer->attachments, list) { + if (!attach->mapped) + continue; + dma_sync_sgtable_for_cpu(attach->dev, &attach->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int msm_audio_heap_dma_buf_end_cpu_access(struct dma_buf *dmabuf, + enum dma_data_direction direction) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + struct msm_audio_heap_attachment *attach; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt && buffer->vaddr) + flush_kernel_vmap_range(buffer->vaddr, buffer->len); + + list_for_each_entry(attach, &buffer->attachments, list) { + if (!attach->mapped) + continue; + dma_sync_sgtable_for_device(attach->dev, &attach->table, direction); + } + mutex_unlock(&buffer->lock); + + return 0; +} + +static int msm_audio_heap_mmap(struct dma_buf *dmabuf, struct vm_area_struct *vma) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + unsigned long size = vma->vm_end - vma->vm_start; + + if (size > buffer->len) + return -EINVAL; + + vm_flags_set(vma, VM_IO | VM_PFNMAP | VM_DONTEXPAND | VM_DONTDUMP); + vma->vm_page_prot = pgprot_writecombine(vma->vm_page_prot); + + return remap_pfn_range(vma, vma->vm_start, PHYS_PFN(buffer->phys), + size, vma->vm_page_prot); +} + +static int msm_audio_heap_vmap(struct dma_buf *dmabuf, struct iosys_map *map) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (!buffer->vmap_cnt) { + buffer->vaddr = memremap(buffer->phys, buffer->len, MEMREMAP_WB); + if (!buffer->vaddr) { + mutex_unlock(&buffer->lock); + return -ENOMEM; + } + } + buffer->vmap_cnt++; + iosys_map_set_vaddr(map, buffer->vaddr); + mutex_unlock(&buffer->lock); + + return 0; +} + +static void msm_audio_heap_vunmap(struct dma_buf *dmabuf, struct iosys_map *map) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + + mutex_lock(&buffer->lock); + if (buffer->vmap_cnt && !--buffer->vmap_cnt) { + memunmap(buffer->vaddr); + buffer->vaddr = NULL; + } + mutex_unlock(&buffer->lock); + iosys_map_clear(map); +} + +static void msm_audio_heap_dma_buf_release(struct dma_buf *dmabuf) +{ + struct msm_audio_heap_buffer *buffer = dmabuf->priv; + + if (buffer->vmap_cnt) { + memunmap(buffer->vaddr); + buffer->vaddr = NULL; + buffer->vmap_cnt = 0; + } + + gen_pool_free(buffer->mem_data->audio_heap_pool, buffer->phys, buffer->len); + kfree(buffer); +} + +static const struct dma_buf_ops msm_audio_heap_buf_ops = { + .attach = msm_audio_heap_attach, + .detach = msm_audio_heap_detach, + .map_dma_buf = msm_audio_heap_map_dma_buf, + .unmap_dma_buf = msm_audio_heap_unmap_dma_buf, + .begin_cpu_access = msm_audio_heap_dma_buf_begin_cpu_access, + .end_cpu_access = msm_audio_heap_dma_buf_end_cpu_access, + .mmap = msm_audio_heap_mmap, + .vmap = msm_audio_heap_vmap, + .vunmap = msm_audio_heap_vunmap, + .release = msm_audio_heap_dma_buf_release, }; +static struct dma_buf *msm_audio_heap_allocate(struct dma_heap *heap, + unsigned long len, u32 fd_flags, + u64 heap_flags) +{ + struct msm_audio_mem_private *mem_data = dma_heap_get_drvdata(heap); + struct msm_audio_heap_buffer *buffer; + DEFINE_DMA_BUF_EXPORT_INFO(exp_info); + struct dma_buf *dmabuf; + size_t size = PAGE_ALIGN(len); + unsigned long phys; + int ret = -ENOMEM; + + if (!size || size > mem_data->audio_heap_size) + return ERR_PTR(-EINVAL); + + + buffer = kzalloc(sizeof(*buffer), GFP_KERNEL); + if (!buffer) + return ERR_PTR(-ENOMEM); + + phys = gen_pool_alloc(mem_data->audio_heap_pool, size); + if (!phys) + goto free_buffer; + + buffer->mem_data = mem_data; + buffer->len = size; + buffer->phys = phys; + INIT_LIST_HEAD(&buffer->attachments); + mutex_init(&buffer->lock); + + exp_info.exp_name = MSM_AUDIO_HEAP_NAME; + exp_info.ops = &msm_audio_heap_buf_ops; + exp_info.size = buffer->len; + exp_info.flags = fd_flags; + exp_info.priv = buffer; + dmabuf = dma_buf_export(&exp_info); + if (IS_ERR(dmabuf)) { + ret = PTR_ERR(dmabuf); + goto free_pool; + } + + + return dmabuf; + +free_pool: + gen_pool_free(mem_data->audio_heap_pool, phys, size); +free_buffer: + kfree(buffer); + return ERR_PTR(ret); +} + +static const struct dma_heap_ops msm_audio_heap_ops = { + .allocate = msm_audio_heap_allocate, +}; + +static bool msm_audio_mem_range_in_audio_heap( + struct msm_audio_mem_private *mem_data, dma_addr_t paddr, size_t len) +{ + phys_addr_t base; + size_t offset; + + if (!mem_data || !mem_data->audio_heap_size || !len) + return false; + + base = mem_data->audio_heap_base; + if (paddr < base || len > mem_data->audio_heap_size) + return false; + + offset = paddr - base; + + return offset <= mem_data->audio_heap_size - len; +} + +static bool msm_audio_mem_skip_buffer_hyp_assign( + struct msm_audio_mem_private *mem_data, dma_addr_t paddr, size_t len) +{ + return mem_data && mem_data->audio_heap_hyp_assigned && + msm_audio_mem_range_in_audio_heap(mem_data, paddr, len); +} + +#ifdef QCOM_HYP_ASSIGN +static int msm_audio_mem_assign_aux_audio_region(struct device *dev, + struct msm_audio_mem_private *mem_data, + struct qcom_scm_vmperm *dst_perms, int dst_count) +{ + struct device_node *rmem_node; + struct reserved_mem *rmem; + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); + int ret; + + rmem_node = of_parse_phandle(dev->of_node, "memory-region", 0); + if (!rmem_node) + return 0; + + rmem = of_reserved_mem_lookup(rmem_node); + of_node_put(rmem_node); + if (!rmem) + return 0; + + if (rmem->base == mem_data->audio_heap_base && + rmem->size == mem_data->audio_heap_size) + return 0; + + ret = qcom_scm_assign_mem(rmem->base, rmem->size, &src_perms, + dst_perms, dst_count); + if (ret) { + dev_err(dev, + "%s: aux audio region assign failed ret=%d base=%pa size=%zu\n", + __func__, ret, &rmem->base, (size_t)rmem->size); + return ret; + } + + mem_data->audio_aux_region_base = rmem->base; + mem_data->audio_aux_region_size = rmem->size; + mem_data->audio_aux_region_hyp_assigned = true; + mem_data->audio_aux_region_perms = src_perms; + + return 0; +} + +static int msm_audio_mem_assign_audio_heap(struct device *dev, + struct msm_audio_mem_private *mem_data) +{ + struct qcom_scm_vmperm *dst_perms; + u64 src_perms = BIT(QCOM_SCM_VMID_HLOS); + int num_vmids, dst_count = 0; + int ret = 0; + u32 vmid; + + if (!mem_data->use_mss_msa_vmid || mem_data->audio_heap_hyp_assigned) + return 0; + + num_vmids = of_property_count_u32_elems(dev->of_node, "qcom,vmid"); + if (num_vmids < 0) { + dev_err(dev, "%s: qcom,vmid missing for MDSP audio heap\n", + __func__); + return num_vmids; + } + + dst_perms = kcalloc(num_vmids + 1, sizeof(*dst_perms), GFP_KERNEL); + if (!dst_perms) + return -ENOMEM; + + dst_perms[dst_count].vmid = QCOM_SCM_VMID_HLOS; + dst_perms[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + + of_property_for_each_u32(dev->of_node, "qcom,vmid", vmid) { + if (vmid == QCOM_SCM_VMID_HLOS) + continue; + + dst_perms[dst_count].vmid = vmid; + dst_perms[dst_count].perm = QCOM_SCM_PERM_RW; + dst_count++; + } + + ret = qcom_scm_assign_mem(mem_data->audio_heap_base, + mem_data->audio_heap_size, &src_perms, + dst_perms, dst_count); + if (ret) { + dev_err(dev, + "%s: audio heap assign failed ret=%d base=%pa size=%zu\n", + __func__, ret, &mem_data->audio_heap_base, + mem_data->audio_heap_size); + goto free_dst_perms; + } + + mem_data->audio_heap_hyp_assigned = true; + mem_data->audio_heap_perms = src_perms; + + ret = msm_audio_mem_assign_aux_audio_region(dev, mem_data, + dst_perms, dst_count); + if (ret) + msm_audio_mem_unassign_audio_heap(dev, mem_data); + +free_dst_perms: + kfree(dst_perms); + return ret; +} + +static void msm_audio_mem_unassign_audio_heap(struct device *dev, + struct msm_audio_mem_private *mem_data) +{ + struct qcom_scm_vmperm hlos_perm = { + .vmid = QCOM_SCM_VMID_HLOS, + .perm = QCOM_SCM_PERM_RW, + }; + u64 src_perms; + int ret; + + if (!mem_data || !mem_data->audio_heap_hyp_assigned) + return; + + if (mem_data->audio_aux_region_hyp_assigned) { + src_perms = mem_data->audio_aux_region_perms; + ret = qcom_scm_assign_mem(mem_data->audio_aux_region_base, + mem_data->audio_aux_region_size, + &src_perms, &hlos_perm, 1); + if (ret) { + dev_err(dev, + "%s: aux audio region unassign failed ret=%d base=%pa size=%zu\n", + __func__, ret, &mem_data->audio_aux_region_base, + mem_data->audio_aux_region_size); + return; + } + + mem_data->audio_aux_region_hyp_assigned = false; + mem_data->audio_aux_region_perms = src_perms; + } + + src_perms = mem_data->audio_heap_perms; + ret = qcom_scm_assign_mem(mem_data->audio_heap_base, + mem_data->audio_heap_size, &src_perms, + &hlos_perm, 1); + if (ret) { + dev_err(dev, + "%s: audio heap unassign failed ret=%d base=%pa size=%zu\n", + __func__, ret, &mem_data->audio_heap_base, + mem_data->audio_heap_size); + return; + } + + mem_data->audio_heap_hyp_assigned = false; + mem_data->audio_heap_perms = src_perms; +} +#else +static int msm_audio_mem_assign_audio_heap(struct device *dev, + struct msm_audio_mem_private *mem_data) +{ + return 0; +} + +static void msm_audio_mem_unassign_audio_heap(struct device *dev, + struct msm_audio_mem_private *mem_data) +{ +} +#endif + +static int msm_audio_mem_register_audio_heap(struct platform_device *pdev, + struct msm_audio_mem_private *mem_data) +{ + struct dma_heap_export_info exp_info = { }; + struct device *dev = &pdev->dev; + struct device_node *rmem_node; + struct reserved_mem *rmem = NULL; + int rmem_indices[] = { 1, 0 }; + int ret; + int i; + + if (!mem_data->use_mss_msa_vmid) + return 0; + + for (i = 0; i < ARRAY_SIZE(rmem_indices); i++) { + rmem_node = of_parse_phandle(dev->of_node, "memory-region", + rmem_indices[i]); + if (!rmem_node) + continue; + + rmem = of_reserved_mem_lookup(rmem_node); + of_node_put(rmem_node); + if (rmem) + break; + + } + + if (!rmem) + return 0; + + mem_data->audio_heap_pool = gen_pool_create(PAGE_SHIFT, dev_to_node(dev)); + if (!mem_data->audio_heap_pool) + return -ENOMEM; + + ret = gen_pool_add(mem_data->audio_heap_pool, rmem->base, rmem->size, + dev_to_node(dev)); + if (ret) { + gen_pool_destroy(mem_data->audio_heap_pool); + mem_data->audio_heap_pool = NULL; + return ret; + } + + mem_data->audio_heap_base = rmem->base; + mem_data->audio_heap_size = rmem->size; + ret = msm_audio_mem_assign_audio_heap(dev, mem_data); + if (ret) { + gen_pool_destroy(mem_data->audio_heap_pool); + mem_data->audio_heap_pool = NULL; + return ret; + } + + exp_info.name = MSM_AUDIO_HEAP_NAME; + exp_info.ops = &msm_audio_heap_ops; + exp_info.priv = mem_data; + mem_data->audio_heap = dma_heap_add(&exp_info); + if (IS_ERR(mem_data->audio_heap)) { + ret = PTR_ERR(mem_data->audio_heap); + mem_data->audio_heap = NULL; + msm_audio_mem_unassign_audio_heap(dev, mem_data); + gen_pool_destroy(mem_data->audio_heap_pool); + mem_data->audio_heap_pool = NULL; + return ret; + } + + return 0; +} + +static bool msm_audio_mem_uses_mss_msa_vmid(struct device *dev) +{ + u32 vmid; + + if (!dev || !dev->of_node) + return false; + + of_property_for_each_u32(dev->of_node, "qcom,vmid", vmid) { + if (vmid == QCOM_SCM_VMID_MSS_MSA) + return true; + } + + return false; +} + +static int msm_audio_mem_get_hyp_map_perms(struct msm_audio_mem_private *mem_data, + u64 *src_vmid_map_list, struct qcom_scm_vmperm **dst_vmids_map, + int *dst_vmids_map_count) +{ + static struct qcom_scm_vmperm mss_dst_vmids_map[] = { + {QCOM_SCM_VMID_MSS_MSA, QCOM_SCM_PERM_RW}, + }; + static struct qcom_scm_vmperm adsp_dst_vmids_map[] = { + {QCOM_SCM_VMID_LPASS, QCOM_SCM_PERM_RW}, + {QCOM_SCM_VMID_ADSP_HEAP, QCOM_SCM_PERM_RW}, + }; + + *src_vmid_map_list = BIT(QCOM_SCM_VMID_HLOS); + if (mem_data->use_mss_msa_vmid) { + *dst_vmids_map = mss_dst_vmids_map; + *dst_vmids_map_count = ARRAY_SIZE(mss_dst_vmids_map); + } else { + *dst_vmids_map = adsp_dst_vmids_map; + *dst_vmids_map_count = ARRAY_SIZE(adsp_dst_vmids_map); + } + + return 0; +} + +static void msm_audio_mem_get_hyp_unmap_perms(bool use_mss_msa_vmid, + u64 *src_vmid_unmap_list, struct qcom_scm_vmperm **dst_vmids_unmap, + int *dst_vmids_unmap_count) +{ + static struct qcom_scm_vmperm hlos_dst_vmids_unmap[] = { + {QCOM_SCM_VMID_HLOS, QCOM_SCM_PERM_RWX}, + }; + + if (use_mss_msa_vmid) + *src_vmid_unmap_list = BIT(QCOM_SCM_VMID_MSS_MSA); + else + *src_vmid_unmap_list = BIT(QCOM_SCM_VMID_LPASS) | + BIT(QCOM_SCM_VMID_ADSP_HEAP); + + *dst_vmids_unmap = hlos_dst_vmids_unmap; + *dst_vmids_unmap_count = ARRAY_SIZE(hlos_dst_vmids_unmap); +} + static void msm_audio_mem_add_allocation( struct msm_audio_mem_private *msm_audio_mem_data, struct msm_audio_alloc_data *alloc_data) @@ -191,7 +775,7 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, * to accommodate both read and write mappings. */ alloc_data->table = dma_buf_map_attachment(alloc_data->attach, - DMA_BIDIRECTIONAL); + DMA_BIDIRECTIONAL); if (IS_ERR(alloc_data->table)) { rc = PTR_ERR(alloc_data->table); dev_err(cb_dev, @@ -203,10 +787,11 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf, /* physical address from mapping */ if (!is_iova) { *addr = sg_phys(alloc_data->table->sgl); - rc = msm_audio_mem_map_kernel((void *)dma_buf, mem_data, iosys_vmap); + rc = msm_audio_mem_map_kernel((void *)dma_buf, mem_data, + iosys_vmap); if (rc) { pr_err("%s: MEM memory mapping for AUDIO failed, err:%d\n", - __func__, rc); + __func__, rc); rc = -ENOMEM; goto detach_dma_buf; } @@ -576,12 +1161,19 @@ static int msm_audio_mem_free(struct dma_buf *dma_buf, struct msm_audio_mem_priv static int msm_audio_hyp_unassign(struct msm_audio_fd_data *msm_audio_fd_data) { int ret = 0; - u64 src_vmid_unmap_list = BIT(QCOM_SCM_VMID_LPASS) | BIT(QCOM_SCM_VMID_ADSP_HEAP); - struct qcom_scm_vmperm dst_vmids_unmap[] = {{QCOM_SCM_VMID_HLOS, QCOM_SCM_PERM_RWX}}; + u64 src_vmid_unmap_list; + struct qcom_scm_vmperm *dst_vmids_unmap; + int dst_vmids_unmap_count; if (msm_audio_fd_data->hyp_assign) { - ret = qcom_scm_assign_mem(msm_audio_fd_data->paddr, msm_audio_fd_data->plen, - &src_vmid_unmap_list, dst_vmids_unmap, ARRAY_SIZE(dst_vmids_unmap)); + msm_audio_mem_get_hyp_unmap_perms(msm_audio_fd_data->use_mss_msa_vmid, + &src_vmid_unmap_list, &dst_vmids_unmap, + &dst_vmids_unmap_count); + ret = qcom_scm_assign_mem(msm_audio_fd_data->paddr, + msm_audio_fd_data->plen, + &src_vmid_unmap_list, + dst_vmids_unmap, + dst_vmids_unmap_count); if (ret < 0) { pr_err("%s: qcom assign unmap failed result = %d addr = 0x%llx size = %zu\n", __func__, ret, msm_audio_fd_data->paddr, msm_audio_fd_data->plen); @@ -663,19 +1255,18 @@ static long msm_audio_mem_ioctl(struct file *file, unsigned int ioctl_num, struct msm_audio_mem_private *mem_data = container_of(file->f_inode->i_cdev, struct msm_audio_mem_private, cdev); u64 src_vmid_map_list = BIT(QCOM_SCM_VMID_HLOS); - struct qcom_scm_vmperm dst_vmids_map[] = {{QCOM_SCM_VMID_LPASS, QCOM_SCM_PERM_RW}, - {QCOM_SCM_VMID_ADSP_HEAP, QCOM_SCM_PERM_RW}}; - u64 src_vmid_unmap_list = BIT(QCOM_SCM_VMID_LPASS) | BIT(QCOM_SCM_VMID_ADSP_HEAP); - struct qcom_scm_vmperm dst_vmids_unmap[] = {{QCOM_SCM_VMID_HLOS, - QCOM_SCM_PERM_RWX}}; + struct qcom_scm_vmperm *dst_vmids_map; + int dst_vmids_map_count; + u64 src_vmid_unmap_list; + struct qcom_scm_vmperm *dst_vmids_unmap; + int dst_vmids_unmap_count; switch (ioctl_num) { case IOCTL_MAP_PHYS_ADDR: - iosys_vmap = kzalloc(sizeof(struct msm_audio_fd_data), GFP_KERNEL); + iosys_vmap = kzalloc(sizeof(*iosys_vmap), GFP_KERNEL); if (!iosys_vmap) return -ENOMEM; - msm_audio_fd_data = kzalloc((sizeof(struct msm_audio_fd_data)), - GFP_KERNEL); + msm_audio_fd_data = kzalloc(sizeof(*msm_audio_fd_data), GFP_KERNEL); if (!msm_audio_fd_data) { kfree(iosys_vmap); return -ENOMEM; @@ -693,6 +1284,7 @@ static long msm_audio_mem_ioctl(struct file *file, unsigned int ioctl_num, msm_audio_fd_data->paddr = paddr; msm_audio_fd_data->plen = pa_len; msm_audio_fd_data->dev = mem_data->cb_dev; + msm_audio_fd_data->use_mss_msa_vmid = mem_data->use_mss_msa_vmid; msm_audio_update_fd_list(msm_audio_fd_data); break; case IOCTL_UNMAP_PHYS_ADDR: @@ -711,11 +1303,17 @@ static long msm_audio_mem_ioctl(struct file *file, unsigned int ioctl_num, pr_err("%s get phys addr failed %d\n", __func__, ret); return ret; } + if (msm_audio_mem_skip_buffer_hyp_assign(mem_data, paddr, pa_len)) { + msm_audio_set_hyp_assign((int)ioctl_param, false); + break; + } + msm_audio_mem_get_hyp_map_perms(mem_data, &src_vmid_map_list, + &dst_vmids_map, &dst_vmids_map_count); ret = qcom_scm_assign_mem(paddr, pa_len, &src_vmid_map_list, - dst_vmids_map, ARRAY_SIZE(dst_vmids_map)); + dst_vmids_map, dst_vmids_map_count); if (ret < 0) { pr_err("%s: qcom_assign failed result = %d addr = 0x%llx size = %lu\n", - __func__, ret, paddr, pa_len); + __func__, ret, paddr, pa_len); return ret; } pr_debug("%s: qcom scm assign success\n", __func__); @@ -727,11 +1325,18 @@ static long msm_audio_mem_ioctl(struct file *file, unsigned int ioctl_num, pr_err("%s get phys addr failed %d\n", __func__, ret); return ret; } + if (msm_audio_mem_skip_buffer_hyp_assign(mem_data, paddr, pa_len)) { + msm_audio_set_hyp_assign((int)ioctl_param, false); + break; + } + msm_audio_mem_get_hyp_unmap_perms(mem_data->use_mss_msa_vmid, + &src_vmid_unmap_list, &dst_vmids_unmap, + &dst_vmids_unmap_count); ret = qcom_scm_assign_mem(paddr, pa_len, &src_vmid_unmap_list, - dst_vmids_unmap, ARRAY_SIZE(dst_vmids_unmap)); + dst_vmids_unmap, dst_vmids_unmap_count); if (ret < 0) { pr_err("%s: qcom scm unassign failed result = %d addr = 0x%llx size = %lu\n", - __func__, ret, paddr, pa_len); + __func__, ret, paddr, pa_len); return ret; } pr_debug("%s: qcom scm unassign success\n", __func__); @@ -835,6 +1440,7 @@ static int q6apm_audio_mem_probe(struct platform_device *pdev) msm_audio_mem_data->driver_name = "msm_audio_mem"; + msm_audio_mem_data->use_mss_msa_vmid = msm_audio_mem_uses_mss_msa_vmid(dev); /* Enable SMMU only if DT has an 'iommus' property */ if (of_find_property(dev->of_node, "iommus", NULL)) @@ -865,11 +1471,16 @@ static int q6apm_audio_mem_probe(struct platform_device *pdev) } if (!rc) { - pr_err("DEBUG:%s:%d:Probed \n",__func__,__LINE__); msm_audio_mem_data->device_status |= MSM_AUDIO_MEM_PROBED; } msm_audio_mem_data->cb_dev = dev; dev_set_drvdata(dev, msm_audio_mem_data); + rc = msm_audio_mem_register_audio_heap(pdev, msm_audio_mem_data); + if (rc) { + dev_err(dev, "%s: audio heap registration failed %d\n", + __func__, rc); + return rc; + } if (!msm_audio_mem_fd_list_init) { INIT_LIST_HEAD(&msm_audio_mem_fd_list.fd_list); mutex_init(&(msm_audio_mem_fd_list.list_mutex)); @@ -880,13 +1491,26 @@ static int q6apm_audio_mem_probe(struct platform_device *pdev) rc = msm_audio_mem_reg_chrdev(msm_audio_mem_data); if (rc) { pr_err("%s register char dev failed, rc : %d\n", __func__, rc); + msm_audio_mem_unassign_audio_heap(dev, msm_audio_mem_data); return rc; } - - devm_snd_soc_register_component(dev, &q6apm_audio_mem_component, NULL, 0); - /* Spawn the CMA child driver only if DT has a memory-region property */ - if (of_find_property(dev->of_node, "memory-region", NULL)) { + rc = devm_snd_soc_register_component(dev, &q6apm_audio_mem_component, + NULL, 0); + if (rc) { + pr_err("%s register component failed, rc : %d\n", __func__, rc); + msm_audio_mem_unreg_chrdev(msm_audio_mem_data); + msm_audio_mem_unassign_audio_heap(dev, msm_audio_mem_data); + return rc; + } + + /* + * Spawn the CMA child driver only if DT has a memory-region property + * and we are not using the MSS MSA VMID path (Shikra uses the + * dedicated audio heap instead of CMA). + */ + if (!msm_audio_mem_data->use_mss_msa_vmid && + of_find_property(dev->of_node, "memory-region", NULL)) { msm_audio_mem_data->cma_pdev = platform_device_register_data(dev, "q6apm-audio-mem-cma", PLATFORM_DEVID_NONE, NULL, 0); @@ -895,7 +1519,7 @@ static int q6apm_audio_mem_probe(struct platform_device *pdev) __func__, PTR_ERR(msm_audio_mem_data->cma_pdev)); msm_audio_mem_data->cma_pdev = NULL; } - } else { + } else if (!msm_audio_mem_data->use_mss_msa_vmid) { dev_info(dev, "%s: no memory-region, CMA driver not spawned\n", __func__); } @@ -911,6 +1535,7 @@ static void q6apm_audio_mem_remove(struct platform_device *pdev) platform_device_unregister(mem_data->cma_pdev); mem_data->smmu_enabled = false; mem_data->device_status = 0; + msm_audio_mem_unassign_audio_heap(&pdev->dev, mem_data); msm_audio_mem_unreg_chrdev(mem_data); } #else @@ -922,6 +1547,7 @@ static int q6apm_audio_mem_remove(struct platform_device *pdev) platform_device_unregister(mem_data->cma_pdev); mem_data->smmu_enabled = false; mem_data->device_status = 0; + msm_audio_mem_unassign_audio_heap(&pdev->dev, mem_data); msm_audio_mem_unreg_chrdev(mem_data); return 0; } @@ -972,3 +1598,4 @@ void q6apm_audio_mem_exit(void) MODULE_DESCRIPTION("Q6APM audio mem driver"); MODULE_LICENSE("GPL"); AR_MODULE_IMPORT_NS(DMA_BUF); +MODULE_IMPORT_NS("DMA_BUF_HEAP"); diff --git a/audioreach-driver/q6apm_audio_pkt.c b/audioreach-driver/q6apm_audio_pkt.c index 0f5274b..0a91305 100644 --- a/audioreach-driver/q6apm_audio_pkt.c +++ b/audioreach-driver/q6apm_audio_pkt.c @@ -17,11 +17,11 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include @@ -34,9 +34,10 @@ #define APM_CMD_CLOSE_ALL 0x01001013 #define APM_CMD_GET_SPF_STATE 0x01001021 #define APM_CMD_RSP_GET_SPF_STATE 0x02001007 -#define APM_CMD_CLOSE_ALL 0x01001013 +#define APM_CMD_GLOBAL_SHARED_MEM_MAP_REGIONS 0x01001059 #define APM_CMD_SHARED_MEM_MAP_REGIONS 0x0100100C -#define APM_MEMORY_MAP_BIT_MASK_IS_OFFSET_MODE 0x00000004UL +#define APM_CMD_SHARED_SATELLITE_MEM_MAP_REGIONS 0x01001026 +#define APM_MEMORY_MAP_BIT_MASK_PHYS_ADDRESS 0x000001C1UL /* Define Logging Macros */ static int audio_pkt_debug_mask; @@ -59,6 +60,7 @@ do { \ #define MODULE_NAME "audio-pkt" #define MINOR_NUMBER_COUNT 1 #define AUDPKT_DRIVER_NAME "aud_pasthru_adsp" +#define AUDPKT_MODEM_DRIVER_NAME "aud_pasthru_modem" struct q6apm_audio_pkt { struct device *dev; @@ -105,6 +107,29 @@ struct audio_gpr_pkt { struct audio_pkt_apm_mem_map audpkt_mem_map; }; +struct audio_gpr_pkt_glb_shm { + struct gpr_hdr audpkt_hdr; + struct { + uint32_t shmem_id; + uint16_t mem_pool_id; + uint16_t num_regions; + uint32_t property_flag; + } mmap_header; + struct audio_pkt_apm_shared_map_region_payload_t mmap_payload; +}; + +struct audio_satellite_gpr_pkt { + struct gpr_hdr audpkt_hdr; + struct { + uint32_t master_mem_handle; + uint32_t satellite_proc_domain_id; + uint16_t mem_pool_id; + uint16_t num_regions; + uint32_t property_flag; + } mmap_header; + struct audio_pkt_apm_shared_map_region_payload_t mmap_payload; +}; + typedef void (*audio_pkt_clnt_cb_fn)(void *buf, int len, void *priv); struct audio_pkt_clnt_ch { @@ -180,8 +205,10 @@ static int q6apm_audio_send_cmd(struct q6apm_audio_pkt *apm, struct gpr_pkt *pkt NULL, &apm->readq, pkt, rsp_opcode); } -static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) +static void *__q6apm_audio_alloc_pkt(gpr_device_t *gdev, int payload_size, + uint32_t opcode, uint32_t token, + uint32_t src_port, uint32_t dest_port, + bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -201,7 +228,7 @@ static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt->hdr.dest_domain = audioreach_gpr_dest_domain(gdev); pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -217,9 +244,12 @@ static void *__q6apm_audio_alloc_pkt(int payload_size, uint32_t opcode, uint32_t return pkt; } -static void *q6apm_audio_alloc_apm_cmd_pkt(int pkt_size, uint32_t opcode, uint32_t token) +static void *q6apm_audio_alloc_apm_cmd_pkt(struct q6apm_audio_pkt *apm, + int pkt_size, uint32_t opcode, + uint32_t token) { - return __q6apm_audio_alloc_pkt(pkt_size, opcode, token, GPR_APM_MODULE_IID, + return __q6apm_audio_alloc_pkt(apm ? apm->adev : NULL, pkt_size, + opcode, token, GPR_APM_MODULE_IID, APM_MODULE_INSTANCE_ID, true); } @@ -227,7 +257,7 @@ static int q6apm_audio_get_apm_state(struct q6apm_audio_pkt *apm) { struct gpr_pkt *pkt; - pkt = q6apm_audio_alloc_apm_cmd_pkt(0, APM_CMD_GET_SPF_STATE, 0); + pkt = q6apm_audio_alloc_apm_cmd_pkt(apm, 0, APM_CMD_GET_SPF_STATE, 0); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -250,7 +280,7 @@ static void q6apm_audio_close_all(void) { struct gpr_pkt *pkt; - pkt = q6apm_audio_alloc_apm_cmd_pkt(0, APM_CMD_CLOSE_ALL, 0); + pkt = q6apm_audio_alloc_apm_cmd_pkt(g_apm, 0, APM_CMD_CLOSE_ALL, 0); if (IS_ERR(pkt)) return; @@ -361,33 +391,85 @@ static ssize_t audio_pkt_read(struct file *file, char __user *buf, } /** - * audpkt_update_physical_addr - Update physical address - * audpkt_hdr: Pointer to the file structure. + * audpkt_chk_and_update_physical_addr - translate fd to physical address + * in a GPR memory-map packet payload. + * + * All APM_CMD_*_MEM_MAP_REGIONS opcodes share the same + * audio_pkt_apm_shared_map_region_payload_t layout at the end of their + * packet body. When the PHYS_ADDRESS flag is not set the shm_addr_lsw + * field carries a DMA-BUF fd that must be resolved to a physical address + * before forwarding to the DSP. */ -static int audpkt_chk_and_update_physical_addr(struct audio_gpr_pkt *gpr_pkt) +static int audpkt_chk_and_update_physical_addr( + struct audio_pkt_apm_shared_map_region_payload_t *payload, + uint32_t property_flag) { - size_t pa_len = 0; dma_addr_t paddr = 0; - int ret = 0; - - if (gpr_pkt->audpkt_mem_map.mmap_header.property_flag & - APM_MEMORY_MAP_BIT_MASK_IS_OFFSET_MODE) { - - /* TODO: move physical address mapping to use DMA-BUF heaps */ - ret = msm_audio_get_phy_addr( - (int) gpr_pkt->audpkt_mem_map.mmap_payload.shm_addr_lsw, - &paddr, &pa_len); - if (ret < 0) { - AUDIO_PKT_ERR("%s Get phy. address failed, ret %d\n", - __func__, ret); - return ret; - } + size_t pa_len = 0; + int ret; - AUDIO_PKT_INFO("%s physical address %pK", __func__, - (void *) paddr); - gpr_pkt->audpkt_mem_map.mmap_payload.shm_addr_lsw = (uint32_t) paddr; - gpr_pkt->audpkt_mem_map.mmap_payload.shm_addr_msw = (uint64_t) paddr >> 32; + if (property_flag & APM_MEMORY_MAP_BIT_MASK_PHYS_ADDRESS) + return 0; + + /* TODO: move physical address mapping to use DMA-BUF heaps */ + ret = msm_audio_get_phy_addr((int)payload->shm_addr_lsw, &paddr, &pa_len); + if (ret < 0) { + AUDIO_PKT_ERR("%s Get phy. address failed, ret %d\n", __func__, ret); + return ret; } + + AUDIO_PKT_INFO("%s physical address %pK", __func__, (void *)paddr); + payload->shm_addr_lsw = (uint32_t)paddr; + payload->shm_addr_msw = (uint64_t)paddr >> 32; + return 0; +} + +static int audpkt_update_mem_map_packet(struct gpr_hdr *audpkt_hdr, + void *kbuf, size_t count) +{ + size_t pkt_size; + struct audio_pkt_apm_shared_map_region_payload_t *payload; + uint32_t property_flag; + int ret; + + switch (audpkt_hdr->opcode) { + case APM_CMD_SHARED_MEM_MAP_REGIONS: { + struct audio_gpr_pkt *pkt = kbuf; + + pkt_size = sizeof(*pkt); + payload = &pkt->audpkt_mem_map.mmap_payload; + property_flag = pkt->audpkt_mem_map.mmap_header.property_flag; + break; + } + case APM_CMD_GLOBAL_SHARED_MEM_MAP_REGIONS: { + struct audio_gpr_pkt_glb_shm *pkt = kbuf; + + pkt_size = sizeof(*pkt); + payload = &pkt->mmap_payload; + property_flag = pkt->mmap_header.property_flag; + break; + } + case APM_CMD_SHARED_SATELLITE_MEM_MAP_REGIONS: { + struct audio_satellite_gpr_pkt *pkt = kbuf; + + pkt_size = sizeof(*pkt); + payload = &pkt->mmap_payload; + property_flag = pkt->mmap_header.property_flag; + break; + } + default: + return 0; + } + + if (count < pkt_size) { + AUDIO_PKT_ERR("Invalid count %zu\n", count); + return -EINVAL; + } + + ret = audpkt_chk_and_update_physical_addr(payload, property_flag); + if (ret < 0) + AUDIO_PKT_ERR("Update Physical Address Failed -%d\n", ret); + return ret; } @@ -421,14 +503,9 @@ static ssize_t audio_pkt_write(struct file *file, const char __user *buf, return PTR_ERR(kbuf); audpkt_hdr = (struct gpr_hdr *) kbuf; - if (audpkt_hdr->opcode == APM_CMD_SHARED_MEM_MAP_REGIONS) { - ret = audpkt_chk_and_update_physical_addr((struct audio_gpr_pkt *) audpkt_hdr); - if (ret < 0) { - AUDIO_PKT_ERR("Update Physical Address Failed -%d\n", ret); - kfree(kbuf); - return ret; - } - } + ret = audpkt_update_mem_map_packet(audpkt_hdr, kbuf, count); + if (ret < 0) + goto free_kbuf; audpkt_port_map = kmalloc(sizeof(*audpkt_port_map), GFP_KERNEL); if (!audpkt_port_map) { @@ -517,25 +594,51 @@ static const struct file_operations audio_pkt_fops = { .poll = audio_pkt_poll, }; +static const char *q6apm_audio_pkt_driver_name(struct device *dev) +{ + struct device_node *node = of_node_get(dev->of_node); + const char *channel; + + while (node) { + struct device_node *parent; + + if (!of_property_read_string(node, "qcom,glink-channels", &channel)) { + of_node_put(node); + if (!strcmp(channel, "modem_apps")) + return AUDPKT_MODEM_DRIVER_NAME; + + return AUDPKT_DRIVER_NAME; + } + + parent = of_get_parent(node); + of_node_put(node); + node = parent; + } + + return AUDPKT_DRIVER_NAME; +} + static int q6apm_audio_pkt_probe(gpr_device_t *adev) { struct device *dev = &adev->dev; struct q6apm_audio_pkt *apm; + const char *driver_name; int ret; apm = devm_kzalloc(dev, sizeof(*apm), GFP_KERNEL); if (!apm) return -ENOMEM; + driver_name = q6apm_audio_pkt_driver_name(dev); ret = alloc_chrdev_region(&apm->audio_pkt_major, 0, - MINOR_NUMBER_COUNT, AUDPKT_DRIVER_NAME); + MINOR_NUMBER_COUNT, driver_name); if (ret < 0) { pr_err("alloc_chrdev_region failed ret:%d\n", ret); goto err_chrdev; } - apm->audio_pkt_class = class_create(AUDPKT_DRIVER_NAME); + apm->audio_pkt_class = class_create(driver_name); if (IS_ERR(apm->audio_pkt_class)) { ret = PTR_ERR(apm->audio_pkt_class); pr_err("class_create failed ret:%ld\n", @@ -545,7 +648,7 @@ static int q6apm_audio_pkt_probe(gpr_device_t *adev) apm->dev = device_create(apm->audio_pkt_class, NULL, apm->audio_pkt_major, NULL, - AUDPKT_DRIVER_NAME); + driver_name); if (IS_ERR(apm->dev)) { ret = PTR_ERR(apm->dev); pr_err("device_create failed ret:%ld\n", @@ -553,7 +656,7 @@ static int q6apm_audio_pkt_probe(gpr_device_t *adev) goto err_device; } - dev_set_name(apm->dev, AUDPKT_DRIVER_NAME); + dev_set_name(apm->dev, driver_name); dev_set_drvdata(dev, apm); @@ -622,8 +725,8 @@ static int q6apm_audio_pkt_callback_core(const struct gpr_resp_pkt *data, void * return -ENODEV; } - hdr_size = hdr->hdr_size * 4; - pkt_size = hdr->pkt_size; + hdr_size = hdr->hdr_size * 4; + pkt_size = hdr->pkt_size; mutex_lock(&apm->audpkt_port_lock); audpkt_port_map = idr_find(&apm->audpkt_port_idr, hdr->token); @@ -653,14 +756,14 @@ static int q6apm_audio_pkt_callback_core(const struct gpr_resp_pkt *data, void * out_hdr->src_port = new_src_port; } - spin_lock_irqsave(&apm->queue_lock, flags); - skb_queue_tail(&apm->queue, skb); - spin_unlock_irqrestore(&apm->queue_lock, flags); + spin_lock_irqsave(&apm->queue_lock, flags); + skb_queue_tail(&apm->queue, skb); + spin_unlock_irqrestore(&apm->queue_lock, flags); /* wake up any blocking processes, waiting for new data */ wake_up_interruptible(&apm->readq); - if(hdr->opcode == APM_CMD_RSP_GET_SPF_STATE) { + if (hdr->opcode == APM_CMD_RSP_GET_SPF_STATE) { result = data->payload; apm->result.opcode = hdr->opcode; apm->result.status = 0; diff --git a/audioreach-driver/q6apm_lpass_dummy_dais.c b/audioreach-driver/q6apm_lpass_dummy_dais.c index 44c34f9..6dfb62d 100644 --- a/audioreach-driver/q6apm_lpass_dummy_dais.c +++ b/audioreach-driver/q6apm_lpass_dummy_dais.c @@ -761,6 +761,37 @@ static int q6i2s_set_sysclk(struct snd_soc_dai *dai, int clk_id, unsigned int fr return ret; } +static int q6apm_lpass_dai_get_clk(struct device *dev, struct device_node *np, + const char *name, struct clk **clk) +{ + *clk = devm_get_clk_from_child(dev, np, name); + if (IS_ERR(*clk)) { + if (PTR_ERR(*clk) == -EPROBE_DEFER) + return dev_err_probe(dev, PTR_ERR(*clk), + "unable to get %s\n", name); + + *clk = NULL; + } + + return 0; +} + +static int q6apm_lpass_dai_get_clks(struct device *dev, struct device_node *np, + struct q6apm_dai_priv_data *priv) +{ + int ret; + + ret = q6apm_lpass_dai_get_clk(dev, np, "mclk", &priv->mclk); + if (ret) + return ret; + + ret = q6apm_lpass_dai_get_clk(dev, np, "bclk", &priv->bclk); + if (ret) + return ret; + + return q6apm_lpass_dai_get_clk(dev, np, "eclk", &priv->eclk); +} + static const struct snd_soc_dai_ops q6dummy_ops = { .startup = q6apm_lpass_dai_startup, }; @@ -773,6 +804,8 @@ static const struct snd_soc_dai_ops q6i2sdummy_ops = { static const struct snd_soc_dai_ops q6tdmdummy_ops = { .startup = q6apm_lpass_dai_startup, + .shutdown = q6i2s_lpass_dai_shutdown, + .set_sysclk = q6i2s_set_sysclk, }; static const struct snd_soc_component_driver q6apm_lpass_dummy_dai_component = { @@ -798,47 +831,14 @@ static int of_q6apm_parse_dai_data(struct device *dev, } switch (id) { - /* MI2S specific properties */ + /* MI2S and TDM specific properties */ case PRIMARY_MI2S_RX ... QUATERNARY_MI2S_TX: case QUINARY_MI2S_RX ... QUINARY_MI2S_TX: + case PRIMARY_TDM_RX_0 ... QUINARY_TDM_TX_7: priv = &data->priv[id]; - priv->mclk = of_clk_get_by_name(node, "mclk"); - if (IS_ERR(priv->mclk)) { - if (PTR_ERR(priv->mclk) == -EPROBE_DEFER) - return dev_err_probe(dev, PTR_ERR(priv->mclk), - "unable to get mi2s mclk\n"); - priv->mclk = NULL; - } - - priv->bclk = of_clk_get_by_name(node, "bclk"); - if (IS_ERR(priv->bclk)) { - if (PTR_ERR(priv->bclk) == -EPROBE_DEFER) { - if (priv->mclk) { - clk_put(priv->mclk); - priv->mclk = NULL; - } - return dev_err_probe(dev, PTR_ERR(priv->bclk), - "unable to get mi2s bclk\n"); - } - priv->bclk = NULL; - } - - priv->eclk = of_clk_get_by_name(node, "eclk"); - if (IS_ERR(priv->eclk)) { - if (PTR_ERR(priv->eclk) == -EPROBE_DEFER) { - if (priv->mclk) { - clk_put(priv->mclk); - priv->mclk = NULL; - } - if (priv->bclk) { - clk_put(priv->bclk); - priv->bclk = NULL; - } - return dev_err_probe(dev, PTR_ERR(priv->eclk), - "unable to get mi2s eclk\n"); - } - priv->eclk = NULL; - } + ret = q6apm_lpass_dai_get_clks(dev, node, priv); + if (ret) + return ret; break; default: break; diff --git a/audioreach-driver/q6prm_audioreach.c b/audioreach-driver/q6prm_audioreach.c index d06326e..e179597 100644 --- a/audioreach-driver/q6prm_audioreach.c +++ b/audioreach-driver/q6prm_audioreach.c @@ -105,8 +105,10 @@ static int q6prm_audioreach_send_cmd_sync(struct q6prm *prm, struct gpr_pkt *pkt NULL, &prm->wait, pkt, rsp_opcode); } -static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uint32_t token, - uint32_t src_port, uint32_t dest_port, bool has_cmd_hdr) +static void *__q6prm_audioreach_alloc_pkt(gpr_device_t *gdev, int payload_size, + uint32_t opcode, uint32_t token, + uint32_t src_port, uint32_t dest_port, + bool has_cmd_hdr) { struct gpr_pkt *pkt; void *p; @@ -126,7 +128,7 @@ static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uin pkt->hdr.dest_port = dest_port; pkt->hdr.src_port = src_port; - pkt->hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt->hdr.dest_domain = audioreach_gpr_dest_domain(gdev); pkt->hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt->hdr.token = token; pkt->hdr.opcode = opcode; @@ -142,10 +144,12 @@ static void *__q6prm_audioreach_alloc_pkt(int payload_size, uint32_t opcode, uin return pkt; } -static void *q6prm_audioreach_alloc_cmd_pkt(int payload_size, uint32_t opcode, uint32_t token, +static void *q6prm_audioreach_alloc_cmd_pkt(gpr_device_t *gdev, int payload_size, + uint32_t opcode, uint32_t token, uint32_t src_port, uint32_t dest_port) { - return __q6prm_audioreach_alloc_pkt(payload_size, opcode, token, src_port, dest_port, true); + return __q6prm_audioreach_alloc_pkt(gdev, payload_size, opcode, token, + src_port, dest_port, true); } static int q6prm_audioreach_set_hw_core_req(struct device *dev, uint32_t hw_block_id, bool enable) @@ -166,7 +170,8 @@ static int q6prm_audioreach_set_hw_core_req(struct device *dev, uint32_t hw_bloc rsp_opcode = PRM_CMD_RSP_RELEASE_HW_RSC; } - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*req), opcode, 0, gdev->svc.id, GPR_PRM_MODULE_IID); + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*req), opcode, 0, + gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -214,8 +219,9 @@ static int q6prm_audioreach_request_lpass_clock(struct device *dev, int clk_id, struct gpr_pkt *pkt; int rc; - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*req), PRM_CMD_REQUEST_HW_RSC, 0, gdev->svc.id, - GPR_PRM_MODULE_IID); + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*req), + PRM_CMD_REQUEST_HW_RSC, 0, + gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -251,8 +257,9 @@ static int q6prm_audioreach_release_lpass_clock(struct device *dev, int clk_id, struct gpr_pkt *pkt; int rc; - pkt = q6prm_audioreach_alloc_cmd_pkt(sizeof(*rel), PRM_CMD_RELEASE_HW_RSC, 0, gdev->svc.id, - GPR_PRM_MODULE_IID); + pkt = q6prm_audioreach_alloc_cmd_pkt(gdev, sizeof(*rel), + PRM_CMD_RELEASE_HW_RSC, 0, + gdev->svc.id, GPR_PRM_MODULE_IID); if (IS_ERR(pkt)) return PTR_ERR(pkt); @@ -330,10 +337,8 @@ static int prm_audioreach_probe(gpr_device_t *gdev) init_waitqueue_head(&cc->wait); dev_set_drvdata(dev, cc); - if (!q6apm_audio_is_adsp_ready()) { - pr_err("DEBUG:%s:%d: failed\n",__func__,__LINE__); + if (!q6apm_audio_is_adsp_ready()) return -EPROBE_DEFER; - } return devm_of_platform_populate(dev); } diff --git a/audioreach-driver/q6prm_audioreach.h b/audioreach-driver/q6prm_audioreach.h index 4917abb..61148a6 100644 --- a/audioreach-driver/q6prm_audioreach.h +++ b/audioreach-driver/q6prm_audioreach.h @@ -4,7 +4,9 @@ #ifndef __Q6PRM_AUDIOREACH_H__ #define __Q6PRM_AUDIOREACH_H__ +#include #include +#include #define LPAIF_MI2S_MCLK 1 #define LPAIF_MI2S_BCLK 2 @@ -101,6 +103,66 @@ /* Clock ID for RX CORE MCLK2 2X MCLK */ #define Q6PRM_LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK 0x318 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_IBIT 0x500 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF0_EBIT 0x501 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_IBIT 0x502 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF1_EBIT 0x503 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_IBIT 0x504 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF2_EBIT 0x505 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_IBIT 0x506 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF3_EBIT 0x507 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_IBIT 0x508 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF4_EBIT 0x509 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_IBIT 0x50A +#define Q6PRM_LPASS_CLK_ID_AUD_INTF5_EBIT 0x50B +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_IBIT 0x50C +#define Q6PRM_LPASS_CLK_ID_AUD_INTF6_EBIT 0x50D +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_IBIT 0x50E +#define Q6PRM_LPASS_CLK_ID_AUD_INTF7_EBIT 0x50F +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_IBIT 0x510 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF8_EBIT 0x511 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_IBIT 0x512 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF9_EBIT 0x513 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_IBIT 0x514 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF10_EBIT 0x515 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_IBIT 0x516 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF11_EBIT 0x517 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_IBIT 0x518 +#define Q6PRM_LPASS_CLK_ID_AUD_INTF12_EBIT 0x519 +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_IBIT 0x550 +#define Q6PRM_LPASS_CLK_ID_AUD_VA_INTF0_EBIT 0x551 + +#ifndef LPASS_CLK_ID_AUD_INTF0_IBIT +#define LPASS_CLK_ID_AUD_INTF0_IBIT 71 +#define LPASS_CLK_ID_AUD_INTF0_EBIT 72 +#define LPASS_CLK_ID_AUD_INTF1_IBIT 73 +#define LPASS_CLK_ID_AUD_INTF1_EBIT 74 +#define LPASS_CLK_ID_AUD_INTF2_IBIT 75 +#define LPASS_CLK_ID_AUD_INTF2_EBIT 76 +#define LPASS_CLK_ID_AUD_INTF3_IBIT 77 +#define LPASS_CLK_ID_AUD_INTF3_EBIT 78 +#define LPASS_CLK_ID_AUD_INTF4_IBIT 79 +#define LPASS_CLK_ID_AUD_INTF4_EBIT 80 +#define LPASS_CLK_ID_AUD_INTF5_IBIT 81 +#define LPASS_CLK_ID_AUD_INTF5_EBIT 82 +#define LPASS_CLK_ID_AUD_INTF6_IBIT 83 +#define LPASS_CLK_ID_AUD_INTF6_EBIT 84 +#define LPASS_CLK_ID_AUD_INTF7_IBIT 85 +#define LPASS_CLK_ID_AUD_INTF7_EBIT 86 +#define LPASS_CLK_ID_AUD_INTF8_IBIT 87 +#define LPASS_CLK_ID_AUD_INTF8_EBIT 88 +#define LPASS_CLK_ID_AUD_INTF9_IBIT 89 +#define LPASS_CLK_ID_AUD_INTF9_EBIT 90 +#define LPASS_CLK_ID_AUD_INTF10_IBIT 91 +#define LPASS_CLK_ID_AUD_INTF10_EBIT 92 +#define LPASS_CLK_ID_AUD_INTF11_IBIT 93 +#define LPASS_CLK_ID_AUD_INTF11_EBIT 94 +#define LPASS_CLK_ID_AUD_INTF12_IBIT 95 +#define LPASS_CLK_ID_AUD_INTF12_EBIT 96 +#define LPASS_CLK_ID_AUD_VA_INTF0_IBIT 97 +#define LPASS_CLK_ID_AUD_VA_INTF0_EBIT 98 +#endif + #define Q6PRM_LPASS_CLK_SRC_INTERNAL 1 #define Q6PRM_LPASS_CLK_ROOT_DEFAULT 0 #define Q6PRM_HW_CORE_ID_LPASS 1 @@ -135,6 +197,11 @@ struct q6dsp_clk_desc { int (*lpass_unvote_clk)(struct device *dev, uint32_t hid, uint32_t h); }; +static inline u16 audioreach_gpr_dest_domain(gpr_device_t *gdev) +{ + return gdev && gdev->domain_id ? gdev->domain_id : GPR_DOMAIN_ID_ADSP; +} + int q6dsp_clock_dev_probe(struct platform_device *pdev); int q6prm_audioreach_set_lpass_clock(struct device *dev, int clk_id, int clk_attr, diff --git a/audioreach-driver/q6prm_audioreach_clock.c b/audioreach-driver/q6prm_audioreach_clock.c index 1ac5e01..87e60bb 100644 --- a/audioreach-driver/q6prm_audioreach_clock.c +++ b/audioreach-driver/q6prm_audioreach_clock.c @@ -65,6 +65,34 @@ static const struct q6dsp_clk_init q6prm_clks[] = { Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_MCLK), Q6PRM_CLK(LPASS_CLK_ID_WSA2_CORE_TX_2X_MCLK), Q6PRM_CLK(LPASS_CLK_ID_RX_CORE_MCLK2_2X_MCLK), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF0_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF1_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF2_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF3_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF4_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF5_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF6_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF7_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF8_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF9_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF10_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF11_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_INTF12_EBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_IBIT), + Q6PRM_CLK(LPASS_CLK_ID_AUD_VA_INTF0_EBIT), Q6DSP_VOTE_CLK(LPASS_HW_MACRO_VOTE, Q6PRM_HW_CORE_ID_LPASS, "LPASS_HW_MACRO"), Q6DSP_VOTE_CLK(LPASS_HW_DCODEC_VOTE, Q6PRM_HW_CORE_ID_DCODEC, diff --git a/dsp/spf-core.c b/dsp/spf-core.c index 28ad3c1..4be2558 100644 --- a/dsp/spf-core.c +++ b/dsp/spf-core.c @@ -12,6 +12,7 @@ #include #include #include +#include "../audioreach-driver/q6prm_audioreach.h" #define APM_STATE_READY_TIMEOUT_MS 10000 #define Q6_READY_TIMEOUT_MS 1000 @@ -37,6 +38,7 @@ struct spf_core_private { }; static struct spf_core_private *spf_core_priv; + struct apm_cmd_rsp_get_spf_status_t { @@ -93,7 +95,7 @@ static bool __spf_core_is_apm_ready(struct spf_core *core) pkt.hdr.opcode = APM_CMD_GET_SPF_STATE; pkt.hdr.dest_port = APM_MODULE_INSTANCE_ID; pkt.hdr.src_port = adev->svc_id; //1 - pkt.hdr.dest_domain = GPR_DOMAIN_ID_ADSP; + pkt.hdr.dest_domain = audioreach_gpr_dest_domain(adev); pkt.hdr.src_domain = GPR_DOMAIN_ID_APPS; pkt.hdr.opcode = APM_CMD_GET_SPF_STATE;