diff options
-rw-r--r-- | drivers/video/mxc_csi.c | 272 | ||||
-rw-r--r-- | drivers/video/mxc_csi.h | 153 |
2 files changed, 425 insertions, 0 deletions
diff --git a/drivers/video/mxc_csi.c b/drivers/video/mxc_csi.c new file mode 100644 index 0000000..d0543bc --- /dev/null +++ b/drivers/video/mxc_csi.c @@ -0,0 +1,272 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/*! + * @file fsl_csi.c, this file is derived from mx27_csi.c + * + * @brief mx25 CMOS Sensor interface functions + * + * @ingroup CSI + */ +#include <common.h> +#include <malloc.h> + +#include <asm/arch/imx-regs.h> +#include <asm/errno.h> +#include <asm/io.h> + +#include <linux/string.h> +#include <linux/list.h> + +#include "mxc_csi.h" + +enum { + STD_NTSC = 0, + STD_PAL, +}; + +void __iomem *csi_regbase; + +static void csihw_reset_frame_count(void) +{ + __raw_writel(__raw_readl(CSI_CSICR3) | BIT_FRMCNT_RST, CSI_CSICR3); +} + +static void csihw_reset(void) +{ + csihw_reset_frame_count(); + __raw_writel(CSICR1_RESET_VAL, CSI_CSICR1); + __raw_writel(CSICR2_RESET_VAL, CSI_CSICR2); + __raw_writel(CSICR3_RESET_VAL, CSI_CSICR3); +} + +/*! + * csi_init_interface + * Init csi interface + */ +void csi_init_interface(void) +{ + unsigned int val = 0; + unsigned int imag_para; + + val |= BIT_SOF_POL; + val |= BIT_REDGE; + val |= BIT_GCLK_MODE; + val |= BIT_HSYNC_POL; + val |= BIT_FCC; + val |= 1 << SHIFT_MCLKDIV; + val |= BIT_MCLKEN; + __raw_writel(val, CSI_CSICR1); + + imag_para = (640 << 16) | 960; + __raw_writel(imag_para, CSI_CSIIMAG_PARA); + + val = 0x1010; + val |= BIT_DMA_REFLASH_RFF; + __raw_writel(val, CSI_CSICR3); +} + +void csi_format_swap16(bool enable) +{ + unsigned int val; + + val = __raw_readl(CSI_CSICR1); + if (enable) { + val |= BIT_PACK_DIR; + val |= BIT_SWAP16_EN; + } else { + val &= ~BIT_PACK_DIR; + val &= ~BIT_SWAP16_EN; + } + + __raw_writel(val, CSI_CSICR1); +} + +void csi_enable_int(int arg) +{ + unsigned long cr1 = __raw_readl(CSI_CSICR1); + + if (arg == 1) { + /* still capture needs DMA intterrupt */ + cr1 |= BIT_FB1_DMA_DONE_INTEN; + cr1 |= BIT_FB2_DMA_DONE_INTEN; + } + __raw_writel(cr1, CSI_CSICR1); +} + +void csi_disable_int(void) +{ + unsigned long cr1 = __raw_readl(CSI_CSICR1); + + cr1 &= ~BIT_FB1_DMA_DONE_INTEN; + cr1 &= ~BIT_FB2_DMA_DONE_INTEN; + __raw_writel(cr1, CSI_CSICR1); +} + +void csi_enable(int arg) +{ + unsigned long cr = __raw_readl(CSI_CSICR18); + + if (arg == 1) + cr |= BIT_CSI_ENABLE; + else + cr &= ~BIT_CSI_ENABLE; + __raw_writel(cr, CSI_CSICR18); +} + +void csi_buf_stride_set(u32 stride) +{ + __raw_writel(stride, CSI_CSIFBUF_PARA); +} + +void csi_deinterlace_enable(bool enable) +{ + unsigned long cr18 = __raw_readl(CSI_CSICR18); + + if (enable == true) + cr18 |= BIT_DEINTERLACE_EN; + else + cr18 &= ~BIT_DEINTERLACE_EN; + + __raw_writel(cr18, CSI_CSICR18); +} + +void csi_deinterlace_mode(int mode) +{ + unsigned long cr18 = __raw_readl(CSI_CSICR18); + + if (mode == STD_NTSC) + cr18 |= BIT_NTSC_EN; + else + cr18 &= ~BIT_NTSC_EN; + + __raw_writel(cr18, CSI_CSICR18); +} + +void csi_tvdec_enable(bool enable) +{ + unsigned long cr18 = __raw_readl(CSI_CSICR18); + unsigned long cr1 = __raw_readl(CSI_CSICR1); + + if (enable == true) { + cr18 |= (BIT_TVDECODER_IN_EN | BIT_BASEADDR_SWITCH_EN); + cr1 |= BIT_CCIR_MODE | BIT_EXT_VSYNC; + cr1 &= ~(BIT_SOF_POL | BIT_REDGE); + } else { + cr18 &= ~(BIT_TVDECODER_IN_EN | BIT_BASEADDR_SWITCH_EN); + cr1 &= ~(BIT_CCIR_MODE | BIT_EXT_VSYNC); + cr1 |= BIT_SOF_POL | BIT_REDGE; + } + + __raw_writel(cr18, CSI_CSICR18); + __raw_writel(cr1, CSI_CSICR1); +} + +void csi_set_32bit_imagpara(int width, int height) +{ + int imag_para = 0; + unsigned long cr3 = __raw_readl(CSI_CSICR3); + + imag_para = (width << 16) | height; + __raw_writel(imag_para, CSI_CSIIMAG_PARA); + + + /* reflash the embeded DMA controller */ + __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); +} + +void csi_set_16bit_imagpara(int width, int height) +{ + int imag_para = 0; + unsigned long cr3 = __raw_readl(CSI_CSICR3); + + imag_para = (width << 16) | (height * 2); + __raw_writel(imag_para, CSI_CSIIMAG_PARA); + + /* reflash the embeded DMA controller */ + __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); +} + +void csi_set_12bit_imagpara(int width, int height) +{ + int imag_para = 0; + unsigned long cr3 = __raw_readl(CSI_CSICR3); + + imag_para = (width << 16) | (height * 3 / 2); + __raw_writel(imag_para, CSI_CSIIMAG_PARA); + + /* reflash the embeded DMA controller */ + __raw_writel(cr3 | BIT_DMA_REFLASH_RFF, CSI_CSICR3); +} + +void csi_dmareq_rff_enable(void) +{ + unsigned long cr3 = __raw_readl(CSI_CSICR3); + + cr3 |= BIT_DMA_REQ_EN_RFF; + cr3 |= BIT_HRESP_ERR_EN; + __raw_writel(cr3, CSI_CSICR3); +} + +void csi_dmareq_rff_disable(void) +{ + unsigned long cr3 = __raw_readl(CSI_CSICR3); + + cr3 &= ~BIT_DMA_REQ_EN_RFF; + cr3 &= ~BIT_HRESP_ERR_EN; + __raw_writel(cr3, CSI_CSICR3); +} + +void csi_disable(void) +{ + csi_dmareq_rff_disable(); + csi_disable_int(); + csi_buf_stride_set(0); + csi_deinterlace_enable(false); + csi_tvdec_enable(false); + csi_enable(0); +} + +void csi_config(struct csi_conf_param *csi_conf) +{ + csi_regbase = (u32 *)CSI1_BASE_ADDR; + + csihw_reset(); + + csi_init_interface(); + csi_dmareq_rff_disable(); + + switch (csi_conf->bpp) { + case 32: + csi_set_32bit_imagpara(csi_conf->width, csi_conf->height); + break; + case 16: + csi_set_16bit_imagpara(csi_conf->width, csi_conf->height); + break; + default: + printf(" %s case not supported, bpp=%d\n", + __func__, csi_conf->bpp); + return; + } + + __raw_writel((u32)csi_conf->fb0addr, CSI_CSIDMASA_FB1); + __raw_writel((u32)csi_conf->fb1addr, CSI_CSIDMASA_FB2); + + csi_buf_stride_set(0); + if (csi_conf->btvmode) { + /* Enable csi PAL/NTSC deinterlace mode */ + csi_buf_stride_set(csi_conf->width); + csi_deinterlace_mode(csi_conf->std); + csi_deinterlace_enable(true); + csi_tvdec_enable(true); + } + + /* start csi */ + csi_dmareq_rff_enable(); + csi_enable_int(1); + csi_enable(1); +} + diff --git a/drivers/video/mxc_csi.h b/drivers/video/mxc_csi.h new file mode 100644 index 0000000..ef671e4 --- /dev/null +++ b/drivers/video/mxc_csi.h @@ -0,0 +1,153 @@ +/* + * Copyright (C) 2014 Freescale Semiconductor, Inc. All Rights Reserved. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/*! + * @file mxc_csi.h + * + * @brief mxc CMOS Sensor interface functions + * + * @ingroup CSI + */ + +#ifndef MXC_CSI_H +#define MXC_CSI_H + +/* reset values */ +#define CSICR1_RESET_VAL 0x40000800 +#define CSICR2_RESET_VAL 0x0 +#define CSICR3_RESET_VAL 0x0 + +/* csi control reg 1 */ +#define BIT_SWAP16_EN (0x1 << 31) +#define BIT_EXT_VSYNC (0x1 << 30) +#define BIT_EOF_INT_EN (0x1 << 29) +#define BIT_PRP_IF_EN (0x1 << 28) +#define BIT_CCIR_MODE (0x1 << 27) +#define BIT_COF_INT_EN (0x1 << 26) +#define BIT_SF_OR_INTEN (0x1 << 25) +#define BIT_RF_OR_INTEN (0x1 << 24) +#define BIT_SFF_DMA_DONE_INTEN (0x1 << 22) +#define BIT_STATFF_INTEN (0x1 << 21) +#define BIT_FB2_DMA_DONE_INTEN (0x1 << 20) +#define BIT_FB1_DMA_DONE_INTEN (0x1 << 19) +#define BIT_RXFF_INTEN (0x1 << 18) +#define BIT_SOF_POL (0x1 << 17) +#define BIT_SOF_INTEN (0x1 << 16) +#define BIT_MCLKDIV (0xF << 12) +#define BIT_HSYNC_POL (0x1 << 11) +#define BIT_CCIR_EN (0x1 << 10) +#define BIT_MCLKEN (0x1 << 9) +#define BIT_FCC (0x1 << 8) +#define BIT_PACK_DIR (0x1 << 7) +#define BIT_CLR_STATFIFO (0x1 << 6) +#define BIT_CLR_RXFIFO (0x1 << 5) +#define BIT_GCLK_MODE (0x1 << 4) +#define BIT_INV_DATA (0x1 << 3) +#define BIT_INV_PCLK (0x1 << 2) +#define BIT_REDGE (0x1 << 1) +#define BIT_PIXEL_BIT (0x1 << 0) + +#define SHIFT_MCLKDIV 12 + +/* control reg 3 */ +#define BIT_FRMCNT (0xFFFF << 16) +#define BIT_FRMCNT_RST (0x1 << 15) +#define BIT_DMA_REFLASH_RFF (0x1 << 14) +#define BIT_DMA_REFLASH_SFF (0x1 << 13) +#define BIT_DMA_REQ_EN_RFF (0x1 << 12) +#define BIT_DMA_REQ_EN_SFF (0x1 << 11) +#define BIT_STATFF_LEVEL (0x7 << 8) +#define BIT_HRESP_ERR_EN (0x1 << 7) +#define BIT_RXFF_LEVEL (0x7 << 4) +#define BIT_TWO_8BIT_SENSOR (0x1 << 3) +#define BIT_ZERO_PACK_EN (0x1 << 2) +#define BIT_ECC_INT_EN (0x1 << 1) +#define BIT_ECC_AUTO_EN (0x1 << 0) + +#define SHIFT_FRMCNT 16 + +/* csi status reg */ +#define BIT_SFF_OR_INT (0x1 << 25) +#define BIT_RFF_OR_INT (0x1 << 24) +#define BIT_DMA_TSF_DONE_SFF (0x1 << 22) +#define BIT_STATFF_INT (0x1 << 21) +#define BIT_DMA_TSF_DONE_FB2 (0x1 << 20) +#define BIT_DMA_TSF_DONE_FB1 (0x1 << 19) +#define BIT_RXFF_INT (0x1 << 18) +#define BIT_EOF_INT (0x1 << 17) +#define BIT_SOF_INT (0x1 << 16) +#define BIT_F2_INT (0x1 << 15) +#define BIT_F1_INT (0x1 << 14) +#define BIT_COF_INT (0x1 << 13) +#define BIT_HRESP_ERR_INT (0x1 << 7) +#define BIT_ECC_INT (0x1 << 1) +#define BIT_DRDY (0x1 << 0) + +/* csi control reg 18 */ +#define BIT_CSI_ENABLE (0x1 << 31) +#define BIT_BASEADDR_SWITCH_SEL (0x1 << 5) +#define BIT_BASEADDR_SWITCH_EN (0x1 << 4) +#define BIT_PARALLEL24_EN (0x1 << 3) +#define BIT_DEINTERLACE_EN (0x1 << 2) +#define BIT_TVDECODER_IN_EN (0x1 << 1) +#define BIT_NTSC_EN (0x1 << 0) + +#define CSI_MCLK_VF 1 +#define CSI_MCLK_ENC 2 +#define CSI_MCLK_RAW 4 +#define CSI_MCLK_I2C 8 + +#define CSI_CSICR1 (csi_regbase) +#define CSI_CSICR2 (csi_regbase + 0x4) +#define CSI_CSICR3 (csi_regbase + 0x8) +#define CSI_STATFIFO (csi_regbase + 0xC) +#define CSI_CSIRXFIFO (csi_regbase + 0x10) +#define CSI_CSIRXCNT (csi_regbase + 0x14) +#define CSI_CSISR (csi_regbase + 0x18) +#define CSI_CSIDBG (csi_regbase + 0x1C) +#define CSI_CSIDMASA_STATFIFO (csi_regbase + 0x20) +#define CSI_CSIDMATS_STATFIFO (csi_regbase + 0x24) +#define CSI_CSIDMASA_FB1 (csi_regbase + 0x28) +#define CSI_CSIDMASA_FB2 (csi_regbase + 0x2C) +#define CSI_CSIFBUF_PARA (csi_regbase + 0x30) +#define CSI_CSIIMAG_PARA (csi_regbase + 0x34) +#define CSI_CSICR18 (csi_regbase + 0x48) +#define CSI_CSICR19 (csi_regbase + 0x4c) + +struct mxs_csi_regs { + u32 csi_csicr1; /* 0x0 */ + u32 csi_csicr2; /* 0x4 */ + u32 csi_csicr3; /* 0x8 */ + u32 csi_statfifo; /* 0xC */ + u32 csi_csirxfifo; /* 0x10 */ + u32 csi_csirxcnt; /* 0x14 */ + u32 csi_csisr; /* 0x18 */ + u32 csi_csidbg; /* 0x1C */ + u32 csi_csidmasa_statfifo; /* 0x20 */ + u32 csi_csidmats_statfifo; /* 0x24 */ + u32 csi_csidmasa_fb1; /* 0x28 */ + u32 csi_csidmasa_fb2; /* 0x2C */ + u32 csi_csifbuf_para; /* 0x30 */ + u32 csi_csiimag_para; /* 0x34 */ + u32 reserver[4]; + u32 csi_csicr18; /* 0x48 */ + u32 csi_csicr19; /* 0x4c */ +}; + +struct csi_conf_param { + unsigned short width; + unsigned short height; + unsigned int pixel_fmt; + unsigned int bpp; + bool btvmode; + unsigned int std; + void *fb0addr; + void *fb1addr; +}; + +void csi_config(struct csi_conf_param *csi_conf); +void csi_disable(void); +#endif |