gecko compliant drivers
Change-Id: I5f19da1472a0e90cc5d16459b5367dc07ec2f28b Signed-off-by: Taha Azzaoui <tazzaoui@codeaurora.org>
This commit is contained in:

committed by
Phani Kumar Uppalapati

parent
5986527a1e
commit
6c8bf95ddf
61
dsp/Kbuild
61
dsp/Kbuild
@@ -108,36 +108,11 @@ COMMON_INC := -I$(AUDIO_ROOT)/$(COMMON_DIR)
|
|||||||
|
|
||||||
ifdef CONFIG_SND_SOC_MSM_QDSP6V2_INTF
|
ifdef CONFIG_SND_SOC_MSM_QDSP6V2_INTF
|
||||||
Q6_OBJS += msm-audio-event-notify.o
|
Q6_OBJS += msm-audio-event-notify.o
|
||||||
Q6_OBJS += audio_calibration.o
|
|
||||||
Q6_OBJS += audio_cal_utils.o
|
|
||||||
Q6_OBJS += q6adm.o
|
|
||||||
Q6_OBJS += q6afe.o
|
|
||||||
Q6_OBJS += q6asm.o
|
|
||||||
Q6_OBJS += q6audio-v2.o
|
|
||||||
Q6_OBJS += q6voice.o
|
|
||||||
Q6_OBJS += q6core.o
|
|
||||||
Q6_OBJS += q6common.o
|
|
||||||
Q6_OBJS += rtac.o
|
|
||||||
Q6_OBJS += q6lsm.o
|
|
||||||
Q6_OBJS += adsp_err.o
|
|
||||||
Q6_OBJS += msm_audio_ion.o
|
|
||||||
Q6_OBJS += q6_init.o
|
Q6_OBJS += q6_init.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_SND_SOC_MSM_QDSP6V2_VM
|
ifdef CONFIG_SND_SOC_MSM_QDSP6V2_VM
|
||||||
Q6_OBJS += msm-audio-event-notify.o
|
Q6_OBJS += msm-audio-event-notify.o
|
||||||
Q6_OBJS += audio_calibration.o
|
|
||||||
Q6_OBJS += audio_cal_utils.o
|
|
||||||
Q6_OBJS += q6adm.o
|
|
||||||
Q6_OBJS += q6afe.o
|
|
||||||
Q6_OBJS += q6asm.o
|
|
||||||
Q6_OBJS += q6audio-v2.o
|
|
||||||
Q6_OBJS += q6voice.o
|
|
||||||
Q6_OBJS += q6core.o
|
|
||||||
Q6_OBJS += q6common.o
|
|
||||||
Q6_OBJS += rtac.o
|
|
||||||
Q6_OBJS += q6lsm.o
|
|
||||||
Q6_OBJS += adsp_err.o
|
|
||||||
Q6_OBJS += msm_audio_ion_vm.o
|
Q6_OBJS += msm_audio_ion_vm.o
|
||||||
Q6_OBJS += q6_init.o
|
Q6_OBJS += q6_init.o
|
||||||
endif
|
endif
|
||||||
@@ -150,18 +125,6 @@ ifdef CONFIG_XT_LOGGING
|
|||||||
Q6_OBJS += sp_params.o
|
Q6_OBJS += sp_params.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_WCD9XXX_CODEC_CORE
|
|
||||||
Q6_OBJS += audio_slimslave.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_DTS_SRS_TM
|
|
||||||
Q6_OBJS += msm-dts-srs-tm-config.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_AFE_HWDEP
|
|
||||||
Q6_OBJS += q6afecal-hwdep.o
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifdef CONFIG_MSM_ADSP_LOADER
|
ifdef CONFIG_MSM_ADSP_LOADER
|
||||||
ADSP_LOADER_OBJS += adsp-loader.o
|
ADSP_LOADER_OBJS += adsp-loader.o
|
||||||
endif
|
endif
|
||||||
@@ -174,16 +137,16 @@ ifdef CONFIG_MSM_QDSP6_NOTIFIER
|
|||||||
QDSP6_NOTIFIER_OBJS += audio_notifier.o audio_ssr.o
|
QDSP6_NOTIFIER_OBJS += audio_notifier.o audio_ssr.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_MSM_ULTRASOUND
|
ifdef CONFIG_GECKO_CORE
|
||||||
USF_OBJS += usf.o usfcdev.o q6usm.o
|
GECKO_CORE_OBJS += gecko-core.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_MSM_MDF
|
ifdef CONFIG_AUDIO_PRM
|
||||||
Q6_OBJS += msm_mdf.o
|
AUDIO_PRM += audio_prm.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
ifdef CONFIG_VOICE_MHI
|
ifdef CONFIG_AUDIO_PKT_ION
|
||||||
Q6_OBJS += voice_mhi.o
|
AUDIO_PKT_ION += msm_audio_ion.o
|
||||||
endif
|
endif
|
||||||
|
|
||||||
LINUX_INC += -Iinclude/linux
|
LINUX_INC += -Iinclude/linux
|
||||||
@@ -244,17 +207,23 @@ q6_dlkm-y := $(Q6_OBJS)
|
|||||||
obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_VM) += q6_dlkm.o
|
obj-$(CONFIG_SND_SOC_MSM_QDSP6V2_VM) += q6_dlkm.o
|
||||||
q6_dlkm-y := $(Q6_OBJS)
|
q6_dlkm-y := $(Q6_OBJS)
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_ULTRASOUND) += usf_dlkm.o
|
|
||||||
usf_dlkm-y := $(USF_OBJS)
|
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp_loader_dlkm.o
|
obj-$(CONFIG_MSM_ADSP_LOADER) += adsp_loader_dlkm.o
|
||||||
adsp_loader_dlkm-y := $(ADSP_LOADER_OBJS)
|
adsp_loader_dlkm-y := $(ADSP_LOADER_OBJS)
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_QDSP6_PDR) += q6_pdr_dlkm.o
|
obj-$(CONFIG_MSM_QDSP6_PDR) += q6_pdr_dlkm.o
|
||||||
q6_pdr_dlkm-y := $(QDSP6_PDR_OBJS)
|
q6_pdr_dlkm-y := $(QDSP6_PDR_OBJS)
|
||||||
|
|
||||||
|
obj-$(CONFIG_GECKO_CORE) += gecko_core_dlkm.o
|
||||||
|
gecko_core_dlkm-y := $(GECKO_CORE_OBJS)
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += q6_notifier_dlkm.o
|
obj-$(CONFIG_MSM_QDSP6_NOTIFIER) += q6_notifier_dlkm.o
|
||||||
q6_notifier_dlkm-y := $(QDSP6_NOTIFIER_OBJS)
|
q6_notifier_dlkm-y := $(QDSP6_NOTIFIER_OBJS)
|
||||||
|
|
||||||
|
obj-$(CONFIG_AUDIO_PRM) += audio_prm_dlkm.o
|
||||||
|
audio_prm_dlkm-y := $(AUDIO_PRM)
|
||||||
|
|
||||||
|
obj-$(CONFIG_AUDIO_PKT_ION) += audpkt_ion_dlkm.o
|
||||||
|
audpkt_ion_dlkm-y := $(AUDIO_PKT_ION)
|
||||||
|
|
||||||
# inject some build related information
|
# inject some build related information
|
||||||
DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"
|
DEFINES += -DBUILD_TIMESTAMP=\"$(shell date -u +'%Y-%m-%dT%H:%M:%SZ')\"
|
||||||
|
331
dsp/audio_prm.c
Normal file
331
dsp/audio_prm.c
Normal file
@@ -0,0 +1,331 @@
|
|||||||
|
/* Copyright (c) 2019-2020, 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
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <ipc/gpr-lite.h>
|
||||||
|
#include <soc/snd_event.h>
|
||||||
|
#include <dsp/audio_prm.h>
|
||||||
|
|
||||||
|
#define TIMEOUT_MS 500
|
||||||
|
|
||||||
|
struct audio_prm {
|
||||||
|
struct gpr_device *adev;
|
||||||
|
wait_queue_head_t wait;
|
||||||
|
struct mutex lock;
|
||||||
|
bool resp_received;
|
||||||
|
atomic_t state;
|
||||||
|
atomic_t status;
|
||||||
|
bool is_adsp_up;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct audio_prm g_prm;
|
||||||
|
|
||||||
|
static int audio_prm_callback(struct gpr_device *adev, void *data)
|
||||||
|
{
|
||||||
|
struct gpr_hdr *hdr = (struct gpr_hdr *)data;
|
||||||
|
uint32_t *payload = GPR_PKT_GET_PAYLOAD(uint32_t, data);
|
||||||
|
|
||||||
|
dev_dbg(&adev->dev, "%s: Payload %x", __func__, hdr->opcode);
|
||||||
|
switch (hdr->opcode) {
|
||||||
|
case GPR_IBASIC_RSP_RESULT:
|
||||||
|
pr_err("%s: Failed response received",__func__);
|
||||||
|
atomic_set(&g_prm.status, payload[1]);
|
||||||
|
g_prm.resp_received = true;
|
||||||
|
break;
|
||||||
|
case PRM_CMD_RSP_REQUEST_HW_RSC:
|
||||||
|
case PRM_CMD_RSP_RELEASE_HW_RSC:
|
||||||
|
/* payload[1] contains the error status for response */
|
||||||
|
if (payload[1] != 0) {
|
||||||
|
atomic_set(&g_prm.status, payload[1]);
|
||||||
|
pr_err("%s: cmd = 0x%x returned error = 0x%x\n",
|
||||||
|
__func__, payload[0], payload[1]);
|
||||||
|
}
|
||||||
|
g_prm.resp_received = true;
|
||||||
|
/* payload[0] contains the param_ID for response */
|
||||||
|
switch (payload[0]) {
|
||||||
|
case PARAM_ID_RSC_AUDIO_HW_CLK:
|
||||||
|
case PARAM_ID_RSC_LPASS_CORE:
|
||||||
|
if (payload[1] != 0)
|
||||||
|
pr_err("%s: PRM command failed with error %d\n",
|
||||||
|
__func__, payload[1]);
|
||||||
|
atomic_set(&g_prm.state, payload[1]);
|
||||||
|
wake_up(&g_prm.wait);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
if (g_prm.resp_received)
|
||||||
|
wake_up(&g_prm.wait);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int prm_gpr_send_pkt(struct gpr_pkt *pkt, wait_queue_head_t *wait)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (wait)
|
||||||
|
atomic_set(&g_prm.state, 1);
|
||||||
|
atomic_set(&g_prm.status, 0);
|
||||||
|
|
||||||
|
mutex_lock(&g_prm.lock);
|
||||||
|
pr_debug("%s: enter",__func__);
|
||||||
|
if (!g_prm.is_adsp_up) {
|
||||||
|
pr_err("%s: ADSP is not up\n", __func__);
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (g_prm.adev == NULL) {
|
||||||
|
pr_err("%s: apr is unregistered\n", __func__);
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
ret = gpr_send_pkt(g_prm.adev, pkt);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s: packet not transmitted %d\n", __func__, ret);
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (wait) {
|
||||||
|
g_prm.resp_received = false;
|
||||||
|
ret = wait_event_timeout(g_prm.wait,
|
||||||
|
(g_prm.resp_received),
|
||||||
|
msecs_to_jiffies(2 * TIMEOUT_MS));
|
||||||
|
if (!ret) {
|
||||||
|
pr_err("%s: pkt send timeout\n", __func__);
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
} else if (atomic_read(&g_prm.status) > 0) {
|
||||||
|
pr_err("%s: DSP returned error %d\n", __func__,
|
||||||
|
atomic_read(&g_prm.status));
|
||||||
|
ret = -EINVAL;
|
||||||
|
} else {
|
||||||
|
pr_err("%s: DSP returned %d\n", __func__,
|
||||||
|
atomic_read(&g_prm.state));
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pr_debug("%s: exit",__func__);
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* prm_set_lpass_clk_cfg() - Set PRM clock
|
||||||
|
*
|
||||||
|
* Return: 0 if clock set is success
|
||||||
|
*/
|
||||||
|
static int audio_prm_set_lpass_clk_cfg_req(struct clk_cfg *cfg)
|
||||||
|
{
|
||||||
|
struct gpr_pkt *pkt;
|
||||||
|
prm_cmd_request_rsc_t prm_rsc_request;
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
size = GPR_HDR_SIZE + sizeof(prm_cmd_request_rsc_t);
|
||||||
|
pkt = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (!pkt)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pkt->hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, size);
|
||||||
|
|
||||||
|
pkt->hdr.src_port = GPR_SVC_ASM;
|
||||||
|
pkt->hdr.dst_port = PRM_MODULE_INSTANCE_ID;
|
||||||
|
pkt->hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
||||||
|
pkt->hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
|
||||||
|
pkt->hdr.token = 0; /* TBD */
|
||||||
|
pkt->hdr.opcode = PRM_CMD_REQUEST_HW_RSC;
|
||||||
|
|
||||||
|
pr_err("%s: clk_id %d size of cmd_req %ld \n",__func__, cfg->clk_id, sizeof(prm_cmd_request_rsc_t));
|
||||||
|
|
||||||
|
prm_rsc_request.payload_header.payload_address_lsw = 0;
|
||||||
|
prm_rsc_request.payload_header.payload_address_msw = 0;
|
||||||
|
prm_rsc_request.payload_header.mem_map_handle = 0;
|
||||||
|
prm_rsc_request.payload_header.payload_size = sizeof(prm_cmd_request_rsc_t) - sizeof(apm_cmd_header_t);
|
||||||
|
|
||||||
|
/** Populate the param payload */
|
||||||
|
prm_rsc_request.module_payload_0.module_instance_id = PRM_MODULE_INSTANCE_ID;
|
||||||
|
prm_rsc_request.module_payload_0.error_code = 0;
|
||||||
|
prm_rsc_request.module_payload_0.param_id = PARAM_ID_RSC_AUDIO_HW_CLK;
|
||||||
|
prm_rsc_request.module_payload_0.param_size =
|
||||||
|
sizeof(prm_cmd_request_rsc_t) - sizeof(apm_cmd_header_t) - sizeof(apm_module_param_data_t);
|
||||||
|
|
||||||
|
prm_rsc_request.num_clk_id_t.num_clock_id = MAX_AUD_HW_CLK_NUM_REQ;
|
||||||
|
|
||||||
|
prm_rsc_request.clock_ids_t[0].clock_id = cfg->clk_id;
|
||||||
|
prm_rsc_request.clock_ids_t[0].clock_freq = cfg->clk_freq_in_hz;
|
||||||
|
prm_rsc_request.clock_ids_t[0].clock_attri = cfg->clk_attri;
|
||||||
|
prm_rsc_request.clock_ids_t[0].clock_root = cfg->clk_root;
|
||||||
|
|
||||||
|
memcpy(&pkt->payload, &prm_rsc_request, sizeof(prm_cmd_request_rsc_t));
|
||||||
|
|
||||||
|
ret = prm_gpr_send_pkt(pkt, &g_prm.wait);
|
||||||
|
|
||||||
|
kfree(pkt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_prm_set_lpass_clk_cfg_rel(struct clk_cfg *cfg)
|
||||||
|
{
|
||||||
|
|
||||||
|
struct gpr_pkt *pkt;
|
||||||
|
prm_cmd_release_rsc_t prm_rsc_release;
|
||||||
|
int ret = 0;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
size = GPR_HDR_SIZE + sizeof(prm_cmd_release_rsc_t);
|
||||||
|
pkt = kzalloc(size, GFP_KERNEL);
|
||||||
|
if (!pkt)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
pkt->hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, size);
|
||||||
|
|
||||||
|
pkt->hdr.src_port = GPR_SVC_ASM;
|
||||||
|
pkt->hdr.dst_port = PRM_MODULE_INSTANCE_ID;
|
||||||
|
pkt->hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
||||||
|
pkt->hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
|
||||||
|
pkt->hdr.token = 0; /* TBD */
|
||||||
|
pkt->hdr.opcode = PRM_CMD_RELEASE_HW_RSC;
|
||||||
|
|
||||||
|
pr_err("%s: clk_id %d size of cmd_req %ld \n",__func__, cfg->clk_id, sizeof(prm_cmd_release_rsc_t));
|
||||||
|
|
||||||
|
prm_rsc_release.payload_header.payload_address_lsw = 0;
|
||||||
|
prm_rsc_release.payload_header.payload_address_msw = 0;
|
||||||
|
prm_rsc_release.payload_header.mem_map_handle = 0;
|
||||||
|
prm_rsc_release.payload_header.payload_size = sizeof(prm_cmd_release_rsc_t) - sizeof(apm_cmd_header_t);
|
||||||
|
|
||||||
|
/** Populate the param payload */
|
||||||
|
prm_rsc_release.module_payload_0.module_instance_id = PRM_MODULE_INSTANCE_ID;
|
||||||
|
prm_rsc_release.module_payload_0.error_code = 0;
|
||||||
|
prm_rsc_release.module_payload_0.param_id = PARAM_ID_RSC_AUDIO_HW_CLK;
|
||||||
|
prm_rsc_release.module_payload_0.param_size =
|
||||||
|
sizeof(prm_cmd_release_rsc_t) - sizeof(apm_cmd_header_t) - sizeof(apm_module_param_data_t);
|
||||||
|
|
||||||
|
prm_rsc_release.num_clk_id_t.num_clock_id = MAX_AUD_HW_CLK_NUM_REQ;
|
||||||
|
|
||||||
|
prm_rsc_release.clock_ids_t[0].clock_id = cfg->clk_id;
|
||||||
|
|
||||||
|
memcpy(&pkt->payload, &prm_rsc_release, sizeof(prm_cmd_release_rsc_t));
|
||||||
|
|
||||||
|
ret = prm_gpr_send_pkt(pkt, &g_prm.wait);
|
||||||
|
|
||||||
|
kfree(pkt);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int audio_prm_set_lpass_clk_cfg (struct clk_cfg *clk, uint8_t enable)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
if (enable)
|
||||||
|
ret = audio_prm_set_lpass_clk_cfg_req (clk);
|
||||||
|
else
|
||||||
|
ret = audio_prm_set_lpass_clk_cfg_rel (clk);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(audio_prm_set_lpass_clk_cfg);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int prm_ssr_enable(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
mutex_lock(&g_prm.lock);
|
||||||
|
g_prm.is_adsp_up = true;
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void prm_ssr_disable(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
mutex_lock(&g_prm.lock);
|
||||||
|
g_prm.is_adsp_up = true;
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct snd_event_ops prm_ssr_ops = {
|
||||||
|
.enable = prm_ssr_enable,
|
||||||
|
.disable = prm_ssr_disable,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int audio_prm_probe(struct gpr_device *adev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
dev_set_drvdata(&adev->dev, &g_prm);
|
||||||
|
|
||||||
|
mutex_init(&g_prm.lock);
|
||||||
|
g_prm.adev = adev;
|
||||||
|
g_prm.is_adsp_up = true;
|
||||||
|
|
||||||
|
init_waitqueue_head(&g_prm.wait);
|
||||||
|
|
||||||
|
ret = snd_event_client_register(&adev->dev, &prm_ssr_ops, NULL);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Registration with snd event failed \n",__func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_err("%s: prm probe success\n", __func__);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int audio_prm_remove(struct gpr_device *adev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
mutex_lock(&g_prm.lock);
|
||||||
|
ret = snd_event_client_deregister(&adev->dev);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Deregistration from SNF failed \n",__func__);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
g_prm.adev = NULL;
|
||||||
|
mutex_unlock(&g_prm.lock);
|
||||||
|
|
||||||
|
kfree(&g_prm);
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id audio_prm_device_id[] = {
|
||||||
|
{ .compatible = "qcom,audio_prm" },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, audio_prm_device_id);
|
||||||
|
|
||||||
|
static struct gpr_driver qcom_audio_prm_driver = {
|
||||||
|
.probe = audio_prm_probe,
|
||||||
|
.remove = audio_prm_remove,
|
||||||
|
.callback = audio_prm_callback,
|
||||||
|
.driver = {
|
||||||
|
.name = "qcom-audio_prm",
|
||||||
|
.of_match_table = of_match_ptr(audio_prm_device_id),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module_gpr_driver(qcom_audio_prm_driver);
|
||||||
|
MODULE_DESCRIPTION("audio prm");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
310
dsp/gecko-core.c
Normal file
310
dsp/gecko-core.c
Normal file
@@ -0,0 +1,310 @@
|
|||||||
|
/* Copyright (c) 2019-2020, 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
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/wait.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/sched.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_platform.h>
|
||||||
|
#include <linux/jiffies.h>
|
||||||
|
#include <ipc/gpr-lite.h>
|
||||||
|
#include <dsp/gecko-core.h>
|
||||||
|
|
||||||
|
#define APM_STATE_READY_TIMEOUT_MS 10000
|
||||||
|
#define Q6_READY_TIMEOUT_MS 1000
|
||||||
|
#define APM_CMD_GET_GECKO_STATE 0x01001021
|
||||||
|
#define APM_CMD_RSP_GET_GECKO_STATE 0x02001007
|
||||||
|
#define APM_MODULE_INSTANCE_ID 0x00000001
|
||||||
|
#define GPR_SVC_ADSP_CORE 0x3
|
||||||
|
|
||||||
|
struct gecko_core {
|
||||||
|
struct gpr_device *adev;
|
||||||
|
wait_queue_head_t wait;
|
||||||
|
struct mutex lock;
|
||||||
|
bool resp_received;
|
||||||
|
bool is_ready;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct gecko_core_private {
|
||||||
|
struct device *dev;
|
||||||
|
struct mutex lock;
|
||||||
|
struct gecko_core *gecko_core_drv;
|
||||||
|
bool is_initial_boot;
|
||||||
|
struct work_struct add_chld_dev_work;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct gecko_core_private *gecko_core_priv;
|
||||||
|
struct apm_cmd_rsp_get_gecko_status_t
|
||||||
|
|
||||||
|
{
|
||||||
|
/* Gecko status
|
||||||
|
* @values
|
||||||
|
* 0 -> Not ready
|
||||||
|
* 1 -> Ready
|
||||||
|
*/
|
||||||
|
uint32_t status;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
static int gecko_core_callback(struct gpr_device *adev, void *data)
|
||||||
|
{
|
||||||
|
struct gecko_core *core = dev_get_drvdata(&adev->dev);
|
||||||
|
struct apm_cmd_rsp_get_gecko_status_t *result;
|
||||||
|
struct gpr_hdr *hdr = data;
|
||||||
|
|
||||||
|
result = GPR_PKT_GET_PAYLOAD(struct apm_cmd_rsp_get_gecko_status_t, data);
|
||||||
|
|
||||||
|
dev_err(&adev->dev ,"%s: Payload %x",__func__, hdr->opcode);
|
||||||
|
switch (hdr->opcode) {
|
||||||
|
case GPR_IBASIC_RSP_RESULT:
|
||||||
|
dev_err(&adev->dev ,"%s: Failed response received",__func__);
|
||||||
|
core->resp_received = true;
|
||||||
|
break;
|
||||||
|
case APM_CMD_RSP_GET_GECKO_STATE:
|
||||||
|
dev_err(&adev->dev ,"%s: sucess response received",__func__);
|
||||||
|
core->is_ready = result->status;
|
||||||
|
core->resp_received = true;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(&adev->dev, "Message ID from apm: 0x%x\n",
|
||||||
|
hdr->opcode);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (core->resp_received)
|
||||||
|
wake_up(&core->wait);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool __gecko_core_is_apm_ready(struct gecko_core *core)
|
||||||
|
{
|
||||||
|
struct gpr_device *adev = core->adev;
|
||||||
|
struct gpr_pkt pkt;
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
pkt.hdr.header = GPR_SET_FIELD(GPR_PKT_VERSION, GPR_PKT_VER) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_HEADER_SIZE, GPR_PKT_HEADER_WORD_SIZE_V) |
|
||||||
|
GPR_SET_FIELD(GPR_PKT_PACKET_SIZE, GPR_PKT_HEADER_BYTE_SIZE_V);
|
||||||
|
|
||||||
|
pkt.hdr.opcode = APM_CMD_GET_GECKO_STATE;
|
||||||
|
pkt.hdr.dst_port = APM_MODULE_INSTANCE_ID;
|
||||||
|
pkt.hdr.src_port = GPR_SVC_ADSP_CORE;
|
||||||
|
pkt.hdr.dst_domain_id = GPR_IDS_DOMAIN_ID_ADSP_V;
|
||||||
|
pkt.hdr.src_domain_id = GPR_IDS_DOMAIN_ID_APPS_V;
|
||||||
|
pkt.hdr.opcode = APM_CMD_GET_GECKO_STATE;
|
||||||
|
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: send_command ret\n", __func__);
|
||||||
|
|
||||||
|
rc = gpr_send_pkt(adev, &pkt);
|
||||||
|
if (rc < 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rc = wait_event_timeout(core->wait, (core->resp_received),
|
||||||
|
msecs_to_jiffies(Q6_READY_TIMEOUT_MS));
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: wait event unblocked \n", __func__);
|
||||||
|
// core->resp_received = true;
|
||||||
|
// core->is_ready = true;
|
||||||
|
if (rc > 0 && core->resp_received) {
|
||||||
|
core->resp_received = false;
|
||||||
|
|
||||||
|
if (core->is_ready)
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: command timedout, ret\n",
|
||||||
|
__func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* gecko_core_is_apm_ready() - Get status of adsp
|
||||||
|
*
|
||||||
|
* Return: Will be an true if apm is ready and false if not.
|
||||||
|
*/
|
||||||
|
bool gecko_core_is_apm_ready(void)
|
||||||
|
{
|
||||||
|
unsigned long timeout;
|
||||||
|
bool ret = false;
|
||||||
|
struct gecko_core *core;
|
||||||
|
|
||||||
|
if (!gecko_core_priv)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
core = gecko_core_priv->gecko_core_drv;
|
||||||
|
if (!core)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
mutex_lock(&core->lock);
|
||||||
|
timeout = jiffies + msecs_to_jiffies(APM_STATE_READY_TIMEOUT_MS);
|
||||||
|
for (;;) {
|
||||||
|
if (__gecko_core_is_apm_ready(core)) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
usleep_range(300000, 300050);
|
||||||
|
if (!time_after(timeout, jiffies)) {
|
||||||
|
ret = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&core->lock);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(gecko_core_is_apm_ready);
|
||||||
|
|
||||||
|
static int gecko_core_probe(struct gpr_device *adev)
|
||||||
|
{
|
||||||
|
struct gecko_core *core;
|
||||||
|
pr_err("%s",__func__);
|
||||||
|
if (!gecko_core_priv) {
|
||||||
|
pr_err("%s: gecko_core platform probe not yet done\n", __func__);
|
||||||
|
return -EPROBE_DEFER;
|
||||||
|
}
|
||||||
|
mutex_lock(&gecko_core_priv->lock);
|
||||||
|
core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||||
|
if (!core)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
dev_set_drvdata(&adev->dev, core);
|
||||||
|
|
||||||
|
mutex_init(&core->lock);
|
||||||
|
core->adev = adev;
|
||||||
|
init_waitqueue_head(&core->wait);
|
||||||
|
gecko_core_priv->gecko_core_drv = core;
|
||||||
|
if (gecko_core_priv->is_initial_boot)
|
||||||
|
schedule_work(&gecko_core_priv->add_chld_dev_work);
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gecko_core_exit(struct gpr_device *adev)
|
||||||
|
{
|
||||||
|
struct gecko_core *core = dev_get_drvdata(&adev->dev);
|
||||||
|
if (!gecko_core_priv) {
|
||||||
|
pr_err("%s: gecko_core platform probe not yet done\n", __func__);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
mutex_lock(&gecko_core_priv->lock);
|
||||||
|
gecko_core_priv->gecko_core_drv = NULL;
|
||||||
|
kfree(core);
|
||||||
|
mutex_unlock(&gecko_core_priv->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id gecko_core_device_id[] = {
|
||||||
|
{ .compatible = "qcom,gecko_core" },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, gecko_core_device_id);
|
||||||
|
|
||||||
|
static struct gpr_driver qcom_gecko_core_driver = {
|
||||||
|
.probe = gecko_core_probe,
|
||||||
|
.remove = gecko_core_exit,
|
||||||
|
.callback = gecko_core_callback,
|
||||||
|
.driver = {
|
||||||
|
.name = "qcom-gecko_core",
|
||||||
|
.of_match_table = of_match_ptr(gecko_core_device_id),
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
static void gecko_core_add_child_devices(struct work_struct *work)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
pr_err("%s:enumarate machine driver\n", __func__);
|
||||||
|
|
||||||
|
if(gecko_core_is_apm_ready()) {
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: apm is up\n",
|
||||||
|
__func__);
|
||||||
|
} else {
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: apm is not up\n",
|
||||||
|
__func__);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = of_platform_populate(gecko_core_priv->dev->of_node,
|
||||||
|
NULL, NULL, gecko_core_priv->dev);
|
||||||
|
if (ret)
|
||||||
|
dev_err(gecko_core_priv->dev, "%s: failed to add child nodes, ret=%d\n",
|
||||||
|
__func__, ret);
|
||||||
|
|
||||||
|
gecko_core_priv->is_initial_boot = false;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gecko_core_platform_driver_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
pr_err("%s",__func__);
|
||||||
|
|
||||||
|
gecko_core_priv = devm_kzalloc(&pdev->dev, sizeof(struct gecko_core_private), GFP_KERNEL);
|
||||||
|
if (!gecko_core_priv)
|
||||||
|
return -ENOMEM;
|
||||||
|
|
||||||
|
gecko_core_priv->dev = &pdev->dev;
|
||||||
|
|
||||||
|
mutex_init(&gecko_core_priv->lock);
|
||||||
|
|
||||||
|
INIT_WORK(&gecko_core_priv->add_chld_dev_work, gecko_core_add_child_devices);
|
||||||
|
|
||||||
|
ret = gpr_driver_register(&qcom_gecko_core_driver);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: gpr driver register failed = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
gecko_core_priv->is_initial_boot = true;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
ret = snd_event_client_register(&pdev->dev, &gpr_ssr_ops, NULL);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s: Registration with SND event fwk failed ret = %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int gecko_core_platform_driver_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
//snd_event_client_deregister(&pdev->dev);
|
||||||
|
gpr_driver_unregister(&qcom_gecko_core_driver);
|
||||||
|
gecko_core_priv = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id gecko_core_of_match[] = {
|
||||||
|
{ .compatible = "qcom,gecko-core-platform", },
|
||||||
|
{},
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct platform_driver gecko_core_driver = {
|
||||||
|
.probe = gecko_core_platform_driver_probe,
|
||||||
|
.remove = gecko_core_platform_driver_remove,
|
||||||
|
.driver = {
|
||||||
|
.name = "gecko-core-platform",
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.of_match_table = gecko_core_of_match,
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
module_platform_driver(gecko_core_driver);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("q6 core");
|
||||||
|
MODULE_LICENSE("GPL v2");
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2020, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/init.h>
|
#include <linux/init.h>
|
||||||
@@ -17,8 +17,15 @@
|
|||||||
#include <linux/of_device.h>
|
#include <linux/of_device.h>
|
||||||
#include <linux/export.h>
|
#include <linux/export.h>
|
||||||
#include <linux/ion.h>
|
#include <linux/ion.h>
|
||||||
|
#include <linux/ioctl.h>
|
||||||
|
#include <linux/cdev.h>
|
||||||
|
#include <linux/fs.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#ifndef CONFIG_GECKO_CORE
|
||||||
#include <ipc/apr.h>
|
#include <ipc/apr.h>
|
||||||
|
#endif
|
||||||
#include <dsp/msm_audio_ion.h>
|
#include <dsp/msm_audio_ion.h>
|
||||||
|
#include <linux/msm_audio.h>
|
||||||
|
|
||||||
#define MSM_AUDIO_ION_PROBED (1 << 0)
|
#define MSM_AUDIO_ION_PROBED (1 << 0)
|
||||||
|
|
||||||
@@ -27,6 +34,10 @@
|
|||||||
|
|
||||||
#define MSM_AUDIO_SMMU_SID_OFFSET 32
|
#define MSM_AUDIO_SMMU_SID_OFFSET 32
|
||||||
|
|
||||||
|
#define TZ_PIL_PROTECT_MEM_SUBSYS_ID 0x0C
|
||||||
|
#define TZ_PIL_CLEAR_PROTECT_MEM_SUBSYS_ID 0x0D
|
||||||
|
#define MSM_AUDIO_ION_DRIVER_NAME "msm_audio_ion"
|
||||||
|
#define MINOR_NUMBER_COUNT 1
|
||||||
struct msm_audio_ion_private {
|
struct msm_audio_ion_private {
|
||||||
bool smmu_enabled;
|
bool smmu_enabled;
|
||||||
struct device *cb_dev;
|
struct device *cb_dev;
|
||||||
@@ -35,6 +46,14 @@ struct msm_audio_ion_private {
|
|||||||
struct mutex list_mutex;
|
struct mutex list_mutex;
|
||||||
u64 smmu_sid_bits;
|
u64 smmu_sid_bits;
|
||||||
u32 smmu_version;
|
u32 smmu_version;
|
||||||
|
bool is_non_hypervisor;
|
||||||
|
/*list to store fd, phy. addr and handle data */
|
||||||
|
struct list_head fd_list;
|
||||||
|
/*char dev related data */
|
||||||
|
dev_t ion_major;
|
||||||
|
struct class *ion_class;
|
||||||
|
struct device *chardev;
|
||||||
|
struct cdev cdev;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct msm_audio_alloc_data {
|
struct msm_audio_alloc_data {
|
||||||
@@ -48,6 +67,13 @@ struct msm_audio_alloc_data {
|
|||||||
|
|
||||||
static struct msm_audio_ion_private msm_audio_ion_data = {0,};
|
static struct msm_audio_ion_private msm_audio_ion_data = {0,};
|
||||||
|
|
||||||
|
struct msm_audio_fd_data {
|
||||||
|
int fd;
|
||||||
|
void *handle;
|
||||||
|
dma_addr_t paddr;
|
||||||
|
struct list_head list;
|
||||||
|
};
|
||||||
|
|
||||||
static void msm_audio_ion_add_allocation(
|
static void msm_audio_ion_add_allocation(
|
||||||
struct msm_audio_ion_private *msm_audio_ion_data,
|
struct msm_audio_ion_private *msm_audio_ion_data,
|
||||||
struct msm_audio_alloc_data *alloc_data)
|
struct msm_audio_alloc_data *alloc_data)
|
||||||
@@ -63,14 +89,52 @@ static void msm_audio_ion_add_allocation(
|
|||||||
mutex_unlock(&(msm_audio_ion_data->list_mutex));
|
mutex_unlock(&(msm_audio_ion_data->list_mutex));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
void *addr = NULL;
|
||||||
|
struct msm_audio_alloc_data *alloc_data = NULL;
|
||||||
|
|
||||||
|
rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = dma_buf_vmap(dma_buf);
|
||||||
|
if (!addr) {
|
||||||
|
pr_err("%s: kernel mapping of dma_buf failed\n",
|
||||||
|
__func__);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* TBD: remove the below section once new API
|
||||||
|
* for mapping kernel virtual address is available.
|
||||||
|
*/
|
||||||
|
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
|
||||||
|
list) {
|
||||||
|
if (alloc_data->dma_buf == dma_buf) {
|
||||||
|
alloc_data->vaddr = addr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
|
||||||
|
exit:
|
||||||
|
return addr;
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
|
static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
|
||||||
dma_addr_t *addr, size_t *len)
|
dma_addr_t *addr, size_t *len, bool is_iova)
|
||||||
{
|
{
|
||||||
|
|
||||||
struct msm_audio_alloc_data *alloc_data;
|
struct msm_audio_alloc_data *alloc_data;
|
||||||
struct device *cb_dev;
|
struct device *cb_dev;
|
||||||
unsigned long ionflag = 0;
|
unsigned long ionflag = 0;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
void *vaddr = NULL;
|
||||||
|
|
||||||
cb_dev = msm_audio_ion_data.cb_dev;
|
cb_dev = msm_audio_ion_data.cb_dev;
|
||||||
|
|
||||||
@@ -122,7 +186,19 @@ static int msm_audio_dma_buf_map(struct dma_buf *dma_buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* physical address from mapping */
|
/* physical address from mapping */
|
||||||
*addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
|
if (!is_iova) {
|
||||||
|
*addr = sg_phys(alloc_data->table->sgl);
|
||||||
|
vaddr = msm_audio_ion_map_kernel((void *)dma_buf);
|
||||||
|
if (IS_ERR_OR_NULL(vaddr)) {
|
||||||
|
pr_err("%s: ION memory mapping for AUDIO failed\n",
|
||||||
|
__func__);
|
||||||
|
rc = -ENOMEM;
|
||||||
|
goto detach_dma_buf;
|
||||||
|
}
|
||||||
|
alloc_data->vaddr = vaddr;
|
||||||
|
} else {
|
||||||
|
*addr = MSM_AUDIO_ION_PHYS_ADDR(alloc_data);
|
||||||
|
}
|
||||||
|
|
||||||
msm_audio_ion_add_allocation(&msm_audio_ion_data,
|
msm_audio_ion_add_allocation(&msm_audio_ion_data,
|
||||||
alloc_data);
|
alloc_data);
|
||||||
@@ -186,17 +262,17 @@ static int msm_audio_dma_buf_unmap(struct dma_buf *dma_buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
|
static int msm_audio_ion_get_phys(struct dma_buf *dma_buf,
|
||||||
dma_addr_t *addr, size_t *len)
|
dma_addr_t *addr, size_t *len, bool is_iova)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
rc = msm_audio_dma_buf_map(dma_buf, addr, len);
|
rc = msm_audio_dma_buf_map(dma_buf, addr, len, is_iova);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: failed to map DMA buf, err = %d\n",
|
pr_err("%s: failed to map DMA buf, err = %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (msm_audio_ion_data.smmu_enabled) {
|
if (msm_audio_ion_data.smmu_enabled && is_iova) {
|
||||||
/* Append the SMMU SID information to the IOVA address */
|
/* Append the SMMU SID information to the IOVA address */
|
||||||
*addr |= msm_audio_ion_data.smmu_sid_bits;
|
*addr |= msm_audio_ion_data.smmu_sid_bits;
|
||||||
}
|
}
|
||||||
@@ -228,43 +304,6 @@ int msm_audio_ion_get_smmu_info(struct device **cb_dev,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *msm_audio_ion_map_kernel(struct dma_buf *dma_buf)
|
|
||||||
{
|
|
||||||
int rc = 0;
|
|
||||||
void *addr = NULL;
|
|
||||||
struct msm_audio_alloc_data *alloc_data = NULL;
|
|
||||||
|
|
||||||
rc = dma_buf_begin_cpu_access(dma_buf, DMA_BIDIRECTIONAL);
|
|
||||||
if (rc) {
|
|
||||||
pr_err("%s: kmap dma_buf_begin_cpu_access fail\n", __func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
addr = dma_buf_vmap(dma_buf);
|
|
||||||
if (!addr) {
|
|
||||||
pr_err("%s: kernel mapping of dma_buf failed\n",
|
|
||||||
__func__);
|
|
||||||
goto exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* TBD: remove the below section once new API
|
|
||||||
* for mapping kernel virtual address is available.
|
|
||||||
*/
|
|
||||||
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
|
||||||
list_for_each_entry(alloc_data, &(msm_audio_ion_data.alloc_list),
|
|
||||||
list) {
|
|
||||||
if (alloc_data->dma_buf == dma_buf) {
|
|
||||||
alloc_data->vaddr = addr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
|
||||||
|
|
||||||
exit:
|
|
||||||
return addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
|
static int msm_audio_ion_unmap_kernel(struct dma_buf *dma_buf)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -311,8 +350,9 @@ static int msm_audio_ion_map_buf(struct dma_buf *dma_buf, dma_addr_t *paddr,
|
|||||||
size_t *plen, void **vaddr)
|
size_t *plen, void **vaddr)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
bool is_iova = true;
|
||||||
|
|
||||||
rc = msm_audio_ion_get_phys(dma_buf, paddr, plen);
|
rc = msm_audio_ion_get_phys(dma_buf, paddr, plen, is_iova);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
|
pr_err("%s: ION Get Physical for AUDIO failed, rc = %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@@ -393,11 +433,37 @@ int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
|
|||||||
|
|
||||||
memset(*vaddr, 0, bufsz);
|
memset(*vaddr, 0, bufsz);
|
||||||
|
|
||||||
|
// Cleanp dmabuf if error?
|
||||||
err:
|
err:
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_audio_ion_alloc);
|
EXPORT_SYMBOL(msm_audio_ion_alloc);
|
||||||
|
|
||||||
|
int msm_audio_ion_phys_free(void *handle,
|
||||||
|
dma_addr_t *paddr,
|
||||||
|
size_t *pa_len,
|
||||||
|
u8 assign_type,
|
||||||
|
int id,
|
||||||
|
int key)
|
||||||
|
{
|
||||||
|
handle = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_audio_ion_phys_free);
|
||||||
|
|
||||||
|
int msm_audio_ion_phys_assign(void **handle, int fd,
|
||||||
|
dma_addr_t *paddr, size_t *pa_len, u8 assign_type, int id)
|
||||||
|
{
|
||||||
|
*handle = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_audio_ion_phys_assign);
|
||||||
|
|
||||||
|
bool msm_audio_is_hypervisor_supported(void)
|
||||||
|
{
|
||||||
|
return !(msm_audio_ion_data.is_non_hypervisor);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_audio_is_hypervisor_supported);
|
||||||
/**
|
/**
|
||||||
* msm_audio_ion_dma_map -
|
* msm_audio_ion_dma_map -
|
||||||
* Memory maps for a given DMA buffer
|
* Memory maps for a given DMA buffer
|
||||||
@@ -435,6 +501,101 @@ int msm_audio_ion_dma_map(dma_addr_t *phys_addr, dma_addr_t *iova_base,
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_audio_ion_dma_map);
|
EXPORT_SYMBOL(msm_audio_ion_dma_map);
|
||||||
|
|
||||||
|
void msm_audio_fd_list_debug(void)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
|
||||||
|
list_for_each_entry(msm_audio_fd_data,
|
||||||
|
&msm_audio_ion_data.fd_list, list) {
|
||||||
|
pr_debug("%s fd %d handle %pK phy. addr %pK\n", __func__,
|
||||||
|
msm_audio_fd_data->fd, msm_audio_fd_data->handle,
|
||||||
|
(void *)msm_audio_fd_data->paddr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_audio_update_fd_list(struct msm_audio_fd_data *msm_audio_fd_data)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data1 = NULL;
|
||||||
|
|
||||||
|
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
list_for_each_entry(msm_audio_fd_data1,
|
||||||
|
&msm_audio_ion_data.fd_list, list) {
|
||||||
|
if (msm_audio_fd_data1->fd == msm_audio_fd_data->fd) {
|
||||||
|
pr_err("%s fd already present, not updating the list",
|
||||||
|
__func__);
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
list_add_tail(&msm_audio_fd_data->list, &msm_audio_ion_data.fd_list);
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
void msm_audio_delete_fd_entry(void *handle)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
struct list_head *ptr, *next;
|
||||||
|
|
||||||
|
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
list_for_each_safe(ptr, next,
|
||||||
|
&msm_audio_ion_data.fd_list) {
|
||||||
|
msm_audio_fd_data = list_entry(ptr, struct msm_audio_fd_data,
|
||||||
|
list);
|
||||||
|
if (msm_audio_fd_data->handle == handle) {
|
||||||
|
pr_debug("%s deleting handle %pK entry from list\n",
|
||||||
|
__func__, handle);
|
||||||
|
list_del(&(msm_audio_fd_data->list));
|
||||||
|
kfree(msm_audio_fd_data);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
}
|
||||||
|
|
||||||
|
int msm_audio_get_phy_addr(int fd, dma_addr_t *paddr)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
int status = -EINVAL;
|
||||||
|
|
||||||
|
if (!paddr) {
|
||||||
|
pr_err("%s Invalid paddr param status %d\n", __func__, status);
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
pr_debug("%s, fd %d\n", __func__, fd);
|
||||||
|
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
list_for_each_entry(msm_audio_fd_data,
|
||||||
|
&msm_audio_ion_data.fd_list, list) {
|
||||||
|
if (msm_audio_fd_data->fd == fd) {
|
||||||
|
*paddr = msm_audio_fd_data->paddr;
|
||||||
|
status = 0;
|
||||||
|
pr_debug("%s Found fd %d paddr %pK\n",
|
||||||
|
__func__, fd, paddr);
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_audio_get_phy_addr);
|
||||||
|
|
||||||
|
void msm_audio_get_handle(int fd, void **handle)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
|
||||||
|
pr_debug("%s fd %d\n", __func__, fd);
|
||||||
|
mutex_lock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
list_for_each_entry(msm_audio_fd_data,
|
||||||
|
&msm_audio_ion_data.fd_list, list) {
|
||||||
|
if (msm_audio_fd_data->fd == fd) {
|
||||||
|
*handle = (struct dma_buf *)msm_audio_fd_data->handle;
|
||||||
|
pr_debug("%s handle %pK\n", __func__, *handle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&(msm_audio_ion_data.list_mutex));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* msm_audio_ion_import-
|
* msm_audio_ion_import-
|
||||||
* Import ION buffer with given file descriptor
|
* Import ION buffer with given file descriptor
|
||||||
@@ -528,6 +689,34 @@ int msm_audio_ion_free(struct dma_buf *dma_buf)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_audio_ion_free);
|
EXPORT_SYMBOL(msm_audio_ion_free);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* msm_audio_ion_crash_handler -
|
||||||
|
* handles cleanup after userspace crashes.
|
||||||
|
*
|
||||||
|
* To be called from machine driver.
|
||||||
|
*/
|
||||||
|
void msm_audio_ion_crash_handler(void)
|
||||||
|
{
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
struct list_head *ptr, *next;
|
||||||
|
void *handle = NULL;
|
||||||
|
|
||||||
|
pr_debug("Inside %s\n", __func__);
|
||||||
|
list_for_each_entry(msm_audio_fd_data,
|
||||||
|
&msm_audio_ion_data.fd_list, list) {
|
||||||
|
handle = msm_audio_fd_data->handle;
|
||||||
|
msm_audio_ion_free(handle);
|
||||||
|
}
|
||||||
|
list_for_each_safe(ptr, next,
|
||||||
|
&msm_audio_ion_data.fd_list) {
|
||||||
|
msm_audio_fd_data = list_entry(ptr, struct msm_audio_fd_data,
|
||||||
|
list);
|
||||||
|
list_del(&(msm_audio_fd_data->list));
|
||||||
|
kfree(msm_audio_fd_data);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(msm_audio_ion_crash_handler);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* msm_audio_ion_mmap -
|
* msm_audio_ion_mmap -
|
||||||
* Audio ION memory map
|
* Audio ION memory map
|
||||||
@@ -680,6 +869,81 @@ u32 msm_audio_populate_upper_32_bits(dma_addr_t pa)
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(msm_audio_populate_upper_32_bits);
|
EXPORT_SYMBOL(msm_audio_populate_upper_32_bits);
|
||||||
|
|
||||||
|
static int msm_audio_ion_open(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
struct msm_audio_ion_private *ion_data = container_of(inode->i_cdev,
|
||||||
|
struct msm_audio_ion_private,
|
||||||
|
cdev);
|
||||||
|
struct device *dev = ion_data->chardev;
|
||||||
|
|
||||||
|
pr_debug("Inside %s\n", __func__);
|
||||||
|
get_device(dev);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_audio_ion_release(struct inode *inode, struct file *file)
|
||||||
|
{
|
||||||
|
struct msm_audio_ion_private *ion_data = container_of(inode->i_cdev,
|
||||||
|
struct msm_audio_ion_private,
|
||||||
|
cdev);
|
||||||
|
struct device *dev = ion_data->chardev;
|
||||||
|
|
||||||
|
pr_debug("Inside %s\n", __func__);
|
||||||
|
put_device(dev);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long msm_audio_ion_ioctl(struct file *file, unsigned int ioctl_num,
|
||||||
|
unsigned long __user ioctl_param)
|
||||||
|
{
|
||||||
|
void *mem_handle;
|
||||||
|
dma_addr_t paddr;
|
||||||
|
size_t pa_len = 0;
|
||||||
|
void *vaddr;
|
||||||
|
int ret = 0;
|
||||||
|
struct msm_audio_fd_data *msm_audio_fd_data = NULL;
|
||||||
|
|
||||||
|
pr_debug("%s ioctl num %u\n", __func__, ioctl_num);
|
||||||
|
switch (ioctl_num) {
|
||||||
|
case IOCTL_MAP_PHYS_ADDR:
|
||||||
|
msm_audio_fd_data = kzalloc((sizeof(struct msm_audio_fd_data)),
|
||||||
|
GFP_KERNEL);
|
||||||
|
if (!msm_audio_fd_data) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
pr_err("%s : Out of memory ret %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = msm_audio_ion_import((struct dma_buf **)&mem_handle, (int)ioctl_param,
|
||||||
|
NULL, 0, &paddr, &pa_len, &vaddr);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s Memory map Failed %d\n", __func__, ret);
|
||||||
|
kfree(msm_audio_fd_data);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
msm_audio_fd_data->fd = (int)ioctl_param;
|
||||||
|
msm_audio_fd_data->handle = mem_handle;
|
||||||
|
msm_audio_fd_data->paddr = paddr;
|
||||||
|
msm_audio_update_fd_list(msm_audio_fd_data);
|
||||||
|
break;
|
||||||
|
case IOCTL_UNMAP_PHYS_ADDR:
|
||||||
|
msm_audio_get_handle((int)ioctl_param, &mem_handle);
|
||||||
|
ret = msm_audio_ion_free(mem_handle);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s Ion free failed %d\n", __func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
msm_audio_delete_fd_entry(mem_handle);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
pr_err("%s Entered default. Invalid ioctl num %u",
|
||||||
|
__func__, ioctl_num);
|
||||||
|
ret = -EINVAL;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_audio_smmu_init(struct device *dev)
|
static int msm_audio_smmu_init(struct device *dev)
|
||||||
{
|
{
|
||||||
INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
|
INIT_LIST_HEAD(&msm_audio_ion_data.alloc_list);
|
||||||
@@ -694,20 +958,83 @@ static const struct of_device_id msm_audio_ion_dt_match[] = {
|
|||||||
};
|
};
|
||||||
MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
|
MODULE_DEVICE_TABLE(of, msm_audio_ion_dt_match);
|
||||||
|
|
||||||
|
static const struct file_operations msm_audio_ion_fops = {
|
||||||
|
.owner = THIS_MODULE,
|
||||||
|
.open = msm_audio_ion_open,
|
||||||
|
.release = msm_audio_ion_release,
|
||||||
|
.unlocked_ioctl = msm_audio_ion_ioctl,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int msm_audio_ion_reg_chrdev(struct msm_audio_ion_private *ion_data)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
ret = alloc_chrdev_region(&ion_data->ion_major, 0,
|
||||||
|
MINOR_NUMBER_COUNT, MSM_AUDIO_ION_DRIVER_NAME);
|
||||||
|
if (ret < 0) {
|
||||||
|
pr_err("%s alloc_chr_dev_region failed ret : %d\n",
|
||||||
|
__func__, ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
pr_debug("%s major number %d", __func__, MAJOR(ion_data->ion_major));
|
||||||
|
ion_data->ion_class = class_create(THIS_MODULE,
|
||||||
|
MSM_AUDIO_ION_DRIVER_NAME);
|
||||||
|
if (IS_ERR(ion_data->ion_class)) {
|
||||||
|
ret = PTR_ERR(ion_data->ion_class);
|
||||||
|
pr_err("%s class create failed. ret : %d", __func__, ret);
|
||||||
|
goto err_class;
|
||||||
|
}
|
||||||
|
ion_data->chardev = device_create(ion_data->ion_class, NULL,
|
||||||
|
ion_data->ion_major, NULL,
|
||||||
|
MSM_AUDIO_ION_DRIVER_NAME);
|
||||||
|
if (IS_ERR(ion_data->chardev)) {
|
||||||
|
ret = PTR_ERR(ion_data->chardev);
|
||||||
|
pr_err("%s device create failed ret : %d\n", __func__, ret);
|
||||||
|
goto err_device;
|
||||||
|
}
|
||||||
|
cdev_init(&ion_data->cdev, &msm_audio_ion_fops);
|
||||||
|
ret = cdev_add(&ion_data->cdev, ion_data->ion_major, 1);
|
||||||
|
if (ret) {
|
||||||
|
pr_err("%s cdev add failed, ret : %d\n", __func__, ret);
|
||||||
|
goto err_cdev;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err_cdev:
|
||||||
|
device_destroy(ion_data->ion_class, ion_data->ion_major);
|
||||||
|
err_device:
|
||||||
|
class_destroy(ion_data->ion_class);
|
||||||
|
err_class:
|
||||||
|
unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int msm_audio_ion_unreg_chrdev(struct msm_audio_ion_private *ion_data)
|
||||||
|
{
|
||||||
|
cdev_del(&ion_data->cdev);
|
||||||
|
device_destroy(ion_data->ion_class, ion_data->ion_major);
|
||||||
|
class_destroy(ion_data->ion_class);
|
||||||
|
unregister_chrdev_region(0, MINOR_NUMBER_COUNT);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
static int msm_audio_ion_probe(struct platform_device *pdev)
|
static int msm_audio_ion_probe(struct platform_device *pdev)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
u64 smmu_sid = 0;
|
u64 smmu_sid = 0;
|
||||||
u64 smmu_sid_mask = 0;
|
u64 smmu_sid_mask = 0;
|
||||||
const char *msm_audio_ion_dt = "qcom,smmu-enabled";
|
const char *msm_audio_ion_dt = "qcom,smmu-enabled";
|
||||||
|
const char *msm_audio_ion_non_hyp = "qcom,non-hyp-assign";
|
||||||
const char *msm_audio_ion_smmu = "qcom,smmu-version";
|
const char *msm_audio_ion_smmu = "qcom,smmu-version";
|
||||||
const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
|
const char *msm_audio_ion_smmu_sid_mask = "qcom,smmu-sid-mask";
|
||||||
bool smmu_enabled;
|
bool smmu_enabled;
|
||||||
enum apr_subsys_state q6_state;
|
bool is_non_hypervisor_en;
|
||||||
struct device *dev = &pdev->dev;
|
struct device *dev = &pdev->dev;
|
||||||
struct of_phandle_args iommuspec;
|
struct of_phandle_args iommuspec;
|
||||||
|
#ifndef CONFIG_GECKO_CORE
|
||||||
|
enum apr_subsys_state q6_state;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
dev_err(dev, "%s: msm_audio_ion_probe\n", __func__);
|
||||||
if (dev->of_node == NULL) {
|
if (dev->of_node == NULL) {
|
||||||
dev_err(dev,
|
dev_err(dev,
|
||||||
"%s: device tree is not found\n",
|
"%s: device tree is not found\n",
|
||||||
@@ -716,6 +1043,10 @@ static int msm_audio_ion_probe(struct platform_device *pdev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
is_non_hypervisor_en = of_property_read_bool(dev->of_node,
|
||||||
|
msm_audio_ion_non_hyp);
|
||||||
|
msm_audio_ion_data.is_non_hypervisor = is_non_hypervisor_en;
|
||||||
|
|
||||||
smmu_enabled = of_property_read_bool(dev->of_node,
|
smmu_enabled = of_property_read_bool(dev->of_node,
|
||||||
msm_audio_ion_dt);
|
msm_audio_ion_dt);
|
||||||
msm_audio_ion_data.smmu_enabled = smmu_enabled;
|
msm_audio_ion_data.smmu_enabled = smmu_enabled;
|
||||||
@@ -724,14 +1055,15 @@ static int msm_audio_ion_probe(struct platform_device *pdev)
|
|||||||
dev_dbg(dev, "%s: SMMU is Disabled\n", __func__);
|
dev_dbg(dev, "%s: SMMU is Disabled\n", __func__);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
#ifndef CONFIG_GECKO_CORE
|
||||||
q6_state = apr_get_q6_state();
|
q6_state = apr_get_q6_state();
|
||||||
if (q6_state == APR_SUBSYS_DOWN) {
|
if (q6_state == APR_SUBSYS_DOWN) {
|
||||||
dev_dbg(dev,
|
dev_info(dev,
|
||||||
"defering %s, adsp_state %d\n",
|
"defering %s, adsp_state %d\n",
|
||||||
__func__, q6_state);
|
__func__, q6_state);
|
||||||
return -EPROBE_DEFER;
|
return -EPROBE_DEFER;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
dev_dbg(dev, "%s: adsp is ready\n", __func__);
|
dev_dbg(dev, "%s: adsp is ready\n", __func__);
|
||||||
|
|
||||||
rc = of_property_read_u32(dev->of_node,
|
rc = of_property_read_u32(dev->of_node,
|
||||||
@@ -785,6 +1117,12 @@ exit:
|
|||||||
|
|
||||||
msm_audio_ion_data.cb_dev = dev;
|
msm_audio_ion_data.cb_dev = dev;
|
||||||
|
|
||||||
|
INIT_LIST_HEAD(&msm_audio_ion_data.fd_list);
|
||||||
|
rc = msm_audio_ion_reg_chrdev(&msm_audio_ion_data);
|
||||||
|
if (rc) {
|
||||||
|
pr_err("%s register char dev failed, rc : %d", __func__, rc);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -796,6 +1134,7 @@ static int msm_audio_ion_remove(struct platform_device *pdev)
|
|||||||
|
|
||||||
msm_audio_ion_data.smmu_enabled = 0;
|
msm_audio_ion_data.smmu_enabled = 0;
|
||||||
msm_audio_ion_data.device_status = 0;
|
msm_audio_ion_data.device_status = 0;
|
||||||
|
msm_audio_ion_unreg_chrdev(&msm_audio_ion_data);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -812,6 +1151,7 @@ static struct platform_driver msm_audio_ion_driver = {
|
|||||||
|
|
||||||
int __init msm_audio_ion_init(void)
|
int __init msm_audio_ion_init(void)
|
||||||
{
|
{
|
||||||
|
pr_debug("%s: msm_audio_ion_init called \n",__func__);
|
||||||
return platform_driver_register(&msm_audio_ion_driver);
|
return platform_driver_register(&msm_audio_ion_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -820,5 +1160,7 @@ void msm_audio_ion_exit(void)
|
|||||||
platform_driver_unregister(&msm_audio_ion_driver);
|
platform_driver_unregister(&msm_audio_ion_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_init(msm_audio_ion_init);
|
||||||
|
module_exit(msm_audio_ion_exit);
|
||||||
MODULE_DESCRIPTION("MSM Audio ION module");
|
MODULE_DESCRIPTION("MSM Audio ION module");
|
||||||
MODULE_LICENSE("GPL v2");
|
MODULE_LICENSE("GPL v2");
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2017, 2019 The Linux Foundation. All rights reserved.
|
* Copyright (c) 2017, 2019-2020 The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
@@ -9,41 +9,42 @@
|
|||||||
|
|
||||||
static int __init audio_q6_init(void)
|
static int __init audio_q6_init(void)
|
||||||
{
|
{
|
||||||
adsp_err_init();
|
// TODO: Is this file required?
|
||||||
audio_cal_init();
|
// adsp_err_init();
|
||||||
rtac_init();
|
// audio_cal_init();
|
||||||
adm_init();
|
// rtac_init();
|
||||||
afe_init();
|
// adm_init();
|
||||||
spk_params_init();
|
// afe_init();
|
||||||
q6asm_init();
|
// spk_params_init();
|
||||||
q6lsm_init();
|
// q6asm_init();
|
||||||
voice_init();
|
// q6lsm_init();
|
||||||
core_init();
|
// voice_init();
|
||||||
msm_audio_ion_init();
|
// core_init();
|
||||||
audio_slimslave_init();
|
// msm_audio_ion_init();
|
||||||
avtimer_init();
|
// audio_slimslave_init();
|
||||||
msm_mdf_init();
|
// avtimer_init();
|
||||||
voice_mhi_init();
|
// msm_mdf_init();
|
||||||
|
// voice_mhi_init();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void __exit audio_q6_exit(void)
|
static void __exit audio_q6_exit(void)
|
||||||
{
|
{
|
||||||
msm_mdf_exit();
|
// msm_mdf_exit();
|
||||||
avtimer_exit();
|
// avtimer_exit();
|
||||||
audio_slimslave_exit();
|
// audio_slimslave_exit();
|
||||||
msm_audio_ion_exit();
|
// msm_audio_ion_exit();
|
||||||
core_exit();
|
// core_exit();
|
||||||
voice_exit();
|
// voice_exit();
|
||||||
q6lsm_exit();
|
// q6lsm_exit();
|
||||||
q6asm_exit();
|
// q6asm_exit();
|
||||||
afe_exit();
|
// afe_exit();
|
||||||
spk_params_exit();
|
// spk_params_exit();
|
||||||
adm_exit();
|
// adm_exit();
|
||||||
rtac_exit();
|
// rtac_exit();
|
||||||
audio_cal_exit();
|
// audio_cal_exit();
|
||||||
adsp_err_exit();
|
// adsp_err_exit();
|
||||||
voice_mhi_exit();
|
// voice_mhi_exit();
|
||||||
}
|
}
|
||||||
|
|
||||||
module_init(audio_q6_init);
|
module_init(audio_q6_init);
|
||||||
|
@@ -5,94 +5,7 @@
|
|||||||
|
|
||||||
#ifndef __Q6_INIT_H__
|
#ifndef __Q6_INIT_H__
|
||||||
#define __Q6_INIT_H__
|
#define __Q6_INIT_H__
|
||||||
int adsp_err_init(void);
|
//int msm_audio_ion_init(void);
|
||||||
int adm_init(void);
|
//void msm_audio_ion_exit(void);
|
||||||
int afe_init(void);
|
|
||||||
int q6asm_init(void);
|
|
||||||
int q6lsm_init(void);
|
|
||||||
int voice_init(void);
|
|
||||||
int audio_cal_init(void);
|
|
||||||
int core_init(void);
|
|
||||||
int rtac_init(void);
|
|
||||||
int msm_audio_ion_init(void);
|
|
||||||
#if IS_ENABLED(CONFIG_MSM_AVTIMER)
|
|
||||||
int avtimer_init(void);
|
|
||||||
#else
|
|
||||||
static inline int avtimer_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_MSM_MDF
|
|
||||||
int msm_mdf_init(void);
|
|
||||||
void msm_mdf_exit(void);
|
|
||||||
#else
|
|
||||||
static inline int msm_mdf_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void msm_mdf_exit(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_XT_LOGGING
|
|
||||||
int spk_params_init(void);
|
|
||||||
void spk_params_exit(void);
|
|
||||||
#else
|
|
||||||
static inline int spk_params_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
static inline void spk_params_exit(void)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if IS_ENABLED(CONFIG_MSM_AVTIMER)
|
|
||||||
void avtimer_exit(void);
|
|
||||||
#else
|
|
||||||
static inline void avtimer_exit(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
void msm_audio_ion_exit(void);
|
|
||||||
void rtac_exit(void);
|
|
||||||
void core_exit(void);
|
|
||||||
void audio_cal_exit(void);
|
|
||||||
void voice_exit(void);
|
|
||||||
void q6lsm_exit(void);
|
|
||||||
void q6asm_exit(void);
|
|
||||||
void afe_exit(void);
|
|
||||||
void adm_exit(void);
|
|
||||||
void adsp_err_exit(void);
|
|
||||||
#if IS_ENABLED(CONFIG_WCD9XXX_CODEC_CORE)
|
|
||||||
int audio_slimslave_init(void);
|
|
||||||
void audio_slimslave_exit(void);
|
|
||||||
#else
|
|
||||||
static inline int audio_slimslave_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
};
|
|
||||||
static inline void audio_slimslave_exit(void)
|
|
||||||
{
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
#ifdef CONFIG_VOICE_MHI
|
|
||||||
int voice_mhi_init(void);
|
|
||||||
void voice_mhi_exit(void);
|
|
||||||
#else
|
|
||||||
static inline int voice_mhi_init(void)
|
|
||||||
{
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline void voice_mhi_exit(void)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
499
include/dsp/audio_prm.h
Normal file
499
include/dsp/audio_prm.h
Normal file
@@ -0,0 +1,499 @@
|
|||||||
|
/* Copyright (c) 2019-2020, 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
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __AUDIO_PRM_H__
|
||||||
|
#define __AUDIO_PRM_H__
|
||||||
|
|
||||||
|
#define PRM_MODULE_INSTANCE_ID 0x00000002
|
||||||
|
|
||||||
|
/* Request and release response payload of the #PRM_CMD_RSP_REQUEST_HW_RSC
|
||||||
|
* and PRM_CMD_RSP_ RELEASE_HW_RSC commands respectively.
|
||||||
|
* This is sent in response to request and release common payload commands.
|
||||||
|
*/
|
||||||
|
struct prm_rsp_req_rel_hw_rsc {
|
||||||
|
/* ID of the resource being requested. The supported values
|
||||||
|
* are HW_RSC_ID_AUDIO_HW_CLK and HW_RSC_ID_LPASS_CORE_CLK.
|
||||||
|
*/
|
||||||
|
uint32_t param_id;
|
||||||
|
|
||||||
|
/* Overall command response status with value 0 for success and non-zero
|
||||||
|
* value for command failure. In case of partial or complete command
|
||||||
|
* failure, this field is followed by resource specific response payload.
|
||||||
|
*/
|
||||||
|
uint32_t status;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Clock configuration structure for request */
|
||||||
|
struct clk_cfg {
|
||||||
|
/* Unique ID of the clock being requested. */
|
||||||
|
uint32_t clk_id;
|
||||||
|
/* Clock frequency in Hz. */
|
||||||
|
uint32_t clk_freq_in_hz;
|
||||||
|
/* Clock attributes with values
|
||||||
|
* 0:invalid
|
||||||
|
* 1:CLOCK_ATTR_NO_COUPLING
|
||||||
|
* 2:CLOCK_ATTR_COUPLE_DIVIDEND
|
||||||
|
* 3:CLOCK_ATTR_COUPLE_DIVISOR
|
||||||
|
* 4:CLOCK_ATTR_INVERT_NO_COUPLING*/
|
||||||
|
uint32_t clk_attri;
|
||||||
|
/* Clock root for this clock with 0 as DEFAULT. */
|
||||||
|
uint32_t clk_root;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Below payload is used to report failed clock ID's and error code. */
|
||||||
|
struct hw_rsc_clk_req_rel_rsp {
|
||||||
|
/* Number of failures while requesting for 1 or more clock IDs. */
|
||||||
|
uint32_t num_failures;
|
||||||
|
};
|
||||||
|
|
||||||
|
/* Clock status structure for response payload */
|
||||||
|
struct clock_status {
|
||||||
|
/* ID of the clock being requested as part of the REQUEST
|
||||||
|
* command and resulted in failure.
|
||||||
|
*/
|
||||||
|
uint32_t clock_id;
|
||||||
|
|
||||||
|
/* Error code corresponding to failure occurred while
|
||||||
|
* requesting this clock ID.
|
||||||
|
*/
|
||||||
|
uint32_t status;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef struct apm_cmd_header_t
|
||||||
|
{
|
||||||
|
uint32_t payload_address_lsw;
|
||||||
|
/**< Lower 32 bits of the payload address. */
|
||||||
|
uint32_t payload_address_msw;
|
||||||
|
/**< Upper 32 bits of the payload address.
|
||||||
|
|
||||||
|
The 64-bit number formed by payload_address_lsw and
|
||||||
|
payload_address_msw must be aligned to a 32-byte boundary and be in
|
||||||
|
contiguous memory.
|
||||||
|
|
||||||
|
@values
|
||||||
|
- For a 32-bit shared memory address, this field must be set to 0.
|
||||||
|
- For a 36-bit shared memory address, bits 31 to 4 of this field must
|
||||||
|
be set to 0. @tablebulletend */
|
||||||
|
uint32_t mem_map_handle;
|
||||||
|
/**< Unique identifier for a shared memory address.
|
||||||
|
|
||||||
|
@values
|
||||||
|
- NULL -- The message is in the payload (in-band).
|
||||||
|
- Non-NULL -- The parameter data payload begins at the address
|
||||||
|
specified by a pointer to the physical address of the payload in
|
||||||
|
shared memory (out-of-band).
|
||||||
|
@contcell
|
||||||
|
The aDSP returns this memory map handle through
|
||||||
|
#apm_CMD_SHARED_MEM_MAP_REGIONS.
|
||||||
|
|
||||||
|
An optional field is available if parameter data is in-band:
|
||||||
|
%afe_port_param_data_v2_t param_data[...].
|
||||||
|
See <b>Parameter data variable payload</b>. */
|
||||||
|
|
||||||
|
uint32_t payload_size;
|
||||||
|
/**< Actual size of the variable payload accompanying the message or in
|
||||||
|
shared memory. This field is used for parsing both in-band and
|
||||||
|
out-of-band data.
|
||||||
|
|
||||||
|
@values > 0 bytes, in multiples of 4 bytes */
|
||||||
|
}apm_cmd_header_t;
|
||||||
|
|
||||||
|
typedef struct apm_module_param_data_t
|
||||||
|
{
|
||||||
|
uint32_t module_instance_id;
|
||||||
|
/**< Valid instance ID of module
|
||||||
|
@values */
|
||||||
|
|
||||||
|
uint32_t param_id;
|
||||||
|
/**< Valid ID of the parameter.
|
||||||
|
|
||||||
|
@values See Chapter */
|
||||||
|
|
||||||
|
uint32_t param_size;
|
||||||
|
/**< Size of the parameter data based upon the
|
||||||
|
module_instance_id/param_id combination.
|
||||||
|
@values > 0 bytes, in multiples of
|
||||||
|
4 bytes at least */
|
||||||
|
|
||||||
|
uint32_t error_code;
|
||||||
|
/**< Error code populated by the entity hosting the module.
|
||||||
|
Applicable only for out-of-band command mode */
|
||||||
|
}apm_module_param_data_t;
|
||||||
|
|
||||||
|
typedef struct audio_hw_clk_cfg_req_param_t
|
||||||
|
{
|
||||||
|
uint32_t num_clock_id;
|
||||||
|
/**< Number of clock ID's being configured */
|
||||||
|
}audio_hw_clk_cfg_req_param_t;
|
||||||
|
|
||||||
|
typedef struct audio_hw_clk_cfg_t
|
||||||
|
{
|
||||||
|
uint32_t clock_id;
|
||||||
|
/**< Unique Clock ID of the clock being requested */
|
||||||
|
|
||||||
|
uint32_t clock_freq;
|
||||||
|
/**< Clock frequency in Hz to set. */
|
||||||
|
|
||||||
|
uint32_t clock_attri;
|
||||||
|
/**< Divider for two clocks that are coupled, if necessary:
|
||||||
|
divider = A/B, where A is the dividend and B is the divisor.
|
||||||
|
@values
|
||||||
|
- #_CLOCK_ATTRIBUTE_COUPLE_NO -- For no divider-related clocks
|
||||||
|
- #_CLOCK_ATTRIBUTE_COUPLE_DIVIDEND
|
||||||
|
- #_CLOCK_ATTRIBUTE_COUPLE_DIVISOR
|
||||||
|
- #_CLOCK_ATTRIBUTE_INVERT_COUPLE_NO */
|
||||||
|
|
||||||
|
uint32_t clock_root;
|
||||||
|
/**< Root clock source.
|
||||||
|
@values #_CLOCK_ROOT_DEFAULT
|
||||||
|
Currently, only _CLOCK_ROOT_DEFAULT is valid. */
|
||||||
|
}audio_hw_clk_cfg_t;
|
||||||
|
|
||||||
|
typedef struct audio_hw_clk_rel_cfg_t
|
||||||
|
{
|
||||||
|
uint32_t clock_id;
|
||||||
|
}audio_hw_clk_rel_cfg_t;
|
||||||
|
|
||||||
|
#define MAX_AUD_HW_CLK_NUM_REQ 1
|
||||||
|
|
||||||
|
typedef struct prm_cmd_request_rsc_t
|
||||||
|
{
|
||||||
|
apm_cmd_header_t payload_header;
|
||||||
|
apm_module_param_data_t module_payload_0;
|
||||||
|
audio_hw_clk_cfg_req_param_t num_clk_id_t;
|
||||||
|
audio_hw_clk_cfg_t clock_ids_t[MAX_AUD_HW_CLK_NUM_REQ];
|
||||||
|
}prm_cmd_request_rsc_t;
|
||||||
|
|
||||||
|
typedef struct prm_cmd_release_rsc_t
|
||||||
|
{
|
||||||
|
apm_cmd_header_t payload_header;
|
||||||
|
apm_module_param_data_t module_payload_0;
|
||||||
|
audio_hw_clk_cfg_req_param_t num_clk_id_t;
|
||||||
|
audio_hw_clk_rel_cfg_t clock_ids_t[MAX_AUD_HW_CLK_NUM_REQ];
|
||||||
|
}prm_cmd_release_rsc_t;
|
||||||
|
|
||||||
|
|
||||||
|
#define PRM_CMD_REQUEST_HW_RSC 0x0100100F
|
||||||
|
|
||||||
|
#define PRM_CMD_RELEASE_HW_RSC 0x01001010
|
||||||
|
|
||||||
|
#define PRM_CMD_RSP_REQUEST_HW_RSC 0x02001002
|
||||||
|
|
||||||
|
#define PRM_CMD_RSP_RELEASE_HW_RSC 0x02001003
|
||||||
|
|
||||||
|
/* Param ID for audio hardware clock */
|
||||||
|
|
||||||
|
#define PARAM_ID_RSC_AUDIO_HW_CLK 0x0800102C
|
||||||
|
|
||||||
|
/* Param ID for lpass core clock */
|
||||||
|
|
||||||
|
#define PARAM_ID_RSC_LPASS_CORE 0x0800102B
|
||||||
|
|
||||||
|
#define HW_RSC_ID_AUDIO_HW_CLK 0x0800102C
|
||||||
|
|
||||||
|
/* Supported OSR clock values */
|
||||||
|
#define OSR_CLOCK_12_P288_MHZ 0xBB8000
|
||||||
|
#define OSR_CLOCK_11_P2896_MHZ 0xAC4400
|
||||||
|
#define OSR_CLOCK_9_P600_MHZ 0x927C00
|
||||||
|
#define OSR_CLOCK_8_P192_MHZ 0x7D0000
|
||||||
|
#define OSR_CLOCK_6_P144_MHZ 0x5DC000
|
||||||
|
#define OSR_CLOCK_4_P096_MHZ 0x3E8000
|
||||||
|
#define OSR_CLOCK_3_P072_MHZ 0x2EE000
|
||||||
|
#define OSR_CLOCK_2_P048_MHZ 0x1F4000
|
||||||
|
#define OSR_CLOCK_1_P536_MHZ 0x177000
|
||||||
|
#define OSR_CLOCK_1_P024_MHZ 0xFA000
|
||||||
|
#define OSR_CLOCK_768_kHZ 0xBB800
|
||||||
|
#define OSR_CLOCK_512_kHZ 0x7D000
|
||||||
|
#define OSR_CLOCK_DISABLE 0x0
|
||||||
|
|
||||||
|
/* Supported Bit clock values */
|
||||||
|
#define IBIT_CLOCK_12_P288_MHZ 0xBB8000
|
||||||
|
#define IBIT_CLOCK_11_P2896_MHZ 0xAC4400
|
||||||
|
#define IBIT_CLOCK_8_P192_MHZ 0x7D0000
|
||||||
|
#define IBIT_CLOCK_6_P144_MHZ 0x5DC000
|
||||||
|
#define IBIT_CLOCK_4_P096_MHZ 0x3E8000
|
||||||
|
#define IBIT_CLOCK_3_P072_MHZ 0x2EE000
|
||||||
|
#define IBIT_CLOCK_2_P8224_MHZ 0x2b1100
|
||||||
|
#define IBIT_CLOCK_2_P048_MHZ 0x1F4000
|
||||||
|
#define IBIT_CLOCK_1_P536_MHZ 0x177000
|
||||||
|
#define IBIT_CLOCK_1_P4112_MHZ 0x158880
|
||||||
|
#define IBIT_CLOCK_1_P024_MHZ 0xFA000
|
||||||
|
#define IBIT_CLOCK_768_KHZ 0xBB800
|
||||||
|
#define IBIT_CLOCK_512_KHZ 0x7D000
|
||||||
|
#define IBIT_CLOCK_256_KHZ 0x3E800
|
||||||
|
#define IBIT_CLOCK_DISABLE 0x0
|
||||||
|
|
||||||
|
/** Clock ID of the primary MI2S internal bit clock (IBIT). */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_MI2S_IBIT 0x100
|
||||||
|
|
||||||
|
/** Clock ID of the primary MI2S external bit clock (EBIT). */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_MI2S_EBIT 0x101
|
||||||
|
|
||||||
|
/** Clock ID of the secondary MI2S IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_MI2S_IBIT 0x102
|
||||||
|
|
||||||
|
/** Clock ID of the secondary MI2S EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_MI2S_EBIT 0x103
|
||||||
|
|
||||||
|
/** Clock ID of the tertiary MI2S IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_MI2S_IBIT 0x104
|
||||||
|
|
||||||
|
/** Clock ID of the tertiary MI2S EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_MI2S_EBIT 0x105
|
||||||
|
|
||||||
|
/** Clock ID of the quaternary MI2S IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_MI2S_IBIT 0x106
|
||||||
|
|
||||||
|
/** Clock ID of the quaternary MI2S EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_MI2S_EBIT 0x107
|
||||||
|
|
||||||
|
/** Clock ID of the quinary MI2S IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_MI2S_IBIT 0x108
|
||||||
|
|
||||||
|
/** Clock ID of the quinary MI2S EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_MI2S_EBIT 0x109
|
||||||
|
|
||||||
|
/** Clock ID of the quinary MI2S OSR. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_MI2S_OSR 0x10A
|
||||||
|
|
||||||
|
/** Clock ID of the senary MI2S IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_MI2S_IBIT 0x10B
|
||||||
|
|
||||||
|
/** Clock ID of the senary MI2S EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_MI2S_EBIT 0x10C
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 0 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT0_I2S_IBIT 0x10D
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 1 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT1_I2S_IBIT 0x10E
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 2 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT2_I2S_IBIT 0x10F
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 3 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT3_I2S_IBIT 0x110
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 4 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT4_I2S_IBIT 0x111
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 5 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT5_I2S_IBIT 0x112
|
||||||
|
|
||||||
|
/** ID of I2S IBIT clock 6 that is used with integrated codec. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_INT6_I2S_IBIT 0x113
|
||||||
|
|
||||||
|
/** Clock ID of the primary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_PCM_IBIT 0x200
|
||||||
|
|
||||||
|
/** Clock ID of the primary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_PCM_EBIT 0x201
|
||||||
|
|
||||||
|
/** Clock ID of the secondary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_PCM_IBIT 0x202
|
||||||
|
|
||||||
|
/** Clock ID of the secondary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_PCM_EBIT 0x203
|
||||||
|
|
||||||
|
/** Clock ID of the tertiary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_PCM_IBIT 0x204
|
||||||
|
|
||||||
|
/** Clock ID of the tertiary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_PCM_EBIT 0x205
|
||||||
|
|
||||||
|
/** Clock ID of the quaternary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_PCM_IBIT 0x206
|
||||||
|
|
||||||
|
/** Clock ID of the quaternary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_PCM_EBIT 0x207
|
||||||
|
|
||||||
|
/** Clock ID of the quinary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_PCM_IBIT 0x208
|
||||||
|
|
||||||
|
/** Clock ID of the quinary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_PCM_EBIT 0x209
|
||||||
|
|
||||||
|
/** Clock ID of the quinary PCM OSR. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_PCM_OSR 0x20A
|
||||||
|
|
||||||
|
/** Clock ID of the senary PCM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_PCM_IBIT 0x20B
|
||||||
|
|
||||||
|
/** Clock ID of the senary PCM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_PCM_EBIT 0x20C
|
||||||
|
|
||||||
|
/** Clock ID for the primary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_TDM_IBIT 0x200
|
||||||
|
|
||||||
|
/** Clock ID for the primary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_TDM_EBIT 0x201
|
||||||
|
|
||||||
|
/** Clock ID for the secondary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_TDM_IBIT 0x202
|
||||||
|
|
||||||
|
/** Clock ID for the secondary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_TDM_EBIT 0x203
|
||||||
|
|
||||||
|
/** Clock ID for the tertiary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_TDM_IBIT 0x204
|
||||||
|
|
||||||
|
/** Clock ID for the tertiary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_TER_TDM_EBIT 0x205
|
||||||
|
|
||||||
|
/** Clock ID for the quaternary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_TDM_IBIT 0x206
|
||||||
|
|
||||||
|
/** Clock ID for the quaternary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUAD_TDM_EBIT 0x207
|
||||||
|
|
||||||
|
/** Clock ID for the quinary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_TDM_IBIT 0x208
|
||||||
|
|
||||||
|
/** Clock ID for the quinary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_TDM_EBIT 0x209
|
||||||
|
|
||||||
|
/** Clock ID for the quinary TDM OSR. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_QUI_TDM_OSR 0x20A
|
||||||
|
|
||||||
|
/** Clock ID for the senary TDM IBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_TDM_IBIT 0x20B
|
||||||
|
|
||||||
|
/** Clock ID for the senary TDM EBIT. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEN_TDM_EBIT 0x20C
|
||||||
|
|
||||||
|
/** Clock ID for MCLK 1. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_MCLK_1 0x300
|
||||||
|
|
||||||
|
/** Clock ID for MCLK 2. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_MCLK_2 0x301
|
||||||
|
|
||||||
|
/** Clock ID for MCLK 3. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_MCLK_3 0x302
|
||||||
|
|
||||||
|
/** Clock ID for MCLK 4. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_MCLK_4 0x303
|
||||||
|
|
||||||
|
/** Clock ID for MCLK 5. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_MCLK_5 0x304
|
||||||
|
|
||||||
|
/** Clock ID for MCLK for WSA core */
|
||||||
|
|
||||||
|
#define CLOCK_ID_WSA_CORE_MCLK 0x305
|
||||||
|
|
||||||
|
/** Clock ID for NPL MCLK for WSA core */
|
||||||
|
|
||||||
|
#define CLOCK_ID_WSA_CORE_NPL_MCLK 0x306
|
||||||
|
|
||||||
|
/** Clock ID for 2X WSA MCLK (2X MCLK or NPL MCLK, both are same) */
|
||||||
|
|
||||||
|
#define CLOCK_ID_WSA_CORE_2X_MCLK CLOCK_ID_WSA_CORE_NPL_MCLK
|
||||||
|
|
||||||
|
/** Clock ID for MCLK for VA core */
|
||||||
|
|
||||||
|
#define CLOCK_ID_VA_CORE_MCLK 0x307
|
||||||
|
|
||||||
|
/** Clock ID for the primary SPDIF output core. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_SPDIF_OUTPUT_CORE 0x400
|
||||||
|
|
||||||
|
/** Clock ID for the secondary SPDIF output core. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_SPDIF_OUTPUT_CORE 0x401
|
||||||
|
|
||||||
|
/** Clock ID for the primary SPDIF input core. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_SPDIF_INPUT_CORE 0x402
|
||||||
|
|
||||||
|
/** Clock ID for the secondary SPDIF input core. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_SPDIF_INPUT_CORE 0x403
|
||||||
|
|
||||||
|
/** Clock ID for the secondary SPDIF output NPL clk. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_PRI_SPDIF_OUTPUT_NPL 0x404
|
||||||
|
|
||||||
|
/** Clock ID for the primary SPDIF output NPL clk. */
|
||||||
|
|
||||||
|
#define CLOCK_ID_SEC_SPDIF_OUTPUT_NPL 0x405
|
||||||
|
|
||||||
|
/** Clock attribute is invalid (reserved for internal use). */
|
||||||
|
#define CLOCK_ATTRIBUTE_INVALID 0x0
|
||||||
|
|
||||||
|
/** Clock attribute for no coupled clocks. */
|
||||||
|
#define CLOCK_ATTRIBUTE_COUPLE_NO 0x1
|
||||||
|
|
||||||
|
/** Clock attribute for the dividend of the coupled clocks. */
|
||||||
|
#define CLOCK_ATTRIBUTE_COUPLE_DIVIDEND 0x2
|
||||||
|
|
||||||
|
/** Clock attribute for the divisor of the coupled clocks. */
|
||||||
|
#define CLOCK_ATTRIBUTE_COUPLE_DIVISOR 0x3
|
||||||
|
|
||||||
|
/** Clock attribute for the invert-and-no-couple case. */
|
||||||
|
#define CLOCK_ATTRIBUTE_INVERT_COUPLE_NO 0x4
|
||||||
|
|
||||||
|
/** Default root clock source. */
|
||||||
|
#define CLOCK_ROOT_DEFAULT 0x0
|
||||||
|
|
||||||
|
int audio_prm_set_lpass_clk_cfg(struct clk_cfg *cfg, uint8_t enable);
|
||||||
|
|
||||||
|
#endif
|
19
include/dsp/gecko-core.h
Normal file
19
include/dsp/gecko-core.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/* Copyright (c) 2019-2020, 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
|
||||||
|
* only version 2 as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __GECKO_CORE_H__
|
||||||
|
#define __GECKO_CORE_H__
|
||||||
|
#include <ipc/gpr-lite.h>
|
||||||
|
|
||||||
|
bool gecko_core_is_apm_ready(void);
|
||||||
|
|
||||||
|
#endif
|
@@ -1,20 +1,32 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2013-2015, 2017-2019, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2013-2015, 2017-2020, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef _LINUX_MSM_AUDIO_ION_H
|
#ifndef _LINUX_MSM_AUDIO_ION_H
|
||||||
#define _LINUX_MSM_AUDIO_ION_H
|
#define _LINUX_MSM_AUDIO_ION_H
|
||||||
#include <dsp/q6asm-v2.h>
|
|
||||||
#include <sound/pcm.h>
|
#include <sound/pcm.h>
|
||||||
#include <linux/msm_ion.h>
|
#include <linux/msm_ion.h>
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
|
|
||||||
|
enum {
|
||||||
|
HLOS_TO_ADSP = 1,
|
||||||
|
ADSP_TO_HLOS,
|
||||||
|
};
|
||||||
|
#define VMID_CP_ADSP_SHARED 33
|
||||||
enum {
|
enum {
|
||||||
MSM_AUDIO_ION_INV_CACHES = 0,
|
MSM_AUDIO_ION_INV_CACHES = 0,
|
||||||
MSM_AUDIO_ION_CLEAN_CACHES,
|
MSM_AUDIO_ION_CLEAN_CACHES,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct audio_buffer {
|
||||||
|
dma_addr_t phys;
|
||||||
|
void *data;
|
||||||
|
uint32_t used;
|
||||||
|
uint32_t size;/* size of buffer */
|
||||||
|
uint32_t actual_size; /* actual number of bytes read by DSP */
|
||||||
|
struct dma_buf *dma_buf;
|
||||||
|
};
|
||||||
int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
|
int msm_audio_ion_alloc(struct dma_buf **dma_buf, size_t bufsz,
|
||||||
dma_addr_t *paddr, size_t *pa_len, void **vaddr);
|
dma_addr_t *paddr, size_t *pa_len, void **vaddr);
|
||||||
|
|
||||||
@@ -30,4 +42,11 @@ int msm_audio_ion_get_smmu_info(struct device **cb_dev, u64 *smmu_sid);
|
|||||||
|
|
||||||
int msm_audio_ion_dma_map(dma_addr_t *phys_addr, dma_addr_t *iova_base,
|
int msm_audio_ion_dma_map(dma_addr_t *phys_addr, dma_addr_t *iova_base,
|
||||||
u32 size, enum dma_data_direction dir);
|
u32 size, enum dma_data_direction dir);
|
||||||
|
int msm_audio_ion_phys_assign(void **mem_hdl, int fd, dma_addr_t *paddr,
|
||||||
|
size_t *pa_len, u8 assign_type, int id);
|
||||||
|
int msm_audio_ion_phys_free(void *mem_hdl, dma_addr_t *paddr,
|
||||||
|
size_t *pa_len, u8 assign_type, int id, int key);
|
||||||
|
bool msm_audio_is_hypervisor_supported(void);
|
||||||
|
int msm_audio_get_phy_addr(int fd, dma_addr_t *paddr);
|
||||||
|
void msm_audio_ion_crash_handler(void);
|
||||||
#endif /* _LINUX_MSM_AUDIO_ION_H */
|
#endif /* _LINUX_MSM_AUDIO_ION_H */
|
||||||
|
@@ -90,11 +90,8 @@
|
|||||||
struct msm_acdb_cmd_device)
|
struct msm_acdb_cmd_device)
|
||||||
#define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \
|
#define AUDIO_GET_ACDB_BLK _IOW(AUDIO_IOCTL_MAGIC, 96, \
|
||||||
struct msm_acdb_cmd_device)
|
struct msm_acdb_cmd_device)
|
||||||
|
#define IOCTL_MAP_PHYS_ADDR _IOW(AUDIO_IOCTL_MAGIC, 97, int)
|
||||||
#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 97, \
|
#define IOCTL_UNMAP_PHYS_ADDR _IOW(AUDIO_IOCTL_MAGIC, 98, int)
|
||||||
struct msm_audio_ion_info)
|
|
||||||
#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 98, \
|
|
||||||
struct msm_audio_ion_info)
|
|
||||||
#define AUDIO_SET_EFFECTS_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 99, \
|
#define AUDIO_SET_EFFECTS_CONFIG _IOW(AUDIO_IOCTL_MAGIC, 99, \
|
||||||
struct msm_hwacc_effects_config)
|
struct msm_hwacc_effects_config)
|
||||||
#define AUDIO_EFFECTS_SET_BUF_LEN _IOW(AUDIO_IOCTL_MAGIC, 100, \
|
#define AUDIO_EFFECTS_SET_BUF_LEN _IOW(AUDIO_IOCTL_MAGIC, 100, \
|
||||||
@@ -107,8 +104,9 @@
|
|||||||
|
|
||||||
#define AUDIO_PM_AWAKE _IOW(AUDIO_IOCTL_MAGIC, 105, unsigned int)
|
#define AUDIO_PM_AWAKE _IOW(AUDIO_IOCTL_MAGIC, 105, unsigned int)
|
||||||
#define AUDIO_PM_RELAX _IOW(AUDIO_IOCTL_MAGIC, 106, unsigned int)
|
#define AUDIO_PM_RELAX _IOW(AUDIO_IOCTL_MAGIC, 106, unsigned int)
|
||||||
|
#define AUDIO_REGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 107, struct msm_audio_ion_info)
|
||||||
#define AUDIO_MAX_COMMON_IOCTL_NUM 107
|
#define AUDIO_DEREGISTER_ION _IOW(AUDIO_IOCTL_MAGIC, 108, struct msm_audio_ion_info)
|
||||||
|
#define AUDIO_MAX_COMMON_IOCTL_NUM 109
|
||||||
|
|
||||||
|
|
||||||
#define HANDSET_MIC 0x01
|
#define HANDSET_MIC 0x01
|
||||||
|
Reference in New Issue
Block a user