4914 lines
132 KiB
C
4914 lines
132 KiB
C
// SPDX-License-Identifier: GPL-2.0
|
|
/*
|
|
* Copyright (c) 2015 MediaTek Inc.
|
|
*/
|
|
|
|
#include <linux/types.h>
|
|
#include <linux/device.h>
|
|
#include <linux/cdev.h>
|
|
#include <linux/platform_device.h>
|
|
#include <linux/interrupt.h>
|
|
#include <linux/slab.h>
|
|
#include <linux/spinlock.h>
|
|
#include <linux/delay.h>
|
|
#include <linux/uaccess.h>
|
|
#include <linux/atomic.h>
|
|
#include <linux/sched.h>
|
|
#include <linux/sched/clock.h>
|
|
#include <linux/mm.h>
|
|
#include <linux/seq_file.h>
|
|
#include <linux/dma-mapping.h>
|
|
#include <linux/pm_runtime.h>
|
|
#include <linux/dma-buf.h>
|
|
|
|
#include "camera_mfb.h"
|
|
#include "engine_request.h"
|
|
|
|
#include <linux/of_platform.h>
|
|
#include <linux/of_irq.h>
|
|
#include <linux/of_address.h>
|
|
|
|
#include <linux/soc/mediatek/mtk-cmdq-ext.h>
|
|
#if IS_ENABLED(CONFIG_MTK_CMDQ_MBOX_EXT)
|
|
#include <cmdq-util.h>
|
|
#endif
|
|
#include <soc/mediatek/smi.h>
|
|
|
|
#define TODO
|
|
#ifndef TODO
|
|
#define MFB_PMQOS
|
|
#endif
|
|
#ifdef MFB_PMQOS
|
|
#include <linux/pm_qos.h>
|
|
#include <mmdvfs_pmqos.h>
|
|
#endif
|
|
|
|
#define USE_SW_TOKEN
|
|
|
|
//#define __MFB_EP_NO_CLKMGR__
|
|
/* #define BYPASS_REG */
|
|
/* Measure the kernel performance */
|
|
/* #define __MFB_KERNEL_PERFORMANCE_MEASURE__ */
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
#include <linux/met_drv.h>
|
|
#include <linux/mtk_ftrace.h>
|
|
#endif
|
|
|
|
#include <linux/module.h>
|
|
#include <linux/kernel.h>
|
|
#include <linux/init.h>
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
/* 64 bit */
|
|
#include <linux/fs.h>
|
|
#include <linux/compat.h>
|
|
#endif
|
|
|
|
#ifdef MFB_USE_WAKELOCK
|
|
#include <linux/pm_wakeup.h>
|
|
#endif
|
|
|
|
/*GKI*/
|
|
#define CHECK_SERVICE_IF_0 0
|
|
#define CHECK_SERVICE_IF_1 1
|
|
|
|
#define CMDQ_COMMON
|
|
#define CLK_COMMON
|
|
|
|
#undef CONFIG_COMPAT
|
|
/* CCF */
|
|
#ifndef __MFB_EP_NO_CLKMGR__
|
|
#if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) /*CCF*/
|
|
#include <linux/clk.h>
|
|
#if (MTK_MFB_REG_VERSION == 3)
|
|
struct MFB_CLK_STRUCT {
|
|
struct clk *CG_IMG2_LARB11;
|
|
struct clk *CG_IMG2_MSS;
|
|
struct clk *CG_IMG2_MFB;
|
|
struct clk *CG_IMG2_GALS;
|
|
struct clk *CG_IMG1_GALS;
|
|
};
|
|
struct MFB_CLK_STRUCT mfb_clk;
|
|
#elif (MTK_MFB_REG_VERSION == 2)
|
|
struct MFB_CLK_STRUCT {
|
|
struct clk *CG_IMG2_LARB11;
|
|
struct clk *CG_IMG2_MSS;
|
|
struct clk *CG_IMG2_MFB;
|
|
struct clk *CG_IMG2_GALS;
|
|
};
|
|
struct MFB_CLK_STRUCT mfb_clk;
|
|
#else
|
|
struct MFB_CLK_STRUCT {
|
|
struct clk *CG_IMG1_LARB9;
|
|
struct clk *CG_IMG1_MSS;
|
|
struct clk *CG_IMG1_MFB;
|
|
};
|
|
struct MFB_CLK_STRUCT mfb_clk;
|
|
#endif
|
|
#endif /* !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) */
|
|
#endif
|
|
|
|
#ifndef MTRUE
|
|
#define MTRUE 1
|
|
#endif
|
|
#ifndef MFALSE
|
|
#define MFALSE 0
|
|
#endif
|
|
|
|
#define MFB_DEV_NAME "camera-mfb"
|
|
|
|
/* #define MFB_WAITIRQ_LOG */
|
|
#define MFB_USE_GCE
|
|
/* #define MFB_DEBUG_USE */
|
|
/*I can' test the situation in FPGA, because the velocity of FPGA is so slow. */
|
|
#define MyTag "[MFB]"
|
|
#define IRQTag "KEEPER"
|
|
|
|
#define LOG_VRB(format, args...) pr_debug(MyTag format, ##args)
|
|
|
|
#ifdef MFB_DEBUG_USE
|
|
#define LOG_DBG(format, args...) pr_info(MyTag format, ##args)
|
|
#else
|
|
#define LOG_DBG(format, args...)
|
|
#endif
|
|
|
|
#define LOG_INF(format, args...) pr_info(MyTag format, ##args)
|
|
#define LOG_NOTICE(format, args...) pr_notice(MyTag format, ##args)
|
|
#define LOG_WRN(format, args...) pr_info(MyTag format, ##args)
|
|
#define LOG_ERR(format, args...) pr_info(MyTag format, ##args)
|
|
#define LOG_AST(format, args...) pr_info(MyTag format, ##args)
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
/* #define MFB_WR32(addr, data) iowrite32(data, addr) // For other projects. */
|
|
/* For 89 Only. // NEED_TUNING_BY_PROJECT */
|
|
#define MFB_WR32(addr, data) writel(data, addr)
|
|
#define MFB_RD32(addr) readl(addr)
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
/* dynamic log level *//*YWtodo*/
|
|
#define MFB_DBG_DBGLOG (0x00000001)
|
|
#define MFB_DBG_INFLOG (0x00000002)
|
|
#define MFB_DBG_INT (0x00000004)
|
|
#define MFB_DBG_READ_REG (0x00000008)
|
|
#define MFB_DBG_WRITE_REG (0x00000010)
|
|
#define MFB_DBG_TASKLET (0x00000020)
|
|
|
|
|
|
/* ///////////////////////////////////////////////////////////////// */
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
|
|
/* CAM interrupt status */
|
|
/* IRQ signal mask */
|
|
|
|
#define INT_ST_MASK_MSS ( \
|
|
MSS_INT_ST)
|
|
#define INT_ST_MASK_MSF ( \
|
|
MSF_INT_ST)
|
|
|
|
#define CMDQ_REG_MASK 0xffffffff
|
|
|
|
static irqreturn_t ISP_Irq_MSS(signed int Irq, void *DeviceId);
|
|
static irqreturn_t ISP_Irq_MSF(signed int Irq, void *DeviceId);
|
|
static void MFB_ScheduleMssWork(struct work_struct *data);
|
|
static void vmss_do_work(struct work_struct *data);
|
|
static void MFB_ScheduleMsfWork(struct work_struct *data);
|
|
static void vmsf_do_work(struct work_struct *data);
|
|
static signed int MSS_DumpReg(void);
|
|
static signed int MSF_DumpReg(void);
|
|
|
|
typedef irqreturn_t(*IRQ_CB) (signed int, void *);
|
|
|
|
struct ISR_TABLE {
|
|
IRQ_CB isr_fp;
|
|
unsigned int int_number;
|
|
char device_name[16];
|
|
};
|
|
|
|
#ifndef CONFIG_OF
|
|
const struct ISR_TABLE MFB_IRQ_CB_TBL[MFB_IRQ_TYPE_AMOUNT] = {
|
|
{ISP_Irq_MSS, MSS_IRQ_BIT_ID, "mss"},
|
|
{ISP_Irq_MSF, MSF_IRQ_BIT_ID, "msf"},
|
|
};
|
|
|
|
#else
|
|
/* int number is got from kernel api */
|
|
const struct ISR_TABLE MFB_IRQ_CB_TBL[MFB_IRQ_TYPE_AMOUNT] = {
|
|
{ISP_Irq_MSS, 0, "mss"},
|
|
{ISP_Irq_MSF, 0, "msf"},
|
|
};
|
|
|
|
#endif
|
|
/* ////////////////////////////////////////////////////////////////////////// */
|
|
|
|
typedef void (*tasklet_cb) (unsigned long);
|
|
struct Tasklet_table {
|
|
tasklet_cb tkt_cb;
|
|
struct tasklet_struct *pMFB_tkt;
|
|
};
|
|
|
|
struct tasklet_struct Mfbtkt[MFB_IRQ_TYPE_AMOUNT];
|
|
|
|
static void ISP_TaskletFunc_MSS(unsigned long data);
|
|
static void ISP_TaskletFunc_MSF(unsigned long data);
|
|
|
|
static struct Tasklet_table MFB_tasklet[MFB_IRQ_TYPE_AMOUNT] = {
|
|
{ISP_TaskletFunc_MSS, &Mfbtkt[MFB_IRQ_TYPE_INT_MSS_ST]},
|
|
{ISP_TaskletFunc_MSF, &Mfbtkt[MFB_IRQ_TYPE_INT_MSF_ST]},
|
|
};
|
|
static struct work_struct logWork;
|
|
static void logPrint(struct work_struct *data);
|
|
|
|
struct wakeup_source MSS_wake_lock;
|
|
struct wakeup_source MSF_wake_lock;
|
|
|
|
static DEFINE_MUTEX(gMfbMssMutex);
|
|
static DEFINE_MUTEX(gMfbMssDequeMutex);
|
|
|
|
static DEFINE_MUTEX(gMfbMsfMutex);
|
|
static DEFINE_MUTEX(gMfbMsfDequeMutex);
|
|
|
|
static DEFINE_MUTEX(MutexMFBRef);
|
|
static DEFINE_MUTEX(Mutexgkibuf); //gki
|
|
#ifdef CONFIG_OF
|
|
|
|
struct MFB_device {
|
|
void __iomem *regs;
|
|
struct device *dev;
|
|
int irq;
|
|
struct device *larb;
|
|
};
|
|
|
|
static struct MFB_device *MFB_devs;
|
|
static int nr_MFB_devs;
|
|
|
|
static struct device *MFB_cmdq_dev;
|
|
static struct cmdq_client *mss_clt, *msf_clt;
|
|
static u16 mss_done_event_id, msf_done_event_id;
|
|
static u16 mss_token_id, msf_token_id;
|
|
|
|
|
|
/* Get HW modules' base address from device nodes */
|
|
#define MSS_DEV_NODE_IDX 1
|
|
#define MSF_DEV_NODE_IDX 0
|
|
#define IMGSYS_DEV_MODE_IDX 2
|
|
|
|
/* static unsigned long gISPSYS_Reg[MFB_IRQ_TYPE_AMOUNT]; */
|
|
|
|
|
|
#define ISP_MSS_BASE (MFB_devs[MSS_DEV_NODE_IDX].regs)
|
|
#define ISP_MSF_BASE (MFB_devs[MSF_DEV_NODE_IDX].regs)
|
|
#define ISP_IMGSYS_BASE (MFB_devs[IMGSYS_DEV_MODE_IDX].regs)
|
|
/* #define ISP_MFB_BASE (gISPSYS_Reg[MFB_DEV_NODE_IDX]) */
|
|
|
|
#else
|
|
#define ISP_MSS_BASE (0x15012000)/*YWtodo*/
|
|
#define ISP_MSF_BASE (0x15010000)/*YWtodo*/
|
|
|
|
#endif
|
|
|
|
|
|
static unsigned int g_u4EnableClockCount;
|
|
static unsigned int g_SuspendCnt;
|
|
|
|
/* maximum number for supporting user to do interrupt operation */
|
|
/* index 0 is for all the user that do not do register irq first */
|
|
#define IRQ_USER_NUM_MAX 31
|
|
#define GKI_BUF_NUM_MAX 200
|
|
|
|
#ifdef MFB_PMQOS
|
|
static struct pm_qos_request mfb_pmqos_request;
|
|
static u64 max_img_freq[4];
|
|
struct plist_head module_request_list; /* all module list */
|
|
struct mm_qos_request mfb_mmqos_request;
|
|
|
|
static spinlock_t SpinLockMfbPmqos;
|
|
static unsigned int qos_scen[4];
|
|
static unsigned int qos_total;
|
|
#endif
|
|
|
|
struct MSS_CONFIG_STRUCT {
|
|
struct MFB_MSSConfig MssFrameConfig[_SUPPORT_MAX_MFB_FRAME_REQUEST_];
|
|
struct MFB_MSSConfig vMssFrameConfig[_SUPPORT_MAX_MFB_FRAME_REQUEST_];
|
|
};
|
|
|
|
static struct MSS_CONFIG_STRUCT g_MssEnqueReq_Struct;
|
|
static struct MSS_CONFIG_STRUCT g_MssDequeReq_Struct;
|
|
|
|
struct MSF_CONFIG_STRUCT {
|
|
struct MFB_MSFConfig MsfFrameConfig[_SUPPORT_MAX_MFB_FRAME_REQUEST_];
|
|
};
|
|
|
|
static struct MSF_CONFIG_STRUCT g_MsfEnqueReq_Struct;
|
|
static struct MSF_CONFIG_STRUCT g_MsfDequeReq_Struct;
|
|
|
|
static struct engine_requests mss_reqs;
|
|
static struct engine_requests vmss_reqs;
|
|
static struct MFB_MSSRequest kMssReq;
|
|
static struct engine_requests msf_reqs;
|
|
static struct engine_requests vmsf_reqs;
|
|
static struct MFB_MSFRequest kMsfReq;
|
|
|
|
//gki
|
|
struct gki_buf {
|
|
unsigned int isUse;
|
|
unsigned int bfd;
|
|
struct dma_buf *dma_buf;
|
|
struct dma_buf_attachment *attach;
|
|
struct sg_table *sgt;
|
|
};
|
|
static int qq_get_cnt;
|
|
static int qq_put_cnt;
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
enum MFB_PROCESS_ID_ENUM {
|
|
MFB_PROCESS_ID_NONE,
|
|
MFB_PROCESS_ID_MSS,
|
|
MFB_PROCESS_ID_vMSS,
|
|
MFB_PROCESS_ID_MSF,
|
|
MFB_PROCESS_ID_vMSF,
|
|
MFB_PROCESS_ID_AMOUNT
|
|
};
|
|
|
|
struct MFB_USER_INFO_STRUCT {
|
|
pid_t Pid;
|
|
pid_t Tid;
|
|
struct engine_requests *reqs;
|
|
enum MFB_PROCESS_ID_ENUM streamtag;
|
|
struct gki_buf gkiBuf[GKI_BUF_NUM_MAX]; /* gki */
|
|
};
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
struct MFB_IRQ_INFO_STRUCT {
|
|
unsigned int Status[MFB_IRQ_TYPE_AMOUNT];
|
|
signed int MssIrqCnt[IRQ_USER_NUM_MAX];
|
|
signed int MssIrqUse[IRQ_USER_NUM_MAX];
|
|
signed int MsfIrqCnt[IRQ_USER_NUM_MAX];
|
|
pid_t ProcessID[IRQ_USER_NUM_MAX];
|
|
pid_t ProcessFD[IRQ_USER_NUM_MAX];
|
|
unsigned int Mask[MFB_IRQ_TYPE_AMOUNT];
|
|
};
|
|
|
|
struct MFB_INFO_STRUCT {
|
|
spinlock_t SpinLockMFB;
|
|
spinlock_t SpinLockIrq[MFB_IRQ_TYPE_AMOUNT];
|
|
wait_queue_head_t WaitQueueHeadMss;
|
|
wait_queue_head_t WaitQueueHeadMsf;
|
|
struct work_struct ScheduleMssWork;
|
|
struct work_struct vmsswork;
|
|
struct work_struct ScheduleMsfWork;
|
|
struct work_struct vmsfwork;
|
|
struct workqueue_struct *wkqueueMss;
|
|
struct workqueue_struct *wkqueueMsf;
|
|
unsigned int UserCount; /* User Count */
|
|
unsigned int DebugMaskMss; /* Debug Mask */
|
|
unsigned int DebugMaskMsf; /* Debug Mask */
|
|
struct MFB_IRQ_INFO_STRUCT IrqInfo;
|
|
};
|
|
|
|
static struct MFB_INFO_STRUCT MFBInfo;
|
|
|
|
enum _eLOG_TYPE {
|
|
_LOG_DBG = 0, /* currently, only used at ipl_buf_ctrl.
|
|
* to protect critical section
|
|
*/
|
|
_LOG_INF = 1,
|
|
_LOG_ERR = 2,
|
|
_LOG_MAX = 3,
|
|
};
|
|
|
|
#define NORMAL_STR_LEN (512)
|
|
#define ERR_PAGE 2
|
|
#define DBG_PAGE 2
|
|
#define INF_PAGE 4
|
|
/* #define SV_LOG_STR_LEN NORMAL_STR_LEN */
|
|
|
|
#define LOG_PPNUM 2
|
|
static unsigned int m_CurrentPPB;
|
|
struct SV_LOG_STR {
|
|
unsigned int _cnt[LOG_PPNUM][_LOG_MAX];
|
|
/* char _str[_LOG_MAX][SV_LOG_STR_LEN]; */
|
|
char *_str[LOG_PPNUM][_LOG_MAX];
|
|
};
|
|
|
|
static void *pLog_kmalloc;
|
|
static struct SV_LOG_STR gSvLog[MFB_IRQ_TYPE_AMOUNT];
|
|
|
|
/* for irq used,keep log until IRQ_LOG_PRINTER being involked, */
|
|
/* limited: */
|
|
/* each log must shorter than 512 bytes */
|
|
/* total log length in each irq/logtype can't over 1024 bytes */
|
|
|
|
#define IRQ_LOG_KEEPER(irq, ppb, logT, fmt, ...) do {\
|
|
char *ptr; \
|
|
char *pDes;\
|
|
int avaLen;\
|
|
unsigned int *ptr2 = &gSvLog[irq]._cnt[ppb][logT];\
|
|
unsigned int str_leng;\
|
|
unsigned int logi;\
|
|
struct SV_LOG_STR *pSrc = &gSvLog[irq];\
|
|
if (logT == _LOG_ERR) {\
|
|
str_leng = NORMAL_STR_LEN*ERR_PAGE; \
|
|
} else if (logT == _LOG_DBG) {\
|
|
str_leng = NORMAL_STR_LEN*DBG_PAGE; \
|
|
} else if (logT == _LOG_INF) {\
|
|
str_leng = NORMAL_STR_LEN*INF_PAGE;\
|
|
} else {\
|
|
str_leng = 0;\
|
|
} \
|
|
ptr = pDes = (char *)&(gSvLog[irq].\
|
|
_str[ppb][logT][gSvLog[irq].\
|
|
_cnt[ppb][logT]]); \
|
|
avaLen = str_leng - 1 - gSvLog[irq]._cnt[ppb][logT];\
|
|
if (avaLen > 1) {\
|
|
snprintf((char *)(pDes), avaLen, fmt,\
|
|
##__VA_ARGS__); \
|
|
if ('\0' != gSvLog[irq]._str[ppb][logT][str_leng - 1]) {\
|
|
LOG_ERR("log str over flow(%d)", irq);\
|
|
} \
|
|
while (*ptr++ != '\0') { \
|
|
(*ptr2)++;\
|
|
} \
|
|
} else { \
|
|
LOG_INF("(%d)(%d)log str avalible=0, print log\n", irq, logT);\
|
|
ptr = pSrc->_str[ppb][logT];\
|
|
if (pSrc->_cnt[ppb][logT] != 0) {\
|
|
if (logT == _LOG_DBG) {\
|
|
for (logi = 0; logi < DBG_PAGE; logi++) {\
|
|
if (ptr[NORMAL_STR_LEN*(logi+1) - 1] !=\
|
|
'\0') {\
|
|
ptr[NORMAL_STR_LEN*(logi+1)\
|
|
- 1] = '\0';\
|
|
LOG_DBG("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
} else {\
|
|
LOG_DBG("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else if (logT == _LOG_INF) {\
|
|
for (logi = 0; logi < INF_PAGE; logi++) {\
|
|
if (ptr[NORMAL_STR_LEN*(logi+1) - 1] !=\
|
|
'\0') {\
|
|
ptr[NORMAL_STR_LEN*(logi+1)\
|
|
- 1] = '\0';\
|
|
LOG_INF("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
} else {\
|
|
LOG_INF("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else if (logT == _LOG_ERR) {\
|
|
for (logi = 0; logi < ERR_PAGE; logi++) {\
|
|
if (ptr[NORMAL_STR_LEN*(logi+1) - 1] !=\
|
|
'\0') {\
|
|
ptr[NORMAL_STR_LEN*(logi+1)\
|
|
- 1] = '\0';\
|
|
LOG_INF("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
} else {\
|
|
LOG_INF("%s",\
|
|
&ptr[NORMAL_STR_LEN*logi]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else {\
|
|
LOG_INF("N.S.%d", logT);\
|
|
} \
|
|
ptr[0] = '\0';\
|
|
pSrc->_cnt[ppb][logT] = 0;\
|
|
avaLen = str_leng - 1;\
|
|
ptr = pDes = (char *)&(\
|
|
pSrc->_str[ppb][logT][pSrc->_cnt[ppb][logT]]);\
|
|
ptr2 = &(pSrc->_cnt[ppb][logT]);\
|
|
snprintf((char *)(pDes), avaLen, fmt, ##__VA_ARGS__);\
|
|
while (*ptr++ != '\0') {\
|
|
(*ptr2)++;\
|
|
} \
|
|
} \
|
|
} \
|
|
} while (0)
|
|
|
|
#define IRQ_LOG_PRINTER(irq, ppb_in, logT_in) do {\
|
|
struct SV_LOG_STR *pSrc = &gSvLog[irq];\
|
|
char *ptr;\
|
|
unsigned int i;\
|
|
signed int ppb = 0;\
|
|
signed int logT = 0;\
|
|
if (ppb_in > 1) {\
|
|
ppb = 1;\
|
|
} else {\
|
|
ppb = ppb_in;\
|
|
} \
|
|
if (logT_in > _LOG_ERR) {\
|
|
logT = _LOG_ERR;\
|
|
} else {\
|
|
logT = logT_in;\
|
|
} \
|
|
ptr = pSrc->_str[ppb][logT];\
|
|
if (pSrc->_cnt[ppb][logT] != 0) {\
|
|
if (logT == _LOG_DBG) {\
|
|
for (i = 0; i < DBG_PAGE; i++) {\
|
|
if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\
|
|
ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\
|
|
LOG_DBG("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
} else {\
|
|
LOG_DBG("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else if (logT == _LOG_INF) {\
|
|
for (i = 0; i < INF_PAGE; i++) {\
|
|
if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\
|
|
ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\
|
|
LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
} else {\
|
|
LOG_INF("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else if (logT == _LOG_ERR) {\
|
|
for (i = 0; i < ERR_PAGE; i++) {\
|
|
if (ptr[NORMAL_STR_LEN*(i+1) - 1] != '\0') {\
|
|
ptr[NORMAL_STR_LEN*(i+1) - 1] = '\0';\
|
|
LOG_ERR("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
} else {\
|
|
LOG_ERR("%s", &ptr[NORMAL_STR_LEN*i]);\
|
|
break;\
|
|
} \
|
|
} \
|
|
} \
|
|
else {\
|
|
LOG_ERR("N.S.%d", logT);\
|
|
} \
|
|
ptr[0] = '\0';\
|
|
pSrc->_cnt[ppb][logT] = 0;\
|
|
} \
|
|
} while (0)
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
#define IMGSYS_REG_CG_CON (ISP_IMGSYS_BASE + 0x0)
|
|
#define IMGSYS_REG_CG_SET (ISP_IMGSYS_BASE + 0x4)
|
|
#define IMGSYS_REG_CG_CLR (ISP_IMGSYS_BASE + 0x8)
|
|
#define IMGSYS_REG_SW_RST (ISP_IMGSYS_BASE + 0xc)
|
|
|
|
#define MFB_MSS_INT_STATUS_REG (ISP_MSS_BASE + 0x508)
|
|
#define MFB_MSF_INT_STATUS_REG (ISP_MSF_BASE + 0x7c8)
|
|
|
|
#define MFB_MSS_TDRI_BASE_REG (ISP_MSS_BASE + 0x804)
|
|
#define MFB_MSF_TDRI_BASE_REG (ISP_MSF_BASE + 0x804)
|
|
|
|
#define MFB_MSS_TDRI_OFST_REG (ISP_MSS_BASE + 0x808)
|
|
#define MFB_MSF_TDRI_OFST_REG (ISP_MSF_BASE + 0x808)
|
|
|
|
#define MFB_MSS_CMDQ_BASE_ADDR_REG (ISP_MSS_BASE + 0x500)
|
|
#define MFB_MSF_CMDQ_BASE_ADDR_REG (ISP_MSF_BASE + 0x7C0)
|
|
|
|
#define MFB_MSS_CQLP_CMD_NUM_REG (ISP_MSS_BASE + 0x600)
|
|
#define MFB_MSF_CQLP_CMD_NUM_REG (ISP_MSF_BASE + 0x7F0)
|
|
|
|
#define MSSTOP_DMA_STOP_REG (ISP_MSS_BASE + 0x414)
|
|
#define MSSTOP_DMA_STOP_STA_REG (ISP_MSS_BASE + 0x418)
|
|
|
|
#define MFBTOP_DMA_STOP_REG (ISP_MSF_BASE + 0x4A4)
|
|
#define MFBTOP_DMA_STOP_STA_REG (ISP_MSF_BASE + 0x4A8)
|
|
#define MFBTOP_RESET_REG (ISP_MSF_BASE + 0x4AC)
|
|
#define MFB_MSF_CMDQ_ENABLE_REG (ISP_MSF_BASE + 0x7C4)
|
|
|
|
#define MFB_MSF_TOP_DEBUG_SEL (ISP_MSF_BASE + 0x4D0)
|
|
#define MFB_MSF_TOP_DEBUG_STA (ISP_MSF_BASE + 0x4D4)
|
|
#define MFB_MSF_DMA_DEBUG_SEL (ISP_MSF_BASE + 0x888)
|
|
#define MFB_MSF_TOP_CRC_1 (ISP_MSF_BASE + 0x4CC)
|
|
|
|
#define MFB_MSS_TOP_DBG_CTL0 (ISP_MSS_BASE + 0x434)
|
|
#define MFB_MSS_TOP_DBG_OUT2 (ISP_MSS_BASE + 0x440)
|
|
#define MFB_MSS_TOP_DBG_OUT3 (ISP_MSS_BASE + 0x444)
|
|
#define MFB_MSS_DMA_DEBUG_SEL (ISP_MSS_BASE + 0x888)
|
|
|
|
#if (MTK_MFB_REG_VERSION >= 2)
|
|
#define MSS_BASE 0x15812000
|
|
#define MSF_BASE 0x15810000
|
|
#else
|
|
#define MSS_BASE 0x15012000
|
|
#define MSF_BASE 0x15010000
|
|
#endif
|
|
|
|
#define MFB_MSS_INT_STATUS_HW (MSS_BASE + 0x508)
|
|
#define MFB_MSF_INT_STATUS_HW (MSF_BASE + 0x7c8)
|
|
|
|
#define ISP_MSS_BASE_HW (MSS_BASE + 0x000)
|
|
#define ISP_MSF_BASE_HW (MSF_BASE + 0x000)
|
|
|
|
#define MFB_MSS_START_HW (MSS_BASE + 0x50c)
|
|
#define MFB_MSF_START_HW (MSF_BASE + 0x7cc)
|
|
|
|
#define MFB_MSS_INT_STA_HW (MSS_BASE + 0x508)
|
|
#define MFB_MSF_INT_STA_HW (MSF_BASE + 0x7c8)
|
|
|
|
#define MFB_MSS_CMDQ_ENABLE_HW (MSS_BASE + 0x504)
|
|
#define MFB_MSF_CMDQ_ENABLE_HW (MSF_BASE + 0x7C4)
|
|
|
|
#define MFB_MSS_CMDQ_BASE_ADDR_HW (MSS_BASE + 0x500)
|
|
#define MFB_MSF_CMDQ_BASE_ADDR_HW (MSF_BASE + 0x7C0)
|
|
|
|
#define MFB_MSS_CQLP_CMD_NUM_HW (MSS_BASE + 0x600)
|
|
#define MFB_MSF_CQLP_CMD_NUM_HW (MSF_BASE + 0x7F0)
|
|
|
|
#define MFB_MSS_CQLP_ENG_EN_HW (MSS_BASE + 0x604)
|
|
#define MFB_MSF_CQLP_ENG_EN_HW (MSF_BASE + 0x7F4)
|
|
|
|
#define MFB_MSS_TDRI_BASE_HW (MSS_BASE + 0x804)
|
|
#define MFB_MSS_TDRI_OFST_HW (MSS_BASE + 0x808)
|
|
#define MFB_MSF_TDRI_BASE_HW (MSF_BASE + 0x804)
|
|
#define MFB_MSF_TDRI_OFST_HW (MSF_BASE + 0x808)
|
|
|
|
#define MFB_MSS_IY_BASE_HW (MSS_BASE + 0xA00)
|
|
#define MFB_MSS_IC_BASE_HW (MSS_BASE + 0xA40)
|
|
#define MFB_MSS_OY_BASE_HW (MSS_BASE + 0x900)
|
|
#define MFB_MSS_OC_BASE_HW (MSS_BASE + 0x940)
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline unsigned int MFB_MsToJiffies(unsigned int Ms)
|
|
{
|
|
return ((Ms * HZ + 512) >> 10);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline unsigned int MFB_UsToJiffies(unsigned int Us)
|
|
{
|
|
return (((Us / 1000) * HZ + 512) >> 10);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline unsigned int MSS_GetIRQState(
|
|
unsigned int type, unsigned int *userNumber, unsigned int stus,
|
|
enum MFB_PROCESS_ID_ENUM whichReq, int ProcessID)
|
|
{
|
|
unsigned int ret = 0;
|
|
unsigned int p;
|
|
unsigned long flags; /* old: unsigned int flags;*/
|
|
/* FIX to avoid build warning */
|
|
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[type]), flags);
|
|
if (stus & MSS_INT_ST) {
|
|
LOG_DBG("%s MssIrqCnt[%d] is %d for pid %d", __func__,
|
|
p,
|
|
MFBInfo.IrqInfo.MssIrqCnt[p],
|
|
MFBInfo.IrqInfo.ProcessID[p]);
|
|
ret = ((MFBInfo.IrqInfo.MssIrqCnt[p] > 0)
|
|
&& (MFBInfo.IrqInfo.ProcessID[p] == ProcessID));
|
|
} else {
|
|
LOG_ERR(
|
|
"WaitIRQ Status Error, type:%d, userNumber:%d, status:%d, whichReq:%d, ProcessID:0x%x\n",
|
|
type, *userNumber, stus, p, ProcessID);
|
|
}
|
|
*userNumber = ret;
|
|
if (ret == 1 && MFBInfo.IrqInfo.MssIrqCnt[p] == 1) {
|
|
LOG_DBG("%s last mssirqcnt %d clearing pid %d for proc %d",
|
|
__func__,
|
|
MFBInfo.IrqInfo.MssIrqCnt[p],
|
|
MFBInfo.IrqInfo.ProcessID[p],
|
|
p);
|
|
MFBInfo.IrqInfo.ProcessID[p] = 0;
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[type]), flags);
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline unsigned int MSF_GetIRQState(
|
|
unsigned int type, unsigned int userNumber, unsigned int stus,
|
|
enum MFB_PROCESS_ID_ENUM whichReq, int ProcessID)
|
|
{
|
|
unsigned int ret = 0;
|
|
unsigned int p;
|
|
unsigned long flags; /* old: unsigned int flags;*/
|
|
/* FIX to avoid build warning */
|
|
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[type]), flags);
|
|
if (stus & MSF_INT_ST) {
|
|
LOG_DBG("%s MsfIrqCnt is %d for pid %d", __func__,
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p],
|
|
MFBInfo.IrqInfo.ProcessFD[p]);
|
|
ret = ((MFBInfo.IrqInfo.MsfIrqCnt[p] > 0)
|
|
&& (MFBInfo.IrqInfo.ProcessFD[p] == ProcessID));
|
|
} else {
|
|
LOG_ERR(
|
|
"WaitIRQ Status Error, type:%d, userNumber:%d, status:%d, whichReq:%d, ProcessID:0x%x\n",
|
|
type, userNumber, stus, p, ProcessID);
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[type]), flags);
|
|
if (ret == 1) {
|
|
LOG_DBG("%s last msfirqcnt %d not clearing pid %d for proc %d",
|
|
__func__,
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p],
|
|
MFBInfo.IrqInfo.ProcessFD[p],
|
|
p);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline unsigned int MFB_JiffiesToMs(unsigned int Jiffies)
|
|
{
|
|
return ((Jiffies * 1000) / HZ);
|
|
}
|
|
|
|
#ifdef MFB_PMQOS
|
|
void MFBQOS_Init(void)
|
|
{
|
|
s32 result = 0;
|
|
u64 img_freq_steps[MAX_FREQ_STEP];
|
|
u32 step_size;
|
|
|
|
/* Call pm_qos_add_request when initialize module or driver prob */
|
|
pm_qos_add_request(
|
|
&mfb_pmqos_request,
|
|
PM_QOS_IMG_FREQ,
|
|
PM_QOS_MM_FREQ_DEFAULT_VALUE);
|
|
|
|
/* Call mmdvfs_qos_get_freq_steps to get supported frequency */
|
|
result = mmdvfs_qos_get_freq_steps(
|
|
PM_QOS_IMG_FREQ,
|
|
img_freq_steps,
|
|
&step_size);
|
|
|
|
if (result < 0 || step_size == 0)
|
|
LOG_INF("get MMDVFS freq steps failed, result: %d\n", result);
|
|
else {
|
|
max_img_freq[0] = img_freq_steps[0];
|
|
max_img_freq[1] = img_freq_steps[1];
|
|
max_img_freq[2] = img_freq_steps[2];
|
|
max_img_freq[3] = img_freq_steps[3];
|
|
}
|
|
|
|
/* Initialize owner list */
|
|
plist_head_init(&module_request_list);
|
|
|
|
/* Call mm_qos_add_request */
|
|
/* when initialize module or driver prob */
|
|
#if (MTK_MFB_REG_VERSION >= 2)
|
|
mm_qos_add_request(&module_request_list,
|
|
&mfb_mmqos_request, M4U_PORT_L11_IMG_MFB_RDMA0);
|
|
#else
|
|
mm_qos_add_request(&module_request_list,
|
|
&mfb_mmqos_request, M4U_PORT_L9_IMG_MFB_RDMA0_MDP);
|
|
#endif
|
|
}
|
|
|
|
void MFBQOS_Uninit(void)
|
|
{
|
|
pm_qos_remove_request(&mfb_pmqos_request);
|
|
|
|
/* Call mm_qos_remove_request */
|
|
/* when de-initialize module or driver remove */
|
|
mm_qos_remove_all_request(&module_request_list);
|
|
}
|
|
|
|
void MFBQOS_Update(bool start, unsigned int scen, unsigned long bw)
|
|
{
|
|
LOG_DBG("start: %d, MFB scen: %d, bw: %lu", start, scen, bw);
|
|
if (start) { /* start MFB, configure MMDVFS to highest CLK */
|
|
LOG_DBG("MFB total: %ld", qos_total);
|
|
spin_lock(&(SpinLockMfbPmqos));
|
|
if (bw != 0)
|
|
qos_scen[scen] = bw;
|
|
qos_total = qos_total + bw;
|
|
if (qos_total > 600000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[0]);
|
|
} else if (qos_total > 300000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[1]);
|
|
} else if (qos_total > 100000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[2]);
|
|
} else {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request, 0);
|
|
}
|
|
} else { /* finish MFB, config MMDVFS to lowest CLK */
|
|
LOG_DBG("MFB total: %ld", qos_total);
|
|
spin_lock(&(SpinLockMfbPmqos));
|
|
qos_total = qos_total - qos_scen[scen];
|
|
if (qos_total > 600000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[0]);
|
|
} else if (qos_total > 300000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[1]);
|
|
} else if (qos_total > 100000000) {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request,
|
|
max_img_freq[2]);
|
|
} else {
|
|
spin_unlock(&(SpinLockMfbPmqos));
|
|
pm_qos_update_request(&mfb_pmqos_request, 0);
|
|
}
|
|
}
|
|
#if CHECK_SERVICE_IF_0 /*YWtodo*/
|
|
if (start) {
|
|
/* Call mm_qos_set_request API to setup estimated data bw */
|
|
mm_qos_set_request(&mfb_mmqos_request,
|
|
bw/1000000, 0, BW_COMP_NONE);
|
|
/* Call mm_qos_update_all_requests API */
|
|
/* update necessary HW configuration for MM BW */
|
|
mm_qos_update_all_request(&module_request_list);
|
|
} else {
|
|
mm_qos_set_request(&mfb_mmqos_request, 0, 0, BW_COMP_NONE);
|
|
mm_qos_update_all_request(&module_request_list);
|
|
}
|
|
#endif
|
|
}
|
|
#endif
|
|
|
|
#if CHECK_SERVICE_IF_0/*YWtodo*/
|
|
static int cmdq_engine_secured(struct cmdqRecStruct *handle,
|
|
enum CMDQ_ENG_ENUM engine)
|
|
{
|
|
cmdqRecSetSecure(handle, 1);
|
|
cmdqRecSecureEnablePortSecurity(handle, (1LL << engine));
|
|
cmdqRecSecureEnableDAPC(handle, (1LL << engine));
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
/*TODO : M4U_PORT */
|
|
#if CHECK_SERVICE_IF_0
|
|
static int cmdq_sec_base(struct cmdqRecStruct *handle, unsigned int dma_sec,
|
|
unsigned int reg, unsigned int val, unsigned int size)
|
|
{
|
|
if (dma_sec != 0)
|
|
cmdqRecWriteSecure(handle, reg, CMDQ_SAM_H_2_MVA, val, 0, size,
|
|
M4U_PORT_MFB_RDMA);
|
|
else
|
|
cmdqRecWrite(handle, reg, val, CMDQ_REG_MASK);
|
|
|
|
return 0;
|
|
}
|
|
#endif
|
|
|
|
static int mfb_get_dma_buf(struct gki_buf *gbf, int fd)
|
|
{
|
|
struct dma_buf *buf;
|
|
|
|
buf = dma_buf_get(fd);
|
|
if (IS_ERR(buf))
|
|
return -1;
|
|
|
|
gbf->dma_buf = buf;
|
|
gbf->attach = dma_buf_attach(gbf->dma_buf, MFB_devs[0].dev);
|
|
if (IS_ERR(gbf->attach))
|
|
goto err_attach;
|
|
|
|
gbf->sgt = dma_buf_map_attachment(gbf->attach, DMA_BIDIRECTIONAL);
|
|
if (IS_ERR(gbf->sgt))
|
|
goto err_map;
|
|
LOG_DBG("QQ get_dma: dma_buf=%p, attach=%p, sgt=%p", gbf->dma_buf, gbf->attach, gbf->sgt);
|
|
return 0;
|
|
|
|
err_map:
|
|
dma_buf_detach(gbf->dma_buf, gbf->attach);
|
|
err_attach:
|
|
dma_buf_put(gbf->dma_buf);
|
|
|
|
return -1;
|
|
}
|
|
|
|
static void mfb_put_dma_buf(struct gki_buf *gbf)
|
|
{
|
|
LOG_DBG("QX put_dma: dma_buf=%p, attach=%p, sgt=%p", gbf->dma_buf, gbf->attach, gbf->sgt);
|
|
dma_buf_unmap_attachment(gbf->attach, gbf->sgt, DMA_BIDIRECTIONAL);
|
|
dma_buf_detach(gbf->dma_buf, gbf->attach);
|
|
dma_buf_put(gbf->dma_buf);
|
|
}
|
|
|
|
static void mss_pkt_tcmds(struct cmdq_pkt *handle,
|
|
struct MFB_MSSConfig *pMssConfig)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
unsigned int t;
|
|
|
|
if (pMssConfig->tpipe_used > TPIPE_NUM_PER_FRAME) {
|
|
pMssConfig->tpipe_used = TPIPE_NUM_PER_FRAME;
|
|
LOG_ERR("tpipe_used %d over limit of %d",
|
|
pMssConfig->tpipe_used, TPIPE_NUM_PER_FRAME);
|
|
}
|
|
|
|
/* fixed 0x0000 0001: [0] MSS, [1] P2*/
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CQLP_ENG_EN_HW,
|
|
pMssConfig->MSSCQLP_ENG_EN, CMDQ_REG_MASK);
|
|
for (t = 0; t < pMssConfig->tpipe_used; t++) {
|
|
/* cq */
|
|
if (pMssConfig->MSSCMDQ_BASE[t] == 0) {
|
|
LOG_ERR("tpipe_used = %d MSSCMDQ_BASE = 0",
|
|
pMssConfig->tpipe_used);
|
|
break;
|
|
}
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CMDQ_ENABLE_HW,
|
|
pMssConfig->MSSCMDQ_ENABLE[t], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_CMDQ_BASE_ADDR_HW,
|
|
pMssConfig->MSSCMDQ_BASE[t], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_CQLP_CMD_NUM_HW,
|
|
pMssConfig->MSSCQLP_CMD_NUM[t], CMDQ_REG_MASK);
|
|
/* tdr */
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_TDRI_BASE_HW,
|
|
pMssConfig->MSSDMT_TDRI_BASE[t], CMDQ_REG_MASK);
|
|
|
|
/* I/O */
|
|
if (pMssConfig->update_dma_en[t] == 1) {
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_IY_BASE_HW,
|
|
pMssConfig->dmas[t].MSSDMT_IY_BASE,
|
|
CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_IC_BASE_HW,
|
|
pMssConfig->dmas[t].MSSDMT_IC_BASE,
|
|
CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_OY_BASE_HW,
|
|
pMssConfig->dmas[t].MSSDMT_OY_BASE,
|
|
CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSS_OC_BASE_HW,
|
|
pMssConfig->dmas[t].MSSDMT_OC_BASE,
|
|
CMDQ_REG_MASK);
|
|
}
|
|
/* start */
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_START_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
/* wfe */
|
|
cmdq_pkt_wfe(handle, mss_done_event_id);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_INT_STA_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
LOG_DBG("MSS_CMDQ_ENABLE%d = 0x%x", t,
|
|
pMssConfig->MSSCMDQ_ENABLE[t]);
|
|
LOG_DBG("MSSCMDQ_BASE%d = 0x%x", t,
|
|
pMssConfig->MSSCMDQ_BASE[t]);
|
|
LOG_DBG("MSSCQLP_CMD_NUM%d = 0x%x", t,
|
|
pMssConfig->MSSCQLP_CMD_NUM[t]);
|
|
LOG_DBG("MSSDMT_TDRI_BASE%d = 0x%x", t,
|
|
pMssConfig->MSSDMT_TDRI_BASE[t]);
|
|
}
|
|
LOG_DBG("%s: tpipe_used is %d", __func__, pMssConfig->tpipe_used);
|
|
LOG_INF("mss cmdq write done %d", pMssConfig->tpipe_used);
|
|
#endif
|
|
}
|
|
|
|
static void mss_norm_sirq(struct cmdq_cb_data data)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct cmdq_pkt *pkt;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
unsigned long flag;
|
|
unsigned int p = 0;
|
|
|
|
pkt = (struct cmdq_pkt *) data.data;
|
|
if (data.err < 0) {
|
|
mfb_request_dump(&mss_reqs);
|
|
MSS_DumpReg();
|
|
LOG_ERR("%s_mss: call back error(%d)", __func__, data.err);
|
|
goto EXIT;
|
|
}
|
|
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flag);
|
|
if (mfb_update_request(&mss_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
queue_work(MFBInfo.wkqueueMss, &MFBInfo.ScheduleMssWork);
|
|
#endif
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSS_ST] |= MSS_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessID[p] = ProcessID;
|
|
MFBInfo.IrqInfo.MssIrqCnt[p]++;
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flag);
|
|
if (bResulst == MTRUE) {
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(0, 0, 0);
|
|
#endif
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMss);
|
|
}
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_INF,
|
|
"%s: bResulst:%d, MssIrqCnt[%d]:0x%x\n",
|
|
__func__, bResulst, p,
|
|
MFBInfo.IrqInfo.MssIrqCnt[p]);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
queue_work(MFBInfo.wkqueueMss, &MFBInfo.ScheduleMssWork);
|
|
#endif
|
|
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSS_ST].pMFB_tkt);
|
|
EXIT:
|
|
cmdq_pkt_destroy(pkt);
|
|
#endif
|
|
}
|
|
|
|
signed int CmdqMSSHW(struct frame *frame)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct MFB_MSSConfig *pMssConfig;
|
|
struct cmdq_pkt *handle;
|
|
|
|
if (frame == NULL || frame->data == NULL)
|
|
return -1;
|
|
|
|
LOG_DBG("%s request sent to CMDQ driver", __func__);
|
|
pMssConfig = (struct MFB_MSSConfig *) frame->data;
|
|
|
|
if (MFB_DBG_DBGLOG == (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMss))
|
|
LOG_DBG("ConfigMSSHW Start!\n");
|
|
|
|
/*cmdq_pkt_cl_create(&handle, mss_clt);*/
|
|
handle = cmdq_pkt_create(mss_clt);
|
|
|
|
handle->priority = 20;
|
|
|
|
/*if (pMssConfig->eng_secured == 1)*//*YWtodo*/
|
|
/*cmdq_engine_secured(handle, CMDQ_ENG_MSS);*/
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_acquire_event(handle, mss_token_id);
|
|
#endif
|
|
#define TPIPE_MODE_PREVIEW
|
|
#ifdef TPIPE_MODE_PREVIEW
|
|
mss_pkt_tcmds(handle, pMssConfig);
|
|
#else
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CMDQ_ENABLE_HW,
|
|
pMssConfig->MSSCMDQ_ENABLE[0], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CMDQ_BASE_ADDR_HW,
|
|
pMssConfig->MSSCMDQ_BASE[0], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CQLP_CMD_NUM_HW,
|
|
pMssConfig->MSSCQLP_CMD_NUM[0], CMDQ_REG_MASK);
|
|
/* fixed 0x0000 0001: [0] MSS, [1] P2*/
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_CQLP_ENG_EN_HW,
|
|
pMssConfig->MSSCQLP_ENG_EN, CMDQ_REG_MASK);
|
|
#ifndef BYPASS_REG
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSS_START_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
cmdq_pkt_wfe(handle, mss_done_event_id);
|
|
/* non-blocking API, Please use cmdqRecFlushAsync() */
|
|
#endif
|
|
#endif
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_clear_event(handle, mss_token_id);
|
|
#endif
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(1, 0, pMssConfig->qos);
|
|
#endif
|
|
cmdq_pkt_flush_threaded(handle, mss_norm_sirq, (void *)handle);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
signed int mss_enque_cb(struct frame *frames, void *req)
|
|
{
|
|
unsigned int f, fcnt;
|
|
struct MFB_MSSRequest *_req;
|
|
struct MFB_MSSConfig *pcfg;
|
|
|
|
_req = (struct MFB_MSSRequest *) req;
|
|
|
|
if (frames == NULL || _req == NULL)
|
|
return -1;
|
|
|
|
fcnt = _req->m_ReqNum;
|
|
for (f = 0; f < fcnt; f++) {
|
|
LOG_DBG("[%s]request enque frame(%d/%d) 0x%p",
|
|
__func__, f, fcnt, frames[f].data);
|
|
memcpy(frames[f].data, &_req->m_pMssConfig[f],
|
|
sizeof(struct MFB_MSSConfig));
|
|
pcfg = &_req->m_pMssConfig[f];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
signed int mss_deque_cb(struct frame *frames, void *req)
|
|
{
|
|
unsigned int f, fcnt;
|
|
struct MFB_MSSRequest *_req;
|
|
struct MFB_MSSConfig *pcfg;
|
|
|
|
_req = (struct MFB_MSSRequest *) req;
|
|
|
|
if (frames == NULL || _req == NULL)
|
|
return -1;
|
|
|
|
fcnt = _req->m_ReqNum;
|
|
for (f = 0; f < fcnt; f++) {
|
|
memcpy(&_req->m_pMssConfig[f], frames[f].data,
|
|
sizeof(struct MFB_MSSConfig));
|
|
LOG_DBG("[%s]request deque frame(%d/%d).", __func__, f, fcnt);
|
|
pcfg = &_req->m_pMssConfig[f];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void mss_vss_sirq(struct cmdq_cb_data data)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct cmdq_pkt *pkt;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
unsigned long flag;
|
|
unsigned int p = 0;
|
|
|
|
pkt = (struct cmdq_pkt *) data.data;
|
|
if (data.err < 0) {
|
|
mfb_request_dump(&vmss_reqs);
|
|
MSS_DumpReg();
|
|
LOG_ERR("%s_mss: call back error(%d)", __func__, data.err);
|
|
goto EXIT;
|
|
}
|
|
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flag);
|
|
if (mfb_update_request(&vmss_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
queue_work(MFBInfo.wkqueueMss, &MFBInfo.vmsswork);
|
|
#endif
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSS_ST] |= MSS_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessID[p] = ProcessID;
|
|
MFBInfo.IrqInfo.MssIrqCnt[p]++;
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flag);
|
|
if (bResulst == MTRUE) {
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(0, 1, 0);
|
|
#endif
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMss);
|
|
}
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_INF,
|
|
"%s: bResulst:%d, MssIrqCnt[%d]:0x%x\n",
|
|
__func__, bResulst, p,
|
|
MFBInfo.IrqInfo.MssIrqCnt[p]);
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSS_ST].pMFB_tkt);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
queue_work(MFBInfo.wkqueueMss, &MFBInfo.vmsswork);
|
|
#endif
|
|
EXIT:
|
|
cmdq_pkt_destroy(pkt);
|
|
#endif
|
|
}
|
|
|
|
signed int vCmdqMSSHW(struct frame *frame)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct MFB_MSSConfig *pMssConfig;
|
|
struct cmdq_pkt *handle;
|
|
|
|
if (frame == NULL || frame->data == NULL)
|
|
return -1;
|
|
|
|
LOG_DBG("%s request sent to CMDQ driver", __func__);
|
|
pMssConfig = (struct MFB_MSSConfig *) frame->data;
|
|
|
|
if (MFB_DBG_DBGLOG == (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMss))
|
|
LOG_DBG("ConfigMSSHW Start!\n");
|
|
|
|
/*cmdq_pkt_cl_create(&handle, mss_clt);*/
|
|
handle = cmdq_pkt_create(mss_clt);
|
|
handle->priority = 0;
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_acquire_event(handle, mss_token_id);
|
|
#endif
|
|
mss_pkt_tcmds(handle, pMssConfig);
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_clear_event(handle, mss_token_id);
|
|
#endif
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(1, 1, pMssConfig->qos);
|
|
#endif
|
|
cmdq_pkt_flush_threaded(handle, mss_vss_sirq, (void *)handle);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static const struct engine_ops mss_ops = {
|
|
.req_enque_cb = mss_enque_cb,
|
|
.req_deque_cb = mss_deque_cb,
|
|
.frame_handler = CmdqMSSHW,
|
|
.req_feedback_cb = NULL,
|
|
};
|
|
|
|
static const struct engine_ops vmss_ops = {
|
|
.req_enque_cb = mss_enque_cb,
|
|
.req_deque_cb = mss_deque_cb,
|
|
.frame_handler = vCmdqMSSHW,
|
|
.req_feedback_cb = NULL,
|
|
};
|
|
|
|
|
|
static void msf_pkt_tcmds(struct cmdq_pkt *handle,
|
|
struct MFB_MSFConfig *pMsfConfig)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
unsigned int t;
|
|
|
|
if (pMsfConfig->tpipe_used > TPIPE_NUM_PER_FRAME) {
|
|
pMsfConfig->tpipe_used = TPIPE_NUM_PER_FRAME;
|
|
LOG_ERR("tpipe_used %d over limit of %d",
|
|
pMsfConfig->tpipe_used, TPIPE_NUM_PER_FRAME);
|
|
}
|
|
|
|
/* fixed 0x0000 0001: [0] MSS, [1] P2*/
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CQLP_ENG_EN_HW,
|
|
pMsfConfig->MSFCQLP_ENG_EN, CMDQ_REG_MASK);
|
|
for (t = 0; t < pMsfConfig->tpipe_used; t++) {
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CMDQ_ENABLE_HW,
|
|
pMsfConfig->MSFCMDQ_ENABLE[t], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSF_CMDQ_BASE_ADDR_HW,
|
|
pMsfConfig->MSFCMDQ_BASE[t], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL,
|
|
(dma_addr_t)MFB_MSF_CQLP_CMD_NUM_HW,
|
|
pMsfConfig->MSFCQLP_CMD_NUM[t], CMDQ_REG_MASK);
|
|
/* tdr */
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_TDRI_BASE_HW,
|
|
pMsfConfig->MFBDMT_TDRI_BASE[t], CMDQ_REG_MASK);
|
|
/* start */
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_START_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
/* wfe */
|
|
cmdq_pkt_wfe(handle, msf_done_event_id);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_INT_STA_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
LOG_DBG("MSF_CMDQ_ENABLE%d = 0x%x", t,
|
|
pMsfConfig->MSFCMDQ_ENABLE[t]);
|
|
LOG_DBG("MSFCMDQ_BASE%d = 0x%x", t,
|
|
pMsfConfig->MSFCMDQ_BASE[t]);
|
|
LOG_DBG("MSFCQLP_CMD_NUM%d = 0x%x", t,
|
|
pMsfConfig->MSFCQLP_CMD_NUM[t]);
|
|
LOG_DBG("MSFDMT_TDRI_BASE%d = 0x%x", t,
|
|
pMsfConfig->MFBDMT_TDRI_BASE[t]);
|
|
}
|
|
LOG_DBG("%s: tpipe_used is %d", __func__, pMsfConfig->tpipe_used);
|
|
#endif
|
|
}
|
|
|
|
static void msf_norm_sirq(struct cmdq_cb_data data)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct cmdq_pkt *pkt;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
unsigned long flag;
|
|
unsigned int p = 0;
|
|
|
|
pkt = (struct cmdq_pkt *) data.data;
|
|
if (data.err < 0) {
|
|
mfb_request_dump(&msf_reqs);
|
|
MSF_DumpReg();
|
|
LOG_ERR("%s: call back error(%d)", __func__, data.err);
|
|
goto EXIT;
|
|
}
|
|
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flag);
|
|
if (mfb_update_request(&msf_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
queue_work(MFBInfo.wkqueueMsf, &MFBInfo.ScheduleMsfWork);
|
|
#endif
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSF_ST] |= MSF_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessFD[p] = ProcessID;
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p]++;
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flag);
|
|
if (bResulst == MTRUE) {
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(0, 2, 0);
|
|
#endif
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMsf);
|
|
}
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_INF,
|
|
"%s, bResulst:%d, MsfIrqCnt[%d]:0x%x\n",
|
|
__func__, bResulst, p, MFBInfo.IrqInfo.MsfIrqCnt[p]);
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSF_ST].pMFB_tkt);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
queue_work(MFBInfo.wkqueueMsf, &MFBInfo.ScheduleMsfWork);
|
|
#endif
|
|
EXIT:
|
|
cmdq_pkt_destroy(pkt);
|
|
#endif
|
|
}
|
|
|
|
signed int CmdqMSFHW(struct frame *frame)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct MFB_MSFConfig *pMsfConfig;
|
|
struct cmdq_pkt *handle;
|
|
|
|
if (frame == NULL || frame->data == NULL)
|
|
return -1;
|
|
|
|
LOG_DBG("%s request sent to CMDQ driver", __func__);
|
|
pMsfConfig = (struct MFB_MSFConfig *) frame->data;
|
|
|
|
if (MFB_DBG_DBGLOG == (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMsf))
|
|
LOG_DBG("ConfigMSFHW Start!\n");
|
|
|
|
/*cmdq_pkt_cl_create(&handle, msf_clt);*/
|
|
handle = cmdq_pkt_create(msf_clt);
|
|
|
|
/*if (pMssConfig->eng_secured == 1)*//*YWtodo*/
|
|
/*cmdq_engine_secured(handle, CMDQ_ENG_MSS);*/
|
|
handle->priority = 20;
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_acquire_event(handle, msf_token_id);
|
|
#endif
|
|
#ifdef TPIPE_MODE_PREVIEW
|
|
msf_pkt_tcmds(handle, pMsfConfig);
|
|
#else
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CMDQ_ENABLE_HW,
|
|
pMsfConfig->MSFCMDQ_ENABLE[0], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CMDQ_BASE_ADDR_HW,
|
|
pMsfConfig->MSFCMDQ_BASE[0], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CQLP_CMD_NUM_HW,
|
|
pMsfConfig->MSFCQLP_CMD_NUM[0], CMDQ_REG_MASK);
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_CQLP_ENG_EN_HW,
|
|
pMsfConfig->MSFCQLP_ENG_EN, CMDQ_REG_MASK);
|
|
|
|
#ifndef BYPASS_REG
|
|
cmdq_pkt_write(handle, NULL, (dma_addr_t)MFB_MSF_START_HW,
|
|
0x1, CMDQ_REG_MASK);
|
|
cmdq_pkt_wfe(handle, msf_done_event_id);
|
|
|
|
/* non-blocking API, Please use cmdqRecFlushAsync() */
|
|
#endif
|
|
#endif
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_clear_event(handle, msf_token_id);
|
|
#endif
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(1, 2, pMsfConfig->qos);
|
|
#endif
|
|
cmdq_pkt_flush_threaded(handle, msf_norm_sirq, (void *)handle);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
signed int msf_enque_cb(struct frame *frames, void *req)
|
|
{
|
|
unsigned int f, fcnt;
|
|
struct MFB_MSFRequest *_req;
|
|
struct MFB_MSFConfig *pcfg;
|
|
|
|
_req = (struct MFB_MSFRequest *) req;
|
|
|
|
if (frames == NULL || _req == NULL)
|
|
return -1;
|
|
|
|
fcnt = _req->m_ReqNum;
|
|
for (f = 0; f < fcnt; f++) {
|
|
memcpy(frames[f].data, &_req->m_pMsfConfig[f],
|
|
sizeof(struct MFB_MSFConfig));
|
|
pcfg = &_req->m_pMsfConfig[f];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
signed int msf_deque_cb(struct frame *frames, void *req)
|
|
{
|
|
unsigned int f, fcnt;
|
|
struct MFB_MSFRequest *_req;
|
|
struct MFB_MSFConfig *pcfg;
|
|
|
|
_req = (struct MFB_MSFRequest *) req;
|
|
|
|
if (frames == NULL || _req == NULL)
|
|
return -1;
|
|
|
|
fcnt = _req->m_ReqNum;
|
|
for (f = 0; f < fcnt; f++) {
|
|
memcpy(&_req->m_pMsfConfig[f], frames[f].data,
|
|
sizeof(struct MFB_MSFConfig));
|
|
LOG_DBG("[%s]request dequeued frame(%d/%d).",
|
|
__func__, f, fcnt);
|
|
pcfg = &_req->m_pMsfConfig[f];
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void msf_vss_sirq(struct cmdq_cb_data data)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct cmdq_pkt *pkt;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
unsigned long flag;
|
|
unsigned int p = 0;
|
|
|
|
pkt = (struct cmdq_pkt *) data.data;
|
|
if (data.err < 0) {
|
|
mfb_request_dump(&vmsf_reqs);
|
|
MSF_DumpReg();
|
|
LOG_ERR("%s: call back error(%d)", __func__, data.err);
|
|
goto EXIT;
|
|
}
|
|
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flag);
|
|
if (mfb_update_request(&vmsf_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
queue_work(MFBInfo.wkqueueMsf, &MFBInfo.vmsfwork);
|
|
#endif
|
|
p = ProcessID % IRQ_USER_NUM_MAX;
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSF_ST] |= MSF_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessFD[p] = ProcessID;
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p]++;
|
|
}
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flag);
|
|
if (bResulst == MTRUE) {
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(0, 3, 0);
|
|
#endif
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMsf);
|
|
}
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_INF,
|
|
"%s: bResulst:%d, MsfIrqCnt[%d]:0x%x\n",
|
|
__func__, bResulst, p, MFBInfo.IrqInfo.MsfIrqCnt[p]);
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSF_ST].pMFB_tkt);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
queue_work(MFBInfo.wkqueueMsf, &MFBInfo.vmsfwork);
|
|
#endif
|
|
EXIT:
|
|
cmdq_pkt_destroy(pkt);
|
|
#endif
|
|
}
|
|
|
|
signed int vCmdqMSFHW(struct frame *frame)
|
|
{
|
|
#ifdef CMDQ_COMMON
|
|
struct MFB_MSFConfig *pMsfConfig;
|
|
struct cmdq_pkt *handle;
|
|
|
|
if (frame == NULL || frame->data == NULL)
|
|
return -1;
|
|
|
|
LOG_DBG("%s request sent to CMDQ driver", __func__);
|
|
pMsfConfig = (struct MFB_MSFConfig *) frame->data;
|
|
|
|
if (MFB_DBG_DBGLOG == (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMsf))
|
|
LOG_DBG("ConfigMSFHW Start!\n");
|
|
|
|
/*cmdq_pkt_cl_create(&handle, msf_clt);*/
|
|
handle = cmdq_pkt_create(msf_clt);
|
|
handle->priority = 0;
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_acquire_event(handle, msf_token_id);
|
|
#endif
|
|
msf_pkt_tcmds(handle, pMsfConfig);
|
|
#ifdef USE_SW_TOKEN
|
|
cmdq_pkt_clear_event(handle, msf_token_id);
|
|
#endif
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Update(1, 3, pMsfConfig->qos);
|
|
#endif
|
|
cmdq_pkt_flush_threaded(handle, msf_vss_sirq, (void *)handle);
|
|
#endif
|
|
return 0;
|
|
}
|
|
|
|
static const struct engine_ops msf_ops = {
|
|
.req_enque_cb = msf_enque_cb,
|
|
.req_deque_cb = msf_deque_cb,
|
|
.frame_handler = CmdqMSFHW,
|
|
.req_feedback_cb = NULL,
|
|
};
|
|
|
|
static const struct engine_ops vmsf_ops = {
|
|
.req_enque_cb = msf_enque_cb,
|
|
.req_deque_cb = msf_deque_cb,
|
|
.frame_handler = vCmdqMSFHW,
|
|
.req_feedback_cb = NULL,
|
|
};
|
|
|
|
/*
|
|
*
|
|
*/
|
|
static signed int MSS_DumpReg(void)
|
|
{
|
|
signed int Ret = 0;
|
|
#ifdef CMDQ_COMMON
|
|
unsigned int i = 0;
|
|
|
|
cmdq_util_err("- E.");
|
|
cmdq_util_err("MSS Config Info\n");
|
|
if (g_u4EnableClockCount == 0)
|
|
return Ret;
|
|
for (i = 0; i < MSS_REG_RANGE; i = i + 0x10) {
|
|
cmdq_util_err(
|
|
"[0x%08X %08X][0x%08X %08X][0x%08X %08X][0x%08X %08X]",
|
|
ISP_MSS_BASE_HW + i + 0x0, MFB_RD32(ISP_MSS_BASE + i + 0x0),
|
|
ISP_MSS_BASE_HW + i + 0x4, MFB_RD32(ISP_MSS_BASE + i + 0x4),
|
|
ISP_MSS_BASE_HW + i + 0x8, MFB_RD32(ISP_MSS_BASE + i + 0x8),
|
|
ISP_MSS_BASE_HW + i + 0xC, MFB_RD32(ISP_MSS_BASE + i + 0xC));
|
|
}
|
|
#if CHECK_SERVICE_IF_0 /*YWtodo sel*/
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 1; j < 7; j++) {
|
|
MFB_WR32(MFB_MSS_DMA_DEBUG_SEL,
|
|
0x000F3F1F & ((i << 16) + (j << 8) + 0));
|
|
cmdq_util_err("debug_mux_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSS_TOP_DBG_OUT2));
|
|
}
|
|
}
|
|
for (i = 1; i < 7; i++) {
|
|
MFB_WR32(MFB_MSS_DMA_DEBUG_SEL, 0x0000001F & i);
|
|
cmdq_util_err("dma_debug_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSS_TOP_DBG_OUT2));
|
|
}
|
|
for (i = 0; i < 16; i++) {
|
|
MFB_WR32(MFB_MSS_DMA_DEBUG_SEL, 0x000F001F & ((i << 16) + 7));
|
|
cmdq_util_err("debug_cnt_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSS_TOP_DBG_OUT2));
|
|
}
|
|
for (i = 0; i < 24; i++) {
|
|
MFB_WR32(MFB_MSS_DMA_DEBUG_SEL, 0x00003F1F & ((i << 8) + 8));
|
|
cmdq_util_err("check_sum_debug_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSS_TOP_DBG_OUT2));
|
|
}
|
|
for (i = 0; i < 15; i++) {
|
|
MFB_WR32(MFB_MSS_TOP_DBG_CTL0, 0x0000FF00 & (0x0 << 8));
|
|
cmdq_util_err("mod_debug_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSS_TOP_DBG_OUT3));
|
|
}
|
|
#endif
|
|
cmdq_util_err("- X.");
|
|
#endif
|
|
return Ret;
|
|
}
|
|
|
|
static signed int MSF_DumpReg(void)
|
|
{
|
|
signed int Ret = 0;
|
|
#ifdef CMDQ_COMMON
|
|
unsigned int i = 0;
|
|
|
|
cmdq_util_err("- E.");
|
|
cmdq_util_err("MSF Config Info\n");
|
|
if (g_u4EnableClockCount == 0)
|
|
return Ret;
|
|
for (i = 0; i < MSF_REG_RANGE; i = i + 0x10) {
|
|
cmdq_util_err(
|
|
"[0x%08X %08X][0x%08X %08X][0x%08X %08X][0x%08X %08X]",
|
|
ISP_MSF_BASE_HW + i + 0x0, MFB_RD32(ISP_MSF_BASE + i + 0x0),
|
|
ISP_MSF_BASE_HW + i + 0x4, MFB_RD32(ISP_MSF_BASE + i + 0x4),
|
|
ISP_MSF_BASE_HW + i + 0x8, MFB_RD32(ISP_MSF_BASE + i + 0x8),
|
|
ISP_MSF_BASE_HW + i + 0xC, MFB_RD32(ISP_MSF_BASE + i + 0xC));
|
|
}
|
|
#if CHECK_SERVICE_IF_0 /*YWtodo sel*/
|
|
for (i = 28; i < 32; i++) {
|
|
MFB_WR32(MFB_MSF_TOP_DEBUG_SEL, 0xFF000000 & (i << 24));
|
|
cmdq_util_err("mfb_top_rdy_ack_debug_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
for (i = 1; i < 28; i++) {
|
|
MFB_WR32(MFB_MSF_TOP_DEBUG_SEL, 0xFF000000 & (i << 24));
|
|
cmdq_util_err("submodule_debug_sel_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
MFB_WR32(MFB_MSF_TOP_DEBUG_SEL, 0xFF000000 & (0x0 << 24));
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x0000001F & 18);
|
|
cmdq_util_err("dma_req_st 0x%08X\n", MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x0000001F & 19);
|
|
cmdq_util_err("dma_rdy_st 0x%08X\n", MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
for (i = 0; i < 3; i++) {
|
|
for (j = 1; j < 20; j++) {
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL,
|
|
0x000F3F1F & ((i << 16) + (j << 8) + 0));
|
|
cmdq_util_err("debug_mux_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
}
|
|
for (i = 0; i < 16; i++) {
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x000F001F & ((i << 16) + 16));
|
|
cmdq_util_err("debug_cnt_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
for (i = 0; i < 60; i++) {
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x00003F1F & ((i << 8) + 17));
|
|
cmdq_util_err("check_sum_debug_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
for (i = 1; i < 16; i++) {
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x0000001F & i);
|
|
cmdq_util_err("dma_debug_data_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
}
|
|
MFB_WR32(MFB_MSF_DMA_DEBUG_SEL, 0x0000001F & 20);
|
|
cmdq_util_err("wdma_otf_overflow 0x%08X\n",
|
|
MFB_RD32(MFB_MSF_TOP_DEBUG_STA));
|
|
|
|
for (i = 0; i < 112; i++) {
|
|
MFB_WR32(MFB_MSF_TOP_DEBUG_SEL,
|
|
0xFFFF0000 & ((3 << 24) + (i << 16)));
|
|
cmdq_util_err("submodule_check_sum_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_CRC_1));
|
|
}
|
|
for (i = 0; i < 29; i++) {
|
|
MFB_WR32(MFB_MSF_TOP_DEBUG_SEL,
|
|
0xFFFF0000 & ((4 << 24) + (i << 16)));
|
|
cmdq_util_err("submodule_CRC_%d 0x%08X\n",
|
|
i, MFB_RD32(MFB_MSF_TOP_CRC_1));
|
|
}
|
|
#endif
|
|
cmdq_util_err("- X.");
|
|
#endif
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
#ifndef __MFB_EP_NO_CLKMGR__
|
|
#if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) /*CCF*/
|
|
static inline void MFB_Prepare_Enable_ccf_clock(void)
|
|
{
|
|
int ret;
|
|
/* must keep this clk open order:
|
|
* CG_SCP_SYS_DIS-> CG_MM_SMI_COMMON -> CG_SCP_SYS_ISP -> MFB clk
|
|
*/
|
|
pm_runtime_get_sync(MFB_devs[0].dev);
|
|
ret = mtk_smi_larb_get(MFB_devs[0].larb);
|
|
if (ret)
|
|
LOG_ERR("mtk_smi_larb_get error\n");
|
|
#if (MTK_MFB_REG_VERSION == 3)
|
|
//smi_bus_prepare_enable(SMI_LARB11, MFB_DEV_NAME);
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_LARB11);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_LARB11 clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_MSS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_MSS clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_MFB);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_MFB clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_GALS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_GALS clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG1_GALS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG1_GALS clock\n");
|
|
#elif (MTK_MFB_REG_VERSION == 2)
|
|
//smi_bus_prepare_enable(SMI_LARB11, MFB_DEV_NAME);
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_LARB11);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_LARB11 clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_MSS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_MSS clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_MFB);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_MFB clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG2_GALS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG2_GALS clock\n");
|
|
#else
|
|
//smi_bus_prepare_enable(SMI_LARB9, MFB_DEV_NAME);
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG1_LARB9);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG1_LARB9 clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG1_MSS);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG1_MSS clock\n");
|
|
|
|
ret = clk_prepare_enable(mfb_clk.CG_IMG1_MFB);
|
|
if (ret)
|
|
LOG_ERR("cannot prepare and enable CG_IMG1_MFB clock\n");
|
|
#endif
|
|
}
|
|
|
|
static inline void MFB_Disable_Unprepare_ccf_clock(void)
|
|
{
|
|
/* must keep this clk close order:
|
|
* MFB clk -> CG_SCP_SYS_ISP -> CG_MM_SMI_COMMON -> CG_SCP_SYS_DIS
|
|
*/
|
|
#if (MTK_MFB_REG_VERSION == 3)
|
|
clk_disable_unprepare(mfb_clk.CG_IMG1_GALS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_GALS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_MFB);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_MSS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_LARB11);
|
|
/*smi_bus_disable_unprepare(SMI_LARB11, MFB_DEV_NAME);*/
|
|
#elif (MTK_MFB_REG_VERSION == 2)
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_GALS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_MFB);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_MSS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG2_LARB11);
|
|
/*smi_bus_disable_unprepare(SMI_LARB11, MFB_DEV_NAME);*/
|
|
#else
|
|
clk_disable_unprepare(mfb_clk.CG_IMG1_MFB);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG1_MSS);
|
|
clk_disable_unprepare(mfb_clk.CG_IMG1_LARB9);
|
|
/*smi_bus_disable_unprepare(SMI_LARB9, MFB_DEV_NAME);*/
|
|
#endif
|
|
mtk_smi_larb_put(MFB_devs[0].larb);
|
|
pm_runtime_put_sync(MFB_devs[0].dev);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static void MFB_EnableClock(bool En)
|
|
{
|
|
if (En) {/* Enable clock. */
|
|
/* LOG_DBG("Mfb clock enbled. g_u4EnableClockCount: %d.", */
|
|
/* g_u4EnableClockCount); */
|
|
switch (g_u4EnableClockCount) {
|
|
case 0:
|
|
#ifndef __MFB_EP_NO_CLKMGR__
|
|
#if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) /*CCF*/
|
|
MFB_Prepare_Enable_ccf_clock();
|
|
#else/*YWtodo*/
|
|
enable_clock(MT_CG_DOWE0_SMI_COMMON, "CAMERA");
|
|
enable_clock(MT_CG_IMAGE_CAM_SMI, "CAMERA");
|
|
enable_clock(MT_CG_IMAGE_CAM_CAM, "CAMERA");
|
|
enable_clock(MT_CG_IMAGE_SEN_TG, "CAMERA");
|
|
enable_clock(MT_CG_IMAGE_SEN_CAM, "CAMERA");
|
|
enable_clock(MT_CG_IMAGE_CAM_SV, "CAMERA");
|
|
/* enable_clock(MT_CG_IMAGE_FD, "CAMERA"); */
|
|
enable_clock(MT_CG_IMAGE_LARB2_SMI, "CAMERA");
|
|
#endif /* #if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) */
|
|
|
|
#else
|
|
/*MFB_WR32(IMGSYS_REG_CG_CLR, 0xFFFFFFFF);*//*YWtodo*/
|
|
#endif
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
spin_lock(&(MFBInfo.SpinLockMFB));
|
|
g_u4EnableClockCount++;
|
|
spin_unlock(&(MFBInfo.SpinLockMFB));
|
|
|
|
} else { /* Disable clock. */
|
|
|
|
/* LOG_DBG("Mfb clock disabled. g_u4EnableClockCount: %d.", */
|
|
/* g_u4EnableClockCount); */
|
|
spin_lock(&(MFBInfo.SpinLockMFB));
|
|
g_u4EnableClockCount--;
|
|
spin_unlock(&(MFBInfo.SpinLockMFB));
|
|
switch (g_u4EnableClockCount) {
|
|
case 0:
|
|
#ifndef __MFB_EP_NO_CLKMGR__
|
|
#if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) /*CCF*/
|
|
MFB_Disable_Unprepare_ccf_clock();
|
|
#else/*YWtodo*/
|
|
/* do disable clock */
|
|
disable_clock(MT_CG_IMAGE_CAM_SMI, "CAMERA");
|
|
disable_clock(MT_CG_IMAGE_CAM_CAM, "CAMERA");
|
|
disable_clock(MT_CG_IMAGE_SEN_TG, "CAMERA");
|
|
disable_clock(MT_CG_IMAGE_SEN_CAM, "CAMERA");
|
|
disable_clock(MT_CG_IMAGE_CAM_SV, "CAMERA");
|
|
/* disable_clock(MT_CG_IMAGE_FD, "CAMERA"); */
|
|
disable_clock(MT_CG_IMAGE_LARB2_SMI, "CAMERA");
|
|
disable_clock(MT_CG_DOWE0_SMI_COMMON, "CAMERA");
|
|
#endif /* #if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) */
|
|
|
|
#else
|
|
/*MFB_WR32(IMGSYS_REG_CG_SET, 0xFFFFFFFF);*//*YWtodo*/
|
|
#endif
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline void MSS_Reset(void)
|
|
{
|
|
#if CHECK_SERVICE_IF_0/*YWtodo*/
|
|
LOG_DBG("- E.");
|
|
LOG_DBG(" MSS Reset start!\n");
|
|
mutex_lock(&(MutexMFBRef));
|
|
|
|
if (MFBInfo.UserCount > 1) {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_DBG("Curr UserCount(%d) users exist", MFBInfo.UserCount);
|
|
} else {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
|
|
/* Reset MSS flow */
|
|
MFB_WR32(MSSTOP_DMA_STOP_REG, 0x100);
|
|
while ((MFB_RD32(MSSTOP_DMA_STOP_STA_REG) & 0x100) != 0x100)
|
|
LOG_DBG("MSS resetting...\n");
|
|
/*Use IMGSYS1*/
|
|
MFB_WR32(IMGSYS_REG_SW_RST, 0x10000);
|
|
udelay(1);
|
|
MFB_WR32(MSSTOP_DMA_STOP_REG, 0x0);
|
|
udelay(1);
|
|
MFB_WR32(IMGSYS_REG_SW_RST, 0x0);
|
|
LOG_DBG(" MSS Reset end!\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/*****************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline void MSF_Reset(void)
|
|
{
|
|
#if CHECK_SERVICE_IF_0/*YWtodo*/
|
|
unsigned int temp;
|
|
|
|
LOG_DBG("- E.");
|
|
LOG_DBG(" MSF Reset start!\n");
|
|
mutex_lock(&(MutexMFBRef));
|
|
|
|
if (MFBInfo.UserCount > 1) {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_DBG("Curr UserCount(%d) users exist", MFBInfo.UserCount);
|
|
} else {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
|
|
/* Reset MSF flow */
|
|
MFB_WR32(MFBTOP_DMA_STOP_REG, 0x80000000);
|
|
while ((MFB_RD32(MFBTOP_DMA_STOP_STA_REG) & 0x80000000)
|
|
!= 0x80000000)
|
|
LOG_DBG("MSF resetting...\n");
|
|
|
|
MFB_WR32(MFBTOP_RESET_REG, 0x1);
|
|
udelay(1);
|
|
temp = MFB_RD32(MFB_MSF_CMDQ_ENABLE_REG);
|
|
MFB_WR32(MFB_MSF_CMDQ_ENABLE_REG, temp | 0x100);
|
|
udelay(1);
|
|
MFB_WR32(MFBTOP_DMA_STOP_REG, 0x0);
|
|
udelay(1);
|
|
MFB_WR32(MFBTOP_RESET_REG, 0x0);
|
|
udelay(1);
|
|
MFB_WR32(MFB_MSF_CMDQ_ENABLE_REG, temp & 0xFFFFFEFF);
|
|
LOG_DBG(" MSF Reset end!\n");
|
|
}
|
|
#endif
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSS_ReadReg(struct MFB_REG_IO_STRUCT *pRegIo)
|
|
{
|
|
unsigned int i;
|
|
signed int Ret = 0;
|
|
/* unsigned int* pData = (unsigned int*)pRegIo->Data; */
|
|
struct MFB_REG_STRUCT *pData = NULL;
|
|
struct MFB_REG_STRUCT *pTmpData = NULL;
|
|
|
|
if ((pRegIo->pData == NULL) || (pRegIo->Count == 0) ||
|
|
(pRegIo->Count > (MSS_REG_RANGE>>2))) {
|
|
LOG_ERR("pRegIo->pData is NULL, Count:%d!!",
|
|
pRegIo->Count);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
pData = kmalloc(
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT), GFP_KERNEL);
|
|
if (pData == NULL) {
|
|
LOG_ERR("ERROR: kmalloc failed, cnt:%d\n",
|
|
pRegIo->Count);
|
|
Ret = -ENOMEM;
|
|
goto EXIT;
|
|
}
|
|
pTmpData = pData;
|
|
if (copy_from_user(pData, (void *)pRegIo->pData,
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT)) == 0) {
|
|
for (i = 0; i < pRegIo->Count; i++) {
|
|
if ((ISP_MSS_BASE + pData->Addr >= ISP_MSS_BASE)
|
|
&& (ISP_MSS_BASE + pData->Addr <
|
|
(ISP_MSS_BASE + MSS_REG_RANGE))
|
|
&& ((pData->Addr & 0x3) == 0)) {
|
|
pData->Val =
|
|
MFB_RD32(ISP_MSS_BASE + pData->Addr);
|
|
} else {
|
|
LOG_ERR("Wrong address(0x%p)",
|
|
(ISP_MSS_BASE + pData->Addr));
|
|
pData->Val = 0;
|
|
}
|
|
pData++;
|
|
}
|
|
pData = pTmpData;
|
|
if (copy_to_user((void *)pRegIo->pData, pData,
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT)) != 0) {
|
|
LOG_ERR("copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
} else {
|
|
LOG_ERR("MFB_READ_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
EXIT:
|
|
if (pData != NULL) {
|
|
kfree(pData);
|
|
pData = NULL;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSF_ReadReg(struct MFB_REG_IO_STRUCT *pRegIo)
|
|
{
|
|
unsigned int i;
|
|
signed int Ret = 0;
|
|
/* unsigned int* pData = (unsigned int*)pRegIo->Data; */
|
|
struct MFB_REG_STRUCT *pData = NULL;
|
|
struct MFB_REG_STRUCT *pTmpData = NULL;
|
|
|
|
if ((pRegIo->pData == NULL) || (pRegIo->Count == 0) ||
|
|
(pRegIo->Count > (MSF_REG_RANGE>>2))) {
|
|
LOG_ERR("pRegIo->pData is NULL, Count:%d!!",
|
|
pRegIo->Count);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
pData = kmalloc(
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT), GFP_KERNEL);
|
|
if (pData == NULL) {
|
|
LOG_ERR("ERROR: kmalloc failed, cnt:%d\n",
|
|
pRegIo->Count);
|
|
Ret = -ENOMEM;
|
|
goto EXIT;
|
|
}
|
|
pTmpData = pData;
|
|
if (copy_from_user(pData, (void *)pRegIo->pData,
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT)) == 0) {
|
|
for (i = 0; i < pRegIo->Count; i++) {
|
|
if ((ISP_MSF_BASE + pData->Addr >= ISP_MSF_BASE)
|
|
&& (ISP_MSF_BASE + pData->Addr <
|
|
(ISP_MSF_BASE + MSF_REG_RANGE))
|
|
&& ((pData->Addr & 0x3) == 0)) {
|
|
pData->Val =
|
|
MFB_RD32(ISP_MSF_BASE + pData->Addr);
|
|
} else {
|
|
LOG_ERR("Wrong address(0x%p)",
|
|
(ISP_MSF_BASE + pData->Addr));
|
|
pData->Val = 0;
|
|
}
|
|
pData++;
|
|
}
|
|
pData = pTmpData;
|
|
if (copy_to_user((void *)pRegIo->pData, pData,
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT)) != 0) {
|
|
LOG_ERR("copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
} else {
|
|
LOG_ERR("MFB_READ_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
EXIT:
|
|
if (pData != NULL) {
|
|
kfree(pData);
|
|
pData = NULL;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
/* Can write sensor's test model only, if need write to other modules,
|
|
* need modify current code flow
|
|
*/
|
|
static signed int MSS_WriteRegToHw(
|
|
struct MFB_REG_STRUCT *pReg, unsigned int Count)
|
|
{
|
|
signed int Ret = 0;
|
|
unsigned int i;
|
|
bool dbgWriteReg;
|
|
|
|
/* Use local variable to store MFBInfo.DebugMask & MFB_DBG_WRITE_REG
|
|
* for saving lock time
|
|
*/
|
|
spin_lock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
dbgWriteReg = MFBInfo.DebugMaskMss & MFB_DBG_WRITE_REG;
|
|
spin_unlock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
|
|
if (dbgWriteReg)
|
|
LOG_DBG("- E.\n");
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
if (dbgWriteReg) {
|
|
LOG_DBG("Addr(0x%lx), Val(0x%x)\n",
|
|
(unsigned long)(ISP_MSS_BASE + pReg[i].Addr),
|
|
(unsigned int) (pReg[i].Val));
|
|
}
|
|
|
|
if (((ISP_MSS_BASE + pReg[i].Addr) <
|
|
(ISP_MSS_BASE + MSS_REG_RANGE))
|
|
&& ((pReg[i].Addr & 0x3) == 0)) {
|
|
MFB_WR32(ISP_MSS_BASE + pReg[i].Addr, pReg[i].Val);
|
|
} else {
|
|
LOG_ERR("wrong address(0x%lx)\n",
|
|
(unsigned long)(ISP_MSS_BASE + pReg[i].Addr));
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
/* Can write sensor's test model only, if need write to other modules,
|
|
* need modify current code flow
|
|
*/
|
|
static signed int MSF_WriteRegToHw(
|
|
struct MFB_REG_STRUCT *pReg, unsigned int Count)
|
|
{
|
|
signed int Ret = 0;
|
|
unsigned int i;
|
|
bool dbgWriteReg;
|
|
|
|
/* Use local variable to store MFBInfo.DebugMask & MFB_DBG_WRITE_REG
|
|
* for saving lock time
|
|
*/
|
|
spin_lock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
dbgWriteReg = MFBInfo.DebugMaskMsf & MFB_DBG_WRITE_REG;
|
|
spin_unlock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
|
|
if (dbgWriteReg)
|
|
LOG_DBG("- E.\n");
|
|
|
|
for (i = 0; i < Count; i++) {
|
|
if (dbgWriteReg) {
|
|
LOG_DBG("Addr(0x%lx), Val(0x%x)\n",
|
|
(unsigned long)(ISP_MSF_BASE + pReg[i].Addr),
|
|
(unsigned int) (pReg[i].Val));
|
|
}
|
|
|
|
if (((ISP_MSF_BASE + pReg[i].Addr) <
|
|
(ISP_MSF_BASE + MSF_REG_RANGE))
|
|
&& ((pReg[i].Addr & 0x3) == 0)) {
|
|
MFB_WR32(ISP_MSF_BASE + pReg[i].Addr, pReg[i].Val);
|
|
} else {
|
|
LOG_ERR("wrong address(0x%lx)\n",
|
|
(unsigned long)(ISP_MSF_BASE + pReg[i].Addr));
|
|
}
|
|
}
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSS_WriteReg(struct MFB_REG_IO_STRUCT *pRegIo)
|
|
{
|
|
signed int Ret = 0;
|
|
/* unsigned char* pData = NULL; */
|
|
struct MFB_REG_STRUCT *pData = NULL;
|
|
|
|
if (MFBInfo.DebugMaskMss & MFB_DBG_WRITE_REG)
|
|
LOG_DBG("Data(0x%p), Count(%d)\n",
|
|
(pRegIo->pData), (pRegIo->Count));
|
|
|
|
if ((pRegIo->pData == NULL) || (pRegIo->Count == 0) ||
|
|
(pRegIo->Count > (MSS_REG_RANGE>>2))) {
|
|
LOG_ERR("ERROR: pRegIo->pData is NULL or Count:%d\n",
|
|
pRegIo->Count);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
/* pData = (unsigned char*)kmalloc( */
|
|
/* (pRegIo->Count)*sizeof(MFB_REG_STRUCT), GFP_ATOMIC); */
|
|
pData = kmalloc(
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT), GFP_KERNEL);
|
|
if (pData == NULL) {
|
|
LOG_ERR(
|
|
"ERROR: kmalloc failed, (process, pid, tgid)=(%s, %d, %d)\n",
|
|
current->comm,
|
|
current->pid, current->tgid);
|
|
Ret = -ENOMEM;
|
|
goto EXIT;
|
|
}
|
|
if (copy_from_user(pData, (void __user *)(pRegIo->pData),
|
|
pRegIo->Count * sizeof(struct MFB_REG_STRUCT)) != 0) {
|
|
LOG_ERR("copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
Ret = MSS_WriteRegToHw(pData, pRegIo->Count);
|
|
EXIT:
|
|
if (pData != NULL) {
|
|
kfree(pData);
|
|
pData = NULL;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSF_WriteReg(struct MFB_REG_IO_STRUCT *pRegIo)
|
|
{
|
|
signed int Ret = 0;
|
|
/* unsigned char* pData = NULL; */
|
|
struct MFB_REG_STRUCT *pData = NULL;
|
|
|
|
if (MFBInfo.DebugMaskMsf & MFB_DBG_WRITE_REG)
|
|
LOG_DBG("Data(0x%p), Count(%d)\n",
|
|
(pRegIo->pData), (pRegIo->Count));
|
|
|
|
if ((pRegIo->pData == NULL) || (pRegIo->Count == 0) ||
|
|
(pRegIo->Count > (MSF_REG_RANGE>>2))) {
|
|
LOG_ERR("ERROR: pRegIo->pData is NULL or Count:%d\n",
|
|
pRegIo->Count);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
/* pData = (unsigned char*)kmalloc( */
|
|
/* (pRegIo->Count)*sizeof(MFB_REG_STRUCT), GFP_ATOMIC); */
|
|
pData = kmalloc(
|
|
(pRegIo->Count) * sizeof(struct MFB_REG_STRUCT), GFP_KERNEL);
|
|
if (pData == NULL) {
|
|
LOG_ERR(
|
|
"ERROR: kmalloc failed, (process, pid, tgid)=(%s, %d, %d)\n",
|
|
current->comm,
|
|
current->pid, current->tgid);
|
|
Ret = -ENOMEM;
|
|
goto EXIT;
|
|
}
|
|
if (copy_from_user(pData, (void __user *)(pRegIo->pData),
|
|
pRegIo->Count * sizeof(struct MFB_REG_STRUCT)) != 0) {
|
|
LOG_ERR("copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
Ret = MSF_WriteRegToHw(pData, pRegIo->Count);
|
|
EXIT:
|
|
if (pData != NULL) {
|
|
kfree(pData);
|
|
pData = NULL;
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSS_WaitIrq(struct MFB_WAIT_IRQ_STRUCT *WaitIrq,
|
|
enum MFB_PROCESS_ID_ENUM whichReq)
|
|
{
|
|
|
|
signed int Ret = 0;
|
|
signed int Timeout = WaitIrq->Timeout;
|
|
|
|
/*unsigned int i;*/
|
|
unsigned long flags; /* old: unsigned int flags;*/
|
|
/* FIX to avoid build warning */
|
|
unsigned int irqStatus;
|
|
/*int cnt = 0;*/
|
|
struct timespec64 time_getrequest;
|
|
unsigned int p;
|
|
|
|
ktime_get_ts64(&time_getrequest);
|
|
|
|
/* Debug interrupt */
|
|
if (MFBInfo.DebugMaskMss & MFB_DBG_INT) {
|
|
if (WaitIrq->Status & MFBInfo.IrqInfo.Mask[WaitIrq->Type]) {
|
|
if (WaitIrq->UserKey > 0) {
|
|
LOG_DBG(
|
|
"+WaitIrq Clr(%d),Type(%d),Sta(0x%08X),Timeout(%d),user(%d),PID(%d)\n",
|
|
WaitIrq->Clear,
|
|
WaitIrq->Type,
|
|
WaitIrq->Status,
|
|
WaitIrq->Timeout,
|
|
WaitIrq->UserKey,
|
|
WaitIrq->ProcessID);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* 1. wait type update */
|
|
if (WaitIrq->Clear == MFB_IRQ_CLEAR_STATUS) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &= (~WaitIrq->Status);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
return Ret;
|
|
}
|
|
|
|
if (WaitIrq->Clear == MFB_IRQ_CLEAR_WAIT) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
if (MFBInfo.IrqInfo.Status[WaitIrq->Type] & WaitIrq->Status)
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &=
|
|
(~WaitIrq->Status);
|
|
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
} else if (WaitIrq->Clear == MFB_IRQ_CLEAR_ALL) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] = 0;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
}
|
|
/* MFB_IRQ_WAIT_CLEAR ==> do nothing */
|
|
|
|
|
|
/* Store irqinfo status in here to redeuce time of spin_lock_irqsave */
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Type != MFB_IRQ_TYPE_INT_MSS_ST) {
|
|
LOG_ERR(
|
|
"No Such Stats can be waited!! irq Type/User/Sts/Pid(0x%x/%d/0x%x/%d)\n",
|
|
WaitIrq->Type,
|
|
WaitIrq->UserKey,
|
|
WaitIrq->Status,
|
|
WaitIrq->ProcessID);
|
|
}
|
|
|
|
|
|
#ifdef MFB_WAITIRQ_LOG
|
|
LOG_INF(
|
|
"before wait_event! Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_INF(
|
|
"urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_INF(
|
|
"MssIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MssIrqCnt);
|
|
#endif
|
|
|
|
/* 2. start to wait signal */
|
|
Timeout = wait_event_interruptible_timeout(MFBInfo.WaitQueueHeadMss,
|
|
MSS_GetIRQState(WaitIrq->Type,
|
|
&WaitIrq->UserKey,
|
|
WaitIrq->Status, whichReq,
|
|
WaitIrq->ProcessID),
|
|
MFB_MsToJiffies(WaitIrq->Timeout));
|
|
|
|
/* check if user is interrupted by system signal */
|
|
if ((Timeout != 0) &&
|
|
(!WaitIrq->UserKey)) {
|
|
LOG_INF(
|
|
"waked up by sys. signal,ret(%d),irq Type/User/Sts/whReq/Pid(0x%x/%d/0x%x/%d/%d)\n",
|
|
Timeout, WaitIrq->Type, WaitIrq->UserKey,
|
|
WaitIrq->Status, whichReq,
|
|
WaitIrq->ProcessID);
|
|
Ret = -ERESTARTSYS; /* actually it should be -ERESTARTSYS */
|
|
goto EXIT;
|
|
}
|
|
/* timeout */
|
|
if (Timeout == 0) {
|
|
/* Store irqinfo status in here to redeuce time of
|
|
* spin_lock_irqsave
|
|
*/
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
LOG_ERR(
|
|
"ERRRR Timeout!Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_ERR("urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_ERR(
|
|
"MssIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MssIrqCnt[whichReq]);
|
|
|
|
if (WaitIrq->bDumpReg)
|
|
MSS_DumpReg();
|
|
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
} else {
|
|
/* Store irqinfo status in here to redeuce time of
|
|
* spin_lock_irqsave
|
|
*/
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_begin("MFB WaitIrq");
|
|
#endif
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Clear == MFB_IRQ_WAIT_CLEAR) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Status & MSS_INT_ST) {
|
|
p = WaitIrq->ProcessID % IRQ_USER_NUM_MAX;
|
|
MFBInfo.IrqInfo.MssIrqCnt[p]--;
|
|
if (MFBInfo.IrqInfo.MssIrqCnt[p] == 0)
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &=
|
|
(~WaitIrq->Status);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_IRQ_WAIT_CLEAR Error, Type(%d), WaitStatus(0x%08X)",
|
|
WaitIrq->Type, WaitIrq->Status);
|
|
}
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
}
|
|
|
|
#ifdef MFB_WAITIRQ_LOG
|
|
LOG_INF(
|
|
"no Timeout!Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_INF("urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_INF(
|
|
"MssIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MssIrqCnt);
|
|
|
|
#endif
|
|
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_end();
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
EXIT:
|
|
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MSF_WaitIrq(struct MFB_WAIT_IRQ_STRUCT *WaitIrq)
|
|
{
|
|
|
|
signed int Ret = 0;
|
|
signed int Timeout = WaitIrq->Timeout;
|
|
enum MFB_PROCESS_ID_ENUM whichReq = MFB_PROCESS_ID_MSF;
|
|
|
|
/*unsigned int i;*/
|
|
unsigned long flags; /* old: unsigned int flags;*/
|
|
/* FIX to avoid build warning */
|
|
unsigned int irqStatus;
|
|
/*int cnt = 0;*/
|
|
struct timespec64 time_getrequest;
|
|
unsigned int p;
|
|
|
|
ktime_get_ts64(&time_getrequest);
|
|
|
|
/* Debug interrupt */
|
|
if (MFBInfo.DebugMaskMsf & MFB_DBG_INT) {
|
|
if (WaitIrq->Status & MFBInfo.IrqInfo.Mask[WaitIrq->Type]) {
|
|
if (WaitIrq->UserKey > 0) {
|
|
LOG_DBG(
|
|
"+WaitIrq Clr(%d),Type(%d),Sta(0x%08X),Timeout(%d),user(%d),PID(%d)\n",
|
|
WaitIrq->Clear,
|
|
WaitIrq->Type,
|
|
WaitIrq->Status,
|
|
WaitIrq->Timeout,
|
|
WaitIrq->UserKey,
|
|
WaitIrq->ProcessID);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* 1. wait type update */
|
|
if (WaitIrq->Clear == MFB_IRQ_CLEAR_STATUS) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &= (~WaitIrq->Status);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
return Ret;
|
|
}
|
|
|
|
if (WaitIrq->Clear == MFB_IRQ_CLEAR_WAIT) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
if (MFBInfo.IrqInfo.Status[WaitIrq->Type] & WaitIrq->Status)
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &=
|
|
(~WaitIrq->Status);
|
|
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
} else if (WaitIrq->Clear == MFB_IRQ_CLEAR_ALL) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] = 0;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
}
|
|
/* MFB_IRQ_WAIT_CLEAR ==> do nothing */
|
|
|
|
|
|
/* Store irqinfo status in here to redeuce time of spin_lock_irqsave */
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Type != MFB_IRQ_TYPE_INT_MSF_ST) {
|
|
LOG_ERR(
|
|
"No Such Stats can be waited!! irq Type/User/Sts/Pid(0x%x/%d/0x%x/%d)\n",
|
|
WaitIrq->Type,
|
|
WaitIrq->UserKey,
|
|
WaitIrq->Status,
|
|
WaitIrq->ProcessID);
|
|
}
|
|
|
|
|
|
#ifdef MFB_WAITIRQ_LOG
|
|
LOG_INF(
|
|
"before wait_event! Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_INF(
|
|
"urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_INF(
|
|
"MsfIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MsfIrqCnt);
|
|
#endif
|
|
|
|
/* 2. start to wait signal */
|
|
Timeout = wait_event_interruptible_timeout(MFBInfo.WaitQueueHeadMsf,
|
|
MSF_GetIRQState(WaitIrq->Type, WaitIrq->UserKey,
|
|
WaitIrq->Status, whichReq,
|
|
WaitIrq->ProcessID),
|
|
MFB_MsToJiffies(WaitIrq->Timeout));
|
|
|
|
p = WaitIrq->ProcessID % IRQ_USER_NUM_MAX;
|
|
/* check if user is interrupted by system signal */
|
|
if ((Timeout != 0) &&
|
|
(!MSF_GetIRQState(
|
|
WaitIrq->Type,
|
|
WaitIrq->UserKey,
|
|
WaitIrq->Status,
|
|
whichReq,
|
|
WaitIrq->ProcessID))) {
|
|
LOG_INF(
|
|
"waked up by sys. signal,ret(%d),irq Type/User/Sts/whReq/Pid(0x%x/%d/0x%x/%d/%d)\n",
|
|
Timeout, WaitIrq->Type, WaitIrq->UserKey,
|
|
WaitIrq->Status, whichReq,
|
|
WaitIrq->ProcessID);
|
|
Ret = -ERESTARTSYS; /* actually it should be -ERESTARTSYS */
|
|
goto EXIT;
|
|
}
|
|
/* timeout */
|
|
if (Timeout == 0) {
|
|
/* Store irqinfo status in here to redeuce time of
|
|
* spin_lock_irqsave
|
|
*/
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
LOG_ERR(
|
|
"ERRRR Timeout!Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_ERR("urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_ERR(
|
|
"MsfIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p]);
|
|
|
|
if (WaitIrq->bDumpReg)
|
|
MSF_DumpReg();
|
|
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
} else {
|
|
/* Store irqinfo status in here to redeuce time of
|
|
* spin_lock_irqsave
|
|
*/
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_begin("MFB WaitIrq");
|
|
#endif
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
irqStatus = MFBInfo.IrqInfo.Status[WaitIrq->Type];
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Clear == MFB_IRQ_WAIT_CLEAR) {
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
|
|
if (WaitIrq->Status & MSF_INT_ST) {
|
|
MFBInfo.IrqInfo.MsfIrqCnt[p]--;
|
|
if (MFBInfo.IrqInfo.MsfIrqCnt[p] == 0)
|
|
MFBInfo.IrqInfo.Status[WaitIrq->Type] &=
|
|
(~WaitIrq->Status);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_IRQ_WAIT_CLEAR Error, Type(%d), WaitStatus(0x%08X)",
|
|
WaitIrq->Type, WaitIrq->Status);
|
|
}
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[WaitIrq->Type]), flags);
|
|
}
|
|
|
|
#ifdef MFB_WAITIRQ_LOG
|
|
LOG_INF(
|
|
"no Timeout!Timeout(%d)Clear(%d),Type(%d),IrqSta(0x%08X), WaitSta(0x%08X)\n",
|
|
WaitIrq->Timeout, WaitIrq->Clear,
|
|
WaitIrq->Type, irqStatus, WaitIrq->Status);
|
|
LOG_INF("urKey(%d),whReq(%d),PID(%d)\n",
|
|
WaitIrq->UserKey, whichReq, WaitIrq->ProcessID);
|
|
LOG_INF(
|
|
"MsfIrqCnt(0x%08X)\n",
|
|
MFBInfo.IrqInfo.MsfIrqCnt);
|
|
|
|
#endif
|
|
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_end();
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
EXIT:
|
|
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static enum MFB_PROCESS_ID_ENUM mss_get_reqs(enum exec_mode exec,
|
|
struct engine_requests **reqs)
|
|
{
|
|
enum MFB_PROCESS_ID_ENUM tag;
|
|
|
|
switch (exec) {
|
|
case EXEC_MODE_NORM:
|
|
*reqs = &mss_reqs;
|
|
tag = MFB_PROCESS_ID_MSS;
|
|
break;
|
|
case EXEC_MODE_VSS:
|
|
*reqs = &vmss_reqs;
|
|
tag = MFB_PROCESS_ID_vMSS;
|
|
break;
|
|
default:
|
|
tag = MFB_PROCESS_ID_NONE;
|
|
LOG_ERR("invalid tile irq mode\n");
|
|
break;
|
|
}
|
|
|
|
return tag;
|
|
}
|
|
|
|
static unsigned int msf_get_reqs(enum exec_mode exec,
|
|
struct engine_requests **reqs)
|
|
{
|
|
unsigned int ret = 0;
|
|
|
|
switch (exec) {
|
|
case EXEC_MODE_NORM:
|
|
*reqs = &msf_reqs;
|
|
break;
|
|
case EXEC_MODE_VSS:
|
|
*reqs = &vmsf_reqs;
|
|
break;
|
|
default:
|
|
ret = 1;
|
|
LOG_ERR("invalid tile irq mode\n");
|
|
break;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
|
|
static long MFB_ioctl(struct file *pFile, unsigned int Cmd, unsigned long Param)
|
|
{
|
|
signed int Ret = 0;
|
|
|
|
/*unsigned int pid = 0;*/
|
|
struct MFB_REG_IO_STRUCT RegIo;
|
|
struct MFB_WAIT_IRQ_STRUCT IrqInfo;
|
|
struct MFB_CLEAR_IRQ_STRUCT ClearIrq;
|
|
struct MFB_MSSRequest mfb_MssReq;
|
|
struct MFB_MSFRequest mfb_MsfReq;
|
|
struct MFB_USER_INFO_STRUCT *pUserInfo;
|
|
struct engine_requests *reqs = NULL;
|
|
struct MFB_MSSConfig *msscfgs = NULL;
|
|
int dequeNum;
|
|
unsigned long flags; /* old: unsigned int flags;*/
|
|
/* FIX to avoid build warning */
|
|
struct MFB_MapTable mfb_maptable;
|
|
unsigned int i = 0;
|
|
|
|
if (pFile->private_data == NULL) {
|
|
LOG_WRN(
|
|
"private_data is NULL,(process, pid, tgid)=(%s, %d, %d)",
|
|
current->comm,
|
|
current->pid, current->tgid);
|
|
return -EFAULT;
|
|
}
|
|
pUserInfo = (struct MFB_USER_INFO_STRUCT *) (pFile->private_data);
|
|
switch (Cmd) {
|
|
case MFB_MSS_RESET:
|
|
{
|
|
spin_lock(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
MSS_Reset();
|
|
spin_unlock(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
break;
|
|
}
|
|
case MFB_MSF_RESET:
|
|
{
|
|
spin_lock(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
MSF_Reset();
|
|
spin_unlock(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
break;
|
|
}
|
|
case MFB_MSS_DUMP_REG:
|
|
{
|
|
Ret = MSS_DumpReg();
|
|
break;
|
|
}
|
|
case MFB_MSF_DUMP_REG:
|
|
{
|
|
Ret = MSF_DumpReg();
|
|
break;
|
|
}
|
|
case MFB_MSS_DUMP_ISR_LOG:
|
|
{
|
|
unsigned int currentPPB = m_CurrentPPB;
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
m_CurrentPPB = (m_CurrentPPB + 1) % LOG_PPNUM;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSS_ST,
|
|
currentPPB, _LOG_INF);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSS_ST,
|
|
currentPPB, _LOG_ERR);
|
|
break;
|
|
}
|
|
case MFB_MSF_DUMP_ISR_LOG:
|
|
{
|
|
unsigned int currentPPB = m_CurrentPPB;
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
m_CurrentPPB = (m_CurrentPPB + 1) % LOG_PPNUM;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSF_ST,
|
|
currentPPB, _LOG_INF);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSF_ST,
|
|
currentPPB, _LOG_ERR);
|
|
break;
|
|
}
|
|
case MFB_MSS_READ_REGISTER:
|
|
{
|
|
if (copy_from_user(&RegIo, (void *)Param,
|
|
sizeof(struct MFB_REG_IO_STRUCT)) == 0) {
|
|
/* 2nd layer behavoir of copy from user is
|
|
* implemented in MFB_ReadReg(...)
|
|
*/
|
|
Ret = MSS_ReadReg(&RegIo);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSS_READ_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSF_READ_REGISTER:
|
|
{
|
|
if (copy_from_user(&RegIo, (void *)Param,
|
|
sizeof(struct MFB_REG_IO_STRUCT)) == 0) {
|
|
/* 2nd layer behavoir of copy from user is
|
|
* implemented in MFB_ReadReg(...)
|
|
*/
|
|
Ret = MSF_ReadReg(&RegIo);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSF_READ_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSS_WRITE_REGISTER:
|
|
{
|
|
if (copy_from_user(&RegIo, (void *)Param,
|
|
sizeof(struct MFB_REG_IO_STRUCT)) == 0) {
|
|
/* 2nd layer behavoir of copy from user is
|
|
* implemented in MFB_WriteReg(...)
|
|
*/
|
|
Ret = MSS_WriteReg(&RegIo);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSS_WRITE_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSF_WRITE_REGISTER:
|
|
{
|
|
if (copy_from_user(&RegIo, (void *)Param,
|
|
sizeof(struct MFB_REG_IO_STRUCT)) == 0) {
|
|
/* 2nd layer behavoir of copy from user is
|
|
* implemented in MFB_WriteReg(...)
|
|
*/
|
|
Ret = MSF_WriteReg(&RegIo);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSF_WRITE_REGISTER copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSS_WAIT_IRQ:
|
|
{
|
|
if (copy_from_user(&IrqInfo, (void *)Param,
|
|
sizeof(struct MFB_WAIT_IRQ_STRUCT)) == 0) {
|
|
if ((IrqInfo.Type >= MFB_IRQ_TYPE_AMOUNT) ||
|
|
(IrqInfo.Type < 0)) {
|
|
Ret = -EFAULT;
|
|
LOG_ERR("invalid type(%d)",
|
|
IrqInfo.Type);
|
|
goto EXIT;
|
|
}
|
|
|
|
if ((IrqInfo.UserKey >= IRQ_USER_NUM_MAX) ||
|
|
(IrqInfo.UserKey < 0)) {
|
|
LOG_ERR(
|
|
"invalid userKey(%d), max(%d), force userkey = 0\n",
|
|
IrqInfo.UserKey,
|
|
IRQ_USER_NUM_MAX);
|
|
IrqInfo.UserKey = 0;
|
|
}
|
|
|
|
LOG_DBG(
|
|
"MSS IRQ clear(%d), type(%d), userKey(%d), timeout(%d), status(%d), streamtag(%d)\n",
|
|
IrqInfo.Clear, IrqInfo.Type,
|
|
IrqInfo.UserKey, IrqInfo.Timeout,
|
|
IrqInfo.Status, pUserInfo->streamtag);
|
|
|
|
IrqInfo.ProcessID = pUserInfo->Pid;
|
|
Ret = MSS_WaitIrq(&IrqInfo,
|
|
pUserInfo->streamtag);
|
|
if (Ret < 0) {
|
|
mfb_request_dump(&mss_reqs);
|
|
mfb_request_dump(&vmss_reqs);
|
|
MSS_DumpReg();
|
|
}
|
|
|
|
if (copy_to_user((void *)Param, &IrqInfo,
|
|
sizeof(struct MFB_WAIT_IRQ_STRUCT)) != 0) {
|
|
LOG_ERR("copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
} else {
|
|
LOG_ERR("MFB_WAIT_IRQ copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSF_WAIT_IRQ:
|
|
{
|
|
if (copy_from_user(&IrqInfo, (void *)Param,
|
|
sizeof(struct MFB_WAIT_IRQ_STRUCT)) == 0) {
|
|
if ((IrqInfo.Type >= MFB_IRQ_TYPE_AMOUNT) ||
|
|
(IrqInfo.Type < 0)) {
|
|
Ret = -EFAULT;
|
|
LOG_ERR("invalid type(%d)",
|
|
IrqInfo.Type);
|
|
goto EXIT;
|
|
}
|
|
|
|
if ((IrqInfo.UserKey >= IRQ_USER_NUM_MAX) ||
|
|
(IrqInfo.UserKey < 0)) {
|
|
LOG_ERR(
|
|
"invalid userKey(%d), max(%d), force userkey = 0\n",
|
|
IrqInfo.UserKey,
|
|
IRQ_USER_NUM_MAX);
|
|
IrqInfo.UserKey = 0;
|
|
}
|
|
|
|
LOG_INF(
|
|
"MSF IRQ clear(%d), type(%d), userKey(%d), timeout(%d), status(%d)\n",
|
|
IrqInfo.Clear, IrqInfo.Type,
|
|
IrqInfo.UserKey, IrqInfo.Timeout,
|
|
IrqInfo.Status);
|
|
|
|
IrqInfo.ProcessID = pUserInfo->Pid;
|
|
Ret = MSF_WaitIrq(&IrqInfo);
|
|
if (Ret < 0) {
|
|
mfb_request_dump(&vmsf_reqs);
|
|
mfb_request_dump(&msf_reqs);
|
|
MSF_DumpReg();
|
|
}
|
|
|
|
if (copy_to_user((void *)Param, &IrqInfo,
|
|
sizeof(struct MFB_WAIT_IRQ_STRUCT)) != 0) {
|
|
LOG_ERR("copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
} else {
|
|
LOG_ERR("MFB_WAIT_IRQ copy_from_user failed");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSS_CLEAR_IRQ:
|
|
{
|
|
if (copy_from_user(&ClearIrq, (void *)Param,
|
|
sizeof(struct MFB_CLEAR_IRQ_STRUCT)) == 0) {
|
|
LOG_DBG("MFB_MSS_CLEAR_IRQ Type(%d)",
|
|
ClearIrq.Type);
|
|
|
|
if ((ClearIrq.Type >= MFB_IRQ_TYPE_AMOUNT) ||
|
|
(ClearIrq.Type < 0)) {
|
|
Ret = -EFAULT;
|
|
LOG_ERR("invalid type(%d)",
|
|
ClearIrq.Type);
|
|
goto EXIT;
|
|
}
|
|
|
|
if ((ClearIrq.UserKey >= IRQ_USER_NUM_MAX)
|
|
|| (ClearIrq.UserKey < 0)) {
|
|
LOG_ERR("errUserEnum(%d)",
|
|
ClearIrq.UserKey);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
LOG_DBG(
|
|
"MFB_MSS_CLEAR_IRQ:Type(%d),Status(0x%08X),IrqStatus(0x%08X)\n",
|
|
ClearIrq.Type, ClearIrq.Status,
|
|
MFBInfo.IrqInfo.Status[ClearIrq.Type]);
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[ClearIrq.Type]),
|
|
flags);
|
|
MFBInfo.IrqInfo.Status[ClearIrq.Type] &=
|
|
(~ClearIrq.Status);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[ClearIrq.Type]),
|
|
flags);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSS_CLEAR_IRQ copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSF_CLEAR_IRQ:
|
|
{
|
|
if (copy_from_user(&ClearIrq, (void *)Param,
|
|
sizeof(struct MFB_CLEAR_IRQ_STRUCT)) == 0) {
|
|
LOG_DBG("MFB_MSF_CLEAR_IRQ Type(%d)",
|
|
ClearIrq.Type);
|
|
|
|
if ((ClearIrq.Type >= MFB_IRQ_TYPE_AMOUNT) ||
|
|
(ClearIrq.Type < 0)) {
|
|
Ret = -EFAULT;
|
|
LOG_ERR("invalid type(%d)",
|
|
ClearIrq.Type);
|
|
goto EXIT;
|
|
}
|
|
|
|
if ((ClearIrq.UserKey >= IRQ_USER_NUM_MAX)
|
|
|| (ClearIrq.UserKey < 0)) {
|
|
LOG_ERR("errUserEnum(%d)",
|
|
ClearIrq.UserKey);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
LOG_DBG(
|
|
"MFB_MSF_CLEAR_IRQ:Type(%d),Status(0x%08X),IrqStatus(0x%08X)\n",
|
|
ClearIrq.Type, ClearIrq.Status,
|
|
MFBInfo.IrqInfo.Status[ClearIrq.Type]);
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[ClearIrq.Type]),
|
|
flags);
|
|
MFBInfo.IrqInfo.Status[ClearIrq.Type] &=
|
|
(~ClearIrq.Status);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[ClearIrq.Type]),
|
|
flags);
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_MSF_CLEAR_IRQ copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSS_ENQUE_REQ:
|
|
{
|
|
if (copy_from_user(&mfb_MssReq, (void *)Param,
|
|
sizeof(struct MFB_MSSRequest)) == 0) {
|
|
LOG_DBG("MSS_ENQNUE_NUM:%d, pid:%d\n",
|
|
mfb_MssReq.m_ReqNum,
|
|
pUserInfo->Pid);
|
|
if (mfb_MssReq.m_ReqNum >
|
|
_SUPPORT_MAX_MFB_FRAME_REQUEST_) {
|
|
LOG_ERR(
|
|
"MSS Enque Num is bigger than enqueNum:%d\n",
|
|
mfb_MssReq.m_ReqNum);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
if (mfb_MssReq.m_pMssConfig == NULL) {
|
|
LOG_ERR("NULL MSS user Config\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
mutex_lock(&gMfbMssMutex);/* Protect the Multi Process*/
|
|
switch (mfb_MssReq.exec) {
|
|
case EXEC_MODE_NORM:
|
|
msscfgs = g_MssEnqueReq_Struct.MssFrameConfig;
|
|
break;
|
|
case EXEC_MODE_VSS:
|
|
msscfgs = g_MssEnqueReq_Struct.vMssFrameConfig;
|
|
break;
|
|
default:
|
|
msscfgs = g_MssEnqueReq_Struct.MssFrameConfig;
|
|
LOG_WRN("invalid irq mode\n");
|
|
break;
|
|
}
|
|
|
|
if (copy_from_user(msscfgs,
|
|
(void *)mfb_MssReq.m_pMssConfig,
|
|
mfb_MssReq.m_ReqNum * sizeof(
|
|
struct MFB_MSSConfig)
|
|
) != 0) {
|
|
LOG_ERR(
|
|
"copy MSSConfig from request is fail!!\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
pUserInfo->streamtag = mss_get_reqs(mfb_MssReq.exec,
|
|
&reqs);
|
|
pUserInfo->reqs = reqs;
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
kMssReq.m_ReqNum = mfb_MssReq.m_ReqNum;
|
|
kMssReq.m_pMssConfig = msscfgs;
|
|
mfb_enque_request(reqs, kMssReq.m_ReqNum, &kMssReq,
|
|
pUserInfo->Pid);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
LOG_DBG("ConfigMSS Request!!\n");
|
|
if (!mfb_request_running(reqs)) {
|
|
LOG_DBG("direct mfb_request_handler\n");
|
|
mfb_request_handler(reqs,
|
|
&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
}
|
|
mutex_unlock(&gMfbMssMutex);
|
|
} else {
|
|
LOG_ERR("MFB_MSS_ENQUE copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSS_DEQUE_REQ:
|
|
{
|
|
if (copy_from_user(&mfb_MssReq, (void *)Param,
|
|
sizeof(struct MFB_MSSRequest)) == 0) {
|
|
reqs = pUserInfo->reqs;
|
|
mutex_lock(&gMfbMssDequeMutex);
|
|
/* Protect the Multi Process */
|
|
|
|
spin_lock_irqsave(&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
kMssReq.m_pMssConfig =
|
|
g_MssDequeReq_Struct.MssFrameConfig;
|
|
mfb_deque_request(reqs, &kMssReq.m_ReqNum,
|
|
&kMssReq);
|
|
dequeNum = kMssReq.m_ReqNum;
|
|
mfb_MssReq.m_ReqNum = dequeNum;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSS_ST]),
|
|
flags);
|
|
|
|
mutex_unlock(&gMfbMssDequeMutex);
|
|
|
|
if (mfb_MssReq.m_pMssConfig == NULL) {
|
|
LOG_ERR("NULL MSS user Config\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
if (copy_to_user(
|
|
(void *)mfb_MssReq.m_pMssConfig,
|
|
&g_MssDequeReq_Struct.MssFrameConfig[0],
|
|
dequeNum * sizeof(
|
|
struct MFB_MSSConfig)) != 0) {
|
|
LOG_ERR(
|
|
"MFB_CMD_MSS_DEQUE_REQ copy_to_user frameconfig failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
if (copy_to_user((void *)Param, &mfb_MssReq,
|
|
sizeof(struct MFB_MSSRequest)) != 0) {
|
|
LOG_ERR(
|
|
"MFB_CMD_MSS_DEQUE_REQ copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_CMD_MSS_DEQUE_REQ copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
case MFB_MSF_ENQUE_REQ:
|
|
{
|
|
if (copy_from_user(&mfb_MsfReq, (void *)Param,
|
|
sizeof(struct MFB_MSFRequest)) == 0) {
|
|
LOG_DBG("MSF_ENQNUE_NUM:%d, pid:%d\n",
|
|
mfb_MsfReq.m_ReqNum,
|
|
pUserInfo->Pid);
|
|
if (mfb_MsfReq.m_ReqNum >
|
|
_SUPPORT_MAX_MFB_FRAME_REQUEST_) {
|
|
LOG_ERR(
|
|
"MSF Enque Num is bigger than enqueNum:%d\n",
|
|
mfb_MsfReq.m_ReqNum);
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
if (mfb_MsfReq.m_pMsfConfig == NULL) {
|
|
LOG_ERR("NULL MSF user Config\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
/* Protect the Multi Process */
|
|
mutex_lock(&gMfbMsfMutex);
|
|
|
|
if (copy_from_user(
|
|
g_MsfEnqueReq_Struct.MsfFrameConfig,
|
|
(void *)mfb_MsfReq.m_pMsfConfig,
|
|
mfb_MsfReq.m_ReqNum *
|
|
sizeof(struct MFB_MSFConfig)) != 0) {
|
|
LOG_ERR(
|
|
"copy MSFConfig from request is fail!!\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
msf_get_reqs(mfb_MsfReq.exec, &reqs);
|
|
pUserInfo->reqs = reqs;
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
kMsfReq.m_ReqNum = mfb_MsfReq.m_ReqNum;
|
|
kMsfReq.m_pMsfConfig =
|
|
g_MsfEnqueReq_Struct.MsfFrameConfig;
|
|
mfb_enque_request(reqs,
|
|
kMsfReq.m_ReqNum,
|
|
&kMsfReq, pUserInfo->Pid);
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
|
|
LOG_DBG("ConfigMSF Request!!\n");
|
|
if (!mfb_request_running(reqs)) {
|
|
LOG_DBG("direct mfb_request_handler\n");
|
|
mfb_request_handler(
|
|
reqs,
|
|
&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSF_ST])
|
|
);
|
|
}
|
|
mutex_unlock(&gMfbMsfMutex);
|
|
} else {
|
|
LOG_ERR("MFB_MSF_ENQUE copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MFB_MSF_DEQUE_REQ:
|
|
{
|
|
if (copy_from_user(&mfb_MsfReq, (void *)Param,
|
|
sizeof(struct MFB_MSFRequest)) == 0) {
|
|
reqs = pUserInfo->reqs;
|
|
mutex_lock(&gMfbMsfDequeMutex);
|
|
/* Protect the Multi Process */
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
kMsfReq.m_pMsfConfig =
|
|
g_MsfDequeReq_Struct.MsfFrameConfig;
|
|
mfb_deque_request(
|
|
reqs,
|
|
&kMsfReq.m_ReqNum,
|
|
&kMsfReq);
|
|
dequeNum = kMsfReq.m_ReqNum;
|
|
mfb_MsfReq.m_ReqNum = dequeNum;
|
|
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSF_ST]),
|
|
flags);
|
|
|
|
mutex_unlock(&gMfbMsfDequeMutex);
|
|
|
|
if (mfb_MsfReq.m_pMsfConfig == NULL) {
|
|
LOG_ERR("NULL MSF user Config\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
|
|
if (copy_to_user(
|
|
(void *)mfb_MsfReq.m_pMsfConfig,
|
|
&g_MsfDequeReq_Struct.MsfFrameConfig[0],
|
|
dequeNum *
|
|
sizeof(struct MFB_MSFConfig)) != 0) {
|
|
LOG_ERR(
|
|
"MFB_MSF_DEQUE_REQ copy_to_user frameconfig failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
if (copy_to_user(
|
|
(void *)Param, &mfb_MsfReq,
|
|
sizeof(struct MFB_MSFRequest)) != 0) {
|
|
LOG_ERR(
|
|
"MFB_MSF_DEQUE_REQ copy_to_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
} else {
|
|
LOG_ERR(
|
|
"MFB_CMD_MSF_DEQUE_REQ copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case MFB_MAP:
|
|
{
|
|
if (copy_from_user(&mfb_maptable, (void *)Param,
|
|
sizeof(struct MFB_MapTable)) == 0) {
|
|
|
|
if (mfb_maptable.buf_fd == 0) {
|
|
LOG_ERR("buf_fd equal 0\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
mutex_lock(&(Mutexgkibuf));
|
|
for (i = 0; i < GKI_BUF_NUM_MAX; i++) {
|
|
if (pUserInfo->gkiBuf[i].isUse == 0) {
|
|
pUserInfo->gkiBuf[i].isUse = 1;
|
|
break;
|
|
}
|
|
}
|
|
if (i == GKI_BUF_NUM_MAX) {
|
|
LOG_ERR("gkiBuf full\n");
|
|
mutex_unlock(&(Mutexgkibuf));
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
pUserInfo->gkiBuf[i].bfd = mfb_maptable.buf_fd;
|
|
if (mfb_get_dma_buf(&pUserInfo->gkiBuf[i], mfb_maptable.buf_fd) != 0) {
|
|
LOG_ERR("get_dma fail\n");
|
|
mutex_unlock(&(Mutexgkibuf));
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
mfb_maptable.buf_pa =
|
|
(unsigned int)sg_dma_address((pUserInfo->gkiBuf[i].sgt)->sgl);
|
|
qq_get_cnt++;
|
|
LOG_DBG("qq_get_cnt = %d pa = 0x%lx\n", qq_get_cnt, mfb_maptable.buf_pa);
|
|
mutex_unlock(&(Mutexgkibuf));
|
|
} else {
|
|
LOG_ERR("MFB_MAP copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
return mfb_maptable.buf_pa;
|
|
break;
|
|
}
|
|
case MFB_UNMAP:
|
|
{
|
|
if (copy_from_user(&mfb_maptable, (void *)Param,
|
|
sizeof(struct MFB_MapTable)) == 0) {
|
|
|
|
if (mfb_maptable.buf_fd == 0) {
|
|
LOG_ERR("buf_fd equal 0\n");
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
mutex_lock(&(Mutexgkibuf));
|
|
for (i = 0; i < GKI_BUF_NUM_MAX; i++) {
|
|
if (pUserInfo->gkiBuf[i].bfd == mfb_maptable.buf_fd) {
|
|
if (pUserInfo->gkiBuf[i].isUse == 1) {
|
|
pUserInfo->gkiBuf[i].isUse = 0;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (i == GKI_BUF_NUM_MAX) {
|
|
LOG_ERR("gkiBuf full\n");
|
|
mutex_unlock(&(Mutexgkibuf));
|
|
Ret = -EFAULT;
|
|
goto EXIT;
|
|
}
|
|
mfb_put_dma_buf(&pUserInfo->gkiBuf[i]);
|
|
mutex_unlock(&(Mutexgkibuf));
|
|
qq_put_cnt++;
|
|
LOG_DBG("qq_put_cnt = %d\n", qq_put_cnt);
|
|
} else {
|
|
LOG_ERR("MFB_MAP copy_from_user failed\n");
|
|
Ret = -EFAULT;
|
|
}
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
LOG_ERR("Unknown Cmd(%d)", Cmd);
|
|
LOG_ERR(
|
|
"Fail, Cmd(%d), Dir(%d), Type(%d), Nr(%d),Size(%d)\n",
|
|
Cmd, _IOC_DIR(Cmd),
|
|
_IOC_TYPE(Cmd), _IOC_NR(Cmd), _IOC_SIZE(Cmd));
|
|
Ret = -EPERM;
|
|
break;
|
|
}
|
|
}
|
|
EXIT:
|
|
if (Ret != 0) {
|
|
LOG_ERR(
|
|
"Fail, Cmd(%d), Pid(%d), (process, pid, tgid)=(%s, %d, %d)",
|
|
Cmd,
|
|
pUserInfo->Pid, current->comm,
|
|
current->pid, current->tgid);
|
|
}
|
|
return Ret;
|
|
}
|
|
|
|
#ifdef CONFIG_COMPAT
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static int compat_get_MFB_read_register_data(
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32,
|
|
struct MFB_REG_IO_STRUCT __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
compat_uptr_t uptr;
|
|
int err;
|
|
|
|
err = get_user(uptr, &data32->pData);
|
|
err |= put_user(compat_ptr(uptr), &data->pData);
|
|
err |= get_user(count, &data32->Count);
|
|
err |= put_user(count, &data->Count);
|
|
return err;
|
|
}
|
|
|
|
static int compat_put_MFB_read_register_data(
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32,
|
|
struct MFB_REG_IO_STRUCT __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
/*compat_uptr_t uptr;*/
|
|
int err = 0;
|
|
/* Assume data pointer is unchanged. */
|
|
/* err = get_user(compat_ptr(uptr), &data->pData); */
|
|
/* err |= put_user(uptr, &data32->pData); */
|
|
err |= get_user(count, &data->Count);
|
|
err |= put_user(count, &data32->Count);
|
|
return err;
|
|
}
|
|
|
|
static int compat_get_MFB_mss_enque_req_data(
|
|
struct compat_MFB_MSSRequest __user *data32,
|
|
struct MFB_MSSRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
compat_uptr_t uptr;
|
|
int err = 0;
|
|
|
|
err = get_user(uptr, &data32->m_pMssConfig);
|
|
err |= put_user(compat_ptr(uptr), &data->m_pMssConfig);
|
|
err |= get_user(count, &data32->m_ReqNum);
|
|
err |= put_user(count, &data->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_put_MFB_mss_enque_req_data(
|
|
struct compat_MFB_MSSRequest __user *data32,
|
|
struct MFB_MSSRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
/*compat_uptr_t uptr;*/
|
|
int err = 0;
|
|
/* Assume data pointer is unchanged. */
|
|
/* err = get_user(compat_ptr(uptr), &data->m_pMssConfig); */
|
|
/* err |= put_user(uptr, &data32->m_pMssConfig); */
|
|
err |= get_user(count, &data->m_ReqNum);
|
|
err |= put_user(count, &data32->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_get_MFB_mss_deque_req_data(
|
|
struct compat_MFB_MSSRequest __user *data32,
|
|
struct MFB_MSSRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
compat_uptr_t uptr;
|
|
int err = 0;
|
|
|
|
err = get_user(uptr, &data32->m_pMssConfig);
|
|
err |= put_user(compat_ptr(uptr), &data->m_pMssConfig);
|
|
err |= get_user(count, &data32->m_ReqNum);
|
|
err |= put_user(count, &data->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_put_MFB_mss_deque_req_data(
|
|
struct compat_MFB_MSSRequest __user *data32,
|
|
struct MFB_MSSRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
/*compat_uptr_t uptr;*/
|
|
int err = 0;
|
|
/* Assume data pointer is unchanged. */
|
|
/* err = get_user(compat_ptr(uptr), &data->m_pMssConfig); */
|
|
/* err |= put_user(uptr, &data32->m_pMssConfig); */
|
|
err |= get_user(count, &data->m_ReqNum);
|
|
err |= put_user(count, &data32->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
static int compat_get_MFB_msf_enque_req_data(
|
|
struct compat_MFB_MSFRequest __user *data32,
|
|
struct MFB_MSFRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
compat_uptr_t uptr;
|
|
int err = 0;
|
|
|
|
err = get_user(uptr, &data32->m_pMsfConfig);
|
|
err |= put_user(compat_ptr(uptr), &data->m_pMsfConfig);
|
|
err |= get_user(count, &data32->m_ReqNum);
|
|
err |= put_user(count, &data->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_put_MFB_msf_enque_req_data(
|
|
struct compat_MFB_MSFRequest __user *data32,
|
|
struct MFB_MSFRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
/*compat_uptr_t uptr;*/
|
|
int err = 0;
|
|
/* Assume data pointer is unchanged. */
|
|
/* err = get_user(compat_ptr(uptr), &data->m_pMsfConfig); */
|
|
/* err |= put_user(uptr, &data32->m_pMsfConfig); */
|
|
err |= get_user(count, &data->m_ReqNum);
|
|
err |= put_user(count, &data32->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_get_MFB_msf_deque_req_data(
|
|
struct compat_MFB_MSFRequest __user *data32,
|
|
struct MFB_MSFRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
compat_uptr_t uptr;
|
|
int err = 0;
|
|
|
|
err = get_user(uptr, &data32->m_pMsfConfig);
|
|
err |= put_user(compat_ptr(uptr), &data->m_pMsfConfig);
|
|
err |= get_user(count, &data32->m_ReqNum);
|
|
err |= put_user(count, &data->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
|
|
static int compat_put_MFB_msf_deque_req_data(
|
|
struct compat_MFB_MSFRequest __user *data32,
|
|
struct MFB_MSFRequest __user *data)
|
|
{
|
|
compat_uint_t count;
|
|
/*compat_uptr_t uptr;*/
|
|
int err = 0;
|
|
/* Assume data pointer is unchanged. */
|
|
/* err = get_user(compat_ptr(uptr), &data->m_pMsfConfig); */
|
|
/* err |= put_user(uptr, &data32->m_pMsfConfig); */
|
|
err |= get_user(count, &data->m_ReqNum);
|
|
err |= put_user(count, &data32->m_ReqNum);
|
|
return err;
|
|
}
|
|
|
|
static long MFB_ioctl_compat(struct file *filp,
|
|
unsigned int cmd, unsigned long arg)
|
|
{
|
|
long ret;
|
|
|
|
|
|
if (!filp->f_op || !filp->f_op->unlocked_ioctl) {
|
|
LOG_ERR("no f_op !!!\n");
|
|
return -ENOTTY;
|
|
}
|
|
switch (cmd) {
|
|
case COMPAT_MFB_MSS_READ_REGISTER:
|
|
{
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32;
|
|
struct MFB_REG_IO_STRUCT __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"compat_get_MFB_MSS_read_register_data error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp,
|
|
MFB_MSS_READ_REGISTER, (unsigned long)data);
|
|
err = compat_put_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"compat_put_MFB_MSS_read_register_data error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSF_READ_REGISTER:
|
|
{
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32;
|
|
struct MFB_REG_IO_STRUCT __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"compat_get_MFB_read_register_data error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp,
|
|
MFB_MSF_READ_REGISTER, (unsigned long)data);
|
|
err = compat_put_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"compat_put_MFB_read_register_data error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSS_WRITE_REGISTER:
|
|
{
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32;
|
|
struct MFB_REG_IO_STRUCT __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"COMPAT_MFB_MSS_WRITE_REGISTER error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp,
|
|
MFB_MSS_WRITE_REGISTER, (unsigned long)data);
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSF_WRITE_REGISTER:
|
|
{
|
|
struct compat_MFB_REG_IO_STRUCT __user *data32;
|
|
struct MFB_REG_IO_STRUCT __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_read_register_data(data32, data);
|
|
if (err) {
|
|
LOG_INF(
|
|
"COMPAT_MFB_MSF_WRITE_REGISTER error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp,
|
|
MFB_MSF_WRITE_REGISTER, (unsigned long)data);
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSS_ENQUE_REQ:
|
|
{
|
|
struct compat_MFB_MSSRequest __user *data32;
|
|
struct MFB_MSSRequest __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_mss_enque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSS_ENQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp, MFB_MSS_ENQUE_REQ,
|
|
(unsigned long)data);
|
|
err = compat_put_MFB_mss_enque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSS_ENQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSS_DEQUE_REQ:
|
|
{
|
|
struct compat_MFB_MSSRequest __user *data32;
|
|
struct MFB_MSSRequest __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_mss_deque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSS_DEQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp, MFB_MSS_DEQUE_REQ,
|
|
(unsigned long)data);
|
|
err = compat_put_MFB_mss_deque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSS_DEQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
case COMPAT_MFB_MSF_ENQUE_REQ:
|
|
{
|
|
struct compat_MFB_MSFRequest __user *data32;
|
|
struct MFB_MSFRequest __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_msf_enque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSF_ENQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp, MFB_MSF_ENQUE_REQ,
|
|
(unsigned long)data);
|
|
err = compat_put_MFB_msf_enque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSF_ENQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
case COMPAT_MFB_MSF_DEQUE_REQ:
|
|
{
|
|
struct compat_MFB_MSFRequest __user *data32;
|
|
struct MFB_MSFRequest __user *data;
|
|
int err;
|
|
|
|
data32 = compat_ptr(arg);
|
|
data = compat_alloc_user_space(sizeof(*data));
|
|
if (data == NULL)
|
|
return -EFAULT;
|
|
|
|
err = compat_get_MFB_msf_deque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSF_DEQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
ret =
|
|
filp->f_op->unlocked_ioctl(filp, MFB_MSF_DEQUE_REQ,
|
|
(unsigned long)data);
|
|
err = compat_put_MFB_msf_deque_req_data(data32, data);
|
|
if (err) {
|
|
LOG_INF("COMPAT_MFB_MSF_DEQUE_REQ error!!!\n");
|
|
return err;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
case MFB_MSS_WAIT_IRQ:
|
|
case MFB_MSF_WAIT_IRQ:
|
|
case MFB_MSS_CLEAR_IRQ: /* structure (no pointer) */
|
|
case MFB_MSF_CLEAR_IRQ: /* structure (no pointer) */
|
|
case MFB_MSS_RESET:
|
|
case MFB_MSF_RESET:
|
|
case MFB_MSS_DUMP_REG:
|
|
case MFB_MSF_DUMP_REG:
|
|
case MFB_MSS_DUMP_ISR_LOG:
|
|
case MFB_MSF_DUMP_ISR_LOG:
|
|
return filp->f_op->unlocked_ioctl(filp, cmd, arg);
|
|
default:
|
|
return -ENOIOCTLCMD;
|
|
/* return MFB_ioctl(filep, cmd, arg); */
|
|
}
|
|
}
|
|
|
|
#endif
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MFB_open(struct inode *pInode, struct file *pFile)
|
|
{
|
|
signed int Ret = 0, i = 0;
|
|
/*int q = 0, p = 0;*/
|
|
struct MFB_USER_INFO_STRUCT *pUserInfo = NULL;
|
|
unsigned long flags;
|
|
|
|
LOG_DBG("- E. UserCount: %d.", MFBInfo.UserCount);
|
|
|
|
|
|
mutex_lock(&(MutexMFBRef));
|
|
|
|
pFile->private_data = NULL;
|
|
pFile->private_data =
|
|
kmalloc(sizeof(struct MFB_USER_INFO_STRUCT), GFP_ATOMIC);
|
|
if (pFile->private_data == NULL) {
|
|
LOG_DBG(
|
|
"ERROR: kmalloc failed, (process, pid, tgid)=(%s, %d, %d)",
|
|
current->comm,
|
|
current->pid,
|
|
current->tgid);
|
|
Ret = -ENOMEM;
|
|
mutex_unlock(&(MutexMFBRef));
|
|
goto EXIT;
|
|
} else {
|
|
pUserInfo = (struct MFB_USER_INFO_STRUCT *) pFile->private_data;
|
|
pUserInfo->Tid = current->tgid;
|
|
pUserInfo->streamtag = MFB_PROCESS_ID_NONE;
|
|
}
|
|
if (MFBInfo.UserCount > 0) {
|
|
MFBInfo.UserCount++;
|
|
for (i = 0; i < IRQ_USER_NUM_MAX; i++) {
|
|
if (MFBInfo.IrqInfo.MssIrqUse[i] == -1)
|
|
break;
|
|
}
|
|
if (i == IRQ_USER_NUM_MAX) {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_DBG("ERROR: MssIrqUse is full (%d)", i);
|
|
goto EXIT;
|
|
}
|
|
MFBInfo.IrqInfo.MssIrqUse[i] = 1;
|
|
pUserInfo->Pid = i;
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_DBG(
|
|
"Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), users exist",
|
|
MFBInfo.UserCount, current->comm,
|
|
current->pid, current->tgid);
|
|
goto EXIT;
|
|
} else {
|
|
MFBInfo.UserCount++;
|
|
|
|
for (i = 0; i < IRQ_USER_NUM_MAX; i++) {
|
|
MFBInfo.IrqInfo.MssIrqCnt[i] = 0;
|
|
MFBInfo.IrqInfo.MsfIrqCnt[i] = 0;
|
|
MFBInfo.IrqInfo.MssIrqUse[i] = -1;
|
|
}
|
|
MFBInfo.IrqInfo.MssIrqUse[0] = 1;
|
|
pUserInfo->Pid = 0;
|
|
//gki
|
|
for (i = 0; i < GKI_BUF_NUM_MAX; i++)
|
|
pUserInfo->gkiBuf[i].isUse = 0;
|
|
qq_get_cnt = 0;
|
|
qq_put_cnt = 0;
|
|
|
|
mfb_register_requests(&mss_reqs, sizeof(struct MFB_MSSConfig));
|
|
mfb_set_engine_ops(&mss_reqs, &mss_ops);
|
|
mfb_register_requests(&vmss_reqs, sizeof(struct MFB_MSSConfig));
|
|
mfb_set_engine_ops(&vmss_reqs, &vmss_ops);
|
|
|
|
mfb_register_requests(&msf_reqs, sizeof(struct MFB_MSFConfig));
|
|
mfb_set_engine_ops(&msf_reqs, &msf_ops);
|
|
mfb_register_requests(&vmsf_reqs, sizeof(struct MFB_MSFConfig));
|
|
mfb_set_engine_ops(&vmsf_reqs, &vmsf_ops);
|
|
|
|
#ifdef MFB_PMQOS
|
|
qos_total = 0;
|
|
for (i = 0; i < 4; i++)
|
|
qos_scen[i] = 0;
|
|
#endif
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_INF(
|
|
"%s + 1st UserCount(%d), (process, pid, tgid)=(%s, %d, %d)",
|
|
__func__, MFBInfo.UserCount, current->comm,
|
|
current->pid, current->tgid);
|
|
}
|
|
|
|
/* Enable clock */
|
|
MFB_EnableClock(MTRUE);
|
|
g_SuspendCnt = 0;
|
|
LOG_INF("MFB open g_u4EnableClockCount: %d", g_u4EnableClockCount);
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]), flags);
|
|
MFBInfo.IrqInfo.Status[MFB_IRQ_TYPE_INT_MSS_ST] = 0;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]), flags);
|
|
|
|
spin_lock_irqsave(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]), flags);
|
|
MFBInfo.IrqInfo.Status[MFB_IRQ_TYPE_INT_MSF_ST] = 0;
|
|
spin_unlock_irqrestore(
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]), flags);
|
|
|
|
#ifdef KERNEL_LOG
|
|
/* In EP, Add MFB_DBG_WRITE_REG for debug. Should remove it after EP */
|
|
MFBInfo.DebugMaskMss =
|
|
(MFB_DBG_INT | MFB_DBG_DBGLOG | MFB_DBG_WRITE_REG);
|
|
MFBInfo.DebugMaskMsf =
|
|
(MFB_DBG_INT | MFB_DBG_DBGLOG | MFB_DBG_WRITE_REG);
|
|
#endif
|
|
|
|
EXIT:
|
|
LOG_DBG("- X. Ret: %d. UserCount: %d.", Ret, MFBInfo.UserCount);
|
|
return Ret;
|
|
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MFB_release(struct inode *pInode, struct file *pFile)
|
|
{
|
|
struct MFB_USER_INFO_STRUCT *pUserInfo = NULL;
|
|
/*unsigned int Reg;*/
|
|
|
|
LOG_DBG("- E. UserCount: %d.", MFBInfo.UserCount);
|
|
|
|
if (pFile->private_data != NULL)
|
|
pUserInfo = (struct MFB_USER_INFO_STRUCT *) pFile->private_data;
|
|
else
|
|
goto EXIT;
|
|
|
|
mutex_lock(&(MutexMFBRef));
|
|
MFBInfo.UserCount--;
|
|
MFBInfo.IrqInfo.MssIrqUse[pUserInfo->Pid] = -1;
|
|
|
|
if (MFBInfo.UserCount > 0) {
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_DBG(
|
|
"Curr UserCount(%d), (process, pid, tgid)=(%s, %d, %d), users exist",
|
|
MFBInfo.UserCount, current->comm,
|
|
current->pid, current->tgid);
|
|
|
|
if (pFile->private_data != NULL) {
|
|
kfree(pFile->private_data);
|
|
pFile->private_data = NULL;
|
|
}
|
|
goto EXIT;
|
|
} else {
|
|
mfb_unregister_requests(&mss_reqs);
|
|
mfb_unregister_requests(&msf_reqs);
|
|
mfb_unregister_requests(&vmss_reqs);
|
|
mfb_unregister_requests(&vmsf_reqs);
|
|
|
|
mutex_unlock(&(MutexMFBRef));
|
|
LOG_INF(
|
|
"%s - last UserCount(%d), (process, pid, tgid)=(%s, %d, %d)",
|
|
__func__, MFBInfo.UserCount, current->comm,
|
|
current->pid, current->tgid);
|
|
|
|
if (pFile->private_data != NULL) {
|
|
kfree(pFile->private_data);
|
|
pFile->private_data = NULL;
|
|
}
|
|
}
|
|
|
|
/* Disable clock. */
|
|
MFB_EnableClock(MFALSE);
|
|
LOG_DBG("MFB release g_u4EnableClockCount: %d", g_u4EnableClockCount);
|
|
|
|
EXIT:
|
|
|
|
LOG_DBG("- X. UserCount: %d.", MFBInfo.UserCount);
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
|
|
static dev_t MFBDevNo;
|
|
static struct cdev *pMFBCharDrv;
|
|
static struct class *pMFBClass;
|
|
|
|
static const struct file_operations MFBFileOper = {
|
|
.owner = THIS_MODULE,
|
|
.open = MFB_open,
|
|
.release = MFB_release,
|
|
/* .flush = mt_MFB_flush, */
|
|
/* .mmap = MFB_mmap, */
|
|
.unlocked_ioctl = MFB_ioctl,
|
|
#ifdef CONFIG_COMPAT
|
|
.compat_ioctl = MFB_ioctl_compat,
|
|
#endif
|
|
};
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline void MFB_UnregCharDev(void)
|
|
{
|
|
LOG_DBG("- E.");
|
|
/* Release char driver */
|
|
if (pMFBCharDrv != NULL) {
|
|
cdev_del(pMFBCharDrv);
|
|
pMFBCharDrv = NULL;
|
|
}
|
|
unregister_chrdev_region(MFBDevNo, 1);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static inline signed int MFB_RegCharDev(void)
|
|
{
|
|
signed int Ret = 0;
|
|
|
|
LOG_DBG("- E.");
|
|
Ret = alloc_chrdev_region(&MFBDevNo, 0, 1, MFB_DEV_NAME);
|
|
if (Ret < 0) {
|
|
LOG_ERR("alloc_chrdev_region failed, %d", Ret);
|
|
return Ret;
|
|
}
|
|
/* Allocate driver */
|
|
pMFBCharDrv = cdev_alloc();
|
|
if (pMFBCharDrv == NULL) {
|
|
LOG_ERR("cdev_alloc failed");
|
|
Ret = -ENOMEM;
|
|
goto EXIT;
|
|
}
|
|
/* Attatch file operation. */
|
|
cdev_init(pMFBCharDrv, &MFBFileOper);
|
|
pMFBCharDrv->owner = THIS_MODULE;
|
|
/* Add to system */
|
|
Ret = cdev_add(pMFBCharDrv, MFBDevNo, 1);
|
|
if (Ret < 0) {
|
|
LOG_ERR("Attatch file operation failed, %d", Ret);
|
|
goto EXIT;
|
|
}
|
|
EXIT:
|
|
if (Ret < 0)
|
|
MFB_UnregCharDev();
|
|
|
|
LOG_DBG("- X.");
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MFB_probe(struct platform_device *pDev)
|
|
{
|
|
signed int Ret = 0;
|
|
/*struct resource *pRes = NULL;*/
|
|
signed int i = 0;
|
|
unsigned char n;
|
|
unsigned int irq_info[3];/* Record interrupts info from device tree */
|
|
struct device *dev = NULL;
|
|
struct MFB_device *_mfb_dev = NULL;
|
|
struct device_node *node;
|
|
struct platform_device *pdev;
|
|
|
|
#ifdef CONFIG_OF
|
|
struct MFB_device *MFB_dev;
|
|
#endif
|
|
|
|
LOG_INF("- E. MFB driver probe. nr_MFB_devs : %d.", nr_MFB_devs);
|
|
|
|
/* Check platform_device parameters */
|
|
#ifdef CONFIG_OF
|
|
|
|
if (pDev == NULL) {
|
|
dev_dbg(&pDev->dev, "pDev is NULL");
|
|
return -ENXIO;
|
|
}
|
|
|
|
nr_MFB_devs += 1;
|
|
_mfb_dev = krealloc(MFB_devs,
|
|
sizeof(struct MFB_device) * nr_MFB_devs, GFP_KERNEL);
|
|
if (!_mfb_dev) {
|
|
dev_dbg(&pDev->dev, "Unable to allocate MFB_devs\n");
|
|
return -ENOMEM;
|
|
}
|
|
MFB_devs = _mfb_dev;
|
|
|
|
MFB_dev = &(MFB_devs[nr_MFB_devs - 1]);
|
|
MFB_dev->dev = &pDev->dev;
|
|
|
|
/* iomap registers */
|
|
MFB_dev->regs = of_iomap(pDev->dev.of_node, 0);
|
|
/* gISPSYS_Reg[nr_MFB_devs - 1] = MFB_dev->regs; */
|
|
|
|
if (!MFB_dev->regs) {
|
|
dev_dbg(&pDev->dev,
|
|
"Unable to ioremap registers, of_iomap fail, nr_MFB_devs=%d, devnode(%s).\n",
|
|
nr_MFB_devs, pDev->dev.of_node->name);
|
|
return -ENOMEM;
|
|
}
|
|
|
|
#if defined(CONFIG_MTK_IOMMU_PGTABLE_EXT) && \
|
|
(CONFIG_MTK_IOMMU_PGTABLE_EXT > 32)
|
|
*(MFB_dev->dev->dma_mask) =
|
|
(u64)DMA_BIT_MASK(CONFIG_MTK_IOMMU_PGTABLE_EXT);
|
|
MFB_dev->dev->coherent_dma_mask =
|
|
(u64)DMA_BIT_MASK(CONFIG_MTK_IOMMU_PGTABLE_EXT);
|
|
#endif
|
|
LOG_INF("nr_MFB_devs=%d, devnode(%s), map_addr=0x%lx\n", nr_MFB_devs,
|
|
pDev->dev.of_node->name, (unsigned long)MFB_dev->regs);
|
|
|
|
/* get IRQ ID and request IRQ */
|
|
MFB_dev->irq = irq_of_parse_and_map(pDev->dev.of_node, 0);
|
|
|
|
if (MFB_dev->irq > 0) {
|
|
/* Get IRQ Flag from device node */
|
|
if (of_property_read_u32_array(
|
|
pDev->dev.of_node, "interrupts",
|
|
irq_info, ARRAY_SIZE(irq_info))) {
|
|
dev_dbg(&pDev->dev, "get irq flags from DTS fail!!\n");
|
|
return -ENODEV;
|
|
}
|
|
|
|
for (i = 0; i < MFB_IRQ_TYPE_AMOUNT; i++) {
|
|
if (strcmp(pDev->dev.of_node->name,
|
|
MFB_IRQ_CB_TBL[i].device_name) == 0) {
|
|
Ret = request_irq(MFB_dev->irq,
|
|
(irq_handler_t) MFB_IRQ_CB_TBL[i].isr_fp,
|
|
irq_info[2],
|
|
(const char *)MFB_IRQ_CB_TBL[i].device_name,
|
|
NULL);
|
|
|
|
if (Ret) {
|
|
dev_dbg(&pDev->dev,
|
|
"Unable to request IRQ, request_irq fail, nr_MFB_devs=%d, devnode(%s), irq=%d, ISR: %s\n",
|
|
nr_MFB_devs,
|
|
pDev->dev.of_node->name,
|
|
MFB_dev->irq,
|
|
MFB_IRQ_CB_TBL[i].device_name);
|
|
return Ret;
|
|
}
|
|
|
|
LOG_INF(
|
|
"nr_MFB_devs=%d, devnode(%s), irq=%d, ISR: %s\n",
|
|
nr_MFB_devs, pDev->dev.of_node->name,
|
|
MFB_dev->irq,
|
|
MFB_IRQ_CB_TBL[i].device_name);
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (i >= MFB_IRQ_TYPE_AMOUNT) {
|
|
LOG_INF(
|
|
"No corresponding ISR!!: nr_MFB_devs=%d, devnode(%s), irq=%d\n",
|
|
nr_MFB_devs, pDev->dev.of_node->name,
|
|
MFB_dev->irq);
|
|
}
|
|
|
|
|
|
} else {
|
|
LOG_INF("No IRQ!!: nr_MFB_devs=%d, devnode(%s), irq=%d\n",
|
|
nr_MFB_devs,
|
|
pDev->dev.of_node->name, MFB_dev->irq);
|
|
}
|
|
#ifdef CMDQ_COMMON
|
|
/*cmdq*/
|
|
MFB_cmdq_dev = &pDev->dev;
|
|
if (nr_MFB_devs == 2) {
|
|
mss_clt = cmdq_mbox_create(MFB_cmdq_dev, 0);
|
|
LOG_INF("mss_clt: 0x%p\n", mss_clt);
|
|
of_property_read_u16(MFB_cmdq_dev->of_node,
|
|
"mss_frame_done", &mss_done_event_id);
|
|
of_property_read_u16(MFB_cmdq_dev->of_node,
|
|
"mss_token", &mss_token_id);
|
|
|
|
}
|
|
if (nr_MFB_devs == 1) {
|
|
msf_clt = cmdq_mbox_create(MFB_cmdq_dev, 0);
|
|
LOG_INF("msf_clt: 0x%p\n", msf_clt);
|
|
of_property_read_u16(MFB_cmdq_dev->of_node,
|
|
"msf_frame_done", &msf_done_event_id);
|
|
of_property_read_u16(MFB_cmdq_dev->of_node,
|
|
"msf_token", &msf_token_id);
|
|
}
|
|
#endif
|
|
#endif
|
|
|
|
/* Only register char driver in the 1st time */
|
|
if (nr_MFB_devs == 1) {/*YWtodo*/
|
|
|
|
/* Register char driver */
|
|
Ret = MFB_RegCharDev();
|
|
if (Ret) {
|
|
dev_dbg(&pDev->dev, "register char failed");
|
|
return Ret;
|
|
}
|
|
#ifndef __MFB_EP_NO_CLKMGR__
|
|
#if !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) /*CCF*/
|
|
/*CCF: Grab clock pointer (struct clk*) */
|
|
#ifdef CLK_COMMON
|
|
#if (MTK_MFB_REG_VERSION == 3)
|
|
mfb_clk.CG_IMG2_LARB11 = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_LARB11");
|
|
mfb_clk.CG_IMG2_MSS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_MSS");
|
|
mfb_clk.CG_IMG2_MFB = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_MFB");
|
|
mfb_clk.CG_IMG2_GALS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_GALS");
|
|
mfb_clk.CG_IMG1_GALS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG1_GALS");
|
|
|
|
if (IS_ERR(mfb_clk.CG_IMG2_LARB11)) {
|
|
LOG_ERR("cannot get CG_IMG2_LARB11 clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_LARB11);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_MSS)) {
|
|
LOG_ERR("cannot get CG_IMG2_MSS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_MSS);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_MFB)) {
|
|
LOG_ERR("cannot get CG_IMG2_MFB clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_MFB);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_GALS)) {
|
|
LOG_ERR("cannot get CG_IMG2_GALS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_GALS);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG1_GALS)) {
|
|
LOG_ERR("cannot get CG_IMG1_GALS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG1_GALS);
|
|
}
|
|
#elif (MTK_MFB_REG_VERSION == 2)
|
|
mfb_clk.CG_IMG2_LARB11 = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_LARB11");
|
|
mfb_clk.CG_IMG2_MSS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_MSS");
|
|
mfb_clk.CG_IMG2_MFB = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_MFB");
|
|
mfb_clk.CG_IMG2_GALS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG2_GALS");
|
|
|
|
if (IS_ERR(mfb_clk.CG_IMG2_LARB11)) {
|
|
LOG_ERR("cannot get CG_IMG2_LARB11 clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_LARB11);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_MSS)) {
|
|
LOG_ERR("cannot get CG_IMG2_MSS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_MSS);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_MFB)) {
|
|
LOG_ERR("cannot get CG_IMG2_MFB clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_MFB);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG2_GALS)) {
|
|
LOG_ERR("cannot get CG_IMG2_GALS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG2_GALS);
|
|
}
|
|
#else
|
|
mfb_clk.CG_IMG1_LARB9 = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG1_LARB9");
|
|
mfb_clk.CG_IMG1_MSS = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG1_MSS");
|
|
mfb_clk.CG_IMG1_MFB = devm_clk_get(&pDev->dev,
|
|
"MFB_CG_IMG1_MFB");
|
|
|
|
if (IS_ERR(mfb_clk.CG_IMG1_LARB9)) {
|
|
LOG_ERR("cannot get CG_IMG1_LARB9 clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG1_LARB9);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG1_MSS)) {
|
|
LOG_ERR("cannot get CG_IMG1_MSS clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG1_MSS);
|
|
}
|
|
if (IS_ERR(mfb_clk.CG_IMG1_MFB)) {
|
|
LOG_ERR("cannot get CG_IMG1_MFB clock\n");
|
|
return PTR_ERR(mfb_clk.CG_IMG1_MFB);
|
|
}
|
|
#endif
|
|
#endif
|
|
#endif /* !defined(CONFIG_MTK_LEGACY) && defined(CONFIG_COMMON_CLK) */
|
|
#endif
|
|
/*gki iommu*/
|
|
dma_set_mask_and_coherent(MFB_dev->dev, DMA_BIT_MASK(34));
|
|
/*gki pm*/
|
|
pm_runtime_enable(MFB_dev->dev);
|
|
if (!pm_runtime_enabled(MFB_dev->dev))
|
|
goto EXIT;
|
|
/*gki smi larb*/
|
|
node = of_parse_phandle(MFB_dev->dev->of_node, "mediatek,larb", 0);
|
|
if (!node)
|
|
return -EINVAL;
|
|
pdev = of_find_device_by_node(node);
|
|
if (WARN_ON(!pdev)) {
|
|
of_node_put(node);
|
|
return -EINVAL;
|
|
}
|
|
of_node_put(node);
|
|
MFB_dev->larb = &pdev->dev;
|
|
|
|
/* Create class register */
|
|
pMFBClass = class_create(THIS_MODULE, "MFBdrv");
|
|
if (IS_ERR(pMFBClass)) {
|
|
Ret = PTR_ERR(pMFBClass);
|
|
LOG_ERR("Unable to create class, err = %d", Ret);
|
|
goto EXIT;
|
|
}
|
|
|
|
dev = device_create(
|
|
pMFBClass, NULL, MFBDevNo, NULL, MFB_DEV_NAME);
|
|
|
|
if (IS_ERR(dev)) {
|
|
Ret = PTR_ERR(dev);
|
|
dev_dbg(&pDev->dev, "Failed to create device: /dev/%s, err = %d",
|
|
MFB_DEV_NAME, Ret);
|
|
goto EXIT;
|
|
}
|
|
|
|
/* Init spinlocks */
|
|
spin_lock_init(&(MFBInfo.SpinLockMFB));
|
|
for (n = 0; n < MFB_IRQ_TYPE_AMOUNT; n++)
|
|
spin_lock_init(&(MFBInfo.SpinLockIrq[n]));
|
|
#ifdef MFB_PMQOS
|
|
spin_lock_init(&(SpinLockMfbPmqos));
|
|
#endif
|
|
init_waitqueue_head(&MFBInfo.WaitQueueHeadMss);
|
|
init_waitqueue_head(&MFBInfo.WaitQueueHeadMsf);
|
|
INIT_WORK(&MFBInfo.ScheduleMssWork, MFB_ScheduleMssWork);
|
|
INIT_WORK(&MFBInfo.vmsswork, vmss_do_work);
|
|
INIT_WORK(&MFBInfo.ScheduleMsfWork, MFB_ScheduleMsfWork);
|
|
INIT_WORK(&MFBInfo.vmsfwork, vmsf_do_work);
|
|
|
|
MFBInfo.wkqueueMss =
|
|
create_singlethread_workqueue("MSS-CMDQ-WQ");
|
|
if (!MFBInfo.wkqueueMss)
|
|
LOG_ERR("NULL MSS-CMDQ-WQ\n");
|
|
MFBInfo.wkqueueMsf =
|
|
create_singlethread_workqueue("MSF-CMDQ-WQ");
|
|
if (!MFBInfo.wkqueueMsf)
|
|
LOG_ERR("NULL MSF-CMDQ-WQ\n");
|
|
#ifdef WAKE_UP
|
|
wakeup_source_init(&MSS_wake_lock, "mss_lock_wakelock");
|
|
wakeup_source_init(&MSF_wake_lock, "msf_lock_wakelock");
|
|
#endif
|
|
INIT_WORK(&logWork, logPrint);
|
|
|
|
for (i = 0; i < MFB_IRQ_TYPE_AMOUNT; i++)
|
|
tasklet_init(
|
|
MFB_tasklet[i].pMFB_tkt,
|
|
MFB_tasklet[i].tkt_cb, 0);
|
|
|
|
/* Init MFBInfo */
|
|
mutex_lock(&(MutexMFBRef));
|
|
MFBInfo.UserCount = 0;
|
|
mutex_unlock(&(MutexMFBRef));
|
|
MFBInfo.IrqInfo.Mask[MFB_IRQ_TYPE_INT_MSS_ST] = INT_ST_MASK_MSS;
|
|
MFBInfo.IrqInfo.Mask[MFB_IRQ_TYPE_INT_MSF_ST] = INT_ST_MASK_MSF;
|
|
}
|
|
|
|
seqlock_init(&(mss_reqs.seqlock));
|
|
seqlock_init(&(vmss_reqs.seqlock));
|
|
seqlock_init(&(msf_reqs.seqlock));
|
|
seqlock_init(&(vmsf_reqs.seqlock));
|
|
|
|
EXIT:
|
|
if (Ret < 0)
|
|
MFB_UnregCharDev();
|
|
|
|
|
|
LOG_INF("- X. MFB driver probe.");
|
|
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
* Called when the device is being detached from the driver
|
|
******************************************************************************/
|
|
static signed int MFB_remove(struct platform_device *pDev)
|
|
{
|
|
/*struct resource *pRes;*/
|
|
signed int IrqNum;
|
|
int i;
|
|
|
|
LOG_DBG("- E.");
|
|
|
|
destroy_workqueue(MFBInfo.wkqueueMss);
|
|
MFBInfo.wkqueueMss = NULL;
|
|
destroy_workqueue(MFBInfo.wkqueueMsf);
|
|
MFBInfo.wkqueueMsf = NULL;
|
|
|
|
/* unregister char driver. */
|
|
MFB_UnregCharDev();
|
|
|
|
/* Release IRQ */
|
|
/*disable_irq(MFBInfo.IrqNum);*//*YWtoclr*/
|
|
IrqNum = platform_get_irq(pDev, 0);
|
|
free_irq(IrqNum, NULL);
|
|
|
|
/* kill tasklet */
|
|
for (i = 0; i < MFB_IRQ_TYPE_AMOUNT; i++)
|
|
tasklet_kill(MFB_tasklet[i].pMFB_tkt);
|
|
#if CHECK_SERVICE_IF_0
|
|
/* free all registered irq(child nodes) */
|
|
MFB_UnRegister_AllregIrq();
|
|
/* free father nodes of irq user list */
|
|
struct my_list_head *head;
|
|
struct my_list_head *father;
|
|
|
|
head = ((struct my_list_head *)(&SupIrqUserListHead.list));
|
|
while (1) {
|
|
father = head;
|
|
if (father->nextirq != father) {
|
|
father = father->nextirq;
|
|
REG_IRQ_NODE *accessNode;
|
|
|
|
typeof(((REG_IRQ_NODE *) 0)->list) * __mptr = (father);
|
|
accessNode =
|
|
((REG_IRQ_NODE *) (
|
|
(char *)__mptr -
|
|
offsetof(REG_IRQ_NODE, list)));
|
|
LOG_INF("free father,reg_T(%d)\n", accessNode->reg_T);
|
|
if (father->nextirq != father) {
|
|
head->nextirq = father->nextirq;
|
|
father->nextirq = father;
|
|
} else { /* last father node */
|
|
head->nextirq = head;
|
|
LOG_INF("break\n");
|
|
break;
|
|
}
|
|
kfree(accessNode);
|
|
}
|
|
}
|
|
#endif
|
|
device_destroy(pMFBClass, MFBDevNo);
|
|
class_destroy(pMFBClass);
|
|
pMFBClass = NULL;
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int bPass1_On_In_Resume_TG1;/*YWtodo*/
|
|
|
|
static signed int MFB_suspend(struct platform_device *pDev, pm_message_t Mesg)
|
|
{
|
|
/*signed int ret = 0;*/
|
|
|
|
if (g_u4EnableClockCount > 0) {
|
|
MFB_EnableClock(MFALSE);
|
|
g_SuspendCnt++;
|
|
}
|
|
bPass1_On_In_Resume_TG1 = 0;
|
|
LOG_DBG("%s:g_u4EnableClockCount(%d) g_SuspendCnt(%d).\n", __func__,
|
|
g_u4EnableClockCount, g_SuspendCnt);
|
|
|
|
|
|
return 0;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static signed int MFB_resume(struct platform_device *pDev)
|
|
{
|
|
LOG_DBG("bPass1_On_In_Resume_TG1(%d).\n", bPass1_On_In_Resume_TG1);
|
|
if (g_SuspendCnt > 0) {
|
|
MFB_EnableClock(MTRUE);
|
|
g_SuspendCnt--;
|
|
}
|
|
LOG_DBG("%s:g_u4EnableClockCount(%d) g_SuspendCnt(%d).\n", __func__,
|
|
g_u4EnableClockCount, g_SuspendCnt);
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#ifdef CONFIG_PM
|
|
/*---------------------------------------------------------------------------*/
|
|
int MFB_pm_suspend(struct device *device)
|
|
{
|
|
struct platform_device *pdev = to_platform_device(device);
|
|
|
|
WARN_ON(pdev == NULL);
|
|
|
|
LOG_DBG("calling %s()\n", __func__);
|
|
|
|
return MFB_suspend(pdev, PMSG_SUSPEND);
|
|
}
|
|
|
|
int MFB_pm_resume(struct device *device)
|
|
{
|
|
struct platform_device *pdev = to_platform_device(device);
|
|
|
|
WARN_ON(pdev == NULL);
|
|
|
|
LOG_DBG("calling %s()\n", __func__);
|
|
|
|
return MFB_resume(pdev);
|
|
}
|
|
#ifndef CONFIG_OF
|
|
/* extern void mt_irq_set_sens(unsigned int irq, unsigned int sens); */
|
|
/* extern void mt_irq_set_polarity(unsigned int irq, unsigned int polarity); */
|
|
#endif
|
|
int MFB_pm_restore_noirq(struct device *device)
|
|
{
|
|
pr_debug("calling %s()\n", __func__);
|
|
#ifndef CONFIG_OF
|
|
mt_irq_set_sens(MFB_IRQ_BIT_ID, MT_LEVEL_SENSITIVE);
|
|
mt_irq_set_polarity(MFB_IRQ_BIT_ID, MT_POLARITY_LOW);
|
|
#endif
|
|
return 0;
|
|
|
|
}
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
#else /*CONFIG_PM */
|
|
/*---------------------------------------------------------------------------*/
|
|
#define MFB_pm_suspend NULL
|
|
#define MFB_pm_resume NULL
|
|
#define MFB_pm_restore_noirq NULL
|
|
/*---------------------------------------------------------------------------*/
|
|
#endif /*CONFIG_PM */
|
|
/*---------------------------------------------------------------------------*/
|
|
#ifdef CONFIG_OF
|
|
/*
|
|
* Note!!! The order and member of .compatible must be the same with that in
|
|
* "MFB_DEV_NODE_ENUM" in camera_MFB.h
|
|
*/
|
|
#if (MTK_MFB_REG_VERSION >= 2)
|
|
static const struct of_device_id MFB_of_ids[] = {
|
|
{.compatible = "mediatek,msf_b",},
|
|
{.compatible = "mediatek,mss_b",},
|
|
{.compatible = "mediatek,imgsys_mfb_b",},
|
|
{}
|
|
};
|
|
#else
|
|
static const struct of_device_id MFB_of_ids[] = {
|
|
{.compatible = "mediatek,msf",},
|
|
{.compatible = "mediatek,mss",},
|
|
{.compatible = "mediatek,imgsys_mfb",},
|
|
{}
|
|
};
|
|
#endif
|
|
#endif
|
|
|
|
const struct dev_pm_ops MFB_pm_ops = {
|
|
.suspend = MFB_pm_suspend,
|
|
.resume = MFB_pm_resume,
|
|
.freeze = MFB_pm_suspend,
|
|
.thaw = MFB_pm_resume,
|
|
/*.pmfbroff = MFB_pm_suspend,*//*YWtodo*/
|
|
.restore = MFB_pm_resume,
|
|
.restore_noirq = MFB_pm_restore_noirq,
|
|
};
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static struct platform_driver MFBDriver = {
|
|
.probe = MFB_probe,
|
|
.remove = MFB_remove,
|
|
.suspend = MFB_suspend,
|
|
.resume = MFB_resume,
|
|
.driver = {
|
|
.name = MFB_DEV_NAME,
|
|
.owner = THIS_MODULE,
|
|
#ifdef CONFIG_OF
|
|
.of_match_table = MFB_of_ids,
|
|
#endif
|
|
#ifdef CONFIG_PM
|
|
.pm = &MFB_pm_ops,
|
|
#endif
|
|
}
|
|
};
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
|
|
int32_t MFB_ClockOnCallback(uint64_t engineFlag)
|
|
{
|
|
/* LOG_DBG("MFB_ClockOnCallback"); */
|
|
/* LOG_DBG("+CmdqEn:%d", g_u4EnableClockCount); */
|
|
/* MFB_EnableClock(MTRUE); */
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t MFB_DumpCallback(uint64_t engineFlag, int level)
|
|
{
|
|
LOG_DBG("MFB_DumpCallback");
|
|
MSS_DumpReg();
|
|
MSF_DumpReg();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t MFB_ResetCallback(uint64_t engineFlag)
|
|
{
|
|
LOG_DBG("MSS_ResetCallback");
|
|
MSS_Reset();
|
|
MSF_Reset();
|
|
|
|
return 0;
|
|
}
|
|
|
|
int32_t MFB_ClockOffCallback(uint64_t engineFlag)
|
|
{
|
|
/* LOG_DBG("MFB_ClockOffCallback"); */
|
|
/* MFB_EnableClock(MFALSE); */
|
|
/* LOG_DBG("-CmdqEn:%d", g_u4EnableClockCount); */
|
|
return 0;
|
|
}
|
|
|
|
static signed int __init MFB_Init(void)
|
|
{
|
|
signed int Ret = 0, j;
|
|
void *tmp;
|
|
int i;
|
|
|
|
LOG_DBG("- E.");
|
|
Ret = platform_driver_register(&MFBDriver);
|
|
if (Ret < 0) {
|
|
LOG_ERR("platform_driver_register fail");
|
|
return Ret;
|
|
}
|
|
|
|
#if CHECK_SERVICE_IF_0
|
|
struct device_node *node = NULL;
|
|
|
|
node = of_find_compatible_node(NULL, NULL, "mediatek,MFB");
|
|
if (!node) {
|
|
LOG_ERR("find mediatek,MFB node failed!!!\n");
|
|
return -ENODEV;
|
|
}
|
|
ISP_MFB_BASE = of_iomap(node, 0);
|
|
if (!ISP_MFB_BASE) {
|
|
LOG_ERR("unable to map ISP_MFB_BASE registers!!!\n");
|
|
return -ENODEV;
|
|
}
|
|
LOG_DBG("ISP_MFB_BASE: %lx\n", ISP_MFB_BASE);
|
|
#endif
|
|
|
|
/* isr log */
|
|
if (PAGE_SIZE < ((MFB_IRQ_TYPE_AMOUNT * NORMAL_STR_LEN * ((
|
|
DBG_PAGE + INF_PAGE + ERR_PAGE) + 1)) * LOG_PPNUM)) {
|
|
i = 0;
|
|
while (i <
|
|
((MFB_IRQ_TYPE_AMOUNT * NORMAL_STR_LEN *
|
|
((DBG_PAGE + INF_PAGE + ERR_PAGE) + 1)) * LOG_PPNUM)) {
|
|
i += PAGE_SIZE;
|
|
}
|
|
} else {
|
|
i = PAGE_SIZE;
|
|
}
|
|
pLog_kmalloc = kmalloc(i, GFP_KERNEL);
|
|
if (pLog_kmalloc == NULL) {
|
|
LOG_ERR("log mem not enough\n");
|
|
return -ENOMEM;
|
|
}
|
|
memset(pLog_kmalloc, 0x00, i);
|
|
tmp = pLog_kmalloc;
|
|
for (i = 0; i < LOG_PPNUM; i++) {
|
|
for (j = 0; j < MFB_IRQ_TYPE_AMOUNT; j++) {
|
|
gSvLog[j]._str[i][_LOG_DBG] = (char *)tmp;
|
|
/* tmp = (void*) ((unsigned int)tmp + */
|
|
/* (NORMAL_STR_LEN*DBG_PAGE)); */
|
|
tmp = (void *)((char *)tmp +
|
|
(NORMAL_STR_LEN * DBG_PAGE));
|
|
gSvLog[j]._str[i][_LOG_INF] = (char *)tmp;
|
|
/* tmp = (void*) ((unsigned int)tmp + */
|
|
/* (NORMAL_STR_LEN*INF_PAGE)); */
|
|
tmp = (void *)((char *)tmp +
|
|
(NORMAL_STR_LEN * INF_PAGE));
|
|
gSvLog[j]._str[i][_LOG_ERR] = (char *)tmp;
|
|
/* tmp = (void*) ((unsigned int)tmp + */
|
|
/* (NORMAL_STR_LEN*ERR_PAGE)); */
|
|
tmp = (void *)((char *)tmp +
|
|
(NORMAL_STR_LEN * ERR_PAGE));
|
|
}
|
|
/* tmp = (void*) ((unsigned int)tmp + NORMAL_STR_LEN); */
|
|
/* log buffer ,in case of overflow */
|
|
tmp = (void *)((char *)tmp + NORMAL_STR_LEN);
|
|
/* log buffer ,in case of overflow */
|
|
}
|
|
|
|
/* Cmdq */
|
|
/* Register MFB callback */
|
|
LOG_DBG("register mfb callback for CMDQ");
|
|
#if CHECK_SERVICE_IF_0/*YWtodo*/
|
|
cmdqCoreRegisterCB(CMDQ_GROUP_MDP,
|
|
MFB_ClockOnCallback,
|
|
MFB_DumpCallback, MFB_ResetCallback,
|
|
MFB_ClockOffCallback);
|
|
#endif
|
|
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Init();
|
|
#endif
|
|
LOG_DBG("- X. Ret: %d.", Ret);
|
|
return Ret;
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static void __exit MFB_Exit(void)
|
|
{
|
|
/*int i;*/
|
|
|
|
LOG_DBG("- E.");
|
|
|
|
#ifdef MFB_PMQOS
|
|
MFBQOS_Uninit();
|
|
#endif
|
|
platform_driver_unregister(&MFBDriver);
|
|
/* Cmdq */
|
|
/* Unregister MFB callback */
|
|
/*cmdqCoreRegisterCB(CMDQ_GROUP_MDP, NULL, NULL, NULL, NULL);YWtodo*/
|
|
|
|
kfree(pLog_kmalloc);
|
|
}
|
|
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static void MFB_ScheduleMssWork(struct work_struct *data)
|
|
{
|
|
if (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMss)
|
|
LOG_DBG("- E.");
|
|
mfb_request_handler(&mss_reqs, &(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
if (!mfb_request_running(&mss_reqs))
|
|
LOG_DBG("[%s]no more requests", __func__);
|
|
}
|
|
|
|
static void vmss_do_work(struct work_struct *data)
|
|
{
|
|
if (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMss)
|
|
LOG_DBG("- E.");
|
|
mfb_request_handler(&vmss_reqs, &(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
if (!mfb_request_running(&vmss_reqs))
|
|
LOG_DBG("[%s]no more requests", __func__);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
static void MFB_ScheduleMsfWork(struct work_struct *data)
|
|
{
|
|
if (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMsf)
|
|
LOG_DBG("- E.");
|
|
mfb_request_handler(&msf_reqs,
|
|
&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
if (!mfb_request_running(&msf_reqs))
|
|
LOG_DBG("[%s]no more requests", __func__);
|
|
}
|
|
|
|
static void vmsf_do_work(struct work_struct *data)
|
|
{
|
|
if (MFB_DBG_DBGLOG & MFBInfo.DebugMaskMsf)
|
|
LOG_DBG("- E.");
|
|
mfb_request_handler(&vmsf_reqs, &(MFBInfo.SpinLockIrq[
|
|
MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
if (!mfb_request_running(&vmsf_reqs))
|
|
LOG_DBG("[%s]no more requests", __func__);
|
|
}
|
|
|
|
|
|
static irqreturn_t ISP_Irq_MSS(signed int Irq, void *DeviceId)
|
|
{
|
|
#if CHECK_SERVICE_IF_1
|
|
/*unsigned int MssStatus;*/
|
|
|
|
/*MssStatus = MFB_RD32(MFB_MSS_INT_STATUS_REG);*//* MSS Status */
|
|
/*MFB_WR32(MFB_MSS_INT_STATUS_REG, MssStatus);*//* MSS Status */
|
|
LOG_DBG("%s:0x%x = 0x%x ", __func__,
|
|
MFB_MSS_INT_STATUS_HW, MssStatus);
|
|
|
|
#else
|
|
unsigned int MssStatus;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
|
|
MssStatus = MFB_RD32(MFB_MSS_INT_STATUS_REG); /* MSS Status */
|
|
MFB_WR32(MFB_MSS_INT_STATUS_REG, MssStatus); /* MSS Status */
|
|
|
|
spin_lock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
if (MSS_INT_ST == (MSS_INT_ST & MssStatus)) {
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_begin("mfb_mss_irq");
|
|
#endif
|
|
|
|
if (mfb_update_request(&mss_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
/* schedule_work(&&MFBInfo.ScheduleMssWork); */
|
|
queue_work(MFBInfo.wkqueue, &MFBInfo.ScheduleMssWork);
|
|
#endif
|
|
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSS_ST] |= MSS_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessID[MFB_PROCESS_ID_MSS] = ProcessID;
|
|
MFBInfo.IrqInfo.MssIrqCnt++;
|
|
}
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_end();
|
|
#endif
|
|
}
|
|
spin_unlock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSS_ST]));
|
|
if (bResulst == MTRUE)
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMss);
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_INF,
|
|
"Irq_MSS:%d, reg 0x%x : 0x%x, bResulst:%d, MssIrqCnt:0x%x\n",
|
|
Irq, MFB_MSS_INT_STATUS_REG, MssStatus,
|
|
bResulst, MFBInfo.IrqInfo.MssIrqCnt);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
/* schedule_work(&MFBInfo.ScheduleMssWork); */
|
|
if (MSS_INT_ST == (MSS_INT_ST & MssStatus))
|
|
queue_work(MFBInfo.wkqueueMss, &MFBInfo.ScheduleMssWork);
|
|
#endif
|
|
|
|
if (MssStatus & MSS_INT_ST)
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSS_ST].pMFB_tkt);
|
|
|
|
#endif
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static irqreturn_t ISP_Irq_MSF(signed int Irq, void *DeviceId)
|
|
{
|
|
#if CHECK_SERVICE_IF_1
|
|
/*unsigned int MsfStatus;*/
|
|
|
|
/*MsfStatus = MFB_RD32(MFB_MSF_INT_STATUS_REG);*//* MSF Status */
|
|
/*MFB_WR32(MFB_MSF_INT_STATUS_REG, MsfStatus);*//* MSF Status */
|
|
LOG_DBG("%s:0x%x = 0x%x ", __func__,
|
|
MFB_MSF_INT_STATUS_HW, MsfStatus);
|
|
#else
|
|
unsigned int MsfStatus;
|
|
bool bResulst = MFALSE;
|
|
pid_t ProcessID;
|
|
|
|
MsfStatus = MFB_RD32(MFB_MSF_INT_STATUS_REG); /* MSF Status */
|
|
MFB_WR32(MFB_MSF_INT_STATUS_REG, MsfStatus); /* MSF Status */
|
|
|
|
spin_lock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
if (MSF_INT_ST == (MSF_INT_ST & MsfStatus)) {
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_begin("mfb_msf_irq");
|
|
#endif
|
|
|
|
if (mfb_update_request(&msf_reqs, &ProcessID) == 0)
|
|
bResulst = MTRUE;
|
|
/* Config the Next frame */
|
|
if (bResulst == MTRUE) {
|
|
#if REQUEST_REGULATION == REQUEST_BASE_REGULATION
|
|
/* schedule_work(&&MFBInfo.ScheduleMsfWork); */
|
|
queue_work(MFBInfo.wkqueue, &MFBInfo.ScheduleMsfWork);
|
|
#endif
|
|
|
|
MFBInfo.IrqInfo
|
|
.Status[MFB_IRQ_TYPE_INT_MSF_ST] |= MSF_INT_ST;
|
|
MFBInfo.IrqInfo
|
|
.ProcessID[MFB_PROCESS_ID_MSF] = ProcessID;
|
|
MFBInfo.IrqInfo.MsfIrqCnt++;
|
|
}
|
|
#ifdef __MFB_KERNEL_PERFORMANCE_MEASURE__
|
|
mt_kernel_trace_end();
|
|
#endif
|
|
}
|
|
spin_unlock(&(MFBInfo.SpinLockIrq[MFB_IRQ_TYPE_INT_MSF_ST]));
|
|
if (bResulst == MTRUE)
|
|
wake_up_interruptible(&MFBInfo.WaitQueueHeadMsf);
|
|
|
|
/* dump log, use tasklet */
|
|
IRQ_LOG_KEEPER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_INF,
|
|
"Irq_MSF:%d, reg 0x%x : 0x%x, bResulst:%d, MsfIrqCnt:0x%x\n",
|
|
Irq, MFB_MSF_INT_STATUS_REG, MsfStatus,
|
|
bResulst, MFBInfo.IrqInfo.MsfIrqCnt);
|
|
|
|
#if (REQUEST_REGULATION == FRAME_BASE_REGULATION)
|
|
/* schedule_work(&MFBInfo.ScheduleMsfWork); */
|
|
if (MSF_INT_ST == (MSF_INT_ST & MsfStatus))
|
|
queue_work(MFBInfo.wkqueueMsf, &MFBInfo.ScheduleMsfWork);
|
|
#endif
|
|
|
|
if (MsfStatus & MSF_INT_ST)
|
|
tasklet_schedule(MFB_tasklet[MFB_IRQ_TYPE_INT_MSF_ST].pMFB_tkt);
|
|
|
|
|
|
#endif
|
|
return IRQ_HANDLED;
|
|
}
|
|
|
|
static void ISP_TaskletFunc_MSS(unsigned long data)
|
|
{
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_DBG);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_INF);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSS_ST, m_CurrentPPB, _LOG_ERR);
|
|
|
|
}
|
|
|
|
static void ISP_TaskletFunc_MSF(unsigned long data)
|
|
{
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_DBG);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_INF);
|
|
IRQ_LOG_PRINTER(MFB_IRQ_TYPE_INT_MSF_ST, m_CurrentPPB, _LOG_ERR);
|
|
|
|
}
|
|
static void logPrint(struct work_struct *data)
|
|
{
|
|
unsigned long arg = 0;
|
|
|
|
ISP_TaskletFunc_MSS(arg);
|
|
ISP_TaskletFunc_MSF(arg);
|
|
}
|
|
|
|
/******************************************************************************
|
|
*
|
|
******************************************************************************/
|
|
module_init(MFB_Init);
|
|
module_exit(MFB_Exit);
|
|
MODULE_DESCRIPTION("Camera MFB driver");
|
|
MODULE_AUTHOR("MM3SW5");
|
|
MODULE_LICENSE("GPL");
|