summaryrefslogtreecommitdiff
path: root/drivers/video/mxc_csi.c
diff options
context:
space:
mode:
authorYe.Li <B37916@freescale.com>2014-06-12 19:39:16 +0800
committerYe Li <ye.li@nxp.com>2017-04-05 14:04:32 +0800
commitbc0639ed8f5069f198067916caf088908492329d (patch)
treeacb8ab692ac87ed0714a7f9573bcb58dd6caddc3 /drivers/video/mxc_csi.c
parent808d447235bd0f9134c7d00fa480cd55b4e0426e (diff)
downloadu-boot-imx-bc0639ed8f5069f198067916caf088908492329d.zip
u-boot-imx-bc0639ed8f5069f198067916caf088908492329d.tar.gz
u-boot-imx-bc0639ed8f5069f198067916caf088908492329d.tar.bz2
ENGR00315894-79 csi: Add csi module
Add csi module. Signed-off-by: Sandor Yu <R01008@freescale.com> Signed-off-by: Ye.Li <B37916@freescale.com> (cherry picked from commit 854ae26758ec8132ef749b98645dd2f43b84e5e2) Signed-off-by: Peng Fan <Peng.Fan@freescale.com> (cherry picked from commit 5f133bd9420109951fd03bd5168801327e929c3b) (cherry picked from commit 16960e59fa3334162d2e2212ee4bc1e7f0c420a3)
Diffstat (limited to 'drivers/video/mxc_csi.c')
-rw-r--r--drivers/video/mxc_csi.c272
1 files changed, 272 insertions, 0 deletions
diff --git a/drivers/video/mxc_csi.c b/drivers/video/mxc_csi.c
new file mode 100644
index 0000000..311f05f
--- /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 <linux/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);
+}
+