Drivers/VCODEC: support vcodec function for hikey970.

Add VCODEC code in kernel to support vcodec for hikey970.

Signed-off-by: xwx495457 <xwx495457@notesmail.huawei.com>
This commit is contained in:
xwx495457
2018-02-12 18:27:29 +08:00
committed by Guodong Xu
parent cae64574fd
commit 8094511eee
65 changed files with 23734 additions and 0 deletions
View File
+3
View File
@@ -210,4 +210,7 @@ source "drivers/fpga/Kconfig"
source "drivers/tee/Kconfig"
source "drivers/vcodec/venc_hivna/Kconfig"
source "drivers/vcodec/vdec_hivna/Kconfig"
endmenu
+2
View File
@@ -177,3 +177,5 @@ obj-$(CONFIG_NVMEM) += nvmem/
obj-$(CONFIG_FPGA) += fpga/
obj-$(CONFIG_TEE) += tee/
obj-$(CONFIG_HISILICON_PLATFORM)+= hisi/
obj-$(CONFIG_HI_VCODEC_VENC) += vcodec/venc_hivna/
obj-$(CONFIG_HI_VCODEC_VDEC) += vcodec/vdec_hivna/
+9
View File
@@ -0,0 +1,9 @@
menu "Hisilicon video vdec support"
config HI_VCODEC_VDEC
tristate "Hisilicon video decoder support"
default n
help
This is the hisilicon decoder driver
endmenu
+1
View File
@@ -0,0 +1 @@
obj-$(CONFIG_HI_VCODEC_VDEC) += omxvdec/ vfmw_v4.0/
+5
View File
@@ -0,0 +1,5 @@
config OMXVDEC
tristate "hisilicon omx video decoder support"
default n
---help---
This is the omxvdec driver
+22
View File
@@ -0,0 +1,22 @@
TOP := drivers/../..
EXTRA_CFLAGS += -DENV_ARMLINUX_KERNEL
EXTRA_CFLAGS += -DHIVDEC_SMMU_SUPPORT
EXTRA_CFLAGS += -Idrivers/vcodec/hi_vcodec/vdec_hivna/omxvdec
EXTRA_CFLAGS += -Idrivers/vcodec/hi_vcodec/vdec_hivna/vfmw_v4.0
EXTRA_CFLAGS += -Idrivers/vcodec/hi_vcodec/vdec_hivna/vfmw_v4.0/format
EXTRA_CFLAGS += -fno-pic
EXTRA_CFLAGS += -DOMXVDEC_TVP_CONFLICT
ifneq ($(TARGET_BUILD_VARIANT), user)
EXTRA_CFLAGS += -DUSER_DISABLE_VDEC_PROC
endif
EXTRA_CFLAGS +=-DPLATFORM_KIRIN970
#build in
obj-$(CONFIG_HI_VCODEC_VDEC) += hi_omxvdec.o
hi_omxvdec-objs += omxvdec.o regulator.o
+569
View File
@@ -0,0 +1,569 @@
/*
* vdec driver interface
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include <linux/clk.h>
#include <linux/of.h>
#include <linux/io.h>
#include "omxvdec.h"
#include "../vfmw_v4.0/linux_kernel_osal.h"
#include "../vfmw_v4.0/vfmw_dts.h"
#include "../vfmw_v4.0/scd_drv.h"
#include "../vfmw_v4.0/format/vdm_drv.h"
#include "../vfmw_v4.0/vfmw_intf.h"
/*lint -e774*/
#define PCTRL_PERI (0xE8A090A4)
#define PCTRL_PERI_SATA0 (0xE8A090BC)
static int gIsNormalInit = 0;
static int gIsDeviceDetected = 0;
static struct class *g_OmxVdecClass = NULL;
static const char g_OmxVdecDrvName[] = OMXVDEC_NAME;
static dev_t g_OmxVdecDevNum;
static OMXVDEC_ENTRY g_OmxVdecEntry;
//Modified for 64-bit platform
typedef enum {
T_IOCTL_ARG,
T_IOCTL_ARG_COMPAT,
T_BUTT,
} COMPAT_TYPE_E;
typedef enum {
KIRIN_970_ES,
KIRIN_970_CS,
KIRIN_980,
KIRIN_BUTT,
} KIRIN_PLATFORM_E;
#define CHECK_PARA_SIZE_RETURN(size, para_size, command) \
do { \
if (size != para_size) { \
printk(KERN_CRIT "%s: prarameter_size is error\n", command); \
return -EINVAL; \
} \
}while(0)
#define CHECK_RETURN(cond, else_print) \
do { \
if (!(cond)) { \
printk(KERN_CRIT "%s : %s\n", __func__, else_print); \
return -EINVAL; \
} \
}while(0)
#define CHECK_SCENE_EQ_RETURN(cond, else_print) \
do { \
if (cond) { \
printk(KERN_INFO "%s : %s\n", __func__, else_print); \
return -EIO; \
} \
}while(0)
static int omxvdec_setup_cdev(OMXVDEC_ENTRY *omxvdec, const struct file_operations *fops)
{
int rc;
struct device *dev;
g_OmxVdecClass = class_create(THIS_MODULE, "omxvdec_class");
if (IS_ERR(g_OmxVdecClass)) {
rc = PTR_ERR(g_OmxVdecClass);
g_OmxVdecClass = NULL;
printk(KERN_CRIT "%s call class_create failed, rc : %d\n", __func__, rc);
return rc;
}
rc = alloc_chrdev_region(&g_OmxVdecDevNum, 0, 1, "hisi video decoder");
if (rc) {
printk(KERN_CRIT "%s call alloc_chrdev_region failed, rc : %d\n", __func__, rc);
goto cls_destroy;
}
dev = device_create(g_OmxVdecClass, NULL, g_OmxVdecDevNum, NULL, OMXVDEC_NAME);
if (IS_ERR(dev)) {
rc = PTR_ERR(dev);
printk(KERN_CRIT "%s call device_create failed, rc : %d\n", __func__, rc);
goto unregister_region;
}
cdev_init(&omxvdec->cdev, fops);
omxvdec->cdev.owner = THIS_MODULE;
omxvdec->cdev.ops = fops;
rc = cdev_add(&omxvdec->cdev, g_OmxVdecDevNum, 1);
if (rc < 0) {
printk(KERN_CRIT "%s call cdev_add failed, rc : %d\n", __func__, rc);
goto dev_destroy;
}
return HI_SUCCESS;
dev_destroy:
device_destroy(g_OmxVdecClass, g_OmxVdecDevNum);
unregister_region:
unregister_chrdev_region(g_OmxVdecDevNum, 1);
cls_destroy:
class_destroy(g_OmxVdecClass);
g_OmxVdecClass = NULL;
return rc;
}
static int omxvdec_cleanup_cdev(OMXVDEC_ENTRY *omxvdec)
{
if (!g_OmxVdecClass) {
printk(KERN_CRIT "%s: Invalid g_OmxVdecClass is NULL", __func__);
return HI_FAILURE;
}
cdev_del(&omxvdec->cdev);
device_destroy(g_OmxVdecClass, g_OmxVdecDevNum);
unregister_chrdev_region(g_OmxVdecDevNum, 1);
class_destroy(g_OmxVdecClass);
g_OmxVdecClass = NULL;
return HI_SUCCESS;
}
static int omxvdec_open(struct inode *inode, struct file *file)
{
int ret = -EBUSY;
OMXVDEC_ENTRY *omxvdec = NULL;
omxvdec = container_of(inode->i_cdev, OMXVDEC_ENTRY, cdev);
VDEC_MUTEX_LOCK(&omxvdec->omxvdec_mutex);
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_scd);
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_vdh);
if (omxvdec->open_count < MAX_OPEN_COUNT) {
omxvdec->open_count++;
if (omxvdec->open_count == 1) {
ret = VDEC_Regulator_Enable();
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s : VDEC_Regulator_Enable failed\n", __func__);
goto error0;
}
ret = VCTRL_OpenVfmw();
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s : vfmw open failed\n", __func__);
goto error1;
}
gIsNormalInit = 1;
}
file->private_data = omxvdec;
ret = HI_SUCCESS;
} else {
printk(KERN_CRIT "%s open omxvdec instance too much\n", __func__);
ret = -EBUSY;
}
printk(KERN_INFO "%s, open_count : %d\n", __func__, omxvdec->open_count);
goto exit;
error1:
(void)VDEC_Regulator_Disable();
error0:
omxvdec->open_count--;
exit:
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_vdh);
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_scd);
VDEC_MUTEX_UNLOCK(&omxvdec->omxvdec_mutex);
return ret;
}
static int omxvdec_release(struct inode *inode, struct file *file)
{
OMXVDEC_ENTRY *omxvdec = NULL;
int ret = HI_SUCCESS;
omxvdec = file->private_data;
if (omxvdec == NULL) {
printk(KERN_CRIT "%s: invalid omxvdec is null\n", __func__);
return -EFAULT;
}
VDEC_MUTEX_LOCK(&omxvdec->omxvdec_mutex);
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_scd);
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_vdh);
if (file->private_data == NULL) {
printk(KERN_CRIT "%s: invalid file->private_data is null\n", __func__);
ret = -EFAULT;
goto exit;
}
if (omxvdec->open_count > 0)
omxvdec->open_count--;
if (omxvdec->open_count == 0) {
VCTRL_CloseVfmw();
VDEC_Regulator_Disable();
gIsNormalInit = 0;
}
file->private_data = NULL;
printk(KERN_INFO "exit %s , open_count : %d\n", __func__, omxvdec->open_count);
exit:
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_vdh);
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_scd);
VDEC_MUTEX_UNLOCK(&omxvdec->omxvdec_mutex);
return ret;
}
/* Modified for 64-bit platform */
static int omxvdec_compat_get_data(COMPAT_TYPE_E eType, void __user *pUser, void *pData)
{
int ret = HI_SUCCESS;
int s32Data = 0;
compat_ulong_t CompatData = 0;
OMXVDEC_IOCTL_MSG *pIoctlMsg = (OMXVDEC_IOCTL_MSG *)pData;
if (NULL == pUser || NULL == pData) {
printk(KERN_CRIT "%s: param is null\n", __func__);
return HI_FAILURE;
}
switch (eType) {
case T_IOCTL_ARG:
if (copy_from_user(pIoctlMsg, pUser, sizeof(*pIoctlMsg))) {
printk(KERN_CRIT "%s puser copy failed\n", __func__);
ret = HI_FAILURE;
}
break;
case T_IOCTL_ARG_COMPAT: {
COMPAT_IOCTL_MSG __user *pCompatMsg = pUser;
ret |= get_user(s32Data, &(pCompatMsg->chan_num));
pIoctlMsg->chan_num = s32Data;
ret |= get_user(s32Data, &(pCompatMsg->in_size));
pIoctlMsg->in_size = s32Data;
ret |= get_user(s32Data, &(pCompatMsg->out_size));
pIoctlMsg->out_size = s32Data;
ret |= get_user(CompatData, &(pCompatMsg->in));
pIoctlMsg->in = (void *) ((unsigned long)CompatData);
ret |= get_user(CompatData, &(pCompatMsg->out));
pIoctlMsg->out = (void *) ((unsigned long)CompatData);
}
break;
default:
printk(KERN_CRIT "%s: unkown type %d\n", __func__, eType);
ret = HI_FAILURE;
break;
}
return ret;
}
static long omxvdec_ioctl_common(struct file *file, unsigned int cmd, unsigned long arg, COMPAT_TYPE_E type)
{
int ret;
int x_scene;
OMXVDEC_IOCTL_MSG vdec_msg;
void *u_arg = (void *)arg;
OMXVDEC_ENTRY *omxvdec = file->private_data;
OMXSCD_REG_CFG_S scd_reg_cfg;
SCD_STATE_REG_S scd_state_reg;
OMXVDH_REG_CFG_S vdm_reg_cfg;
VDMHAL_BACKUP_S vdm_state_reg;
int vdm_is_run;
x_scene = VCTRL_Scen_Ident(cmd);
CHECK_SCENE_EQ_RETURN(x_scene == 1, "xxx scene");
CHECK_RETURN(omxvdec != NULL, "omxvdec is null");
ret = omxvdec_compat_get_data(type, u_arg, &vdec_msg);
CHECK_RETURN(ret == HI_SUCCESS, "compat data get failed");
switch (cmd) {
case VDEC_IOCTL_VDM_PROC:
CHECK_PARA_SIZE_RETURN(sizeof(vdm_reg_cfg), vdec_msg.in_size, "VDEC_IOCTL_VDM_PROC_IN");
CHECK_PARA_SIZE_RETURN(sizeof(vdm_state_reg), vdec_msg.out_size, "VDEC_IOCTL_VDM_PROC_OUT");
if (copy_from_user(&vdm_reg_cfg, vdec_msg.in, sizeof(vdm_reg_cfg))) {
printk(KERN_CRIT "VDEC_IOCTL_VDM_PROC : copy_from_user failed\n");
return -EFAULT;
}
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_vdh);
dsb(sy);
ret = VCTRL_VDMHal_Process(&vdm_reg_cfg, &vdm_state_reg);
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "VCTRL_VDMHal_Process failed\n");
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_vdh);
return -EIO;
}
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_vdh);
if (copy_to_user(vdec_msg.out, &vdm_state_reg, sizeof(vdm_state_reg))) {
printk(KERN_CRIT "VDEC_IOCTL_VDM_PROC : copy_to_user failed\n");
return -EFAULT;
}
break;
case VDEC_IOCTL_GET_VDM_HWSTATE:
CHECK_PARA_SIZE_RETURN(sizeof(vdm_is_run), vdec_msg.out_size, "VDEC_IOCTL_GET_VDM_HWSTATE");
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_vdh);
vdm_is_run = VCTRL_VDMHAL_IsRun();
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_vdh);
if (copy_to_user(vdec_msg.out, &vdm_is_run, sizeof(vdm_is_run))) {
printk(KERN_CRIT "VDEC_IOCTL_GET_VDM_HWSTATE : copy_to_user failed\n");
return -EFAULT;
}
break;
case VDEC_IOCTL_SCD_PROC:
CHECK_PARA_SIZE_RETURN(sizeof(scd_reg_cfg), vdec_msg.in_size, "VDEC_IOCTL_SCD_PROC_IN");
CHECK_PARA_SIZE_RETURN(sizeof(scd_state_reg), vdec_msg.out_size, "VDEC_IOCTL_SCD_PROC_OUT");
if (copy_from_user(&scd_reg_cfg, vdec_msg.in, sizeof(scd_reg_cfg))) {
printk(KERN_CRIT "VDEC_IOCTL_SCD_PROC : copy_from_user failed\n");
return -EFAULT;
}
VDEC_MUTEX_LOCK(&omxvdec->vdec_mutex_scd);
dsb(sy);
ret = VCTRL_SCDHal_Process(&scd_reg_cfg, &scd_state_reg);
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "VCTRL_SCDHal_Process failed\n");
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_scd);
return -EIO;
}
VDEC_MUTEX_UNLOCK(&omxvdec->vdec_mutex_scd);
if (copy_to_user(vdec_msg.out, &scd_state_reg, sizeof(scd_state_reg))) {
printk(KERN_CRIT "VDEC_IOCTL_SCD_PROC : copy_to_user failed\n");
return -EFAULT;
}
break;
default:
/* could not handle ioctl */
printk(KERN_CRIT "%s %d: cmd : %d is not supported\n", __func__, __LINE__, _IOC_NR(cmd));
return -ENOTTY;
}
return 0;
}
static long omxvdec_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
return omxvdec_ioctl_common(file, cmd, arg, T_IOCTL_ARG);
}
/* Modified for 64-bit platform */
#ifdef CONFIG_COMPAT
static long omxvdec_compat_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
void *user_ptr = compat_ptr(arg);
return omxvdec_ioctl_common(file, cmd, (unsigned long)user_ptr, T_IOCTL_ARG_COMPAT);
}
#endif
static const struct file_operations omxvdec_fops = {
.owner = THIS_MODULE,
.open = omxvdec_open,
.unlocked_ioctl = omxvdec_ioctl,
#ifdef CONFIG_COMPAT
.compat_ioctl = omxvdec_compat_ioctl,
#endif
.release = omxvdec_release,
};
static int omxvdec_probe(struct platform_device *pltdev)
{
int ret;
if (gIsDeviceDetected == 1) {
printk(KERN_DEBUG "Already probe omxvdec\n");
return 0;
}
platform_set_drvdata(pltdev, NULL);
memset(&g_OmxVdecEntry, 0, sizeof(OMXVDEC_ENTRY)); /* unsafe_function_ignore: memset */
VDEC_INIT_MUTEX(&g_OmxVdecEntry.omxvdec_mutex);
VDEC_INIT_MUTEX(&g_OmxVdecEntry.vdec_mutex_scd);
VDEC_INIT_MUTEX(&g_OmxVdecEntry.vdec_mutex_vdh);
ret = omxvdec_setup_cdev(&g_OmxVdecEntry, &omxvdec_fops);
if (ret < 0) {
printk(KERN_CRIT "%s call omxvdec_setup_cdev failed\n", __func__);
goto cleanup0;
}
ret = VDEC_Regulator_Probe(&pltdev->dev);
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s call Regulator_Initialize failed\n", __func__);
goto cleanup1;
}
g_OmxVdecEntry.device = &pltdev->dev;
platform_set_drvdata(pltdev, &g_OmxVdecEntry);
gIsDeviceDetected = 1;
return 0;
cleanup1:
omxvdec_cleanup_cdev(&g_OmxVdecEntry);
cleanup0:
return ret;
}
static int omxvdec_remove(struct platform_device *pltdev)
{
OMXVDEC_ENTRY *omxvdec = NULL;
omxvdec = platform_get_drvdata(pltdev);
if (omxvdec != NULL) {
if (IS_ERR(omxvdec)) {
printk(KERN_ERR "call platform_get_drvdata err, errno : %ld\n", PTR_ERR(omxvdec));
} else {
omxvdec_cleanup_cdev(omxvdec);
VDEC_Regulator_Remove(&pltdev->dev);
platform_set_drvdata(pltdev, NULL);
gIsDeviceDetected = 0;
}
}
return 0;
}
static int omxvdec_suspend(struct platform_device *pltdev, pm_message_t state)
{
int ret;
printk(KERN_INFO "%s enter\n", __func__);
if (gIsNormalInit != 0)
VCTRL_Suspend();
ret = VDEC_Regulator_Disable();
if (ret != HI_SUCCESS)
printk(KERN_CRIT "%s disable regulator failed\n", __func__);
printk(KERN_INFO "%s success\n", __func__);
return HI_SUCCESS;
}
static int omxvdec_resume(struct platform_device *pltdev)
{
int ret;
CLK_RATE_E resume_clk = VDEC_CLK_RATE_NORMAL;
printk(KERN_INFO "%s enter\n", __func__);
VDEC_Regulator_GetClkRate(&resume_clk);
if (gIsNormalInit != 0) {
ret = VDEC_Regulator_Enable();
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s enable regulator failed\n", __func__);
return HI_FAILURE;
}
ret = VDEC_Regulator_SetClkRate(resume_clk);
if (ret != HI_SUCCESS)
{
printk(KERN_CRIT "%s, set clk failed\n", __func__);
}
VCTRL_Resume();
}
printk(KERN_INFO "%s success\n", __func__);
return HI_SUCCESS;
}
static void omxvdec_device_release(struct device *dev)
{
return;
}
static struct platform_driver omxvdec_driver = {
.probe = omxvdec_probe,
.remove = omxvdec_remove,
.suspend = omxvdec_suspend,
.resume = omxvdec_resume,
.driver = {
.name = (char*) g_OmxVdecDrvName,
.owner = THIS_MODULE,
.of_match_table = Hisi_Vdec_Match_Table
},
};
static struct platform_device omxvdec_device = {
.name = g_OmxVdecDrvName,
.id = -1,
.dev = {
.platform_data = NULL,
.release = omxvdec_device_release,
},
};
int __init OMXVDEC_DRV_ModInit(void)
{
int ret;
ret = platform_device_register(&omxvdec_device);
if (ret < 0) {
printk(KERN_CRIT "%s call platform_device_register failed\n", __func__);
return ret;
}
ret = platform_driver_register(&omxvdec_driver);
if (ret < 0) {
printk(KERN_CRIT "%s call platform_driver_register failed\n", __func__);
goto exit;
}
#ifdef MODULE
printk(KERN_INFO "Load hi_omxvdec.ko :%d success\n", OMXVDEC_VERSION);
#endif
return HI_SUCCESS;
exit:
platform_device_unregister(&omxvdec_device);
return ret;
}
void __exit OMXVDEC_DRV_ModExit(void)
{
platform_driver_unregister(&omxvdec_driver);
platform_device_unregister(&omxvdec_device);
#ifdef MODULE
printk(KERN_INFO "Unload hi_omxvdec.ko : %d success\n", OMXVDEC_VERSION);
#endif
}
module_init(OMXVDEC_DRV_ModInit);
module_exit(OMXVDEC_DRV_ModExit);
MODULE_AUTHOR("gaoyajun@hisilicon.com");
MODULE_DESCRIPTION("vdec driver");
MODULE_LICENSE("GPL");
+122
View File
@@ -0,0 +1,122 @@
#ifndef __OMXVDEC_H__
#define __OMXVDEC_H__
#include "regulator.h"
#include "../vfmw_v4.0/public.h"
#include "../vfmw_v4.0/scd_drv.h"
#include <linux/ioctl.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/cdev.h>
#include <linux/delay.h>
#include <linux/sched.h>
#include <linux/module.h>
#include <linux/proc_fs.h>
#include <linux/version.h>
#include <linux/kthread.h>
#include <linux/seq_file.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <asm/uaccess.h>
#include <asm/atomic.h>
#ifdef CONFIG_COMPAT
#include <linux/compat.h>
#endif
#if defined(__KERNEL__)
#include <linux/version.h>
#endif
#define OMXVDEC_NAME "hi_vdec"
#define PATH_LEN (256)
#define OMXVDEC_VERSION (2017032300)
#define MAX_OPEN_COUNT (32)
#ifndef NULL
#define NULL (0L)
#endif
#define HI_SUCCESS (0)
#define HI_FAILURE (-1)
#define RETURN_FAIL_IF_COND_IS_TRUE(cond, str) \
do { \
if (cond) \
{ \
printk(KERN_CRIT "[%s : %d]- %s\n", __func__, __LINE__, str); \
return HI_FAILURE; \
} \
}while(0)
#define VDEC_INIT_MUTEX(lock) \
do { \
mutex_init(lock); \
} while(0)
#define VDEC_MUTEX_LOCK(lock) \
do { \
mutex_lock(lock); \
} while(0)
#define VDEC_MUTEX_UNLOCK(lock) \
do { \
mutex_unlock(lock); \
} while(0)
typedef struct {
unsigned char u8IsMapVirtual;
unsigned char u8IsMapped;
unsigned int u32ShareFd;
unsigned int u32StartPhyAddr;
unsigned int u32Size;
void *pStartVirAddr;
} MEM_BUFFER_S;
typedef struct hi_OMXVDEC_IOCTL_MSG {
int chan_num;
int in_size;
int out_size;
void *in;
void *out;
} OMXVDEC_IOCTL_MSG;
//Modified for 64-bit platform
typedef struct hi_COMPAT_IOCTL_MSG {
int chan_num;
int in_size;
int out_size;
compat_ulong_t in;
compat_ulong_t out;
} COMPAT_IOCTL_MSG;
typedef struct {
unsigned int open_count;
atomic_t nor_chan_num;
atomic_t sec_chan_num;
MEM_BUFFER_S com_msg_pool;
struct mutex omxvdec_mutex;
struct mutex vdec_mutex_scd;
struct mutex vdec_mutex_vdh;
struct cdev cdev;
struct device *device;
} OMXVDEC_ENTRY;
typedef int(*VDEC_PROC_CMD) (OMXVDEC_IOCTL_MSG *pVdecMsg);
#define VDEC_IOCTL_MAGIC 'v'
#define VDEC_IOCTL_SET_CLK_RATE \
_IO(VDEC_IOCTL_MAGIC, 20)
#define VDEC_IOCTL_GET_VDM_HWSTATE \
_IO(VDEC_IOCTL_MAGIC, 21)
#define VDEC_IOCTL_SCD_PROC \
_IO(VDEC_IOCTL_MAGIC, 22)
#define VDEC_IOCTL_VDM_PROC \
_IO(VDEC_IOCTL_MAGIC, 23)
#endif
+395
View File
@@ -0,0 +1,395 @@
/*
* vdec regulator manager
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "regulator.h"
#include <linux/hisi/hisi-iommu.h>
#include <linux/iommu.h>
#include <linux/platform_device.h>
#include <linux/regulator/consumer.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/clk.h>
#include <linux/printk.h>
/*lint -e774*/
#define VDEC_REGULATOR_NAME "ldo_vdec"
#define MEDIA_REGULATOR_NAME "ldo_media"
#define VCODEC_CLOCK_NAME "clk_gate_vdecfreq"
#define VCODEC_CLK_RATE "dec_clk_rate"
static unsigned int g_clock_values[] = {450000000, 300000000, 185000000};
static unsigned int g_VdecClkRate_l = 185000000;
static unsigned int g_VdecClkRate_n = 300000000;
static unsigned int g_VdecClkRate_h = 450000000;
static unsigned int g_CurClkRate = 0;
static int g_VdecPowerOn = 0;
static struct clk *g_PvdecClk = NULL;
static struct regulator *g_VdecRegulator = NULL;
static struct regulator *g_MediaRegulator = NULL;
static struct iommu_domain *g_VdecSmmuDomain = NULL;
struct mutex g_RegulatorMutex;
static VFMW_DTS_CONFIG_S g_DtsConfig;
static CLK_RATE_E g_ResumeClkType = VDEC_CLK_RATE_LOW;
#ifdef HIVDEC_SMMU_SUPPORT
/*----------------------------------------
func: iommu enable intf
----------------------------------------*/
static int VDEC_Enable_Iommu(struct device *dev)
{
int ret = HI_FAILURE;
g_VdecSmmuDomain = iommu_domain_alloc(dev->bus);
if (NULL == g_VdecSmmuDomain) {
printk(KERN_ERR "%s iommu_domain_alloc failed!\n", __func__);
return HI_FAILURE;
}
ret = iommu_attach_device(g_VdecSmmuDomain, dev);
if (ret) {
printk(KERN_ERR "iommu_attach_device failed!\n");
goto out_free_domain;
}
return HI_SUCCESS;
out_free_domain:
iommu_domain_free(g_VdecSmmuDomain);
return HI_FAILURE;
}
static void VDEC_Disable_Iommu(struct device *dev)
{
g_VdecSmmuDomain = NULL;
if( g_VdecSmmuDomain && dev) {
iommu_detach_device(g_VdecSmmuDomain, dev);
iommu_domain_free(g_VdecSmmuDomain);
g_VdecSmmuDomain = NULL;
}
}
static unsigned long long VDEC_GetSmmuBasePhy(struct device *dev)
{
struct iommu_domain_data *domain_data = NULL;
if (VDEC_Enable_Iommu(dev) == HI_FAILURE)
return 0;
domain_data = (struct iommu_domain_data *)(g_VdecSmmuDomain->priv);
return (unsigned long long) (domain_data->phy_pgd_base);
}
#endif
static int read_clock_rate_value(struct device_node *np, unsigned int index, unsigned int *clock)
{
int ret;
ret = of_property_read_u32_index(np, VCODEC_CLK_RATE, index, clock);
if (ret) {
printk(KERN_CRIT "read clock rate[%d] failed\n", index);
*clock = g_clock_values[index];
return HI_FAILURE;
}
return HI_SUCCESS;
}
static int VDEC_Init_ClockRate(struct device *dev)
{
int ret;
struct clk *pvdec_clk = NULL;
pvdec_clk = devm_clk_get(dev, VCODEC_CLOCK_NAME);
if (IS_ERR_OR_NULL(pvdec_clk)) {
printk(KERN_CRIT "%s can not get clock\n", __func__);
return HI_FAILURE;
}
g_PvdecClk = pvdec_clk;
ret = read_clock_rate_value(dev->of_node, 0, &g_VdecClkRate_h);
ret += read_clock_rate_value(dev->of_node, 1, &g_VdecClkRate_n);
ret += read_clock_rate_value(dev->of_node, 2, &g_VdecClkRate_l);
RETURN_FAIL_IF_COND_IS_TRUE(ret, "read clock failed");
g_CurClkRate = g_VdecClkRate_l;
return HI_SUCCESS;
}
static int VDEC_GetDtsConfigInfo(struct device *dev, VFMW_DTS_CONFIG_S *pDtsConfig)
{
int ret;
struct device_node *np_crg = NULL;
struct device_node *np = dev->of_node;
struct resource res;
RETURN_FAIL_IF_COND_IS_TRUE(dev->of_node == NULL, "device node is null");
RETURN_FAIL_IF_COND_IS_TRUE(pDtsConfig == NULL, "dts config is null");
pDtsConfig->VdecIrqNumNorm = irq_of_parse_and_map(np, 0);
RETURN_FAIL_IF_COND_IS_TRUE(pDtsConfig->VdecIrqNumNorm == 0, "get irq num failed");
/*
FIXME irq_of_parse_and_map(np, 1);
FIXME irq_of_parse_and_map(np, 2);
*/
pDtsConfig->VdecIrqNumProt = 323;
pDtsConfig->VdecIrqNumSafe = 324;
/* Get reg base addr & size, return 0 if success */
ret = of_address_to_resource(np, 0, &res);
RETURN_FAIL_IF_COND_IS_TRUE(ret, "of_address_to_resource failed");
pDtsConfig->VdhRegBaseAddr = res.start;
pDtsConfig->VdhRegRange = resource_size(&res);
#ifdef HIVDEC_SMMU_SUPPORT
/* Get reg base addr, return 0 if failed */
pDtsConfig->SmmuPageBaseAddr = VDEC_GetSmmuBasePhy(dev);
RETURN_FAIL_IF_COND_IS_TRUE(pDtsConfig->SmmuPageBaseAddr == 0, "get smmu base addr failed");
#endif
np_crg = of_find_compatible_node(NULL, NULL, "hisilicon,media2-crg");
RETURN_FAIL_IF_COND_IS_TRUE(!np_crg, "can't find media2-crg node");
ret = of_address_to_resource(np_crg, 0, &res);
RETURN_FAIL_IF_COND_IS_TRUE(ret, "of_address_to_resource failed");
pDtsConfig->PERICRG_RegBaseAddr = res.start;
ret = VDEC_Init_ClockRate(dev);
RETURN_FAIL_IF_COND_IS_TRUE(ret != HI_SUCCESS, "init clock failed");
return HI_SUCCESS;
}
/******************************** SHARE FUNC **********************************/
/*----------------------------------------
func: regulator probe entry
----------------------------------------*/
int VDEC_Regulator_Probe(struct device *dev)
{
int ret;
g_VdecRegulator = NULL;
g_MediaRegulator = NULL;
if (dev == NULL) {
printk(KERN_CRIT "%s, invalid params", __func__);
return HI_FAILURE;
}
memset(&g_DtsConfig, 0, sizeof(g_DtsConfig)); /* unsafe_function_ignore: memset */
ret = VDEC_GetDtsConfigInfo(dev, &g_DtsConfig);
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s Regulator_GetDtsConfigInfo failed\n", __func__);
return HI_FAILURE;
}
ret = VFMW_SetDtsConfig(&g_DtsConfig);
if (ret != HI_SUCCESS) {
printk(KERN_CRIT "%s VFMW_SetDtsConfig failed\n", __func__);
return HI_FAILURE;
}
VDEC_INIT_MUTEX(&g_RegulatorMutex);
return HI_SUCCESS;
}
/*----------------------------------------
func: regulator deinitialize
----------------------------------------*/
int VDEC_Regulator_Remove(struct device * dev)
{
VDEC_MUTEX_LOCK(&g_RegulatorMutex);
VDEC_Disable_Iommu(dev);
g_VdecRegulator = NULL;
g_MediaRegulator = NULL;
g_PvdecClk = NULL;
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
}
/*----------------------------------------
func: enable regulator
----------------------------------------*/
int VDEC_Regulator_Enable(void)
{
int ret;
VDEC_MUTEX_LOCK(&g_RegulatorMutex);
if (g_VdecPowerOn == 1) {
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
}
if (g_PvdecClk == NULL) {
printk(KERN_CRIT "%s: invalid g_PvdecClk is NULL\n", __func__);
goto error_exit;
}
ret = clk_prepare_enable(g_PvdecClk);
if (ret != 0) {
printk(KERN_CRIT "%s clk_prepare_enable failed\n", __func__);
goto error_exit;
}
ret = clk_set_rate(g_PvdecClk, g_VdecClkRate_l);
if (ret)
{
printk(KERN_CRIT "%s Failed to clk_set_rate:%u, return %d\n", __func__, g_VdecClkRate_l, ret);
goto error_unprepare_clk;
}
printk(KERN_INFO "vdec regulator enable\n");
g_VdecPowerOn = 1;
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
error_unprepare_clk:
clk_disable_unprepare(g_PvdecClk);
error_exit:
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_FAILURE;
}
/*----------------------------------------
func: disable regulator
----------------------------------------*/
int VDEC_Regulator_Disable(void)
{
int ret;
VDEC_MUTEX_LOCK(&g_RegulatorMutex);
if (g_VdecPowerOn == 0) {
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
}
if (g_PvdecClk == NULL) {
printk(KERN_CRIT "%s g_PvdecClk is NULL\n", __func__);
goto error_exit;
}
ret = clk_set_rate(g_PvdecClk, g_VdecClkRate_l);
if (ret) {
printk(KERN_CRIT "%s Failed to clk_set_rate:%u, return %d\n", __func__, g_VdecClkRate_l, ret);
//goto error_exit;//continue, no return
}
clk_disable_unprepare(g_PvdecClk);
g_VdecPowerOn = 0;
printk(KERN_INFO "vdec regulator disable\n");
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
error_exit:
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_FAILURE;
}
/*----------------------------------------
func: get decoder clock rate
----------------------------------------*/
void VDEC_Regulator_GetClkRate(CLK_RATE_E *pClkRate)
{
VDEC_MUTEX_LOCK(&g_RegulatorMutex);
*pClkRate = g_ResumeClkType;
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
}
int VDEC_Regulator_SetClkRate(CLK_RATE_E eClkRate)
{
int ret = 0;
unsigned int rate = 0;
unsigned char need_set_flag = 1;
VDEC_MUTEX_LOCK(&g_RegulatorMutex);
if (g_DtsConfig.IsFPGA) {
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
}
if (IS_ERR_OR_NULL(g_PvdecClk)) {
printk(KERN_ERR "Couldn't get clk [%s]\n", __func__);
goto error_exit;
}
rate = (unsigned int) clk_get_rate(g_PvdecClk);
switch (eClkRate) {
case VDEC_CLK_RATE_LOW:
if (g_VdecClkRate_l == rate) {
need_set_flag = 0;
} else {
rate = g_VdecClkRate_l;
need_set_flag = 1;
}
break;
case VDEC_CLK_RATE_NORMAL:
if (g_VdecClkRate_n == rate) {
need_set_flag = 0;
}
else {
rate = g_VdecClkRate_n;
need_set_flag = 1;
}
break;
case VDEC_CLK_RATE_HIGH:
if (g_VdecClkRate_h == rate) {
need_set_flag = 0;
} else {
rate = g_VdecClkRate_h;
need_set_flag = 1;
}
break;
default:
printk(KERN_ERR "[%s] unsupport clk rate enum %d\n", __func__, eClkRate);
goto error_exit;
}
if (need_set_flag == 1) {
ret = clk_set_rate(g_PvdecClk, rate);
if (ret != 0) {
printk(KERN_ERR "Failed to clk_set_rate %u HZ[%s] ret : %d\n", rate, __func__, ret);
goto error_exit;
}
g_CurClkRate = rate;
g_ResumeClkType = eClkRate;
}
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_SUCCESS;
error_exit:
VDEC_MUTEX_UNLOCK(&g_RegulatorMutex);
return HI_FAILURE;
}
+27
View File
@@ -0,0 +1,27 @@
#ifndef __VDEC_REGULATOR_H__
#define __VDEC_REGULATOR_H__
#include "../vfmw_v4.0/vfmw_dts.h"
#include "omxvdec.h"
#include <linux/platform_device.h>
typedef enum {
VDEC_CLK_RATE_LOW = 0,
VDEC_CLK_RATE_NORMAL,
VDEC_CLK_RATE_HIGH,
VDEC_CLK_RATE_BUTT,
}CLK_RATE_E;
static const struct of_device_id Hisi_Vdec_Match_Table[] = {
{.compatible = "hisi,kirin970-vdec",},
{ }
};
int VDEC_Regulator_Probe(struct device *dev);
int VDEC_Regulator_Remove(struct device *dev);
int VDEC_Regulator_Enable(void);
int VDEC_Regulator_Disable(void);
void VDEC_Regulator_GetClkRate(CLK_RATE_E *pClkRate);
int VDEC_Regulator_SetClkRate(CLK_RATE_E eClkRate);
#endif
+5
View File
@@ -0,0 +1,5 @@
config VDEC_VFMW
tristate "hisilicon video firmware support"
default n
---help---
This is the vfmw driver
+12
View File
@@ -0,0 +1,12 @@
TOP := drivers/../..
VFMW_DIR := drivers/vcodec/vdec_hivna
include $(VFMW_DIR)/vfmw_v4.0/vfmw_make.cfg
EXTRA_CFLAGS += -Idrivers/vcodec/vdec_hivna
EXTRA_CFLAGS += -Idrivers/vcodec/vdec_hivna/omxvdec
EXTRA_CFLAGS += $(VFMW_CFLAGS) -fno-pic
#build in
obj-$(CONFIG_HI_VCODEC_VDEC) += hi_vfmw.o
hi_vfmw-objs := $(VFMW_CFILES)
+166
View File
@@ -0,0 +1,166 @@
#ifndef __VDM_DRV_HEADER__
#define __VDM_DRV_HEADER__
#include "../vfmw.h"
#include "../sysconfig.h"
#define VDMDRV_OK (0)
#define VDMDRV_ERR (-1)
#define MSG_SLOT_SIZE (256)
#define LUMA_HISTORGAM_NUM (32)
#define HEVC_ONE_MSG_SLOT_LEN (320) // 64*5
#define MAX_FRAME_NUM (32)
#ifdef VFMW_HEVC_SUPPORT
#define USE_MSG_SLOT_SIZE HEVC_ONE_MSG_SLOT_LEN
#else
#define USE_MSG_SLOT_SIZE MSG_SLOT_SIZE
#endif
typedef enum {
VDH_SHAREFD_MESSAGE_POOL = 0,
VDH_SHAREFD_STREAM_BUF = 1,
VDH_SHAREFD_PMV_BUF = 2,
VDH_SHAREFD_FRM_BUF = 3,
VDH_SHAREFD_MAX = (VDH_SHAREFD_FRM_BUF + MAX_FRAME_NUM)
}VDH_SHAREFD;
typedef enum {
VDH_STATE_REG = 1,
INT_STATE_REG = 2,
INT_MASK_REG = 3,
VCTRL_STATE_REG = 4,
} REG_ID_E;
typedef enum {
VDM_IDLE_STATE = 0,
VDM_DECODE_STATE = 1,
VDM_REPAIR_STATE_0 = 2,
VDM_REPAIR_STATE_1 = 3
} VDMDRV_STATEMACHINE_E;
typedef enum {
VDMDRV_SLEEP_STAGE_NONE = 0,
VDMDRV_SLEEP_STAGE_PREPARE,
VDMDRV_SLEEP_STAGE_SLEEP
} VDMDRV_SLEEP_STAGE_E;
typedef enum {
FIRST_REPAIR = 0,
SECOND_REPAIR
} REPAIRTIME_S;
typedef enum hi_CONFIG_VDH_CMD {
CONFIG_VDH_AfterDec_CMD = 200,
CONFIG_VDH_ACTIVATEDEC_CMD
} CONFIG_VDH_CMD;
typedef struct {
unsigned int vdh_reset_flag;
unsigned int GlbResetFlag;
int VdhStartRepairFlag;
int VdhStartHwDecFlag;
int VdhBasicCfg0;
int VdhBasicCfg1;
int VdhAvmAddr;
int VdhVamAddr;
int VdhStreamBaseAddr;
int VdhEmarId;
int VdhYstAddr;
int VdhYstride;
int VdhUvstride;//VREG_UVSTRIDE_1D
int VdhCfgInfoAddr;//CFGINFO_ADDR
int VdhUvoffset;
int VdhRefPicType;
int VdhFfAptEn;
REPAIRTIME_S RepairTime;
VID_STD_E VidStd;
int ValidGroupNum0;
int vdh_share_fd[VDH_SHAREFD_MAX];
unsigned int vdhFrmBufNum;
int IsFrmBufRemap;
int IsPmvBufRemap;
int IsAllBufRemap;
} OMXVDH_REG_CFG_S;
typedef struct {
// vdm register base vir addr
int *pVdmRegVirAddr;
// vdm hal base addr
unsigned int HALMemBaseAddr;
int HALMemSize;
int VahbStride;
/* message pool */
unsigned int MsgSlotAddr[256];
int ValidMsgSlotNum;
/* vlc code table */
unsigned int H264TabAddr; /* 32 Kbyte */
unsigned int MPEG2TabAddr; /* 32 Kbyte */
unsigned int MPEG4TabAddr; /* 32 Kbyte */
unsigned int AVSTabAddr; /* 32 Kbyte */
unsigned int VC1TabAddr;
/* cabac table */
unsigned int H264MnAddr;
/* nei info for vdh for hevc */
unsigned int sed_top_phy_addr;
unsigned int pmv_top_phy_addr;
unsigned int pmv_left_phy_addr;
unsigned int rcn_top_phy_addr;
unsigned int mn_phy_addr;
unsigned int tile_segment_info_phy_addr;
unsigned int dblk_left_phy_addr;
unsigned int dblk_top_phy_addr;
unsigned int sao_left_phy_addr;
unsigned int sao_top_phy_addr;
unsigned int ppfd_phy_addr;
int ppfd_buf_len;
/*nei info for vdh */
unsigned int SedTopAddr; /* len = 64*4*x */
unsigned int PmvTopAddr; /* len = 64*4*x */
unsigned int RcnTopAddr; /* len = 64*4*x */
unsigned int ItransTopAddr;
unsigned int DblkTopAddr;
unsigned int PpfdBufAddr;
unsigned int PpfdBufLen;
unsigned int IntensityConvTabAddr;
unsigned int BitplaneInfoAddr;
unsigned int Vp6TabAddr;
unsigned int Vp8TabAddr;
/* VP9 */
unsigned int DblkLeftAddr;
unsigned int Vp9ProbTabAddr;
unsigned int Vp9ProbCntAddr;
unsigned char *luma_2d_vir_addr;
unsigned int luma_2d_phy_addr;
unsigned char *chrom_2d_vir_addr;
unsigned int chrom_2d_phy_addr;
} VDMHAL_HWMEM_S;
typedef struct {
unsigned int Int_State_Reg;
unsigned int BasicCfg1;
unsigned int VdmState;
unsigned int Mb0QpInCurrPic;
unsigned int SwitchRounding;
unsigned int SedSta;
unsigned int SedEnd0;
unsigned int DecCyclePerPic;
unsigned int RdBdwidthPerPic;
unsigned int WrBdWidthPerPic;
unsigned int RdReqPerPic;
unsigned int WrReqPerPic;
unsigned int LumaSumHigh;
unsigned int LumaSumLow;
unsigned int LumaHistorgam[LUMA_HISTORGAM_NUM];
} VDMHAL_BACKUP_S;
extern VDMHAL_HWMEM_S g_HwMem[MAX_VDH_NUM];
#endif
+553
View File
@@ -0,0 +1,553 @@
/*
* vdm hal interface
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "vfmw.h"
#include "mem_manage.h"
//#include "public.h"
#include "scd_drv.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "omxvdec.h"
#include "linux_kernel_osal.h"
#ifdef VFMW_MPEG2_SUPPORT
#include "vdm_hal_mpeg2.h"
#endif
#ifdef VFMW_H264_SUPPORT
#include "vdm_hal_h264.h"
#endif
#ifdef VFMW_HEVC_SUPPORT
#include "vdm_hal_hevc.h"
#endif
#ifdef VFMW_MPEG4_SUPPORT
#include "vdm_hal_mpeg4.h"
#endif
#ifdef VFMW_VP8_SUPPORT
#include "vdm_hal_vp8.h"
#endif
#ifdef VFMW_VP9_SUPPORT
#include "vdm_hal_vp9.h"
#endif
#include "vfmw_intf.h"
#ifdef HIVDEC_SMMU_SUPPORT
#include "smmu.h"
#endif
VDMHAL_HWMEM_S g_HwMem[MAX_VDH_NUM];
VDMHAL_BACKUP_S g_VdmRegState;
static VDMDRV_SLEEP_STAGE_E s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_NONE;
static VDMDRV_STATEMACHINE_E s_VdmState = VDM_IDLE_STATE;
void VDMHAL_EnableInt(int VdhId)
{
unsigned int D32 = 0xFFFFFFFE;
int *p32 = NULL;
if (VdhId != 0) {
printk(KERN_ERR "VDH ID is wrong\n");
return;
}
if (g_HwMem[VdhId].pVdmRegVirAddr == NULL) {
p32 = (int *) MEM_Phy2Vir(gVdhRegBaseAddr);
if (p32 == NULL) {
printk(KERN_ERR "vdm register virtual address not mapped, reset failed\n");
return;
}
g_HwMem[VdhId].pVdmRegVirAddr = p32;
}
WR_VREG(VREG_INT_MASK, D32, VdhId);
return;
}
int VDMHAL_CfgRpReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int D32 = 0;
WR_VREG(VREG_AVM_ADDR, pVdhRegCfg->VdhAvmAddr, 0);
D32 = 0x2000C203;
WR_VREG(VREG_BASIC_CFG1, D32, 0);
D32 = 0x00300C03;
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
return VDMHAL_OK;
}
void VDMHAL_IMP_Init(void)
{
memset(g_HwMem, 0, sizeof(g_HwMem));
memset(&g_VdmRegState, 0, sizeof(g_VdmRegState));
g_HwMem[0].pVdmRegVirAddr = (int *) MEM_Phy2Vir(gVdhRegBaseAddr);
VDMHAL_IMP_GlbReset();
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_NONE;
s_VdmState = VDM_IDLE_STATE;
}
void VDMHAL_IMP_DeInit(void)
{
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_NONE;
s_VdmState = VDM_IDLE_STATE;
}
void VDMHAL_IMP_ResetVdm(int VdhId)
{
int i;
int tmp = 0;
unsigned int reg;
unsigned int reg_rst_ok;
unsigned int *pVdmResetVirAddr;
unsigned int *pVdmResetOkVirAddr;
pVdmResetVirAddr = (unsigned int *) MEM_Phy2Vir(gSOFTRST_REQ_Addr);
pVdmResetOkVirAddr = (unsigned int *) MEM_Phy2Vir(gSOFTRST_OK_ADDR);
if ((pVdmResetVirAddr == NULL)
|| (pVdmResetOkVirAddr == NULL)
|| (g_HwMem[VdhId].pVdmRegVirAddr == NULL)) {
printk(KERN_ERR "map vdm register fail, vir(pVdmResetVirAddr) : (%pK), vir(pVdmResetOkVirAddr) : (%pK)\n", pVdmResetVirAddr, pVdmResetOkVirAddr);
return;
}
RD_VREG(VREG_INT_MASK, tmp, VdhId);
/* require mfde reset */
reg = *(volatile unsigned int *)pVdmResetVirAddr;
*(volatile unsigned int *)pVdmResetVirAddr = reg | (unsigned int) (1 << MFDE_RESET_CTRL_BIT);
/* wait for reset ok */
for (i = 0; i < 100; i++) {
reg_rst_ok = *(volatile unsigned int *)pVdmResetOkVirAddr;
if (reg_rst_ok & (1 << MFDE_RESET_OK_BIT))
break;
VFMW_OSAL_uDelay(10);
}
if (i >= 100)
printk(KERN_ERR "%s reset failed\n", __func__);
/* clear reset require */
*(volatile unsigned int *)pVdmResetVirAddr = reg & (unsigned int) (~(1 << MFDE_RESET_CTRL_BIT));
WR_VREG(VREG_INT_MASK, tmp, VdhId);
s_VdmState = VDM_IDLE_STATE;
return;
}
void VDMHAL_IMP_GlbReset(void)
{
int i;
unsigned int reg, reg_rst_ok;
unsigned int *pResetVirAddr = NULL;
unsigned int *pResetOKVirAddr = NULL;
pResetVirAddr = (unsigned int *) MEM_Phy2Vir(gSOFTRST_REQ_Addr);
pResetOKVirAddr = (unsigned int *) MEM_Phy2Vir(gSOFTRST_OK_ADDR);
if (pResetVirAddr == NULL || pResetOKVirAddr == NULL) {
printk(KERN_ERR "VDMHAL_GlbReset: map vdm register fail, vir(pResetVirAddr) : (%pK), vir(pResetOKVirAddr) : (%pK)\n", pResetVirAddr, pResetOKVirAddr);
return;
}
/* require all reset, include mfde scd bpd */
reg = *(volatile unsigned int *)pResetVirAddr;
*(volatile unsigned int *)pResetVirAddr = reg | (unsigned int) (1 << ALL_RESET_CTRL_BIT);
/* wait for reset ok */
for (i = 0; i < 100; i++) {
reg_rst_ok = *(volatile unsigned int *)pResetOKVirAddr;
if (reg_rst_ok & (1 << ALL_RESET_OK_BIT))
break;
VFMW_OSAL_uDelay(10);
}
if (i >= 100)
printk(KERN_ERR "Glb Reset Failed\n");
/* clear reset require */
*(volatile unsigned int *)pResetVirAddr = reg & (unsigned int) (~(1 << ALL_RESET_CTRL_BIT));
return;
}
void VDMHAL_IMP_ClearIntState(int VdhId)
{
int *p32;
unsigned int D32 = 0xFFFFFFFF;
if (VdhId > (MAX_VDH_NUM - 1)) {
printk(KERN_ERR "%s: VdhId : %d is more than %d\n", __func__, VdhId, (MAX_VDH_NUM - 1));
return;
}
if (g_HwMem[VdhId].pVdmRegVirAddr == NULL) {
if ((p32 = (int *) MEM_Phy2Vir(gVdhRegBaseAddr)) != NULL) {
g_HwMem[VdhId].pVdmRegVirAddr = p32;
} else {
printk(KERN_ERR " %s %d vdm register virtual address not mapped, reset failed\n", __func__, __LINE__);
return;
}
}
WR_VREG(VREG_INT_STATE, D32, VdhId);
return;
}
int VDMHAL_IMP_CheckReg(REG_ID_E reg_id, int VdhId)
{
int *p32;
int dat = 0;
unsigned int reg_type;
if (VdhId > (MAX_VDH_NUM - 1)) {
printk(KERN_ERR "%s: Invalid VdhId is %d\n", __func__, VdhId);
return VDMHAL_ERR;
}
if (g_HwMem[VdhId].pVdmRegVirAddr == NULL) {
if ((p32 = (int *) MEM_Phy2Vir(gVdhRegBaseAddr)) != NULL) {
g_HwMem[VdhId].pVdmRegVirAddr = p32;
} else {
printk(KERN_ERR " %s %d vdm register virtual address not mapped, reset failed\n", __func__, __LINE__);
return 0;
}
}
switch (reg_id) {
case VDH_STATE_REG:
reg_type = VREG_VDH_STATE;
break;
case INT_STATE_REG:
reg_type = VREG_INT_STATE;
break;
case INT_MASK_REG:
reg_type = VREG_INT_MASK;
break;
case VCTRL_STATE_REG:
reg_type = VREG_VCTRL_STATE;
break;
default:
printk(KERN_ERR "%s: unkown reg_id is %d\n", __func__, reg_id);
return 0;
}
RD_VREG(reg_type, dat, 0);
return dat;
}
int VDMHAL_IMP_PrepareDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
VDMHAL_HWMEM_S *pHwMem = &(g_HwMem[0]);
int *p32;
if (NULL == pHwMem->pVdmRegVirAddr)
{
if (NULL != (p32 = (int *)MEM_Phy2Vir(gVdhRegBaseAddr)))
{
pHwMem->pVdmRegVirAddr = p32;
}
else
{
printk(KERN_ERR "vdm register virtual address not mapped, VDMHAL_PrepareDecfailed\n");
return VDMHAL_ERR;
}
}
if (VFMW_AVS == pVdhRegCfg->VidStd)
WR_SCDREG(REG_AVS_FLAG, 0x00000001);
else
WR_SCDREG(REG_AVS_FLAG, 0x00000000);
WR_SCDREG(REG_VDH_SELRST, 0x00000001);
switch (pVdhRegCfg->VidStd) {
#ifdef VFMW_H264_SUPPORT
case VFMW_H264:
return H264HAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_HEVC_SUPPORT
case VFMW_HEVC:
return HEVCHAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_MPEG2_SUPPORT
case VFMW_MPEG2:
return MP2HAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_MPEG4_SUPPORT
case VFMW_MPEG4:
return MP4HAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_VP8_SUPPORT
case VFMW_VP8:
return VP8HAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_VP9_SUPPORT
case VFMW_VP9:
return VP9HAL_StartDec(pVdhRegCfg);
#endif
#ifdef VFMW_MVC_SUPPORT
case VFMW_MVC:
return H264HAL_StartDec(pVdhRegCfg);
#endif
default:
break;
}
return VDMHAL_ERR;
}
int VDMHAL_IsVdmRun(int VdhId)
{
int Data32 = 0;
if (g_HwMem[VdhId].pVdmRegVirAddr == NULL) {
printk(KERN_ERR "VDM register not mapped yet\n");
return 0;
}
RD_VREG(VREG_VCTRL_STATE, Data32, VdhId);
return (Data32 == 1 ? 0 : 1);
}
int VDMHAL_IMP_BackupInfo(void)
{
int i = 0;
int regTmp;
g_VdmRegState.Int_State_Reg = VDMHAL_IMP_CheckReg(INT_STATE_REG, 0);
RD_VREG(VREG_BASIC_CFG1, g_VdmRegState.BasicCfg1, 0);
RD_VREG(VREG_VDH_STATE, g_VdmRegState.VdmState, 0);
RD_VREG(VREG_MB0_QP_IN_CURR_PIC, g_VdmRegState.Mb0QpInCurrPic, 0);
RD_VREG(VREG_SWITCH_ROUNDING, g_VdmRegState.SwitchRounding, 0);
{
RD_VREG(VREG_SED_STA, g_VdmRegState.SedSta, 0);
RD_VREG(VREG_SED_END0, g_VdmRegState.SedEnd0, 0);
RD_VREG(VREG_DEC_CYCLEPERPIC, g_VdmRegState.DecCyclePerPic, 0);
RD_VREG(VREG_RD_BDWIDTH_PERPIC, g_VdmRegState.RdBdwidthPerPic, 0);
RD_VREG(VREG_WR_BDWIDTH_PERPIC, g_VdmRegState.WrBdWidthPerPic, 0);
RD_VREG(VREG_RD_REQ_PERPIC, g_VdmRegState.RdReqPerPic, 0);
RD_VREG(VREG_WR_REQ_PERPIC, g_VdmRegState.WrReqPerPic, 0);
RD_VREG(VREG_LUMA_SUM_LOW, g_VdmRegState.LumaSumLow, 0);
RD_VREG(VREG_LUMA_SUM_HIGH, g_VdmRegState.LumaSumHigh, 0);
}
for (i = 0; i < 32; i++) {
regTmp = VREG_LUMA_HISTORGRAM + i * 4;
RD_VREG(regTmp, g_VdmRegState.LumaHistorgam[i], 0);
}
return VDMHAL_OK;
}
void VDMHAL_GetRegState(VDMHAL_BACKUP_S *pVdmRegState)
{
memcpy(pVdmRegState, &g_VdmRegState, sizeof(*pVdmRegState));
s_VdmState = VDM_IDLE_STATE;
}
int VDMHAL_IMP_PrepareRepair(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
VDMHAL_HWMEM_S *pHwMem = &(g_HwMem[0]);
int *p32;
int ret;
if (NULL == pVdhRegCfg)
{
printk(KERN_ERR "%s: parameter is NULL\n", __func__);
return VDMHAL_ERR;
}
if ( NULL == pHwMem->pVdmRegVirAddr )
{
if ( NULL != (p32 = (int *)MEM_Phy2Vir(gVdhRegBaseAddr)) )
{
pHwMem->pVdmRegVirAddr = p32;
}
else
{
printk(KERN_ERR "vdm register virtual address not mapped, VDMHAL_PrepareRepair failed\n");
return VDMHAL_ERR;
}
}
if (pVdhRegCfg->RepairTime == FIRST_REPAIR) {
if (pVdhRegCfg->ValidGroupNum0 > 0)
ret = VDMHAL_CfgRpReg(pVdhRegCfg);
else
ret = VDMHAL_ERR;
} else if (pVdhRegCfg->RepairTime == SECOND_REPAIR) {
printk(KERN_ERR "SECOND_REPAIR Parameter Error\n");
ret = VDMHAL_ERR;
} else {
printk(KERN_ERR " parameter error\n");
ret = VDMHAL_ERR;
}
return ret;
}
void VDMHAL_IMP_StartHwRepair(int VdhId)
{
int D32 = 0;
RD_VREG(VREG_BASIC_CFG0, D32, VdhId);
D32 = 0x4000000;
WR_VREG(VREG_BASIC_CFG0, D32, VdhId);
#ifdef HIVDEC_SMMU_SUPPORT
SMMU_SetMasterReg(MFDE, SECURE_OFF, SMMU_ON);
#endif
VDMHAL_IMP_ClearIntState(VdhId);
VDMHAL_EnableInt(VdhId);
VFMW_OSAL_Mb();
WR_VREG(VREG_VDH_START, 0, VdhId);
WR_VREG(VREG_VDH_START, 1, VdhId);
WR_VREG(VREG_VDH_START, 0, VdhId);
return;
}
void VDMHAL_IMP_StartHwDecode(int VdhId)
{
#ifdef HIVDEC_SMMU_SUPPORT
SMMU_SetMasterReg(MFDE, SECURE_OFF, SMMU_ON);
#endif
VDMHAL_IMP_ClearIntState(VdhId);
VDMHAL_EnableInt(VdhId);
VFMW_OSAL_Mb();
WR_VREG(VREG_VDH_START, 0, 0);
WR_VREG(VREG_VDH_START, 1, 0);
WR_VREG(VREG_VDH_START, 0, 0);
return;
}
void VDMHAL_ISR(int VdhId)
{
VDMHAL_IMP_BackupInfo();
VDMHAL_IMP_ClearIntState(VdhId);
VFMW_OSAL_GiveEvent(G_VDMHWDONEEVENT);
}
int VDMHAL_HwDecProc(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int ret = VDMDRV_ERR;
s_VdmState = VDM_DECODE_STATE;
if (pVdhRegCfg->VdhStartHwDecFlag == 1) {
ret = VDMHAL_IMP_PrepareDec(pVdhRegCfg);
if (ret == VDMDRV_OK) {
VDMHAL_IMP_StartHwDecode(0);
} else {
ret = VDMDRV_ERR;
printk(KERN_ERR "%s prepare dec fail \n", __func__);
}
} else if (pVdhRegCfg->VdhStartRepairFlag == 1) {
ret = VDMHAL_IMP_PrepareRepair(pVdhRegCfg);
if (ret == VDMDRV_OK) {
VDMHAL_IMP_StartHwRepair(0);
} else {
ret = VDMDRV_ERR;
printk(KERN_ERR "%s prepare repair fail \n", __func__);
}
} else {
ret = VDMDRV_ERR;
printk(KERN_ERR "%s process type error \n", __func__);
}
if (ret != VDMDRV_OK) {
s_VdmState = VDM_IDLE_STATE;
}
return ret;
}
int VDMHAL_PrepareSleep(void)
{
int ret = VDMDRV_OK;
VFMW_OSAL_SemaDown(G_VDH_SEM);
if (s_eVdmDrvSleepState == VDMDRV_SLEEP_STAGE_NONE) {
if (VDM_IDLE_STATE == s_VdmState) {
printk(KERN_INFO "%s, idle state \n", __func__);
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_SLEEP;
} else {
printk(KERN_INFO "%s, work state \n", __func__);
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_PREPARE;
}
ret = VDMDRV_OK;
} else {
ret = VDMDRV_ERR;
}
VFMW_OSAL_SemaUp(G_VDH_SEM);
return ret;
}
void VDMHAL_ForceSleep(void)
{
printk(KERN_INFO "%s, force state \n", __func__);
VFMW_OSAL_SemaDown(G_VDH_SEM);
if (s_eVdmDrvSleepState != VDMDRV_SLEEP_STAGE_SLEEP) {
VDMHAL_IMP_ResetVdm(0);
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_SLEEP;
}
VFMW_OSAL_SemaUp(G_VDH_SEM);
}
void VDMHAL_ExitSleep(void)
{
VFMW_OSAL_SemaDown(G_VDH_SEM);
s_eVdmDrvSleepState = VDMDRV_SLEEP_STAGE_NONE;
VFMW_OSAL_SemaUp(G_VDH_SEM);
}
VDMDRV_SLEEP_STAGE_E VDMHAL_GetSleepStage(void)
{
return s_eVdmDrvSleepState;
}
void VDMHAL_SetSleepStage(VDMDRV_SLEEP_STAGE_E sleepState)
{
VFMW_OSAL_SemaDown(G_VDH_SEM);
s_eVdmDrvSleepState = sleepState;
VFMW_OSAL_SemaUp(G_VDH_SEM);
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef _VDM_HAL_HEADER_
#define _VDM_HAL_HEADER_
#include "vdm_drv.h"
#include <linux/io.h>
#include "../../omxvdec/omxvdec.h"
#define VDMHAL_OK (0)
#define VDMHAL_ERR (-1)
#define MAX_SLICE_SLOT_NUM (200)
#define FIRST_REPAIR (0)
#define SECOND_REPAIR (1)
#define MAX_IMG_WIDTH_IN_MB (512)
#define MAX_IMG_HALF_HEIGHT_IN_MB (256)
#define MAX_IMG_HEIGHT_IN_MB (MAX_IMG_HALF_HEIGHT_IN_MB * 2)
#define MAX_MB_NUM_IN_PIC (MAX_IMG_WIDTH_IN_MB * MAX_IMG_HEIGHT_IN_MB)
#define MAX_SLOT_WIDTH (4096)
#define MAX_STRIDE ((1024 * MAX_SLOT_WIDTH / 64 + ((1024) - 1)) & (~ ((1024) - 1)))
/************************************************************************/
/* Register read/write interface */
/************************************************************************/
/* mfde register read/write */
#if 1
#define RD_VREG( reg, dat, VdhId ) \
do { \
if (VdhId < MAX_VDH_NUM) \
dat = readl(((volatile int*)((char*)g_HwMem[VdhId].pVdmRegVirAddr + reg))); \
else \
dprint(PRN_ALWS,"%s: RD_VREG but VdhId : %d is more than MAX_VDH_NUM : %d\n", __func__, VdhId, MAX_VDH_NUM); \
} while(0)
#define WR_VREG( reg, dat, VdhId ) \
do { \
if (VdhId < MAX_VDH_NUM) \
writel((dat), ((volatile int*)((char*)g_HwMem[VdhId].pVdmRegVirAddr + reg))); \
else \
dprint(PRN_ALWS,"%s: WR_VREG but VdhId : %d is more than MAX_VDH_NUM : %d\n", __func__, VdhId, MAX_VDH_NUM); \
} while(0)
#else // xy test
#define RD_VREG( reg, dat, VdhId ) \
do { \
if (VdhId < MAX_VDH_NUM) { \
printk(KERN_INFO "%s: RD_VREG \n", __func__ ); \
dat = *((volatile int*)((char*)g_HwMem[VdhId].pVdmRegVirAddr + reg)); \
} \
else \
printk(KERN_INFO "%s: RD_VREG but VdhId : %d is more than MAX_VDH_NUM : %d\n", __func__, VdhId, MAX_VDH_NUM); \
} while(0)
#define WR_VREG( reg, dat, VdhId ) \
do { \
if (VdhId < MAX_VDH_NUM) \
(*(volatile int*)((char*)g_HwMem[VdhId].pVdmRegVirAddr + reg)) = dat; \
else \
printk(KERN_INFO "%s: WR_VREG but VdhId : %d is more than MAX_VDH_NUM : %d\n", __func__, VdhId, MAX_VDH_NUM); \
} while(0)
#endif
#if 0
/* message pool read/write */
#define RD_MSGWORD( vir_addr, dat ) \
do { \
dat = *((volatile int*)(vir_addr)); \
} while(0)
#define WR_MSGWORD( vir_addr, dat ) \
do { \
*((volatile int*)((char*)(vir_addr))) = dat; \
} while(0)
/* condition check */
#define VDMHAL_ASSERT_RET( cond, else_print ) \
do { \
if (!(cond)) { \
printk(KERN_ERR "%s %d: %s\n", __func__, __LINE__, else_print ); \
return VDMHAL_ERR; \
} \
} while(0)
#endif
#endif
+31
View File
@@ -0,0 +1,31 @@
#ifndef _VDM_HAL_API_HEADER_
#define _VDM_HAL_API_HEADER_
#include "mem_manage.h"
#include "vfmw.h"
#include "vdm_hal_local.h"
#include "vfmw_intf.h"
void VDMHAL_IMP_ResetVdm(int VdhId);
void VDMHAL_IMP_GlbReset(void);
void VDMHAL_IMP_ClearIntState(int VdhId);
int VDMHAL_IMP_CheckReg(REG_ID_E reg_id, int VdhId);
void VDMHAL_IMP_StartHwRepair(int VdhId);
void VDMHAL_IMP_StartHwDecode(int VdhId);
int VDMHAL_IMP_PrepareDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
int VDMHAL_IMP_PrepareRepair(OMXVDH_REG_CFG_S *pVdhRegCfg);
int VDMHAL_IMP_BackupInfo(void);
void VDMHAL_IMP_GetCharacter(void);
void VDMHAL_IMP_WriteScdEMARID(void);
void VDMHAL_IMP_Init(void);
void VDMHAL_IMP_DeInit(void);
void VDMHAL_ISR(int VdhId);
int VDMHAL_HwDecProc(OMXVDH_REG_CFG_S *pVdhRegCfg);
void VDMHAL_GetRegState(VDMHAL_BACKUP_S *pVdmRegState);
int VDMHAL_IsVdmRun(int VdhId);
int VDMHAL_PrepareSleep(void);
void VDMHAL_ForceSleep(void);
void VDMHAL_ExitSleep(void);
VDMDRV_SLEEP_STAGE_E VDMHAL_GetSleepStage(void);
void VDMHAL_SetSleepStage(VDMDRV_SLEEP_STAGE_E sleepState);
#endif
+107
View File
@@ -0,0 +1,107 @@
/*
* vdec hal for h264
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "vfmw.h"
#include "mem_manage.h"
//#include "public.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_h264.h"
#include <linux/printk.h>
int H264HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
unsigned int D32;
D32 = 0;
((BASIC_CFG0 *)(&D32))->mbamt_to_dec = ((BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->mbamt_to_dec;
((BASIC_CFG0 *)(&D32))->load_qmatrix_flag = 1;
((BASIC_CFG0 *)(&D32))->marker_bit_detect_en = 0;
((BASIC_CFG0 *)(&D32))->ac_last_detect_en = 0;
((BASIC_CFG0 *)(&D32))->coef_idx_detect_en = 1;
((BASIC_CFG0 *)(&D32))->vop_type_detect_en = 0;
((BASIC_CFG0 *)(&D32))->sec_mode_en = 0;
WR_VREG(VREG_BASIC_CFG0, D32, 0);
D32 = 0;
((BASIC_CFG1 *)(&D32))->video_standard = 0x0;
//((BASIC_CFG1 *)(&D32))->ddr_stride = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->ddr_stride;
((BASIC_CFG1 *)(&D32))->fst_slc_grp = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->fst_slc_grp;
((BASIC_CFG1 *)(&D32))->mv_output_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->mv_output_en;
((BASIC_CFG1 *)(&D32))->uv_order_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->uv_order_en;
((BASIC_CFG1 *)(&D32))->vdh_2d_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->vdh_2d_en;
((BASIC_CFG1 *)(&D32))->max_slcgrp_num = 2;
((BASIC_CFG1 *)(&D32))->compress_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->compress_en;
((BASIC_CFG1 *)(&D32))->ppfd_en = 0;
((BASIC_CFG1 *)(&D32))->line_num_output_en = 0;
WR_VREG(VREG_BASIC_CFG1, D32, 0);
D32 = 0;
((AVM_ADDR *)(&D32))->av_msg_addr = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0;
WR_VREG(VREG_AVM_ADDR, D32, 0);
D32 = 0;
((VAM_ADDR *)(&D32))->va_msg_addr = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0;
WR_VREG(VREG_VAM_ADDR, D32, 0);
D32 = 0;
((STREAM_BASE_ADDR *)(&D32))->stream_base_addr = (pVdhRegCfg->VdhStreamBaseAddr) & 0xFFFFFFF0;
WR_VREG(VREG_STREAM_BASE_ADDR, D32, 0);
D32 = RD_SCDREG(REG_EMAR_ID);
if (pVdhRegCfg->VdhEmarId == 0) {
D32 = D32 & (~(0x100));
} else {
D32 = D32 | 0x100;
}
WR_SCDREG(REG_EMAR_ID, D32);
D32 = 0x00300C03;
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
D32 = 0;
((YSTADDR_1D *)(&D32))->ystaddr_1d = (pVdhRegCfg->VdhYstAddr) & 0xFFFFFFF0;
WR_VREG(VREG_YSTADDR_1D, D32, 0);
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
D32 = 0;
WR_VREG(VREG_HEAD_INF_OFFSET, D32, 0);
WR_VREG(VREG_REF_PIC_TYPE, pVdhRegCfg->VdhRefPicType, 0);
if (pVdhRegCfg->VdhFfAptEn == 0x2) {
D32 = 0x2;
} else {
D32 = 0x0;
}
WR_VREG(VREG_FF_APT_EN, D32, 0);
//UVSTRIDE_1D
WR_VREG( VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0 );
//CFGINFO_ADDR
WR_VREG(VREG_CFGINFO_ADDR, pVdhRegCfg->VdhCfgInfoAddr, 0);
//DDR_INTERLEAVE_MODE
D32 = 0x03;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
return VDMHAL_OK;
}
@@ -0,0 +1,8 @@
#ifndef __VDM_HAL_H264_H__
#define __VDM_HAL_H264_H__
#include "mem_manage.h"
//#include "memory.h"
#include "vfmw_intf.h"
int H264HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif
+119
View File
@@ -0,0 +1,119 @@
/*
* vdec hal for hevc
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "vfmw.h"
#include "mem_manage.h"
//#include "public.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_hevc.h"
#include <linux/printk.h>
static int HEVCHAL_CfgVdmReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
unsigned int D32;
//BASIC_CFG0
D32 = 0;
((HEVC_BASIC_CFG0 *)(&D32))->marker_bit_detect_en = 0;
((HEVC_BASIC_CFG0 *)(&D32))->ac_last_detect_en = 0;
((HEVC_BASIC_CFG0 *)(&D32))->coef_idx_detect_en = 1; //(run_cnt>64) check enable switch
((HEVC_BASIC_CFG0 *)(&D32))->vop_type_detect_en = 0;
((HEVC_BASIC_CFG0 *)(&D32))->load_qmatrix_flag = ((HEVC_BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->load_qmatrix_flag;
((HEVC_BASIC_CFG0 *)(&D32))->luma_sum_en = 0; //enable switch:conculate luma pixel
((HEVC_BASIC_CFG0 *)(&D32))->luma_histogram_en = 0; //enable switch:conculate luma histogram
((HEVC_BASIC_CFG0 *)(&D32))->mbamt_to_dec = ((HEVC_BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->mbamt_to_dec;
((HEVC_BASIC_CFG0*)(&D32))->vdh_safe_flag = 0;
WR_VREG( VREG_BASIC_CFG0, D32, 0 );
//BASIC_CFG1
/*set uv order 0: v first; 1: u first */
D32 = 0;
((HEVC_BASIC_CFG1 *)(&D32))->video_standard = 0xD;
((HEVC_BASIC_CFG1 *)(&D32))->fst_slc_grp = ((HEVC_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->fst_slc_grp;
((HEVC_BASIC_CFG1 *)(&D32))->mv_output_en = 1;
((HEVC_BASIC_CFG1 *)(&D32))->uv_order_en = ((HEVC_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->uv_order_en;
((HEVC_BASIC_CFG1 *)(&D32))->vdh_2d_en = ((HEVC_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->vdh_2d_en;
((HEVC_BASIC_CFG1 *)(&D32))->max_slcgrp_num = 3;
((HEVC_BASIC_CFG1 *)(&D32))->line_num_output_en = 0; //enable switch:output "decodered pixel line of current frame" to DDR
((HEVC_BASIC_CFG1 *)(&D32))->frm_cmp_en = ((HEVC_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->frm_cmp_en;
((HEVC_BASIC_CFG1 *)(&D32))->ppfd_en = 0;
WR_VREG( VREG_BASIC_CFG1, D32, 0 );
//AVM_ADDR
D32 = 0;
((AVM_ADDR *)(&D32))->av_msg_addr = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0;
WR_VREG(VREG_AVM_ADDR, D32, 0);
//VAM_ADDR
D32 = 0;
((VAM_ADDR *)(&D32))->va_msg_addr = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0;
WR_VREG(VREG_VAM_ADDR, D32, 0);
//STREAM_BASE_ADDR
D32 = 0;
((STREAM_BASE_ADDR *)(&D32))->stream_base_addr = (pVdhRegCfg->VdhStreamBaseAddr) & 0xFFFFFFF0;
WR_VREG(VREG_STREAM_BASE_ADDR, D32, 0);
//TIME_OUT
D32 = 0x00300C03; //Õâ¸öÖµÅäÖà l00214825
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
WR_VREG(VREG_YSTADDR_1D, pVdhRegCfg->VdhYstAddr, 0);
//YSTRIDE_1D
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
//UVOFFSET_1D
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
//HEAD_INF_OFFSET
D32 = 0;
WR_VREG(VREG_HEAD_INF_OFFSET, D32, 0); //don't match with document l00214825
//UVSTRIDE_1D
WR_VREG( VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0 );
//CFGINFO_ADDR
WR_VREG(VREG_CFGINFO_ADDR, pVdhRegCfg->VdhCfgInfoAddr, 0);
//DDR_INTERLEAVE_MODE
D32 = 0x03;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
//FF_APT_EN
D32 = 0x2;
WR_VREG(VREG_FF_APT_EN, D32, 0);
//EMAR_ADDR
D32 = 0x101;
WR_SCDREG(REG_EMAR_ID, D32);
return VDMHAL_OK;
}
int HEVCHAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int Ret;
Ret = HEVCHAL_CfgVdmReg(pVdhRegCfg);
if (Ret != VDMHAL_OK) {
printk(KERN_ERR "HEVC register config failed\n");
return VDMHAL_ERR;
}
return VDMHAL_OK;
}
@@ -0,0 +1,9 @@
#ifndef __VDM_HAL__HEVC_H__
#define __VDM_HAL__HEVC_H__
#include "mem_manage.h"
//#include "memory.h"
#include "vfmw_intf.h"
int HEVCHAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif
+283
View File
@@ -0,0 +1,283 @@
#ifndef _VDM_HAL_LOCAL_HEADER_
#define _VDM_HAL_LOCAL_HEADER_
#include "mem_manage.h"
#include "vfmw.h"
#include "vdm_hal.h"
#define VHB_STRIDE_BYTE (0x400) // byte stride
#define HW_MEM_SIZE (640 * 1024 + 64 * 4)
#define HW_HEVC_MEM_SIZE (2 * 1024 * 1024 + 64 * 4) //(4*1024*1024 + 100*1024)
#define MSG_SLOT_NUM (MAX_SLICE_SLOT_NUM + 5 + 1)
#define UP_MSG_SLOT_INDEX (0)
#define RP_MSG_SLOT_INDEX (2)
#define DN_MSG_HEAD_SLOT_INDEX (4)
#define DN_MSG_SLOT_INDEX (5)
#define CA_HEVC_MN_ADDR_LEN (1024)
#define CA_MN_ADDR_LEN (64 * 4 * 20)
#define SED_TOP_ADDR_LEN (352 * 96) //(64*4*96)
#define PMV_TOP_ADDR_LEN (352 * 128) //(64*4*96)
#define RCN_TOP_ADDR_LEN (352 * 128) //(64*4*96)
#define ITRANS_TOP_ADDR_LEN (352 * 128) //(128*128)
#define DBLK_TOP_ADDR_LEN (352 * 192) //(128*512)
#define PPFD_BUF_LEN_DEFAULT (64 * 4 * 400) //(64*4*800)
#define INTENSITY_CONV_TAB_ADDR_LEN (256 * 2 * 2 * 3)
#define VP8_TAB_ADDR_LEN (32 * 1024)
#define VP6_TAB_ADDR_LEN (4 * 1024)
#define MAX_REF_FRAME_NUM (16)
/*********************************************************
for hevc
**********************************************************/
#ifdef VFMW_HEVC_SUPPORT
/*** UHD decode memory define ***/
#define CFG_HEVC_PROFILE_LEVEL_5
#define CFG_HEVC_MAX_PIX_HEIGHT (2304)
#if defined (CFG_HEVC_PROFILE_LEVEL_5)
#define HEVC_PROFILE_LEVEL_5
#else
#define HEVC_PROFILE_LEVEL_6
#endif
#if defined (HEVC_PROFILE_LEVEL_5)
#define HEVC_MAX_SLICE_NUM (200)
#else
#define HEVC_MAX_SLICE_NUM (600)
#endif
#if !defined (CFG_HEVC_MAX_PIX_WIDTH)
#define HEVC_MAX_PIX_WIDTH (4096)
#else
#define HEVC_MAX_PIX_WIDTH (CFG_HEVC_MAX_PIX_WIDTH)
#endif
// 3798MV100 logic support tile num is 20x22
#if !defined (CFG_HEVC_MAX_PIX_HEIGHT)
#define HEVC_MAX_PIX_HEIGHT (4096)
#else
#define HEVC_MAX_PIX_HEIGHT (CFG_HEVC_MAX_PIX_HEIGHT)
#endif
#define HEVC_SED_TOP_ADDR_LEN (64*4*HEVC_MAX_PIX_WIDTH)
#define HEVC_PMV_TOP_ADDR_LEN (64*4*HEVC_MAX_PIX_WIDTH)
#define HEVC_PMV_LEFT_ADDR_LEN (64*4*HEVC_MAX_PIX_HEIGHT)
#define HEVC_RCN_TOP_ADDR_LEN (64*4*HEVC_MAX_PIX_WIDTH)
#define HEVC_TILE_SEGMENT_INFO_LEN (2048) //(512*2+20*4+22*4=1192, 1024????) z00290437 20141024
#define HEVC_SAO_LEFT_ADDR_LEN (64*4*HEVC_MAX_PIX_HEIGHT)
#define HEVC_DBLK_LEFT_ADDR_LEN (64*4*HEVC_MAX_PIX_HEIGHT)
#define HEVC_SAO_TOP_ADDR_LEN (64*4*HEVC_MAX_PIX_WIDTH)
#define HEVC_DBLK_TOP_ADDR_LEN (64*4*HEVC_MAX_PIX_WIDTH)
/*********************** MSG SLOT PARA DEFINE *********************/
#define HEVC_MAX_SLOT_NUM (HEVC_MAX_SLICE_NUM+5) //z00290437 20141025
#ifdef VFMW_VP9_SUPPORT
#define VP9_MAX_PIC_WIDTH 8192
#define VP9_MAX_PIC_HEIGHT 8192
//============================== VP9 =============================
#define VP9_SED_TOP_ADDR_LEN (64*4*VP9_MAX_PIC_WIDTH)
#define VP9_PMV_TOP_ADDR_LEN (64*4*VP9_MAX_PIC_WIDTH)
#define VP9_RCN_TOP_ADDR_LEN (64*4*VP9_MAX_PIC_WIDTH)
#define VP9_DBLK_TOP_ADDR_LEN (64*4*VP9_MAX_PIC_WIDTH)
#define VP9_DBLK_LEFT_ADDR_LEN (VP9_MAX_PIC_HEIGHT * 8)
#ifndef VP9_NEW_PROB
#define VP9_PROB_TAB_ADDR_LEN (20 * 64 * 4)//(18 * 64 * 4)
#define VP9_PROB_CNT_ADDR_LEN (VP9_MAX_PIC_WIDTH * 4) /* 3301 is enought */
#else
#define VP9_PROB_TAB_ADDR_LEN (20*64*4)
#define VP9_PROB_CNT_ADDR_LEN (20*64*4)
#endif // modified by j00367396@20160923
#endif
#endif
//control registers
#define VREG_VDH_START 0x000
#define VREG_BASIC_CFG0 0x008
#define VREG_BASIC_CFG1 0x00c
#define VREG_AVM_ADDR 0x010
#define VREG_VAM_ADDR 0x014
#define VREG_STREAM_BASE_ADDR 0x018
//state registers
#define VREG_VDH_STATE 0x01c
#define VREG_VCTRL_STATE 0x028
//0x0001FF00: all RAM OnChip
//0x0002FF00: all RAM OnChip, except DBLK RAM
#define VREG_SED_TO 0x03c
#define VREG_ITRANS_TO 0x040
#define VREG_PMV_TO 0x044
#define VREG_PRC_TO 0x048
#define VREG_RCN_TO 0x04c
#define VREG_DBLK_TO 0x050
#define VREG_PPFD_TO 0x054
#define VREG_PART_DEC_OVER_INT_LEVEL 0x05c
//1d registers
#define VREG_YSTADDR_1D 0x060
#define VREG_YSTRIDE_1D 0x064
#define VREG_UVOFFSET_1D 0x068
//prc registers
#define VREG_HEAD_INF_OFFSET 0x06c
//ppfd registers
#define VREG_PPFD_BUF_ADDR 0x080
#define VREG_PPFD_BUF_LEN 0x084
#define VREG_REF_PIC_TYPE 0x094
#define VREG_FF_APT_EN 0x098
//mask & clear
#define VREG_SAFE_INT_STATE 0x0a8
#define VREG_SAFE_INT_MASK 0x0aC
#define VREG_NORM_INT_STATE 0x020
#define VREG_NORM_INT_MASK 0x024
#define VREG_INT_STATE VREG_NORM_INT_STATE
#define VREG_INT_MASK VREG_NORM_INT_MASK
#define VREG_UVSTRIDE_1D 0x0c4
#define VREG_CFGINFO_ADDR 0x0C8
#define VREG_DDR_INTERLEAVE_MODE 0x0F4
//clock div offset
#define PERI_CRG_CORE_DIV 0xCC
#define PERI_CRG_AXI_DIV 0xD0
//performance count registers
#define VREG_DEC_CYCLEPERPIC 0x0B0
#define VREG_RD_BDWIDTH_PERPIC 0x0B4
#define VREG_WR_BDWIDTH_PERPIC 0x0B8
#define VREG_RD_REQ_PERPIC 0x0BC
#define VREG_WR_REQ_PERPIC 0x0C0
#define VREG_MB0_QP_IN_CURR_PIC 0x0D0
#define VREG_SWITCH_ROUNDING 0x0D4
//sed registers
#define VREG_SED_STA 0x1000
#define VREG_SED_END0 0x1014
#define VREG_LUMA_HISTORGRAM 0x8100
#define VREG_LUMA_SUM_LOW 0x8180
#define VREG_LUMA_SUM_HIGH 0x8184
typedef struct {
unsigned int mbamt_to_dec :20;
unsigned int memory_clock_gating_en :1;
unsigned int module_clock_gating_en :1;
unsigned int marker_bit_detect_en :1;
unsigned int ac_last_detect_en :1;
unsigned int coef_idx_detect_en :1;
unsigned int vop_type_detect_en :1;
unsigned int reserved :2;
unsigned int luma_sum_en :1;
unsigned int luma_historgam_en :1;
unsigned int load_qmatrix_flag :1;
unsigned int sec_mode_en :1;
} BASIC_CFG0;
typedef struct {
unsigned int mbamt_to_dec :20;
unsigned int memory_clock_gating_en :1;
unsigned int module_clock_gating_en :1;
unsigned int marker_bit_detect_en :1;
unsigned int ac_last_detect_en :1;
unsigned int coef_idx_detect_en :1;
unsigned int vop_type_detect_en :1;
unsigned int work_mode :2;
unsigned int luma_sum_en :1;
unsigned int luma_histogram_en :1;
unsigned int load_qmatrix_flag :1;
unsigned int vdh_safe_flag :1;
} HEVC_BASIC_CFG0;
typedef struct {
unsigned int video_standard :4;
unsigned int reserved: 9;
unsigned int uv_order_en :1;
unsigned int fst_slc_grp :1;
unsigned int mv_output_en :1;
unsigned int max_slcgrp_num :12;
unsigned int line_num_output_en :1;
unsigned int vdh_2d_en :1;
unsigned int compress_en :1;
unsigned int ppfd_en :1;
} BASIC_CFG1;
typedef struct {
unsigned int video_standard :4;
unsigned int reserved :9;
unsigned int uv_order_en :1;
unsigned int fst_slc_grp :1;
unsigned int mv_output_en :1;
unsigned int max_slcgrp_num :12;
unsigned int line_num_output_en :1;
unsigned int vdh_2d_en :1;
unsigned int frm_cmp_en :1;
unsigned int ppfd_en :1;
} HEVC_BASIC_CFG1;
typedef struct {
unsigned int video_standard: 4;
unsigned int reserved: 9;
unsigned int uv_order_en: 1; //l00214825 0624
unsigned int fst_slc_grp: 1;
unsigned int mv_output_en: 1;
unsigned int max_slcgrp_num: 12;
unsigned int line_num_output_en: 1;
unsigned int vdh_2d_en: 1;
unsigned int frm_cmp_en: 1;
unsigned int ppfd_en: 1;
} VP9_BASIC_CFG1;
typedef struct {
unsigned int av_msg_addr :32;
} AVM_ADDR;
typedef struct {
unsigned int va_msg_addr :32;
} VAM_ADDR;
typedef struct {
unsigned int stream_base_addr :32;
} STREAM_BASE_ADDR;
typedef struct {
unsigned int ystaddr_1d :32;
} YSTADDR_1D;
typedef struct {
unsigned int ff_apt_en :1;
unsigned int reserved :31;
} FF_APT_EN;
typedef struct {
unsigned int ref_pic_type_0 :2;
unsigned int ref_pic_type_1 :2;
unsigned int ref_pic_type_2 :2;
unsigned int ref_pic_type_3 :2;
unsigned int ref_pic_type_4 :2;
unsigned int ref_pic_type_5 :2;
unsigned int ref_pic_type_6 :2;
unsigned int ref_pic_type_7 :2;
unsigned int ref_pic_type_8 :2;
unsigned int ref_pic_type_9 :2;
unsigned int ref_pic_type_10 :2;
unsigned int ref_pic_type_11 :2;
unsigned int ref_pic_type_12 :2;
unsigned int ref_pic_type_13 :2;
unsigned int ref_pic_type_14 :2;
unsigned int ref_pic_type_15 :2;
} REF_PIC_TYPE;
typedef struct {
unsigned int ppfd_buf_addr :32;
} PPFD_BUF_ADDR;
typedef struct {
unsigned int ppfd_buf_len :16;
unsigned int reserved :16;
} PPFD_BUF_LEN;
#endif
+105
View File
@@ -0,0 +1,105 @@
/*
* vdec hal for mp2
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#ifndef __VDM_HAL_MPEG2_C__
#define __VDM_HAL_MPEG2_C__
#include "public.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_mpeg2.h"
#include <linux/printk.h>
static int MP2HAL_CfgReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int D32;
D32 = 0;
((BASIC_CFG0 *)(&D32))->mbamt_to_dec = ((BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->mbamt_to_dec;
((BASIC_CFG0 *)(&D32))->load_qmatrix_flag = 1;
((BASIC_CFG0 *)(&D32))->marker_bit_detect_en = 1;
((BASIC_CFG0 *)(&D32))->ac_last_detect_en = 0;
((BASIC_CFG0 *)(&D32))->coef_idx_detect_en = 1;
((BASIC_CFG0 *)(&D32))->vop_type_detect_en = 0;
((BASIC_CFG0 *)(&D32))->sec_mode_en = 0;
WR_VREG( VREG_BASIC_CFG0, D32, 0 );
D32 = 0;
((BASIC_CFG1 *)(&D32))->video_standard = 0x3;
//((BASIC_CFG1 *)(&D32))->ddr_stride = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->ddr_stride;
((BASIC_CFG1 *)(&D32))->fst_slc_grp = 1;
((BASIC_CFG1 *)(&D32))->mv_output_en = 1;
((BASIC_CFG1 *)(&D32))->uv_order_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->uv_order_en;
((BASIC_CFG1 *)(&D32))->vdh_2d_en = 1;
((BASIC_CFG1 *)(&D32))->max_slcgrp_num = 3;
((BASIC_CFG1 *)(&D32))->ppfd_en = 0;
((BASIC_CFG1 *)(&D32))->line_num_output_en = 0;
((BASIC_CFG1 *)(&D32))->compress_en = 0;
/*set uv order 0: v first; 1: u first */
WR_VREG( VREG_BASIC_CFG1, D32, 0 );
D32 = 0;
((AVM_ADDR *)(&D32))->av_msg_addr = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0;
WR_VREG(VREG_AVM_ADDR, D32, 0);
D32 = 0;
((VAM_ADDR *)(&D32))->va_msg_addr = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0;
WR_VREG(VREG_VAM_ADDR, D32, 0);
WR_VREG(VREG_STREAM_BASE_ADDR, pVdhRegCfg->VdhStreamBaseAddr, 0);
//EMAR_ADDR
D32 = 0x101;
WR_SCDREG(REG_EMAR_ID, D32);
//TIME_OUT
D32 = 0x00300C03;
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
D32 = 0;
((YSTADDR_1D *)(&D32))->ystaddr_1d = (pVdhRegCfg->VdhYstAddr) & 0xFFFFFFF0;
WR_VREG(VREG_YSTADDR_1D, D32, 0);
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
D32 = 0;
((REF_PIC_TYPE *)(&D32))->ref_pic_type_0 = ((REF_PIC_TYPE *)(&pVdhRegCfg->VdhRefPicType))->ref_pic_type_0;
((REF_PIC_TYPE *)(&D32))->ref_pic_type_1 = ((REF_PIC_TYPE *)(&pVdhRegCfg->VdhRefPicType))->ref_pic_type_1;
WR_VREG( VREG_REF_PIC_TYPE, D32, 0 );
D32 = 0;
((FF_APT_EN *)(&D32))->ff_apt_en = 0;//USE_FF_APT_EN;
WR_VREG( VREG_FF_APT_EN, D32, 0 );
//VREG_UVSTRIDE_1D
WR_VREG( VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0 );
//DDR_INTERLEAVE_MODE
D32 = 0x03;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
return VDMHAL_OK;
}
int MP2HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
if (MP2HAL_CfgReg(pVdhRegCfg) != VDMHAL_OK) {
printk(KERN_ERR "MP2 register config failed\n");
return VDMHAL_ERR;
}
return VDMHAL_OK;
}
#endif
@@ -0,0 +1,8 @@
#ifndef __VDM_HAL_MPEG2_H__
#define __VDM_HAL_MPEG2_H__
//#include "memory.h"
#include "vfmw_intf.h"
int MP2HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif
+110
View File
@@ -0,0 +1,110 @@
/*
* vdec hal for mp4
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "vfmw.h"
#include "mem_manage.h"
//#include "public.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_mpeg4.h"
#include <linux/printk.h>
static int MP4HAL_CfgReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
unsigned int D32;
int SlotWidth;
//BASIC_CFG0
D32 = 0;
D32 = (pVdhRegCfg->VdhBasicCfg0 & 0x000FFFFF) // [15:0] mbamt_to_dec
| ( 1 << 22 )
| ( 0 << 23 )
| ( 0 << 24 )
| ( 1 << 25 )
| ( 1 << 30 ) // ld_qmatrix_flag
| ( 0 << 31 ); // Normal Mode
WR_VREG( VREG_BASIC_CFG0, D32, 0);
/*set uv order 0: v first; 1: u first */
D32 = 0x2 // [3:0] video_standard
| (((pVdhRegCfg->VdhBasicCfg1 >> 13) & 0x1) << 13 ) // uv_order_en
| ( 1 << 14 ) // [14] fst_slc_grp
| ( 1 << 15 ) // [15] mv_output_en
| ( 1 << 16 ) // [27:16] max_slcgrp_num
| ( 0 << 28 ) // line_num_output_en
| ( 1 << 29 ) // vdh_2d_en //l00214825 0710
| ( 0 << 30 ) //compress_en
| ( 0 << 31 ); // [31] ppfd_en 0==not ppfd dec
WR_VREG(VREG_BASIC_CFG1, D32, 0);
D32 = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0; // mpeg4 down msg
WR_VREG(VREG_AVM_ADDR, D32, 0);
D32 = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0; // mpeg4 up msg
WR_VREG(VREG_VAM_ADDR, D32, 0);
WR_VREG(VREG_STREAM_BASE_ADDR, pVdhRegCfg->VdhStreamBaseAddr, 0);
//EMAR_ADDR
D32 = 0x101;
SlotWidth = pVdhRegCfg->VdhYstride / 8;
if (SlotWidth > 1920)
{
D32 = D32 & (~(0x100));
}
else
{
D32 = D32 | (0x100);
}
WR_SCDREG(REG_EMAR_ID, D32);
D32 = 0x00300C03;
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
D32 = (pVdhRegCfg->VdhYstAddr) & 0xFFFFFFF0;
WR_VREG(VREG_YSTADDR_1D, D32, 0);
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
D32 = 0;
WR_VREG(VREG_FF_APT_EN, D32, 0);
WR_VREG( VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0 );
D32 = 0x03;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
return VDMHAL_OK;
}
int MP4HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int ret;
ret = MP4HAL_CfgReg(pVdhRegCfg);
if (ret != VDMHAL_OK) {
printk(KERN_ERR "MP4 register config failed\n");
return VDMHAL_ERR;
}
return VDMHAL_OK;
}
@@ -0,0 +1,9 @@
#ifndef _VDM_HAL_MPEG4_HEADER_
#define _VDM_HAL_MPEG4_HEADER_
#include "mem_manage.h"
//#include "memory.h"
#include "vfmw_intf.h"
int MP4HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif
+100
View File
@@ -0,0 +1,100 @@
/*
* vdec hal for vp8
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#ifndef __VDM_HAL_VP8_C__
#define __VDM_HAL_VP8_C__
//#include "public.h"
#include "vdm_hal.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_vp8.h"
#include <linux/printk.h>
static int VP8HAL_CfgReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
unsigned int D32;
//BASIC_CFG0
D32 = 0;
((BASIC_CFG0 *)(&D32))->mbamt_to_dec = ((BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->mbamt_to_dec;
((BASIC_CFG0 *)(&D32))->load_qmatrix_flag = 0;
((BASIC_CFG0 *)(&D32))->sec_mode_en = 0;
WR_VREG( VREG_BASIC_CFG0, D32, 0);
//BASIC_CFG1
/*set uv order 0: v first; 1: u first */
D32 = 0x20000000;
((BASIC_CFG1 *)(&D32))->video_standard = 0x0C;
//((BASIC_CFG1 *)(&D32))->ddr_stride = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->ddr_stride;
((BASIC_CFG1 *)(&D32))->fst_slc_grp = 1;
((BASIC_CFG1 *)(&D32))->mv_output_en = 1;
((BASIC_CFG1 *)(&D32))->uv_order_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->uv_order_en;
((BASIC_CFG1 *)(&D32))->vdh_2d_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->vdh_2d_en;
((BASIC_CFG1 *)(&D32))->max_slcgrp_num = 0;
((BASIC_CFG1 *)(&D32))->compress_en = ((BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->compress_en;
((BASIC_CFG1 *)(&D32))->ppfd_en = 0;
WR_VREG( VREG_BASIC_CFG1, D32, 0);
//AVM_ADDR
D32 = 0;
((AVM_ADDR *)(&D32))->av_msg_addr = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0;
WR_VREG(VREG_AVM_ADDR, D32, 0);
//VAM_ADDR
D32 = 0;
((VAM_ADDR *)(&D32))->va_msg_addr = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0;
WR_VREG(VREG_VAM_ADDR, D32, 0);
//STREAM_BASE_ADDR
WR_VREG(VREG_STREAM_BASE_ADDR, pVdhRegCfg->VdhStreamBaseAddr, 0);
//EMAR_ADDR
D32 = 0x101;
WR_SCDREG(REG_EMAR_ID, D32);
//YSTADDR_1D
D32 = 0;
((YSTADDR_1D *)(&D32))->ystaddr_1d = (pVdhRegCfg->VdhYstAddr) & 0xFFFFFFF0; //caution
WR_VREG(VREG_YSTADDR_1D, D32, 0);
//YSTRIDE_1D
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
//UVOFFSET_1D
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
D32 = 0;
WR_VREG(VREG_HEAD_INF_OFFSET, D32, 0);
WR_VREG( VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0 );
WR_VREG(VREG_CFGINFO_ADDR, pVdhRegCfg->VdhCfgInfoAddr, 0);
D32 = 0x03;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
return VDMHAL_OK;
}
int VP8HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int Ret;
Ret = VP8HAL_CfgReg(pVdhRegCfg);
if (Ret != VDMHAL_OK) {
printk(KERN_ERR "VP8 register config failed\n");
return VDMHAL_ERR;
}
return VDMHAL_OK;
}
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef __VDM_HAL_VP8_HERAER__
#define __VDM_HAL_VP8_HERAER__
//#include "memory.h"
#include "vfmw_intf.h"
int VP8HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif
+140
View File
@@ -0,0 +1,140 @@
/*-----------------------------------------------------------------------*/
/*!!Warning: Huawei key information asset. No spread without permission. */
/*CODEMARK:EG4uRhTwMmgcVFBsBnYHCDadN5jJKSuVyxmmaCmKFU6eJEbB2fyHF9weu4/jer/hxLHb+S1e
E0zVg4C3NiZh4Rryzsvo1gOdvy7M+qFCBFQKTTAFAVC3Q4e533WXdeQrddo4r2cqTmRg3Xeb
SI3trXaSV012ETxvJrJ/pkfs27/lT6wemL9iW3PaGW8//pmW7hQ7qCDBgWp7sMvcMuyYAWRh
jMb6+4xlgVl55z+iUl5XDCi0pMRG2hXB2hXZd5i/HJastZrWJFR4dVOatPlImg==#*/
/*--!!Warning: Deleting or modifying the preceding information is prohibited.--*/
/******************************************************************************
(C), 2001-2015,
******************************************************************************
: vdm_hal_vp9.c
: 稿
: z00290437
: 2015-02-03
:
: VDMV300
:
1. :
2. :
3.:
******************************************************************************/
#ifndef __VDM_HAL_VP9_C__
#define __VDM_HAL_VP9_C__
//#include "public.h"
#include "vdm_hal.h"
#include "vdm_hal_api.h"
#include "vdm_hal_local.h"
#include "vdm_hal_vp9.h"
#include <linux/printk.h>
static int VP9HAL_CfgReg(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
unsigned int D32;
//BASIC_CFG0
D32 = 0;
((BASIC_CFG0*)(&D32))->mbamt_to_dec = ((BASIC_CFG0 *)(&pVdhRegCfg->VdhBasicCfg0))->mbamt_to_dec;
((BASIC_CFG0*)(&D32))->load_qmatrix_flag = 0;
//((BASIC_CFG0*)(&D32))->repair_en = 0;
WR_VREG(VREG_BASIC_CFG0, D32, 0);
//BASIC_CFG1
D32 = 0;
((VP9_BASIC_CFG1*)(&D32))->video_standard = 0x0E; //VFMW_VP9;
// ((VP9_BASIC_CFG1*)(&D32))->ddr_stride = pVp9DecParam->ddr_stride >> 6;
((VP9_BASIC_CFG1*)(&D32))->uv_order_en = ((VP9_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->uv_order_en;
((VP9_BASIC_CFG1*)(&D32))->fst_slc_grp = 1;
((VP9_BASIC_CFG1*)(&D32))->mv_output_en = 1;
((VP9_BASIC_CFG1*)(&D32))->max_slcgrp_num = 3;
((VP9_BASIC_CFG1*)(&D32))->line_num_output_en = 0;
// ((BASIC_CFG1*)(&D32))->compress_en = pVp9DecParam->Compress_en;
((VP9_BASIC_CFG1*)(&D32))->vdh_2d_en = ((VP9_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->vdh_2d_en; ////1; by j00367396
((VP9_BASIC_CFG1*)(&D32))->frm_cmp_en = ((VP9_BASIC_CFG1 *)(&pVdhRegCfg->VdhBasicCfg1))->frm_cmp_en; //for tmp linear
((VP9_BASIC_CFG1*)(&D32))->ppfd_en = 0;
WR_VREG(VREG_BASIC_CFG1, D32, 0);
//AVM_ADDR
D32 = 0;
((AVM_ADDR*)(&D32))->av_msg_addr = (pVdhRegCfg->VdhAvmAddr) & 0xFFFFFFF0;
WR_VREG(VREG_AVM_ADDR, D32, 0);
//VAM_ADDR
D32 = 0;
((VAM_ADDR*)(&D32))->va_msg_addr = (pVdhRegCfg->VdhVamAddr) & 0xFFFFFFF0;
WR_VREG(VREG_VAM_ADDR, D32, 0);
//STREAM_BASE_ADDR
WR_VREG(VREG_STREAM_BASE_ADDR, pVdhRegCfg->VdhStreamBaseAddr, 0);
//PRC_CACHE_TYPE
D32 = 0x0;
WR_VREG(VREG_FF_APT_EN, D32, 0);
//EMAR_ADDR
D32 = 0x101;
WR_SCDREG(REG_EMAR_ID, D32);
//TIME_OUT
D32 = 0x00300C03;
WR_VREG(VREG_SED_TO, D32, 0);
WR_VREG(VREG_ITRANS_TO, D32, 0);
WR_VREG(VREG_PMV_TO, D32, 0);
WR_VREG(VREG_PRC_TO, D32, 0);
WR_VREG(VREG_RCN_TO, D32, 0);
WR_VREG(VREG_DBLK_TO, D32, 0);
WR_VREG(VREG_PPFD_TO, D32, 0);
//DEC_OVER_INT_LEVEL
D32 = 60;
WR_VREG(VREG_PART_DEC_OVER_INT_LEVEL, D32, 0);
//YSTADDR_1D
D32 = 0;
((YSTADDR_1D *)(&D32))->ystaddr_1d = (pVdhRegCfg->VdhYstAddr) & 0xFFFFFFF0;
WR_VREG(VREG_YSTADDR_1D, D32, 0);
//YSTRIDE_1D
WR_VREG(VREG_YSTRIDE_1D, pVdhRegCfg->VdhYstride, 0);
//UVOFFSET_1D
WR_VREG(VREG_UVOFFSET_1D, pVdhRegCfg->VdhUvoffset, 0);
//UVSTRIDE_1D
WR_VREG(VREG_UVSTRIDE_1D, pVdhRegCfg->VdhUvstride, 0);
//CFGINFO_ADDR
WR_VREG(VREG_CFGINFO_ADDR, pVdhRegCfg->VdhCfgInfoAddr, 0);
//DDR_INTERLEAVE_MODE
D32 = 0x3;
WR_VREG(VREG_DDR_INTERLEAVE_MODE, D32, 0);
return VDMHAL_OK;
}
int VP9HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg)
{
int Ret;
Ret = VP9HAL_CfgReg(pVdhRegCfg);
if (Ret != VDMHAL_OK) {
printk(KERN_ERR "VP9 register config failed\n");
return VDMHAL_ERR;
}
return VDMHAL_OK;
}
#endif
+9
View File
@@ -0,0 +1,9 @@
#ifndef __VDM_HAL_VP9_H__
#define __VDM_HAL_VP9_H__
//#include "memory.h"
#include "vfmw_intf.h"
int VP9HAL_StartDec(OMXVDH_REG_CFG_S *pVdhRegCfg);
#endif //__VDM_HAL_AVS_H__
+408
View File
@@ -0,0 +1,408 @@
/*
* osal
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
//#include "public.h"
#include "linux_kernel_osal.h"
#ifdef ENV_ARMLINUX_KERNEL
/* SpinLock */
OSAL_IRQ_SPIN_LOCK g_SpinLock_SCD;
OSAL_IRQ_SPIN_LOCK g_SpinLock_VDH;
OSAL_IRQ_SPIN_LOCK g_SpinLock_Record;
/* Mutext */
OSAL_TASK_MUTEX g_IntEvent;
OSAL_TASK_MUTEX g_ScdHwDoneEvent;
OSAL_TASK_MUTEX g_VdmHwDoneEvent;
/* Semaphore */
OSAL_SEMA g_SCDSem;
OSAL_SEMA g_VDHSem;
OSAL_SEMA g_BPDSem;
/* Extern */
extern Vfmw_Osal_Func_Ptr g_vfmw_osal_fun_ptr;
#define OSAL_Print printk
#define MAX_WAIT_EVENT_CNT 100
#define TIME_PERIOD(begin, end) ((end >= begin) ? (end - begin) : (0xffffffff - begin + end))
unsigned int OSAL_GetTimeInMs(void)
{
unsigned long long SysTime;
SysTime = sched_clock();
do_div(SysTime, 1000000);
return (unsigned int) SysTime;
}
unsigned int OSAL_GetTimeInUs(void)
{
unsigned long long SysTime;
SysTime = sched_clock();
do_div(SysTime, 1000);
return (unsigned int) SysTime;
}
static inline int OSAL_InitEvent(OSAL_EVENT *pEvent, int InitVal)
{
pEvent->flag = InitVal;
init_waitqueue_head(&(pEvent->queue_head));
return OSAL_OK;
}
static inline int OSAL_GiveEvent(OSAL_EVENT *pEvent)
{
pEvent->flag = 1;
wake_up_interruptible(&(pEvent->queue_head));
return OSAL_OK;
}
static inline int OSAL_WaitEvent(OSAL_EVENT *pEvent, int msWaitTime)
{
int ret;
unsigned int cnt = 0;
unsigned int start_time, cur_time;
start_time = VFMW_OSAL_GetTimeInMs();
do {
ret = wait_event_interruptible_timeout((pEvent->queue_head), (pEvent->flag != 0), (msecs_to_jiffies(msWaitTime)));/*lint !e666*/
if (ret < 0) {
cur_time = VFMW_OSAL_GetTimeInMs();
if (TIME_PERIOD(start_time, cur_time) > (unsigned int)msWaitTime) {
printk(KERN_CRIT "wait event time out, time : %d, cnt: %d\n", TIME_PERIOD(start_time, cur_time), cnt);
ret = 0;
break;
}
}
cnt++;
} while ((pEvent->flag == 0) && (ret < 0));
if (cnt > MAX_WAIT_EVENT_CNT) {
printk(KERN_CRIT "the max cnt of wait_event interrupts by singal is %d\n", cnt);
}
if (ret == 0) {
printk(KERN_CRIT "wait pEvent signal timeout\n");
}
pEvent->flag = 0; //(pEvent->flag>0)? (pEvent->flag-1): 0;
return (ret != 0) ? OSAL_OK : OSAL_ERR;
}
unsigned char *OSAL_RegisterMap(unsigned int PhyAddr, unsigned int Size)
{
return (unsigned char *) ioremap_nocache(PhyAddr, Size);
}
void OSAL_RegisterUnMap(unsigned char *VirAddr, unsigned int Size)
{
iounmap(VirAddr);
return;
}
int OSAL_FileWrite(char *buf, int len, struct file *filp)
{
int writelen;
mm_segment_t oldfs;
if (filp == NULL)
return -ENOENT;
if (filp->f_op->write == NULL)
return -ENOSYS;
if (((filp->f_flags & O_ACCMODE) & (O_WRONLY | O_RDWR)) == 0)
return -EACCES;
oldfs = get_fs();
set_fs(KERNEL_DS);/*lint !e501*/
writelen = filp->f_op->write(filp, buf, len, &filp->f_pos);
set_fs(oldfs);
return writelen;
}
static inline void OSAL_SEMA_INTIT(OSAL_SEMA *pSem)
{
sema_init(pSem, 1);
}
static inline int OSAL_DOWN_INTERRUPTIBLE(OSAL_SEMA *pSem)
{
return down_interruptible(pSem);
}
static inline void OSAL_UP(OSAL_SEMA *pSem)
{
up(pSem);
}
static inline void OSAL_SpinLockIRQInit(OSAL_IRQ_SPIN_LOCK *pIntrMutex)
{
spin_lock_init(&pIntrMutex->irq_lock);
pIntrMutex->isInit = 1;
}
static inline int OSAL_SpinLockIRQ(OSAL_IRQ_SPIN_LOCK *pIntrMutex)
{
if (pIntrMutex->isInit == 0) {
spin_lock_init(&pIntrMutex->irq_lock);
pIntrMutex->isInit = 1;
}
spin_lock_irqsave(&pIntrMutex->irq_lock, pIntrMutex->irq_lockflags);
return OSAL_OK;
}
static inline int OSAL_SpinUnLockIRQ(OSAL_IRQ_SPIN_LOCK *pIntrMutex)
{
spin_unlock_irqrestore(&pIntrMutex->irq_lock, pIntrMutex->irq_lockflags);
return OSAL_OK;
}
void OSAL_Mb(void)
{
mb();
}
void OSAL_uDelay(unsigned long usecs)
{
udelay(usecs);
}
void OSAL_mSleep(unsigned int msecs)
{
msleep(msecs);
}
int OSAL_RequestIrq(unsigned int irq, OSAL_IRQ_HANDLER_t handler, unsigned long flags, const char *name, void *dev)
{
return request_irq(irq, (irq_handler_t) handler, flags, name, dev);
}
void OSAL_FreeIrq(unsigned int irq, void *dev)
{
free_irq(irq, dev);
}
void *OSAL_AllocVirMem(int Size)
{
return vmalloc(Size);
}
void OSAL_FreeVirMem(void *p)
{
if (p)
vfree(p);
}
OSAL_IRQ_SPIN_LOCK *GetSpinLockByEnum(SpinLockType LockType)
{
OSAL_IRQ_SPIN_LOCK *pSpinLock = NULL;
switch (LockType) {
case G_SPINLOCK_SCD:
pSpinLock = &g_SpinLock_SCD;
break;
case G_SPINLOCK_RECORD:
pSpinLock = &g_SpinLock_Record;
break;
case G_SPINLOCK_VDH:
pSpinLock = &g_SpinLock_VDH;
break;
default:
printk(KERN_ERR "%s unkown SpinLockType %d\n", __func__, LockType);
break;
}
return pSpinLock;
}
void OSAL_SpinLockInit(SpinLockType LockType)
{
OSAL_IRQ_SPIN_LOCK *pSpinLock = NULL;
pSpinLock = GetSpinLockByEnum(LockType);
OSAL_SpinLockIRQInit(pSpinLock);
}
int OSAL_SpinLock(SpinLockType LockType)
{
OSAL_IRQ_SPIN_LOCK *pSpinLock = NULL;
pSpinLock = GetSpinLockByEnum(LockType);
return OSAL_SpinLockIRQ(pSpinLock);
}
int OSAL_SpinUnLock(SpinLockType LockType)
{
OSAL_IRQ_SPIN_LOCK *pSpinLock = NULL;
pSpinLock = GetSpinLockByEnum(LockType);
return OSAL_SpinUnLockIRQ(pSpinLock);
}
OSAL_SEMA *GetSemByEnum(SemType Sem)
{
OSAL_SEMA *pSem = NULL;
switch (Sem) {
case G_SCD_SEM:
pSem = &g_SCDSem;
break;
case G_VDH_SEM:
pSem = &g_VDHSem;
break;
case G_BPD_SEM:
pSem = &g_BPDSem;
break;
default:
printk(KERN_ERR "%s unkown SemType %d\n", __func__, Sem);
break;
}
return pSem;
}
void OSAL_SemInit(SemType Sem)
{
OSAL_SEMA *pSem = NULL;
pSem = GetSemByEnum(Sem);
OSAL_SEMA_INTIT(pSem);
}
int OSAL_SemDown(SemType Sem)
{
OSAL_SEMA *pSem = NULL;
pSem = GetSemByEnum(Sem);
return OSAL_DOWN_INTERRUPTIBLE(pSem);
}
void OSAL_SemUp(SemType Sem)
{
OSAL_SEMA *pSem = NULL;
pSem = GetSemByEnum(Sem);
OSAL_UP(pSem);
}
int OSAL_InitWaitQue(MutexType mutextType, int initVal)
{
int retVal = OSAL_ERR;
switch (mutextType) {
case G_SCDHWDONEEVENT:
retVal = OSAL_InitEvent(&g_ScdHwDoneEvent, initVal);
break;
case G_VDMHWDONEEVENT:
retVal = OSAL_InitEvent(&g_VdmHwDoneEvent, initVal);
break;
default:
break;
}
return retVal;
}
int OSAL_WakeupWaitQue(MutexType mutexType)
{
int retVal = OSAL_ERR;
switch (mutexType) {
case G_SCDHWDONEEVENT:
retVal = OSAL_GiveEvent(&g_ScdHwDoneEvent);
break;
case G_VDMHWDONEEVENT:
retVal = OSAL_GiveEvent(&g_VdmHwDoneEvent);
break;
default:
break;
}
return retVal;
}
int OSAL_WaitWaitQue(MutexType mutexType, int waitTimeInMs)
{
int retVal = OSAL_ERR;
switch (mutexType) {
case G_SCDHWDONEEVENT:
retVal = OSAL_WaitEvent(&g_ScdHwDoneEvent, waitTimeInMs);
break;
case G_VDMHWDONEEVENT:
retVal = OSAL_WaitEvent(&g_VdmHwDoneEvent, waitTimeInMs);
break;
default:
break;
}
return retVal;
}
void OSAL_InitInterface(void)
{
memset(&g_vfmw_osal_fun_ptr, 0, sizeof(g_vfmw_osal_fun_ptr));
g_vfmw_osal_fun_ptr.pfun_Osal_GetTimeInMs = OSAL_GetTimeInMs;
g_vfmw_osal_fun_ptr.pfun_Osal_GetTimeInUs = OSAL_GetTimeInUs;
g_vfmw_osal_fun_ptr.pfun_Osal_SpinLockInit = OSAL_SpinLockInit;
g_vfmw_osal_fun_ptr.pfun_Osal_SpinLock = OSAL_SpinLock;
g_vfmw_osal_fun_ptr.pfun_Osal_SpinUnLock = OSAL_SpinUnLock;
g_vfmw_osal_fun_ptr.pfun_Osal_SemaInit = OSAL_SemInit;
g_vfmw_osal_fun_ptr.pfun_Osal_SemaDown = OSAL_SemDown;
g_vfmw_osal_fun_ptr.pfun_Osal_SemaUp = OSAL_SemUp;
g_vfmw_osal_fun_ptr.pfun_Osal_Print = OSAL_Print;
g_vfmw_osal_fun_ptr.pfun_Osal_mSleep = OSAL_mSleep;
g_vfmw_osal_fun_ptr.pfun_Osal_Mb = OSAL_Mb;
g_vfmw_osal_fun_ptr.pfun_Osal_uDelay = OSAL_uDelay;
g_vfmw_osal_fun_ptr.pfun_Osal_InitEvent = OSAL_InitWaitQue;
g_vfmw_osal_fun_ptr.pfun_Osal_GiveEvent = OSAL_WakeupWaitQue;
g_vfmw_osal_fun_ptr.pfun_Osal_WaitEvent = OSAL_WaitWaitQue;
g_vfmw_osal_fun_ptr.pfun_Osal_RequestIrq = OSAL_RequestIrq;
g_vfmw_osal_fun_ptr.pfun_Osal_FreeIrq = OSAL_FreeIrq;
g_vfmw_osal_fun_ptr.pfun_Osal_RegisterMap = OSAL_RegisterMap;
g_vfmw_osal_fun_ptr.pfun_Osal_RegisterUnMap = OSAL_RegisterUnMap;
g_vfmw_osal_fun_ptr.pfun_Osal_AllocVirMem = OSAL_AllocVirMem;
g_vfmw_osal_fun_ptr.pfun_Osal_FreeVirMem = OSAL_FreeVirMem;
}
#endif
+84
View File
@@ -0,0 +1,84 @@
#ifndef __VFMW_LINUX_KERNEL_OSAL_HEADER__
#define __VFMW_LINUX_KERNEL_OSAL_HEADER__
#include <asm/cacheflush.h>
#include <linux/kthread.h>
#include <linux/hrtimer.h>
#include <linux/module.h>
#include <linux/moduleparam.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/stat.h>
#include <linux/wait.h>
#include <linux/syscalls.h>
#include <linux/sched.h>
#include <linux/proc_fs.h>
#include <linux/fs.h>
#include <linux/vmalloc.h>
#include <linux/mm.h>
#include <linux/poll.h>
#include <linux/types.h>
#include <linux/errno.h>
#include <linux/fcntl.h>
#include <linux/miscdevice.h>
#include <linux/proc_fs.h>
#include <linux/slab.h>
#include <linux/interrupt.h>
#include <linux/ioport.h>
#include <linux/string.h>
#include <linux/delay.h>
#include <linux/version.h>
#include <asm/uaccess.h>
#include <asm/io.h>
#include <asm/ioctl.h>
#include <linux/semaphore.h>
#include "vfmw_osal_ext.h"
/*======================================================================*/
/* struct define */
/*======================================================================*/
typedef struct hiKERN_EVENT_S {
wait_queue_head_t queue_head;
int flag;
} OSAL_EVENT;
typedef struct hiKERN_IRQ_LOCK_S {
spinlock_t irq_lock;
unsigned long irq_lockflags;
int isInit;
} OSAL_IRQ_SPIN_LOCK;
/*======================================================================*/
/* define */
/*======================================================================*/
typedef struct task_struct* OSAL_TASK;
typedef struct file OSAL_FILE;
typedef struct semaphore OSAL_SEMA;
typedef OSAL_EVENT OSAL_TASK_MUTEX;
/*======================================================================*/
/* function declare */
/*======================================================================*/
/************************************************************************/
/* time: get in ms/us */
/************************************************************************/
unsigned int OSAL_GetTimeInMs(void);
unsigned int OSAL_GetTimeInUs(void);
/************************************************************************/
/* file: open/close/read/write */
/************************************************************************/
int OSAL_FileWrite(char *buf, int len, struct file *filp);
/************************************************************************/
/* linux kernel osal function pointer initialize */
/************************************************************************/
void OSAL_InitInterface(void);
#endif
+180
View File
@@ -0,0 +1,180 @@
/*
* vdec mem_manager
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include "mem_manage.h"
#include "sysconfig.h"
#include "vfmw_osal_ext.h"
//#include "public.h"
#include "linux_kernel_osal.h"
#define MAX_MEM_MAN_RECORD_NUM (MAX_CHAN_NUM*32)
MEM_RECORD_S s_MemRecord[MAX_MEM_MAN_RECORD_NUM];
void MEM_InitMemManager(void)
{
VFMW_OSAL_SpinLock(G_SPINLOCK_RECORD);
memset(s_MemRecord, 0, sizeof(s_MemRecord));
VFMW_OSAL_SpinUnLock(G_SPINLOCK_RECORD);
}
int MEM_AddMemRecord(unsigned int PhyAddr, void *VirAddr, unsigned int Length)
{
int i;
char IsErrorFlag = 0;
int TargetPos = -1;
int ret = MEM_MAN_ERR;
VFMW_OSAL_SpinLock(G_SPINLOCK_RECORD);
for (i = 0; i < MAX_MEM_MAN_RECORD_NUM; i++) {
if ((s_MemRecord[i].PhyAddr <= PhyAddr) && (PhyAddr < s_MemRecord[i].PhyAddr + s_MemRecord[i].Length)) {
IsErrorFlag = 1;
break;
}
if (s_MemRecord[i].Length == 0 && TargetPos == -1)
TargetPos = i;
}
if (IsErrorFlag == 1) {
printk(KERN_CRIT "%s conflict occured\n ", __func__);
ret = MEM_MAN_ERR;
} else if (TargetPos == -1) {
printk(KERN_CRIT "%s no free record slot\n ", __func__);
ret = MEM_MAN_ERR;
} else {
s_MemRecord[TargetPos].PhyAddr = PhyAddr;
s_MemRecord[TargetPos].VirAddr = VirAddr;
s_MemRecord[TargetPos].Length = Length;
ret = MEM_MAN_OK;
}
VFMW_OSAL_SpinUnLock(G_SPINLOCK_RECORD);
return ret;
}
int MEM_DelMemRecord(unsigned int PhyAddr, void *VirAddr, unsigned int Length)
{
int i;
VFMW_OSAL_SpinLock(G_SPINLOCK_RECORD);
for (i = 0; i < MAX_MEM_MAN_RECORD_NUM; i++) {
if (s_MemRecord[i].Length == 0)
continue;
if (PhyAddr == s_MemRecord[i].PhyAddr && VirAddr == s_MemRecord[i].VirAddr &&
Length == s_MemRecord[i].Length) {
s_MemRecord[i].Length = 0;
s_MemRecord[i].PhyAddr = 0;
s_MemRecord[i].VirAddr = 0;
VFMW_OSAL_SpinUnLock(G_SPINLOCK_RECORD);
return MEM_MAN_OK;
}
}
VFMW_OSAL_SpinUnLock(G_SPINLOCK_RECORD);
return MEM_MAN_ERR;
}
void *MEM_Phy2Vir(unsigned int PhyAddr)
{
unsigned int i;
unsigned char *VirAddr = NULL;
for (i = 0; i < MAX_MEM_MAN_RECORD_NUM; i++) {
if (s_MemRecord[i].Length == 0)
continue;
if ((PhyAddr >= s_MemRecord[i].PhyAddr) && (PhyAddr < s_MemRecord[i].PhyAddr + s_MemRecord[i].Length)) {
VirAddr = s_MemRecord[i].VirAddr + (PhyAddr - s_MemRecord[i].PhyAddr);
break;
}
}
return (void *) VirAddr;
}
unsigned int MEM_Vir2Phy(unsigned char *VirAddr)
{
unsigned int i;
unsigned int PhyAddr = 0;
for (i = 0; i < MAX_MEM_MAN_RECORD_NUM; i++) {
if (s_MemRecord[i].Length == 0)
continue;
if ((VirAddr >= s_MemRecord[i].VirAddr) && (VirAddr < s_MemRecord[i].VirAddr + s_MemRecord[i].Length)) {
PhyAddr = s_MemRecord[i].PhyAddr + (VirAddr - s_MemRecord[i].VirAddr);
break;
}
}
return PhyAddr;
}
void MEM_WritePhyWord(unsigned int PhyAddr, unsigned int Data32)
{
unsigned int *pDst;
pDst = (unsigned int *) MEM_Phy2Vir(PhyAddr);
if (pDst != NULL)
writel(Data32, pDst);
}
unsigned int MEM_ReadPhyWord(unsigned int PhyAddr)
{
unsigned int *pDst;
unsigned int Data32;
Data32 = 0;
pDst = (unsigned int *) MEM_Phy2Vir(PhyAddr);
if (pDst != NULL) {
Data32 = readl((volatile unsigned int *)pDst);
}
return Data32;
}
int MEM_MapRegisterAddr(unsigned int RegStartPhyAddr, unsigned int RegByteLen, MEM_RECORD_S *pMemRecord)
{
unsigned char *ptr;
if (pMemRecord == NULL || RegStartPhyAddr == 0 || RegByteLen == 0 || VFMW_OSAL_RegisterMap == NULL)
return MEM_MAN_ERR;
memset(pMemRecord, 0, sizeof(*pMemRecord));
ptr = VFMW_OSAL_RegisterMap(RegStartPhyAddr, RegByteLen);
if (ptr != NULL) {
pMemRecord->PhyAddr = RegStartPhyAddr;
pMemRecord->VirAddr = ptr;
pMemRecord->Length = RegByteLen;
return MEM_MAN_OK;
}
return MEM_MAN_ERR;
}
void MEM_UnmapRegisterAddr(unsigned int PhyAddr, unsigned char *VirAddr, unsigned int Size)
{
if (PhyAddr == 0 || VirAddr == 0 || VFMW_OSAL_RegisterUnMap == NULL)
return;
VFMW_OSAL_RegisterUnMap(VirAddr, Size);
return;
}
+34
View File
@@ -0,0 +1,34 @@
#ifndef _VFMW_MEM_MANAGE_HEAD_
#define _VFMW_MEM_MANAGE_HEAD_
#include "vfmw.h"
#define MEM_MAN_ERR -1
#define MEM_MAN_OK 0
typedef struct {
unsigned int PhyAddr;
unsigned int Length;
int IsSecMem;
unsigned char *VirAddr;
} MEM_RECORD_S;
void MEM_InitMemManager(void);
int MEM_AddMemRecord(unsigned int PhyAddr, void *VirAddr, unsigned int Length);
int MEM_DelMemRecord(unsigned int PhyAddr, void *VirAddr, unsigned int Length);
void *MEM_Phy2Vir(unsigned int PhyAddr);
unsigned int MEM_Vir2Phy(unsigned char *VirAddr);
void MEM_WritePhyWord(unsigned int PhyAddr, unsigned int Data32);
unsigned int MEM_ReadPhyWord(unsigned int PhyAddr);
int MEM_MapRegisterAddr(unsigned int RegStartPhyAddr, unsigned int RegByteLen, MEM_RECORD_S *pMemRecord);
void MEM_UnmapRegisterAddr(unsigned int PhyAddr, unsigned char *VirAddr, unsigned int Size);
#endif
+55
View File
@@ -0,0 +1,55 @@
#ifndef __PUBLIC_H__
#define __PUBLIC_H__
#include "vfmw.h"
/* 0X0 : ALWYS, 0X1: ALWYS and FATAL, 0X3: ALWYS and FATAL and ERROR */
#define DEFAULT_PRINT_ENABLE (0x3)
typedef enum {
DEV_SCREEN = 1,
DEV_SYSLOG,
DEV_FILE,
DEV_MEM
} PRINT_DEVICE_TYPE;
#if 0
#define dprint_vfmw_nothing(type, fmt, arg...) ({do{}while(0);0;})
#define dprint_sos_kernel(type, fmt, arg...) \
do{ \
if ((PRN_ALWS == type) || (0 != (DEFAULT_PRINT_ENABLE & (1LL << type)))) \
{ \
printk(KERN_ALERT "VDEC S: "fmt, ##arg); \
} \
}while(0)
#define dprint_linux_kernel(type, fmt, arg...) \
do{ \
if ((PRN_ALWS == type) || (0 != (DEFAULT_PRINT_ENABLE & (1LL << type)))) \
{ \
printk(KERN_ALERT "VDEC : "fmt, ##arg); \
} \
}while(0)
#ifdef HI_ADVCA_FUNCTION_RELEASE
#define dprint(type, fmt, arg...) dprint_vfmw_nothing(type, fmt, ##arg)
#else
#ifdef ENV_ARMLINUX_KERNEL
#define dprint(type, fmt, arg...) dprint_linux_kernel(type, fmt, ##arg)
#else
#define dprint(type, fmt, arg...) dprint_vfmw_nothing(type, fmt, ##arg)
#endif
#endif
#else
#ifdef HI_ADVCA_FUNCTION_RELEASE
#define dprint(type, fmt, arg...)
#else
//#define dprint(type, fmt, arg...) printk(type fmt, ##arg)
#define dprint(type, fmt, arg...)
#endif
#endif
#endif
+261
View File
@@ -0,0 +1,261 @@
/*
* vdec driver for scd master
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
//#include "public.h"
#include "scd_drv.h"
#include "vfmw_intf.h"
#include "linux_kernel_osal.h"
#include "./format/vdm_hal_api.h"
#ifdef HIVDEC_SMMU_SUPPORT
#include "smmu.h"
#endif
static SCDDRV_SLEEP_STAGE_E s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_NONE;
static SCD_STATE_REG_S gScdStateReg;
static SCD_STATE_E s_SCDState = SCD_IDLE;
static void PrintScdVtrlReg(void);
int SCDDRV_ResetSCD(void)
{
unsigned int tmp;
unsigned int i;
unsigned int reg_rst_ok;
unsigned int reg;
unsigned int *pScdResetReg = NULL;
unsigned int *pScdResetOkReg = NULL;
pScdResetReg = (unsigned int *) MEM_Phy2Vir(gSOFTRST_REQ_Addr);
pScdResetOkReg = (unsigned int *) MEM_Phy2Vir(gSOFTRST_OK_ADDR);
if (pScdResetReg == NULL || pScdResetOkReg == NULL) {
printk(KERN_CRIT "scd reset register map fail\n");
return VF_ERR_SYS;
}
tmp = RD_SCDREG(REG_SCD_INT_MASK);
reg = *(volatile unsigned int *)pScdResetReg;
*(volatile unsigned int *)pScdResetReg = reg | (unsigned int) (1 << SCD_RESET_CTRL_BIT);
for (i = 0; i < 100; i++) {
reg_rst_ok = *(volatile unsigned int *)pScdResetOkReg;
if (reg_rst_ok & (1 << SCD_RESET_OK_BIT))
break;
VFMW_OSAL_uDelay(10);
}
if (i >= 100)
printk(KERN_CRIT "%s reset failed\n", __func__);
else
printk(KERN_INFO "%s reset success\n", __func__);
*(volatile unsigned int *)pScdResetReg = reg & (unsigned int) (~(1 << SCD_RESET_CTRL_BIT));
WR_SCDREG(REG_SCD_INT_MASK, tmp);
s_SCDState = SCD_IDLE;
return FMW_OK;
}
int SCDDRV_PrepareSleep(void)
{
int ret = SCDDRV_OK;
VFMW_OSAL_SemaDown(G_SCD_SEM);
if (s_eScdDrvSleepStage == SCDDRV_SLEEP_STAGE_NONE) {
if (SCD_IDLE == s_SCDState) {
printk(KERN_INFO "%s, idle state \n", __func__);
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_SLEEP;
} else {
printk(KERN_INFO "%s, decoded state \n", __func__);
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_PREPARE;
}
ret = SCDDRV_OK;
} else {
ret = SCDDRV_ERR;
}
VFMW_OSAL_SemaUp(G_SCD_SEM);
return ret;
}
SCDDRV_SLEEP_STAGE_E SCDDRV_GetSleepStage(void)
{
return s_eScdDrvSleepStage;
}
void SCDDRV_SetSleepStage(SCDDRV_SLEEP_STAGE_E sleepState)
{
VFMW_OSAL_SemaDown(G_SCD_SEM);
s_eScdDrvSleepStage = sleepState;
VFMW_OSAL_SemaUp(G_SCD_SEM);
}
void SCDDRV_ForceSleep(void)
{
printk(KERN_INFO "%s, force state \n", __func__);
VFMW_OSAL_SemaDown(G_SCD_SEM);
if (s_eScdDrvSleepStage != SCDDRV_SLEEP_STAGE_SLEEP) {
SCDDRV_ResetSCD();
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_SLEEP;
}
VFMW_OSAL_SemaUp(G_SCD_SEM);
}
void SCDDRV_ExitSleep(void)
{
VFMW_OSAL_SemaDown(G_SCD_SEM);
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_NONE;
VFMW_OSAL_SemaUp(G_SCD_SEM);
}
int SCDDRV_WriteReg(SCD_CONFIG_REG_S *pSmCtrlReg )
{
if (s_SCDState != SCD_IDLE)
return SCDDRV_ERR;
s_SCDState = SCD_WORKING;
WR_SCDREG(REG_SCD_INI_CLR, 1);
// LIST_ADDRESS
WR_SCDREG(REG_LIST_ADDRESS, (unsigned int)pSmCtrlReg->DownMsgPhyAddr);
// UP_ADDRESS
WR_SCDREG(REG_UP_ADDRESS, (unsigned int) pSmCtrlReg->UpMsgPhyAddr);
// UP_LEN
WR_SCDREG(REG_UP_LEN, (unsigned int) pSmCtrlReg->UpLen);
// BUFFER_FIRST
WR_SCDREG(REG_BUFFER_FIRST, (unsigned int) pSmCtrlReg->BufferFirst);
// BUFFER_LAST
WR_SCDREG(REG_BUFFER_LAST, (unsigned int) pSmCtrlReg->BufferLast);
// BUFFER_INI
WR_SCDREG(REG_BUFFER_INI, (unsigned int) pSmCtrlReg->BufferIni);
// SCD_PROTOCOL
WR_SCDREG(REG_SCD_PROTOCOL, (unsigned int) ((pSmCtrlReg->ScdLowdlyEnable << 8)
| ((pSmCtrlReg->SliceCheckFlag << 4) & 0x10)
| (pSmCtrlReg->ScdProtocol & 0x0f)));
#ifdef HIVDEC_SMMU_SUPPORT
SMMU_SetMasterReg(SCD, SECURE_OFF, SMMU_ON);
#endif
#ifndef SCD_BUSY_WAITTING
WR_SCDREG(REG_SCD_INT_MASK, 0);
#endif
PrintScdVtrlReg();
// SCD_START
WR_SCDREG(REG_SCD_START, 0);
WR_SCDREG(REG_SCD_START, (unsigned int) (pSmCtrlReg->ScdStart & 0x01));
return SCDDRV_OK;
}
void SCDDRV_SaveStateReg(void)
{
gScdStateReg.ScdProtocol = RD_SCDREG(REG_SCD_PROTOCOL);
gScdStateReg.Scdover = RD_SCDREG(REG_SCD_OVER);
gScdStateReg.ScdInt = RD_SCDREG(REG_SCD_INT);
gScdStateReg.ScdNum = RD_SCDREG(REG_SCD_NUM);
gScdStateReg.ScdRollAddr = RD_SCDREG(REG_ROLL_ADDR);
gScdStateReg.SrcEaten = RD_SCDREG(REG_SRC_EATEN);
gScdStateReg.UpLen = RD_SCDREG(REG_UP_LEN);
}
void SCDDRV_init(void)
{
memset(&gScdStateReg, 0, sizeof(gScdStateReg));
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_NONE;
s_SCDState = SCD_IDLE;
}
void SCDDRV_DeInit(void)
{
s_eScdDrvSleepStage = SCDDRV_SLEEP_STAGE_NONE;
s_SCDState = SCD_IDLE;
}
void SCDDRV_ISR(void)
{
int dat = 0;
dat = RD_SCDREG(REG_SCD_OVER) & 0x01;
if ((dat & 1) == 0) {
printk(KERN_CRIT "End0: SM_SCDIntServeProc()\n");
return;
}
SCDDRV_SaveStateReg();
WR_SCDREG(REG_SCD_INI_CLR, 1);
VFMW_OSAL_GiveEvent(G_SCDHWDONEEVENT);
}
void SCDDRV_GetRegState(SCD_STATE_REG_S *pScdStateReg)
{
memcpy(pScdStateReg, &gScdStateReg, sizeof(*pScdStateReg));
s_SCDState = SCD_IDLE;
}
int WaitSCDFinish(void)
{
int i;
if (SCD_WORKING == s_SCDState) {
for (i = 0; i < SCD_TIME_OUT_COUNT; i++) {
if ((RD_SCDREG(REG_SCD_OVER) & 1))
return SCDDRV_OK;
}
return SCDDRV_ERR;
} else {
return SCDDRV_OK;
}
}
static void PrintScdVtrlReg(void)
{
SCD_CONFIG_REG_S SmCtrlReg;
memset(&SmCtrlReg, 0, sizeof(SmCtrlReg));
SmCtrlReg.DownMsgPhyAddr = RD_SCDREG(REG_LIST_ADDRESS);
SmCtrlReg.UpMsgPhyAddr = RD_SCDREG(REG_UP_ADDRESS);
SmCtrlReg.UpLen = RD_SCDREG(REG_UP_LEN);
SmCtrlReg.BufferFirst = RD_SCDREG(REG_BUFFER_FIRST);
SmCtrlReg.BufferLast = RD_SCDREG(REG_BUFFER_LAST);
SmCtrlReg.BufferIni = RD_SCDREG(REG_BUFFER_INI);
SmCtrlReg.ScdProtocol = RD_SCDREG(REG_SCD_PROTOCOL);
SmCtrlReg.ScdStart = RD_SCDREG(REG_SCD_START);
}
#ifdef ENV_ARMLINUX_KERNEL
int SCDDRV_IsScdIdle(void)
{
int ret = SCDDRV_OK;
if (SCD_IDLE == s_SCDState) {
ret = SCDDRV_OK;
} else if (SCD_WORKING == s_SCDState) {
ret = SCDDRV_ERR;
} else {
ret = SCDDRV_ERR;
printk(KERN_ERR "%s : s_SCDState : %d is wrong\n", __func__, s_SCDState);
}
return ret;
}
#endif
+166
View File
@@ -0,0 +1,166 @@
#ifndef __SCD_DRV_H__
#define __SCD_DRV_H__
#include "mem_manage.h"
//#include "../omxvdec/memory.h"
#include "vfmw.h"
#define SCDDRV_OK (0)
#define SCDDRV_ERR (-1)
#define SCD_TIME_OUT_COUNT (200)
#define REG_SCD_START (0x800)
#define REG_LIST_ADDRESS (0x804)
#define REG_UP_ADDRESS (0x808)
#define REG_UP_LEN (0x80c)
#define REG_BUFFER_FIRST (0x810)
#define REG_BUFFER_LAST (0x814)
#define REG_BUFFER_INI (0x818)
#define REG_SCD_PROTOCOL (0x820)
/* state registers */
#define REG_SCD_OVER (0x840)
#define REG_SCD_INT (0x844)
#define REG_SCD_NUM (0x84c)
#define REG_ROLL_ADDR (0x850)
#define REG_SRC_EATEN (0x854)
#define REG_SCD_SAFE_INT_MASK (0x884)
#define REG_SCD_SAFE_INI_CLR (0x888)
#define REG_SCD_NORM_INT_MASK (0x81c)
#define REG_SCD_NORM_INI_CLR (0x824)
#define REG_SCD_INT_MASK REG_SCD_NORM_INT_MASK
#define REG_SCD_INI_CLR REG_SCD_NORM_INI_CLR
#define REG_AVS_FLAG (0x0000)
#define REG_EMAR_ID (0x0004)
#define REG_VDH_SELRST (0x0008)
#define SM_SCD_UP_INFO_NUM (2)
#ifdef CFG_MAX_RAW_NUM
#define MAX_STREAM_RAW_NUM (CFG_MAX_RAW_NUM)
#else
#define MAX_STREAM_RAW_NUM (1024)
#endif
#ifdef CFG_MAX_SEG_NUM
#define MAX_STREAM_SEG_NUM (CFG_MAX_SEG_NUM)
#else
#define MAX_STREAM_SEG_NUM (1024 + 128)
#endif
#define SM_MAX_DOWNMSG_SIZE (3 * MAX_STREAM_RAW_NUM * sizeof(SINT32))
#define SM_MAX_UPMSG_SIZE (SM_SCD_UP_INFO_NUM * MAX_STREAM_SEG_NUM * sizeof(SINT32))
typedef enum {
FMW_OK = 0,
FMW_ERR_PARAM = -1,
FMW_ERR_NOMEM = -2,
FMW_ERR_NOTRDY = -3,
FMW_ERR_BUSY = -4,
FMW_ERR_RAWNULL = -5,
FMW_ERR_SEGFULL = -6,
FMW_ERR_SCD = -7
} FMW_RETVAL_E;
typedef enum {
SCDDRV_SLEEP_STAGE_NONE = 0,
SCDDRV_SLEEP_STAGE_PREPARE,
SCDDRV_SLEEP_STAGE_SLEEP
} SCDDRV_SLEEP_STAGE_E;
typedef enum {
SCD_IDLE = 0,
SCD_WORKING,
} SCD_STATE_E;
/* register operator */
#define RD_SCDREG(reg) MEM_ReadPhyWord((gScdRegBaseAddr + reg))
#define WR_SCDREG(reg, dat) MEM_WritePhyWord((gScdRegBaseAddr + reg),(dat))
#define FMW_ASSERT_RET( cond, ret ) \
do{ \
if (!(cond)) \
return (ret); \
} while (0)
/*######################################################
struct defs.
######################################################*/
typedef enum {
SCD_SHAREFD_MESSAGE_POOL = 0,
SCD_SHAREFD_OUTPUT_BUF = 1,
SCD_SHAREFD_MAX
}SCD_SHAREFD;
typedef struct {
int Scdover;
int ScdInt;
int ShortScdNum;
int ScdNum;
unsigned int ScdRollAddr;
int SrcEaten;
} SM_STATEREG_S;
typedef struct
{
char SliceCheckFlag;
char ScdStart;
unsigned int DownMsgPhyAddr;
unsigned int UpMsgPhyAddr;
int UpLen;
unsigned int BufferFirst;
unsigned int BufferLast;
unsigned int BufferIni;
int ScdProtocol;
int ScdLowdlyEnable;
int scd_share_fd[SCD_SHAREFD_MAX];
int IsScdAllBufRemap;
} SCD_CONFIG_REG_S;
typedef struct {
int ScdProtocol;
int Scdover;
int ScdInt;
int ScdNum;
unsigned int ScdRollAddr;
int SrcEaten;
int UpLen;
} SCD_STATE_REG_S;
typedef enum hi_CONFIG_SCD_CMD {
CONFIG_SCD_REG_CMD = 100,
} CONFIG_SCD_CMD;
typedef struct {
CONFIG_SCD_CMD cmd;
int eVidStd;
unsigned int SResetFlag;
unsigned int GlbResetFlag;
SCD_CONFIG_REG_S SmCtrlReg;
} OMXSCD_REG_CFG_S;
int SCDDRV_PrepareSleep(void);
SCDDRV_SLEEP_STAGE_E SCDDRV_GetSleepStage(void);
void SCDDRV_SetSleepStage(SCDDRV_SLEEP_STAGE_E sleepState);
void SCDDRV_ForceSleep(void);
void SCDDRV_ExitSleep(void);
int SCDDRV_ResetSCD(void);
int SCDDRV_WriteReg(SCD_CONFIG_REG_S *pSmCtrlReg );
void SCDDRV_GetRegState(SCD_STATE_REG_S *pScdStateReg);
void SCDDRV_ISR(void);
void SCDDRV_init(void);
void SCDDRV_DeInit(void);
#ifdef ENV_ARMLINUX_KERNEL
int SCDDRV_IsScdIdle(void);
#endif
#endif
+479
View File
@@ -0,0 +1,479 @@
/*
* vdec driver for smmu master
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#ifdef ENV_ARMLINUX_KERNEL
#include <asm/memory.h>
#include <linux/types.h>
#include <linux/gfp.h>
#endif
#include <linux/printk.h>
#include "smmu.h"
//#include "public.h"
#include "mem_manage.h"
#include "linux_kernel_osal.h"
#include <linux/io.h>
#include "../omxvdec/omxvdec.h"
#define SMRx_ID_SIZE 32
#define SMMU_RWERRADDR_SIZE 128
#define HIVDEC_SMMU_COMMON_OFFSET (0x20000)
#define HIVDEC_SMMU_MASTER_OFFSET (0xF000)
#define HIVDEC_SMMU_COMMON_BASE_ADDR (gVdhRegBaseAddr + HIVDEC_SMMU_COMMON_OFFSET)
#define HIVDEC_SMMU_MASTER_BASE_ADDR (gVdhRegBaseAddr + HIVDEC_SMMU_MASTER_OFFSET)
//SMMU common and Master(MFDE/SCD/BPD) virtual base address
typedef struct {
int *pSMMUCommonBaseVirAddr;
int *pSMMUMasterBaseVirAddr;
int *pSMMUMFDERegVirAddr;
int *pSMMUBPDRegVirAddr;
int *pSMMUSCDRegVirAddr;
} SMMU_REG_VIR_S;
SMMU_REG_VIR_S gSmmuRegVir;
MEM_DESC_S gAllocMem_RD;
MEM_DESC_S gAllocMem_WR;
int gSmmuInitFlag = 0;
int gMfdeSecureFlag = 0;
int gMfdeSmmuFlag = 1;
int gScdSecureFlag = 0;
int gScdSmmuFlag = 1;
int gBpdSecureFlag = 0;
int gBpdSmmuFlag = 0;
//smmu common regs r/w
#define RD_SMMU_COMMON_VREG( reg, dat ) \
do { \
(dat) = readl(((volatile int*)((char*)gSmmuRegVir.pSMMUCommonBaseVirAddr + (reg)))); \
} while(0)
#define WR_SMMU_COMMON_VREG( reg, dat ) \
do { \
writel((dat), ((volatile int*)((char*)gSmmuRegVir.pSMMUCommonBaseVirAddr + (reg)))); \
} while(0)
//smmu master regs r/w
#define RD_SMMU_MASTER_VREG( reg, dat ) \
do { \
(dat) = readl(((volatile int*)((char*)gSmmuRegVir.pSMMUMasterBaseVirAddr + (reg)))); \
} while(0)
#define WR_SMMU_MASTER_VREG( reg, dat ) \
do { \
writel((dat), ((volatile int*)((char*)gSmmuRegVir.pSMMUMasterBaseVirAddr + (reg)))); \
} while(0)
//mfde regs r/w
#define RD_SMMU_MFDE_VREG( reg, dat ) \
do { \
(dat) = readl(((volatile int*)((char*)gSmmuRegVir.pSMMUMFDERegVirAddr + (reg)))); \
} while(0)
#define WR_SMMU_MFDE_VREG( reg, dat ) \
do { \
writel((dat), ((volatile int*)((char*)gSmmuRegVir.pSMMUMFDERegVirAddr + (reg)))); \
} while(0)
//bpd regs r/w
#define RD_SMMU_BPD_VREG( reg, dat ) \
do { \
(dat) = readl(((volatile int*)((char*)gSmmuRegVir.pSMMUBPDRegVirAddr + (reg)))); \
} while(0)
#define WR_SMMU_BPD_VREG( reg, dat ) \
do { \
writel((dat), ((volatile int*)((char*)gSmmuRegVir.pSMMUBPDRegVirAddr + (reg)))); \
} while(0)
//scd regs r/w
#define RD_SMMU_SCD_VREG( reg, dat ) \
do { \
(dat) = readl(((volatile int*)((char*)gSmmuRegVir.pSMMUSCDRegVirAddr + (reg)))); \
} while(0)
#define WR_SMMU_SCD_VREG( reg, dat ) \
do { \
writel((dat), ((volatile int*)((char*)gSmmuRegVir.pSMMUSCDRegVirAddr + (reg)))); \
} while(0)
/**
*function: set SMMU common register
*addr: register's vir addr
*val: value to be set
*bw: bit width
*bs: bit start
*/
static void set_common_reg(unsigned int addr, int val, int bw, int bs)
{
int mask = (1UL << bw) - 1UL;
int tmp = 0;
RD_SMMU_COMMON_VREG(addr, tmp);
tmp &= ~(mask << bs);/*lint !e502*/
WR_SMMU_COMMON_VREG(addr, tmp | ((val & mask) << bs));
}
/**
*function: set SMMU master register
*addr: register's vir addr
*val: value to be set
*bw: bit width
*bs: bit start
*/
static void set_master_reg(unsigned int addr, int val, int bw, int bs)
{
int mask = (1UL << bw) - 1UL;
int tmp = 0;
RD_SMMU_MASTER_VREG(addr, tmp);
tmp &= ~(mask << bs);/*lint !e502*/
WR_SMMU_MASTER_VREG(addr, (tmp | ((val & mask) << bs)));
}
/**
*function: set mfde/scd/bpd register
*master_type: MFDE/SCD/BPD
*addr: register's vir addr
*val: value to be set
*bw: bit width
*bs: bit start
*/
static void set_vdh_master_reg(SMMU_MASTER_TYPE master_type, unsigned int addr, int val, int bw, int bs)
{
int mask = (1UL << bw) - 1UL;
int tmp = 0;
switch (master_type) {
case MFDE:
RD_SMMU_MFDE_VREG(addr, tmp);
tmp &= ~(mask << bs);/*lint !e502*/
WR_SMMU_MFDE_VREG(addr, tmp | ((val & mask) << bs));
break;
case BPD:
RD_SMMU_BPD_VREG(addr, tmp);
tmp &= ~(mask << bs);/*lint !e502*/
WR_SMMU_BPD_VREG(addr, tmp | ((val & mask) << bs));
break;
case SCD:
RD_SMMU_SCD_VREG(addr, tmp);
tmp &= ~(mask << bs);/*lint !e502*/
WR_SMMU_SCD_VREG(addr, tmp | ((val & mask) << bs));
break;
default:
break;
}
}
/**
*function: set mfde mmu cfg register
*/
static void set_mmu_cfg_reg_mfde(SMMU_MASTER_TYPE master_type, unsigned int secure_en, unsigned int mmu_en)
{
if (mmu_en) { //MMU enable
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_EN, 0x1, 1, 12); //[12]mmu_en=1
if (secure_en) { //secure
printk(KERN_INFO "IN %s not support this mode: mmu_en:secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_SECURE, 0x1, 1, 31); //[31]secure_en=1
} else { //non-secure
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_SECURE, 0x0, 1, 31); //[31]secure_en=0
}
} else { //MMU disable
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_EN, 0x0, 1, 12); //[12]mmu_en=0
if (secure_en) { //secure
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_SECURE, 0x1, 1, 31); //[31]secure_en=1
} else { //non-secure
printk(KERN_INFO "IN %s not support this mode: non_mmu:non_secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_MFDE_MMU_CFG_SECURE, 0x0, 1, 31); //[31]secure_en=0
}
}
}
/**
*function: set bpd mmu cfg register
*/
static void set_mmu_cfg_reg_bpd(SMMU_MASTER_TYPE master_type, unsigned int secure_en, unsigned int mmu_en)
{
if (mmu_en) { //MMU enable
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x1, 1, 21); //[21]mmu_en=1
if (secure_en) { //secure
printk(KERN_INFO "IN %s not support this mode: mmu_en:secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x1, 1, 20); //[20]secure_en=1
} else { //non-secure
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x0, 1, 20); //[20]secure_en=0
}
} else { //MMU disable
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x0, 1, 21); //[21]mmu_en=0
if (secure_en) { //secure
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x1, 1, 20); //[20]secure_en=1
} else { //non-secure
printk(KERN_INFO "IN %s not support this mode: non_mmu:non_secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_BPD_MMU_CFG, 0x0, 1, 20); //[20]secure_en=0
}
}
}
/**
*function: set scd mmu cfg register
*/
static void set_mmu_cfg_reg_scd(SMMU_MASTER_TYPE master_type, unsigned int secure_en, unsigned int mmu_en)
{
if (mmu_en) { //MMU enable
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x1, 1, 9);//[9]mmu_en=1
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x1, 1, 13);//[13]rdbuf_mmu_en=1
if (secure_en) { //secure
printk(KERN_INFO "IN %s not support this mode: mmu_en:secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x1, 1, 7); //[7]secure_en=1
} else { //non-secure
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x0, 1, 7); //[7]secure_en=0
}
} else { //MMU disable
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x0, 1, 9); //[9]mmu_en=0
if (secure_en) { //secure
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x1, 1, 7); //[7]secure_en=1
} else { //non-secure
printk(KERN_INFO "IN %s not support this mode: non_mmu:non_secure\n", __func__);
printk(KERN_INFO "%s, secure_en:%d, mmu_en:%d\n", __func__, secure_en, mmu_en);
set_vdh_master_reg(master_type, REG_SCD_MMU_CFG, 0x0, 1, 7); //[7]secure_en=0
}
}
}
static int smmu_mem_alloc(unsigned int size, MEM_DESC_S *pMemDesc)
{
void *virt_addr = NULL;
if (pMemDesc == NULL) {
printk(KERN_ERR "%s: invalid param pMemDesc is NULL\n", __func__);
return SMMU_ERR;
}
if (pMemDesc->VirAddr != 0L) {
printk(KERN_ERR "%s param StartVirAddr %pK is not NULL\n", __func__, (void*)pMemDesc->VirAddr);
return SMMU_ERR;
}
if (MEM_CMA_ZERO == pMemDesc->MemType)
virt_addr = kzalloc(size, GFP_KERNEL | GFP_DMA); //restrict [0 ~ 4G]
else
virt_addr = kmalloc(size, GFP_KERNEL | GFP_DMA); //restrict [0 ~ 4G]
if (!virt_addr) {
printk(KERN_ERR "%s Alloc virt_addr failed\n", __func__);
return SMMU_ERR;
}
pMemDesc->VirAddr = (unsigned long long)virt_addr;
pMemDesc->PhyAddr = __pa(virt_addr);/*lint !e648*/
return SMMU_OK;
}
static void smmu_mem_dealloc(MEM_DESC_S *pMemDesc)
{
if (pMemDesc == NULL) {
printk(KERN_ERR "%s : Invalid pMemDesc is NULL\n", __func__);
return;
}
if (pMemDesc->VirAddr == 0L) {
printk(KERN_ERR "%s : Invalid pMemDesc->VirAddr is NULL\n", __func__);
return;
}
kfree((void *)pMemDesc->VirAddr);
pMemDesc->VirAddr = 0L;
return;
}
/**
*function: Alloc MEM for TLB miss .
*/
#ifdef ENV_ARMLINUX_KERNEL
static int alloc_smmu_tlb_miss_addr(void)
{
int ret = SMMU_ERR;
gAllocMem_RD.MemType = MEM_CMA_ZERO;
ret = smmu_mem_alloc(SMMU_RWERRADDR_SIZE, &gAllocMem_RD);
if (ret != MEM_MAN_OK) {
printk(KERN_ERR "%s kzalloc mem for smmu rderr failed\n", __func__);
return SMMU_ERR;
}
gAllocMem_WR.MemType = MEM_CMA_ZERO;
ret = smmu_mem_alloc(SMMU_RWERRADDR_SIZE, &gAllocMem_WR);
if (ret != MEM_MAN_OK) {
printk(KERN_ERR "%s kzalloc mem for smmu wrerr failed\n", __func__);
smmu_mem_dealloc(&gAllocMem_RD);
return SMMU_ERR;
}
return SMMU_OK;
}
#endif
/**
*function: init SMMU global registers.
*/
void SMMU_InitGlobalReg(void)
{
unsigned int i = 0;
if (gSmmuInitFlag != 1) {
printk(KERN_DEBUG "%s Smmu initialization failed\n", __func__);
return;
}
//0000 0000 0000 1111 0000 0000 0011 1000 --> 0x000f0038
set_common_reg(SMMU_SCR, 0x0, 1, 0);//SMMU_SCR[0].glb_bypass
set_common_reg(SMMU_SCR, 0x3, 2, 1);//SMMU_SCR[1].rqos_en SMMU_SCR[2].wqos_en
//SMRX_S had set default value. Only need to set SMMU_SMRx_NS secure SID bypass
//SMMU_SMRx[0]smr_bypass=0(non-bypass); SMMU_SMRx[2:3]smr_ptw_qos=0x3;
for (i = 0; i < SMRx_ID_SIZE; i += 2) {
set_common_reg(SMMU_SMRx_NS + i*0x4, 0x1C, 32, 0);//0x00000003 none secure
}
for (i = 1; i < SMRx_ID_SIZE; i += 2) {
set_common_reg(SMMU_SMRx_NS + i*0x4, 0x1D, 32, 0);//0x00000002 secure
}
set_common_reg(SMMU_CB_TTBR0, gSmmuPageBase, 32, 0);
set_common_reg(SMMU_FAMA_CTRL1_NS, (gSmmuPageBase>>32)&0x7F, 32, 0);
set_common_reg(SMMU_CB_TTBCR, 0x1, 1, 0);
if (gAllocMem_RD.PhyAddr != 0 && gAllocMem_WR.PhyAddr != 0) {
set_common_reg(SMMU_ERR_RDADDR, (gAllocMem_RD.PhyAddr & 0xFFFFFFFF), 32, 0);
set_common_reg(SMMU_ADDR_MSB, (gAllocMem_RD.PhyAddr>>32)&0x7F, 7, 0);
set_common_reg(SMMU_ERR_WRADDR, (gAllocMem_WR.PhyAddr & 0xFFFFFFFF), 32, 0);
set_common_reg(SMMU_ADDR_MSB, (gAllocMem_WR.PhyAddr>>32)&0x7F, 7, 7);
}
//glb_bypass, 0x0: normal mode, 0x1: bypass mode
set_master_reg(SMMU_MSTR_GLB_BYPASS, 0x0, 32, 0); //master mmu enable
}
/**
*function: set MFDE/SCD/BPD mmu cfg register, MMU or secure.
*/
void SMMU_SetMasterReg(SMMU_MASTER_TYPE master_type, unsigned char secure_en, unsigned char mmu_en)
{
switch (master_type) {
case MFDE:
set_mmu_cfg_reg_mfde(master_type, secure_en, mmu_en);
gMfdeSecureFlag = secure_en;
gMfdeSmmuFlag = mmu_en;
break;
case SCD:
set_mmu_cfg_reg_scd(master_type, secure_en, mmu_en);
gScdSecureFlag = secure_en;
gScdSmmuFlag = mmu_en;
break;
case BPD:
set_mmu_cfg_reg_bpd(master_type, secure_en, mmu_en);
gBpdSecureFlag = secure_en;
gBpdSmmuFlag = mmu_en;
break;
default:
printk(KERN_ERR "%s unkown master type %d\n", __func__, master_type);
break;
}
}
void SMMU_IntServProc(void)
{
int tmp = -1;
RD_SMMU_COMMON_VREG(SMMU_INTSTAT_NS, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_0, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_1, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_2, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_3, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_4, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_5, tmp);
RD_SMMU_MASTER_VREG(SMMU_MSTR_DBG_6, tmp);
}
/**
*function: get registers virtual address, and alloc mem for TLB miss.
*/
int SMMU_Init(void)
{
int ret = SMMU_ERR;
memset(&gSmmuRegVir, 0, sizeof(gSmmuRegVir));
gSmmuRegVir.pSMMUMFDERegVirAddr = (int *) MEM_Phy2Vir(gVdhRegBaseAddr);
if (gSmmuRegVir.pSMMUMFDERegVirAddr == NULL) {
printk(KERN_ERR "%s pSMMUMFDERegVirAddr is NULL, SMMU Init failed\n", __func__);
return SMMU_ERR;
}
gSmmuRegVir.pSMMUSCDRegVirAddr = (int *) MEM_Phy2Vir(gScdRegBaseAddr);
if (gSmmuRegVir.pSMMUSCDRegVirAddr == NULL) {
printk(KERN_ERR "%s pSMMUSCDRegVirAddr is NULL, SMMU Init failed\n", __func__);
return SMMU_ERR;
}
gSmmuRegVir.pSMMUBPDRegVirAddr = (int *) MEM_Phy2Vir(gBpdRegBaseAddr);
if (gSmmuRegVir.pSMMUBPDRegVirAddr == NULL) {
printk(KERN_ERR "%s pSMMUBPDRegVirAddr is NULL, SMMU Init failed\n", __func__);
return SMMU_ERR;
}
gSmmuRegVir.pSMMUCommonBaseVirAddr = (int *) MEM_Phy2Vir(HIVDEC_SMMU_COMMON_BASE_ADDR);
if (gSmmuRegVir.pSMMUCommonBaseVirAddr == NULL) {
printk(KERN_ERR "%s pSMMUCommonBaseVirAddr is NULL, SMMU Init failed\n", __func__);
return SMMU_ERR;
}
gSmmuRegVir.pSMMUMasterBaseVirAddr = (int *) MEM_Phy2Vir(HIVDEC_SMMU_MASTER_BASE_ADDR);
if (gSmmuRegVir.pSMMUMasterBaseVirAddr == NULL) {
printk(KERN_ERR "%s pSMMUMasterBaseVirAddr is NULL, SMMU Init failed\n", __func__);
return SMMU_ERR;
}
memset(&gAllocMem_RD, 0, sizeof(gAllocMem_RD));
memset(&gAllocMem_WR, 0, sizeof(gAllocMem_WR));
#ifdef ENV_ARMLINUX_KERNEL
ret = alloc_smmu_tlb_miss_addr();
if (ret != SMMU_OK) {
printk(KERN_ERR "%s alloc_smmu_tlb_miss_addr failed\n", __func__);
return SMMU_ERR;
}
#endif
gSmmuInitFlag = 1;
return SMMU_OK;
}
/**
*function: free mem of SMMU_ERR_RDADDR and SMMU_ERR_WRADDR.
*/
void SMMU_DeInit(void)
{
if (gAllocMem_RD.PhyAddr != 0)
smmu_mem_dealloc(&gAllocMem_RD);
if (gAllocMem_WR.PhyAddr != 0)
smmu_mem_dealloc(&gAllocMem_WR);
}
+64
View File
@@ -0,0 +1,64 @@
#ifndef __HIVDEC_SMMU_H__
#define __HIVDEC_SMMU_H__
#include "sysconfig.h" //for VDM_REG_PHY_ADDR, SCD_REG_PHY_ADDR, BPD_REG_PHY_ADDR
#include "vfmw.h"
#define SMMU_OK 0
#define SMMU_ERR -1
#define SECURE_ON 1
#define SECURE_OFF 0
#define SMMU_ON 1
#define SMMU_OFF 0
/*******************************************************************************
**SMMU COMMON registers
*/
#define SMMU_SCR (0x0000)
//non-secure
#define SMMU_INTSTAT_NS (0x0018)
#define SMMU_SMRx_NS (0x0020) //(0x0020+n*0x4) SMMU control register per stream for non-secure
#define SMMU_CB_TTBR0 (0x0204) //SMMU translation table base register for non-secure context bank0
#define SMMU_FAMA_CTRL1_NS (0x0224)//SMMU Control Register for FAMA for TCU of Non-Secure Context Bank
#define SMMU_CB_TTBCR (0x020C) //SMMU Translation Table Base Control Register for Non-Secure Context Bank
#define SMMU_ADDR_MSB (0x0300) //Register for MSB of all 33-bits address configuration
#define SMMU_ERR_RDADDR (0x0304) //SMMU Error Address of TLB miss for Read transaction
#define SMMU_ERR_WRADDR (0x0308) //SMMU Error Address of TLB miss for Write transaction
/**********************************************
**MASTER(MFDE/SCD/BPD) registers
*/
#define REG_MFDE_MMU_CFG_SECURE (0x0008)
#define REG_MFDE_MMU_CFG_EN (0x000c)
#define REG_SCD_MMU_CFG (0x0820)
#define REG_BPD_MMU_CFG (0x0004)
/***********************************************/
/*************************************************
**SMMU MASTER registers
*/
#define SMMU_MSTR_GLB_BYPASS (0x0000)
#define SMMU_MSTR_DBG_0 (0x0010)
#define SMMU_MSTR_DBG_1 (0x0014)
#define SMMU_MSTR_DBG_2 (0x0018)
#define SMMU_MSTR_DBG_3 (0x001c)
#define SMMU_MSTR_DBG_4 (0x0020)
#define SMMU_MSTR_DBG_5 (0x0024)
#define SMMU_MSTR_DBG_6 (0x0028)
/***********************************************/
typedef enum {
MFDE = 0,
BPD,
SCD,
} SMMU_MASTER_TYPE;
int SMMU_Init(void);
void SMMU_DeInit(void);
void SMMU_SetMasterReg(SMMU_MASTER_TYPE master_type, unsigned char secure_en, unsigned char mmu_en);
void SMMU_InitGlobalReg(void);
void SMMU_IntServProc(void);
#endif
+54
View File
@@ -0,0 +1,54 @@
/*--------------------------------------------------------------------------------------------------------------------------*/
/*!!Warning: This is a key information asset of Huawei Tech Co.,Ltd */
/*CODEMARK:kOyQZYzjDpyGdBAEC2GaWinjiDDUykL9e8pckESWBbMVmSWkBuyJO01cTiy3TdzKxGk0oBQa
mSMf7J4FkTpfvzHyMxSEsfcbL/G0fFswaAZ8tsS4we+PBWC6a/UNlzCWIaw+Ujkv9NAY+as0
fg7WZIRvw27AjvRqJbkRJvqFUORSa6KPQaSBMxCxJTGTTf//sQbjPOyYldN0OVR9ut4HFO4U
ZguGQVqcOAJQbE96v6175DqhuprKgQB8R+2fu7VD3qtX+ZJh/t0512oqv+e8YA==*/
/*--------------------------------------------------------------------------------------------------------------------------*/
#ifndef __VFMW_SYSCONFIG_HEADER__
#define __VFMW_SYSCONFIG_HEADER__
#include "vfmw.h"
/* valid vdh num */
#define MAX_VDH_NUM (1)
/* register offset */
#define SCD_REG_OFFSET (0xc000)
#define BPD_REG_OFFSET (0xd000)
#define SOFTRST_REQ_OFFSET (0xcc0c)//(0xf80c)
#define SOFTRST_OK_OFFSET (0xcc10)//(0xf810)
#define ALL_RESET_CTRL_BIT (0)
#define MFDE_RESET_CTRL_BIT (1)
#define SCD_RESET_CTRL_BIT (2)
#define BPD_RESET_CTRL_BIT (3)
#define ALL_RESET_OK_BIT (0)
#define MFDE_RESET_OK_BIT (1)
#define SCD_RESET_OK_BIT (2)
#define BPD_RESET_OK_BIT (3)
/* FPGA flag */
extern unsigned int gIsFPGA;
/* register base addr & range */
extern unsigned int gVdhRegBaseAddr;
extern unsigned int gScdRegBaseAddr;
extern unsigned int gBpdRegBaseAddr;
extern unsigned int gVdhRegRange;
extern unsigned int gSOFTRST_REQ_Addr;
extern unsigned int gSOFTRST_OK_ADDR;
/* smmu page table base addr */
extern unsigned long long gSmmuPageBase;
/* peri crg base addr */
extern unsigned int gPERICRG_RegBaseAddr;
/* irq num */
extern unsigned int gVdecIrqNumNorm;
extern unsigned int gVdecIrqNumProt;
extern unsigned int gVdecIrqNumSafe;
#endif
+66
View File
@@ -0,0 +1,66 @@
#ifndef __VDEC_FIRMWARE_H__
#define __VDEC_FIRMWARE_H__
#define VFMW_VERSION_NUM (2017032400)
#define TVP_CHAN_NUM (0)
#define MAX_CHAN_NUM (32)
#define MAX_FRAME_NUM (32)
#define VDEC_OK (0)
#define VDEC_ERR (-1)
#define VF_ERR_SYS (-20)
typedef enum {
VFMW_START_RESERVED = 0,
VFMW_H264 = 0,
VFMW_VC1,
VFMW_MPEG4,
VFMW_MPEG2,
VFMW_H263,
VFMW_DIVX3,
VFMW_AVS,
VFMW_JPEG,
VFMW_REAL8 = 8,
VFMW_REAL9 = 9,
VFMW_VP6 = 10,
VFMW_VP6F,
VFMW_VP6A,
VFMW_VP8,
VFMW_VP9,
VFMW_SORENSON,
VFMW_MVC,
VFMW_HEVC,
VFMW_RAW,
VFMW_USER, /*## vfmw simply provide frame path. for external decoder, eg. mjpeg ## */
VFMW_END_RESERVED
} VID_STD_E;
/*memory type*/
typedef enum {
MEM_ION = 0, // ion default
MEM_ION_CTG, // ion contigeous
MEM_CMA, // kmalloc
MEM_CMA_ZERO, // kzalloc
} MEM_TYPE_E;
/* memroy description */
typedef struct {
unsigned char IsSecure;
MEM_TYPE_E MemType;
unsigned long long PhyAddr;
unsigned int Length;
unsigned long long VirAddr;
} MEM_DESC_S;
typedef struct {
unsigned int IsFPGA;
unsigned int VdecIrqNumNorm;
unsigned int VdecIrqNumProt;
unsigned int VdecIrqNumSafe;
unsigned int VdhRegBaseAddr;
unsigned int VdhRegRange;
unsigned long long SmmuPageBaseAddr;
unsigned int PERICRG_RegBaseAddr;
} VFMW_DTS_CONFIG_S;
#endif // __VDEC_FIRMWARE_H__
+73
View File
@@ -0,0 +1,73 @@
##############################################################
# vfmw support config #
##############################################################
################# vfmw_h264 #################################
VFMW_H264_SUPPORT = YES
#VFMW_H264_SUPPORT = NO
################# vfmw_hevc #################################
VFMW_HEVC_SUPPORT = YES
#VFMW_HEVC_SUPPORT = NO
################# vfmw_mpeg2 #################################
VFMW_MPEG2_SUPPORT = YES
#VFMW_MPEG2_SUPPORT = NO
################# vfmw_mpeg4 #################################
VFMW_MPEG4_SUPPORT = YES
#VFMW_MPEG4_SUPPORT = NO
################# vfmw_vp8 #################################
VFMW_VP8_SUPPORT = YES
#VFMW_VP8_SUPPORT = NO
################# vfmw_vp9 #################################
VFMW_VP9_SUPPORT = YES
#VFMW_VP9_SUPPORT = NO
################# vfmw_raw_num #############################
#VFMW_RAW_NUM_SUPPORT = YES
VFMW_RAW_NUM_SUPPORT = NO
VFMW_MAX_RAW_NUM = 256
################# vfmw_seg_num #############################
#VFMW_SEG_NUM_SUPPORT = YES
VFMW_SEG_NUM_SUPPORT = NO
VFMW_MAX_SEG_NUM = 256
################# vfmw_scd_msg_buffer ######################
#VFMW_SCD_MSG_SUPPORT = YES
VFMW_SCD_MSG_SUPPORT = NO
VFMW_SCD_MSG_BUF = 64*1024
################# product_recpos ###########################
#VFMW_RECPOS_SUPPORT = YES
VFMW_RECPOS_SUPPORT = NO
################# SCD_SUPPORT ##############################
VFMW_SCD_SUPPORT = YES
#VFMW_SCD_SUPPORT = NO
################# VDH_SUPPORT ##############################
VFMW_VDH_SUPPORT = YES
#VFMW_VDH_SUPPORT = NO
################# VFMW SYSTEM REG DISABLE ##################
VFMW_SYSTEM_REG_DISABLE = YES
#VFMW_SYSTEM_REG_DISABLE = NO
################# VFMW SMMU ################################
HIVDEC_SMMU_SUPPORT = YES
#HIVDEC_SMMU_SUPPORT = NO
################# VFMW TVP #################################
ifeq ($(TARGET_BOARD_PLATFORM), kirin970)
VFMW_TVP_SUPPORT = YES
#VFMW_TVP_SUPPORT = NO
endif
################# CONSTRAINT_VDH_PERFORMANCE #################################
CONSTRAINT_VDH_PERFORMANCE = NO
#CONSTRAINT_VDH_PERFORMANCE = YES
+82
View File
@@ -0,0 +1,82 @@
#include "vfmw_dts.h"
#include "sysconfig.h"
//#include "public.h"
#include "omxvdec.h"
#include <linux/printk.h>
unsigned int gIsFPGA = 0;
unsigned int gVdhRegBaseAddr = 0;
unsigned int gScdRegBaseAddr = 0;
unsigned int gBpdRegBaseAddr = 0;
unsigned int gVdhRegRange = 0;
unsigned int gSOFTRST_REQ_Addr = 0;
unsigned int gSOFTRST_OK_ADDR = 0;
unsigned long long gSmmuPageBase = 0;
unsigned int gPERICRG_RegBaseAddr = 0;
/* irq num */
unsigned int gVdecIrqNumNorm = 0;
unsigned int gVdecIrqNumProt = 0;
unsigned int gVdecIrqNumSafe = 0;
int VFMW_SetDtsConfig(VFMW_DTS_CONFIG_S *pDtsConfig)
{
if (pDtsConfig == NULL) {
printk(KERN_ERR "%s : pDtsConfig is NULL\n", __func__);
return VDEC_ERR;
}
if (pDtsConfig->VdecIrqNumNorm == 0 || pDtsConfig->VdecIrqNumProt == 0 || pDtsConfig->VdecIrqNumSafe == 0 ||
pDtsConfig->VdhRegBaseAddr == 0 || pDtsConfig->VdhRegRange == 0 || pDtsConfig->SmmuPageBaseAddr == 0 ||
pDtsConfig->PERICRG_RegBaseAddr == 0) {
printk(KERN_ERR "%s invalid param: IsFPGA : %d, VdecIrqNumNorm : %d, VdecIrqNumProt : %d, VdecIrqNumSafe : %d, VdhRegBaseAddr : %pK, VdhRegSize : %d, SmmuPageBaseAddr : %pK, PERICRG_RegBaseAddr : %pK\n", __func__,
pDtsConfig->IsFPGA, pDtsConfig->VdecIrqNumNorm, pDtsConfig->VdecIrqNumProt, pDtsConfig->VdecIrqNumSafe, (void *)(uintptr_t)(pDtsConfig->VdhRegBaseAddr), pDtsConfig->VdhRegRange, (void *)(uintptr_t)(pDtsConfig->SmmuPageBaseAddr), (void *)(uintptr_t)(pDtsConfig->PERICRG_RegBaseAddr));
return VDEC_ERR;
}
gIsFPGA = pDtsConfig->IsFPGA;
gVdecIrqNumNorm = pDtsConfig->VdecIrqNumNorm;
gVdecIrqNumProt = pDtsConfig->VdecIrqNumProt;
gVdecIrqNumSafe = pDtsConfig->VdecIrqNumSafe;
gVdhRegBaseAddr = pDtsConfig->VdhRegBaseAddr;
gVdhRegRange = pDtsConfig->VdhRegRange;
gSmmuPageBase = pDtsConfig->SmmuPageBaseAddr;
gPERICRG_RegBaseAddr = pDtsConfig->PERICRG_RegBaseAddr;
gScdRegBaseAddr = gVdhRegBaseAddr + SCD_REG_OFFSET;
gBpdRegBaseAddr = gVdhRegBaseAddr + BPD_REG_OFFSET;
gSOFTRST_REQ_Addr = gVdhRegBaseAddr + SOFTRST_REQ_OFFSET;
gSOFTRST_OK_ADDR = gVdhRegBaseAddr + SOFTRST_OK_OFFSET;
#if 0
printk(KERN_ERR "%s invalid param: IsFPGA : %d, VdecIrqNumNorm : %d, VdecIrqNumProt : %d, VdecIrqNumSafe : %d, VdhRegBaseAddr : 0x%x, VdhRegSize : %d, SmmuPageBaseAddr : 0x%x, PERICRG_RegBaseAddr : 0x%x,range = 0x%x\n", __func__,
pDtsConfig->IsFPGA, pDtsConfig->VdecIrqNumNorm, pDtsConfig->VdecIrqNumProt, pDtsConfig->VdecIrqNumSafe, (pDtsConfig->VdhRegBaseAddr), pDtsConfig->VdhRegRange, (pDtsConfig->SmmuPageBaseAddr),(uintptr_t)(pDtsConfig->PERICRG_RegBaseAddr),pDtsConfig->VdhRegRange);
#endif
return VDEC_OK;
}
int VFMW_GetDtsConfig(VFMW_DTS_CONFIG_S *pDtsConfig)
{
if (pDtsConfig == NULL) {
printk(KERN_ERR "%s FATAL: pDtsConfig is NULL\n", __func__);
return VDEC_ERR;
}
pDtsConfig->IsFPGA = gIsFPGA;
pDtsConfig->VdecIrqNumNorm = gVdecIrqNumNorm;
pDtsConfig->VdecIrqNumProt = gVdecIrqNumProt;
pDtsConfig->VdecIrqNumSafe = gVdecIrqNumSafe;
pDtsConfig->VdhRegBaseAddr = gVdhRegBaseAddr;
pDtsConfig->VdhRegRange = gVdhRegRange;
pDtsConfig->SmmuPageBaseAddr = gSmmuPageBase;
pDtsConfig->PERICRG_RegBaseAddr = gPERICRG_RegBaseAddr;
return VDEC_OK;
}
#ifdef ENV_ARMLINUX_KERNEL
EXPORT_SYMBOL(VFMW_SetDtsConfig);
#endif
+8
View File
@@ -0,0 +1,8 @@
#ifndef __VFMW_DTS_H__
#define __VFMW_DTS_H__
#include "vfmw.h"
int VFMW_SetDtsConfig(VFMW_DTS_CONFIG_S *pDtsConfig);
int VFMW_GetDtsConfig(VFMW_DTS_CONFIG_S *pDtsConfig);
#endif
+376
View File
@@ -0,0 +1,376 @@
/*
* vfmw interface
*
* Copyright (c) 2017 Hisilicon Limited
*
* Author: gaoyajun<gaoyajun@hisilicon.com>
*
* This software is licensed under the terms of the GNU General Public
* License version 2, as published by the Free Software Foundation.
*
*/
#include <linux/module.h>
#include <linux/kern_levels.h>
#include <linux/printk.h>
//#include "public.h"
#include "vfmw_intf.h"
#include "../omxvdec/omxvdec.h"
#ifdef HIVDEC_SMMU_SUPPORT
#include "smmu.h"
#endif
#include "./format/vdm_hal_api.h"
#include "vfmw_osal_ext.h"
#include "linux_kernel_osal.h"
#ifndef IRQF_DISABLED
#define IRQF_DISABLED (0x00000020)
#endif
#define VDM_TIMEOUT (400)//ms
#define VDM_FPGA_TIMEOUT (500000)//ms
#define SCD_TIMEOUT (400)//ms
#define SCD_FPGA_TIMEOUT (200000)//ms
#define SCEN_IDENT (0x828)
#define MAP_SIZE (256 * 1024)
#define TIME_PERIOD(begin, end) ((end >= begin)? (end-begin):(0xffffffff - begin + end))
// cppcheck-suppress *
#define VCTRL_ASSERT_RET(cond, else_print) \
do { \
if (!(cond)) { \
printk(KERN_ERR "%s %d %s\n", __func__, __LINE__, else_print ); \
return VCTRL_ERR; \
} \
}while(0)
static DRV_MEM_S g_RegsBaseAddr;
Vfmw_Osal_Func_Ptr g_vfmw_osal_fun_ptr;
void VCTRL_Suspend(void)
{
unsigned char isScdSleep = 0;
unsigned char isVdmSleep = 0;
unsigned int SleepCount = 0;
unsigned int BeginTime, EntrTime, CurTime;
EntrTime = VFMW_OSAL_GetTimeInMs();
SCDDRV_PrepareSleep();
VDMHAL_PrepareSleep();
BeginTime = VFMW_OSAL_GetTimeInMs();
do {
if (SCDDRV_SLEEP_STAGE_SLEEP == SCDDRV_GetSleepStage())
isScdSleep = 1;
if (VDMHAL_GetSleepStage() == VDMDRV_SLEEP_STAGE_SLEEP)
isVdmSleep = 1;
if ((isScdSleep == 1) && (isVdmSleep == 1)) {
break;
} else {
if (SleepCount > 30) {
if (isScdSleep != 1) {
printk(KERN_ERR "Force scd sleep\n");
SCDDRV_ForceSleep();
}
if (isVdmSleep != 1) {
printk(KERN_ERR "Force vdm sleep\n");
VDMHAL_ForceSleep();
}
break;
}
VFMW_OSAL_mSleep(10);
SleepCount++;
}
} while ((isScdSleep != 1) || (isVdmSleep != 1));
CurTime = VFMW_OSAL_GetTimeInMs();
printk(KERN_INFO "Vfmw suspend totally take %d ms\n", TIME_PERIOD(EntrTime, CurTime));
return;
}
void VCTRL_Resume(void)
{
unsigned int EntrTime, CurTime;
EntrTime = VFMW_OSAL_GetTimeInMs();
SMMU_InitGlobalReg();
SCDDRV_ExitSleep();
VDMHAL_ExitSleep();
CurTime = VFMW_OSAL_GetTimeInMs();
printk(KERN_INFO "Vfmw resume totally take %d ms\n", TIME_PERIOD(EntrTime, CurTime));
return;
}
static int VCTRL_ISR(int irq, void *dev_id)
{
unsigned int D32;
D32 = RD_SCDREG(REG_SCD_INI_CLR)&0x1;
if (D32 == 1)
SCDDRV_ISR();
RD_VREG(VREG_INT_STATE, D32, 0);
if (D32 == 1)
VDMHAL_ISR(0);
return IRQ_HANDLED;
}
static int VCTRL_RequestIrq(unsigned int IrqNumNorm, unsigned int IrqNumProt, unsigned int IrqNumSafe)
{
#if !defined(VDM_BUSY_WAITTING)
if (VFMW_OSAL_RequestIrq(IrqNumNorm, VCTRL_ISR, IRQF_DISABLED, "vdec_norm_irq", NULL) != 0) { //for 2.6.24ÒÔºó
printk(KERN_ERR "Request vdec norm irq %d failed\n", IrqNumNorm);
return VCTRL_ERR;
}
#endif
return VCTRL_OK;
}
static void VCTRL_FreeIrq(unsigned int IrqNumNorm, unsigned int IrqNumProt, unsigned int IrqNumSafe)
{
#if !defined(VDM_BUSY_WAITTING)
VFMW_OSAL_FreeIrq(IrqNumNorm, NULL);
#endif
}
static int VCTRL_HalInit(void)
{
#ifdef HIVDEC_SMMU_SUPPORT
if (SMMU_Init() != SMMU_OK) {
printk(KERN_ERR "SMMU_Init failed\n");
return VCTRL_ERR;
}
#endif
SCDDRV_init();
VDMHAL_IMP_Init();
SMMU_InitGlobalReg();
return VCTRL_OK;
}
static void VCTRL_HalDeInit(void)
{
#ifdef HIVDEC_SMMU_SUPPORT
SMMU_DeInit();
#endif
VDMHAL_IMP_DeInit();
SCDDRV_DeInit();
}
int VCTRL_OpenDrivers(void)
{
MEM_RECORD_S *pstMem;
int ret = VCTRL_ERR;
pstMem = &g_RegsBaseAddr.stVdhReg;
if (MEM_MapRegisterAddr(gVdhRegBaseAddr, MAP_SIZE, pstMem) == MEM_MAN_OK) {
if (MEM_AddMemRecord(pstMem->PhyAddr, pstMem->VirAddr, pstMem->Length) != MEM_MAN_OK) {
printk(KERN_ERR "%s %d MEM_AddMemRecord failed\n", __func__, __LINE__);
goto exit;
}
} else {
printk(KERN_ERR "Map vdh register failed! gVdhRegBaseAddr : %pK, gVdhRegRange : %d\n",
(void *)(uintptr_t)gVdhRegBaseAddr, gVdhRegRange);
goto exit;
}
ret = VCTRL_RequestIrq(gVdecIrqNumNorm, gVdecIrqNumProt, gVdecIrqNumSafe);
if (ret != VCTRL_OK) {
printk(KERN_ERR "VCTRL_RequestIrq failed\n");
goto exit;
}
if (VCTRL_HalInit() != VCTRL_OK) {
printk(KERN_ERR "VCTRL_HalInit failed\n");
goto exit;
}
VFMW_OSAL_InitEvent(G_SCDHWDONEEVENT, 0);
VFMW_OSAL_InitEvent(G_VDMHWDONEEVENT, 0);
return VCTRL_OK;
exit:
VCTRL_CloseVfmw();
return VCTRL_ERR;
}
int VCTRL_OpenVfmw(void)
{
memset(&g_RegsBaseAddr, 0, sizeof(g_RegsBaseAddr)); /* unsafe_function_ignore: m
emset */
MEM_InitMemManager();
if (VCTRL_OpenDrivers() != VCTRL_OK) {
printk(KERN_ERR "OpenDrivers fail\n");
return VCTRL_ERR;
}
return VCTRL_OK;
}
int VCTRL_CloseVfmw(void)
{
MEM_RECORD_S *pstMem;
VCTRL_HalDeInit();
pstMem = &g_RegsBaseAddr.stVdhReg;
if (pstMem->Length != 0) {
MEM_UnmapRegisterAddr(pstMem->PhyAddr, pstMem->VirAddr, pstMem->Length);
MEM_DelMemRecord(pstMem->PhyAddr, pstMem->VirAddr, pstMem->Length);
memset(&g_RegsBaseAddr.stVdhReg, 0, sizeof(g_RegsBaseAddr.stVdhReg)); /* unsafe_function_ignore: m
emset */
}
VCTRL_FreeIrq(gVdecIrqNumNorm, gVdecIrqNumProt, gVdecIrqNumSafe);
return VCTRL_OK;
}
int VCTRL_VDMHal_Process(OMXVDH_REG_CFG_S *pVdmRegCfg, VDMHAL_BACKUP_S *pVdmRegState)
{
int ret = HI_SUCCESS;
VDMDRV_SLEEP_STAGE_E sleepState;
sleepState = VDMHAL_GetSleepStage();
if (VDMDRV_SLEEP_STAGE_SLEEP == sleepState) {
printk(KERN_INFO "vdm sleep state\n");
return HI_FAILURE;
}
if (pVdmRegCfg->vdh_reset_flag)
VDMHAL_IMP_ResetVdm(0);
VFMW_OSAL_InitEvent(G_VDMHWDONEEVENT, 0);
ret = VDMHAL_HwDecProc(pVdmRegCfg);
if (ret) {
printk(KERN_ERR "%s config error\n", __func__);
} else {
ret = VFMW_OSAL_WaitEvent(G_VDMHWDONEEVENT, VDM_TIMEOUT);
if (ret == HI_SUCCESS) {
VDMHAL_GetRegState(pVdmRegState);
} else {
printk(KERN_ERR "VFMW_OSAL_WaitEvent wait time out\n");
VDMHAL_IMP_ResetVdm(0);
}
}
sleepState = VDMHAL_GetSleepStage();
if (sleepState == VDMDRV_SLEEP_STAGE_PREPARE)
VDMHAL_SetSleepStage(VDMDRV_SLEEP_STAGE_SLEEP);
return ret;
}
int VCTRL_SCDHal_Process(OMXSCD_REG_CFG_S *pScdRegCfg,SCD_STATE_REG_S *pScdStateReg)
{
int ret = HI_SUCCESS;
SCDDRV_SLEEP_STAGE_E sleepState;
CONFIG_SCD_CMD cmd = pScdRegCfg->cmd;
sleepState = SCDDRV_GetSleepStage();
if (SCDDRV_SLEEP_STAGE_SLEEP == sleepState) {
printk(KERN_INFO "SCD sleep state\n");
return HI_FAILURE;
}
if (pScdRegCfg->SResetFlag) {
if (SCDDRV_ResetSCD() != HI_SUCCESS) {
printk(KERN_ERR "VDEC_IOCTL_SCD_WAIT_HW_DONE Reset SCD failed\n");
return HI_FAILURE;
}
}
switch (cmd) {
case CONFIG_SCD_REG_CMD:
VFMW_OSAL_InitEvent(G_SCDHWDONEEVENT, 0);
ret = SCDDRV_WriteReg(&pScdRegCfg->SmCtrlReg );
if (ret != HI_SUCCESS) {
printk(KERN_ERR "SCD busy\n");
return HI_FAILURE;
}
ret = VFMW_OSAL_WaitEvent(G_SCDHWDONEEVENT,SCD_TIMEOUT);
if (ret == HI_SUCCESS) {
SCDDRV_GetRegState(pScdStateReg);
} else {
printk(KERN_INFO "VDEC_IOCTL_SCD_WAIT_HW_DONE wait time out\n");
SCDDRV_ResetSCD();
}
sleepState = SCDDRV_GetSleepStage();
if (sleepState == SCDDRV_SLEEP_STAGE_PREPARE) {
SCDDRV_SetSleepStage(SCDDRV_SLEEP_STAGE_SLEEP);
}
break;
default:
printk(KERN_ERR " cmd type unknown:%d\n", cmd);
return HI_FAILURE;
}
return ret;
}
int VCTRL_VDMHAL_IsRun(void)
{
return VDMHAL_IsVdmRun(0);
}
int VCTRL_Scen_Ident(unsigned int cmd)
{
if ((RD_SCDREG(SCEN_IDENT) == 1) && (cmd != VDEC_IOCTL_SET_CLK_RATE))
return 1;
return 0;
}
int VFMW_DRV_ModInit(void)
{
OSAL_InitInterface();
VFMW_OSAL_SemaInit(G_SCD_SEM);
VFMW_OSAL_SemaInit(G_VDH_SEM);
VFMW_OSAL_SemaInit(G_BPD_SEM);
VFMW_OSAL_SpinLockInit(G_SPINLOCK_SCD);
VFMW_OSAL_SpinLockInit(G_SPINLOCK_VDH);
VFMW_OSAL_SpinLockInit(G_SPINLOCK_RECORD);
VFMW_OSAL_InitEvent(G_SCDHWDONEEVENT, 0);
VFMW_OSAL_InitEvent(G_VDMHWDONEEVENT, 0);
#ifdef MODULE
printk(KERN_INFO "%s : Load hi_vfmw.ko (%d) success\n", __func__, VFMW_VERSION_NUM);
#endif
return 0;
}
void VFMW_DRV_ModExit(void)
{
#ifdef MODULE
printk(KERN_INFO "%s : Unload hi_vfmw.ko (%d) success\n",__func__, VFMW_VERSION_NUM);
#endif
return;
}
module_init(VFMW_DRV_ModInit);
module_exit(VFMW_DRV_ModExit);
MODULE_AUTHOR("gaoyajun");
MODULE_LICENSE("GPL");
+33
View File
@@ -0,0 +1,33 @@
#ifndef __VFMW_INTF_H__
#define __VFMW_INTF_H__
//#include "../omxvdec/memory.h"
#include "./format/vdm_drv.h"
#include "scd_drv.h"
#define VCTRL_OK 0
#define VCTRL_ERR -1
#define MSG_POOL_ADDR_CHECK
typedef struct hiDRV_MEM_S {
MEM_RECORD_S stVdhReg;
} DRV_MEM_S;
int VCTRL_OpenDrivers(void);
int VCTRL_OpenVfmw(void);
int VCTRL_CloseVfmw(void);
int VCTRL_VDMHal_Process(OMXVDH_REG_CFG_S *pVdmRegCfg, VDMHAL_BACKUP_S *pVdmRegStatei);
int VCTRL_SCDHal_Process(OMXSCD_REG_CFG_S *pScdRegCfg, SCD_STATE_REG_S *pScdStateReg);
int VCTRL_VDMHAL_IsRun(void);
void VCTRL_Suspend(void);
void VCTRL_Resume(void);
int VCTRL_Scen_Ident(unsigned int cmd);
#endif
+147
View File
@@ -0,0 +1,147 @@
################################################################################################
# purpose:
# This file provide two vars: VFMW_CFLAGS, VFMW_CFILES
# VFMW_CFLAGS --- compile options for vfmw
# VFMW_CFILES --- specify the files to be compiled
###############################################################################################
VFMW_DIR := drivers/vcodec/vdec_hivna/vfmw_v4.0
VFMW_INC_DIR := $(VFMW_DIR)
SCENE_DIR := kirin
include $(VFMW_DIR)/vfmw_config.cfg
#===============================================================================
# options
#===============================================================================
VFMW_CFLAGS := -DENV_ARMLINUX_KERNEL
VFMW_CFLAGS += -DSCD_MP4_SLICE_ENABLE
VFMW_CFLAGS += -DVFMW_EXTRA_TYPE_DEFINE
VFMW_CFLAGS += -DPRODUCT_KIRIN
VFMW_CFLAGS += -DQ_MATRIX_FIXED
VFMW_CFLAGS += -DPLATFORM_KIRIN970
ifneq ($(TARGET_BUILD_VARIANT),user)
VFMW_CFLAGS += -DUSER_DISABLE_VDEC_PROC
endif
################ VDH_VERSION #############
ifeq ($(VFMW_VDH_SUPPORT),YES)
VDH_DIR := format
VFMW_CFLAGS += -DVFMW_VDH_SUPPORT
endif
##########################################
################ TEST OPTION ############
#VFMW_CFLAGS += -DKTEST_VFMW_SLEEP
ifeq ($(VFMW_TEST),YES)
VFMW_CFLAGS += -DVFMW_KTEST
endif
##########################################
################ SMMU VERSION ############
ifeq ($(HIVDEC_SMMU_SUPPORT),YES)
VFMW_CFLAGS += -DHIVDEC_SMMU_SUPPORT
endif
##########################################
#===============================================================================
# include path
#===============================================================================
VFMW_CFLAGS += -I$(VFMW_INC_DIR)
#===============================================================================
# VFMW_CFILES
#===============================================================================
VFMW_CFILES := vfmw_dts.o
VFMW_CFILES += linux_kernel_osal.o \
mem_manage.o \
vfmw_intf.o \
scd_drv.o
#===============================================================================
# vdh hal seclect
#===============================================================================
VFMW_CFILES += $(VDH_DIR)/vdm_hal.o
#===============================================================================
# SMMU hal seclect
#===============================================================================
ifeq ($(HIVDEC_SMMU_SUPPORT),YES)
VFMW_CFILES += smmu.o
endif
#===============================================================================
# vfmw video type support
#===============================================================================
################# vfmw_h264 #################
ifeq ($(VFMW_H264_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_H264_SUPPORT
VFMW_CFILES += $(VDH_DIR)/vdm_hal_h264.o
endif
################# vfmw_hevc #################
ifeq ($(VFMW_HEVC_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_HEVC_SUPPORT
VFMW_CFILES += /$(VDH_DIR)/vdm_hal_hevc.o
endif
################# vfmw_mpeg2 #################
ifeq ($(VFMW_MPEG2_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_MPEG2_SUPPORT
VFMW_CFILES += $(VDH_DIR)/vdm_hal_mpeg2.o
endif
################# vfmw_mpeg4 #################
ifeq ($(VFMW_MPEG4_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_MPEG4_SUPPORT
VFMW_CFILES += $(VDH_DIR)/vdm_hal_mpeg4.o
endif
################# vfmw_bpd #################
ifeq ($(VFMW_BPD_H_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_BPD_H_SUPPORT
endif
################# vfmw_vp8 #################
ifeq ($(VFMW_VP8_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_VP8_SUPPORT
VFMW_CFILES += $(VDH_DIR)/vdm_hal_vp8.o
endif
################# vfmw_vp9 #################
ifeq ($(VFMW_VP9_SUPPORT),YES)
VFMW_CFLAGS += -DVFMW_VP9_SUPPORT
VFMW_CFILES += $(VDH_DIR)/vdm_hal_vp9.o
endif
################# vfmw_raw_num #################
ifeq ($(VFMW_RAW_NUM_SUPPORT),YES)
VFMW_CFLAGS += -DCFG_MAX_RAW_NUM=$(VFMW_MAX_RAW_NUM)
endif
################# vfmw_seg_num #################
ifeq ($(VFMW_SEG_NUM_SUPPORT),YES)
VFMW_CFLAGS += -DCFG_MAX_SEG_NUM=$(VFMW_MAX_SEG_NUM)
endif
################# vfmw_scd_msg_buffer ##########
ifeq ($(VFMW_SCD_MSG_SUPPORT),YES)
VFMW_CFLAGS += -DCFG_SCD_BUF=$(VFMW_SCD_MSG_BUF)
endif
################# VFMW_SYSTEM_REG_DISABLE #######
ifeq ($(VFMW_SYSTEM_REG_DISABLE),YES)
VFMW_CFLAGS += -DVFMW_SYSTEM_REG_DISABLE
endif
################# CONSTRAINT_VDH_PERFORMANCE #######
ifeq ($(CONSTRAINT_VDH_PERFORMANCE),YES)
VFMW_CFLAGS += -DCONSTRAINT_VDH_PERFORMANCE
endif
################# TARGET_BOARD_PLATFORM############
ifeq ($(TARGET_BOARD_PLATFORM), hi3660)
VFMW_CFLAGS +=-DPLATFORM_HI3660
endif
+121
View File
@@ -0,0 +1,121 @@
#ifndef __VFMW_OSAL_EXT_HEADER__
#define __VFMW_OSAL_EXT_HEADER__
#include "vfmw.h"
#include "mem_manage.h"
#define OSAL_OK 0
#define OSAL_ERR -1
typedef int(*OSAL_IRQ_HANDLER_t) (int, void *);
typedef enum SpinLockType {
G_SPINLOCK_SCD = 0,
G_SPINLOCK_VDH,
G_SPINLOCK_RECORD,
} SpinLockType;
typedef enum MutexType {
G_SCDHWDONEEVENT = 0,
G_VDMHWDONEEVENT,
} MutexType;
typedef enum SemType {
G_SCD_SEM = 0,
G_VDH_SEM,
G_BPD_SEM,
} SemType;
typedef unsigned int (*FN_OSAL_GetTimeInMs) (void);
typedef unsigned int (*FN_OSAL_GetTimeInUs) (void);
typedef void (*FN_OSAL_SpinLockInit) (SpinLockType);
typedef int (*FN_OSAL_SpinLock) (SpinLockType);
typedef int (*FN_OSAL_SpinUnlock) (SpinLockType);
typedef void (*FN_OSAL_SemaInit) (SemType);
typedef int (*FN_OSAL_SemaDown) (SemType);
typedef void (*FN_OSAL_SemaUp) (SemType);
typedef int (*FN_OSAL_Print) (const char *, ...);
typedef void (*FN_OSAL_Mb) (void);
typedef void (*FN_OSAL_uDelay) (unsigned long);
typedef void (*FN_OSAL_mSleep) (unsigned int);
typedef int (*FN_OSAL_InitEvent) (MutexType, int);
typedef int (*FN_OSAL_GiveEvent) (MutexType);
typedef int (*FN_OSAL_WaitEvent) (MutexType, int);
typedef int (*FN_OSAL_MemAlloc) (unsigned char *, unsigned int, unsigned int, unsigned int, MEM_DESC_S *);
typedef int (*FN_OSAL_MemFree) (MEM_DESC_S *);
typedef unsigned char *(*FN_OSAL_RegisterMap) (unsigned int, unsigned int);
typedef void (*FN_OSAL_RegisterUnMap) (unsigned char *, unsigned int);
typedef unsigned char *(*FN_OSAL_Mmap) (unsigned int, unsigned int);
typedef unsigned char *(*FN_OSAL_MmapCache) (unsigned int, unsigned int);
typedef void (*FN_OSAL_MunMap) (unsigned char *);
typedef int (*FN_OSAL_RequestIrq) (unsigned int, OSAL_IRQ_HANDLER_t, unsigned long, const char *, void *);
typedef void (*FN_OSAL_FreeIrq) (unsigned int, void *);
typedef void *(*FN_OSAL_AllocVirMem) (int);
typedef void (*FN_OSAL_FreeVirMem) (void *);
typedef int (*FN_OSAL_ProcInit) (void);
typedef void (*FN_OSAL_ProcExit) (void);
typedef struct Vfmw_Osal_Func_Ptr {
FN_OSAL_GetTimeInMs pfun_Osal_GetTimeInMs;
FN_OSAL_GetTimeInUs pfun_Osal_GetTimeInUs;
FN_OSAL_SpinLockInit pfun_Osal_SpinLockInit;
FN_OSAL_SpinLock pfun_Osal_SpinLock;
FN_OSAL_SpinUnlock pfun_Osal_SpinUnLock;
FN_OSAL_SemaInit pfun_Osal_SemaInit;
FN_OSAL_SemaDown pfun_Osal_SemaDown;
FN_OSAL_SemaUp pfun_Osal_SemaUp;
FN_OSAL_Print pfun_Osal_Print;
FN_OSAL_Mb pfun_Osal_Mb;
FN_OSAL_uDelay pfun_Osal_uDelay;
FN_OSAL_mSleep pfun_Osal_mSleep;
FN_OSAL_InitEvent pfun_Osal_InitEvent;
FN_OSAL_GiveEvent pfun_Osal_GiveEvent;
FN_OSAL_WaitEvent pfun_Osal_WaitEvent;
FN_OSAL_RequestIrq pfun_Osal_RequestIrq;
FN_OSAL_FreeIrq pfun_Osal_FreeIrq;
FN_OSAL_MemAlloc pfun_Osal_MemAlloc;
FN_OSAL_MemFree pfun_Osal_MemFree;
FN_OSAL_RegisterMap pfun_Osal_RegisterMap;
FN_OSAL_RegisterUnMap pfun_Osal_RegisterUnMap;
FN_OSAL_Mmap pfun_Osal_Mmap;
FN_OSAL_MmapCache pfun_Osal_MmapCache;
FN_OSAL_MunMap pfun_Osal_MunMap;
FN_OSAL_AllocVirMem pfun_Osal_AllocVirMem;
FN_OSAL_FreeVirMem pfun_Osal_FreeVirMem;
FN_OSAL_ProcInit pfun_Osal_ProcInit;
FN_OSAL_ProcExit pfun_Osal_ProcExit;
} Vfmw_Osal_Func_Ptr;
extern Vfmw_Osal_Func_Ptr g_vfmw_osal_fun_ptr;
#define VFMW_OSAL_GetTimeInMs g_vfmw_osal_fun_ptr.pfun_Osal_GetTimeInMs
#define VFMW_OSAL_GetTimeInUs g_vfmw_osal_fun_ptr.pfun_Osal_GetTimeInUs
#define VFMW_OSAL_SpinLockInit g_vfmw_osal_fun_ptr.pfun_Osal_SpinLockInit
#define VFMW_OSAL_SpinLock g_vfmw_osal_fun_ptr.pfun_Osal_SpinLock
#define VFMW_OSAL_SpinUnLock g_vfmw_osal_fun_ptr.pfun_Osal_SpinUnLock
#define VFMW_OSAL_SemaInit g_vfmw_osal_fun_ptr.pfun_Osal_SemaInit
#define VFMW_OSAL_SemaDown g_vfmw_osal_fun_ptr.pfun_Osal_SemaDown
#define VFMW_OSAL_SemaUp g_vfmw_osal_fun_ptr.pfun_Osal_SemaUp
#define VFMW_OSAL_Print g_vfmw_osal_fun_ptr.pfun_Osal_Print
#define VFMW_OSAL_Mb g_vfmw_osal_fun_ptr.pfun_Osal_Mb
#define VFMW_OSAL_uDelay g_vfmw_osal_fun_ptr.pfun_Osal_uDelay
#define VFMW_OSAL_mSleep g_vfmw_osal_fun_ptr.pfun_Osal_mSleep
#define VFMW_OSAL_InitEvent g_vfmw_osal_fun_ptr.pfun_Osal_InitEvent
#define VFMW_OSAL_GiveEvent g_vfmw_osal_fun_ptr.pfun_Osal_GiveEvent
#define VFMW_OSAL_WaitEvent g_vfmw_osal_fun_ptr.pfun_Osal_WaitEvent
#define VFMW_OSAL_RequestIrq g_vfmw_osal_fun_ptr.pfun_Osal_RequestIrq
#define VFMW_OSAL_FreeIrq g_vfmw_osal_fun_ptr.pfun_Osal_FreeIrq
#define VFMW_OSAL_MemAlloc g_vfmw_osal_fun_ptr.pfun_Osal_MemAlloc
#define VFMW_OSAL_MemFree g_vfmw_osal_fun_ptr.pfun_Osal_MemFree
#define VFMW_OSAL_RegisterMap g_vfmw_osal_fun_ptr.pfun_Osal_RegisterMap
#define VFMW_OSAL_RegisterUnMap g_vfmw_osal_fun_ptr.pfun_Osal_RegisterUnMap
#define VFMW_OSAL_Mmap g_vfmw_osal_fun_ptr.pfun_Osal_Mmap
#define VFMW_OSAL_MmapCache g_vfmw_osal_fun_ptr.pfun_Osal_MmapCache
#define VFMW_OSAL_MunMap g_vfmw_osal_fun_ptr.pfun_Osal_MunMap
#define VFMW_OSAL_AllocVirMem g_vfmw_osal_fun_ptr.pfun_Osal_AllocVirMem
#define VFMW_OSAL_FreeVirMem g_vfmw_osal_fun_ptr.pfun_Osal_FreeVirMem
#define VFMW_OSAL_ProcInit g_vfmw_osal_fun_ptr.pfun_Osal_ProcInit
#define VFMW_OSAL_ProcExit g_vfmw_osal_fun_ptr.pfun_Osal_ProcExit
#endif
+8
View File
@@ -0,0 +1,8 @@
menu "Hisilicon video venc support"
config HI_VCODEC_VENC
#depends on ANDROID_PMEM
tristate "Support for venc"
default n
help
The decode device provides venc function
endmenu
+16
View File
@@ -0,0 +1,16 @@
# Add your debugging flag (or not) to CFLAGS
include drivers/vcodec/venc_hivna/drv_venc_make.cfg
EXTRA_CFLAGS += $(VENC_CFLAGS) -fno-pic
EXTRA_CFLAGS += -Idrivers/vcodec/venc_hivna
EXTRA_CFLAGS += -DPLATFORM_KIRIN970
obj-$(CONFIG_HI_VCODEC_VENC) += hi_omxvenc.o
hi_omxvenc-objs := venc_regulator.o \
drv_venc_intf.o \
drv_venc_efl.o \
drv_venc_osal.o \
drv_venc.o \
hal_venc.o \
hi_drv_mem.o
File diff suppressed because it is too large Load Diff
+48
View File
@@ -0,0 +1,48 @@
/*
* Copyright (C), 2004-2050, Hisilicon Tech. Co., Ltd.
*
* File Name : drv_venc.c
* Version : Initial Draft
* Author : Hisilicon multimedia software group
* Created : 2010/04/07
* Last Modified :
* Description :
* Function List :
*
* History :
* 1.Date :
* Author : j00131665
* Modification : Created file
*/
#include "drv_venc.h"
#include "venc_regulator.h"
#include "drv_venc_osal.h"
unsigned int b_Regular_down_flag = 1;
/* 外边复位vedu, 并设置时钟,撤销复位l00214825 */
int VENC_DRV_BoardInit(void)
{
int ret = 0;
HI_DBG_VENC("enter %s()\n", __func__);
ret = Venc_Regulator_Enable();/*lint !e838 */
if (ret != 0){
HI_INFO_VENC("enable regulator failed\n", __func__);
return HI_FAILURE;
}
HI_DBG_VENC("exit %s ()\n", __func__);
return HI_SUCCESS;
}
void VENC_DRV_BoardDeinit(void)
{
HI_DBG_VENC("enter %s ()\n", __func__);
Venc_Regulator_Disable();
HI_DBG_VENC("exit %s ()\n", __func__);
}
+85
View File
@@ -0,0 +1,85 @@
#ifndef __DRV_VENC_H__
#define __DRV_VENC_H__
#include "Vedu_RegAll_Kirin970.h"
#include "drv_venc_efl.h"
#include <linux/fs.h>
#include <linux/platform_device.h>
#include <linux/hisi/hisi-iommu.h>
#include <linux/iommu.h>
#ifndef _M_IX86
typedef unsigned long long HI_U64;
#else
typedef __int64 HI_U64;
#endif
#ifndef NULL
#define NULL 0L
#endif
#define HI_SUCCESS (0)
#define HI_FAILURE (-1)
#define MAX_STREAMBUF_NUM (16)
#define IOC_TYPE_VENC 'V'
extern unsigned int b_Regular_down_flag;
typedef enum
{
VENC_SET_CFGREG = 100,
VENC_SET_CFGREGSIMPLE
}CMD_TYPE;
typedef enum {
VENC_CLK_RATE_LOW = 0,
VENC_CLK_RATE_NORMAL,
VENC_CLK_RATE_HIGH,
} VENC_CLK_TYPE;
typedef struct
{
int InteralShareFd;
int ImageShareFd;
int StreamShareFd[MAX_STREAMBUF_NUM];
int StreamHeadShareFd;
}VENC_MEM_INFO_S;
typedef struct
{
CMD_TYPE cmd;
int bResetReg;
int bClkCfg;
int bFirstNal2Send;
unsigned int bSecureFlag;
U_FUNC_VCPI_RAWINT hw_done_type;
S_HEVC_AVC_REGS_TYPE_CFG all_reg;
VENC_CLK_TYPE clk_type;
VENC_MEM_INFO_S mem_info;
}VENC_REG_INFO_S;
#define CMD_VENC_START_ENCODE _IOWR(IOC_TYPE_VENC, 0x32, VENC_REG_INFO_S)
int VENC_DRV_BoardInit(void);
void VENC_DRV_BoardDeinit(void);
int VENC_DRV_MemProcAdd(void);
void VENC_DRV_MemProcDel(void);
void VENC_HAL_ClrAllInt(S_HEVC_AVC_REGS_TYPE * pVeduReg);
void VENC_HAL_DisableAllInt(S_HEVC_AVC_REGS_TYPE * pVeduReg);
int VENC_HAL_ResetReg(void);
void VENC_HAL_StartEncode(S_HEVC_AVC_REGS_TYPE * pVeduReg);
void VENC_HAL_Get_CfgRegSimple(VENC_REG_INFO_S * pVeduReg);
void VENC_HAL_Get_Reg_Venc(VENC_REG_INFO_S * pVeduReg);
void VeduHal_CfgReg_IntraSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_LambdaSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_QpgmapSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_AddrSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_SlcHeadSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_SMMUSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg_PREMMUSet(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgRegSimple(VENC_REG_INFO_S * channelcfg);
void VeduHal_CfgReg(VENC_REG_INFO_S * regcfginfo);
void VENC_HAL_SetSmmuAddr(S_HEVC_AVC_REGS_TYPE * pVeduReg);
#endif //__DRV_VENC_H__
+65
View File
@@ -0,0 +1,65 @@
##############################################################
# VENC DRV CFG #
##############################################################
############## VENC_SIMULATE #######################
#VENC_SIMULATE = YES
VENC_SIMULATE = NO
############## TEST_TIME ###########################
#TEST_TIME = YES
TEST_TIME = NO
############## SLICE_INT_EN ########################
#SLICE_INT_EN = YES
SLICE_INT_EN = NO
############## RE_ENCODE_EN ########################
#RE_ENCODE_EN = YES
RE_ENCODE_EN = NO
############## SPLIT_SPS_PPS #######################
SPLIT_SPS_PPS = YES
#SPLIT_SPS_PPS = NO
############## SHUTDOWN_REGULATOR_EN ###############
#SHUTDOWN_REGULATOR_EN = YES
SHUTDOWN_REGULATOR_EN = NO
############## IRQ_EN ##############################
IRQ_EN = YES
#IRQ_EN = NO
############## MD5_WC_EN ###########################
#MD5_WC_EN = YES
MD5_WC_EN = NO
############## RCN_DBG_EN ###########################
#RCN_DBG_EN = YES
RCN_DBG_EN = NO
############## HARDWARE_SPLIT_SPS_PPS_EN ###########
#HARDWARE_SPLIT_SPS_PPS_EN = YES
HARDWARE_SPLIT_SPS_PPS_EN = NO
############## OUTPUT_LOWDELAY_EN ##################
#OUTPUT_LOWDELAY_EN = YES
OUTPUT_LOWDELAY_EN = NO
############## SAO_LOWPOWER_EN #####################
#SAO_LOWPOWER_EN = YES
SAO_LOWPOWER_EN = NO
############## VENC_VOLT_HOLD #####################
#VENC_VOLT_HOLD = YES
VENC_VOLT_HOLD = NO
############## VENC_SMMU_QOS_PRINT #####################
#VENC_SMMU_QOS_PRINT = YES
VENC_SMMU_QOS_PRINT = NO
############## VENC_TIMER_ENABLE #####################
#VENC_TIMER_ENABLE = YES
VENC_TIMER_ENABLE = NO
+196
View File
@@ -0,0 +1,196 @@
#include "drv_venc_efl.h"
#include "drv_venc_osal.h"
#include "hi_drv_mem.h"
/*lint -e774 -e697 -e838*/
/*lint -e685 -e568 -e687 -e701 -e713 -e574 -e702 -e737*/
unsigned int gVencIsFPGA = 0;
unsigned int gVeduIrqNumNorm = 0;
unsigned int gVeduIrqNumPort = 0;
unsigned int gVeduIrqNumSafe = 0;
unsigned int gVencRegBaseAddr = 0;
unsigned int gVencRegRange = 0;
HI_U64 gSmmuPageBaseAddr = 0;
U_FUNC_VCPI_RAWINT g_hw_done_type ;
VEDU_OSAL_EVENT g_hw_done_event;
/*******************************************************************/
VeduEfl_IpCtx_S VeduIpCtx;
int VENC_SetDtsConfig(VeduEfl_DTS_CONFIG_S *pDtsConfig)
{
if (!pDtsConfig){
HI_FATAL_VENC("pDtsConfig is NULL\n");
return HI_FAILURE;
}
if (pDtsConfig->VeduIrqNumNorm == 0 || pDtsConfig->VeduIrqNumProt == 0 || pDtsConfig->VeduIrqNumSafe == 0 || pDtsConfig->VencRegBaseAddr == 0 ||
pDtsConfig->VencRegRange == 0 || pDtsConfig->SmmuPageBaseAddr == 0){
HI_ERR_VENC("invalid param, VeduIrqNumNorm:%d, VeduIrqNumProt:%d, VeduIrqNumSafe:%d, VencRegBaseAddr:%pK, VencRegRange:%d, SmmuPageBaseAddr:%pK\n",
pDtsConfig->VeduIrqNumNorm, pDtsConfig->VeduIrqNumProt, pDtsConfig->VeduIrqNumSafe, (void *)(uintptr_t)(pDtsConfig->VencRegBaseAddr), pDtsConfig->VencRegRange, (void *)(uintptr_t)(pDtsConfig->SmmuPageBaseAddr));
return HI_FAILURE;
}
gVencIsFPGA = pDtsConfig->IsFPGA;
gVeduIrqNumNorm = pDtsConfig->VeduIrqNumNorm;
gVeduIrqNumPort = pDtsConfig->VeduIrqNumProt;
gVeduIrqNumSafe = pDtsConfig->VeduIrqNumSafe;
gVencRegBaseAddr = pDtsConfig->VencRegBaseAddr;
gVencRegRange = pDtsConfig->VencRegRange;
gSmmuPageBaseAddr = pDtsConfig->SmmuPageBaseAddr;
return HI_SUCCESS;
}
static void Venc_ISR(void)
{
unsigned int *pINTCLR = NULL;
S_HEVC_AVC_REGS_TYPE *pAllReg = NULL;
HI_DBG_VENC("enter %s ()\n", __func__);
if (!VeduIpCtx.pRegBase) {
HI_ERR_VENC("VeduIpCtx.pRegBase invalid");
return ;
}
pAllReg = (S_HEVC_AVC_REGS_TYPE *)VeduIpCtx.pRegBase;/*lint !e826 */
pINTCLR = (unsigned int *)&(pAllReg->VEDU_VCPI_INTCLR.u32);
g_hw_done_type.bits.vcpi_rint_vedu_timeout = pAllReg->FUNC_VCPI_RAWINT.bits.vcpi_rint_vedu_timeout;
g_hw_done_type.bits.vcpi_rint_vedu_slice_end = pAllReg->FUNC_VCPI_RAWINT.bits.vcpi_rint_vedu_slice_end;
g_hw_done_type.bits.vcpi_rint_ve_eop = pAllReg->FUNC_VCPI_RAWINT.bits.vcpi_rint_ve_eop;
#ifdef VENC_SIMULATE
pAllReg->FUNC_VCPI_RAWINT.bits.vcpi_rint_ve_eop = 0;
#endif
if (g_hw_done_type.bits.vcpi_rint_vedu_timeout
|| g_hw_done_type.bits.vcpi_rint_ve_eop) {
*pINTCLR = 0xFFFFFFFF;
VENC_DRV_OsalGiveEvent(&g_hw_done_event);
} else {
*pINTCLR = 0xFFFFFFBE;
}
HI_DBG_VENC("out %s ()\n", __func__);
}
/******************************************************************************
Function :
Description: IP-VEDU & IP-JPGE Open & Close
Calls :
Input :
Output :
Return :
Others :
******************************************************************************/
int VENC_DRV_EflOpenVedu(void)
{
HI_DBG_VENC("enter %s()\n", __func__);
HiMemSet((void *)&VeduIpCtx, 0, sizeof(VeduIpCtx));
if (VENC_DRV_OsalLockCreate( &VeduIpCtx.pChnLock ) == HI_FAILURE){
HI_ERR_VENC("VENC_DRV_OsalLockCreate failed\n");
return HI_FAILURE;
}
VeduIpCtx.pRegBase = (unsigned int *)HiMmap(gVencRegBaseAddr, gVencRegRange);
if (!VeduIpCtx.pRegBase){
HI_ERR_VENC("ioremap failed\n");
VENC_DRV_OsalLockDestroy( VeduIpCtx.pChnLock );
return HI_FAILURE;
}
HI_DBG_VENC("HI_DDR_MEM_Init\n");
if (HI_SUCCESS != DRV_MEM_INIT()) {
HI_ERR_VENC("DRV_MEM_INIT failed\n");
VENC_DRV_OsalLockDestroy( VeduIpCtx.pChnLock );
HiMunmap(VeduIpCtx.pRegBase);
return HI_FAILURE;
}
VeduIpCtx.IpFree = 1;
VENC_HAL_SetSmmuAddr((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
VENC_HAL_DisableAllInt((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
VENC_HAL_ClrAllInt ((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
#ifdef IRQ_EN
if (VENC_DRV_OsalIrqInit(gVeduIrqNumNorm, Venc_ISR) == HI_FAILURE){
HI_ERR_VENC("VENC_DRV_OsalIrqInit failed\n");
VENC_DRV_OsalLockDestroy( VeduIpCtx.pChnLock );
HiMunmap(VeduIpCtx.pRegBase);
DRV_MEM_EXIT();
return HI_FAILURE;
}
#endif
/* creat thread to manage channel */
VeduIpCtx.StopTask = 0;
VeduIpCtx.TaskRunning = 0;
VENC_DRV_OsalInitEvent(&g_hw_done_event, 0);
HI_DBG_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
}
int VENC_DRV_EflCloseVedu( void )
{
unsigned int TimeOutCnt = 0;
#ifdef MD5_WC_EN
int i = 0;
unsigned char digesttmp[16] ;
unsigned char digesttmp2[100] ;
HiMemSet(digesttmp, 0, 16);
HiMemSet(digesttmp2, 0, 100);
#endif
HI_DBG_VENC("enter %s()\n", __func__);
VeduIpCtx.StopTask = 1;
while ((VeduIpCtx.TaskRunning) && (TimeOutCnt < 100)) {
HiSleepMs(1);
TimeOutCnt ++;
}
VENC_HAL_DisableAllInt((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
VENC_HAL_ClrAllInt((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
#ifdef IRQ_EN
VENC_DRV_OsalIrqFree(gVeduIrqNumNorm);
#endif
HiMunmap(VeduIpCtx.pRegBase);
DRV_MEM_EXIT();
VENC_DRV_OsalLockDestroy( VeduIpCtx.pChnLock );
HI_DBG_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
}
int VENC_DRV_EflSuspendVedu(void)
{
unsigned int TimeOutCnt = 0;
HI_INFO_VENC("enter %s()\n", __func__);
VeduIpCtx.StopTask = 1;
while ((VeduIpCtx.TaskRunning) && (TimeOutCnt < 100)) {
HiSleepMs(1);
TimeOutCnt ++;
}
HI_INFO_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
}
int VENC_DRV_EflResumeVedu(void)
{
HI_INFO_VENC("enter %s()\n", __func__);
VeduIpCtx.StopTask = 0;
VeduIpCtx.TaskRunning = 0;
HI_INFO_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
}
+47
View File
@@ -0,0 +1,47 @@
#ifndef __DRV_VENC_EFL_H__
#define __DRV_VENC_EFL_H__
#include "hi_drv_mem.h"
#include "drv_venc.h"
enum {
VEDU_H265 = 0,
VEDU_H264 = 1
};
typedef struct {
unsigned int IpFree; /* for channel control */
unsigned long long CurrHandle;//HI_U64 CurrHandle; /* used in ISR */
unsigned int *pRegBase;
void *pChnLock; /* lock ChnCtx[MAX_CHN] */
void *pTask_Frame; /* for both venc & omxvenc */
void *pTask_Stream; /* juse for omxvenc */
unsigned int StopTask;
unsigned int TaskRunning; /* to block Close IP */
unsigned int bReEncode;
} VeduEfl_IpCtx_S;
typedef struct {
unsigned int IsFPGA;
unsigned int VeduIrqNumNorm;
unsigned int VeduIrqNumProt;
unsigned int VeduIrqNumSafe;
unsigned int VencRegBaseAddr;
unsigned int VencRegRange;
unsigned int normalRate;
unsigned int highRate;
unsigned int lowRate;
unsigned long long SmmuPageBaseAddr;//HI_U64 SmmuPageBaseAddr;
} VeduEfl_DTS_CONFIG_S;
int VENC_DRV_EflOpenVedu(void);
int VENC_DRV_EflCloseVedu(void);
int VENC_DRV_EflResumeVedu(void);
int VENC_DRV_EflSuspendVedu(void);
int VENC_SetDtsConfig(VeduEfl_DTS_CONFIG_S* info);
/*************************************************************************************/
#endif //__DRV_VENC_EFL_H__
+534
View File
@@ -0,0 +1,534 @@
/*
* Copyright (C), 2001-2011, Hisilicon Tech. Co., Ltd.
*
* File Name : viu.c
* Version : Initial Draft
* Author : Hisilicon multimedia software group
* Created :
* Description :
*
* History :
* 1.Date : 2010/03/17
* Author : j00131665
* Modification: Created file
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/cdev.h>
#include <linux/platform_device.h>
#include "drv_venc_osal.h"
#include "drv_venc.h"
#include "venc_regulator.h"
#include "drv_venc.h"
#define VERSION_STRING "1234"
#define PCTRL_PERI 0xE8A090A4
#define PCTRL_PERI_SATA0 (0xE8A090BC)
#define MAX_OPEN_COUNT 3
/*lint -e750 -e838 -e715*/
#ifndef VM_RESERVED /*for kernel up to 3.7.0 version*/
# define VM_RESERVED (VM_DONTEXPAND | VM_DONTDUMP)
#endif
/*============Deviece===============*/
typedef struct {
dev_t dev;
struct device* venc_device;
//struct device* venc_device_2;
struct cdev cdev;
struct class* venc_class;
}VENC_ENTRY;
typedef enum {
KIRIN_960,
KIRIN_970_ES,
KIRIN_970_CS,
}KIRIN_PLATFORM_E;
typedef struct {
MEM_BUFFER_S internalbuffer;
MEM_BUFFER_S imagebuffer;
MEM_BUFFER_S streambuffer[MAX_STREAMBUF_NUM];
MEM_BUFFER_S streamheadbuffer;
}VENC_MEM_INFO;
struct semaphore g_VencMutex;
static int g_vencOpenFlag = 0;
static int g_vencDevDetected = 0;
//VENC device open times
atomic_t g_VencCount = ATOMIC_INIT(0);
int VENC_DRV_Resume(struct platform_device *pltdev);
int VENC_DRV_Suspend(struct platform_device *pltdev, pm_message_t state);
static int VENC_DRV_SetupCdev(VENC_ENTRY *venc, const struct file_operations *fops);
static int VENC_DRV_CleanupCdev(VENC_ENTRY *venc);
static int VENC_DRV_Probe(struct platform_device * pltdev);
static int VENC_DRV_Remove(struct platform_device *pltdev);
extern VeduEfl_IpCtx_S VeduIpCtx;
extern U_FUNC_VCPI_RAWINT g_hw_done_type;
extern VEDU_OSAL_EVENT g_hw_done_event;
extern unsigned int gVencIsFPGA;
static int venc_drv_waithwdone(U_FUNC_VCPI_RAWINT *hw_done_type)
{
int Ret = HI_FAILURE;
Ret = VENC_DRV_OsalWaitEvent(&g_hw_done_event, msecs_to_jiffies(500));/*lint !e712 !e747 */
if (Ret != 0) {
hw_done_type->u32 = 0;
HI_ERR_VENC("wait timeout, Ret value is %d\n", Ret);
return Ret;
}
*hw_done_type = g_hw_done_type;
return Ret;
}
static int venc_drv_register_info(VENC_REG_INFO_S *regcfginfo)
{
int Ret = HI_SUCCESS;
CMD_TYPE cmd = regcfginfo->cmd;
switch (cmd) {
case VENC_SET_CFGREG:
if (regcfginfo->bResetReg == 1)
{
Ret = VENC_HAL_ResetReg();
if (Ret != HI_SUCCESS)
{
HI_ERR_VENC("reset venc hal reset reg, Ret:%d\n", Ret);
break;
}
}
VeduHal_CfgReg(regcfginfo);
VENC_HAL_StartEncode((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
Ret = venc_drv_waithwdone(&regcfginfo->hw_done_type) ;
if((Ret == HI_SUCCESS ) && (!regcfginfo->hw_done_type.bits.vcpi_rint_vedu_timeout))
{
VENC_HAL_Get_Reg_Venc(regcfginfo);
HI_DBG_VENC("get venc hal reg info\n");
}
break;
case VENC_SET_CFGREGSIMPLE:
VeduHal_CfgRegSimple(regcfginfo);
VENC_HAL_StartEncode((S_HEVC_AVC_REGS_TYPE*)(VeduIpCtx.pRegBase));/*lint !e826 */
Ret = venc_drv_waithwdone(&regcfginfo->hw_done_type) ;
if((Ret == HI_SUCCESS ) && (!regcfginfo->hw_done_type.bits.vcpi_rint_vedu_timeout))
{
VENC_HAL_Get_Reg_Venc(regcfginfo);
HI_DBG_VENC("get venc hal reg info\n");
}
break;
default:
HI_ERR_VENC("cmd type unknown:0x%x in default case\n", cmd);
Ret = HI_FAILURE;
break;
}
return Ret;
}
static int VENC_DRV_Open(struct inode *finode, struct file *ffile)
{
int Ret = 0;
Ret = HiVENC_DOWN_INTERRUPTIBLE(&g_VencMutex);
if (Ret) {
HI_FATAL_VENC("Open down interruptible failed\n");
return HI_FAILURE;
}
if (atomic_read(&g_VencCount) == MAX_OPEN_COUNT) {
HI_FATAL_VENC("open venc too much\n");
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return -EAGAIN;
}
if (atomic_inc_return(&g_VencCount) == 1) {
Ret = VENC_DRV_BoardInit();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("board init failed, ret value is %d\n", Ret);
atomic_dec(&g_VencCount);
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
Ret = VENC_DRV_EflOpenVedu();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("venc firmware layer open failed, ret value is %d\n", Ret);
atomic_dec(&g_VencCount);
VENC_DRV_BoardDeinit();
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
}
g_vencOpenFlag = 1;
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
HI_INFO_VENC("Open venc device successfully\n");
return HI_SUCCESS;
}
static int VENC_DRV_Close(struct inode *finode, struct file *ffile)
{
int Ret = 0;
Ret = HiVENC_DOWN_INTERRUPTIBLE(&g_VencMutex);
if (Ret) {
HI_FATAL_VENC("Close down interruptible failed\n");
return HI_FAILURE;
}
if (atomic_dec_and_test(&g_VencCount)) {
Ret = VENC_DRV_EflCloseVedu();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("venc firmware layer close failed, ret value is %d\n", Ret);
VENC_DRV_BoardDeinit();
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
VENC_DRV_BoardDeinit();
g_vencOpenFlag = 0;
}
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
HI_INFO_VENC("Close venc device successfully\n");
return HI_SUCCESS;
}
int VENC_DRV_Suspend(struct platform_device *pltdev, pm_message_t state)
{
int Ret = 0;
HI_INFO_VENC("enter\n");
Ret = HiVENC_DOWN_INTERRUPTIBLE(&g_VencMutex);
if (Ret) {
HI_ERR_VENC("Suspend down interruptible failed\n");
return HI_FAILURE;
}
if (!g_vencOpenFlag) {
HI_INFO_VENC("venc device already suspend\n");
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_SUCCESS;
}
Ret = VENC_DRV_EflSuspendVedu();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("venc firmware layer suspend failed, ret value is %d\n", Ret);
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
VENC_DRV_BoardDeinit();
g_hw_done_event.flag = 0;
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
HI_INFO_VENC("exit\n");
return HI_SUCCESS;
}/*lint !e715*/
int VENC_DRV_Resume(struct platform_device *pltdev)
{
int Ret = 0;
HI_INFO_VENC("enter\n");
Ret = HiVENC_DOWN_INTERRUPTIBLE(&g_VencMutex);
if (Ret) {
HI_FATAL_VENC("Resume down interruptible failed\n");
return HI_FAILURE;
}
if (!g_vencOpenFlag) {
HI_INFO_VENC("venc device already resume\n");
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return 0;
}
Ret = VENC_DRV_BoardInit();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("board init failed, ret value is %d\n", Ret);
atomic_dec(&g_VencCount);
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
Ret = VENC_DRV_EflResumeVedu();
if (Ret != HI_SUCCESS) {
HI_FATAL_VENC("venc firmware layer resume failed, ret value is %d\n", Ret);
atomic_dec(&g_VencCount);
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return HI_FAILURE;
}
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
HI_INFO_VENC("exit\n");
return HI_SUCCESS;
}/*lint !e715*/
static long VENC_Ioctl(struct file *file, unsigned int ucmd, unsigned long uarg)
{
int Ret;
int cmd = (int)ucmd;
void *arg = (void *)uarg;
VENC_REG_INFO_S *regcfginfo = NULL;
VENC_MEM_INFO VencMapInfo;
if (!arg) {
//HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
HI_FATAL_VENC("uarg is NULL\n");
return HI_FAILURE;
}
switch (cmd) {
case CMD_VENC_START_ENCODE:/*lint !e30 !e142*/
VeduIpCtx.TaskRunning = 1;
regcfginfo = (VENC_REG_INFO_S *)arg;
HiMemSet((void*)&VencMapInfo, 0, sizeof(VencMapInfo));
VENC_DRV_OsalInitEvent(&g_hw_done_event, 0);
Ret = venc_drv_register_info(regcfginfo);
VeduIpCtx.TaskRunning = 0;
HI_DBG_VENC("venc cfg reg info, Ret:%d\n", Ret);
break;
default:
HI_ERR_VENC("venc cmd unknown:0x%x\n", ucmd);
Ret = HI_FAILURE;
break;
}
//HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return Ret;
}
static long VENC_DRV_Ioctl(struct file *file, unsigned int cmd, unsigned long arg)
{
long Ret;
Ret = HiVENC_DOWN_INTERRUPTIBLE(&g_VencMutex);
if (Ret != 0)
{
HI_FATAL_VENC("Ioctl, down interruptible failed\n");
return Ret;
}
Ret = (long)HI_DRV_UserCopy(file, cmd, arg, VENC_Ioctl);
HiVENC_UP_INTERRUPTIBLE(&g_VencMutex);
return Ret;
}
static struct file_operations VENC_FOPS =
{
.owner = THIS_MODULE,/*lint !e64 */
.open = VENC_DRV_Open,
.unlocked_ioctl = VENC_DRV_Ioctl,
.compat_ioctl = VENC_DRV_Ioctl,
.release = VENC_DRV_Close,
};/*lint !e785 */
static const struct of_device_id venc_of_match[] = {
{ .compatible = "hisi,kirin970-venc", },/*lint !e785 */
{ }/*lint !e785 */
};
static struct platform_driver Venc_driver = {
.probe = VENC_DRV_Probe,
.remove = VENC_DRV_Remove,
.suspend = VENC_DRV_Suspend,
.resume = VENC_DRV_Resume,
.driver = {
.name = "hi_venc",
.owner = THIS_MODULE,/*lint !e64 */
.of_match_table = venc_of_match
},/*lint !e785 */
};/*lint !e785 */
static struct platform_device Venc_device = {
.name = "hi_venc",
.id = -1,
.dev = {
.platform_data = NULL,
.release = NULL,
},/*lint !e785 */
};/*lint !e785 */
static int VENC_DRV_SetupCdev(VENC_ENTRY *venc, const struct file_operations *fops)
{
int err = 0;
HI_INFO_VENC("enter %s()\n", __func__);
err = alloc_chrdev_region(&venc->dev, 0, 1, "hi_venc");
if (err < 0) {
return HI_FAILURE;
}
HiMemSet((void*)&(venc->cdev), 0, sizeof(struct cdev));
cdev_init(&(venc->cdev), &VENC_FOPS);
venc->cdev.owner = THIS_MODULE;/*lint !e64 */
venc->cdev.ops = &VENC_FOPS;
err = cdev_add(&(venc->cdev), venc->dev, 1);
/*在/sys/class/目录下创建设备类别目录hi_venc*/
venc->venc_class = class_create(THIS_MODULE, "hi_venc");/*lint !e64 */
if (IS_ERR(venc->venc_class)) {
err = PTR_ERR(venc->venc_class);/*lint !e712 */
HI_ERR_VENC("Fail to create hi_venc class\n");
goto unregister_region;
//return HI_FAILURE;/*lint !e438 */
}
/*在/dev/目录和/sys/class/hi_venc目录下分别创建设备文件hi_venc*/
venc->venc_device = device_create(venc->venc_class, NULL, venc->dev, "%s", "hi_venc");
if (IS_ERR(venc->venc_device)) {
err = PTR_ERR(venc->venc_device);/*lint !e712 */
HI_ERR_VENC("Fail to create hi_venc device\n");
goto cls_destroy;
//return HI_FAILURE;/*lint !e438 */
}
HI_INFO_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
cls_destroy:
class_destroy(venc->venc_class);
venc->venc_class = NULL;
unregister_region:
unregister_chrdev_region(venc->dev, 1);
return 0;
}/*lint !e550 */
static int VENC_DRV_CleanupCdev(VENC_ENTRY *venc)
{
/*销毁设备类别和设备*/
if (venc->venc_class) {
device_destroy(venc->venc_class,venc->dev);
class_destroy(venc->venc_class);
}
cdev_del(&(venc->cdev));
unregister_chrdev_region(venc->dev,1);
return 0;
}
static int VENC_DRV_Probe(struct platform_device * pltdev)
{
int ret = HI_FAILURE;
VENC_ENTRY *venc = NULL;
HI_INFO_VENC("omxvenc prepare to probe\n");
HiVENC_INIT_MUTEX(&g_VencMutex);
if (g_vencDevDetected) {
HI_INFO_VENC("venc device detected already\n");
return HI_SUCCESS;
}
venc = HiMemVAlloc(sizeof(VENC_ENTRY));/*lint !e747 */
if (!venc) {
HI_FATAL_VENC("call vmalloc failed\n");
return ret;
}
HiMemSet((void *)venc, 0, sizeof(VENC_ENTRY));
ret = VENC_DRV_SetupCdev(venc, &VENC_FOPS);
if (ret < 0) {
HI_ERR_VENC("setup char device failed\n");
goto free;
}
platform_set_drvdata(pltdev, venc);
g_vencDevDetected = 1;
ret = Venc_Regulator_Init(pltdev);
if (ret < 0) {
HI_FATAL_VENC("init regulator failed\n");
goto cleanup;
}
HI_INFO_VENC("omxvenc probe successfully\n");
return ret;
cleanup:
VENC_DRV_CleanupCdev(venc);
free:
HiMemVFree(venc);
return ret;
}
static int VENC_DRV_Remove(struct platform_device *pltdev)
{
VENC_ENTRY *venc = NULL;
HI_INFO_VENC("omxvenc prepare to remove\n");
venc = platform_get_drvdata(pltdev);
if (venc) {
VENC_DRV_CleanupCdev(venc);
Venc_Regulator_Deinit(pltdev);
}
else {
HI_ERR_VENC("get platform drvdata err\n");
}
platform_set_drvdata(pltdev,NULL);
HiMemVFree(venc);
g_vencDevDetected = 0;
HI_INFO_VENC("remove omxvenc successfully\n");
return 0;
}
int __init VENC_DRV_ModInit(void)
{
int ret = 0;
HI_INFO_VENC("enter %s()\n", __func__);
ret = platform_device_register(&Venc_device);
if (ret < 0) {
HI_ERR_VENC("regist platform device failed\n");
return ret;
}
ret = platform_driver_register(&Venc_driver);/*lint !e64 */
if (ret < 0) {
HI_ERR_VENC("regist platform driver failed\n");
goto exit;
}
HI_INFO_VENC("success\n");
#ifdef MODULE
HI_INFO_VENC("Load hi_venc.ko success\t(%s)\n", VERSION_STRING);
#endif
HI_INFO_VENC("exit %s()\n", __func__);
return HI_SUCCESS;
exit:
platform_device_unregister(&Venc_device);
#ifdef MODULE
HI_ERR_VENC("Load hi_venc.ko failed\t(%s)\n", VERSION_STRING);
#endif
return ret;
}
void VENC_DRV_ModExit(void)
{
HI_INFO_VENC("enter %s()\n", __func__);
platform_driver_unregister(&Venc_driver);
platform_device_unregister(&Venc_device);
HI_INFO_VENC("exit %s()\n", __func__);
return;
}
/*lint -e528*/
module_init(VENC_DRV_ModInit); /*lint !e528*/
module_exit(VENC_DRV_ModExit); /*lint !e528*/
/*lint -e753*/
MODULE_LICENSE("Dual BSD/GPL"); /*lint !e753*/
+82
View File
@@ -0,0 +1,82 @@
##########################################################
# VENC DRV MAKE CONFIG #
##########################################################
include drivers/vcodec/venc_hivna/drv_venc_config.cfg
############## VENC_SIMULATE #######################
ifeq ($(VENC_SIMULATE),YES)
VENC_CFLAGS := -DVENC_SIMULATE
endif
############## TEST_TIME ###########################
ifeq ($(TEST_TIME),YES)
VENC_CFLAGS += -DTEST_TIME
endif
############## SLICE_INT_EN ########################
ifeq ($(SLICE_INT_EN),YES)
VENC_CFLAGS += -DSLICE_INT_EN
endif
############## RE_ENCODE_EN ########################
ifeq ($(RE_ENCODE_EN),YES)
VENC_CFLAGS += -DRE_ENCODE_EN
endif
############## SPLIT_SPS_PPS #######################
ifeq ($(SPLIT_SPS_PPS),YES)
VENC_CFLAGS += -DSPLIT_SPS_PPS
endif
############## SHUTDOWN_REGULATOR_EN ###############
ifeq ($(SHUTDOWN_REGULATOR_EN),YES)
VENC_CFLAGS += -DSHUTDOWN_REGULATOR_EN
endif
############## IRQ_EN ##############################
ifeq ($(IRQ_EN),YES)
VENC_CFLAGS += -DIRQ_EN
endif
############## MD5_WC_EN ###########################
ifeq ($(MD5_WC_EN),YES)
VENC_CFLAGS += -DMD5_WC_EN
endif
############## RCN_DBG_EN ###########################
ifeq ($(RCN_DBG_EN),YES)
VENC_CFLAGS += -DRCN_DBG_EN
endif
############## HARDWARE_SPLIT_SPS_PPS_EN ###########
ifeq ($(HARDWARE_SPLIT_SPS_PPS_EN), YES)
VENC_CFLAGS += -DHARDWARE_SPLIT_SPS_PPS_EN
endif
############## OUTPUT_LOWDELAY_EN ##################
ifeq ($(OUTPUT_LOWDELAY_EN),YES)
VENC_CFLAGS += -DOUTPUT_LOWDELAY_EN
endif
############## SAO_LOWPOWER_EN #####################
ifeq ($(SAO_LOWPOWER_EN),YES)
VENC_CFLAGS += -DSAO_LOWPOWER_EN
endif
############## VENC_VOLT_HOLD ######################
ifeq ($(VENC_VOLT_HOLD),YES)
VENC_CFLAGS += -DVENC_VOLT_HOLD
endif
############## VENC_SMMU_QOS_PRINT ######################
ifeq ($(VENC_SMMU_QOS_PRINT),YES)
VENC_CFLAGS += -DVENC_SMMU_QOS_PRINT
endif
############## VENC_TIMER_ENABLE #####################
ifeq ($(VENC_TIMER_ENABLE),YES)
VENC_CFLAGS += -DVENC_TIMER_ENABLE
endif
+258
View File
@@ -0,0 +1,258 @@
#include <linux/kthread.h>
#include <linux/delay.h>
#include "drv_venc_osal.h"
#include "hi_drv_mem.h"
#define TIME_PERIOD(begin, end) ((end >= begin) ? (end - begin) : (0xffffffff - begin + end))
/*lint -e747 -e712 -e732 -e715 -e774 -e845 -e438 -e838*/
unsigned int g_VencPrintEnable = 0xf;
char *pszMsg[((char)VENC_ALW) + 1] = {"FATAL","ERR","WARN","IFO","DBG"}; /*lint !e785 */
char g_VencPrintMsg[1024];
static void (*ptrVencCallBack)(void);
static irqreturn_t VENC_DRV_OsalVencISR(int Irq, void *DevID)
{
(*ptrVencCallBack)();
return IRQ_HANDLED;
}
int VENC_DRV_OsalIrqInit( unsigned int Irq, void (*ptrCallBack)(void))
{
int ret = 0;
if (Irq != 0) {
ptrVencCallBack = ptrCallBack;
ret = request_irq(Irq, VENC_DRV_OsalVencISR, 0, "DT_device", NULL);
} else {
HI_FATAL_VENC("params is invaild\n");
ret = HI_FAILURE;
}
if (ret == 0) {
return HI_SUCCESS;
} else {
HI_FATAL_VENC("request irq failed\n");
return HI_FAILURE;
}
}
void VENC_DRV_OsalIrqFree(unsigned int Irq)
{
free_irq(Irq, NULL);
}
int VENC_DRV_OsalLockCreate(void **phLock)
{
spinlock_t *pLock = NULL;
pLock = (spinlock_t *)vmalloc(sizeof(spinlock_t));
if (!pLock) {
HI_FATAL_VENC("vmalloc failed\n");
return HI_FAILURE;
}
spin_lock_init( pLock );
*phLock = pLock;
return HI_SUCCESS;
}
void VENC_DRV_OsalLockDestroy( void* hLock )
{
if (hLock) {
vfree((void *)hLock);
//hLock = NULL;
}
}
/************************************************************************/
/* 初始化事件 */
/************************************************************************/
int VENC_DRV_OsalInitEvent(VEDU_OSAL_EVENT *pEvent, int InitVal)
{
pEvent->flag = InitVal;
init_waitqueue_head(&(pEvent->queue_head));
return HI_SUCCESS;
}
/************************************************************************/
/* 发出事件唤醒 */
/************************************************************************/
int VENC_DRV_OsalGiveEvent(VEDU_OSAL_EVENT *pEvent)
{
pEvent->flag = 1;
wake_up(&(pEvent->queue_head));
return HI_SUCCESS;
}
HI_U64 get_sys_time(void)
{
HI_U64 sys_time;
sys_time = sched_clock();
do_div(sys_time, 1000000);
return sys_time;
}
/************************************************************************/
/* 等待事件 */
/* 事件发生返回OSAL_OK,超时返回OSAL_ERR 若condition不满足就阻塞等待 */
/* 被唤醒返回 0 ,超时返回非-1 */
/************************************************************************/
int VENC_DRV_OsalWaitEvent(VEDU_OSAL_EVENT *pEvent, unsigned int msWaitTime)
{
int l_ret = 0;
unsigned int cnt = 0;
HI_U64 start_time, cur_time;
start_time = get_sys_time();
do {
l_ret = wait_event_interruptible_timeout((pEvent->queue_head), (pEvent->flag != 0), (msecs_to_jiffies(msWaitTime))); /*lint !e665 !e666 !e40 !e713 !e578*/
if (l_ret < 0) {
cur_time = get_sys_time();
if (TIME_PERIOD(start_time, cur_time) > (HI_U64)msWaitTime) {
HI_FATAL_VENC("wait event time out, time : %lld, cnt: %d\n", TIME_PERIOD(start_time, cur_time), cnt);
l_ret = 0;
break;
}
}
cnt++;
} while ((pEvent->flag == 0) && (l_ret < 0));
if (cnt > 100) {
HI_FATAL_VENC("the max cnt of wait_event interrupts by singal is %d\n", cnt);
}
if (l_ret == 0) {
HI_FATAL_VENC("wait pEvent signal timeout\n");
}
pEvent->flag = 0;//(pEvent->flag>0)? (pEvent->flag-1): 0;
return (l_ret != 0) ? HI_SUCCESS : HI_FAILURE;
}
int HiMemCpy(void*a_pHiDstMem, void *a_pHiSrcMem, size_t a_Size)
{
if ((!a_pHiDstMem) || (!a_pHiSrcMem)) {
HI_FATAL_VENC("params is invaild\n");
return HI_FAILURE;
}
memcpy((void *)a_pHiDstMem, (void *)a_pHiSrcMem, a_Size); /* unsafe_function_ignore: memcpy */
return HI_SUCCESS;
}
int HiMemSet(void *a_pHiDstMem, int a_Value, size_t a_Size)
{
if (!a_pHiDstMem) {
HI_FATAL_VENC("params is invaild\n");
return HI_FAILURE;
}
memset((void *)a_pHiDstMem, a_Value, a_Size); /* unsafe_function_ignore: memset */
return HI_SUCCESS;
}
void HiSleepMs(unsigned int a_MilliSec)
{
msleep(a_MilliSec);
}
unsigned int* HiMmap(unsigned int Addr ,unsigned int Range)
{
unsigned int *res_addr = NULL;
res_addr = (unsigned int *)ioremap(Addr, Range);
return res_addr;
}
void HiMunmap(unsigned int * pMemAddr)
{
if (!pMemAddr) {
HI_FATAL_VENC("params is invaild\n");
return;
}
iounmap(pMemAddr);
}
int HiStrNCmp(const char* pStrName,const char* pDstName,int nSize)
{
int ret = 0;
if (pStrName && pDstName) {
ret = strncmp(pStrName,pDstName,nSize);
return ret;
}
return HI_FAILURE;
}
void *HiMemVAlloc(unsigned int nMemSize)
{
void * memaddr = NULL;
if (nMemSize) {
memaddr = vmalloc(nMemSize);
}
return memaddr;
}
void HiMemVFree(void *pMemAddr)
{
if (pMemAddr) {
vfree((void *)pMemAddr);
}
}
void HiVENC_INIT_MUTEX(void *pSem)
{
if (pSem) {
sema_init((struct semaphore *)pSem, 1);
}
}
int HiVENC_DOWN_INTERRUPTIBLE(void *pSem)
{
int Ret = -1;
if (pSem) {
Ret = down_interruptible((struct semaphore *)pSem);
}
return Ret;
}
void HiVENC_UP_INTERRUPTIBLE(void *pSem)
{
if (pSem) {
up((struct semaphore *)pSem);
}
}
void HI_PRINT(unsigned int type,char *file, int line , char *function, char *msg, ... )
{
va_list args;
unsigned int uTotalChar;
if ( ((1 << type) & g_VencPrintEnable) == 0 && (type != VENC_ALW) ) /*lint !e701 */
return ;
va_start(args, msg);
uTotalChar = vsnprintf(g_VencPrintMsg, sizeof(g_VencPrintMsg), msg, args); /* unsafe_function_ignore: vsnprintf */
g_VencPrintMsg[sizeof(g_VencPrintMsg) - 1] = '\0';
va_end(args);
if (uTotalChar <= 0 || uTotalChar >= 1023) /*lint !e775 */
return;
printk(KERN_ALERT "%s:<%d:%s>%s \n", pszMsg[type], line, function, g_VencPrintMsg);
return;
}
+59
View File
@@ -0,0 +1,59 @@
#ifndef __DRV_VENC_OSAL_H__
#define __DRV_VENC_OSAL_H__
#include <linux/rtc.h>
typedef struct hiKERN_EVENT_S
{
wait_queue_head_t queue_head;
int flag;
} KERN_EVENT_S;
typedef KERN_EVENT_S VEDU_OSAL_EVENT;
typedef unsigned long VEDU_LOCK_FLAG;
#define MESCS_TO_JIFFIES(time) msecs_to_jiffies(time)
#define HiWaitEvent( pEvent, flag) wait_event_interruptible((pEvent), (flag))
#define HiWaitEventTimeOut( pEvent, flag, msWaitTime) wait_event_interruptible_timeout((pEvent), (flag), (msWaitTime))
extern unsigned int g_VencPrintEnable;
typedef enum {
VENC_FATAL = 0,
VENC_ERR,
VENC_WARN,
VENC_INFO,
VENC_DBG,
VENC_ALW,
}VENC_PRINT_TYPE;
#define HI_FATAL_VENC(fmt,...) HI_PRINT(VENC_FATAL,(char *)__FILE__, (int)__LINE__, (char *)__FUNCTION__, fmt, ##__VA_ARGS__)
#define HI_ERR_VENC(fmt,...) HI_PRINT(VENC_ERR,(char *)__FILE__, (int)__LINE__, (char *)__FUNCTION__, fmt, ##__VA_ARGS__)
#define HI_WARN_VENC(fmt,...) HI_PRINT(VENC_WARN,(char *)__FILE__, (int)__LINE__, (char *)__FUNCTION__, fmt,##__VA_ARGS__)
#define HI_INFO_VENC(fmt,...) HI_PRINT(VENC_INFO,(char *)__FILE__, (int)__LINE__, (char *)__FUNCTION__, fmt,##__VA_ARGS__)
#define HI_DBG_VENC(fmt,...) HI_PRINT(VENC_DBG,(char *)__FILE__, (int)__LINE__, (char *)__FUNCTION__, fmt,##__VA_ARGS__)
void HI_PRINT(unsigned int type, char *file, int line, char *function, char *msg, ... );
unsigned int* HiMmap(unsigned int Addr ,unsigned int Range);
void HiMunmap(unsigned int * pMemAddr);
int HiStrNCmp(const char* pStrName,const char* pDstName,int nSize);
void HiSleepMs(unsigned int a_MilliSec);
void* HiMemVAlloc(unsigned int nMemSize);
void HiMemVFree(void * pMemAddr);
int HiMemSet(void * a_pHiDstMem, int a_Value, size_t a_Size);
int HiMemCpy(void * a_pHiDstMem, void * a_pHiSrcMem, size_t a_Size);
void HiVENC_INIT_MUTEX(void* pSem);
int HiVENC_DOWN_INTERRUPTIBLE(void* pSem);
void HiVENC_UP_INTERRUPTIBLE(void* pSem);
int VENC_DRV_OsalIrqInit(unsigned int Irq, void(*ptrCallBack)(void));
void VENC_DRV_OsalIrqFree(unsigned int Irq);
int VENC_DRV_OsalLockCreate (void** phLock);
void VENC_DRV_OsalLockDestroy(void* hLock);
unsigned int GetTimeInUs(void);
int VENC_DRV_OsalInitEvent( VEDU_OSAL_EVENT *pEvent, int InitVal );
int VENC_DRV_OsalGiveEvent( VEDU_OSAL_EVENT *pEvent );
int VENC_DRV_OsalWaitEvent( VEDU_OSAL_EVENT *pEvent, unsigned int msWaitTime );
#endif //__DRV_VENC_OSAL_H__
+3296
View File
File diff suppressed because it is too large Load Diff
+239
View File
@@ -0,0 +1,239 @@
#include "drv_venc_osal.h"
#include "hi_drv_mem.h"
#include <asm/uaccess.h>
#define MAX_BUFFER_SIZE (10*1024)
char *g_sbuf = NULL;
int g_venc_node_num = 0;
struct semaphore g_VencMemSem;
venc_mem_buf g_venc_mem_node[MAX_KMALLOC_MEM_NODE];
VENC_SMMU_ERR_ADDR g_smmu_err_mem;
int DRV_MEM_INIT(void)
{
char *sbuf;
int s32Ret;
MEM_BUFFER_S MEM_SMMU_RD_ADDR;
MEM_BUFFER_S MEM_SMMU_WR_ADDR;
HiVENC_INIT_MUTEX(&g_VencMemSem);
sbuf = HiMemVAlloc(MAX_BUFFER_SIZE);
if (!sbuf) {
HI_FATAL_VENC("call vmalloc failed\n");
return HI_FAILURE;
}
HiMemSet((void *)&g_venc_mem_node, 0, MAX_KMALLOC_MEM_NODE*sizeof(g_venc_mem_node[0]));
HiMemSet((void *)&g_smmu_err_mem, 0, sizeof(g_smmu_err_mem));
HiMemSet((void *)&MEM_SMMU_RD_ADDR, 0, sizeof(MEM_BUFFER_S));
HiMemSet((void *)&MEM_SMMU_WR_ADDR, 0, sizeof(MEM_BUFFER_S));
MEM_SMMU_RD_ADDR.u32Size = SMMU_RWERRADDR_SIZE;
s32Ret = DRV_MEM_KAlloc("SMMU_RDERR", "OMXVENC", &MEM_SMMU_RD_ADDR);
if (s32Ret != HI_SUCCESS ) {
HI_ERR_VENC("SMMU_RDERR alloc failed\n");
goto err_sbuf_exit;
}
MEM_SMMU_WR_ADDR.u32Size = SMMU_RWERRADDR_SIZE;
s32Ret = DRV_MEM_KAlloc("SMMU_WRERR", "OMXVENC", &MEM_SMMU_WR_ADDR);
if (s32Ret != HI_SUCCESS ) {
HI_ERR_VENC("SMMU_WRERR alloc failed\n");
goto err_rd_smmu_exit;
}
g_smmu_err_mem.RdAddr = MEM_SMMU_RD_ADDR.u64StartPhyAddr;//config alloc phyaddr,in order system don't dump
g_smmu_err_mem.WrAddr = MEM_SMMU_WR_ADDR.u64StartPhyAddr;
g_sbuf = sbuf;
HiMemSet((void *)g_sbuf, 0, MAX_BUFFER_SIZE);
return HI_SUCCESS;
err_rd_smmu_exit:
DRV_MEM_KFree(&MEM_SMMU_RD_ADDR);
err_sbuf_exit:
HiMemVFree(sbuf);
return HI_FAILURE;
}
int DRV_MEM_EXIT(void)
{
int i;
if (g_sbuf) {
HiMemVFree(g_sbuf);
g_sbuf = NULL;
}
/* Exit kfree mem for register's VEDU_COMN1_REGS.COMN1_SMMU_ERR_RDADDRR*/
for (i = 0; i < MAX_KMALLOC_MEM_NODE; i++) {
if (g_venc_mem_node[i].virt_addr != NULL) {
kfree(g_venc_mem_node[i].virt_addr);
HiMemSet(&g_venc_mem_node[i], 0, sizeof(g_venc_mem_node[i]));
}
}
g_venc_node_num = 0;
return HI_SUCCESS;
}
/* kalloc */
int DRV_MEM_KAlloc(const char* bufName, const char *zone_name, MEM_BUFFER_S *psMBuf)
{
unsigned int i;
int ret = HI_FAILURE;
void *virt_addr = NULL;
if (psMBuf == NULL || psMBuf->u32Size == 0) {
HI_FATAL_VENC("invalid Param, psMBuf is NULL or size is zero\n");
return ret;
}
if (HiVENC_DOWN_INTERRUPTIBLE(&g_VencMemSem)) {
HI_FATAL_VENC("Kalloc, down_interruptible failed\n");
return ret;
}
for (i = 0; i < MAX_KMALLOC_MEM_NODE; i++) {
if ((0 == g_venc_mem_node[i].phys_addr) && (g_venc_mem_node[i].virt_addr == NULL)) {
break;
}
}
if (i == MAX_KMALLOC_MEM_NODE) {
HI_FATAL_VENC("No free ion mem node\n");
goto err_exit;
}
virt_addr = kmalloc(psMBuf->u32Size, GFP_KERNEL | GFP_DMA);/*lint !e747*/
if (IS_ERR_OR_NULL(virt_addr)) {
HI_FATAL_VENC("call kzalloc failed, size : %d\n", psMBuf->u32Size);
goto err_exit;
}
memset(virt_addr, 0, psMBuf->u32Size); /* unsafe_function_ignore: memset */ /*lint !e668*/
psMBuf->pStartVirAddr = virt_addr;
psMBuf->u64StartPhyAddr = __pa(virt_addr);/*lint !e648 !e834 !e712*/
snprintf(g_venc_mem_node[i].node_name, MAX_MEM_NAME_LEN, "%s", bufName); /* unsafe_function_ignore: snprintf */
snprintf(g_venc_mem_node[i].zone_name, MAX_MEM_NAME_LEN, "%s", zone_name); /* unsafe_function_ignore: snprintf */
g_venc_mem_node[i].virt_addr = psMBuf->pStartVirAddr;
g_venc_mem_node[i].phys_addr = psMBuf->u64StartPhyAddr;
g_venc_mem_node[i].size = psMBuf->u32Size;
g_venc_node_num++;
ret = HI_SUCCESS;
err_exit:
HiVENC_UP_INTERRUPTIBLE(&g_VencMemSem);
return ret; /*lint !e593*/
} /*lint !e593*/
/* kfree */
int DRV_MEM_KFree(const MEM_BUFFER_S *psMBuf)
{
unsigned int i;
int ret = HI_FAILURE;
if (NULL == psMBuf || psMBuf->pStartVirAddr == NULL || psMBuf->u64StartPhyAddr == 0) {
HI_FATAL_VENC("invalid Parameters\n");
return ret;
}
if (HiVENC_DOWN_INTERRUPTIBLE(&g_VencMemSem)) {
HI_FATAL_VENC("Kfree, down interruptible failed\n");
return ret;
}
for (i=0; i<MAX_KMALLOC_MEM_NODE; i++) {
if ((psMBuf->u64StartPhyAddr == g_venc_mem_node[i].phys_addr) &&
(psMBuf->pStartVirAddr == g_venc_mem_node[i].virt_addr))
{
break;
}
}
if(i == MAX_KMALLOC_MEM_NODE) {
HI_FATAL_VENC("No free ion mem node\n");
goto err_exit;
}
kfree(g_venc_mem_node[i].virt_addr);
HiMemSet(&g_venc_mem_node[i], 0, sizeof(g_venc_mem_node[i]));/*lint !e866 */
g_venc_node_num = (g_venc_node_num > 0)?(g_venc_node_num-1):0;
ret = HI_SUCCESS;
err_exit:
HiVENC_UP_INTERRUPTIBLE(&g_VencMemSem);
return ret;
}
int HI_DRV_UserCopy(struct file *file, unsigned int cmd, unsigned long arg,
long (*func)(struct file *file, unsigned int cmd, unsigned long uarg))
{
//HI_CHAR sbuf[768];
void *parg = NULL;
int err = -EINVAL;
/* Copy arguments into temp kernel buffer */
if (!(void __user*)arg) {
HI_FATAL_VENC("arg is NULL\n");
goto out;
}
if (_IOC_SIZE(cmd) <= MAX_BUFFER_SIZE) {
parg = g_sbuf;
} else {
HI_FATAL_VENC("cmd size is too long\n");
goto out;
}
if (!parg) {
HI_FATAL_VENC("parg is NULL\n");
goto out;
}
err = -EFAULT;
if (_IOC_DIR(cmd) & _IOC_WRITE) {
if (copy_from_user(parg, (void __user*)arg, _IOC_SIZE(cmd))) {/*lint !e747 */
HI_FATAL_VENC("copy_from_user failed, cmd value is 0x%x\n", cmd);
goto out;
}
}
/* call driver */
err = func(file, cmd, (long)(parg)); /*lint !e732 !e712*/
if (err == -ENOIOCTLCMD)
err = -EINVAL;
if (err < 0)
goto out;
/* Copy results into user buffer */
switch (_IOC_DIR(cmd)) {
case _IOC_READ:
case (_IOC_WRITE | _IOC_READ):
if (copy_to_user((void __user *)arg, parg, _IOC_SIZE(cmd))) {/*lint !e747 */
HI_FATAL_VENC("copy_to_user failed, cmd value is 0x%x\n", cmd);
err = -EFAULT;
}
break;
default:
goto out;
}
out:
return err;
}
+72
View File
@@ -0,0 +1,72 @@
/*
* Copyright (C), 2001-2011, Hisilicon Tech. Co., Ltd.
*
* File Name : hi_type.h
* Version : Initial Draft
* Author : Hisilicon multimedia software group
* Created : 2005/4/23
*
* Last Modified :
* Description : The common data type defination
* Function List :
*
* History :
* 1.Date : 2008/06/28
* Author : c42025
* Modification: modified definition for HI_S8
*
* 2.Date : 2008/10/31
* Author : z44949
* Modification: Translate the chinese comment
*/
#ifndef __HI_DRV_MEM_H__
#define __HI_DRV_MEM_H__
#include "drv_venc.h"
#include <linux/seq_file.h>
#include <linux/vmalloc.h>
#include <linux/hisi/hisi_ion.h>
#define MAX_MEM_NAME_LEN (15)
#define MAX_KMALLOC_MEM_NODE (16) /*1 channel need 2 node ,there is have max 8 channels*/
#define MAX_ION_MEM_NODE (200)
#define SMMU_RWERRADDR_SIZE (128)
typedef struct {
unsigned long long RdAddr; // HI_U64
unsigned long long WrAddr; // HI_U64
} VENC_SMMU_ERR_ADDR;
typedef struct {
void *pStartVirAddr;
unsigned long long u64StartPhyAddr; // HI_U64
unsigned int u32Size;
unsigned char u8IsMapped;
unsigned int u32ShareFd;
} MEM_BUFFER_S;
typedef struct {
char node_name[MAX_MEM_NAME_LEN];
char zone_name[MAX_MEM_NAME_LEN];
void* virt_addr;
unsigned long long phys_addr; // HI_U64
unsigned int size;
struct ion_handle *handle;
} venc_mem_buf;
/***********************************************************************************
memory menage relative functions
***********************************************************************************/
int HI_DRV_UserCopy(struct file *file, unsigned int cmd, unsigned long arg, long (*func)(struct file *file, unsigned int cmd, unsigned long uarg));
/**************************************platform.h**************************************************/
int DRV_MEM_INIT(void);
int DRV_MEM_EXIT(void);
int DRV_MEM_KAlloc(const char* bufName, const char *zone_name, MEM_BUFFER_S *psMBuf);
int DRV_MEM_KFree(const MEM_BUFFER_S *psMBuf);
/**************************************************************************************/
#endif /* __HI_DRV_MEM_H__ */
+275
View File
@@ -0,0 +1,275 @@
#include <linux/clk.h>
#include <linux/of_irq.h>
#include <linux/of_address.h>
#include <linux/regulator/consumer.h>
#include <linux/hisi/hisi-iommu.h>
#include "venc_regulator.h"
#include "drv_venc_osal.h"
#include "drv_venc.h"
#define VENC_CLK_RATE "enc_clk_rate"
#define VENC_REGULATOR_NAME "ldo_venc"
#define MEDIA_REGULATOR_NAME "ldo_media"
#define VENC_CLOCK_NAME "clk_gate_vencfreq"
static struct clk *g_PvencClk = NULL;
struct iommu_domain *g_hisi_mmu_domain = NULL;
static VeduEfl_DTS_CONFIG_S g_VencDtsConfig;
static VENC_CLK_TYPE g_currClk = VENC_CLK_RATE_LOW;
static unsigned int g_vencQosMode = 0x2;
static int g_VencPowerOn = 0;
/*lint -e838 -e747 -e774 -e845*/
static int Venc_Enable_Iommu(struct platform_device *pdev)
{
struct iommu_domain *hisi_domain = NULL;
struct iommu_domain_data* domain_data = NULL;
struct device *dev = NULL;
//uint64_t phy_pgd_base = 0;
int ret = HI_FAILURE;
if ((!pdev ) || (!(&pdev->dev))){
HI_ERR_VENC("%s, invalid Parameters\n", __func__);
return HI_FAILURE;
}
dev = &pdev->dev;
hisi_domain = iommu_domain_alloc(dev->bus);
if (!hisi_domain) {
HI_ERR_VENC("%s, iommu_domain_alloc failed\n", __func__);
return HI_FAILURE;
}
ret = iommu_attach_device(hisi_domain, dev);
if (ret){
HI_ERR_VENC("iommu_attach_device failed\n");
goto out_free_domain;
}
g_hisi_mmu_domain = hisi_domain;
domain_data = (struct iommu_domain_data *)(g_hisi_mmu_domain->priv);
if (domain_data == NULL){
//pCtx->phy_pgd_base = (uint64_t)(domain_data->phy_pgd_base);
//}else{
goto out_detach_device;
}
return HI_SUCCESS;
out_detach_device:
iommu_detach_device(g_hisi_mmu_domain, dev);
out_free_domain:
iommu_domain_free(hisi_domain);
return HI_FAILURE;
}
static int Venc_Disable_Iommu(struct platform_device *pdev)
{
if( g_hisi_mmu_domain && pdev) {
iommu_detach_device(g_hisi_mmu_domain, &pdev->dev);
iommu_domain_free(g_hisi_mmu_domain);
g_hisi_mmu_domain = NULL;
return HI_SUCCESS;
}
return HI_FAILURE;
}
static int Venc_GetDtsConfigInfo(struct platform_device *pdev, VeduEfl_DTS_CONFIG_S *pDtsConfig)
{
unsigned int rate_h = 0;
unsigned int rate_n = 0;
unsigned int rate_l = 0;
int ret = HI_FAILURE;
struct resource res;
struct clk *pvenc_clk = NULL;
struct device_node *np = NULL;
struct device *dev = &pdev->dev;
struct iommu_domain_data *domain_data = NULL;
if (!dev) {
HI_FATAL_VENC("invalid argument, dev is NULL\n");
return HI_FAILURE;
}
np = dev->of_node;
HiMemSet(&res, 0, sizeof(res));
if ((!np) || (!pDtsConfig)) {
HI_FATAL_VENC("invalid argument np or pDtsConfig is NULL\n");
return HI_FAILURE;
}
/* 1 read IRQ num from dts */
pDtsConfig->VeduIrqNumNorm = irq_of_parse_and_map(np, 0);
if (pDtsConfig->VeduIrqNumNorm == 0) {
HI_FATAL_VENC("parse and map irq VeduIrqNumNorm failed\n");
return HI_FAILURE;
}
pDtsConfig->VeduIrqNumProt = irq_of_parse_and_map(np, 1);
if (pDtsConfig->VeduIrqNumProt == 0) {
HI_FATAL_VENC("parse and map irq VeduIrqNumProt failed\n");
return HI_FAILURE;
}
pDtsConfig->VeduIrqNumSafe = irq_of_parse_and_map(np, 2);
if (pDtsConfig->VeduIrqNumSafe == 0) {
HI_FATAL_VENC("parse and map irq VeduIrqNumSafe failed\n");
return HI_FAILURE;
}
/* 2 read venc register start address, range */
ret = of_address_to_resource(np, 0, &res);
if (ret) {
HI_FATAL_VENC("address to resource failed, ret value is %d\n", ret);
return HI_FAILURE;
}
pDtsConfig->VencRegBaseAddr = res.start;/*lint !e712 */
pDtsConfig->VencRegRange = resource_size(&res);/*lint !e712 */
/* 3 read venc clk rate [low, high], venc clock */
pvenc_clk = devm_clk_get(dev, VENC_CLOCK_NAME);
if (IS_ERR_OR_NULL(pvenc_clk)) {
HI_FATAL_VENC("can not get venc clock, pvenc_clk is 0x%pK\n", pvenc_clk);
return HI_FAILURE;
}
g_PvencClk = pvenc_clk;
ret = of_property_read_u32_index(np, VENC_CLK_RATE, 0, &rate_h);
ret += of_property_read_u32_index(np, VENC_CLK_RATE, 1, &rate_n);
ret += of_property_read_u32_index(np, VENC_CLK_RATE, 2, &rate_l);
if (ret) {
HI_FATAL_VENC("can not get venc rate, return %d\n", ret);
return HI_FAILURE;
}
pDtsConfig->highRate = rate_h;
pDtsConfig->normalRate = rate_n;
pDtsConfig->lowRate = rate_l;
HI_INFO_VENC("venc_clk_rate: highRate:%u, normalRate:%u, lowRate:%u\n", pDtsConfig->highRate, pDtsConfig->normalRate, pDtsConfig->lowRate);
/* 4 get venc qos mode */
ret = of_property_read_u32(np, "venc_qos_mode", &g_vencQosMode);
if (ret) {
g_vencQosMode = 0x2;
HI_ERR_VENC("get venc qos mode failed set default\n");
}
domain_data = (struct iommu_domain_data *)(g_hisi_mmu_domain->priv);
if (domain_data) {
pDtsConfig->SmmuPageBaseAddr = (uint64_t)(domain_data->phy_pgd_base);
HI_INFO_VENC("SmmuPageBaseAddr is 0x%pK\n", __func__, pDtsConfig->SmmuPageBaseAddr);
}
return HI_SUCCESS;
}
int Venc_Regulator_Init(struct platform_device *pdev)
{
int ret = 0;
if (!pdev) {
HI_FATAL_VENC("invalid argument\n");
return HI_FAILURE;
}
/* 1 create smmu domain */
ret = Venc_Enable_Iommu(pdev);
if (ret < 0) {
HI_FATAL_VENC("enable venc iommu failed\n");
return HI_FAILURE;
}
/* 2 read venc dts info from dts */
HiMemSet(&g_VencDtsConfig, 0, sizeof(VeduEfl_DTS_CONFIG_S));
ret = Venc_GetDtsConfigInfo(pdev, &g_VencDtsConfig);
if (ret != HI_SUCCESS) {
HI_FATAL_VENC("get venc DTS config info failed\n");
return HI_FAILURE;
}
/* 3 set dts into to efi */
ret = VENC_SetDtsConfig(&g_VencDtsConfig);
if (ret != HI_SUCCESS) {
HI_FATAL_VENC("set venc DTS config info failed\n");
return HI_FAILURE;
}
return HI_SUCCESS;
}
void Venc_Regulator_Deinit(struct platform_device *pdev)
{
if (pdev)
Venc_Disable_Iommu(pdev);
}
int Venc_Regulator_Enable(void)
{
int ret = HI_FAILURE;
if (1 == g_VencPowerOn) {
return HI_SUCCESS;
}
if(IS_ERR_OR_NULL(g_PvencClk)) {
HI_FATAL_VENC("invalid_argument g_PvencClk:0x%pK\n",
g_PvencClk);
return HI_FAILURE;
}
ret = clk_prepare_enable(g_PvencClk);
if (ret != 0) {
HI_FATAL_VENC("prepare clk enable failed\n");
return HI_FAILURE;
}
ret = clk_set_rate(g_PvencClk, g_VencDtsConfig.lowRate);
if(ret != 0) {
HI_FATAL_VENC("set clk low rate failed\n");
goto on_error_prepare_clk;
}
g_currClk = VENC_CLK_RATE_LOW;
ret = clk_set_rate(g_PvencClk, g_VencDtsConfig.lowRate);
if(ret != 0) {
HI_FATAL_VENC("set clk low rate failed\n");
goto on_error_prepare_clk;
}
g_VencPowerOn = 1;
HI_INFO_VENC("++\n");
return HI_SUCCESS;
on_error_prepare_clk:
clk_disable_unprepare(g_PvencClk);
return HI_FAILURE;
}
int Venc_Regulator_Disable(void)
{
int ret = HI_FAILURE;
HI_INFO_VENC("Venc_Regulator_Disable\n");
if (0 == g_VencPowerOn) {
return HI_SUCCESS;
}
if(IS_ERR_OR_NULL(g_PvencClk)) {
HI_FATAL_VENC("invalid_argument g_PvencClk:0x%pK\n",g_PvencClk);
return HI_FAILURE;
}
ret = clk_set_rate(g_PvencClk, g_VencDtsConfig.lowRate);
if(ret != 0) {
HI_ERR_VENC("set clk lowrate:%u failed\n", g_VencDtsConfig.lowRate);
//return HI_FAILURE;//continue, no need return
}
g_currClk = VENC_CLK_RATE_LOW;
clk_disable_unprepare(g_PvencClk);
g_VencPowerOn = 0;
HI_INFO_VENC("--\n");
return HI_SUCCESS;
}/*lint !e715 */
+12
View File
@@ -0,0 +1,12 @@
#ifndef __VENC_REGULATOR_H__
#define __VENC_REGULATOR_H__
#include "drv_venc.h"
#include <linux/fs.h>
#include <linux/platform_device.h>
int Venc_Regulator_Init(struct platform_device *pdev);
void Venc_Regulator_Deinit(struct platform_device *pdev);
int Venc_Regulator_Enable(void);
int Venc_Regulator_Disable(void);
#endif