camera: sync V5.7 code and verify single_online_test
Change-Id: I0f894b8b50bcb2cf4ea10d749d9de1b0e11265e2
This commit is contained in:
@@ -69,12 +69,14 @@
|
||||
interrupt-names = "ipe-irq";
|
||||
clocks = <&ccu CLK_CSI>,
|
||||
<&ccu CLK_CCIC_4X>,
|
||||
<&ccu CLK_ISP_BUS>;
|
||||
clock-names = "csi_func", "ccic_func", "isp_axi";
|
||||
<&ccu CLK_ISP_BUS>,
|
||||
<&ccu CLK_DPU_MCLK>;
|
||||
clock-names = "csi_func", "ccic_func", "isp_axi", "dpu_mclk";
|
||||
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>,
|
||||
<&reset RESET_LCD_MCLK>;
|
||||
reset-names = "isp_ahb_reset", "csi_reset",
|
||||
"ccic_4x_reset", "isp_ci_reset";
|
||||
"ccic_4x_reset", "isp_ci_reset", "mclk_reset";
|
||||
interconnects = <&dram_range3>;
|
||||
interconnect-names = "dma-mem";
|
||||
status = "okay";
|
||||
@@ -89,14 +91,16 @@
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <82>;
|
||||
interrupt-names = "ipe-irq";
|
||||
clocks = <&ccu CLK_CSI>, <&ccu CLK_CCIC_4X>,
|
||||
<&ccu CLK_ISP_BUS>;
|
||||
clock-names = "csi_func", "ccic_func",
|
||||
"isp_axi";
|
||||
clocks = <&ccu CLK_CSI>,
|
||||
<&ccu CLK_CCIC_4X>,
|
||||
<&ccu CLK_ISP_BUS>,
|
||||
<&ccu CLK_DPU_MCLK>;
|
||||
clock-names = "csi_func", "ccic_func", "isp_axi", "dpu_mclk";
|
||||
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>,
|
||||
<&reset RESET_LCD_MCLK>;
|
||||
reset-names = "isp_ahb_reset", "csi_reset",
|
||||
"ccic_4x_reset", "isp_ci_reset";
|
||||
"ccic_4x_reset", "isp_ci_reset", "mclk_reset";
|
||||
interconnects = <&dram_range3>;
|
||||
interconnect-names = "dma-mem";
|
||||
status = "okay";
|
||||
@@ -111,14 +115,16 @@
|
||||
interrupt-parent = <&intc>;
|
||||
interrupts = <83>;
|
||||
interrupt-names = "ipe-irq";
|
||||
clocks = <&ccu CLK_CSI>, <&ccu CLK_CCIC_4X>,
|
||||
<&ccu CLK_ISP_BUS>;
|
||||
clock-names = "csi_func", "ccic_func",
|
||||
"isp_axi";
|
||||
clocks = <&ccu CLK_CSI>,
|
||||
<&ccu CLK_CCIC_4X>,
|
||||
<&ccu CLK_ISP_BUS>,
|
||||
<&ccu CLK_DPU_MCLK>;
|
||||
clock-names = "csi_func", "ccic_func", "isp_axi", "dpu_mclk";
|
||||
resets = <&reset RESET_ISP_AHB>, <&reset RESET_CSI>,
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>;
|
||||
<&reset RESET_CCIC_4X>, <&reset RESET_ISP_CI>,
|
||||
<&reset RESET_LCD_MCLK>;
|
||||
reset-names = "isp_ahb_reset", "csi_reset",
|
||||
"ccic_4x_reset", "isp_ci_reset";
|
||||
"ccic_4x_reset", "isp_ci_reset", "mclk_reset";
|
||||
interconnects = <&dram_range3>;
|
||||
interconnect-names = "dma-mem";
|
||||
status = "okay";
|
||||
|
||||
@@ -12,6 +12,7 @@ cam_ccic_v2-objs += cam_ccic/ccic_hwreg.o
|
||||
cam_ccic_v2-objs += cam_ccic/csiphy.o
|
||||
cam_ccic_v2-objs += cam_ccic/ccic_drv.o
|
||||
cam_ccic_v2-objs += cam_ccic/dptc_drv.o
|
||||
cam_ccic_v2-objs += cam_ccic/ccic_vdev.o
|
||||
|
||||
obj-$(CONFIG_SPACEMIT_K1X_CPP_V2) += cam_cpp_v2.o
|
||||
cam_cpp_v2-objs += cam_cpp/k1x_cpp.o
|
||||
|
||||
@@ -18,11 +18,13 @@
|
||||
#include <media/v4l2-dev.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <linux/media-bus-format.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/clk.h>
|
||||
#include "ccic_drv.h"
|
||||
#include "ccic_hwreg.h"
|
||||
#include "csiphy.h"
|
||||
#include "ccic_vdev.h"
|
||||
|
||||
#ifdef CONFIG_ARCH_ZYNQMP
|
||||
#include "dptc_drv.h"
|
||||
@@ -31,8 +33,19 @@
|
||||
|
||||
#define K1X_CCIC_DRV_NAME "k1xccic"
|
||||
|
||||
#define CAM_ALIGN(a, b) ({ \
|
||||
unsigned int ___tmp1 = (a); \
|
||||
unsigned int ___tmp2 = (b); \
|
||||
unsigned int ___tmp3 = ___tmp1 % ___tmp2; \
|
||||
___tmp1 /= ___tmp2; \
|
||||
if (___tmp3) \
|
||||
___tmp1++; \
|
||||
___tmp1 *= ___tmp2; \
|
||||
___tmp1; \
|
||||
})
|
||||
static LIST_HEAD(ccic_devices);
|
||||
static DEFINE_MUTEX(list_lock);
|
||||
static void ccic_dma_bh_handler(struct ccic_dma_work_struct *ccic_dma_work);
|
||||
|
||||
static void ccic_irqmask(struct ccic_ctrl *ctrl, int on)
|
||||
{
|
||||
@@ -131,17 +144,23 @@ static int ccic_config_csi2_dphy(struct ccic_ctrl *ctrl,
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int ccic_config_csi2_vc(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1)
|
||||
static int ccic_config_csi2_vc_dt(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1, u8 dt0, u8 dt1)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ccic_dev *ccic_dev = ctrl->ccic_dev;
|
||||
|
||||
switch (md) {
|
||||
case CCIC_CSI2VC_NM: /* Normal mode */
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_VCCTRL, CSI2_VCCTRL_DT_ENABLE);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT0_EN);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT1_EN);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL,
|
||||
CSI2_VCCTRL_MD_NORMAL, CSI2_VCCTRL_MD_MASK);
|
||||
break;
|
||||
case CCIC_CSI2VC_VC: /* Virtual Channel mode */
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_VCCTRL, CSI2_VCCTRL_DT_ENABLE);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT0_EN);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT1_EN);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL,
|
||||
CSI2_VCCTRL_MD_VC, CSI2_VCCTRL_MD_MASK);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL, vc0 << 14,
|
||||
@@ -150,9 +169,23 @@ static int ccic_config_csi2_vc(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1)
|
||||
CSI2_VCCTRL_VC1_MASK);
|
||||
break;
|
||||
case CCIC_CSI2VC_DT: /* TODO: Data-Type Interleaving */
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL,
|
||||
CSI2_VCCTRL_MD_DT, CSI2_VCCTRL_MD_MASK);
|
||||
//ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL,
|
||||
// CSI2_VCCTRL_MD_DT, CSI2_VCCTRL_MD_MASK);
|
||||
pr_err("csi2 vc mode %d todo\n", md);
|
||||
ret = -EINVAL;
|
||||
break;
|
||||
case CCIC_CSI2VC_VCDT:
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_VCCTRL, CSI2_VCCTRL_DT_ENABLE);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT0_EN);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_DT_FLT, CSI2_DT_FLT2_EN);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL, vc0 << 14,
|
||||
CSI2_VCCTRL_VC0_MASK);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_VCCTRL, vc1 << 22,
|
||||
CSI2_VCCTRL_VC1_MASK);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_DT_FLT, dt0 << CSI2_DT_FLT0_SHIFT,
|
||||
CSI2_DT_FLT0_MASK);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CSI2_DT_FLT, dt1 << CSI2_DT_FLT2_SHIFT,
|
||||
CSI2_DT_FLT2_MASK);
|
||||
break;
|
||||
default:
|
||||
dev_err(ccic_dev->dev, "invalid csi2 vc mode %d\n", md);
|
||||
@@ -292,10 +325,10 @@ static int axi_set_clock_rates(struct clk *clock)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ccic_dma_clk_enable(struct ccic_dma *dma, int on)
|
||||
static int ccic_dma_clk_enable(struct ccic_dma *dma, int on)
|
||||
{
|
||||
struct ccic_dev *ccic = dma->ccic_dev;
|
||||
struct device *dev = &ccic->pdev->dev;
|
||||
struct ccic_dev *ccic_dev = dma->ccic_dev;
|
||||
struct device *dev = &ccic_dev->pdev->dev;
|
||||
int ret;
|
||||
|
||||
if (on) {
|
||||
@@ -303,30 +336,198 @@ int ccic_dma_clk_enable(struct ccic_dma *dma, int on)
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
ret = clk_prepare_enable(ccic->axi_clk);
|
||||
ret = clk_prepare_enable(ccic_dev->axi_clk);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_sync(dev);
|
||||
return ret;
|
||||
}
|
||||
reset_control_deassert(ccic->isp_ci_reset);
|
||||
reset_control_deassert(ccic_dev->isp_ci_reset);
|
||||
|
||||
ret = axi_set_clock_rates(ccic->axi_clk);
|
||||
ret = axi_set_clock_rates(ccic_dev->axi_clk);
|
||||
if (ret < 0) {
|
||||
pm_runtime_put_sync(dev);
|
||||
return ret;
|
||||
}
|
||||
reset_control_deassert(ccic->isp_ci_reset);
|
||||
reset_control_deassert(ccic_dev->isp_ci_reset);
|
||||
} else {
|
||||
clk_disable_unprepare(ccic->axi_clk);
|
||||
reset_control_assert(ccic->isp_ci_reset);
|
||||
clk_disable_unprepare(ccic_dev->axi_clk);
|
||||
reset_control_assert(ccic_dev->isp_ci_reset);
|
||||
pm_runtime_put_sync(dev);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_dma_enable(struct ccic_dma *dma_dev, int enable)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
|
||||
if (enable) {
|
||||
//ccic_reg_set_bit(ccic_dev, REG_IRQMASK, FRAMEIRQS);
|
||||
ccic_dma_set_burst(ccic_dev);
|
||||
/* 0x3c: enable ccic dma */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CTRL0, BIT(0));
|
||||
ccic_reg_set_bit(ccic_dev, 0x40, BIT(31) | BIT(26));
|
||||
ccic_reg_clear_bit(ccic_dev, 0x40, BIT(25));
|
||||
} else {
|
||||
//ccic_reg_clear_bit(ccic_dev, REG_IRQMASK, FRAMEIRQS);
|
||||
/* 0x3c: disable ccic dma */
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CTRL0, BIT(0));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_dma_set_fmt(struct ccic_dma *dma_dev,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int pix_fmt)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
struct device *dev = ccic_dev->dev;
|
||||
unsigned int data_fmt = C0_DF_BAYER, imgsz_w = 0, imgsz_h = 0;
|
||||
unsigned int stride_y = 0, stride_uv = 0;
|
||||
|
||||
switch (pix_fmt) {
|
||||
case MEDIA_BUS_FMT_UYVY8_2X8:
|
||||
data_fmt = C0_DF_BAYER;
|
||||
imgsz_w = width;
|
||||
stride_y = 0;
|
||||
imgsz_h = height;
|
||||
stride_uv = 0;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_SBGGR8_1X8:
|
||||
case MEDIA_BUS_FMT_SGBRG8_1X8:
|
||||
case MEDIA_BUS_FMT_SGRBG8_1X8:
|
||||
case MEDIA_BUS_FMT_SRGGB8_1X8:
|
||||
data_fmt = C0_DF_BAYER;
|
||||
imgsz_w = width;
|
||||
stride_y = 0;//CAM_ALIGN(imgsz_w, 8);
|
||||
imgsz_h = height;
|
||||
stride_uv = 0;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_SBGGR10_1X10:
|
||||
case MEDIA_BUS_FMT_SGBRG10_1X10:
|
||||
case MEDIA_BUS_FMT_SGRBG10_1X10:
|
||||
case MEDIA_BUS_FMT_SRGGB10_1X10:
|
||||
data_fmt = C0_DF_BAYER;
|
||||
imgsz_w = width * 5 / 4;
|
||||
stride_y = 0;//CAM_ALIGN(imgsz_w, 8);
|
||||
imgsz_h = height;
|
||||
stride_uv = 0;
|
||||
break;
|
||||
case MEDIA_BUS_FMT_SBGGR12_1X12:
|
||||
case MEDIA_BUS_FMT_SGBRG12_1X12:
|
||||
case MEDIA_BUS_FMT_SGRBG12_1X12:
|
||||
case MEDIA_BUS_FMT_SRGGB12_1X12:
|
||||
data_fmt = C0_DF_BAYER;
|
||||
imgsz_w = width * 3 / 2;
|
||||
stride_y = 0;//CAM_ALIGN(imgsz_w, 8);
|
||||
imgsz_h = height;
|
||||
stride_uv = 0;
|
||||
break;
|
||||
default:
|
||||
pr_err("%s failed: invalid pixfmt %d\n", __func__, pix_fmt);
|
||||
return -1;
|
||||
}
|
||||
|
||||
dev_info(dev, "stride_y=0x%x, width=%u\n", stride_y, width);
|
||||
ccic_reg_write(ccic_dev, REG_IMGPITCH, stride_uv << 16 | stride_y);
|
||||
ccic_reg_write(ccic_dev, REG_IMGSIZE, imgsz_h << 16 | imgsz_w);
|
||||
ccic_reg_write(ccic_dev, REG_IMGOFFSET, 0x0);
|
||||
ccic_reg_write_mask(ccic_dev, REG_CTRL0, data_fmt, C0_DF_MASK);
|
||||
/* Make sure it knows we want to use hsync/vsync. */
|
||||
ccic_reg_write_mask(ccic_dev, REG_CTRL0, C0_SIF_HVSYNC, C0_SIFM_MASK);
|
||||
/* Need set following bit for auto-recovery */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CTRL0, C0_EOFFLUSH);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_dma_set_addr(struct ccic_dma *dma_dev,
|
||||
unsigned long addr_y,
|
||||
unsigned long addr_u,
|
||||
unsigned long addr_v)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
|
||||
ccic_reg_write(ccic_dev, 0x00, (u32)(addr_y & 0xffffffff));
|
||||
ccic_reg_write(ccic_dev, 0x0c, (u32)(addr_u & 0xffffffff));
|
||||
ccic_reg_write(ccic_dev, 0x18, (u32)(addr_v & 0xffffffff));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_dma_shadow_ready(struct ccic_dma *dma_dev)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
ccic_reg_set_bit(ccic_dev, REG_CTRL1, C1_SHADOW_RDY);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_dma_src_select(struct ccic_dma *dma_dev, int src, unsigned int main_ccic_id)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
return ccic_dma_src_sel(ccic_dev, src, main_ccic_id);
|
||||
}
|
||||
|
||||
static void ccic_dma_dump_regs(struct ccic_dma *dma_dev)
|
||||
{
|
||||
unsigned int reg_val = 0;
|
||||
struct ccic_dev *ccic_dev = dma_dev->ccic_dev;
|
||||
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x30);
|
||||
printk(KERN_INFO "ccic%d [0x30]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x28);
|
||||
printk(KERN_INFO "ccic%d [0x28]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x2c);
|
||||
printk(KERN_INFO "ccic%d [0x2c]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x24);
|
||||
printk(KERN_INFO "ccic%d [0x24]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x34);
|
||||
printk(KERN_INFO "ccic%d [0x34]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x38);
|
||||
printk(KERN_INFO "ccic%d [0x38]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x3c);
|
||||
printk(KERN_INFO "ccic%d [0x3c]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x40);
|
||||
printk(KERN_INFO "ccic%d [0x40]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x44);
|
||||
printk(KERN_INFO "ccic%d [0x44]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x48);
|
||||
printk(KERN_INFO "ccic%d [0x48]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x310);
|
||||
printk(KERN_INFO "ccic%d [0x310]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x60);
|
||||
printk(KERN_INFO "ccic%d [0x60]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x23c);
|
||||
printk(KERN_INFO "ccic%d [0x23c]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x128);
|
||||
printk(KERN_INFO "ccic%d [0x128]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x12c);
|
||||
printk(KERN_INFO "ccic%d [0x12c]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x134);
|
||||
printk(KERN_INFO "ccic%d [0x134]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x138);
|
||||
printk(KERN_INFO "ccic%d [0x138]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x100);
|
||||
printk(KERN_INFO "ccic%d [0x100]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x140);
|
||||
printk(KERN_INFO "ccic%d [0x140]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x144);
|
||||
printk(KERN_INFO "ccic%d [0x144]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
reg_val = ccic_reg_read(ccic_dev, 0x124);
|
||||
printk(KERN_INFO "ccic%d [0x124]=0x%08x\n", ccic_dev->index, reg_val);
|
||||
}
|
||||
static struct ccic_dma_ops ccic_dma_ops = {
|
||||
.set_fmt = ccic_dma_set_fmt,
|
||||
.shadow_ready = ccic_dma_shadow_ready,
|
||||
.set_addr = ccic_dma_set_addr,
|
||||
.ccic_enable = ccic_dma_enable,
|
||||
.clk_enable = ccic_dma_clk_enable,
|
||||
.src_sel = ccic_dma_src_select,
|
||||
.dump_regs = ccic_dma_dump_regs,
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -372,10 +573,13 @@ int ccic_clk_enable(struct ccic_ctrl *ctrl, int en)
|
||||
pr_err("rpm get failed\n");
|
||||
return ret;
|
||||
}
|
||||
pm_stay_awake(&ccic_dev->pdev->dev);
|
||||
|
||||
clk_prepare_enable(ccic_dev->dpu_clk);
|
||||
reset_control_deassert(ccic_dev->mclk_reset);
|
||||
|
||||
//clk_prepare_enable(ccic_dev->ahb_clk);
|
||||
reset_control_deassert(ccic_dev->ahb_reset);
|
||||
|
||||
clk_prepare_enable(ccic_dev->clk4x);
|
||||
reset_control_deassert(ccic_dev->ccic_4x_reset);
|
||||
clk_prepare_enable(ccic_dev->csi_clk);
|
||||
@@ -394,9 +598,12 @@ int ccic_clk_enable(struct ccic_ctrl *ctrl, int en)
|
||||
clk_disable_unprepare(ccic_dev->clk4x);
|
||||
reset_control_assert(ccic_dev->ccic_4x_reset);
|
||||
|
||||
clk_disable_unprepare(ccic_dev->dpu_clk);
|
||||
reset_control_assert(ccic_dev->mclk_reset);
|
||||
|
||||
//clk_disable_unprepare(ccic_dev->ahb_clk);
|
||||
reset_control_assert(ccic_dev->ahb_reset);
|
||||
|
||||
pm_relax(&ccic_dev->pdev->dev);
|
||||
pm_runtime_put_sync(&ccic_dev->pdev->dev);
|
||||
}
|
||||
|
||||
@@ -405,13 +612,14 @@ int ccic_clk_enable(struct ccic_ctrl *ctrl, int en)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ccic_config_csi2_mbus(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1, int lanes)
|
||||
int ccic_config_csi2_mbus(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1, u8 dt0, u8 dt1,
|
||||
int lanes)
|
||||
{
|
||||
int ret;
|
||||
struct ccic_dev *ccic_dev = ctrl->ccic_dev;
|
||||
struct mipi_csi2 csi2para;
|
||||
|
||||
ret = ccic_config_csi2_vc(ctrl, md, vc0, vc1);
|
||||
ret = ccic_config_csi2_vc_dt(ctrl, md, vc0, vc1, dt0, dt1);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
@@ -545,9 +753,16 @@ static int ccic_init_clk(struct ccic_dev *dev)
|
||||
if (IS_ERR_OR_NULL(dev->isp_ci_reset))
|
||||
return PTR_ERR(dev->isp_ci_reset);
|
||||
|
||||
dev->mclk_reset = devm_reset_control_get_optional_shared(&dev->pdev->dev, "mclk_reset");
|
||||
if (IS_ERR_OR_NULL(dev->mclk_reset))
|
||||
return PTR_ERR(dev->mclk_reset);
|
||||
|
||||
dev->csi_clk = devm_clk_get(&dev->pdev->dev, "csi_func");
|
||||
if (IS_ERR(dev->csi_clk))
|
||||
return PTR_ERR(dev->csi_clk);
|
||||
dev->dpu_clk = devm_clk_get(&dev->pdev->dev, "dpu_mclk");
|
||||
if (IS_ERR(dev->dpu_clk))
|
||||
return PTR_ERR(dev->dpu_clk);
|
||||
|
||||
dev->clk4x = devm_clk_get(&dev->pdev->dev, "ccic_func");
|
||||
return PTR_ERR_OR_ZERO(dev->clk4x);
|
||||
@@ -650,6 +865,31 @@ void ccic_ctrl_put(struct ccic_ctrl *ctrl)
|
||||
|
||||
EXPORT_SYMBOL(ccic_ctrl_put);
|
||||
|
||||
|
||||
int ccic_dma_get(struct ccic_dma **ccic_dma, int id)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = NULL;
|
||||
struct ccic_dev *tmp = NULL;
|
||||
struct ccic_dma *dma = NULL;
|
||||
|
||||
list_for_each_entry(tmp, &ccic_devices, list) {
|
||||
if (tmp->index == id) {
|
||||
ccic_dev = tmp;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!ccic_dev) {
|
||||
pr_err("ccic%d not found", id);
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
dma = ccic_dev->dma;
|
||||
*ccic_dma = dma;
|
||||
pr_debug("acquire ccic%d dma dev succeed\n", id);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(ccic_dma_get);
|
||||
static void ipe_error_irq_handler(struct ccic_dev *ccic, u32 ipestatus, u32 csi2status)
|
||||
{
|
||||
static DEFINE_RATELIMIT_STATE(rs, 5 * HZ, 20);
|
||||
@@ -664,10 +904,110 @@ static void ipe_error_irq_handler(struct ccic_dev *ccic, u32 ipestatus, u32 csi2
|
||||
}
|
||||
}
|
||||
|
||||
static int ccic_put_dma_work(struct ccic_dma_context *dma_ctx,
|
||||
struct ccic_dma_work_struct *ccic_dma_work)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
spin_lock_irqsave(&dma_ctx->slock, flags);
|
||||
list_del_init(&ccic_dma_work->busy_list_entry);
|
||||
list_add(&ccic_dma_work->idle_list_entry, &dma_ctx->dma_work_idle_list);
|
||||
spin_unlock_irqrestore(&dma_ctx->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int ccic_get_dma_work(struct ccic_dma_context *dma_ctx,
|
||||
struct ccic_dma_work_struct **ccic_dma_work)
|
||||
{
|
||||
unsigned long flags = 0;
|
||||
|
||||
spin_lock_irqsave(&dma_ctx->slock, flags);
|
||||
*ccic_dma_work = list_first_entry_or_null(&dma_ctx->dma_work_idle_list, struct ccic_dma_work_struct, idle_list_entry);
|
||||
if (NULL == *ccic_dma_work) {
|
||||
spin_unlock_irqrestore(&dma_ctx->slock, flags);
|
||||
return -1;
|
||||
}
|
||||
list_del_init(&((*ccic_dma_work)->idle_list_entry));
|
||||
list_add(&((*ccic_dma_work)->busy_list_entry), &dma_ctx->dma_work_busy_list);
|
||||
spin_unlock_irqrestore(&dma_ctx->slock, flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void ccic_dma_bh_handler(struct ccic_dma_work_struct *ccic_dma_work)
|
||||
{
|
||||
struct spm_ccic_vnode *ac_vnode = ccic_dma_work->ac_vnode;
|
||||
struct device *dev = ac_vnode->ccic_dev->dev;
|
||||
struct ccic_dma_context *dma_ctx = &ac_vnode->dma_ctx;
|
||||
struct spm_ccic_vbuffer *n = NULL, *pos = NULL;
|
||||
//unsigned int irq_status = ccic_dma_work->irq_status;
|
||||
LIST_HEAD(export_list);
|
||||
unsigned long flags = 0;
|
||||
|
||||
spin_lock(&ac_vnode->waitq_head.lock);
|
||||
ac_vnode->in_tasklet = 1;
|
||||
if (ac_vnode->in_streamoff || !ac_vnode->is_streaming) {
|
||||
wake_up_locked(&ac_vnode->waitq_head);
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
goto dma_tasklet_finish;
|
||||
}
|
||||
wake_up_locked(&ac_vnode->waitq_head);
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
spin_lock_irqsave(&ac_vnode->slock, flags);
|
||||
list_for_each_entry_safe(pos, n, &ac_vnode->busy_list, list_entry) {
|
||||
if (pos->flags & (AC_BUF_FLAG_HW_ERR | AC_BUF_FLAG_SW_ERR | AC_BUF_FLAG_DONE_TOUCH)) {
|
||||
list_del_init(&(pos->list_entry));
|
||||
atomic_dec(&ac_vnode->busy_buf_cnt);
|
||||
list_add_tail(&(pos->list_entry), &export_list);
|
||||
}
|
||||
}
|
||||
spin_unlock_irqrestore(&ac_vnode->slock, flags);
|
||||
list_for_each_entry_safe(pos, n, &export_list, list_entry) {
|
||||
if (!(pos->flags & AC_BUF_FLAG_SOF_TOUCH)) {
|
||||
dev_warn(dev, "%s export buf index=%u frameid=%u without sof touch\n", ac_vnode->name, pos->vb2_v4l2_buf.vb2_buf.index, pos->vb2_v4l2_buf.sequence);
|
||||
}
|
||||
if (pos->flags & AC_BUF_FLAG_HW_ERR) {
|
||||
//pos->vb2_v4l2_buf.flags |= V4L2_BUF_FLAG_ERROR_HW;
|
||||
dev_warn(dev, "%s export buf index=%u frameid=%u with hw error\n", ac_vnode->name, pos->vb2_v4l2_buf.vb2_buf.index, pos->vb2_v4l2_buf.sequence);
|
||||
spm_cvdev_export_ccic_vbuffer(pos, 1);
|
||||
ac_vnode->hw_err_frm++;
|
||||
} else if (pos->flags & AC_BUF_FLAG_SW_ERR) {
|
||||
//pos->vb2_v4l2_buf.flags |= V4L2_BUF_FLAG_ERROR_SW;
|
||||
dev_warn(dev, "%s export buf index=%u frameid=%u with sw error\n", ac_vnode->name, pos->vb2_v4l2_buf.vb2_buf.index, pos->vb2_v4l2_buf.sequence);
|
||||
spm_cvdev_export_ccic_vbuffer(pos, 1);
|
||||
ac_vnode->sw_err_frm++;
|
||||
} else if (pos->flags & AC_BUF_FLAG_DONE_TOUCH) {
|
||||
spm_cvdev_export_ccic_vbuffer(pos, 0);
|
||||
ac_vnode->ok_frm++;
|
||||
}
|
||||
}
|
||||
dma_tasklet_finish:
|
||||
if (ac_vnode) {
|
||||
spin_lock(&ac_vnode->waitq_head.lock);
|
||||
ac_vnode->in_tasklet = 0;
|
||||
wake_up_locked(&ac_vnode->waitq_head);
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
}
|
||||
ccic_put_dma_work(dma_ctx, ccic_dma_work);
|
||||
}
|
||||
|
||||
static void ccic_dma_tasklet_handler(unsigned long param)
|
||||
{
|
||||
struct ccic_dma_work_struct *ccic_dma_work = (struct ccic_dma_work_struct*)param;
|
||||
ccic_dma_bh_handler(ccic_dma_work);
|
||||
}
|
||||
static irqreturn_t k1x_ccic_isr(int irq, void *data)
|
||||
{
|
||||
struct ccic_dev *ccic_dev = data;
|
||||
uint32_t irqs, csi2status;
|
||||
struct spm_ccic_vnode *ac_vnode = (struct spm_ccic_vnode*)ccic_dev->vnode;
|
||||
struct ccic_dma_context *dma_ctx = &ac_vnode->dma_ctx;
|
||||
struct spm_ccic_vbuffer *pos = NULL, *ac_vb = NULL;
|
||||
struct ccic_dma_work_struct *ccic_dma_work = NULL;
|
||||
struct ccic_dma *ccic_dma = ac_vnode->ccic_dev->dma;
|
||||
struct device *dev = ac_vnode->ccic_dev->dev;
|
||||
uint32_t irqs = 0, csi2status = 0, tmp = 0;
|
||||
int ret = 0;
|
||||
|
||||
irqs = ccic_reg_read(ccic_dev, REG_IRQSTAT);
|
||||
if (!(irqs & ~IRQ_IDI_PRO_LINE))
|
||||
@@ -682,8 +1022,8 @@ static irqreturn_t k1x_ccic_isr(int irq, void *data)
|
||||
if (irqs & IRQ_DMA_PRO_LINE)
|
||||
pr_debug("CCIC%d: IRQ_DMA_PRO_LINE\n", ccic_dev->index);
|
||||
|
||||
if (irqs & IRQ_IDI_PRO_LINE)
|
||||
pr_debug("CCIC%d: IRQ_IDI_PRO_LINE\n", ccic_dev->index);
|
||||
//if (irqs & IRQ_IDI_PRO_LINE)
|
||||
// pr_debug("CCIC%d: IRQ_IDI_PRO_LINE\n", ccic_dev->index);
|
||||
|
||||
if (irqs & IRQ_CSI2IDI_FLUSH)
|
||||
pr_debug("CCIC%d: IRQ_CSI2IDI_FLUSH\n", ccic_dev->index);
|
||||
@@ -700,6 +1040,84 @@ static irqreturn_t k1x_ccic_isr(int irq, void *data)
|
||||
if (irqs & IRQ_DPHY_LN_ULPS_ACTIVE)
|
||||
pr_debug("CCIC%d: IRQ_DPHY_LN_ULPS_ACTIVE\n", ccic_dev->index);
|
||||
|
||||
//if (irqs & IRQ_DMA_SOF) {
|
||||
// dev_dbg(dev, "CCIC%d: IRQ_DMA_SOF\n", ccic_dev->index);
|
||||
//}
|
||||
if (irqs & IRQ_DMA_SOF || irqs & IRQ_SHADOW_NOT_RDY) {
|
||||
ac_vnode->frame_id++;
|
||||
ac_vnode->total_frm++;
|
||||
}
|
||||
spin_lock(&ac_vnode->waitq_head.lock);
|
||||
ac_vnode->in_irq = 1;
|
||||
if (ac_vnode->in_streamoff) {
|
||||
ac_vnode->in_irq = 0;
|
||||
wake_up_locked(&ac_vnode->waitq_head);
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
if (ac_vnode->is_streaming && (irqs & FRAMEIRQS)) {
|
||||
//if (irqs & IRQ_CSI_SOF) {
|
||||
if (irqs & IRQ_DMA_SOF || irqs & IRQ_SHADOW_NOT_RDY) {
|
||||
spm_cvdev_dq_idle_vbuffer(ac_vnode, &ac_vb);
|
||||
if (ac_vb) {
|
||||
spm_cvdev_q_busy_vbuffer(ac_vnode, ac_vb);
|
||||
ccic_update_dma_addr(ac_vnode, ac_vb, 0);
|
||||
ccic_dma->ops->shadow_ready(ccic_dma);
|
||||
}
|
||||
}
|
||||
tmp = irqs;
|
||||
spin_lock(&(ac_vnode->slock));
|
||||
list_for_each_entry(pos, &(ac_vnode->busy_list), list_entry) {
|
||||
if (!tmp)
|
||||
break;
|
||||
if (tmp & (IRQ_DMA_OVERFLOW | IRQ_DMA_NOT_DONE)) {
|
||||
if (!(pos->flags & AC_BUF_FLAG_SOF_TOUCH)) {
|
||||
dev_info(dev, "CCIC%d: dma err(0x%08x) without sof, drop it\n", ccic_dev->index, tmp);
|
||||
tmp &= ~(IRQ_DMA_OVERFLOW | IRQ_DMA_NOT_DONE);
|
||||
} else if (!(pos->flags & AC_BUF_FLAG_HW_ERR)) {
|
||||
pos->flags |= AC_BUF_FLAG_HW_ERR;
|
||||
dev_info(dev, "CCIC%d: dma err(0x%08x)\n", ccic_dev->index, tmp);
|
||||
tmp &= ~(IRQ_DMA_OVERFLOW | IRQ_DMA_NOT_DONE);
|
||||
}
|
||||
}
|
||||
if (tmp & IRQ_DMA_EOF) {
|
||||
if (!(pos->flags & AC_BUF_FLAG_SOF_TOUCH)) {
|
||||
dev_info(dev, "CCIC%d: dma done without sof, drop it\n", ccic_dev->index);
|
||||
tmp &= ~IRQ_DMA_EOF;
|
||||
} else if (!(pos->flags & AC_BUF_FLAG_DONE_TOUCH)) {
|
||||
pos->flags |= AC_BUF_FLAG_DONE_TOUCH;
|
||||
pos->vb2_v4l2_buf.sequence = ac_vnode->frame_id - 1;
|
||||
pos->vb2_v4l2_buf.vb2_buf.timestamp = ktime_get_ns();
|
||||
tmp &= ~IRQ_DMA_EOF;
|
||||
//dev_info(dev, "CCIC%d: dma done\n", ccic_dev->index);
|
||||
}
|
||||
}
|
||||
if (tmp & IRQ_DMA_SOF) {
|
||||
if (pos->flags & AC_BUF_FLAG_SOF_TOUCH) {
|
||||
if (!(pos->flags & (AC_BUF_FLAG_DONE_TOUCH | AC_BUF_FLAG_HW_ERR | AC_BUF_FLAG_SW_ERR))) {
|
||||
dev_warn(dev, "CCIC%d: next sof arrived without dma done or err\n", ccic_dev->index);
|
||||
pos->flags |= AC_BUF_FLAG_SW_ERR;
|
||||
}
|
||||
} else {
|
||||
pos->flags |= (AC_BUF_FLAG_SOF_TOUCH | AC_BUF_FLAG_TIMESTAMPED);
|
||||
tmp &= ~IRQ_DMA_SOF;
|
||||
}
|
||||
}
|
||||
}
|
||||
spin_unlock(&(ac_vnode->slock));
|
||||
ret = ccic_get_dma_work(dma_ctx, &ccic_dma_work);
|
||||
if (ret) {
|
||||
dev_warn(dev, "CCIC%d: dma work idle list was null\n", ccic_dev->index);
|
||||
} else {
|
||||
ccic_dma_work->irq_status = irqs;
|
||||
tasklet_schedule(&(ccic_dma_work->dma_tasklet));
|
||||
}
|
||||
}
|
||||
spin_lock(&ac_vnode->waitq_head.lock);
|
||||
ac_vnode->in_irq = 0;
|
||||
wake_up_locked(&ac_vnode->waitq_head);
|
||||
spin_unlock(&ac_vnode->waitq_head.lock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -710,10 +1128,8 @@ static int k1x_ccic_probe(struct platform_device *pdev)
|
||||
struct ccic_ctrl *ccic_ctrl;
|
||||
struct ccic_dma *ccic_dma;
|
||||
struct device *dev = &pdev->dev;
|
||||
char buf[32];
|
||||
int ret;
|
||||
int irq;
|
||||
|
||||
pr_debug("%s begin to probe\n", dev_name(&pdev->dev));
|
||||
|
||||
ret = of_property_read_u32(np, "cell-index", &pdev->id);
|
||||
if (ret < 0) {
|
||||
@@ -753,13 +1169,13 @@ static int k1x_ccic_probe(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
/* get irqs */
|
||||
irq = platform_get_irq_byname(pdev, "ipe-irq");
|
||||
if (irq < 0) {
|
||||
ccic_dev->irq = platform_get_irq_byname(pdev, "ipe-irq");
|
||||
if (ccic_dev->irq < 0) {
|
||||
dev_err(&pdev->dev, "no irq resource");
|
||||
return -ENODEV;
|
||||
}
|
||||
dev_dbg(&pdev->dev, "ipe irq: %d\n", irq);
|
||||
ret = devm_request_irq(&pdev->dev, irq, k1x_ccic_isr,
|
||||
|
||||
ret = devm_request_irq(&pdev->dev, ccic_dev->irq, k1x_ccic_isr,
|
||||
IRQF_SHARED, K1X_CCIC_DRV_NAME, ccic_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "fail to request irq\n");
|
||||
@@ -786,7 +1202,7 @@ static int k1x_ccic_probe(struct platform_device *pdev)
|
||||
ccic_dev->dev = &pdev->dev;
|
||||
ccic_dev->ctrl = ccic_ctrl;
|
||||
ccic_dev->dma = ccic_dma;
|
||||
ccic_dev->interrupt_mask_value = CSI2PHYERRS;
|
||||
ccic_dev->interrupt_mask_value = CSI2PHYERRS | FRAMEIRQS;
|
||||
dev_set_drvdata(dev, ccic_dev);
|
||||
|
||||
/* enable runtime pm */
|
||||
@@ -796,7 +1212,24 @@ static int k1x_ccic_probe(struct platform_device *pdev)
|
||||
|
||||
ccic_device_register(ccic_dev);
|
||||
|
||||
pr_debug("%s probed", dev_name(&pdev->dev));
|
||||
dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(33));
|
||||
ret = v4l2_device_register(&pdev->dev, &ccic_dev->v4l2_dev);
|
||||
if (ret) {
|
||||
dev_err(&pdev->dev, "failed to register v4l2 dev\n");
|
||||
return ret;
|
||||
}
|
||||
snprintf(buf, 32, "CCIC%d", ccic_ctrl->index);
|
||||
ccic_dev->vnode = spm_cvdev_create_vnode(buf, ccic_dev->index,
|
||||
&ccic_dev->v4l2_dev,
|
||||
&pdev->dev,
|
||||
ccic_dev,
|
||||
ccic_dma_tasklet_handler,
|
||||
0);
|
||||
if (NULL == ccic_dev->vnode) {
|
||||
dev_err(&pdev->dev, "failed to create ccic vnode\n");
|
||||
return -EPROBE_DEFER;
|
||||
}
|
||||
pr_info("%s probed in %s", dev_name(&pdev->dev), __func__);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -809,6 +1242,8 @@ static int k1x_ccic_remove(struct platform_device *pdev)
|
||||
ccic_dev = dev_get_drvdata(&pdev->dev);
|
||||
dma = ccic_dev->dma;
|
||||
|
||||
spm_cvdev_destroy_vnode((struct spm_ccic_vnode*)ccic_dev->vnode);
|
||||
v4l2_device_unregister(&ccic_dev->v4l2_dev);
|
||||
ccic_device_unregister(ccic_dev);
|
||||
|
||||
/* disable runtime pm */
|
||||
|
||||
@@ -48,8 +48,8 @@ struct mipi_csi2 {
|
||||
int dphy_type; /* 0: DPHY on chip, 1: DPTC off chip */
|
||||
u32 dphy[5]; /* DPHY: CSI2_DPHY1, CSI2_DPHY2, CSI2_DPHY3, CSI2_DPHY5, CSI2_DPHY6 */
|
||||
int calc_dphy;
|
||||
int enable_dpcm;
|
||||
struct csi_dphy_desc dphy_desc;
|
||||
int enable_dpcm;
|
||||
};
|
||||
|
||||
#define HS_SETTLE_POS_MAX (100)
|
||||
@@ -106,36 +106,27 @@ enum ccic_csi2vc_mode {
|
||||
CCIC_CSI2VC_NM = 0,
|
||||
CCIC_CSI2VC_VC,
|
||||
CCIC_CSI2VC_DT,
|
||||
CCIC_CSI2VC_VCDT,
|
||||
};
|
||||
|
||||
enum ccic_csi2vc_chnl {
|
||||
CCIC_CSI2VC_MAIN = 0,
|
||||
CCIC_CSI2VC_VCDT,
|
||||
CCIC_CSI2VC_SUB,
|
||||
};
|
||||
|
||||
struct ccic_ctrl_ops {
|
||||
void (*irq_mask)(struct ccic_ctrl *ctrl, int on);
|
||||
int (*clk_enable)(struct ccic_ctrl *ctrl, int en);
|
||||
int (*config_csi2_mbus)(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1,
|
||||
int lanes);
|
||||
int (*config_csi2_mbus)(struct ccic_ctrl *ctrl, int md, u8 vc0, u8 vc1, u8 dt0, u8 dt1, int lanes);
|
||||
int (*config_csi2idi_mux)(struct ccic_ctrl *ctrl, int chnl, int idi, int en);
|
||||
int (*reset_csi2idi)(struct ccic_ctrl *ctrl, int idi, int rst);
|
||||
};
|
||||
|
||||
struct ccic_dma {
|
||||
int index;
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct video_device vdev;
|
||||
struct ccic_dev *ccic_dev;
|
||||
struct v4l2_pix_format pix_format;
|
||||
struct mutex ops_mutex;
|
||||
spinlock_t dev_lock;
|
||||
struct list_head pending_bq;
|
||||
struct list_head active_bq;
|
||||
struct vb2_queue vb_queue;
|
||||
u32 csi_sof_cnt;
|
||||
u32 dma_sof_cnt;
|
||||
u32 dma_eof_cnt;
|
||||
|
||||
struct ccic_dma_ops *ops;
|
||||
};
|
||||
@@ -148,11 +139,16 @@ enum ccic_dma_sel {
|
||||
};
|
||||
|
||||
struct ccic_dma_ops {
|
||||
int (*setup_image)(struct ccic_dma *dma_dev);
|
||||
int (*shadow_ready)(struct ccic_dma *dma_dev, int enable);
|
||||
int (*set_addr)(struct ccic_dma *dma_dev, u8 chnl, u32 addr);
|
||||
int (*ccic_enable)(struct ccic_dma *dma_dev, int enable);
|
||||
int (*clk_enable)(struct ccic_dma *dma_dev, int enable);
|
||||
int (*set_fmt)(struct ccic_dma *dma_dev,
|
||||
unsigned int width,
|
||||
unsigned int height,
|
||||
unsigned int pix_fmt);
|
||||
int (*shadow_ready)(struct ccic_dma *dma_dev);
|
||||
int (*set_addr)(struct ccic_dma *dma_dev, unsigned long addr_y, unsigned long addr_u, unsigned long addr_v);
|
||||
int (*ccic_enable)(struct ccic_dma *dma_dev, int enable);
|
||||
int (*clk_enable)(struct ccic_dma *dma_dev, int enable);
|
||||
int (*src_sel)(struct ccic_dma *dma_dev, int src, unsigned int main_ccic_id);
|
||||
void (*dump_regs)(struct ccic_dma *dma_dev);
|
||||
};
|
||||
|
||||
struct ccic_dev {
|
||||
@@ -160,17 +156,19 @@ struct ccic_dev {
|
||||
struct device *dev;
|
||||
struct platform_device *pdev;
|
||||
struct list_head list;
|
||||
struct resource *irq;
|
||||
int irq;
|
||||
struct resource *mem;
|
||||
void __iomem *base;
|
||||
struct clk *csi_clk;
|
||||
struct clk *clk4x;
|
||||
// struct clk *ahb_clk;
|
||||
//struct clk *ahb_clk;
|
||||
struct clk *axi_clk;
|
||||
struct clk *dpu_clk;
|
||||
struct reset_control *ahb_reset;
|
||||
struct reset_control *csi_reset;
|
||||
struct reset_control *ccic_4x_reset;
|
||||
struct reset_control *isp_ci_reset;
|
||||
struct reset_control *mclk_reset;
|
||||
|
||||
int dma_burst;
|
||||
spinlock_t ccic_lock; /* protect the struct members and HW */
|
||||
@@ -182,6 +180,8 @@ struct ccic_dev {
|
||||
struct ccic_dma *dma;
|
||||
/* object for csiphy part */
|
||||
struct csiphy_device *csiphy;
|
||||
struct v4l2_device v4l2_dev;
|
||||
void *vnode;
|
||||
};
|
||||
|
||||
/*
|
||||
@@ -220,5 +220,6 @@ static inline void ccic_reg_clear_bit(struct ccic_dev *ccic_dev,
|
||||
|
||||
int ccic_ctrl_get(struct ccic_ctrl **ctrl_host, int id,
|
||||
irqreturn_t(*handler) (struct ccic_ctrl *, u32));
|
||||
int ccic_dma_get(struct ccic_dma **ccic_dma, int id);
|
||||
int ccic_dphy_hssettle_set(unsigned int ccic_id, unsigned int dphy_freg);
|
||||
#endif
|
||||
|
||||
@@ -64,7 +64,7 @@ int ccic_csi2_lanes_enable(struct ccic_dev *ccic_dev, int lanes)
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if 0
|
||||
int ccic_csi2_vc_ctrl(struct ccic_dev *ccic_dev, int md, u8 vc0, u8 vc1)
|
||||
{
|
||||
int ret = 0;
|
||||
@@ -94,27 +94,51 @@ int ccic_csi2_vc_ctrl(struct ccic_dev *ccic_dev, int md, u8 vc0, u8 vc1)
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ccic_dma_src_sel(struct ccic_dev *ccic_dev, int sel)
|
||||
#endif
|
||||
int ccic_dma_src_sel(struct ccic_dev *ccic_dev, int sel, unsigned int main_ccic_id)
|
||||
{
|
||||
switch (sel) {
|
||||
case CCIC_DMA_SEL_LOCAL_MAIN:
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDC_SEL);
|
||||
/* FIXME: no need */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
break;
|
||||
case CCIC_DMA_SEL_LOCAL_VCDT:
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDC_SEL);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0,
|
||||
CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
/* FIXME: no need */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
break;
|
||||
case CCIC_DMA_SEL_REMOTE_VCDT:
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDC_SEL);
|
||||
/* When EXT_TIM_ENA is enabled, this field must be enabled too. */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
if (ccic_dev->index == 0) {
|
||||
if (main_ccic_id == 2) {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
} else {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
}
|
||||
} else if (ccic_dev->index == 1) {
|
||||
if (main_ccic_id == 2) {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
} else {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
}
|
||||
} else {
|
||||
if (main_ccic_id == 0) {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_clear_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
} else {
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_EXT_TIM_ENA);
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_VCDT_SEL);
|
||||
/* When EXT_TIM_ENA is enabled, this field must be enabled too. */
|
||||
ccic_reg_set_bit(ccic_dev, REG_CSI2_CTRL0, CSI2_C0_ENABLE);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case CCIC_DMA_SEL_REMOTE_MAIN:
|
||||
default:
|
||||
|
||||
@@ -8,6 +8,9 @@
|
||||
#ifndef __CCIC_HWREG_H__
|
||||
#define __CCIC_HWREG_H__
|
||||
|
||||
#ifndef BIT
|
||||
#define BIT(nr) (1 << (nr))
|
||||
#endif
|
||||
#define REG_Y0BAR 0x00
|
||||
#define REG_U0BAR 0x0c
|
||||
#define REG_V0BAR 0x18
|
||||
@@ -51,7 +54,7 @@
|
||||
#define IRQ_CSI2PARSE_ERR (BIT(29))
|
||||
#define IRQ_CSI2GENSHORTPACKVALID (BIT(30))
|
||||
#define IRQ_CSI2GENSHORTPACK_ERR (BIT(31))
|
||||
// #define FRAMEIRQS (IRQ_CSI_SOF | IRQ_CSI_EOF | IRQ_DMA_SOF | IRQ_DMA_EOF)
|
||||
// #define FRAMEIRQS (IRQ_CSI_SOF | IRQ_CSI_EOF | IRQ_DMA_SOF | IRQ_DMA_EOF | IRQ_DMA_OVERFLOW | IRQ_DMA_NOT_DONE | IRQ_SHADOW_NOT_RDY)
|
||||
#define FRAMEIRQS (IRQ_DMA_SOF | IRQ_DMA_EOF | IRQ_DMA_OVERFLOW | IRQ_DMA_NOT_DONE | IRQ_SHADOW_NOT_RDY)
|
||||
#define CSI2PHYERRS (0xFF0B0000)
|
||||
#define ALLIRQS (FRAMEIRQS | CSI2PHYERRS | IRQ_CSI2IDI_HBLK2HSYNC)
|
||||
@@ -151,7 +154,7 @@
|
||||
#define CSI2_C0_EXT_TIM_ENA (0x1 << 3)
|
||||
#define CSI2_C0_VLEN (0x4 << 4)
|
||||
#define CSI2_C0_VLEN_MASK (0xf << 4)
|
||||
#define CSI2_C0_VCDC_SEL (0x1 << 13)
|
||||
#define CSI2_C0_VCDT_SEL (0x1 << 13)
|
||||
#define REG_CSI2_VCCTRL 0x114
|
||||
#define CSI2_VCCTRL_MD_MASK (0x3 << 0)
|
||||
#define CSI2_VCCTRL_MD_NORMAL (0x0 << 0)
|
||||
@@ -160,6 +163,17 @@
|
||||
#define CSI2_VCCTRL_VC0_MASK (0x3 << 14)
|
||||
#define CSI2_VCCTRL_DT1_MASK (0x3 << 16)
|
||||
#define CSI2_VCCTRL_VC1_MASK (0x3 << 22)
|
||||
#define CSI2_VCCTRL_DT_ENABLE (0x1 << 24)
|
||||
#define REG_CSI2_DT_FLT 0x11c
|
||||
#define CSI2_DT_FLT0_MASK (BIT(0)|BIT(1)|BIT(2)|BIT(3)|BIT(4)|BIT(5))
|
||||
#define CSI2_DT_FLT0_SHIFT (0)
|
||||
#define CSI2_DT_FLT0_EN (BIT(6))
|
||||
#define CSI2_DT_FLT1_MASK (BIT(8)|BIT(9)|BIT(10)|BIT(11)|BIT(12)|BIT(13))
|
||||
#define CSI2_DT_FLT1_SHIFT (8)
|
||||
#define CSI2_DT_FLT1_EN (BIT(14))
|
||||
#define CSI2_DT_FLT2_MASK (BIT(16)|BIT(17)|BIT(18)|BIT(19)|BIT(20)|BIT(21))
|
||||
#define CSI2_DT_FLT2_SHIFT (16)
|
||||
#define CSI2_DT_FLT2_EN (BIT(22))
|
||||
#define REG_CSI2_DPHY1 0x124
|
||||
#define CSI2_DHPY1_ANA_PU (0x1 << 0)
|
||||
#define CSI2_DHPY1_BIF_EN (0x1 << 1)
|
||||
@@ -225,12 +239,11 @@
|
||||
|
||||
int ccic_csi2_config_dphy(struct ccic_dev *ccic_dev, int lanes, int enable);
|
||||
int ccic_csi2_lanes_enable(struct ccic_dev *ccic_dev, int lanes);
|
||||
int ccic_csi2_vc_ctrl(struct ccic_dev *ccic_dev, int md, u8 vc0, u8 vc1);
|
||||
int ccic_dma_src_sel(struct ccic_dev *ccic_dev, int sel);
|
||||
int ccic_dma_set_out_format(struct ccic_dev *ccic_dev, u32 pixfmt, u32 width,
|
||||
u32 height);
|
||||
//int ccic_csi2_vc_ctrl(struct ccic_dev *ccic_dev, int md, u8 vc0, u8 vc1);
|
||||
int ccic_dma_src_sel(struct ccic_dev *ccic_dev, int sel, unsigned int main_ccic_id);
|
||||
int ccic_dma_set_out_format(struct ccic_dev *ccic_dev, u32 pixfmt, u32 width, u32 height);
|
||||
int ccic_dma_set_burst(struct ccic_dev *ccic_dev);
|
||||
void ccic_dma_enable(struct ccic_dev *ccic_dev, int en);
|
||||
//void ccic_dma_enable(struct ccic_dev *ccic_dev, int en);
|
||||
int ccic_csi2idi_src_sel(struct ccic_dev *ccic_dev, int sel);
|
||||
void ccic_csi2idi_reset(struct ccic_dev *ccic_dev, int reset);
|
||||
void ccic_hw_dump_regs(struct ccic_dev *ccic_dev);
|
||||
|
||||
1407
drivers/media/platform/spacemit/camera/cam_ccic/ccic_vdev.c
Normal file
1407
drivers/media/platform/spacemit/camera/cam_ccic/ccic_vdev.c
Normal file
File diff suppressed because it is too large
Load Diff
174
drivers/media/platform/spacemit/camera/cam_ccic/ccic_vdev.h
Normal file
174
drivers/media/platform/spacemit/camera/cam_ccic/ccic_vdev.h
Normal file
@@ -0,0 +1,174 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* vdev.h - video divece functions
|
||||
*
|
||||
* Copyright(C) 2019 SPM Micro Limited
|
||||
*/
|
||||
|
||||
#ifndef _SPM_VDEV_H_
|
||||
#define _SPM_VDEV_H_
|
||||
#include <media/v4l2-dev.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <linux/notifier.h>
|
||||
#include "ccic_drv.h"
|
||||
|
||||
#define CCIC_DMA_WORK_MAX_CNT (16)
|
||||
|
||||
struct spm_ccic_vbuffer;
|
||||
struct spm_ccic_vnode;
|
||||
|
||||
struct ccic_dma_context
|
||||
{
|
||||
struct list_head dma_work_idle_list;
|
||||
struct list_head dma_work_busy_list;
|
||||
spinlock_t slock;
|
||||
struct spm_ccic_vnode *ac_vnode;
|
||||
};
|
||||
|
||||
struct spm_ccic_vnode {
|
||||
struct video_device vnode;
|
||||
char name[32];
|
||||
struct vb2_queue buf_queue;
|
||||
struct list_head queued_list;
|
||||
struct list_head busy_list;
|
||||
struct ccic_dma_context dma_ctx;
|
||||
atomic_t queued_buf_cnt;
|
||||
atomic_t busy_buf_cnt;
|
||||
atomic_t ref_cnt;
|
||||
spinlock_t slock;
|
||||
struct mutex mlock;
|
||||
struct v4l2_format cur_fmt;
|
||||
struct wait_queue_head waitq_head;
|
||||
int in_streamoff;
|
||||
int in_tasklet;
|
||||
int in_irq;
|
||||
int is_streaming;
|
||||
unsigned int idx;
|
||||
unsigned int total_frm;
|
||||
unsigned int sw_err_frm;
|
||||
unsigned int hw_err_frm;
|
||||
unsigned int ok_frm;
|
||||
unsigned int planes_offset[VB2_MAX_FRAME][VB2_MAX_PLANES];
|
||||
unsigned int v4l2_buf_flags[VB2_MAX_FRAME];
|
||||
struct ccic_dev *ccic_dev;
|
||||
int csi2vc;
|
||||
int src_sel;
|
||||
int lane_num;
|
||||
int ccic_mode;
|
||||
int ch_mode;
|
||||
unsigned int main_ccic_id;
|
||||
unsigned int main_vc;
|
||||
unsigned int sub_vc;
|
||||
unsigned int main_dt;
|
||||
unsigned int sub_dt;
|
||||
uint64_t frame_id;
|
||||
void *usr_data;
|
||||
};
|
||||
|
||||
struct ccic_dma_work_struct {
|
||||
struct tasklet_struct dma_tasklet;
|
||||
struct list_head idle_list_entry;
|
||||
struct list_head busy_list_entry;
|
||||
unsigned int irq_status;
|
||||
struct spm_ccic_vnode *ac_vnode;
|
||||
};
|
||||
|
||||
#define AC_BUF_FLAG_SOF_TOUCH (1 << 0)
|
||||
#define AC_BUF_FLAG_DONE_TOUCH (1 << 1)
|
||||
#define AC_BUF_FLAG_HW_ERR (1 << 2)
|
||||
#define AC_BUF_FLAG_SW_ERR (1 << 3)
|
||||
#define AC_BUF_FLAG_TIMESTAMPED (1 << 4)
|
||||
#define AC_BUF_FLAG_CCIC_TOUCH (1 << 5)
|
||||
|
||||
#define AC_BUF_RESERVED_DATA_LEN (32)
|
||||
struct spm_ccic_vbuffer {
|
||||
struct vb2_v4l2_buffer vb2_v4l2_buf;
|
||||
struct list_head list_entry;
|
||||
unsigned int reset_flag;
|
||||
unsigned int flags;
|
||||
struct spm_ccic_vnode *ac_vnode;
|
||||
unsigned char reserved[AC_BUF_RESERVED_DATA_LEN];
|
||||
};
|
||||
|
||||
#define vb2_buffer_to_spm_ccic_vbuffer(vb) ((struct spm_ccic_vbuffer*)(vb))
|
||||
|
||||
#define CAM_ALIGN(a, b) ({ \
|
||||
unsigned int ___tmp1 = (a); \
|
||||
unsigned int ___tmp2 = (b); \
|
||||
unsigned int ___tmp3 = ___tmp1 % ___tmp2; \
|
||||
___tmp1 /= ___tmp2; \
|
||||
if (___tmp3) \
|
||||
___tmp1++; \
|
||||
___tmp1 *= ___tmp2; \
|
||||
___tmp1; \
|
||||
})
|
||||
|
||||
#define is_vnode_streaming(vnode) ((vnode)->buf_queue.streaming)
|
||||
|
||||
static inline dma_addr_t spm_vb2_buf_paddr(struct vb2_buffer *vb, unsigned int plane_no)
|
||||
{
|
||||
unsigned int offset = 0;
|
||||
dma_addr_t paddr = 0;
|
||||
struct spm_ccic_vbuffer *ac_vb = vb2_buffer_to_spm_ccic_vbuffer(vb);
|
||||
struct spm_ccic_vnode *ac_vnode = ac_vb->ac_vnode;
|
||||
dma_addr_t *dma_addr = (dma_addr_t*)vb2_plane_cookie(vb, plane_no);
|
||||
|
||||
BUG_ON(!ac_vnode);
|
||||
offset = ac_vnode->planes_offset[vb->index][plane_no];
|
||||
paddr = *dma_addr + offset;
|
||||
return paddr;
|
||||
}
|
||||
|
||||
static inline void ccic_update_dma_addr(struct spm_ccic_vnode *ac_vnode,
|
||||
struct spm_ccic_vbuffer *ac_vbuf, unsigned int offset)
|
||||
{
|
||||
dma_addr_t p0 = 0;
|
||||
struct ccic_dma *ccic_dma = ac_vnode->ccic_dev->dma;
|
||||
struct vb2_buffer *vb2_buf = &(ac_vbuf->vb2_v4l2_buf.vb2_buf);
|
||||
|
||||
p0 = spm_vb2_buf_paddr(vb2_buf, 0) + offset;
|
||||
ccic_dma->ops->set_addr(ccic_dma, p0, 0, 0);
|
||||
}
|
||||
|
||||
static inline void* ac_vnode_get_usrdata(struct spm_ccic_vnode *ac_vnode)
|
||||
{
|
||||
return ac_vnode->usr_data;
|
||||
}
|
||||
|
||||
static inline struct spm_ccic_vbuffer* to_ccic_vbuffer(struct vb2_buffer *vb2)
|
||||
{
|
||||
struct vb2_v4l2_buffer *vb2_v4l2_buf = to_vb2_v4l2_buffer(vb2);
|
||||
return container_of(vb2_v4l2_buf, struct spm_ccic_vbuffer, vb2_v4l2_buf);
|
||||
}
|
||||
|
||||
struct spm_ccic_vnode* spm_cvdev_create_vnode(const char *name,
|
||||
unsigned int idx,
|
||||
struct v4l2_device *v4l2_dev,
|
||||
struct device *alloc_dev,
|
||||
struct ccic_dev *ccic_dev,
|
||||
void (*dma_tasklet_handler)(unsigned long),
|
||||
unsigned int min_buffers_needed);
|
||||
void spm_cvdev_destroy_vnode(struct spm_ccic_vnode *ac_vnode);
|
||||
|
||||
|
||||
int spm_cvdev_busy_list_empty(struct spm_ccic_vnode *ac_vnode);
|
||||
int __spm_cvdev_busy_list_empty(struct spm_ccic_vnode *ac_vnode);
|
||||
int spm_cvdev_idle_list_empty(struct spm_ccic_vnode *ac_vnode);
|
||||
int __spm_cvdev_idle_list_empty(struct spm_ccic_vnode *ac_vnode);
|
||||
int spm_cvdev_dq_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int spm_cvdev_pick_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int __spm_cvdev_pick_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int spm_cvdev_q_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer *ac_vb);
|
||||
int __spm_cvdev_dq_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int __spm_cvdev_q_idle_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer *ac_vb);
|
||||
int spm_cvdev_dq_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int spm_cvdev_pick_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int __spm_cvdev_pick_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int spm_cvdev_q_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer *ac_vb);
|
||||
int __spm_cvdev_dq_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer **ac_vb);
|
||||
int __spm_cvdev_q_busy_vbuffer(struct spm_ccic_vnode *ac_vnode, struct spm_ccic_vbuffer *ac_vb);
|
||||
int spm_cvdev_export_ccic_vbuffer(struct spm_ccic_vbuffer *ac_vb, int with_error);
|
||||
void spm_cvdev_fill_v4l2_format(struct v4l2_format *f);
|
||||
#endif
|
||||
@@ -1185,7 +1185,7 @@ static int csi_subdev_video_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
cam_err("%s(%s) config mux(enable) failed ret=%d", __func__, sc_subdev->name, ret);
|
||||
return ret;
|
||||
}
|
||||
ret = csi_ctrl->ops->config_csi2_mbus(csi_ctrl, CCIC_CSI2VC_NM, 0, 0, mipi_lane_num);
|
||||
ret = csi_ctrl->ops->config_csi2_mbus(csi_ctrl, CCIC_CSI2VC_NM, 0, 0, 0, 0, mipi_lane_num);
|
||||
if (ret) {
|
||||
cam_err("%s(%s) config mbus(enable) lane=%d failed ret=%d", __func__, sc_subdev->name, 4, ret);
|
||||
return ret;
|
||||
@@ -1193,7 +1193,7 @@ static int csi_subdev_video_s_stream(struct v4l2_subdev *sd, int enable)
|
||||
csi_ctrl->ops->irq_mask(csi_ctrl, 1);
|
||||
} else {
|
||||
csi_ctrl->ops->irq_mask(csi_ctrl, 0);
|
||||
csi_ctrl->ops->config_csi2_mbus(csi_ctrl, CCIC_CSI2VC_NM, 0, 0, 0);
|
||||
csi_ctrl->ops->config_csi2_mbus(csi_ctrl, CCIC_CSI2VC_NM, 0, 0, 0, 0, 0);
|
||||
csi_ctrl->ops->config_csi2idi_mux(csi_ctrl, csi2vc, csi2idi, 0);
|
||||
csi_subdev_core_s_power(sd, 0);
|
||||
}
|
||||
|
||||
37
include/uapi/media/k1x/k1x_ccic_uapi.h
Normal file
37
include/uapi/media/k1x/k1x_ccic_uapi.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
|
||||
/*
|
||||
* mars11_ccic_uapi.h - Driver uapi for SPACEMIT K1X CCIC
|
||||
*
|
||||
* Copyright (C) 2024 SPACEMIT Micro Limited
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_LINUX_K1X_CCIC_H_
|
||||
#define _UAPI_LINUX_K1X_CCIC_H_
|
||||
//#include <linux/videodev2.h>
|
||||
|
||||
enum {
|
||||
CCIC_MODE_NM = 0,
|
||||
CCIC_MODE_VC,
|
||||
CCIC_MODE_VCDT,
|
||||
};
|
||||
|
||||
enum {
|
||||
CCIC_CH_MODE_MAIN = 0,
|
||||
CCIC_CH_MODE_SUB,
|
||||
};
|
||||
|
||||
struct v4l2_ccic_params {
|
||||
unsigned int lane_num;
|
||||
int ccic_mode;
|
||||
int ch_mode;
|
||||
unsigned int main_ccic_id;
|
||||
unsigned int main_vc;
|
||||
unsigned int sub_vc;
|
||||
unsigned int main_dt;
|
||||
unsigned int sub_dt;
|
||||
};
|
||||
|
||||
|
||||
#define BASE_VIDIOC_CCIC (BASE_VIDIOC_PRIVATE + 20)
|
||||
#define VIDIOC_CCIC_S_PARAMS _IOWR('V', BASE_VIDIOC_CCIC + 1, struct v4l2_ccic_params)
|
||||
#endif
|
||||
Reference in New Issue
Block a user