// SPDX-License-Identifier: GPL-2.0 // // Copyright (C) 2018 MediaTek Inc. #include "mtk-scp-ultra-common.h" #include "mtk-base-scp-ultra.h" #include #include #include //#include "audio_ultra_msg_id.h" #include "ultra_ipi.h" #include "mtk-base-afe.h" #include "mtk-scp-ultra.h" #include "mtk-afe-external.h" #define AFE_AGENT_SET_OFFSET 4 #define AFE_AGENT_CLR_OFFSET 8 /* don't use this directly if not necessary */ static struct mtk_base_afe *local_scp_ultra_afe; static void *ipi_recv_private; int ultra_set_dsp_afe(struct mtk_base_afe *afe) { if (!afe) { pr_err("%s(), afe is NULL", __func__); return -1; } local_scp_ultra_afe = afe; return 0; } EXPORT_SYMBOL_GPL(ultra_set_dsp_afe); struct mtk_base_afe *get_afe_base(void) { if (!local_scp_ultra_afe) pr_err("%s(), local_scp_ultra_afe is NULL", __func__); return local_scp_ultra_afe; } void set_ipi_recv_private(void *priv) { pr_debug("%s\n", __func__); if (priv != NULL) ipi_recv_private = priv; else pr_debug("%s ipi_recv_private has been set\n", __func__); } void *ultra_get_ipi_recv_private(void) { if (!ipi_recv_private) pr_info("%s(), ipi_recv_private is NULL", __func__); return ipi_recv_private; } void ultra_set_ipi_recv_private(void *priv) { pr_debug("%s()\n", __func__); if (!ipi_recv_private) ipi_recv_private = priv; else pr_info("%s() has been set\n", __func__); } void set_afe_dl_irq_target(int scp_enable) { struct mtk_base_afe *afe = get_afe_base(); struct mtk_base_scp_ultra *scp_ultra = get_scp_ultra_base(); struct mtk_base_afe_memif *memif = &afe->memif[scp_ultra->ultra_mem.ultra_dl_memif_id]; struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage]; const struct mtk_base_irq_data *irq_data = irqs->irq_data; if (scp_enable) { regmap_update_bits(afe->regmap, irq_data->irq_ap_en_reg, 0x1 << irq_data->irq_ap_en_shift, 0x0); regmap_update_bits(afe->regmap, irq_data->irq_scp_en_reg, 0x1 << irq_data->irq_scp_en_shift, 0x1 << irq_data->irq_scp_en_shift); } else { regmap_update_bits(afe->regmap, irq_data->irq_scp_en_reg, 0x1 << irq_data->irq_scp_en_shift, 0); regmap_update_bits(afe->regmap, irq_data->irq_ap_en_reg, 0x1 << irq_data->irq_ap_en_shift, 0x1 << irq_data->irq_ap_en_shift); } pr_debug("%s(), scp_en=%d,memif=%d,ap_en_reg:0x%x,scp_en_reg:0x%x\n", __func__, scp_enable, scp_ultra->ultra_mem.ultra_dl_memif_id, irq_data->irq_ap_en_reg, irq_data->irq_scp_en_reg); } void set_afe_ul_irq_target(int scp_enable) { struct mtk_base_afe *afe = get_afe_base(); struct mtk_base_scp_ultra *scp_ultra = get_scp_ultra_base(); struct mtk_base_afe_memif *memif = &afe->memif[scp_ultra->ultra_mem.ultra_ul_memif_id]; struct mtk_base_afe_irq *irqs = &afe->irqs[memif->irq_usage]; const struct mtk_base_irq_data *irq_data = irqs->irq_data; if (scp_enable) { regmap_update_bits(afe->regmap, irq_data->irq_ap_en_reg, 0x1 << irq_data->irq_ap_en_shift, 0x0); regmap_update_bits(afe->regmap, irq_data->irq_scp_en_reg, 0x1 << irq_data->irq_scp_en_shift, 0x1 << irq_data->irq_scp_en_shift); } else { regmap_update_bits(afe->regmap, irq_data->irq_scp_en_reg, 0x1 << irq_data->irq_scp_en_shift, 0); regmap_update_bits(afe->regmap, irq_data->irq_ap_en_reg, 0x1 << irq_data->irq_ap_en_shift, 0x1 << irq_data->irq_ap_en_shift); } pr_debug("%s(),scp_en=%d,memif=%d,ap_en_reg:0x%x,scp_en_reg:0x%x\n", __func__, scp_enable, scp_ultra->ultra_mem.ultra_ul_memif_id, irq_data->irq_ap_en_reg, irq_data->irq_scp_en_reg); } int ultra_memif_set_enable(struct mtk_base_afe *afe, int afe_id) { struct mtk_base_afe_memif *memif = &afe->memif[afe_id]; int reg = 0; if (memif->data->enable_shift < 0) { pr_info("%s(), error, id %d, enable_shift < 0\n", __func__, afe_id); return 0; } if (memif->data->enable_reg < 0) { pr_info("%s(), error, id %d, enable_reg < 0\n", __func__, afe_id); return 0; } if (afe->is_memif_bit_banding) reg = memif->data->enable_reg + AFE_AGENT_SET_OFFSET; else reg = memif->data->enable_reg; return regmap_update_bits(afe->regmap, reg, 1 << memif->data->enable_shift, 1 << memif->data->enable_shift); } int ultra_memif_set_disable(struct mtk_base_afe *afe, int afe_id) { struct mtk_base_afe_memif *memif = &afe->memif[afe_id]; int reg = 0; int val = 0; if (memif->data->enable_shift < 0) { pr_info("%s(), error, id %d, enable_shift < 0\n", __func__, afe_id); return 0; } if (memif->data->enable_reg < 0) { pr_info("%s(), error, id %d, enable_reg < 0\n", __func__, afe_id); return 0; } if (afe->is_memif_bit_banding) { reg = memif->data->enable_reg + AFE_AGENT_CLR_OFFSET; val = 1; } else { reg = memif->data->enable_reg; val = 0; } return regmap_update_bits(afe->regmap, reg, 1 << memif->data->enable_shift, val << memif->data->enable_shift); } int ultra_memif_set_enable_hw_sema(struct mtk_base_afe *afe, int afe_id) { int ret = 0; int scp_sem_ret = NOTIFY_STOP; if (!afe) return -EPERM; if (!afe->is_scp_sema_support) return ultra_memif_set_enable(afe, afe_id); if (afe->is_memif_bit_banding == 0) { scp_sem_ret = notify_3way_semaphore_control( NOTIFIER_SCP_3WAY_SEMAPHORE_GET, NULL); if (scp_sem_ret != NOTIFY_STOP) { pr_info("%s error, adsp_sem_ret[%d]\n", __func__, ret); return -EBUSY; } } ret = ultra_memif_set_enable(afe, afe_id); if (afe->is_memif_bit_banding == 0) { notify_3way_semaphore_control( NOTIFIER_SCP_3WAY_SEMAPHORE_RELEASE, NULL); } return ret; } int ultra_memif_set_disable_hw_sema(struct mtk_base_afe *afe, int afe_id) { int ret = 0; int scp_sem_ret = NOTIFY_STOP; if (!afe) return -EPERM; if (!afe->is_scp_sema_support) return ultra_memif_set_disable(afe, afe_id); if (afe->is_memif_bit_banding == 0) { scp_sem_ret = notify_3way_semaphore_control( NOTIFIER_SCP_3WAY_SEMAPHORE_GET, NULL); if (scp_sem_ret != NOTIFY_STOP) { pr_info("%s error, adsp_sem_ret[%d]\n", __func__, ret); return -EBUSY; } } ret = ultra_memif_set_disable(afe, afe_id); if (afe->is_memif_bit_banding == 0) { notify_3way_semaphore_control( NOTIFIER_SCP_3WAY_SEMAPHORE_RELEASE, NULL); } return ret; } int ultra_irq_set_enable_hw_sema(struct mtk_base_afe *afe, const struct mtk_base_irq_data *irq_data, int afe_id) { int ret = 0; int scp_sem_ret = NOTIFY_STOP; if (!afe) return -ENODEV; if (!irq_data) return -ENODEV; if (!afe->is_scp_sema_support) return regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 1 << irq_data->irq_en_shift, 1 << irq_data->irq_en_shift); scp_sem_ret = notify_3way_semaphore_control(NOTIFIER_SCP_3WAY_SEMAPHORE_GET, NULL); if (scp_sem_ret != NOTIFY_STOP) { pr_info("%s error, scp_sem_ret[%d]\n", __func__, scp_sem_ret); return -EBUSY; } regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 1 << irq_data->irq_en_shift, 1 << irq_data->irq_en_shift); notify_3way_semaphore_control(NOTIFIER_SCP_3WAY_SEMAPHORE_RELEASE, NULL); return ret; } int ultra_irq_set_disable_hw_sema(struct mtk_base_afe *afe, const struct mtk_base_irq_data *irq_data, int afe_id) { int ret = 0; int scp_sem_ret = NOTIFY_STOP; if (!afe) return -ENODEV; if (!irq_data) return -ENODEV; if (!afe->is_scp_sema_support) return regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 1 << irq_data->irq_en_shift, 0 << irq_data->irq_en_shift); scp_sem_ret = notify_3way_semaphore_control(NOTIFIER_SCP_3WAY_SEMAPHORE_GET, NULL); if (scp_sem_ret != NOTIFY_STOP) { pr_info("%s error, scp_sem_ret[%d]\n", __func__, scp_sem_ret); return -EBUSY; } regmap_update_bits(afe->regmap, irq_data->irq_en_reg, 1 << irq_data->irq_en_shift, 0 << irq_data->irq_en_shift); notify_3way_semaphore_control(NOTIFIER_SCP_3WAY_SEMAPHORE_RELEASE, NULL); return ret; }