kernel-brax3-ubuntu-touch/drivers/misc/mediatek/cameraisp/pda/isp_7s/camera_pda.c
erascape f319b992b1 kernel-5.15: Initial import brax3 UT kernel
* halium configs enabled

Signed-off-by: erascape <erascape@proton.me>
2025-09-23 15:17:10 +00:00

2731 lines
81 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

// SPDX-License-Identifier: GPL-2.0
/*
* Copyright (c) 2021 MediaTek Inc.
*/
#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/clk.h>
#include <linux/pm_runtime.h>
#include <linux/jiffies.h>
#include <linux/time.h> //do_gettimeofday()
#include "mtk-interconnect.h"
// --------- DMA-BUF ----------
#include <linux/dma-heap.h>
#include <linux/dma-direction.h>
#include <linux/scatterlist.h>
#include <linux/dma-buf.h>
// ----------------------------
#include <soc/mediatek/mmdvfs_v3.h>
#include "camera_pda.h"
// --------- define region --------
// #define FPGA_UT
// #define GET_PDA_TIME
// #define FOR_DEBUG
// #define FOR_DEBUG_VA_DATA
// #define SMI_LOG
#define CHECK_IRQ_COUNT
#define PDA_MMQOS
// --------------------------------
#define PDA_DEV_NAME "camera-pda"
#define LOG_INF(format, args...) \
pr_info(PDA_DEV_NAME " [%s] " format, __func__, ##args)
#ifndef MTRUE
#define MTRUE 1
#endif
#ifndef MFALSE
#define MFALSE 0
#endif
//define the write register function
#define mt_reg_sync_writel(v, a) \
do { \
*(unsigned int *)(a) = (v); \
mb(); /*make sure register access in order */ \
} while (0)
#define PDA_WR32(addr, data) mt_reg_sync_writel(data, addr)
#define PDA_RD32(addr) ioread32(addr)
void __iomem *CAMSYS_CONFIG_BASE;
#define CAMSYS_BASE_ADDR CAMSYS_CONFIG_BASE
#define REG_CAMSYS_CG_SET (CAMSYS_BASE_ADDR + 0x4)
#define REG_CAMSYS_CG_CLR (CAMSYS_BASE_ADDR + 0x8)
#define REG_CAMSYS_SW_RST (CAMSYS_BASE_ADDR + 0xA0)
#define PDA_DONE 0x00000001
#define PDA_ERROR 0x00000002
#define PDA_STATUS_REG 0x00000001
#define PDA_CLEAR_REG 0x00000000
#define PDA_TRIGGER 0x00000003
#define PDA_DOUBLE_BUFFER 0x00000009
#define PDA_MAKE_RESET 0x00000002
#define MASK_BIT_ZERO 0x00000001
#define PDA_RESET_VALUE 0x00000001
#define PDA_HW_RESET 0x00000004
struct device *g_dev1, *g_dev2;
static spinlock_t g_PDA_SpinLock;
wait_queue_head_t g_wait_queue_head;
// PDA HW quantity
static unsigned int g_PDA_quantity;
#ifdef CHECK_IRQ_COUNT
// Calculate reasonable irq counts
static unsigned int g_reasonable_IRQCount;
static int g_PDA0_IRQCount;
static int g_PDA1_IRQCount;
#endif
static struct PDA_Data_t g_pda_Pdadata;
// pda device information
static struct PDA_device PDA_devs[PDA_MAX_QUANTITY];
// Enable clock count
static unsigned int g_u4EnableClockCount;
#ifdef GET_PDA_TIME
// Get PDA process time
struct timespec64 time_end;
struct timespec64 total_time_begin, total_time_end;
struct timespec64 pda1_done_b, pda1_done_e;
struct timespec64 pda2_done_b, pda2_done_e;
#endif
//calculate 1024 roi data
unsigned int g_rgn_x_buf[PDA_MAXROI_PER_ROUND];
unsigned int g_rgn_y_buf[PDA_MAXROI_PER_ROUND];
unsigned int g_rgn_h_buf[PDA_MAXROI_PER_ROUND];
unsigned int g_rgn_w_buf[PDA_MAXROI_PER_ROUND];
unsigned int g_rgn_iw_buf[PDA_MAXROI_PER_ROUND];
// buffer mmu
struct pda_mmu g_image_mmu;
struct pda_mmu g_table_mmu;
struct pda_mmu g_output_mmu;
// Output buffer
unsigned long g_Address_LI[4];
unsigned long g_Address_RI[4];
unsigned long g_Address_LT;
unsigned long g_Address_RT;
static unsigned long g_OutputBufferAddr;
static unsigned long g_OutputBufferOffset;
// current Process ROI number
unsigned int g_CurrentProcRoiNum[PDA_MAX_QUANTITY];
static inline void PDA_Prepare_Enable_ccf_clock(void)
{
mtk_mmdvfs_enable_vcp(true, VCP_PWR_USR_PDA);
#if IS_ENABLED(CONFIG_OF)
/* consumer device starting work*/
if (g_PDA_quantity > 0)
pm_runtime_get_sync(g_dev1); //Note: Its not larb's device.
if (g_PDA_quantity > 1)
pm_runtime_get_sync(g_dev2); //Note: Its not larb's device.
#ifdef FOR_DEBUG
LOG_INF("pm_runtime_get_sync done\n");
#endif
#endif
pda_clk_prepare_enable();
}
static inline void PDA_Disable_Unprepare_ccf_clock(void)
{
pda_clk_disable_unprepare();
#if IS_ENABLED(CONFIG_OF)
if (g_PDA_quantity > 1)
pm_runtime_put_sync(g_dev2);
if (g_PDA_quantity > 0)
pm_runtime_put_sync(g_dev1);
#ifdef FOR_DEBUG
LOG_INF("pm_runtime_put_sync done\n");
#endif
#endif
mtk_mmdvfs_enable_vcp(false, VCP_PWR_USR_PDA);
}
/**************************************************************
*
**************************************************************/
static void EnableClock(bool En)
{
if (En) { /* Enable clock. */
// Enable clock count
spin_lock(&g_PDA_SpinLock);
switch (g_u4EnableClockCount) {
case 0:
g_u4EnableClockCount++;
spin_unlock(&g_PDA_SpinLock);
#ifndef FPGA_UT
#ifdef FOR_DEBUG
LOG_INF("It's real ic load, Enable Clock");
#endif
PDA_Prepare_Enable_ccf_clock();
#else
// Enable clock by hardcode:
LOG_INF("It's LDVT load, Enable Clock");
//PDA_WR32(REG_CAMSYS_CG_CLR, 0xFFFFFFFF);
#endif
break;
default:
g_u4EnableClockCount++;
spin_unlock(&g_PDA_SpinLock);
break;
}
} else { /* Disable clock. */
// Disable clock count
spin_lock(&g_PDA_SpinLock);
g_u4EnableClockCount--;
switch (g_u4EnableClockCount) {
case 0:
spin_unlock(&g_PDA_SpinLock);
#ifndef FPGA_UT
#ifdef FOR_DEBUG
LOG_INF("It's real ic load, Disable Clock");
#endif
PDA_Disable_Unprepare_ccf_clock();
#else
// Disable clock by hardcode:
LOG_INF("It's LDVT load, Disable Clock");
//PDA_WR32(REG_CAMSYS_CG_SET, 0xFFFFFFFF);
#endif
break;
default:
spin_unlock(&g_PDA_SpinLock);
break;
}
}
}
static void pda_reset(unsigned int PDA_Index)
{
unsigned long end = 0;
end = jiffies + msecs_to_jiffies(100);
// reset HW status
PDA_devs[PDA_Index].HWstatus = 0;
// clear dma_soft_rst_stat
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_DMA_RST_REG,
PDA_CLEAR_REG);
// make reset
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_DMA_RST_REG,
PDA_MAKE_RESET);
wmb(); /* TBC */
while (time_before(jiffies, end)) {
if ((PDA_RD32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_DMA_RST_REG) &
MASK_BIT_ZERO)) {
// equivalent to hardware reset
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_TOP_CTL_REG,
PDA_HW_RESET);
// clear reset signal
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_DMA_RST_REG,
PDA_CLEAR_REG);
wmb(); /* TBC */
// clear hardware reset signal
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_TOP_CTL_REG,
PDA_CLEAR_REG);
// LOG_INF("reset PDA%d hw success\n", PDA_Index);
return;
}
LOG_INF("PDA%d Wait EMI request, DMA_RST:0x%x\n",
PDA_Index,
PDA_RD32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_DMA_RST_REG));
usleep_range(10, 20);
}
LOG_INF("reset PDA%d hw timeout\n", PDA_Index);
}
#ifndef FPGA_UT
static void pda_nontransaction_reset(unsigned int PDA_Index)
{
unsigned int MRAW_reset_value = 0;
unsigned int Reset_Bitmask = 0;
// equivalent to hardware reset
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_TOP_CTL_REG,
PDA_HW_RESET);
// clear hardware reset signal
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDA_TOP_CTL_REG,
PDA_CLEAR_REG);
//MRAW PDA reset
MRAW_reset_value = PDA_RD32(REG_CAMSYS_SW_RST);
Reset_Bitmask = GetResetBitMask(PDA_Index);
// LOG_INF("before, MRAW_reset_value: %x\n", MRAW_reset_value);
MRAW_reset_value |= Reset_Bitmask;
PDA_WR32(REG_CAMSYS_SW_RST, MRAW_reset_value);
// LOG_INF("after, MRAW_reset_value: %x\n", PDA_RD32(REG_CAMSYS_SW_RST));
MRAW_reset_value &= (!Reset_Bitmask);
PDA_WR32(REG_CAMSYS_SW_RST, MRAW_reset_value);
// LOG_INF("clear bit, MRAW_reset_value: %x\n", PDA_RD32(REG_CAMSYS_SW_RST));
}
#endif
static int pda_get_dma_buffer(struct pda_mmu *mmu, int fd)
{
struct dma_buf *buf;
#ifdef FOR_DEBUG
LOG_INF("get_dma_buffer_fd= %d\n", fd);
#endif
if (fd < 0)
return -1;
buf = dma_buf_get(fd);
if (IS_ERR(buf))
return -1;
mmu->dma_buf = buf;
mmu->attach = dma_buf_attach(mmu->dma_buf, g_dev1);
if (IS_ERR(mmu->attach))
goto err_attach;
#ifdef FOR_DEBUG
LOG_INF("mmu->attach = %x\n", mmu->attach);
#endif
mmu->sgt = dma_buf_map_attachment(mmu->attach, DMA_BIDIRECTIONAL);
if (IS_ERR(mmu->sgt))
goto err_map;
#ifdef FOR_DEBUG
LOG_INF("mmu->sgt = %x\n", mmu->sgt);
#endif
return 0;
err_map:
dma_buf_detach(mmu->dma_buf, mmu->attach);
LOG_INF("err_map!\n");
err_attach:
LOG_INF("err_attach!\n");
dma_buf_put(mmu->dma_buf);
return -1;
}
static void pda_put_dma_buffer(struct pda_mmu *mmu)
{
if (mmu->attach == NULL || mmu->sgt == NULL) {
LOG_INF("attach or sgt is null, no need to free iova\n");
return;
}
if (mmu->dma_buf) {
dma_buf_unmap_attachment(mmu->attach, mmu->sgt, DMA_BIDIRECTIONAL);
dma_buf_detach(mmu->dma_buf, mmu->attach);
dma_buf_put(mmu->dma_buf);
}
}
static int Get_Input_Addr_From_DMABUF(struct PDA_Data_t *pda_PdaConfig)
{
int ret = 0;
unsigned int i = 0;
unsigned long nAddress_Image = 0;
unsigned int nB_N = 0;
#ifdef FOR_DEBUG_VA_DATA
// buffer address
unsigned int *g_buf_LI_va;
unsigned int *g_buf_LT_va;
struct dma_buf_map map_i, map_t;
#endif
ret = pda_get_dma_buffer(&g_image_mmu, pda_PdaConfig->FD_L_Image);
if (ret < 0) {
LOG_INF("Left image, pda_get_dma_buffer fail!\n");
return ret;
}
nAddress_Image = (unsigned long) sg_dma_address(g_image_mmu.sgt->sgl);
// Left image buffer
g_Address_LI[0] = nAddress_Image;
pda_PdaConfig->PDA_PDAI_P1_BASE_ADDR = (unsigned int)g_Address_LI[0];
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_LI[0] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_REG,
(unsigned int)(g_Address_LI[0]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Left image MVA = 0x%lx\n", g_Address_LI[0]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Left image MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_MSB_REG));
LOG_INF("Left image MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_REG));
}
// get kernel va
ret = dma_buf_vmap(g_image_mmu.dma_buf, &map_i);
if (ret) {
LOG_INF("Left image map failed\n");
return -1;
}
g_buf_LI_va = map_i.vaddr;
//va
LOG_INF("Left image buffer va = %x\n", g_buf_LI_va);
LOG_INF("Left image buffer va data = %x\n", *g_buf_LI_va);
#endif
// Right image buffer
g_Address_RI[0] = g_Address_LI[0] + pda_PdaConfig->ImageSize;
pda_PdaConfig->PDA_PDAI_P2_BASE_ADDR = (unsigned int)(g_Address_RI[0]);
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_RI[0] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_REG,
(unsigned int)(g_Address_RI[0]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Right image MVA = 0x%lx\n", g_Address_RI[0]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Right image MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_MSB_REG));
LOG_INF("Right image MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_REG));
}
//va
LOG_INF("Right image buffer va = %x\n",
(g_buf_LI_va + pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Right image buffer va data = %x\n",
*(g_buf_LI_va + pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
nB_N = pda_PdaConfig->PDA_FrameSetting.PDA_CFG_254.Bits.PDA_B_N;
#ifdef FOR_DEBUG
LOG_INF("B_N = %d\n", nB_N);
#endif
if (nB_N > 3) {
LOG_INF("Fail: B_N out of range\n");
pda_put_dma_buffer(&g_image_mmu);
return -1;
}
if (nB_N == 0)
goto TABLE_BUFFER;
// L/R image index 1 --------------------------------------------------------
// Left image buffer
g_Address_LI[1] = g_Address_RI[0] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_LI[1] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_REG,
(unsigned int)(g_Address_LI[1]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Left image 1 MVA = 0x%lx\n", g_Address_LI[1]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Left image 1 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_MSB_REG));
LOG_INF("Left image 1 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_REG));
}
//va
LOG_INF("Left image 1 buffer va = %x\n",
(g_buf_LI_va + 2*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Left image 1 buffer va data = %x\n",
*(g_buf_LI_va + 2*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
// Right image buffer
g_Address_RI[1] = g_Address_LI[1] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_RI[1] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_REG,
(unsigned int)(g_Address_RI[1]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Right image 1 MVA = 0x%lx\n", g_Address_RI[1]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Right image 1 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_MSB_REG));
LOG_INF("Right image 1 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_REG));
}
//va
LOG_INF("Right image 1 buffer va = %x\n",
(g_buf_LI_va + 3*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Right image 1 buffer va data = %x\n",
*(g_buf_LI_va + 3*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
if (nB_N == 1)
goto TABLE_BUFFER;
// L/R image index 2 --------------------------------------------------------
// Left image buffer
g_Address_LI[2] = g_Address_RI[1] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_LI[2] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_REG,
(unsigned int)(g_Address_LI[2]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Left image 2 MVA = 0x%lx\n", g_Address_LI[2]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Left image 2 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_MSB_REG));
LOG_INF("Left image 2 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_REG));
}
//va
LOG_INF("Left image 2 buffer va = %x\n",
(g_buf_LI_va + 4*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Left image 2 buffer va data = %x\n",
*(g_buf_LI_va + 4*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
// Right image buffer
g_Address_RI[2] = g_Address_LI[2] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_RI[2] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_REG,
(unsigned int)(g_Address_RI[2]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Right image 2 MVA = 0x%lx\n", g_Address_RI[2]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Right image 2 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_MSB_REG));
LOG_INF("Right image 2 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_REG));
}
//va
LOG_INF("Right image 2 buffer va = %x\n",
(g_buf_LI_va + 5*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Right image 2 buffer va data = %x\n",
*(g_buf_LI_va + 5*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
if (nB_N == 2)
goto TABLE_BUFFER;
// L/R image index 3 --------------------------------------------------------
// Left image buffer
g_Address_LI[3] = g_Address_RI[2] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_LI[3] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_REG,
(unsigned int)(g_Address_LI[3]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Left image 3 MVA = 0x%lx\n", g_Address_LI[3]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Left image 3 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_MSB_REG));
LOG_INF("Left image 3 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_REG));
}
//va
LOG_INF("Left image 3 buffer va = %x\n",
(g_buf_LI_va + 6*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Left image 3 buffer va data = %x\n",
*(g_buf_LI_va + 6*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
// Right image buffer
g_Address_RI[3] = g_Address_LI[3] + pda_PdaConfig->ImageSize;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_RI[3] >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_REG,
(unsigned int)(g_Address_RI[3]));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Right image 3 MVA = 0x%lx\n", g_Address_RI[3]);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Right image 3 MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_MSB_REG));
LOG_INF("Right image 3 MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_REG));
}
//va
LOG_INF("Right image 3 buffer va = %x\n",
(g_buf_LI_va + 7*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
LOG_INF("Right image 3 buffer va data = %x\n",
*(g_buf_LI_va + 7*pda_PdaConfig->ImageSize / sizeof(unsigned int)));
#endif
TABLE_BUFFER:
// Left table buffer
ret = pda_get_dma_buffer(&g_table_mmu, pda_PdaConfig->FD_L_Table);
if (ret < 0) {
LOG_INF("Left table, pda_get_dma_buffer fail!\n");
return ret;
}
g_Address_LT = (unsigned long) sg_dma_address(g_table_mmu.sgt->sgl);
pda_PdaConfig->PDA_PDATI_P1_BASE_ADDR = (unsigned int)g_Address_LT;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_LT >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_REG,
(unsigned int)(g_Address_LT));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Left table MVA = 0x%lx\n", g_Address_LT);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Left table MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_MSB_REG));
LOG_INF("Left table MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_REG));
}
// get kernel va
ret = dma_buf_vmap(g_table_mmu.dma_buf, &map_t);
if (ret) {
LOG_INF("Left table map failed\n");
return -1;
}
g_buf_LT_va = map_t.vaddr;
//va
LOG_INF("Left table buffer va = %x\n", g_buf_LT_va);
LOG_INF("Left table buffer va data = %x\n", *g_buf_LT_va);
#endif
// Right table buffer
g_Address_RT = g_Address_LT + pda_PdaConfig->TableSize;
pda_PdaConfig->PDA_PDATI_P2_BASE_ADDR = (unsigned int)(g_Address_RT);
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_MSB_REG,
(unsigned int)(g_Address_RT >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_REG,
(unsigned int)(g_Address_RT));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Right table MVA = 0x%lx\n", g_Address_RT);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Right table MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_MSB_REG));
LOG_INF("Right table MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_REG));
}
//va
LOG_INF("Right table buffer va = %x\n",
(g_buf_LT_va + pda_PdaConfig->TableSize / sizeof(unsigned int)));
LOG_INF("Right table buffer va data = %x\n",
*(g_buf_LT_va + pda_PdaConfig->TableSize / sizeof(unsigned int)));
#endif
#ifdef FOR_DEBUG_VA_DATA
dma_buf_vunmap(g_image_mmu.dma_buf, &map_i);
dma_buf_vunmap(g_table_mmu.dma_buf, &map_t);
#endif
return ret;
}
static int Get_Output_Addr_From_DMABUF(struct PDA_Data_t *pda_PdaConfig)
{
int ret = 0;
unsigned int i = 0;
#ifdef FOR_DEBUG_VA_DATA
// buffer address
unsigned int *g_buf_Out_va;
struct dma_buf_map map_o;
#endif
// Output buffer
ret = pda_get_dma_buffer(&g_output_mmu, pda_PdaConfig->FD_Output);
if (ret < 0) {
LOG_INF("Output, pda_get_dma_buffer fail!\n");
return ret;
}
g_OutputBufferAddr = (unsigned long) sg_dma_address(g_output_mmu.sgt->sgl);
pda_PdaConfig->PDA_PDAO_P1_BASE_ADDR = (unsigned int)g_OutputBufferAddr;
for (i = 0; i < g_PDA_quantity; i++) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_MSB_REG,
(unsigned int)(g_OutputBufferAddr >> 32));
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_REG,
(unsigned int)(g_OutputBufferAddr));
}
#ifdef FOR_DEBUG_VA_DATA
LOG_INF("Output buffer MVA = 0x%lx\n", g_OutputBufferAddr);
for (i = 0; i < g_PDA_quantity; i++) {
LOG_INF("Output buffer MVA MSB = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_MSB_REG));
LOG_INF("Output buffer MVA = 0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_REG));
}
// get kernel va
ret = dma_buf_vmap(g_output_mmu.dma_buf, &map_o);
if (ret) {
LOG_INF("Output map failed\n");
return -1;
}
g_buf_Out_va = map_o.vaddr;
//va
LOG_INF("Output buffer va = %x\n", g_buf_Out_va);
LOG_INF("Output buffer va data = %x\n", *g_buf_Out_va);
dma_buf_vunmap(g_output_mmu.dma_buf, &map_o);
#endif
return ret;
}
static void HWDMASettings(struct PDA_Data_t *pda_PdaConfig)
{
unsigned int i;
for (i = 0; i < g_PDA_quantity; i++) {
// --------- Frame setting part -----------
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_0_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_0.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_1_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_1.Raw);
// need set roi number every process
// PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_2_REG,
// pda_PdaConfig->PDA_FrameSetting.PDA_CFG_2.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_3_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_3.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_4_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_4.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_5_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_5.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_6_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_6.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_7_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_7.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_8_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_8.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_9_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_9.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_10_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_10.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_11_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_11.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_12_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_12.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_13_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_13.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_254_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_254.Raw);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_CFG_255_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_255.Raw);
// --------- DMA Secure part -------------
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_SECURE_REG, 0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_SECURE_1_REG, 0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_SECURE_2_REG, 0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_SECURE_3_REG, 0x00000000);
// --------- config setting hard code part --------------
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_STRIDE_REG, OUT_BYTE_PER_ROI);
// Left image
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON0_REG, 0x100000cc);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON1_REG, 0x10330033);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON2_REG, 0x00660066);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON3_REG, 0x00880088);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON4_REG, 0x00660066);
// Left image 1
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON2_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON3_REG, 0x00300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON4_REG, 0x80200020);
// Left image 2
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON2_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON3_REG, 0x00300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON4_REG, 0x80200020);
// Left image 3
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON2_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON3_REG, 0x00300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON4_REG, 0x80200020);
// Left table
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON0_REG, 0x10000033);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON1_REG, 0x000c000c);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON2_REG, 0x00190019);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON3_REG, 0x00220022);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON4_REG, 0x00190019);
// Right image
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON0_REG, 0x100000cc);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON1_REG, 0x10330033);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON2_REG, 0x00660066);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON3_REG, 0x00880088);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON4_REG, 0x00660066);
// Right image 1
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON2_REG, 0x10200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON3_REG, 0x80300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON4_REG, 0x80200020);
// Right image 2
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON2_REG, 0x10200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON3_REG, 0x80300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON4_REG, 0x00200020);
// Right image 3
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON0_REG, 0x10000040);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON2_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON3_REG, 0x00300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON4_REG, 0x00200020);
// Right table
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON0_REG, 0x10000033);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON1_REG, 0x000c000c);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON2_REG, 0x00190019);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON3_REG, 0x00220022);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON4_REG, 0x00190019);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_XSIZE_REG, (OUT_BYTE_PER_ROI-1));
// Output
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON0_REG, 0x10000060);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON1_REG, 0x00100010);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON2_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON3_REG, 0x00300030);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON4_REG, 0x00200020);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_EN_REG, 0x7ff);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_RST_REG, 0x1);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_TOP_REG, 0x7802);
// DCM all off: 0x00001FFF
// DCM all on: 0x00000000
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_DCM_DIS_REG, 0x00001FFF);
//disable dma error irq: 0x00000000
//enable dma error irq: 0xffff0000
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_ERR_STAT_REG,
0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_TOP_CTL_REG, 0x00000000);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_IRQ_TRIG_REG, 0x0);
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_AUTO_TRIG_REG, 0x0);
// setting read clear
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_ERR_STAT_EN_REG, 0x00000001);
// read 0x3b4, avoid the impact of previous data
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_ERR_STAT_REG);
// read clear dma status
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_ERR_STAT_REG);
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_ERR_STAT_REG);
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_ERR_STAT_REG);
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_ERR_STAT_REG);
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_ERR_STAT_REG);
}
}
static int ProcessROIData(struct PDA_Data_t *pda_data,
unsigned int RoiProcNum,
unsigned int ROIIndex,
unsigned int isFixROI,
unsigned int p_index)
{
unsigned int i = 0, j = 0;
unsigned int xnum = 0, ynum = 0;
unsigned int woverlap = 0, hoverlap = 0;
unsigned int x_p, y_p, w_p, h_p;
unsigned int nWidth = 0, nHeight = 0;
int nLocalBufIndex = 0;
unsigned int nXDirLoopCount = 0;
if (isFixROI) {
#ifdef FOR_DEBUG
LOG_INF("Sequential ROI\n");
#endif
xnum = pda_data->xnum[p_index];
ynum = pda_data->ynum[p_index];
woverlap = (int)pda_data->woverlap[p_index];
hoverlap = (int)pda_data->hoverlap[p_index];
x_p = pda_data->fix_rgn_x[p_index];
y_p = pda_data->fix_rgn_y[p_index];
w_p = pda_data->fix_rgn_w[p_index];
h_p = pda_data->fix_rgn_h[p_index];
if (xnum <= 0 || ynum <= 0) {
LOG_INF("xnum(%d) or ynum(%d) value is invalid\n", xnum, ynum);
return -1;
}
nWidth = w_p / xnum;
nHeight = h_p / ynum;
#ifdef FOR_DEBUG
LOG_INF("p_index(%d), nWidth(%d), nHeight(%d)\n", p_index, nWidth, nHeight);
LOG_INF("xnum(%d), ynum(%d)\n", xnum, ynum);
LOG_INF("woverlap(%d), hoverlap(%d)\n", woverlap, hoverlap);
LOG_INF("x_p(%d), y_p(%d), w_p(%d), h_p(%d)\n", x_p, y_p, w_p, h_p);
#endif
if (w_p < xnum || h_p < ynum) {
LOG_INF("w_p(%d)/h_p(%d) can't less than xnum(%d)/ynum(%d)\n",
w_p, h_p, xnum, ynum);
return -1;
}
if (pda_data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_XNUM == 0) {
LOG_INF("Fail: PDA_PR_XNUM is zero\n");
return -1;
}
for (j = (ROIIndex / xnum); j < ynum; j++) {
i = (nXDirLoopCount == 0 ? (ROIIndex % xnum) : 0);
for (; i < xnum; i++) {
nLocalBufIndex = j * xnum + i - ROIIndex;
if (nLocalBufIndex >= PDA_MAXROI_PER_ROUND || nLocalBufIndex < 0) {
LOG_INF("nLocalBufIndex out of range (%d)\n",
nLocalBufIndex);
return -1;
}
if (i != 0 && i != xnum - 1) {
g_rgn_x_buf[nLocalBufIndex] =
x_p + nWidth * i - nWidth * woverlap / 100;
g_rgn_w_buf[nLocalBufIndex] =
nWidth + 2 * nWidth * woverlap / 100;
} else if (i == 0) {
g_rgn_x_buf[nLocalBufIndex] = x_p + nWidth * i;
g_rgn_w_buf[nLocalBufIndex] =
nWidth + nWidth * woverlap / 100;
} else {
g_rgn_x_buf[nLocalBufIndex] =
x_p + nWidth * i - nWidth * woverlap / 100;
g_rgn_w_buf[nLocalBufIndex] =
nWidth + nWidth * woverlap / 100;
}
if (j != 0 && j != ynum - 1) {
g_rgn_y_buf[nLocalBufIndex] =
y_p + nHeight * j - nHeight * hoverlap / 100;
g_rgn_h_buf[nLocalBufIndex] =
nHeight + 2 * nHeight * hoverlap / 100;
} else if (j == 0) {
g_rgn_y_buf[nLocalBufIndex] = y_p + nHeight * j;
g_rgn_h_buf[nLocalBufIndex] =
nHeight + nHeight * hoverlap / 100;
} else {
g_rgn_y_buf[nLocalBufIndex] =
y_p + nHeight * j - nHeight * hoverlap / 100;
g_rgn_h_buf[nLocalBufIndex] =
nHeight + nHeight * hoverlap / 100;
}
g_rgn_iw_buf[nLocalBufIndex] =
g_rgn_w_buf[nLocalBufIndex] *
(pda_data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PAT_WIDTH /
pda_data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_XNUM);
#ifdef FOR_DEBUG
LOG_INF("ROI_IW_%d, iw:%d, w:%d, pat_width:%d\n",
nLocalBufIndex,
g_rgn_iw_buf[nLocalBufIndex],
g_rgn_w_buf[nLocalBufIndex],
pda_data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PAT_WIDTH);
#endif
// calculate done
if (nLocalBufIndex >= (RoiProcNum-1))
goto CALDONE;
} // for i
// use for check if first x direction loop or not
nXDirLoopCount++;
} // for j
} else {
#ifdef FOR_DEBUG
LOG_INF("Random ROI\n");
#endif
for (i = 0; i < RoiProcNum; i++) {
g_rgn_x_buf[i] = pda_data->rgn_x[ROIIndex+i];
g_rgn_y_buf[i] = pda_data->rgn_y[ROIIndex+i];
g_rgn_w_buf[i] = pda_data->rgn_w[ROIIndex+i];
g_rgn_h_buf[i] = pda_data->rgn_h[ROIIndex+i];
g_rgn_iw_buf[i] = pda_data->rgn_iw[ROIIndex+i];
}
}
CALDONE:
#ifdef FOR_DEBUG
LOG_INF("Calculate ROI done\n");
#endif
return 0;
}
static int CheckDesignLimitation(struct PDA_Data_t *PDA_Data,
unsigned int RoiProcNum,
unsigned int ROIIndex)
{
unsigned int i = 0;
int nROIIndex = 0;
int nTempVar = 0;
#ifdef FOR_DEBUG
LOG_INF("Check Design Limitation\n");
#endif
// frame constraint
if (PDA_Data->PDA_FrameSetting.PDA_CFG_0.Bits.PDA_WIDTH % 4 != 0) {
LOG_INF("Frame width must be multiple of 4\n");
PDA_Data->Status = -4;
return -1;
}
// ROI constraint
for (i = 0; i < RoiProcNum; i++) {
nROIIndex = i + ROIIndex;
#ifdef FOR_DEBUG
LOG_INF("nROIIndex:%d, i:%d\n", nROIIndex, i);
#endif
if (g_rgn_w_buf[i] % 4 != 0) {
LOG_INF("ROI_%d width(%d) must be multiple of 4\n",
nROIIndex,
g_rgn_w_buf[i]);
PDA_Data->Status = -5;
return -1;
}
if (g_rgn_w_buf[i] > 3280) {
LOG_INF("ROI_%d width(%d) must be less than 3280\n",
nROIIndex,
g_rgn_w_buf[i]);
PDA_Data->Status = -6;
return -1;
}
if (g_rgn_x_buf[i] % 2 != 0) {
LOG_INF("ROI_%d xoffset(%d) must be multiple of 2\n",
nROIIndex,
g_rgn_x_buf[i]);
PDA_Data->Status = -7;
return -1;
}
if (g_rgn_iw_buf[i] < 41) {
LOG_INF("ROI_%d IW(%d) must be greater than 41\n",
nROIIndex,
g_rgn_iw_buf[i]);
PDA_Data->Status = -8;
return -1;
}
nTempVar = (1 << PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_BIN_FCTR);
if (g_rgn_h_buf[i] % nTempVar != 0) {
LOG_INF("ROI_%d height(%d) must be multiple of Binning number(%d)\n",
i,
g_rgn_h_buf[i],
nTempVar);
PDA_Data->Status = -9;
return -1;
}
// ROI boundary must be on the boundary of patch
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_XNUM;
if (g_rgn_x_buf[i] % nTempVar != 0) {
LOG_INF("ROI_%d ROI boundary must be on the boundary of patch\n",
nROIIndex);
LOG_INF("ROI_%d_x: %d, PDA_PR_XNUM: %d\n",
nROIIndex,
g_rgn_x_buf[i],
nTempVar);
PDA_Data->Status = -10;
return -1;
}
if (g_rgn_w_buf[i] % nTempVar != 0) {
LOG_INF("ROI_%d ROI boundary must be on the boundary of patch\n",
nROIIndex);
LOG_INF("ROI_%d_w: %d, PDA_PR_XNUM: %d\n",
nROIIndex,
g_rgn_w_buf[i],
nTempVar);
PDA_Data->Status = -10;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_YNUM;
if (g_rgn_y_buf[i] % nTempVar != 0) {
LOG_INF("ROI_%d ROI boundary must be on the boundary of patch\n",
nROIIndex);
LOG_INF("ROI_%d_y: %d, PDA_PR_YNUM: %d\n",
nROIIndex,
g_rgn_y_buf[i],
nTempVar);
PDA_Data->Status = -10;
return -1;
}
if (g_rgn_h_buf[i] % nTempVar != 0) {
LOG_INF("ROI_%d ROI boundary must be on the boundary of patch\n",
nROIIndex);
LOG_INF("ROI_%d_h: %d, PDA_PR_YNUM: %d\n",
nROIIndex,
g_rgn_h_buf[i],
nTempVar);
PDA_Data->Status = -10;
return -1;
}
// ROI can't exceed the image region
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_0.Bits.PDA_WIDTH;
if ((g_rgn_x_buf[i]+g_rgn_w_buf[i]) > nTempVar) {
LOG_INF("ROI_%d ROI exceed the image region\n", nROIIndex);
PDA_Data->Status = -11;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_0.Bits.PDA_HEIGHT;
if ((g_rgn_y_buf[i]+g_rgn_h_buf[i]) > nTempVar) {
LOG_INF("ROI_%d ROI exceed the image region\n", nROIIndex);
PDA_Data->Status = -11;
return -1;
}
// Register Range Limitation check
if (g_rgn_x_buf[i] > 8191) {
LOG_INF("ROI_X_%d (%d) out of range\n", nROIIndex, g_rgn_x_buf[i]);
PDA_Data->Status = -19;
return -1;
}
if (g_rgn_y_buf[i] > 8191) {
LOG_INF("ROI_Y_%d (%d) out of range\n", nROIIndex, g_rgn_y_buf[i]);
PDA_Data->Status = -20;
return -1;
}
if (g_rgn_w_buf[i] < 20) {
LOG_INF("ROI_W_%d (%d) out of range\n", nROIIndex, g_rgn_w_buf[i]);
PDA_Data->Status = -21;
return -1;
}
if (g_rgn_h_buf[i] < 4 || g_rgn_h_buf[i] > 4092) {
LOG_INF("ROI_H_%d (%d) out of range\n", nROIIndex, g_rgn_h_buf[i]);
PDA_Data->Status = -22;
return -1;
}
if (g_rgn_iw_buf[i] > 3280) {
LOG_INF("ROI_IW_%d (%d) out of range, w:%d, pat_width:%d\n",
nROIIndex,
g_rgn_iw_buf[i],
g_rgn_w_buf[i],
PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PAT_WIDTH);
PDA_Data->Status = -23;
return -1;
}
}
// Register Range Limitation check
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_0.Bits.PDA_WIDTH;
if (nTempVar < 20 || nTempVar > 8191) {
LOG_INF("Frame width (%d) out of range\n", nTempVar);
PDA_Data->Status = -12;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_0.Bits.PDA_HEIGHT;
if (nTempVar < 4 || nTempVar > 8191) {
LOG_INF("Frame height (%d) out of range\n", nTempVar);
PDA_Data->Status = -13;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_XNUM;
if (nTempVar < 1 || nTempVar > 16) {
LOG_INF("PDA_PR_XNUM (%d) out of range\n", nTempVar);
PDA_Data->Status = -14;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PR_YNUM;
if (nTempVar < 1 || nTempVar > 16) {
LOG_INF("PDA_PR_YNUM (%d) out of range\n", nTempVar);
PDA_Data->Status = -15;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_PAT_WIDTH;
if (nTempVar < 1 || nTempVar > 512) {
LOG_INF("PDA_PAT_WIDTH (%d) out of range\n", nTempVar);
PDA_Data->Status = -16;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_1.Bits.PDA_RNG_ST;
if (nTempVar > 40) {
LOG_INF("PDA_RNG_ST (%d) out of range\n", nTempVar);
PDA_Data->Status = -17;
return -1;
}
nTempVar = PDA_Data->PDA_FrameSetting.PDA_CFG_2.Bits.PDA_TBL_STRIDE;
if (nTempVar < 5 || nTempVar > 2048) {
LOG_INF("PDA_TBL_STRIDE (%d) out of range\n", nTempVar);
PDA_Data->Status = -18;
return -1;
}
return 0;
}
static void FillRegSettings(struct PDA_Data_t *pda_PdaConfig,
unsigned int RoiProcNum,
unsigned long OuputAddr,
unsigned int PDA_Index)
{
unsigned int RegIndex = 14;
unsigned int RegIndex_last = 256;
//int ROI_MAX_INDEX = RoiProcNum-1;
unsigned int ROI_MAX_INDEX = 0;
unsigned int ROI_last = 0;
unsigned int pair = 0;
unsigned int nTemp = 0;
if (RoiProcNum > PDA_MAXROI_PER_ROUND) {
LOG_INF("RoiProcNum out of range (%d)\n", RoiProcNum);
return;
}
// modify roi number register, change [12:6] bit to RoiProcNum
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_2.Bits.PDA_RGN_NUM = RoiProcNum;
// roi number register setting
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_CFG_2_REG,
pda_PdaConfig->PDA_FrameSetting.PDA_CFG_2.Raw);
if (RoiProcNum > 45 && PDA_MAXROI_PER_ROUND > 45) {
ROI_MAX_INDEX = 44;
ROI_last = RoiProcNum - 45;
} else {
ROI_MAX_INDEX = RoiProcNum-1;
ROI_last = 0;
}
// ROI data sequentially fill to PDA_CFG[14] ~ PDA_CFG[126]
for (pair = 0; pair <= ROI_MAX_INDEX; pair += 2) {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
(g_rgn_y_buf[pair] << 16) + g_rgn_x_buf[pair]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
(g_rgn_h_buf[pair] << 16) + g_rgn_w_buf[pair]);
if (pair == ROI_MAX_INDEX && pair%2 == 0) {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
g_rgn_iw_buf[pair]);
} else {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
(g_rgn_x_buf[pair+1] << 16) + g_rgn_iw_buf[pair]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
(g_rgn_w_buf[pair+1] << 16) + g_rgn_y_buf[pair+1]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex++)),
(g_rgn_iw_buf[pair+1] << 16) + g_rgn_h_buf[pair+1]);
}
}
// ROI data sequentially fill to PDA_CFG[127] ~ PDA_CFG[253]
for (pair = 45; pair <= (ROI_last-1+45); pair += 2) {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
(g_rgn_y_buf[pair] << 16) + g_rgn_x_buf[pair]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
(g_rgn_h_buf[pair] << 16) + g_rgn_w_buf[pair]);
if (pair == (ROI_last-1+45) && pair%2 != 0) {
// Process PDA_CFG[254] specially
if (pair == (PDA_MAXROI_PER_ROUND - 1)) {
nTemp = pda_PdaConfig->PDA_FrameSetting.PDA_CFG_254.Raw;
#ifdef FOR_DEBUG
LOG_INF("PDA_CFG_254 : 0x%x\n", nTemp);
#endif
nTemp = (nTemp & 0xFFFF0000) | g_rgn_iw_buf[pair];
#ifdef FOR_DEBUG
LOG_INF("PDA_CFG_254 merge iw_95 : 0x%x\n", nTemp);
#endif
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
nTemp);
} else {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
g_rgn_iw_buf[pair]);
}
} else {
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
(g_rgn_x_buf[pair+1] << 16) + g_rgn_iw_buf[pair]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
(g_rgn_w_buf[pair+1] << 16) + g_rgn_y_buf[pair+1]);
PDA_WR32((PDA_devs[PDA_Index].m_pda_base + 0x004*(RegIndex_last++)),
(g_rgn_iw_buf[pair+1] << 16) + g_rgn_h_buf[pair+1]);
}
}
// output buffer address setting
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDAO_P1_BASE_ADDR_MSB_REG,
(unsigned int)(OuputAddr >> 32));
PDA_WR32(PDA_devs[PDA_Index].m_pda_base + PDA_PDAO_P1_BASE_ADDR_REG,
(unsigned int)(OuputAddr));
#ifdef FOR_DEBUG
LOG_INF("Fill Register Settings done\n");
#endif
}
static void LOGHWRegister(unsigned int i)
{
LOG_INF("CFG_0/1/2/3/4/5/6: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_4_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_5_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_6_REG));
LOG_INF("CFG_7/8/9/10/11/12/13: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_7_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_8_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_9_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_10_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_11_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_12_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_13_REG));
LOG_INF("CFG_14/15/16/17/18/19/20: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_14_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_15_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_16_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_17_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_18_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_19_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_20_REG));
LOG_INF("CFG_21/22/23/24/25/26/27/28: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_21_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_22_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_23_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_24_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_25_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_26_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_27_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_28_REG));
LOG_INF("CFG_254/255: 0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_254_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_CFG_255_REG));
LOG_INF("I_P1/TI_P1/I_P2/TI_P2/Out: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_REG));
LOG_INF("LI_P3/RI_P3/LI_P4/RI_P4/LI_P5/RI_P5: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_REG));
LOG_INF("SECURE/I_STRIDE/O_P1_XSIZE: 0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_SECURE_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_STRIDE_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_XSIZE_REG));
LOG_INF("TILE_STATUS/TILE_STATUS_1: 0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_TILE_STATUS_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_TILE_STATUS_1_REG));
LOG_INF("PDAI_P1_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_CON4_REG));
LOG_INF("PDATI_P1_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_CON4_REG));
LOG_INF("PDAI_P2_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_CON4_REG));
LOG_INF("PDATI_P2_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_CON4_REG));
LOG_INF("PDALI_P3_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_CON4_REG));
LOG_INF("PDARI_P3_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_CON4_REG));
LOG_INF("PDALI_P4_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_CON4_REG));
LOG_INF("PDARI_P4_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_CON4_REG));
LOG_INF("PDALI_P5_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_CON4_REG));
LOG_INF("PDARI_P5_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_CON4_REG));
LOG_INF("PDAO_P1_CON0/CON1/CON2/CON3/CON4: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON0_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON1_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON2_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON3_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_CON4_REG));
LOG_INF("DMA_EN/DMA_RST/DMA_TOP/DCM_DIS/DCM_ST: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_EN_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_RST_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DMA_TOP_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DCM_DIS_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DCM_ST_REG));
LOG_INF("[ERR_STAT]I_P1/TI_P1/I_P2/TI_P2/O_P1: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_ERR_STAT_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_ERR_STAT_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_ERR_STAT_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_ERR_STAT_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_ERR_STAT_REG));
LOG_INF("ERR_STAT_EN/ERR_STAT/TOP_CTL: 0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_ERR_STAT_EN_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_ERR_STAT_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_TOP_CTL_REG));
LOG_INF("IRQ_TRIG/PDAO_DMA_EXISTED_ECO: 0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_IRQ_TRIG_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_DMA_EXISTED_ECO_REG));
LOG_INF("[MSB]I_P1/TI_P1/I_P2/TI_P2/O_P1: 0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_MSB_REG));
LOG_INF("[MSB]LI_P3/RI_P3/LI_P3/RI_P3/LI_P3/RI_P3: 0x%x/0x%x/0x%x/0x%x/0x%x/0x%x\n",
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P3_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P3_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P4_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P4_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDALI_P5_BASE_ADDR_MSB_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDARI_P5_BASE_ADDR_MSB_REG));
}
static void TF_dump_log(unsigned int hw_trigger_num)
{
unsigned int i = 0;
unsigned int sel_index = 0;
unsigned int Debug_Sel[] = {0x00008120, 0x0000400e, 0x0000c000,
0x11000000, 0x12000000, 0x13000000, 0x14000000, 0x15000000, 0x16000000,
0x14000000, 0x14100000, 0x14200000, 0x14300000, 0x14400000, 0x14500000,
0x21000000, 0x22000000, 0x23000000, 0x24000000, 0x25000000,
0x24000000, 0x24100000, 0x24200000, 0x24300000, 0x24400000, 0x24500000,
0x31000000, 0x32000000, 0x33000000, 0x34000000, 0x35000000,
0x34000000, 0x34100000, 0x34200000, 0x34300000, 0x34400000, 0x34500000,
0x41000000, 0x42000000, 0x43000000, 0x44000000, 0x45000000,
0x44000000, 0x44100000, 0x44200000, 0x44300000, 0x44400000, 0x44500000,
0x51000000, 0x52000000, 0x53000000, 0x54000000, 0x55000000,
0x54000000, 0x54100000, 0x54200000, 0x54300000, 0x54400000, 0x54500000};
unsigned int Length_Arr = sizeof(Debug_Sel)/sizeof(*Debug_Sel);
#ifdef SMI_LOG
// SMI log
mtk_smi_dbg_hang_detect("PDA device");
#endif
// check debug data
for (i = 0; i < hw_trigger_num; i++) {
for (sel_index = 0; sel_index < Length_Arr; ++sel_index) {
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_DEBUG_SEL_REG,
Debug_Sel[sel_index]);
LOG_INF("PDA_%d DEBUG_SEL/DEBUG_DATA: 0x%x/0x%x\n",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DEBUG_SEL_REG),
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_DEBUG_DATA_REG));
}
}
// check hw register setting
for (i = 0; i < hw_trigger_num; i++) {
LOG_INF("[outer] PDA_%d register LOG +++++\n", i);
LOGHWRegister(i);
}
}
static void TimeoutHandler(unsigned int hw_trigger_num)
{
#ifndef FPGA_UT
unsigned int i = 0;
#endif
TF_dump_log(hw_trigger_num);
#ifndef FPGA_UT
// reset flow
for (i = 0; i < hw_trigger_num; i++) {
pda_reset(i);
pda_nontransaction_reset(i);
}
#endif
}
static void pda_execute(unsigned int hw_trigger_num)
{
unsigned int i;
#ifdef FOR_DEBUG
LOG_INF("+\n");
#endif
for (i = 0; i < hw_trigger_num; i++) {
// PDA_TOP_CTL set 1'b1 to bit3, to load register from double buffer
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_TOP_CTL_REG, PDA_DOUBLE_BUFFER);
// make sure all the pda setting take effect
wmb();
// PDA_TOP_CTL set 1'b1 to bit1, to trigger sof
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_TOP_CTL_REG, PDA_TRIGGER);
// make sure all the pda setting take effect
wmb();
// write 0 after trigger
PDA_WR32(PDA_devs[i].m_pda_base + PDA_PDA_TOP_CTL_REG, PDA_CLEAR_REG);
#ifdef GET_PDA_TIME
if (i == 0)
ktime_get_real_ts64(&pda1_done_b);
else
ktime_get_real_ts64(&pda2_done_b);
#endif
}
#ifdef FOR_DEBUG
LOG_INF("-\n");
#endif
}
#ifndef FPGA_UT
static int check_pda_status(unsigned int hw_trigger_num)
{
unsigned int i = 0;
for (i = 0; i < hw_trigger_num; i++) {
if (PDA_devs[i].HWstatus == 0) {
#ifdef FOR_DEBUG
LOG_INF("PDA%d HWstatus = %d\n", i, PDA_devs[i].HWstatus);
#endif
return 0;
}
}
return 1;
}
#endif
static inline unsigned int pda_ms_to_jiffies(unsigned int ms)
{
return ((ms * HZ + 512) >> 10);
}
static signed int pda_wait_irq(struct PDA_Data_t *pda_data, unsigned int hw_trigger_num)
{
int ret = 0;
unsigned int i = 0;
#ifdef FPGA_UT
int nCount_irq = 0;
int nstatus_one = 0, nstatus_two = 0;
#endif
/* start to wait signal */
#ifndef FPGA_UT
ret = wait_event_interruptible_timeout(g_wait_queue_head,
check_pda_status(hw_trigger_num),
pda_ms_to_jiffies(pda_data->Timeout));
#else
LOG_INF("hw_trigger_num = %d\n", hw_trigger_num);
while (nCount_irq < 1000) {
LOG_INF("nCount_irq = %d\n", nCount_irq);
if (hw_trigger_num > 1) {
nstatus_one = PDA_RD32(PDA_devs[0].m_pda_base + PDA_PDA_ERR_STAT_REG) &
PDA_STATUS_REG;
nstatus_two = PDA_RD32(PDA_devs[1].m_pda_base + PDA_PDA_ERR_STAT_REG) &
PDA_STATUS_REG;
if (nstatus_one == 1) {
PDA_devs[0].HWstatus = 1;
LOG_INF("nstatus_one = 1\n");
}
if (nstatus_two == 1) {
PDA_devs[1].HWstatus = 1;
LOG_INF("nstatus_two = 1\n");
}
if (PDA_devs[0].HWstatus == 1 && PDA_devs[1].HWstatus == 1) {
ret = 1;
break;
}
} else {
nstatus_one = PDA_RD32(PDA_devs[0].m_pda_base + PDA_PDA_ERR_STAT_REG) &
PDA_STATUS_REG;
if (nstatus_one == 1) {
LOG_INF("nstatus_one = 1\n");
PDA_devs[0].HWstatus = 1;
ret = 1;
break;
}
}
nCount_irq++;
}
#endif
if (ret == 0) {
TimeoutHandler(hw_trigger_num);
// timeout error
LOG_INF("wait_event_interruptible_timeout Fail\n");
pda_data->Status = -2;
return -1;
} else if (ret < 0) {
LOG_INF("wait_event return value:%d\n", ret);
if (ret == -ERESTARTSYS)
LOG_INF("Interrupted by a signal\n");
#ifndef FPGA_UT
for (i = 0; i < hw_trigger_num; i++) {
pda_reset(i);
pda_nontransaction_reset(i);
}
#endif
return -1;
}
#ifdef GET_PDA_TIME
ktime_get_real_ts64(&time_end);
#endif
// pda status
pda_data->Status = 1;
// update status to user
for (i = 0; i < hw_trigger_num; i++) {
if (PDA_devs[i].HWstatus < 0) {
pda_data->Status = PDA_devs[i].HWstatus;
LOG_INF("PDA%d HW error (%d)", i, PDA_devs[i].HWstatus);
LOG_INF("PDA%d PDA_PDAI_P1_ERR_STAT_REG = 0x%x",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_ERR_STAT_REG));
LOG_INF("PDA%d PDA_PDATI_P1_ERR_STAT_REG = 0x%x",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_ERR_STAT_REG));
LOG_INF("PDA%d PDA_PDAI_P2_ERR_STAT_REG = 0x%x",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_ERR_STAT_REG));
LOG_INF("PDA%d PDA_PDATI_P2_ERR_STAT_REG = 0x%x",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_ERR_STAT_REG));
LOG_INF("PDA%d PDA_PDAO_P1_ERR_STAT_REG = 0x%x",
i, PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_ERR_STAT_REG));
#ifndef FPGA_UT
// reset flow
pda_nontransaction_reset(i);
#endif
}
}
return ret;
}
#ifndef FPGA_UT
static irqreturn_t pda_irqhandle(signed int Irq, void *DeviceId)
{
unsigned int nPdaStatus = 0;
if (g_u4EnableClockCount > 0) {
// read pda status
nPdaStatus = PDA_RD32(PDA_devs[0].m_pda_base + PDA_PDA_ERR_STAT_REG) &
PDA_STATUS_REG;
}
#ifdef FOR_DEBUG
LOG_INF("PDA0 PDA_PDA_ERR_STAT_REG = 0x%x", nPdaStatus);
#endif
// for WCL=1 case, write 1 to clear pda done status
// PDA_WR32(PDA_devs[0].m_pda_base + PDA_PDA_ERR_STAT_REG, 0x00000001);
PDA_devs[0].HWstatus = 1;
#ifdef GET_PDA_TIME
ktime_get_real_ts64(&pda1_done_e);
#endif
#ifdef CHECK_IRQ_COUNT
++g_PDA0_IRQCount;
if (g_PDA0_IRQCount > g_reasonable_IRQCount) {
PDA_devs[0].HWstatus = -29;
pda_nontransaction_reset(0);
}
#endif
// wake up user space WAIT_IRQ flag
wake_up_interruptible(&g_wait_queue_head);
return IRQ_HANDLED;
}
static irqreturn_t pda2_irqhandle(signed int Irq, void *DeviceId)
{
unsigned int nPdaStatus = 0;
if (g_u4EnableClockCount > 0) {
// read pda status
nPdaStatus = PDA_RD32(PDA_devs[1].m_pda_base + PDA_PDA_ERR_STAT_REG) &
PDA_STATUS_REG;
}
#ifdef FOR_DEBUG
LOG_INF("PDA1 PDA_PDA_ERR_STAT_REG = 0x%x", nPdaStatus);
#endif
// for WCL=1 case, write 1 to clear pda done status
// PDA_WR32(PDA_devs[1].m_pda_base + PDA_PDA_ERR_STAT_REG, 0x00000001);
PDA_devs[1].HWstatus = 1;
#ifdef GET_PDA_TIME
ktime_get_real_ts64(&pda2_done_e);
#endif
#ifdef CHECK_IRQ_COUNT
++g_PDA1_IRQCount;
if (g_PDA1_IRQCount > g_reasonable_IRQCount) {
PDA_devs[1].HWstatus = -29;
pda_nontransaction_reset(1);
}
#endif
// wake up user space WAIT_IRQ flag
wake_up_interruptible(&g_wait_queue_head);
return IRQ_HANDLED;
}
#endif
static int PDAProcessFunction(unsigned int nUserROINumber,
unsigned int nROIcount,
unsigned int isFixROI,
unsigned int p_index)
{
unsigned int i = 0;
unsigned int nOneRoundProcROI = 0;
unsigned int hw_trigger_num = 0;
unsigned int nRemainder = 0, nFactor = 0;
unsigned int nCurrentProcRoiIndex = 0;
unsigned long nOutputAddr = 0;
int nirqRet = 0;
unsigned int CheckAddress = 0, CheckAddressMSB = 0;
while (nROIcount > 0) {
// read 0x3b4, avoid the impact of previous data
// LOG_INF("PDA status before process = %d\n",
// PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDA_ERR_STAT_REG));
#ifdef FOR_DEBUG
LOG_INF("nROIcount = %d\n", nROIcount);
#endif
// reset HW status
for (i = 0; i < g_PDA_quantity; i++)
PDA_devs[i].HWstatus = 0;
// reset local variable
nOneRoundProcROI = 0;
//reset hw trigger number
hw_trigger_num = g_PDA_quantity;
// assign strategy, used for multi-engine
if (nROIcount >= (PDA_MAXROI_PER_ROUND * g_PDA_quantity)) {
for (i = 0; i < g_PDA_quantity; i++) {
g_CurrentProcRoiNum[i] = PDA_MAXROI_PER_ROUND;
nOneRoundProcROI += g_CurrentProcRoiNum[i];
#ifdef FOR_DEBUG
LOG_INF("g_CurrentProcRoiNum[%d] = %d\n",
i, g_CurrentProcRoiNum[i]);
LOG_INF("OneRoundProcROI = %d\n", nOneRoundProcROI);
#endif
}
} else {
if (g_PDA_quantity == 0) {
LOG_INF("Fail: g_PDA_quantity is zero\n");
return -1;
}
nRemainder = nROIcount % g_PDA_quantity;
nFactor = nROIcount / g_PDA_quantity;
for (i = 0; i < g_PDA_quantity; i++) {
g_CurrentProcRoiNum[i] = nFactor;
if (nRemainder > 0) {
g_CurrentProcRoiNum[i]++;
nRemainder--;
}
nOneRoundProcROI += g_CurrentProcRoiNum[i];
#ifdef FOR_DEBUG
LOG_INF("g_CurrentProcRoiNum[%d] = %d\n",
i, g_CurrentProcRoiNum[i]);
LOG_INF("OneRoundProcROI = %d\n", nOneRoundProcROI);
#endif
}
}
// data preparing
for (i = 0; i < g_PDA_quantity; i++) {
// current process ROI index
if (i == 0)
nCurrentProcRoiIndex = (nUserROINumber - nROIcount);
else if (i > 0)
nCurrentProcRoiIndex += g_CurrentProcRoiNum[i - 1];
else
LOG_INF("Index is out of range, i = %d\n", i);
#ifdef FOR_DEBUG
LOG_INF("nCurrentProcRoiIndex = %d\n",
nCurrentProcRoiIndex);
#endif
if (g_CurrentProcRoiNum[i] == 0) {
hw_trigger_num = i;
#ifdef FOR_DEBUG
LOG_INF("assign roi number is zero, no need to process\n");
#endif
break;
}
#ifdef FOR_DEBUG
LOG_INF("i:%d, g_CurrentProcRoiNum:%d, nCurrentProcRoiIndex:%d\n",
i,
g_CurrentProcRoiNum[i],
nCurrentProcRoiIndex);
#endif
// calculate 1024 ROI data
if (ProcessROIData(&g_pda_Pdadata,
g_CurrentProcRoiNum[i],
nCurrentProcRoiIndex,
isFixROI,
p_index) < 0) {
LOG_INF("ProcessROIData Fail\n");
g_pda_Pdadata.Status = -24;
return -1;
}
if (CheckDesignLimitation(&g_pda_Pdadata,
g_CurrentProcRoiNum[i],
nCurrentProcRoiIndex) < 0) {
LOG_INF("CheckDesignLimitation Fail\n");
return -1;
}
// output address is equal to
// total ROI number multiple by 1408
nOutputAddr = g_OutputBufferAddr;
nOutputAddr += nCurrentProcRoiIndex * OUT_BYTE_PER_ROI;
if (g_OutputBufferOffset + (g_CurrentProcRoiNum[i]*OUT_BYTE_PER_ROI) >
g_pda_Pdadata.OutputSize) {
LOG_INF("fail, output buffer out of range\n");
LOG_INF("Current output buffer addr: 0x%lx\n",
nOutputAddr);
LOG_INF("Base output buffer addr: 0x%lx\n",
nOutputAddr);
LOG_INF("PDA%d ROI process num: %d\n",
i, g_CurrentProcRoiNum[i]);
LOG_INF("Output buffer size: %d\n",
g_pda_Pdadata.OutputSize);
LOG_INF("Current process ROI index: %d\n",
nCurrentProcRoiIndex);
LOG_INF("nUserROINumber: %d\n",
nUserROINumber);
LOG_INF("nROIcount: %d\n", nROIcount);
g_pda_Pdadata.Status = -30;
return -1;
}
#ifdef FOR_DEBUG
LOG_INF("(nOutputAddr+g_OutputBufferOffset): 0x%lx\n",
(nOutputAddr+g_OutputBufferOffset));
#endif
FillRegSettings(&g_pda_Pdadata,
g_CurrentProcRoiNum[i],
(nOutputAddr+g_OutputBufferOffset),
i);
}
// check input/output buffer address is valid
for (i = 0; i < hw_trigger_num; i++) {
CheckAddress =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_REG);
CheckAddressMSB =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P1_BASE_ADDR_MSB_REG);
if (CheckAddress == 0 && CheckAddressMSB == 0) {
LOG_INF("PDA_%d PDA_PDAI_P1_BASE_ADDR is zero\n", i);
g_pda_Pdadata.Status = -30;
return -1;
}
CheckAddress =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_REG);
CheckAddressMSB =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P1_BASE_ADDR_MSB_REG);
if (CheckAddress == 0 && CheckAddressMSB == 0) {
LOG_INF("PDA_%d PDA_PDATI_P1_BASE_ADDR is zero\n", i);
g_pda_Pdadata.Status = -30;
return -1;
}
CheckAddress =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_REG);
CheckAddressMSB =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAI_P2_BASE_ADDR_MSB_REG);
if (CheckAddress == 0 && CheckAddressMSB == 0) {
LOG_INF("PDA_%d PDA_PDAI_P2_BASE_ADDR is zero\n", i);
g_pda_Pdadata.Status = -30;
return -1;
}
CheckAddress =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_REG);
CheckAddressMSB =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDATI_P2_BASE_ADDR_MSB_REG);
if (CheckAddress == 0 && CheckAddressMSB == 0) {
LOG_INF("PDA_%d PDA_PDATI_P2_BASE_ADDR is zero\n", i);
g_pda_Pdadata.Status = -30;
return -1;
}
CheckAddress =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_REG);
CheckAddressMSB =
PDA_RD32(PDA_devs[i].m_pda_base + PDA_PDAO_P1_BASE_ADDR_MSB_REG);
if (CheckAddress == 0 && CheckAddressMSB == 0) {
LOG_INF("PDA_%d PDA_PDAO_P1_BASE_ADDR is zero\n", i);
g_pda_Pdadata.Status = -30;
return -1;
}
}
// trigger PDA work
pda_execute(hw_trigger_num);
nirqRet = pda_wait_irq(&g_pda_Pdadata, hw_trigger_num);
if (nirqRet < 0) {
LOG_INF("pda_wait_irq Fail (%d)\n", nirqRet);
return -1;
}
// update roi count which needed to process
nROIcount -= nOneRoundProcROI;
}
return 1;
}
static long PDA_Ioctl(struct file *a_pstFile,
unsigned int a_u4Command,
unsigned long a_u4Param)
{
long nRet = 0;
int nROIcount = 0;
unsigned int nUserROINumber = 0;
unsigned int i;
int ret = 0;
struct PDA_Init_Data Init_Data;
if (g_PDA_quantity == 0) {
LOG_INF("no PDA support\n");
return -1;
}
switch (a_u4Command) {
case PDA_RESET:
for (i = 0; i < g_PDA_quantity; i++)
pda_reset(i);
break;
case PDA_GET_VERSION:
if (copy_from_user(&Init_Data,
(void *)a_u4Param,
sizeof(struct PDA_Init_Data)) != 0) {
LOG_INF("PDA_GET_VERSION copy_from_user failed\n");
nRet = -EFAULT;
break;
}
Init_Data.Kversion = KERNEL_VERSION;
LOG_INF("kernel version: %d\n", Init_Data.Kversion);
if (copy_to_user((void *)a_u4Param,
&Init_Data,
sizeof(struct PDA_Init_Data)) != 0) {
LOG_INF("PDA_GET_VERSION copy_to_user failed\n");
nRet = -EFAULT;
}
break;
case PDA_ENQUE_WAITIRQ:
#ifdef FOR_DEBUG
LOG_INF("PDA_ENQUE_WAITIRQ\n");
#endif
spin_lock(&g_PDA_SpinLock);
if (g_u4EnableClockCount == 0) {
LOG_INF("Cannot process without enable pda clock\n");
spin_unlock(&g_PDA_SpinLock);
return -1;
}
spin_unlock(&g_PDA_SpinLock);
#ifdef GET_PDA_TIME
ktime_get_real_ts64(&total_time_begin);
#endif
#ifndef FPGA_UT
// MRAW PDA reset
for (i = 0; i < g_PDA_quantity; i++)
pda_nontransaction_reset(i);
#endif
// reset HW status
for (i = 0; i < g_PDA_quantity; i++)
PDA_devs[i].HWstatus = 0;
#ifdef CHECK_IRQ_COUNT
// reset PDA0/PDA1 IRQ count
g_PDA0_IRQCount = 0;
g_PDA1_IRQCount = 0;
#ifdef FOR_DEBUG
LOG_INF("PDA0_IRQCount = %d, PDA1_IRQCount = %d\n",
g_PDA0_IRQCount, g_PDA1_IRQCount);
#endif
#endif
// reset output buffer address offset
g_OutputBufferOffset = 0;
if (copy_from_user(&g_pda_Pdadata,
(void *)a_u4Param,
sizeof(struct PDA_Data_t)) != 0) {
LOG_INF("PDA_ENQUE_WAITIRQ copy_from_user failed\n");
nRet = -EFAULT;
break;
}
ret = g_pda_Pdadata.ROInumber == 0 && g_pda_Pdadata.nNumerousROI == 0;
if (g_pda_Pdadata.ROInumber > PDAROIARRAYMAX || ret) {
g_pda_Pdadata.Status = -28;
LOG_INF("ROI number out of range, ROInumber/nNumerousROI:%d/%d\n",
g_pda_Pdadata.ROInumber,
g_pda_Pdadata.nNumerousROI);
LOG_INF("rgn:%d,fix:%d,xnum:%d,siz:%d,FD:%d,cfg0:0x%x,sta:%d/%d\n",
g_pda_Pdadata.rgn_h[0],
g_pda_Pdadata.fix_rgn_h[0],
g_pda_Pdadata.xnum[0],
g_pda_Pdadata.OutputSize,
g_pda_Pdadata.FD_Output,
g_pda_Pdadata.PDA_FrameSetting.PDA_CFG_0.Raw,
g_pda_Pdadata.Status,
g_pda_Pdadata.Timeout);
goto EXIT_WITHOUT_FREE_IOVA;
}
#ifdef PDA_MMQOS
pda_mmqos_bw_set(&g_pda_Pdadata.PDA_FrameSetting);
#endif
if (Get_Input_Addr_From_DMABUF(&g_pda_Pdadata) < 0) {
g_pda_Pdadata.Status = -26;
LOG_INF("Get_Input_Addr_From_DMABUF fail\n");
goto EXIT_WITHOUT_FREE_IOVA;
}
// output buffer mapping iova
if (Get_Output_Addr_From_DMABUF(&g_pda_Pdadata) < 0) {
g_pda_Pdadata.Status = -27;
LOG_INF("Get_Output_Addr_From_DMABUF fail\n");
goto INPUT_BUFFER_FREE_IOVA;
}
// PDA HW and DMA setting
HWDMASettings(&g_pda_Pdadata);
// ------------------------ PDA pre-process done -----------------
// Process flexible roi
nUserROINumber = g_pda_Pdadata.ROInumber;
#ifdef FOR_DEBUG
LOG_INF("nUserROINumber = %d\n", nUserROINumber);
LOG_INF("g_PDA_quantity = %d\n", g_PDA_quantity);
#endif
if (nUserROINumber == 0) {
#ifdef FOR_DEBUG
LOG_INF("no flexible roi needed\n");
#endif
goto FIX_ROI;
}
#ifdef CHECK_IRQ_COUNT
// setting reasonable IRQ count
g_reasonable_IRQCount = 1 +
(int)((nUserROINumber-1)/(PDA_MAXROI_PER_ROUND*g_PDA_quantity));
// reset PDA0/PDA1 IRQ count
g_PDA0_IRQCount = 0;
g_PDA1_IRQCount = 0;
#ifdef FOR_DEBUG
LOG_INF("g_reasonable_IRQCount = %d\n", g_reasonable_IRQCount);
#endif
#endif
// Init ROI count which needed to process
nROIcount = nUserROINumber;
if (PDAProcessFunction(nUserROINumber, nROIcount, MFALSE, 0) < 0) {
LOG_INF("Flexible ROI, PDA process fail\n");
goto EXIT;
}
g_OutputBufferOffset += nUserROINumber*OUT_BYTE_PER_ROI;
#ifdef FOR_DEBUG
LOG_INF("g_OutputBufferOffset: %d\n", g_OutputBufferOffset);
#endif
FIX_ROI:
// Process fix roi
#ifdef FOR_DEBUG
LOG_INF("nNumerousROI:%d\n", g_pda_Pdadata.nNumerousROI);
#endif
if (g_pda_Pdadata.nNumerousROI > FIXROIARRAYMAX) {
g_pda_Pdadata.Status = -28;
LOG_INF("ROI number out of range,nNumerousROI:%d\n",
g_pda_Pdadata.nNumerousROI);
goto EXIT;
}
for (i = 0; i < g_pda_Pdadata.nNumerousROI; ++i) {
nUserROINumber = g_pda_Pdadata.xnum[i]*g_pda_Pdadata.ynum[i];
#ifdef FOR_DEBUG
LOG_INF("nUserROINumber = %d\n", nUserROINumber);
#endif
if (nUserROINumber == 0 || nUserROINumber > 1024) {
g_pda_Pdadata.Status = -28;
LOG_INF("ROI number out of range,idx/ROI/x/ynum:%d/%d/%d/%d\n",
i,
nUserROINumber,
g_pda_Pdadata.xnum[i],
g_pda_Pdadata.ynum[i]);
goto EXIT;
}
#ifdef CHECK_IRQ_COUNT
// setting reasonable IRQ count
g_reasonable_IRQCount = 1 +
(int)((nUserROINumber-1)/(PDA_MAXROI_PER_ROUND*g_PDA_quantity));
// reset PDA0/PDA1 IRQ count
g_PDA0_IRQCount = 0;
g_PDA1_IRQCount = 0;
#ifdef FOR_DEBUG
LOG_INF("g_reasonable_IRQCount = %d\n", g_reasonable_IRQCount);
#endif
#endif
// Init ROI count which needed to process
nROIcount = nUserROINumber;
if (PDAProcessFunction(nUserROINumber, nROIcount, MTRUE, i) < 0) {
LOG_INF("Fix ROI, PDA process fail\n");
goto EXIT;
}
g_OutputBufferOffset += nUserROINumber*OUT_BYTE_PER_ROI;
#ifdef FOR_DEBUG
LOG_INF("g_OutputBufferOffset: %d\n", g_OutputBufferOffset);
#endif
}
//////////////////////////////////////////////////////////////////////////////
EXIT:
// free output iova
#ifdef FOR_DEBUG
LOG_INF("free output iova\n");
#endif
pda_put_dma_buffer(&g_output_mmu);
INPUT_BUFFER_FREE_IOVA:
//free input iova
#ifdef FOR_DEBUG
LOG_INF("free input iova\n");
#endif
pda_put_dma_buffer(&g_image_mmu);
pda_put_dma_buffer(&g_table_mmu);
EXIT_WITHOUT_FREE_IOVA:
#ifdef FOR_DEBUG
LOG_INF("Exit\n");
#endif
#ifndef FPGA_UT
// reset flow
for (i = 0; i < g_PDA_quantity; i++) {
pda_reset(i);
pda_nontransaction_reset(i);
}
#endif
#ifdef GET_PDA_TIME
// for compute pda process time
ktime_get_real_ts64(&total_time_end);
LOG_INF("PDA 1 execute time (%d)\n",
(pda1_done_e.tv_nsec - pda1_done_b.tv_nsec)/1000);
LOG_INF("PDA 2 execute time (%d)\n",
(pda2_done_e.tv_nsec - pda2_done_b.tv_nsec)/1000);
LOG_INF("SW wait time (%d)\n",
(time_end.tv_nsec - pda1_done_b.tv_nsec)/1000);
LOG_INF("kernel total cost time (%d)\n",
(total_time_end.tv_nsec-total_time_begin.tv_nsec)/1000);
#endif
if (copy_to_user((void *)a_u4Param,
&g_pda_Pdadata,
sizeof(struct PDA_Data_t)) != 0) {
LOG_INF("copy_to_user failed\n");
nRet = -EFAULT;
}
break;
default:
LOG_INF("Unknown Cmd(%d)\n", a_u4Command);
break;
}
return nRet;
}
#if IS_ENABLED(CONFIG_COMPAT)
static long PDA_Ioctl_Compat(struct file *a_pstFile, unsigned int a_u4Command,
unsigned long a_u4Param)
{
long i4RetValue = 0;
return i4RetValue;
}
#endif
static int PDA_Open(struct inode *a_pstInode, struct file *a_pstFile)
{
//Enable clock
EnableClock(MTRUE);
LOG_INF("PDA open g_u4EnableClockCount: %d", g_u4EnableClockCount);
#ifdef CHECK_IRQ_COUNT
g_reasonable_IRQCount = 0;
g_PDA0_IRQCount = 0;
g_PDA1_IRQCount = 0;
#ifdef FOR_DEBUG
LOG_INF("IRQCount, Reasonable = %d, PDA0 = %d, PDA1 = %d\n",
g_reasonable_IRQCount, g_PDA0_IRQCount, g_PDA1_IRQCount);
#endif
#endif
return 0;
}
static int PDA_Release(struct inode *a_pstInode, struct file *a_pstFile)
{
#ifdef PDA_MMQOS
pda_mmqos_bw_reset();
#endif
//Disable clock
EnableClock(MFALSE);
LOG_INF("PDA release g_u4EnableClockCount: %d", g_u4EnableClockCount);
return 0;
}
/*******************************************************************************
*
******************************************************************************/
static dev_t g_PDA_devno;
static struct cdev *g_pPDA_CharDrv;
static struct class *actuator_class;
static struct device *lens_device;
static const struct file_operations g_stPDA_fops = {
.owner = THIS_MODULE,
.open = PDA_Open,
.release = PDA_Release,
.unlocked_ioctl = PDA_Ioctl,
#if IS_ENABLED(CONFIG_COMPAT)
.compat_ioctl = PDA_Ioctl_Compat,
#endif
};
static inline int PDA_RegCharDev(void)
{
int nRet = 0;
LOG_INF("Register char driver Start\n");
/* Allocate char driver no. */
nRet = alloc_chrdev_region(&g_PDA_devno, 0, 1, PDA_DEV_NAME);
if (nRet < 0) {
LOG_INF("Allocate device no failed\n");
return nRet;
}
/* Allocate driver */
g_pPDA_CharDrv = cdev_alloc();
if (g_pPDA_CharDrv == NULL) {
unregister_chrdev_region(g_PDA_devno, 1);
LOG_INF("cdev_alloc failed\n");
return nRet;
}
/* Attach file operation. */
cdev_init(g_pPDA_CharDrv, &g_stPDA_fops);
g_pPDA_CharDrv->owner = THIS_MODULE;
/* Add to system */
nRet = cdev_add(g_pPDA_CharDrv, g_PDA_devno, 1);
if (nRet < 0) {
LOG_INF("Attach file operation failed\n");
unregister_chrdev_region(g_PDA_devno, 1);
return nRet;
}
actuator_class = class_create(THIS_MODULE, "PDAdrv");
if (IS_ERR(actuator_class)) {
int ret = PTR_ERR(actuator_class);
LOG_INF("Unable to create class, err = %d\n", ret);
// unregister_chrdev_region(g_PDA_devno, 1);
return ret;
}
lens_device = device_create(actuator_class, NULL, g_PDA_devno, NULL,
PDA_DEV_NAME);
if (IS_ERR(lens_device)) {
int ret = PTR_ERR(lens_device);
LOG_INF("create dev err: /dev/%s, err = %d\n", PDA_DEV_NAME, ret);
// unregister_chrdev_region(g_PDA_devno, 1);
return ret;
}
LOG_INF("Register char driver End\n");
return nRet;
}
static inline void PDA_UnRegCharDev(void)
{
LOG_INF("UnRegCharDev Start\n");
/* Release char driver */
cdev_del(g_pPDA_CharDrv);
unregister_chrdev_region(g_PDA_devno, 1);
device_destroy(actuator_class, g_PDA_devno);
class_destroy(actuator_class);
LOG_INF("UnRegCharDev End\n");
}
/*****************************************************************************
*
****************************************************************************/
static int PDA_probe(struct platform_device *pdev)
{
int nRet = 0;
unsigned int irq_info[3]; /* Record interrupts info from device tree */
struct device_node *node;
LOG_INF("probe Start\n");
// init pda quantity
g_PDA_quantity = 0;
/* Register char driver */
nRet = PDA_RegCharDev();
if (nRet < 0) {
LOG_INF(" register char device failed!\n");
return nRet;
}
LOG_INF("probe - register char driver\n");
spin_lock_init(&g_PDA_SpinLock);
LOG_INF("spin_lock_init done\n");
init_waitqueue_head(&g_wait_queue_head);
LOG_INF("init_waitqueue_head done\n");
//PDA node
node = of_find_compatible_node(NULL, NULL, "mediatek,camera-pda");
if (!node) {
LOG_INF("find camera-pda node failed\n");
return -1;
}
LOG_INF("find camera-pda node done\n");
// must porting in dts
pda_init_larb(pdev);
#if IS_ENABLED(CONFIG_OF)
g_dev1 = &pdev->dev;
if (dma_set_mask_and_coherent(g_dev1, DMA_BIT_MASK(34)))
LOG_INF("No suitable DMA available\n");
//power on smi
/* consumer driver probe*/
pm_runtime_enable(g_dev1); //Note: Its not larb's device.
LOG_INF("pm_runtime_enable pda1 done\n");
#endif
if (pda_devm_clk_get(pdev))
return -1;
// get PDA address, and PDA quantity
PDA_devs[0].m_pda_base = of_iomap(node, 0);
if (!PDA_devs[0].m_pda_base)
LOG_INF("PDA0 base m_pda_base failed\n");
// get IRQ ID and request IRQ
PDA_devs[0].irq = irq_of_parse_and_map(node, 0);
LOG_INF("PDA_dev[0]->irq: %d", PDA_devs[0].irq);
if (PDA_devs[0].irq != 0)
g_PDA_quantity++;
LOG_INF("PDA quantity: %d\n", g_PDA_quantity);
CAMSYS_CONFIG_BASE = pda_get_camsys_address();
if (!CAMSYS_CONFIG_BASE)
LOG_INF("base CAMSYS_CONFIG_BASE failed\n");
if (PDA_devs[0].irq > 0) {
if (PDA_devs[0].irq > 0 && g_PDA_quantity > 0) {
// Get IRQ Flag from device node
nRet = of_property_read_u32_array(node,
"interrupts",
irq_info,
ARRAY_SIZE(irq_info));
if (nRet) {
LOG_INF("PDA1 get irq flags from DTS fail!!\n");
return -ENODEV;
}
LOG_INF("PDA1 irq_info: %d\n", irq_info[2]);
nRet = request_irq(PDA_devs[0].irq,
(irq_handler_t) pda_irqhandle,
irq_info[2],
(const char *)node->name,
NULL);
if (nRet) {
LOG_INF("PDA1 request_irq Fail: %d\n", nRet);
return nRet;
}
} else {
LOG_INF("PDA1 get IRQ ID Fail or No IRQ: %d\n", PDA_devs[0].irq);
}
}
#ifdef PDA_MMQOS
pda_mmqos_init(g_dev1);
#endif
LOG_INF("Attached!!\n");
LOG_INF("probe End\n");
return nRet;
}
static int PDA_remove(struct platform_device *pdev)
{
PDA_UnRegCharDev();
pm_runtime_disable(&pdev->dev);
return 0;
}
static int PDA_suspend(struct platform_device *pdev, pm_message_t mesg)
{
return 0;
}
static int PDA_resume(struct platform_device *pdev)
{
return 0;
}
static int PDA2_probe(struct platform_device *pdev)
{
int nRet = 0;
struct device_node *node;
unsigned int irq_info[3];
LOG_INF("PDA2 probe Start\n");
// get PDA node
node = of_find_compatible_node(NULL, NULL, "mediatek,camera-pda2");
if (!node) {
LOG_INF("find camera-pda node failed\n");
return -1;
}
LOG_INF("find camera-pda node done\n");
// must porting in dts
pda_init_larb(pdev);
#if IS_ENABLED(CONFIG_OF)
g_dev2 = &pdev->dev;
if (dma_set_mask_and_coherent(g_dev2, DMA_BIT_MASK(34)))
LOG_INF("No suitable DMA available\n");
//power on smi
// consumer driver probe
pm_runtime_enable(g_dev2); //Note: Its not larb's device.
LOG_INF("pm_runtime_enable pda2 done\n");
#endif
// get PDA address, and PDA quantity
PDA_devs[1].m_pda_base = of_iomap(node, 0);
if (!PDA_devs[1].m_pda_base)
LOG_INF("base m_pda_base failed, index: %d\n", 1);
// get IRQ ID and request IRQ
PDA_devs[1].irq = irq_of_parse_and_map(node, 0);
LOG_INF("PDA_dev[1]->irq: %d", PDA_devs[1].irq);
if (PDA_devs[1].irq != 0)
g_PDA_quantity++;
LOG_INF("PDA quantity: %d\n", g_PDA_quantity);
if (PDA_devs[1].irq > 0) {
if (PDA_devs[1].irq > 0 && g_PDA_quantity > 1) {
// Get IRQ Flag from device node
nRet = of_property_read_u32_array(node,
"interrupts",
irq_info,
ARRAY_SIZE(irq_info));
if (nRet) {
LOG_INF("PDA2 get irq flags from DTS fail!!\n");
return -ENODEV;
}
LOG_INF("PDA2 irq_info: %d\n", irq_info[2]);
nRet = request_irq(PDA_devs[1].irq,
(irq_handler_t) pda2_irqhandle,
irq_info[2],
(const char *)node->name,
NULL);
if (nRet) {
LOG_INF("PDA2 request_irq Fail: %d\n", nRet);
return nRet;
}
} else {
LOG_INF("PDA2 get IRQ ID Fail or No IRQ: %d\n", PDA_devs[1].irq);
}
}
LOG_INF("PDA2 probe End\n");
return nRet;
}
static int PDA2_remove(struct platform_device *pdev)
{
pm_runtime_disable(&pdev->dev);
return 0;
}
//////////////////////////////////////// PDA driver //////////////////////////
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id gpda_of_device_id[] = {
{.compatible = "mediatek,camera-pda",},
{}
};
#endif
MODULE_DEVICE_TABLE(of, gpda_of_device_id);
static struct platform_driver PDADriver = {
.probe = PDA_probe,
.remove = PDA_remove,
.suspend = PDA_suspend,
.resume = PDA_resume,
.driver = {
.name = PDA_DEV_NAME,
.owner = THIS_MODULE,
#if IS_ENABLED(CONFIG_OF)
.of_match_table = of_match_ptr(gpda_of_device_id),
#endif
}
};
//////////////////////////////////////// PDA 2 driver ////////////////////////
#if IS_ENABLED(CONFIG_OF)
static const struct of_device_id gpda2_of_device_id[] = {
{.compatible = "mediatek,camera-pda2",},
{}
};
#endif
MODULE_DEVICE_TABLE(of, gpda2_of_device_id);
static struct platform_driver PDA2Driver = {
.probe = PDA2_probe,
.remove = PDA2_remove,
.driver = {
.name = "camera-pda2",
.owner = THIS_MODULE,
.of_match_table = of_match_ptr(gpda2_of_device_id),
}
};
static int __init camera_pda_init(void)
{
int ret = 0;
ret = platform_driver_register(&PDADriver);
if (ret < 0) {
LOG_INF("platform_driver_register PDADriver\n");
return ret;
}
ret = platform_driver_register(&PDA2Driver);
if (ret < 0) {
LOG_INF("platform_driver_register PDADriver\n");
return ret;
}
return ret;
}
static void __exit camera_pda_exit(void)
{
platform_driver_unregister(&PDADriver);
platform_driver_unregister(&PDA2Driver);
}
/****************************************************************************
*
****************************************************************************/
module_init(camera_pda_init);
module_exit(camera_pda_exit);
MODULE_DESCRIPTION("Camera PDA driver");
MODULE_AUTHOR("MM6SW3");
MODULE_LICENSE("GPL");