5732 lines
184 KiB
C

// SPDX-License-Identifier: GPL-2.0
/*
* drivers/video/rockchip/video/vehicle_cif.c
*
* mipi_dphy/csi_host/vicap driver for vehicle
*
* Copyright (C) 2022 Rockchip Electronics Co., Ltd.
* Authors:
* Jianwei Fan <jianwei.fan@rock-chips.com>
*
*/
#include <linux/init.h>
#include <linux/module.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/kernel.h>
#include <linux/time.h>
#include <linux/platform_device.h>
#include <linux/kthread.h>
#include <linux/interrupt.h>
#include <linux/fb.h>
#include <linux/clk.h>
#include <linux/clkdev.h>
#include <linux/of_gpio.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>
#include <linux/reset.h>
#include "vehicle-csi2-dphy-common.h"
#include "vehicle_cif.h"
#include "vehicle_flinger.h"
#include "vehicle_main.h"
#include <linux/regmap.h>
#include <linux/mfd/syscon.h>
#include <media/v4l2-mediabus.h>
#include <linux/delay.h>
#include <linux/pm_runtime.h>
#include <soc/rockchip/rockchip-system-status.h>
#include <linux/phy/phy.h>
#include <linux/uaccess.h>
#include <linux/bits.h>
#include "vehicle_samsung_dcphy_common.h"
#define CIF_DG VEHICLE_DG
#define CIF_ERR VEHICLE_DGERR
static struct vehicle_cif *g_cif;
#define write_reg(base, addr, val) \
writel(val, (addr) + (base))
#define read_reg(base, addr) \
readl((addr) + (base))
#define vehicle_write_csihost_reg(base, addr, val) write_reg(base, addr, val)
#define vehicle_read_csihost_reg(base, addr) read_reg(base, addr)
//define cif clk and rst
static const char * const rk3568_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
"iclk_cif_g",
};
static const char * const rk3568_cif_rsts[] = {
"rst_cif_a",
"rst_cif_h",
"rst_cif_d",
"rst_cif_p",
"rst_cif_i",
};
static const char * const rk3588_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
};
static const char * const rk3588_cif_rsts[] = {
"rst_cif_a",
"rst_cif_h",
"rst_cif_d",
};
static const char * const rk3562_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
"csirx0_data",
"csirx1_data",
"csirx2_data",
"csirx3_data",
};
static const char * const rk3562_cif_rsts[] = {
"rst_cif_a",
"rst_cif_h",
"rst_cif_d",
"rst_cif_i0",
"rst_cif_i1",
"rst_cif_i2",
"rst_cif_i3",
};
static const char * const rk3576_cif_clks[] = {
"aclk_cif",
"hclk_cif",
"dclk_cif",
"i0clk_cif",
"i1clk_cif",
"i2clk_cif",
"i3clk_cif",
"i4clk_cif",
};
static const char * const rk3576_cif_rsts[] = {
"rst_cif_a",
"rst_cif_h",
"rst_cif_d",
"rst_cif_iclk0",
"rst_cif_iclk1",
"rst_cif_iclk2",
"rst_cif_iclk3",
"rst_cif_iclk4",
};
//define dphy and csi clks/rst
static struct clk_bulk_data rk3568_csi2_dphy_hw_clks[] = {
{ .id = "pclk" },
};
static struct clk_bulk_data rk3568_csi2_clks[] = {
{ .id = "pclk_csi2host" },
};
static const char * const rk3568_csi2_rsts[] = {
"srst_csihost_p",
};
static struct clk_bulk_data rk3588_csi2_dphy_hw_clks[] = {
{ .id = "pclk" },
};
static const char * const rk3588_csi2_dphy_hw_rsts[] = {
"srst_csiphy",
"srst_p_csiphy",
};
static struct clk_bulk_data rk3588_csi2_clks[] = {
{ .id = "pclk_csi2host" },
};
static struct clk_bulk_data rk3588_csi2_dcphy_clks[] = {
{ .id = "pclk_csi2host" },
{ .id = "iclk_csi2host" },
};
static const char * const rk3588_csi2_rsts[] = {
"srst_csihost_p",
"srst_csihost_vicap",
};
static struct clk_bulk_data rk3562_csi2_dphy_hw_clks[] = {
{ .id = "pclk" },
};
static const char * const rk3562_csi2_dphy_hw_rsts[] = {
"srst_p_csiphy",
};
static struct clk_bulk_data rk3562_csi2_clks[] = {
{ .id = "pclk_csi2host" },
};
static const char * const rk3562_csi2_rsts[] = {
"srst_csihost_p",
};
static struct clk_bulk_data rk3576_csi2_dphy_hw_clks[] = {
{ .id = "pclk" },
};
static const char * const rk3576_csi2_dphy_hw_rsts[] = {
"srst_p_csiphy",
};
static struct clk_bulk_data rk3576_csi2_clks[] = {
{ .id = "pclk_csi2host" },
};
static struct clk_bulk_data rk3576_csi2_dcphy_clks[] = {
{ .id = "pclk_csi2host" },
{ .id = "iclk_csi2host" },
};
static const char * const rk3576_csi2_rsts[] = {
"srst_csihost_p",
};
//define cif regs
static const struct vehicle_cif_reg rk3568_cif_regs[] = {
[CIF_REG_DVP_CTRL] = CIF_REG_NAME(CIF_CTRL, "CIF_REG_DVP_CTRL"),
[CIF_REG_DVP_INTEN] = CIF_REG_NAME(CIF_INTEN, "CIF_REG_DVP_INTEN"),
[CIF_REG_DVP_INTSTAT] = CIF_REG_NAME(CIF_INTSTAT, "CIF_REG_DVP_INTSTAT"),
[CIF_REG_DVP_FOR] = CIF_REG_NAME(CIF_FOR, "CIF_REG_DVP_FOR"),
[CIF_REG_DVP_MULTI_ID] = CIF_REG_NAME(CIF_MULTI_ID, "CIF_REG_DVP_MULTI_ID"),
[CIF_REG_DVP_FRM0_ADDR_Y] = CIF_REG_NAME(CIF_FRM0_ADDR_Y, "CIF_REG_DVP_FRM0_ADDR_Y"),
[CIF_REG_DVP_FRM0_ADDR_UV] = CIF_REG_NAME(CIF_FRM0_ADDR_UV, "CIF_REG_DVP_FRM0_ADDR_UV"),
[CIF_REG_DVP_FRM1_ADDR_Y] = CIF_REG_NAME(CIF_FRM1_ADDR_Y, "CIF_REG_DVP_FRM1_ADDR_Y"),
[CIF_REG_DVP_FRM1_ADDR_UV] = CIF_REG_NAME(CIF_FRM1_ADDR_UV, "CIF_REG_DVP_FRM1_ADDR_UV"),
[CIF_REG_DVP_VIR_LINE_WIDTH] = CIF_REG_NAME(CIF_VIR_LINE_WIDTH,
"CIF_REG_DVP_VIR_LINE_WIDTH"),
[CIF_REG_DVP_SET_SIZE] = CIF_REG_NAME(CIF_SET_SIZE, "CIF_REG_DVP_SET_SIZE"),
[CIF_REG_DVP_LINE_INT_NUM] = CIF_REG_NAME(CIF_LINE_INT_NUM, "CIF_REG_DVP_LINE_INT_NUM"),
[CIF_REG_DVP_LINE_CNT] = CIF_REG_NAME(CIF_LINE_CNT, "CIF_REG_DVP_LINE_CNT"),
[CIF_REG_DVP_CROP] = CIF_REG_NAME(RV1126_CIF_CROP, "CIF_REG_DVP_CROP"),
[CIF_REG_DVP_FIFO_ENTRY] = CIF_REG_NAME(RK3568_CIF_FIFO_ENTRY, "CIF_REG_DVP_FIFO_ENTRY"),
[CIF_REG_DVP_FRAME_STATUS] = CIF_REG_NAME(RV1126_CIF_FRAME_STATUS,
"CIF_REG_DVP_FRAME_STATUS"),
[CIF_REG_DVP_CUR_DST] = CIF_REG_NAME(RV1126_CIF_CUR_DST, "CIF_REG_DVP_CUR_DST"),
[CIF_REG_DVP_LAST_LINE] = CIF_REG_NAME(RV1126_CIF_LAST_LINE, "CIF_REG_DVP_LAST_LINE"),
[CIF_REG_DVP_LAST_PIX] = CIF_REG_NAME(RV1126_CIF_LAST_PIX, "CIF_REG_DVP_LAST_PIX"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID1] = CIF_REG_NAME(CIF_FRM0_ADDR_Y_ID1,
"CIF_REG_DVP_FRM0_ADDR_Y_ID1"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID1] = CIF_REG_NAME(CIF_FRM0_ADDR_UV_ID1,
"CIF_REG_DVP_FRM0_ADDR_UV_ID1"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID1] = CIF_REG_NAME(CIF_FRM1_ADDR_Y_ID1,
"CIF_REG_DVP_FRM1_ADDR_Y_ID1"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID1] = CIF_REG_NAME(CIF_FRM1_ADDR_UV_ID1,
"CIF_REG_DVP_FRM1_ADDR_UV_ID1"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID2] = CIF_REG_NAME(CIF_FRM0_ADDR_Y_ID2,
"CIF_REG_DVP_FRM0_ADDR_Y_ID2"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID2] = CIF_REG_NAME(CIF_FRM0_ADDR_UV_ID2,
"CIF_REG_DVP_FRM0_ADDR_UV_ID2"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID2] = CIF_REG_NAME(CIF_FRM1_ADDR_Y_ID2,
"CIF_REG_DVP_FRM1_ADDR_Y_ID2"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID2] = CIF_REG_NAME(CIF_FRM1_ADDR_UV_ID2,
"CIF_REG_DVP_FRM1_ADDR_UV_ID2"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID3] = CIF_REG_NAME(CIF_FRM0_ADDR_Y_ID3,
"CIF_REG_DVP_FRM0_ADDR_Y_ID3"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID3] = CIF_REG_NAME(CIF_FRM0_ADDR_UV_ID3,
"CIF_REG_DVP_FRM0_ADDR_UV_ID3"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID3] = CIF_REG_NAME(CIF_FRM1_ADDR_Y_ID3,
"CIF_REG_DVP_FRM1_ADDR_Y_ID3"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID3] = CIF_REG_NAME(CIF_FRM1_ADDR_UV_ID3,
"CIF_REG_DVP_FRM1_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG_NAME(CIF_CSI_ID0_CTRL0,
"CIF_REG_MIPI_LVDS_ID0_CTRL0"),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG_NAME(CIF_CSI_ID0_CTRL1,
"CIF_REG_MIPI_LVDS_ID0_CTRL1"),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG_NAME(CIF_CSI_ID1_CTRL0,
"CIF_REG_MIPI_LVDS_ID1_CTRL0"),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG_NAME(CIF_CSI_ID1_CTRL1,
"CIF_REG_MIPI_LVDS_ID1_CTRL1"),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG_NAME(CIF_CSI_ID2_CTRL0,
"CIF_REG_MIPI_LVDS_ID2_CTRL0"),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG_NAME(CIF_CSI_ID2_CTRL1,
"CIF_REG_MIPI_LVDS_ID2_CTRL1"),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG_NAME(CIF_CSI_ID3_CTRL0,
"CIF_REG_MIPI_LVDS_ID3_CTRL0"),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG_NAME(CIF_CSI_ID3_CTRL1,
"CIF_REG_MIPI_LVDS_ID3_CTRL1"),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG_NAME(CIF_CSI_MIPI_LVDS_CTRL,
"CIF_REG_MIPI_LVDS_CTRL"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID1] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID1] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID1] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID2] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID2] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID2] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG_NAME(CIF_CSI_FRM0_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG_NAME(CIF_CSI_FRM1_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID3] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID3] = CIF_REG_NAME(CIF_CSI_FRM0_VLW_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID3] = CIF_REG_NAME(CIF_CSI_FRM1_VLW_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID3"),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG_NAME(CIF_CSI_INTEN, "CIF_REG_MIPI_LVDS_INTEN"),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG_NAME(CIF_CSI_INTSTAT, "CIF_REG_MIPI_LVDS_INTSTAT"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG_NAME(CIF_CSI_LINE_INT_NUM_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG_NAME(CIF_CSI_LINE_INT_NUM_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG_NAME(CIF_CSI_LINE_CNT_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG_NAME(CIF_CSI_LINE_CNT_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3"),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG_NAME(CIF_CSI_ID0_CROP_START,
"CIF_REG_MIPI_LVDS_ID0_CROP_START"),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG_NAME(CIF_CSI_ID1_CROP_START,
"CIF_REG_MIPI_LVDS_ID1_CROP_START"),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG_NAME(CIF_CSI_ID2_CROP_START,
"CIF_REG_MIPI_LVDS_ID2_CROP_START"),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG_NAME(CIF_CSI_ID3_CROP_START,
"CIF_REG_MIPI_LVDS_ID3_CROP_START"),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG_NAME(CIF_CSI_FRAME_NUM_VC0,
"CIF_REG_MIPI_FRAME_NUM_VC0"),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG_NAME(CIF_CSI_FRAME_NUM_VC1,
"CIF_REG_MIPI_FRAME_NUM_VC1"),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG_NAME(CIF_CSI_FRAME_NUM_VC2,
"CIF_REG_MIPI_FRAME_NUM_VC2"),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG_NAME(CIF_CSI_FRAME_NUM_VC3,
"CIF_REG_MIPI_FRAME_NUM_VC3"),
[CIF_REG_Y_STAT_CONTROL] = CIF_REG_NAME(CIF_Y_STAT_CONTROL,
"CIF_REG_Y_STAT_CONTROL"),
[CIF_REG_Y_STAT_VALUE] = CIF_REG_NAME(CIF_Y_STAT_VALUE, "CIF_REG_Y_STAT_VALUE"),
[CIF_REG_MMU_DTE_ADDR] = CIF_REG_NAME(CIF_MMU_DTE_ADDR, "CIF_REG_MMU_DTE_ADDR"),
[CIF_REG_MMU_STATUS] = CIF_REG_NAME(CIF_MMU_STATUS, "CIF_REG_MMU_STATUS"),
[CIF_REG_MMU_COMMAND] = CIF_REG_NAME(CIF_MMU_COMMAND, "CIF_REG_MMU_COMMAND"),
[CIF_REG_MMU_PAGE_FAULT_ADDR] = CIF_REG_NAME(CIF_MMU_PAGE_FAULT_ADDR,
"CIF_REG_MMU_PAGE_FAULT_ADDR"),
[CIF_REG_MMU_ZAP_ONE_LINE] = CIF_REG_NAME(CIF_MMU_ZAP_ONE_LINE, "CIF_REG_MMU_ZAP_ONE_LINE"),
[CIF_REG_MMU_INT_RAWSTAT] = CIF_REG_NAME(CIF_MMU_INT_RAWSTAT, "CIF_REG_MMU_INT_RAWSTAT"),
[CIF_REG_MMU_INT_CLEAR] = CIF_REG_NAME(CIF_MMU_INT_CLEAR, "CIF_REG_MMU_INT_CLEAR"),
[CIF_REG_MMU_INT_MASK] = CIF_REG_NAME(CIF_MMU_INT_MASK, "CIF_REG_MMU_INT_MASK"),
[CIF_REG_MMU_INT_STATUS] = CIF_REG_NAME(CIF_MMU_INT_STATUS, "CIF_REG_MMU_INT_STATUS"),
[CIF_REG_MMU_AUTO_GATING] = CIF_REG_NAME(CIF_MMU_AUTO_GATING, "CIF_REG_MMU_AUTO_GATING"),
[CIF_REG_GRF_CIFIO_CON] = CIF_REG_NAME(CIF_GRF_VI_CON0, "CIF_REG_GRF_CIFIO_CON"),
[CIF_REG_GRF_CIFIO_CON1] = CIF_REG_NAME(CIF_GRF_VI_CON1, "CIF_REG_GRF_CIFIO_CON1"),
};
static const struct vehicle_cif_reg rk3588_cif_regs[] = {
[CIF_REG_DVP_CTRL] = CIF_REG_NAME(DVP_CTRL, "CIF_REG_DVP_CTRL"),
[CIF_REG_DVP_INTEN] = CIF_REG_NAME(DVP_INTEN, "CIF_REG_DVP_INTEN"),
[CIF_REG_DVP_INTSTAT] = CIF_REG_NAME(DVP_INTSTAT, "CIF_REG_DVP_INTSTAT"),
[CIF_REG_DVP_FOR] = CIF_REG_NAME(DVP_FOR, "CIF_REG_DVP_FOR"),
[CIF_REG_DVP_MULTI_ID] = CIF_REG_NAME(DVP_MULTI_ID, "CIF_REG_DVP_MULTI_ID"),
[CIF_REG_DVP_SAV_EAV] = CIF_REG_NAME(DVP_SAV_EAV, "CIF_REG_DVP_SAV_EAV"),
[CIF_REG_DVP_FRM0_ADDR_Y] = CIF_REG_NAME(DVP_FRM0_ADDR_Y_ID0, "CIF_REG_DVP_FRM0_ADDR_Y"),
[CIF_REG_DVP_FRM0_ADDR_UV] = CIF_REG_NAME(DVP_FRM0_ADDR_UV_ID0, "CIF_REG_DVP_FRM0_ADDR_UV"),
[CIF_REG_DVP_FRM1_ADDR_Y] = CIF_REG_NAME(DVP_FRM1_ADDR_Y_ID0, "CIF_REG_DVP_FRM1_ADDR_Y"),
[CIF_REG_DVP_FRM1_ADDR_UV] = CIF_REG_NAME(DVP_FRM1_ADDR_UV_ID0, "CIF_REG_DVP_FRM1_ADDR_UV"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID1] = CIF_REG_NAME(DVP_FRM0_ADDR_Y_ID1,
"CIF_REG_DVP_FRM0_ADDR_Y_ID1"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID1] = CIF_REG_NAME(DVP_FRM0_ADDR_UV_ID1,
"CIF_REG_DVP_FRM0_ADDR_UV_ID1"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID1] = CIF_REG_NAME(DVP_FRM1_ADDR_Y_ID1,
"CIF_REG_DVP_FRM1_ADDR_Y_ID1"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID1] = CIF_REG_NAME(DVP_FRM1_ADDR_UV_ID1,
"CIF_REG_DVP_FRM1_ADDR_UV_ID1"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID2] = CIF_REG_NAME(DVP_FRM0_ADDR_Y_ID2,
"CIF_REG_DVP_FRM0_ADDR_Y_ID2"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID2] = CIF_REG_NAME(DVP_FRM0_ADDR_UV_ID2,
"CIF_REG_DVP_FRM0_ADDR_UV_ID2"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID2] = CIF_REG_NAME(DVP_FRM1_ADDR_Y_ID2,
"CIF_REG_DVP_FRM1_ADDR_Y_ID2"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID2] = CIF_REG_NAME(DVP_FRM1_ADDR_UV_ID2,
"CIF_REG_DVP_FRM1_ADDR_UV_ID2"),
[CIF_REG_DVP_FRM0_ADDR_Y_ID3] = CIF_REG_NAME(DVP_FRM0_ADDR_Y_ID3,
"CIF_REG_DVP_FRM0_ADDR_Y_ID3"),
[CIF_REG_DVP_FRM0_ADDR_UV_ID3] = CIF_REG_NAME(DVP_FRM0_ADDR_UV_ID3,
"CIF_REG_DVP_FRM0_ADDR_UV_ID3"),
[CIF_REG_DVP_FRM1_ADDR_Y_ID3] = CIF_REG_NAME(DVP_FRM1_ADDR_Y_ID3,
"CIF_REG_DVP_FRM1_ADDR_Y_ID3"),
[CIF_REG_DVP_FRM1_ADDR_UV_ID3] = CIF_REG_NAME(DVP_FRM1_ADDR_UV_ID3,
"CIF_REG_DVP_FRM1_ADDR_UV_ID3"),
[CIF_REG_DVP_VIR_LINE_WIDTH] = CIF_REG_NAME(DVP_VIR_LINE_WIDTH,
"CIF_REG_DVP_VIR_LINE_WIDTH"),
[CIF_REG_DVP_SET_SIZE] = CIF_REG_NAME(DVP_CROP_SIZE, "CIF_REG_DVP_SET_SIZE"),
[CIF_REG_DVP_CROP] = CIF_REG_NAME(DVP_CROP, "CIF_REG_DVP_CROP"),
[CIF_REG_DVP_LINE_INT_NUM] = CIF_REG_NAME(DVP_LINE_INT_NUM_01, "CIF_REG_DVP_LINE_INT_NUM"),
[CIF_REG_DVP_LINE_INT_NUM1] = CIF_REG_NAME(DVP_LINE_INT_NUM_23,
"CIF_REG_DVP_LINE_INT_NUM1"),
[CIF_REG_DVP_LINE_CNT] = CIF_REG_NAME(DVP_LINE_INT_NUM_01, "CIF_REG_DVP_LINE_CNT"),
[CIF_REG_DVP_LINE_CNT1] = CIF_REG_NAME(DVP_LINE_INT_NUM_23, "CIF_REG_DVP_LINE_CNT1"),
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL0,
"CIF_REG_MIPI_LVDS_ID0_CTRL0"),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL1,
"CIF_REG_MIPI_LVDS_ID0_CTRL1"),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL0,
"CIF_REG_MIPI_LVDS_ID1_CTRL0"),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL1,
"CIF_REG_MIPI_LVDS_ID1_CTRL1"),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL0,
"CIF_REG_MIPI_LVDS_ID2_CTRL0"),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL1,
"CIF_REG_MIPI_LVDS_ID2_CTRL1"),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL0,
"CIF_REG_MIPI_LVDS_ID3_CTRL0"),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL1,
"CIF_REG_MIPI_LVDS_ID3_CTRL1"),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG_NAME(CSI_MIPI0_CTRL, "CIF_REG_MIPI_LVDS_CTRL"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_VLW_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_VLW_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_VLW_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_VLW_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3"),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG_NAME(CSI_MIPI0_INTEN, "CIF_REG_MIPI_LVDS_INTEN"),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG_NAME(CSI_MIPI0_INTSTAT, "CIF_REG_MIPI_LVDS_INTSTAT"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3"),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID0_CROP_START,
"CIF_REG_MIPI_LVDS_ID0_CROP_START"),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID1_CROP_START,
"CIF_REG_MIPI_LVDS_ID1_CROP_START"),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID2_CROP_START,
"CIF_REG_MIPI_LVDS_ID2_CROP_START"),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID3_CROP_START,
"CIF_REG_MIPI_LVDS_ID3_CROP_START"),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC0,
"CIF_REG_MIPI_FRAME_NUM_VC0"),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC1,
"CIF_REG_MIPI_FRAME_NUM_VC1"),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC2,
"CIF_REG_MIPI_FRAME_NUM_VC2"),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC3,
"CIF_REG_MIPI_FRAME_NUM_VC3"),
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID0,
"CIF_REG_MIPI_EFFECT_CODE_ID0"),
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID1,
"CIF_REG_MIPI_EFFECT_CODE_ID1"),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID2,
"CIF_REG_MIPI_EFFECT_CODE_ID2"),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID3,
"CIF_REG_MIPI_EFFECT_CODE_ID3"),
[CIF_REG_MIPI_ON_PAD] = CIF_REG_NAME(CSI_MIPI0_ON_PAD, "CIF_REG_MIPI_ON_PAD"),
[CIF_REG_GLB_CTRL] = CIF_REG_NAME(GLB_CTRL, "CIF_REG_GLB_CTRL"),
[CIF_REG_GLB_INTEN] = CIF_REG_NAME(GLB_INTEN, "CIF_REG_GLB_INTEN"),
[CIF_REG_GLB_INTST] = CIF_REG_NAME(GLB_INTST, "CIF_REG_GLB_INTST"),
[CIF_REG_SCL_CH_CTRL] = CIF_REG_NAME(SCL_CH_CTRL, "CIF_REG_SCL_CH_CTRL"),
[CIF_REG_SCL_CTRL] = CIF_REG_NAME(SCL_CTRL, "CIF_REG_SCL_CTRL"),
[CIF_REG_SCL_FRM0_ADDR_CH0] = CIF_REG_NAME(SCL_FRM0_ADDR_CH0,
"CIF_REG_SCL_FRM0_ADDR_CH0"),
[CIF_REG_SCL_FRM1_ADDR_CH0] = CIF_REG_NAME(SCL_FRM1_ADDR_CH0,
"CIF_REG_SCL_FRM1_ADDR_CH0"),
[CIF_REG_SCL_VLW_CH0] = CIF_REG_NAME(SCL_VLW_CH0, "CIF_REG_SCL_VLW_CH0"),
[CIF_REG_SCL_FRM0_ADDR_CH1] = CIF_REG_NAME(SCL_FRM0_ADDR_CH1,
"CIF_REG_SCL_FRM0_ADDR_CH1"),
[CIF_REG_SCL_FRM1_ADDR_CH1] = CIF_REG_NAME(SCL_FRM1_ADDR_CH1,
"CIF_REG_SCL_FRM1_ADDR_CH1"),
[CIF_REG_SCL_VLW_CH1] = CIF_REG_NAME(SCL_VLW_CH1, "CIF_REG_SCL_VLW_CH1"),
[CIF_REG_SCL_FRM0_ADDR_CH2] = CIF_REG_NAME(SCL_FRM0_ADDR_CH2,
"CIF_REG_SCL_FRM0_ADDR_CH2"),
[CIF_REG_SCL_FRM1_ADDR_CH2] = CIF_REG_NAME(SCL_FRM1_ADDR_CH2,
"CIF_REG_SCL_FRM1_ADDR_CH2"),
[CIF_REG_SCL_VLW_CH2] = CIF_REG_NAME(SCL_VLW_CH2, "CIF_REG_SCL_VLW_CH2"),
[CIF_REG_SCL_FRM0_ADDR_CH3] = CIF_REG_NAME(SCL_FRM0_ADDR_CH3, "CIF_REG_SCL_FRM0_ADDR_CH3"),
[CIF_REG_SCL_FRM1_ADDR_CH3] = CIF_REG_NAME(SCL_FRM1_ADDR_CH3, "CIF_REG_SCL_FRM1_ADDR_CH3"),
[CIF_REG_SCL_VLW_CH3] = CIF_REG_NAME(SCL_VLW_CH3, "CIF_REG_SCL_VLW_CH3"),
[CIF_REG_SCL_BLC_CH0] = CIF_REG_NAME(SCL_BLC_CH0, "CIF_REG_SCL_BLC_CH0"),
[CIF_REG_SCL_BLC_CH1] = CIF_REG_NAME(SCL_BLC_CH1, "CIF_REG_SCL_BLC_CH1"),
[CIF_REG_SCL_BLC_CH2] = CIF_REG_NAME(SCL_BLC_CH2, "CIF_REG_SCL_BLC_CH2"),
[CIF_REG_SCL_BLC_CH3] = CIF_REG_NAME(SCL_BLC_CH3, "CIF_REG_SCL_BLC_CH3"),
[CIF_REG_TOISP0_CTRL] = CIF_REG_NAME(TOISP0_CH_CTRL, "CIF_REG_TOISP0_CTRL"),
[CIF_REG_TOISP0_SIZE] = CIF_REG_NAME(TOISP0_CROP_SIZE, "CIF_REG_TOISP0_SIZE"),
[CIF_REG_TOISP0_CROP] = CIF_REG_NAME(TOISP0_CROP, "CIF_REG_TOISP0_CROP"),
[CIF_REG_TOISP1_CTRL] = CIF_REG_NAME(TOISP1_CH_CTRL, "CIF_REG_TOISP1_CTRL"),
[CIF_REG_TOISP1_SIZE] = CIF_REG_NAME(TOISP1_CROP_SIZE, "CIF_REG_TOISP1_SIZE"),
[CIF_REG_TOISP1_CROP] = CIF_REG_NAME(TOISP1_CROP, "CIF_REG_TOISP1_CROP"),
[CIF_REG_GRF_CIFIO_CON] = CIF_REG_NAME(CIF_GRF_SOC_CON2, "CIF_REG_GRF_CIFIO_CON"),
};
static const struct vehicle_cif_reg rk3562_cif_regs[] = {
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL0,
"CIF_REG_MIPI_LVDS_ID0_CTRL0"),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL1,
"CIF_REG_MIPI_LVDS_ID0_CTRL1"),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL0,
"CIF_REG_MIPI_LVDS_ID1_CTRL0"),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL1,
"CIF_REG_MIPI_LVDS_ID1_CTRL1"),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL0,
"CIF_REG_MIPI_LVDS_ID2_CTRL0"),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL1,
"CIF_REG_MIPI_LVDS_ID2_CTRL1"),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL0,
"CIF_REG_MIPI_LVDS_ID3_CTRL0"),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL1,
"CIF_REG_MIPI_LVDS_ID3_CTRL1"),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG_NAME(CSI_MIPI0_CTRL, "CIF_REG_MIPI_LVDS_CTRL"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_VLW_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_VLW_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_VLW_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_VLW_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3"),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG_NAME(CSI_MIPI0_INTEN, "CIF_REG_MIPI_LVDS_INTEN"),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG_NAME(CSI_MIPI0_INTSTAT, "CIF_REG_MIPI_LVDS_INTSTAT"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID0_1,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID2_3,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3"),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID0_CROP_START,
"CIF_REG_MIPI_LVDS_ID0_CROP_START"),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID1_CROP_START,
"CIF_REG_MIPI_LVDS_ID1_CROP_START"),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID2_CROP_START,
"CIF_REG_MIPI_LVDS_ID2_CROP_START"),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID3_CROP_START,
"CIF_REG_MIPI_LVDS_ID3_CROP_START"),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC0,
"CIF_REG_MIPI_FRAME_NUM_VC0"),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC1,
"CIF_REG_MIPI_FRAME_NUM_VC1"),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC2,
"CIF_REG_MIPI_FRAME_NUM_VC2"),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC3,
"CIF_REG_MIPI_FRAME_NUM_VC3"),
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID0,
"CIF_REG_MIPI_EFFECT_CODE_ID0"),
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID1,
"CIF_REG_MIPI_EFFECT_CODE_ID1"),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID2,
"CIF_REG_MIPI_EFFECT_CODE_ID2"),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID3,
"CIF_REG_MIPI_EFFECT_CODE_ID3"),
[CIF_REG_MIPI_ON_PAD] = CIF_REG_NAME(CSI_MIPI0_ON_PAD, "CIF_REG_MIPI_ON_PAD"),
[CIF_REG_GLB_CTRL] = CIF_REG_NAME(GLB_CTRL, "CIF_REG_GLB_CTRL"),
[CIF_REG_GLB_INTEN] = CIF_REG_NAME(GLB_INTEN, "CIF_REG_GLB_INTEN"),
[CIF_REG_GLB_INTST] = CIF_REG_NAME(GLB_INTST, "CIF_REG_GLB_INTST"),
[CIF_REG_SCL_CH_CTRL] = CIF_REG_NAME(SCL_CH_CTRL, "CIF_REG_SCL_CH_CTRL"),
[CIF_REG_SCL_CTRL] = CIF_REG_NAME(SCL_CTRL, "CIF_REG_SCL_CTRL"),
[CIF_REG_SCL_FRM0_ADDR_CH0] = CIF_REG_NAME(SCL_FRM0_ADDR_CH0,
"CIF_REG_SCL_FRM0_ADDR_CH0"),
[CIF_REG_SCL_FRM1_ADDR_CH0] = CIF_REG_NAME(SCL_FRM1_ADDR_CH0,
"CIF_REG_SCL_FRM1_ADDR_CH0"),
[CIF_REG_SCL_VLW_CH0] = CIF_REG_NAME(SCL_VLW_CH0, "CIF_REG_SCL_VLW_CH0"),
[CIF_REG_SCL_BLC_CH0] = CIF_REG_NAME(SCL_BLC_CH0, "CIF_REG_SCL_BLC_CH0"),
[CIF_REG_TOISP0_CTRL] = CIF_REG_NAME(TOISP0_CH_CTRL, "CIF_REG_TOISP0_CTRL"),
[CIF_REG_TOISP0_SIZE] = CIF_REG_NAME(TOISP0_CROP_SIZE, "CIF_REG_TOISP0_SIZE"),
[CIF_REG_TOISP0_CROP] = CIF_REG_NAME(TOISP0_CROP, "CIF_REG_TOISP0_CROP"),
};
static const struct vehicle_cif_reg rk3576_cif_regs[] = {
[CIF_REG_DVP_CTRL] = CIF_REG_NAME(DVP_CTRL, "CIF_REG_DVP_CTRL"),
[CIF_REG_DVP_INTEN] = CIF_REG_NAME(DVP_INTEN, "CIF_REG_DVP_INTEN"),
[CIF_REG_DVP_INTSTAT] = CIF_REG_NAME(DVP_INTSTAT, "CIF_REG_DVP_INTSTAT"),
[CIF_REG_DVP_FOR] = CIF_REG_NAME(DVP_FOR, "CIF_REG_DVP_FOR"),
[CIF_REG_DVP_SAV_EAV] = CIF_REG_NAME(DVP_SAV_EAV, "CIF_REG_DVP_SAV_EAV"),
[CIF_REG_DVP_FRM0_ADDR_Y] = CIF_REG_NAME(DVP_FRM0_ADDR_Y_ID0, "CIF_REG_DVP_FRM0_ADDR_Y"),
[CIF_REG_DVP_FRM0_ADDR_UV] = CIF_REG_NAME(DVP_FRM0_ADDR_UV_ID0, "CIF_REG_DVP_FRM0_ADDR_UV"),
[CIF_REG_DVP_FRM1_ADDR_Y] = CIF_REG_NAME(DVP_FRM1_ADDR_Y_ID0, "CIF_REG_DVP_FRM1_ADDR_Y"),
[CIF_REG_DVP_FRM1_ADDR_UV] = CIF_REG_NAME(DVP_FRM1_ADDR_UV_ID0, "CIF_REG_DVP_FRM1_ADDR_UV"),
[CIF_REG_DVP_VIR_LINE_WIDTH] = CIF_REG_NAME(DVP_VIR_LINE_WIDTH,
"CIF_REG_DVP_VIR_LINE_WIDTH"),
[CIF_REG_DVP_SET_SIZE] = CIF_REG_NAME(DVP_CROP_SIZE, "CIF_REG_DVP_SET_SIZE"),
[CIF_REG_DVP_CROP] = CIF_REG_NAME(DVP_CROP, "CIF_REG_DVP_CROP"),
[CIF_REG_DVP_LINE_INT_NUM] = CIF_REG_NAME(DVP_LINE_INT_NUM_01, "CIF_REG_DVP_LINE_INT_NUM"),
[CIF_REG_DVP_LINE_CNT] = CIF_REG_NAME(DVP_LINE_CNT_01, "CIF_REG_DVP_LINE_CNT"),
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL0,
"CIF_REG_MIPI_LVDS_ID0_CTRL0"),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID0_CTRL1,
"CIF_REG_MIPI_LVDS_ID0_CTRL1"),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL0,
"CIF_REG_MIPI_LVDS_ID1_CTRL0"),
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID1_CTRL1,
"CIF_REG_MIPI_LVDS_ID1_CTRL1"),
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL0,
"CIF_REG_MIPI_LVDS_ID2_CTRL0"),
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID2_CTRL1,
"CIF_REG_MIPI_LVDS_ID2_CTRL1"),
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL0,
"CIF_REG_MIPI_LVDS_ID3_CTRL0"),
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG_NAME(CSI_MIPI0_ID3_CTRL1,
"CIF_REG_MIPI_LVDS_ID3_CTRL1"),
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG_NAME(CSI_MIPI0_CTRL, "CIF_REG_MIPI_LVDS_CTRL"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID0,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG_NAME(CSI_MIPI0_VLW_ID0,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID1,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG_NAME(CSI_MIPI0_VLW_ID1,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID2,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG_NAME(CSI_MIPI0_VLW_ID2,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_Y_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM0_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG_NAME(CSI_MIPI0_FRM1_ADDR_UV_ID3,
"CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3"),
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG_NAME(CSI_MIPI0_VLW_ID3,
"CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3"),
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG_NAME(CSI_MIPI0_INTEN, "CIF_REG_MIPI_LVDS_INTEN"),
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG_NAME(CSI_MIPI0_INTSTAT, "CIF_REG_MIPI_LVDS_INTSTAT"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID0_1_RK3576,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_INT_NUM_ID2_3_RK3576,
"CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID0_1_RK3576,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1"),
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG_NAME(CSI_MIPI0_LINE_CNT_ID2_3_RK3576,
"CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3"),
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID0_CROP_START_RK3576,
"CIF_REG_MIPI_LVDS_ID0_CROP_START"),
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID1_CROP_START_RK3576,
"CIF_REG_MIPI_LVDS_ID1_CROP_START"),
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID2_CROP_START_RK3576,
"CIF_REG_MIPI_LVDS_ID2_CROP_START"),
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG_NAME(CSI_MIPI0_ID3_CROP_START_RK3576,
"CIF_REG_MIPI_LVDS_ID3_CROP_START"),
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC0_RK3576,
"CIF_REG_MIPI_FRAME_NUM_VC0"),
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC1_RK3576,
"CIF_REG_MIPI_FRAME_NUM_VC1"),
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC2_RK3576,
"CIF_REG_MIPI_FRAME_NUM_VC2"),
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG_NAME(CSI_MIPI0_FRAME_NUM_VC3_RK3576,
"CIF_REG_MIPI_FRAME_NUM_VC3"),
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID0_RK3576,
"CIF_REG_MIPI_EFFECT_CODE_ID0"),
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID1_RK3576,
"CIF_REG_MIPI_EFFECT_CODE_ID1"),
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID2_RK3576,
"CIF_REG_MIPI_EFFECT_CODE_ID2"),
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG_NAME(CSI_MIPI0_EFFECT_CODE_ID3_RK3576,
"CIF_REG_MIPI_EFFECT_CODE_ID3"),
[CIF_REG_MIPI_ON_PAD] = CIF_REG_NAME(CSI_MIPI0_ON_PAD_RK3576, "CIF_REG_MIPI_ON_PAD"),
[CIF_REG_MIPI_SET_SIZE_ID0] = CIF_REG_NAME(CSI_MIPI0_SET_FRAME_SIZE_ID0_RK3576,
"CIF_REG_MIPI_SET_SIZE_ID0"),
[CIF_REG_MIPI_SET_SIZE_ID1] = CIF_REG_NAME(CSI_MIPI0_SET_FRAME_SIZE_ID1_RK3576,
"CIF_REG_MIPI_SET_SIZE_ID1"),
[CIF_REG_MIPI_SET_SIZE_ID2] = CIF_REG_NAME(CSI_MIPI0_SET_FRAME_SIZE_ID2_RK3576,
"CIF_REG_MIPI_SET_SIZE_ID2"),
[CIF_REG_MIPI_SET_SIZE_ID3] = CIF_REG_NAME(CSI_MIPI0_SET_FRAME_SIZE_ID3_RK3576,
"CIF_REG_MIPI_SET_SIZE_ID3"),
[CIF_REG_GLB_CTRL] = CIF_REG_NAME(GLB_CTRL, "CIF_REG_GLB_CTRL"),
[CIF_REG_GLB_INTEN] = CIF_REG_NAME(GLB_INTEN, "CIF_REG_GLB_INTEN"),
[CIF_REG_GLB_INTST] = CIF_REG_NAME(GLB_INTST, "CIF_REG_GLB_INTST"),
[CIF_REG_SCL_CH_CTRL] = CIF_REG_NAME(SCL_CH_CTRL, "CIF_REG_SCL_CH_CTRL"),
[CIF_REG_SCL_CTRL] = CIF_REG_NAME(SCL_CTRL, "CIF_REG_SCL_CTRL"),
[CIF_REG_SCL_FRM0_ADDR_CH0] = CIF_REG_NAME(SCL_FRM0_ADDR_CH0, "CIF_REG_SCL_FRM0_ADDR_CH0"),
[CIF_REG_SCL_FRM1_ADDR_CH0] = CIF_REG_NAME(SCL_FRM1_ADDR_CH0, "CIF_REG_SCL_FRM1_ADDR_CH0"),
[CIF_REG_SCL_VLW_CH0] = CIF_REG_NAME(SCL_VLW_CH0, "CIF_REG_SCL_VLW_CH0"),
[CIF_REG_SCL_BLC_CH0] = CIF_REG_NAME(SCL_BLC_CH0, "CIF_REG_SCL_BLC_CH0"),
[CIF_REG_TOISP0_CTRL] = CIF_REG_NAME(TOISP0_CH_CTRL, "CIF_REG_TOISP0_CTRL"),
[CIF_REG_TOISP0_SIZE] = CIF_REG_NAME(TOISP0_CROP_SIZE, "CIF_REG_TOISP0_SIZE"),
[CIF_REG_TOISP0_CROP] = CIF_REG_NAME(TOISP0_CROP, "CIF_REG_TOISP0_CROP"),
[CIF_REG_GRF_CIFIO_CON] = CIF_REG_NAME(CIF_GRF_IOC_MISC_CON1_RK3576,
"CIF_REG_GRF_CIFIO_CON"),
};
//define dphy and csi regs
static const struct grf_reg rk3568_grf_dphy_regs[] = {
[GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_VI_CON0, 4, 0),
[GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_VI_CON0, 4, 4),
[GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_VI_CON0, 1, 8),
[GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_VI_CON0, 1, 9),
[GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_VI_CON0, 1, 10),
[GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_VI_CON0, 1, 11),
[GRF_DPHY_ISP_CSI2PHY_SEL] = GRF_REG(GRF_VI_CON1, 1, 12),
[GRF_DPHY_CIF_CSI2PHY_SEL] = GRF_REG(GRF_VI_CON1, 1, 11),
[GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_VI_CON1, 1, 7),
};
static const struct csi2dphy_reg rk3568_csi2dphy_regs[] = {
[CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE),
[CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN),
[CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE),
[CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN),
[CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE),
[CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN),
[CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE),
[CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN),
[CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE),
[CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN),
[CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE),
[CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN),
[CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE),
[CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN),
};
static const struct grf_reg rk3588_grf_dphy_regs[] = {
[GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_DPHY_CON0, 4, 0),
[GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_DPHY_CON0, 4, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_DPHY_CON0, 2, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_DPHY_CON0, 2, 6),
[GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_DPHY_CON0, 1, 8),
[GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 9),
[GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_DPHY_CON0, 1, 10),
[GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 11),
[GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 6),
[GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON2, 1, 7),
[GRF_DPHY_CSIHOST2_SEL] = GRF_REG(GRF_SOC_CON2, 1, 8),
[GRF_DPHY_CSIHOST3_SEL] = GRF_REG(GRF_SOC_CON2, 1, 9),
[GRF_DPHY_CSIHOST4_SEL] = GRF_REG(GRF_SOC_CON2, 1, 10),
[GRF_DPHY_CSIHOST5_SEL] = GRF_REG(GRF_SOC_CON2, 1, 11),
};
static const struct csi2dphy_reg rk3588_csi2dphy_regs[] = {
[CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE),
[CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN),
[CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE),
[CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN),
[CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE),
[CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN),
[CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE),
[CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN),
[CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE),
[CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN),
[CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE),
[CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN),
[CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE),
[CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN),
[CSI2PHY_CLK1_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_LANE_EN),
};
static const struct grf_reg rk3588_grf_dcphy_regs[] = {
[GRF_CPHY_MODE] = GRF_REG(GRF_DCPHY_CON0, 9, 0),
};
static const struct csi2dphy_reg rk3588_csi2dcphy_regs[] = {
[CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_WR_THS_SETTLE),
[CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_THS_SETTLE),
[CSI2PHY_LANE0_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE0_WR_ERR_SOT_SYNC),
[CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_THS_SETTLE),
[CSI2PHY_LANE1_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE1_WR_ERR_SOT_SYNC),
[CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_THS_SETTLE),
[CSI2PHY_LANE2_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE2_WR_ERR_SOT_SYNC),
[CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_THS_SETTLE),
[CSI2PHY_LANE3_ERR_SOT_SYNC] = CSI2PHY_REG(CSI2_DCPHY_LANE3_WR_ERR_SOT_SYNC),
[CSI2PHY_CLK_LANE_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_CLK_LANE_ENABLE),
[CSI2PHY_DATA_LANE0_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE0_ENABLE),
[CSI2PHY_DATA_LANE1_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE1_ENABLE),
[CSI2PHY_DATA_LANE2_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE2_ENABLE),
[CSI2PHY_DATA_LANE3_ENABLE] = CSI2PHY_REG(CSI2_DCPHY_DATA_LANE3_ENABLE),
[CSI2PHY_S0C_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0C_GNR_CON1),
[CSI2PHY_S0C_ANA_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0C_ANA_CON1),
[CSI2PHY_S0C_ANA_CON2] = CSI2PHY_REG(CSI2_DCPHY_S0C_ANA_CON2),
[CSI2PHY_S0C_ANA_CON3] = CSI2PHY_REG(CSI2_DCPHY_S0C_ANA_CON3),
[CSI2PHY_COMBO_S0D0_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_GNR_CON1),
[CSI2PHY_COMBO_S0D0_ANA_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_ANA_CON1),
[CSI2PHY_COMBO_S0D0_ANA_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_ANA_CON2),
[CSI2PHY_COMBO_S0D0_ANA_CON3] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_ANA_CON3),
[CSI2PHY_COMBO_S0D0_ANA_CON6] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_ANA_CON6),
[CSI2PHY_COMBO_S0D0_ANA_CON7] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_ANA_CON7),
[CSI2PHY_COMBO_S0D0_DESKEW_CON0] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_DESKEW_CON0),
[CSI2PHY_COMBO_S0D0_DESKEW_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_DESKEW_CON2),
[CSI2PHY_COMBO_S0D0_DESKEW_CON4] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_DESKEW_CON4),
[CSI2PHY_COMBO_S0D0_CRC_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_CRC_CON1),
[CSI2PHY_COMBO_S0D0_CRC_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D0_CRC_CON2),
[CSI2PHY_COMBO_S0D1_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_GNR_CON1),
[CSI2PHY_COMBO_S0D1_ANA_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_ANA_CON1),
[CSI2PHY_COMBO_S0D1_ANA_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_ANA_CON2),
[CSI2PHY_COMBO_S0D1_ANA_CON3] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_ANA_CON3),
[CSI2PHY_COMBO_S0D1_ANA_CON6] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_ANA_CON6),
[CSI2PHY_COMBO_S0D1_ANA_CON7] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_ANA_CON7),
[CSI2PHY_COMBO_S0D1_DESKEW_CON0] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_DESKEW_CON0),
[CSI2PHY_COMBO_S0D1_DESKEW_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_DESKEW_CON2),
[CSI2PHY_COMBO_S0D1_DESKEW_CON4] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_DESKEW_CON4),
[CSI2PHY_COMBO_S0D1_CRC_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_CRC_CON1),
[CSI2PHY_COMBO_S0D1_CRC_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D1_CRC_CON2),
[CSI2PHY_COMBO_S0D2_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_GNR_CON1),
[CSI2PHY_COMBO_S0D2_ANA_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_ANA_CON1),
[CSI2PHY_COMBO_S0D2_ANA_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_ANA_CON2),
[CSI2PHY_COMBO_S0D2_ANA_CON3] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_ANA_CON3),
[CSI2PHY_COMBO_S0D2_ANA_CON6] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_ANA_CON6),
[CSI2PHY_COMBO_S0D2_ANA_CON7] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_ANA_CON7),
[CSI2PHY_COMBO_S0D2_DESKEW_CON0] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_DESKEW_CON0),
[CSI2PHY_COMBO_S0D2_DESKEW_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_DESKEW_CON2),
[CSI2PHY_COMBO_S0D2_DESKEW_CON4] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_DESKEW_CON4),
[CSI2PHY_COMBO_S0D2_CRC_CON1] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_CRC_CON1),
[CSI2PHY_COMBO_S0D2_CRC_CON2] = CSI2PHY_REG(CSI2_DCPHY_COMBO_S0D2_CRC_CON2),
[CSI2PHY_S0D3_GNR_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0D3_GNR_CON1),
[CSI2PHY_S0D3_ANA_CON1] = CSI2PHY_REG(CSI2_DCPHY_S0D3_ANA_CON1),
[CSI2PHY_S0D3_ANA_CON2] = CSI2PHY_REG(CSI2_DCPHY_S0D3_ANA_CON2),
[CSI2PHY_S0D3_ANA_CON3] = CSI2PHY_REG(CSI2_DCPHY_S0D3_ANA_CON3),
[CSI2PHY_S0D3_DESKEW_CON0] = CSI2PHY_REG(CSI2_DCPHY_S0D3_DESKEW_CON0),
[CSI2PHY_S0D3_DESKEW_CON2] = CSI2PHY_REG(CSI2_DCPHY_S0D3_DESKEW_CON2),
[CSI2PHY_S0D3_DESKEW_CON4] = CSI2PHY_REG(CSI2_DCPHY_S0D3_DESKEW_CON4),
};
static const struct grf_reg rk3562_grf_dphy_regs[] = {
[GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(RK3562_GRF_VI_CON0, 4, 0),
[GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(RK3562_GRF_VI_CON0, 4, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(RK3562_GRF_VI_CON0, 2, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(RK3562_GRF_VI_CON0, 2, 6),
[GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(RK3562_GRF_VI_CON0, 1, 8),
[GRF_DPHY_CLK_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 9),
[GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(RK3562_GRF_VI_CON0, 1, 10),
[GRF_DPHY_CLK1_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 11),
[GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 12),
[GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(RK3562_GRF_VI_CON0, 1, 13),
[GRF_DPHY1_CSI2PHY_FORCERXMODE] = GRF_REG(RK3562_GRF_VI_CON1, 4, 0),
[GRF_DPHY1_CSI2PHY_DATALANE_EN] = GRF_REG(RK3562_GRF_VI_CON1, 4, 4),
[GRF_DPHY1_CSI2PHY_DATALANE_EN0] = GRF_REG(RK3562_GRF_VI_CON1, 2, 4),
[GRF_DPHY1_CSI2PHY_DATALANE_EN1] = GRF_REG(RK3562_GRF_VI_CON1, 2, 6),
[GRF_DPHY1_CSI2PHY_CLKLANE_EN] = GRF_REG(RK3562_GRF_VI_CON1, 1, 8),
[GRF_DPHY1_CLK_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON1, 1, 9),
[GRF_DPHY1_CSI2PHY_CLKLANE1_EN] = GRF_REG(RK3562_GRF_VI_CON1, 1, 10),
[GRF_DPHY1_CLK1_INV_SEL] = GRF_REG(RK3562_GRF_VI_CON1, 1, 11),
};
static const struct csi2dphy_reg rk3562_csi2dphy_regs[] = {
[CSI2PHY_REG_CTRL_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CTRL_LANE_ENABLE),
[CSI2PHY_DUAL_CLK_EN] = CSI2PHY_REG(CSI2_DPHY_DUAL_CAL_EN),
[CSI2PHY_CLK_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK_WR_THS_SETTLE),
[CSI2PHY_CLK_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK_CALIB_EN),
[CSI2PHY_LANE0_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_WR_THS_SETTLE),
[CSI2PHY_LANE0_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE0_CALIB_EN),
[CSI2PHY_LANE1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_WR_THS_SETTLE),
[CSI2PHY_LANE1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE1_CALIB_EN),
[CSI2PHY_LANE2_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_WR_THS_SETTLE),
[CSI2PHY_LANE2_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE2_CALIB_EN),
[CSI2PHY_LANE3_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_WR_THS_SETTLE),
[CSI2PHY_LANE3_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_LANE3_CALIB_EN),
[CSI2PHY_CLK1_THS_SETTLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_WR_THS_SETTLE),
[CSI2PHY_CLK1_CALIB_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_CALIB_EN),
[CSI2PHY_CLK1_LANE_ENABLE] = CSI2PHY_REG(CSI2_DPHY_CLK1_LANE_EN),
};
static const struct grf_reg rk3576_grf_dphy_regs[] = {
[GRF_DPHY_CSI2PHY_FORCERXMODE] = GRF_REG(GRF_DPHY_CON0, 4, 0),
[GRF_DPHY_CSI2PHY_DATALANE_EN] = GRF_REG(GRF_DPHY_CON0, 4, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN0] = GRF_REG(GRF_DPHY_CON0, 2, 4),
[GRF_DPHY_CSI2PHY_DATALANE_EN1] = GRF_REG(GRF_DPHY_CON0, 2, 6),
[GRF_DPHY_CSI2PHY_CLKLANE_EN] = GRF_REG(GRF_DPHY_CON0, 1, 8),
[GRF_DPHY_CLK_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 9),
[GRF_DPHY_CSI2PHY_CLKLANE1_EN] = GRF_REG(GRF_DPHY_CON0, 1, 10),
[GRF_DPHY_CLK1_INV_SEL] = GRF_REG(GRF_DPHY_CON0, 1, 11),
[GRF_DPHY_CSI2PHY_LANE_SEL] = GRF_REG(GRF_SOC_CON5_RK3576, 1, 1),
[GRF_DPHY_CSI2PHY1_LANE_SEL] = GRF_REG(GRF_SOC_CON5_RK3576, 1, 2),
};
//define dcphy params
static struct rkmodule_csi_dphy_param rk3588_dcphy_param = {
.vendor = PHY_VENDOR_SAMSUNG,
.lp_vol_ref = 3,
.lp_hys_sw = {3, 0, 0, 0},
.lp_escclk_pol_sel = {1, 0, 0, 0},
.skew_data_cal_clk = {0, 3, 3, 3},
.clk_hs_term_sel = 2,
.data_hs_term_sel = {2, 2, 2, 2},
.reserved = {0},
};
/* These tables must be sorted by .range_h ascending. */
static const struct hsfreq_range rk3568_csi2_dphy_hw_hsfreq_ranges[] = {
{ 109, 0x02}, { 149, 0x03}, { 199, 0x06}, { 249, 0x06},
{ 299, 0x06}, { 399, 0x08}, { 499, 0x0b}, { 599, 0x0e},
{ 699, 0x10}, { 799, 0x12}, { 999, 0x16}, {1199, 0x1e},
{1399, 0x23}, {1599, 0x2d}, {1799, 0x32}, {1999, 0x37},
{2199, 0x3c}, {2399, 0x41}, {2499, 0x46}
};
/* These tables must be sorted by .range_h ascending. */
static const struct hsfreq_range rk3588_csi2_dcphy_d_hw_hsfreq_ranges[] = {
{ 80, 0x105}, { 100, 0x106}, { 120, 0x107}, { 140, 0x108},
{ 160, 0x109}, { 180, 0x10a}, { 200, 0x10b}, { 220, 0x10c},
{ 240, 0x10d}, { 270, 0x10e}, { 290, 0x10f}, { 310, 0x110},
{ 330, 0x111}, { 350, 0x112}, { 370, 0x113}, { 390, 0x114},
{ 410, 0x115}, { 430, 0x116}, { 450, 0x117}, { 470, 0x118},
{ 490, 0x119}, { 510, 0x11a}, { 540, 0x11b}, { 560, 0x11c},
{ 580, 0x11d}, { 600, 0x11e}, { 620, 0x11f}, { 640, 0x120},
{ 660, 0x121}, { 680, 0x122}, { 700, 0x123}, { 720, 0x124},
{ 740, 0x125}, { 760, 0x126}, { 790, 0x127}, { 810, 0x128},
{ 830, 0x129}, { 850, 0x12a}, { 870, 0x12b}, { 890, 0x12c},
{ 910, 0x12d}, { 930, 0x12e}, { 950, 0x12f}, { 970, 0x130},
{ 990, 0x131}, {1010, 0x132}, {1030, 0x133}, {1060, 0x134},
{1080, 0x135}, {1100, 0x136}, {1120, 0x137}, {1140, 0x138},
{1160, 0x139}, {1180, 0x13a}, {1200, 0x13b}, {1220, 0x13c},
{1240, 0x13d}, {1260, 0x13e}, {1280, 0x13f}, {1310, 0x140},
{1330, 0x141}, {1350, 0x142}, {1370, 0x143}, {1390, 0x144},
{1410, 0x145}, {1430, 0x146}, {1450, 0x147}, {1470, 0x148},
{1490, 0x149}, {1580, 0x007}, {1740, 0x008}, {1910, 0x009},
{2070, 0x00a}, {2240, 0x00b}, {2410, 0x00c}, {2570, 0x00d},
{2740, 0x00e}, {2910, 0x00f}, {3070, 0x010}, {3240, 0x011},
{3410, 0x012}, {3570, 0x013}, {3740, 0x014}, {3890, 0x015},
{4070, 0x016}, {4240, 0x017}, {4400, 0x018}, {4500, 0x019},
};
static struct csi2_dphy_hw rk3568_csi2_dphy_hw = {
.dphy_clks = rk3568_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3568_csi2_dphy_hw_clks),
.csi2_clks = rk3568_csi2_clks,
.num_csi2_clks = ARRAY_SIZE(rk3568_csi2_clks),
.csi2_rsts = rk3568_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3568_csi2_rsts),
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
.csi2dphy_regs = rk3568_csi2dphy_regs,
.grf_regs = rk3568_grf_dphy_regs,
.chip_id = CHIP_ID_RK3568,
};
static struct csi2_dphy_hw rk3588_csi2_dphy_hw = {
.dphy_clks = rk3588_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3588_csi2_dphy_hw_clks),
.dphy_rsts = rk3588_csi2_dphy_hw_rsts,
.num_dphy_rsts = ARRAY_SIZE(rk3588_csi2_dphy_hw_rsts),
.csi2_clks = rk3588_csi2_clks,
.num_csi2_clks = ARRAY_SIZE(rk3588_csi2_clks),
.csi2_rsts = rk3588_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3588_csi2_rsts),
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
.csi2dphy_regs = rk3588_csi2dphy_regs,
.grf_regs = rk3588_grf_dphy_regs,
.chip_id = CHIP_ID_RK3588,
};
static struct csi2_dphy_hw rk3588_csi2_dcphy_hw = {
.dphy_clks = rk3588_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3588_csi2_dphy_hw_clks),
.csi2_clks = rk3588_csi2_dcphy_clks,
.num_csi2_clks = ARRAY_SIZE(rk3588_csi2_dcphy_clks),
.csi2_rsts = rk3588_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3588_csi2_rsts),
.hsfreq_ranges = rk3588_csi2_dcphy_d_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3588_csi2_dcphy_d_hw_hsfreq_ranges),
.csi2dphy_regs = rk3588_csi2dcphy_regs,
.grf_regs = rk3588_grf_dcphy_regs,
.chip_id = CHIP_ID_RK3588_DCPHY,
};
static struct csi2_dphy_hw rk3562_csi2_dphy_hw = {
.dphy_clks = rk3562_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3562_csi2_dphy_hw_clks),
.dphy_rsts = rk3562_csi2_dphy_hw_rsts,
.num_dphy_rsts = ARRAY_SIZE(rk3562_csi2_dphy_hw_rsts),
.csi2_clks = rk3562_csi2_clks,
.num_csi2_clks = ARRAY_SIZE(rk3562_csi2_clks),
.csi2_rsts = rk3562_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3562_csi2_rsts),
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
.csi2dphy_regs = rk3562_csi2dphy_regs,
.grf_regs = rk3562_grf_dphy_regs,
.chip_id = CHIP_ID_RK3562,
};
static struct csi2_dphy_hw rk3576_csi2_dphy_hw = {
.dphy_clks = rk3576_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3576_csi2_dphy_hw_clks),
.dphy_rsts = rk3576_csi2_dphy_hw_rsts,
.num_dphy_rsts = ARRAY_SIZE(rk3576_csi2_dphy_hw_rsts),
.csi2_clks = rk3576_csi2_clks,
.num_csi2_clks = ARRAY_SIZE(rk3576_csi2_clks),
.csi2_rsts = rk3576_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3576_csi2_rsts),
.hsfreq_ranges = rk3568_csi2_dphy_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3568_csi2_dphy_hw_hsfreq_ranges),
.csi2dphy_regs = rk3588_csi2dphy_regs,
.grf_regs = rk3576_grf_dphy_regs,
.chip_id = CHIP_ID_RK3576,
};
static struct csi2_dphy_hw rk3576_csi2_dcphy_hw = {
.dphy_clks = rk3576_csi2_dphy_hw_clks,
.num_dphy_clks = ARRAY_SIZE(rk3576_csi2_dphy_hw_clks),
.csi2_clks = rk3576_csi2_dcphy_clks,
.num_csi2_clks = ARRAY_SIZE(rk3576_csi2_dcphy_clks),
.csi2_rsts = rk3576_csi2_rsts,
.num_csi2_rsts = ARRAY_SIZE(rk3576_csi2_rsts),
.hsfreq_ranges = rk3588_csi2_dcphy_d_hw_hsfreq_ranges,
.num_hsfreq_ranges = ARRAY_SIZE(rk3588_csi2_dcphy_d_hw_hsfreq_ranges),
.csi2dphy_regs = rk3588_csi2dcphy_regs,
.grf_regs = rk3588_grf_dcphy_regs,
.chip_id = CHIP_ID_RK3588_DCPHY,
};
static const struct cif_input_fmt in_fmts[] = {
{
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_YUYV,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_YUYV,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_YUYV,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_YUYV,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_INTERLACED,
}, {
.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_YVYU,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_YVYU,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_YVYU8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_YVYU,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_YVYU,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_INTERLACED,
}, {
.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_UYVY,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_UYVY,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_UYVY8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_UYVY,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_UYVY,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_INTERLACED,
}, {
.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_VYUY,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_VYUY,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_VYUY8_2X8,
.dvp_fmt_val = YUV_INPUT_422 | YUV_INPUT_ORDER_VYUY,
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.csi_yuv_order = CSI_YUV_INPUT_ORDER_VYUY,
.fmt_type = CIF_FMT_TYPE_YUV,
.field = V4L2_FIELD_INTERLACED,
}, {
.mbus_code = MEDIA_BUS_FMT_SBGGR8_1X8,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGBRG8_1X8,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGRBG8_1X8,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SRGGB8_1X8,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SBGGR10_1X10,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGBRG10_1X10,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGRBG10_1X10,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SRGGB10_1X10,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SBGGR12_1X12,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGBRG12_1X12,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SGRBG12_1X12,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_SRGGB12_1X12,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_RGB888_1X24,
.csi_fmt_val = CSI_WRDDR_TYPE_RGB888,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_Y8_1X8,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_Y10_1X10,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}, {
.mbus_code = MEDIA_BUS_FMT_Y12_1X12,
.dvp_fmt_val = INPUT_MODE_RAW | RAW_DATA_WIDTH_12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
.field = V4L2_FIELD_NONE,
}
};
static const struct cif_output_fmt out_fmts[] = {
{
.fourcc = V4L2_PIX_FMT_NV16,
.cplanes = 2,
.mplanes = 1,
.fmt_val = YUV_OUTPUT_422 | UV_STORAGE_ORDER_UVUV,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV61,
.fmt_val = YUV_OUTPUT_422 | UV_STORAGE_ORDER_VUVU,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV422,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV12,
.fmt_val = YUV_OUTPUT_420 | UV_STORAGE_ORDER_UVUV,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420SP,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_NV21,
.fmt_val = YUV_OUTPUT_420 | UV_STORAGE_ORDER_VUVU,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_YUV420SP,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_YUYV,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_YVYU,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_UYVY,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_VYUY,
.cplanes = 2,
.mplanes = 1,
.bpp = { 8, 16 },
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_YUV,
}, {
.fourcc = V4L2_PIX_FMT_RGB24,
.cplanes = 1,
.mplanes = 1,
.bpp = { 24 },
.csi_fmt_val = CSI_WRDDR_TYPE_RGB888,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_RGB565,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_BGR666,
.cplanes = 1,
.mplanes = 1,
.bpp = { 18 },
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR8,
.cplanes = 1,
.mplanes = 1,
.bpp = { 8 },
.raw_bpp = 8,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR10,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 10,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SRGGB12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGRBG12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SGBRG12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR12,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 12,
.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_SBGGR16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.raw_bpp = 16,
.fmt_type = CIF_FMT_TYPE_RAW,
}, {
.fourcc = V4L2_PIX_FMT_Y16,
.cplanes = 1,
.mplanes = 1,
.bpp = { 16 },
.fmt_type = CIF_FMT_TYPE_RAW,
}
/* TODO: We can support NV12M/NV21M/NV16M/NV61M too */
};
static void rkcif_write_reg(struct vehicle_cif *cif,
enum cif_reg_index index, u32 val)
{
void __iomem *base = cif->base;
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
int csi_offset = 0;
if (cif->inf_id == RKCIF_MIPI_LVDS &&
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
index <= CIF_REG_MIPI_ON_PAD) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
csi_offset = cif->csi_host_idx * 0x100;
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
if (cif->csi_host_idx < 3)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->csi_host_idx < 2)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x100 + cif->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
write_reg(base, reg->offset + csi_offset, val);
} else {
VEHICLE_INFO("write index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
}
VEHICLE_DG("@%s register[%s] offset(0x%x) csi_offset(0x%x) value:0x%x !\n",
__func__, reg->name, reg->offset, csi_offset, val);
}
static void rkcif_write_reg_or(struct vehicle_cif *cif,
enum cif_reg_index index, u32 val)
{
void __iomem *base = cif->base;
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
unsigned int reg_val = 0x0;
int csi_offset = 0;
if (cif->inf_id == RKCIF_MIPI_LVDS &&
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
index <= CIF_REG_MIPI_ON_PAD) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
csi_offset = cif->csi_host_idx * 0x100;
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
if (cif->csi_host_idx < 3)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->csi_host_idx < 2)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x100 + cif->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
reg_val = read_reg(base, reg->offset + csi_offset);
reg_val |= val;
write_reg(base, reg->offset + csi_offset, reg_val);
} else {
VEHICLE_INFO("write index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
}
VEHICLE_DG("@%s register[%s] offset(0x%x) csi_offset(0x%x) value:0x%x !\n",
__func__, reg->name, reg->offset, csi_offset, reg_val);
}
static void rkcif_write_reg_and(struct vehicle_cif *cif,
enum cif_reg_index index, u32 val)
{
void __iomem *base = cif->base;
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
unsigned int reg_val = 0x0;
int csi_offset = 0;
if (cif->inf_id == RKCIF_MIPI_LVDS &&
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
index <= CIF_REG_MIPI_ON_PAD) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
csi_offset = cif->csi_host_idx * 0x100;
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
if (cif->csi_host_idx < 3)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->csi_host_idx < 2)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x100 + cif->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0) {
reg_val = read_reg(base, reg->offset + csi_offset);
reg_val &= val;
write_reg(base, reg->offset + csi_offset, reg_val);
} else {
VEHICLE_INFO("write index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
}
VEHICLE_DG("@%s register[%s] offset(0x%x) csi_offset(0x%x) value:0x%x !\n",
__func__, reg->name, reg->offset, csi_offset, reg_val);
}
static unsigned int rkcif_read_reg(struct vehicle_cif *cif,
enum cif_reg_index index)
{
unsigned int val = 0x0;
void __iomem *base = cif->base;
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
int csi_offset = 0;
if (cif->inf_id == RKCIF_MIPI_LVDS &&
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
index <= CIF_REG_MIPI_ON_PAD) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
csi_offset = cif->csi_host_idx * 0x100;
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
if (cif->csi_host_idx < 3)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x500;
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->csi_host_idx < 2)
csi_offset = cif->csi_host_idx * 0x200;
else
csi_offset = 0x100 + cif->csi_host_idx * 0x100;
}
}
if (index < CIF_REG_INDEX_MAX) {
if (index == CIF_REG_GLB_CTRL || index == CIF_REG_DVP_CTRL || reg->offset != 0x0)
val = read_reg(base, reg->offset + csi_offset);
else
VEHICLE_INFO("read index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
VEHICLE_DG("@%s register[%s] offset(0x%x) csi_offset(0x%x) value:0x%x !\n",
__func__, reg->name, reg->offset, csi_offset, val);
return val;
}
static void rkvehicle_cif_write_grf_reg(struct vehicle_cif *cif,
enum cif_reg_index index, u32 val)
{
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
if (index < CIF_REG_INDEX_MAX) {
if (index > CIF_REG_DVP_CTRL) {
if (!IS_ERR(cif->regmap_grf))
regmap_write(cif->regmap_grf, reg->offset, val);
} else {
VEHICLE_INFO("write index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
VEHICLE_DG("@%s reg[%s] offset(0x%x): 0x%x !\n",
__func__, reg->name, reg->offset, val);
}
}
static u32 rkvehicle_cif_read_grf_reg(struct vehicle_cif *cif,
enum cif_reg_index index)
{
const struct vehicle_cif_reg *reg = &cif->cif_regs[index];
u32 val = 0xffff;
if (index < CIF_REG_INDEX_MAX) {
if (index > CIF_REG_DVP_CTRL) {
if (!IS_ERR(cif->regmap_grf))
regmap_read(cif->regmap_grf, reg->offset, &val);
} else {
VEHICLE_INFO("read index(%d) reg[%s]: 0x%x failed, maybe useless!!!\n",
index, reg->name, val);
}
VEHICLE_DG("@%s reg[%s] offset(0x%x): 0x%x !\n",
__func__, reg->name, reg->offset, val);
}
return val;
}
static inline void write_csi2_dphy_reg(struct csi2_dphy_hw *hw,
int index, u32 value)
{
const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index];
if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) ||
(index == CSI2PHY_CLK_LANE_ENABLE) ||
((index != CSI2PHY_REG_CTRL_LANE_ENABLE) &&
(reg->offset != 0x0)))
writel(value, hw->csi2_dphy_base + reg->offset);
VEHICLE_DG("@%s offset(0x%x) reg val: 0x%x !\n",
__func__, reg->offset, value);
}
static inline void write_csi2_dphy_reg_mask(struct csi2_dphy_hw *hw,
int index, u32 value, u32 mask)
{
const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index];
u32 read_val = 0;
read_val = readl(hw->csi2_dphy_base + reg->offset);
read_val &= ~mask;
read_val |= value;
writel(read_val, hw->csi2_dphy_base + reg->offset);
}
static inline void read_csi2_dphy_reg(struct csi2_dphy_hw *hw,
int index, u32 *value)
{
const struct csi2dphy_reg *reg = &hw->csi2dphy_regs[index];
if ((index == CSI2PHY_REG_CTRL_LANE_ENABLE) ||
(index == CSI2PHY_CLK_LANE_ENABLE) ||
((index != CSI2PHY_REG_CTRL_LANE_ENABLE) &&
(reg->offset != 0x0)))
*value = readl(hw->csi2_dphy_base + reg->offset);
VEHICLE_DG("@%s offset(0x%x) reg val: 0x%x !\n",
__func__, reg->offset, *value);
}
static void csi_mipidphy_wr_ths_settle(struct csi2_dphy_hw *hw,
int hsfreq,
enum csi2_dphy_lane lane)
{
unsigned int val = 0;
unsigned int offset;
switch (lane) {
case CSI2_DPHY_LANE_CLOCK:
offset = CSI2PHY_CLK_THS_SETTLE;
break;
case CSI2_DPHY_LANE_CLOCK1:
offset = CSI2PHY_CLK1_THS_SETTLE;
break;
case CSI2_DPHY_LANE_DATA0:
offset = CSI2PHY_LANE0_THS_SETTLE;
break;
case CSI2_DPHY_LANE_DATA1:
offset = CSI2PHY_LANE1_THS_SETTLE;
break;
case CSI2_DPHY_LANE_DATA2:
offset = CSI2PHY_LANE2_THS_SETTLE;
break;
case CSI2_DPHY_LANE_DATA3:
offset = CSI2PHY_LANE3_THS_SETTLE;
break;
default:
return;
}
read_csi2_dphy_reg(hw, offset, &val);
val = (val & ~0x7f) | hsfreq;
write_csi2_dphy_reg(hw, offset, val);
}
static void rkvehicle_cif_cfg_dvp_clk_sampling_edge(struct vehicle_cif *cif,
enum rkcif_clk_edge edge)
{
u32 val = 0x0;
if (!IS_ERR(cif->regmap_grf)) {
if (cif->chip_id == CHIP_RK3568_VEHICLE_CIF) {
if (edge == RKCIF_CLK_RISING)
val = RK3568_CIF_PCLK_SAMPLING_EDGE_RISING;
else
val = RK3568_CIF_PCLK_SAMPLING_EDGE_FALLING;
}
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
if (edge == RKCIF_CLK_RISING)
val = RK3588_CIF_PCLK_SAMPLING_EDGE_RISING;
else
val = RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING;
}
rkvehicle_cif_write_grf_reg(cif, CIF_REG_GRF_CIFIO_CON, val);
}
}
static int rkcif_dvp_get_input_yuv_order(struct vehicle_cfg *cfg)
{
unsigned int mask;
switch (cfg->mbus_code) {
case MEDIA_BUS_FMT_UYVY8_2X8:
mask = CSI_YUV_INPUT_ORDER_UYVY >> 11;
break;
case MEDIA_BUS_FMT_VYUY8_2X8:
mask = CSI_YUV_INPUT_ORDER_VYUY >> 11;
break;
case MEDIA_BUS_FMT_YUYV8_2X8:
mask = CSI_YUV_INPUT_ORDER_YUYV >> 11;
break;
case MEDIA_BUS_FMT_YVYU8_2X8:
mask = CSI_YUV_INPUT_ORDER_YVYU >> 11;
break;
default:
mask = CSI_YUV_INPUT_ORDER_UYVY >> 11;
break;
}
return mask;
}
static int cif_stream_setup(struct vehicle_cif *cif)
{
struct vehicle_cfg *cfg = &cif->cif_cfg;
u32 val, mbus_flags,
xfer_mode = 0, yc_swap = 0,
inputmode = 0, mipimode = 0,
input_format = 0, output_format = 0, crop = 0,
out_fmt_mask = 0,
multi_id_en = BT656_1120_MULTI_ID_DISABLE,
multi_id_mode = BT656_1120_MULTI_ID_MODE_1,
multi_id_sel = BT656_1120_MULTI_ID_SEL_LSB,
bt1120_edge_mode = BT1120_CLOCK_SINGLE_EDGES;
u32 sav_detect = BT656_DETECT_SAV;
u32 in_fmt_yuv_order = 0;
mbus_flags = cfg->mbus_flags;
/* set dvp clk sample edge */
if (mbus_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
rkvehicle_cif_cfg_dvp_clk_sampling_edge(cif, RKCIF_CLK_RISING);
else
rkvehicle_cif_cfg_dvp_clk_sampling_edge(cif, RKCIF_CLK_FALLING);
inputmode = cfg->input_format<<2; //INPUT_MODE_YUV or INPUT_MODE_BT656_YUV422
//YUV_INPUT_ORDER_UYVY, MEDIA_BUS_FMT_UYVY8_2X8, CCIR_INPUT_ORDER_ODD
input_format = (cfg->yuv_order<<5) | YUV_INPUT_422 | (cfg->field_order<<9);
if (cfg->output_format == CIF_OUTPUT_FORMAT_420)
output_format = YUV_OUTPUT_420 | UV_STORAGE_ORDER_UVUV;
else
output_format = YUV_OUTPUT_422 | UV_STORAGE_ORDER_UVUV;
if (cif->chip_id == CHIP_RK3568_VEHICLE_CIF) {
val = cfg->vsync | (cfg->href<<1) | inputmode | mipimode
| input_format | output_format
| xfer_mode | yc_swap | multi_id_en
| multi_id_sel | multi_id_mode | bt1120_edge_mode;
} else {
out_fmt_mask = (CSI_WRDDR_TYPE_YUV420SP_RK3588 << 11) |
(CSI_YUV_OUTPUT_ORDER_UYVY << 1);
in_fmt_yuv_order = rkcif_dvp_get_input_yuv_order(cfg);
val = cfg->vsync | (cfg->href<<1) | inputmode
| in_fmt_yuv_order | out_fmt_mask
| yc_swap | multi_id_en | multi_id_sel
| sav_detect | multi_id_mode | bt1120_edge_mode;
}
if (cif->chip_id >= CHIP_RK3576_VEHICLE_CIF)
val |= DVP_UVDS_EN;
rkcif_write_reg(cif, CIF_REG_DVP_FOR, val);
rkcif_write_reg(cif, CIF_REG_DVP_VIR_LINE_WIDTH, cfg->width);
rkcif_write_reg(cif, CIF_REG_DVP_SET_SIZE,
cfg->width | (cfg->height << 16));
crop = (cfg->start_x | (cfg->start_y<<16));
rkcif_write_reg(cif, CIF_REG_DVP_CROP, crop);
rkcif_write_reg(cif, CIF_REG_DVP_FRAME_STATUS, FRAME_STAT_CLS);
if (cif->chip_id < CHIP_RK3588_VEHICLE_CIF) {
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, INTSTAT_CLS);
rkcif_write_reg(cif, CIF_REG_DVP_SCL_CTRL, ENABLE_YUV_16BIT_BYPASS);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN,
FRAME_END_EN | INTSTAT_ERR |
PST_INF_FRAME_END);
/* enable line int for sof */
rkcif_write_reg(cif, CIF_REG_DVP_LINE_INT_NUM, 0x1);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, LINE_INT_EN);
} else if (cif->chip_id < CHIP_RK3576_VEHICLE_CIF) {
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, 0x3c3ffff);
rkcif_write_reg_or(cif, CIF_REG_DVP_INTEN, 0x033ffff);//0x3c3ffff
} else {
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, 0x3c3ffff);
rkcif_write_reg_or(cif, CIF_REG_DVP_INTEN, 0x3c3ff0f);
}
cif->interlaced_enable = false;
return 0;
}
static inline void csi2_dphy_write_sys_grf_reg(struct csi2_dphy_hw *hw,
int index, u8 value)
{
const struct grf_reg *reg = &hw->grf_regs[index];
unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift);
if (reg->shift)
regmap_write(hw->regmap_sys_grf, reg->offset, val);
}
static inline void csi2_dphy_write_grf_reg(struct csi2_dphy_hw *hw,
int index, u8 value)
{
const struct grf_reg *reg = &hw->grf_regs[index];
unsigned int val = HIWORD_UPDATE(value, reg->mask, reg->shift);
if (reg->shift)
regmap_write(hw->regmap_grf, reg->offset, val);
}
static inline u32 csi2_dphy_read_grf_reg(struct csi2_dphy_hw *hw, int index)
{
const struct grf_reg *reg = &hw->grf_regs[index];
unsigned int val = 0;
if (reg->shift) {
regmap_read(hw->regmap_grf, reg->offset, &val);
val = (val >> reg->shift) & reg->mask;
}
return val;
}
static void csi2_dphy_config_dual_mode(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
u32 val;
val = ~GRF_CSI2PHY_LANE_SEL_SPLIT;
if (cif->dphy_hw->phy_index < 3) {
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN,
GENMASK(cif->cif_cfg.lanes - 1, 0));
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1);
if (cif->chip_id != CHIP_RK3588_VEHICLE_CIF &&
cif->chip_id != CHIP_RK3576_VEHICLE_CIF)
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
else
csi2_dphy_write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL, val);
} else {
if (cif->chip_id <= CHIP_RK3588_VEHICLE_CIF ||
cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN,
GENMASK(cif->cif_cfg.lanes - 1, 0));
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN, 0x1);
} else {
csi2_dphy_write_grf_reg(hw, GRF_DPHY1_CSI2PHY_DATALANE_EN,
GENMASK(cif->cif_cfg.lanes - 1, 0));
csi2_dphy_write_grf_reg(hw, GRF_DPHY1_CSI2PHY_CLKLANE_EN, 0x1);
}
if (cif->chip_id != CHIP_RK3588_VEHICLE_CIF &&
cif->chip_id != CHIP_RK3576_VEHICLE_CIF)
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val);
else
csi2_dphy_write_sys_grf_reg(hw, GRF_DPHY_CSI2PHY1_LANE_SEL, val);
}
}
static int vehicle_csi2_dphy_stream_start(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
const struct hsfreq_range *hsfreq_ranges = hw->hsfreq_ranges;
int num_hsfreq_ranges = hw->num_hsfreq_ranges;
int i, hsfreq = 0;
u32 val = 0, pre_val;
mutex_lock(&hw->mutex);
/* set data lane num and enable clock lane */
/*
* for rk356x: dphy0 is used just for full mode,
* dphy1 is used just for split mode,uses lane0_1,
* dphy2 is used just for split mode,uses lane2_3
*/
read_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, &pre_val);
val |= (GENMASK(cif->cif_cfg.lanes - 1, 0) <<
CSI2_DPHY_CTRL_DATALANE_ENABLE_OFFSET_BIT) |
(0x1 << CSI2_DPHY_CTRL_CLKLANE_ENABLE_OFFSET_BIT);
val |= pre_val;
write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, val);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1e);
write_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, 0x1f);
csi2_dphy_config_dual_mode(cif);
}
/* not into receive mode/wait stopstate */
csi2_dphy_write_grf_reg(hw, GRF_DPHY_CSI2PHY_FORCERXMODE, 0x0);
/* enable calibration */
if (hw->data_rate_mbps > 1500) {
write_csi2_dphy_reg(hw, CSI2PHY_CLK_CALIB_ENABLE, 0x80);
if (cif->cif_cfg.lanes > 0x00)
write_csi2_dphy_reg(hw, CSI2PHY_LANE0_CALIB_ENABLE, 0x80);
if (cif->cif_cfg.lanes > 0x01)
write_csi2_dphy_reg(hw, CSI2PHY_LANE1_CALIB_ENABLE, 0x80);
if (cif->cif_cfg.lanes > 0x02)
write_csi2_dphy_reg(hw, CSI2PHY_LANE2_CALIB_ENABLE, 0x80);
if (cif->cif_cfg.lanes > 0x03)
write_csi2_dphy_reg(hw, CSI2PHY_LANE3_CALIB_ENABLE, 0x80);
}
/* set clock lane and data lane */
for (i = 0; i < num_hsfreq_ranges; i++) {
if (hsfreq_ranges[i].range_h >= hw->data_rate_mbps) {
hsfreq = hsfreq_ranges[i].cfg_bit;
break;
}
}
if (i == num_hsfreq_ranges) {
i = num_hsfreq_ranges - 1;
dev_warn(hw->dev, "data rate: %lld mbps, max support %d mbps",
hw->data_rate_mbps, hsfreq_ranges[i].range_h + 1);
hsfreq = hsfreq_ranges[i].cfg_bit;
}
VEHICLE_DG("mipi data_rate_mbps %lld, matched bit(0x%0x), lanes(%d)\n",
hw->data_rate_mbps, hsfreq, cif->cif_cfg.lanes);
csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_CLOCK);
if (cif->cif_cfg.lanes > 0x00)
csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA0);
if (cif->cif_cfg.lanes > 0x01)
csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA1);
if (cif->cif_cfg.lanes > 0x02)
csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA2);
if (cif->cif_cfg.lanes > 0x03)
csi_mipidphy_wr_ths_settle(hw, hsfreq, CSI2_DPHY_LANE_DATA3);
atomic_inc(&hw->stream_cnt);
mutex_unlock(&hw->mutex);
return 0;
}
static void vehicle_samsung_dcphy_rx_config_settle(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
const struct hsfreq_range *hsfreq_ranges = NULL;
int num_hsfreq_ranges = 0;
int i, hsfreq = 0;
u32 sot_sync = 0;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
hsfreq_ranges = hw->hsfreq_ranges;
num_hsfreq_ranges = hw->num_hsfreq_ranges;
sot_sync = 0x03;
}
/* set data lane */
for (i = 0; i < num_hsfreq_ranges; i++) {
if (hsfreq_ranges[i].range_h >= hw->data_rate_mbps) {
hsfreq = hsfreq_ranges[i].cfg_bit;
break;
}
}
/*clk settle fix to 0x301*/
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY)
regmap_write(samsung->regmap, RX_CLK_THS_SETTLE, 0x301);
if (cif->cif_cfg.lanes > 0x00) {
regmap_update_bits(samsung->regmap, RX_LANE0_THS_SETTLE, 0x1ff, hsfreq);
regmap_update_bits(samsung->regmap, RX_LANE0_ERR_SOT_SYNC, 0xff, sot_sync);
}
if (cif->cif_cfg.lanes > 0x01) {
regmap_update_bits(samsung->regmap, RX_LANE1_THS_SETTLE, 0x1ff, hsfreq);
regmap_update_bits(samsung->regmap, RX_LANE1_ERR_SOT_SYNC, 0xff, sot_sync);
}
if (cif->cif_cfg.lanes > 0x02) {
regmap_update_bits(samsung->regmap, RX_LANE2_THS_SETTLE, 0x1ff, hsfreq);
regmap_update_bits(samsung->regmap, RX_LANE2_ERR_SOT_SYNC, 0xff, sot_sync);
}
if (cif->cif_cfg.lanes > 0x03) {
regmap_update_bits(samsung->regmap, RX_LANE3_THS_SETTLE, 0x1ff, hsfreq);
regmap_update_bits(samsung->regmap, RX_LANE3_ERR_SOT_SYNC, 0xff, sot_sync);
}
}
static int vehicle_samsung_dcphy_rx_config_common(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
u32 dlysel = 0;
int i = 0;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
if (hw->data_rate_mbps < 1500)
dlysel = 0;
else if (hw->data_rate_mbps < 2000)
dlysel = 3 << 8;
else if (hw->data_rate_mbps < 3000)
dlysel = 2 << 8;
else if (hw->data_rate_mbps < 4000)
dlysel = 1 << 8;
else if (hw->data_rate_mbps < 6500)
dlysel = 0;
if (hw->dphy_param->clk_hs_term_sel > 0x7) {
dev_err(hw->dev, "clk_hs_term_sel error param %d\n",
hw->dphy_param->clk_hs_term_sel);
return -EINVAL;
}
for (i = 0; i < cif->cif_cfg.lanes; i++) {
if (hw->dphy_param->data_hs_term_sel[i] > 0x7) {
dev_err(hw->dev, "data_hs_term_sel[%d] error param %d\n",
i,
hw->dphy_param->data_hs_term_sel[i]);
return -EINVAL;
}
if (hw->dphy_param->lp_hys_sw[i] > 0x3) {
dev_err(hw->dev, "lp_hys_sw[%d] error param %d\n",
i,
hw->dphy_param->lp_hys_sw[i]);
return -EINVAL;
}
if (hw->dphy_param->lp_escclk_pol_sel[i] > 0x1) {
dev_err(hw->dev, "lp_escclk_pol_sel[%d] error param %d\n",
i,
hw->dphy_param->lp_escclk_pol_sel[i]);
return -EINVAL;
}
if (hw->dphy_param->skew_data_cal_clk[i] > 0x1f) {
dev_err(hw->dev, "skew_data_cal_clk[%d] error param %d\n",
i,
hw->dphy_param->skew_data_cal_clk[i]);
return -EINVAL;
}
}
regmap_write(samsung->regmap, RX_S0C_GNR_CON1, 0x1450);
regmap_write(samsung->regmap, RX_S0C_ANA_CON1, 0x8000);
regmap_write(samsung->regmap, RX_S0C_ANA_CON2, hw->dphy_param->clk_hs_term_sel);
regmap_write(samsung->regmap, RX_S0C_ANA_CON3, 0x0600);
if (cif->cif_cfg.lanes > 0x00) {
regmap_write(samsung->regmap, RX_COMBO_S0D0_GNR_CON1, 0x1450);
regmap_write(samsung->regmap, RX_COMBO_S0D0_ANA_CON1, 0x8000);
regmap_write(samsung->regmap, RX_COMBO_S0D0_ANA_CON2, dlysel |
hw->dphy_param->data_hs_term_sel[0]);
regmap_write(samsung->regmap, RX_COMBO_S0D0_ANA_CON3, 0x0600 |
(hw->dphy_param->lp_hys_sw[0] << 4) |
(hw->dphy_param->lp_escclk_pol_sel[0] << 11));
regmap_write(samsung->regmap, RX_COMBO_S0D0_ANA_CON7, 0x40);
regmap_write(samsung->regmap, RX_COMBO_S0D0_DESKEW_CON2,
hw->dphy_param->skew_data_cal_clk[0]);
if (hw->data_rate_mbps >= 1500 &&
cif->chip_id >= CHIP_RK3576_VEHICLE_CIF) {
regmap_write(samsung->regmap, RX_COMBO_S0D0_DESKEW_CON0, BIT(0));
regmap_write(samsung->regmap, RX_COMBO_S0D0_DESKEW_CON4, 0x81A);
}
}
if (cif->cif_cfg.lanes > 0x01) {
regmap_write(samsung->regmap, RX_COMBO_S0D1_GNR_CON1, 0x1450);
regmap_write(samsung->regmap, RX_COMBO_S0D1_ANA_CON1, 0x8000);
regmap_write(samsung->regmap, RX_COMBO_S0D1_ANA_CON2, dlysel |
hw->dphy_param->data_hs_term_sel[1]);
regmap_write(samsung->regmap, RX_COMBO_S0D1_ANA_CON3, 0x0600 |
(hw->dphy_param->lp_hys_sw[1] << 4) |
(hw->dphy_param->lp_escclk_pol_sel[1] << 11));
regmap_write(samsung->regmap, RX_COMBO_S0D1_ANA_CON7, 0x40);
regmap_write(samsung->regmap, RX_COMBO_S0D1_DESKEW_CON2,
hw->dphy_param->skew_data_cal_clk[1]);
if (hw->data_rate_mbps >= 1500 &&
cif->chip_id >= CHIP_RK3576_VEHICLE_CIF) {
regmap_write(samsung->regmap, RX_COMBO_S0D1_DESKEW_CON0, BIT(0));
regmap_write(samsung->regmap, RX_COMBO_S0D1_DESKEW_CON4, 0x81A);
}
}
if (cif->cif_cfg.lanes > 0x02) {
regmap_write(samsung->regmap, RX_COMBO_S0D2_GNR_CON1, 0x1450);
regmap_write(samsung->regmap, RX_COMBO_S0D2_ANA_CON1, 0x8000);
regmap_write(samsung->regmap, RX_COMBO_S0D2_ANA_CON2, dlysel |
hw->dphy_param->data_hs_term_sel[2]);
regmap_write(samsung->regmap, RX_COMBO_S0D2_ANA_CON3, 0x0600 |
(hw->dphy_param->lp_hys_sw[2] << 4) |
(hw->dphy_param->lp_escclk_pol_sel[2] << 11));
regmap_write(samsung->regmap, RX_COMBO_S0D2_ANA_CON7, 0x40);
regmap_write(samsung->regmap, RX_COMBO_S0D2_DESKEW_CON2,
hw->dphy_param->skew_data_cal_clk[2]);
if (hw->data_rate_mbps >= 1500 &&
cif->chip_id >= CHIP_RK3576_VEHICLE_CIF) {
regmap_write(samsung->regmap, RX_COMBO_S0D2_DESKEW_CON0, BIT(0));
regmap_write(samsung->regmap, RX_COMBO_S0D2_DESKEW_CON4, 0x81A);
}
}
if (cif->cif_cfg.lanes > 0x03) {
regmap_write(samsung->regmap, RX_S0D3_GNR_CON1, 0x1450);
regmap_write(samsung->regmap, RX_S0D3_ANA_CON1, 0x8000);
regmap_write(samsung->regmap, RX_S0D3_ANA_CON2, dlysel |
hw->dphy_param->data_hs_term_sel[3]);
regmap_write(samsung->regmap, RX_S0D3_ANA_CON3, 0x0600 |
(hw->dphy_param->lp_hys_sw[3] << 4) |
(hw->dphy_param->lp_escclk_pol_sel[3] << 11));
regmap_write(samsung->regmap, RX_S0D3_DESKEW_CON2,
hw->dphy_param->skew_data_cal_clk[3]);
if (hw->data_rate_mbps >= 1500 &&
cif->chip_id >= CHIP_RK3576_VEHICLE_CIF) {
regmap_write(samsung->regmap, RX_S0D3_DESKEW_CON0, BIT(0));
regmap_write(samsung->regmap, RX_S0D3_DESKEW_CON4, 0x81A);
}
}
}
return 0;
}
static int vehicle_samsung_dcphy_rx_lane_enable(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
u32 sts;
int ret = 0;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY)
regmap_update_bits(samsung->regmap, RX_CLK_LANE_ENABLE, PHY_ENABLE, PHY_ENABLE);
if (cif->cif_cfg.lanes > 0x00)
regmap_update_bits(samsung->regmap, RX_DATA_LANE0_ENABLE, PHY_ENABLE, PHY_ENABLE);
if (cif->cif_cfg.lanes > 0x01)
regmap_update_bits(samsung->regmap, RX_DATA_LANE1_ENABLE, PHY_ENABLE, PHY_ENABLE);
if (cif->cif_cfg.lanes > 0x02)
regmap_update_bits(samsung->regmap, RX_DATA_LANE2_ENABLE, PHY_ENABLE, PHY_ENABLE);
if (cif->cif_cfg.lanes > 0x03)
regmap_update_bits(samsung->regmap, RX_DATA_LANE3_ENABLE, PHY_ENABLE, PHY_ENABLE);
/*wait for clk lane ready*/
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
ret = regmap_read_poll_timeout(samsung->regmap, RX_CLK_LANE_ENABLE,
sts, (sts & PHY_READY), 200, 4000);
if (ret < 0) {
dev_err(samsung->dev, "phy rx clk lane is not locked\n");
return -EINVAL;
}
}
/*wait for data lane ready*/
if (cif->cif_cfg.lanes > 0x00) {
ret = regmap_read_poll_timeout(samsung->regmap, RX_DATA_LANE0_ENABLE,
sts, (sts & PHY_READY), 200, 2000);
if (ret < 0) {
dev_err(samsung->dev, "phy rx data lane 0 is not locked\n");
return -EINVAL;
}
}
if (cif->cif_cfg.lanes > 0x01) {
ret = regmap_read_poll_timeout(samsung->regmap, RX_DATA_LANE1_ENABLE,
sts, (sts & PHY_READY), 200, 2000);
if (ret < 0) {
dev_err(samsung->dev, "phy rx data lane 1 is not locked\n");
return -EINVAL;
}
}
if (cif->cif_cfg.lanes > 0x02) {
ret = regmap_read_poll_timeout(samsung->regmap, RX_DATA_LANE2_ENABLE,
sts, (sts & PHY_READY), 200, 2000);
if (ret < 0) {
dev_err(samsung->dev, "phy rx data lane 2 is not locked\n");
return -EINVAL;
}
}
if (cif->cif_cfg.lanes > 0x03) {
ret = regmap_read_poll_timeout(samsung->regmap, RX_DATA_LANE3_ENABLE,
sts, (sts & PHY_READY), 200, 2000);
if (ret < 0) {
dev_err(samsung->dev, "phy rx data lane 3 is not locked\n");
return -EINVAL;
}
}
return 0;
}
static void vehicle_samsung_mipi_dcphy_bias_block_enable(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
struct csi2_dphy_hw *csi_dphy = samsung->dphy_vehicle[0];
u32 bias_con2 = 0x3223;
if (csi_dphy &&
csi_dphy->dphy_param->lp_vol_ref != 3 &&
csi_dphy->dphy_param->lp_vol_ref < 0x7) {
bias_con2 &= 0xfffffff8;
bias_con2 |= csi_dphy->dphy_param->lp_vol_ref;
dev_info(samsung->dev,
"rx change lp_vol_ref to %d, it may cause tx exception\n",
csi_dphy->dphy_param->lp_vol_ref);
}
regmap_write(samsung->regmap, BIAS_CON0, 0x0010);
regmap_write(samsung->regmap, BIAS_CON1, 0x0110);
regmap_write(samsung->regmap, BIAS_CON2, bias_con2);
/* default output voltage select:
* dphy: 400mv
* cphy: 530mv
*/
if (samsung->c_option)
regmap_update_bits(samsung->regmap, BIAS_CON4,
I_MUX_SEL_MASK, I_MUX_SEL(2));
}
static int vehicle_csi2_dcphy_stream_start(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
int ret = 0;
dev_info(hw->dev, "mipi dcphy stream on\n");
mutex_lock(&hw->mutex);
if (samsung->s_phy_rst)
reset_control_assert(samsung->s_phy_rst);
vehicle_samsung_mipi_dcphy_bias_block_enable(cif);
ret = vehicle_samsung_dcphy_rx_config_common(cif);
if (ret)
goto out_streamon;
vehicle_samsung_dcphy_rx_config_settle(cif);
ret = vehicle_samsung_dcphy_rx_lane_enable(cif);
if (ret)
goto out_streamon;
if (samsung->s_phy_rst)
reset_control_deassert(samsung->s_phy_rst);
atomic_inc(&hw->stream_cnt);
mutex_unlock(&hw->mutex);
return 0;
out_streamon:
if (samsung->s_phy_rst)
reset_control_deassert(samsung->s_phy_rst);
mutex_unlock(&hw->mutex);
dev_err(hw->dev, "stream on error\n");
return -EINVAL;
}
static int vehicle_csi2_dcphy_stream_stop(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct samsung_mipi_dcphy *samsung = hw->samsung_phy;
dev_info(hw->dev, "mipi dcphy stream off\n");
if (atomic_dec_return(&hw->stream_cnt))
return 0;
mutex_lock(&hw->mutex);
if (samsung->s_phy_rst)
reset_control_assert(samsung->s_phy_rst);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY)
regmap_update_bits(samsung->regmap, RX_CLK_LANE_ENABLE, PHY_ENABLE, 0);
if (cif->cif_cfg.lanes > 0x00)
regmap_update_bits(samsung->regmap, RX_DATA_LANE0_ENABLE, PHY_ENABLE, 0);
if (cif->cif_cfg.lanes > 0x01)
regmap_update_bits(samsung->regmap, RX_DATA_LANE1_ENABLE, PHY_ENABLE, 0);
if (cif->cif_cfg.lanes > 0x02)
regmap_update_bits(samsung->regmap, RX_DATA_LANE2_ENABLE, PHY_ENABLE, 0);
if (cif->cif_cfg.lanes > 0x03)
regmap_update_bits(samsung->regmap, RX_DATA_LANE3_ENABLE, PHY_ENABLE, 0);
if (samsung->s_phy_rst)
reset_control_deassert(samsung->s_phy_rst);
usleep_range(500, 1000);
mutex_unlock(&hw->mutex);
return 0;
}
static void vehicle_csi2_disable(struct vehicle_cif *cif)
{
void __iomem *base = cif->csi2_base;
vehicle_write_csihost_reg(base, CSIHOST_RESETN, 0);
vehicle_write_csihost_reg(base, CSIHOST_MSK1, 0xffffffff);
vehicle_write_csihost_reg(base, CSIHOST_MSK2, 0xffffffff);
}
static void vehicle_csi2_enable(struct vehicle_cif *cif,
enum host_type_t host_type)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
void __iomem *base = hw->csi2_base;
int lanes = cif->cif_cfg.lanes;
vehicle_write_csihost_reg(base, CSIHOST_N_LANES, lanes - 1);
if (host_type == RK_DSI_RXHOST) {
vehicle_write_csihost_reg(base, CSIHOST_CONTROL,
SW_CPHY_EN(0) | SW_DSI_EN(1) |
SW_DATATYPE_FS(0x01) | SW_DATATYPE_FE(0x11) |
SW_DATATYPE_LS(0x21) | SW_DATATYPE_LE(0x31));
/* Disable some error interrupt when HOST work on DSI RX mode */
vehicle_write_csihost_reg(base, CSIHOST_MSK1, 0xe00000f0);
vehicle_write_csihost_reg(base, CSIHOST_MSK2, 0xff00);
} else {
vehicle_write_csihost_reg(base, CSIHOST_CONTROL,
SW_CPHY_EN(0) | SW_DSI_EN(0) |
SW_DATATYPE_FS(0x0) | SW_DATATYPE_FE(0x01) |
SW_DATATYPE_LS(0x02) | SW_DATATYPE_LE(0x03));
vehicle_write_csihost_reg(base, CSIHOST_MSK1, 0);
vehicle_write_csihost_reg(base, CSIHOST_MSK2, 0xf000);
}
vehicle_write_csihost_reg(base, CSIHOST_RESETN, 1);
}
static int vehicle_csi2_stream_start(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
enum host_type_t host_type;
int i;
host_type = RK_CSI_RXHOST;
vehicle_csi2_enable(cif, host_type);
for (i = 0; i < RK_CSI2_ERR_MAX; i++)
hw->err_list[i].cnt = 0;
return 0;
}
static void vehicle_cif_csi_get_vc_num(struct vehicle_cif *cif)
{
int vc_num = 0;
unsigned int mbus_flags = cif->cif_cfg.mbus_flags;
for (vc_num = 0; vc_num < RKCIF_MAX_CSI_CHANNEL; vc_num++) {
if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_0) {
cif->channels[vc_num].vc = vc_num;
mbus_flags ^= V4L2_MBUS_CSI2_CHANNEL_0;
continue;
}
if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_1) {
cif->channels[vc_num].vc = vc_num;
mbus_flags ^= V4L2_MBUS_CSI2_CHANNEL_1;
continue;
}
if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_2) {
cif->channels[vc_num].vc = vc_num;
mbus_flags ^= V4L2_MBUS_CSI2_CHANNEL_2;
continue;
}
if (mbus_flags & V4L2_MBUS_CSI2_CHANNEL_3) {
cif->channels[vc_num].vc = vc_num;
mbus_flags ^= V4L2_MBUS_CSI2_CHANNEL_3;
continue;
}
}
cif->num_channels = vc_num ? (vc_num - 1) : 1;
if (cif->num_channels == 1)
cif->channels[0].vc = 0;
}
static const struct
cif_input_fmt *find_input_fmt(u32 mbus_code)
{
const struct cif_input_fmt *fmt;
u32 i;
for (i = 0; i < ARRAY_SIZE(in_fmts); i++) {
fmt = &in_fmts[i];
if (mbus_code == fmt->mbus_code)
return fmt;
}
return NULL;
}
static const struct
cif_output_fmt *find_output_fmt(u32 pixelfmt)
{
const struct cif_output_fmt *fmt;
u32 i;
for (i = 0; i < ARRAY_SIZE(out_fmts); i++) {
fmt = &out_fmts[i];
if (fmt->fourcc == pixelfmt)
return fmt;
}
return NULL;
}
static enum cif_reg_index get_reg_index_of_id_ctrl0(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_ID0_CTRL0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_ID1_CTRL0;
break;
case 2:
index = CIF_REG_MIPI_LVDS_ID2_CTRL0;
break;
case 3:
index = CIF_REG_MIPI_LVDS_ID3_CTRL0;
break;
default:
index = CIF_REG_MIPI_LVDS_ID0_CTRL0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_id_ctrl1(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_ID0_CTRL1;
break;
case 1:
index = CIF_REG_MIPI_LVDS_ID1_CTRL1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_ID2_CTRL1;
break;
case 3:
index = CIF_REG_MIPI_LVDS_ID3_CTRL1;
break;
default:
index = CIF_REG_MIPI_LVDS_ID0_CTRL1;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm0_y_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm_num(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_FRAME_NUM_VC0;
break;
case 1:
index = CIF_REG_MIPI_FRAME_NUM_VC1;
break;
case 2:
index = CIF_REG_MIPI_FRAME_NUM_VC2;
break;
case 3:
index = CIF_REG_MIPI_FRAME_NUM_VC3;
break;
default:
index = CIF_REG_MIPI_FRAME_NUM_VC0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm1_y_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm0_uv_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm1_uv_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm0_y_vlw(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm1_y_vlw(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm0_uv_vlw(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_frm1_uv_vlw(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0;
break;
case 1:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID1;
break;
case 2:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID2;
break;
case 3:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID3;
break;
default:
index = CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0;
break;
}
return index;
}
static enum cif_reg_index get_reg_index_of_id_crop_start(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_MIPI_LVDS_ID0_CROP_START;
break;
case 1:
index = CIF_REG_MIPI_LVDS_ID1_CROP_START;
break;
case 2:
index = CIF_REG_MIPI_LVDS_ID2_CROP_START;
break;
case 3:
index = CIF_REG_MIPI_LVDS_ID3_CROP_START;
break;
default:
index = CIF_REG_MIPI_LVDS_ID0_CROP_START;
break;
}
return index;
}
static enum cif_reg_index get_dvp_reg_index_of_frm0_y_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_DVP_FRM0_ADDR_Y;
break;
case 1:
index = CIF_REG_DVP_FRM0_ADDR_Y_ID1;
break;
case 2:
index = CIF_REG_DVP_FRM0_ADDR_Y_ID2;
break;
case 3:
index = CIF_REG_DVP_FRM0_ADDR_Y_ID3;
break;
default:
index = CIF_REG_DVP_FRM0_ADDR_Y;
break;
}
return index;
}
static enum cif_reg_index get_dvp_reg_index_of_frm1_y_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_DVP_FRM1_ADDR_Y;
break;
case 1:
index = CIF_REG_DVP_FRM1_ADDR_Y_ID1;
break;
case 2:
index = CIF_REG_DVP_FRM1_ADDR_Y_ID2;
break;
case 3:
index = CIF_REG_DVP_FRM1_ADDR_Y_ID3;
break;
default:
index = CIF_REG_DVP_FRM0_ADDR_Y;
break;
}
return index;
}
static enum cif_reg_index get_dvp_reg_index_of_frm0_uv_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_DVP_FRM0_ADDR_UV;
break;
case 1:
index = CIF_REG_DVP_FRM0_ADDR_UV_ID1;
break;
case 2:
index = CIF_REG_DVP_FRM0_ADDR_UV_ID2;
break;
case 3:
index = CIF_REG_DVP_FRM0_ADDR_UV_ID3;
break;
default:
index = CIF_REG_DVP_FRM0_ADDR_UV;
break;
}
return index;
}
static enum cif_reg_index get_dvp_reg_index_of_frm1_uv_addr(int channel_id)
{
enum cif_reg_index index;
switch (channel_id) {
case 0:
index = CIF_REG_DVP_FRM1_ADDR_UV;
break;
case 1:
index = CIF_REG_DVP_FRM1_ADDR_UV_ID1;
break;
case 2:
index = CIF_REG_DVP_FRM1_ADDR_UV_ID2;
break;
case 3:
index = CIF_REG_DVP_FRM1_ADDR_UV_ID3;
break;
default:
index = CIF_REG_DVP_FRM1_ADDR_UV;
break;
}
return index;
}
static unsigned char get_data_type(u32 pixelformat, u8 cmd_mode_en)
{
switch (pixelformat) {
/* csi raw8 */
case MEDIA_BUS_FMT_SBGGR8_1X8:
case MEDIA_BUS_FMT_SGBRG8_1X8:
case MEDIA_BUS_FMT_SGRBG8_1X8:
case MEDIA_BUS_FMT_SRGGB8_1X8:
return 0x2a;
/* csi raw10 */
case MEDIA_BUS_FMT_SBGGR10_1X10:
case MEDIA_BUS_FMT_SGBRG10_1X10:
case MEDIA_BUS_FMT_SGRBG10_1X10:
case MEDIA_BUS_FMT_SRGGB10_1X10:
return 0x2b;
/* csi raw12 */
case MEDIA_BUS_FMT_SBGGR12_1X12:
case MEDIA_BUS_FMT_SGBRG12_1X12:
case MEDIA_BUS_FMT_SGRBG12_1X12:
case MEDIA_BUS_FMT_SRGGB12_1X12:
return 0x2c;
/* csi uyvy 422 */
case MEDIA_BUS_FMT_UYVY8_2X8:
case MEDIA_BUS_FMT_VYUY8_2X8:
case MEDIA_BUS_FMT_YUYV8_2X8:
case MEDIA_BUS_FMT_YVYU8_2X8:
return 0x1e;
case MEDIA_BUS_FMT_RGB888_1X24: {
if (cmd_mode_en) /* dsi command mode*/
return 0x39;
else /* dsi video mode */
return 0x3e;
}
default:
return 0x2b;
}
}
#define UV_OFFSET (cif->cif_cfg.width * cif->cif_cfg.height)
static int vehicle_cif_init_buffer(struct vehicle_cif *cif,
int init, int csi_ch)
{
struct vehicle_rkcif_dummy_buffer *dummy_buf = &cif->dummy_buf;
u32 frm0_addr_y, frm0_addr_uv;
u32 frm1_addr_y, frm1_addr_uv;
unsigned long y_addr, uv_addr;
int i;
if (cif->cif_cfg.buf_num < 2)
return -EINVAL;
if (cif->cif_cfg.buf_num > MAX_BUF_NUM)
cif->cif_cfg.buf_num = MAX_BUF_NUM;
for (i = 0 ; i < cif->cif_cfg.buf_num; i++) {
cif->frame_buf[i] = cif->cif_cfg.buf_phy_addr[i];
if (cif->frame_buf[i] == 0)
return -EINVAL;
}
cif->last_buf_index = 0;
cif->current_buf_index = 1;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
frm0_addr_y = get_reg_index_of_frm0_y_addr(csi_ch);
frm0_addr_uv = get_reg_index_of_frm0_uv_addr(csi_ch);
frm1_addr_y = get_reg_index_of_frm1_y_addr(csi_ch);
frm1_addr_uv = get_reg_index_of_frm1_uv_addr(csi_ch);
} else {
frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(csi_ch);
frm0_addr_uv = get_dvp_reg_index_of_frm0_uv_addr(csi_ch);
frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(csi_ch);
frm1_addr_uv = get_dvp_reg_index_of_frm1_uv_addr(csi_ch);
}
spin_lock(&cif->vbq_lock);
y_addr = vehicle_flinger_request_cif_buffer();
if (y_addr) {
uv_addr = y_addr + UV_OFFSET;
rkcif_write_reg(cif, frm0_addr_y, y_addr);
rkcif_write_reg(cif, frm0_addr_uv, uv_addr);
cif->active[0] = y_addr;
} else {
rkcif_write_reg(cif, frm0_addr_y, dummy_buf->dma_addr);
rkcif_write_reg(cif, frm0_addr_uv, dummy_buf->dma_addr);
cif->active[0] = y_addr;
}
y_addr = vehicle_flinger_request_cif_buffer();
if (y_addr) {
uv_addr = y_addr + UV_OFFSET;
rkcif_write_reg(cif, frm1_addr_y, y_addr);
rkcif_write_reg(cif, frm1_addr_uv, uv_addr);
cif->active[1] = y_addr;
} else {
rkcif_write_reg(cif, frm1_addr_y, dummy_buf->dma_addr);
rkcif_write_reg(cif, frm1_addr_uv, dummy_buf->dma_addr);
cif->active[1] = y_addr;
}
if (cif->cif_cfg.type != V4L2_MBUS_CSI2_DPHY) {
int ch_id;
for (ch_id = 0; ch_id < 4; ch_id++) {
if (ch_id == csi_ch)
continue;
rkcif_write_reg(cif, get_dvp_reg_index_of_frm0_y_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_reg(cif, get_dvp_reg_index_of_frm1_y_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_reg(cif, get_dvp_reg_index_of_frm0_uv_addr(ch_id),
dummy_buf->dma_addr);
rkcif_write_reg(cif, get_dvp_reg_index_of_frm1_uv_addr(ch_id),
dummy_buf->dma_addr);
}
}
spin_unlock(&cif->vbq_lock);
return 0;
}
static int vehicle_cif_csi_channel_init(struct vehicle_cif *cif,
struct vehicle_csi_channel_info *channel)
{
struct vehicle_cfg *cfg = &cif->cif_cfg;
const struct cif_output_fmt *fmt;
u32 fourcc;
channel->enable = 1;
channel->width = cfg->width;
channel->height = cfg->height;
cif->interlaced_enable = false;
channel->cmd_mode_en = 0; /* default use DSI Video Mode */
channel->crop_en = 1;
channel->crop_st_x = cfg->start_x;
channel->crop_st_y = cfg->start_y;
channel->width = cfg->width;
channel->height = cfg->height;
if (cfg->output_format == CIF_OUTPUT_FORMAT_420) {
fmt = find_output_fmt(V4L2_PIX_FMT_NV12);
if (!fmt) {
VEHICLE_DGERR("can not find output format: 0x%x", V4L2_PIX_FMT_NV12);
return -EINVAL;
}
} else {
fmt = find_output_fmt(V4L2_PIX_FMT_NV16);
if (!fmt) {
VEHICLE_DGERR("can not find output format: 0x%x", V4L2_PIX_FMT_NV16);
return -EINVAL;
}
}
channel->fmt_val = fmt->csi_fmt_val;
VEHICLE_INFO("%s, LINE=%d, channel->fmt_val = 0x%x, fmt->csi_fmt_val= 0x%x",
__func__, __LINE__, channel->fmt_val, fmt->csi_fmt_val);
/*
* for mipi or lvds, when enable compact, the virtual width of raw10/raw12
* needs aligned with :ALIGN(bits_per_pixel * width / 8, 8), if enable 16bit mode
* needs aligned with :ALIGN(bits_per_pixel * width * 2, 8), to optimize reading and
* writing of ddr, aligned with 256
*/
if (fmt->fmt_type == CIF_FMT_TYPE_RAW && channel->fmt_val != CSI_WRDDR_TYPE_RAW8)
channel->virtual_width = ALIGN(channel->width * 2, 8);
else
channel->virtual_width = ALIGN(channel->width * fmt->bpp[0] / 8, 8);
if (channel->fmt_val == CSI_WRDDR_TYPE_RGB888)
channel->width = channel->width * fmt->bpp[0] / 8;
/*
* rk cif don't support output yuyv fmt data
* if user request yuyv fmt, the input mode must be RAW8
* and the width is double Because the real input fmt is
* yuyv
*/
fourcc = fmt->fourcc;
if (fourcc == V4L2_PIX_FMT_YUYV || fourcc == V4L2_PIX_FMT_YVYU ||
fourcc == V4L2_PIX_FMT_UYVY || fourcc == V4L2_PIX_FMT_VYUY) {
channel->fmt_val = CSI_WRDDR_TYPE_RAW8;
channel->width *= 2;
channel->virtual_width *= 2;
}
VEHICLE_DG("%s, LINE=%d, channel->fmt_val = 0x%x", __func__, __LINE__, channel->fmt_val);
if (cfg->input_format == CIF_INPUT_FORMAT_PAL ||
cfg->input_format == CIF_INPUT_FORMAT_NTSC) {
VEHICLE_INFO("CVBS IN PAL or NTSC config.");
cif->interlaced_enable = true;
if (!cif->use_hw_interlace) {
channel->virtual_width *= 2;
cif->interlaced_offset = channel->width;
cif->interlaced_counts = 0;
cif->interlaced_buffer = 0;
channel->height /= 2;
}
VEHICLE_INFO("do denterlaced.\n");
}
channel->data_type = get_data_type(cfg->mbus_code,
channel->cmd_mode_en);
return 0;
}
static int vehicle_cif_csi_channel_set(struct vehicle_cif *cif,
struct vehicle_csi_channel_info *channel,
enum v4l2_mbus_type mbus_type)
{
unsigned int val = 0x0;
if (channel->id >= 4)
return -EINVAL;
if (!channel->enable) {
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(channel->id),
CSI_DISABLE_CAPTURE);
return 0;
}
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTSTAT,
~(CSI_START_INTSTAT(channel->id) |
CSI_DMA_END_INTSTAT(channel->id) |
CSI_LINE_INTSTAT(channel->id)));
/* 0. need set CIF_CSI_INTEN to 0x0 first */
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTEN, 0x0);
/* enable id0 frame start int for sof(long frame, for hdr)
* vehicle don't need this
*/
if (channel->id == RKCIF_STREAM_MIPI_ID0)
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_START_INTEN(channel->id));
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1,
0x3fff << 16 | 0x3fff);
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3,
0x3fff << 16 | 0x3fff);
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_DMA_END_INTEN(channel->id));
rkcif_write_reg(cif, CIF_REG_MIPI_WATER_LINE,
CIF_MIPI_LVDS_SW_WATER_LINE_25_RK1808 |
CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE_RK1808 |
CIF_MIPI_LVDS_SW_HURRY_VALUE_RK1808(0x3) |
CIF_MIPI_LVDS_SW_HURRY_ENABLE_RK1808);
val = CIF_MIPI_LVDS_SW_PRESS_VALUE(0x3) |
CIF_MIPI_LVDS_SW_PRESS_ENABLE |
CIF_MIPI_LVDS_SW_HURRY_VALUE(0x3) |
CIF_MIPI_LVDS_SW_HURRY_ENABLE |
CIF_MIPI_LVDS_SW_WATER_LINE_25 |
CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE;
val &= ~CIF_MIPI_LVDS_SW_SEL_LVDS;
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_CTRL, val);
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_ALL_ERROR_INTEN);
rkcif_write_reg(cif, get_reg_index_of_id_ctrl1(channel->id),
channel->width | (channel->height << 16));
rkcif_write_reg(cif, get_reg_index_of_frm0_y_vlw(channel->id),
channel->virtual_width);
rkcif_write_reg(cif, get_reg_index_of_frm1_y_vlw(channel->id),
channel->virtual_width);
rkcif_write_reg(cif, get_reg_index_of_frm0_uv_vlw(channel->id),
channel->virtual_width);
rkcif_write_reg(cif, get_reg_index_of_frm1_uv_vlw(channel->id),
channel->virtual_width);
if (channel->crop_en)
rkcif_write_reg(cif, get_reg_index_of_id_crop_start(channel->id),
channel->crop_st_y << 16 | channel->crop_st_x);
return 0;
}
/*config reg for rk3588*/
static int vehicle_cif_csi_channel_set_v1(struct vehicle_cif *cif,
struct vehicle_csi_channel_info *channel,
enum v4l2_mbus_type mbus_type)
{
unsigned int val = 0x0;
if (channel->id >= 4)
return -EINVAL;
if (!channel->enable) {
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(channel->id),
CSI_DISABLE_CAPTURE);
return 0;
}
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTSTAT,
~(CSI_START_INTSTAT(channel->id) |
CSI_DMA_END_INTSTAT(channel->id) |
CSI_LINE_INTSTAT_V1(channel->id)));
/* enable id0 frame start int for sof(long frame, for hdr)
* vehicle don't need this
*/
if (channel->id == RKCIF_STREAM_MIPI_ID0)
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_START_INTEN(channel->id));
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1,
0x3fff << 16 | 0x3fff);
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3,
0x3fff << 16 | 0x3fff);
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_DMA_END_INTEN(channel->id));
if (cif->chip_id > CHIP_RK3562_VEHICLE_CIF) {
val = CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE |
(CIF_MIPI_LVDS_SW_WATER_LINE_25 << 19);
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_CTRL, val);
} else {
val = CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_PRESS_ENABLE |
CIF_MIPI_LVDS_SW_HURRY_VALUE_RK3588(0x3) |
CIF_MIPI_LVDS_SW_HURRY_ENABLE |
CIF_MIPI_LVDS_SW_WATER_LINE_25 |
CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE;
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_CTRL, val);
}
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTEN,
CSI_ALL_ERROR_INTEN_V1);
if (cif->chip_id < CHIP_RK3576_VEHICLE_CIF)
rkcif_write_reg(cif, get_reg_index_of_id_ctrl1(channel->id),
(channel->width) | (channel->height << 16));
else
rkcif_write_reg(cif, CIF_REG_MIPI_SET_SIZE_ID0 + channel->id,
(channel->width) | (channel->height << 16));
rkcif_write_reg(cif, get_reg_index_of_frm0_y_vlw(channel->id),
channel->virtual_width);
if (channel->crop_en)
rkcif_write_reg(cif, get_reg_index_of_id_crop_start(channel->id),
channel->crop_st_y << 16 | channel->crop_st_x);
return 0;
}
static int vehicle_cif_stream_start(struct vehicle_cif *cif)
{
struct vehicle_csi_channel_info *channel;
vehicle_cif_csi_get_vc_num(cif);
/* just need init virtual channel 0 */
channel = &cif->channels[0];
channel->id = 0;
vehicle_cif_csi_channel_init(cif, channel);
if (cif->chip_id < CHIP_RK3588_VEHICLE_CIF)
vehicle_cif_csi_channel_set(cif, channel, V4L2_MBUS_CSI2_DPHY);
else
vehicle_cif_csi_channel_set_v1(cif, channel, V4L2_MBUS_CSI2_DPHY);
return 0;
}
static int cif_csi_stream_setup(struct vehicle_cif *cif)
{
vehicle_csi2_stream_start(cif);
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588_DCPHY)
vehicle_csi2_dcphy_stream_start(cif);
else
vehicle_csi2_dphy_stream_start(cif);
vehicle_cif_stream_start(cif);
return 0;
}
static void vehicle_csi2_dphy_hw_do_reset(struct vehicle_cif *cif)
{
unsigned int i;
struct csi2_dphy_hw *dphy_hw = cif->dphy_hw;
for (i = 0; i < dphy_hw->num_dphy_rsts; i++)
if (dphy_hw->dphy_rst[i])
reset_control_assert(dphy_hw->dphy_rst[i]);
udelay(5);
for (i = 0; i < dphy_hw->num_dphy_rsts; i++)
if (dphy_hw->dphy_rst[i])
reset_control_deassert(dphy_hw->dphy_rst[i]);
}
static void vehicle_csi2_hw_soft_reset(struct vehicle_cif *cif)
{
unsigned int i;
struct csi2_dphy_hw *dphy_hw = cif->dphy_hw;
for (i = 0; i < dphy_hw->num_csi2_rsts; i++)
if (dphy_hw->csi2_rst[i])
reset_control_assert(dphy_hw->csi2_rst[i]);
udelay(5);
for (i = 0; i < dphy_hw->num_csi2_rsts; i++)
if (dphy_hw->csi2_rst[i])
reset_control_deassert(dphy_hw->csi2_rst[i]);
}
static int vehicle_csi2_dphy_stream_stop(struct vehicle_cif *cif)
{
struct csi2_dphy_hw *hw = cif->dphy_hw;
mutex_lock(&hw->mutex);
write_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, 0x01);
if (cif->dphy_hw->chip_id >= CHIP_ID_RK3588)
vehicle_csi2_dphy_hw_do_reset(cif);
usleep_range(500, 1000);
mutex_unlock(&hw->mutex);
return 0;
}
static void vehicle_rkcif_disable_sys_clk(struct rk_cif_clk *clk)
{
int i;
for (i = clk->clks_num - 1; i >= 0; i--)
clk_disable_unprepare(clk->clks[i]);
}
static int vehicle_rkcif_enable_sys_clk(struct rk_cif_clk *clk)
{
int i, ret = -EINVAL;
for (i = 0; i < clk->clks_num; i++) {
ret = clk_prepare_enable(clk->clks[i]);
if (ret < 0)
goto err;
}
return 0;
err:
for (--i; i >= 0; --i)
clk_disable_unprepare(clk->clks[i]);
return ret;
}
/* sensor mclk set */
static void rkcif_s_mclk(struct vehicle_cif *cif, int on, int clk_rate)
{
int err = 0;
struct device *dev = cif->dev;
struct rk_cif_clk *clk = &cif->clk;
//return ;
if (on && !clk->on) {
if (!IS_ERR(clk->xvclk)) {
err = clk_set_rate(clk->xvclk, clk_rate);
if (err < 0)
dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
}
if (!IS_ERR(clk->xvclk)) {
err = clk_prepare_enable(clk->xvclk);
if (err < 0)
dev_err(dev, "Failed to enable xvclk\n");
}
} else {
if (!IS_ERR(clk->xvclk))
clk_disable_unprepare(clk->xvclk);
}
usleep_range(2000, 5000);
}
static int rk_cif_mclk_ctrl(struct vehicle_cif *cif, int on, int clk_rate)
{
int err = 0;
struct rk_cif_clk *clk = &cif->clk;
if (on && !clk->on) {
vehicle_rkcif_enable_sys_clk(clk);
clk->on = true;
} else if (!on && clk->on) {
vehicle_rkcif_disable_sys_clk(clk);
clk->on = false;
}
return err;
}
static void csi2_disable_dphy_clk(struct csi2_dphy_hw *hw)
{
int i;
for (i = hw->num_dphy_clks - 1; i >= 0; i--) {
clk_disable_unprepare(hw->dphy_clks[i].clk);
VEHICLE_INFO("%s(%d) disable dphy clk: %s\n",
__func__, __LINE__, hw->dphy_clks[i].id);
}
}
static int csi2_enable_dphy_clk(struct csi2_dphy_hw *hw)
{
int i, ret = -EINVAL;
for (i = 0; i < hw->num_dphy_clks; i++) {
ret = clk_prepare_enable(hw->dphy_clks[i].clk);
if (ret < 0)
goto err;
VEHICLE_INFO("%s(%d) enable dphy clk: %s\n",
__func__, __LINE__, hw->dphy_clks[i].id);
}
return 0;
err:
VEHICLE_DGERR("%s(%d) enable dphy clk: %s err\n",
__func__, __LINE__, hw->dphy_clks[i].id);
for (--i; i >= 0; --i)
clk_disable_unprepare(hw->dphy_clks[i].clk);
return ret;
}
static void csi2_disable_clk(struct csi2_dphy_hw *hw)
{
int i;
for (i = hw->num_csi2_clks - 1; i >= 0; i--) {
clk_disable_unprepare(hw->csi2_clks[i].clk);
VEHICLE_INFO("%s(%d) disable csi2 clk: %s\n",
__func__, __LINE__, hw->csi2_clks[i].id);
}
}
static int csi2_enable_clk(struct csi2_dphy_hw *hw)
{
int i, ret = -EINVAL;
for (i = 0; i < hw->num_csi2_clks; i++) {
ret = clk_prepare_enable(hw->csi2_clks[i].clk);
if (ret < 0)
goto err;
VEHICLE_INFO("%s(%d) enable csi2 clk: %s\n",
__func__, __LINE__, hw->csi2_clks[i].id);
}
return 0;
err:
VEHICLE_DGERR("%s(%d) enable csi2 clk: %s err\n",
__func__, __LINE__, hw->csi2_clks[i].id);
for (--i; i >= 0; --i)
clk_disable_unprepare(hw->csi2_clks[i].clk);
return ret;
}
static int vehicle_csi2_clk_ctrl(struct vehicle_cif *cif, int on)
{
int ret = 0;
struct csi2_dphy_hw *dphy_hw = cif->dphy_hw;
on = !!on;
if (on) {
ret = csi2_enable_dphy_clk(dphy_hw);
if (ret < 0) {
VEHICLE_DGERR("enable csi dphy clk failed!");
goto err;
}
ret = csi2_enable_clk(dphy_hw);
if (ret < 0) {
VEHICLE_DGERR("enable csi dphy clk failed!");
goto err;
}
dphy_hw->on = true;
} else {
csi2_disable_dphy_clk(dphy_hw);
csi2_disable_clk(dphy_hw);
dphy_hw->on = false;
}
return 0;
err:
return ret;
}
static int vehicle_csi2_stream_stop(struct vehicle_cif *cif)
{
vehicle_csi2_disable(cif);
return 0;
}
static int vehicle_cif_stream_stop(struct vehicle_cif *cif)
{
return 0;
}
static int vehicle_cif_csi_stream_stop(struct vehicle_cif *cif)
{
vehicle_cif_stream_stop(cif);
vehicle_csi2_stream_stop(cif);
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588_DCPHY)
vehicle_csi2_dcphy_stream_stop(cif);
else
vehicle_csi2_dphy_stream_stop(cif);
return 0;
}
static int vehicle_cif_csi2_s_stream(struct vehicle_cif *cif,
int enable,
enum v4l2_mbus_type mbus_type)
{
unsigned int val = 0x0;
const struct cif_input_fmt *infmt;
struct vehicle_csi_channel_info *channel;
int id;
channel = &cif->channels[0];
if (enable) {
val = CSI_ENABLE_CAPTURE | channel->fmt_val |
channel->cmd_mode_en << 4 | channel->crop_en << 5 |
channel->id << 8 | channel->data_type << 10;
val &= ~CSI_ENABLE_MIPI_COMPACT;
infmt = find_input_fmt(cif->cif_cfg.mbus_code);
if (!infmt) {
VEHICLE_INFO("Input fmt is invalid, use default!\n");
val |= CSI_YUV_INPUT_ORDER_UYVY;
} else {
val |= infmt->csi_yuv_order;
}
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(channel->id), val);
cif->state = RKCIF_STATE_STREAMING;
} else {
id = channel->id;
val = rkcif_read_reg(cif, get_reg_index_of_id_ctrl0(id));
val &= ~CSI_ENABLE_CAPTURE;
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(id), val);
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTSTAT,
CSI_START_INTSTAT(id) |
CSI_DMA_END_INTSTAT(id) |
CSI_LINE_INTSTAT(id));
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTEN,
~(CSI_START_INTEN(id) |
CSI_DMA_END_INTEN(id) |
CSI_LINE_INTEN(id)));
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTEN,
~CSI_ALL_ERROR_INTEN);
cif->state = RKCIF_STATE_READY;
}
return 0;
}
static int vehicle_cif_csi2_s_stream_v1(struct vehicle_cif *cif,
int enable,
enum v4l2_mbus_type mbus_type)
{
unsigned int val = 0x0;
const struct cif_input_fmt *infmt;
struct vehicle_csi_channel_info *channel;
struct vehicle_cfg *cfg = &cif->cif_cfg;
int id;
channel = &cif->channels[0];
if (enable) {
if (cif->chip_id <= CHIP_RK3562_VEHICLE_CIF) {
val = CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE |
channel->cmd_mode_en << 26 | CSI_ENABLE_CROP_V1 |
channel->id << 8 | channel->data_type << 10;
infmt = find_input_fmt(cif->cif_cfg.mbus_code);
if (!infmt) {
VEHICLE_INFO("Input fmt is invalid, use default!\n");
val |= CSI_YUV_INPUT_ORDER_UYVY;
} else {
val |= infmt->csi_yuv_order | infmt->csi_fmt_val;
}
if (cfg->output_format == CIF_OUTPUT_FORMAT_420) {
if (find_output_fmt(V4L2_PIX_FMT_NV12))
val |= CSI_WRDDR_TYPE_YUV420SP_RK3588 |
CSI_YUV_OUTPUT_ORDER_UYVY;
} else {
if (find_output_fmt(V4L2_PIX_FMT_NV16))
val |= CSI_WRDDR_TYPE_YUV422SP_RK3588 |
CSI_YUV_OUTPUT_ORDER_UYVY;
}
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(channel->id), val);
} else {
val = CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE_RK3576 |
CSI_ENABLE_CROP_RK3576;
infmt = find_input_fmt(cif->cif_cfg.mbus_code);
if (!infmt) {
VEHICLE_INFO("Input fmt is invalid, use default!\n");
val |= CSI_YUV_INPUT_ORDER_UYVY;
} else if (cif->interlaced_enable) {
val |= (infmt->csi_yuv_order >> 4) |
((infmt->csi_fmt_val + 1) << 4);
} else {
val |= (infmt->csi_yuv_order >> 4) | (infmt->csi_fmt_val << 4);
}
if (cfg->output_format == CIF_OUTPUT_FORMAT_420) {
if (find_output_fmt(V4L2_PIX_FMT_NV12))
val |= CSI_WRDDR_TYPE_YUV420SP_RK3588 << 3 |
CSI_YUV_OUTPUT_ORDER_UYVY >> 4;
} else {
if (find_output_fmt(V4L2_PIX_FMT_NV16))
val |= CSI_WRDDR_TYPE_YUV422SP_RK3588 << 3 |
CSI_YUV_OUTPUT_ORDER_UYVY >> 4;
}
if (cfg->output_format == CIF_OUTPUT_FORMAT_420)
val |= CSI_UVDS_EN;
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(channel->id), val);
val = channel->data_type << 2;
rkcif_write_reg(cif, get_reg_index_of_id_ctrl1(channel->id), val);
}
rkcif_write_reg(cif, CIF_REG_MIPI_EFFECT_CODE_ID0, 0x02410251);
rkcif_write_reg(cif, CIF_REG_MIPI_EFFECT_CODE_ID1, 0x02420252);
cif->state = RKCIF_STATE_STREAMING;
} else {
id = channel->id;
val = rkcif_read_reg(cif, get_reg_index_of_id_ctrl0(id));
if (cif->chip_id >= CHIP_RK3576_VEHICLE_CIF)
val &= ~(CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE_RK3576);
else
val &= ~(CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE);
rkcif_write_reg(cif, get_reg_index_of_id_ctrl0(id), val);
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_INTSTAT,
CSI_START_INTSTAT(id) |
CSI_DMA_END_INTSTAT(id) |
CSI_LINE_INTSTAT(id));
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTEN,
~(CSI_START_INTEN(id) |
CSI_DMA_END_INTEN(id) |
CSI_LINE_INTEN(id)));
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_INTEN,
~CSI_ALL_ERROR_INTEN_V1);
rkcif_write_reg_and(cif, CIF_REG_MIPI_LVDS_CTRL,
~CSI_ENABLE_CAPTURE);
cif->state = RKCIF_STATE_READY;
}
return 0;
}
static int cif_interrupt_setup(struct vehicle_cif *cif)
{
rkcif_write_reg(cif, CIF_REG_DVP_INTEN,
FRAME_END_EN | INTSTAT_ERR |
PST_INF_FRAME_END);
/* enable line int for sof */
rkcif_write_reg(cif, CIF_REG_DVP_LINE_INT_NUM, 0x1);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, LINE_INT_EN);
return 0;
}
static void vehicle_cif_dvp_dump_regs(struct vehicle_cif *cif)
{
int val;
if (!vehicle_debug)
return;
val = rkcif_read_reg(cif, CIF_REG_DVP_CTRL);
VEHICLE_DG("CIF_REG_DVP_CTRL = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
VEHICLE_DG("CIF_REG_DVP_INTEN = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_INTSTAT);
VEHICLE_DG("CIF_REG_DVP_INTSTAT = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FOR);
VEHICLE_DG("CIF_REG_DVP_FOR = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_MULTI_ID);
VEHICLE_DG("CIF_REG_DVP_MULTI_ID = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LINE_NUM_ADDR);
VEHICLE_DG("CIF_REG_DVP_LINE_NUM_ADDR = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FRM0_ADDR_Y);
VEHICLE_DG("CIF_REG_DVP_FRM0_ADDR_Y = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FRM0_ADDR_UV);
VEHICLE_DG("CIF_REG_DVP_FRM0_ADDR_UV = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FRM1_ADDR_Y);
VEHICLE_DG("CIF_REG_DVP_FRM1_ADDR_Y = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FRM1_ADDR_UV);
VEHICLE_DG("CIF_REG_DVP_FRM1_ADDR_UV = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_VIR_LINE_WIDTH);
VEHICLE_DG("CIF_REG_DVP_VIR_LINE_WIDTH = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_SET_SIZE);
VEHICLE_DG("CIF_REG_DVP_SET_SIZE = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LINE_INT_NUM);
VEHICLE_DG("CIF_REG_DVP_LINE_INT_NUM = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LINE_CNT);
VEHICLE_DG("CIF_REG_DVP_LINE_CNT = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_CROP);
VEHICLE_DG("CIF_REG_DVP_CROP = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_SCL_CTRL);
VEHICLE_DG("CIF_REG_DVP_SCL_CTRL = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_FRAME_STATUS);
VEHICLE_DG("CIF_REG_DVP_FRAME_STATUS = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_CUR_DST);
VEHICLE_DG("CIF_REG_DVP_CUR_DST = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LAST_LINE);
VEHICLE_DG("CIF_REG_DVP_LAST_LINE = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LAST_PIX);
VEHICLE_DG("CIF_REG_DVP_LAST_PIX = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_SCL_VALID_NUM);
VEHICLE_DG("CIF_REG_DVP_SCL_VALID_NUM = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_DVP_LINE_NUM_ADDR);
VEHICLE_DG("CIF_REG_DVP_LINE_NUM_ADDR = 0X%x\r\n", val);
/* read dvp clk sample edge */
val = rkvehicle_cif_read_grf_reg(cif, CIF_REG_GRF_CIFIO_CON);
VEHICLE_DG("CIF_REG_GRF_CIFIO_CON = 0X%x\r\n", val);
}
static void vehicle_cif_csi2_dump_regs(struct vehicle_cif *cif)
{
int val = 0;
void __iomem *csi2_base = cif->csi2_base;
struct csi2_dphy_hw *hw = cif->dphy_hw;
if (!vehicle_debug)
return;
/* 1. dump csi2-dphy regs */
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588) {
VEHICLE_DG("\n\n DUMP CSI-DPHY REGS: \r\n");
read_csi2_dphy_reg(hw, CSI2PHY_REG_CTRL_LANE_ENABLE, &val);
VEHICLE_DG("CSI2PHY_REG_CTRL_LANE_ENABLE = 0x%x\r\n", val);
read_csi2_dphy_reg(hw, CSI2PHY_DUAL_CLK_EN, &val);
VEHICLE_DG("CSI2PHY_DUAL_CLK_EN = 0x%x\r\n", val);
val = csi2_dphy_read_grf_reg(hw, GRF_DPHY_CSI2PHY_FORCERXMODE);
VEHICLE_DG("GRF_DPHY_CSI2PHY_FORCERXMODE = 0x%x\r\n", val);
val = csi2_dphy_read_grf_reg(hw, GRF_DPHY_CSI2PHY_LANE_SEL);
VEHICLE_DG("GRF_DPHY_CSI2PHY_LANE_SEL = 0x%x\r\n", val);
val = csi2_dphy_read_grf_reg(hw, GRF_DPHY_CSI2PHY_DATALANE_EN);
VEHICLE_DG("GRF_DPHY_CSI2PHY_DATALANE_EN = 0x%x\r\n", val);
val = csi2_dphy_read_grf_reg(hw, GRF_DPHY_CSI2PHY_CLKLANE_EN);
VEHICLE_DG("GRF_DPHY_CSI2PHY_CLKLANE_EN = 0x%x\r\n", val);
}
/* 2. dump csi2 regs */
VEHICLE_DG("\n\n DUMP CSI2 REGS: \r\n");
val = vehicle_read_csihost_reg(csi2_base, CSIHOST_N_LANES);
VEHICLE_DG("CSIHOST_N_LANES = 0x%x\r\n", val);
val = vehicle_read_csihost_reg(csi2_base, CSIHOST_CONTROL);
VEHICLE_DG("CSIHOST_CONTROL = 0x%x\r\n", val);
val = vehicle_read_csihost_reg(csi2_base, CSIHOST_MSK1);
VEHICLE_DG("CSIHOST_MSK1 = 0x%x\r\n", val);
val = vehicle_read_csihost_reg(csi2_base, CSIHOST_MSK2);
VEHICLE_DG("CSIHOST_MSK2 = 0x%x\r\n", val);
val = vehicle_read_csihost_reg(csi2_base, CSIHOST_RESETN);
VEHICLE_DG("CSIHOST_RESETN = 0x%x\r\n", val);
/* 3. dump cif regs */
VEHICLE_DG("\n\n DUMP MIPI CIF REGS: \r\n");
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_CTRL);
VEHICLE_DG("CIF_REG_MIPI_LVDS_CTRL = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_INTEN);
VEHICLE_DG("CIF_REG_MIPI_LVDS_INTEN = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_INTSTAT);
VEHICLE_DG("CIF_REG_MIPI_LVDS_INTSTAT = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_ID0_CTRL0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_ID0_CTRL0 = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_ID0_CTRL1);
VEHICLE_DG("CIF_REG_MIPI_LVDS_ID0_CTRL1 = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1);
VEHICLE_DG("CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1 = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3);
VEHICLE_DG("CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3 = 0x%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME0_VLW_UV_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME1_VLW_Y_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME1_VLW_UV_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0);
VEHICLE_DG("CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0 = 0X%x\r\n", val);
val = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_ID0_CROP_START);
VEHICLE_DG("CIF_REG_MIPI_LVDS_ID0_CROP_START = 0X%x\r\n", val);
/* read dvp clk sample edge */
val = rkvehicle_cif_read_grf_reg(cif, CIF_REG_GRF_CIFIO_CON);
VEHICLE_DG("CIF_REG_GRF_CIFIO_CON = 0X%x\r\n", val);
}
static int vehicle_cif_s_stream(struct vehicle_cif *cif, int enable)
{
int cif_ctrl_val;
unsigned int dma_en = 0;
cif->is_enabled = enable;
VEHICLE_INFO("%s enable=%d\n", __func__, enable);
if (enable) {
cif->irqinfo.cifirq_idx = 0;
cif->irqinfo.cifirq_normal_idx = 0;
cif->irqinfo.cifirq_abnormal_idx = 0;
cif->irqinfo.dmairq_idx = 0;
cif->irqinfo.all_err_cnt = 0;
cif->irqinfo.dvp_bus_err_cnt = 0;
cif->irqinfo.dvp_overflow_cnt = 0;
cif->irqinfo.dvp_pix_err_cnt = 0;
cif->irqinfo.dvp_line_err_cnt = 0;
cif->irqinfo.dvp_size_err_cnt = 0;
cif->irqinfo.dvp_bwidth_lack_cnt = 0;
cif->irqinfo.csi_size_err_cnt = 0;
rkcif_write_reg(cif, CIF_REG_DVP_INTEN,
FRAME_END_EN | INTSTAT_ERR |
PST_INF_FRAME_END);
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
rkcif_write_reg(cif, CIF_REG_DVP_LINE_INT_NUM, 0x1);
rkcif_write_reg_or(cif, CIF_REG_DVP_INTEN, 0x033ffff);
}
dma_en = DVP_DMA_EN;
if (cif->chip_id < CHIP_RK3588_VEHICLE_CIF) {
rkcif_write_reg(cif, CIF_REG_DVP_CTRL,
AXI_BURST_16 | MODE_PINGPONG | ENABLE_CAPTURE);
} else if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
rkcif_write_reg(cif, CIF_REG_DVP_CTRL,
DVP_SW_WATER_LINE_25
| dma_en
| DVP_PRESS_EN
| DVP_HURRY_EN
| DVP_SW_WATER_LINE_25
| DVP_SW_PRESS_VALUE(3)
| DVP_SW_HURRY_VALUE(3)
| ENABLE_CAPTURE);
} else {
dma_en = DVP_SW_DMA_EN_RK3676(0);
rkcif_write_reg(cif, CIF_REG_DVP_CTRL,
DVP_SW_WATER_LINE_25_RK3576
| DVP_SW_CAP_EN_RK3576(0)
| dma_en
| ENABLE_CAPTURE);
}
cif->frame_idx = 0;
cif->state = RKCIF_STATE_STREAMING;
} else {
cif_ctrl_val = rkcif_read_reg(cif, CIF_REG_DVP_CTRL);
cif_ctrl_val &= ~ENABLE_CAPTURE;
rkcif_write_reg(cif, CIF_REG_DVP_CTRL, cif_ctrl_val);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, 0);
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, 0x3ff);
rkcif_write_reg(cif, CIF_REG_DVP_FRAME_STATUS, 0x0);
cif->state = RKCIF_STATE_READY;
}
return 0;
}
static int vehicle_cif_create_dummy_buf(struct vehicle_cif *cif)
{
struct vehicle_rkcif_dummy_buffer *dummy_buf = &cif->dummy_buf;
struct vehicle_cfg *cfg = &cif->cif_cfg;
/* get a maximum plane size */
dummy_buf->size = cfg->width * cfg->height * 2;
dummy_buf->vaddr = dma_alloc_coherent(cif->dev, dummy_buf->size,
&dummy_buf->dma_addr,
GFP_KERNEL);
if (!dummy_buf->vaddr) {
VEHICLE_DGERR("Failed to allocate the memory for dummy buffer\n");
return -ENOMEM;
}
VEHICLE_INFO("Allocate dummy buffer, size: 0x%08x\n", dummy_buf->size);
return 0;
}
static void vehicle_cif_destroy_dummy_buf(struct vehicle_cif *cif)
{
struct vehicle_rkcif_dummy_buffer *dummy_buf = &cif->dummy_buf;
VEHICLE_INFO("Destroy dummy buffer, size: 0x%08x\n", dummy_buf->size);
if (dummy_buf->vaddr)
dma_free_coherent(cif->dev, dummy_buf->size,
dummy_buf->vaddr, dummy_buf->dma_addr);
dummy_buf->dma_addr = 0;
dummy_buf->vaddr = NULL;
}
static void vehicle_cif_hw_soft_reset(struct vehicle_cif *cif)
{
unsigned int i;
struct rk_cif_clk *clk = &cif->clk;
for (i = 0; i < clk->rsts_num; i++)
if (clk->cif_rst[i])
reset_control_assert(clk->cif_rst[i]);
udelay(10);
for (i = 0; i < clk->rsts_num; i++)
if (clk->cif_rst[i])
reset_control_deassert(clk->cif_rst[i]);
}
static void vehicle_rkcif_do_soft_reset(struct vehicle_cif *cif)
{
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY)
rkcif_write_reg_or(cif, CIF_REG_MIPI_LVDS_CTRL, 0x000A0000);
else
rkcif_write_reg_or(cif, CIF_REG_DVP_CTRL, 0x000A0000);
usleep_range(10, 20);
VEHICLE_INFO("vicap do soft reset 0x%x\n", 0x000A0000);
}
static int vehicle_cif_do_stop_stream(struct vehicle_cif *cif)
{
if (!cif)
return -1;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF) {
vehicle_cif_csi2_s_stream_v1(cif, 0, V4L2_MBUS_CSI2_DPHY);
vehicle_cif_csi_stream_stop(cif);
} else {
vehicle_cif_csi2_s_stream(cif, 0, V4L2_MBUS_CSI2_DPHY);
vehicle_cif_csi_stream_stop(cif);
}
} else {
vehicle_cif_s_stream(cif, 0);
}
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF)
vehicle_rkcif_do_soft_reset(cif);
vehicle_cif_destroy_dummy_buf(cif);
return 0;
}
static int vehicle_cif_do_start_stream(struct vehicle_cif *cif)
{
int ret = 0;
if (!cif)
return -ENODEV;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
/* 1. stream setup */
cif_csi_stream_setup(cif);
/* 2. create dummy buf */
ret = vehicle_cif_create_dummy_buf(cif);
if (ret < 0)
VEHICLE_DGERR("Failed to create dummy_buf, %d\n", ret);
/* 3. cif init buffer */
if (vehicle_cif_init_buffer(cif, 1, cif->channels[0].id) < 0)
return -EINVAL;
/* 4. dump cif regs */
vehicle_cif_csi2_dump_regs(cif);
/* 5. start stream */
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF)
vehicle_cif_csi2_s_stream_v1(cif, 1, V4L2_MBUS_CSI2_DPHY);
else
vehicle_cif_csi2_s_stream(cif, 1, V4L2_MBUS_CSI2_DPHY);
} else {
/* 1. stream setup */
cif_stream_setup(cif);
/* 2. create dummy buf */
ret = vehicle_cif_create_dummy_buf(cif);
if (ret < 0)
VEHICLE_DGERR("Failed to create dummy_buf, %d\n", ret);
/* 3. cif init buffer */
if (vehicle_cif_init_buffer(cif, 1, 0) < 0)
return -EINVAL;
/* 4. enable interrupts */
if (cif->chip_id < CHIP_RK3588_VEHICLE_CIF)
cif_interrupt_setup(cif);
/* 5. dump cif regs */
vehicle_cif_dvp_dump_regs(cif);
/* 6. start stream */
vehicle_cif_s_stream(cif, 1);
}
return 0;
}
static void vehicle_rkcif_disable_sys_clk(struct rk_cif_clk *clk);
static int vehicle_rkcif_enable_sys_clk(struct rk_cif_clk *clk);
static void vehicle_cif_reset(struct vehicle_cif *cif, int only_rst)
{
int ret = 0;
mutex_lock(&cif->stream_lock);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
VEHICLE_DG("%s enter, V4L2_MBUS_CSI2 reset need to do!\n", __func__);
// goto unlock_reset;
if (only_rst == 1) {
vehicle_cif_hw_soft_reset(cif);
} else {
vehicle_cif_do_stop_stream(cif);
vehicle_cif_hw_soft_reset(cif);
vehicle_cif_do_start_stream(cif);
}
} else {
int ctrl_reg, inten_reg, crop_reg, set_size_reg, for_reg;
int vir_line_width_reg, scl_reg;
int y0_reg, uv0_reg, y1_reg, uv1_reg;
VEHICLE_DG("%s enter, do reset!\n", __func__);
if (only_rst == 1) {
vehicle_cif_hw_soft_reset(cif);
} else {
ctrl_reg = rkcif_read_reg(cif, CIF_REG_DVP_CTRL);
if (ctrl_reg & ENABLE_CAPTURE)
rkcif_write_reg(cif, CIF_REG_DVP_CTRL,
ctrl_reg & ~ENABLE_CAPTURE);
crop_reg = rkcif_read_reg(cif, CIF_REG_DVP_CROP);
set_size_reg = rkcif_read_reg(cif, CIF_REG_DVP_SET_SIZE);
inten_reg = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
for_reg = rkcif_read_reg(cif, CIF_REG_DVP_FOR);
vir_line_width_reg = rkcif_read_reg(cif,
CIF_REG_DVP_VIR_LINE_WIDTH);
scl_reg = rkcif_read_reg(cif, CIF_REG_DVP_SCL_CTRL);
y0_reg = rkcif_read_reg(cif, CIF_REG_DVP_FRM0_ADDR_Y);
uv0_reg = rkcif_read_reg(cif, CIF_REG_DVP_FRM0_ADDR_UV);
y1_reg = rkcif_read_reg(cif, CIF_REG_DVP_FRM1_ADDR_Y);
uv1_reg = rkcif_read_reg(cif, CIF_REG_DVP_FRM1_ADDR_UV);
udelay(20);
vehicle_cif_hw_soft_reset(cif);
vehicle_rkcif_disable_sys_clk(&cif->clk);
udelay(5);
ret = vehicle_rkcif_enable_sys_clk(&cif->clk);
if (ret < 0) {
VEHICLE_DGERR("@%s, resume cif clk failed!\n", __func__);
goto unlock_reset;
}
rkcif_write_reg(cif, CIF_REG_DVP_CTRL,
ctrl_reg & ~ENABLE_CAPTURE);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, inten_reg);
rkcif_write_reg(cif, CIF_REG_DVP_CROP, crop_reg);
rkcif_write_reg(cif, CIF_REG_DVP_SET_SIZE, set_size_reg);
rkcif_write_reg(cif, CIF_REG_DVP_FOR, for_reg);
rkcif_write_reg(cif, CIF_REG_DVP_VIR_LINE_WIDTH,
vir_line_width_reg);
rkcif_write_reg(cif, CIF_REG_DVP_SCL_CTRL, scl_reg);
rkcif_write_reg(cif, CIF_REG_DVP_FRM0_ADDR_Y, y0_reg);
rkcif_write_reg(cif, CIF_REG_DVP_FRM0_ADDR_UV, uv0_reg);
rkcif_write_reg(cif, CIF_REG_DVP_FRM1_ADDR_Y, y1_reg);
rkcif_write_reg(cif, CIF_REG_DVP_FRM1_ADDR_UV, uv1_reg);
}
}
unlock_reset:
mutex_unlock(&cif->stream_lock);
}
static void vehicle_cif_reset_delay(struct vehicle_cif *cif)
{
mdelay(10);
vehicle_cif_reset(cif, 0);
mdelay(10);
vehicle_cif_s_stream(cif, 1);
}
static void cif_capture_en(char *reg, int enable)
{
int val = 0;
val = read_reg(reg, CIF_REG_DVP_CTRL);
if (enable == 1)
write_reg(reg, CIF_REG_DVP_CTRL, val | ENABLE_CAPTURE);
else
write_reg(reg, CIF_REG_DVP_CTRL, val & (~ENABLE_CAPTURE));
}
static void vehicle_cif_reset_work_func(struct work_struct *work)
{
struct vehicle_cif *cif = container_of(work, struct vehicle_cif,
work.work);
if (cif->stopping)
return;
atomic_set(&cif->reset_status, 1);
vehicle_cif_reset_delay(cif);
atomic_set(&cif->reset_status, 0);
wake_up(&cif->wq_stopped);
}
int vehicle_wait_cif_reset_done(void)
{
struct vehicle_cif *cif = g_cif;
int ret = 0, retry = 2;
for (retry = 2; retry >= 0; retry--) {
ret = wait_event_timeout(cif->wq_stopped,
!atomic_read(&cif->reset_status),
msecs_to_jiffies(200));
if (!ret) {
VEHICLE_DG("%s wait cif reset timeout, left try times(%d)!\n",
__func__, retry);
} else {
break;
}
}
return 0;
}
static int cif_irq_error_process(struct vehicle_cif *cif, unsigned int reg_intstat)
{
VEHICLE_DG("%s cif->irqinfo.all_err_cnt(%lld)\n", __func__,
cif->irqinfo.all_err_cnt);
if (reg_intstat & INTSTAT_ERR) {
cif->irqinfo.all_err_cnt++;
if (reg_intstat & BUS_ERR) {
cif->irqinfo.dvp_bus_err_cnt++;
VEHICLE_DGERR("dvp bus err\n");
}
if (reg_intstat & DVP_ALL_OVERFLOW) {
cif->irqinfo.dvp_overflow_cnt++;
VEHICLE_DGERR("dvp overflow err\n");
}
if (reg_intstat & LINE_ERR) {
cif->irqinfo.dvp_line_err_cnt++;
VEHICLE_DGERR("dvp line err\n");
}
if (reg_intstat & PIX_ERR) {
cif->irqinfo.dvp_pix_err_cnt++;
VEHICLE_DGERR("dvp pix err\n");
}
if (cif->irqinfo.all_err_cnt < 10) {
u32 mask;
VEHICLE_DGERR("ERROR: DVP_ALL_ERROR:0x%x!!\n", reg_intstat);
mask = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
mask &= ~INTSTAT_ERR;
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, mask);
return -2;
} else if (cif->irqinfo.all_err_cnt >= 10) {
u32 mask;
mask = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
mask &= ~INTSTAT_ERR;
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, mask);
VEHICLE_DGERR("ERROR: DVP_ALL_ERROR:0x%x!!\n", reg_intstat);
return -2;
}
}
return 0;
}
static int vehicle_cif_csi2_g_mipi_id(unsigned int intstat)
{
if (intstat & CSI_FRAME_END_ID0) {
if ((intstat & CSI_FRAME_END_ID0) == CSI_FRAME_END_ID0)
VEHICLE_DG("frame0/1 trigger simultaneously in ID0\n");
return RKCIF_STREAM_MIPI_ID0;
}
if (intstat & CSI_FRAME_END_ID1) {
if ((intstat & CSI_FRAME_END_ID1) == CSI_FRAME_END_ID1)
VEHICLE_DG("frame0/1 trigger simultaneously in ID1\n");
return RKCIF_STREAM_MIPI_ID1;
}
if (intstat & CSI_FRAME_END_ID2) {
if ((intstat & CSI_FRAME_END_ID2) == CSI_FRAME_END_ID2)
VEHICLE_DG("frame0/1 trigger simultaneously in ID2\n");
return RKCIF_STREAM_MIPI_ID2;
}
if (intstat & CSI_FRAME_END_ID3) {
if ((intstat & CSI_FRAME_END_ID3) == CSI_FRAME_END_ID3)
VEHICLE_DG("frame0/1 trigger simultaneously in ID3\n");
return RKCIF_STREAM_MIPI_ID3;
}
return -EINVAL;
}
static __maybe_unused int rkcif_dvp_g_ch_id_by_fe(unsigned int intstat)
{
if (intstat & DVP_ALL_END_ID0) {
if ((intstat & DVP_ALL_END_ID0) ==
DVP_ALL_END_ID0)
VEHICLE_DG("frame0/1 trigger simultaneously in DVP ID0\n");
return RKCIF_STREAM_MIPI_ID0;
}
if (intstat & DVP_ALL_END_ID1) {
if ((intstat & DVP_ALL_END_ID1) ==
DVP_ALL_END_ID1)
VEHICLE_DG("frame0/1 trigger simultaneously in DVP ID1\n");
return RKCIF_STREAM_MIPI_ID1;
}
if (intstat & DVP_ALL_END_ID2) {
if ((intstat & DVP_ALL_END_ID2) ==
DVP_ALL_END_ID2)
VEHICLE_DG("frame0/1 trigger simultaneously in DVP ID2\n");
return RKCIF_STREAM_MIPI_ID2;
}
if (intstat & DVP_ALL_END_ID3) {
if ((intstat & DVP_ALL_END_ID3) ==
DVP_ALL_END_ID3)
VEHICLE_DG("frame0/1 trigger simultaneously in DVP ID3\n");
return RKCIF_STREAM_MIPI_ID3;
}
return -EINVAL;
}
static int vehicle_cif_next_buffer(struct vehicle_cif *cif, u32 frame_ready, int mipi_id)
{
u32 frm0_addr_y, frm0_addr_uv;
u32 frm1_addr_y, frm1_addr_uv;
unsigned long y_addr = 0, uv_addr = 0;
static unsigned long temp_y_addr, temp_uv_addr;
int commit_buf = 0;
struct vehicle_rkcif_dummy_buffer *dummy_buf = &cif->dummy_buf;
u32 frm_num_reg, frame_id = 0;
VEHICLE_DG("@%s, enter, mipi_id(%d)\n", __func__, mipi_id);
if ((frame_ready > 1) || (cif->cif_cfg.buf_num < 2) ||
(cif->cif_cfg.buf_num > MAX_BUF_NUM))
return 0;
cif->last_buf_index = cif->current_buf_index;
cif->current_buf_index = (cif->current_buf_index + 1) %
cif->cif_cfg.buf_num;
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
frm0_addr_y = get_reg_index_of_frm0_y_addr(mipi_id);
frm0_addr_uv = get_reg_index_of_frm0_uv_addr(mipi_id);
frm1_addr_y = get_reg_index_of_frm1_y_addr(mipi_id);
frm1_addr_uv = get_reg_index_of_frm1_uv_addr(mipi_id);
frm_num_reg = get_reg_index_of_frm_num(mipi_id);
frame_id = rkcif_read_reg(cif, frm_num_reg);
VEHICLE_DG("@%s, frm_num_reg(0x%x), frame_id:0x%x\n", __func__,
frm_num_reg, frame_id);
} else {
frm0_addr_y = get_dvp_reg_index_of_frm0_y_addr(mipi_id);
frm0_addr_uv = get_dvp_reg_index_of_frm0_uv_addr(mipi_id);
frm1_addr_y = get_dvp_reg_index_of_frm1_y_addr(mipi_id);
frm1_addr_uv = get_dvp_reg_index_of_frm1_uv_addr(mipi_id);
}
spin_lock(&cif->vbq_lock);
if (!cif->interlaced_enable || cif->use_hw_interlace) {
temp_y_addr = vehicle_flinger_request_cif_buffer();
if (temp_y_addr == 0) {
VEHICLE_INFO("%s,warnning request buffer failed\n", __func__);
spin_unlock(&cif->vbq_lock);
if (dummy_buf->vaddr) {
if (frame_ready == 0) {
rkcif_write_reg(cif, frm0_addr_y, dummy_buf->dma_addr);
rkcif_write_reg(cif, frm0_addr_uv, dummy_buf->dma_addr);
} else {
rkcif_write_reg(cif, frm1_addr_y, dummy_buf->dma_addr);
rkcif_write_reg(cif, frm1_addr_uv, dummy_buf->dma_addr);
}
VEHICLE_INFO("frame Drop to dummy buf\n");
} else {
VEHICLE_INFO("dummy buf is null!\n");
}
return -1;
}
temp_uv_addr = temp_y_addr + UV_OFFSET;
y_addr = temp_y_addr;
uv_addr = temp_uv_addr;
commit_buf = 0;
} else if (cif->interlaced_enable && !cif->use_hw_interlace) {
if ((frame_id != 0 && (frame_id & 0xffff) % 2 == 0) ||
(frame_id == 0 && (cif->interlaced_counts % 2 == 0))) {
temp_y_addr = vehicle_flinger_request_cif_buffer();
if (temp_y_addr == 0) {
VEHICLE_DGERR("%s,warnning request buffer failed\n", __func__);
spin_unlock(&cif->vbq_lock);
return -1;
}
temp_uv_addr = temp_y_addr + UV_OFFSET;
y_addr = temp_y_addr;
uv_addr = temp_uv_addr;
commit_buf = -1; //not ok yet
} else {
y_addr = temp_y_addr + cif->interlaced_offset;
//uv_addr = temp_uv_addr;
uv_addr = temp_uv_addr + cif->interlaced_offset;
commit_buf = 0; //even & odd field add
if (temp_y_addr == 0) {
VEHICLE_DGERR("%s,warnning temp_y_addr is NULL!\n", __func__);
spin_unlock(&cif->vbq_lock);
return -1;
}
}
WARN_ON(y_addr == cif->interlaced_offset);
WARN_ON(uv_addr == cif->interlaced_offset);
}
if (frame_ready == 0) {
rkcif_write_reg(cif, frm0_addr_y, y_addr);
rkcif_write_reg(cif, frm0_addr_uv, uv_addr);
cif->active[0] = temp_y_addr;
} else {
rkcif_write_reg(cif, frm1_addr_y, y_addr);
rkcif_write_reg(cif, frm1_addr_uv, uv_addr);
cif->active[1] = temp_y_addr;
}
cif->interlaced_counts++;
spin_unlock(&cif->vbq_lock);
return commit_buf;
}
/***************************** irq operation ******************************/
//discard the first few frames to solve display abnormality after different model camera switch
static int drop_frames_number;
static irqreturn_t rk_camera_irq(int irq, void *data)
{
struct vehicle_cif *cif = (struct vehicle_cif *)data;
u32 lastline, lastpix, ctl;
u32 cif_frmst, frmid, int_en;
unsigned int intstat, i = 0xff;
int frame_ready = 0;
int frame_phase = 0;
unsigned long addr;
int mipi_id = 0;
if (drop_frames_number > 0) {
VEHICLE_INFO("%s discard the first few frames!\n", __func__);
drop_frames_number--;
goto IRQ_EXIT;
}
VEHICLE_DG("%s enter, cifirq_normal_idx(%ld) cif->frame_idx(%d)!\n", __func__,
cif->irqinfo.cifirq_normal_idx, cif->frame_idx);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
if (!cif->stopping) {
if (cif->irqinfo.cifirq_normal_idx == cif->frame_idx) {
cif->irqinfo.cifirq_abnormal_idx++;
} else {
cif->irqinfo.cifirq_normal_idx = cif->frame_idx;
cif->irqinfo.cifirq_abnormal_idx = 0;
}
}
intstat = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_INTSTAT);
lastline = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1);
/* clear all interrupts that has been triggered */
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_INTSTAT, intstat);
/* when not detect new FRAME_END continue over 5 irq, reset, it's abnormal */
if (cif->irqinfo.cifirq_abnormal_idx >= 5) {
VEHICLE_DGERR(
"ERROR: cifirq_abnormal_idx reach(%ld) consecutive, do reset work!!\n",
cif->irqinfo.cifirq_abnormal_idx);
// mod_delayed_work(system_wq, &cif->work,
// msecs_to_jiffies(1));
cif->irqinfo.cifirq_abnormal_idx = 0;
vehicle_cif_stat_change_notify();
goto IRQ_EXIT;
}
if (intstat & CSI_FIFO_OVERFLOW) {
cif->irqinfo.csi_overflow_cnt++;
VEHICLE_DGERR(
"ERROR: csi fifo overflow, intstat:0x%x, lastline:%d!!\n",
intstat, lastline);
goto IRQ_EXIT;
}
if (intstat & CSI_BANDWIDTH_LACK) {
cif->irqinfo.csi_bwidth_lack_cnt++;
VEHICLE_DGERR(
"ERROR: csi bandwidth lack, intstat:0x%x!!\n",
intstat);
if (cif->irqinfo.csi_bwidth_lack_cnt >= 5) {
//do reset work
// mod_delayed_work(system_wq, &cif->work,
// msecs_to_jiffies(1));
}
goto IRQ_EXIT;
}
if (intstat & CSI_ALL_ERROR_INTEN) {
cif->irqinfo.all_err_cnt++;
VEHICLE_DGERR(
"ERROR: CSI_ALL_ERROR_INTEN:0x%x!!\n", intstat);
goto IRQ_EXIT;
}
/* if do not reach frame dma end, return irq */
mipi_id = vehicle_cif_csi2_g_mipi_id(intstat);
if (mipi_id < 0)
goto IRQ_EXIT;
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
mipi_id = vehicle_cif_csi2_g_mipi_id(intstat);
VEHICLE_DG(" i(%d) mipi_id(%d)\n", i, mipi_id);
if (mipi_id < 0)
continue;
if (cif->stopping) {
vehicle_cif_csi2_s_stream(cif, 0, V4L2_MBUS_CSI2_DPHY);
cif->stopping = false;
wake_up(&cif->wq_stopped);
continue;
}
if (cif->state != RKCIF_STATE_STREAMING)
continue;
switch (mipi_id) {
case RKCIF_STREAM_MIPI_ID0:
frame_phase = SW_FRM_END_ID0(intstat);
intstat &= ~CSI_FRAME_END_ID0;
break;
case RKCIF_STREAM_MIPI_ID1:
frame_phase = SW_FRM_END_ID1(intstat);
intstat &= ~CSI_FRAME_END_ID1;
break;
case RKCIF_STREAM_MIPI_ID2:
frame_phase = SW_FRM_END_ID2(intstat);
intstat &= ~CSI_FRAME_END_ID2;
break;
case RKCIF_STREAM_MIPI_ID3:
frame_phase = SW_FRM_END_ID3(intstat);
intstat &= ~CSI_FRAME_END_ID3;
break;
}
if (frame_phase & CIF_CSI_FRAME1_READY)
frame_ready = 1;
else if (frame_phase & CIF_CSI_FRAME0_READY)
frame_ready = 0;
addr = cif->active[frame_ready];
if (vehicle_cif_next_buffer(cif, frame_ready, mipi_id) < 0)
VEHICLE_DG("cif_nex_buffer error, do not commit %lx\n", addr);
else
vehicle_flinger_commit_cif_buffer(addr);
}
cif->frame_idx++;
} else {
intstat = rkcif_read_reg(cif, CIF_REG_DVP_INTSTAT);
cif_frmst = rkcif_read_reg(cif, CIF_REG_DVP_FRAME_STATUS);
lastline = rkcif_read_reg(cif, CIF_REG_DVP_LAST_LINE);
lastline = CIF_FETCH_Y_LAST_LINE(lastline);
lastpix = rkcif_read_reg(cif, CIF_REG_DVP_LAST_PIX);
lastpix = CIF_FETCH_Y_LAST_LINE(lastpix);
ctl = rkcif_read_reg(cif, CIF_REG_DVP_CTRL);
VEHICLE_DG("lastline:%d, lastpix:%d, ctl:%d\n",
lastline, lastpix, ctl);
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, intstat);
if ((intstat & LINE_INT_END) && !(intstat & (FRAME_END))) {
if ((intstat & (PRE_INF_FRAME_END | PST_INF_FRAME_END)) == 0x0) {
if ((intstat & INTSTAT_ERR) == 0x0) {
int_en = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
int_en &= ~LINE_INT_EN;
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, int_en);
}
}
}
/* 0. error process */
if (cif_irq_error_process(cif, intstat) < 0) {
VEHICLE_DGERR("irq error, to do... reset, intstat=%x\n", intstat);
// mod_delayed_work(system_wq, &cif->work,
// msecs_to_jiffies(1));
vehicle_cif_stat_change_notify();
goto IRQ_EXIT;
}
/* There are two irqs enabled:
* - PST_INF_FRAME_END: cif FIFO is ready,
* this is prior to FRAME_END
* - FRAME_END: cif has saved frame to memory,
* a frame ready
*/
if ((intstat & PST_INF_FRAME_END)) {
cif->irqinfo.cifirq_idx++;
if (cif->stopping) {
/* To stop CIF ASAP, before FRAME_END irq */
vehicle_cif_s_stream(cif, 0);
cif->stopping = false;
wake_up(&cif->wq_stopped);
goto IRQ_EXIT;
}
}
if ((intstat & FRAME_END)) {
int_en = rkcif_read_reg(cif, CIF_REG_DVP_INTEN);
int_en |= LINE_INT_EN;
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, int_en);
if (cif->stopping) {
vehicle_cif_s_stream(cif, 0);
cif->stopping = false;
wake_up(&cif->wq_stopped);
goto IRQ_EXIT;
}
frmid = CIF_GET_FRAME_ID(cif_frmst);
if ((cif_frmst == 0xfffd0002) || (cif_frmst == 0xfffe0002)) {
VEHICLE_DG("frmid:%d, frmstat:0x%x\n",
frmid, cif_frmst);
rkcif_write_reg(cif, CIF_REG_DVP_FRAME_STATUS,
FRAME_STAT_CLS);
}
if ((!(cif_frmst & CIF_F0_READY) && !(cif_frmst & CIF_F1_READY))) {
VEHICLE_DG("err f0 && f1 not ready\n");
cif_capture_en(cif->base, 0);
rkcif_write_reg(cif, CIF_REG_DVP_INTEN, 0);
mod_delayed_work(system_wq, &cif->work,
msecs_to_jiffies(1));
goto IRQ_EXIT;
}
if (cif_frmst & CIF_F0_READY)
frame_ready = 0;
else
frame_ready = 1;
addr = cif->active[frame_ready];
if (vehicle_cif_next_buffer(cif, frame_ready, mipi_id) < 0)
CIF_DG("cif_nex_buffer error, do not commit %lx\n", addr);
else
vehicle_flinger_commit_cif_buffer(addr);
cif->frame_idx++;
}
}
cif->irqinfo.all_frm_end_cnt++;
IRQ_EXIT:
return IRQ_HANDLED;
}
static irqreturn_t rk_camera_irq_v1(int irq, void *data)
{
struct vehicle_cif *cif = (struct vehicle_cif *)data;
u32 lastline;
unsigned int intstat, i = 0xff, bak_intstat = 0;
int frame_ready = 0;
int frame_phase = 0;
unsigned long addr;
int mipi_id = 0;
if (drop_frames_number > 0) {
VEHICLE_INFO("%s discard the first few frames!\n", __func__);
drop_frames_number--;
goto IRQ_EXIT;
}
VEHICLE_DG("%s enter, cifirq_normal_idx(%ld) cif->frame_idx(%d)!\n", __func__,
cif->irqinfo.cifirq_normal_idx, cif->frame_idx);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
if (!cif->stopping) {
if (cif->irqinfo.cifirq_normal_idx == cif->frame_idx) {
cif->irqinfo.cifirq_abnormal_idx++;
} else {
cif->irqinfo.cifirq_normal_idx = cif->frame_idx;
cif->irqinfo.cifirq_abnormal_idx = 0;
}
}
intstat = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_INTSTAT);
lastline = rkcif_read_reg(cif, CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1);
/* clear all interrupts that has been triggered */
if (intstat) {
bak_intstat = intstat;
VEHICLE_DG("%s bak_intstat = %d!\n", __func__, bak_intstat);
rkcif_write_reg(cif, CIF_REG_MIPI_LVDS_INTSTAT, intstat);
} else {
goto IRQ_EXIT;
}
/* when not detect new FRAME_END continue over 5 irq, reset, it's abnormal */
if (cif->irqinfo.cifirq_abnormal_idx >= 5) {
VEHICLE_DGERR(
"ERROR: cifirq_abnormal_idx reach(%ld) consecutive, do reset work!!\n",
cif->irqinfo.cifirq_abnormal_idx);
cif->irqinfo.cifirq_abnormal_idx = 0;
vehicle_cif_stat_change_notify();
goto IRQ_EXIT;
}
if (intstat & CSI_SIZE_ERR) {
cif->irqinfo.csi_size_err_cnt++;
VEHICLE_DGERR("ERROR: csi size error, intstat:0x%x, lastline:%d!!\n",
intstat, lastline);
goto IRQ_EXIT;
}
if (intstat & CSI_FIFO_OVERFLOW_V1) {
cif->irqinfo.csi_overflow_cnt++;
VEHICLE_DGERR("ERROR: csi fifo overflow, intstat:0x%x, lastline:%d!!\n",
intstat, lastline);
goto IRQ_EXIT;
}
if (intstat & CSI_BANDWIDTH_LACK_V1) {
cif->irqinfo.csi_bwidth_lack_cnt++;
VEHICLE_DGERR("ERROR: csi bandwidth lack, intstat:0x%x!!\n",
intstat);
goto IRQ_EXIT;
}
if (intstat & CSI_ALL_ERROR_INTEN_V1) {
cif->irqinfo.all_err_cnt++;
VEHICLE_DGERR("ERROR: CSI_ALL_ERROR_INTEN:0x%x!!\n", intstat);
goto IRQ_EXIT;
}
/* if do not reach frame dma end, return irq */
mipi_id = vehicle_cif_csi2_g_mipi_id(intstat);
if (mipi_id < 0)
goto IRQ_EXIT;
for (i = 0; i < RKCIF_MAX_STREAM_MIPI; i++) {
mipi_id = vehicle_cif_csi2_g_mipi_id(intstat);
VEHICLE_DG(" i(%d) mipi_id(%d)\n", i, mipi_id);
if (mipi_id < 0)
continue;
if (cif->stopping) {
vehicle_cif_csi2_s_stream_v1(cif, 0, V4L2_MBUS_CSI2_DPHY);
cif->stopping = false;
wake_up(&cif->wq_stopped);
continue;
}
if (cif->state != RKCIF_STATE_STREAMING)
continue;
switch (mipi_id) {
case RKCIF_STREAM_MIPI_ID0:
frame_phase = SW_FRM_END_ID0(intstat);
intstat &= ~CSI_FRAME_END_ID0;
break;
case RKCIF_STREAM_MIPI_ID1:
frame_phase = SW_FRM_END_ID1(intstat);
intstat &= ~CSI_FRAME_END_ID1;
break;
case RKCIF_STREAM_MIPI_ID2:
frame_phase = SW_FRM_END_ID2(intstat);
intstat &= ~CSI_FRAME_END_ID2;
break;
case RKCIF_STREAM_MIPI_ID3:
frame_phase = SW_FRM_END_ID3(intstat);
intstat &= ~CSI_FRAME_END_ID3;
break;
}
if (frame_phase & CIF_CSI_FRAME1_READY)
frame_ready = 1;
else if (frame_phase & CIF_CSI_FRAME0_READY)
frame_ready = 0;
addr = cif->active[frame_ready];
if (vehicle_cif_next_buffer(cif, frame_ready, mipi_id) < 0)
VEHICLE_DGERR("cif_nex_buffer error, do not commit %lx\n", addr);
else
vehicle_flinger_commit_cif_buffer(addr);
}
cif->frame_idx++;
} else {
int ch_id;
intstat = rkcif_read_reg(cif, CIF_REG_DVP_INTSTAT);
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, intstat);
if (intstat & DVP_SIZE_ERR) {
cif->irqinfo.dvp_size_err_cnt++;
VEHICLE_DGERR("dvp size err intstat 0x%x\n", intstat);
}
if (intstat & DVP_FIFO_OVERFLOW) {
cif->irqinfo.dvp_overflow_cnt++;
VEHICLE_DGERR("dvp fifo overflow err intstat 0x%x\n", intstat);
}
if (intstat & DVP_BANDWIDTH_LACK) {
cif->irqinfo.dvp_bwidth_lack_cnt++;
VEHICLE_DGERR("dvp bandwidth lack err intstat 0x%x\n", intstat);
}
if (intstat & INTSTAT_ERR_RK3588) {
cif->irqinfo.all_err_cnt++;
VEHICLE_DGERR("ERROR: DVP_ALL_ERROR_INTEN:0x%x!!\n", intstat);
}
for (i = 0; i < RKCIF_MAX_STREAM_DVP; i++) {
ch_id = rkcif_dvp_g_ch_id_by_fe(intstat);
if (ch_id < 0)
continue;
if (cif->stopping) {
vehicle_cif_s_stream(cif, 0);
cif->stopping = false;
wake_up(&cif->wq_stopped);
continue;
}
if (cif->state != RKCIF_STATE_STREAMING)
continue;
switch (ch_id) {
case RKCIF_STREAM_MIPI_ID0:
frame_phase = SW_FRM_END_ID0(intstat);
intstat &= ~DVP_ALL_END_ID0;
break;
case RKCIF_STREAM_MIPI_ID1:
frame_phase = SW_FRM_END_ID1(intstat);
intstat &= ~DVP_ALL_END_ID1;
break;
case RKCIF_STREAM_MIPI_ID2:
frame_phase = SW_FRM_END_ID2(intstat);
intstat &= ~DVP_ALL_END_ID2;
break;
case RKCIF_STREAM_MIPI_ID3:
frame_phase = SW_FRM_END_ID3(intstat);
intstat &= ~DVP_ALL_END_ID3;
break;
}
if (frame_phase & CIF_F0_READY)
frame_ready = 0;
else
frame_ready = 1;
addr = cif->active[frame_ready];
if (vehicle_cif_next_buffer(cif, frame_ready, ch_id) < 0)
VEHICLE_DGERR("cif_nex_buffer error, do not commit %lx\n", addr);
else
vehicle_flinger_commit_cif_buffer(addr);
cif->frame_idx++;
}
}
cif->irqinfo.all_frm_end_cnt++;
IRQ_EXIT:
return IRQ_HANDLED;
}
#define vehicle_csi2_err_strncat(dst_str, src_str) {\
if (strlen(dst_str) + strlen(src_str) < CSI_ERRSTR_LEN)\
strncat(dst_str, src_str, strlen(src_str)); }
static void vehicle_csi2_find_err_vc(int val, char *vc_info)
{
int i;
char cur_str[CSI_VCINFO_LEN] = {0};
memset(vc_info, 0, sizeof(*vc_info));
for (i = 0; i < 4; i++) {
if ((val >> i) & 0x1) {
snprintf(cur_str, CSI_VCINFO_LEN, " %d", i);
if (strlen(vc_info) + strlen(cur_str) < CSI_VCINFO_LEN)
strncat(vc_info, cur_str, strlen(cur_str));
}
}
}
static void vehicle_csi2_err_print_work(struct work_struct *work)
{
struct vehicle_csi2_err_state_work *err_state = container_of(work,
struct vehicle_csi2_err_state_work,
work);
pr_err("mipi_csi2: ERR%d:0x%x %s\n", err_state->err_num,
err_state->err_val, err_state->err_str);
if (err_state->err_num == 1)
pr_info("mipi_csi2: err_stat:0x%lx\n", err_state->err_stat);
}
static irqreturn_t vehicle_csirx_irq1(int irq, void *data)
{
struct vehicle_cif *cif = (struct vehicle_cif *)data;
struct csi2_dphy_hw *hw = cif->dphy_hw;
struct csi2_err_stats *err_list = NULL;
unsigned long err_stat = 0;
u32 val;
char err_str[CSI_ERRSTR_LEN] = {0};
char cur_str[CSI_ERRSTR_LEN] = {0};
char vc_info[CSI_VCINFO_LEN] = {0};
val = read_reg(hw->csi2_base, CSIHOST_ERR1);
if (val) {
write_reg(hw->csi2_base,
CSIHOST_ERR1, 0x0);
if (val & CSIHOST_ERR1_PHYERR_SPTSYNCHS) {
err_list = &hw->err_list[RK_CSI2_ERR_SOTSYN];
err_list->cnt++;
vehicle_csi2_find_err_vc(val & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(sot sync,lane:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_BNDRY_MATCH) {
err_list = &hw->err_list[RK_CSI2_ERR_FS_FE_MIS];
err_list->cnt++;
vehicle_csi2_find_err_vc((val >> 4) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(fs/fe miss,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_SEQ) {
err_list = &hw->err_list[RK_CSI2_ERR_FRM_SEQ_ERR];
err_list->cnt++;
vehicle_csi2_find_err_vc((val >> 8) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(f_seq,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_FRM_DATA) {
err_list = &hw->err_list[RK_CSI2_ERR_CRC_ONCE];
err_list->cnt++;
vehicle_csi2_find_err_vc((val >> 12) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(err_data,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_CRC) {
err_list = &hw->err_list[RK_CSI2_ERR_CRC];
err_list->cnt++;
vehicle_csi2_find_err_vc((val >> 24) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(crc,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_ECC2) {
err_list = &hw->err_list[RK_CSI2_ERR_CRC];
err_list->cnt++;
snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc2) ");
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR1_ERR_CTRL) {
vehicle_csi2_find_err_vc((val >> 16) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(ctrl,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
hw->err_list[RK_CSI2_ERR_ALL].cnt++;
err_stat = ((hw->err_list[RK_CSI2_ERR_FS_FE_MIS].cnt & 0xff) << 8) |
((hw->err_list[RK_CSI2_ERR_ALL].cnt) & 0xff);
cif->err_state.err_val = val;
cif->err_state.err_num = 1;
cif->err_state.err_stat = err_stat;
strscpy(cif->err_state.err_str, err_str, CSI_ERRSTR_LEN);
queue_work(cif->err_state.err_print_wq, &cif->err_state.work);
}
return IRQ_HANDLED;
}
static irqreturn_t vehicle_csirx_irq2(int irq, void *data)
{
struct vehicle_cif *cif = (struct vehicle_cif *)data;
struct csi2_dphy_hw *hw = cif->dphy_hw;
u32 val;
char cur_str[CSI_ERRSTR_LEN] = {0};
char err_str[CSI_ERRSTR_LEN] = {0};
char vc_info[CSI_VCINFO_LEN] = {0};
val = read_reg(hw->csi2_base, CSIHOST_ERR2);
if (val) {
if (val & CSIHOST_ERR2_PHYERR_ESC) {
vehicle_csi2_find_err_vc(val & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(ULPM,lane:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR2_PHYERR_SOTHS) {
vehicle_csi2_find_err_vc((val >> 4) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(sot,lane:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR2_ECC_CORRECTED) {
vehicle_csi2_find_err_vc((val >> 8) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(ecc,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR2_ERR_ID) {
vehicle_csi2_find_err_vc((val >> 12) & 0xf, vc_info);
snprintf(cur_str, CSI_ERRSTR_LEN, "(err id,vc:%s) ", vc_info);
vehicle_csi2_err_strncat(err_str, cur_str);
}
if (val & CSIHOST_ERR2_PHYERR_CODEHS) {
snprintf(cur_str, CSI_ERRSTR_LEN, "(err code) ");
vehicle_csi2_err_strncat(err_str, cur_str);
}
cif->err_state.err_val = val;
cif->err_state.err_num = 2;
strscpy(cif->err_state.err_str, err_str, CSI_ERRSTR_LEN);
queue_work(cif->err_state.err_print_wq, &cif->err_state.work);
}
return IRQ_HANDLED;
}
int vehicle_cif_reverse_open(struct vehicle_cfg *v_cfg)
{
int ret = 0;
struct vehicle_cif *cif = g_cif;
if (!cif)
return -ENODEV;
mutex_lock(&cif->stream_lock);
memcpy(&cif->cif_cfg, v_cfg, sizeof(struct vehicle_cfg));
ret = pm_runtime_get_sync(cif->dev);
if (ret < 0) {
pm_runtime_put_noidle(cif->dev);
VEHICLE_DGERR("%s pm_runtime_get_sync failed\n", __func__);
goto exit;
}
/*get dcphy param*/
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588_DCPHY) {
if (cif->cif_cfg.dphy_param) {
cif->dphy_hw->dphy_param = cif->cif_cfg.dphy_param;
dev_info(cif->dev, "-----get dphy param from sensor----\n");
} else {
cif->dphy_hw->dphy_param = &rk3588_dcphy_param;
dev_info(cif->dev, "fail to get dphy param, used default value\n");
}
}
/* set ddr fix freq */
rockchip_set_system_status(SYS_STATUS_CIF0);
vehicle_cif_hw_soft_reset(cif);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
/* 0. set mipi-dphy data rate */
cif->dphy_hw->data_rate_mbps = cif->cif_cfg.mipi_freq * 2 / 1000 / 1000;
/* 0. set csi2 & dphy clk */
vehicle_csi2_hw_soft_reset(cif);
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 ||
cif->dphy_hw->chip_id >= CHIP_ID_RK3562)
vehicle_csi2_dphy_hw_do_reset(cif);
if (!cif->dphy_hw->on)
vehicle_csi2_clk_ctrl(cif, 1);
/* 1. stream setup */
cif_csi_stream_setup(cif);
/* 2. create dummy buf */
ret = vehicle_cif_create_dummy_buf(cif);
if (ret < 0)
VEHICLE_DGERR("Failed to create dummy_buf, %d\n", ret);
/* 3. cif init buffer */
if (vehicle_cif_init_buffer(cif, 1, cif->channels[0].id) < 0)
goto exit;
/* 4. dump cif regs */
vehicle_cif_csi2_dump_regs(cif);
/* 5. start stream */
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF)
vehicle_cif_csi2_s_stream_v1(cif, 1, V4L2_MBUS_CSI2_DPHY);
else
vehicle_cif_csi2_s_stream(cif, 1, V4L2_MBUS_CSI2_DPHY);
} else {
/* 1. stream setup */
cif_stream_setup(cif);
/* 2. create dummy buf */
ret = vehicle_cif_create_dummy_buf(cif);
if (ret < 0)
VEHICLE_DGERR("Failed to create dummy_buf, %d\n", ret);
/* 2. cif init buffer */
if (vehicle_cif_init_buffer(cif, 1, 0) < 0)
goto exit;
/* 3. enable interrupts */
if (cif->chip_id < CHIP_RK3588_VEHICLE_CIF)
cif_interrupt_setup(cif);
/* 4. dump cif regs */
vehicle_cif_dvp_dump_regs(cif);
/* 5. start stream */
vehicle_cif_s_stream(cif, 1);
}
cif->stopping = false;
drop_frames_number = cif->drop_frames;
mutex_unlock(&cif->stream_lock);
return 0;
exit:
mutex_unlock(&cif->stream_lock);
return -1;
}
int vehicle_cif_reverse_close(void)
{
int ret = 0;
struct vehicle_cif *cif = g_cif;
if (!cif)
return -ENODEV;
mutex_lock(&cif->stream_lock);
VEHICLE_DG("%s cif reverse start closing\n", __func__);
cif->stopping = true;
cancel_delayed_work_sync(&(cif->work));
flush_delayed_work(&(cif->work));
cancel_work_sync(&cif->err_state.work);
ret = wait_event_timeout(cif->wq_stopped,
cif->state != RKCIF_STATE_STREAMING,
msecs_to_jiffies(100));
if (!ret) {
VEHICLE_DGERR("%s wait stream stop timeout!\n", __func__);
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF)
vehicle_cif_csi2_s_stream_v1(cif, 0, V4L2_MBUS_CSI2_DPHY);
else
vehicle_cif_csi2_s_stream(cif, 0, V4L2_MBUS_CSI2_DPHY);
} else {
vehicle_cif_s_stream(cif, 0);
}
//cif->stopping = false;
}
if (cif->cif_cfg.type == V4L2_MBUS_CSI2_DPHY) {
vehicle_cif_csi_stream_stop(cif);
vehicle_csi2_hw_soft_reset(cif);
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 ||
cif->dphy_hw->chip_id >= CHIP_ID_RK3562)
vehicle_csi2_dphy_hw_do_reset(cif);
if (cif->dphy_hw->on)
vehicle_csi2_clk_ctrl(cif, 0);
}
vehicle_cif_destroy_dummy_buf(cif);
//vehicle_csi2_hw_soft_reset(cif);
//vehicle_cif_hw_soft_reset(cif);
rockchip_clear_system_status(SYS_STATUS_CIF0);
mutex_unlock(&cif->stream_lock);
cif->stopping = false;
return 0;
}
static void vehicle_cif_dphy_get_node(struct vehicle_cif *cif)
{
struct device_node *node = NULL;
struct device_node *cp = NULL;
struct device *dev = cif->dev;
const char *status = NULL;
node = of_parse_phandle(dev->of_node, "rockchip,cif-phy", 0);
if (!node) {
VEHICLE_DGERR("get cif-phy dts failed\n");
return;
}
for_each_child_of_node(node, cp) {
of_property_read_string(cp, "status", &status);
if (status && !strcmp(status, "disabled"))
continue;
else
cif->phy_node = cp;
VEHICLE_INFO("status: %s %s\n", cp->name, status);
}
}
static int cif_parse_dt(struct vehicle_cif *cif)
{
struct device *dev = cif->dev;
struct device_node *node;
struct device_node *phy_node = cif->phy_node;
struct device_node *cif_node;
struct device_node *cis2_node;
if (of_property_read_u32(dev->of_node, "cif,drop-frames",
&cif->drop_frames)) {
VEHICLE_INFO("%s:Get cif, drop-frames failed!\n", __func__);
cif->drop_frames = 0; //default drop frames;
}
if (of_property_read_u32(dev->of_node, "cif,chip-id",
&cif->chip_id)) {
VEHICLE_INFO("%s:Get cif, chip_id failed!\n", __func__);
cif->chip_id = CHIP_RK3588_VEHICLE_CIF; //default rk3588;
}
cif_node = of_parse_phandle(dev->of_node, "rockchip,cif", 0);
cif->base = (char *)of_iomap(cif_node, 0);
node = of_parse_phandle(dev->of_node, "rockchip,cru", 0);
cif->cru_base = of_iomap(node, 0);
node = of_parse_phandle(dev->of_node, "rockchip,grf", 0);
cif->grf_base = of_iomap(node, 0);
cif->regmap_grf = syscon_regmap_lookup_by_phandle(dev->of_node, "rockchip,grf");
if (IS_ERR(cif->regmap_grf))
VEHICLE_DGERR("unable to get rockchip,grf\n");
cif->irq = irq_of_parse_and_map(cif_node, 0);
if (cif->irq < 0) {
VEHICLE_DGERR("%s: request cif irq failed\n", __func__);
iounmap(cif->base);
iounmap(cif->cru_base);
iounmap(cif->grf_base);
return -ENODEV;
}
if (of_property_read_u32(phy_node, "csihost-idx", &cif->csi_host_idx)) {
VEHICLE_INFO("Get %s csihost-idx failed! sensor link to dvp!!\n",
phy_node->name);
cif->inf_id = RKCIF_DVP;
} else {
cif->inf_id = RKCIF_MIPI_LVDS;
VEHICLE_INFO("sensor link to %s!!\n", phy_node->name);
}
if (cif->inf_id == RKCIF_MIPI_LVDS) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF &&
!(cif->csi_host_idx == RKCIF_MIPI0_CSI2 ||
cif->csi_host_idx == RKCIF_MIPI1_CSI2)) {
node = of_parse_phandle(phy_node, "rockchip,csi2-dphy", 0);
cif->csi2_dphy_base = of_iomap(node, 0);
cif->regmap_dphy_grf =
syscon_regmap_lookup_by_phandle(phy_node, "rockchip,dphy-grf");
if (IS_ERR(cif->regmap_dphy_grf))
VEHICLE_INFO("unable to get rockchip,dphy-grf\n");
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF &&
cif->csi_host_idx != RKCIF_MIPI0_CSI2) {
node = of_parse_phandle(phy_node, "rockchip,csi2-dphy", 0);
cif->csi2_dphy_base = of_iomap(node, 0);
cif->regmap_dphy_grf =
syscon_regmap_lookup_by_phandle(phy_node, "rockchip,dphy-grf");
if (IS_ERR(cif->regmap_dphy_grf))
VEHICLE_INFO("unable to get rockchip,dphy-grf\n");
cif->dphy_sys_grf =
syscon_regmap_lookup_by_phandle(phy_node, "rockchip,sys-grf");
if (IS_ERR(cif->dphy_sys_grf))
VEHICLE_INFO("unable to get rockchip,sys-grf\n");
} else if (cif->chip_id != CHIP_RK3588_VEHICLE_CIF &&
cif->chip_id != CHIP_RK3576_VEHICLE_CIF) {
node = of_parse_phandle(phy_node, "rockchip,csi2-dphy", 0);
cif->csi2_dphy_base = of_iomap(node, 0);
}
cis2_node = of_parse_phandle(phy_node, "rockchip,csi2", 0);
cif->csi2_base = of_iomap(cis2_node, 0);
cif->csi2_irq1 = irq_of_parse_and_map(cis2_node, 0);
if (cif->csi2_irq1 < 0) {
VEHICLE_DGERR("%s: request csi-intr1 failed\n", __func__);
iounmap(cif->base);
iounmap(cif->cru_base);
iounmap(cif->grf_base);
iounmap(cif->csi2_dphy_base);
iounmap(cif->csi2_base);
return -ENODEV;
}
cif->csi2_irq2 = irq_of_parse_and_map(cis2_node, 1);
if (cif->csi2_irq2 < 0) {
VEHICLE_DGERR("%s: request csi-intr2 failed\n", __func__);
iounmap(cif->base);
iounmap(cif->cru_base);
iounmap(cif->grf_base);
iounmap(cif->csi2_dphy_base);
iounmap(cif->csi2_base);
return -ENODEV;
}
}
VEHICLE_DG("%s, drop_frames = %d\n", __func__, cif->drop_frames);
return 0;
}
int vehicle_cif_init_mclk(struct vehicle_cif *cif)
{
struct device *dev = cif->dev;
struct rk_cif_clk *clk = &cif->clk;
/* sensor MCLK:
* current use CLK_CIF_OUT
*/
vehicle_cif_dphy_get_node(cif);
clk->xvclk = of_clk_get_by_name(cif->phy_node, "xvclk");
if (IS_ERR(clk->xvclk)) {
dev_err(dev, "Failed to get sensor xvclk\n");
return -EINVAL;
}
rkcif_s_mclk(cif, 1, 24000000);
VEHICLE_INFO("%s(%d): set sensor MCLK rate 24MHZ OK!\n", __func__, __LINE__);
return 0;
}
static int vehicle_cif_deinit_mclk(struct vehicle_cif *cif)
{
struct rk_cif_clk *clk = &cif->clk;
/* release sensor MCLK:
* current use CLK_CIF_OUT
*/
if (!IS_ERR(clk->xvclk))
clk_disable_unprepare(clk->xvclk);
clk_put(clk->xvclk);
return 0;
}
int vehicle_cif_init(struct vehicle_cif *cif)
{
int ret;
struct device *dev;
struct rk_cif_clk *clk;
struct csi2_dphy_hw *dphy_hw;
struct clk *tmp_cif_clk = NULL;
int i;
int inf_id;
if (!cif)
return -ENODEV;
dev = cif->dev;
clk = &cif->clk;
g_cif = cif;
/* 0. dts parse */
if (cif_parse_dt(cif) < -1) {
VEHICLE_DGERR("%s: cif_parse_dt failed\n", __func__);
return -ENODEV;
}
inf_id = cif->inf_id;
if (inf_id == RKCIF_MIPI_LVDS) {
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
if (cif->csi_host_idx == RKCIF_MIPI0_CSI2 ||
cif->csi_host_idx == RKCIF_MIPI1_CSI2)
dphy_hw = &rk3588_csi2_dcphy_hw;
else
dphy_hw = &rk3588_csi2_dphy_hw;
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
dphy_hw = &rk3562_csi2_dphy_hw;
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->csi_host_idx == RKCIF_MIPI0_CSI2)
dphy_hw = &rk3576_csi2_dcphy_hw;
else
dphy_hw = &rk3576_csi2_dphy_hw;
} else {
dphy_hw = &rk3568_csi2_dphy_hw;
}
}
/* 1. cif/csi2-dphy/csi2 clk setup */
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
clk->clks_num = ARRAY_SIZE(rk3588_cif_clks);
clk->rsts_num = ARRAY_SIZE(rk3588_cif_rsts);
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
clk->clks_num = ARRAY_SIZE(rk3562_cif_clks);
clk->rsts_num = ARRAY_SIZE(rk3562_cif_rsts);
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
clk->clks_num = ARRAY_SIZE(rk3576_cif_clks);
clk->rsts_num = ARRAY_SIZE(rk3576_cif_rsts);
} else {
clk->clks_num = ARRAY_SIZE(rk3568_cif_clks);
clk->rsts_num = ARRAY_SIZE(rk3568_cif_rsts);
}
if (inf_id == RKCIF_MIPI_LVDS) {
cif->dphy_hw = dphy_hw;
dphy_hw->dev = cif->dev;
/*get phy_index*/
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588) {
if (cif->csi_host_idx >= RKCIF_MIPI4_CSI2)
cif->dphy_hw->phy_index = 3;
else
cif->dphy_hw->phy_index = 0;
} else if (cif->dphy_hw->chip_id == CHIP_ID_RK3562) {
if (cif->csi_host_idx >= RKCIF_MIPI2_CSI2)
cif->dphy_hw->phy_index = 3;
else
cif->dphy_hw->phy_index = 0;
} else if (cif->dphy_hw->chip_id == CHIP_ID_RK3576) {
if (cif->csi_host_idx >= RKCIF_MIPI3_CSI2)
cif->dphy_hw->phy_index = 3;
else
cif->dphy_hw->phy_index = 0;
} else {
cif->dphy_hw->phy_index = 0;
}
/*get mipi dcphy*/
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588_DCPHY) {
struct phy *dcphy = NULL;
struct samsung_mipi_dcphy *dcphy_hw = NULL;
dcphy = of_phy_get(cif->phy_node, "dcphy");
if (IS_ERR(dcphy)) {
ret = PTR_ERR(dcphy);
dev_err(dev, "failed to get mipi dcphy: %d\n", ret);
return ret;
}
dcphy_hw = phy_get_drvdata(dcphy);
dcphy_hw->dphy_vehicle[dcphy_hw->dphy_vehicle_num] = cif->dphy_hw;
dcphy_hw->dphy_vehicle_num++;
cif->dphy_hw->samsung_phy = dcphy_hw;
}
/* csi2 mipidphy rsts */
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3562 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3576) {
for (i = 0; i < dphy_hw->num_dphy_rsts; i++) {
struct reset_control *rst = NULL;
rst = of_reset_control_get(cif->phy_node, dphy_hw->dphy_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", dphy_hw->dphy_rsts[i]);
return PTR_ERR(rst);
}
dphy_hw->dphy_rst[i] = rst;
}
} else {
dev_info(dev, "use mipi dcphy, no need request rst\n");
}
/* csi2 mipidphy clks */
for (i = 0; i < dphy_hw->num_dphy_clks; i++) {
struct clk *tmp_clk =
of_clk_get_by_name(cif->phy_node, dphy_hw->dphy_clks[i].id);
if (IS_ERR(tmp_clk)) {
dev_err(dev, "failed to get %s\n", dphy_hw->dphy_clks[i].id);
return PTR_ERR(tmp_clk);
}
dev_info(dev, "clk get %s\n", dphy_hw->dphy_clks[i].id);
dphy_hw->dphy_clks[i].clk = tmp_clk;
}
/* csi2 clks */
for (i = 0; i < dphy_hw->num_csi2_clks; i++) {
struct clk *tmp_clk =
of_clk_get_by_name(cif->phy_node, dphy_hw->csi2_clks[i].id);
if (IS_ERR(tmp_clk)) {
dev_err(dev, "failed to get %s\n", dphy_hw->csi2_clks[i].id);
return PTR_ERR(tmp_clk);
}
dev_info(dev, "clk get %s\n", dphy_hw->csi2_clks[i].id);
dphy_hw->csi2_clks[i].clk = tmp_clk;
}
/* csi2 rsts */
for (i = 0; i < dphy_hw->num_csi2_rsts; i++) {
struct reset_control *rst = NULL;
rst = of_reset_control_get(cif->phy_node, dphy_hw->csi2_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", dphy_hw->csi2_rsts[i]);
return PTR_ERR(rst);
}
dphy_hw->csi2_rst[i] = rst;
}
dphy_hw->on = false;
}
/* vicap clks */
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
for (i = 0; i < clk->clks_num; i++) {
tmp_cif_clk = devm_clk_get(dev, rk3588_cif_clks[i]);
if (IS_ERR(tmp_cif_clk)) {
dev_err(dev, "failed to get %s\n", rk3588_cif_clks[i]);
return PTR_ERR(tmp_cif_clk);
}
clk->clks[i] = tmp_cif_clk;
clk->on = false;
}
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
for (i = 0; i < clk->clks_num; i++) {
tmp_cif_clk = devm_clk_get(dev, rk3562_cif_clks[i]);
if (IS_ERR(tmp_cif_clk)) {
dev_err(dev, "failed to get %s\n", rk3562_cif_clks[i]);
return PTR_ERR(tmp_cif_clk);
}
clk->clks[i] = tmp_cif_clk;
clk->on = false;
}
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
for (i = 0; i < clk->clks_num; i++) {
tmp_cif_clk = devm_clk_get(dev, rk3576_cif_clks[i]);
if (IS_ERR(tmp_cif_clk)) {
dev_err(dev, "failed to get %s\n", rk3576_cif_clks[i]);
return PTR_ERR(tmp_cif_clk);
}
clk->clks[i] = tmp_cif_clk;
clk->on = false;
}
} else {
for (i = 0; i < clk->clks_num; i++) {
tmp_cif_clk = devm_clk_get(dev, rk3568_cif_clks[i]);
if (IS_ERR(tmp_cif_clk)) {
dev_err(dev, "failed to get %s\n", rk3568_cif_clks[i]);
return PTR_ERR(tmp_cif_clk);
}
clk->clks[i] = tmp_cif_clk;
clk->on = false;
}
}
/* vicap rsts */
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
for (i = 0; i < clk->rsts_num; i++) {
struct reset_control *rst = NULL;
if (rk3588_cif_rsts[i])
rst = devm_reset_control_get(dev, rk3588_cif_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", rk3588_cif_rsts[i]);
return PTR_ERR(rst);
}
clk->cif_rst[i] = rst;
}
} else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF) {
for (i = 0; i < clk->rsts_num; i++) {
struct reset_control *rst = NULL;
if (rk3562_cif_rsts[i])
rst = devm_reset_control_get(dev, rk3562_cif_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", rk3562_cif_rsts[i]);
return PTR_ERR(rst);
}
clk->cif_rst[i] = rst;
}
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
for (i = 0; i < clk->rsts_num; i++) {
struct reset_control *rst = NULL;
if (rk3576_cif_rsts[i])
rst = devm_reset_control_get(dev, rk3576_cif_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", rk3576_cif_rsts[i]);
return PTR_ERR(rst);
}
clk->cif_rst[i] = rst;
}
} else {
for (i = 0; i < clk->rsts_num; i++) {
struct reset_control *rst = NULL;
if (rk3568_cif_rsts[i])
rst = devm_reset_control_get(dev, rk3568_cif_rsts[i]);
if (IS_ERR(rst)) {
dev_err(dev, "failed to get %s\n", rk3568_cif_rsts[i]);
return PTR_ERR(rst);
}
clk->cif_rst[i] = rst;
}
}
/* 2. set cif clk & sensor mclk */
rk_cif_mclk_ctrl(cif, 1, 24000000);
INIT_DELAYED_WORK(&cif->work, vehicle_cif_reset_work_func);
if (inf_id == RKCIF_MIPI_LVDS)
/* 2. set csi2 & dphy clk */
if (!cif->dphy_hw->on)
vehicle_csi2_clk_ctrl(cif, 1);
/* 3. request cif irq & mipi csi irq1-2 */
if (cif->chip_id >= CHIP_RK3588_VEHICLE_CIF) {
ret = devm_request_irq(dev, cif->irq,
rk_camera_irq_v1, IRQF_SHARED, "vehicle_cif", cif);
if (ret < 0) {
VEHICLE_DGERR("request cif irq failed!\n");
return -EINVAL;
}
} else {
ret = devm_request_irq(dev, cif->irq,
rk_camera_irq, IRQF_SHARED, "vehicle_cif", cif);
if (ret < 0) {
VEHICLE_DGERR("request cif irq failed!\n");
return -EINVAL;
}
}
VEHICLE_DG("%s(%d):\n", __func__, __LINE__);
if (inf_id == RKCIF_MIPI_LVDS) {
ret = devm_request_irq(dev, cif->csi2_irq1, vehicle_csirx_irq1,
IRQF_SHARED, "vehicle_csi_intr1", cif);
if (ret < 0) {
VEHICLE_DGERR("request csirx irq1 failed!\n");
return -EINVAL;
}
ret = devm_request_irq(dev, cif->csi2_irq2, vehicle_csirx_irq2,
IRQF_SHARED, "vehicle_csi_intr2", cif);
if (ret < 0) {
VEHICLE_DGERR("request csirx irq2 failed!\n");
return -EINVAL;
}
}
/* 4. set cif regs */
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF)
cif->cif_regs = rk3588_cif_regs;
else if (cif->chip_id == CHIP_RK3562_VEHICLE_CIF)
cif->cif_regs = rk3562_cif_regs;
else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF)
cif->cif_regs = rk3576_cif_regs;
else
cif->cif_regs = rk3568_cif_regs;
if (inf_id == RKCIF_MIPI_LVDS) {
/* 5. set csi2-mipi-dphy reg */
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3568 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3562 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3576)
cif->dphy_hw->csi2_dphy_base = cif->csi2_dphy_base;
/* 7. set mipi-csi2 reg */
cif->dphy_hw->csi2_base = cif->csi2_base;
/* 8. set dphy grf regmap */
if (cif->chip_id == CHIP_RK3588_VEHICLE_CIF) {
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588) {
cif->dphy_hw->regmap_grf = cif->regmap_dphy_grf;
cif->dphy_hw->regmap_sys_grf = cif->regmap_grf;
}
} else if (cif->chip_id == CHIP_RK3576_VEHICLE_CIF) {
if (cif->dphy_hw->chip_id == CHIP_ID_RK3576) {
cif->dphy_hw->regmap_grf = cif->regmap_dphy_grf;
cif->dphy_hw->regmap_sys_grf = cif->dphy_sys_grf;
}
} else {
cif->dphy_hw->regmap_grf = cif->regmap_grf;
}
mutex_init(&dphy_hw->mutex);
}
if (cif->inf_id == RKCIF_MIPI_LVDS && cif->chip_id <= CHIP_RK3562_VEHICLE_CIF)
cif->use_hw_interlace = false;
else
cif->use_hw_interlace = true;
/* 9. init waitqueue */
atomic_set(&cif->reset_status, 0);
init_waitqueue_head(&cif->wq_stopped);
spin_lock_init(&cif->vbq_lock);
INIT_WORK(&cif->err_state.work, vehicle_csi2_err_print_work);
cif->err_state.err_print_wq = create_workqueue("cis2_err_print_queue");
if (cif->err_state.err_print_wq == NULL) {
dev_err(dev, "%s: %s create failed.\n", __func__,
"csi2_err_print_wq");
}
return 0;
}
int vehicle_cif_deinit(struct vehicle_cif *cif)
{
struct rk_cif_clk *clk = &cif->clk;
struct device *dev = cif->dev;
int i;
struct csi2_dphy_hw *dphy_hw = cif->dphy_hw;
int inf_id = cif->inf_id;
// vehicle_cif_s_stream(cif, 0);
// vehicle_cif_do_stop_stream(cif);
/* set csi2-dphy csi cif clk & sensor mclk */
rk_cif_mclk_ctrl(cif, 0, 0);
if (inf_id == RKCIF_MIPI_LVDS)
if (cif->dphy_hw->on)
vehicle_csi2_clk_ctrl(cif, 0);
/* release sensor MCLK */
vehicle_cif_deinit_mclk(cif);
/* vicap rsts release */
for (i = 0; i < clk->rsts_num; i++)
reset_control_put(clk->cif_rst[i]);
/* vicap clk release */
for (i = 0; i < clk->clks_num; i++)
devm_clk_put(dev, clk->clks[i]);
if (inf_id == RKCIF_MIPI_LVDS) {
/*dcphy put*/
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588_DCPHY) {
struct samsung_mipi_dcphy *dcphy_hw = cif->dphy_hw->samsung_phy;
struct csi2_dphy_hw *csi2_dphy = NULL;
for (i = 0; i < dcphy_hw->dphy_vehicle_num; i++) {
csi2_dphy = dcphy_hw->dphy_vehicle[i];
if (csi2_dphy) {
dcphy_hw->dphy_vehicle[i] = NULL;
dcphy_hw->dphy_vehicle_num--;
break;
}
}
}
/* dphy clks release */
for (i = 0; i < dphy_hw->num_dphy_clks; i++)
clk_put(dphy_hw->dphy_clks[i].clk);
/* dphy rsts release */
if (cif->dphy_hw->chip_id == CHIP_ID_RK3588 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3562 ||
cif->dphy_hw->chip_id == CHIP_ID_RK3576) {
for (i = 0; i < dphy_hw->num_dphy_rsts; i++)
reset_control_put(dphy_hw->dphy_rst[i]);
}
/* csi2 clks release */
for (i = 0; i < dphy_hw->num_csi2_clks; i++)
clk_put(dphy_hw->csi2_clks[i].clk);
/* csi2 resets release */
for (i = 0; i < dphy_hw->num_csi2_rsts; i++)
reset_control_put(dphy_hw->csi2_rst[i]);
mutex_destroy(&dphy_hw->mutex);
}
devm_free_irq(dev, cif->irq, cif);
if (inf_id == RKCIF_MIPI_LVDS) {
devm_free_irq(dev, cif->csi2_irq1, cif);
devm_free_irq(dev, cif->csi2_irq2, cif);
}
if (cif->err_state.err_print_wq) {
flush_workqueue(cif->err_state.err_print_wq);
destroy_workqueue(cif->err_state.err_print_wq);
}
return 0;
}