msm: eva: propagate tip of CVP driver to EVA
Merge cvp driver to EVA Change-Id: I3fb962bfae750f49f821c16061bd78fa5425959e Signed-off-by: George Shen <sqiao@codeaurora.org>
This commit is contained in:
@@ -148,9 +148,13 @@ struct cvp_kmd_hfi_packet {
|
|||||||
#define CVP_KMD_PROP_PWR_FW_OP 0x1B
|
#define CVP_KMD_PROP_PWR_FW_OP 0x1B
|
||||||
#define CVP_KMD_PROP_PWR_DDR_OP 0x1C
|
#define CVP_KMD_PROP_PWR_DDR_OP 0x1C
|
||||||
#define CVP_KMD_PROP_PWR_SYSCACHE_OP 0x1D
|
#define CVP_KMD_PROP_PWR_SYSCACHE_OP 0x1D
|
||||||
|
#define CVP_KMD_PROP_PWR_FPS_FDU 0x1E
|
||||||
|
#define CVP_KMD_PROP_PWR_FPS_MPU 0x1F
|
||||||
|
#define CVP_KMD_PROP_PWR_FPS_OD 0x20
|
||||||
|
#define CVP_KMD_PROP_PWR_FPS_ICA 0x21
|
||||||
|
|
||||||
#define MAX_KMD_PROP_NUM_PER_PACKET 8
|
#define MAX_KMD_PROP_NUM_PER_PACKET 8
|
||||||
#define MAX_KMD_PROP_TYPE (CVP_KMD_PROP_PWR_SYSCACHE_OP + 1)
|
#define MAX_KMD_PROP_TYPE (CVP_KMD_PROP_PWR_FPS_ICA + 1)
|
||||||
|
|
||||||
struct cvp_kmd_sys_property {
|
struct cvp_kmd_sys_property {
|
||||||
__u32 prop_type;
|
__u32 prop_type;
|
||||||
@@ -159,7 +163,7 @@ struct cvp_kmd_sys_property {
|
|||||||
|
|
||||||
struct cvp_kmd_sys_properties {
|
struct cvp_kmd_sys_properties {
|
||||||
__u32 prop_num;
|
__u32 prop_num;
|
||||||
struct cvp_kmd_sys_property prop_data[8];
|
struct cvp_kmd_sys_property prop_data[MAX_KMD_PROP_NUM_PER_PACKET];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define SESSION_CREATE 1
|
#define SESSION_CREATE 1
|
||||||
|
@@ -18,7 +18,8 @@ msm-eva-objs := eva/cvp.o \
|
|||||||
eva/msm_cvp_clocks.o\
|
eva/msm_cvp_clocks.o\
|
||||||
eva/msm_cvp_dsp.o \
|
eva/msm_cvp_dsp.o \
|
||||||
eva/msm_cvp_buf.o \
|
eva/msm_cvp_buf.o \
|
||||||
eva/msm_cvp_synx.o
|
eva/msm_cvp_synx.o \
|
||||||
|
eva/cvp_fw_load.o
|
||||||
|
|
||||||
obj-$(CONFIG_MSM_EVA) := msm-eva.o
|
obj-$(CONFIG_MSM_EVA) := msm-eva.o
|
||||||
|
|
||||||
|
@@ -107,6 +107,17 @@ static int read_platform_resources(struct msm_cvp_core *core,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void init_cycle_info(struct cvp_cycle_info *info)
|
||||||
|
{
|
||||||
|
memset(info->sum_fps, 0, HFI_MAX_HW_THREADS*sizeof(u32));
|
||||||
|
memset(info->hi_ctrl_lim, 0, HFI_MAX_HW_THREADS*sizeof(u32));
|
||||||
|
memset(info->lo_ctrl_lim, 0, HFI_MAX_HW_THREADS*sizeof(u32));
|
||||||
|
memset(info->cycle, 0,
|
||||||
|
HFI_MAX_HW_THREADS*sizeof(struct cvp_cycle_stat));
|
||||||
|
info->conf_freq = 0;
|
||||||
|
mutex_init(&info->lock);
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_cvp_initialize_core(struct platform_device *pdev,
|
static int msm_cvp_initialize_core(struct platform_device *pdev,
|
||||||
struct msm_cvp_core *core)
|
struct msm_cvp_core *core)
|
||||||
{
|
{
|
||||||
@@ -132,6 +143,7 @@ static int msm_cvp_initialize_core(struct platform_device *pdev,
|
|||||||
|
|
||||||
INIT_DELAYED_WORK(&core->fw_unload_work, msm_cvp_fw_unload_handler);
|
INIT_DELAYED_WORK(&core->fw_unload_work, msm_cvp_fw_unload_handler);
|
||||||
INIT_WORK(&core->ssr_work, msm_cvp_ssr_handler);
|
INIT_WORK(&core->ssr_work, msm_cvp_ssr_handler);
|
||||||
|
init_cycle_info(&core->dyn_clk);
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
@@ -490,6 +502,7 @@ static int msm_cvp_remove(struct platform_device *pdev)
|
|||||||
sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group);
|
sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group);
|
||||||
dev_set_drvdata(&pdev->dev, NULL);
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
mutex_destroy(&core->lock);
|
mutex_destroy(&core->lock);
|
||||||
|
mutex_destroy(&core->dyn_clk.lock);
|
||||||
kfree(core);
|
kfree(core);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -268,4 +268,6 @@ int cvp_iris_hfi_initialize(struct cvp_hfi_device *hdev, u32 device_id,
|
|||||||
struct msm_cvp_platform_resources *res,
|
struct msm_cvp_platform_resources *res,
|
||||||
hfi_cmd_response_callback callback);
|
hfi_cmd_response_callback callback);
|
||||||
|
|
||||||
|
int load_cvp_fw_impl(struct iris_hfi_device *device);
|
||||||
|
int unload_cvp_fw_impl(struct iris_hfi_device *device);
|
||||||
#endif
|
#endif
|
||||||
|
166
msm/eva/cvp_fw_load.c
Normal file
166
msm/eva/cvp_fw_load.c
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2020, The Linux Foundation. All rights reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/pm_qos.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/qcom_scm.h>
|
||||||
|
#include "msm_cvp_debug.h"
|
||||||
|
#include "cvp_comm_def.h"
|
||||||
|
#include "cvp_core_hfi.h"
|
||||||
|
#include "cvp_hfi.h"
|
||||||
|
#ifdef CVP_MDT_ENABLED
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/firmware.h>
|
||||||
|
#include <linux/soc/qcom/mdt_loader.h>
|
||||||
|
#else
|
||||||
|
#include <soc/qcom/subsystem_restart.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define MAX_FIRMWARE_NAME_SIZE 128
|
||||||
|
|
||||||
|
#ifdef CVP_MDT_ENABLED
|
||||||
|
static int __load_fw_to_memory(struct platform_device *pdev,
|
||||||
|
const char *fw_name)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
const struct firmware *firmware = NULL;
|
||||||
|
char firmware_name[MAX_FIRMWARE_NAME_SIZE] = {0};
|
||||||
|
struct device_node *node = NULL;
|
||||||
|
struct resource res = {0};
|
||||||
|
phys_addr_t phys = 0;
|
||||||
|
size_t res_size = 0;
|
||||||
|
ssize_t fw_size = 0;
|
||||||
|
void *virt = NULL;
|
||||||
|
int pas_id = 0;
|
||||||
|
|
||||||
|
if (!fw_name || !(*fw_name) || !pdev) {
|
||||||
|
dprintk(CVP_ERR, "%s: Invalid inputs\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (strlen(fw_name) >= MAX_FIRMWARE_NAME_SIZE - 4) {
|
||||||
|
dprintk(CVP_ERR, "%s: Invalid fw name\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
scnprintf(firmware_name, ARRAY_SIZE(firmware_name), "%s.mdt", fw_name);
|
||||||
|
|
||||||
|
rc = of_property_read_u32(pdev->dev.of_node, "pas-id", &pas_id);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"%s: error %d while reading DT for \"pas-id\"\n",
|
||||||
|
__func__, rc);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0);
|
||||||
|
if (!node) {
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"%s: DT error getting \"memory-region\" property\n",
|
||||||
|
__func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = of_address_to_resource(node, 0, &res);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"%s: error %d getting \"memory-region\" resource\n",
|
||||||
|
__func__, rc);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
phys = res.start;
|
||||||
|
res_size = (size_t)resource_size(&res);
|
||||||
|
|
||||||
|
rc = request_firmware(&firmware, firmware_name, &pdev->dev);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR, "%s: error %d requesting \"%s\"\n",
|
||||||
|
__func__, rc, firmware_name);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
fw_size = qcom_mdt_get_size(firmware);
|
||||||
|
if (fw_size < 0 || res_size < (size_t)fw_size) {
|
||||||
|
rc = -EINVAL;
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"%s: Corrupted fw image. Alloc size: %lu, fw size: %ld",
|
||||||
|
__func__, res_size, fw_size);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
virt = memremap(phys, res_size, MEMREMAP_WC);
|
||||||
|
if (!virt) {
|
||||||
|
rc = -ENOMEM;
|
||||||
|
dprintk(CVP_ERR, "%s: unable to remap firmware memory\n",
|
||||||
|
__func__);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = qcom_mdt_load(&pdev->dev, firmware, firmware_name,
|
||||||
|
pas_id, virt, phys, res_size, NULL);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR, "%s: error %d loading \"%s\"\n",
|
||||||
|
__func__, rc, firmware_name);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
rc = qcom_scm_pas_auth_and_reset(pas_id);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR, "%s: error %d authenticating \"%s\"\n",
|
||||||
|
__func__, rc, firmware_name);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
memunmap(virt);
|
||||||
|
release_firmware(firmware);
|
||||||
|
dprintk(CVP_CORE, "%s: firmware \"%s\" loaded successfully\n",
|
||||||
|
__func__, firmware_name);
|
||||||
|
return pas_id;
|
||||||
|
|
||||||
|
exit:
|
||||||
|
if (virt)
|
||||||
|
memunmap(virt);
|
||||||
|
if (firmware)
|
||||||
|
release_firmware(firmware);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int load_cvp_fw_impl(struct iris_hfi_device *device)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
|
||||||
|
if (!device->resources.fw.cookie) {
|
||||||
|
#ifdef CVP_MDT_ENABLED
|
||||||
|
device->resources.fw.cookie =
|
||||||
|
__load_fw_to_memory(device->res->pdev,
|
||||||
|
device->res->fw_name);
|
||||||
|
if (device->resources.fw.cookie <= 0) {
|
||||||
|
dprintk(CVP_ERR, "Failed to download firmware\n");
|
||||||
|
device->resources.fw.cookie = 0;
|
||||||
|
rc = -ENOMEM;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
device->resources.fw.cookie =
|
||||||
|
subsystem_get_with_fwname("evass",
|
||||||
|
device->res->fw_name);
|
||||||
|
if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
|
||||||
|
dprintk(CVP_ERR, "Failed to download firmware\n");
|
||||||
|
device->resources.fw.cookie = NULL;
|
||||||
|
rc = -ENOMEM;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
int unload_cvp_fw_impl(struct iris_hfi_device *device)
|
||||||
|
{
|
||||||
|
#ifdef CVP_MDT_ENABLED
|
||||||
|
qcom_scm_pas_shutdown(device->resources.fw.cookie);
|
||||||
|
device->resources.fw.cookie = 0;
|
||||||
|
#else
|
||||||
|
subsystem_put(device->resources.fw.cookie);
|
||||||
|
device->resources.fw.cookie = NULL;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
@@ -21,7 +21,6 @@
|
|||||||
#include <linux/soc/qcom/llcc-qcom.h>
|
#include <linux/soc/qcom/llcc-qcom.h>
|
||||||
#include <linux/qcom_scm.h>
|
#include <linux/qcom_scm.h>
|
||||||
#include <linux/soc/qcom/smem.h>
|
#include <linux/soc/qcom/smem.h>
|
||||||
#include <soc/qcom/subsystem_restart.h>
|
|
||||||
#include <linux/dma-mapping.h>
|
#include <linux/dma-mapping.h>
|
||||||
#include <linux/reset.h>
|
#include <linux/reset.h>
|
||||||
#include "hfi_packetization.h"
|
#include "hfi_packetization.h"
|
||||||
@@ -304,6 +303,7 @@ static void power_off_iris2(struct iris_hfi_device *device);
|
|||||||
|
|
||||||
static int __set_ubwc_config(struct iris_hfi_device *device);
|
static int __set_ubwc_config(struct iris_hfi_device *device);
|
||||||
static void __noc_error_info_iris2(struct iris_hfi_device *device);
|
static void __noc_error_info_iris2(struct iris_hfi_device *device);
|
||||||
|
static int __enable_hw_power_collapse(struct iris_hfi_device *device);
|
||||||
|
|
||||||
static struct iris_hfi_vpu_ops iris2_ops = {
|
static struct iris_hfi_vpu_ops iris2_ops = {
|
||||||
.interrupt_init = interrupt_init_iris2,
|
.interrupt_init = interrupt_init_iris2,
|
||||||
@@ -364,9 +364,34 @@ int get_hfi_version(void)
|
|||||||
return hfi->version;
|
return hfi->version;
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_msg_size(void)
|
unsigned int get_msg_size(struct cvp_hfi_msg_session_hdr *hdr)
|
||||||
{
|
{
|
||||||
return sizeof(struct cvp_hfi_msg_session_hdr);
|
struct msm_cvp_core *core;
|
||||||
|
struct iris_hfi_device *device;
|
||||||
|
u32 minor_ver;
|
||||||
|
|
||||||
|
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||||
|
if (core)
|
||||||
|
device = core->device->hfi_device_data;
|
||||||
|
else
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
|
dprintk(CVP_ERR, "%s: NULL device\n", __func__);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
minor_ver = (device->version & HFI_VERSION_MINOR_MASK) >>
|
||||||
|
HFI_VERSION_MINOR_SHIFT;
|
||||||
|
|
||||||
|
if (minor_ver < 2)
|
||||||
|
return sizeof(struct cvp_hfi_msg_session_hdr);
|
||||||
|
|
||||||
|
if (hdr->packet_type == HFI_MSG_SESSION_CVP_FD)
|
||||||
|
return sizeof(struct cvp_hfi_msg_session_hdr_ext);
|
||||||
|
else
|
||||||
|
return sizeof(struct cvp_hfi_msg_session_hdr);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
unsigned int get_msg_session_id(void *msg)
|
unsigned int get_msg_session_id(void *msg)
|
||||||
@@ -1102,8 +1127,31 @@ static int __tzbsp_set_cvp_state(enum tzbsp_subsys_state state)
|
|||||||
|
|
||||||
static inline int __boot_firmware(struct iris_hfi_device *device)
|
static inline int __boot_firmware(struct iris_hfi_device *device)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0, loop = 10;
|
||||||
u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 1000;
|
u32 ctrl_init_val = 0, ctrl_status = 0, count = 0, max_tries = 1000;
|
||||||
|
u32 reg_gdsc;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Hand off control of regulators to h/w _after_ enabling clocks.
|
||||||
|
* Note that the GDSC will turn off when switching from normal
|
||||||
|
* (s/w triggered) to fast (HW triggered) unless the h/w vote is
|
||||||
|
* present. Since Iris isn't up yet, the GDSC will be off briefly.
|
||||||
|
*/
|
||||||
|
if (__enable_hw_power_collapse(device))
|
||||||
|
dprintk(CVP_ERR, "Failed to enabled inter-frame PC\n");
|
||||||
|
|
||||||
|
while (loop) {
|
||||||
|
reg_gdsc = __read_register(device, CVP_CC_MVS1_GDSCR);
|
||||||
|
if (reg_gdsc & 0x80000000) {
|
||||||
|
usleep_range(100, 200);
|
||||||
|
loop--;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!loop)
|
||||||
|
dprintk(CVP_ERR, "fail to power off CORE during resume\n");
|
||||||
|
|
||||||
ctrl_init_val = BIT(0);
|
ctrl_init_val = BIT(0);
|
||||||
__write_register(device, CVP_CTRL_INIT, ctrl_init_val);
|
__write_register(device, CVP_CTRL_INIT, ctrl_init_val);
|
||||||
@@ -1492,8 +1540,6 @@ static int __interface_dsp_queues_init(struct iris_hfi_device *dev)
|
|||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
u32 i;
|
u32 i;
|
||||||
struct cvp_hfi_queue_table_header *q_tbl_hdr;
|
|
||||||
struct cvp_hfi_queue_header *q_hdr;
|
|
||||||
struct cvp_iface_q_info *iface_q;
|
struct cvp_iface_q_info *iface_q;
|
||||||
int offset = 0;
|
int offset = 0;
|
||||||
phys_addr_t fw_bias = 0;
|
phys_addr_t fw_bias = 0;
|
||||||
@@ -1552,43 +1598,11 @@ static int __interface_dsp_queues_init(struct iris_hfi_device *dev)
|
|||||||
iface_q->q_array.align_virtual_addr = kvaddr + offset;
|
iface_q->q_array.align_virtual_addr = kvaddr + offset;
|
||||||
iface_q->q_array.mem_size = CVP_IFACEQ_QUEUE_SIZE;
|
iface_q->q_array.mem_size = CVP_IFACEQ_QUEUE_SIZE;
|
||||||
offset += iface_q->q_array.mem_size;
|
offset += iface_q->q_array.mem_size;
|
||||||
iface_q->q_hdr = CVP_IFACEQ_GET_QHDR_START_ADDR(
|
|
||||||
dev->dsp_iface_q_table.align_virtual_addr, i);
|
|
||||||
__set_queue_hdr_defaults(iface_q->q_hdr);
|
|
||||||
spin_lock_init(&iface_q->hfi_lock);
|
spin_lock_init(&iface_q->hfi_lock);
|
||||||
}
|
}
|
||||||
|
|
||||||
q_tbl_hdr = (struct cvp_hfi_queue_table_header *)
|
cvp_dsp_init_hfi_queue_hdr(dev);
|
||||||
dev->dsp_iface_q_table.align_virtual_addr;
|
|
||||||
q_tbl_hdr->qtbl_version = 0;
|
|
||||||
q_tbl_hdr->device_addr = (void *)dev;
|
|
||||||
strlcpy(q_tbl_hdr->name, "msm_cvp", sizeof(q_tbl_hdr->name));
|
|
||||||
q_tbl_hdr->qtbl_size = CVP_IFACEQ_TABLE_SIZE;
|
|
||||||
q_tbl_hdr->qtbl_qhdr0_offset =
|
|
||||||
sizeof(struct cvp_hfi_queue_table_header);
|
|
||||||
q_tbl_hdr->qtbl_qhdr_size = sizeof(struct cvp_hfi_queue_header);
|
|
||||||
q_tbl_hdr->qtbl_num_q = CVP_IFACEQ_NUMQ;
|
|
||||||
q_tbl_hdr->qtbl_num_active_q = CVP_IFACEQ_NUMQ;
|
|
||||||
|
|
||||||
iface_q = &dev->dsp_iface_queues[CVP_IFACEQ_CMDQ_IDX];
|
|
||||||
q_hdr = iface_q->q_hdr;
|
|
||||||
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
|
||||||
q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
|
|
||||||
|
|
||||||
iface_q = &dev->dsp_iface_queues[CVP_IFACEQ_MSGQ_IDX];
|
|
||||||
q_hdr = iface_q->q_hdr;
|
|
||||||
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
|
||||||
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
|
|
||||||
|
|
||||||
iface_q = &dev->dsp_iface_queues[CVP_IFACEQ_DBGQ_IDX];
|
|
||||||
q_hdr = iface_q->q_hdr;
|
|
||||||
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
|
||||||
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
|
|
||||||
/*
|
|
||||||
* Set receive request to zero on debug queue as there is no
|
|
||||||
* need of interrupt from cvp hardware for debug messages
|
|
||||||
*/
|
|
||||||
q_hdr->qhdr_rx_req = 0;
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
fail_dma_map:
|
fail_dma_map:
|
||||||
@@ -1964,6 +1978,7 @@ static int __sys_set_power_control(struct iris_hfi_device *device,
|
|||||||
static int iris_hfi_core_init(void *device)
|
static int iris_hfi_core_init(void *device)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
u32 ipcc_iova;
|
||||||
struct cvp_hfi_cmd_sys_init_packet pkt;
|
struct cvp_hfi_cmd_sys_init_packet pkt;
|
||||||
struct cvp_hfi_cmd_sys_get_property_packet version_pkt;
|
struct cvp_hfi_cmd_sys_get_property_packet version_pkt;
|
||||||
struct iris_hfi_device *dev;
|
struct iris_hfi_device *dev;
|
||||||
@@ -2011,6 +2026,12 @@ static int iris_hfi_core_init(void *device)
|
|||||||
goto err_core_init;
|
goto err_core_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = msm_cvp_map_ipcc_regs(&ipcc_iova);
|
||||||
|
if (!rc) {
|
||||||
|
dprintk(CVP_CORE, "IPCC iova 0x%x\n", ipcc_iova);
|
||||||
|
__write_register(dev, CVP_MMAP_ADDR, ipcc_iova);
|
||||||
|
}
|
||||||
|
|
||||||
rc = __boot_firmware(dev);
|
rc = __boot_firmware(dev);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "Failed to start core\n");
|
dprintk(CVP_ERR, "Failed to start core\n");
|
||||||
@@ -3350,7 +3371,7 @@ static int reset_ahb2axi_bridge(struct iris_hfi_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* wait for deassert */
|
/* wait for deassert */
|
||||||
usleep_range(400, 450);
|
usleep_range(1000, 1050);
|
||||||
|
|
||||||
rc = __handle_reset_clk(device->res, i, DEASSERT, s);
|
rc = __handle_reset_clk(device->res, i, DEASSERT, s);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -3625,11 +3646,6 @@ static void __deinit_resources(struct iris_hfi_device *device)
|
|||||||
device->sys_init_capabilities = NULL;
|
device->sys_init_capabilities = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int __protect_cp_mem(struct iris_hfi_device *device)
|
|
||||||
{
|
|
||||||
return device ? 0 : -EINVAL;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int __disable_regulator(struct regulator_info *rinfo,
|
static int __disable_regulator(struct regulator_info *rinfo,
|
||||||
struct iris_hfi_device *device)
|
struct iris_hfi_device *device)
|
||||||
{
|
{
|
||||||
@@ -4014,15 +4030,6 @@ static int __iris_power_on(struct iris_hfi_device *device)
|
|||||||
device->intr_status = 0;
|
device->intr_status = 0;
|
||||||
enable_irq(device->cvp_hal_data->irq);
|
enable_irq(device->cvp_hal_data->irq);
|
||||||
|
|
||||||
/*
|
|
||||||
* Hand off control of regulators to h/w _after_ enabling clocks.
|
|
||||||
* Note that the GDSC will turn off when switching from normal
|
|
||||||
* (s/w triggered) to fast (HW triggered) unless the h/w vote is
|
|
||||||
* present. Since Iris isn't up yet, the GDSC will be off briefly.
|
|
||||||
*/
|
|
||||||
if (__enable_hw_power_collapse(device))
|
|
||||||
dprintk(CVP_ERR, "Failed to enabled inter-frame PC\n");
|
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
|
|
||||||
fail_enable_clks:
|
fail_enable_clks:
|
||||||
@@ -4175,10 +4182,10 @@ static void power_off_iris2(struct iris_hfi_device *device)
|
|||||||
/* HPG 6.1.2 Step 6 */
|
/* HPG 6.1.2 Step 6 */
|
||||||
__disable_unprepare_clks(device);
|
__disable_unprepare_clks(device);
|
||||||
|
|
||||||
/* HPG 6.1.2 Step 7 & 8 */
|
/*
|
||||||
if (call_iris_op(device, reset_ahb2axi_bridge, device))
|
* HPG 6.1.2 Step 7 & 8
|
||||||
dprintk(CVP_ERR, "Failed to reset ahb2axi\n");
|
* per new HPG update, core clock reset will be unnecessary
|
||||||
|
*/
|
||||||
if (__unvote_buses(device))
|
if (__unvote_buses(device))
|
||||||
dprintk(CVP_WARN, "Failed to unvote for buses\n");
|
dprintk(CVP_WARN, "Failed to unvote for buses\n");
|
||||||
|
|
||||||
@@ -4212,8 +4219,6 @@ static inline int __resume(struct iris_hfi_device *device)
|
|||||||
goto err_iris_power_on;
|
goto err_iris_power_on;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
reg_gdsc = __read_register(device, CVP_CC_MVS1C_GDSCR);
|
reg_gdsc = __read_register(device, CVP_CC_MVS1C_GDSCR);
|
||||||
reg_cbcr = __read_register(device, CVP_CC_MVS1C_CBCR);
|
reg_cbcr = __read_register(device, CVP_CC_MVS1C_CBCR);
|
||||||
if (!(reg_gdsc & 0x80000000) || (reg_cbcr & 0x80000000))
|
if (!(reg_gdsc & 0x80000000) || (reg_cbcr & 0x80000000))
|
||||||
@@ -4228,6 +4233,7 @@ static inline int __resume(struct iris_hfi_device *device)
|
|||||||
}
|
}
|
||||||
|
|
||||||
__setup_ucregion_memory_map(device);
|
__setup_ucregion_memory_map(device);
|
||||||
|
|
||||||
/* Wait for boot completion */
|
/* Wait for boot completion */
|
||||||
rc = __boot_firmware(device);
|
rc = __boot_firmware(device);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
@@ -4293,31 +4299,13 @@ static int __load_fw(struct iris_hfi_device *device)
|
|||||||
|
|
||||||
if ((!device->res->use_non_secure_pil && !device->res->firmware_base)
|
if ((!device->res->use_non_secure_pil && !device->res->firmware_base)
|
||||||
|| device->res->use_non_secure_pil) {
|
|| device->res->use_non_secure_pil) {
|
||||||
if (!device->resources.fw.cookie)
|
rc = load_cvp_fw_impl(device);
|
||||||
device->resources.fw.cookie =
|
if (rc)
|
||||||
subsystem_get_with_fwname("evass",
|
|
||||||
device->res->fw_name);
|
|
||||||
|
|
||||||
if (IS_ERR_OR_NULL(device->resources.fw.cookie)) {
|
|
||||||
dprintk(CVP_ERR, "Failed to download firmware\n");
|
|
||||||
device->resources.fw.cookie = NULL;
|
|
||||||
rc = -ENOMEM;
|
|
||||||
goto fail_load_fw;
|
goto fail_load_fw;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!device->res->firmware_base) {
|
|
||||||
rc = __protect_cp_mem(device);
|
|
||||||
if (rc) {
|
|
||||||
dprintk(CVP_ERR, "Failed to protect memory\n");
|
|
||||||
goto fail_protect_mem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return rc;
|
return rc;
|
||||||
fail_protect_mem:
|
|
||||||
if (device->resources.fw.cookie)
|
|
||||||
subsystem_put(device->resources.fw.cookie);
|
|
||||||
device->resources.fw.cookie = NULL;
|
|
||||||
fail_load_fw:
|
fail_load_fw:
|
||||||
call_iris_op(device, power_off, device);
|
call_iris_op(device, power_off, device);
|
||||||
fail_iris_power_on:
|
fail_iris_power_on:
|
||||||
@@ -4336,10 +4324,9 @@ static void __unload_fw(struct iris_hfi_device *device)
|
|||||||
if (device->state != IRIS_STATE_DEINIT)
|
if (device->state != IRIS_STATE_DEINIT)
|
||||||
flush_workqueue(device->iris_pm_workq);
|
flush_workqueue(device->iris_pm_workq);
|
||||||
|
|
||||||
subsystem_put(device->resources.fw.cookie);
|
unload_cvp_fw_impl(device);
|
||||||
__interface_queues_release(device);
|
__interface_queues_release(device);
|
||||||
call_iris_op(device, power_off, device);
|
call_iris_op(device, power_off, device);
|
||||||
device->resources.fw.cookie = NULL;
|
|
||||||
__deinit_resources(device);
|
__deinit_resources(device);
|
||||||
|
|
||||||
dprintk(CVP_WARN, "Firmware unloaded\n");
|
dprintk(CVP_WARN, "Firmware unloaded\n");
|
||||||
@@ -4389,9 +4376,12 @@ static int iris_hfi_get_core_capabilities(void *dev)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static u32 cvp_arp_test_regs[16];
|
||||||
|
static u32 cvp_dma_test_regs[512];
|
||||||
|
|
||||||
static void __noc_error_info_iris2(struct iris_hfi_device *device)
|
static void __noc_error_info_iris2(struct iris_hfi_device *device)
|
||||||
{
|
{
|
||||||
u32 val = 0;
|
u32 val = 0, regi, i;
|
||||||
|
|
||||||
val = __read_register(device, CVP_NOC_ERR_SWID_LOW_OFFS);
|
val = __read_register(device, CVP_NOC_ERR_SWID_LOW_OFFS);
|
||||||
dprintk(CVP_ERR, "CVP_NOC_ERL_MAIN_SWID_LOW: %#x\n", val);
|
dprintk(CVP_ERR, "CVP_NOC_ERL_MAIN_SWID_LOW: %#x\n", val);
|
||||||
@@ -4446,6 +4436,32 @@ static void __noc_error_info_iris2(struct iris_hfi_device *device)
|
|||||||
dprintk(CVP_ERR, "CVP_NOC_CORE_ERL_MAIN_ERRLOG3_LOW: %#x\n", val);
|
dprintk(CVP_ERR, "CVP_NOC_CORE_ERL_MAIN_ERRLOG3_LOW: %#x\n", val);
|
||||||
val = __read_register(device, CVP_NOC_CORE_ERR_ERRLOG3_HIGH_OFFS);
|
val = __read_register(device, CVP_NOC_CORE_ERR_ERRLOG3_HIGH_OFFS);
|
||||||
dprintk(CVP_ERR, "CVP_NOC_CORE_ERL_MAIN_ERRLOG3_HIGH: %#x\n", val);
|
dprintk(CVP_ERR, "CVP_NOC_CORE_ERL_MAIN_ERRLOG3_HIGH: %#x\n", val);
|
||||||
|
#define CVP_SS_CLK_HALT 0x8
|
||||||
|
#define CVP_SS_CLK_EN 0xC
|
||||||
|
#define CVP_SS_ARP_TEST_BUS_CONTROL 0x700
|
||||||
|
#define CVP_SS_ARP_TEST_BUS_REGISTER 0x704
|
||||||
|
#define CVP_DMA_TEST_BUS_CONTROL 0x66A0
|
||||||
|
#define CVP_DMA_TEST_BUS_REGISTER 0x66A4
|
||||||
|
#define CVP_VPU_WRAPPER_CORE_CONFIG 0xB0088
|
||||||
|
__write_register(device, CVP_SS_CLK_HALT, 0);
|
||||||
|
__write_register(device, CVP_SS_CLK_EN, 0x3f);
|
||||||
|
__write_register(device, CVP_VPU_WRAPPER_CORE_CONFIG, 0);
|
||||||
|
|
||||||
|
for (i = 0; i < 15; i++) {
|
||||||
|
regi = 0xC0000000 + i;
|
||||||
|
__write_register(device, CVP_SS_ARP_TEST_BUS_CONTROL, regi);
|
||||||
|
val = __read_register(device, CVP_SS_ARP_TEST_BUS_REGISTER);
|
||||||
|
cvp_arp_test_regs[i] = val;
|
||||||
|
dprintk(CVP_ERR, "ARP_CTL:%x - %x\n", regi, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (i = 0; i < 512; i++) {
|
||||||
|
regi = 0x40000000 + i;
|
||||||
|
__write_register(device, CVP_DMA_TEST_BUS_CONTROL, regi);
|
||||||
|
val = __read_register(device, CVP_DMA_TEST_BUS_REGISTER);
|
||||||
|
cvp_dma_test_regs[i] = val;
|
||||||
|
dprintk(CVP_ERR, "DMA_CTL:%x - %x\n", regi, val);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iris_hfi_noc_error_info(void *dev)
|
static int iris_hfi_noc_error_info(void *dev)
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
#include <media/msm_media_info.h>
|
#include <media/msm_media_info.h>
|
||||||
#include "cvp_hfi_helper.h"
|
#include "cvp_hfi_helper.h"
|
||||||
#include "cvp_hfi_api.h"
|
#include "cvp_hfi_api.h"
|
||||||
|
#include "cvp_comm_def.h"
|
||||||
|
|
||||||
#define HFI_CMD_SESSION_CVP_START \
|
#define HFI_CMD_SESSION_CVP_START \
|
||||||
(HFI_DOMAIN_BASE_CVP + HFI_ARCH_COMMON_OFFSET + \
|
(HFI_DOMAIN_BASE_CVP + HFI_ARCH_COMMON_OFFSET + \
|
||||||
@@ -199,7 +200,11 @@ struct cvp_hal_session {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct msm_cvp_fw {
|
struct msm_cvp_fw {
|
||||||
|
#ifdef CVP_MDT_ENABLED
|
||||||
|
int cookie;
|
||||||
|
#else
|
||||||
void *cookie;
|
void *cookie;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
int cvp_hfi_process_msg_packet(u32 device_id,
|
int cvp_hfi_process_msg_packet(u32 device_id,
|
||||||
|
@@ -369,7 +369,7 @@ void cvp_hfi_deinitialize(enum msm_cvp_hfi_type hfi_type,
|
|||||||
int get_pkt_index(struct cvp_hal_session_cmd_pkt *hdr);
|
int get_pkt_index(struct cvp_hal_session_cmd_pkt *hdr);
|
||||||
int get_signal_from_pkt_type(unsigned int type);
|
int get_signal_from_pkt_type(unsigned int type);
|
||||||
int get_hfi_version(void);
|
int get_hfi_version(void);
|
||||||
unsigned int get_msg_size(void);
|
unsigned int get_msg_size(struct cvp_hfi_msg_session_hdr *hdr);
|
||||||
unsigned int get_msg_session_id(void *msg);
|
unsigned int get_msg_session_id(void *msg);
|
||||||
unsigned int get_msg_errorcode(void *msg);
|
unsigned int get_msg_errorcode(void *msg);
|
||||||
int get_msg_opconfigs(void *msg, unsigned int *session_id,
|
int get_msg_opconfigs(void *msg, unsigned int *session_id,
|
||||||
|
@@ -336,6 +336,29 @@ struct cvp_hfi_msg_session_hdr {
|
|||||||
u32 stream_idx;
|
u32 stream_idx;
|
||||||
} __packed;
|
} __packed;
|
||||||
|
|
||||||
|
#define HFI_MAX_HW_ACTIVATIONS_PER_FRAME (6)
|
||||||
|
#define HFI_MAX_HW_THREADS (4)
|
||||||
|
|
||||||
|
enum hfi_hw_thread {
|
||||||
|
HFI_HW_FDU,
|
||||||
|
HFI_HW_MPU,
|
||||||
|
HFI_HW_OD,
|
||||||
|
HFI_HW_ICA
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cvp_hfi_msg_session_hdr_ext {
|
||||||
|
u32 size;
|
||||||
|
u32 packet_type;
|
||||||
|
u32 session_id;
|
||||||
|
u32 error_type;
|
||||||
|
struct cvp_hfi_client client_data;
|
||||||
|
u32 stream_idx;
|
||||||
|
u32 busy_cycles;
|
||||||
|
u32 total_cycles;
|
||||||
|
u32 hw_cycles[HFI_MAX_HW_THREADS][HFI_MAX_HW_ACTIVATIONS_PER_FRAME];
|
||||||
|
u32 fw_cycles[HFI_MAX_HW_ACTIVATIONS_PER_FRAME];
|
||||||
|
} __packed;
|
||||||
|
|
||||||
struct cvp_hfi_buffer_mapping_type {
|
struct cvp_hfi_buffer_mapping_type {
|
||||||
u32 index;
|
u32 index;
|
||||||
u32 device_addr;
|
u32 device_addr;
|
||||||
|
@@ -220,4 +220,5 @@
|
|||||||
#define CVP_CC_MVS0C_GDSCR (CVP_CC_BASE_OFFS + 0xBF8)
|
#define CVP_CC_MVS0C_GDSCR (CVP_CC_BASE_OFFS + 0xBF8)
|
||||||
#define CVP_CC_MVS1C_GDSCR (CVP_CC_BASE_OFFS + 0xC98)
|
#define CVP_CC_MVS1C_GDSCR (CVP_CC_BASE_OFFS + 0xC98)
|
||||||
#define CVP_CC_MVS1C_CBCR (CVP_CC_BASE_OFFS + 0xCD4)
|
#define CVP_CC_MVS1C_CBCR (CVP_CC_BASE_OFFS + 0xCD4)
|
||||||
|
#define CVP_CC_MVS1_GDSCR (CVP_CC_BASE_OFFS + 0xD98)
|
||||||
#endif
|
#endif
|
||||||
|
@@ -313,7 +313,7 @@ static int hfi_process_session_set_buf_done(u32 device_id,
|
|||||||
struct cvp_hfi_msg_session_hdr *pkt =
|
struct cvp_hfi_msg_session_hdr *pkt =
|
||||||
(struct cvp_hfi_msg_session_hdr *)hdr;
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
||||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||||
unsigned int pkt_size = get_msg_size();
|
unsigned int pkt_size = get_msg_size(pkt);
|
||||||
|
|
||||||
if (!pkt || pkt->size < pkt_size) {
|
if (!pkt || pkt->size < pkt_size) {
|
||||||
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
||||||
@@ -367,7 +367,7 @@ static int hfi_process_session_rel_buf_done(u32 device_id,
|
|||||||
struct cvp_hfi_msg_session_hdr *pkt =
|
struct cvp_hfi_msg_session_hdr *pkt =
|
||||||
(struct cvp_hfi_msg_session_hdr *)hdr;
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
||||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||||
unsigned int pkt_size = get_msg_size();
|
unsigned int pkt_size = get_msg_size(pkt);
|
||||||
|
|
||||||
if (!pkt || pkt->size < pkt_size) {
|
if (!pkt || pkt->size < pkt_size) {
|
||||||
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
||||||
@@ -393,6 +393,8 @@ static int hfi_process_session_cvp_operation_config(u32 device_id,
|
|||||||
{
|
{
|
||||||
struct cvp_hfi_msg_session_op_cfg_packet *pkt =
|
struct cvp_hfi_msg_session_op_cfg_packet *pkt =
|
||||||
(struct cvp_hfi_msg_session_op_cfg_packet *)hdr;
|
(struct cvp_hfi_msg_session_op_cfg_packet *)hdr;
|
||||||
|
struct cvp_hfi_msg_session_hdr *lhdr =
|
||||||
|
(struct cvp_hfi_msg_session_hdr *)hdr;
|
||||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||||
int signal;
|
int signal;
|
||||||
unsigned int conf_id, session_id, error_type;
|
unsigned int conf_id, session_id, error_type;
|
||||||
@@ -400,7 +402,7 @@ static int hfi_process_session_cvp_operation_config(u32 device_id,
|
|||||||
if (!pkt) {
|
if (!pkt) {
|
||||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
} else if (pkt->size < get_msg_size()) {
|
} else if (pkt->size < get_msg_size(lhdr)) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: bad_pkt_size\n", __func__);
|
"%s: bad_pkt_size\n", __func__);
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
@@ -514,7 +516,7 @@ static int hfi_process_session_cvp_msg(u32 device_id,
|
|||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(&sess_msg->pkt, pkt, get_msg_size());
|
memcpy(&sess_msg->pkt, pkt, get_msg_size(pkt));
|
||||||
|
|
||||||
dprintk(CVP_HFI,
|
dprintk(CVP_HFI,
|
||||||
"%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
|
"%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
|
||||||
|
@@ -111,12 +111,15 @@ static int cvp_wait_process_message(struct msm_cvp_inst *inst,
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (out)
|
if (!out) {
|
||||||
memcpy(out, &msg->pkt, sizeof(struct cvp_hfi_msg_session_hdr));
|
kmem_cache_free(cvp_driver->msg_cache, msg);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
kmem_cache_free(cvp_driver->msg_cache, msg);
|
hdr = (struct cvp_hfi_msg_session_hdr *)&msg->pkt;
|
||||||
hdr = (struct cvp_hfi_msg_session_hdr *)out;
|
memcpy(out, &msg->pkt, get_msg_size(hdr));
|
||||||
msm_cvp_unmap_frame(inst, hdr->client_data.kdata);
|
msm_cvp_unmap_frame(inst, hdr->client_data.kdata);
|
||||||
|
kmem_cache_free(cvp_driver->msg_cache, msg);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
return rc;
|
return rc;
|
||||||
@@ -271,7 +274,7 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q,
|
|||||||
|
|
||||||
f = list_first_entry(&q->wait_list, struct cvp_fence_command, list);
|
f = list_first_entry(&q->wait_list, struct cvp_fence_command, list);
|
||||||
list_del_init(&f->list);
|
list_del_init(&f->list);
|
||||||
list_add_tail(&q->sched_list, &f->list);
|
list_add_tail(&f->list, &q->sched_list);
|
||||||
|
|
||||||
mutex_unlock(&q->lock);
|
mutex_unlock(&q->lock);
|
||||||
*fence = f;
|
*fence = f;
|
||||||
@@ -279,6 +282,166 @@ static bool cvp_fence_wait(struct cvp_fence_queue *q,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int cvp_readjust_clock(struct msm_cvp_core *core,
|
||||||
|
u32 avg_cycles, enum hfi_hw_thread i)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
struct allowed_clock_rates_table *tbl = NULL;
|
||||||
|
unsigned int tbl_size = 0;
|
||||||
|
unsigned int cvp_min_rate = 0, cvp_max_rate = 0;
|
||||||
|
unsigned long tmp = core->curr_freq;
|
||||||
|
unsigned long lo_freq = 0;
|
||||||
|
u32 j;
|
||||||
|
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s:%d - %d - avg_cycles %u > hi_tresh %u\n",
|
||||||
|
__func__, __LINE__, i, avg_cycles,
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i]);
|
||||||
|
|
||||||
|
core->curr_freq = ((avg_cycles * core->dyn_clk.sum_fps[i]) << 1)/3;
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s - cycles tot %u, avg %u. sum_fps %u, cur_freq %u\n",
|
||||||
|
__func__,
|
||||||
|
core->dyn_clk.cycle[i].total,
|
||||||
|
avg_cycles,
|
||||||
|
core->dyn_clk.sum_fps[i],
|
||||||
|
core->curr_freq);
|
||||||
|
|
||||||
|
tbl = core->resources.allowed_clks_tbl;
|
||||||
|
tbl_size = core->resources.allowed_clks_tbl_size;
|
||||||
|
cvp_min_rate = tbl[0].clock_rate;
|
||||||
|
cvp_max_rate = tbl[tbl_size - 1].clock_rate;
|
||||||
|
|
||||||
|
if (core->curr_freq > cvp_max_rate) {
|
||||||
|
core->curr_freq = cvp_max_rate;
|
||||||
|
lo_freq = (tbl_size > 1) ?
|
||||||
|
tbl[tbl_size - 2].clock_rate :
|
||||||
|
cvp_min_rate;
|
||||||
|
} else if (core->curr_freq <= cvp_min_rate) {
|
||||||
|
core->curr_freq = cvp_min_rate;
|
||||||
|
lo_freq = cvp_min_rate;
|
||||||
|
} else {
|
||||||
|
for (j = 1; j < tbl_size; j++)
|
||||||
|
if (core->curr_freq <= tbl[j].clock_rate)
|
||||||
|
break;
|
||||||
|
core->curr_freq = tbl[j].clock_rate;
|
||||||
|
lo_freq = tbl[j-1].clock_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s:%d - %d - Readjust to %u\n",
|
||||||
|
__func__, __LINE__, i, core->curr_freq);
|
||||||
|
rc = msm_cvp_set_clocks(core);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR,
|
||||||
|
"Failed to set clock rate %u: %d %s\n",
|
||||||
|
core->curr_freq, rc, __func__);
|
||||||
|
core->curr_freq = tmp;
|
||||||
|
} else {
|
||||||
|
lo_freq = (lo_freq < core->dyn_clk.conf_freq) ?
|
||||||
|
core->dyn_clk.conf_freq : lo_freq;
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i] = core->dyn_clk.sum_fps[i] ?
|
||||||
|
((core->curr_freq*3)>>1)/core->dyn_clk.sum_fps[i] : 0;
|
||||||
|
core->dyn_clk.lo_ctrl_lim[i] =
|
||||||
|
core->dyn_clk.sum_fps[i] ?
|
||||||
|
((lo_freq*3)>>1)/core->dyn_clk.sum_fps[i] : 0;
|
||||||
|
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s - Readjust clk to %u. New lim [%d] hi %u lo %u\n",
|
||||||
|
__func__, core->curr_freq, i,
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i],
|
||||||
|
core->dyn_clk.lo_ctrl_lim[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvp_check_clock(struct msm_cvp_inst *inst,
|
||||||
|
struct cvp_hfi_msg_session_hdr_ext *hdr)
|
||||||
|
{
|
||||||
|
int rc = 0;
|
||||||
|
u32 i, j;
|
||||||
|
u32 hw_cycles[HFI_MAX_HW_THREADS] = {0};
|
||||||
|
u32 fw_cycles = 0;
|
||||||
|
struct msm_cvp_core *core = inst->core;
|
||||||
|
|
||||||
|
for (i = 0; i < HFI_MAX_HW_ACTIVATIONS_PER_FRAME; ++i)
|
||||||
|
fw_cycles += hdr->fw_cycles[i];
|
||||||
|
|
||||||
|
for (i = 0; i < HFI_MAX_HW_THREADS; ++i)
|
||||||
|
for (j = 0; j < HFI_MAX_HW_ACTIVATIONS_PER_FRAME; ++j)
|
||||||
|
hw_cycles[i] += hdr->hw_cycles[i][j];
|
||||||
|
|
||||||
|
dprintk(CVP_PWR, "%s - cycles fw %u. FDU %d MPU %d ODU %d ICA %d\n",
|
||||||
|
__func__, fw_cycles, hw_cycles[0],
|
||||||
|
hw_cycles[1], hw_cycles[2], hw_cycles[3]);
|
||||||
|
|
||||||
|
mutex_lock(&core->dyn_clk.lock);
|
||||||
|
for (i = 0; i < HFI_MAX_HW_THREADS; ++i) {
|
||||||
|
dprintk(CVP_PWR, "%s - %d: hw_cycles %u, tens_thresh %u\n",
|
||||||
|
__func__, i, hw_cycles[i],
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i]);
|
||||||
|
if (core->dyn_clk.hi_ctrl_lim[i]) {
|
||||||
|
if (core->dyn_clk.cycle[i].size < CVP_CYCLE_STAT_SIZE)
|
||||||
|
core->dyn_clk.cycle[i].size++;
|
||||||
|
else
|
||||||
|
core->dyn_clk.cycle[i].total -=
|
||||||
|
core->dyn_clk.cycle[i].busy[
|
||||||
|
core->dyn_clk.cycle[i].idx];
|
||||||
|
if (hw_cycles[i]) {
|
||||||
|
core->dyn_clk.cycle[i].busy[
|
||||||
|
core->dyn_clk.cycle[i].idx]
|
||||||
|
= hw_cycles[i] + fw_cycles;
|
||||||
|
core->dyn_clk.cycle[i].total
|
||||||
|
+= hw_cycles[i] + fw_cycles;
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s: busy (hw + fw) cycles = %u\n",
|
||||||
|
__func__,
|
||||||
|
core->dyn_clk.cycle[i].busy[
|
||||||
|
core->dyn_clk.cycle[i].idx]);
|
||||||
|
dprintk(CVP_PWR, "total cycles %u\n",
|
||||||
|
core->dyn_clk.cycle[i].total);
|
||||||
|
} else {
|
||||||
|
core->dyn_clk.cycle[i].busy[
|
||||||
|
core->dyn_clk.cycle[i].idx] =
|
||||||
|
hdr->busy_cycles;
|
||||||
|
core->dyn_clk.cycle[i].total +=
|
||||||
|
hdr->busy_cycles;
|
||||||
|
dprintk(CVP_PWR,
|
||||||
|
"%s - busy cycles = %u total %u\n",
|
||||||
|
__func__,
|
||||||
|
core->dyn_clk.cycle[i].busy[
|
||||||
|
core->dyn_clk.cycle[i].idx],
|
||||||
|
core->dyn_clk.cycle[i].total);
|
||||||
|
}
|
||||||
|
|
||||||
|
core->dyn_clk.cycle[i].idx =
|
||||||
|
(core->dyn_clk.cycle[i].idx ==
|
||||||
|
CVP_CYCLE_STAT_SIZE-1) ?
|
||||||
|
0 : core->dyn_clk.cycle[i].idx+1;
|
||||||
|
|
||||||
|
dprintk(CVP_PWR, "%s - %d: size %u, tens_thresh %u\n",
|
||||||
|
__func__, i, core->dyn_clk.cycle[i].size,
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i]);
|
||||||
|
if (core->dyn_clk.cycle[i].size == CVP_CYCLE_STAT_SIZE
|
||||||
|
&& core->dyn_clk.hi_ctrl_lim[i] != 0) {
|
||||||
|
u32 avg_cycles =
|
||||||
|
core->dyn_clk.cycle[i].total>>3;
|
||||||
|
if ((avg_cycles > core->dyn_clk.hi_ctrl_lim[i])
|
||||||
|
|| (avg_cycles <=
|
||||||
|
core->dyn_clk.lo_ctrl_lim[i])) {
|
||||||
|
rc = cvp_readjust_clock(core,
|
||||||
|
avg_cycles,
|
||||||
|
i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&core->dyn_clk.lock);
|
||||||
|
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
||||||
struct cvp_fence_command *fc,
|
struct cvp_fence_command *fc,
|
||||||
struct cvp_hfi_cmd_session_hdr *pkt)
|
struct cvp_hfi_cmd_session_hdr *pkt)
|
||||||
@@ -290,7 +453,8 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
|||||||
struct cvp_hfi_device *hdev;
|
struct cvp_hfi_device *hdev;
|
||||||
struct cvp_session_queue *sq;
|
struct cvp_session_queue *sq;
|
||||||
u32 hfi_err = HFI_ERR_NONE;
|
u32 hfi_err = HFI_ERR_NONE;
|
||||||
struct cvp_hfi_msg_session_hdr *hdr;
|
struct cvp_hfi_msg_session_hdr_ext hdr;
|
||||||
|
bool clock_check = false;
|
||||||
|
|
||||||
dprintk(CVP_SYNX, "%s %s\n", current->comm, __func__);
|
dprintk(CVP_SYNX, "%s %s\n", current->comm, __func__);
|
||||||
|
|
||||||
@@ -298,7 +462,8 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
|||||||
sq = &inst->session_queue_fence;
|
sq = &inst->session_queue_fence;
|
||||||
ktid = pkt->client_data.kdata;
|
ktid = pkt->client_data.kdata;
|
||||||
|
|
||||||
if (cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state)) {
|
rc = cvp_synx_ops(inst, CVP_INPUT_SYNX, fc, &synx_state);
|
||||||
|
if (rc) {
|
||||||
msm_cvp_unmap_frame(inst, pkt->client_data.kdata);
|
msm_cvp_unmap_frame(inst, pkt->client_data.kdata);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
@@ -314,9 +479,16 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
|||||||
|
|
||||||
timeout = msecs_to_jiffies(CVP_MAX_WAIT_TIME);
|
timeout = msecs_to_jiffies(CVP_MAX_WAIT_TIME);
|
||||||
rc = cvp_wait_process_message(inst, sq, &ktid, timeout,
|
rc = cvp_wait_process_message(inst, sq, &ktid, timeout,
|
||||||
(struct cvp_kmd_hfi_packet *)pkt);
|
(struct cvp_kmd_hfi_packet *)&hdr);
|
||||||
hdr = (struct cvp_hfi_msg_session_hdr *)pkt;
|
if (get_msg_size((struct cvp_hfi_msg_session_hdr *) &hdr)
|
||||||
hfi_err = hdr->error_type;
|
== sizeof(struct cvp_hfi_msg_session_hdr_ext)) {
|
||||||
|
struct cvp_hfi_msg_session_hdr_ext *fhdr =
|
||||||
|
(struct cvp_hfi_msg_session_hdr_ext *)&hdr;
|
||||||
|
dprintk(CVP_HFI, "busy cycle 0x%x, total 0x%x\n",
|
||||||
|
fhdr->busy_cycles, fhdr->total_cycles);
|
||||||
|
clock_check = true;
|
||||||
|
}
|
||||||
|
hfi_err = hdr.error_type;
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message rc %d\n",
|
dprintk(CVP_ERR, "%s %s: cvp_wait_process_message rc %d\n",
|
||||||
current->comm, __func__, rc);
|
current->comm, __func__, rc);
|
||||||
@@ -339,19 +511,23 @@ static int cvp_fence_proc(struct msm_cvp_inst *inst,
|
|||||||
|
|
||||||
exit:
|
exit:
|
||||||
rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state);
|
rc = cvp_synx_ops(inst, CVP_OUTPUT_SYNX, fc, &synx_state);
|
||||||
|
if (clock_check)
|
||||||
|
cvp_check_clock(inst,
|
||||||
|
(struct cvp_hfi_msg_session_hdr_ext *)&hdr);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cvp_alloc_fence_data(struct cvp_fence_command **f, u32 size)
|
static int cvp_alloc_fence_data(struct cvp_fence_command **f, u32 size)
|
||||||
{
|
{
|
||||||
struct cvp_fence_command *fcmd;
|
struct cvp_fence_command *fcmd;
|
||||||
|
int alloc_size = sizeof(struct cvp_hfi_msg_session_hdr_ext);
|
||||||
|
|
||||||
fcmd = kzalloc(sizeof(struct cvp_fence_command), GFP_KERNEL);
|
fcmd = kzalloc(sizeof(struct cvp_fence_command), GFP_KERNEL);
|
||||||
if (!fcmd)
|
if (!fcmd)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
fcmd->pkt = kzalloc(size, GFP_KERNEL);
|
alloc_size = (alloc_size >= size) ? alloc_size : size;
|
||||||
|
fcmd->pkt = kzalloc(alloc_size, GFP_KERNEL);
|
||||||
if (!fcmd->pkt) {
|
if (!fcmd->pkt) {
|
||||||
kfree(fcmd);
|
kfree(fcmd);
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
@@ -414,6 +590,7 @@ wait:
|
|||||||
mutex_lock(&q->lock);
|
mutex_lock(&q->lock);
|
||||||
cvp_release_synx(inst, f);
|
cvp_release_synx(inst, f);
|
||||||
list_del_init(&f->list);
|
list_del_init(&f->list);
|
||||||
|
state = q->state;
|
||||||
mutex_unlock(&q->lock);
|
mutex_unlock(&q->lock);
|
||||||
|
|
||||||
dprintk(CVP_SYNX, "%s done with %d ktid %llu frameID %llu rc %d\n",
|
dprintk(CVP_SYNX, "%s done with %d ktid %llu frameID %llu rc %d\n",
|
||||||
@@ -421,6 +598,9 @@ wait:
|
|||||||
|
|
||||||
cvp_free_fence_data(f);
|
cvp_free_fence_data(f);
|
||||||
|
|
||||||
|
if (rc && state != QUEUE_ACTIVE)
|
||||||
|
goto exit;
|
||||||
|
|
||||||
goto wait;
|
goto wait;
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
@@ -587,7 +767,7 @@ static void aggregate_power_update(struct msm_cvp_core *core,
|
|||||||
} else {
|
} else {
|
||||||
i = 1;
|
i = 1;
|
||||||
}
|
}
|
||||||
dprintk(CVP_PROF, "pwrUpdate %pK fdu %u od %u mpu %u ica %u\n",
|
dprintk(CVP_PROF, "pwrUpdate fdu %u od %u mpu %u ica %u\n",
|
||||||
inst->prop.fdu_cycles,
|
inst->prop.fdu_cycles,
|
||||||
inst->prop.od_cycles,
|
inst->prop.od_cycles,
|
||||||
inst->prop.mpu_cycles,
|
inst->prop.mpu_cycles,
|
||||||
@@ -629,6 +809,21 @@ static void aggregate_power_update(struct msm_cvp_core *core,
|
|||||||
op_bw_max[i] =
|
op_bw_max[i] =
|
||||||
(op_bw_max[i] >= inst->prop.ddr_op_bw) ?
|
(op_bw_max[i] >= inst->prop.ddr_op_bw) ?
|
||||||
op_bw_max[i] : inst->prop.ddr_op_bw;
|
op_bw_max[i] : inst->prop.ddr_op_bw;
|
||||||
|
|
||||||
|
dprintk(CVP_PWR, "%s:%d - fps fdu %d mpu %d od %d ica %d\n",
|
||||||
|
__func__, __LINE__,
|
||||||
|
inst->prop.fps[HFI_HW_FDU], inst->prop.fps[HFI_HW_MPU],
|
||||||
|
inst->prop.fps[HFI_HW_OD], inst->prop.fps[HFI_HW_ICA]);
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_FDU] += inst->prop.fps[HFI_HW_FDU];
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_MPU] += inst->prop.fps[HFI_HW_MPU];
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_OD] += inst->prop.fps[HFI_HW_OD];
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_ICA] += inst->prop.fps[HFI_HW_ICA];
|
||||||
|
dprintk(CVP_PWR, "%s:%d - sum_fps fdu %d mpu %d od %d ica %d\n",
|
||||||
|
__func__, __LINE__,
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_FDU],
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_MPU],
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_OD],
|
||||||
|
core->dyn_clk.sum_fps[HFI_HW_ICA]);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i < 2; i++) {
|
for (i = 0; i < 2; i++) {
|
||||||
@@ -680,6 +875,7 @@ static int adjust_bw_freqs(void)
|
|||||||
struct cvp_power_level rt_pwr = {0}, nrt_pwr = {0};
|
struct cvp_power_level rt_pwr = {0}, nrt_pwr = {0};
|
||||||
unsigned long tmp, core_sum, op_core_sum, bw_sum;
|
unsigned long tmp, core_sum, op_core_sum, bw_sum;
|
||||||
int i, rc = 0;
|
int i, rc = 0;
|
||||||
|
unsigned long ctrl_freq;
|
||||||
|
|
||||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||||
|
|
||||||
@@ -714,7 +910,7 @@ static int adjust_bw_freqs(void)
|
|||||||
|
|
||||||
if (core_sum > cvp_max_rate) {
|
if (core_sum > cvp_max_rate) {
|
||||||
core_sum = cvp_max_rate;
|
core_sum = cvp_max_rate;
|
||||||
} else if (core_sum < cvp_min_rate) {
|
} else if (core_sum <= cvp_min_rate) {
|
||||||
core_sum = cvp_min_rate;
|
core_sum = cvp_min_rate;
|
||||||
} else {
|
} else {
|
||||||
for (i = 1; i < tbl_size; i++)
|
for (i = 1; i < tbl_size; i++)
|
||||||
@@ -745,6 +941,18 @@ static int adjust_bw_freqs(void)
|
|||||||
core->curr_freq = tmp;
|
core->curr_freq = tmp;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ctrl_freq = (core->curr_freq*3)>>1;
|
||||||
|
mutex_lock(&core->dyn_clk.lock);
|
||||||
|
core->dyn_clk.conf_freq = core->curr_freq;
|
||||||
|
for (i = 0; i < HFI_MAX_HW_THREADS; ++i) {
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i] = core->dyn_clk.sum_fps[i] ?
|
||||||
|
ctrl_freq/core->dyn_clk.sum_fps[i] : 0;
|
||||||
|
core->dyn_clk.lo_ctrl_lim[i] =
|
||||||
|
core->dyn_clk.hi_ctrl_lim[i];
|
||||||
|
}
|
||||||
|
mutex_unlock(&core->dyn_clk.lock);
|
||||||
|
|
||||||
hdev->clk_freq = core->curr_freq;
|
hdev->clk_freq = core->curr_freq;
|
||||||
rc = icc_set_bw(bus->client, bw_sum, 0);
|
rc = icc_set_bw(bus->client, bw_sum, 0);
|
||||||
if (rc)
|
if (rc)
|
||||||
@@ -1122,7 +1330,7 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst,
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (props->prop_num >= MAX_KMD_PROP_NUM_PER_PACKET) {
|
if (props->prop_num > MAX_KMD_PROP_NUM_PER_PACKET) {
|
||||||
dprintk(CVP_ERR, "Too many properties %d to set\n",
|
dprintk(CVP_ERR, "Too many properties %d to set\n",
|
||||||
props->prop_num);
|
props->prop_num);
|
||||||
return -E2BIG;
|
return -E2BIG;
|
||||||
@@ -1194,6 +1402,18 @@ static int msm_cvp_set_sysprop(struct msm_cvp_inst *inst,
|
|||||||
case CVP_KMD_PROP_PWR_SYSCACHE_OP:
|
case CVP_KMD_PROP_PWR_SYSCACHE_OP:
|
||||||
session_prop->ddr_op_cache = prop_array[i].data;
|
session_prop->ddr_op_cache = prop_array[i].data;
|
||||||
break;
|
break;
|
||||||
|
case CVP_KMD_PROP_PWR_FPS_FDU:
|
||||||
|
session_prop->fps[HFI_HW_FDU] = prop_array[i].data;
|
||||||
|
break;
|
||||||
|
case CVP_KMD_PROP_PWR_FPS_MPU:
|
||||||
|
session_prop->fps[HFI_HW_MPU] = prop_array[i].data;
|
||||||
|
break;
|
||||||
|
case CVP_KMD_PROP_PWR_FPS_OD:
|
||||||
|
session_prop->fps[HFI_HW_OD] = prop_array[i].data;
|
||||||
|
break;
|
||||||
|
case CVP_KMD_PROP_PWR_FPS_ICA:
|
||||||
|
session_prop->fps[HFI_HW_ICA] = prop_array[i].data;
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"unrecognized sys property to set %d\n",
|
"unrecognized sys property to set %d\n",
|
||||||
@@ -1275,10 +1495,8 @@ static int cvp_drain_fence_sched_list(struct msm_cvp_inst *inst)
|
|||||||
mutex_lock(&q->lock);
|
mutex_lock(&q->lock);
|
||||||
list_for_each_entry(f, &q->sched_list, list) {
|
list_for_each_entry(f, &q->sched_list, list) {
|
||||||
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
||||||
dprintk(CVP_SYNX, "%s: frame %llu is in sched_list\n",
|
dprintk(CVP_SYNX, "%s: frame %llu %llu is in sched_list\n",
|
||||||
__func__, ktid);
|
__func__, ktid, f->frame_id);
|
||||||
dprintk(CVP_SYNX, "%s: frameID %llu is in sched_list\n",
|
|
||||||
__func__, f->frame_id);
|
|
||||||
++count;
|
++count;
|
||||||
}
|
}
|
||||||
mutex_unlock(&q->lock);
|
mutex_unlock(&q->lock);
|
||||||
@@ -1310,14 +1528,71 @@ retry:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cvp_clean_fence_queue(struct msm_cvp_inst *inst, int synx_state)
|
||||||
|
{
|
||||||
|
struct cvp_fence_queue *q;
|
||||||
|
struct cvp_fence_command *f, *d;
|
||||||
|
u64 ktid;
|
||||||
|
|
||||||
|
q = &inst->fence_cmd_queue;
|
||||||
|
|
||||||
|
mutex_lock(&q->lock);
|
||||||
|
q->mode = OP_DRAINING;
|
||||||
|
|
||||||
|
list_for_each_entry_safe(f, d, &q->wait_list, list) {
|
||||||
|
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
||||||
|
|
||||||
|
dprintk(CVP_SYNX, "%s: (%#x) flush frame %llu %llu wait_list\n",
|
||||||
|
__func__, hash32_ptr(inst->session), ktid, f->frame_id);
|
||||||
|
|
||||||
|
list_del_init(&f->list);
|
||||||
|
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
|
||||||
|
cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f, synx_state);
|
||||||
|
cvp_release_synx(inst, f);
|
||||||
|
cvp_free_fence_data(f);
|
||||||
|
}
|
||||||
|
|
||||||
|
list_for_each_entry(f, &q->sched_list, list) {
|
||||||
|
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
||||||
|
|
||||||
|
dprintk(CVP_SYNX, "%s: (%#x)flush frame %llu %llu sched_list\n",
|
||||||
|
__func__, hash32_ptr(inst->session), ktid, f->frame_id);
|
||||||
|
cvp_cancel_synx(inst, CVP_INPUT_SYNX, f, synx_state);
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&q->lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst)
|
||||||
|
{
|
||||||
|
struct cvp_fence_queue *q;
|
||||||
|
u32 count = 0, max_retries = 100;
|
||||||
|
|
||||||
|
cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_ERROR);
|
||||||
|
cvp_fence_thread_stop(inst);
|
||||||
|
|
||||||
|
/* Waiting for all output synx sent */
|
||||||
|
q = &inst->fence_cmd_queue;
|
||||||
|
retry:
|
||||||
|
mutex_lock(&q->lock);
|
||||||
|
if (list_empty(&q->sched_list)) {
|
||||||
|
mutex_unlock(&q->lock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
mutex_unlock(&q->lock);
|
||||||
|
usleep_range(500, 1000);
|
||||||
|
if (++count > max_retries)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
goto retry;
|
||||||
|
}
|
||||||
|
|
||||||
static int cvp_flush_all(struct msm_cvp_inst *inst)
|
static int cvp_flush_all(struct msm_cvp_inst *inst)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct msm_cvp_inst *s;
|
struct msm_cvp_inst *s;
|
||||||
struct cvp_fence_queue *q;
|
struct cvp_fence_queue *q;
|
||||||
struct cvp_fence_command *f, *d;
|
|
||||||
struct cvp_hfi_device *hdev;
|
struct cvp_hfi_device *hdev;
|
||||||
u64 ktid;
|
|
||||||
|
|
||||||
if (!inst || !inst->core) {
|
if (!inst || !inst->core) {
|
||||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||||
@@ -1328,40 +1603,15 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
|
|||||||
if (!s)
|
if (!s)
|
||||||
return -ECONNRESET;
|
return -ECONNRESET;
|
||||||
|
|
||||||
|
dprintk(CVP_SESS, "session %llx (%#x)flush all starts\n",
|
||||||
|
inst, hash32_ptr(inst->session));
|
||||||
q = &inst->fence_cmd_queue;
|
q = &inst->fence_cmd_queue;
|
||||||
hdev = inst->core->device;
|
hdev = inst->core->device;
|
||||||
|
|
||||||
mutex_lock(&q->lock);
|
cvp_clean_fence_queue(inst, SYNX_STATE_SIGNALED_CANCEL);
|
||||||
q->mode = OP_DRAINING;
|
|
||||||
|
|
||||||
list_for_each_entry_safe(f, d, &q->wait_list, list) {
|
dprintk(CVP_SESS, "%s: (%#x) send flush to fw\n",
|
||||||
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
__func__, hash32_ptr(inst->session));
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n",
|
|
||||||
__func__, ktid);
|
|
||||||
dprintk(CVP_SESS, "%s: flush frameID %llu from wait_list\n",
|
|
||||||
__func__, f->frame_id);
|
|
||||||
|
|
||||||
list_del_init(&f->list);
|
|
||||||
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
|
|
||||||
cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f);
|
|
||||||
cvp_release_synx(inst, f);
|
|
||||||
cvp_free_fence_data(f);
|
|
||||||
}
|
|
||||||
|
|
||||||
list_for_each_entry(f, &q->sched_list, list) {
|
|
||||||
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: flush frame %llu from sched_list\n",
|
|
||||||
__func__, ktid);
|
|
||||||
dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n",
|
|
||||||
__func__, f->frame_id);
|
|
||||||
cvp_cancel_synx(inst, CVP_INPUT_SYNX, f);
|
|
||||||
}
|
|
||||||
|
|
||||||
mutex_unlock(&q->lock);
|
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: send flush to fw\n", __func__);
|
|
||||||
|
|
||||||
/* Send flush to FW */
|
/* Send flush to FW */
|
||||||
rc = call_hfi_op(hdev, session_flush, (void *)inst->session);
|
rc = call_hfi_op(hdev, session_flush, (void *)inst->session);
|
||||||
@@ -1377,7 +1627,8 @@ static int cvp_flush_all(struct msm_cvp_inst *inst)
|
|||||||
dprintk(CVP_WARN, "%s: wait for signal failed, rc %d\n",
|
dprintk(CVP_WARN, "%s: wait for signal failed, rc %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: received flush from fw\n", __func__);
|
dprintk(CVP_SESS, "%s: (%#x) received flush from fw\n",
|
||||||
|
__func__, hash32_ptr(inst->session));
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
rc = cvp_drain_fence_sched_list(inst);
|
rc = cvp_drain_fence_sched_list(inst);
|
||||||
@@ -1440,6 +1691,8 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)
|
|||||||
if (!s)
|
if (!s)
|
||||||
return -ECONNRESET;
|
return -ECONNRESET;
|
||||||
|
|
||||||
|
dprintk(CVP_SESS, "Session %llx, flush frame with id %llu\n",
|
||||||
|
inst, frame_id);
|
||||||
q = &inst->fence_cmd_queue;
|
q = &inst->fence_cmd_queue;
|
||||||
|
|
||||||
mutex_lock(&q->lock);
|
mutex_lock(&q->lock);
|
||||||
@@ -1453,14 +1706,13 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)
|
|||||||
|
|
||||||
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: flush frame %llu from wait_list\n",
|
dprintk(CVP_SYNX, "%s: flush frame %llu %llu from wait_list\n",
|
||||||
__func__, ktid);
|
__func__, ktid, f->frame_id);
|
||||||
dprintk(CVP_SESS, "%s: flush frameID %llu from wait_list\n",
|
|
||||||
__func__, f->frame_id);
|
|
||||||
|
|
||||||
list_del_init(&f->list);
|
list_del_init(&f->list);
|
||||||
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
|
msm_cvp_unmap_frame(inst, f->pkt->client_data.kdata);
|
||||||
cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f);
|
cvp_cancel_synx(inst, CVP_OUTPUT_SYNX, f,
|
||||||
|
SYNX_STATE_SIGNALED_CANCEL);
|
||||||
cvp_release_synx(inst, f);
|
cvp_release_synx(inst, f);
|
||||||
cvp_free_fence_data(f);
|
cvp_free_fence_data(f);
|
||||||
}
|
}
|
||||||
@@ -1471,11 +1723,10 @@ static int cvp_flush_frame(struct msm_cvp_inst *inst, u64 frame_id)
|
|||||||
|
|
||||||
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
ktid = f->pkt->client_data.kdata & (FENCE_BIT - 1);
|
||||||
|
|
||||||
dprintk(CVP_SESS, "%s: flush frame %llu from sched_list\n",
|
dprintk(CVP_SYNX, "%s: flush frame %llu %llu from sched_list\n",
|
||||||
__func__, ktid);
|
__func__, ktid, f->frame_id);
|
||||||
dprintk(CVP_SESS, "%s: flush frameID %llu from sched_list\n",
|
cvp_cancel_synx(inst, CVP_INPUT_SYNX, f,
|
||||||
__func__, f->frame_id);
|
SYNX_STATE_SIGNALED_CANCEL);
|
||||||
cvp_cancel_synx(inst, CVP_INPUT_SYNX, f);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex_unlock(&q->lock);
|
mutex_unlock(&q->lock);
|
||||||
@@ -1640,7 +1891,7 @@ int msm_cvp_session_init(struct msm_cvp_inst *inst)
|
|||||||
inst->prop.priority = 0;
|
inst->prop.priority = 0;
|
||||||
inst->prop.is_secure = 0;
|
inst->prop.is_secure = 0;
|
||||||
inst->prop.dsp_mask = 0;
|
inst->prop.dsp_mask = 0;
|
||||||
inst->prop.fthread_nr = 2;
|
inst->prop.fthread_nr = 3;
|
||||||
|
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
@@ -33,4 +33,5 @@ int msm_cvp_handle_syscall(struct msm_cvp_inst *inst, struct cvp_kmd_arg *arg);
|
|||||||
int msm_cvp_session_init(struct msm_cvp_inst *inst);
|
int msm_cvp_session_init(struct msm_cvp_inst *inst);
|
||||||
int msm_cvp_session_deinit(struct msm_cvp_inst *inst);
|
int msm_cvp_session_deinit(struct msm_cvp_inst *inst);
|
||||||
int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst);
|
int msm_cvp_session_queue_stop(struct msm_cvp_inst *inst);
|
||||||
|
int cvp_stop_clean_fence_queue(struct msm_cvp_inst *inst);
|
||||||
#endif
|
#endif
|
||||||
|
@@ -498,6 +498,10 @@ static void msm_cvp_unmap_frame_buf(struct msm_cvp_inst *inst,
|
|||||||
} else if (atomic_dec_and_test(&smem->refcount)) {
|
} else if (atomic_dec_and_test(&smem->refcount)) {
|
||||||
clear_bit(smem->bitmap_index,
|
clear_bit(smem->bitmap_index,
|
||||||
&inst->dma_cache.usage_bitmap);
|
&inst->dma_cache.usage_bitmap);
|
||||||
|
dprintk(CVP_MEM, "smem %x %d iova %#x to be reused\n",
|
||||||
|
hash32_ptr(inst->session),
|
||||||
|
smem->size,
|
||||||
|
smem->device_addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -515,7 +519,8 @@ void msm_cvp_unmap_frame(struct msm_cvp_inst *inst, u64 ktid)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ktid &= (FENCE_BIT - 1);
|
ktid &= (FENCE_BIT - 1);
|
||||||
dprintk(CVP_MEM, "%s: unmap frame %llu\n", __func__, ktid);
|
dprintk(CVP_MEM, "%s: (%#x) unmap frame %llu\n",
|
||||||
|
__func__, hash32_ptr(inst->session), ktid);
|
||||||
|
|
||||||
found = false;
|
found = false;
|
||||||
mutex_lock(&inst->frames.lock);
|
mutex_lock(&inst->frames.lock);
|
||||||
|
@@ -166,6 +166,7 @@ int msm_cvp_smem_cache_operations(struct dma_buf *dbuf,
|
|||||||
enum smem_cache_ops cache_op,
|
enum smem_cache_ops cache_op,
|
||||||
unsigned long offset,
|
unsigned long offset,
|
||||||
unsigned long size);
|
unsigned long size);
|
||||||
|
int msm_cvp_map_ipcc_regs(u32 *iova);
|
||||||
|
|
||||||
/* CVP driver internal buffer management functions*/
|
/* CVP driver internal buffer management functions*/
|
||||||
struct cvp_internal_buf *cvp_allocate_arp_bufs(struct msm_cvp_inst *inst,
|
struct cvp_internal_buf *cvp_allocate_arp_bufs(struct msm_cvp_inst *inst,
|
||||||
|
@@ -8,7 +8,9 @@
|
|||||||
#include <linux/slab.h>
|
#include <linux/slab.h>
|
||||||
#include <linux/kernel.h>
|
#include <linux/kernel.h>
|
||||||
#include <linux/bitops.h>
|
#include <linux/bitops.h>
|
||||||
|
#ifndef CVP_MDT_ENABLED
|
||||||
#include <soc/qcom/subsystem_restart.h>
|
#include <soc/qcom/subsystem_restart.h>
|
||||||
|
#endif
|
||||||
#include <asm/div64.h>
|
#include <asm/div64.h>
|
||||||
#include "msm_cvp_common.h"
|
#include "msm_cvp_common.h"
|
||||||
#include "cvp_hfi_api.h"
|
#include "cvp_hfi_api.h"
|
||||||
@@ -402,6 +404,8 @@ int wait_for_sess_signal_receipt(struct msm_cvp_inst *inst,
|
|||||||
call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
|
call_hfi_op(hdev, flush_debug_queue, hdev->hfi_device_data);
|
||||||
dump_hfi_queue(hdev->hfi_device_data);
|
dump_hfi_queue(hdev->hfi_device_data);
|
||||||
rc = -EIO;
|
rc = -EIO;
|
||||||
|
} else if (inst->state == MSM_CVP_CORE_INVALID) {
|
||||||
|
rc = -ECONNRESET;
|
||||||
} else {
|
} else {
|
||||||
rc = 0;
|
rc = 0;
|
||||||
}
|
}
|
||||||
@@ -623,11 +627,13 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
|
|||||||
struct msm_cvp_core *core = NULL;
|
struct msm_cvp_core *core = NULL;
|
||||||
struct cvp_hfi_device *hdev = NULL;
|
struct cvp_hfi_device *hdev = NULL;
|
||||||
struct msm_cvp_inst *inst = NULL;
|
struct msm_cvp_inst *inst = NULL;
|
||||||
int rc = 0;
|
int i, rc = 0;
|
||||||
unsigned long flags = 0;
|
unsigned long flags = 0;
|
||||||
enum cvp_core_state cur_state;
|
enum cvp_core_state cur_state;
|
||||||
|
|
||||||
|
#ifndef CVP_MDT_ENABLED
|
||||||
subsystem_crashed("evass");
|
subsystem_crashed("evass");
|
||||||
|
#endif
|
||||||
if (!response) {
|
if (!response) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"Failed to get valid response for sys error\n");
|
"Failed to get valid response for sys error\n");
|
||||||
@@ -663,6 +669,10 @@ static void handle_sys_error(enum hal_command_response cmd, void *data)
|
|||||||
inst->cur_cmd_type, inst->state);
|
inst->cur_cmd_type, inst->state);
|
||||||
if (inst->state != MSM_CVP_CORE_INVALID) {
|
if (inst->state != MSM_CVP_CORE_INVALID) {
|
||||||
change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
|
change_cvp_inst_state(inst, MSM_CVP_CORE_INVALID);
|
||||||
|
if (cvp_stop_clean_fence_queue(inst))
|
||||||
|
dprintk(CVP_ERR, "Failed to clean fences\n");
|
||||||
|
for (i = 0; i < ARRAY_SIZE(inst->completions); i++)
|
||||||
|
complete(&inst->completions[i]);
|
||||||
spin_lock_irqsave(&inst->event_handler.lock, flags);
|
spin_lock_irqsave(&inst->event_handler.lock, flags);
|
||||||
inst->event_handler.event = CVP_SSR_EVENT;
|
inst->event_handler.event = CVP_SSR_EVENT;
|
||||||
spin_unlock_irqrestore(
|
spin_unlock_irqrestore(
|
||||||
|
@@ -17,6 +17,8 @@ static int dspVMperm[DSP_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC,
|
|||||||
PERM_READ | PERM_WRITE | PERM_EXEC };
|
PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||||
static int hlosVMperm[HLOS_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
|
static int hlosVMperm[HLOS_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||||
|
|
||||||
|
static int cvp_reinit_dsp(void);
|
||||||
|
|
||||||
static int cvp_dsp_send_cmd(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
static int cvp_dsp_send_cmd(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
@@ -40,7 +42,8 @@ exit:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd,
|
||||||
|
uint32_t len, struct cvp_dsp_rsp_msg *rsp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
@@ -63,12 +66,15 @@ static int cvp_dsp_send_cmd_sync(struct cvp_dsp_cmd_msg *cmd, uint32_t len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
|
rsp->ret = me->pending_dsp2cpu_rsp.ret;
|
||||||
|
rsp->dsp_state = me->pending_dsp2cpu_rsp.dsp_state;
|
||||||
me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
|
me->pending_dsp2cpu_rsp.type = CVP_INVALID_RPMSG_TYPE;
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
||||||
uint32_t size_in_bytes)
|
uint32_t size_in_bytes,
|
||||||
|
struct cvp_dsp_rsp_msg *rsp)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
@@ -88,7 +94,7 @@ static int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
|||||||
"%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n",
|
"%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n",
|
||||||
__func__, phys_addr, size_in_bytes, cmd.ddr_type);
|
__func__, phys_addr, size_in_bytes, cmd.ddr_type);
|
||||||
|
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||||
@@ -224,6 +230,8 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
bool retried = false;
|
||||||
|
|
||||||
cmd.type = CPU2DSP_SUSPEND;
|
cmd.type = CPU2DSP_SUSPEND;
|
||||||
|
|
||||||
@@ -231,8 +239,11 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||||||
if (me->state != DSP_READY)
|
if (me->state != DSP_READY)
|
||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
|
retry:
|
||||||
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
rc = cvp_dsp_send_cmd_sync(&cmd,
|
||||||
|
sizeof(struct cvp_dsp_cmd_msg),
|
||||||
|
&rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||||
@@ -240,8 +251,31 @@ int cvp_dsp_suspend(uint32_t session_flag)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
me->state = DSP_SUSPEND;
|
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||||
|
goto fatal_exit;
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||||
|
if (!retried) {
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
retried = true;
|
||||||
|
rc = cvp_reinit_dsp();
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
if (rc)
|
||||||
|
goto fatal_exit;
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
} else {
|
||||||
|
goto fatal_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
me->state = DSP_SUSPEND;
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
fatal_exit:
|
||||||
|
me->state = DSP_INVALID;
|
||||||
|
cvp_hyp_assign_from_dsp();
|
||||||
|
rc = -ENOTSUPP;
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&me->lock);
|
mutex_unlock(&me->lock);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -252,6 +286,7 @@ int cvp_dsp_resume(uint32_t session_flag)
|
|||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
|
||||||
cmd.type = CPU2DSP_RESUME;
|
cmd.type = CPU2DSP_RESUME;
|
||||||
|
|
||||||
@@ -260,7 +295,9 @@ int cvp_dsp_resume(uint32_t session_flag)
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
/* Use cvp_dsp_send_cmd_sync after dsp driver is ready */
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
rc = cvp_dsp_send_cmd_sync(&cmd,
|
||||||
|
sizeof(struct cvp_dsp_cmd_msg),
|
||||||
|
&rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
"%s: cvp_dsp_send_cmd failed rc = %d\n",
|
||||||
@@ -280,6 +317,7 @@ int cvp_dsp_shutdown(uint32_t session_flag)
|
|||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
|
||||||
cmd.type = CPU2DSP_SHUTDOWN;
|
cmd.type = CPU2DSP_SHUTDOWN;
|
||||||
|
|
||||||
@@ -288,7 +326,7 @@ int cvp_dsp_shutdown(uint32_t session_flag)
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
me->state = DSP_INACTIVE;
|
me->state = DSP_INACTIVE;
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: cvp_dsp_send_cmd failed with rc = %d\n",
|
"%s: cvp_dsp_send_cmd failed with rc = %d\n",
|
||||||
@@ -312,6 +350,8 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
int rc;
|
int rc;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
bool retried = false;
|
||||||
|
|
||||||
cmd.type = CPU2DSP_REGISTER_BUFFER;
|
cmd.type = CPU2DSP_REGISTER_BUFFER;
|
||||||
cmd.session_id = session_id;
|
cmd.session_id = session_id;
|
||||||
@@ -330,12 +370,43 @@ int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||||||
__func__, cmd.buff_size, cmd.session_id);
|
__func__, cmd.buff_size, cmd.session_id);
|
||||||
|
|
||||||
mutex_lock(&me->lock);
|
mutex_lock(&me->lock);
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
retry:
|
||||||
|
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFAIL || rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||||
|
dprintk(CVP_WARN, "%s, DSP return err %d\n", __func__, rsp.ret);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||||
|
goto fatal_exit;
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||||
|
if (!retried) {
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
retried = true;
|
||||||
|
rc = cvp_reinit_dsp();
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
if (rc)
|
||||||
|
goto fatal_exit;
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
} else {
|
||||||
|
goto fatal_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
fatal_exit:
|
||||||
|
me->state = DSP_INVALID;
|
||||||
|
cvp_hyp_assign_from_dsp();
|
||||||
|
rc = -ENOTSUPP;
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&me->lock);
|
mutex_unlock(&me->lock);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -349,6 +420,8 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||||||
struct cvp_dsp_cmd_msg cmd;
|
struct cvp_dsp_cmd_msg cmd;
|
||||||
int rc;
|
int rc;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
bool retried = false;
|
||||||
|
|
||||||
cmd.type = CPU2DSP_DEREGISTER_BUFFER;
|
cmd.type = CPU2DSP_DEREGISTER_BUFFER;
|
||||||
cmd.session_id = session_id;
|
cmd.session_id = session_id;
|
||||||
@@ -367,12 +440,43 @@ int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
|||||||
__func__, cmd.buff_size, cmd.session_id);
|
__func__, cmd.buff_size, cmd.session_id);
|
||||||
|
|
||||||
mutex_lock(&me->lock);
|
mutex_lock(&me->lock);
|
||||||
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg));
|
retry:
|
||||||
|
rc = cvp_dsp_send_cmd_sync(&cmd, sizeof(struct cvp_dsp_cmd_msg), &rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
dprintk(CVP_ERR, "%s send failed rc = %d\n", __func__, rc);
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFAIL || rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||||
|
dprintk(CVP_WARN, "%s, DSP return err %d\n", __func__, rsp.ret);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EUNAVAILABLE)
|
||||||
|
goto fatal_exit;
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFATAL) {
|
||||||
|
if (!retried) {
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
retried = true;
|
||||||
|
rc = cvp_reinit_dsp();
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
if (rc)
|
||||||
|
goto fatal_exit;
|
||||||
|
else
|
||||||
|
goto retry;
|
||||||
|
} else {
|
||||||
|
goto fatal_exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
|
||||||
|
fatal_exit:
|
||||||
|
me->state = DSP_INVALID;
|
||||||
|
cvp_hyp_assign_from_dsp();
|
||||||
|
rc = -ENOTSUPP;
|
||||||
exit:
|
exit:
|
||||||
mutex_unlock(&me->lock);
|
mutex_unlock(&me->lock);
|
||||||
return rc;
|
return rc;
|
||||||
@@ -393,11 +497,156 @@ static struct rpmsg_driver cvp_dsp_rpmsg_client = {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static void cvp_dsp_set_queue_hdr_defaults(struct cvp_hfi_queue_header *q_hdr)
|
||||||
|
{
|
||||||
|
q_hdr->qhdr_status = 0x1;
|
||||||
|
q_hdr->qhdr_type = CVP_IFACEQ_DFLT_QHDR;
|
||||||
|
q_hdr->qhdr_q_size = CVP_IFACEQ_QUEUE_SIZE / 4;
|
||||||
|
q_hdr->qhdr_pkt_size = 0;
|
||||||
|
q_hdr->qhdr_rx_wm = 0x1;
|
||||||
|
q_hdr->qhdr_tx_wm = 0x1;
|
||||||
|
q_hdr->qhdr_rx_req = 0x1;
|
||||||
|
q_hdr->qhdr_tx_req = 0x0;
|
||||||
|
q_hdr->qhdr_rx_irq_status = 0x0;
|
||||||
|
q_hdr->qhdr_tx_irq_status = 0x0;
|
||||||
|
q_hdr->qhdr_read_idx = 0x0;
|
||||||
|
q_hdr->qhdr_write_idx = 0x0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cvp_dsp_init_hfi_queue_hdr(struct iris_hfi_device *device)
|
||||||
|
{
|
||||||
|
u32 i;
|
||||||
|
struct cvp_hfi_queue_table_header *q_tbl_hdr;
|
||||||
|
struct cvp_hfi_queue_header *q_hdr;
|
||||||
|
struct cvp_iface_q_info *iface_q;
|
||||||
|
|
||||||
|
for (i = 0; i < CVP_IFACEQ_NUMQ; i++) {
|
||||||
|
iface_q = &device->dsp_iface_queues[i];
|
||||||
|
iface_q->q_hdr = CVP_IFACEQ_GET_QHDR_START_ADDR(
|
||||||
|
device->dsp_iface_q_table.align_virtual_addr, i);
|
||||||
|
cvp_dsp_set_queue_hdr_defaults(iface_q->q_hdr);
|
||||||
|
}
|
||||||
|
q_tbl_hdr = (struct cvp_hfi_queue_table_header *)
|
||||||
|
device->dsp_iface_q_table.align_virtual_addr;
|
||||||
|
q_tbl_hdr->qtbl_version = 0;
|
||||||
|
q_tbl_hdr->device_addr = (void *)device;
|
||||||
|
strlcpy(q_tbl_hdr->name, "msm_cvp", sizeof(q_tbl_hdr->name));
|
||||||
|
q_tbl_hdr->qtbl_size = CVP_IFACEQ_TABLE_SIZE;
|
||||||
|
q_tbl_hdr->qtbl_qhdr0_offset =
|
||||||
|
sizeof(struct cvp_hfi_queue_table_header);
|
||||||
|
q_tbl_hdr->qtbl_qhdr_size = sizeof(struct cvp_hfi_queue_header);
|
||||||
|
q_tbl_hdr->qtbl_num_q = CVP_IFACEQ_NUMQ;
|
||||||
|
q_tbl_hdr->qtbl_num_active_q = CVP_IFACEQ_NUMQ;
|
||||||
|
|
||||||
|
iface_q = &device->dsp_iface_queues[CVP_IFACEQ_CMDQ_IDX];
|
||||||
|
q_hdr = iface_q->q_hdr;
|
||||||
|
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
||||||
|
q_hdr->qhdr_type |= HFI_Q_ID_HOST_TO_CTRL_CMD_Q;
|
||||||
|
|
||||||
|
iface_q = &device->dsp_iface_queues[CVP_IFACEQ_MSGQ_IDX];
|
||||||
|
q_hdr = iface_q->q_hdr;
|
||||||
|
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
||||||
|
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_MSG_Q;
|
||||||
|
|
||||||
|
iface_q = &device->dsp_iface_queues[CVP_IFACEQ_DBGQ_IDX];
|
||||||
|
q_hdr = iface_q->q_hdr;
|
||||||
|
q_hdr->qhdr_start_addr = iface_q->q_array.align_device_addr;
|
||||||
|
q_hdr->qhdr_type |= HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q;
|
||||||
|
/*
|
||||||
|
* Set receive request to zero on debug queue as there is no
|
||||||
|
* need of interrupt from cvp hardware for debug messages
|
||||||
|
*/
|
||||||
|
q_hdr->qhdr_rx_req = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int __reinit_dsp(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
uint32_t flag = 0;
|
||||||
|
uint64_t addr;
|
||||||
|
uint32_t size;
|
||||||
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
|
struct msm_cvp_core *core;
|
||||||
|
struct iris_hfi_device *device;
|
||||||
|
|
||||||
|
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||||
|
if (core && core->device)
|
||||||
|
device = core->device->hfi_device_data;
|
||||||
|
else
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (!device) {
|
||||||
|
dprintk(CVP_ERR, "%s: NULL device\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force shutdown DSP */
|
||||||
|
rc = cvp_dsp_shutdown(flag);
|
||||||
|
if (rc)
|
||||||
|
return rc;
|
||||||
|
|
||||||
|
/* Resend HFI queue */
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
if (!device->dsp_iface_q_table.align_virtual_addr) {
|
||||||
|
dprintk(CVP_ERR, "%s: DSP HFI queue released\n", __func__);
|
||||||
|
rc = -EINVAL;
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle;
|
||||||
|
size = device->dsp_iface_q_table.mem_data.size;
|
||||||
|
|
||||||
|
if (!addr || !size) {
|
||||||
|
dprintk(CVP_DSP, "%s: HFI queue is not ready\n", __func__);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cvp_hyp_assign_to_dsp(addr, size);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_ERR, "%s: cvp_hyp_assign_to_dsp. rc=%d\n",
|
||||||
|
__func__, rc);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size, &rsp);
|
||||||
|
if (rc) {
|
||||||
|
dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
|
||||||
|
__func__, rc);
|
||||||
|
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
if (rsp.ret) {
|
||||||
|
dprintk(CVP_ERR, "%s: DSP error %d %d\n", __func__,
|
||||||
|
rsp.ret, rsp.dsp_state);
|
||||||
|
rc = -ENODEV;
|
||||||
|
}
|
||||||
|
exit:
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int cvp_reinit_dsp(void)
|
||||||
|
{
|
||||||
|
int rc;
|
||||||
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
|
||||||
|
rc = __reinit_dsp();
|
||||||
|
if (rc) {
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
me->state = DSP_INVALID;
|
||||||
|
cvp_hyp_assign_from_dsp();
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
}
|
||||||
|
return rc;
|
||||||
|
}
|
||||||
|
|
||||||
void cvp_dsp_send_hfi_queue(void)
|
void cvp_dsp_send_hfi_queue(void)
|
||||||
{
|
{
|
||||||
struct msm_cvp_core *core;
|
struct msm_cvp_core *core;
|
||||||
struct iris_hfi_device *device;
|
struct iris_hfi_device *device;
|
||||||
struct cvp_dsp_apps *me = &gfa_cv;
|
struct cvp_dsp_apps *me = &gfa_cv;
|
||||||
|
struct cvp_dsp_rsp_msg rsp;
|
||||||
uint64_t addr;
|
uint64_t addr;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
int rc;
|
int rc;
|
||||||
@@ -418,6 +667,13 @@ void cvp_dsp_send_hfi_queue(void)
|
|||||||
mutex_lock(&device->lock);
|
mutex_lock(&device->lock);
|
||||||
mutex_lock(&me->lock);
|
mutex_lock(&me->lock);
|
||||||
|
|
||||||
|
if (!device->dsp_iface_q_table.align_virtual_addr) {
|
||||||
|
dprintk(CVP_ERR, "%s: DSP HFI queue released\n", __func__);
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
mutex_unlock(&device->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle;
|
addr = (uint64_t)device->dsp_iface_q_table.mem_data.dma_handle;
|
||||||
size = device->dsp_iface_q_table.mem_data.size;
|
size = device->dsp_iface_q_table.mem_data.size;
|
||||||
|
|
||||||
@@ -436,7 +692,13 @@ void cvp_dsp_send_hfi_queue(void)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size);
|
if (me->state == DSP_PROBED) {
|
||||||
|
cvp_dsp_init_hfi_queue_hdr(device);
|
||||||
|
dprintk(CVP_WARN,
|
||||||
|
"%s: Done init of HFI queue headers\n", __func__);
|
||||||
|
}
|
||||||
|
|
||||||
|
rc = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)addr, size, &rsp);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
|
dprintk(CVP_WARN, "%s: Send HFI Queue failed rc = %d\n",
|
||||||
__func__, rc);
|
__func__, rc);
|
||||||
@@ -444,6 +706,30 @@ void cvp_dsp_send_hfi_queue(void)
|
|||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EUNSUPPORTED) {
|
||||||
|
dprintk(CVP_WARN, "%s unsupported cmd %d\n",
|
||||||
|
__func__, rsp.type);
|
||||||
|
goto exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rsp.ret == CPU2DSP_EFATAL || rsp.ret == CPU2DSP_EUNAVAILABLE) {
|
||||||
|
dprintk(CVP_ERR, "%s fatal error returned %d\n",
|
||||||
|
__func__, rsp.dsp_state);
|
||||||
|
me->state = DSP_INVALID;
|
||||||
|
cvp_hyp_assign_from_dsp();
|
||||||
|
goto exit;
|
||||||
|
} else if (rsp.ret == CPU2DSP_EINVALSTATE) {
|
||||||
|
dprintk(CVP_ERR, "%s dsp invalid state %d\n",
|
||||||
|
__func__, rsp.dsp_state);
|
||||||
|
mutex_unlock(&me->lock);
|
||||||
|
if (cvp_reinit_dsp()) {
|
||||||
|
dprintk(CVP_ERR, "%s reinit dsp fail\n", __func__);
|
||||||
|
mutex_unlock(&device->lock);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mutex_lock(&me->lock);
|
||||||
|
}
|
||||||
|
|
||||||
dprintk(CVP_DSP, "%s: dsp initialized\n", __func__);
|
dprintk(CVP_DSP, "%s: dsp initialized\n", __func__);
|
||||||
me->state = DSP_READY;
|
me->state = DSP_READY;
|
||||||
|
|
||||||
@@ -498,8 +784,10 @@ wait_dsp:
|
|||||||
switch (me->pending_dsp2cpu_cmd.type) {
|
switch (me->pending_dsp2cpu_cmd.type) {
|
||||||
case DSP2CPU_POWERON:
|
case DSP2CPU_POWERON:
|
||||||
{
|
{
|
||||||
if (me->state == DSP_READY)
|
if (me->state == DSP_READY) {
|
||||||
|
cmd.ret = 0;
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
mutex_unlock(&me->lock);
|
mutex_unlock(&me->lock);
|
||||||
old_state = me->state;
|
old_state = me->state;
|
||||||
|
@@ -24,6 +24,16 @@
|
|||||||
int cvp_dsp_device_init(void);
|
int cvp_dsp_device_init(void);
|
||||||
void cvp_dsp_device_exit(void);
|
void cvp_dsp_device_exit(void);
|
||||||
void cvp_dsp_send_hfi_queue(void);
|
void cvp_dsp_send_hfi_queue(void);
|
||||||
|
void cvp_dsp_init_hfi_queue_hdr(struct iris_hfi_device *device);
|
||||||
|
|
||||||
|
enum CPU2DSP_STATUS {
|
||||||
|
CPU2DSP_SUCCESS = 0,
|
||||||
|
CPU2DSP_EFAIL = 1,
|
||||||
|
CPU2DSP_EFATAL = 2,
|
||||||
|
CPU2DSP_EUNAVAILABLE = 3,
|
||||||
|
CPU2DSP_EINVALSTATE = 4,
|
||||||
|
CPU2DSP_EUNSUPPORTED = 5,
|
||||||
|
};
|
||||||
|
|
||||||
enum CVP_DSP_COMMAND {
|
enum CVP_DSP_COMMAND {
|
||||||
CPU2DSP_SEND_HFI_QUEUE = 0,
|
CPU2DSP_SEND_HFI_QUEUE = 0,
|
||||||
@@ -58,7 +68,8 @@ struct cvp_dsp_cmd_msg {
|
|||||||
struct cvp_dsp_rsp_msg {
|
struct cvp_dsp_rsp_msg {
|
||||||
uint32_t type;
|
uint32_t type;
|
||||||
int32_t ret;
|
int32_t ret;
|
||||||
uint32_t reserved[CVP_DSP_MAX_RESERVED];
|
uint32_t dsp_state;
|
||||||
|
uint32_t reserved[CVP_DSP_MAX_RESERVED - 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cvp_dsp2cpu_cmd_msg {
|
struct cvp_dsp2cpu_cmd_msg {
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include <media/msm_media_info.h>
|
#include <media/msm_media_info.h>
|
||||||
#include <media/msm_eva_private.h>
|
#include <media/msm_eva_private.h>
|
||||||
#include "cvp_hfi_api.h"
|
#include "cvp_hfi_api.h"
|
||||||
|
#include "cvp_hfi_helper.h"
|
||||||
#include <synx_api.h>
|
#include <synx_api.h>
|
||||||
|
|
||||||
#define MAX_SUPPORTED_INSTANCES 16
|
#define MAX_SUPPORTED_INSTANCES 16
|
||||||
@@ -192,7 +193,7 @@ enum msm_cvp_modes {
|
|||||||
|
|
||||||
struct cvp_session_msg {
|
struct cvp_session_msg {
|
||||||
struct list_head node;
|
struct list_head node;
|
||||||
struct cvp_hfi_msg_session_hdr pkt;
|
struct cvp_hfi_msg_session_hdr_ext pkt;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct cvp_session_queue {
|
struct cvp_session_queue {
|
||||||
@@ -203,6 +204,23 @@ struct cvp_session_queue {
|
|||||||
wait_queue_head_t wq;
|
wait_queue_head_t wq;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define CVP_CYCLE_STAT_SIZE 8
|
||||||
|
struct cvp_cycle_stat {
|
||||||
|
u32 busy[CVP_CYCLE_STAT_SIZE];
|
||||||
|
u32 total;
|
||||||
|
u32 idx;
|
||||||
|
u32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct cvp_cycle_info {
|
||||||
|
u32 sum_fps[HFI_MAX_HW_THREADS];
|
||||||
|
u32 hi_ctrl_lim[HFI_MAX_HW_THREADS];
|
||||||
|
u32 lo_ctrl_lim[HFI_MAX_HW_THREADS];
|
||||||
|
struct cvp_cycle_stat cycle[HFI_MAX_HW_THREADS];
|
||||||
|
unsigned long conf_freq;
|
||||||
|
struct mutex lock;
|
||||||
|
};
|
||||||
|
|
||||||
struct cvp_session_prop {
|
struct cvp_session_prop {
|
||||||
u32 type;
|
u32 type;
|
||||||
u32 kernel_mask;
|
u32 kernel_mask;
|
||||||
@@ -224,6 +242,7 @@ struct cvp_session_prop {
|
|||||||
u32 ddr_op_bw;
|
u32 ddr_op_bw;
|
||||||
u32 ddr_cache;
|
u32 ddr_cache;
|
||||||
u32 ddr_op_cache;
|
u32 ddr_op_cache;
|
||||||
|
u32 fps[HFI_MAX_HW_THREADS];
|
||||||
};
|
};
|
||||||
|
|
||||||
enum cvp_event_t {
|
enum cvp_event_t {
|
||||||
@@ -265,6 +284,7 @@ struct msm_cvp_core {
|
|||||||
u32 last_fault_addr;
|
u32 last_fault_addr;
|
||||||
bool trigger_ssr;
|
bool trigger_ssr;
|
||||||
unsigned long curr_freq;
|
unsigned long curr_freq;
|
||||||
|
struct cvp_cycle_info dyn_clk;
|
||||||
atomic64_t kernel_trans_id;
|
atomic64_t kernel_trans_id;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -10,6 +10,9 @@ static int _get_pkt_hdr_from_user(struct cvp_kmd_arg __user *up,
|
|||||||
struct cvp_hal_session_cmd_pkt *pkt_hdr)
|
struct cvp_hal_session_cmd_pkt *pkt_hdr)
|
||||||
{
|
{
|
||||||
struct cvp_kmd_hfi_packet *u;
|
struct cvp_kmd_hfi_packet *u;
|
||||||
|
struct cvp_hfi_msg_session_hdr *hdr;
|
||||||
|
|
||||||
|
hdr = (struct cvp_hfi_msg_session_hdr *)pkt_hdr;
|
||||||
|
|
||||||
u = &up->data.hfi_pkt;
|
u = &up->data.hfi_pkt;
|
||||||
|
|
||||||
@@ -33,7 +36,7 @@ static int _get_pkt_hdr_from_user(struct cvp_kmd_arg __user *up,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
set_default_pkt_hdr:
|
set_default_pkt_hdr:
|
||||||
pkt_hdr->size = get_msg_size();
|
pkt_hdr->size = get_msg_size(hdr);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -451,7 +454,7 @@ static int _put_user_session_info(
|
|||||||
static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
|
static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i, size = get_msg_size() >> 2;
|
int i, size;
|
||||||
struct cvp_kmd_arg __user *up = (struct cvp_kmd_arg *)arg;
|
struct cvp_kmd_arg __user *up = (struct cvp_kmd_arg *)arg;
|
||||||
struct cvp_hal_session_cmd_pkt pkt_hdr;
|
struct cvp_hal_session_cmd_pkt pkt_hdr;
|
||||||
|
|
||||||
@@ -467,9 +470,12 @@ static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
|
|||||||
case CVP_KMD_RECEIVE_MSG_PKT:
|
case CVP_KMD_RECEIVE_MSG_PKT:
|
||||||
{
|
{
|
||||||
struct cvp_kmd_hfi_packet *k, *u;
|
struct cvp_kmd_hfi_packet *k, *u;
|
||||||
|
struct cvp_hfi_msg_session_hdr *hdr;
|
||||||
|
|
||||||
k = &kp->data.hfi_pkt;
|
k = &kp->data.hfi_pkt;
|
||||||
u = &up->data.hfi_pkt;
|
u = &up->data.hfi_pkt;
|
||||||
|
hdr = (struct cvp_hfi_msg_session_hdr *)k;
|
||||||
|
size = get_msg_size(hdr) >> 2;
|
||||||
for (i = 0; i < size; i++)
|
for (i = 0; i < size; i++)
|
||||||
if (put_user(k->pkt_data[i], &u->pkt_data[i]))
|
if (put_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||||
return -EFAULT;
|
return -EFAULT;
|
||||||
|
@@ -115,6 +115,25 @@ void msm_cvp_free_platform_resources(
|
|||||||
msm_cvp_free_bus_vectors(res);
|
msm_cvp_free_bus_vectors(res);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int msm_cvp_load_ipcc_regs(struct msm_cvp_platform_resources *res)
|
||||||
|
{
|
||||||
|
int ret = 0;
|
||||||
|
unsigned int reg_config[2];
|
||||||
|
struct platform_device *pdev = res->pdev;
|
||||||
|
|
||||||
|
ret = of_property_read_u32_array(pdev->dev.of_node, "qcom,ipcc-reg",
|
||||||
|
reg_config, 2);
|
||||||
|
if (ret) {
|
||||||
|
dprintk(CVP_ERR, "Failed to read ipcc reg: %d\n", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
res->ipcc_reg_base = reg_config[0];
|
||||||
|
res->ipcc_reg_size = reg_config[1];
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static int msm_cvp_load_reg_table(struct msm_cvp_platform_resources *res)
|
static int msm_cvp_load_reg_table(struct msm_cvp_platform_resources *res)
|
||||||
{
|
{
|
||||||
struct reg_set *reg_set;
|
struct reg_set *reg_set;
|
||||||
@@ -783,6 +802,10 @@ int cvp_read_platform_resources_from_dt(
|
|||||||
goto err_load_reg_table;
|
goto err_load_reg_table;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
rc = msm_cvp_load_ipcc_regs(res);
|
||||||
|
if (rc)
|
||||||
|
dprintk(CVP_ERR, "Failed to load IPCC regs: %d\n", rc);
|
||||||
|
|
||||||
rc = msm_cvp_load_regulator_table(res);
|
rc = msm_cvp_load_regulator_table(res);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "Failed to load list of regulators %d\n", rc);
|
dprintk(CVP_ERR, "Failed to load list of regulators %d\n", rc);
|
||||||
|
@@ -136,7 +136,9 @@ struct msm_cvp_mem_cdsp {
|
|||||||
struct msm_cvp_platform_resources {
|
struct msm_cvp_platform_resources {
|
||||||
phys_addr_t firmware_base;
|
phys_addr_t firmware_base;
|
||||||
phys_addr_t register_base;
|
phys_addr_t register_base;
|
||||||
|
phys_addr_t ipcc_reg_base;
|
||||||
uint32_t register_size;
|
uint32_t register_size;
|
||||||
|
uint32_t ipcc_reg_size;
|
||||||
uint32_t irq;
|
uint32_t irq;
|
||||||
uint32_t sku_version;
|
uint32_t sku_version;
|
||||||
struct allowed_clock_rates_table *allowed_clks_tbl;
|
struct allowed_clock_rates_table *allowed_clks_tbl;
|
||||||
|
@@ -73,8 +73,8 @@ int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc,
|
|||||||
rc = synx_import(ssid, ¶ms);
|
rc = synx_import(ssid, ¶ms);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: synx_import failed\n",
|
"%s: %d synx_import failed\n",
|
||||||
__func__);
|
__func__, h_synx);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -102,8 +102,8 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc)
|
|||||||
rc = synx_release(ssid, h_synx);
|
rc = synx_release(ssid, h_synx);
|
||||||
if (rc)
|
if (rc)
|
||||||
dprintk(CVP_ERR,
|
dprintk(CVP_ERR,
|
||||||
"%s: synx_release %d failed\n",
|
"%s: synx_release %d, %d failed\n",
|
||||||
__func__, i);
|
__func__, h_synx, i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@@ -111,14 +111,14 @@ int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc)
|
|||||||
|
|
||||||
static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
|
static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
|
||||||
enum cvp_synx_type type,
|
enum cvp_synx_type type,
|
||||||
struct cvp_fence_command *fc)
|
struct cvp_fence_command *fc,
|
||||||
|
int synx_state)
|
||||||
{
|
{
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
int i;
|
int i;
|
||||||
int h_synx;
|
int h_synx;
|
||||||
struct synx_session ssid;
|
struct synx_session ssid;
|
||||||
int start = 0, end = 0;
|
int start = 0, end = 0;
|
||||||
int synx_state = SYNX_STATE_SIGNALED_CANCEL;
|
|
||||||
|
|
||||||
ssid = inst->synx_session_id;
|
ssid = inst->synx_session_id;
|
||||||
|
|
||||||
@@ -137,11 +137,12 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
|
|||||||
h_synx = fc->synx[i];
|
h_synx = fc->synx[i];
|
||||||
if (h_synx) {
|
if (h_synx) {
|
||||||
rc = synx_signal(ssid, h_synx, synx_state);
|
rc = synx_signal(ssid, h_synx, synx_state);
|
||||||
if (rc) {
|
dprintk(CVP_SYNX, "Cancel synx %d session %llx\n",
|
||||||
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
|
h_synx, inst);
|
||||||
__func__, i);
|
if (rc)
|
||||||
synx_state = SYNX_STATE_SIGNALED_ERROR;
|
dprintk(CVP_ERR,
|
||||||
}
|
"%s: synx_signal %d %d %d failed\n",
|
||||||
|
__func__, h_synx, i, synx_state);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,14 +152,14 @@ static int cvp_cancel_synx_impl(struct msm_cvp_inst *inst,
|
|||||||
}
|
}
|
||||||
|
|
||||||
int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
||||||
struct cvp_fence_command *fc)
|
struct cvp_fence_command *fc, int synx_state)
|
||||||
{
|
{
|
||||||
if (fc->signature != 0xFEEDFACE) {
|
if (fc->signature != 0xFEEDFACE) {
|
||||||
dprintk(CVP_ERR, "%s deprecated synx path\n", __func__);
|
dprintk(CVP_ERR, "%s deprecated synx path\n", __func__);
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return cvp_cancel_synx_impl(inst, type, fc);
|
return cvp_cancel_synx_impl(inst, type, fc, synx_state);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
|
static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
|
||||||
@@ -186,6 +187,8 @@ static int cvp_wait_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
|
|||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
dprintk(CVP_SYNX, "Wait synx %d returned succes\n",
|
||||||
|
h_synx);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -203,10 +206,12 @@ static int cvp_signal_synx(struct synx_session ssid, u32 *synx, u32 num_synx,
|
|||||||
if (h_synx) {
|
if (h_synx) {
|
||||||
rc = synx_signal(ssid, h_synx, synx_state);
|
rc = synx_signal(ssid, h_synx, synx_state);
|
||||||
if (rc) {
|
if (rc) {
|
||||||
dprintk(CVP_ERR, "%s: synx_signal %d failed\n",
|
dprintk(CVP_ERR,
|
||||||
current->comm, i);
|
"%s: synx_signal %d %d failed\n",
|
||||||
|
current->comm, h_synx, i);
|
||||||
synx_state = SYNX_STATE_SIGNALED_ERROR;
|
synx_state = SYNX_STATE_SIGNALED_ERROR;
|
||||||
}
|
}
|
||||||
|
dprintk(CVP_SYNX, "Signaled synx %d\n", h_synx);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
@@ -48,7 +48,7 @@ int cvp_import_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc,
|
|||||||
u32 *fence);
|
u32 *fence);
|
||||||
int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc);
|
int cvp_release_synx(struct msm_cvp_inst *inst, struct cvp_fence_command *fc);
|
||||||
int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
int cvp_cancel_synx(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
||||||
struct cvp_fence_command *fc);
|
struct cvp_fence_command *fc, int synx_state);
|
||||||
int cvp_synx_ops(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
int cvp_synx_ops(struct msm_cvp_inst *inst, enum cvp_synx_type type,
|
||||||
struct cvp_fence_command *fc, u32 *synx_state);
|
struct cvp_fence_command *fc, u32 *synx_state);
|
||||||
void cvp_dump_fence_queue(struct msm_cvp_inst *inst);
|
void cvp_dump_fence_queue(struct msm_cvp_inst *inst);
|
||||||
|
@@ -14,6 +14,7 @@
|
|||||||
#include "msm_cvp_core.h"
|
#include "msm_cvp_core.h"
|
||||||
#include "msm_cvp_debug.h"
|
#include "msm_cvp_debug.h"
|
||||||
#include "msm_cvp_resources.h"
|
#include "msm_cvp_resources.h"
|
||||||
|
#include "cvp_core_hfi.h"
|
||||||
|
|
||||||
|
|
||||||
static int msm_dma_get_device_address(struct dma_buf *dbuf, u32 align,
|
static int msm_dma_get_device_address(struct dma_buf *dbuf, u32 align,
|
||||||
@@ -471,3 +472,41 @@ struct context_bank_info *msm_cvp_smem_get_context_bank(bool is_secure,
|
|||||||
|
|
||||||
return match;
|
return match;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int msm_cvp_map_ipcc_regs(u32 *iova)
|
||||||
|
{
|
||||||
|
struct context_bank_info *cb;
|
||||||
|
struct msm_cvp_core *core;
|
||||||
|
struct cvp_hfi_device *hfi_ops;
|
||||||
|
struct iris_hfi_device *dev = NULL;
|
||||||
|
phys_addr_t paddr;
|
||||||
|
u32 size;
|
||||||
|
|
||||||
|
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||||
|
if (core) {
|
||||||
|
hfi_ops = core->device;
|
||||||
|
if (hfi_ops)
|
||||||
|
dev = hfi_ops->hfi_device_data;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!dev)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
paddr = dev->res->ipcc_reg_base;
|
||||||
|
size = dev->res->ipcc_reg_size;
|
||||||
|
|
||||||
|
if (!paddr || !size)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
cb = msm_cvp_smem_get_context_bank(false, dev->res, 0);
|
||||||
|
if (!cb) {
|
||||||
|
dprintk(CVP_ERR, "%s: fail to get context bank\n", __func__);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
*iova = dma_map_resource(cb->dev, paddr, size, DMA_BIDIRECTIONAL, 0);
|
||||||
|
if (*iova == DMA_MAPPING_ERROR) {
|
||||||
|
dprintk(CVP_WARN, "%s: fail to map IPCC regs\n", __func__);
|
||||||
|
return -EFAULT;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
Reference in New Issue
Block a user