/* Copyright (c) 2020 Kneron, Inc. All Rights Reserved. * * The information contained herein is property of Kneron, Inc. * Terms and conditions of usage are described in detail in Kneron * STANDARD SOFTWARE LICENSE AGREEMENT. * * Licensees are granted free, non-transferable use of the information. * NO WARRANTY of ANY KIND is provided. This heading must NOT be removed * from the file. */ /****************************************************************************** * Filename: * --------- * kdrv_mipicsirx.c * * Project: * -------- * KL520 * * Description: * ------------ * This is MIPI CSIRX driver * * Author: * ------- * Albert Chen ** ******************************************************************************/ /****************************************************************************** Head Block of The File ******************************************************************************/ // Sec 0: Comment block of the file // Sec 1: Include File #include "board.h" #include "kmdw_camera.h" #include "kdrv_mipicsirx.h" #include "kdrv_clock.h" #include "kdrv_scu_ext.h" #define ROUND_UP(x, y) ((((x) + (y - 1)) / y) * y) #define CSI2RX_REG_VIDR 0x00 #define CSI2RX_REG_DIDR 0x01 #define CSI2RX_REG_CR 0x04 //Control Register #define CSI2RX_REG_VSCR 0x05 //DPI V Sync Control Register #define CSI2RX_REG_ECR 0x06 #define CSI2RX_REG_TCNR 0x08 #define CSI2RX_REG_HRTVR 0x0A //HS RX Timeout Value Register #define CSI2RX_REG_FIUR 0x0B #define CSI2RX_REG_ITR 0x12 //Initialization Timer Register #define CSI2RX_REG_VSTR0 0x14 //DPI VC0 V Sync Timing Register #define CSI2RX_REG_HSTR0 0x15 //DPI VC0 H Sync Timing Register #define CSI2RX_REG_VSTR1 0x16 #define CSI2RX_REG_HSTR1 0x17 #define CSI2RX_REG_VSTR2 0x18 #define CSI2RX_REG_HSTR2 0x19 #define CSI2RX_REG_VSTR3 0x1A #define CSI2RX_REG_HSTR3 0x1B #define CSI2RX_REG_MCR 0x1C //DPI Mapping Control Register #define CSI2RX_REG_VSTER 0x1E #define CSI2RX_REG_HPNR 0x20 //DPI Horizontal Pixel Number #define CSI2RX_REG_PECR 0x28 //PPI Enable Control Register #define CSI2RX_REG_DLMR 0x2A #define CSI2RX_REG_CSIERR 0x30 #define CSI2RX_REG_INTSTS 0x33 #define CSI2RX_REG_ESR 0x34 #define CSI2RX_REG_DPISR 0x38 #define CSI2RX_REG_INTER 0x3C #define CSI2RX_REG_FFR 0x3D #define CSI2RX_REG_DPCMR 0x48 #define CSI2RX_REG_FRR 0x4C #define CSI2RX_REG_PFTR 0x50 #define CSI2RX_REG_PUDTR 0x58 #define CSI2RX_REG_FRCR 0x80 #define CSI2RX_REG_FNR 0x88 #define CSI2RX_REG_BPGLR 0x90 #define CSI2RX_REG_BPGHR 0x91 #define MAX_VIDEO_MEM 8 << 20 #define CSIRX_0_BASE CSIRX_FTCSIRX100_PA_BASE #define CSIRX_1_BASE CSIRX_FTCSIRX100_1_PA_BASE /* DPI V Sync Control Register (VSCR, Address = 0x05) */ #define CSIRX_REG_VSCR_SET_VSTU0(addr, val) SET_MASKED_BIT(addr, val, 0) /* PPI Enable Control Register (PECR, Address = 0x28) */ #define CSIRX_REG_PECR_GET_PEC(addr) GET_BITS(addr, 0, 7) #define CSIRX_REG_PECR_SET_PEC(addr, val) SET_MASKED_BITS(addr, val, 0, 7) /* Data Lane Mapping Register 0 */ #define CSIRX_REG_0_DLMR0 (CSIRX_0_BASE + 0x2A) #define CSIRX_REG_0_DLMR0_GET_L1() GET_BITS(CSIRX_REG_0_DLMR0, 4, 6) #define CSIRX_REG_0_DLMR0_GET_L0() GET_BITS(CSIRX_REG_0_DLMR0, 0, 2) #define CSIRX_REG_1_DLMR0 (CSIRX_1_BASE + 0x2A) #define CSIRX_REG_1_DLMR0_GET_L1() GET_BITS(CSIRX_REG_1_DLMR0, 4, 6) #define CSIRX_REG_1_DLMR0_GET_L0() GET_BITS(CSIRX_REG_1_DLMR0, 0, 2) #define CSIRX_REG_0_FEATURE0 (CSIRX_0_BASE + 0x40) #define CSIRX_REG_1_FEATURE0 (CSIRX_1_BASE + 0x40) /* DPI FIFO Address Depth */ #define CSIRX_REG_0_FEATURE0_GET_DFAD() GET_BITS(CSIRX_REG_0_FEATURE0, 5, 7) #define CSIRX_REG_1_FEATURE0_GET_DFAD() GET_BITS(CSIRX_REG_1_FEATURE0, 5, 7) /* Lane Number */ #define CSIRX_REG_0_FEATURE0_GET_LN() GET_BITS(CSIRX_REG_0_FEATURE0, 2, 4) #define CSIRX_REG_1_FEATURE0_GET_LN() GET_BITS(CSIRX_REG_1_FEATURE0, 2, 4) /* Virtual channel number */ #define CSIRX_REG_0_FEATURE0_GET_VCN() GET_BITS(CSIRX_REG_0_FEATURE0, 0, 1) #define CSIRX_REG_1_FEATURE0_GET_VCN() GET_BITS(CSIRX_REG_1_FEATURE0, 0, 1) #define CSIRX_REG_0_FEATURE6 (CSIRX_0_BASE + 0x46) #define CSIRX_REG_1_FEATURE6 (CSIRX_1_BASE + 0x46) /* ASC Indicator */ #define CSIRX_REG_0_FEATURE6_GET_ASC() GET_BIT(CSIRX_REG_0_FEATURE6, 7) #define CSIRX_REG_1_FEATURE6_GET_ASC() GET_BIT(CSIRX_REG_1_FEATURE6, 7) /* APB Indicator */ #define CSIRX_REG_0_FEATURE6_GET_APB() GET_BIT(CSIRX_REG_0_FEATURE6, 6) #define CSIRX_REG_1_FEATURE6_GET_APB() GET_BIT(CSIRX_REG_1_FEATURE6, 6) /* I2C Indicator */ #define CSIRX_REG_0_FEATURE6_GET_I2C() GET_BIT(CSIRX_REG_0_FEATURE6, 5) #define CSIRX_REG_1_FEATURE6_GET_I2C() GET_BIT(CSIRX_REG_1_FEATURE6, 5) /* DPCM_EN Indicator */ #define CSIRX_REG_0_FEATURE6_GET_DPCM() GET_BIT(CSIRX_REG_0_FEATURE6, 4) #define CSIRX_REG_1_FEATURE6_GET_DPCM() GET_BIT(CSIRX_REG_1_FEATURE6, 4) /* CHK_DATA Indicator */ #define CSIRX_REG_0_FEATURE6_GET_CD() GET_BIT(CSIRX_REG_0_FEATURE6, 3) #define CSIRX_REG_1_FEATURE6_GET_CD() GET_BIT(CSIRX_REG_1_FEATURE6, 3) /* DUAL_PIXEL Indicator */ #define CSIRX_REG_0_FEATURE6_GET_DP() GET_BIT(CSIRX_REG_0_FEATURE6, 2) #define CSIRX_REG_1_FEATURE6_GET_DP() GET_BIT(CSIRX_REG_1_FEATURE6, 2) /* FRC Indicator */ #define CSIRX_REG_0_FEATURE6_GET_FRC() GET_BIT(CSIRX_REG_0_FEATURE6, 1) #define CSIRX_REG_1_FEATURE6_GET_FRC() GET_BIT(CSIRX_REG_1_FEATURE6, 1) /* DPI_PG Indicator */ #define CSIRX_REG_0_FEATURE6_GET_PG() GET_BIT(CSIRX_REG_0_FEATURE6, 0) #define CSIRX_REG_1_FEATURE6_GET_PG() GET_BIT(CSIRX_REG_1_FEATURE6, 0) #define CSIRX_REG_0_FEATURE7 (CSIRX_0_BASE + 0x47) #define CSIRX_REG_1_FEATURE7 (CSIRX_1_BASE + 0x47) /* OCTA_PIXEL Indicator */ #define CSIRX_REG_0_FEATURE7_GET_OP() GET_BIT(CSIRX_REG_0_FEATURE7, 4) #define CSIRX_REG_1_FEATURE7_GET_OP() GET_BIT(CSIRX_REG_1_FEATURE7, 4) /* MONO_RGB_EN Indicator */ #define CSIRX_REG_0_FEATURE7_GET_MR() GET_BIT(CSIRX_REG_0_FEATURE7, 3) #define CSIRX_REG_1_FEATURE7_GET_MR() GET_BIT(CSIRX_REG_1_FEATURE7, 3) /* CRC_CHK Indicator */ #define CSIRX_REG_0_FEATURE7_GET_CRC() GET_BIT(CSIRX_REG_0_FEATURE7, 2) #define CSIRX_REG_1_FEATURE7_GET_CRC() GET_BIT(CSIRX_REG_1_FEATURE7, 2) /* LANE_SWAP Indicator */ #define CSIRX_REG_0_FEATURE7_GET_SWAP() GET_BIT(CSIRX_REG_0_FEATURE7, 1) #define CSIRX_REG_1_FEATURE7_GET_SWAP() GET_BIT(CSIRX_REG_1_FEATURE7, 1) /* QUAD_PIXEL Indicator */ #define CSIRX_REG_0_FEATURE7_GET_QP() GET_BIT(CSIRX_REG_0_FEATURE7, 0) #define CSIRX_REG_1_FEATURE7_GET_QP() GET_BIT(CSIRX_REG_1_FEATURE7, 0) #define CSIRX_REG_0_BPGLR0 (CSIRX_0_BASE + 0x90) #define CSIRX_REG_1_BPGLR0 (CSIRX_1_BASE + 0x90) #define CSIRX_REG_0_BPGLR0_SET_VLN(val) SET_MASKED_BITS(CSIRX_REG_0_BPGLR0, val, 0, 7) #define CSIRX_REG_1_BPGLR0_SET_VLN(val) SET_MASKED_BITS(CSIRX_REG_1_BPGLR0, val, 0, 7) #define CSIRX_REG_0_BPGHR0 (CSIRX_0_BASE + 0x91) #define CSIRX_REG_1_BPGHR0 (CSIRX_1_BASE + 0x91) #define CSIRX_REG_0_BPGHR0_SET_PT(val) SET_MASKED_BITS(CSIRX_REG_0_BPGHR0, val, 6, 7) #define CSIRX_REG_1_BPGHR0_SET_PT(val) SET_MASKED_BITS(CSIRX_REG_1_BPGHR0, val, 6, 7) #define CSIRX_REG_0_BPGHR0_SET_PS(val) SET_MASKED_BIT(CSIRX_REG_0_BPGHR0, val, 5) #define CSIRX_REG_1_BPGHR0_SET_PS(val) SET_MASKED_BIT(CSIRX_REG_1_BPGHR0, val, 5) #define CSIRX_REG_0_BPGHR0_SET_GE(val) SET_MASKED_BIT(CSIRX_REG_0_BPGHR0, val, 4) #define CSIRX_REG_1_BPGHR0_SET_GE(val) SET_MASKED_BIT(CSIRX_REG_1_BPGHR0, val, 4) #define CSIRX_REG_0_BPGHR0_SET_VLN(val) SET_MASKED_BITS(CSIRX_REG_0_BPGHR0, val, 0, 3) #define CSIRX_REG_1_BPGHR0_SET_VLN(val) SET_MASKED_BITS(CSIRX_REG_1_BPGHR0, val, 0, 3) /****************************************************************************** Declaration of External Variables & Functions ******************************************************************************/ // Sec 3: declaration of external variable // Sec 4: declaration of external function prototype /****************************************************************************** Declaration of data structure ******************************************************************************/ // Sec 5: structure, uniou, enum, linked list struct kdrv_csirx_context { uint32_t csi_rx_base; uint32_t mipi_rx_phy_csr; uint32_t mipi_lane_num; }; /****************************************************************************** Declaration of Global Variables & Functions ******************************************************************************/ // Sec 6: declaration of global variable struct kdrv_csirx_context csirx_ctx[CSI2RX_CAM_NUM]; // Sec 7: declaration of global function prototype /****************************************************************************** Declaration of static Global Variables & Functions ******************************************************************************/ // Sec 8: declaration of static global variable // Sec 9: declaration of static function prototype /****************************************************************************** // Sec 10: C Functions ******************************************************************************/ kdrv_status_t kdrv_csi2rx_initialize(uint32_t cam_idx) { if(cam_idx == CSI2RX_CAM_0) { csirx_ctx[cam_idx].csi_rx_base = CSIRX_FTCSIRX100_PA_BASE; csirx_ctx[cam_idx].mipi_rx_phy_csr = MIPIRX_PHY_CSR_PA_BASE; csirx_ctx[cam_idx].mipi_lane_num = 2; SCU_EXTREG_MISC_SET_DPI_MUX_0_sel(0); } else if(cam_idx == CSI2RX_CAM_1) { csirx_ctx[cam_idx].csi_rx_base = CSIRX_FTCSIRX100_1_PA_BASE; csirx_ctx[cam_idx].mipi_rx_phy_csr = MIPIRX_PHY_CSR_1_PA_BASE; csirx_ctx[cam_idx].mipi_lane_num = 2; SCU_EXTREG_MISC_SET_DPI_MUX_1_sel(0); } return KDRV_STATUS_OK; } kdrv_status_t kdrv_csi2rx_enable(uint32_t input_type, uint32_t cam_idx, uint32_t sensor_idx, struct cam_format* fmt) { uint32_t csirx_base = csirx_ctx[cam_idx].csi_rx_base; int32_t val, width; if(input_type != IMGSRC_IN_PORT_MIPI) return KDRV_STATUS_OK; width = ROUND_UP(fmt->width, 4); outw(csirx_base + CSI2RX_REG_HPNR , width); masked_outw(csirx_base + CSI2RX_REG_CR, 0x0d, 0xff); masked_outw(csirx_base + CSI2RX_REG_MCR, 0x00, 0xff); masked_outw(csirx_base + CSI2RX_REG_VSCR, 0x03, 0x03); masked_outw(csirx_base + CSI2RX_REG_VSTR0, 0xff, 0xff); masked_outw(csirx_base + CSI2RX_REG_VSTR1, 0xff, 0xff); #ifdef SOURCE_FROM_PATTERN CSIRX_REG_PECR_SET_PEC(csirx_base + CSI2RX_REG_PECR, 1); val = (inw(csirx_base + CSI2RX_REG_BPGLR) & 0xFF); cam_msg("CSI2RX_REG_BPGLR val=%x\n", val); val = (inw(csirx_base + CSI2RX_REG_BPGHR) & 0x0F); switch (fmt->pixelformat) { case V2K_PIX_FMT_RGB565: val |= 0x40; break; case V2K_PIX_FMT_RAW10: val |= 0x40; break; case V2K_PIX_FMT_RAW8: val |= 0; break; } outw(csirx_base + CSI2RX_REG_BPGHR, val); val = inw(csirx_base + CSI2RX_REG_BPGHR); #endif switch (sensor_idx) { case SENSOR_ID_OV9286: case SENSOR_ID_HMXRICA: case SENSOR_ID_SC132GS: val = 245; outw(csirx_base + CSI2RX_REG_PFTR , val); break; case SENSOR_ID_GC2145: CSIRX_REG_VSCR_SET_VSTU0(csirx_base, 1); break; default:; } return KDRV_STATUS_OK; } kdrv_status_t kdrv_csi2rx_start(uint32_t input_type, uint32_t cam_idx) { uint32_t i; uint32_t val; if(input_type != IMGSRC_IN_PORT_MIPI) return KDRV_STATUS_OK; val = 0; for (i = 0; i < csirx_ctx[cam_idx].mipi_lane_num; i++) val |= BIT0 << i; CSIRX_REG_PECR_SET_PEC(csirx_ctx[cam_idx].csi_rx_base + CSI2RX_REG_PECR, val); return KDRV_STATUS_OK; } kdrv_status_t kdrv_csi2rx_set_power(uint32_t cam_idx, uint32_t on) { uint32_t mask, val = 0; if (cam_idx == CSI2RX_CAM_0) { mask = (SCU_EXTREG_CSIRX_CTRL0_ClkLnEn | SCU_EXTREG_CSIRX_CTRL0_Enable); if (on) { val = mask; } masked_outw(SCU_EXTREG_CSIRX_CTRL0, val, mask); } else if (cam_idx == CSI2RX_CAM_1) { mask = (SCU_EXTREG_CSIRX_CTRL1_ClkLnEn | SCU_EXTREG_CSIRX_CTRL1_Enable); if (on) { val = mask; } masked_outw(SCU_EXTREG_CSIRX_CTRL1, val, mask); } return KDRV_STATUS_OK; } kdrv_status_t kdrv_csi2rx_reset(uint32_t cam_idx, uint32_t sensor_idx) { uint32_t mask, val; uint32_t mipi_rx_phy_csr = csirx_ctx[cam_idx].mipi_rx_phy_csr; if (cam_idx == CSI2RX_CAM_0) { mask = SCU_EXTREG_CSIRX_CTRL0_ClkLnEn | SCU_EXTREG_CSIRX_CTRL0_Enable | SCU_EXTREG_CSIRX_CTRL0_apb_rst_n | SCU_EXTREG_CSIRX_CTRL0_pwr_rst_n | SCU_EXTREG_CSIRX_CTRL0_sys_rst_n; val = mask; masked_outw(SCU_EXTREG_CSIRX_CTRL0, val, mask); if (sensor_idx == SENSOR_ID_GC2145) outb(mipi_rx_phy_csr + 0x11, 0x7); else outb(mipi_rx_phy_csr + 0x11, 0x3); } else if (cam_idx == CSI2RX_CAM_1) { mask = SCU_EXTREG_CSIRX_CTRL1_ClkLnEn | SCU_EXTREG_CSIRX_CTRL1_Enable | SCU_EXTREG_CSIRX_CTRL1_apb_rst_n | SCU_EXTREG_CSIRX_CTRL1_pwr_rst_n | SCU_EXTREG_CSIRX_CTRL1_sys_rst_n; val = mask; masked_outw(SCU_EXTREG_CSIRX_CTRL1, val, mask); if (sensor_idx == SENSOR_ID_GC2145) outb(mipi_rx_phy_csr + 0x11, 0x7); else outb(mipi_rx_phy_csr + 0x11, 0x3); } return KDRV_STATUS_OK; }