// 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 <dt-bindings/soc/rockchip-system-status.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",
|
};
|
|
//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",
|
};
|
|
//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"),
|
};
|
|
//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),
|
};
|
|
//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 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;
|
}
|
}
|
|
if (index < CIF_REG_INDEX_MAX) {
|
if (index == CIF_REG_DVP_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;
|
}
|
}
|
|
if (index < CIF_REG_INDEX_MAX) {
|
if (index == CIF_REG_DVP_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;
|
}
|
}
|
|
if (index < CIF_REG_INDEX_MAX) {
|
if (index == CIF_REG_DVP_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;
|
}
|
}
|
|
if (index < CIF_REG_INDEX_MAX) {
|
if (index == CIF_REG_DVP_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;
|
}
|
|
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 {
|
rkcif_write_reg(cif, CIF_REG_DVP_INTSTAT, 0x3c3ffff);
|
rkcif_write_reg_or(cif, CIF_REG_DVP_INTEN, 0x033ffff);//0x3c3ffff
|
}
|
|
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)
|
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_ID_RK3588) {
|
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)
|
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 (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 (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 (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]);
|
}
|
}
|
|
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;
|
/* set cif input format yuv422*/
|
channel->fmt_val = CSI_WRDDR_TYPE_YUV422;
|
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.");
|
channel->virtual_width *= 2;
|
cif->interlaced_enable = true;
|
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));
|
|
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);
|
|
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);
|
|
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) {
|
val = CSI_ENABLE_CAPTURE | CSI_DMA_ENABLE | channel->fmt_val |
|
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;
|
}
|
|
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);
|
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));
|
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 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
|
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);
|
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) {
|
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 ((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%x\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)
|
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)
|
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_RK3588_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 {
|
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 {
|
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 {
|
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) {
|
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 {
|
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 (rk3568_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 (rk3568_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 {
|
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 = request_irq(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 = request_irq(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 = request_irq(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 = request_irq(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
|
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->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 {
|
cif->dphy_hw->regmap_grf = cif->regmap_grf;
|
}
|
mutex_init(&dphy_hw->mutex);
|
}
|
/* 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) {
|
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);
|
}
|
|
free_irq(cif->irq, cif);
|
if (inf_id == RKCIF_MIPI_LVDS) {
|
free_irq(cif->csi2_irq1, cif);
|
free_irq(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;
|
}
|