msm: cvp: Port CVP driver to 5.x kernel
Add new CVP feature support. Make CVP driver work with 5.x kernel: Modified bus and ion function calls. Modified synx and firmware version function calls. Demodulized CPU-DSP driver interface. Added Lahaina platform configuration. Enable building CVP driver as DLKM. Change-Id: I8a0a21b3ae87c19bf4e59bed16e9dba304503cc6 Signed-off-by: George Shen <sqiao@codeaurora.org>
This commit is contained in:
parent
a203c595ba
commit
ffe925cbca
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
source "drivers/media/platform/msm/synx/Kconfig"
|
||||
source "drivers/media/platform/msm/cvp/Kconfig"
|
||||
|
@ -1,3 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
|
||||
obj-$(CONFIG_MSM_GLOBAL_SYNX) += synx/
|
||||
obj-$(CONFIG_MSM_CVP) += cvp/
|
||||
|
10
drivers/media/platform/msm/cvp/Kconfig
Normal file
10
drivers/media/platform/msm/cvp/Kconfig
Normal file
@ -0,0 +1,10 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
#
|
||||
# CVP CORE
|
||||
#
|
||||
|
||||
menuconfig MSM_CVP
|
||||
tristate "MSM CVP driver"
|
||||
help
|
||||
Enable support of MSM CVP driver for
|
||||
Qualcomm Technologies, Inc.
|
21
drivers/media/platform/msm/cvp/Makefile
Normal file
21
drivers/media/platform/msm/cvp/Makefile
Normal file
@ -0,0 +1,21 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
ccflags-y += -I$(srctree)/drivers/media/platform/msm/cvp/
|
||||
ccflags-y += -I$(srctree)/drivers/media/platform/msm/synx/
|
||||
|
||||
msm-cvp-objs := cvp.o \
|
||||
msm_cvp_ioctl.o \
|
||||
msm_cvp_platform.o \
|
||||
msm_cvp_common.o \
|
||||
msm_cvp_core.o \
|
||||
msm_cvp.o \
|
||||
msm_smem.o \
|
||||
msm_cvp_debug.o \
|
||||
msm_cvp_res_parse.o \
|
||||
cvp_hfi.o \
|
||||
hfi_response_handler.o \
|
||||
hfi_packetization.o \
|
||||
cvp_core_hfi.o \
|
||||
msm_cvp_clocks.o \
|
||||
msm_cvp_dsp.o
|
||||
|
||||
obj-$(CONFIG_MSM_CVP) := msm-cvp.o
|
607
drivers/media/platform/msm/cvp/cvp.c
Normal file
607
drivers/media/platform/msm/cvp/cvp.c
Normal file
@ -0,0 +1,607 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/io.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include "msm_cvp_common.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp_internal.h"
|
||||
#include "msm_cvp_res_parse.h"
|
||||
#include "msm_cvp_resources.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "cvp_private.h"
|
||||
#include "msm_cvp_clocks.h"
|
||||
#include "msm_cvp_dsp.h"
|
||||
|
||||
#define BASE_DEVICE_NUMBER 32
|
||||
#define CLASS_NAME "cvp"
|
||||
#define DRIVER_NAME "cvp"
|
||||
|
||||
struct msm_cvp_drv *cvp_driver;
|
||||
|
||||
static int cvp_open(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int rc;
|
||||
struct msm_cvp_core *core = container_of(inode->i_cdev,
|
||||
struct msm_cvp_core, cdev);
|
||||
struct msm_cvp_inst *inst;
|
||||
|
||||
dprintk(CVP_DBG, "%s: Enter\n", __func__);
|
||||
|
||||
rc = cvp_dsp_device_init();
|
||||
inst = msm_cvp_open(core->id, MSM_CVP_USER);
|
||||
if (!inst || rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to create cvp instance rc=%d\n", rc);
|
||||
return -ENOMEM;
|
||||
}
|
||||
filp->private_data = inst;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cvp_close(struct inode *inode, struct file *filp)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_inst *inst = filp->private_data;
|
||||
|
||||
rc = msm_cvp_close(inst);
|
||||
filp->private_data = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static unsigned int cvp_poll(struct file *filp, struct poll_table_struct *p)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_inst *inst = filp->private_data;
|
||||
unsigned long flags = 0;
|
||||
|
||||
poll_wait(filp, &inst->event_handler.wq, p);
|
||||
|
||||
spin_lock_irqsave(&inst->event_handler.lock, flags);
|
||||
if (inst->event_handler.event == CVP_SSR_EVENT)
|
||||
rc |= POLLPRI;
|
||||
spin_unlock_irqrestore(&inst->event_handler.lock, flags);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations cvp_fops = {
|
||||
.owner = THIS_MODULE,
|
||||
.open = cvp_open,
|
||||
.release = cvp_close,
|
||||
.unlocked_ioctl = cvp_unblocked_ioctl,
|
||||
.compat_ioctl = cvp_compat_ioctl,
|
||||
.poll = cvp_poll,
|
||||
};
|
||||
|
||||
static int read_platform_resources(struct msm_cvp_core *core,
|
||||
struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!core || !pdev) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params %pK %pK\n",
|
||||
__func__, core, pdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core->hfi_type = CVP_HFI_IRIS;
|
||||
core->resources.pdev = pdev;
|
||||
if (pdev->dev.of_node) {
|
||||
/* Target supports DT, parse from it */
|
||||
rc = cvp_read_platform_resources_from_drv_data(core);
|
||||
rc = cvp_read_platform_resources_from_dt(&core->resources);
|
||||
} else {
|
||||
dprintk(CVP_ERR, "pdev node is NULL\n");
|
||||
rc = -EINVAL;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_cvp_initialize_core(struct platform_device *pdev,
|
||||
struct msm_cvp_core *core)
|
||||
{
|
||||
int i = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (!core)
|
||||
return -EINVAL;
|
||||
rc = read_platform_resources(core, pdev);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to get platform resources\n");
|
||||
return rc;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&core->instances);
|
||||
mutex_init(&core->lock);
|
||||
|
||||
core->state = CVP_CORE_UNINIT;
|
||||
for (i = SYS_MSG_INDEX(SYS_MSG_START);
|
||||
i <= SYS_MSG_INDEX(SYS_MSG_END); i++) {
|
||||
init_completion(&core->completions[i]);
|
||||
}
|
||||
|
||||
INIT_DELAYED_WORK(&core->fw_unload_work, msm_cvp_fw_unload_handler);
|
||||
INIT_WORK(&core->ssr_work, msm_cvp_ssr_handler);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static ssize_t link_name_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct msm_cvp_core *core = dev_get_drvdata(dev);
|
||||
|
||||
if (core)
|
||||
if (dev == core->dev)
|
||||
return snprintf(buf, PAGE_SIZE, "msm_cvp\n");
|
||||
else
|
||||
return 0;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(link_name);
|
||||
|
||||
static ssize_t pwr_collapse_delay_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
unsigned long val = 0;
|
||||
int rc = 0;
|
||||
struct msm_cvp_core *core = NULL;
|
||||
|
||||
rc = kstrtoul(buf, 0, &val);
|
||||
if (rc)
|
||||
return rc;
|
||||
else if (!val)
|
||||
return -EINVAL;
|
||||
|
||||
core = get_cvp_core(MSM_CORE_CVP);
|
||||
if (!core)
|
||||
return -EINVAL;
|
||||
core->resources.msm_cvp_pwr_collapse_delay = val;
|
||||
return count;
|
||||
}
|
||||
|
||||
static ssize_t pwr_collapse_delay_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct msm_cvp_core *core = NULL;
|
||||
|
||||
core = get_cvp_core(MSM_CORE_CVP);
|
||||
if (!core)
|
||||
return -EINVAL;
|
||||
|
||||
return snprintf(buf, PAGE_SIZE, "%u\n",
|
||||
core->resources.msm_cvp_pwr_collapse_delay);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(pwr_collapse_delay);
|
||||
|
||||
static ssize_t thermal_level_show(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
return snprintf(buf, PAGE_SIZE, "%d\n", cvp_driver->thermal_level);
|
||||
}
|
||||
|
||||
static ssize_t thermal_level_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc = 0, val = 0;
|
||||
|
||||
rc = kstrtoint(buf, 0, &val);
|
||||
if (rc || val < 0) {
|
||||
dprintk(CVP_WARN,
|
||||
"Invalid thermal level value: %s\n", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
dprintk(CVP_DBG, "Thermal level old %d new %d\n",
|
||||
cvp_driver->thermal_level, val);
|
||||
|
||||
if (val == cvp_driver->thermal_level)
|
||||
return count;
|
||||
cvp_driver->thermal_level = val;
|
||||
|
||||
msm_cvp_comm_handle_thermal_event();
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RW(thermal_level);
|
||||
|
||||
static ssize_t sku_version_show(struct device *dev,
|
||||
struct device_attribute *attr, char *buf)
|
||||
{
|
||||
return scnprintf(buf, PAGE_SIZE, "%d",
|
||||
cvp_driver->sku_version);
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_RO(sku_version);
|
||||
|
||||
static ssize_t boot_store(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int rc = 0, val = 0;
|
||||
static int booted;
|
||||
|
||||
rc = kstrtoint(buf, 0, &val);
|
||||
if (rc || val < 0) {
|
||||
dprintk(CVP_WARN,
|
||||
"Invalid boot value: %s\n", buf);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (val > 0 && booted == 0) {
|
||||
struct msm_cvp_inst *inst;
|
||||
|
||||
inst = msm_cvp_open(MSM_CORE_CVP, MSM_CVP_BOOT);
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to create cvp instance\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
rc = msm_cvp_close(inst);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to close cvp instance\n");
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
booted = 1;
|
||||
return count;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR_WO(boot);
|
||||
|
||||
static struct attribute *msm_cvp_core_attrs[] = {
|
||||
&dev_attr_pwr_collapse_delay.attr,
|
||||
&dev_attr_thermal_level.attr,
|
||||
&dev_attr_sku_version.attr,
|
||||
&dev_attr_link_name.attr,
|
||||
&dev_attr_boot.attr,
|
||||
NULL
|
||||
};
|
||||
|
||||
static struct attribute_group msm_cvp_core_attr_group = {
|
||||
.attrs = msm_cvp_core_attrs,
|
||||
};
|
||||
|
||||
static const struct of_device_id msm_cvp_plat_match[] = {
|
||||
{.compatible = "qcom,msm-cvp"},
|
||||
{.compatible = "qcom,msm-cvp,context-bank"},
|
||||
{.compatible = "qcom,msm-cvp,bus"},
|
||||
{.compatible = "qcom,msm-cvp,mem-cdsp"},
|
||||
{}
|
||||
};
|
||||
|
||||
static int msm_probe_cvp_device(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_core *core;
|
||||
|
||||
if (!cvp_driver) {
|
||||
dprintk(CVP_ERR, "Invalid cvp driver\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = kzalloc(sizeof(*core), GFP_KERNEL);
|
||||
if (!core)
|
||||
return -ENOMEM;
|
||||
|
||||
core->platform_data = cvp_get_drv_data(&pdev->dev);
|
||||
dev_set_drvdata(&pdev->dev, core);
|
||||
rc = msm_cvp_initialize_core(pdev, core);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to init core\n");
|
||||
goto err_core_init;
|
||||
}
|
||||
|
||||
core->id = MSM_CORE_CVP;
|
||||
|
||||
rc = alloc_chrdev_region(&core->dev_num, 0, 1, DRIVER_NAME);
|
||||
if (rc < 0) {
|
||||
dprintk(CVP_ERR, "alloc_chrdev_region failed: %d\n",
|
||||
rc);
|
||||
goto err_alloc_chrdev;
|
||||
}
|
||||
|
||||
core->class = class_create(THIS_MODULE, CLASS_NAME);
|
||||
if (IS_ERR(core->class)) {
|
||||
rc = PTR_ERR(core->class);
|
||||
dprintk(CVP_ERR, "class_create failed: %d\n",
|
||||
rc);
|
||||
goto err_class_create;
|
||||
}
|
||||
|
||||
core->dev = device_create(core->class, NULL,
|
||||
core->dev_num, NULL, DRIVER_NAME);
|
||||
if (IS_ERR(core->dev)) {
|
||||
rc = PTR_ERR(core->dev);
|
||||
dprintk(CVP_ERR, "device_create failed: %d\n",
|
||||
rc);
|
||||
goto err_device_create;
|
||||
}
|
||||
dev_set_drvdata(core->dev, core);
|
||||
|
||||
cdev_init(&core->cdev, &cvp_fops);
|
||||
rc = cdev_add(&core->cdev,
|
||||
MKDEV(MAJOR(core->dev_num), 0), 1);
|
||||
if (rc < 0) {
|
||||
dprintk(CVP_ERR, "cdev_add failed: %d\n",
|
||||
rc);
|
||||
goto error_cdev_add;
|
||||
}
|
||||
|
||||
/* finish setting up the 'core' */
|
||||
mutex_lock(&cvp_driver->lock);
|
||||
if (cvp_driver->num_cores + 1 > MSM_CVP_CORES_MAX) {
|
||||
mutex_unlock(&cvp_driver->lock);
|
||||
dprintk(CVP_ERR, "Maximum cores already exist, core_no = %d\n",
|
||||
cvp_driver->num_cores);
|
||||
goto err_cores_exceeded;
|
||||
}
|
||||
cvp_driver->num_cores++;
|
||||
mutex_unlock(&cvp_driver->lock);
|
||||
|
||||
rc = sysfs_create_group(&core->dev->kobj, &msm_cvp_core_attr_group);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to create attributes\n");
|
||||
goto err_cores_exceeded;
|
||||
}
|
||||
|
||||
core->device = cvp_hfi_initialize(core->hfi_type, core->id,
|
||||
&core->resources, &cvp_handle_cmd_response);
|
||||
if (IS_ERR_OR_NULL(core->device)) {
|
||||
mutex_lock(&cvp_driver->lock);
|
||||
cvp_driver->num_cores--;
|
||||
mutex_unlock(&cvp_driver->lock);
|
||||
|
||||
rc = PTR_ERR(core->device) ?: -EBADHANDLE;
|
||||
if (rc != -EPROBE_DEFER)
|
||||
dprintk(CVP_ERR, "Failed to create HFI device\n");
|
||||
else
|
||||
dprintk(CVP_DBG, "msm_cvp: request probe defer\n");
|
||||
goto err_hfi_initialize;
|
||||
}
|
||||
|
||||
mutex_lock(&cvp_driver->lock);
|
||||
list_add_tail(&core->list, &cvp_driver->cores);
|
||||
mutex_unlock(&cvp_driver->lock);
|
||||
|
||||
core->debugfs_root = msm_cvp_debugfs_init_core(
|
||||
core, cvp_driver->debugfs_root);
|
||||
|
||||
cvp_driver->sku_version = core->resources.sku_version;
|
||||
|
||||
dprintk(CVP_DBG, "populating sub devices\n");
|
||||
/*
|
||||
* Trigger probe for each sub-device i.e. qcom,msm-cvp,context-bank.
|
||||
* When msm_cvp_probe is called for each sub-device, parse the
|
||||
* context-bank details and store it in core->resources.context_banks
|
||||
* list.
|
||||
*/
|
||||
rc = of_platform_populate(pdev->dev.of_node, msm_cvp_plat_match, NULL,
|
||||
&pdev->dev);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to trigger probe for sub-devices\n");
|
||||
goto err_fail_sub_device_probe;
|
||||
}
|
||||
|
||||
atomic64_set(&core->kernel_trans_id, 0);
|
||||
|
||||
return rc;
|
||||
|
||||
err_fail_sub_device_probe:
|
||||
cvp_hfi_deinitialize(core->hfi_type, core->device);
|
||||
err_hfi_initialize:
|
||||
err_cores_exceeded:
|
||||
cdev_del(&core->cdev);
|
||||
error_cdev_add:
|
||||
device_destroy(core->class, core->dev_num);
|
||||
err_device_create:
|
||||
class_destroy(core->class);
|
||||
err_class_create:
|
||||
unregister_chrdev_region(core->dev_num, 1);
|
||||
err_alloc_chrdev:
|
||||
sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group);
|
||||
err_core_init:
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
kfree(core);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_cvp_probe_mem_cdsp(struct platform_device *pdev)
|
||||
{
|
||||
return cvp_read_mem_cdsp_resources_from_dt(pdev);
|
||||
}
|
||||
|
||||
static int msm_cvp_probe_context_bank(struct platform_device *pdev)
|
||||
{
|
||||
return cvp_read_context_bank_resources_from_dt(pdev);
|
||||
}
|
||||
|
||||
static int msm_cvp_probe_bus(struct platform_device *pdev)
|
||||
{
|
||||
return cvp_read_bus_resources_from_dt(pdev);
|
||||
}
|
||||
|
||||
static int msm_cvp_probe(struct platform_device *pdev)
|
||||
{
|
||||
/*
|
||||
* Sub devices probe will be triggered by of_platform_populate() towards
|
||||
* the end of the probe function after msm-cvp device probe is
|
||||
* completed. Return immediately after completing sub-device probe.
|
||||
*/
|
||||
if (of_device_is_compatible(pdev->dev.of_node, "qcom,msm-cvp")) {
|
||||
return msm_probe_cvp_device(pdev);
|
||||
} else if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"qcom,msm-cvp,bus")) {
|
||||
return msm_cvp_probe_bus(pdev);
|
||||
} else if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"qcom,msm-cvp,context-bank")) {
|
||||
return msm_cvp_probe_context_bank(pdev);
|
||||
} else if (of_device_is_compatible(pdev->dev.of_node,
|
||||
"qcom,msm-cvp,mem-cdsp")) {
|
||||
return msm_cvp_probe_mem_cdsp(pdev);
|
||||
}
|
||||
|
||||
/* How did we end up here? */
|
||||
MSM_CVP_ERROR(1);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int msm_cvp_remove(struct platform_device *pdev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_core *core;
|
||||
|
||||
if (!pdev) {
|
||||
dprintk(CVP_ERR, "%s invalid input %pK", __func__, pdev);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = dev_get_drvdata(&pdev->dev);
|
||||
if (!core) {
|
||||
dprintk(CVP_ERR, "%s invalid core", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cvp_hfi_deinitialize(core->hfi_type, core->device);
|
||||
msm_cvp_free_platform_resources(&core->resources);
|
||||
sysfs_remove_group(&pdev->dev.kobj, &msm_cvp_core_attr_group);
|
||||
dev_set_drvdata(&pdev->dev, NULL);
|
||||
mutex_destroy(&core->lock);
|
||||
kfree(core);
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_cvp_pm_suspend(struct device *dev)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_core *core;
|
||||
|
||||
/*
|
||||
* Bail out if
|
||||
* - driver possibly not probed yet
|
||||
* - not the main device. We don't support power management on
|
||||
* subdevices (e.g. context banks)
|
||||
*/
|
||||
if (!dev || !dev->driver ||
|
||||
!of_device_is_compatible(dev->of_node, "qcom,msm-cvp"))
|
||||
return 0;
|
||||
|
||||
core = dev_get_drvdata(dev);
|
||||
if (!core) {
|
||||
dprintk(CVP_ERR, "%s invalid core\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = msm_cvp_suspend(core->id);
|
||||
if (rc == -ENOTSUPP)
|
||||
rc = 0;
|
||||
else if (rc)
|
||||
dprintk(CVP_WARN, "Failed to suspend: %d\n", rc);
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_cvp_pm_resume(struct device *dev)
|
||||
{
|
||||
dprintk(CVP_INFO, "%s\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops msm_cvp_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(msm_cvp_pm_suspend, msm_cvp_pm_resume)
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, msm_cvp_plat_match);
|
||||
|
||||
static struct platform_driver msm_cvp_driver = {
|
||||
.probe = msm_cvp_probe,
|
||||
.remove = msm_cvp_remove,
|
||||
.driver = {
|
||||
.name = "msm_cvp",
|
||||
.of_match_table = msm_cvp_plat_match,
|
||||
.pm = &msm_cvp_pm_ops,
|
||||
},
|
||||
};
|
||||
|
||||
static int __init msm_cvp_init(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
cvp_driver = kzalloc(sizeof(*cvp_driver),
|
||||
GFP_KERNEL);
|
||||
if (!cvp_driver) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to allocate memroy for msm_cvp_drv\n");
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&cvp_driver->cores);
|
||||
mutex_init(&cvp_driver->lock);
|
||||
cvp_driver->debugfs_root = msm_cvp_debugfs_init_drv();
|
||||
if (!cvp_driver->debugfs_root)
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to create debugfs for msm_cvp\n");
|
||||
|
||||
rc = platform_driver_register(&msm_cvp_driver);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to register platform driver\n");
|
||||
debugfs_remove_recursive(cvp_driver->debugfs_root);
|
||||
kfree(cvp_driver);
|
||||
cvp_driver = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
cvp_driver->msg_cache = KMEM_CACHE(cvp_session_msg, 0);
|
||||
cvp_driver->fence_data_cache = KMEM_CACHE(msm_cvp_fence_thread_data, 0);
|
||||
cvp_driver->frame_cache = KMEM_CACHE(msm_cvp_frame, 0);
|
||||
cvp_driver->frame_buf_cache = KMEM_CACHE(msm_cvp_frame_buf, 0);
|
||||
cvp_driver->internal_buf_cache = KMEM_CACHE(msm_cvp_internal_buffer, 0);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static void __exit msm_cvp_exit(void)
|
||||
{
|
||||
cvp_dsp_device_exit();
|
||||
kmem_cache_destroy(cvp_driver->msg_cache);
|
||||
kmem_cache_destroy(cvp_driver->fence_data_cache);
|
||||
kmem_cache_destroy(cvp_driver->frame_cache);
|
||||
kmem_cache_destroy(cvp_driver->frame_buf_cache);
|
||||
kmem_cache_destroy(cvp_driver->internal_buf_cache);
|
||||
|
||||
platform_driver_unregister(&msm_cvp_driver);
|
||||
debugfs_remove_recursive(cvp_driver->debugfs_root);
|
||||
mutex_destroy(&cvp_driver->lock);
|
||||
kfree(cvp_driver);
|
||||
cvp_driver = NULL;
|
||||
}
|
||||
|
||||
module_init(msm_cvp_init);
|
||||
module_exit(msm_cvp_exit);
|
||||
|
||||
MODULE_LICENSE("GPL v2");
|
52
drivers/media/platform/msm/cvp/cvp_core_hfi.c
Normal file
52
drivers/media/platform/msm/cvp/cvp_core_hfi.c
Normal file
@ -0,0 +1,52 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/slab.h>
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "cvp_core_hfi.h"
|
||||
|
||||
struct cvp_hfi_device *cvp_hfi_initialize(enum msm_cvp_hfi_type hfi_type,
|
||||
u32 device_id, struct msm_cvp_platform_resources *res,
|
||||
hfi_cmd_response_callback callback)
|
||||
{
|
||||
struct cvp_hfi_device *hdev = NULL;
|
||||
int rc = 0;
|
||||
|
||||
hdev = kzalloc(sizeof(struct cvp_hfi_device), GFP_KERNEL);
|
||||
if (!hdev) {
|
||||
dprintk(CVP_ERR, "%s: failed to allocate hdev\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
rc = cvp_iris_hfi_initialize(hdev, device_id, res, callback);
|
||||
|
||||
if (rc) {
|
||||
if (rc != -EPROBE_DEFER)
|
||||
dprintk(CVP_ERR, "%s device init failed rc = %d",
|
||||
__func__, rc);
|
||||
goto err_hfi_init;
|
||||
}
|
||||
|
||||
return hdev;
|
||||
|
||||
err_hfi_init:
|
||||
kfree(hdev);
|
||||
return ERR_PTR(rc);
|
||||
}
|
||||
|
||||
void cvp_hfi_deinitialize(enum msm_cvp_hfi_type hfi_type,
|
||||
struct cvp_hfi_device *hdev)
|
||||
{
|
||||
if (!hdev) {
|
||||
dprintk(CVP_ERR, "%s invalid device %pK", __func__, hdev);
|
||||
return;
|
||||
}
|
||||
|
||||
cvp_iris_hfi_delete_device(hdev->hfi_device_data);
|
||||
|
||||
kfree(hdev);
|
||||
}
|
||||
|
279
drivers/media/platform/msm/cvp/cvp_core_hfi.h
Normal file
279
drivers/media/platform/msm/cvp/cvp_core_hfi.h
Normal file
@ -0,0 +1,279 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_CVP_CORE_HFI_H__
|
||||
#define __H_CVP_CORE_HFI_H__
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_qos.h>
|
||||
#include <linux/spinlock.h>
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "cvp_hfi_helper.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "cvp_hfi.h"
|
||||
#include "msm_cvp_resources.h"
|
||||
#include "hfi_packetization.h"
|
||||
|
||||
#define HFI_MASK_QHDR_TX_TYPE 0xFF000000
|
||||
#define HFI_MASK_QHDR_RX_TYPE 0x00FF0000
|
||||
#define HFI_MASK_QHDR_PRI_TYPE 0x0000FF00
|
||||
#define HFI_MASK_QHDR_Q_ID_TYPE 0x000000FF
|
||||
#define HFI_Q_ID_HOST_TO_CTRL_CMD_Q 0x00
|
||||
#define HFI_Q_ID_CTRL_TO_HOST_MSG_Q 0x01
|
||||
#define HFI_Q_ID_CTRL_TO_HOST_DEBUG_Q 0x02
|
||||
#define HFI_MASK_QHDR_STATUS 0x000000FF
|
||||
|
||||
#define CVP_IFACEQ_NUMQ 3
|
||||
#define CVP_IFACEQ_CMDQ_IDX 0
|
||||
#define CVP_IFACEQ_MSGQ_IDX 1
|
||||
#define CVP_IFACEQ_DBGQ_IDX 2
|
||||
#define CVP_IFACEQ_MAX_BUF_COUNT 50
|
||||
#define CVP_IFACE_MAX_PARALLEL_CLNTS 16
|
||||
#define CVP_IFACEQ_DFLT_QHDR 0x01010000
|
||||
|
||||
#define CVP_MAX_NAME_LENGTH 64
|
||||
#define CVP_MAX_PC_SKIP_COUNT 10
|
||||
#define CVP_MAX_SUBCACHES 4
|
||||
#define CVP_MAX_SUBCACHE_SIZE 52
|
||||
|
||||
struct cvp_hfi_queue_table_header {
|
||||
u32 qtbl_version;
|
||||
u32 qtbl_size;
|
||||
u32 qtbl_qhdr0_offset;
|
||||
u32 qtbl_qhdr_size;
|
||||
u32 qtbl_num_q;
|
||||
u32 qtbl_num_active_q;
|
||||
void *device_addr;
|
||||
char name[256];
|
||||
};
|
||||
|
||||
struct cvp_hfi_queue_header {
|
||||
u32 qhdr_status;
|
||||
u32 qhdr_start_addr;
|
||||
u32 qhdr_type;
|
||||
u32 qhdr_q_size;
|
||||
u32 qhdr_pkt_size;
|
||||
u32 qhdr_pkt_drop_cnt;
|
||||
u32 qhdr_rx_wm;
|
||||
u32 qhdr_tx_wm;
|
||||
u32 qhdr_rx_req;
|
||||
u32 qhdr_tx_req;
|
||||
u32 qhdr_rx_irq_status;
|
||||
u32 qhdr_tx_irq_status;
|
||||
u32 qhdr_read_idx;
|
||||
u32 qhdr_write_idx;
|
||||
};
|
||||
|
||||
struct cvp_hfi_mem_map_table {
|
||||
u32 mem_map_num_entries;
|
||||
u32 mem_map_table_base_addr;
|
||||
};
|
||||
|
||||
struct cvp_hfi_mem_map {
|
||||
u32 virtual_addr;
|
||||
u32 physical_addr;
|
||||
u32 size;
|
||||
u32 attr;
|
||||
};
|
||||
|
||||
#define CVP_IFACEQ_TABLE_SIZE (sizeof(struct cvp_hfi_queue_table_header) \
|
||||
+ sizeof(struct cvp_hfi_queue_header) * CVP_IFACEQ_NUMQ)
|
||||
|
||||
#define CVP_IFACEQ_QUEUE_SIZE (CVP_IFACEQ_MAX_PKT_SIZE * \
|
||||
CVP_IFACEQ_MAX_BUF_COUNT * CVP_IFACE_MAX_PARALLEL_CLNTS)
|
||||
|
||||
#define CVP_IFACEQ_GET_QHDR_START_ADDR(ptr, i) \
|
||||
(void *)((ptr + sizeof(struct cvp_hfi_queue_table_header)) + \
|
||||
(i * sizeof(struct cvp_hfi_queue_header)))
|
||||
|
||||
#define QDSS_SIZE 4096
|
||||
#define SFR_SIZE 4096
|
||||
|
||||
#define QUEUE_SIZE (CVP_IFACEQ_TABLE_SIZE + \
|
||||
(CVP_IFACEQ_QUEUE_SIZE * CVP_IFACEQ_NUMQ))
|
||||
|
||||
#define ALIGNED_QDSS_SIZE ALIGN(QDSS_SIZE, SZ_4K)
|
||||
#define ALIGNED_SFR_SIZE ALIGN(SFR_SIZE, SZ_4K)
|
||||
#define ALIGNED_QUEUE_SIZE ALIGN(QUEUE_SIZE, SZ_4K)
|
||||
#define SHARED_QSIZE ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \
|
||||
ALIGNED_QDSS_SIZE, SZ_1M)
|
||||
|
||||
struct cvp_mem_addr {
|
||||
u32 align_device_addr;
|
||||
u8 *align_virtual_addr;
|
||||
u32 mem_size;
|
||||
struct msm_cvp_smem mem_data;
|
||||
};
|
||||
|
||||
struct cvp_iface_q_info {
|
||||
spinlock_t hfi_lock;
|
||||
void *q_hdr;
|
||||
struct cvp_mem_addr q_array;
|
||||
};
|
||||
|
||||
/*
|
||||
* These are helper macros to iterate over various lists within
|
||||
* iris_hfi_device->res. The intention is to cut down on a lot of boiler-plate
|
||||
* code
|
||||
*/
|
||||
|
||||
/* Read as "for each 'thing' in a set of 'thingies'" */
|
||||
#define iris_hfi_for_each_thing(__device, __thing, __thingy) \
|
||||
iris_hfi_for_each_thing_continue(__device, __thing, __thingy, 0)
|
||||
|
||||
#define iris_hfi_for_each_thing_reverse(__device, __thing, __thingy) \
|
||||
iris_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||
(__device)->res->__thingy##_set.count - 1)
|
||||
|
||||
/* TODO: the __from parameter technically not required since we can figure it
|
||||
* out with some pointer magic (i.e. __thing - __thing##_tbl[0]). If this macro
|
||||
* sees extensive use, probably worth cleaning it up but for now omitting it
|
||||
* since it introduces unnecessary complexity.
|
||||
*/
|
||||
#define iris_hfi_for_each_thing_continue(__device, __thing, __thingy, __from) \
|
||||
for (__thing = &(__device)->res->\
|
||||
__thingy##_set.__thingy##_tbl[__from]; \
|
||||
__thing < &(__device)->res->__thingy##_set.__thingy##_tbl[0] + \
|
||||
((__device)->res->__thingy##_set.count - __from); \
|
||||
++__thing)
|
||||
|
||||
#define iris_hfi_for_each_thing_reverse_continue(__device, __thing, __thingy, \
|
||||
__from) \
|
||||
for (__thing = &(__device)->res->\
|
||||
__thingy##_set.__thingy##_tbl[__from]; \
|
||||
__thing >= &(__device)->res->__thingy##_set.__thingy##_tbl[0]; \
|
||||
--__thing)
|
||||
|
||||
/* Regular set helpers */
|
||||
#define iris_hfi_for_each_regulator(__device, __rinfo) \
|
||||
iris_hfi_for_each_thing(__device, __rinfo, regulator)
|
||||
|
||||
#define iris_hfi_for_each_regulator_reverse(__device, __rinfo) \
|
||||
iris_hfi_for_each_thing_reverse(__device, __rinfo, regulator)
|
||||
|
||||
#define iris_hfi_for_each_regulator_reverse_continue(__device, __rinfo, \
|
||||
__from) \
|
||||
iris_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||
regulator, __from)
|
||||
|
||||
/* Clock set helpers */
|
||||
#define iris_hfi_for_each_clock(__device, __cinfo) \
|
||||
iris_hfi_for_each_thing(__device, __cinfo, clock)
|
||||
|
||||
#define iris_hfi_for_each_clock_reverse(__device, __cinfo) \
|
||||
iris_hfi_for_each_thing_reverse(__device, __cinfo, clock)
|
||||
|
||||
#define iris_hfi_for_each_clock_reverse_continue(__device, __rinfo, \
|
||||
__from) \
|
||||
iris_hfi_for_each_thing_reverse_continue(__device, __rinfo, \
|
||||
clock, __from)
|
||||
|
||||
/* Bus set helpers */
|
||||
#define iris_hfi_for_each_bus(__device, __binfo) \
|
||||
iris_hfi_for_each_thing(__device, __binfo, bus)
|
||||
#define iris_hfi_for_each_bus_reverse(__device, __binfo) \
|
||||
iris_hfi_for_each_thing_reverse(__device, __binfo, bus)
|
||||
|
||||
/* Subcache set helpers */
|
||||
#define iris_hfi_for_each_subcache(__device, __sinfo) \
|
||||
iris_hfi_for_each_thing(__device, __sinfo, subcache)
|
||||
#define iris_hfi_for_each_subcache_reverse(__device, __sinfo) \
|
||||
iris_hfi_for_each_thing_reverse(__device, __sinfo, subcache)
|
||||
|
||||
#define call_iris_op(d, op, args...) \
|
||||
(((d) && (d)->vpu_ops && (d)->vpu_ops->op) ? \
|
||||
((d)->vpu_ops->op(args)):0)
|
||||
|
||||
struct cvp_hal_data {
|
||||
u32 irq;
|
||||
phys_addr_t firmware_base;
|
||||
u8 __iomem *register_base;
|
||||
u8 __iomem *gcc_reg_base;
|
||||
u32 register_size;
|
||||
u32 gcc_reg_size;
|
||||
};
|
||||
|
||||
struct iris_resources {
|
||||
struct msm_cvp_fw fw;
|
||||
};
|
||||
|
||||
enum dsp_flag {
|
||||
DSP_INIT = BIT(0),
|
||||
DSP_SUSPEND = BIT(1),
|
||||
};
|
||||
|
||||
enum iris_hfi_state {
|
||||
IRIS_STATE_DEINIT = 1,
|
||||
IRIS_STATE_INIT,
|
||||
};
|
||||
|
||||
enum reset_state {
|
||||
INIT = 1,
|
||||
ASSERT,
|
||||
DEASSERT,
|
||||
};
|
||||
|
||||
struct iris_hfi_device;
|
||||
|
||||
struct iris_hfi_vpu_ops {
|
||||
void (*interrupt_init)(struct iris_hfi_device *ptr);
|
||||
void (*setup_dsp_uc_memmap)(struct iris_hfi_device *device);
|
||||
void (*clock_config_on_enable)(struct iris_hfi_device *device);
|
||||
int (*reset_ahb2axi_bridge)(struct iris_hfi_device *device);
|
||||
void (*power_off)(struct iris_hfi_device *device);
|
||||
void (*noc_error_info)(struct iris_hfi_device *device);
|
||||
};
|
||||
|
||||
struct iris_hfi_device {
|
||||
struct list_head list;
|
||||
struct list_head sess_head;
|
||||
u32 version;
|
||||
u32 intr_status;
|
||||
u32 device_id;
|
||||
u32 clk_freq;
|
||||
u32 last_packet_type;
|
||||
unsigned long clk_bitrate;
|
||||
unsigned long scaled_rate;
|
||||
struct msm_cvp_gov_data bus_vote;
|
||||
bool power_enabled;
|
||||
bool reg_dumped;
|
||||
struct mutex lock;
|
||||
msm_cvp_callback callback;
|
||||
struct cvp_mem_addr iface_q_table;
|
||||
struct cvp_mem_addr dsp_iface_q_table;
|
||||
struct cvp_mem_addr qdss;
|
||||
struct cvp_mem_addr sfr;
|
||||
struct cvp_mem_addr mem_addr;
|
||||
struct cvp_iface_q_info iface_queues[CVP_IFACEQ_NUMQ];
|
||||
struct cvp_iface_q_info dsp_iface_queues[CVP_IFACEQ_NUMQ];
|
||||
u32 dsp_flags;
|
||||
struct cvp_hal_data *cvp_hal_data;
|
||||
struct workqueue_struct *cvp_workq;
|
||||
struct workqueue_struct *iris_pm_workq;
|
||||
int spur_count;
|
||||
int reg_count;
|
||||
struct iris_resources resources;
|
||||
struct msm_cvp_platform_resources *res;
|
||||
enum iris_hfi_state state;
|
||||
struct cvp_hfi_packetization_ops *pkt_ops;
|
||||
enum hfi_packetization_type packetization_type;
|
||||
struct msm_cvp_cb_info *response_pkt;
|
||||
u8 *raw_packet;
|
||||
struct pm_qos_request qos;
|
||||
unsigned int skip_pc_count;
|
||||
struct msm_cvp_capability *sys_init_capabilities;
|
||||
struct iris_hfi_vpu_ops *vpu_ops;
|
||||
struct delayed_work dsp_init_work;
|
||||
};
|
||||
|
||||
void cvp_iris_hfi_delete_device(void *device);
|
||||
|
||||
int cvp_iris_hfi_initialize(struct cvp_hfi_device *hdev, u32 device_id,
|
||||
struct msm_cvp_platform_resources *res,
|
||||
hfi_cmd_response_callback callback);
|
||||
|
||||
#endif
|
4830
drivers/media/platform/msm/cvp/cvp_hfi.c
Normal file
4830
drivers/media/platform/msm/cvp/cvp_hfi.c
Normal file
File diff suppressed because it is too large
Load Diff
207
drivers/media/platform/msm/cvp/cvp_hfi.h
Normal file
207
drivers/media/platform/msm/cvp/cvp_hfi.h
Normal file
@ -0,0 +1,207 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_CVP_HFI_H__
|
||||
#define __H_CVP_HFI_H__
|
||||
|
||||
#include <media/msm_media_info.h>
|
||||
#include "cvp_hfi_helper.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_START \
|
||||
(HFI_DOMAIN_BASE_CVP + HFI_ARCH_COMMON_OFFSET + \
|
||||
HFI_CMD_START_OFFSET + 0x1000)
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_SET_BUFFERS\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x001)
|
||||
#define HFI_CMD_SESSION_CVP_RELEASE_BUFFERS\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x002)
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_DS\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x003)
|
||||
#define HFI_CMD_SESSION_CVP_HCD_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x004)
|
||||
#define HFI_CMD_SESSION_CVP_HCD_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x005)
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x006)
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x007)
|
||||
#define HFI_CMD_SESSION_CVP_SVM\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x008)
|
||||
#define HFI_CMD_SESSION_CVP_NCC_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x009)
|
||||
#define HFI_CMD_SESSION_CVP_NCC_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x00A)
|
||||
#define HFI_CMD_SESSION_CVP_DFS_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x00B)
|
||||
#define HFI_CMD_SESSION_CVP_DFS_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x00C)
|
||||
#define HFI_CMD_SESSION_CVP_FTEXT\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x00F)
|
||||
|
||||
/* ==========CHAINED OPERATIONS===================*/
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_SVM_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x010)
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_SVM_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x011)
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_SVM_HCD_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x012)
|
||||
#define HFI_CMD_SESSION_CVP_CV_HOG_SVM_HCD_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x013)
|
||||
#define HFI_CMD_SESSION_CVP_OPTICAL_FLOW\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x014)
|
||||
|
||||
/* ===========USECASE OPERATIONS===============*/
|
||||
#define HFI_CMD_SESSION_CVP_DC_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x030)
|
||||
#define HFI_CMD_SESSION_CVP_DC_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x031)
|
||||
#define HFI_CMD_SESSION_CVP_DCM_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x034)
|
||||
#define HFI_CMD_SESSION_CVP_DCM_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x035)
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_DME_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x039)
|
||||
#define HFI_CMD_SESSION_CVP_DME_BASIC_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x03B)
|
||||
#define HFI_CMD_SESSION_CVP_DME_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x03A)
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_CV_TME_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x047)
|
||||
#define HFI_CMD_SESSION_CVP_CV_TME_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x048)
|
||||
#define HFI_CMD_SESSION_CVP_CV_OD_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x049)
|
||||
#define HFI_CMD_SESSION_CVP_CV_OD_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x04A)
|
||||
#define HFI_CMD_SESSION_CVP_CV_ODT_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x04B)
|
||||
#define HFI_CMD_SESSION_CVP_CV_ODT_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x04C)
|
||||
|
||||
#define HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x04D)
|
||||
#define HFI_CMD_SESSION_CVP_PYS_HCD_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x050)
|
||||
#define HFI_CMD_SESSION_CVP_PYS_HCD_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x051)
|
||||
#define HFI_CMD_SESSION_CVP_SET_MODEL_BUFFERS\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x052)
|
||||
#define HFI_CMD_SESSION_CVP_FD_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x053)
|
||||
#define HFI_CMD_SESSION_CVP_FD_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x054)
|
||||
#define HFI_CMD_SESSION_CVP_ICA_FRAME\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x100)
|
||||
#define HFI_CMD_SESSION_CVP_ICA_CONFIG\
|
||||
(HFI_CMD_SESSION_CVP_START + 0x101)
|
||||
|
||||
|
||||
#define HFI_MSG_SESSION_CVP_START \
|
||||
(HFI_DOMAIN_BASE_CVP + HFI_ARCH_COMMON_OFFSET + \
|
||||
HFI_MSG_START_OFFSET + 0x1000)
|
||||
|
||||
#define HFI_MSG_SESSION_CVP_SET_BUFFERS\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x001)
|
||||
#define HFI_MSG_SESSION_CVP_RELEASE_BUFFERS \
|
||||
(HFI_MSG_SESSION_CVP_START + 0x002)
|
||||
#define HFI_MSG_SESSION_CVP_DS\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x003)
|
||||
#define HFI_MSG_SESSION_CVP_HCD\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x004)
|
||||
#define HFI_MSG_SESSION_CVP_CV_HOG\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x005)
|
||||
#define HFI_MSG_SESSION_CVP_SVM\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x006)
|
||||
#define HFI_MSG_SESSION_CVP_NCC\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x007)
|
||||
#define HFI_MSG_SESSION_CVP_DFS\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x008)
|
||||
#define HFI_MSG_SESSION_CVP_TME\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x009)
|
||||
#define HFI_MSG_SESSION_CVP_FTEXT\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x00A)
|
||||
|
||||
#define HFI_MSG_SESSION_CVP_ICA\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x014)
|
||||
|
||||
#define HFI_MSG_SESSION_CVP_DME\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x023)
|
||||
#define HFI_MSG_SESSION_CVP_OPERATION_CONFIG (HFI_MSG_SESSION_CVP_START + 0x030)
|
||||
|
||||
#define HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x034)
|
||||
#define HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x036)
|
||||
#define HFI_MSG_SESSION_CVP_FD\
|
||||
(HFI_MSG_SESSION_CVP_START + 0x037)
|
||||
|
||||
#define CVP_IFACEQ_MAX_PKT_SIZE 1024
|
||||
#define CVP_IFACEQ_MED_PKT_SIZE 768
|
||||
#define CVP_IFACEQ_MIN_PKT_SIZE 8
|
||||
#define CVP_IFACEQ_VAR_SMALL_PKT_SIZE 100
|
||||
#define CVP_IFACEQ_VAR_LARGE_PKT_SIZE 512
|
||||
#define CVP_IFACEQ_VAR_HUGE_PKT_SIZE (1024*12)
|
||||
|
||||
struct cvp_hfi_cmd_session_flush_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 flush_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_get_property_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_session_abort_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_property_info_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[128];
|
||||
};
|
||||
|
||||
enum session_flags {
|
||||
SESSION_PAUSE = BIT(1),
|
||||
};
|
||||
|
||||
struct cvp_hal_session {
|
||||
struct list_head list;
|
||||
void *session_id;
|
||||
u32 flags;
|
||||
void *device;
|
||||
};
|
||||
|
||||
struct msm_cvp_fw {
|
||||
void *cookie;
|
||||
};
|
||||
|
||||
int cvp_hfi_process_msg_packet(u32 device_id,
|
||||
struct cvp_hal_msg_pkt_hdr *msg_hdr,
|
||||
struct msm_cvp_cb_info *info);
|
||||
|
||||
enum cvp_status cvp_hfi_process_sys_init_done_prop_read(
|
||||
struct cvp_hfi_msg_sys_init_done_packet *pkt,
|
||||
struct cvp_hal_sys_init_done *sys_init_done);
|
||||
|
||||
enum cvp_status hfi_process_session_init_done_prop_read(
|
||||
struct cvp_hfi_msg_sys_session_init_done_packet *pkt,
|
||||
struct cvp_hal_session_init_done *session_init_done);
|
||||
|
||||
#endif
|
440
drivers/media/platform/msm/cvp/cvp_hfi_api.h
Normal file
440
drivers/media/platform/msm/cvp/cvp_hfi_api.h
Normal file
@ -0,0 +1,440 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CVP_HFI_API_H__
|
||||
#define __CVP_HFI_API_H__
|
||||
|
||||
#include <linux/log2.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/hash.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include "msm_cvp_resources.h"
|
||||
#include "cvp_hfi_helper.h"
|
||||
|
||||
#define CONTAINS(__a, __sz, __t) (\
|
||||
(__t >= __a) && \
|
||||
(__t < __a + __sz) \
|
||||
)
|
||||
|
||||
#define OVERLAPS(__t, __tsz, __a, __asz) (\
|
||||
(__t <= __a) && \
|
||||
(__t + __tsz >= __a + __asz) \
|
||||
)
|
||||
|
||||
#define CVP_VERSION_LENGTH 128
|
||||
|
||||
/* 16 encoder and 16 decoder sessions */
|
||||
#define CVP_MAX_SESSIONS 32
|
||||
|
||||
#define HFI_DFS_CONFIG_CMD_SIZE 38
|
||||
#define HFI_DFS_FRAME_CMD_SIZE 16
|
||||
#define HFI_DFS_FRAME_BUFFERS_OFFSET 8
|
||||
#define HFI_DFS_BUF_NUM 4
|
||||
|
||||
#define HFI_DME_CONFIG_CMD_SIZE 194
|
||||
#define HFI_DME_BASIC_CONFIG_CMD_SIZE 51
|
||||
#define HFI_DME_FRAME_CMD_SIZE 28
|
||||
#define HFI_DME_FRAME_BUFFERS_OFFSET 12
|
||||
#define HFI_DME_BUF_NUM 8
|
||||
|
||||
#define HFI_PERSIST_CMD_SIZE 11
|
||||
#define HFI_PERSIST_BUFFERS_OFFSET 7
|
||||
#define HFI_PERSIST_BUF_NUM 2
|
||||
|
||||
#define HFI_DS_CMD_SIZE 50
|
||||
#define HFI_DS_BUFFERS_OFFSET 44
|
||||
#define HFI_DS_BUF_NUM 3
|
||||
|
||||
#define HFI_OF_CONFIG_CMD_SIZE 34
|
||||
#define HFI_OF_FRAME_CMD_SIZE 24
|
||||
#define HFI_OF_BUFFERS_OFFSET 8
|
||||
#define HFI_OF_BUF_NUM 8
|
||||
|
||||
#define HFI_ODT_CONFIG_CMD_SIZE 23
|
||||
#define HFI_ODT_FRAME_CMD_SIZE 33
|
||||
#define HFI_ODT_BUFFERS_OFFSET 11
|
||||
#define HFI_ODT_BUF_NUM 11
|
||||
|
||||
#define HFI_OD_CONFIG_CMD_SIZE 24
|
||||
#define HFI_OD_FRAME_CMD_SIZE 12
|
||||
#define HFI_OD_BUFFERS_OFFSET 6
|
||||
#define HFI_OD_BUF_NUM 3
|
||||
|
||||
#define HFI_NCC_CONFIG_CMD_SIZE 47
|
||||
#define HFI_NCC_FRAME_CMD_SIZE 22
|
||||
#define HFI_NCC_BUFFERS_OFFSET 8
|
||||
#define HFI_NCC_BUF_NUM 7
|
||||
|
||||
#define HFI_ICA_CONFIG_CMD_SIZE 127
|
||||
#define HFI_ICA_FRAME_CMD_SIZE 14
|
||||
#define HFI_ICA_BUFFERS_OFFSET 6
|
||||
#define HFI_ICA_BUF_NUM 4
|
||||
|
||||
#define HFI_HCD_CONFIG_CMD_SIZE 46
|
||||
#define HFI_HCD_FRAME_CMD_SIZE 18
|
||||
#define HFI_HCD_BUFFERS_OFFSET 12
|
||||
#define HFI_HCD_BUF_NUM 3
|
||||
|
||||
#define HFI_DCM_CONFIG_CMD_SIZE 20
|
||||
#define HFI_DCM_FRAME_CMD_SIZE 19
|
||||
#define HFI_DCM_BUFFERS_OFFSET 9
|
||||
#define HFI_DCM_BUF_NUM 5
|
||||
|
||||
#define HFI_PYS_HCD_CONFIG_CMD_SIZE 461
|
||||
#define HFI_PYS_HCD_FRAME_CMD_SIZE 66
|
||||
#define HFI_PYS_HCD_BUFFERS_OFFSET 14
|
||||
#define HFI_PYS_HCD_BUF_NUM 26
|
||||
|
||||
#define HFI_FD_CONFIG_CMD_SIZE 28
|
||||
#define HFI_FD_FRAME_CMD_SIZE 10
|
||||
#define HFI_FD_BUFFERS_OFFSET 6
|
||||
#define HFI_FD_BUF_NUM 2
|
||||
|
||||
#define HFI_MODEL_CMD_SIZE 9
|
||||
#define HFI_MODEL_BUFFERS_OFFSET 7
|
||||
#define HFI_MODEL_BUF_NUM 1
|
||||
|
||||
#define DFS_BIT_OFFSET (CVP_KMD_HFI_DFS_FRAME_CMD - CVP_KMD_CMD_START)
|
||||
#define DME_BIT_OFFSET (CVP_KMD_HFI_DME_FRAME_CMD - CVP_KMD_CMD_START)
|
||||
#define PERSIST_BIT_OFFSET (CVP_KMD_HFI_PERSIST_CMD - CVP_KMD_CMD_START)
|
||||
#define ICA_BIT_OFFSET (CVP_KMD_HFI_ICA_FRAME_CMD - CVP_KMD_CMD_START)
|
||||
#define FD_BIT_OFFSET (CVP_KMD_HFI_FD_FRAME_CMD - CVP_KMD_CMD_START)
|
||||
|
||||
#define HFI_VERSION_MAJOR_MASK 0xFF000000
|
||||
#define HFI_VERSION_MAJOR_SHFIT 24
|
||||
#define HFI_VERSION_MINOR_MASK 0x00FFFFE0
|
||||
#define HFI_VERSION_MINOR_SHIFT 5
|
||||
#define HFI_VERSION_BRANCH_MASK 0x0000001F
|
||||
#define HFI_VERSION_BRANCH_SHIFT 0
|
||||
|
||||
enum cvp_status {
|
||||
CVP_ERR_NONE = 0x0,
|
||||
CVP_ERR_FAIL = 0x80000000,
|
||||
CVP_ERR_ALLOC_FAIL,
|
||||
CVP_ERR_ILLEGAL_OP,
|
||||
CVP_ERR_BAD_PARAM,
|
||||
CVP_ERR_BAD_HANDLE,
|
||||
CVP_ERR_NOT_SUPPORTED,
|
||||
CVP_ERR_BAD_STATE,
|
||||
CVP_ERR_MAX_CLIENTS,
|
||||
CVP_ERR_IFRAME_EXPECTED,
|
||||
CVP_ERR_HW_FATAL,
|
||||
CVP_ERR_BITSTREAM_ERR,
|
||||
CVP_ERR_INDEX_NOMORE,
|
||||
CVP_ERR_SEQHDR_PARSE_FAIL,
|
||||
CVP_ERR_INSUFFICIENT_BUFFER,
|
||||
CVP_ERR_BAD_POWER_STATE,
|
||||
CVP_ERR_NO_VALID_SESSION,
|
||||
CVP_ERR_TIMEOUT,
|
||||
CVP_ERR_CMDQFULL,
|
||||
CVP_ERR_START_CODE_NOT_FOUND,
|
||||
CVP_ERR_NOC_ERROR,
|
||||
CVP_ERR_CLIENT_PRESENT = 0x90000001,
|
||||
CVP_ERR_CLIENT_FATAL,
|
||||
CVP_ERR_CMD_QUEUE_FULL,
|
||||
CVP_ERR_UNUSED = 0x10000000
|
||||
};
|
||||
|
||||
enum hal_property {
|
||||
HAL_UNUSED_PROPERTY = 0xFFFFFFFF,
|
||||
};
|
||||
|
||||
enum hal_ssr_trigger_type {
|
||||
SSR_ERR_FATAL = 1,
|
||||
SSR_SW_DIV_BY_ZERO,
|
||||
SSR_HW_WDOG_IRQ,
|
||||
SSR_SESSION_ABORT,
|
||||
};
|
||||
|
||||
enum hal_intra_refresh_mode {
|
||||
HAL_INTRA_REFRESH_NONE,
|
||||
HAL_INTRA_REFRESH_CYCLIC,
|
||||
HAL_INTRA_REFRESH_RANDOM,
|
||||
HAL_UNUSED_INTRA = 0x10000000,
|
||||
};
|
||||
|
||||
enum cvp_resource_id {
|
||||
CVP_RESOURCE_NONE,
|
||||
CVP_RESOURCE_SYSCACHE,
|
||||
CVP_UNUSED_RESOURCE = 0x10000000,
|
||||
};
|
||||
|
||||
struct cvp_resource_hdr {
|
||||
enum cvp_resource_id resource_id;
|
||||
void *resource_handle;
|
||||
};
|
||||
|
||||
struct cvp_buffer_addr_info {
|
||||
enum hal_buffer buffer_type;
|
||||
u32 buffer_size;
|
||||
u32 num_buffers;
|
||||
u32 align_device_addr;
|
||||
u32 extradata_addr;
|
||||
u32 extradata_size;
|
||||
u32 response_required;
|
||||
};
|
||||
|
||||
/* Needs to be exactly the same as hfi_buffer_info */
|
||||
struct cvp_hal_buffer_info {
|
||||
u32 buffer_addr;
|
||||
u32 extra_data_addr;
|
||||
};
|
||||
|
||||
struct cvp_hal_fw_info {
|
||||
char version[CVP_VERSION_LENGTH];
|
||||
phys_addr_t base_addr;
|
||||
int register_base;
|
||||
int register_size;
|
||||
int irq;
|
||||
};
|
||||
|
||||
enum hal_flush {
|
||||
HAL_FLUSH_INPUT,
|
||||
HAL_FLUSH_OUTPUT,
|
||||
HAL_FLUSH_ALL,
|
||||
HAL_UNUSED_FLUSH = 0x10000000,
|
||||
};
|
||||
|
||||
enum hal_event_type {
|
||||
HAL_EVENT_SEQ_CHANGED_SUFFICIENT_RESOURCES,
|
||||
HAL_EVENT_SEQ_CHANGED_INSUFFICIENT_RESOURCES,
|
||||
HAL_EVENT_RELEASE_BUFFER_REFERENCE,
|
||||
HAL_UNUSED_SEQCHG = 0x10000000,
|
||||
};
|
||||
|
||||
/* HAL Response */
|
||||
#define IS_HAL_SYS_CMD(cmd) ((cmd) >= HAL_SYS_INIT_DONE && \
|
||||
(cmd) <= HAL_SYS_ERROR)
|
||||
#define IS_HAL_SESSION_CMD(cmd) ((cmd) >= HAL_SESSION_EVENT_CHANGE && \
|
||||
(cmd) <= HAL_SESSION_ERROR)
|
||||
enum hal_command_response {
|
||||
HAL_NO_RESP,
|
||||
HAL_SYS_INIT_DONE,
|
||||
HAL_SYS_SET_RESOURCE_DONE,
|
||||
HAL_SYS_RELEASE_RESOURCE_DONE,
|
||||
HAL_SYS_PING_ACK_DONE,
|
||||
HAL_SYS_PC_PREP_DONE,
|
||||
HAL_SYS_IDLE,
|
||||
HAL_SYS_DEBUG,
|
||||
HAL_SYS_WATCHDOG_TIMEOUT,
|
||||
HAL_SYS_ERROR,
|
||||
/* SESSION COMMANDS_DONE */
|
||||
HAL_SESSION_EVENT_CHANGE,
|
||||
HAL_SESSION_INIT_DONE,
|
||||
HAL_SESSION_END_DONE,
|
||||
HAL_SESSION_SET_BUFFER_DONE,
|
||||
HAL_SESSION_ABORT_DONE,
|
||||
HAL_SESSION_STOP_DONE,
|
||||
HAL_SESSION_CVP_OPERATION_CONFIG,
|
||||
HAL_SESSION_FLUSH_DONE,
|
||||
HAL_SESSION_SUSPEND_DONE,
|
||||
HAL_SESSION_RESUME_DONE,
|
||||
HAL_SESSION_SET_PROP_DONE,
|
||||
HAL_SESSION_GET_PROP_DONE,
|
||||
HAL_SESSION_RELEASE_BUFFER_DONE,
|
||||
HAL_SESSION_REGISTER_BUFFER_DONE,
|
||||
HAL_SESSION_UNREGISTER_BUFFER_DONE,
|
||||
HAL_SESSION_RELEASE_RESOURCE_DONE,
|
||||
HAL_SESSION_DFS_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_DFS_FRAME_CMD_DONE,
|
||||
HAL_SESSION_DME_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_DME_BASIC_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_DME_FRAME_CMD_DONE,
|
||||
HAL_SESSION_TME_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_ODT_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_OD_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_NCC_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_ICA_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_HCD_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_DC_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_DCM_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_PYS_HCD_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_FD_CONFIG_CMD_DONE,
|
||||
HAL_SESSION_PERSIST_CMD_DONE,
|
||||
HAL_SESSION_MODEL_BUF_CMD_DONE,
|
||||
HAL_SESSION_ICA_FRAME_CMD_DONE,
|
||||
HAL_SESSION_FD_FRAME_CMD_DONE,
|
||||
HAL_SESSION_PROPERTY_INFO,
|
||||
HAL_SESSION_ERROR,
|
||||
HAL_RESPONSE_UNUSED = 0x10000000,
|
||||
};
|
||||
|
||||
struct msm_cvp_capability {
|
||||
u32 reserved[183];
|
||||
};
|
||||
|
||||
struct cvp_hal_sys_init_done {
|
||||
u32 dec_codec_supported;
|
||||
u32 enc_codec_supported;
|
||||
u32 codec_count;
|
||||
struct msm_cvp_capability *capabilities;
|
||||
u32 max_sessions_supported;
|
||||
};
|
||||
|
||||
struct cvp_hal_session_init_done {
|
||||
struct msm_cvp_capability capability;
|
||||
};
|
||||
|
||||
struct msm_cvp_cb_cmd_done {
|
||||
u32 device_id;
|
||||
void *session_id;
|
||||
enum cvp_status status;
|
||||
u32 size;
|
||||
union {
|
||||
struct cvp_hfi_msg_session_hdr msg_hdr;
|
||||
struct cvp_resource_hdr resource_hdr;
|
||||
struct cvp_buffer_addr_info buffer_addr_info;
|
||||
struct cvp_hal_sys_init_done sys_init_done;
|
||||
struct cvp_hal_session_init_done session_init_done;
|
||||
struct cvp_hal_buffer_info buffer_info;
|
||||
enum hal_flush flush_type;
|
||||
} data;
|
||||
};
|
||||
|
||||
struct cvp_hal_index_extradata_input_crop_payload {
|
||||
u32 size;
|
||||
u32 version;
|
||||
u32 port_index;
|
||||
u32 left;
|
||||
u32 top;
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
struct msm_cvp_cb_event {
|
||||
u32 device_id;
|
||||
void *session_id;
|
||||
enum cvp_status status;
|
||||
u32 height;
|
||||
u32 width;
|
||||
int bit_depth;
|
||||
u32 hal_event_type;
|
||||
u32 packet_buffer;
|
||||
u32 extra_data_buffer;
|
||||
u32 pic_struct;
|
||||
u32 colour_space;
|
||||
u32 profile;
|
||||
u32 level;
|
||||
u32 entropy_mode;
|
||||
u32 capture_buf_count;
|
||||
struct cvp_hal_index_extradata_input_crop_payload crop_data;
|
||||
};
|
||||
|
||||
struct msm_cvp_cb_data_done {
|
||||
u32 device_id;
|
||||
void *session_id;
|
||||
enum cvp_status status;
|
||||
u32 size;
|
||||
u32 clnt_data;
|
||||
};
|
||||
|
||||
struct msm_cvp_cb_info {
|
||||
enum hal_command_response response_type;
|
||||
union {
|
||||
struct msm_cvp_cb_cmd_done cmd;
|
||||
struct msm_cvp_cb_event event;
|
||||
struct msm_cvp_cb_data_done data;
|
||||
} response;
|
||||
};
|
||||
|
||||
enum msm_cvp_hfi_type {
|
||||
CVP_HFI_IRIS,
|
||||
};
|
||||
|
||||
enum msm_cvp_thermal_level {
|
||||
CVP_THERMAL_NORMAL = 0,
|
||||
CVP_THERMAL_LOW,
|
||||
CVP_THERMAL_HIGH,
|
||||
CVP_THERMAL_CRITICAL
|
||||
};
|
||||
|
||||
struct msm_cvp_gov_data {
|
||||
struct cvp_bus_vote_data *data;
|
||||
u32 data_count;
|
||||
};
|
||||
|
||||
enum msm_cvp_power_mode {
|
||||
CVP_POWER_NORMAL = 0,
|
||||
CVP_POWER_LOW,
|
||||
CVP_POWER_TURBO
|
||||
};
|
||||
|
||||
struct cvp_bus_vote_data {
|
||||
u32 domain;
|
||||
u32 ddr_bw;
|
||||
u32 sys_cache_bw;
|
||||
enum msm_cvp_power_mode power_mode;
|
||||
bool use_sys_cache;
|
||||
};
|
||||
|
||||
struct cvp_hal_cmd_sys_get_property_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
#define call_hfi_op(q, op, args...) \
|
||||
(((q) && (q)->op) ? ((q)->op(args)) : 0)
|
||||
|
||||
struct msm_cvp_hfi_defs {
|
||||
unsigned int size;
|
||||
unsigned int type;
|
||||
unsigned int buf_offset;
|
||||
unsigned int buf_num;
|
||||
enum hal_command_response resp;
|
||||
};
|
||||
|
||||
struct cvp_hfi_device {
|
||||
void *hfi_device_data;
|
||||
/*Add function pointers for all the hfi functions below*/
|
||||
int (*core_init)(void *device);
|
||||
int (*core_release)(void *device);
|
||||
int (*core_trigger_ssr)(void *device, enum hal_ssr_trigger_type);
|
||||
int (*session_init)(void *device, void *session_id, void **new_session);
|
||||
int (*session_end)(void *session);
|
||||
int (*session_abort)(void *session);
|
||||
int (*session_set_buffers)(void *sess,
|
||||
struct cvp_buffer_addr_info *buffer_info);
|
||||
int (*session_release_buffers)(void *sess,
|
||||
struct cvp_buffer_addr_info *buffer_info);
|
||||
int (*session_send)(void *sess,
|
||||
struct cvp_kmd_hfi_packet *in_pkt);
|
||||
int (*scale_clocks)(void *dev, u32 freq);
|
||||
int (*vote_bus)(void *dev, struct cvp_bus_vote_data *data,
|
||||
int num_data);
|
||||
int (*get_fw_info)(void *dev, struct cvp_hal_fw_info *fw_info);
|
||||
int (*session_clean)(void *sess);
|
||||
int (*get_core_capabilities)(void *dev);
|
||||
int (*suspend)(void *dev);
|
||||
int (*flush_debug_queue)(void *dev);
|
||||
int (*noc_error_info)(void *dev);
|
||||
int (*validate_session)(void *sess, const char *func);
|
||||
};
|
||||
|
||||
typedef void (*hfi_cmd_response_callback) (enum hal_command_response cmd,
|
||||
void *data);
|
||||
typedef void (*msm_cvp_callback) (u32 response, void *callback);
|
||||
|
||||
struct cvp_hfi_device *cvp_hfi_initialize(enum msm_cvp_hfi_type hfi_type,
|
||||
u32 device_id, struct msm_cvp_platform_resources *res,
|
||||
hfi_cmd_response_callback callback);
|
||||
void cvp_hfi_deinitialize(enum msm_cvp_hfi_type hfi_type,
|
||||
struct cvp_hfi_device *hdev);
|
||||
|
||||
int get_pkt_index(struct cvp_hal_session_cmd_pkt *hdr);
|
||||
int get_signal_from_pkt_type(unsigned int type);
|
||||
int set_feature_bitmask(int pkt_index, unsigned long *bitmask);
|
||||
int get_hfi_version(void);
|
||||
unsigned int get_msg_size(void);
|
||||
unsigned int get_msg_session_id(void *msg);
|
||||
unsigned int get_msg_errorcode(void *msg);
|
||||
int get_msg_opconfigs(void *msg, unsigned int *session_id,
|
||||
unsigned int *error_type, unsigned int *config_id);
|
||||
extern const struct msm_cvp_hfi_defs cvp_hfi_defs[];
|
||||
|
||||
#endif /*__CVP_HFI_API_H__ */
|
502
drivers/media/platform/msm/cvp/cvp_hfi_helper.h
Normal file
502
drivers/media/platform/msm/cvp/cvp_hfi_helper.h
Normal file
@ -0,0 +1,502 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __H_CVP_HFI_HELPER_H__
|
||||
#define __H_CVP_HFI_HELPER_H__
|
||||
|
||||
#define HFI_COMMON_BASE (0)
|
||||
#define HFI_DOMAIN_BASE_COMMON (HFI_COMMON_BASE + 0)
|
||||
#define HFI_DOMAIN_BASE_CVP (HFI_COMMON_BASE + 0x04000000)
|
||||
|
||||
#define HFI_ARCH_COMMON_OFFSET (0)
|
||||
|
||||
#define HFI_CMD_START_OFFSET (0x00010000)
|
||||
#define HFI_MSG_START_OFFSET (0x00020000)
|
||||
|
||||
#define HFI_ERR_NONE HFI_COMMON_BASE
|
||||
#define HFI_ERR_SYS_FATAL (HFI_COMMON_BASE + 0x1)
|
||||
#define HFI_ERR_SYS_INVALID_PARAMETER (HFI_COMMON_BASE + 0x2)
|
||||
#define HFI_ERR_SYS_VERSION_MISMATCH (HFI_COMMON_BASE + 0x3)
|
||||
#define HFI_ERR_SYS_INSUFFICIENT_RESOURCES (HFI_COMMON_BASE + 0x4)
|
||||
#define HFI_ERR_SYS_MAX_SESSIONS_REACHED (HFI_COMMON_BASE + 0x5)
|
||||
#define HFI_ERR_SYS_UNSUPPORTED_CODEC (HFI_COMMON_BASE + 0x6)
|
||||
#define HFI_ERR_SYS_SESSION_IN_USE (HFI_COMMON_BASE + 0x7)
|
||||
#define HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE (HFI_COMMON_BASE + 0x8)
|
||||
#define HFI_ERR_SYS_UNSUPPORTED_DOMAIN (HFI_COMMON_BASE + 0x9)
|
||||
#define HFI_ERR_SYS_NOC_ERROR (HFI_COMMON_BASE + 0x11)
|
||||
#define HFI_ERR_SESSION_FATAL (HFI_COMMON_BASE + 0x1001)
|
||||
#define HFI_ERR_SESSION_INVALID_PARAMETER (HFI_COMMON_BASE + 0x1002)
|
||||
#define HFI_ERR_SESSION_BAD_POINTER (HFI_COMMON_BASE + 0x1003)
|
||||
#define HFI_ERR_SESSION_INVALID_SESSION_ID (HFI_COMMON_BASE + 0x1004)
|
||||
#define HFI_ERR_SESSION_INVALID_STREAM_ID (HFI_COMMON_BASE + 0x1005)
|
||||
#define HFI_ERR_SESSION_INCORRECT_STATE_OPERATION \
|
||||
(HFI_COMMON_BASE + 0x1006)
|
||||
#define HFI_ERR_SESSION_UNSUPPORTED_PROPERTY (HFI_COMMON_BASE + 0x1007)
|
||||
|
||||
#define HFI_ERR_SESSION_UNSUPPORTED_SETTING (HFI_COMMON_BASE + 0x1008)
|
||||
|
||||
#define HFI_ERR_SESSION_INSUFFICIENT_RESOURCES (HFI_COMMON_BASE + 0x1009)
|
||||
|
||||
#define HFI_ERR_SESSION_STREAM_CORRUPT (HFI_COMMON_BASE + 0x100B)
|
||||
#define HFI_ERR_SESSION_ENC_OVERFLOW (HFI_COMMON_BASE + 0x100C)
|
||||
#define HFI_ERR_SESSION_UNSUPPORTED_STREAM (HFI_COMMON_BASE + 0x100D)
|
||||
#define HFI_ERR_SESSION_CMDSIZE (HFI_COMMON_BASE + 0x100E)
|
||||
#define HFI_ERR_SESSION_UNSUPPORT_CMD (HFI_COMMON_BASE + 0x100F)
|
||||
#define HFI_ERR_SESSION_UNSUPPORT_BUFFERTYPE (HFI_COMMON_BASE + 0x1010)
|
||||
#define HFI_ERR_SESSION_BUFFERCOUNT_TOOSMALL (HFI_COMMON_BASE + 0x1011)
|
||||
#define HFI_ERR_SESSION_INVALID_SCALE_FACTOR (HFI_COMMON_BASE + 0x1012)
|
||||
#define HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED (HFI_COMMON_BASE + 0x1013)
|
||||
|
||||
#define HFI_EVENT_SYS_ERROR (HFI_COMMON_BASE + 0x1)
|
||||
#define HFI_EVENT_SESSION_ERROR (HFI_COMMON_BASE + 0x2)
|
||||
|
||||
#define HFI_TME_PROFILE_DEFAULT 0x00000001
|
||||
#define HFI_TME_PROFILE_FRC 0x00000002
|
||||
#define HFI_TME_PROFILE_ASW 0x00000004
|
||||
#define HFI_TME_PROFILE_DFS_BOKEH 0x00000008
|
||||
|
||||
#define HFI_TME_LEVEL_INTEGER 0x00000001
|
||||
|
||||
#define HFI_BUFFER_INPUT (HFI_COMMON_BASE + 0x1)
|
||||
#define HFI_BUFFER_OUTPUT (HFI_COMMON_BASE + 0x2)
|
||||
#define HFI_BUFFER_OUTPUT2 (HFI_COMMON_BASE + 0x3)
|
||||
#define HFI_BUFFER_INTERNAL_PERSIST (HFI_COMMON_BASE + 0x4)
|
||||
#define HFI_BUFFER_INTERNAL_PERSIST_1 (HFI_COMMON_BASE + 0x5)
|
||||
#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH (HFI_COMMON_BASE + 0x6)
|
||||
#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH_1 (HFI_COMMON_BASE + 0x7)
|
||||
#define HFI_BUFFER_COMMON_INTERNAL_SCRATCH_2 (HFI_COMMON_BASE + 0x8)
|
||||
#define HFI_BUFFER_COMMON_INTERNAL_RECON (HFI_COMMON_BASE + 0x9)
|
||||
#define HFI_BUFFER_EXTRADATA_OUTPUT (HFI_COMMON_BASE + 0xA)
|
||||
#define HFI_BUFFER_EXTRADATA_OUTPUT2 (HFI_COMMON_BASE + 0xB)
|
||||
#define HFI_BUFFER_EXTRADATA_INPUT (HFI_COMMON_BASE + 0xC)
|
||||
|
||||
|
||||
#define HFI_PROPERTY_SYS_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + 0x0000)
|
||||
#define HFI_PROPERTY_SYS_DEBUG_CONFIG \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x001)
|
||||
#define HFI_PROPERTY_SYS_RESOURCE_OCMEM_REQUIREMENT_INFO \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x002)
|
||||
#define HFI_PROPERTY_SYS_CONFIG_VCODEC_CLKFREQ \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x003)
|
||||
#define HFI_PROPERTY_SYS_IDLE_INDICATOR \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x004)
|
||||
#define HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x005)
|
||||
#define HFI_PROPERTY_SYS_IMAGE_VERSION \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x006)
|
||||
#define HFI_PROPERTY_SYS_CONFIG_COVERAGE \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x007)
|
||||
#define HFI_PROPERTY_SYS_UBWC_CONFIG \
|
||||
(HFI_PROPERTY_SYS_COMMON_START + 0x008)
|
||||
|
||||
#define HFI_DEBUG_MSG_LOW 0x00000001
|
||||
#define HFI_DEBUG_MSG_MEDIUM 0x00000002
|
||||
#define HFI_DEBUG_MSG_HIGH 0x00000004
|
||||
#define HFI_DEBUG_MSG_ERROR 0x00000008
|
||||
#define HFI_DEBUG_MSG_FATAL 0x00000010
|
||||
#define HFI_DEBUG_MSG_PERF 0x00000020
|
||||
|
||||
#define HFI_DEBUG_MODE_QUEUE 0x00000001
|
||||
#define HFI_DEBUG_MODE_QDSS 0x00000002
|
||||
|
||||
struct cvp_hfi_debug_config {
|
||||
u32 debug_config;
|
||||
u32 debug_mode;
|
||||
};
|
||||
|
||||
struct cvp_hfi_enable {
|
||||
u32 enable;
|
||||
};
|
||||
|
||||
#define HFI_RESOURCE_SYSCACHE 0x00000002
|
||||
|
||||
struct cvp_hfi_resource_subcache_type {
|
||||
u32 size;
|
||||
u32 sc_id;
|
||||
};
|
||||
|
||||
struct cvp_hfi_resource_syscache_info_type {
|
||||
u32 num_entries;
|
||||
struct cvp_hfi_resource_subcache_type rg_subcache_entries[1];
|
||||
};
|
||||
|
||||
#define HFI_CMD_SYS_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + HFI_CMD_START_OFFSET \
|
||||
+ 0x0000)
|
||||
#define HFI_CMD_SYS_INIT (HFI_CMD_SYS_COMMON_START + 0x001)
|
||||
#define HFI_CMD_SYS_PC_PREP (HFI_CMD_SYS_COMMON_START + 0x002)
|
||||
#define HFI_CMD_SYS_SET_RESOURCE (HFI_CMD_SYS_COMMON_START + 0x003)
|
||||
#define HFI_CMD_SYS_RELEASE_RESOURCE (HFI_CMD_SYS_COMMON_START + 0x004)
|
||||
#define HFI_CMD_SYS_SET_PROPERTY (HFI_CMD_SYS_COMMON_START + 0x005)
|
||||
#define HFI_CMD_SYS_GET_PROPERTY (HFI_CMD_SYS_COMMON_START + 0x006)
|
||||
#define HFI_CMD_SYS_SESSION_INIT (HFI_CMD_SYS_COMMON_START + 0x007)
|
||||
#define HFI_CMD_SYS_SESSION_END (HFI_CMD_SYS_COMMON_START + 0x008)
|
||||
#define HFI_CMD_SYS_SET_BUFFERS (HFI_CMD_SYS_COMMON_START + 0x009)
|
||||
#define HFI_CMD_SYS_SESSION_ABORT (HFI_CMD_SYS_COMMON_START + 0x00A)
|
||||
#define HFI_CMD_SYS_TEST_START (HFI_CMD_SYS_COMMON_START + 0x100)
|
||||
|
||||
#define HFI_MSG_SYS_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + \
|
||||
HFI_MSG_START_OFFSET + 0x0000)
|
||||
#define HFI_MSG_SYS_INIT_DONE (HFI_MSG_SYS_COMMON_START + 0x1)
|
||||
#define HFI_MSG_SYS_PC_PREP_DONE (HFI_MSG_SYS_COMMON_START + 0x2)
|
||||
#define HFI_MSG_SYS_RELEASE_RESOURCE (HFI_MSG_SYS_COMMON_START + 0x3)
|
||||
#define HFI_MSG_SYS_DEBUG (HFI_MSG_SYS_COMMON_START + 0x4)
|
||||
#define HFI_MSG_SYS_SESSION_INIT_DONE (HFI_MSG_SYS_COMMON_START + 0x6)
|
||||
#define HFI_MSG_SYS_SESSION_END_DONE (HFI_MSG_SYS_COMMON_START + 0x7)
|
||||
#define HFI_MSG_SYS_IDLE (HFI_MSG_SYS_COMMON_START + 0x8)
|
||||
#define HFI_MSG_SYS_COV (HFI_MSG_SYS_COMMON_START + 0x9)
|
||||
#define HFI_MSG_SYS_PROPERTY_INFO (HFI_MSG_SYS_COMMON_START + 0xA)
|
||||
#define HFI_MSG_SYS_SESSION_ABORT_DONE (HFI_MSG_SYS_COMMON_START + 0xC)
|
||||
#define HFI_MSG_SESSION_SYNC_DONE (HFI_MSG_SESSION_OX_START + 0xD)
|
||||
|
||||
#define HFI_MSG_SESSION_COMMON_START \
|
||||
(HFI_DOMAIN_BASE_COMMON + HFI_ARCH_COMMON_OFFSET + \
|
||||
HFI_MSG_START_OFFSET + 0x1000)
|
||||
#define HFI_MSG_EVENT_NOTIFY (HFI_MSG_SESSION_COMMON_START + 0x1)
|
||||
#define HFI_MSG_SESSION_GET_SEQUENCE_HEADER_DONE \
|
||||
(HFI_MSG_SESSION_COMMON_START + 0x2)
|
||||
|
||||
#define HFI_CMD_SYS_TEST_SSR (HFI_CMD_SYS_TEST_START + 0x1)
|
||||
#define HFI_TEST_SSR_SW_ERR_FATAL 0x1
|
||||
#define HFI_TEST_SSR_SW_DIV_BY_ZERO 0x2
|
||||
#define HFI_TEST_SSR_HW_WDOG_IRQ 0x3
|
||||
|
||||
struct cvp_hal_cmd_pkt_hdr {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
};
|
||||
|
||||
struct cvp_hal_msg_pkt_hdr {
|
||||
u32 size;
|
||||
u32 packet;
|
||||
};
|
||||
|
||||
struct cvp_hal_session_cmd_pkt {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_init_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 arch_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_pc_prep_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_set_resource_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 resource_handle;
|
||||
u32 resource_type;
|
||||
u32 rg_resource_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_release_resource_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 resource_type;
|
||||
u32 resource_handle;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_set_property_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_get_property_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
enum HFI_SESSION_TYPE {
|
||||
HFI_SESSION_CV = 1,
|
||||
HFI_SESSION_DME,
|
||||
HFI_SESSION_ODT,
|
||||
HFI_SESSION_FD
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_session_init_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 session_type;
|
||||
u32 session_kmask;
|
||||
u32 session_prio;
|
||||
u32 is_secure;
|
||||
u32 dsp_ac_mask;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_session_end_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_set_buffers_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 buffer_type;
|
||||
u32 buffer_size;
|
||||
u32 num_buffers;
|
||||
u32 rg_buffer_addr[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_set_ubwc_config_packet_type {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
struct {
|
||||
u32 max_channel_override : 1;
|
||||
u32 mal_length_override : 1;
|
||||
u32 hb_override : 1;
|
||||
u32 bank_swzl_level_override : 1;
|
||||
u32 bank_spreading_override : 1;
|
||||
u32 reserved : 27;
|
||||
} override_bit_info;
|
||||
u32 max_channels;
|
||||
u32 mal_length;
|
||||
u32 highest_bank_bit;
|
||||
u32 bank_swzl_level;
|
||||
u32 bank_spreading;
|
||||
u32 reserved[2];
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_set_property_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_client {
|
||||
u32 transaction_id;
|
||||
u32 data1;
|
||||
u32 data2;
|
||||
u32 kdata1;
|
||||
u32 kdata2;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
};
|
||||
|
||||
struct cvp_hfi_client_d {
|
||||
u32 transaction_id;
|
||||
u32 data1;
|
||||
u32 data2;
|
||||
};
|
||||
|
||||
struct cvp_buf_desc {
|
||||
u32 fd;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct cvp_hfi_buf_type {
|
||||
s32 fd;
|
||||
u32 size;
|
||||
u32 offset;
|
||||
u32 flags;
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_set_buffers_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client client_data;
|
||||
struct cvp_hfi_buf_type buf_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_set_buffers_packet_d {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client_d client_data;
|
||||
u32 buffer_addr;
|
||||
u32 buffer_size;
|
||||
};
|
||||
|
||||
struct cvp_session_release_buffers_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client client_data;
|
||||
u32 kernel_type;
|
||||
u32 buffer_type;
|
||||
u32 num_buffers;
|
||||
u32 buffer_idx;
|
||||
};
|
||||
|
||||
struct cvp_session_release_buffers_packet_d {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client_d client_data;
|
||||
u32 buffer_type;
|
||||
u32 num_buffers;
|
||||
u32 buffer_idx;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_hdr {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client client_data;
|
||||
u32 stream_idx;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_session_hdr {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
struct cvp_hfi_client client_data;
|
||||
u32 stream_idx;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_session_hdr_d {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client_d client_data;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_buffer_mapping_type {
|
||||
u32 index;
|
||||
u32 device_addr;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_session_sync_process_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 sync_id;
|
||||
u32 rg_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_event_notify_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 event_id;
|
||||
u32 event_data1;
|
||||
u32 event_data2;
|
||||
u32 rg_ext_event_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_session_op_cfg_packet_d {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
struct cvp_hfi_client_d client_data;
|
||||
u32 op_conf_id;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_session_op_cfg_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
struct cvp_hfi_client client_data;
|
||||
u32 stream_idx;
|
||||
u32 op_conf_id;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_release_buffer_ref_event_packet {
|
||||
u32 packet_buffer;
|
||||
u32 extra_data_buffer;
|
||||
u32 output_tag;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_init_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 error_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_pc_prep_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_release_resource_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 resource_handle;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_session_init_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
u32 num_properties;
|
||||
u32 rg_property_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_session_end_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_session_get_sequence_header_done_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 session_id;
|
||||
u32 error_type;
|
||||
u32 header_len;
|
||||
u32 sequence_header;
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_debug_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 msg_type;
|
||||
u32 msg_size;
|
||||
u32 time_stamp_hi;
|
||||
u32 time_stamp_lo;
|
||||
u8 rg_msg_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_msg_sys_coverage_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 msg_size;
|
||||
u32 time_stamp_hi;
|
||||
u32 time_stamp_lo;
|
||||
u8 rg_msg_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_sfr_struct {
|
||||
u32 bufSize;
|
||||
u8 rg_data[1];
|
||||
};
|
||||
|
||||
struct cvp_hfi_cmd_sys_test_ssr_packet {
|
||||
u32 size;
|
||||
u32 packet_type;
|
||||
u32 trigger_type;
|
||||
};
|
||||
|
||||
#endif
|
223
drivers/media/platform/msm/cvp/cvp_hfi_io.h
Normal file
223
drivers/media/platform/msm/cvp/cvp_hfi_io.h
Normal file
@ -0,0 +1,223 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __CVP_HFI_IO_H__
|
||||
#define __CVP_HFI_IO_H__
|
||||
|
||||
#include <linux/io.h>
|
||||
|
||||
#define CVP_CPU_BASE_OFFS 0x000A0000
|
||||
#define CVP_AON_BASE_OFFS 0x000E0000
|
||||
|
||||
#define CVP_CPU_CS_A2HSOFTINTEN (CVP_CPU_BASE_OFFS + 0x10)
|
||||
#define CVP_CPU_CS_A2HSOFTINTENCLR (CVP_CPU_BASE_OFFS + 0x14)
|
||||
#define CVP_CPU_CS_A2HSOFTINT (CVP_CPU_BASE_OFFS + 0x18)
|
||||
#define CVP_CPU_CS_A2HSOFTINTCLR (CVP_CPU_BASE_OFFS + 0x1C)
|
||||
#define CVP_CPU_CS_VMIMSG (CVP_CPU_BASE_OFFS + 0x34)
|
||||
#define CVP_CPU_CS_VMIMSGAG0 (CVP_CPU_BASE_OFFS + 0x38)
|
||||
#define CVP_CPU_CS_VMIMSGAG1 (CVP_CPU_BASE_OFFS + 0x3C)
|
||||
#define CVP_CPU_CS_VMIMSGAG2 (CVP_CPU_BASE_OFFS + 0x40)
|
||||
#define CVP_CPU_CS_VMIMSGAG3 (CVP_CPU_BASE_OFFS + 0x44)
|
||||
#define CVP_CPU_CS_SCIACMD (CVP_CPU_BASE_OFFS + 0x48)
|
||||
#define CVP_CPU_CS_H2XSOFTINTEN (CVP_CPU_BASE_OFFS + 0x148)
|
||||
|
||||
/* CVP_CTRL_STATUS */
|
||||
#define CVP_CPU_CS_SCIACMDARG0 (CVP_CPU_BASE_OFFS + 0x4C)
|
||||
#define CVP_CPU_CS_SCIACMDARG0_BMSK 0xff
|
||||
#define CVP_CPU_CS_SCIACMDARG0_SHFT 0x0
|
||||
#define CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK 0xfe
|
||||
#define CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_SHFT 0x1
|
||||
#define CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK 0x1
|
||||
#define CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_SHFT 0x0
|
||||
#define CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY 0x100
|
||||
|
||||
/* HFI_QTBL_INFO */
|
||||
#define CVP_CPU_CS_SCIACMDARG1 (CVP_CPU_BASE_OFFS + 0x50)
|
||||
|
||||
/* HFI_QTBL_ADDR */
|
||||
#define CVP_CPU_CS_SCIACMDARG2 (CVP_CPU_BASE_OFFS + 0x54)
|
||||
|
||||
/* HFI_VERSION_INFO */
|
||||
#define CVP_CPU_CS_SCIACMDARG3 (CVP_CPU_BASE_OFFS + 0x58)
|
||||
|
||||
/* CVP_SFR_ADDR */
|
||||
#define CVP_CPU_CS_SCIBCMD (CVP_CPU_BASE_OFFS + 0x5C)
|
||||
|
||||
/* CVP_MMAP_ADDR */
|
||||
#define CVP_CPU_CS_SCIBCMDARG0 (CVP_CPU_BASE_OFFS + 0x60)
|
||||
|
||||
/* CVP_UC_REGION_ADDR */
|
||||
#define CVP_CPU_CS_SCIBARG1 (CVP_CPU_BASE_OFFS + 0x64)
|
||||
|
||||
/* CVP_UC_REGION_ADDR */
|
||||
#define CVP_CPU_CS_SCIBARG2 (CVP_CPU_BASE_OFFS + 0x68)
|
||||
|
||||
#define CVP_CPU_CS_SCIBARG3 (CVP_CPU_BASE_OFFS + 0x6C)
|
||||
|
||||
#define CVP_CPU_CS_H2ASOFTINTEN (CVP_CPU_BASE_OFFS + 0x148)
|
||||
#define CVP_CPU_CS_H2ASOFTINTENCLR (CVP_CPU_BASE_OFFS + 0x14c)
|
||||
#define CVP_CPU_CS_H2ASOFTINT (CVP_CPU_BASE_OFFS + 0x150)
|
||||
#define CVP_CPU_CS_H2ASOFTINTCLR (CVP_CPU_BASE_OFFS + 0x154)
|
||||
|
||||
/* FAL10 Feature Control */
|
||||
#define CVP_CPU_CS_X2RPMh (CVP_CPU_BASE_OFFS + 0x168)
|
||||
#define CVP_CPU_CS_X2RPMh_MASK0_BMSK 0x1
|
||||
#define CVP_CPU_CS_X2RPMh_MASK0_SHFT 0x0
|
||||
#define CVP_CPU_CS_X2RPMh_MASK1_BMSK 0x2
|
||||
#define CVP_CPU_CS_X2RPMh_MASK1_SHFT 0x1
|
||||
#define CVP_CPU_CS_X2RPMh_SWOVERRIDE_BMSK 0x4
|
||||
#define CVP_CPU_CS_X2RPMh_SWOVERRIDE_SHFT 0x3
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: cvp_wrapper
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define CVP_WRAPPER_BASE_OFFS 0x000B0000
|
||||
|
||||
#define CVP_WRAPPER_HW_VERSION (CVP_WRAPPER_BASE_OFFS + 0x00)
|
||||
#define CVP_WRAPPER_HW_VERSION_MAJOR_VERSION_MASK 0x78000000
|
||||
#define CVP_WRAPPER_HW_VERSION_MAJOR_VERSION_SHIFT 28
|
||||
#define CVP_WRAPPER_HW_VERSION_MINOR_VERSION_MASK 0xFFF0000
|
||||
#define CVP_WRAPPER_HW_VERSION_MINOR_VERSION_SHIFT 16
|
||||
#define CVP_WRAPPER_HW_VERSION_STEP_VERSION_MASK 0xFFFF
|
||||
|
||||
#define CVP_WRAPPER_INTR_STATUS (CVP_WRAPPER_BASE_OFFS + 0x0C)
|
||||
#define CVP_WRAPPER_INTR_STATUS_A2HWD_BMSK 0x8
|
||||
#define CVP_WRAPPER_INTR_STATUS_A2H_BMSK 0x4
|
||||
|
||||
#define CVP_WRAPPER_INTR_MASK (CVP_WRAPPER_BASE_OFFS + 0x10)
|
||||
#define CVP_FATAL_INTR_BMSK (CVP_WRAPPER_INTR_MASK_CPU_NOC_BMSK | \
|
||||
CVP_WRAPPER_INTR_MASK_CORE_NOC_BMSK | \
|
||||
CVP_WRAPPER_INTR_MASK_A2HWD_BMSK)
|
||||
#define CVP_WRAPPER_INTR_MASK_CPU_NOC_BMSK 0x40
|
||||
#define CVP_WRAPPER_INTR_MASK_CORE_NOC_BMSK 0x20
|
||||
#define CVP_WRAPPER_INTR_MASK_A2HWD_BMSK 0x8
|
||||
#define CVP_WRAPPER_INTR_MASK_A2HCPU_BMSK 0x4
|
||||
#define CVP_WRAPPER_INTR_MASK_A2HCPU_SHFT 0x2
|
||||
|
||||
#define CVP_WRAPPER_INTR_CLEAR (CVP_WRAPPER_BASE_OFFS + 0x14)
|
||||
#define CVP_WRAPPER_TZ_BASE_OFFS 0x000C0000
|
||||
#define CVP_WRAPPER_INTR_CLEAR_A2HWD_BMSK 0x10
|
||||
#define CVP_WRAPPER_INTR_CLEAR_A2HWD_SHFT 0x4
|
||||
#define CVP_WRAPPER_INTR_CLEAR_A2H_BMSK 0x4
|
||||
#define CVP_WRAPPER_INTR_CLEAR_A2H_SHFT 0x2
|
||||
#define CVP_WRAPPER_CPU_STATUS (CVP_WRAPPER_TZ_BASE_OFFS + 0x10)
|
||||
#define CVP_WRAPPER_CPU_CGC_DIS (CVP_WRAPPER_BASE_OFFS + 0x2010)
|
||||
|
||||
#define CVP_WRAPPER_CPU_CLOCK_CONFIG (CVP_WRAPPER_BASE_OFFS + 0x50)
|
||||
#define CVP_WRAPPER_DEBUG_BRIDGE_LPI_CONTROL (CVP_WRAPPER_BASE_OFFS + 0x54)
|
||||
#define CVP_WRAPPER_DEBUG_BRIDGE_LPI_STATUS (CVP_WRAPPER_BASE_OFFS + 0x58)
|
||||
#define CVP_WRAPPER_CORE_CLOCK_CONFIG (CVP_WRAPPER_BASE_OFFS + 0x88)
|
||||
|
||||
#define CVP_CTRL_INIT CVP_CPU_CS_SCIACMD
|
||||
|
||||
#define CVP_CTRL_STATUS CVP_CPU_CS_SCIACMDARG0
|
||||
#define CVP_CTRL_INIT_STATUS__M \
|
||||
CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_STATUS_BMSK
|
||||
#define CVP_CTRL_ERROR_STATUS__M \
|
||||
CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_ERROR_STATUS_BMSK
|
||||
#define CVP_CTRL_INIT_IDLE_MSG_BMSK \
|
||||
CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_INIT_IDLE_MSG_BMSK
|
||||
#define CVP_CTRL_STATUS_PC_READY \
|
||||
CVP_CPU_CS_SCIACMDARG0_HFI_CTRL_PC_READY
|
||||
|
||||
|
||||
#define CVP_QTBL_INFO CVP_CPU_CS_SCIACMDARG1
|
||||
|
||||
#define CVP_QTBL_ADDR CVP_CPU_CS_SCIACMDARG2
|
||||
|
||||
#define CVP_VERSION_INFO CVP_CPU_CS_SCIACMDARG3
|
||||
|
||||
#define CVP_SFR_ADDR CVP_CPU_CS_SCIBCMD
|
||||
#define CVP_MMAP_ADDR CVP_CPU_CS_SCIBCMDARG0
|
||||
#define CVP_UC_REGION_ADDR CVP_CPU_CS_SCIBARG1
|
||||
#define CVP_UC_REGION_SIZE CVP_CPU_CS_SCIBARG2
|
||||
|
||||
/* HFI_DSP_QTBL_ADDR
|
||||
* 31:3 - HFI_DSP_QTBL_ADDR
|
||||
* 4-byte aligned Address
|
||||
*/
|
||||
#define HFI_DSP_QTBL_ADDR CVP_CPU_CS_VMIMSG
|
||||
|
||||
/* HFI_DSP_UC_REGION_ADDR
|
||||
* 31:20 - HFI_DSP_UC_REGION_ADDR
|
||||
* 1MB aligned address.
|
||||
* Uncached Region start Address. This region covers
|
||||
* HFI DSP QTable,
|
||||
* HFI DSP Queue Headers,
|
||||
* HFI DSP Queues,
|
||||
*/
|
||||
#define HFI_DSP_UC_REGION_ADDR CVP_CPU_CS_VMIMSGAG0
|
||||
|
||||
/* HFI_DSP_UC_REGION_SIZE
|
||||
* 31:20 - HFI_DSP_UC_REGION_SIZE
|
||||
* Multiples of 1MB.
|
||||
* Size of the DSP_UC_REGION Uncached Region
|
||||
*/
|
||||
#define HFI_DSP_UC_REGION_SIZE CVP_CPU_CS_VMIMSGAG1
|
||||
|
||||
/*
|
||||
* --------------------------------------------------------------------------
|
||||
* MODULE: vcodec noc error log registers
|
||||
* --------------------------------------------------------------------------
|
||||
*/
|
||||
#define CVP_NOC_BASE_OFFS 0x000D0000
|
||||
#define CVP_NOC_ERR_SWID_LOW_OFFS (CVP_NOC_BASE_OFFS + 0x80)
|
||||
#define CVP_NOC_ERR_SWID_HIGH_OFFS (CVP_NOC_BASE_OFFS + 0x84)
|
||||
#define CVP_NOC_ERR_MAINCTL_LOW_OFFS (CVP_NOC_BASE_OFFS + 0x88)
|
||||
#define CVP_NOC_ERR_ERRVLD_LOW_OFFS (CVP_NOC_BASE_OFFS + 0x90)
|
||||
#define CVP_NOC_ERR_ERRCLR_LOW_OFFS (CVP_NOC_BASE_OFFS + 0x98)
|
||||
#define CVP_NOC_ERR_ERRLOG0_LOW_OFFS (CVP_NOC_BASE_OFFS + 0xA0)
|
||||
#define CVP_NOC_ERR_ERRLOG0_HIGH_OFFS (CVP_NOC_BASE_OFFS + 0xA4)
|
||||
#define CVP_NOC_ERR_ERRLOG1_LOW_OFFS (CVP_NOC_BASE_OFFS + 0xA8)
|
||||
#define CVP_NOC_ERR_ERRLOG1_HIGH_OFFS (CVP_NOC_BASE_OFFS + 0xAC)
|
||||
#define CVP_NOC_ERR_ERRLOG2_LOW_OFFS (CVP_NOC_BASE_OFFS + 0xB0)
|
||||
#define CVP_NOC_ERR_ERRLOG2_HIGH_OFFS (CVP_NOC_BASE_OFFS + 0xB4)
|
||||
#define CVP_NOC_ERR_ERRLOG3_LOW_OFFS (CVP_NOC_BASE_OFFS + 0xB8)
|
||||
#define CVP_NOC_ERR_ERRLOG3_HIGH_OFFS (CVP_NOC_BASE_OFFS + 0xBC)
|
||||
#define CVP_NOC_SBM_SENSELN0_LOW (CVP_NOC_BASE_OFFS + 0x300)
|
||||
|
||||
#define CVP_NOC_CORE_BASE_OFFS 0x00010000
|
||||
#define CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN0_LOW \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1100)
|
||||
#define CVP_NOC_MAIN_SIDEBANDMANAGER_SENSELN1_HIGH \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x110C)
|
||||
#define CVP_NOC_CORE_ERR_SWID_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1200)
|
||||
#define CVP_NOC_CORE_ERR_SWID_HIGH_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1204)
|
||||
#define CVP_NOC_CORE_ERR_MAINCTL_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1208)
|
||||
#define CVP_NOC_CORE_ERR_ERRVLD_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1210)
|
||||
#define CVP_NOC_CORE_ERR_ERRCLR_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1218)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG0_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1220)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG0_HIGH_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1224)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG1_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1228)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG1_HIGH_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x122C)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG2_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1230)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG2_HIGH_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1234)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG3_LOW_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x1238)
|
||||
#define CVP_NOC_CORE_ERR_ERRLOG3_HIGH_OFFS \
|
||||
(CVP_NOC_CORE_BASE_OFFS + 0x123C)
|
||||
|
||||
|
||||
#define CVP_AON_WRAPPER_MVP_NOC_LPI_CONTROL (CVP_AON_BASE_OFFS)
|
||||
#define CVP_AON_WRAPPER_MVP_NOC_LPI_STATUS (CVP_AON_BASE_OFFS + 0x4)
|
||||
|
||||
#define CVP_CC_BASE_OFFS 0x000F0000
|
||||
#define CVP_CC_MVS0C_GDSCR (CVP_CC_BASE_OFFS + 0xBF8)
|
||||
#define CVP_CC_MVS1C_GDSCR (CVP_CC_BASE_OFFS + 0xC98)
|
||||
#define CVP_CC_MVS1C_CBCR (CVP_CC_BASE_OFFS + 0xCD4)
|
||||
#endif
|
18
drivers/media/platform/msm/cvp/cvp_private.h
Normal file
18
drivers/media/platform/msm/cvp/cvp_private.h
Normal file
@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_V4L2_PRIVATE_H_
|
||||
#define _MSM_V4L2_PRIVATE_H_
|
||||
|
||||
#include <media/msm_cvp_private.h>
|
||||
#include "msm_cvp_debug.h"
|
||||
|
||||
long cvp_unblocked_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
long cvp_compat_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg);
|
||||
|
||||
#endif
|
505
drivers/media/platform/msm/cvp/hfi_packetization.c
Normal file
505
drivers/media/platform/msm/cvp/hfi_packetization.c
Normal file
@ -0,0 +1,505 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "hfi_packetization.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
|
||||
/* Set up look-up tables to convert HAL_* to HFI_*.
|
||||
*
|
||||
* The tables below mostly take advantage of the fact that most
|
||||
* HAL_* types are defined bitwise. So if we index them normally
|
||||
* when declaring the tables, we end up with huge arrays with wasted
|
||||
* space. So before indexing them, we apply log2 to use a more
|
||||
* sensible index.
|
||||
*/
|
||||
|
||||
int cvp_create_pkt_cmd_sys_init(struct cvp_hfi_cmd_sys_init_packet *pkt,
|
||||
u32 arch_type)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!pkt)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->packet_type = HFI_CMD_SYS_INIT;
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_init_packet);
|
||||
pkt->arch_type = arch_type;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_pc_prep(struct cvp_hfi_cmd_sys_pc_prep_packet *pkt)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!pkt)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->packet_type = HFI_CMD_SYS_PC_PREP;
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_pc_prep_packet);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_debug_config(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode)
|
||||
{
|
||||
struct cvp_hfi_debug_config *hfi;
|
||||
|
||||
if (!pkt)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_property_packet) +
|
||||
sizeof(struct cvp_hfi_debug_config) + sizeof(u32);
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_DEBUG_CONFIG;
|
||||
hfi = (struct cvp_hfi_debug_config *) &pkt->rg_property_data[1];
|
||||
hfi->debug_config = mode;
|
||||
hfi->debug_mode = HFI_DEBUG_MODE_QUEUE;
|
||||
if (msm_cvp_fw_debug_mode
|
||||
<= (HFI_DEBUG_MODE_QUEUE | HFI_DEBUG_MODE_QDSS))
|
||||
hfi->debug_mode = msm_cvp_fw_debug_mode;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_coverage_config(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode)
|
||||
{
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "In %s(), No input packet\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_property_packet) +
|
||||
sizeof(u32);
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_CONFIG_COVERAGE;
|
||||
pkt->rg_property_data[1] = mode;
|
||||
dprintk(CVP_DBG, "Firmware coverage mode %d\n",
|
||||
pkt->rg_property_data[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_set_idle_indicator(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode)
|
||||
{
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "In %s(), No input packet\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_property_packet) +
|
||||
sizeof(u32);
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IDLE_INDICATOR;
|
||||
pkt->rg_property_data[1] = mode;
|
||||
dprintk(CVP_DBG, "Firmware idle indicator mode %d\n",
|
||||
pkt->rg_property_data[1]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_set_resource(
|
||||
struct cvp_hfi_cmd_sys_set_resource_packet *pkt,
|
||||
struct cvp_resource_hdr *res_hdr,
|
||||
void *res_value)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 i = 0;
|
||||
|
||||
if (!pkt || !res_hdr || !res_value) {
|
||||
dprintk(CVP_ERR,
|
||||
"Invalid paramas pkt %pK res_hdr %pK res_value %pK\n",
|
||||
pkt, res_hdr, res_value);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_RESOURCE;
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_resource_packet);
|
||||
pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
|
||||
|
||||
switch (res_hdr->resource_id) {
|
||||
case CVP_RESOURCE_SYSCACHE:
|
||||
{
|
||||
struct cvp_hfi_resource_syscache_info_type *res_sc_info =
|
||||
(struct cvp_hfi_resource_syscache_info_type *)res_value;
|
||||
struct cvp_hfi_resource_subcache_type *res_sc =
|
||||
(struct cvp_hfi_resource_subcache_type *)
|
||||
&(res_sc_info->rg_subcache_entries[0]);
|
||||
|
||||
struct cvp_hfi_resource_syscache_info_type *hfi_sc_info =
|
||||
(struct cvp_hfi_resource_syscache_info_type *)
|
||||
&pkt->rg_resource_data[0];
|
||||
|
||||
struct cvp_hfi_resource_subcache_type *hfi_sc =
|
||||
(struct cvp_hfi_resource_subcache_type *)
|
||||
&(hfi_sc_info->rg_subcache_entries[0]);
|
||||
|
||||
pkt->resource_type = HFI_RESOURCE_SYSCACHE;
|
||||
hfi_sc_info->num_entries = res_sc_info->num_entries;
|
||||
|
||||
pkt->size += (sizeof(struct cvp_hfi_resource_subcache_type))
|
||||
* hfi_sc_info->num_entries;
|
||||
|
||||
for (i = 0; i < hfi_sc_info->num_entries; i++) {
|
||||
hfi_sc[i] = res_sc[i];
|
||||
dprintk(CVP_DBG, "entry hfi#%d, sc_id %d, size %d\n",
|
||||
i, hfi_sc[i].sc_id, hfi_sc[i].size);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dprintk(CVP_ERR,
|
||||
"Invalid resource_id %d\n", res_hdr->resource_id);
|
||||
rc = -ENOTSUPP;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_release_resource(
|
||||
struct cvp_hfi_cmd_sys_release_resource_packet *pkt,
|
||||
struct cvp_resource_hdr *res_hdr)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!pkt || !res_hdr) {
|
||||
dprintk(CVP_ERR,
|
||||
"Invalid paramas pkt %pK res_hdr %pK\n",
|
||||
pkt, res_hdr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_release_resource_packet);
|
||||
pkt->packet_type = HFI_CMD_SYS_RELEASE_RESOURCE;
|
||||
pkt->resource_handle = hash32_ptr(res_hdr->resource_handle);
|
||||
|
||||
switch (res_hdr->resource_id) {
|
||||
case CVP_RESOURCE_SYSCACHE:
|
||||
pkt->resource_type = HFI_RESOURCE_SYSCACHE;
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR,
|
||||
"Invalid resource_id %d\n", res_hdr->resource_id);
|
||||
rc = -ENOTSUPP;
|
||||
}
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"rel_res: pkt_type 0x%x res_type 0x%x prepared\n",
|
||||
pkt->packet_type, pkt->resource_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
inline int cvp_create_pkt_cmd_sys_session_init(
|
||||
struct cvp_hfi_cmd_sys_session_init_packet *pkt,
|
||||
struct cvp_hal_session *session)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_inst *inst = session->session_id;
|
||||
|
||||
if (!pkt || !inst)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_session_init_packet);
|
||||
pkt->packet_type = HFI_CMD_SYS_SESSION_INIT;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
pkt->session_type = inst->prop.type;
|
||||
pkt->session_kmask = inst->prop.kernel_mask;
|
||||
pkt->session_prio = inst->prop.priority;
|
||||
pkt->is_secure = inst->prop.is_secure;
|
||||
pkt->dsp_ac_mask = inst->prop.dsp_mask;
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int create_pkt_cmd_sys_ubwc_config(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
struct msm_cvp_ubwc_config_data *ubwc_config)
|
||||
{
|
||||
int rc = 0;
|
||||
struct cvp_hfi_cmd_sys_set_ubwc_config_packet_type *hfi;
|
||||
|
||||
if (!pkt)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_property_packet) +
|
||||
sizeof(struct cvp_hfi_cmd_sys_set_ubwc_config_packet_type)
|
||||
+ sizeof(u32);
|
||||
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_UBWC_CONFIG;
|
||||
hfi = (struct cvp_hfi_cmd_sys_set_ubwc_config_packet_type *)
|
||||
&pkt->rg_property_data[1];
|
||||
|
||||
hfi->max_channels = ubwc_config->max_channels;
|
||||
hfi->override_bit_info.max_channel_override =
|
||||
ubwc_config->override_bit_info.max_channel_override;
|
||||
|
||||
hfi->mal_length = ubwc_config->mal_length;
|
||||
hfi->override_bit_info.mal_length_override =
|
||||
ubwc_config->override_bit_info.mal_length_override;
|
||||
|
||||
hfi->highest_bank_bit = ubwc_config->highest_bank_bit;
|
||||
hfi->override_bit_info.hb_override =
|
||||
ubwc_config->override_bit_info.hb_override;
|
||||
|
||||
hfi->bank_swzl_level = ubwc_config->bank_swzl_level;
|
||||
hfi->override_bit_info.bank_swzl_level_override =
|
||||
ubwc_config->override_bit_info.bank_swzl_level_override;
|
||||
|
||||
hfi->bank_spreading = ubwc_config->bank_spreading;
|
||||
hfi->override_bit_info.bank_spreading_override =
|
||||
ubwc_config->override_bit_info.bank_spreading_override;
|
||||
hfi->size = sizeof(struct cvp_hfi_cmd_sys_set_ubwc_config_packet_type);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_session_cmd(struct cvp_hal_session_cmd_pkt *pkt,
|
||||
int pkt_type, struct cvp_hal_session *session)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!pkt)
|
||||
return -EINVAL;
|
||||
|
||||
pkt->size = sizeof(struct cvp_hal_session_cmd_pkt);
|
||||
pkt->packet_type = pkt_type;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_power_control(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt, u32 enable)
|
||||
{
|
||||
struct cvp_hfi_enable *hfi;
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "No input packet\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_set_property_packet) +
|
||||
sizeof(struct cvp_hfi_enable) + sizeof(u32);
|
||||
pkt->packet_type = HFI_CMD_SYS_SET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_CODEC_POWER_PLANE_CTRL;
|
||||
hfi = (struct cvp_hfi_enable *) &pkt->rg_property_data[1];
|
||||
hfi->enable = enable;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_session_set_buffers(
|
||||
void *cmd,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_buffer_addr_info *buffer_info)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned int ver;
|
||||
|
||||
ver = get_hfi_version();
|
||||
ver = (ver & HFI_VERSION_MINOR_MASK) >> HFI_VERSION_MINOR_SHIFT;
|
||||
|
||||
if (!cmd || !session)
|
||||
return -EINVAL;
|
||||
|
||||
if (ver < 1) {
|
||||
struct cvp_hfi_cmd_session_set_buffers_packet_d *pkt;
|
||||
|
||||
pkt = (struct cvp_hfi_cmd_session_set_buffers_packet_d *)cmd;
|
||||
pkt->packet_type = HFI_CMD_SESSION_CVP_SET_BUFFERS;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
pkt->buffer_addr = buffer_info->align_device_addr;
|
||||
pkt->buffer_size = buffer_info->buffer_size;
|
||||
pkt->size =
|
||||
sizeof(struct cvp_hfi_cmd_session_set_buffers_packet_d);
|
||||
} else {
|
||||
struct cvp_hfi_cmd_session_set_buffers_packet *pkt;
|
||||
|
||||
pkt = (struct cvp_hfi_cmd_session_set_buffers_packet *)cmd;
|
||||
pkt->packet_type = HFI_CMD_SESSION_CVP_SET_BUFFERS;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
pkt->buf_type.fd = buffer_info->align_device_addr;
|
||||
pkt->buf_type.size = buffer_info->buffer_size;
|
||||
pkt->size =
|
||||
sizeof(struct cvp_hfi_cmd_session_set_buffers_packet);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_session_release_buffers(
|
||||
void *cmd,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_buffer_addr_info *buffer_info)
|
||||
{
|
||||
unsigned int ver;
|
||||
|
||||
ver = get_hfi_version();
|
||||
ver = (ver & HFI_VERSION_MINOR_MASK) >> HFI_VERSION_MINOR_SHIFT;
|
||||
|
||||
if (!cmd || !session)
|
||||
return -EINVAL;
|
||||
|
||||
if (ver < 1) {
|
||||
struct cvp_session_release_buffers_packet_d *pkt;
|
||||
|
||||
pkt = (struct cvp_session_release_buffers_packet_d *)cmd;
|
||||
pkt->packet_type = HFI_CMD_SESSION_CVP_RELEASE_BUFFERS;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
pkt->num_buffers = buffer_info->num_buffers;
|
||||
pkt->buffer_type = buffer_info->buffer_type;
|
||||
pkt->size =
|
||||
sizeof(struct cvp_session_release_buffers_packet_d) +
|
||||
((buffer_info->num_buffers - 1) * sizeof(u32));
|
||||
} else {
|
||||
struct cvp_session_release_buffers_packet *pkt;
|
||||
|
||||
pkt = (struct cvp_session_release_buffers_packet *)cmd;
|
||||
pkt->packet_type = HFI_CMD_SESSION_CVP_RELEASE_BUFFERS;
|
||||
pkt->session_id = hash32_ptr(session);
|
||||
pkt->num_buffers = buffer_info->num_buffers;
|
||||
pkt->buffer_type = buffer_info->buffer_type;
|
||||
pkt->size =
|
||||
sizeof(struct cvp_session_release_buffers_packet) +
|
||||
((buffer_info->num_buffers - 1) * sizeof(u32));
|
||||
}
|
||||
|
||||
if (buffer_info->buffer_type == HAL_BUFFER_OUTPUT ||
|
||||
buffer_info->buffer_type == HAL_BUFFER_OUTPUT2) {
|
||||
dprintk(CVP_ERR, "%s: deprecated buffer_type\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_session_send(
|
||||
struct cvp_kmd_hfi_packet *out_pkt,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_kmd_hfi_packet *in_pkt)
|
||||
{
|
||||
int def_idx;
|
||||
struct cvp_hal_session_cmd_pkt *ptr =
|
||||
(struct cvp_hal_session_cmd_pkt *)in_pkt;
|
||||
|
||||
if (!out_pkt || !in_pkt || !session)
|
||||
return -EINVAL;
|
||||
|
||||
if (ptr->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int))
|
||||
goto error_hfi_packet;
|
||||
|
||||
if (ptr->session_id != hash32_ptr(session))
|
||||
goto error_hfi_packet;
|
||||
|
||||
def_idx = get_pkt_index(ptr);
|
||||
if (def_idx < 0) {
|
||||
memcpy(out_pkt, in_pkt, ptr->size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (cvp_hfi_defs[def_idx].type != ptr->packet_type)
|
||||
goto error_hfi_packet;
|
||||
|
||||
memcpy(out_pkt, in_pkt, ptr->size);
|
||||
|
||||
return 0;
|
||||
|
||||
error_hfi_packet:
|
||||
dprintk(CVP_ERR, "%s incorrect packet: size=%d type=%d sessionid=%d\n",
|
||||
__func__, ptr->size, ptr->packet_type, ptr->session_id);
|
||||
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static int get_hfi_ssr_type(enum hal_ssr_trigger_type type)
|
||||
{
|
||||
int rc = HFI_TEST_SSR_HW_WDOG_IRQ;
|
||||
|
||||
switch (type) {
|
||||
case SSR_ERR_FATAL:
|
||||
rc = HFI_TEST_SSR_SW_ERR_FATAL;
|
||||
break;
|
||||
case SSR_SW_DIV_BY_ZERO:
|
||||
rc = HFI_TEST_SSR_SW_DIV_BY_ZERO;
|
||||
break;
|
||||
case SSR_HW_WDOG_IRQ:
|
||||
rc = HFI_TEST_SSR_HW_WDOG_IRQ;
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_WARN,
|
||||
"SSR trigger type not recognized, using WDOG.\n");
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_ssr_cmd(enum hal_ssr_trigger_type type,
|
||||
struct cvp_hfi_cmd_sys_test_ssr_packet *pkt)
|
||||
{
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "Invalid params, device: %pK\n", pkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_test_ssr_packet);
|
||||
pkt->packet_type = HFI_CMD_SYS_TEST_SSR;
|
||||
pkt->trigger_type = get_hfi_ssr_type(type);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_create_pkt_cmd_sys_image_version(
|
||||
struct cvp_hfi_cmd_sys_get_property_packet *pkt)
|
||||
{
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s invalid param :%pK\n", __func__, pkt);
|
||||
return -EINVAL;
|
||||
}
|
||||
pkt->size = sizeof(struct cvp_hfi_cmd_sys_get_property_packet);
|
||||
pkt->packet_type = HFI_CMD_SYS_GET_PROPERTY;
|
||||
pkt->num_properties = 1;
|
||||
pkt->rg_property_data[0] = HFI_PROPERTY_SYS_IMAGE_VERSION;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct cvp_hfi_packetization_ops hfi_default = {
|
||||
.sys_init = cvp_create_pkt_cmd_sys_init,
|
||||
.sys_pc_prep = cvp_create_pkt_cmd_sys_pc_prep,
|
||||
.sys_power_control = cvp_create_pkt_cmd_sys_power_control,
|
||||
.sys_set_resource = cvp_create_pkt_cmd_sys_set_resource,
|
||||
.sys_debug_config = cvp_create_pkt_cmd_sys_debug_config,
|
||||
.sys_coverage_config = cvp_create_pkt_cmd_sys_coverage_config,
|
||||
.sys_set_idle_indicator = cvp_create_pkt_cmd_sys_set_idle_indicator,
|
||||
.sys_release_resource = cvp_create_pkt_cmd_sys_release_resource,
|
||||
.sys_image_version = cvp_create_pkt_cmd_sys_image_version,
|
||||
.sys_ubwc_config = create_pkt_cmd_sys_ubwc_config,
|
||||
.ssr_cmd = cvp_create_pkt_ssr_cmd,
|
||||
.session_init = cvp_create_pkt_cmd_sys_session_init,
|
||||
.session_cmd = cvp_create_pkt_cmd_session_cmd,
|
||||
.session_set_buffers =
|
||||
cvp_create_pkt_cmd_session_set_buffers,
|
||||
.session_release_buffers =
|
||||
cvp_create_pkt_cmd_session_release_buffers,
|
||||
.session_send = cvp_create_pkt_cmd_session_send,
|
||||
};
|
||||
|
||||
struct cvp_hfi_packetization_ops *cvp_hfi_get_pkt_ops_handle(
|
||||
enum hfi_packetization_type type)
|
||||
{
|
||||
dprintk(CVP_DBG, "%s selected\n",
|
||||
type == HFI_PACKETIZATION_4XX ?
|
||||
"4xx packetization" : "Unknown hfi");
|
||||
|
||||
switch (type) {
|
||||
case HFI_PACKETIZATION_4XX:
|
||||
return &hfi_default;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
77
drivers/media/platform/msm/cvp/hfi_packetization.h
Normal file
77
drivers/media/platform/msm/cvp/hfi_packetization.h
Normal file
@ -0,0 +1,77 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __HFI_PACKETIZATION__
|
||||
#define __HFI_PACKETIZATION__
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "cvp_hfi_helper.h"
|
||||
#include "cvp_hfi.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
|
||||
#define call_hfi_pkt_op(q, op, ...) \
|
||||
(((q) && (q)->pkt_ops && (q)->pkt_ops->op) ? \
|
||||
((q)->pkt_ops->op(__VA_ARGS__)) : 0)
|
||||
|
||||
enum hfi_packetization_type {
|
||||
HFI_PACKETIZATION_4XX,
|
||||
};
|
||||
|
||||
struct cvp_hfi_packetization_ops {
|
||||
int (*sys_init)(struct cvp_hfi_cmd_sys_init_packet *pkt, u32 arch_type);
|
||||
int (*sys_pc_prep)(struct cvp_hfi_cmd_sys_pc_prep_packet *pkt);
|
||||
int (*sys_power_control)(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 enable);
|
||||
int (*sys_set_resource)(
|
||||
struct cvp_hfi_cmd_sys_set_resource_packet *pkt,
|
||||
struct cvp_resource_hdr *resource_hdr,
|
||||
void *resource_value);
|
||||
int (*sys_debug_config)(struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode);
|
||||
int (*sys_coverage_config)(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode);
|
||||
int (*sys_set_idle_indicator)(
|
||||
struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
u32 mode);
|
||||
int (*sys_release_resource)(
|
||||
struct cvp_hfi_cmd_sys_release_resource_packet *pkt,
|
||||
struct cvp_resource_hdr *resource_hdr);
|
||||
int (*sys_image_version)(
|
||||
struct cvp_hfi_cmd_sys_get_property_packet *pkt);
|
||||
int (*sys_ubwc_config)(struct cvp_hfi_cmd_sys_set_property_packet *pkt,
|
||||
struct msm_cvp_ubwc_config_data *ubwc_config);
|
||||
int (*ssr_cmd)(enum hal_ssr_trigger_type type,
|
||||
struct cvp_hfi_cmd_sys_test_ssr_packet *pkt);
|
||||
int (*session_init)(
|
||||
struct cvp_hfi_cmd_sys_session_init_packet *pkt,
|
||||
struct cvp_hal_session *session);
|
||||
int (*session_cmd)(struct cvp_hal_session_cmd_pkt *pkt,
|
||||
int pkt_type, struct cvp_hal_session *session);
|
||||
int (*session_set_buffers)(
|
||||
void *pkt,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_buffer_addr_info *buffer_info);
|
||||
int (*session_release_buffers)(
|
||||
void *pkt,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_buffer_addr_info *buffer_info);
|
||||
int (*session_get_buf_req)(
|
||||
struct cvp_hfi_cmd_session_get_property_packet *pkt,
|
||||
struct cvp_hal_session *session);
|
||||
int (*session_flush)(struct cvp_hfi_cmd_session_flush_packet *pkt,
|
||||
struct cvp_hal_session *session, enum hal_flush flush_mode);
|
||||
int (*session_sync_process)(
|
||||
struct cvp_hfi_cmd_session_sync_process_packet *pkt,
|
||||
struct cvp_hal_session *session);
|
||||
int (*session_send)(
|
||||
struct cvp_kmd_hfi_packet *out_pkt,
|
||||
struct cvp_hal_session *session,
|
||||
struct cvp_kmd_hfi_packet *in_pkt);
|
||||
};
|
||||
|
||||
struct cvp_hfi_packetization_ops *cvp_hfi_get_pkt_ops_handle(
|
||||
enum hfi_packetization_type);
|
||||
#endif
|
760
drivers/media/platform/msm/cvp/hfi_response_handler.c
Normal file
760
drivers/media/platform/msm/cvp/hfi_response_handler.c
Normal file
@ -0,0 +1,760 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/bitops.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/hash.h>
|
||||
#include <linux/soc/qcom/smem.h>
|
||||
#include "cvp_hfi_helper.h"
|
||||
#include "cvp_hfi_io.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "cvp_hfi.h"
|
||||
#include "msm_cvp_common.h"
|
||||
|
||||
extern struct msm_cvp_drv *cvp_driver;
|
||||
|
||||
static int _deprecated_hfi_msg_process(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info,
|
||||
struct msm_cvp_inst *inst);
|
||||
|
||||
static enum cvp_status hfi_map_err_status(u32 hfi_err)
|
||||
{
|
||||
enum cvp_status cvp_err;
|
||||
|
||||
switch (hfi_err) {
|
||||
case HFI_ERR_NONE:
|
||||
cvp_err = CVP_ERR_NONE;
|
||||
break;
|
||||
case HFI_ERR_SYS_FATAL:
|
||||
cvp_err = CVP_ERR_HW_FATAL;
|
||||
break;
|
||||
case HFI_ERR_SYS_NOC_ERROR:
|
||||
cvp_err = CVP_ERR_NOC_ERROR;
|
||||
break;
|
||||
case HFI_ERR_SYS_VERSION_MISMATCH:
|
||||
case HFI_ERR_SYS_INVALID_PARAMETER:
|
||||
case HFI_ERR_SYS_SESSION_ID_OUT_OF_RANGE:
|
||||
case HFI_ERR_SESSION_INVALID_PARAMETER:
|
||||
case HFI_ERR_SESSION_INVALID_SESSION_ID:
|
||||
case HFI_ERR_SESSION_INVALID_STREAM_ID:
|
||||
cvp_err = CVP_ERR_BAD_PARAM;
|
||||
break;
|
||||
case HFI_ERR_SYS_INSUFFICIENT_RESOURCES:
|
||||
case HFI_ERR_SYS_UNSUPPORTED_DOMAIN:
|
||||
case HFI_ERR_SYS_UNSUPPORTED_CODEC:
|
||||
case HFI_ERR_SESSION_UNSUPPORTED_PROPERTY:
|
||||
case HFI_ERR_SESSION_UNSUPPORTED_SETTING:
|
||||
case HFI_ERR_SESSION_INSUFFICIENT_RESOURCES:
|
||||
case HFI_ERR_SESSION_UNSUPPORTED_STREAM:
|
||||
cvp_err = CVP_ERR_NOT_SUPPORTED;
|
||||
break;
|
||||
case HFI_ERR_SYS_MAX_SESSIONS_REACHED:
|
||||
cvp_err = CVP_ERR_MAX_CLIENTS;
|
||||
break;
|
||||
case HFI_ERR_SYS_SESSION_IN_USE:
|
||||
cvp_err = CVP_ERR_CLIENT_PRESENT;
|
||||
break;
|
||||
case HFI_ERR_SESSION_FATAL:
|
||||
cvp_err = CVP_ERR_CLIENT_FATAL;
|
||||
break;
|
||||
case HFI_ERR_SESSION_BAD_POINTER:
|
||||
cvp_err = CVP_ERR_BAD_PARAM;
|
||||
break;
|
||||
case HFI_ERR_SESSION_INCORRECT_STATE_OPERATION:
|
||||
cvp_err = CVP_ERR_BAD_STATE;
|
||||
break;
|
||||
default:
|
||||
cvp_err = CVP_ERR_FAIL;
|
||||
break;
|
||||
}
|
||||
return cvp_err;
|
||||
}
|
||||
|
||||
static int hfi_process_sys_error(u32 device_id,
|
||||
struct cvp_hfi_msg_event_notify_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
||||
|
||||
info->response_type = HAL_SYS_ERROR;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_error(u32 device_id,
|
||||
struct cvp_hfi_msg_event_notify_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
||||
cmd_done.status = hfi_map_err_status(pkt->event_data1);
|
||||
info->response.cmd = cmd_done;
|
||||
dprintk(CVP_INFO, "Received: SESSION_ERROR with event id : %#x %#x\n",
|
||||
pkt->event_data1, pkt->event_data2);
|
||||
switch (pkt->event_data1) {
|
||||
/* Ignore below errors */
|
||||
case HFI_ERR_SESSION_INVALID_SCALE_FACTOR:
|
||||
case HFI_ERR_SESSION_UPSCALE_NOT_SUPPORTED:
|
||||
dprintk(CVP_INFO, "Non Fatal: HFI_EVENT_SESSION_ERROR\n");
|
||||
info->response_type = HAL_RESPONSE_UNUSED;
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR,
|
||||
"%s: session %x data1 %#x, data2 %#x\n", __func__,
|
||||
pkt->session_id, pkt->event_data1, pkt->event_data2);
|
||||
info->response_type = HAL_RESPONSE_UNUSED;
|
||||
break;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_event_notify(u32 device_id,
|
||||
struct cvp_hfi_msg_event_notify_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
dprintk(CVP_DBG, "Received: EVENT_NOTIFY\n");
|
||||
|
||||
if (pkt->size < sizeof(struct cvp_hfi_msg_event_notify_packet)) {
|
||||
dprintk(CVP_ERR, "Invalid Params\n");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
switch (pkt->event_id) {
|
||||
case HFI_EVENT_SYS_ERROR:
|
||||
dprintk(CVP_ERR, "HFI_EVENT_SYS_ERROR: %d, %#x\n",
|
||||
pkt->event_data1, pkt->event_data2);
|
||||
return hfi_process_sys_error(device_id, pkt, info);
|
||||
|
||||
case HFI_EVENT_SESSION_ERROR:
|
||||
dprintk(CVP_INFO, "HFI_EVENT_SESSION_ERROR[%#x]\n",
|
||||
pkt->session_id);
|
||||
return hfi_process_session_error(device_id, pkt, info);
|
||||
|
||||
default:
|
||||
*info = (struct msm_cvp_cb_info) {
|
||||
.response_type = HAL_RESPONSE_UNUSED,
|
||||
};
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int hfi_process_sys_init_done(u32 device_id,
|
||||
struct cvp_hfi_msg_sys_init_done_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
enum cvp_status status = CVP_ERR_NONE;
|
||||
|
||||
dprintk(CVP_DBG, "RECEIVED: SYS_INIT_DONE\n");
|
||||
if (sizeof(struct cvp_hfi_msg_sys_init_done_packet) > pkt->size) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt_size: %d\n", __func__,
|
||||
pkt->size);
|
||||
return -E2BIG;
|
||||
}
|
||||
if (!pkt->num_properties) {
|
||||
dprintk(CVP_DBG,
|
||||
"hal_process_sys_init_done: no_properties\n");
|
||||
goto err_no_prop;
|
||||
}
|
||||
|
||||
status = hfi_map_err_status(pkt->error_type);
|
||||
if (status) {
|
||||
dprintk(CVP_ERR, "%s: status %#x\n",
|
||||
__func__, status);
|
||||
goto err_no_prop;
|
||||
}
|
||||
|
||||
err_no_prop:
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = NULL;
|
||||
cmd_done.status = (u32)status;
|
||||
cmd_done.size = sizeof(struct cvp_hal_sys_init_done);
|
||||
|
||||
info->response_type = HAL_SYS_INIT_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum cvp_status cvp_hfi_process_sys_init_done_prop_read(
|
||||
struct cvp_hfi_msg_sys_init_done_packet *pkt,
|
||||
struct cvp_hal_sys_init_done *sys_init_done)
|
||||
{
|
||||
enum cvp_status status = CVP_ERR_NONE;
|
||||
u32 rem_bytes, num_properties;
|
||||
u8 *data_ptr;
|
||||
|
||||
if (!pkt || !sys_init_done) {
|
||||
dprintk(CVP_ERR,
|
||||
"hfi_msg_sys_init_done: Invalid input\n");
|
||||
return CVP_ERR_FAIL;
|
||||
}
|
||||
|
||||
rem_bytes = pkt->size - sizeof(struct
|
||||
cvp_hfi_msg_sys_init_done_packet) + sizeof(u32);
|
||||
|
||||
if (!rem_bytes) {
|
||||
dprintk(CVP_ERR,
|
||||
"hfi_msg_sys_init_done: missing_prop_info\n");
|
||||
return CVP_ERR_FAIL;
|
||||
}
|
||||
|
||||
status = hfi_map_err_status(pkt->error_type);
|
||||
if (status) {
|
||||
dprintk(CVP_ERR, "%s: status %#x\n", __func__, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
data_ptr = (u8 *) &pkt->rg_property_data[0];
|
||||
num_properties = pkt->num_properties;
|
||||
dprintk(CVP_DBG,
|
||||
"%s: data_start %pK, num_properties %#x\n",
|
||||
__func__, data_ptr, num_properties);
|
||||
|
||||
sys_init_done->capabilities = NULL;
|
||||
return status;
|
||||
}
|
||||
|
||||
static int hfi_process_session_init_done(u32 device_id,
|
||||
struct cvp_hfi_msg_sys_session_init_done_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
struct cvp_hal_session_init_done session_init_done = { {0} };
|
||||
|
||||
dprintk(CVP_DBG, "RECEIVED: SESSION_INIT_DONE[%x]\n", pkt->session_id);
|
||||
|
||||
if (sizeof(struct cvp_hfi_msg_sys_session_init_done_packet)
|
||||
> pkt->size) {
|
||||
dprintk(CVP_ERR,
|
||||
"hal_process_session_init_done: bad_pkt_size\n");
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
||||
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
||||
cmd_done.data.session_init_done = session_init_done;
|
||||
cmd_done.size = sizeof(struct cvp_hal_session_init_done);
|
||||
|
||||
info->response_type = HAL_SESSION_INIT_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
static int hfi_process_session_end_done(u32 device_id,
|
||||
struct cvp_hfi_msg_sys_session_end_done_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
dprintk(CVP_DBG, "RECEIVED: SESSION_END_DONE[%#x]\n", pkt->session_id);
|
||||
|
||||
if (!pkt || pkt->size !=
|
||||
sizeof(struct cvp_hfi_msg_sys_session_end_done_packet)) {
|
||||
dprintk(CVP_ERR, "%s: bad packet/packet size\n", __func__);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
||||
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
||||
cmd_done.size = 0;
|
||||
|
||||
info->response_type = HAL_SESSION_END_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_abort_done(u32 device_id,
|
||||
struct cvp_hfi_msg_sys_session_abort_done_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
dprintk(CVP_DBG, "RECEIVED: SESSION_ABORT_DONE[%#x]\n",
|
||||
pkt->session_id);
|
||||
|
||||
if (!pkt || pkt->size !=
|
||||
sizeof(struct cvp_hfi_msg_sys_session_abort_done_packet)) {
|
||||
dprintk(CVP_ERR, "%s: bad packet/packet size: %d\n",
|
||||
__func__, pkt ? pkt->size : 0);
|
||||
return -E2BIG;
|
||||
}
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)pkt->session_id;
|
||||
cmd_done.status = hfi_map_err_status(pkt->error_type);
|
||||
cmd_done.size = 0;
|
||||
|
||||
info->response_type = HAL_SESSION_ABORT_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_set_buf_done(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
unsigned int pkt_size = get_msg_size();
|
||||
|
||||
if (!pkt || pkt->size < pkt_size) {
|
||||
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
||||
pkt ? pkt->size : 0);
|
||||
return -E2BIG;
|
||||
}
|
||||
dprintk(CVP_DBG, "RECEIVED:CVP_SET_BUFFER_DONE[%#x]\n",
|
||||
pkt->session_id);
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
||||
cmd_done.size = 0;
|
||||
|
||||
info->response_type = HAL_SESSION_SET_BUFFER_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int hfi_process_session_rel_buf_done(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
unsigned int pkt_size = get_msg_size();
|
||||
|
||||
if (!pkt || pkt->size < pkt_size) {
|
||||
dprintk(CVP_ERR, "bad packet/packet size %d\n",
|
||||
pkt ? pkt->size : 0);
|
||||
return -E2BIG;
|
||||
}
|
||||
dprintk(CVP_DBG, "RECEIVED:CVP_RELEASE_BUFFER_DONE[%#x]\n",
|
||||
pkt->session_id);
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
||||
cmd_done.size = 0;
|
||||
|
||||
info->response_type = HAL_SESSION_RELEASE_BUFFER_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_cvp_operation_config(u32 device_id,
|
||||
struct cvp_hfi_msg_session_op_cfg_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
int signal;
|
||||
unsigned int conf_id, session_id, error_type;
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size < get_msg_size()) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: bad_pkt_size\n", __func__);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
get_msg_opconfigs(pkt, &session_id, &error_type, &conf_id);
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)session_id;
|
||||
cmd_done.status = hfi_map_err_status(error_type);
|
||||
cmd_done.size = 0;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: device_id=%d status=%d, sessionid=%pK config=%x\n",
|
||||
__func__, device_id, cmd_done.status,
|
||||
cmd_done.session_id, pkt->op_conf_id);
|
||||
|
||||
if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS)
|
||||
signal = get_signal_from_pkt_type(
|
||||
HFI_CMD_SESSION_CVP_SET_PERSIST_BUFFERS);
|
||||
else if (pkt->packet_type == HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS)
|
||||
signal = get_signal_from_pkt_type(
|
||||
HFI_CMD_SESSION_CVP_SET_MODEL_BUFFERS);
|
||||
else
|
||||
signal = get_signal_from_pkt_type(conf_id);
|
||||
|
||||
if (signal < 0) {
|
||||
dprintk(CVP_ERR, "%s Invalid op config id\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
info->response_type = signal;
|
||||
info->response.cmd = cmd_done;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct msm_cvp_inst *cvp_get_inst_from_id(struct msm_cvp_core *core,
|
||||
unsigned int session_id)
|
||||
{
|
||||
struct msm_cvp_inst *inst = NULL;
|
||||
bool match = false;
|
||||
int count = 0;
|
||||
|
||||
if (!core || !session_id)
|
||||
return NULL;
|
||||
|
||||
retry:
|
||||
if (mutex_trylock(&core->lock)) {
|
||||
list_for_each_entry(inst, &core->instances, list) {
|
||||
if (hash32_ptr(inst->session) == session_id) {
|
||||
match = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
inst = match ? inst : NULL;
|
||||
mutex_unlock(&core->lock);
|
||||
} else {
|
||||
if (core->state == CVP_CORE_UNINIT)
|
||||
return NULL;
|
||||
usleep_range(100, 200);
|
||||
count++;
|
||||
if (count < 1000)
|
||||
goto retry;
|
||||
else
|
||||
dprintk(CVP_ERR, "timeout locking core mutex\n");
|
||||
}
|
||||
|
||||
return inst;
|
||||
|
||||
}
|
||||
|
||||
static int hfi_process_session_cvp_msg(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct cvp_session_msg *sess_msg;
|
||||
struct msm_cvp_inst *inst = NULL;
|
||||
struct msm_cvp_core *core;
|
||||
void *session_id;
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size > MAX_HFI_PKT_SIZE * sizeof(unsigned int)) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
|
||||
return -E2BIG;
|
||||
}
|
||||
session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||
inst = cvp_get_inst_from_id(core, (unsigned int)session_id);
|
||||
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "%s: invalid session\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (inst->deprecate_bitmask) {
|
||||
if (pkt->packet_type == HFI_MSG_SESSION_CVP_DME
|
||||
|| pkt->packet_type == HFI_MSG_SESSION_CVP_ICA
|
||||
|| pkt->packet_type == HFI_MSG_SESSION_CVP_FD) {
|
||||
u64 ktid;
|
||||
u32 kdata1, kdata2;
|
||||
|
||||
kdata1 = pkt->client_data.kdata1;
|
||||
kdata2 = pkt->client_data.kdata2;
|
||||
ktid = ((u64)kdata2 << 32) | kdata1;
|
||||
msm_cvp_unmap_buf_cpu(inst, ktid);
|
||||
|
||||
return _deprecated_hfi_msg_process(device_id,
|
||||
pkt, info, inst);
|
||||
}
|
||||
dprintk(CVP_ERR, "Invalid deprecate_bitmask %#x\n",
|
||||
inst->deprecate_bitmask);
|
||||
}
|
||||
|
||||
sess_msg = kmem_cache_alloc(cvp_driver->msg_cache, GFP_KERNEL);
|
||||
if (sess_msg == NULL) {
|
||||
dprintk(CVP_ERR, "%s runs out msg cache memory\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
memcpy(&sess_msg->pkt, pkt, get_msg_size());
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: Received msg %x cmd_done.status=%d sessionid=%x\n",
|
||||
__func__, pkt->packet_type,
|
||||
hfi_map_err_status(get_msg_errorcode(pkt)), session_id);
|
||||
|
||||
spin_lock(&inst->session_queue.lock);
|
||||
if (inst->session_queue.msg_count >= MAX_NUM_MSGS_PER_SESSION) {
|
||||
dprintk(CVP_ERR, "Reached session queue size limit\n");
|
||||
goto error_handle_msg;
|
||||
}
|
||||
list_add_tail(&sess_msg->node, &inst->session_queue.msgs);
|
||||
inst->session_queue.msg_count++;
|
||||
spin_unlock(&inst->session_queue.lock);
|
||||
|
||||
wake_up_all(&inst->session_queue.wq);
|
||||
|
||||
info->response_type = HAL_NO_RESP;
|
||||
|
||||
return 0;
|
||||
|
||||
error_handle_msg:
|
||||
spin_unlock(&inst->session_queue.lock);
|
||||
kmem_cache_free(cvp_driver->msg_cache, sess_msg);
|
||||
return -ENOMEM;
|
||||
}
|
||||
|
||||
static int hfi_process_session_cvp_dme(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size < get_msg_size()) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
||||
cmd_done.size = 0;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: device_id=%d cmd_done.status=%d sessionid=%#x\n",
|
||||
__func__, device_id, cmd_done.status, cmd_done.session_id);
|
||||
info->response_type = HAL_SESSION_DME_FRAME_CMD_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_cvp_ica(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size < get_msg_size()) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
||||
cmd_done.size = 0;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: device_id=%d cmd_done.status=%d sessionid=%#x\n",
|
||||
__func__, device_id, cmd_done.status, cmd_done.session_id);
|
||||
info->response_type = HAL_SESSION_ICA_FRAME_CMD_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int hfi_process_session_cvp_fd(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
struct msm_cvp_cb_cmd_done cmd_done = {0};
|
||||
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size < get_msg_size()) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt_size %d\n", __func__, pkt->size);
|
||||
return -E2BIG;
|
||||
}
|
||||
|
||||
cmd_done.device_id = device_id;
|
||||
cmd_done.session_id = (void *)(uintptr_t)get_msg_session_id(pkt);
|
||||
cmd_done.status = hfi_map_err_status(get_msg_errorcode(pkt));
|
||||
cmd_done.size = 0;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: device_id=%d cmd_done.status=%d sessionid=%#x\n",
|
||||
__func__, device_id, cmd_done.status, cmd_done.session_id);
|
||||
info->response_type = HAL_SESSION_FD_FRAME_CMD_DONE;
|
||||
info->response.cmd = cmd_done;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _deprecated_hfi_msg_process(u32 device_id,
|
||||
struct cvp_hfi_msg_session_hdr *pkt,
|
||||
struct msm_cvp_cb_info *info,
|
||||
struct msm_cvp_inst *inst)
|
||||
{
|
||||
if (pkt->packet_type == HFI_MSG_SESSION_CVP_DME)
|
||||
if (test_bit(DME_BIT_OFFSET,
|
||||
&inst->deprecate_bitmask))
|
||||
return hfi_process_session_cvp_dme(
|
||||
device_id, (void *)pkt, info);
|
||||
|
||||
if (pkt->packet_type == HFI_MSG_SESSION_CVP_ICA)
|
||||
if (test_bit(ICA_BIT_OFFSET,
|
||||
&inst->deprecate_bitmask))
|
||||
return hfi_process_session_cvp_ica(
|
||||
device_id, (void *)pkt, info);
|
||||
|
||||
if (pkt->packet_type == HFI_MSG_SESSION_CVP_FD)
|
||||
if (test_bit(FD_BIT_OFFSET,
|
||||
&inst->deprecate_bitmask))
|
||||
return hfi_process_session_cvp_fd(
|
||||
device_id, (void *)pkt, info);
|
||||
|
||||
dprintk(CVP_ERR, "Deprecatd MSG doesn't match bitmask %x %lx\n",
|
||||
pkt->packet_type, inst->deprecate_bitmask);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void hfi_process_sys_get_prop_image_version(
|
||||
struct cvp_hfi_msg_sys_property_info_packet *pkt)
|
||||
{
|
||||
int i = 0;
|
||||
const u32 version_string_size = 128;
|
||||
u8 *str_image_version;
|
||||
int req_bytes;
|
||||
|
||||
req_bytes = pkt->size - sizeof(*pkt);
|
||||
if (req_bytes < version_string_size ||
|
||||
!pkt->rg_property_data[1] ||
|
||||
pkt->num_properties > 1) {
|
||||
dprintk(CVP_ERR, "%s: bad_pkt: %d\n", __func__, req_bytes);
|
||||
return;
|
||||
}
|
||||
str_image_version = (u8 *)&pkt->rg_property_data[1];
|
||||
/*
|
||||
* The version string returned by firmware includes null
|
||||
* characters at the start and in between. Replace the null
|
||||
* characters with space, to print the version info.
|
||||
*/
|
||||
for (i = 0; i < version_string_size; i++) {
|
||||
if (str_image_version[i] != '\0')
|
||||
cvp_driver->fw_version[i] = str_image_version[i];
|
||||
else
|
||||
cvp_driver->fw_version[i] = ' ';
|
||||
}
|
||||
cvp_driver->fw_version[i] = '\0';
|
||||
dprintk(CVP_DBG, "F/W version: %s\n", cvp_driver->fw_version);
|
||||
}
|
||||
|
||||
static int hfi_process_sys_property_info(u32 device_id,
|
||||
struct cvp_hfi_msg_sys_property_info_packet *pkt,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
if (!pkt) {
|
||||
dprintk(CVP_ERR, "%s: invalid param\n", __func__);
|
||||
return -EINVAL;
|
||||
} else if (pkt->size > sizeof(*pkt)) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: bad_pkt_size %d\n", __func__, pkt->size);
|
||||
return -E2BIG;
|
||||
} else if (!pkt->num_properties) {
|
||||
dprintk(CVP_WARN,
|
||||
"%s: no_properties\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (pkt->rg_property_data[0]) {
|
||||
case HFI_PROPERTY_SYS_IMAGE_VERSION:
|
||||
hfi_process_sys_get_prop_image_version(pkt);
|
||||
|
||||
*info = (struct msm_cvp_cb_info) {
|
||||
.response_type = HAL_RESPONSE_UNUSED,
|
||||
};
|
||||
return 0;
|
||||
default:
|
||||
dprintk(CVP_DBG,
|
||||
"%s: unknown_prop_id: %x\n",
|
||||
__func__, pkt->rg_property_data[0]);
|
||||
return -ENOTSUPP;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int cvp_hfi_process_msg_packet(u32 device_id,
|
||||
struct cvp_hal_msg_pkt_hdr *msg_hdr,
|
||||
struct msm_cvp_cb_info *info)
|
||||
{
|
||||
typedef int (*pkt_func_def)(u32, void *, struct msm_cvp_cb_info *info);
|
||||
pkt_func_def pkt_func = NULL;
|
||||
|
||||
if (!info || !msg_hdr || msg_hdr->size < CVP_IFACEQ_MIN_PKT_SIZE) {
|
||||
dprintk(CVP_ERR, "%s: bad packet/packet size\n",
|
||||
__func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dprintk(CVP_DBG, "Received HFI MSG with type %#x\n", msg_hdr->packet);
|
||||
switch (msg_hdr->packet) {
|
||||
case HFI_MSG_EVENT_NOTIFY:
|
||||
pkt_func = (pkt_func_def)hfi_process_event_notify;
|
||||
break;
|
||||
case HFI_MSG_SYS_INIT_DONE:
|
||||
pkt_func = (pkt_func_def)hfi_process_sys_init_done;
|
||||
break;
|
||||
case HFI_MSG_SYS_SESSION_INIT_DONE:
|
||||
pkt_func = (pkt_func_def)hfi_process_session_init_done;
|
||||
break;
|
||||
case HFI_MSG_SYS_PROPERTY_INFO:
|
||||
pkt_func = (pkt_func_def)hfi_process_sys_property_info;
|
||||
break;
|
||||
case HFI_MSG_SYS_SESSION_END_DONE:
|
||||
pkt_func = (pkt_func_def)hfi_process_session_end_done;
|
||||
break;
|
||||
case HFI_MSG_SESSION_CVP_SET_BUFFERS:
|
||||
pkt_func = (pkt_func_def) hfi_process_session_set_buf_done;
|
||||
break;
|
||||
case HFI_MSG_SESSION_CVP_RELEASE_BUFFERS:
|
||||
pkt_func = (pkt_func_def)hfi_process_session_rel_buf_done;
|
||||
break;
|
||||
case HFI_MSG_SYS_SESSION_ABORT_DONE:
|
||||
pkt_func = (pkt_func_def)hfi_process_session_abort_done;
|
||||
break;
|
||||
case HFI_MSG_SESSION_CVP_OPERATION_CONFIG:
|
||||
case HFI_MSG_SESSION_CVP_SET_PERSIST_BUFFERS:
|
||||
case HFI_MSG_SESSION_CVP_SET_MODEL_BUFFERS:
|
||||
pkt_func =
|
||||
(pkt_func_def)hfi_process_session_cvp_operation_config;
|
||||
break;
|
||||
case HFI_MSG_SESSION_CVP_DS:
|
||||
case HFI_MSG_SESSION_CVP_DFS:
|
||||
case HFI_MSG_SESSION_CVP_DME:
|
||||
case HFI_MSG_SESSION_CVP_FD:
|
||||
pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_DBG, "Use default msg handler: %#x\n",
|
||||
msg_hdr->packet);
|
||||
pkt_func = (pkt_func_def)hfi_process_session_cvp_msg;
|
||||
break;
|
||||
}
|
||||
|
||||
return pkt_func ?
|
||||
pkt_func(device_id, (void *)msg_hdr, info) : -ENOTSUPP;
|
||||
}
|
2398
drivers/media/platform/msm/cvp/msm_cvp.c
Normal file
2398
drivers/media/platform/msm/cvp/msm_cvp.c
Normal file
File diff suppressed because it is too large
Load Diff
17
drivers/media/platform/msm/cvp/msm_cvp.h
Normal file
17
drivers/media/platform/msm/cvp/msm_cvp.h
Normal file
@ -0,0 +1,17 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_CVP_H_
|
||||
#define _MSM_CVP_H_
|
||||
|
||||
#include "msm_cvp_internal.h"
|
||||
#include "msm_cvp_common.h"
|
||||
#include "msm_cvp_clocks.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp_dsp.h"
|
||||
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_deinit(struct msm_cvp_inst *inst);
|
||||
#endif
|
25
drivers/media/platform/msm/cvp/msm_cvp_clocks.c
Normal file
25
drivers/media/platform/msm/cvp/msm_cvp_clocks.c
Normal file
@ -0,0 +1,25 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "msm_cvp_common.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp_clocks.h"
|
||||
|
||||
int msm_cvp_set_clocks(struct msm_cvp_core *core)
|
||||
{
|
||||
struct cvp_hfi_device *hdev;
|
||||
int rc;
|
||||
|
||||
if (!core || !core->device) {
|
||||
dprintk(CVP_ERR, "%s Invalid args: %pK\n", __func__, core);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hdev = core->device;
|
||||
rc = call_hfi_op(hdev, scale_clocks,
|
||||
hdev->hfi_device_data, core->curr_freq);
|
||||
return rc;
|
||||
}
|
12
drivers/media/platform/msm/cvp/msm_cvp_clocks.h
Normal file
12
drivers/media/platform/msm/cvp/msm_cvp_clocks.h
Normal file
@ -0,0 +1,12 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MSM_CVP_CLOCKS_H_
|
||||
#define _MSM_CVP_CLOCKS_H_
|
||||
#include "msm_cvp_internal.h"
|
||||
|
||||
int msm_cvp_set_clocks(struct msm_cvp_core *core);
|
||||
#endif
|
1854
drivers/media/platform/msm/cvp/msm_cvp_common.c
Normal file
1854
drivers/media/platform/msm/cvp/msm_cvp_common.c
Normal file
File diff suppressed because it is too large
Load Diff
51
drivers/media/platform/msm/cvp/msm_cvp_common.h
Normal file
51
drivers/media/platform/msm/cvp/msm_cvp_common.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef _MSM_CVP_COMMON_H_
|
||||
#define _MSM_CVP_COMMON_H_
|
||||
#include "msm_cvp_internal.h"
|
||||
|
||||
enum load_calc_quirks {
|
||||
LOAD_CALC_NO_QUIRKS = 0,
|
||||
LOAD_CALC_IGNORE_TURBO_LOAD = 1 << 0,
|
||||
LOAD_CALC_IGNORE_THUMBNAIL_LOAD = 1 << 1,
|
||||
LOAD_CALC_IGNORE_NON_REALTIME_LOAD = 1 << 2,
|
||||
};
|
||||
|
||||
void cvp_put_inst(struct msm_cvp_inst *inst);
|
||||
struct msm_cvp_inst *cvp_get_inst(struct msm_cvp_core *core,
|
||||
void *session_id);
|
||||
struct msm_cvp_inst *cvp_get_inst_validate(struct msm_cvp_core *core,
|
||||
void *session_id);
|
||||
void cvp_change_inst_state(struct msm_cvp_inst *inst,
|
||||
enum instance_state state);
|
||||
struct msm_cvp_core *get_cvp_core(int core_id);
|
||||
int msm_cvp_comm_try_state(struct msm_cvp_inst *inst, int state);
|
||||
int msm_cvp_deinit_core(struct msm_cvp_inst *inst);
|
||||
int msm_cvp_comm_suspend(int core_id);
|
||||
void msm_cvp_comm_session_clean(struct msm_cvp_inst *inst);
|
||||
int msm_cvp_comm_kill_session(struct msm_cvp_inst *inst);
|
||||
void msm_cvp_comm_generate_session_error(struct msm_cvp_inst *inst);
|
||||
void msm_cvp_comm_generate_sys_error(struct msm_cvp_inst *inst);
|
||||
int msm_cvp_comm_smem_cache_operations(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_smem *mem, enum smem_cache_ops cache_ops);
|
||||
int msm_cvp_comm_check_core_init(struct msm_cvp_core *core);
|
||||
void msm_cvp_comm_print_inst_info(struct msm_cvp_inst *inst);
|
||||
int msm_cvp_comm_unmap_cvp_buffer(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_internal_buffer *cbuf);
|
||||
void print_cvp_buffer(u32 tag, const char *str,
|
||||
struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_internal_buffer *cbuf);
|
||||
int wait_for_sess_signal_receipt(struct msm_cvp_inst *inst,
|
||||
enum hal_command_response cmd);
|
||||
int wait_for_sess_signal_receipt_fence(struct msm_cvp_inst *inst,
|
||||
enum hal_command_response cmd);
|
||||
int cvp_comm_set_arp_buffers(struct msm_cvp_inst *inst);
|
||||
int cvp_comm_release_persist_buffers(struct msm_cvp_inst *inst);
|
||||
void print_client_buffer(u32 tag, const char *str,
|
||||
struct msm_cvp_inst *inst, struct cvp_kmd_buffer *cbuf);
|
||||
void msm_cvp_unmap_buf_cpu(struct msm_cvp_inst *inst, u64 ktid);
|
||||
#endif
|
454
drivers/media/platform/msm/cvp/msm_cvp_core.c
Normal file
454
drivers/media/platform/msm/cvp/msm_cvp_core.c
Normal file
@ -0,0 +1,454 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/sched.h>
|
||||
#include <linux/slab.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include "msm_cvp_internal.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp.h"
|
||||
#include "msm_cvp_common.h"
|
||||
#include <linux/delay.h>
|
||||
#include "cvp_hfi_api.h"
|
||||
#include "msm_cvp_clocks.h"
|
||||
#include <linux/dma-buf.h>
|
||||
#include <media/msm_media_info.h>
|
||||
|
||||
#define MAX_EVENTS 30
|
||||
#define NUM_CYCLES16X16_HCD_FRAME 95
|
||||
#define NUM_CYCLES16X16_DME_FRAME 600
|
||||
#define NUM_CYCLES16X16_NCC_FRAME 400
|
||||
#define NUM_CYCLES16X16_DS_FRAME 80
|
||||
#define NUM_CYCLESFW_FRAME 1680000
|
||||
#define NUM_DME_MAX_FEATURE_POINTS 500
|
||||
#define CYCLES_MARGIN_IN_POWEROF2 3
|
||||
|
||||
int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc,
|
||||
struct cvp_kmd_request_power *cvp_voting)
|
||||
{
|
||||
unsigned int cvp_cycles = 0;
|
||||
unsigned int hcd_cycles = 0;
|
||||
unsigned int dme_cycles = 0;
|
||||
unsigned int ds_cycles = 0;
|
||||
unsigned int ncc_cycles = 0;
|
||||
unsigned int num_16x16_blocks = 0;
|
||||
|
||||
unsigned int cvp_bw = 0;
|
||||
unsigned int ds_pixel_read = 0;
|
||||
unsigned int ds_pixel_write = 0;
|
||||
unsigned int hcd_pixel_read = 0;
|
||||
unsigned int hcd_stats_write = 0;
|
||||
unsigned int dme_pixel_read = 0;
|
||||
unsigned int ncc_pixel_read = 0;
|
||||
unsigned int process_width = 0;
|
||||
unsigned int process_height = 0;
|
||||
|
||||
if (!cvp_desc || !cvp_voting) {
|
||||
dprintk(CVP_ERR, "%s: invalid args\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cvp_desc->is_downscale) {
|
||||
num_16x16_blocks = (cvp_desc->fullres_width>>4)
|
||||
* (cvp_desc->fullres_height>>4);
|
||||
ds_cycles = NUM_CYCLES16X16_DS_FRAME * num_16x16_blocks;
|
||||
process_width = cvp_desc->downscale_width;
|
||||
process_height = cvp_desc->downscale_height;
|
||||
num_16x16_blocks = (process_width>>4)*(process_height>>4);
|
||||
hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks;
|
||||
/*Estimate downscale output (always UBWC) BW stats*/
|
||||
if (cvp_desc->fullres_width <= 1920) {
|
||||
/*w*h/1.58=w*h*(81/128)*/
|
||||
ds_pixel_write = ((process_width*process_height*81)>>7);
|
||||
} else {
|
||||
/*w*h/2.38=w*h*(54/128)*/
|
||||
ds_pixel_write = ((process_width*process_height*54)>>7);
|
||||
}
|
||||
/*Estimate downscale input BW stats based on colorfmt*/
|
||||
switch (cvp_desc->colorfmt) {
|
||||
case COLOR_FMT_NV12:
|
||||
{
|
||||
/*w*h*1.5*/
|
||||
ds_pixel_read = ((cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 3)>>1);
|
||||
break;
|
||||
}
|
||||
case COLOR_FMT_P010:
|
||||
{
|
||||
/*w*h*2*1.5*/
|
||||
ds_pixel_read = cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 3;
|
||||
break;
|
||||
}
|
||||
case COLOR_FMT_NV12_UBWC:
|
||||
{
|
||||
/*w*h*1.5/factor(factor=width>1920?2.38:1.58)*/
|
||||
if (cvp_desc->fullres_width <= 1920) {
|
||||
/*w*h*1.5/1.58 = w*h*121/128*/
|
||||
ds_pixel_read = ((cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 121)>>7);
|
||||
} else {
|
||||
/*w*h*1.5/1.61 = w*h*119/128*/
|
||||
ds_pixel_read = ((cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 119)>>7);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case COLOR_FMT_NV12_BPP10_UBWC:
|
||||
{
|
||||
/*w*h*1.33*1.5/factor(factor=width>1920?2.38:1.58)*/
|
||||
if (cvp_desc->fullres_width <= 1920) {
|
||||
/*w*h*1.33*1.5/1.58 = w*h*5/4*/
|
||||
ds_pixel_read = ((cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 5)>>2);
|
||||
} else {
|
||||
/*w*h*1.33*1.5/1.61 = w*h*79/64*/
|
||||
ds_pixel_read = ((cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 79)>>6);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
dprintk(CVP_ERR, "Defaulting to linear P010\n");
|
||||
/*w*h*1.5*2 COLOR_FMT_P010*/
|
||||
ds_pixel_read = (cvp_desc->fullres_width
|
||||
* cvp_desc->fullres_height * 3);
|
||||
}
|
||||
} else {
|
||||
process_width = cvp_desc->fullres_width;
|
||||
process_height = cvp_desc->fullres_height;
|
||||
num_16x16_blocks = (process_width>>4)*(process_height>>4);
|
||||
hcd_cycles = NUM_CYCLES16X16_HCD_FRAME * num_16x16_blocks;
|
||||
}
|
||||
|
||||
dme_cycles = NUM_CYCLES16X16_DME_FRAME * NUM_DME_MAX_FEATURE_POINTS;
|
||||
ncc_cycles = NUM_CYCLES16X16_NCC_FRAME * NUM_DME_MAX_FEATURE_POINTS;
|
||||
|
||||
cvp_cycles = dme_cycles + ds_cycles + hcd_cycles + ncc_cycles;
|
||||
cvp_cycles = cvp_cycles + (cvp_cycles>>CYCLES_MARGIN_IN_POWEROF2);
|
||||
|
||||
cvp_voting->clock_cycles_a = cvp_cycles * cvp_desc->fps;
|
||||
cvp_voting->clock_cycles_b = 0;
|
||||
cvp_voting->reserved[0] = NUM_CYCLESFW_FRAME * cvp_desc->fps;
|
||||
cvp_voting->reserved[1] = cvp_cycles * cvp_desc->op_rate;
|
||||
cvp_voting->reserved[2] = 0;
|
||||
cvp_voting->reserved[3] = NUM_CYCLESFW_FRAME*cvp_desc->op_rate;
|
||||
|
||||
if (process_width <= 1920) {
|
||||
/*w*h*1.5(for filter fetch overhead)/1.58=w*h*(3/2)*(5/8)*/
|
||||
hcd_pixel_read = ((process_width * process_height * 15)>>4);
|
||||
/*num_16x16_blocks*8*4*/
|
||||
hcd_stats_write = (num_16x16_blocks<<5);
|
||||
/*NUM_DME_MAX_FEATURE_POINTS*96*48/1.58*/
|
||||
dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 2880;
|
||||
/*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/1.58*/
|
||||
ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1040;
|
||||
} else {
|
||||
/*w*h*1.5(for filter fetch overhead)/2.38=w*h*(3/2)*(54/128)*/
|
||||
hcd_pixel_read = ((process_width * process_height * 81)>>7);
|
||||
/*num_16x16_blocks*8*4*/
|
||||
hcd_stats_write = (num_16x16_blocks<<5);
|
||||
/*NUM_DME_MAX_FEATURE_POINTS*96*48/2.38*/
|
||||
dme_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 1944;
|
||||
/*NUM_DME_MAX_FEATURE_POINTS*(18/8+1)*32*8*2/2.38*/
|
||||
ncc_pixel_read = NUM_DME_MAX_FEATURE_POINTS * 702;
|
||||
}
|
||||
|
||||
cvp_bw = ds_pixel_read + ds_pixel_write + hcd_pixel_read
|
||||
+ hcd_stats_write + dme_pixel_read + ncc_pixel_read;
|
||||
|
||||
cvp_voting->ddr_bw = cvp_bw * cvp_desc->fps;
|
||||
cvp_voting->reserved[4] = cvp_bw * cvp_desc->op_rate;
|
||||
|
||||
dprintk(CVP_DBG, "%s Voting cycles_a, b, bw: %d %d %d\n", __func__,
|
||||
cvp_voting->clock_cycles_a, cvp_voting->clock_cycles_b,
|
||||
cvp_voting->ddr_bw);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_est_cycles);
|
||||
|
||||
int msm_cvp_poll(void *instance, struct file *filp,
|
||||
struct poll_table_struct *wait)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_poll);
|
||||
|
||||
int msm_cvp_private(void *cvp_inst, unsigned int cmd,
|
||||
struct cvp_kmd_arg *arg)
|
||||
{
|
||||
int rc = 0;
|
||||
struct msm_cvp_inst *inst = (struct msm_cvp_inst *)cvp_inst;
|
||||
|
||||
if (!inst || !arg) {
|
||||
dprintk(CVP_ERR, "%s: invalid args\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = msm_cvp_handle_syscall(inst, arg);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_private);
|
||||
|
||||
static bool msm_cvp_check_for_inst_overload(struct msm_cvp_core *core)
|
||||
{
|
||||
u32 instance_count = 0;
|
||||
u32 secure_instance_count = 0;
|
||||
struct msm_cvp_inst *inst = NULL;
|
||||
bool overload = false;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(inst, &core->instances, list) {
|
||||
instance_count++;
|
||||
/* This flag is not updated yet for the current instance */
|
||||
if (inst->flags & CVP_SECURE)
|
||||
secure_instance_count++;
|
||||
}
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
/* Instance count includes current instance as well. */
|
||||
|
||||
if ((instance_count >= core->resources.max_inst_count) ||
|
||||
(secure_instance_count >=
|
||||
core->resources.max_secure_inst_count))
|
||||
overload = true;
|
||||
return overload;
|
||||
}
|
||||
|
||||
static int _init_session_queue(struct msm_cvp_inst *inst)
|
||||
{
|
||||
spin_lock_init(&inst->session_queue.lock);
|
||||
INIT_LIST_HEAD(&inst->session_queue.msgs);
|
||||
inst->session_queue.msg_count = 0;
|
||||
init_waitqueue_head(&inst->session_queue.wq);
|
||||
inst->session_queue.state = QUEUE_ACTIVE;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void _deinit_session_queue(struct msm_cvp_inst *inst)
|
||||
{
|
||||
struct cvp_session_msg *msg, *tmpmsg;
|
||||
|
||||
/* free all messages */
|
||||
spin_lock(&inst->session_queue.lock);
|
||||
list_for_each_entry_safe(msg, tmpmsg, &inst->session_queue.msgs, node) {
|
||||
list_del_init(&msg->node);
|
||||
kmem_cache_free(cvp_driver->msg_cache, msg);
|
||||
}
|
||||
inst->session_queue.msg_count = 0;
|
||||
inst->session_queue.state = QUEUE_STOP;
|
||||
spin_unlock(&inst->session_queue.lock);
|
||||
|
||||
wake_up_all(&inst->session_queue.wq);
|
||||
}
|
||||
|
||||
void *msm_cvp_open(int core_id, int session_type)
|
||||
{
|
||||
struct msm_cvp_inst *inst = NULL;
|
||||
struct msm_cvp_core *core = NULL;
|
||||
int rc = 0;
|
||||
int i = 0;
|
||||
|
||||
if (core_id >= MSM_CVP_CORES_MAX ||
|
||||
session_type >= MSM_CVP_MAX_DEVICES) {
|
||||
dprintk(CVP_ERR, "Invalid input, core_id = %d, session = %d\n",
|
||||
core_id, session_type);
|
||||
goto err_invalid_core;
|
||||
}
|
||||
core = get_cvp_core(core_id);
|
||||
if (!core) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to find core for core_id = %d\n", core_id);
|
||||
goto err_invalid_core;
|
||||
}
|
||||
|
||||
core->resources.max_inst_count = MAX_SUPPORTED_INSTANCES;
|
||||
if (msm_cvp_check_for_inst_overload(core)) {
|
||||
dprintk(CVP_ERR, "Instance num reached Max, rejecting session");
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(inst, &core->instances, list)
|
||||
dprintk(CVP_ERR, "inst %pK, cmd %d id %d\n",
|
||||
inst, inst->cur_cmd_type,
|
||||
hash32_ptr(inst->session));
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
inst = kzalloc(sizeof(*inst), GFP_KERNEL);
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "Failed to allocate memory\n");
|
||||
rc = -ENOMEM;
|
||||
goto err_invalid_core;
|
||||
}
|
||||
|
||||
pr_info(CVP_DBG_TAG "Opening cvp instance: %pK\n", "info", inst);
|
||||
mutex_init(&inst->sync_lock);
|
||||
mutex_init(&inst->lock);
|
||||
mutex_init(&inst->fence_lock);
|
||||
spin_lock_init(&inst->event_handler.lock);
|
||||
|
||||
INIT_MSM_CVP_LIST(&inst->persistbufs);
|
||||
INIT_MSM_CVP_LIST(&inst->cvpcpubufs);
|
||||
INIT_MSM_CVP_LIST(&inst->cvpdspbufs);
|
||||
INIT_MSM_CVP_LIST(&inst->frames);
|
||||
|
||||
init_waitqueue_head(&inst->event_handler.wq);
|
||||
|
||||
kref_init(&inst->kref);
|
||||
|
||||
inst->session_type = session_type;
|
||||
inst->state = MSM_CVP_CORE_UNINIT_DONE;
|
||||
inst->core = core;
|
||||
inst->clk_data.min_freq = 0;
|
||||
inst->clk_data.curr_freq = 0;
|
||||
inst->clk_data.ddr_bw = 0;
|
||||
inst->clk_data.sys_cache_bw = 0;
|
||||
inst->clk_data.bitrate = 0;
|
||||
inst->clk_data.core_id = 0;
|
||||
inst->deprecate_bitmask = 0;
|
||||
|
||||
for (i = SESSION_MSG_INDEX(SESSION_MSG_START);
|
||||
i <= SESSION_MSG_INDEX(SESSION_MSG_END); i++) {
|
||||
init_completion(&inst->completions[i]);
|
||||
}
|
||||
|
||||
msm_cvp_session_init(inst);
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_add_tail(&inst->list, &core->instances);
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
rc = _init_session_queue(inst);
|
||||
if (rc)
|
||||
goto fail_init;
|
||||
|
||||
rc = msm_cvp_comm_try_state(inst, MSM_CVP_CORE_INIT_DONE);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to move cvp instance to init state\n");
|
||||
goto fail_init;
|
||||
}
|
||||
|
||||
inst->debugfs_root =
|
||||
msm_cvp_debugfs_init_inst(inst, core->debugfs_root);
|
||||
|
||||
return inst;
|
||||
fail_init:
|
||||
_deinit_session_queue(inst);
|
||||
mutex_lock(&core->lock);
|
||||
list_del(&inst->list);
|
||||
mutex_unlock(&core->lock);
|
||||
mutex_destroy(&inst->sync_lock);
|
||||
mutex_destroy(&inst->lock);
|
||||
mutex_destroy(&inst->fence_lock);
|
||||
|
||||
DEINIT_MSM_CVP_LIST(&inst->persistbufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->cvpcpubufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->cvpdspbufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->frames);
|
||||
|
||||
kfree(inst);
|
||||
inst = NULL;
|
||||
err_invalid_core:
|
||||
return inst;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_open);
|
||||
|
||||
static void msm_cvp_cleanup_instance(struct msm_cvp_inst *inst)
|
||||
{
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
if (cvp_comm_release_persist_buffers(inst))
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to release persist buffers\n");
|
||||
}
|
||||
|
||||
int msm_cvp_destroy(struct msm_cvp_inst *inst)
|
||||
{
|
||||
struct msm_cvp_core *core;
|
||||
|
||||
if (!inst || !inst->core) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
core = inst->core;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
/* inst->list lives in core->instances */
|
||||
list_del(&inst->list);
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
DEINIT_MSM_CVP_LIST(&inst->persistbufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->cvpcpubufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->cvpdspbufs);
|
||||
DEINIT_MSM_CVP_LIST(&inst->frames);
|
||||
|
||||
mutex_destroy(&inst->sync_lock);
|
||||
mutex_destroy(&inst->lock);
|
||||
mutex_destroy(&inst->fence_lock);
|
||||
|
||||
msm_cvp_debugfs_deinit_inst(inst);
|
||||
_deinit_session_queue(inst);
|
||||
|
||||
pr_info(CVP_DBG_TAG "Closed cvp instance: %pK session_id = %d\n",
|
||||
"info", inst, hash32_ptr(inst->session));
|
||||
if (inst->cur_cmd_type)
|
||||
dprintk(CVP_ERR, "deleted instance has pending cmd %d\n",
|
||||
inst->cur_cmd_type);
|
||||
inst->session = (void *)0xdeadbeef;
|
||||
kfree(inst);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void close_helper(struct kref *kref)
|
||||
{
|
||||
struct msm_cvp_inst *inst = container_of(kref,
|
||||
struct msm_cvp_inst, kref);
|
||||
|
||||
msm_cvp_destroy(inst);
|
||||
}
|
||||
|
||||
int msm_cvp_close(void *instance)
|
||||
{
|
||||
struct msm_cvp_inst *inst = instance;
|
||||
int rc = 0;
|
||||
|
||||
if (!inst || !inst->core) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
msm_cvp_cleanup_instance(inst);
|
||||
|
||||
if (inst->session_type != MSM_CVP_BOOT)
|
||||
msm_cvp_session_deinit(inst);
|
||||
|
||||
rc = msm_cvp_comm_try_state(inst, MSM_CVP_CORE_UNINIT);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to move inst %pK to uninit state\n", inst);
|
||||
rc = msm_cvp_deinit_core(inst);
|
||||
}
|
||||
|
||||
msm_cvp_comm_session_clean(inst);
|
||||
|
||||
kref_put(&inst->kref, close_helper);
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_close);
|
||||
|
||||
int msm_cvp_suspend(int core_id)
|
||||
{
|
||||
return msm_cvp_comm_suspend(core_id);
|
||||
}
|
||||
EXPORT_SYMBOL(msm_cvp_suspend);
|
104
drivers/media/platform/msm/cvp/msm_cvp_core.h
Normal file
104
drivers/media/platform/msm/cvp/msm_cvp_core.h
Normal file
@ -0,0 +1,104 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_CVP_CORE_H_
|
||||
#define _MSM_CVP_CORE_H_
|
||||
|
||||
#include <linux/poll.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/ion.h>
|
||||
#include <linux/msm_ion.h>
|
||||
#include <media/msm_cvp_private.h>
|
||||
#include <media/msm_cvp_vidc.h>
|
||||
|
||||
#define HAL_BUFFER_MAX 0xe
|
||||
|
||||
enum smem_type {
|
||||
SMEM_DMA = 1,
|
||||
};
|
||||
|
||||
enum smem_prop {
|
||||
SMEM_UNCACHED = 0x1,
|
||||
SMEM_CACHED = 0x2,
|
||||
SMEM_SECURE = 0x4,
|
||||
SMEM_ADSP = 0x8,
|
||||
SMEM_NON_PIXEL = 0x10
|
||||
};
|
||||
|
||||
/* NOTE: if you change this enum you MUST update the
|
||||
* "buffer-type-tz-usage-table" for any affected target
|
||||
* in arch/arm/boot/dts/<arch>.dtsi
|
||||
*/
|
||||
enum hal_buffer {
|
||||
HAL_BUFFER_NONE = 0x0,
|
||||
HAL_BUFFER_INPUT = 0x1,
|
||||
HAL_BUFFER_OUTPUT = 0x2,
|
||||
HAL_BUFFER_OUTPUT2 = 0x4,
|
||||
HAL_BUFFER_EXTRADATA_INPUT = 0x8,
|
||||
HAL_BUFFER_EXTRADATA_OUTPUT = 0x10,
|
||||
HAL_BUFFER_EXTRADATA_OUTPUT2 = 0x20,
|
||||
HAL_BUFFER_INTERNAL_SCRATCH = 0x40,
|
||||
HAL_BUFFER_INTERNAL_SCRATCH_1 = 0x80,
|
||||
HAL_BUFFER_INTERNAL_SCRATCH_2 = 0x100,
|
||||
HAL_BUFFER_INTERNAL_PERSIST = 0x200,
|
||||
HAL_BUFFER_INTERNAL_PERSIST_1 = 0x400,
|
||||
HAL_BUFFER_INTERNAL_CMD_QUEUE = 0x800,
|
||||
HAL_BUFFER_INTERNAL_RECON = 0x1000,
|
||||
};
|
||||
|
||||
struct cvp_dma_mapping_info {
|
||||
struct device *dev;
|
||||
struct iommu_domain *domain;
|
||||
struct sg_table *table;
|
||||
struct dma_buf_attachment *attach;
|
||||
struct dma_buf *buf;
|
||||
void *cb_info;
|
||||
};
|
||||
|
||||
struct msm_cvp_smem {
|
||||
u32 refcount;
|
||||
s32 fd;
|
||||
struct dma_buf *dma_buf;
|
||||
void *kvaddr;
|
||||
u32 device_addr;
|
||||
dma_addr_t dma_handle;
|
||||
u32 offset;
|
||||
u32 size;
|
||||
u32 flags;
|
||||
u32 buffer_type;
|
||||
struct cvp_dma_mapping_info mapping_info;
|
||||
};
|
||||
|
||||
enum smem_cache_ops {
|
||||
SMEM_CACHE_CLEAN,
|
||||
SMEM_CACHE_INVALIDATE,
|
||||
SMEM_CACHE_CLEAN_INVALIDATE,
|
||||
};
|
||||
|
||||
enum core_id {
|
||||
MSM_CORE_CVP = 0,
|
||||
MSM_CVP_CORES_MAX,
|
||||
};
|
||||
|
||||
enum session_type {
|
||||
MSM_CVP_USER = 1,
|
||||
MSM_CVP_KERNEL,
|
||||
MSM_CVP_BOOT,
|
||||
MSM_CVP_UNKNOWN,
|
||||
MSM_CVP_MAX_DEVICES = MSM_CVP_UNKNOWN,
|
||||
};
|
||||
|
||||
void *msm_cvp_open(int core_id, int session_type);
|
||||
int msm_cvp_close(void *instance);
|
||||
int msm_cvp_suspend(int core_id);
|
||||
int msm_cvp_poll(void *instance, struct file *filp,
|
||||
struct poll_table_struct *pt);
|
||||
int msm_cvp_private(void *cvp_inst, unsigned int cmd,
|
||||
struct cvp_kmd_arg *arg);
|
||||
int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc,
|
||||
struct cvp_kmd_request_power *cvp_voting);
|
||||
|
||||
#endif
|
466
drivers/media/platform/msm/cvp/msm_cvp_debug.c
Normal file
466
drivers/media/platform/msm/cvp/msm_cvp_debug.c
Normal file
@ -0,0 +1,466 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#define CREATE_TRACE_POINTS
|
||||
#define MAX_SSR_STRING_LEN 10
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp_common.h"
|
||||
#include "cvp_core_hfi.h"
|
||||
|
||||
int msm_cvp_debug = CVP_ERR | CVP_WARN | CVP_FW | CVP_DBG;
|
||||
EXPORT_SYMBOL(msm_cvp_debug);
|
||||
|
||||
int msm_cvp_debug_out = CVP_OUT_PRINTK;
|
||||
EXPORT_SYMBOL(msm_cvp_debug_out);
|
||||
|
||||
int msm_cvp_fw_debug = 0x18;
|
||||
int msm_cvp_fw_debug_mode = 1;
|
||||
int msm_cvp_fw_low_power_mode = 1;
|
||||
bool msm_cvp_fw_coverage = !true;
|
||||
bool msm_cvp_thermal_mitigation_disabled = !true;
|
||||
int msm_cvp_clock_voting = !1;
|
||||
bool msm_cvp_syscache_disable = !true;
|
||||
|
||||
#define MAX_DBG_BUF_SIZE 4096
|
||||
|
||||
struct cvp_core_inst_pair {
|
||||
struct msm_cvp_core *core;
|
||||
struct msm_cvp_inst *inst;
|
||||
};
|
||||
|
||||
static int core_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
dprintk(CVP_INFO, "%s: Enter\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static u32 write_str(char *buffer,
|
||||
size_t size, const char *fmt, ...)
|
||||
{
|
||||
va_list args;
|
||||
u32 len;
|
||||
|
||||
va_start(args, fmt);
|
||||
len = vscnprintf(buffer, size, fmt, args);
|
||||
va_end(args);
|
||||
return len;
|
||||
}
|
||||
|
||||
static ssize_t core_info_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct msm_cvp_core *core = file->private_data;
|
||||
struct cvp_hfi_device *hdev;
|
||||
struct cvp_hal_fw_info fw_info = { {0} };
|
||||
char *dbuf, *cur, *end;
|
||||
int i = 0, rc = 0;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (!core || !core->device) {
|
||||
dprintk(CVP_ERR, "Invalid params, core: %pK\n", core);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbuf = kzalloc(MAX_DBG_BUF_SIZE, GFP_KERNEL);
|
||||
if (!dbuf) {
|
||||
dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
|
||||
return -ENOMEM;
|
||||
}
|
||||
cur = dbuf;
|
||||
end = cur + MAX_DBG_BUF_SIZE;
|
||||
hdev = core->device;
|
||||
|
||||
cur += write_str(cur, end - cur, "===============================\n");
|
||||
cur += write_str(cur, end - cur, "CORE %d: %pK\n", core->id, core);
|
||||
cur += write_str(cur, end - cur, "===============================\n");
|
||||
cur += write_str(cur, end - cur, "Core state: %d\n", core->state);
|
||||
rc = call_hfi_op(hdev, get_fw_info, hdev->hfi_device_data, &fw_info);
|
||||
if (rc) {
|
||||
dprintk(CVP_WARN, "Failed to read FW info\n");
|
||||
goto err_fw_info;
|
||||
}
|
||||
|
||||
cur += write_str(cur, end - cur,
|
||||
"FW version : %s\n", &fw_info.version);
|
||||
cur += write_str(cur, end - cur,
|
||||
"base addr: 0x%x\n", fw_info.base_addr);
|
||||
cur += write_str(cur, end - cur,
|
||||
"register_base: 0x%x\n", fw_info.register_base);
|
||||
cur += write_str(cur, end - cur,
|
||||
"register_size: %u\n", fw_info.register_size);
|
||||
cur += write_str(cur, end - cur, "irq: %u\n", fw_info.irq);
|
||||
|
||||
err_fw_info:
|
||||
for (i = SYS_MSG_START; i < SYS_MSG_END; i++) {
|
||||
cur += write_str(cur, end - cur, "completions[%d]: %s\n", i,
|
||||
completion_done(&core->completions[SYS_MSG_INDEX(i)]) ?
|
||||
"pending" : "done");
|
||||
}
|
||||
len = simple_read_from_buffer(buf, count, ppos,
|
||||
dbuf, cur - dbuf);
|
||||
|
||||
kfree(dbuf);
|
||||
return len;
|
||||
}
|
||||
|
||||
static const struct file_operations core_info_fops = {
|
||||
.open = core_info_open,
|
||||
.read = core_info_read,
|
||||
};
|
||||
|
||||
static int trigger_ssr_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
file->private_data = inode->i_private;
|
||||
dprintk(CVP_INFO, "%s: Enter\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static ssize_t trigger_ssr_write(struct file *filp, const char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
unsigned long ssr_trigger_val = 0;
|
||||
int rc = 0;
|
||||
struct msm_cvp_core *core = filp->private_data;
|
||||
size_t size = MAX_SSR_STRING_LEN;
|
||||
char kbuf[MAX_SSR_STRING_LEN + 1] = {0};
|
||||
|
||||
if (!buf)
|
||||
return -EINVAL;
|
||||
|
||||
if (!count)
|
||||
goto exit;
|
||||
|
||||
if (count < size)
|
||||
size = count;
|
||||
|
||||
if (copy_from_user(kbuf, buf, size)) {
|
||||
dprintk(CVP_WARN, "%s User memory fault\n", __func__);
|
||||
rc = -EFAULT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
rc = kstrtoul(kbuf, 0, &ssr_trigger_val);
|
||||
if (rc) {
|
||||
dprintk(CVP_WARN, "returning error err %d\n", rc);
|
||||
rc = -EINVAL;
|
||||
} else {
|
||||
msm_cvp_trigger_ssr(core, ssr_trigger_val);
|
||||
rc = count;
|
||||
}
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static const struct file_operations ssr_fops = {
|
||||
.open = trigger_ssr_open,
|
||||
.write = trigger_ssr_write,
|
||||
};
|
||||
|
||||
struct dentry *msm_cvp_debugfs_init_drv(void)
|
||||
{
|
||||
bool ok = false;
|
||||
struct dentry *dir = NULL;
|
||||
|
||||
dir = debugfs_create_dir("msm_cvp", NULL);
|
||||
if (IS_ERR_OR_NULL(dir)) {
|
||||
dir = NULL;
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
#define __debugfs_create(__type, __name, __value) ({ \
|
||||
struct dentry *f = debugfs_create_##__type(__name, 0644, \
|
||||
dir, __value); \
|
||||
if (IS_ERR_OR_NULL(f)) { \
|
||||
dprintk(CVP_ERR, "Failed creating debugfs file '%pd/%s'\n", \
|
||||
dir, __name); \
|
||||
f = NULL; \
|
||||
} \
|
||||
f; \
|
||||
})
|
||||
|
||||
ok =
|
||||
__debugfs_create(x32, "debug_level", &msm_cvp_debug) &&
|
||||
__debugfs_create(x32, "fw_level", &msm_cvp_fw_debug) &&
|
||||
__debugfs_create(u32, "fw_debug_mode", &msm_cvp_fw_debug_mode) &&
|
||||
__debugfs_create(bool, "fw_coverage", &msm_cvp_fw_coverage) &&
|
||||
__debugfs_create(u32, "fw_low_power_mode",
|
||||
&msm_cvp_fw_low_power_mode) &&
|
||||
__debugfs_create(u32, "debug_output", &msm_cvp_debug_out) &&
|
||||
__debugfs_create(bool, "disable_thermal_mitigation",
|
||||
&msm_cvp_thermal_mitigation_disabled) &&
|
||||
__debugfs_create(bool, "disable_cvp_syscache",
|
||||
&msm_cvp_syscache_disable);
|
||||
|
||||
#undef __debugfs_create
|
||||
|
||||
if (!ok)
|
||||
goto failed_create_dir;
|
||||
|
||||
return dir;
|
||||
|
||||
failed_create_dir:
|
||||
if (dir)
|
||||
debugfs_remove_recursive(cvp_driver->debugfs_root);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int _clk_rate_set(void *data, u64 val)
|
||||
{
|
||||
struct msm_cvp_core *core;
|
||||
struct cvp_hfi_device *dev;
|
||||
struct allowed_clock_rates_table *tbl = NULL;
|
||||
unsigned int tbl_size, i;
|
||||
|
||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||
dev = core->device;
|
||||
tbl = core->resources.allowed_clks_tbl;
|
||||
tbl_size = core->resources.allowed_clks_tbl_size;
|
||||
|
||||
if (val == 0) {
|
||||
struct iris_hfi_device *hdev = dev->hfi_device_data;
|
||||
|
||||
msm_cvp_clock_voting = 0;
|
||||
call_hfi_op(dev, scale_clocks, hdev, hdev->clk_freq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (i = 0; i < tbl_size; i++)
|
||||
if (val <= tbl[i].clock_rate)
|
||||
break;
|
||||
|
||||
if (i == tbl_size)
|
||||
msm_cvp_clock_voting = tbl[tbl_size-1].clock_rate;
|
||||
else
|
||||
msm_cvp_clock_voting = tbl[i].clock_rate;
|
||||
|
||||
dprintk(CVP_WARN, "Override cvp_clk_rate with %d\n",
|
||||
msm_cvp_clock_voting);
|
||||
|
||||
call_hfi_op(dev, scale_clocks, dev->hfi_device_data,
|
||||
msm_cvp_clock_voting);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _clk_rate_get(void *data, u64 *val)
|
||||
{
|
||||
struct msm_cvp_core *core;
|
||||
struct iris_hfi_device *hdev;
|
||||
|
||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||
hdev = core->device->hfi_device_data;
|
||||
if (msm_cvp_clock_voting)
|
||||
*val = msm_cvp_clock_voting;
|
||||
else
|
||||
*val = hdev->clk_freq;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_DEBUGFS_ATTRIBUTE(clk_rate_fops, _clk_rate_get, _clk_rate_set, "%llu\n");
|
||||
|
||||
|
||||
struct dentry *msm_cvp_debugfs_init_core(struct msm_cvp_core *core,
|
||||
struct dentry *parent)
|
||||
{
|
||||
struct dentry *dir = NULL;
|
||||
char debugfs_name[MAX_DEBUGFS_NAME];
|
||||
|
||||
if (!core) {
|
||||
dprintk(CVP_ERR, "Invalid params, core: %pK\n", core);
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
snprintf(debugfs_name, MAX_DEBUGFS_NAME, "core%d", core->id);
|
||||
dir = debugfs_create_dir(debugfs_name, parent);
|
||||
if (!dir) {
|
||||
dprintk(CVP_ERR, "Failed to create debugfs for msm_cvp\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("info", 0444, dir, core, &core_info_fops)) {
|
||||
dprintk(CVP_ERR, "debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("trigger_ssr", 0200,
|
||||
dir, core, &ssr_fops)) {
|
||||
dprintk(CVP_ERR, "debugfs_create_file: fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
if (!debugfs_create_file("clock_rate", 0644, dir,
|
||||
NULL, &clk_rate_fops)) {
|
||||
dprintk(CVP_ERR, "debugfs_create_file: clock_rate fail\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
failed_create_dir:
|
||||
return dir;
|
||||
}
|
||||
|
||||
static int inst_info_open(struct inode *inode, struct file *file)
|
||||
{
|
||||
dprintk(CVP_INFO, "Open inode ptr: %pK\n", inode->i_private);
|
||||
file->private_data = inode->i_private;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int publish_unreleased_reference(struct msm_cvp_inst *inst,
|
||||
char **dbuf, char *end)
|
||||
{
|
||||
dprintk(CVP_DBG, "%s deprecated function\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void put_inst_helper(struct kref *kref)
|
||||
{
|
||||
struct msm_cvp_inst *inst = container_of(kref,
|
||||
struct msm_cvp_inst, kref);
|
||||
|
||||
msm_cvp_destroy(inst);
|
||||
}
|
||||
|
||||
static ssize_t inst_info_read(struct file *file, char __user *buf,
|
||||
size_t count, loff_t *ppos)
|
||||
{
|
||||
struct cvp_core_inst_pair *idata = file->private_data;
|
||||
struct msm_cvp_core *core;
|
||||
struct msm_cvp_inst *inst, *temp = NULL;
|
||||
char *dbuf, *cur, *end;
|
||||
int i;
|
||||
ssize_t len = 0;
|
||||
|
||||
if (!idata || !idata->core || !idata->inst) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params\n", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
core = idata->core;
|
||||
inst = idata->inst;
|
||||
|
||||
mutex_lock(&core->lock);
|
||||
list_for_each_entry(temp, &core->instances, list) {
|
||||
if (temp == inst)
|
||||
break;
|
||||
}
|
||||
inst = ((temp == inst) && kref_get_unless_zero(&inst->kref)) ?
|
||||
inst : NULL;
|
||||
mutex_unlock(&core->lock);
|
||||
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "%s: Instance has become obsolete", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dbuf = kzalloc(MAX_DBG_BUF_SIZE, GFP_KERNEL);
|
||||
if (!dbuf) {
|
||||
dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
|
||||
len = -ENOMEM;
|
||||
goto failed_alloc;
|
||||
}
|
||||
cur = dbuf;
|
||||
end = cur + MAX_DBG_BUF_SIZE;
|
||||
|
||||
cur += write_str(cur, end - cur, "==============================\n");
|
||||
cur += write_str(cur, end - cur, "INSTANCE: %pK (%s)\n", inst,
|
||||
inst->session_type == MSM_CVP_USER ? "User" : "Kernel");
|
||||
cur += write_str(cur, end - cur, "==============================\n");
|
||||
cur += write_str(cur, end - cur, "core: %pK\n", inst->core);
|
||||
cur += write_str(cur, end - cur, "state: %d\n", inst->state);
|
||||
cur += write_str(cur, end - cur, "secure: %d\n",
|
||||
!!(inst->flags & CVP_SECURE));
|
||||
for (i = SESSION_MSG_START; i < SESSION_MSG_END; i++) {
|
||||
cur += write_str(cur, end - cur, "completions[%d]: %s\n", i,
|
||||
completion_done(&inst->completions[SESSION_MSG_INDEX(i)]) ?
|
||||
"pending" : "done");
|
||||
}
|
||||
|
||||
publish_unreleased_reference(inst, &cur, end);
|
||||
len = simple_read_from_buffer(buf, count, ppos,
|
||||
dbuf, cur - dbuf);
|
||||
|
||||
kfree(dbuf);
|
||||
failed_alloc:
|
||||
kref_put(&inst->kref, put_inst_helper);
|
||||
return len;
|
||||
}
|
||||
|
||||
static int inst_info_release(struct inode *inode, struct file *file)
|
||||
{
|
||||
dprintk(CVP_INFO, "Release inode ptr: %pK\n", inode->i_private);
|
||||
file->private_data = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct file_operations inst_info_fops = {
|
||||
.open = inst_info_open,
|
||||
.read = inst_info_read,
|
||||
.release = inst_info_release,
|
||||
};
|
||||
|
||||
struct dentry *msm_cvp_debugfs_init_inst(struct msm_cvp_inst *inst,
|
||||
struct dentry *parent)
|
||||
{
|
||||
struct dentry *dir = NULL, *info = NULL;
|
||||
char debugfs_name[MAX_DEBUGFS_NAME];
|
||||
struct cvp_core_inst_pair *idata = NULL;
|
||||
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "Invalid params, inst: %pK\n", inst);
|
||||
goto exit;
|
||||
}
|
||||
snprintf(debugfs_name, MAX_DEBUGFS_NAME, "inst_%p", inst);
|
||||
|
||||
idata = kzalloc(sizeof(*idata), GFP_KERNEL);
|
||||
if (!idata) {
|
||||
dprintk(CVP_ERR, "%s: Allocation failed!\n", __func__);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
idata->core = inst->core;
|
||||
idata->inst = inst;
|
||||
|
||||
dir = debugfs_create_dir(debugfs_name, parent);
|
||||
if (!dir) {
|
||||
dprintk(CVP_ERR, "Failed to create debugfs for msm_cvp\n");
|
||||
goto failed_create_dir;
|
||||
}
|
||||
|
||||
info = debugfs_create_file("info", 0444, dir,
|
||||
idata, &inst_info_fops);
|
||||
if (!info) {
|
||||
dprintk(CVP_ERR, "debugfs_create_file: info fail\n");
|
||||
goto failed_create_file;
|
||||
}
|
||||
|
||||
dir->d_inode->i_private = info->d_inode->i_private;
|
||||
inst->debug.pdata[FRAME_PROCESSING].sampling = true;
|
||||
return dir;
|
||||
|
||||
failed_create_file:
|
||||
debugfs_remove_recursive(dir);
|
||||
dir = NULL;
|
||||
failed_create_dir:
|
||||
kfree(idata);
|
||||
exit:
|
||||
return dir;
|
||||
}
|
||||
|
||||
void msm_cvp_debugfs_deinit_inst(struct msm_cvp_inst *inst)
|
||||
{
|
||||
struct dentry *dentry = NULL;
|
||||
|
||||
if (!inst || !inst->debugfs_root)
|
||||
return;
|
||||
|
||||
dentry = inst->debugfs_root;
|
||||
if (dentry->d_inode) {
|
||||
dprintk(CVP_INFO, "Destroy %pK\n", dentry->d_inode->i_private);
|
||||
kfree(dentry->d_inode->i_private);
|
||||
dentry->d_inode->i_private = NULL;
|
||||
}
|
||||
debugfs_remove_recursive(dentry);
|
||||
inst->debugfs_root = NULL;
|
||||
}
|
154
drivers/media/platform/msm/cvp/msm_cvp_debug.h
Normal file
154
drivers/media/platform/msm/cvp/msm_cvp_debug.h
Normal file
@ -0,0 +1,154 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_CVP_DEBUG__
|
||||
#define __MSM_CVP_DEBUG__
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/delay.h>
|
||||
#include "msm_cvp_internal.h"
|
||||
#include "trace/events/msm_cvp_events.h"
|
||||
|
||||
#ifndef CVP_DBG_LABEL
|
||||
#define CVP_DBG_LABEL "msm_cvp"
|
||||
#endif
|
||||
|
||||
#define CVP_DBG_TAG CVP_DBG_LABEL ": %4s: "
|
||||
|
||||
/* To enable messages OR these values and
|
||||
* echo the result to debugfs file.
|
||||
*
|
||||
* To enable all messages set debug_level = 0x101F
|
||||
*/
|
||||
|
||||
enum cvp_msg_prio {
|
||||
CVP_ERR = 0x0001,
|
||||
CVP_WARN = 0x0002,
|
||||
CVP_INFO = 0x0004,
|
||||
CVP_DBG = 0x0008,
|
||||
CVP_PROF = 0x0010,
|
||||
CVP_PKT = 0x0020,
|
||||
CVP_FW = 0x1000,
|
||||
};
|
||||
|
||||
enum cvp_msg_out {
|
||||
CVP_OUT_PRINTK = 0,
|
||||
};
|
||||
|
||||
enum msm_cvp_debugfs_event {
|
||||
MSM_CVP_DEBUGFS_EVENT_ETB,
|
||||
MSM_CVP_DEBUGFS_EVENT_EBD,
|
||||
MSM_CVP_DEBUGFS_EVENT_FTB,
|
||||
MSM_CVP_DEBUGFS_EVENT_FBD,
|
||||
};
|
||||
|
||||
extern int msm_cvp_debug;
|
||||
extern int msm_cvp_debug_out;
|
||||
extern int msm_cvp_fw_debug;
|
||||
extern int msm_cvp_fw_debug_mode;
|
||||
extern int msm_cvp_fw_low_power_mode;
|
||||
extern bool msm_cvp_fw_coverage;
|
||||
extern bool msm_cvp_thermal_mitigation_disabled;
|
||||
extern int msm_cvp_clock_voting;
|
||||
extern bool msm_cvp_syscache_disable;
|
||||
|
||||
#define dprintk(__level, __fmt, arg...) \
|
||||
do { \
|
||||
if (msm_cvp_debug & __level) { \
|
||||
if (msm_cvp_debug_out == CVP_OUT_PRINTK) { \
|
||||
pr_info(CVP_DBG_TAG __fmt, \
|
||||
get_debug_level_str(__level), \
|
||||
## arg); \
|
||||
} \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define MSM_CVP_ERROR(value) \
|
||||
do { if (value) \
|
||||
dprintk(CVP_ERR, "BugOn"); \
|
||||
WARN_ON(value); \
|
||||
} while (0)
|
||||
|
||||
|
||||
struct dentry *msm_cvp_debugfs_init_drv(void);
|
||||
struct dentry *msm_cvp_debugfs_init_core(struct msm_cvp_core *core,
|
||||
struct dentry *parent);
|
||||
struct dentry *msm_cvp_debugfs_init_inst(struct msm_cvp_inst *inst,
|
||||
struct dentry *parent);
|
||||
void msm_cvp_debugfs_deinit_inst(struct msm_cvp_inst *inst);
|
||||
|
||||
static inline char *get_debug_level_str(int level)
|
||||
{
|
||||
switch (level) {
|
||||
case CVP_ERR:
|
||||
return "err";
|
||||
case CVP_WARN:
|
||||
return "warn";
|
||||
case CVP_INFO:
|
||||
return "info";
|
||||
case CVP_DBG:
|
||||
return "dbg";
|
||||
case CVP_PROF:
|
||||
return "prof";
|
||||
case CVP_PKT:
|
||||
return "pkt";
|
||||
case CVP_FW:
|
||||
return "fw";
|
||||
default:
|
||||
return "???";
|
||||
}
|
||||
}
|
||||
|
||||
static inline void show_stats(struct msm_cvp_inst *i)
|
||||
{
|
||||
int x;
|
||||
|
||||
for (x = 0; x < MAX_PROFILING_POINTS; x++) {
|
||||
if (i->debug.pdata[x].name[0] &&
|
||||
(msm_cvp_debug & CVP_PROF)) {
|
||||
if (i->debug.samples) {
|
||||
dprintk(CVP_PROF, "%s averaged %d ms/sample\n",
|
||||
i->debug.pdata[x].name,
|
||||
i->debug.pdata[x].cumulative /
|
||||
i->debug.samples);
|
||||
}
|
||||
|
||||
dprintk(CVP_PROF, "%s Samples: %d\n",
|
||||
i->debug.pdata[x].name,
|
||||
i->debug.samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static inline void msm_cvp_res_handle_fatal_hw_error(
|
||||
struct msm_cvp_platform_resources *resources,
|
||||
bool enable_fatal)
|
||||
{
|
||||
enable_fatal &= resources->debug_timeout;
|
||||
MSM_CVP_ERROR(enable_fatal);
|
||||
}
|
||||
|
||||
static inline void msm_cvp_handle_hw_error(struct msm_cvp_core *core)
|
||||
{
|
||||
bool enable_fatal = true;
|
||||
|
||||
/*
|
||||
* In current implementation user-initiated SSR triggers
|
||||
* a fatal error from hardware. However, there is no way
|
||||
* to know if fatal error is due to SSR or not. Handle
|
||||
* user SSR as non-fatal.
|
||||
*/
|
||||
if (core->trigger_ssr) {
|
||||
core->trigger_ssr = false;
|
||||
enable_fatal = false;
|
||||
}
|
||||
|
||||
/* CVP driver can decide FATAL handling of HW errors
|
||||
* based on multiple factors. This condition check will
|
||||
* be enhanced later.
|
||||
*/
|
||||
msm_cvp_res_handle_fatal_hw_error(&core->resources, enable_fatal);
|
||||
}
|
||||
|
||||
#endif
|
567
drivers/media/platform/msm/cvp/msm_cvp_dsp.c
Normal file
567
drivers/media/platform/msm/cvp/msm_cvp_dsp.c
Normal file
@ -0,0 +1,567 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/rpmsg.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include <soc/qcom/secure_buffer.h>
|
||||
#include "msm_cvp_dsp.h"
|
||||
|
||||
#define VMID_CDSP_Q6 (30)
|
||||
#define SRC_VM_NUM 1
|
||||
#define DEST_VM_NUM 2
|
||||
#define CVP_DSP_SEND_HFI_CMD_QUEUE 0
|
||||
#define CVP_DSP_SUSPEND 1
|
||||
#define CVP_DSP_RESUME 2
|
||||
#define CVP_DSP_SHUTDOWN 3
|
||||
#define CVP_DSP_REGISTER_BUFFER 4
|
||||
#define CVP_DSP_DEREGISTER_BUFFER 5
|
||||
#define STATUS_INIT 0
|
||||
#define STATUS_DEINIT 1
|
||||
#define STATUS_OK 2
|
||||
#define STATUS_SSR 3
|
||||
#define CVP_DSP_MAX_RESERVED 5
|
||||
|
||||
struct cvp_dsp_cmd_msg {
|
||||
uint32_t cmd_msg_type;
|
||||
int32_t ret_val;
|
||||
uint64_t msg_ptr;
|
||||
uint32_t msg_ptr_len;
|
||||
uint32_t buff_fd_iova;
|
||||
uint32_t buff_index;
|
||||
uint32_t buff_size;
|
||||
uint32_t session_id;
|
||||
int32_t ddr_type;
|
||||
uint32_t buff_fd;
|
||||
uint32_t buff_offset;
|
||||
uint32_t buff_fd_size;
|
||||
uint32_t reserved1;
|
||||
uint32_t reserved2;
|
||||
};
|
||||
|
||||
struct cvp_dsp_rsp_msg {
|
||||
uint32_t cmd_msg_type;
|
||||
int32_t ret_val;
|
||||
uint32_t reserved[CVP_DSP_MAX_RESERVED];
|
||||
};
|
||||
|
||||
struct cvp_dsp_rsp_context {
|
||||
struct completion work;
|
||||
};
|
||||
|
||||
struct cvp_dsp_apps {
|
||||
struct rpmsg_device *chan;
|
||||
struct mutex smd_mutex;
|
||||
struct mutex reg_buffer_mutex;
|
||||
struct mutex dereg_buffer_mutex;
|
||||
int rpmsg_register;
|
||||
uint32_t cdsp_state;
|
||||
uint32_t cvp_shutdown;
|
||||
struct completion reg_buffer_work;
|
||||
struct completion dereg_buffer_work;
|
||||
struct completion shutdown_work;
|
||||
struct completion cmdqueue_send_work;
|
||||
struct work_struct ssr_work;
|
||||
struct iris_hfi_device *device;
|
||||
};
|
||||
|
||||
|
||||
static struct cvp_dsp_apps gfa_cv;
|
||||
|
||||
static struct cvp_dsp_cmd_msg cmd_msg;
|
||||
|
||||
static struct cvp_dsp_rsp_msg cmd_msg_rsp;
|
||||
|
||||
static int cvp_dsp_send_cmd(void *msg, uint32_t len)
|
||||
{
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
int err = 0;
|
||||
|
||||
if (IS_ERR_OR_NULL(me->chan)) {
|
||||
dprintk(CVP_ERR, "%s: DSP GLink is not ready\n", __func__);
|
||||
err = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
err = rpmsg_send(me->chan->ept, msg, len);
|
||||
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
void msm_cvp_cdsp_ssr_handler(struct work_struct *work)
|
||||
{
|
||||
struct cvp_dsp_apps *me;
|
||||
uint64_t msg_ptr;
|
||||
uint32_t msg_ptr_len;
|
||||
int err;
|
||||
|
||||
me = container_of(work, struct cvp_dsp_apps, ssr_work);
|
||||
if (!me) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
msg_ptr = cmd_msg.msg_ptr;
|
||||
msg_ptr_len = cmd_msg.msg_ptr_len;
|
||||
|
||||
err = cvp_dsp_send_cmd_hfi_queue((phys_addr_t *)msg_ptr,
|
||||
msg_ptr_len,
|
||||
(void *)NULL);
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed to send HFI Queue address. err=%d\n",
|
||||
__func__, err);
|
||||
return;
|
||||
}
|
||||
|
||||
if (me->device) {
|
||||
mutex_lock(&me->device->lock);
|
||||
me->device->dsp_flags |= DSP_INIT;
|
||||
mutex_unlock(&me->device->lock);
|
||||
}
|
||||
dprintk(CVP_DBG, "%s: dsp recover from SSR successfully\n", __func__);
|
||||
}
|
||||
|
||||
static int cvp_dsp_rpmsg_probe(struct rpmsg_device *rpdev)
|
||||
{
|
||||
int err = 0;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
uint32_t cdsp_state, cvp_shutdown;
|
||||
uint64_t msg_ptr;
|
||||
uint32_t msg_ptr_len;
|
||||
int srcVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6};
|
||||
int destVM[SRC_VM_NUM] = {VMID_HLOS};
|
||||
int destVMperm[SRC_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||
|
||||
if (strcmp(rpdev->dev.parent->of_node->name, "cdsp")) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed to probe rpmsg device.Node name:%s\n",
|
||||
__func__, rpdev->dev.parent->of_node->name);
|
||||
err = -EINVAL;
|
||||
goto bail;
|
||||
}
|
||||
mutex_lock(&me->smd_mutex);
|
||||
me->chan = rpdev;
|
||||
cdsp_state = me->cdsp_state;
|
||||
cvp_shutdown = me->cvp_shutdown;
|
||||
msg_ptr = cmd_msg.msg_ptr;
|
||||
msg_ptr_len = cmd_msg.msg_ptr_len;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
|
||||
if (cdsp_state == STATUS_SSR && cvp_shutdown == STATUS_OK) {
|
||||
err = hyp_assign_phys((uint64_t)msg_ptr,
|
||||
msg_ptr_len, srcVM, DEST_VM_NUM, destVM,
|
||||
destVMperm, SRC_VM_NUM);
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed to hyp_assign. err=%d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
schedule_work(&me->ssr_work);
|
||||
mutex_lock(&me->smd_mutex);
|
||||
cdsp_state = me->cdsp_state;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
}
|
||||
|
||||
dprintk(CVP_INFO,
|
||||
"%s: Successfully probed. cdsp_state=%d cvp_shutdown=%d\n",
|
||||
__func__, cdsp_state, cvp_shutdown);
|
||||
bail:
|
||||
return err;
|
||||
}
|
||||
|
||||
static void cvp_dsp_rpmsg_remove(struct rpmsg_device *rpdev)
|
||||
{
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
cancel_work_sync(&me->ssr_work);
|
||||
mutex_lock(&me->smd_mutex);
|
||||
me->chan = NULL;
|
||||
me->cdsp_state = STATUS_SSR;
|
||||
if (me->device) {
|
||||
mutex_lock(&me->device->lock);
|
||||
me->device->dsp_flags &= ~DSP_INIT;
|
||||
mutex_unlock(&me->device->lock);
|
||||
}
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
dprintk(CVP_INFO,
|
||||
"%s: CDSP SSR triggered\n", __func__);
|
||||
}
|
||||
|
||||
static int cvp_dsp_rpmsg_callback(struct rpmsg_device *rpdev,
|
||||
void *data, int len, void *priv, u32 addr)
|
||||
{
|
||||
struct cvp_dsp_rsp_msg *dsp_response =
|
||||
(struct cvp_dsp_rsp_msg *)data;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: cmd_msg_type=0x%x dsp_response->ret_val =0x%x\n"
|
||||
, __func__, dsp_response->cmd_msg_type, dsp_response->ret_val);
|
||||
switch (dsp_response->cmd_msg_type) {
|
||||
case CVP_DSP_REGISTER_BUFFER:
|
||||
complete(&me->reg_buffer_work);
|
||||
break;
|
||||
case CVP_DSP_DEREGISTER_BUFFER:
|
||||
complete(&me->dereg_buffer_work);
|
||||
break;
|
||||
case CVP_DSP_SHUTDOWN:
|
||||
complete(&me->shutdown_work);
|
||||
break;
|
||||
case CVP_DSP_SUSPEND:
|
||||
break;
|
||||
case CVP_DSP_RESUME:
|
||||
break;
|
||||
case CVP_DSP_SEND_HFI_CMD_QUEUE:
|
||||
complete(&me->cmdqueue_send_work);
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Invalid cmd_msg_type received from dsp: %d\n",
|
||||
__func__, dsp_response->cmd_msg_type);
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
||||
uint32_t size_in_bytes,
|
||||
struct iris_hfi_device *device)
|
||||
{
|
||||
int err, timeout;
|
||||
struct msm_cvp_core *core;
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
int srcVM[SRC_VM_NUM] = {VMID_HLOS};
|
||||
int destVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6};
|
||||
int destVMperm[DEST_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC,
|
||||
PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_SEND_HFI_CMD_QUEUE;
|
||||
local_cmd_msg.msg_ptr = (uint64_t)phys_addr;
|
||||
local_cmd_msg.msg_ptr_len = size_in_bytes;
|
||||
local_cmd_msg.ddr_type = of_fdt_get_ddrtype();
|
||||
if (local_cmd_msg.ddr_type < 0) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Incorrect DDR type value %d\n",
|
||||
__func__, local_cmd_msg.ddr_type);
|
||||
err = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
cmd_msg.msg_ptr = (uint64_t)phys_addr;
|
||||
cmd_msg.msg_ptr_len = (size_in_bytes);
|
||||
me->device = device;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: address of buffer, PA=0x%pK size_buff=%d ddr_type=%d\n",
|
||||
__func__, phys_addr, size_in_bytes, local_cmd_msg.ddr_type);
|
||||
|
||||
err = hyp_assign_phys((uint64_t)local_cmd_msg.msg_ptr,
|
||||
local_cmd_msg.msg_ptr_len, srcVM, SRC_VM_NUM, destVM,
|
||||
destVMperm, DEST_VM_NUM);
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed in hyp_assign. err=%d\n",
|
||||
__func__, err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd faidmesgled with err=%d\n",
|
||||
__func__, err);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
core = list_first_entry(&cvp_driver->cores,
|
||||
struct msm_cvp_core, list);
|
||||
timeout = msecs_to_jiffies(
|
||||
core->resources.msm_cvp_dsp_rsp_timeout);
|
||||
if (!wait_for_completion_timeout(&me->cmdqueue_send_work, timeout)) {
|
||||
dprintk(CVP_ERR, "failed to send cmdqueue\n");
|
||||
err = -ETIMEDOUT;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
me->cvp_shutdown = STATUS_OK;
|
||||
me->cdsp_state = STATUS_OK;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
|
||||
exit:
|
||||
return err;
|
||||
}
|
||||
|
||||
int cvp_dsp_suspend(uint32_t session_flag)
|
||||
{
|
||||
int err = 0;
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
uint32_t cdsp_state;
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
cdsp_state = me->cdsp_state;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
|
||||
if (cdsp_state == STATUS_SSR)
|
||||
return 0;
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_SUSPEND;
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err != 0)
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with err=%d\n",
|
||||
__func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int cvp_dsp_resume(uint32_t session_flag)
|
||||
{
|
||||
int err;
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
uint32_t cdsp_state;
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
cdsp_state = me->cdsp_state;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
|
||||
if (cdsp_state == STATUS_SSR)
|
||||
return 0;
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_RESUME;
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err != 0)
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with err=%d\n",
|
||||
__func__, err);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
void cvp_dsp_set_cvp_ssr(void)
|
||||
{
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
me->cvp_shutdown = STATUS_SSR;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
}
|
||||
|
||||
int cvp_dsp_shutdown(uint32_t session_flag)
|
||||
{
|
||||
struct msm_cvp_core *core;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
int err, local_cmd_msg_rsp, timeout;
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
int srcVM[DEST_VM_NUM] = {VMID_HLOS, VMID_CDSP_Q6};
|
||||
int destVM[SRC_VM_NUM] = {VMID_HLOS};
|
||||
int destVMperm[SRC_VM_NUM] = { PERM_READ | PERM_WRITE | PERM_EXEC };
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_SHUTDOWN;
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err != 0)
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with err=%d\n",
|
||||
__func__, err);
|
||||
|
||||
core = list_first_entry(&cvp_driver->cores, struct msm_cvp_core, list);
|
||||
timeout = msecs_to_jiffies(core->resources.msm_cvp_dsp_rsp_timeout);
|
||||
err = wait_for_completion_timeout(&me->shutdown_work, timeout);
|
||||
if (!err) {
|
||||
dprintk(CVP_ERR, "failed to shutdown dsp\n");
|
||||
return -ETIMEDOUT;
|
||||
}
|
||||
|
||||
mutex_lock(&me->smd_mutex);
|
||||
local_cmd_msg.msg_ptr = cmd_msg.msg_ptr;
|
||||
local_cmd_msg.msg_ptr_len = cmd_msg.msg_ptr_len;
|
||||
mutex_unlock(&me->smd_mutex);
|
||||
local_cmd_msg_rsp = cmd_msg_rsp.ret_val;
|
||||
if (local_cmd_msg_rsp == 0) {
|
||||
err = hyp_assign_phys((uint64_t)local_cmd_msg.msg_ptr,
|
||||
local_cmd_msg.msg_ptr_len, srcVM, DEST_VM_NUM,
|
||||
destVM, destVMperm, SRC_VM_NUM);
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed to hyp_assign. err=%d\n",
|
||||
__func__, err);
|
||||
return err;
|
||||
}
|
||||
} else {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Skipping hyp_assign as CDSP sent invalid response=%d\n",
|
||||
__func__, local_cmd_msg_rsp);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
||||
uint32_t buff_fd_size, uint32_t buff_size,
|
||||
uint32_t buff_offset, uint32_t buff_index,
|
||||
uint32_t buff_fd_iova)
|
||||
{
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
int err;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_REGISTER_BUFFER;
|
||||
local_cmd_msg.session_id = session_id;
|
||||
local_cmd_msg.buff_fd = buff_fd;
|
||||
local_cmd_msg.buff_fd_size = buff_fd_size;
|
||||
local_cmd_msg.buff_size = buff_size;
|
||||
local_cmd_msg.buff_offset = buff_offset;
|
||||
local_cmd_msg.buff_index = buff_index;
|
||||
local_cmd_msg.buff_fd_iova = buff_fd_iova;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: cmd_msg_type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n",
|
||||
__func__, local_cmd_msg.cmd_msg_type, buff_fd_iova,
|
||||
local_cmd_msg.buff_index);
|
||||
dprintk(CVP_DBG,
|
||||
"%s: buff_size=0x%x session_id=0x%x\n",
|
||||
__func__, local_cmd_msg.buff_size, local_cmd_msg.session_id);
|
||||
|
||||
mutex_lock(&me->reg_buffer_mutex);
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err != 0) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with err=%d\n",
|
||||
__func__, err);
|
||||
mutex_unlock(&me->reg_buffer_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: calling wait_for_completion work=%pK\n",
|
||||
__func__, &me->reg_buffer_work);
|
||||
wait_for_completion(&me->reg_buffer_work);
|
||||
mutex_unlock(&me->reg_buffer_mutex);
|
||||
dprintk(CVP_DBG,
|
||||
"%s: done calling wait_for_completion\n", __func__);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
||||
uint32_t buff_fd_size, uint32_t buff_size,
|
||||
uint32_t buff_offset, uint32_t buff_index,
|
||||
uint32_t buff_fd_iova)
|
||||
{
|
||||
struct cvp_dsp_cmd_msg local_cmd_msg;
|
||||
int err;
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
local_cmd_msg.cmd_msg_type = CVP_DSP_DEREGISTER_BUFFER;
|
||||
local_cmd_msg.session_id = session_id;
|
||||
local_cmd_msg.buff_fd = buff_fd;
|
||||
local_cmd_msg.buff_fd_size = buff_fd_size;
|
||||
local_cmd_msg.buff_size = buff_size;
|
||||
local_cmd_msg.buff_offset = buff_offset;
|
||||
local_cmd_msg.buff_index = buff_index;
|
||||
local_cmd_msg.buff_fd_iova = buff_fd_iova;
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: cmd_msg_type=0x%x, buff_fd_iova=0x%x buff_index=0x%x\n",
|
||||
__func__, local_cmd_msg.cmd_msg_type, buff_fd_iova,
|
||||
local_cmd_msg.buff_index);
|
||||
dprintk(CVP_DBG,
|
||||
"%s: buff_size=0x%x session_id=0x%x\n",
|
||||
__func__, local_cmd_msg.buff_size, local_cmd_msg.session_id);
|
||||
|
||||
mutex_lock(&me->dereg_buffer_mutex);
|
||||
err = cvp_dsp_send_cmd
|
||||
(&local_cmd_msg, sizeof(struct cvp_dsp_cmd_msg));
|
||||
if (err != 0) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cvp_dsp_send_cmd failed with err=%d\n",
|
||||
__func__, err);
|
||||
mutex_unlock(&me->dereg_buffer_mutex);
|
||||
return err;
|
||||
}
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: calling wait_for_completion work=%pK\n",
|
||||
__func__, &me->dereg_buffer_work);
|
||||
wait_for_completion(&me->dereg_buffer_work);
|
||||
dprintk(CVP_DBG,
|
||||
"%s: done calling wait_for_completion\n", __func__);
|
||||
mutex_unlock(&me->dereg_buffer_mutex);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static const struct rpmsg_device_id cvp_dsp_rpmsg_match[] = {
|
||||
{ CVP_APPS_DSP_GLINK_GUID },
|
||||
{ },
|
||||
};
|
||||
|
||||
static struct rpmsg_driver cvp_dsp_rpmsg_client = {
|
||||
.id_table = cvp_dsp_rpmsg_match,
|
||||
.probe = cvp_dsp_rpmsg_probe,
|
||||
.remove = cvp_dsp_rpmsg_remove,
|
||||
.callback = cvp_dsp_rpmsg_callback,
|
||||
.drv = {
|
||||
.name = "qcom,msm_cvp_dsp_rpmsg",
|
||||
},
|
||||
};
|
||||
|
||||
int cvp_dsp_device_init(void)
|
||||
{
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
int err;
|
||||
|
||||
if (me->cdsp_state == STATUS_DEINIT) {
|
||||
mutex_init(&me->smd_mutex);
|
||||
mutex_init(&me->reg_buffer_mutex);
|
||||
mutex_init(&me->dereg_buffer_mutex);
|
||||
init_completion(&me->shutdown_work);
|
||||
init_completion(&me->reg_buffer_work);
|
||||
init_completion(&me->dereg_buffer_work);
|
||||
init_completion(&me->cmdqueue_send_work);
|
||||
me->cvp_shutdown = STATUS_INIT;
|
||||
me->cdsp_state = STATUS_INIT;
|
||||
INIT_WORK(&me->ssr_work, msm_cvp_cdsp_ssr_handler);
|
||||
err = register_rpmsg_driver(&cvp_dsp_rpmsg_client);
|
||||
if (err) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s : register_rpmsg failed with err %d\n",
|
||||
__func__, err);
|
||||
goto register_bail;
|
||||
}
|
||||
me->rpmsg_register = 1;
|
||||
}
|
||||
return 0;
|
||||
|
||||
register_bail:
|
||||
me->cvp_shutdown = STATUS_DEINIT;
|
||||
me->cdsp_state = STATUS_DEINIT;
|
||||
return err;
|
||||
}
|
||||
|
||||
void cvp_dsp_device_exit(void)
|
||||
{
|
||||
struct cvp_dsp_apps *me = &gfa_cv;
|
||||
|
||||
me->cvp_shutdown = STATUS_DEINIT;
|
||||
me->cdsp_state = STATUS_DEINIT;
|
||||
mutex_destroy(&me->smd_mutex);
|
||||
mutex_destroy(&me->reg_buffer_mutex);
|
||||
mutex_destroy(&me->dereg_buffer_mutex);
|
||||
if (me->rpmsg_register == 1)
|
||||
unregister_rpmsg_driver(&cvp_dsp_rpmsg_client);
|
||||
}
|
106
drivers/media/platform/msm/cvp/msm_cvp_dsp.h
Normal file
106
drivers/media/platform/msm/cvp/msm_cvp_dsp.h
Normal file
@ -0,0 +1,106 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef MSM_CVP_DSP_H
|
||||
#define MSM_CVP_DSP_H
|
||||
|
||||
#include <linux/types.h>
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "cvp_core_hfi.h"
|
||||
|
||||
#define CVP_APPS_DSP_GLINK_GUID "cvp-glink-apps-dsp"
|
||||
#define CVP_APPS_DSP_SMD_GUID "cvp-smd-apps-dsp"
|
||||
|
||||
/*
|
||||
* API for CVP driver to send physical address to dsp driver
|
||||
* @param phys_addr
|
||||
* Physical address of command message queue
|
||||
* that needs to be mapped to CDSP.
|
||||
* It should be allocated from CMA adsp_mem region.
|
||||
*
|
||||
* @param size_in_bytes
|
||||
* Size in bytes of command message queue
|
||||
*/
|
||||
int cvp_dsp_send_cmd_hfi_queue(phys_addr_t *phys_addr,
|
||||
uint32_t size_in_bytes, struct iris_hfi_device *device);
|
||||
|
||||
/*
|
||||
* API for CVP driver to suspend CVP session during
|
||||
* power collapse
|
||||
*
|
||||
* @param session_flag
|
||||
* Flag to share details of session.
|
||||
*/
|
||||
int cvp_dsp_suspend(uint32_t session_flag);
|
||||
|
||||
/*
|
||||
* API for CVP driver to resume CVP session during
|
||||
* power collapse
|
||||
*
|
||||
* @param session_flag
|
||||
* Flag to share details of session.
|
||||
*/
|
||||
int cvp_dsp_resume(uint32_t session_flag);
|
||||
|
||||
/*
|
||||
* API for CVP driver to shutdown CVP session during
|
||||
* cvp subsystem error.
|
||||
*
|
||||
* @param session_flag
|
||||
* Flag to share details of session.
|
||||
*/
|
||||
int cvp_dsp_shutdown(uint32_t session_flag);
|
||||
|
||||
/*
|
||||
* API for CVP driver to set CVP status during
|
||||
* cvp subsystem error.
|
||||
*
|
||||
*/
|
||||
void cvp_dsp_set_cvp_ssr(void);
|
||||
|
||||
/*
|
||||
* API to register iova buffer address with CDSP
|
||||
*
|
||||
* @session_id: cvp session id
|
||||
* @buff_fd: buffer fd
|
||||
* @buff_fd_size: total size of fd in bytes
|
||||
* @buff_size: size in bytes of cvp buffer
|
||||
* @buff_offset: buffer offset
|
||||
* @buff_index: buffer index
|
||||
* @iova_buff_addr: IOVA buffer address
|
||||
*/
|
||||
int cvp_dsp_register_buffer(uint32_t session_id, uint32_t buff_fd,
|
||||
uint32_t buff_fd_size, uint32_t buff_size,
|
||||
uint32_t buff_offset, uint32_t buff_index,
|
||||
uint32_t buff_fd_iova);
|
||||
|
||||
/*
|
||||
* API to de-register iova buffer address from CDSP
|
||||
*
|
||||
* @session_id: cvp session id
|
||||
* @buff_fd: buffer fd
|
||||
* @buff_fd_size: total size of fd in bytes
|
||||
* @buff_size: size in bytes of cvp buffer
|
||||
* @buff_offset: buffer offset
|
||||
* @buff_index: buffer index
|
||||
* @iova_buff_addr: IOVA buffer address
|
||||
*/
|
||||
int cvp_dsp_deregister_buffer(uint32_t session_id, uint32_t buff_fd,
|
||||
uint32_t buff_fd_size, uint32_t buff_size,
|
||||
uint32_t buff_offset, uint32_t buff_index,
|
||||
uint32_t buff_fd_iova);
|
||||
|
||||
/*
|
||||
* API to initialize CPU and DSP driver interface
|
||||
*/
|
||||
int cvp_dsp_device_init(void);
|
||||
|
||||
/*
|
||||
* API to deinitilized CPU and DSP driver interface
|
||||
*/
|
||||
void cvp_dsp_device_exit(void);
|
||||
|
||||
#endif // MSM_CVP_DSP_H
|
||||
|
417
drivers/media/platform/msm/cvp/msm_cvp_internal.h
Normal file
417
drivers/media/platform/msm/cvp/msm_cvp_internal.h
Normal file
@ -0,0 +1,417 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_CVP_INTERNAL_H_
|
||||
#define _MSM_CVP_INTERNAL_H_
|
||||
|
||||
#include <linux/atomic.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/time.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/completion.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/interconnect.h>
|
||||
#include <linux/kref.h>
|
||||
#include <linux/cdev.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kthread.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include <media/msm_media_info.h>
|
||||
#include <media/msm_cvp_private.h>
|
||||
#include "cvp_hfi_api.h"
|
||||
|
||||
#define MAX_SUPPORTED_INSTANCES 16
|
||||
#define MAX_NAME_LENGTH 64
|
||||
#define MAX_DEBUGFS_NAME 50
|
||||
#define MAX_DSP_INIT_ATTEMPTS 16
|
||||
#define FENCE_WAIT_SIGNAL_TIMEOUT 100
|
||||
#define FENCE_WAIT_SIGNAL_RETRY_TIMES 20
|
||||
|
||||
#define SYS_MSG_START HAL_SYS_INIT_DONE
|
||||
#define SYS_MSG_END HAL_SYS_ERROR
|
||||
#define SESSION_MSG_START HAL_SESSION_EVENT_CHANGE
|
||||
#define SESSION_MSG_END HAL_SESSION_ERROR
|
||||
#define SYS_MSG_INDEX(__msg) (__msg - SYS_MSG_START)
|
||||
#define SESSION_MSG_INDEX(__msg) (__msg - SESSION_MSG_START)
|
||||
|
||||
#define call_core_op(c, op, args...) \
|
||||
(((c) && (c)->core_ops && (c)->core_ops->op) ? \
|
||||
((c)->core_ops->op(args)) : 0)
|
||||
|
||||
#define ARP_BUF_SIZE 0x100000
|
||||
|
||||
#define CVP_RT_PRIO_THRESHOLD 1
|
||||
|
||||
struct msm_cvp_inst;
|
||||
|
||||
enum cvp_core_state {
|
||||
CVP_CORE_UNINIT = 0,
|
||||
CVP_CORE_INIT,
|
||||
CVP_CORE_INIT_DONE,
|
||||
};
|
||||
|
||||
/*
|
||||
* Do not change the enum values unless
|
||||
* you know what you are doing
|
||||
*/
|
||||
enum instance_state {
|
||||
MSM_CVP_CORE_UNINIT_DONE = 0x0001,
|
||||
MSM_CVP_CORE_INIT,
|
||||
MSM_CVP_CORE_INIT_DONE,
|
||||
MSM_CVP_OPEN,
|
||||
MSM_CVP_OPEN_DONE,
|
||||
MSM_CVP_CLOSE,
|
||||
MSM_CVP_CLOSE_DONE,
|
||||
MSM_CVP_CORE_UNINIT,
|
||||
MSM_CVP_CORE_INVALID
|
||||
};
|
||||
|
||||
struct msm_cvp_list {
|
||||
struct list_head list;
|
||||
struct mutex lock;
|
||||
};
|
||||
|
||||
static inline void INIT_MSM_CVP_LIST(struct msm_cvp_list *mlist)
|
||||
{
|
||||
mutex_init(&mlist->lock);
|
||||
INIT_LIST_HEAD(&mlist->list);
|
||||
}
|
||||
|
||||
static inline void DEINIT_MSM_CVP_LIST(struct msm_cvp_list *mlist)
|
||||
{
|
||||
mutex_destroy(&mlist->lock);
|
||||
}
|
||||
|
||||
enum buffer_owner {
|
||||
DRIVER,
|
||||
FIRMWARE,
|
||||
CLIENT,
|
||||
MAX_OWNER
|
||||
};
|
||||
|
||||
struct cvp_freq_data {
|
||||
struct list_head list;
|
||||
u32 device_addr;
|
||||
unsigned long freq;
|
||||
bool turbo;
|
||||
};
|
||||
|
||||
struct cvp_internal_buf {
|
||||
struct list_head list;
|
||||
u32 buffer_type;
|
||||
struct msm_cvp_smem smem;
|
||||
enum buffer_owner buffer_ownership;
|
||||
bool mark_remove;
|
||||
};
|
||||
|
||||
struct msm_cvp_common_data {
|
||||
char key[128];
|
||||
int value;
|
||||
};
|
||||
|
||||
enum sku_version {
|
||||
SKU_VERSION_0 = 0,
|
||||
SKU_VERSION_1,
|
||||
SKU_VERSION_2,
|
||||
};
|
||||
|
||||
enum vpu_version {
|
||||
VPU_VERSION_4 = 1,
|
||||
VPU_VERSION_5,
|
||||
};
|
||||
|
||||
struct msm_cvp_ubwc_config_data {
|
||||
struct {
|
||||
u32 max_channel_override : 1;
|
||||
u32 mal_length_override : 1;
|
||||
u32 hb_override : 1;
|
||||
u32 bank_swzl_level_override : 1;
|
||||
u32 bank_spreading_override : 1;
|
||||
u32 reserved : 27;
|
||||
} override_bit_info;
|
||||
|
||||
u32 max_channels;
|
||||
u32 mal_length;
|
||||
u32 highest_bank_bit;
|
||||
u32 bank_swzl_level;
|
||||
u32 bank_spreading;
|
||||
};
|
||||
|
||||
#define IS_VPU_4(ver) \
|
||||
(ver == VPU_VERSION_4)
|
||||
|
||||
#define IS_VPU_5(ver) \
|
||||
(ver == VPU_VERSION_5)
|
||||
|
||||
struct msm_cvp_platform_data {
|
||||
struct msm_cvp_common_data *common_data;
|
||||
unsigned int common_data_length;
|
||||
unsigned int sku_version;
|
||||
uint32_t vpu_ver;
|
||||
struct msm_cvp_ubwc_config_data *ubwc_config;
|
||||
};
|
||||
|
||||
struct msm_cvp_drv {
|
||||
struct mutex lock;
|
||||
struct list_head cores;
|
||||
int num_cores;
|
||||
struct dentry *debugfs_root;
|
||||
int thermal_level;
|
||||
u32 sku_version;
|
||||
struct kmem_cache *msg_cache;
|
||||
struct kmem_cache *fence_data_cache;
|
||||
struct kmem_cache *frame_cache;
|
||||
struct kmem_cache *frame_buf_cache;
|
||||
struct kmem_cache *internal_buf_cache;
|
||||
char fw_version[CVP_VERSION_LENGTH];
|
||||
};
|
||||
|
||||
enum profiling_points {
|
||||
SYS_INIT = 0,
|
||||
SESSION_INIT,
|
||||
LOAD_RESOURCES,
|
||||
FRAME_PROCESSING,
|
||||
FW_IDLE,
|
||||
MAX_PROFILING_POINTS,
|
||||
};
|
||||
|
||||
struct cvp_buf_type {
|
||||
s32 fd;
|
||||
u32 size;
|
||||
u32 offset;
|
||||
u32 flags;
|
||||
union {
|
||||
struct dma_buf *dbuf;
|
||||
struct {
|
||||
u32 reserved1;
|
||||
u32 reserved2;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct cvp_clock_data {
|
||||
int buffer_counter;
|
||||
int load;
|
||||
int load_low;
|
||||
int load_norm;
|
||||
int load_high;
|
||||
int min_threshold;
|
||||
int max_threshold;
|
||||
enum hal_buffer buffer_type;
|
||||
unsigned long bitrate;
|
||||
unsigned long min_freq;
|
||||
unsigned long curr_freq;
|
||||
u32 ddr_bw;
|
||||
u32 sys_cache_bw;
|
||||
u32 operating_rate;
|
||||
u32 core_id;
|
||||
bool low_latency_mode;
|
||||
bool turbo_mode;
|
||||
};
|
||||
|
||||
struct cvp_profile_data {
|
||||
int start;
|
||||
int stop;
|
||||
int cumulative;
|
||||
char name[64];
|
||||
int sampling;
|
||||
int average;
|
||||
};
|
||||
|
||||
struct msm_cvp_debug {
|
||||
struct cvp_profile_data pdata[MAX_PROFILING_POINTS];
|
||||
int profile;
|
||||
int samples;
|
||||
};
|
||||
|
||||
enum msm_cvp_modes {
|
||||
CVP_SECURE = BIT(0),
|
||||
CVP_TURBO = BIT(1),
|
||||
CVP_THUMBNAIL = BIT(2),
|
||||
CVP_LOW_POWER = BIT(3),
|
||||
CVP_REALTIME = BIT(4),
|
||||
};
|
||||
|
||||
#define MAX_NUM_MSGS_PER_SESSION 128
|
||||
#define CVP_MAX_WAIT_TIME 2000
|
||||
|
||||
struct cvp_session_msg {
|
||||
struct list_head node;
|
||||
struct cvp_hfi_msg_session_hdr pkt;
|
||||
};
|
||||
|
||||
enum queue_state {
|
||||
QUEUE_INIT,
|
||||
QUEUE_ACTIVE = 1,
|
||||
QUEUE_STOP = 2,
|
||||
QUEUE_INVALID,
|
||||
};
|
||||
|
||||
struct cvp_session_queue {
|
||||
spinlock_t lock;
|
||||
enum queue_state state;
|
||||
unsigned int msg_count;
|
||||
struct list_head msgs;
|
||||
wait_queue_head_t wq;
|
||||
};
|
||||
|
||||
struct cvp_session_prop {
|
||||
u32 type;
|
||||
u32 kernel_mask;
|
||||
u32 priority;
|
||||
u32 is_secure;
|
||||
u32 dsp_mask;
|
||||
u32 fdu_cycles;
|
||||
u32 od_cycles;
|
||||
u32 mpu_cycles;
|
||||
u32 ica_cycles;
|
||||
u32 fw_cycles;
|
||||
u32 fdu_op_cycles;
|
||||
u32 od_op_cycles;
|
||||
u32 mpu_op_cycles;
|
||||
u32 ica_op_cycles;
|
||||
u32 fw_op_cycles;
|
||||
u32 ddr_bw;
|
||||
u32 ddr_op_bw;
|
||||
u32 ddr_cache;
|
||||
u32 ddr_op_cache;
|
||||
};
|
||||
|
||||
enum cvp_event_t {
|
||||
CVP_NO_EVENT,
|
||||
CVP_SSR_EVENT = 1,
|
||||
CVP_SYS_ERROR_EVENT,
|
||||
CVP_MAX_CLIENTS_EVENT,
|
||||
CVP_HW_UNSUPPORTED_EVENT,
|
||||
CVP_INVALID_EVENT,
|
||||
};
|
||||
|
||||
struct cvp_session_event {
|
||||
spinlock_t lock;
|
||||
enum cvp_event_t event;
|
||||
wait_queue_head_t wq;
|
||||
};
|
||||
|
||||
struct msm_cvp_core {
|
||||
struct list_head list;
|
||||
struct mutex lock;
|
||||
int id;
|
||||
dev_t dev_num;
|
||||
struct cdev cdev;
|
||||
struct class *class;
|
||||
struct device *dev;
|
||||
struct cvp_hfi_device *device;
|
||||
struct msm_cvp_platform_data *platform_data;
|
||||
struct list_head instances;
|
||||
struct dentry *debugfs_root;
|
||||
enum cvp_core_state state;
|
||||
struct completion completions[SYS_MSG_END - SYS_MSG_START + 1];
|
||||
enum msm_cvp_hfi_type hfi_type;
|
||||
struct msm_cvp_platform_resources resources;
|
||||
struct msm_cvp_capability *capabilities;
|
||||
struct delayed_work fw_unload_work;
|
||||
struct work_struct ssr_work;
|
||||
enum hal_ssr_trigger_type ssr_type;
|
||||
bool smmu_fault_handled;
|
||||
u32 last_fault_addr;
|
||||
bool trigger_ssr;
|
||||
unsigned long min_freq;
|
||||
unsigned long curr_freq;
|
||||
struct msm_cvp_core_ops *core_ops;
|
||||
atomic64_t kernel_trans_id;
|
||||
};
|
||||
|
||||
struct msm_cvp_inst {
|
||||
struct list_head list;
|
||||
struct mutex sync_lock, lock;
|
||||
struct msm_cvp_core *core;
|
||||
enum session_type session_type;
|
||||
struct cvp_session_queue session_queue;
|
||||
struct cvp_session_event event_handler;
|
||||
void *session;
|
||||
enum instance_state state;
|
||||
struct msm_cvp_list freqs;
|
||||
struct msm_cvp_list persistbufs;
|
||||
struct msm_cvp_list cvpcpubufs;
|
||||
struct msm_cvp_list cvpdspbufs;
|
||||
struct msm_cvp_list frames;
|
||||
struct completion completions[SESSION_MSG_END - SESSION_MSG_START + 1];
|
||||
struct dentry *debugfs_root;
|
||||
struct msm_cvp_debug debug;
|
||||
struct cvp_clock_data clk_data;
|
||||
enum msm_cvp_modes flags;
|
||||
struct msm_cvp_capability capability;
|
||||
struct kref kref;
|
||||
unsigned long deprecate_bitmask;
|
||||
struct cvp_kmd_request_power power;
|
||||
struct cvp_session_prop prop;
|
||||
u32 cur_cmd_type;
|
||||
struct mutex fence_lock;
|
||||
};
|
||||
|
||||
struct msm_cvp_fence_thread_data {
|
||||
struct msm_cvp_inst *inst;
|
||||
unsigned int device_id;
|
||||
struct cvp_kmd_hfi_fence_packet in_fence_pkt;
|
||||
unsigned int arg_type;
|
||||
};
|
||||
|
||||
extern struct msm_cvp_drv *cvp_driver;
|
||||
|
||||
void cvp_handle_cmd_response(enum hal_command_response cmd, void *data);
|
||||
int msm_cvp_trigger_ssr(struct msm_cvp_core *core,
|
||||
enum hal_ssr_trigger_type type);
|
||||
int msm_cvp_noc_error_info(struct msm_cvp_core *core);
|
||||
|
||||
enum msm_cvp_flags {
|
||||
MSM_CVP_FLAG_DEFERRED = BIT(0),
|
||||
MSM_CVP_FLAG_RBR_PENDING = BIT(1),
|
||||
MSM_CVP_FLAG_QUEUED = BIT(2),
|
||||
};
|
||||
|
||||
struct msm_cvp_internal_buffer {
|
||||
struct list_head list;
|
||||
struct msm_cvp_smem smem;
|
||||
struct cvp_kmd_buffer buf;
|
||||
};
|
||||
|
||||
struct msm_cvp_frame_buf {
|
||||
struct list_head list;
|
||||
struct cvp_buf_type buf;
|
||||
};
|
||||
|
||||
struct msm_cvp_frame {
|
||||
struct list_head list;
|
||||
struct msm_cvp_list bufs;
|
||||
u64 ktid;
|
||||
};
|
||||
|
||||
void msm_cvp_comm_handle_thermal_event(void);
|
||||
int msm_cvp_smem_alloc(size_t size, u32 align, u32 flags, int map_kernel,
|
||||
void *res, u32 session_type, struct msm_cvp_smem *smem);
|
||||
int msm_cvp_smem_free(struct msm_cvp_smem *smem);
|
||||
|
||||
struct context_bank_info *msm_cvp_smem_get_context_bank(u32 session_type,
|
||||
bool is_secure, struct msm_cvp_platform_resources *res,
|
||||
unsigned long ion_flags);
|
||||
int msm_cvp_smem_map_dma_buf(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_smem *smem);
|
||||
int msm_cvp_smem_unmap_dma_buf(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_smem *smem);
|
||||
struct dma_buf *msm_cvp_smem_get_dma_buf(int fd);
|
||||
void msm_cvp_smem_put_dma_buf(void *dma_buf);
|
||||
int msm_cvp_smem_cache_operations(struct dma_buf *dbuf,
|
||||
enum smem_cache_ops cache_op, unsigned long offset, unsigned long size);
|
||||
void msm_cvp_fw_unload_handler(struct work_struct *work);
|
||||
void msm_cvp_ssr_handler(struct work_struct *work);
|
||||
/*
|
||||
* XXX: normally should be in msm_cvp_core.h, but that's meant for public APIs,
|
||||
* whereas this is private
|
||||
*/
|
||||
int msm_cvp_destroy(struct msm_cvp_inst *inst);
|
||||
void *cvp_get_drv_data(struct device *dev);
|
||||
#endif
|
672
drivers/media/platform/msm/cvp/msm_cvp_ioctl.c
Normal file
672
drivers/media/platform/msm/cvp/msm_cvp_ioctl.c
Normal file
@ -0,0 +1,672 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "cvp_private.h"
|
||||
#include "cvp_hfi_api.h"
|
||||
|
||||
static int _get_pkt_hdr_from_user(struct cvp_kmd_arg __user *up,
|
||||
struct cvp_hal_session_cmd_pkt *pkt_hdr)
|
||||
{
|
||||
struct cvp_kmd_hfi_packet *u;
|
||||
|
||||
u = &up->data.hfi_pkt;
|
||||
|
||||
if (get_user(pkt_hdr->size, &u->pkt_data[0]))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(pkt_hdr->packet_type, &u->pkt_data[1]))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_pkt_index(pkt_hdr) < 0) {
|
||||
dprintk(CVP_ERR, "user mode provides incorrect hfi\n");
|
||||
goto set_default_pkt_hdr;
|
||||
}
|
||||
|
||||
if (pkt_hdr->size > MAX_HFI_PKT_SIZE*sizeof(unsigned int)) {
|
||||
dprintk(CVP_ERR, "user HFI packet too large %x\n",
|
||||
pkt_hdr->size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
set_default_pkt_hdr:
|
||||
pkt_hdr->size = get_msg_size();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_fence_pkt_hdr_from_user(struct cvp_kmd_arg __user *up,
|
||||
struct cvp_hal_session_cmd_pkt *pkt_hdr)
|
||||
{
|
||||
struct cvp_kmd_hfi_fence_packet *u;
|
||||
|
||||
u = &up->data.hfi_fence_pkt;
|
||||
|
||||
if (get_user(pkt_hdr->size, &u->pkt_data[0]))
|
||||
return -EFAULT;
|
||||
|
||||
if (get_user(pkt_hdr->packet_type, &u->pkt_data[1]))
|
||||
return -EFAULT;
|
||||
|
||||
if (pkt_hdr->size > (MAX_HFI_PKT_SIZE*sizeof(unsigned int)))
|
||||
return -EINVAL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Size is in unit of u32 */
|
||||
static int _copy_pkt_from_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up,
|
||||
unsigned int size)
|
||||
{
|
||||
struct cvp_kmd_hfi_packet *k, *u;
|
||||
int i;
|
||||
|
||||
k = &kp->data.hfi_pkt;
|
||||
u = &up->data.hfi_pkt;
|
||||
for (i = 0; i < size; i++)
|
||||
if (get_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Size is in unit of u32 */
|
||||
static int _copy_fence_pkt_from_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up,
|
||||
unsigned int size)
|
||||
{
|
||||
struct cvp_kmd_hfi_fence_packet *k, *u;
|
||||
int i;
|
||||
|
||||
k = &kp->data.hfi_fence_pkt;
|
||||
u = &up->data.hfi_fence_pkt;
|
||||
for (i = 0; i < MAX_HFI_FENCE_OFFSET; i++) {
|
||||
if (get_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
for (i = 0; i < MAX_HFI_FENCE_SIZE; i++) {
|
||||
if (get_user(k->fence_data[i], &u->fence_data[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _copy_sysprop_from_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up)
|
||||
{
|
||||
struct cvp_kmd_sys_properties *k, *u;
|
||||
|
||||
k = &kp->data.sys_properties;
|
||||
u = &up->data.sys_properties;
|
||||
|
||||
if (get_user(k->prop_num, &u->prop_num))
|
||||
return -EFAULT;
|
||||
|
||||
if (k->prop_num < 1 || k->prop_num > 32) {
|
||||
dprintk(CVP_ERR, "Num of prop out of range %d\n", k->prop_num);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return _copy_pkt_from_user(kp, up,
|
||||
(k->prop_num*((sizeof(struct cvp_kmd_sys_property)>>2)+1)));
|
||||
}
|
||||
|
||||
static int _copy_pkt_to_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up,
|
||||
unsigned int size)
|
||||
{
|
||||
struct cvp_kmd_hfi_packet *k, *u;
|
||||
int i;
|
||||
|
||||
k = &kp->data.hfi_pkt;
|
||||
u = &up->data.hfi_pkt;
|
||||
for (i = 0; i < size; i++)
|
||||
if (put_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _copy_fence_pkt_to_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up,
|
||||
unsigned int size)
|
||||
{
|
||||
struct cvp_kmd_hfi_fence_packet *k, *u;
|
||||
int i;
|
||||
|
||||
k = &kp->data.hfi_fence_pkt;
|
||||
u = &up->data.hfi_fence_pkt;
|
||||
for (i = 0; i < MAX_HFI_FENCE_OFFSET; i++) {
|
||||
if (put_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
for (i = 0; i < MAX_HFI_FENCE_SIZE; i++) {
|
||||
if (put_user(k->fence_data[i], &u->fence_data[i]))
|
||||
return -EFAULT;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _copy_sysprop_to_user(struct cvp_kmd_arg *kp,
|
||||
struct cvp_kmd_arg __user *up)
|
||||
{
|
||||
struct cvp_kmd_sys_properties *k, *u;
|
||||
|
||||
k = &kp->data.sys_properties;
|
||||
u = &up->data.sys_properties;
|
||||
|
||||
if (put_user(k->prop_data.data, &u->prop_data.data))
|
||||
return -EFAULT;
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
static void _set_deprecate_bitmask(struct cvp_kmd_arg *kp,
|
||||
struct msm_cvp_inst *inst)
|
||||
{
|
||||
dprintk(CVP_INFO, "%s: kp->type = %#x\n", __func__, kp->type);
|
||||
|
||||
switch (kp->type) {
|
||||
case CVP_KMD_HFI_DFS_FRAME_CMD:
|
||||
{
|
||||
set_bit(DFS_BIT_OFFSET, &inst->deprecate_bitmask);
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_DME_FRAME_CMD:
|
||||
{
|
||||
set_bit(DME_BIT_OFFSET, &inst->deprecate_bitmask);
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_DME_FRAME_FENCE_CMD:
|
||||
{
|
||||
set_bit(DME_BIT_OFFSET, &inst->deprecate_bitmask);
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_FD_FRAME_CMD:
|
||||
{
|
||||
set_bit(FD_BIT_OFFSET, &inst->deprecate_bitmask);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static void print_hfi_short(struct cvp_kmd_arg __user *up)
|
||||
{
|
||||
struct cvp_kmd_hfi_packet *pkt;
|
||||
unsigned int words[5];
|
||||
|
||||
pkt = &up->data.hfi_pkt;
|
||||
if (get_user(words[0], &up->type) ||
|
||||
get_user(words[1], &up->buf_offset) ||
|
||||
get_user(words[2], &up->buf_num) ||
|
||||
get_user(words[3], &pkt->pkt_data[0]) ||
|
||||
get_user(words[4], &pkt->pkt_data[1]))
|
||||
dprintk(CVP_ERR, "Failed to print ioctl cmd\n");
|
||||
|
||||
dprintk(CVP_DBG, "IOCTL cmd type %#x, offset %d, num %d, pkt %d %#x\n",
|
||||
words[0], words[1], words[2], words[3], words[4]);
|
||||
}
|
||||
|
||||
static int _copy_session_ctrl_to_user(
|
||||
struct cvp_kmd_session_control *k,
|
||||
struct cvp_kmd_session_control *u)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (put_user(k->ctrl_type, &u->ctrl_type))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 8; i++)
|
||||
if (put_user(k->ctrl_data[i], &u->ctrl_data[i]))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int _get_session_ctrl_from_user(
|
||||
struct cvp_kmd_session_control *k,
|
||||
struct cvp_kmd_session_control *u)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (get_user(k->ctrl_type, &u->ctrl_type))
|
||||
return -EFAULT;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
if (get_user(k->ctrl_data[i], &u->ctrl_data[i]))
|
||||
return -EFAULT;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int convert_from_user(struct cvp_kmd_arg *kp,
|
||||
unsigned long arg,
|
||||
struct msm_cvp_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
int i;
|
||||
struct cvp_kmd_arg __user *up = (struct cvp_kmd_arg *)arg;
|
||||
struct cvp_hal_session_cmd_pkt pkt_hdr;
|
||||
int pkt_idx;
|
||||
|
||||
if (!kp || !up) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
print_hfi_short(up);
|
||||
|
||||
if (get_user(kp->type, &up->type))
|
||||
return -EFAULT;
|
||||
|
||||
_set_deprecate_bitmask(kp, inst);
|
||||
|
||||
if (get_user(kp->buf_offset, &up->buf_offset) ||
|
||||
get_user(kp->buf_num, &up->buf_num))
|
||||
return -EFAULT;
|
||||
|
||||
switch (kp->type) {
|
||||
case CVP_KMD_GET_SESSION_INFO:
|
||||
{
|
||||
struct cvp_kmd_session_info *k, *u;
|
||||
|
||||
k = &kp->data.session;
|
||||
u = &up->data.session;
|
||||
if (get_user(k->session_id, &u->session_id))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 10; i++)
|
||||
if (get_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_REQUEST_POWER:
|
||||
{
|
||||
struct cvp_kmd_request_power *k, *u;
|
||||
|
||||
k = &kp->data.req_power;
|
||||
u = &up->data.req_power;
|
||||
if (get_user(k->clock_cycles_a, &u->clock_cycles_a) ||
|
||||
get_user(k->clock_cycles_b, &u->clock_cycles_b) ||
|
||||
get_user(k->ddr_bw, &u->ddr_bw) ||
|
||||
get_user(k->sys_cache_bw, &u->sys_cache_bw))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 8; i++)
|
||||
if (get_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_REGISTER_BUFFER:
|
||||
{
|
||||
struct cvp_kmd_buffer *k, *u;
|
||||
|
||||
k = &kp->data.regbuf;
|
||||
u = &up->data.regbuf;
|
||||
if (get_user(k->type, &u->type) ||
|
||||
get_user(k->index, &u->index) ||
|
||||
get_user(k->fd, &u->fd) ||
|
||||
get_user(k->size, &u->size) ||
|
||||
get_user(k->offset, &u->offset) ||
|
||||
get_user(k->pixelformat, &u->pixelformat) ||
|
||||
get_user(k->flags, &u->flags))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 5; i++)
|
||||
if (get_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_UNREGISTER_BUFFER:
|
||||
{
|
||||
struct cvp_kmd_buffer *k, *u;
|
||||
|
||||
k = &kp->data.unregbuf;
|
||||
u = &up->data.unregbuf;
|
||||
if (get_user(k->type, &u->type) ||
|
||||
get_user(k->index, &u->index) ||
|
||||
get_user(k->fd, &u->fd) ||
|
||||
get_user(k->size, &u->size) ||
|
||||
get_user(k->offset, &u->offset) ||
|
||||
get_user(k->pixelformat, &u->pixelformat) ||
|
||||
get_user(k->flags, &u->flags))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 5; i++)
|
||||
if (get_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_SEND_CMD:
|
||||
{
|
||||
struct cvp_kmd_send_cmd *k, *u;
|
||||
|
||||
k = &kp->data.send_cmd;
|
||||
u = &up->data.send_cmd;
|
||||
if (get_user(k->cmd_address_fd, &u->cmd_address_fd) ||
|
||||
get_user(k->cmd_size, &u->cmd_size))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 10; i++)
|
||||
if (get_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SEND_CMD_PKT:
|
||||
case CVP_KMD_HFI_DFS_CONFIG_CMD:
|
||||
case CVP_KMD_HFI_DFS_FRAME_CMD:
|
||||
case CVP_KMD_HFI_DME_CONFIG_CMD:
|
||||
case CVP_KMD_HFI_DME_FRAME_CMD:
|
||||
case CVP_KMD_HFI_PERSIST_CMD:
|
||||
case CVP_KMD_HFI_FD_FRAME_CMD:
|
||||
{
|
||||
if (_get_pkt_hdr_from_user(up, &pkt_hdr)) {
|
||||
dprintk(CVP_ERR, "Invalid syscall: %x, %x, %x\n",
|
||||
kp->type, pkt_hdr.size, pkt_hdr.packet_type);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = _copy_pkt_from_user(kp, up, (pkt_hdr.size >> 2));
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SEND_FENCE_CMD_PKT:
|
||||
case CVP_KMD_HFI_DME_FRAME_FENCE_CMD:
|
||||
{
|
||||
if (_get_fence_pkt_hdr_from_user(up, &pkt_hdr)) {
|
||||
dprintk(CVP_ERR, "Invalid syscall: %x, %x, %x\n",
|
||||
kp->type, pkt_hdr.size, pkt_hdr.packet_type);
|
||||
return -EFAULT;
|
||||
}
|
||||
dprintk(CVP_DBG, "system call cmd pkt: %d 0x%x\n",
|
||||
pkt_hdr.size, pkt_hdr.packet_type);
|
||||
|
||||
pkt_idx = get_pkt_index(&pkt_hdr);
|
||||
if (pkt_idx < 0) {
|
||||
dprintk(CVP_ERR, "%s incorrect packet %d, %x\n",
|
||||
__func__,
|
||||
pkt_hdr.size,
|
||||
pkt_hdr.packet_type);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
set_feature_bitmask(pkt_idx, &inst->deprecate_bitmask);
|
||||
|
||||
rc = _copy_fence_pkt_from_user(kp, up, (pkt_hdr.size >> 2));
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_DFS_FRAME_CMD_RESPONSE:
|
||||
case CVP_KMD_HFI_DME_FRAME_CMD_RESPONSE:
|
||||
case CVP_KMD_HFI_PERSIST_CMD_RESPONSE:
|
||||
case CVP_KMD_RECEIVE_MSG_PKT:
|
||||
break;
|
||||
case CVP_KMD_SESSION_CONTROL:
|
||||
{
|
||||
struct cvp_kmd_session_control *k, *u;
|
||||
|
||||
k = &kp->data.session_ctrl;
|
||||
u = &up->data.session_ctrl;
|
||||
|
||||
rc = _get_session_ctrl_from_user(k, u);
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_GET_SYS_PROPERTY:
|
||||
{
|
||||
if (_copy_sysprop_from_user(kp, up)) {
|
||||
dprintk(CVP_ERR, "Failed to get sysprop from user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SET_SYS_PROPERTY:
|
||||
{
|
||||
if (_copy_sysprop_from_user(kp, up)) {
|
||||
dprintk(CVP_ERR, "Failed to set sysprop from user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_UPDATE_POWER:
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR, "%s: unknown cmd type 0x%x\n",
|
||||
__func__, kp->type);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int convert_to_user(struct cvp_kmd_arg *kp, unsigned long arg)
|
||||
{
|
||||
int rc = 0;
|
||||
int i, size = get_msg_size() >> 2;
|
||||
struct cvp_kmd_arg __user *up = (struct cvp_kmd_arg *)arg;
|
||||
struct cvp_hal_session_cmd_pkt pkt_hdr;
|
||||
|
||||
if (!kp || !up) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (put_user(kp->type, &up->type))
|
||||
return -EFAULT;
|
||||
|
||||
switch (kp->type) {
|
||||
case CVP_KMD_RECEIVE_MSG_PKT:
|
||||
{
|
||||
struct cvp_kmd_hfi_packet *k, *u;
|
||||
|
||||
k = &kp->data.hfi_pkt;
|
||||
u = &up->data.hfi_pkt;
|
||||
for (i = 0; i < size; i++)
|
||||
if (put_user(k->pkt_data[i], &u->pkt_data[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_GET_SESSION_INFO:
|
||||
{
|
||||
struct cvp_kmd_session_info *k, *u;
|
||||
|
||||
k = &kp->data.session;
|
||||
u = &up->data.session;
|
||||
if (put_user(k->session_id, &u->session_id))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 10; i++)
|
||||
if (put_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_REQUEST_POWER:
|
||||
{
|
||||
struct cvp_kmd_request_power *k, *u;
|
||||
|
||||
k = &kp->data.req_power;
|
||||
u = &up->data.req_power;
|
||||
if (put_user(k->clock_cycles_a, &u->clock_cycles_a) ||
|
||||
put_user(k->clock_cycles_b, &u->clock_cycles_b) ||
|
||||
put_user(k->ddr_bw, &u->ddr_bw) ||
|
||||
put_user(k->sys_cache_bw, &u->sys_cache_bw))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 8; i++)
|
||||
if (put_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_REGISTER_BUFFER:
|
||||
{
|
||||
struct cvp_kmd_buffer *k, *u;
|
||||
|
||||
k = &kp->data.regbuf;
|
||||
u = &up->data.regbuf;
|
||||
if (put_user(k->type, &u->type) ||
|
||||
put_user(k->index, &u->index) ||
|
||||
put_user(k->fd, &u->fd) ||
|
||||
put_user(k->size, &u->size) ||
|
||||
put_user(k->offset, &u->offset) ||
|
||||
put_user(k->pixelformat, &u->pixelformat) ||
|
||||
put_user(k->flags, &u->flags))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 5; i++)
|
||||
if (put_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_UNREGISTER_BUFFER:
|
||||
{
|
||||
struct cvp_kmd_buffer *k, *u;
|
||||
|
||||
k = &kp->data.unregbuf;
|
||||
u = &up->data.unregbuf;
|
||||
if (put_user(k->type, &u->type) ||
|
||||
put_user(k->index, &u->index) ||
|
||||
put_user(k->fd, &u->fd) ||
|
||||
put_user(k->size, &u->size) ||
|
||||
put_user(k->offset, &u->offset) ||
|
||||
put_user(k->pixelformat, &u->pixelformat) ||
|
||||
put_user(k->flags, &u->flags))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 5; i++)
|
||||
if (put_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_HFI_SEND_CMD:
|
||||
{
|
||||
struct cvp_kmd_send_cmd *k, *u;
|
||||
|
||||
dprintk(CVP_DBG, "%s: CVP_KMD_HFI_SEND_CMD\n",
|
||||
__func__);
|
||||
|
||||
k = &kp->data.send_cmd;
|
||||
u = &up->data.send_cmd;
|
||||
if (put_user(k->cmd_address_fd, &u->cmd_address_fd) ||
|
||||
put_user(k->cmd_size, &u->cmd_size))
|
||||
return -EFAULT;
|
||||
for (i = 0; i < 10; i++)
|
||||
if (put_user(k->reserved[i], &u->reserved[i]))
|
||||
return -EFAULT;
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SEND_CMD_PKT:
|
||||
case CVP_KMD_HFI_DFS_CONFIG_CMD:
|
||||
case CVP_KMD_HFI_DFS_FRAME_CMD:
|
||||
case CVP_KMD_HFI_DFS_FRAME_CMD_RESPONSE:
|
||||
case CVP_KMD_HFI_DME_CONFIG_CMD:
|
||||
case CVP_KMD_HFI_DME_FRAME_CMD:
|
||||
case CVP_KMD_HFI_DME_FRAME_CMD_RESPONSE:
|
||||
case CVP_KMD_HFI_PERSIST_CMD:
|
||||
case CVP_KMD_HFI_PERSIST_CMD_RESPONSE:
|
||||
case CVP_KMD_HFI_FD_FRAME_CMD:
|
||||
{
|
||||
if (_get_pkt_hdr_from_user(up, &pkt_hdr))
|
||||
return -EFAULT;
|
||||
|
||||
dprintk(CVP_DBG, "Send user cmd pkt: %d %d\n",
|
||||
pkt_hdr.size, pkt_hdr.packet_type);
|
||||
rc = _copy_pkt_to_user(kp, up, (pkt_hdr.size >> 2));
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SEND_FENCE_CMD_PKT:
|
||||
case CVP_KMD_HFI_DME_FRAME_FENCE_CMD:
|
||||
{
|
||||
if (_get_fence_pkt_hdr_from_user(up, &pkt_hdr))
|
||||
return -EFAULT;
|
||||
|
||||
dprintk(CVP_DBG, "Send user cmd pkt: %d %d\n",
|
||||
pkt_hdr.size, pkt_hdr.packet_type);
|
||||
|
||||
rc = _copy_fence_pkt_to_user(kp, up, (pkt_hdr.size >> 2));
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SESSION_CONTROL:
|
||||
{
|
||||
struct cvp_kmd_session_control *k, *u;
|
||||
|
||||
k = &kp->data.session_ctrl;
|
||||
u = &up->data.session_ctrl;
|
||||
rc = _copy_session_ctrl_to_user(k, u);
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_GET_SYS_PROPERTY:
|
||||
{
|
||||
if (_copy_sysprop_to_user(kp, up)) {
|
||||
dprintk(CVP_ERR, "Fail to copy sysprop to user\n");
|
||||
return -EFAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CVP_KMD_SET_SYS_PROPERTY:
|
||||
break;
|
||||
case CVP_KMD_UPDATE_POWER:
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR, "%s: unknown cmd type 0x%x\n",
|
||||
__func__, kp->type);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static long cvp_ioctl(struct msm_cvp_inst *inst,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
int rc;
|
||||
struct cvp_kmd_arg karg;
|
||||
|
||||
if (!inst) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
memset(&karg, 0, sizeof(struct cvp_kmd_arg));
|
||||
|
||||
if (convert_from_user(&karg, arg, inst)) {
|
||||
dprintk(CVP_ERR, "%s: failed to get from user cmd %x\n",
|
||||
__func__, karg.type);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
rc = msm_cvp_private((void *)inst, cmd, &karg);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "%s: failed cmd type %x %d\n",
|
||||
__func__, karg.type, rc);
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (convert_to_user(&karg, arg)) {
|
||||
dprintk(CVP_ERR, "%s: failed to copy to user cmd %x\n",
|
||||
__func__, karg.type);
|
||||
return -EFAULT;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
long cvp_unblocked_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct msm_cvp_inst *inst;
|
||||
|
||||
if (!filp || !filp->private_data) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst = filp->private_data;
|
||||
return cvp_ioctl(inst, cmd, arg);
|
||||
}
|
||||
|
||||
long cvp_compat_ioctl(struct file *filp,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
struct msm_cvp_inst *inst;
|
||||
|
||||
if (!filp || !filp->private_data) {
|
||||
dprintk(CVP_ERR, "%s: invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
inst = filp->private_data;
|
||||
return cvp_ioctl(inst, cmd, (unsigned long)compat_ptr(arg));
|
||||
}
|
229
drivers/media/platform/msm/cvp/msm_cvp_platform.c
Normal file
229
drivers/media/platform/msm/cvp/msm_cvp_platform.c
Normal file
@ -0,0 +1,229 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/debugfs.h>
|
||||
#include <linux/dma-mapping.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/ioctl.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of_fdt.h>
|
||||
#include "msm_cvp_internal.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
|
||||
#define DDR_TYPE_LPDDR4 0x6
|
||||
#define DDR_TYPE_LPDDR4X 0x7
|
||||
#define DDR_TYPE_LPDDR4Y 0x8
|
||||
#define DDR_TYPE_LPDDR5 0x9
|
||||
|
||||
#define UBWC_CONFIG(mco, mlo, hbo, bslo, bso, rs, mc, ml, hbb, bsl, bsp) \
|
||||
{ \
|
||||
.override_bit_info.max_channel_override = mco, \
|
||||
.override_bit_info.mal_length_override = mlo, \
|
||||
.override_bit_info.hb_override = hbo, \
|
||||
.override_bit_info.bank_swzl_level_override = bslo, \
|
||||
.override_bit_info.bank_spreading_override = bso, \
|
||||
.override_bit_info.reserved = rs, \
|
||||
.max_channels = mc, \
|
||||
.mal_length = ml, \
|
||||
.highest_bank_bit = hbb, \
|
||||
.bank_swzl_level = bsl, \
|
||||
.bank_spreading = bsp, \
|
||||
}
|
||||
|
||||
static struct msm_cvp_common_data default_common_data[] = {
|
||||
{
|
||||
.key = "qcom,never-unload-fw",
|
||||
.value = 1,
|
||||
},
|
||||
};
|
||||
|
||||
static struct msm_cvp_common_data sm8250_common_data[] = {
|
||||
{
|
||||
.key = "qcom,never-unload-fw",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,sw-power-collapse",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,domain-attr-non-fatal-faults",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,max-secure-instances",
|
||||
.value = 2, /*
|
||||
* As per design driver allows 3rd
|
||||
* instance as well since the secure
|
||||
* flags were updated later for the
|
||||
* current instance. Hence total
|
||||
* secure sessions would be
|
||||
* max-secure-instances + 1.
|
||||
*/
|
||||
},
|
||||
{
|
||||
.key = "qcom,max-hw-load",
|
||||
.value = 3916800, /*
|
||||
* 1920x1088/256 MBs@480fps. It is less
|
||||
* any other usecases (ex:
|
||||
* 3840x2160@120fps, 4096x2160@96ps,
|
||||
* 7680x4320@30fps)
|
||||
*/
|
||||
},
|
||||
{
|
||||
.key = "qcom,power-collapse-delay",
|
||||
.value = 3000,
|
||||
},
|
||||
{
|
||||
.key = "qcom,hw-resp-timeout",
|
||||
.value = 2000,
|
||||
},
|
||||
{
|
||||
.key = "qcom,dsp-resp-timeout",
|
||||
.value = 1000
|
||||
},
|
||||
{
|
||||
.key = "qcom,debug-timeout",
|
||||
.value = 0,
|
||||
}
|
||||
};
|
||||
|
||||
static struct msm_cvp_common_data sm8350_common_data[] = {
|
||||
{
|
||||
.key = "qcom,never-unload-fw",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,sw-power-collapse",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,domain-attr-non-fatal-faults",
|
||||
.value = 1,
|
||||
},
|
||||
{
|
||||
.key = "qcom,max-secure-instances",
|
||||
.value = 2, /*
|
||||
* As per design driver allows 3rd
|
||||
* instance as well since the secure
|
||||
* flags were updated later for the
|
||||
* current instance. Hence total
|
||||
* secure sessions would be
|
||||
* max-secure-instances + 1.
|
||||
*/
|
||||
},
|
||||
{
|
||||
.key = "qcom,max-hw-load",
|
||||
.value = 3916800, /*
|
||||
* 1920x1088/256 MBs@480fps. It is less
|
||||
* any other usecases (ex:
|
||||
* 3840x2160@120fps, 4096x2160@96ps,
|
||||
* 7680x4320@30fps)
|
||||
*/
|
||||
},
|
||||
{
|
||||
.key = "qcom,power-collapse-delay",
|
||||
.value = 3000,
|
||||
},
|
||||
{
|
||||
.key = "qcom,hw-resp-timeout",
|
||||
.value = 2000,
|
||||
},
|
||||
{
|
||||
.key = "qcom,dsp-resp-timeout",
|
||||
.value = 1000
|
||||
},
|
||||
{
|
||||
.key = "qcom,debug-timeout",
|
||||
.value = 0,
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/* Default UBWC config for LPDDR5 */
|
||||
static struct msm_cvp_ubwc_config_data kona_ubwc_data[] = {
|
||||
UBWC_CONFIG(1, 1, 1, 0, 0, 0, 8, 32, 16, 0, 0),
|
||||
};
|
||||
|
||||
|
||||
static struct msm_cvp_platform_data default_data = {
|
||||
.common_data = default_common_data,
|
||||
.common_data_length = ARRAY_SIZE(default_common_data),
|
||||
.sku_version = 0,
|
||||
.vpu_ver = VPU_VERSION_5,
|
||||
.ubwc_config = 0x0,
|
||||
};
|
||||
|
||||
static struct msm_cvp_platform_data sm8250_data = {
|
||||
.common_data = sm8250_common_data,
|
||||
.common_data_length = ARRAY_SIZE(sm8250_common_data),
|
||||
.sku_version = 0,
|
||||
.vpu_ver = VPU_VERSION_5,
|
||||
.ubwc_config = kona_ubwc_data,
|
||||
};
|
||||
|
||||
static struct msm_cvp_platform_data sm8350_data = {
|
||||
.common_data = sm8350_common_data,
|
||||
.common_data_length = ARRAY_SIZE(sm8350_common_data),
|
||||
.sku_version = 0,
|
||||
.vpu_ver = VPU_VERSION_5,
|
||||
.ubwc_config = kona_ubwc_data,
|
||||
};
|
||||
|
||||
static const struct of_device_id msm_cvp_dt_match[] = {
|
||||
{
|
||||
.compatible = "qcom,lahaina-cvp",
|
||||
.data = &sm8350_data,
|
||||
},
|
||||
{
|
||||
.compatible = "qcom,kona-cvp",
|
||||
.data = &sm8250_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE(of, msm_cvp_dt_match);
|
||||
|
||||
void *cvp_get_drv_data(struct device *dev)
|
||||
{
|
||||
struct msm_cvp_platform_data *driver_data;
|
||||
const struct of_device_id *match;
|
||||
uint32_t ddr_type = DDR_TYPE_LPDDR5;
|
||||
|
||||
driver_data = &default_data;
|
||||
|
||||
if (!IS_ENABLED(CONFIG_OF) || !dev->of_node)
|
||||
goto exit;
|
||||
|
||||
match = of_match_node(msm_cvp_dt_match, dev->of_node);
|
||||
|
||||
if (!match)
|
||||
return NULL;
|
||||
|
||||
driver_data = (struct msm_cvp_platform_data *)match->data;
|
||||
|
||||
if (!strcmp(match->compatible, "qcom,kona-cvp")) {
|
||||
ddr_type = of_fdt_get_ddrtype();
|
||||
if (ddr_type == -ENOENT) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to get ddr type, use LPDDR5\n");
|
||||
}
|
||||
|
||||
if (driver_data->ubwc_config &&
|
||||
(ddr_type == DDR_TYPE_LPDDR4 ||
|
||||
ddr_type == DDR_TYPE_LPDDR4X ||
|
||||
ddr_type == DDR_TYPE_LPDDR4Y))
|
||||
driver_data->ubwc_config->highest_bank_bit = 15;
|
||||
}
|
||||
exit:
|
||||
return driver_data;
|
||||
}
|
1041
drivers/media/platform/msm/cvp/msm_cvp_res_parse.c
Normal file
1041
drivers/media/platform/msm/cvp/msm_cvp_res_parse.c
Normal file
File diff suppressed because it is too large
Load Diff
30
drivers/media/platform/msm/cvp/msm_cvp_res_parse.h
Normal file
30
drivers/media/platform/msm/cvp/msm_cvp_res_parse.h
Normal file
@ -0,0 +1,30 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_CVP_RES_PARSE_H__
|
||||
#define __MSM_CVP_RES_PARSE_H__
|
||||
#include <linux/of.h>
|
||||
#include "msm_cvp_resources.h"
|
||||
#include "msm_cvp_common.h"
|
||||
void msm_cvp_free_platform_resources(
|
||||
struct msm_cvp_platform_resources *res);
|
||||
|
||||
int read_hfi_type(struct platform_device *pdev);
|
||||
|
||||
int cvp_read_platform_resources_from_drv_data(
|
||||
struct msm_cvp_core *core);
|
||||
int cvp_read_platform_resources_from_dt(
|
||||
struct msm_cvp_platform_resources *res);
|
||||
|
||||
int cvp_read_context_bank_resources_from_dt(struct platform_device *pdev);
|
||||
|
||||
int cvp_read_bus_resources_from_dt(struct platform_device *pdev);
|
||||
int cvp_read_mem_cdsp_resources_from_dt(struct platform_device *pdev);
|
||||
|
||||
int msm_cvp_load_u32_table(struct platform_device *pdev,
|
||||
struct device_node *of_node, char *table_name, int struct_size,
|
||||
u32 **table, u32 *num_elements);
|
||||
|
||||
#endif
|
176
drivers/media/platform/msm/cvp/msm_cvp_resources.h
Normal file
176
drivers/media/platform/msm/cvp/msm_cvp_resources.h
Normal file
@ -0,0 +1,176 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#ifndef __MSM_CVP_RESOURCES_H__
|
||||
#define __MSM_CVP_RESOURCES_H__
|
||||
|
||||
#include <linux/devfreq.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include <linux/soc/qcom/llcc-qcom.h>
|
||||
|
||||
struct reg_value_pair {
|
||||
u32 reg;
|
||||
u32 value;
|
||||
};
|
||||
|
||||
struct reg_set {
|
||||
struct reg_value_pair *reg_tbl;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct addr_range {
|
||||
u32 start;
|
||||
u32 size;
|
||||
};
|
||||
|
||||
struct addr_set {
|
||||
struct addr_range *addr_tbl;
|
||||
int count;
|
||||
};
|
||||
|
||||
struct context_bank_info {
|
||||
struct list_head list;
|
||||
const char *name;
|
||||
u32 buffer_type;
|
||||
bool is_secure;
|
||||
struct addr_range addr_range;
|
||||
struct device *dev;
|
||||
struct iommu_domain *domain;
|
||||
};
|
||||
|
||||
struct regulator_info {
|
||||
struct regulator *regulator;
|
||||
bool has_hw_power_collapse;
|
||||
char *name;
|
||||
};
|
||||
|
||||
struct regulator_set {
|
||||
struct regulator_info *regulator_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct clock_info {
|
||||
const char *name;
|
||||
struct clk *clk;
|
||||
u32 count;
|
||||
bool has_scaling;
|
||||
bool has_mem_retention;
|
||||
};
|
||||
|
||||
struct clock_set {
|
||||
struct clock_info *clock_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct bus_info {
|
||||
char *name;
|
||||
int master;
|
||||
int slave;
|
||||
unsigned int range[2];
|
||||
const char *governor;
|
||||
struct device *dev;
|
||||
struct devfreq_dev_profile devfreq_prof;
|
||||
struct devfreq *devfreq;
|
||||
struct icc_path *client;
|
||||
bool is_prfm_gov_used;
|
||||
};
|
||||
|
||||
struct bus_set {
|
||||
struct bus_info *bus_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct reset_info {
|
||||
struct reset_control *rst;
|
||||
const char *name;
|
||||
};
|
||||
|
||||
struct reset_set {
|
||||
struct reset_info *reset_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct allowed_clock_rates_table {
|
||||
u32 clock_rate;
|
||||
};
|
||||
|
||||
struct clock_profile_entry {
|
||||
u32 codec_mask;
|
||||
u32 vpp_cycles;
|
||||
u32 vsp_cycles;
|
||||
u32 low_power_cycles;
|
||||
};
|
||||
|
||||
struct clock_freq_table {
|
||||
struct clock_profile_entry *clk_prof_entries;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct subcache_info {
|
||||
const char *name;
|
||||
bool isactive;
|
||||
bool isset;
|
||||
struct llcc_slice_desc *subcache;
|
||||
};
|
||||
|
||||
struct subcache_set {
|
||||
struct subcache_info *subcache_tbl;
|
||||
u32 count;
|
||||
};
|
||||
|
||||
struct msm_cvp_mem_cdsp {
|
||||
struct device *dev;
|
||||
};
|
||||
|
||||
struct msm_cvp_platform_resources {
|
||||
phys_addr_t firmware_base;
|
||||
phys_addr_t register_base;
|
||||
uint32_t register_size;
|
||||
uint32_t irq;
|
||||
uint32_t sku_version;
|
||||
struct allowed_clock_rates_table *allowed_clks_tbl;
|
||||
u32 allowed_clks_tbl_size;
|
||||
struct clock_freq_table clock_freq_tbl;
|
||||
bool sys_cache_present;
|
||||
bool sys_cache_res_set;
|
||||
struct subcache_set subcache_set;
|
||||
struct reg_set reg_set;
|
||||
struct addr_set qdss_addr_set;
|
||||
uint32_t max_load;
|
||||
struct platform_device *pdev;
|
||||
struct regulator_set regulator_set;
|
||||
struct clock_set clock_set;
|
||||
struct bus_set bus_set;
|
||||
struct reset_set reset_set;
|
||||
bool use_non_secure_pil;
|
||||
bool sw_power_collapsible;
|
||||
struct list_head context_banks;
|
||||
bool thermal_mitigable;
|
||||
const char *fw_name;
|
||||
const char *hfi_version;
|
||||
bool never_unload_fw;
|
||||
bool debug_timeout;
|
||||
uint32_t pm_qos_latency_us;
|
||||
uint32_t max_inst_count;
|
||||
uint32_t max_secure_inst_count;
|
||||
int msm_cvp_hw_rsp_timeout;
|
||||
int msm_cvp_dsp_rsp_timeout;
|
||||
int msm_cvp_firmware_unload_delay;
|
||||
uint32_t msm_cvp_pwr_collapse_delay;
|
||||
bool non_fatal_pagefaults;
|
||||
struct msm_cvp_mem_cdsp mem_cdsp;
|
||||
uint32_t vpu_ver;
|
||||
uint32_t fw_cycles;
|
||||
struct msm_cvp_ubwc_config_data *ubwc_config;
|
||||
};
|
||||
|
||||
static inline bool is_iommu_present(struct msm_cvp_platform_resources *res)
|
||||
{
|
||||
return !list_empty(&res->context_banks);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
552
drivers/media/platform/msm/cvp/msm_smem.c
Normal file
552
drivers/media/platform/msm/cvp/msm_smem.c
Normal file
@ -0,0 +1,552 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/dma-buf.h>
|
||||
#include <linux/dma-direction.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/msm_dma_iommu_mapping.h>
|
||||
#include <linux/ion.h>
|
||||
#include <linux/msm_ion.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/types.h>
|
||||
#include "msm_cvp_core.h"
|
||||
#include "msm_cvp_debug.h"
|
||||
#include "msm_cvp_resources.h"
|
||||
|
||||
|
||||
static int msm_dma_get_device_address(struct dma_buf *dbuf, u32 align,
|
||||
dma_addr_t *iova, u32 *buffer_size, u32 flags, unsigned long ion_flags,
|
||||
u32 session_type, struct msm_cvp_platform_resources *res,
|
||||
struct cvp_dma_mapping_info *mapping_info)
|
||||
{
|
||||
int rc = 0;
|
||||
struct dma_buf_attachment *attach;
|
||||
struct sg_table *table = NULL;
|
||||
struct context_bank_info *cb = NULL;
|
||||
|
||||
if (!dbuf || !iova || !buffer_size || !mapping_info) {
|
||||
dprintk(CVP_ERR, "Invalid params: %pK, %pK, %pK, %pK\n",
|
||||
dbuf, iova, buffer_size, mapping_info);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (is_iommu_present(res)) {
|
||||
cb = msm_cvp_smem_get_context_bank(
|
||||
session_type, (flags & SMEM_SECURE),
|
||||
res, ion_flags);
|
||||
if (!cb) {
|
||||
dprintk(CVP_ERR,
|
||||
"%s: Failed to get context bank device\n",
|
||||
__func__);
|
||||
rc = -EIO;
|
||||
goto mem_map_failed;
|
||||
}
|
||||
|
||||
/* Check if the dmabuf size matches expected size */
|
||||
if (dbuf->size < *buffer_size) {
|
||||
rc = -EINVAL;
|
||||
dprintk(CVP_ERR,
|
||||
"Size mismatch: Dmabuf size: %zu Expected Size: %lu",
|
||||
dbuf->size, *buffer_size);
|
||||
msm_cvp_res_handle_fatal_hw_error(res,
|
||||
true);
|
||||
goto mem_buf_size_mismatch;
|
||||
}
|
||||
|
||||
/* Prepare a dma buf for dma on the given device */
|
||||
attach = dma_buf_attach(dbuf, cb->dev);
|
||||
if (IS_ERR_OR_NULL(attach)) {
|
||||
rc = PTR_ERR(attach) ?: -ENOMEM;
|
||||
dprintk(CVP_ERR, "Failed to attach dmabuf\n");
|
||||
goto mem_buf_attach_failed;
|
||||
}
|
||||
|
||||
/*
|
||||
* Get the scatterlist for the given attachment
|
||||
* Mapping of sg is taken care by map attachment
|
||||
*/
|
||||
attach->dma_map_attrs = DMA_ATTR_DELAYED_UNMAP;
|
||||
/*
|
||||
* We do not need dma_map function to perform cache operations
|
||||
* on the whole buffer size and hence pass skip sync flag.
|
||||
* We do the required cache operations separately for the
|
||||
* required buffer size
|
||||
*/
|
||||
attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC;
|
||||
if (res->sys_cache_present)
|
||||
attach->dma_map_attrs |=
|
||||
DMA_ATTR_IOMMU_USE_UPSTREAM_HINT;
|
||||
|
||||
table = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL);
|
||||
if (IS_ERR_OR_NULL(table)) {
|
||||
rc = PTR_ERR(table) ?: -ENOMEM;
|
||||
dprintk(CVP_ERR, "Failed to map table\n");
|
||||
goto mem_map_table_failed;
|
||||
}
|
||||
|
||||
/* debug trace's need to be updated later */
|
||||
trace_msm_cvp_smem_buffer_iommu_op_start("MAP", 0, 0,
|
||||
align, *iova, *buffer_size);
|
||||
|
||||
if (table->sgl) {
|
||||
*iova = table->sgl->dma_address;
|
||||
*buffer_size = table->sgl->dma_length;
|
||||
} else {
|
||||
dprintk(CVP_ERR, "sgl is NULL\n");
|
||||
rc = -ENOMEM;
|
||||
goto mem_map_sg_failed;
|
||||
}
|
||||
|
||||
mapping_info->dev = cb->dev;
|
||||
mapping_info->domain = cb->domain;
|
||||
mapping_info->table = table;
|
||||
mapping_info->attach = attach;
|
||||
mapping_info->buf = dbuf;
|
||||
mapping_info->cb_info = (void *)cb;
|
||||
|
||||
trace_msm_cvp_smem_buffer_iommu_op_end("MAP", 0, 0,
|
||||
align, *iova, *buffer_size);
|
||||
} else {
|
||||
dprintk(CVP_DBG, "iommu not present, use phys mem addr\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
mem_map_sg_failed:
|
||||
dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL);
|
||||
mem_map_table_failed:
|
||||
dma_buf_detach(dbuf, attach);
|
||||
mem_buf_size_mismatch:
|
||||
mem_buf_attach_failed:
|
||||
mem_map_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int msm_dma_put_device_address(u32 flags,
|
||||
struct cvp_dma_mapping_info *mapping_info)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!mapping_info) {
|
||||
dprintk(CVP_WARN, "Invalid mapping_info\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (!mapping_info->dev || !mapping_info->table ||
|
||||
!mapping_info->buf || !mapping_info->attach ||
|
||||
!mapping_info->cb_info) {
|
||||
dprintk(CVP_WARN, "Invalid params\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
trace_msm_cvp_smem_buffer_iommu_op_start("UNMAP", 0, 0, 0, 0, 0);
|
||||
dma_buf_unmap_attachment(mapping_info->attach,
|
||||
mapping_info->table, DMA_BIDIRECTIONAL);
|
||||
dma_buf_detach(mapping_info->buf, mapping_info->attach);
|
||||
trace_msm_cvp_smem_buffer_iommu_op_end("UNMAP", 0, 0, 0, 0, 0);
|
||||
|
||||
mapping_info->dev = NULL;
|
||||
mapping_info->domain = NULL;
|
||||
mapping_info->table = NULL;
|
||||
mapping_info->attach = NULL;
|
||||
mapping_info->buf = NULL;
|
||||
mapping_info->cb_info = NULL;
|
||||
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct dma_buf *msm_cvp_smem_get_dma_buf(int fd)
|
||||
{
|
||||
struct dma_buf *dma_buf;
|
||||
|
||||
dma_buf = dma_buf_get(fd);
|
||||
if (IS_ERR_OR_NULL(dma_buf)) {
|
||||
dprintk(CVP_ERR, "Failed to get dma_buf for %d, error %ld\n",
|
||||
fd, PTR_ERR(dma_buf));
|
||||
dma_buf = NULL;
|
||||
}
|
||||
|
||||
return dma_buf;
|
||||
}
|
||||
|
||||
void msm_cvp_smem_put_dma_buf(void *dma_buf)
|
||||
{
|
||||
if (!dma_buf) {
|
||||
dprintk(CVP_ERR, "%s: NULL dma_buf\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
dma_buf_put((struct dma_buf *)dma_buf);
|
||||
}
|
||||
|
||||
int msm_cvp_smem_map_dma_buf(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_smem *smem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
dma_addr_t iova = 0;
|
||||
u32 temp = 0;
|
||||
u32 buffer_size = 0;
|
||||
u32 align = SZ_4K;
|
||||
struct dma_buf *dbuf;
|
||||
unsigned long ion_flags = 0;
|
||||
|
||||
if (!inst || !smem) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params: %pK %pK\n",
|
||||
__func__, inst, smem);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (smem->refcount) {
|
||||
smem->refcount++;
|
||||
return rc;
|
||||
}
|
||||
|
||||
if (smem->fd > 0) {
|
||||
dbuf = msm_cvp_smem_get_dma_buf(smem->fd);
|
||||
if (!dbuf) {
|
||||
rc = -EINVAL;
|
||||
dprintk(CVP_ERR, "%s: Invalid fd=%d", __func__,
|
||||
smem->fd);
|
||||
return rc;
|
||||
}
|
||||
smem->dma_buf = dbuf;
|
||||
} else {
|
||||
dbuf = smem->dma_buf;
|
||||
get_dma_buf(dbuf);
|
||||
}
|
||||
|
||||
rc = dma_buf_get_flags(dbuf, &ion_flags);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to get dma buf flags: %d\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
if (ion_flags & ION_FLAG_CACHED)
|
||||
smem->flags |= SMEM_CACHED;
|
||||
|
||||
if (ion_flags & ION_FLAG_SECURE)
|
||||
smem->flags |= SMEM_SECURE;
|
||||
|
||||
buffer_size = smem->size;
|
||||
if (smem->offset > dbuf->size - 1 ||
|
||||
smem->offset + buffer_size > dbuf->size) {
|
||||
dprintk(CVP_WARN, "%s: invalid offset %d or size %d\n",
|
||||
__func__, smem->offset, buffer_size);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Ignore the buffer_type from user space. Only use ion flags */
|
||||
rc = msm_dma_get_device_address(dbuf, align, &iova, &buffer_size,
|
||||
smem->flags, ion_flags, inst->session_type,
|
||||
&(inst->core->resources), &smem->mapping_info);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to get device address: %d\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
temp = (u32)iova;
|
||||
if ((dma_addr_t)temp != iova) {
|
||||
dprintk(CVP_ERR, "iova(%pa) truncated to %#x", &iova, temp);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
smem->device_addr = (u32)iova;
|
||||
smem->refcount++;
|
||||
|
||||
return rc;
|
||||
exit:
|
||||
dma_buf_put(dbuf);
|
||||
smem->device_addr = 0x0;
|
||||
smem->dma_buf = NULL;
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_cvp_smem_unmap_dma_buf(struct msm_cvp_inst *inst,
|
||||
struct msm_cvp_smem *smem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!inst || !smem) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params: %pK %pK\n",
|
||||
__func__, inst, smem);
|
||||
rc = -EINVAL;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (smem->refcount) {
|
||||
smem->refcount--;
|
||||
} else {
|
||||
dprintk(CVP_WARN,
|
||||
"unmap called while refcount is zero already\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (smem->refcount)
|
||||
goto exit;
|
||||
|
||||
rc = msm_dma_put_device_address(smem->flags, &smem->mapping_info);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to put device address: %d\n", rc);
|
||||
goto exit;
|
||||
}
|
||||
|
||||
msm_cvp_smem_put_dma_buf(smem->dma_buf);
|
||||
|
||||
smem->device_addr = 0x0;
|
||||
smem->dma_buf = NULL;
|
||||
|
||||
exit:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int alloc_dma_mem(size_t size, u32 align, u32 flags, int map_kernel,
|
||||
struct msm_cvp_platform_resources *res, u32 session_type,
|
||||
struct msm_cvp_smem *mem)
|
||||
{
|
||||
dma_addr_t iova = 0;
|
||||
u32 buffer_size = 0;
|
||||
unsigned long heap_mask = 0;
|
||||
int rc = 0;
|
||||
int ion_flags = 0;
|
||||
struct dma_buf *dbuf = NULL;
|
||||
|
||||
if (!res) {
|
||||
dprintk(CVP_ERR, "%s: NULL res\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
align = ALIGN(align, SZ_4K);
|
||||
size = ALIGN(size, SZ_4K);
|
||||
|
||||
if (is_iommu_present(res)) {
|
||||
if (flags & SMEM_ADSP) {
|
||||
dprintk(CVP_DBG, "Allocating from ADSP heap\n");
|
||||
heap_mask = ION_HEAP(ION_ADSP_HEAP_ID);
|
||||
} else {
|
||||
heap_mask = ION_HEAP(ION_SYSTEM_HEAP_ID);
|
||||
}
|
||||
} else {
|
||||
dprintk(CVP_DBG,
|
||||
"allocate shared memory from adsp heap size %zx align %d\n",
|
||||
size, align);
|
||||
heap_mask = ION_HEAP(ION_ADSP_HEAP_ID);
|
||||
}
|
||||
|
||||
if (flags & SMEM_CACHED)
|
||||
ion_flags |= ION_FLAG_CACHED;
|
||||
|
||||
if (flags & SMEM_NON_PIXEL)
|
||||
ion_flags |= ION_FLAG_CP_NON_PIXEL;
|
||||
|
||||
if (flags & SMEM_SECURE) {
|
||||
ion_flags |= ION_FLAG_SECURE;
|
||||
heap_mask = ION_HEAP(ION_SECURE_HEAP_ID);
|
||||
}
|
||||
|
||||
trace_msm_cvp_smem_buffer_dma_op_start("ALLOC", (u32)ion_flags,
|
||||
heap_mask, size, align, flags, map_kernel);
|
||||
dbuf = ion_alloc(size, heap_mask, ion_flags);
|
||||
if (IS_ERR_OR_NULL(dbuf)) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to allocate shared memory = %x bytes, %llx, %x\n",
|
||||
size, heap_mask, ion_flags);
|
||||
rc = -ENOMEM;
|
||||
goto fail_shared_mem_alloc;
|
||||
}
|
||||
trace_msm_cvp_smem_buffer_dma_op_end("ALLOC", (u32)ion_flags,
|
||||
heap_mask, size, align, flags, map_kernel);
|
||||
|
||||
mem->flags = flags;
|
||||
mem->buffer_type = ion_flags;
|
||||
mem->offset = 0;
|
||||
mem->size = size;
|
||||
mem->dma_buf = dbuf;
|
||||
mem->kvaddr = NULL;
|
||||
|
||||
rc = msm_dma_get_device_address(dbuf, align, &iova, &buffer_size, flags,
|
||||
ion_flags, session_type, res, &mem->mapping_info);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "Failed to get device address: %d\n",
|
||||
rc);
|
||||
goto fail_device_address;
|
||||
}
|
||||
mem->device_addr = (u32)iova;
|
||||
if ((dma_addr_t)mem->device_addr != iova) {
|
||||
dprintk(CVP_ERR, "iova(%pa) truncated to %#x",
|
||||
&iova, mem->device_addr);
|
||||
goto fail_device_address;
|
||||
}
|
||||
|
||||
if (map_kernel) {
|
||||
dma_buf_begin_cpu_access(dbuf, DMA_BIDIRECTIONAL);
|
||||
mem->kvaddr = dma_buf_vmap(dbuf);
|
||||
if (!mem->kvaddr) {
|
||||
dprintk(CVP_ERR,
|
||||
"Failed to map shared mem in kernel\n");
|
||||
rc = -EIO;
|
||||
goto fail_map;
|
||||
}
|
||||
}
|
||||
|
||||
dprintk(CVP_DBG,
|
||||
"%s: dma_buf = %pK, device_addr = %x, size = %d, kvaddr = %pK, buffer_type = %#x, flags = %#lx\n",
|
||||
__func__, mem->dma_buf, mem->device_addr, mem->size,
|
||||
mem->kvaddr, mem->buffer_type, mem->flags);
|
||||
return rc;
|
||||
|
||||
fail_map:
|
||||
if (map_kernel)
|
||||
dma_buf_end_cpu_access(dbuf, DMA_BIDIRECTIONAL);
|
||||
fail_device_address:
|
||||
dma_buf_put(dbuf);
|
||||
fail_shared_mem_alloc:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int free_dma_mem(struct msm_cvp_smem *mem)
|
||||
{
|
||||
dprintk(CVP_DBG,
|
||||
"%s: dma_buf = %pK, device_addr = %x, size = %d, kvaddr = %pK, buffer_type = %#x\n",
|
||||
__func__, mem->dma_buf, mem->device_addr, mem->size,
|
||||
mem->kvaddr, mem->buffer_type);
|
||||
|
||||
if (mem->device_addr) {
|
||||
msm_dma_put_device_address(mem->flags, &mem->mapping_info);
|
||||
mem->device_addr = 0x0;
|
||||
}
|
||||
|
||||
if (mem->kvaddr) {
|
||||
dma_buf_vunmap(mem->dma_buf, mem->kvaddr);
|
||||
mem->kvaddr = NULL;
|
||||
dma_buf_end_cpu_access(mem->dma_buf, DMA_BIDIRECTIONAL);
|
||||
}
|
||||
|
||||
if (mem->dma_buf) {
|
||||
trace_msm_cvp_smem_buffer_dma_op_start("FREE",
|
||||
(u32)mem->buffer_type, -1, mem->size, -1,
|
||||
mem->flags, -1);
|
||||
dma_buf_put(mem->dma_buf);
|
||||
mem->dma_buf = NULL;
|
||||
trace_msm_cvp_smem_buffer_dma_op_end(
|
||||
"FREE", (u32)mem->buffer_type,
|
||||
-1, mem->size, -1, mem->flags, -1);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int msm_cvp_smem_alloc(size_t size, u32 align, u32 flags, int map_kernel,
|
||||
void *res, u32 session_type, struct msm_cvp_smem *smem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!smem || !size) {
|
||||
dprintk(CVP_ERR, "%s: NULL smem or %d size\n",
|
||||
__func__, (u32)size);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
rc = alloc_dma_mem(size, align, flags, map_kernel,
|
||||
(struct msm_cvp_platform_resources *)res,
|
||||
session_type, smem);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int msm_cvp_smem_free(struct msm_cvp_smem *smem)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
if (!smem) {
|
||||
dprintk(CVP_ERR, "NULL smem passed\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
rc = free_dma_mem(smem);
|
||||
|
||||
return rc;
|
||||
};
|
||||
|
||||
int msm_cvp_smem_cache_operations(struct dma_buf *dbuf,
|
||||
enum smem_cache_ops cache_op, unsigned long offset, unsigned long size)
|
||||
{
|
||||
int rc = 0;
|
||||
unsigned long flags = 0;
|
||||
|
||||
if (!dbuf) {
|
||||
dprintk(CVP_ERR, "%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
/* Return if buffer doesn't support caching */
|
||||
rc = dma_buf_get_flags(dbuf, &flags);
|
||||
if (rc) {
|
||||
dprintk(CVP_ERR, "%s: dma_buf_get_flags failed, err %d\n",
|
||||
__func__, rc);
|
||||
return rc;
|
||||
} else if (!(flags & ION_FLAG_CACHED)) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
switch (cache_op) {
|
||||
case SMEM_CACHE_CLEAN:
|
||||
case SMEM_CACHE_CLEAN_INVALIDATE:
|
||||
rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_BIDIRECTIONAL,
|
||||
offset, size);
|
||||
if (rc)
|
||||
break;
|
||||
rc = dma_buf_end_cpu_access_partial(dbuf, DMA_BIDIRECTIONAL,
|
||||
offset, size);
|
||||
break;
|
||||
case SMEM_CACHE_INVALIDATE:
|
||||
rc = dma_buf_begin_cpu_access_partial(dbuf, DMA_TO_DEVICE,
|
||||
offset, size);
|
||||
if (rc)
|
||||
break;
|
||||
rc = dma_buf_end_cpu_access_partial(dbuf, DMA_FROM_DEVICE,
|
||||
offset, size);
|
||||
break;
|
||||
default:
|
||||
dprintk(CVP_ERR, "%s: cache (%d) operation not supported\n",
|
||||
__func__, cache_op);
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
struct context_bank_info *msm_cvp_smem_get_context_bank(u32 session_type,
|
||||
bool is_secure, struct msm_cvp_platform_resources *res,
|
||||
unsigned long ion_flags)
|
||||
{
|
||||
struct context_bank_info *cb = NULL, *match = NULL;
|
||||
char *search_str;
|
||||
char *non_secure_cb = "cvp_hlos";
|
||||
char *secure_nonpixel_cb = "cvp_sec_nonpixel";
|
||||
char *secure_pixel_cb = "cvp_sec_pixel";
|
||||
|
||||
if (ion_flags & ION_FLAG_CP_PIXEL)
|
||||
search_str = secure_pixel_cb;
|
||||
else if (ion_flags & ION_FLAG_CP_NON_PIXEL)
|
||||
search_str = secure_nonpixel_cb;
|
||||
else
|
||||
search_str = non_secure_cb;
|
||||
|
||||
list_for_each_entry(cb, &res->context_banks, list) {
|
||||
if (cb->is_secure == is_secure &&
|
||||
!strcmp(search_str, cb->name)) {
|
||||
match = cb;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!match)
|
||||
dprintk(CVP_ERR,
|
||||
"%s: cb not found for buffer_type %x, is_secure %d\n",
|
||||
__func__, ion_flags, is_secure);
|
||||
|
||||
return match;
|
||||
}
|
69
include/media/msm_cvp_vidc.h
Normal file
69
include/media/msm_cvp_vidc.h
Normal file
@ -0,0 +1,69 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*
|
||||
* CVP driver functions shared with video driver.
|
||||
*/
|
||||
|
||||
#ifndef _MSM_CVP_VIDC_H_
|
||||
#define _MSM_CVP_VIDC_H_
|
||||
#include <uapi/media/msm_cvp_private.h>
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_usecase_desc - store generic usecase
|
||||
* description
|
||||
* @fullres_width: process width of full resolution frame
|
||||
* @fullres_height: process height of full resolution frame
|
||||
* @downscale_width: width of downscaled frame
|
||||
* @downscale_height: height of downscaled frame
|
||||
* @is_downscale: is downscaling enabled in pipeline
|
||||
* @fps: frame rate
|
||||
* @op_rate: stream operation rate
|
||||
* @colorfmt: format based on msm_media_info.h
|
||||
* @reserved[16]: for future use
|
||||
*/
|
||||
struct cvp_kmd_usecase_desc {
|
||||
unsigned int fullres_width;
|
||||
unsigned int fullres_height;
|
||||
unsigned int downscale_width;
|
||||
unsigned int downscale_height;
|
||||
unsigned int is_downscale;
|
||||
unsigned int fps;
|
||||
unsigned int op_rate;
|
||||
unsigned int colorfmt;
|
||||
int reserved[16];
|
||||
};
|
||||
|
||||
#define VIDEO_NONREALTIME 1
|
||||
#define VIDEO_REALTIME 5
|
||||
|
||||
#if IS_ENABLED(CONFIG_MSM_CVP)
|
||||
void *msm_cvp_open(int core_id, int session_type);
|
||||
int msm_cvp_close(void *instance);
|
||||
int msm_cvp_private(void *cvp_inst, unsigned int cmd, struct cvp_kmd_arg *arg);
|
||||
int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc,
|
||||
struct cvp_kmd_request_power *cvp_voting);
|
||||
|
||||
#else
|
||||
static inline void *msm_cvp_open(int core_id, int session_type)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
static inline int msm_cvp_close(void *instance)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int msm_cvp_private(void *cvp_inst, unsigned int cmd,
|
||||
struct cvp_kmd_arg *arg)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
static inline int msm_cvp_est_cycles(struct cvp_kmd_usecase_desc *cvp_desc,
|
||||
struct cvp_kmd_request_power *cvp_voting)
|
||||
{
|
||||
return -EINVAL;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
1355
include/media/msm_media_info.h
Normal file
1355
include/media/msm_media_info.h
Normal file
File diff suppressed because it is too large
Load Diff
341
include/trace/events/msm_cvp_events.h
Normal file
341
include/trace/events/msm_cvp_events.h
Normal file
@ -0,0 +1,341 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#undef TRACE_SYSTEM
|
||||
#define TRACE_SYSTEM msm_cvp_events
|
||||
|
||||
#if !defined(_TRACE_MSM_CVP_H_) || defined(TRACE_HEADER_MULTI_READ)
|
||||
#define _TRACE_MSM_CVP_H
|
||||
#include <linux/types.h>
|
||||
#include <linux/tracepoint.h>
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_v4l2_cvp,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, dummy)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->dummy = dummy;
|
||||
),
|
||||
|
||||
TP_printk("%s", __entry->dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_open_start,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_open_end,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_close_start,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_close_end,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_fw_load_start,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp, msm_v4l2_cvp_fw_load_end,
|
||||
|
||||
TP_PROTO(char *dummy),
|
||||
|
||||
TP_ARGS(dummy)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_cvp_common,
|
||||
|
||||
TP_PROTO(void *instp, int old_state, int new_state),
|
||||
|
||||
TP_ARGS(instp, old_state, new_state),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(void *, instp)
|
||||
__field(int, old_state)
|
||||
__field(int, new_state)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->instp = instp;
|
||||
__entry->old_state = old_state;
|
||||
__entry->new_state = new_state;
|
||||
),
|
||||
|
||||
TP_printk("Moved inst: %p from 0x%x to 0x%x",
|
||||
__entry->instp,
|
||||
__entry->old_state,
|
||||
__entry->new_state)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_common, msm_cvp_common_state_change,
|
||||
|
||||
TP_PROTO(void *instp, int old_state, int new_state),
|
||||
|
||||
TP_ARGS(instp, old_state, new_state)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(cvp_venus_hfi_var,
|
||||
|
||||
TP_PROTO(u32 cp_start, u32 cp_size,
|
||||
u32 cp_nonpixel_start, u32 cp_nonpixel_size),
|
||||
|
||||
TP_ARGS(cp_start, cp_size, cp_nonpixel_start, cp_nonpixel_size),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(u32, cp_start)
|
||||
__field(u32, cp_size)
|
||||
__field(u32, cp_nonpixel_start)
|
||||
__field(u32, cp_nonpixel_size)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->cp_start = cp_start;
|
||||
__entry->cp_size = cp_size;
|
||||
__entry->cp_nonpixel_start = cp_nonpixel_start;
|
||||
__entry->cp_nonpixel_size = cp_nonpixel_size;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"TZBSP_MEM_PROTECT_VIDEO_VAR done, cp_start : 0x%x, cp_size : 0x%x, cp_nonpixel_start : 0x%x, cp_nonpixel_size : 0x%x",
|
||||
__entry->cp_start,
|
||||
__entry->cp_size,
|
||||
__entry->cp_nonpixel_start,
|
||||
__entry->cp_nonpixel_size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(cvp_venus_hfi_var, cvp_venus_hfi_var_done,
|
||||
|
||||
TP_PROTO(u32 cp_start, u32 cp_size,
|
||||
u32 cp_nonpixel_start, u32 cp_nonpixel_size),
|
||||
|
||||
TP_ARGS(cp_start, cp_size, cp_nonpixel_start, cp_nonpixel_size)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_v4l2_cvp_buffer_events,
|
||||
|
||||
TP_PROTO(char *event_type, u32 device_addr, int64_t timestamp,
|
||||
u32 alloc_len, u32 filled_len, u32 offset),
|
||||
|
||||
TP_ARGS(event_type, device_addr, timestamp, alloc_len,
|
||||
filled_len, offset),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, event_type)
|
||||
__field(u32, device_addr)
|
||||
__field(int64_t, timestamp)
|
||||
__field(u32, alloc_len)
|
||||
__field(u32, filled_len)
|
||||
__field(u32, offset)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->event_type = event_type;
|
||||
__entry->device_addr = device_addr;
|
||||
__entry->timestamp = timestamp;
|
||||
__entry->alloc_len = alloc_len;
|
||||
__entry->filled_len = filled_len;
|
||||
__entry->offset = offset;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s, device_addr : 0x%x, timestamp : %lld, alloc_len : 0x%x, filled_len : 0x%x, offset : 0x%x",
|
||||
__entry->event_type,
|
||||
__entry->device_addr,
|
||||
__entry->timestamp,
|
||||
__entry->alloc_len,
|
||||
__entry->filled_len,
|
||||
__entry->offset)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp_buffer_events, msm_v4l2_cvp_buffer_event_start,
|
||||
|
||||
TP_PROTO(char *event_type, u32 device_addr, int64_t timestamp,
|
||||
u32 alloc_len, u32 filled_len, u32 offset),
|
||||
|
||||
TP_ARGS(event_type, device_addr, timestamp, alloc_len,
|
||||
filled_len, offset)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_v4l2_cvp_buffer_events, msm_v4l2_cvp_buffer_event_end,
|
||||
|
||||
TP_PROTO(char *event_type, u32 device_addr, int64_t timestamp,
|
||||
u32 alloc_len, u32 filled_len, u32 offset),
|
||||
|
||||
TP_ARGS(event_type, device_addr, timestamp, alloc_len,
|
||||
filled_len, offset)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_cvp_smem_buffer_dma_ops,
|
||||
|
||||
TP_PROTO(char *buffer_op, u32 buffer_type, u32 heap_mask,
|
||||
size_t size, u32 align, u32 flags, int map_kernel),
|
||||
|
||||
TP_ARGS(buffer_op, buffer_type, heap_mask, size, align,
|
||||
flags, map_kernel),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, buffer_op)
|
||||
__field(u32, buffer_type)
|
||||
__field(u32, heap_mask)
|
||||
__field(u32, size)
|
||||
__field(u32, align)
|
||||
__field(u32, flags)
|
||||
__field(int, map_kernel)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->buffer_op = buffer_op;
|
||||
__entry->buffer_type = buffer_type;
|
||||
__entry->heap_mask = heap_mask;
|
||||
__entry->size = size;
|
||||
__entry->align = align;
|
||||
__entry->flags = flags;
|
||||
__entry->map_kernel = map_kernel;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s, buffer_type : 0x%x, heap_mask : 0x%x, size : 0x%x, align : 0x%x, flags : 0x%x, map_kernel : %d",
|
||||
__entry->buffer_op,
|
||||
__entry->buffer_type,
|
||||
__entry->heap_mask,
|
||||
__entry->size,
|
||||
__entry->align,
|
||||
__entry->flags,
|
||||
__entry->map_kernel)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_smem_buffer_dma_ops, msm_cvp_smem_buffer_dma_op_start,
|
||||
|
||||
TP_PROTO(char *buffer_op, u32 buffer_type, u32 heap_mask,
|
||||
size_t size, u32 align, u32 flags, int map_kernel),
|
||||
|
||||
TP_ARGS(buffer_op, buffer_type, heap_mask, size, align,
|
||||
flags, map_kernel)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_smem_buffer_dma_ops, msm_cvp_smem_buffer_dma_op_end,
|
||||
|
||||
TP_PROTO(char *buffer_op, u32 buffer_type, u32 heap_mask,
|
||||
size_t size, u32 align, u32 flags, int map_kernel),
|
||||
|
||||
TP_ARGS(buffer_op, buffer_type, heap_mask, size, align,
|
||||
flags, map_kernel)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_cvp_smem_buffer_iommu_ops,
|
||||
|
||||
TP_PROTO(char *buffer_op, int domain_num, int partition_num,
|
||||
unsigned long align, unsigned long iova,
|
||||
unsigned long buffer_size),
|
||||
|
||||
TP_ARGS(buffer_op, domain_num, partition_num, align, iova, buffer_size),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(char *, buffer_op)
|
||||
__field(int, domain_num)
|
||||
__field(int, partition_num)
|
||||
__field(unsigned long, align)
|
||||
__field(unsigned long, iova)
|
||||
__field(unsigned long, buffer_size)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->buffer_op = buffer_op;
|
||||
__entry->domain_num = domain_num;
|
||||
__entry->partition_num = partition_num;
|
||||
__entry->align = align;
|
||||
__entry->iova = iova;
|
||||
__entry->buffer_size = buffer_size;
|
||||
),
|
||||
|
||||
TP_printk(
|
||||
"%s, domain : %d, partition : %d, align : %lx, iova : 0x%lx, buffer_size=%lx",
|
||||
__entry->buffer_op,
|
||||
__entry->domain_num,
|
||||
__entry->partition_num,
|
||||
__entry->align,
|
||||
__entry->iova,
|
||||
__entry->buffer_size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_smem_buffer_iommu_ops, msm_cvp_smem_buffer_iommu_op_start,
|
||||
|
||||
TP_PROTO(char *buffer_op, int domain_num, int partition_num,
|
||||
unsigned long align, unsigned long iova,
|
||||
unsigned long buffer_size),
|
||||
|
||||
TP_ARGS(buffer_op, domain_num, partition_num, align, iova, buffer_size)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_smem_buffer_iommu_ops, msm_cvp_smem_buffer_iommu_op_end,
|
||||
|
||||
TP_PROTO(char *buffer_op, int domain_num, int partition_num,
|
||||
unsigned long align, unsigned long iova,
|
||||
unsigned long buffer_size),
|
||||
|
||||
TP_ARGS(buffer_op, domain_num, partition_num, align, iova, buffer_size)
|
||||
);
|
||||
|
||||
DECLARE_EVENT_CLASS(msm_cvp_perf,
|
||||
|
||||
TP_PROTO(const char *name, unsigned long value),
|
||||
|
||||
TP_ARGS(name, value),
|
||||
|
||||
TP_STRUCT__entry(
|
||||
__field(const char *, name)
|
||||
__field(unsigned long, value)
|
||||
),
|
||||
|
||||
TP_fast_assign(
|
||||
__entry->name = name;
|
||||
__entry->value = value;
|
||||
),
|
||||
|
||||
TP_printk("%s %lu", __entry->name, __entry->value)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_perf, msm_cvp_perf_clock_scale,
|
||||
|
||||
TP_PROTO(const char *clock_name, unsigned long frequency),
|
||||
|
||||
TP_ARGS(clock_name, frequency)
|
||||
);
|
||||
|
||||
DEFINE_EVENT(msm_cvp_perf, msm_cvp_perf_bus_vote,
|
||||
|
||||
TP_PROTO(const char *governor_mode, unsigned long ab),
|
||||
|
||||
TP_ARGS(governor_mode, ab)
|
||||
);
|
||||
|
||||
#endif
|
||||
|
||||
#include <trace/define_trace.h>
|
315
include/uapi/media/msm_cvp_private.h
Normal file
315
include/uapi/media/msm_cvp_private.h
Normal file
@ -0,0 +1,315 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
|
||||
/*
|
||||
* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
#ifndef __MSM_CVP_PRIVATE_H__
|
||||
#define __MSM_CVP_PRIVATE_H__
|
||||
|
||||
#define MAX_DFS_HFI_PARAMS 20
|
||||
#define HFI_MAX_PLANES 4
|
||||
|
||||
#define BASE_PRIVATE_CVP 36
|
||||
|
||||
/* VIDIOC private cvp command */
|
||||
#define VIDIOC_CVP_CMD \
|
||||
_IOWR('V', BASE_PRIVATE_CVP, struct cvp_kmd_arg)
|
||||
|
||||
/* Commands type */
|
||||
#define CVP_KMD_CMD_BASE 0x10000000
|
||||
#define CVP_KMD_CMD_START (CVP_KMD_CMD_BASE + 0x1000)
|
||||
|
||||
/*
|
||||
* userspace clients pass one of the below arguments type
|
||||
* in struct cvp_kmd_arg (@type field).
|
||||
*/
|
||||
|
||||
/*
|
||||
* CVP_KMD_GET_SESSION_INFO - this argument type is used to
|
||||
* get the session information from driver. it passes
|
||||
* struct cvp_kmd_session_info {}
|
||||
*/
|
||||
#define CVP_KMD_GET_SESSION_INFO (CVP_KMD_CMD_START + 1)
|
||||
|
||||
/*
|
||||
* CVP_KMD_REQUEST_POWER - this argument type is used to
|
||||
* set the power required to driver. it passes
|
||||
* struct cvp_kmd_request_power {}
|
||||
*/
|
||||
#define CVP_KMD_REQUEST_POWER (CVP_KMD_CMD_START + 2)
|
||||
|
||||
/*
|
||||
* CVP_KMD_REGISTER_BUFFER - this argument type is used to
|
||||
* register the buffer to driver. it passes
|
||||
* struct cvp_kmd_buffer {}
|
||||
*/
|
||||
#define CVP_KMD_REGISTER_BUFFER (CVP_KMD_CMD_START + 3)
|
||||
|
||||
/*
|
||||
* CVP_KMD_REGISTER_BUFFER - this argument type is used to
|
||||
* unregister the buffer to driver. it passes
|
||||
* struct cvp_kmd_buffer {}
|
||||
*/
|
||||
#define CVP_KMD_UNREGISTER_BUFFER (CVP_KMD_CMD_START + 4)
|
||||
|
||||
#define CVP_KMD_HFI_SEND_CMD (CVP_KMD_CMD_START + 5)
|
||||
|
||||
#define CVP_KMD_HFI_DFS_CONFIG_CMD (CVP_KMD_CMD_START + 6)
|
||||
|
||||
#define CVP_KMD_HFI_DFS_FRAME_CMD (CVP_KMD_CMD_START + 7)
|
||||
|
||||
#define CVP_KMD_HFI_DFS_FRAME_CMD_RESPONSE (CVP_KMD_CMD_START + 8)
|
||||
|
||||
#define CVP_KMD_HFI_DME_CONFIG_CMD (CVP_KMD_CMD_START + 9)
|
||||
|
||||
#define CVP_KMD_HFI_DME_FRAME_CMD (CVP_KMD_CMD_START + 10)
|
||||
|
||||
#define CVP_KMD_HFI_DME_FRAME_CMD_RESPONSE (CVP_KMD_CMD_START + 11)
|
||||
|
||||
#define CVP_KMD_HFI_PERSIST_CMD (CVP_KMD_CMD_START + 12)
|
||||
|
||||
#define CVP_KMD_HFI_PERSIST_CMD_RESPONSE (CVP_KMD_CMD_START + 13)
|
||||
|
||||
#define CVP_KMD_HFI_DME_FRAME_FENCE_CMD (CVP_KMD_CMD_START + 14)
|
||||
|
||||
#define CVP_KMD_HFI_ICA_FRAME_CMD (CVP_KMD_CMD_START + 15)
|
||||
|
||||
#define CVP_KMD_HFI_FD_FRAME_CMD (CVP_KMD_CMD_START + 16)
|
||||
|
||||
#define CVP_KMD_UPDATE_POWER (CVP_KMD_CMD_START + 17)
|
||||
|
||||
#define CVP_KMD_SEND_CMD_PKT (CVP_KMD_CMD_START + 64)
|
||||
|
||||
#define CVP_KMD_RECEIVE_MSG_PKT (CVP_KMD_CMD_START + 65)
|
||||
|
||||
#define CVP_KMD_SET_SYS_PROPERTY (CVP_KMD_CMD_START + 66)
|
||||
|
||||
#define CVP_KMD_GET_SYS_PROPERTY (CVP_KMD_CMD_START + 67)
|
||||
|
||||
#define CVP_KMD_SESSION_CONTROL (CVP_KMD_CMD_START + 68)
|
||||
|
||||
#define CVP_KMD_SEND_FENCE_CMD_PKT (0x10001000 + 69)
|
||||
|
||||
/* flags */
|
||||
#define CVP_KMD_FLAG_UNSECURE 0x00000000
|
||||
#define CVP_KMD_FLAG_SECURE 0x00000001
|
||||
|
||||
/* buffer type */
|
||||
#define CVP_KMD_BUFTYPE_INPUT 0x00000001
|
||||
#define CVP_KMD_BUFTYPE_OUTPUT 0x00000002
|
||||
#define CVP_KMD_BUFTYPE_INTERNAL_1 0x00000003
|
||||
#define CVP_KMD_BUFTYPE_INTERNAL_2 0x00000004
|
||||
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_session_info - session information
|
||||
* @session_id: current session id
|
||||
*/
|
||||
struct cvp_kmd_session_info {
|
||||
unsigned int session_id;
|
||||
unsigned int reserved[10];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_request_power - power / clock data information
|
||||
* @clock_cycles_a: clock cycles per second required for hardware_a
|
||||
* @clock_cycles_b: clock cycles per second required for hardware_b
|
||||
* @ddr_bw: bandwidth required for ddr in bps
|
||||
* @sys_cache_bw: bandwidth required for system cache in bps
|
||||
*/
|
||||
struct cvp_kmd_request_power {
|
||||
unsigned int clock_cycles_a;
|
||||
unsigned int clock_cycles_b;
|
||||
unsigned int ddr_bw;
|
||||
unsigned int sys_cache_bw;
|
||||
unsigned int reserved[8];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_buffer - buffer information to be registered
|
||||
* @index: index of buffer
|
||||
* @type: buffer type
|
||||
* @fd: file descriptor of buffer
|
||||
* @size: allocated size of buffer
|
||||
* @offset: offset in fd from where usable data starts
|
||||
* @pixelformat: fourcc format
|
||||
* @flags: buffer flags
|
||||
*/
|
||||
struct cvp_kmd_buffer {
|
||||
unsigned int index;
|
||||
unsigned int type;
|
||||
unsigned int fd;
|
||||
unsigned int size;
|
||||
unsigned int offset;
|
||||
unsigned int pixelformat;
|
||||
unsigned int flags;
|
||||
unsigned int reserved[5];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_send_cmd - sending generic HFI command
|
||||
* @cmd_address_fd: file descriptor of cmd_address
|
||||
* @cmd_size: allocated size of buffer
|
||||
*/
|
||||
struct cvp_kmd_send_cmd {
|
||||
unsigned int cmd_address_fd;
|
||||
unsigned int cmd_size;
|
||||
unsigned int reserved[10];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_color_plane_info - color plane info
|
||||
* @stride: stride of plane
|
||||
* @buf_size: size of plane
|
||||
*/
|
||||
struct cvp_kmd_color_plane_info {
|
||||
int stride[HFI_MAX_PLANES];
|
||||
unsigned int buf_size[HFI_MAX_PLANES];
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_client_data - store generic client
|
||||
* data
|
||||
* @transactionid: transaction id
|
||||
* @client_data1: client data to be used during callback
|
||||
* @client_data2: client data to be used during callback
|
||||
*/
|
||||
struct cvp_kmd_client_data {
|
||||
unsigned int transactionid;
|
||||
unsigned int client_data1;
|
||||
unsigned int client_data2;
|
||||
};
|
||||
|
||||
#define CVP_COLOR_PLANE_INFO_SIZE \
|
||||
sizeof(struct cvp_kmd_color_plane_info)
|
||||
#define CVP_CLIENT_DATA_SIZE sizeof(struct cvp_kmd_client_data)
|
||||
#define CVP_DFS_CONFIG_CMD_SIZE 38
|
||||
#define CVP_DFS_FRAME_CMD_SIZE 16
|
||||
#define CVP_DFS_FRAME_BUFFERS_OFFSET 8
|
||||
|
||||
#define CVP_DME_CONFIG_CMD_SIZE 194
|
||||
#define CVP_DME_FRAME_CMD_SIZE 28
|
||||
#define CVP_DME_FRAME_BUFFERS_OFFSET 12
|
||||
#define CVP_DME_BUF_NUM 8
|
||||
|
||||
#define CVP_PERSIST_CMD_SIZE 11
|
||||
#define CVP_PERSIST_BUFFERS_OFFSET 7
|
||||
#define CVP_PERSIST_BUF_NUM 2
|
||||
|
||||
struct cvp_kmd_dfs_config {
|
||||
unsigned int cvp_dfs_config[CVP_DFS_CONFIG_CMD_SIZE];
|
||||
};
|
||||
|
||||
struct cvp_kmd_dfs_frame {
|
||||
unsigned int frame_data[CVP_DFS_FRAME_CMD_SIZE];
|
||||
};
|
||||
|
||||
struct cvp_kmd_dme_config {
|
||||
unsigned int cvp_dme_config[CVP_DME_CONFIG_CMD_SIZE];
|
||||
};
|
||||
|
||||
struct cvp_kmd_dme_frame {
|
||||
unsigned int frame_data[CVP_DME_FRAME_CMD_SIZE];
|
||||
};
|
||||
|
||||
struct cvp_kmd_persist_buf {
|
||||
unsigned int persist_data[CVP_PERSIST_CMD_SIZE];
|
||||
};
|
||||
|
||||
#define MAX_HFI_PKT_SIZE 470
|
||||
|
||||
struct cvp_kmd_hfi_packet {
|
||||
unsigned int pkt_data[MAX_HFI_PKT_SIZE];
|
||||
};
|
||||
|
||||
#define CVP_KMD_PROP_HFI_VERSION 1
|
||||
#define CVP_KMD_PROP_SESSION_TYPE 2
|
||||
#define CVP_KMD_PROP_SESSION_KERNELMASK 3
|
||||
#define CVP_KMD_PROP_SESSION_PRIORITY 4
|
||||
#define CVP_KMD_PROP_SESSION_SECURITY 5
|
||||
#define CVP_KMD_PROP_SESSION_DSPMASK 6
|
||||
|
||||
#define CVP_KMD_PROP_PWR_FDU 0x10
|
||||
#define CVP_KMD_PROP_PWR_ICA 0x11
|
||||
#define CVP_KMD_PROP_PWR_OD 0x12
|
||||
#define CVP_KMD_PROP_PWR_MPU 0x13
|
||||
#define CVP_KMD_PROP_PWR_FW 0x14
|
||||
#define CVP_KMD_PROP_PWR_DDR 0x15
|
||||
#define CVP_KMD_PROP_PWR_SYSCACHE 0x16
|
||||
#define CVP_KMD_PROP_PWR_FDU_OP 0x17
|
||||
#define CVP_KMD_PROP_PWR_ICA_OP 0x18
|
||||
#define CVP_KMD_PROP_PWR_OD_OP 0x19
|
||||
#define CVP_KMD_PROP_PWR_MPU_OP 0x1A
|
||||
#define CVP_KMD_PROP_PWR_FW_OP 0x1B
|
||||
#define CVP_KMD_PROP_PWR_DDR_OP 0x1C
|
||||
#define CVP_KMD_PROP_PWR_SYSCACHE_OP 0x1D
|
||||
|
||||
#define MAX_KMD_PROP_NUM (CVP_KMD_PROP_PWR_SYSCACHE_OP + 1)
|
||||
|
||||
struct cvp_kmd_sys_property {
|
||||
unsigned int prop_type;
|
||||
unsigned int data;
|
||||
};
|
||||
|
||||
struct cvp_kmd_sys_properties {
|
||||
unsigned int prop_num;
|
||||
struct cvp_kmd_sys_property prop_data;
|
||||
};
|
||||
|
||||
#define SESSION_CREATE 1
|
||||
#define SESSION_DELETE 2
|
||||
#define SESSION_START 3
|
||||
#define SESSION_STOP 4
|
||||
#define SESSION_INFO 5
|
||||
|
||||
struct cvp_kmd_session_control {
|
||||
unsigned int ctrl_type;
|
||||
unsigned int ctrl_data[8];
|
||||
};
|
||||
|
||||
#define MAX_HFI_FENCE_SIZE 16
|
||||
#define MAX_HFI_FENCE_OFFSET (MAX_HFI_PKT_SIZE-MAX_HFI_FENCE_SIZE)
|
||||
struct cvp_kmd_hfi_fence_packet {
|
||||
unsigned int pkt_data[MAX_HFI_FENCE_OFFSET];
|
||||
unsigned int fence_data[MAX_HFI_FENCE_SIZE];
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* struct cvp_kmd_arg - argument passed with VIDIOC_CVP_CMD
|
||||
* To be deprecated
|
||||
* @type: command type
|
||||
* @buf_offset: offset to buffer list in the command
|
||||
* @buf_num: number of buffers in the command
|
||||
* @session: session information
|
||||
* @req_power: power information
|
||||
* @regbuf: buffer to be registered
|
||||
* @unregbuf: buffer to be unregistered
|
||||
* @send_cmd: sending generic HFI command
|
||||
* @dfs_config: sending DFS config command
|
||||
* @dfs_frame: sending DFS frame command
|
||||
* @hfi_pkt: HFI packet created by user library
|
||||
* @sys_properties System properties read or set by user library
|
||||
* @hfi_fence_pkt: HFI fence packet created by user library
|
||||
*/
|
||||
struct cvp_kmd_arg {
|
||||
unsigned int type;
|
||||
unsigned int buf_offset;
|
||||
unsigned int buf_num;
|
||||
union cvp_data_t {
|
||||
struct cvp_kmd_session_info session;
|
||||
struct cvp_kmd_request_power req_power;
|
||||
struct cvp_kmd_buffer regbuf;
|
||||
struct cvp_kmd_buffer unregbuf;
|
||||
struct cvp_kmd_send_cmd send_cmd;
|
||||
struct cvp_kmd_dfs_config dfs_config;
|
||||
struct cvp_kmd_dfs_frame dfs_frame;
|
||||
struct cvp_kmd_dme_config dme_config;
|
||||
struct cvp_kmd_dme_frame dme_frame;
|
||||
struct cvp_kmd_persist_buf pbuf_cmd;
|
||||
struct cvp_kmd_hfi_packet hfi_pkt;
|
||||
struct cvp_kmd_sys_properties sys_properties;
|
||||
struct cvp_kmd_hfi_fence_packet hfi_fence_pkt;
|
||||
struct cvp_kmd_session_control session_ctrl;
|
||||
} data;
|
||||
};
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user