source "drivers/media/platform/s5p-tv/Kconfig"
source "drivers/media/platform/am437x/Kconfig"
source "drivers/media/platform/xilinx/Kconfig"
+source "drivers/media/platform/rk-isp10/Kconfig"
endif # V4L_PLATFORM_DRIVERS
obj-$(CONFIG_VIDEO_ROCKCHIP_VPU) += rockchip-vpu/
ccflags-y += -I$(srctree)/drivers/media/i2c
+
+obj-$(CONFIG_VIDEO_RK_CIF_ISP10) += rk-isp10/
--- /dev/null
+config VIDEO_RK_CIF_ISP10
+ tristate "Rockchip cif isp10 camera sensors"
+ depends on VIDEO_V4L2 && I2C
+ select VIDEOBUF_GEN
+ select VIDEOBUF_DMA_CONTIG
+ select VIDEOBUF_VMALLOC
+ default n
+
+ ---help---
+ Say Y here to enable selecting the
+ rockchip cif isp10 camera sensors
--- /dev/null
+
+obj-$(CONFIG_VIDEO_RK_CIF_ISP10) += video_cif_isp10.o
+video_cif_isp10-objs += cif_isp10.o cif_isp10_img_src.o cif_isp10_img_src_v4l2-subdev.o cif_isp10_isp.o cif_isp10_pltfrm.o cif_isp10_rk3288.o cif_isp10_rk3399.o cif_isp10_v4l2.o
\ No newline at end of file
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/videodev2.h>
+#include <media/videobuf-dma-contig.h>
+#include "cif_isp10_regs.h"
+#include "cif_isp10.h"
+#include <linux/pm_runtime.h>
+#include <linux/vmalloc.h>
+
+static int cif_isp10_mipi_isr(
+ unsigned int mis,
+ void *cntxt);
+static int cif_isp10_isp_isr(
+ unsigned int mis,
+ void *cntxt);
+static void init_output_formats(void);
+
+struct v4l2_fmtdesc output_formats[MAX_NB_FORMATS];
+
+/* JPEG quantization tables for JPEG encoding */
+/* DC luma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char dc_luma_table_annex_k[] = {
+ 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b
+};
+
+/* DC chroma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char dc_chroma_table_annex_k[] = {
+ 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
+ 0x08, 0x09, 0x0a, 0x0b
+};
+
+/* AC luma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char ac_luma_table_annex_k[] = {
+ 0x00, 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03,
+ 0x05, 0x05, 0x04, 0x04, 0x00, 0x00, 0x01, 0x7d,
+ 0x01, 0x02, 0x03, 0x00, 0x04, 0x11, 0x05, 0x12,
+ 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61, 0x07,
+ 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08,
+ 0x23, 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0,
+ 0x24, 0x33, 0x62, 0x72, 0x82, 0x09, 0x0a, 0x16,
+ 0x17, 0x18, 0x19, 0x1a, 0x25, 0x26, 0x27, 0x28,
+ 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,
+ 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49,
+ 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59,
+ 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69,
+ 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78, 0x79,
+ 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88, 0x89,
+ 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
+ 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7,
+ 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6,
+ 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3, 0xc4, 0xc5,
+ 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3, 0xd4,
+ 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2,
+ 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea,
+ 0xf1, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+/* AC Chroma table according to ISO/IEC 10918-1 annex K */
+static const unsigned char ac_chroma_table_annex_k[] = {
+ 0x00, 0x02, 0x01, 0x02, 0x04, 0x04, 0x03, 0x04,
+ 0x07, 0x05, 0x04, 0x04, 0x00, 0x01, 0x02, 0x77,
+ 0x00, 0x01, 0x02, 0x03, 0x11, 0x04, 0x05, 0x21,
+ 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
+ 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91,
+ 0xa1, 0xb1, 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0,
+ 0x15, 0x62, 0x72, 0xd1, 0x0a, 0x16, 0x24, 0x34,
+ 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19, 0x1a, 0x26,
+ 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
+ 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48,
+ 0x49, 0x4a, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
+ 0x59, 0x5a, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68,
+ 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
+ 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
+ 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96,
+ 0x97, 0x98, 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5,
+ 0xa6, 0xa7, 0xa8, 0xa9, 0xaa, 0xb2, 0xb3, 0xb4,
+ 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2, 0xc3,
+ 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
+ 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda,
+ 0xe2, 0xe3, 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9,
+ 0xea, 0xf2, 0xf3, 0xf4, 0xf5, 0xf6, 0xf7, 0xf8,
+ 0xf9, 0xfa
+};
+
+/* Standard JPEG quantization tables */
+/* luma */
+/* According to JPEG spec:
+ * [
+ * 16, 11, 10, 16, 24, 40, 51, 61,
+ * 12, 12, 14, 19, 26, 58, 60, 55,
+ * 14, 13, 16, 24, 40, 57, 69, 56,
+ * 14, 17, 22, 29, 51, 87, 80, 62,
+ * 18, 22, 37, 56, 68, 109, 103, 77,
+ * 24, 35, 55, 64, 81, 104, 113, 92,
+ * 49, 64, 78, 87, 103, 121, 120, 101,
+ * 72, 92, 95, 98, 112, 100, 103, 99
+ * ]
+ */
+
+/* CIF needs it in zigzag order */
+static const unsigned char yq_table_base_zigzag[] = {
+ 16, 11, 12, 14, 12, 10, 16, 14,
+ 13, 14, 18, 17, 16, 19, 24, 40,
+ 26, 24, 22, 22, 24, 49, 35, 37,
+ 29, 40, 58, 51, 61, 60, 57, 51,
+ 56, 55, 64, 72, 92, 78, 64, 68,
+ 87, 69, 55, 56, 80, 109, 81, 87,
+ 95, 98, 103, 104, 103, 62, 77, 113,
+ 121, 112, 100, 120, 92, 101, 103, 99
+};
+
+/* chroma */
+/* According to JPEG spec:
+ * [
+ * 17, 18, 24, 47, 99, 99, 99, 99,
+ * 18, 21, 26, 66, 99, 99, 99, 99,
+ * 24, 26, 56, 99, 99, 99, 99, 99,
+ * 47, 66, 99, 99, 99, 99, 99, 99,
+ * 99, 99, 99, 99, 99, 99, 99, 99,
+ * 99, 99, 99, 99, 99, 99, 99, 99,
+ * 99, 99, 99, 99, 99, 99, 99, 99,
+ * 99, 99, 99, 99, 99, 99, 99, 99
+ * ]
+ */
+
+/* CIF needs it in zigzag order */
+static const unsigned char uvq_table_base_zigzag[] = {
+ 17, 18, 18, 24, 21, 24, 47, 26,
+ 26, 47, 99, 66, 56, 66, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99,
+ 99, 99, 99, 99, 99, 99, 99, 99
+};
+
+static struct cif_isp10_fmt cif_isp10_output_format[] = {
+/* ************* YUV422 ************* */
+{
+ .name = "YUV422-Interleaved",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YUV422-Interleaved",
+ .fourcc = V4L2_PIX_FMT_YUYV,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YVU422-Interleaved",
+ .fourcc = V4L2_PIX_FMT_UYVY,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YUV422-Planar",
+ .fourcc = V4L2_PIX_FMT_YUV422P,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YUV422-Semi-Planar",
+ .fourcc = V4L2_PIX_FMT_NV16,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************* YUV420 ************* */
+{
+ .name = "YUV420-Planar",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .flags = 0,
+ .depth = 12,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YUV420-Planar",
+ .fourcc = V4L2_PIX_FMT_YUV420,
+ .flags = 0,
+ .depth = 12,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YVU420-Planar",
+ .fourcc = V4L2_PIX_FMT_YVU420,
+ .flags = 0,
+ .depth = 12,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YUV420-Semi-Planar",
+ .fourcc = V4L2_PIX_FMT_NV12,
+ .flags = 0,
+ .depth = 12,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YVU420-Semi-Planar",
+ .fourcc = V4L2_PIX_FMT_NV21,
+ .flags = 0,
+ .depth = 12,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************* YUV400 ************* */
+{
+ .name = "YVU400-Grey-Planar",
+ .fourcc = V4L2_PIX_FMT_GREY,
+ .flags = 0,
+ .depth = 8,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************* YUV444 ************* */
+{
+ .name = "YVU444-Planar",
+ .fourcc = V4L2_PIX_FMT_YUV444,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+{
+ .name = "YVU444-Semi-Planar",
+ .fourcc = V4L2_PIX_FMT_NV24,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************* JPEG ************* */
+{
+ .name = "JPEG",
+ .fourcc = V4L2_PIX_FMT_JPEG,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************ RGB565 *********** */
+{
+ .name = "RGB565",
+ .fourcc = V4L2_PIX_FMT_RGB565,
+ .flags = 0,
+ .depth = 16,
+ .rotation = false,
+ .overlay = false,
+},
+/* ************ SGRBG8 *********** */
+{
+ .name = "SGRBG8",
+ .fourcc = V4L2_PIX_FMT_SGRBG8,
+ .flags = 0,
+ .depth = 8,
+ .rotation = false,
+ .overlay = false,
+},
+};
+
+struct cif_isp10_hw_error {
+ char *name;
+ unsigned int count;
+ unsigned int mask;
+ unsigned int type; /* isp:0 ;mipi:1 */
+};
+
+static struct cif_isp10_hw_error cif_isp10_hw_errors[] = {
+ {
+ .name = "isp_data_loss",
+ .count = 0,
+ .mask = CIF_ISP_DATA_LOSS,
+ .type = 0,
+ },
+ {
+ .name = "isp_pic_size_err",
+ .count = 0,
+ .mask = CIF_ISP_PIC_SIZE_ERROR,
+ .type = 0,
+ },
+ {
+ .name = "mipi_fifo_err",
+ .count = 0,
+ .mask = CIF_MIPI_SYNC_FIFO_OVFLW(1),
+ .type = 1,
+ },
+ {
+ .name = "dphy_err_sot",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_SOT(3),
+ .type = 1,
+ },
+ {
+ .name = "dphy_err_sot_sync",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_SOT_SYNC(3),
+ .type = 1,
+ },
+ {
+ .name = "dphy_err_eot_sync",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_EOT_SYNC(3),
+ .type = 1,
+ },
+ {
+ .name = "dphy_err_ctrl",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_CTRL(3),
+ .type = 1,
+ },
+ {
+ .name = "csi_err_protocol",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_PROTOCOL,
+ .type = 2,
+ },
+ {
+ .name = "csi_err_ecc1",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_ECC1,
+ .type = 2,
+ },
+ {
+ .name = "csi_err_ecc2",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_ECC2,
+ .type = 2,
+ },
+ {
+ .name = "csi_err_cs",
+ .count = 0,
+ .mask = CIF_MIPI_ERR_CS,
+ .type = 2,
+ },
+ {
+ .name = "fifo_ovf",
+ .count = 0,
+ .mask = (3 << 0),
+ .type = 2,
+ },
+ {
+ .name = "isp_outform",
+ .count = 0,
+ .mask = CIF_ISP_ERR_OUTFORM_SIZE,
+ .type = 0,
+ },
+ {
+ .name = "isp_stab",
+ .count = 0,
+ .mask = CIF_ISP_ERR_IS_SIZE,
+ .type = 0,
+ },
+ {
+ .name = "isp_inform",
+ .count = 0,
+ .mask = CIF_ISP_ERR_INFORM_SIZE,
+ .type = 0,
+ }
+};
+
+/* Defines */
+
+#define CIF_ISP10_INVALID_BUFF_ADDR ((u32)~0)
+#define CIF_ISP10_MI_IS_BUSY(dev)\
+ (dev->config.mi_config.mp.busy ||\
+ dev->config.mi_config.sp.busy ||\
+ dev->config.mi_config.dma.busy)
+enum {
+ CIF_ISP10_ASYNC_JPEG = 0x1,
+ CIF_ISP10_ASYNC_YCFLT = 0x2,
+ CIF_ISP10_ASYNC_ISM = 0x4,
+ CIF_ISP10_ASYNC_DMA = 0x8
+};
+
+#define CIF_ISP10_ALWAYS_ASYNC 0x00
+#define CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS (false)
+
+#ifndef DIV_ROUND_UP
+#define DIV_ROUND_UP(x, y) (((x) + (y) - 1) / (y))
+#endif
+
+#ifndef DIV_TRUNCATE
+#define DIV_TRUNCATE(x, y) ((x) / (y))
+#endif
+
+/* Structures and Types */
+
+/* Static Functions */
+static const char *cif_isp10_interface_string(
+ enum pltfrm_cam_itf_type itf)
+{
+ switch (itf) {
+ case PLTFRM_CAM_ITF_MIPI:
+ return "MIPI";
+ case PLTFRM_CAM_ITF_BT601_8:
+ return "DVP_BT601_8Bit";
+ case PLTFRM_CAM_ITF_BT656_8:
+ return "DVP_BT656_8Bit";
+ case PLTFRM_CAM_ITF_BT601_10:
+ return "DVP_BT601_10Bit";
+ case PLTFRM_CAM_ITF_BT656_10:
+ return "DVP_BT656_10Bit";
+ case PLTFRM_CAM_ITF_BT601_12:
+ return "DVP_BT601_12Bit";
+ case PLTFRM_CAM_ITF_BT656_12:
+ return "DVP_BT656_12Bit";
+ case PLTFRM_CAM_ITF_BT601_16:
+ return "DVP_BT601_16Bit";
+ case PLTFRM_CAM_ITF_BT656_16:
+ return "DVP_BT656_16Bit";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+static const char *cif_isp10_img_src_state_string(
+ enum cif_isp10_img_src_state state)
+{
+ switch (state) {
+ case CIF_ISP10_IMG_SRC_STATE_OFF:
+ return "OFF";
+ case CIF_ISP10_IMG_SRC_STATE_SW_STNDBY:
+ return "SW_STNDBY";
+ case CIF_ISP10_IMG_SRC_STATE_STREAMING:
+ return "STREAMING";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+static const char *cif_isp10_state_string(
+ enum cif_isp10_state state)
+{
+ switch (state) {
+ case CIF_ISP10_STATE_DISABLED:
+ return "DISABLED";
+ case CIF_ISP10_STATE_INACTIVE:
+ return "INACTIVE";
+ case CIF_ISP10_STATE_READY:
+ return "READY";
+ case CIF_ISP10_STATE_STREAMING:
+ return "STREAMING";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+static const char *cif_isp10_pm_state_string(
+ enum cif_isp10_pm_state pm_state)
+{
+ switch (pm_state) {
+ case CIF_ISP10_PM_STATE_OFF:
+ return "OFF";
+ case CIF_ISP10_PM_STATE_SW_STNDBY:
+ return "STANDBY";
+ case CIF_ISP10_PM_STATE_SUSPENDED:
+ return "SUSPENDED";
+ case CIF_ISP10_PM_STATE_STREAMING:
+ return "STREAMING";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+static const char *cif_isp10_stream_id_string(
+ enum cif_isp10_stream_id stream_id)
+{
+ switch (stream_id) {
+ case CIF_ISP10_STREAM_SP:
+ return "SP";
+ case CIF_ISP10_STREAM_MP:
+ return "MP";
+ case CIF_ISP10_STREAM_DMA:
+ return "DMA";
+ case CIF_ISP10_STREAM_ISP:
+ return "ISP";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+static const char *cif_isp10_inp_string(
+ enum cif_isp10_inp inp)
+{
+ switch (inp) {
+ case CIF_ISP10_INP_CSI:
+ return "CSI";
+ case CIF_ISP10_INP_CPI:
+ return "CPI";
+ case CIF_ISP10_INP_DMA:
+ return "DMA(ISP)";
+ case CIF_ISP10_INP_DMA_IE:
+ return "DMA(Image Effects)";
+ case CIF_ISP10_INP_DMA_SP:
+ return "DMA(SP)";
+ default:
+ return "UNKNOWN/UNSUPPORTED";
+ }
+}
+
+enum cif_isp10_inp cif_isp10_input_index2inp(
+ struct cif_isp10_device *dev,
+ unsigned int input)
+{
+ struct pltfrm_cam_itf itf;
+
+ if (input >= dev->img_src_cnt)
+ return input - dev->img_src_cnt + CIF_ISP10_INP_DMA;
+
+ cif_isp10_pltfrm_g_interface_config(
+ dev->img_src_array[input],
+ &itf);
+ if (PLTFRM_CAM_ITF_IS_MIPI(itf.type))
+ return CIF_ISP10_INP_CSI;
+ if (PLTFRM_CAM_ITF_IS_DVP(itf.type))
+ return CIF_ISP10_INP_CPI;
+
+ return -EINVAL;
+}
+
+static const char *cif_isp10_pix_fmt_string(int pixfmt)
+{
+ switch (pixfmt) {
+ case CIF_YUV400:
+ return "YUV400";
+ case CIF_YUV420I:
+ return "YUV420I";
+ case CIF_YUV420SP:
+ return "YUV420SP";
+ case CIF_YUV420P:
+ return "YUV420P";
+ case CIF_YVU420I:
+ return "YVU420I";
+ case CIF_YVU420SP:
+ return "YVU420SP";
+ case CIF_YVU420P:
+ return "YVU420P";
+ case CIF_YUV422I:
+ return "YUV422I";
+ case CIF_YUV422SP:
+ return "YUV422SP";
+ case CIF_YUV422P:
+ return "YUV422P";
+ case CIF_YVU422I:
+ return "YVU422I";
+ case CIF_YVU422SP:
+ return "YVU422SP";
+ case CIF_YVU422P:
+ return "YVU422P";
+ case CIF_YUV444I:
+ return "YUV444I";
+ case CIF_YUV444SP:
+ return "YUV444SP";
+ case CIF_YUV444P:
+ return "YUV444P";
+ case CIF_YVU444I:
+ return "YVU444I";
+ case CIF_YVU444SP:
+ return "YVU444SP";
+ case CIF_YVU444P:
+ return "YVU444SP";
+ case CIF_UYV400:
+ return "UYV400";
+ case CIF_UYV420I:
+ return "UYV420I";
+ case CIF_UYV420SP:
+ return "UYV420SP";
+ case CIF_UYV420P:
+ return "UYV420P";
+ case CIF_VYU420I:
+ return "VYU420I";
+ case CIF_VYU420SP:
+ return "VYU420SP";
+ case CIF_VYU420P:
+ return "VYU420P";
+ case CIF_UYV422I:
+ return "UYV422I";
+ case CIF_UYV422SP:
+ return "UYV422I";
+ case CIF_UYV422P:
+ return "UYV422P";
+ case CIF_VYU422I:
+ return "VYU422I";
+ case CIF_VYU422SP:
+ return "VYU422SP";
+ case CIF_VYU422P:
+ return "VYU422P";
+ case CIF_UYV444I:
+ return "UYV444I";
+ case CIF_UYV444SP:
+ return "UYV444SP";
+ case CIF_UYV444P:
+ return "UYV444P";
+ case CIF_VYU444I:
+ return "VYU444I";
+ case CIF_VYU444SP:
+ return "VYU444SP";
+ case CIF_VYU444P:
+ return "VYU444P";
+ case CIF_RGB565:
+ return "RGB565";
+ case CIF_RGB666:
+ return "RGB666";
+ case CIF_RGB888:
+ return "RGB888";
+ case CIF_BAYER_SBGGR8:
+ return "BAYER BGGR8";
+ case CIF_BAYER_SGBRG8:
+ return "BAYER GBRG8";
+ case CIF_BAYER_SGRBG8:
+ return "BAYER GRBG8";
+ case CIF_BAYER_SRGGB8:
+ return "BAYER RGGB8";
+ case CIF_BAYER_SBGGR10:
+ return "BAYER BGGR10";
+ case CIF_BAYER_SGBRG10:
+ return "BAYER GBRG10";
+ case CIF_BAYER_SGRBG10:
+ return "BAYER GRBG10";
+ case CIF_BAYER_SRGGB10:
+ return "BAYER RGGB10";
+ case CIF_BAYER_SBGGR12:
+ return "BAYER BGGR12";
+ case CIF_BAYER_SGBRG12:
+ return "BAYER GBRG12";
+ case CIF_BAYER_SGRBG12:
+ return "BAYER GRBG12";
+ case CIF_BAYER_SRGGB12:
+ return "BAYER RGGB12";
+ case CIF_DATA:
+ return "DATA";
+ case CIF_JPEG:
+ return "JPEG";
+ default:
+ return "unknown/unsupported";
+ }
+}
+
+static void cif_isp10_debug_print_mi_sp(struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_info(dev->dev,
+ "\n MI_CTRL 0x%08x/0x%08x\n"
+ " MI_STATUS 0x%08x\n"
+ " MI_RIS 0x%08x/0x%08x\n"
+ " MI_IMSC 0x%08x\n"
+ " MI_SP_Y_SIZE %d/%d\n"
+ " MI_SP_CB_SIZE %d/%d\n"
+ " MI_SP_CR_SIZE %d/%d\n"
+ " MI_SP_PIC_WIDTH %d\n"
+ " MI_SP_PIC_HEIGHT %d\n"
+ " MI_SP_PIC_LLENGTH %d\n"
+ " MI_SP_PIC_SIZE %d\n"
+ " MI_SP_Y_BASE_AD 0x%08x/0x%08x\n"
+ " MI_SP_Y_OFFS_CNT %d/%d\n"
+ " MI_SP_Y_OFFS_CNT_START %d\n"
+ " MI_SP_CB_OFFS_CNT %d/%d\n"
+ " MI_SP_CB_OFFS_CNT_START %d\n"
+ " MI_SP_CR_OFFS_CNT %d/%d\n"
+ " MI_SP_CR_OFFS_CNT_START %d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_STATUS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_RIS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MIS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_IMSC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_PIC_WIDTH),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_PIC_HEIGHT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_LLENGTH),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_PIC_SIZE),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_OFFS_CNT_START),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_OFFS_CNT_START),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_OFFS_CNT_START));
+}
+
+static void cif_isp10_debug_print_mi_mp(struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_info(dev->dev,
+ "\n MI_CTRL 0x%08x/0x%08x\n"
+ " MI_STATUS 0x%08x\n"
+ " MI_BYTE_CNT %d\n"
+ " MI_RIS 0x%08x/0x%08x\n"
+ " MI_IMSC 0x%08x\n"
+ " MI_MP_Y_SIZE %d/%d\n"
+ " MI_MP_CB_SIZE %d/%d\n"
+ " MI_MP_CR_SIZE %d/%d\n"
+ " MI_MP_Y_BASE_AD 0x%08x/0x%08x\n"
+ " MI_MP_Y_OFFS_CNT %d/%d\n"
+ " MI_MP_Y_OFFS_CNT_START %d\n"
+ " MI_MP_CB_OFFS_CNT %d/%d\n"
+ " MI_MP_CB_OFFS_CNT_START %d\n"
+ " MI_MP_CR_OFFS_CNT %d/%d\n"
+ " MI_MP_CR_OFFS_CNT_START %d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_STATUS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_BYTE_CNT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_RIS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MIS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_IMSC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_OFFS_CNT_START),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_OFFS_CNT_START),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_OFFS_CNT_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_OFFS_CNT_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_OFFS_CNT_START));
+}
+
+static void cif_isp10_debug_print_srsz(struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_info(dev->dev,
+ "\n SRSZ_CTRL 0x%08x/0x%08x\n"
+ " SRSZ_SCALE_HY %d/%d\n"
+ " SRSZ_SCALE_HCB %d/%d\n"
+ " SRSZ_SCALE_HCR %d/%d\n"
+ " SRSZ_SCALE_VY %d/%d\n"
+ " SRSZ_SCALE_VC %d/%d\n"
+ " SRSZ_PHASE_HY %d/%d\n"
+ " SRSZ_PHASE_HC %d/%d\n"
+ " SRSZ_PHASE_VY %d/%d\n"
+ " SRSZ_PHASE_VC %d/%d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCB),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCB_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCR),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCR_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VC_SHD));
+}
+
+static void cif_isp10_debug_print_mrsz(struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_info(dev->dev,
+ "\n MRSZ_CTRL 0x%08x/0x%08x\n"
+ " MRSZ_SCALE_HY %d/%d\n"
+ " MRSZ_SCALE_HCB %d/%d\n"
+ " MRSZ_SCALE_HCR %d/%d\n"
+ " MRSZ_SCALE_VY %d/%d\n"
+ " MRSZ_SCALE_VC %d/%d\n"
+ " MRSZ_PHASE_HY %d/%d\n"
+ " MRSZ_PHASE_HC %d/%d\n"
+ " MRSZ_PHASE_VY %d/%d\n"
+ " MRSZ_PHASE_VC %d/%d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCB),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCB_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCR),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCR_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VC_SHD));
+}
+
+static void cif_isp10_debug_print_block(
+ struct cif_isp10_device *dev,
+ const char *block_name)
+{
+ if (!strncmp(block_name, "all", 3)) {
+ cif_isp10_debug_print_srsz(dev);
+ cif_isp10_debug_print_mrsz(dev);
+ cif_isp10_debug_print_mi_sp(dev);
+ cif_isp10_debug_print_mi_mp(dev);
+ } else if (!strncmp(block_name, "srsz", 4)) {
+ cif_isp10_debug_print_srsz(dev);
+ } else if (!strncmp(block_name, "mrsz", 4)) {
+ cif_isp10_debug_print_mrsz(dev);
+ } else if (!strncmp(block_name, "mi_sp", 5)) {
+ cif_isp10_debug_print_mi_sp(dev);
+ } else if (!strncmp(block_name, "mi_mp", 5)) {
+ cif_isp10_debug_print_mi_mp(dev);
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown block %s\n", block_name);
+ }
+}
+
+static u32 cif_isp10_calc_llength(
+ u32 width,
+ u32 stride,
+ enum cif_isp10_pix_fmt pix_fmt)
+{
+ if (stride == 0)
+ return width;
+
+ if (CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt)) {
+ u32 num_cplanes =
+ CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt);
+ if (num_cplanes == 0)
+ return 8 * stride / CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+ else
+ return stride;
+ } else if (CIF_ISP10_PIX_FMT_IS_RGB(pix_fmt)) {
+ return 8 * stride / CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+ } else {
+ return width;
+ }
+}
+
+static int cif_isp10_set_pm_state(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_pm_state pm_state)
+{
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%s -> %s\n",
+ cif_isp10_pm_state_string(dev->pm_state),
+ cif_isp10_pm_state_string(pm_state));
+
+ if (dev->pm_state == pm_state)
+ return 0;
+
+ switch (pm_state) {
+ case CIF_ISP10_PM_STATE_OFF:
+ case CIF_ISP10_PM_STATE_SUSPENDED:
+ if ((dev->pm_state == CIF_ISP10_PM_STATE_SW_STNDBY) ||
+ (dev->pm_state == CIF_ISP10_PM_STATE_STREAMING)) {
+ pm_runtime_put_sync(dev->dev);
+ }
+ break;
+ case CIF_ISP10_PM_STATE_SW_STNDBY:
+ case CIF_ISP10_PM_STATE_STREAMING:
+ if ((dev->pm_state == CIF_ISP10_PM_STATE_OFF) ||
+ (dev->pm_state == CIF_ISP10_PM_STATE_SUSPENDED)) {
+ pm_runtime_get_sync(dev->dev);
+ }
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown or unsupported PM state %d\n", pm_state);
+ return -EINVAL;
+ }
+
+ dev->pm_state = pm_state;
+
+ return 0;
+}
+
+static int cif_isp10_img_src_set_state(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_img_src_state state)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%s -> %s\n",
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ cif_isp10_img_src_state_string(state));
+
+ if (dev->img_src_state == state)
+ return 0;
+
+ switch (state) {
+ case CIF_ISP10_IMG_SRC_STATE_OFF:
+ ret = cif_isp10_img_src_s_power(dev->img_src, false);
+ break;
+ case CIF_ISP10_IMG_SRC_STATE_SW_STNDBY:
+ if (dev->img_src_state == CIF_ISP10_IMG_SRC_STATE_STREAMING) {
+ ret = cif_isp10_img_src_s_streaming(
+ dev->img_src, false);
+ } else {
+ ret = cif_isp10_img_src_s_power(dev->img_src, true);
+ }
+ break;
+ case CIF_ISP10_IMG_SRC_STATE_STREAMING:
+ if (dev->config.flash_mode !=
+ CIF_ISP10_FLASH_MODE_OFF)
+ cif_isp10_img_src_s_ctrl(dev->img_src,
+ CIF_ISP10_CID_FLASH_MODE,
+ dev->config.flash_mode);
+ ret = cif_isp10_img_src_s_streaming(dev->img_src, true);
+ break;
+ default:
+ break;
+ }
+
+ if ((dev->config.flash_mode != CIF_ISP10_FLASH_MODE_OFF) &&
+ (IS_ERR_VALUE(ret) ||
+ (state == CIF_ISP10_IMG_SRC_STATE_OFF)))
+ cif_isp10_img_src_s_ctrl(dev->img_src,
+ CIF_ISP10_CID_FLASH_MODE,
+ CIF_ISP10_FLASH_MODE_OFF);
+
+ if (!IS_ERR_VALUE(ret))
+ dev->img_src_state = state;
+ else
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+
+ return ret;
+}
+
+static int cif_isp10_img_srcs_init(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ memset(dev->img_src_array, 0x00, sizeof(dev->img_src_array));
+ dev->img_src_cnt = cif_isp10_pltfrm_get_img_src_device(dev->dev,
+ dev->img_src_array, CIF_ISP10_NUM_INPUTS);
+
+ if (dev->img_src_cnt > 0)
+ return 0;
+
+ dev->img_src_cnt = 0;
+ ret = -EFAULT;
+
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_img_src_select_strm_fmt(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ u32 index;
+ struct cif_isp10_strm_fmt_desc strm_fmt_desc;
+ struct cif_isp10_strm_fmt request_strm_fmt;
+ bool matching_format_found = false;
+ bool better_match = false;
+ u32 target_width, target_height;
+ u32 img_src_width, img_src_height;
+ u32 best_diff = ~0;
+ int vblanking;
+
+ if (IS_ERR_OR_NULL(dev->img_src)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "no image source selected as input (call s_input first)\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ ret = cif_isp10_get_target_frm_size(dev,
+ &target_width, &target_height);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ /* find the best matching format from the image source */
+ /* TODO: frame interval and pixel format handling */
+ for (index = 0;; index++) {
+ if (IS_ERR_VALUE(cif_isp10_img_src_enum_strm_fmts(dev->img_src,
+ index, &strm_fmt_desc)))
+ break;
+ if (!strm_fmt_desc.discrete_frmsize) {
+ if (strm_fmt_desc.min_frmsize.width >= target_width)
+ img_src_width = strm_fmt_desc.min_frmsize.width;
+ else if (strm_fmt_desc.max_frmsize.width >=
+ target_width)
+ img_src_width = target_width;
+ else
+ img_src_width = strm_fmt_desc.max_frmsize.width;
+ if (strm_fmt_desc.min_frmsize.height >= target_height)
+ img_src_height =
+ strm_fmt_desc.min_frmsize.height;
+ else if (strm_fmt_desc.max_frmsize.height >=
+ target_height)
+ img_src_height = target_height;
+ else
+ img_src_height =
+ strm_fmt_desc.max_frmsize.height;
+ } else {
+ img_src_width = strm_fmt_desc.min_frmsize.width;
+ img_src_height = strm_fmt_desc.min_frmsize.height;
+ }
+ if ((img_src_width >= target_width) &&
+ (img_src_height >= target_height)) {
+ u32 diff = abs(
+ target_height -
+ (target_width * img_src_height /
+ img_src_width));
+ if (matching_format_found) {
+ if (dev->config.jpeg_config.enable &&
+ ((img_src_width >=
+ request_strm_fmt.frm_fmt.width) &&
+ (img_src_height >
+ request_strm_fmt.frm_fmt.height)))
+ /*
+ * for image capturing we try to
+ * maximize the size
+ */
+ better_match = true;
+ else if (!dev->config.jpeg_config.enable &&
+ ((strm_fmt_desc.min_intrvl.denominator /
+ strm_fmt_desc.min_intrvl.numerator) >
+ (request_strm_fmt.frm_intrvl.denominator /
+ request_strm_fmt.frm_intrvl.numerator)))
+ /* maximize fps */
+ better_match = true;
+ else if (!dev->config.jpeg_config.enable &&
+ ((strm_fmt_desc.min_intrvl.denominator /
+ strm_fmt_desc.min_intrvl.numerator) ==
+ (request_strm_fmt.frm_intrvl.denominator /
+ request_strm_fmt.frm_intrvl.numerator)) &&
+ (diff < best_diff))
+ /*
+ * chose better aspect ratio
+ * match if fps equal
+ */
+ better_match = true;
+ else
+ better_match = false;
+ }
+
+ if (!matching_format_found ||
+ better_match) {
+ request_strm_fmt.frm_fmt.width =
+ strm_fmt_desc.min_frmsize.width;
+ request_strm_fmt.frm_fmt.height =
+ strm_fmt_desc.min_frmsize.height;
+ request_strm_fmt.frm_fmt.std_id =
+ strm_fmt_desc.std_id;
+ request_strm_fmt.frm_fmt.pix_fmt =
+ strm_fmt_desc.pix_fmt;
+ request_strm_fmt.frm_intrvl.numerator =
+ strm_fmt_desc.min_intrvl.numerator;
+ request_strm_fmt.frm_intrvl.denominator =
+ strm_fmt_desc.min_intrvl.denominator;
+ request_strm_fmt.frm_fmt.defrect =
+ strm_fmt_desc.defrect;
+ best_diff = diff;
+ matching_format_found = true;
+ }
+ }
+ }
+
+ if (!matching_format_found) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "no matching image source format (%dx%d) found\n",
+ target_width, target_height);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ cif_isp10_pltfrm_pr_dbg(
+ dev->dev,
+ "requesting format %s %dx%d(%d,%d,%d,%d)@%d/%dfps from %s\n",
+ cif_isp10_pix_fmt_string(request_strm_fmt.frm_fmt.pix_fmt),
+ request_strm_fmt.frm_fmt.width,
+ request_strm_fmt.frm_fmt.height,
+ request_strm_fmt.frm_fmt.defrect.left,
+ request_strm_fmt.frm_fmt.defrect.top,
+ request_strm_fmt.frm_fmt.defrect.width,
+ request_strm_fmt.frm_fmt.defrect.height,
+ request_strm_fmt.frm_intrvl.denominator,
+ request_strm_fmt.frm_intrvl.numerator,
+ cif_isp10_img_src_g_name(dev->img_src));
+
+ ret = cif_isp10_img_src_s_strm_fmt(dev->img_src, &request_strm_fmt);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ dev->config.img_src_output = request_strm_fmt;
+
+ ret = cif_isp10_img_src_g_ctrl(dev->img_src,
+ CIF_ISP10_CID_VBLANKING, &vblanking);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_dbg(
+ dev->dev,
+ "get vblanking failed: %d\n", ret);
+ vblanking = 0;
+ }
+
+ if (vblanking >= 0)
+ dev->isp_dev.v_blanking_us = vblanking;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+/*
+ * This should only be called when configuring CIF
+ * or at the frame end interrupt
+ */
+static void cif_isp10_config_ism(struct cif_isp10_device *dev, bool async)
+{
+ const struct cif_isp10_ism_config *pconfig =
+ &dev->config.isp_config.ism_config;
+
+ if (pconfig->ism_en) {
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%dx%d -> %dx%d@(%d,%d)\n",
+ dev->isp_dev.input_width,
+ dev->isp_dev.input_height,
+ pconfig->ism_params.h_size,
+ pconfig->ism_params.v_size,
+ pconfig->ism_params.h_offs,
+ pconfig->ism_params.v_offs);
+ cif_iowrite32(pconfig->ism_params.recenter,
+ dev->config.base_addr + CIF_ISP_IS_RECENTER);
+ cif_iowrite32(pconfig->ism_params.max_dx,
+ dev->config.base_addr + CIF_ISP_IS_MAX_DX);
+ cif_iowrite32(pconfig->ism_params.max_dy,
+ dev->config.base_addr + CIF_ISP_IS_MAX_DY);
+ cif_iowrite32(pconfig->ism_params.displace,
+ dev->config.base_addr + CIF_ISP_IS_DISPLACE);
+ cif_iowrite32(pconfig->ism_params.h_offs,
+ dev->config.base_addr + CIF_ISP_IS_H_OFFS);
+ cif_iowrite32(pconfig->ism_params.v_offs,
+ dev->config.base_addr + CIF_ISP_IS_V_OFFS);
+ cif_iowrite32(pconfig->ism_params.h_size,
+ dev->config.base_addr + CIF_ISP_IS_H_SIZE);
+ cif_iowrite32(pconfig->ism_params.v_size,
+ dev->config.base_addr + CIF_ISP_IS_V_SIZE);
+ cif_iowrite32OR(1,
+ dev->config.base_addr + CIF_ISP_IS_CTRL);
+ dev->config.isp_config.output.width =
+ dev->config.isp_config.ism_config.ism_params.h_size;
+ dev->config.isp_config.output.height =
+ dev->config.isp_config.ism_config.ism_params.v_size;
+ } else {
+ cif_iowrite32(pconfig->ism_params.recenter,
+ dev->config.base_addr + CIF_ISP_IS_RECENTER);
+ cif_iowrite32(pconfig->ism_params.max_dx,
+ dev->config.base_addr + CIF_ISP_IS_MAX_DX);
+ cif_iowrite32(pconfig->ism_params.max_dy,
+ dev->config.base_addr + CIF_ISP_IS_MAX_DY);
+ cif_iowrite32(pconfig->ism_params.displace,
+ dev->config.base_addr + CIF_ISP_IS_DISPLACE);
+ cif_iowrite32(0,
+ dev->config.base_addr + CIF_ISP_IS_H_OFFS);
+ cif_iowrite32(0,
+ dev->config.base_addr + CIF_ISP_IS_V_OFFS);
+ cif_iowrite32(dev->config.isp_config.output.width,
+ dev->config.base_addr + CIF_ISP_IS_H_SIZE);
+ cif_iowrite32(dev->config.isp_config.output.height,
+ dev->config.base_addr + CIF_ISP_IS_V_SIZE);
+ cif_iowrite32(0,
+ dev->config.base_addr + CIF_ISP_IS_CTRL);
+ }
+
+ if (async)
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n ISP_IS_H_OFFS %d/%d\n"
+ " ISP_IS_V_OFFS %d/%d\n"
+ " ISP_IS_H_SIZE %d/%d\n"
+ " ISP_IS_V_SIZE %d/%d\n"
+ " ISP_IS_RECENTER 0x%08x\n"
+ " ISP_IS_MAX_DX %d\n"
+ " ISP_IS_MAX_DY %d\n"
+ " ISP_IS_DISPLACE 0x%08x\n"
+ " ISP_IS_CTRL 0x%08x\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_H_OFFS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_H_OFFS_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_V_OFFS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_V_OFFS_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_H_SIZE),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_H_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_V_SIZE),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_V_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_RECENTER),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_MAX_DX),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_MAX_DY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_DISPLACE),
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_IS_CTRL));
+}
+
+static void cif_isp10_program_jpeg_tables(
+ struct cif_isp10_device *dev)
+{
+ unsigned int ratio = dev->config.jpeg_config.ratio;
+ unsigned int i = 0;
+ unsigned int q, q_next, scale;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "ratio %d\n", ratio);
+
+ /* Y q-table 0 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_QUANT0,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ if (ratio != 50) {
+ scale = (ratio < 50) ? 5000 / ratio : 200 - (ratio << 1);
+ for (i = 0; i < 32; i++) {
+ q = yq_table_base_zigzag[i * 2];
+ q_next = yq_table_base_zigzag[i * 2 + 1];
+ q = (scale * q + 50) / 100;
+ q = (q > 1) ? ((q < 255) ? q : 255) : 1;
+ q_next = (scale * q_next + 50) / 100;
+ q_next = (q_next > 1) ?
+ ((q_next < 255) ? q_next : 255) : 1;
+ cif_iowrite32(q_next + (q << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+ } else {
+ for (i = 0; i < 32; i++) {
+ q = yq_table_base_zigzag[i * 2];
+ q_next = yq_table_base_zigzag[i * 2 + 1];
+ cif_iowrite32(q_next + (q << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+ }
+
+ /* U/V q-table 0 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_QUANT1,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ if (ratio != 50) {
+ for (i = 0; i < 32; i++) {
+ q = uvq_table_base_zigzag[i * 2];
+ q_next = uvq_table_base_zigzag[i * 2 + 1];
+ q = (scale * q + 50) / 100;
+ q = (q > 1) ? ((q < 255) ? q : 255) : 1;
+ q_next = (scale * q_next + 50) / 100;
+ q_next = (q_next > 1) ?
+ ((q_next < 255) ? q_next : 255) : 1;
+ cif_iowrite32(q_next + (q << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+ } else {
+ for (i = 0; i < 32; i++) {
+ q = uvq_table_base_zigzag[i * 2];
+ q_next = uvq_table_base_zigzag[i * 2 + 1];
+ cif_iowrite32(q_next + (q << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+ }
+
+ /* Y AC-table 0 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_HUFFAC0,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ cif_iowrite32(178, dev->config.base_addr + CIF_JPE_TAC0_LEN);
+ for (i = 0; i < (178 / 2); i++) {
+ cif_iowrite32(ac_luma_table_annex_k[i * 2 + 1] +
+ (ac_luma_table_annex_k[i * 2] << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+
+ /* U/V AC-table 1 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_HUFFAC1,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ cif_iowrite32(178, dev->config.base_addr + CIF_JPE_TAC1_LEN);
+ for (i = 0; i < (178 / 2); i++) {
+ cif_iowrite32(ac_chroma_table_annex_k[i * 2 + 1] +
+ (ac_chroma_table_annex_k[i * 2] << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+
+ /* Y DC-table 0 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_HUFFDC0,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ cif_iowrite32(28, dev->config.base_addr + CIF_JPE_TDC0_LEN);
+ for (i = 0; i < (28 / 2); i++) {
+ cif_iowrite32(dc_luma_table_annex_k[i * 2 + 1] +
+ (dc_luma_table_annex_k[i * 2] << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+
+ /* U/V DC-table 1 programming */
+ cif_iowrite32(CIF_JPE_TAB_ID_HUFFDC1,
+ dev->config.base_addr + CIF_JPE_TABLE_ID);
+ cif_iowrite32(28, dev->config.base_addr + CIF_JPE_TDC1_LEN);
+ for (i = 0; i < (28 / 2); i++) {
+ cif_iowrite32(dc_chroma_table_annex_k[i * 2 + 1] +
+ (dc_chroma_table_annex_k[i * 2] << 8),
+ dev->config.base_addr +
+ CIF_JPE_TABLE_DATA);
+ }
+}
+
+static void cif_isp10_select_jpeg_tables(
+ struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ /* Selects quantization table for Y */
+ cif_iowrite32(CIF_JPE_TQ_TAB0,
+ dev->config.base_addr + CIF_JPE_TQ_Y_SELECT);
+ /* Selects quantization table for U */
+ cif_iowrite32(CIF_JPE_TQ_TAB1,
+ dev->config.base_addr + CIF_JPE_TQ_U_SELECT);
+ /* Selects quantization table for V */
+ cif_iowrite32(CIF_JPE_TQ_TAB1,
+ dev->config.base_addr + CIF_JPE_TQ_V_SELECT);
+ /* Selects Huffman DC table */
+ cif_iowrite32(CIF_DC_V_TABLE | CIF_DC_U_TABLE,
+ dev->config.base_addr + CIF_JPE_DC_TABLE_SELECT);
+ /* Selects Huffman AC table */
+ cif_iowrite32(CIF_AC_V_TABLE | CIF_AC_U_TABLE,
+ dev->config.base_addr + CIF_JPE_AC_TABLE_SELECT);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "\n JPE_TQ_Y_SELECT 0x%08x\n"
+ " JPE_TQ_U_SELECT 0x%08x\n"
+ " JPE_TQ_V_SELECT 0x%08x\n"
+ " JPE_DC_TABLE_SELECT 0x%08x\n"
+ " JPE_AC_TABLE_SELECT 0x%08x\n",
+ cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_Y_SELECT),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_U_SELECT),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_TQ_V_SELECT),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_DC_TABLE_SELECT),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_AC_TABLE_SELECT));
+}
+
+static int cif_isp10_config_img_src(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ struct isp_supplemental_sensor_mode_data sensor_mode;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+ ret = cif_isp10_img_src_set_state(dev,
+ CIF_ISP10_IMG_SRC_STATE_SW_STNDBY);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ if (!dev->sp_stream.updt_cfg &&
+ !dev->mp_stream.updt_cfg)
+ return 0;
+
+ ret = cif_isp10_pltfrm_g_interface_config(dev->img_src,
+ &dev->config.cam_itf);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_SENSOR_MODE_DATA, &sensor_mode);
+ if (IS_ERR_VALUE(ret)) {
+ dev->img_src_exps.exp_valid_frms = 2;
+ } else {
+ if ((sensor_mode.exposure_valid_frame < 2) ||
+ (sensor_mode.exposure_valid_frame > 6))
+ dev->img_src_exps.exp_valid_frms = 2;
+ else
+ dev->img_src_exps.exp_valid_frms =
+ sensor_mode.exposure_valid_frame;
+ }
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "cam_itf: (type: 0x%x, dphy: %d, vc: %d, nb_lanes: %d, bitrate: %d)",
+ dev->config.cam_itf.type,
+ dev->config.cam_itf.cfg.mipi.dphy_index,
+ dev->config.cam_itf.cfg.mipi.vc,
+ dev->config.cam_itf.cfg.mipi.nb_lanes,
+ dev->config.cam_itf.cfg.mipi.bit_rate);
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_isp(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ u32 h_offs;
+ u32 v_offs;
+ u32 yuv_seq = 0;
+ u32 bpp;
+ u32 isp_input_sel = 0;
+ u32 isp_bayer_pat = 0;
+ u32 acq_mult = 1;
+ u32 irq_mask = 0;
+ u32 signal = 0;
+ enum cif_isp10_pix_fmt in_pix_fmt;
+ struct cif_isp10_frm_fmt *output;
+ struct pltfrm_cam_itf *cam_itf;
+
+ if (dev->config.input_sel == CIF_ISP10_INP_DMA_IE) {
+ dev->config.isp_config.output =
+ dev->config.mi_config.dma.output;
+ cifisp_disable_isp(&dev->isp_dev);
+ return 0;
+ } else if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP) {
+ cif_iowrite32AND(~CIF_ICCL_ISP_CLK,
+ dev->config.base_addr + CIF_ICCL);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "ISP disabled\n");
+ return 0;
+ }
+ cif_iowrite32OR(CIF_ICCL_ISP_CLK,
+ dev->config.base_addr + CIF_ICCL);
+
+ in_pix_fmt = dev->config.isp_config.input->pix_fmt;
+
+ output = &dev->config.isp_config.output;
+ cam_itf = &dev->config.cam_itf;
+
+ if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+ if (!dev->config.mi_config.raw_enable) {
+ output->pix_fmt = CIF_YUV422I;
+
+ if ((dev->mp_stream.state == CIF_ISP10_STATE_READY) &&
+ (dev->sp_stream.state ==
+ CIF_ISP10_STATE_READY)) {
+ if (dev->config.mi_config.mp.output.
+ quantization !=
+ dev->config.mi_config.sp.output.
+ quantization) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "colorspace quantization (mp: %d, sp: %d) is not support!\n",
+ dev->
+ config.mi_config.mp.output.
+ quantization,
+ dev->
+ config.mi_config.sp.output.
+ quantization);
+ }
+ }
+
+ if (dev->sp_stream.state == CIF_ISP10_STATE_READY) {
+ output->quantization =
+ dev->config.mi_config.sp.output.quantization;
+ }
+
+ if (dev->mp_stream.state == CIF_ISP10_STATE_READY) {
+ output->quantization =
+ dev->config.mi_config.sp.output.quantization;
+ }
+
+ cif_iowrite32(0xc,
+ dev->config.base_addr + CIF_ISP_DEMOSAIC);
+
+ if (PLTFRM_CAM_ITF_IS_BT656(dev->config.cam_itf.type)) {
+ cif_iowrite32(
+ CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ } else {
+ cif_iowrite32(
+ CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ }
+ } else {
+ output->pix_fmt = in_pix_fmt;
+ if (PLTFRM_CAM_ITF_IS_BT656(dev->config.cam_itf.type)) {
+ cif_iowrite32(
+ CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ } else {
+ cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_RAW_PICT,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ }
+ }
+
+ bpp = CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt);
+ if (bpp == 8) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB;
+ } else if (bpp == 10) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB;
+ } else if (bpp == 12) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "%d bits per pixel not supported\n", bpp);
+ ret = -EINVAL;
+ goto err;
+ }
+ if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+ isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR;
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+ isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG;
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+ isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG;
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+ isp_bayer_pat = CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "BAYER pattern not supported\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if (CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+ output->pix_fmt = in_pix_fmt;
+ acq_mult = 2;
+ if (dev->config.input_sel == CIF_ISP10_INP_DMA) {
+ bpp = CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt);
+ bpp =
+ bpp * 4 /
+ (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ in_pix_fmt) *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ in_pix_fmt) / 2));
+ if (bpp == 8) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB;
+ } else if (bpp == 10) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB;
+ } else if (bpp == 12) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "format %s not supported, invalid bpp %d\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt),
+ bpp);
+ ret = -EINVAL;
+ goto err;
+ }
+ cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_ITU601,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ } else{
+ if (PLTFRM_CAM_ITF_IS_MIPI(
+ dev->config.cam_itf.type)) {
+ isp_input_sel = CIF_ISP_ACQ_PROP_IN_SEL_12B;
+ cif_iowrite32(CIF_ISP_CTRL_ISP_MODE_ITU601,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ } else if (PLTFRM_CAM_ITF_IS_DVP(
+ dev->config.cam_itf.type)) {
+ if (PLTFRM_CAM_ITF_IS_BT656(
+ dev->config.cam_itf.type)) {
+ cif_iowrite32(
+ CIF_ISP_CTRL_ISP_MODE_ITU656,
+ dev->config.base_addr +
+ CIF_ISP_CTRL);
+ } else {
+ cif_iowrite32(
+ CIF_ISP_CTRL_ISP_MODE_ITU601,
+ dev->config.base_addr +
+ CIF_ISP_CTRL);
+ }
+
+ switch (PLTFRM_CAM_ITF_DVP_BW(
+ dev->config.cam_itf.type)) {
+ case 8:
+ isp_input_sel =
+ CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO;
+ break;
+ case 10:
+ isp_input_sel =
+ CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO;
+ break;
+ case 12:
+ isp_input_sel =
+ CIF_ISP_ACQ_PROP_IN_SEL_12B;
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "%s isn't support for cif isp10\n",
+ cif_isp10_interface_string(
+ dev->config.cam_itf.type));
+ break;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "%s isn't support for cif isp10\n",
+ cif_isp10_interface_string(
+ dev->config.cam_itf.type));
+ }
+ /*
+ * ISP DATA LOSS is only meaningful
+ * when input is not DMA
+ */
+ irq_mask |= CIF_ISP_DATA_LOSS;
+ }
+ if (CIF_ISP10_PIX_FMT_YUV_IS_YC_SWAPPED(in_pix_fmt)) {
+ yuv_seq = CIF_ISP_ACQ_PROP_CBYCRY;
+ cif_isp10_pix_fmt_set_yc_swapped(output->pix_fmt, 0);
+ } else if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(in_pix_fmt)) {
+ yuv_seq = CIF_ISP_ACQ_PROP_YCRYCB;
+ } else {
+ yuv_seq = CIF_ISP_ACQ_PROP_YCBYCR;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "format %s not supported\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* Set up input acquisition properties*/
+ if (PLTFRM_CAM_ITF_IS_DVP(cam_itf->type)) {
+ signal =
+ ((cam_itf->cfg.dvp.pclk == PLTFRM_CAM_SDR_POS_EDG) ?
+ CIF_ISP_ACQ_PROP_POS_EDGE : CIF_ISP_ACQ_PROP_NEG_EDGE);
+
+ if (PLTFRM_CAM_ITF_IS_BT601(cam_itf->type)) {
+ signal |=
+ (cam_itf->cfg.dvp.vsync ==
+ PLTFRM_CAM_SIGNAL_HIGH_LEVEL) ?
+ CIF_ISP_ACQ_PROP_VSYNC_HIGH :
+ CIF_ISP_ACQ_PROP_VSYNC_LOW;
+
+ signal |=
+ (cam_itf->cfg.dvp.hsync ==
+ PLTFRM_CAM_SIGNAL_HIGH_LEVEL) ?
+ CIF_ISP_ACQ_PROP_HSYNC_HIGH :
+ CIF_ISP_ACQ_PROP_HSYNC_LOW;
+
+ } else {
+ signal |= CIF_ISP_ACQ_PROP_HSYNC_HIGH |
+ CIF_ISP_ACQ_PROP_VSYNC_HIGH;
+ }
+ } else {
+ signal = CIF_ISP_ACQ_PROP_NEG_EDGE |
+ CIF_ISP_ACQ_PROP_HSYNC_HIGH |
+ CIF_ISP_ACQ_PROP_VSYNC_HIGH;
+ }
+
+ cif_iowrite32(signal |
+ yuv_seq |
+ CIF_ISP_ACQ_PROP_FIELD_SEL_ALL |
+ isp_input_sel |
+ isp_bayer_pat |
+ (0 << 20), /* input_selection_no_app */
+ dev->config.base_addr + CIF_ISP_ACQ_PROP);
+ cif_iowrite32(0,
+ dev->config.base_addr + CIF_ISP_ACQ_NR_FRAMES);
+
+ /* Acquisition Size */
+ cif_iowrite32(dev->config.isp_config.input->defrect.left,
+ dev->config.base_addr + CIF_ISP_ACQ_H_OFFS);
+ cif_iowrite32(dev->config.isp_config.input->defrect.top,
+ dev->config.base_addr + CIF_ISP_ACQ_V_OFFS);
+ cif_iowrite32(
+ acq_mult * dev->config.isp_config.input->defrect.width,
+ dev->config.base_addr + CIF_ISP_ACQ_H_SIZE);
+ cif_iowrite32(
+ dev->config.isp_config.input->defrect.height,
+ dev->config.base_addr + CIF_ISP_ACQ_V_SIZE);
+
+ /* do cropping to match output aspect ratio */
+ ret = cif_isp10_calc_isp_cropping(dev,
+ &output->width, &output->height,
+ &h_offs, &v_offs);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ cif_iowrite32(v_offs,
+ dev->config.base_addr + CIF_ISP_OUT_V_OFFS);
+ cif_iowrite32(h_offs,
+ dev->config.base_addr + CIF_ISP_OUT_H_OFFS);
+ cif_iowrite32(output->width,
+ dev->config.base_addr + CIF_ISP_OUT_H_SIZE);
+ cif_iowrite32(output->height,
+ dev->config.base_addr + CIF_ISP_OUT_V_SIZE);
+
+ dev->isp_dev.input_width =
+ dev->config.isp_config.input->defrect.width;
+ dev->isp_dev.input_height =
+ dev->config.isp_config.input->defrect.height;
+
+ /* interrupt mask */
+ irq_mask |=
+ CIF_ISP_FRAME |
+ CIF_ISP_PIC_SIZE_ERROR |
+ CIF_ISP_FRAME_IN |
+ CIF_ISP_V_START;
+ cif_iowrite32(irq_mask,
+ dev->config.base_addr + CIF_ISP_IMSC);
+
+ if (!dev->config.mi_config.raw_enable)
+ cifisp_configure_isp(&dev->isp_dev,
+ in_pix_fmt,
+ output->quantization);
+ else
+ cifisp_disable_isp(&dev->isp_dev);
+
+ cif_isp10_pltfrm_pr_dbg(
+ dev->dev,
+ "\n ISP_CTRL 0x%08x\n"
+ " ISP_IMSC 0x%08x\n"
+ " ISP_ACQ_PROP 0x%08x\n"
+ " ISP_ACQ %dx%d@(%d,%d)\n"
+ " ISP_OUT %dx%d@(%d,%d)\n"
+ " ISP_IS %dx%d@(%d,%d)\n",
+ cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IMSC),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_PROP),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_H_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_V_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_H_OFFS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_ACQ_V_OFFS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_H_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_V_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_H_OFFS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_OUT_V_OFFS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IS_H_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IS_V_SIZE),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IS_H_OFFS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IS_V_OFFS));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_mipi(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ u32 data_type;
+ u32 mipi_ctrl;
+ u32 shutdown_lanes;
+ u32 i;
+ enum cif_isp10_pix_fmt in_pix_fmt;
+
+ if (!CIF_ISP10_INP_IS_MIPI(dev->config.input_sel)) {
+ cif_iowrite32AND(~CIF_ICCL_MIPI_CLK,
+ dev->config.base_addr + CIF_ICCL);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "MIPI disabled\n");
+ return 0;
+ }
+ cif_iowrite32OR(CIF_ICCL_MIPI_CLK,
+ dev->config.base_addr + CIF_ICCL);
+
+ in_pix_fmt = dev->config.img_src_output.frm_fmt.pix_fmt;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "input %s, vc = %d, nb_lanes = %d\n",
+ cif_isp10_inp_string(dev->config.input_sel),
+ dev->config.cam_itf.cfg.mipi.vc,
+ dev->config.cam_itf.cfg.mipi.nb_lanes);
+
+ if ((dev->config.cam_itf.cfg.mipi.nb_lanes == 0) ||
+ (dev->config.cam_itf.cfg.mipi.nb_lanes > 4)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "invalid number (%d) of MIPI lanes, valid range is [1..4]\n",
+ dev->config.cam_itf.cfg.mipi.nb_lanes);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ shutdown_lanes = 0x00;
+ for (i = 0; i < dev->config.cam_itf.cfg.mipi.nb_lanes; i++)
+ shutdown_lanes |= (1 << i);
+
+ mipi_ctrl =
+ CIF_MIPI_CTRL_NUM_LANES(
+ dev->config.cam_itf.cfg.mipi.nb_lanes - 1) |
+ CIF_MIPI_CTRL_ERR_SOT_HS_ENA |
+ CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP |
+ CIF_MIPI_CTRL_SHUTDOWNLANES(shutdown_lanes) |
+ CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_ENA |
+ CIF_MIPI_CTRL_ERR_SOT_HS_ENA |
+ CIF_MIPI_CTRL_CLOCKLANE_ENA;
+
+ cif_iowrite32(mipi_ctrl,
+ dev->config.base_addr + CIF_MIPI_CTRL);
+
+ /* mipi_dphy */
+ cif_isp10_pltfrm_mipi_dphy_config(dev);
+
+ /* Configure Data Type and Virtual Channel */
+ if (CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+ if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 12))
+ data_type = CSI2_DT_YUV420_8b;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 15))
+ data_type = CSI2_DT_YUV420_10b;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4) &&
+ (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 16))
+ data_type = CSI2_DT_YUV422_8b;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4) &&
+ (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 20))
+ data_type = CSI2_DT_YUV422_10b;
+ else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported format %s\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+ if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 8) {
+ data_type = CSI2_DT_RAW8;
+ } else if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 10) {
+ data_type = CSI2_DT_RAW10;
+ } else if (CIF_ISP10_PIX_FMT_GET_BPP(in_pix_fmt) == 12) {
+ data_type = CSI2_DT_RAW12;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported format %s\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if (in_pix_fmt == CIF_RGB565) {
+ data_type = CSI2_DT_RGB565;
+ } else if (in_pix_fmt == CIF_RGB666) {
+ data_type = CSI2_DT_RGB666;
+ } else if (in_pix_fmt == CIF_RGB888) {
+ data_type = CSI2_DT_RGB888;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported format %s\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ cif_iowrite32(
+ CIF_MIPI_DATA_SEL_DT(data_type) |
+ CIF_MIPI_DATA_SEL_VC(
+ dev->config.cam_itf.cfg.mipi.vc),
+ dev->config.base_addr + CIF_MIPI_IMG_DATA_SEL);
+
+ /* Enable MIPI interrupts */
+ cif_iowrite32(~0,
+ dev->config.base_addr + CIF_MIPI_ICR);
+ /*
+ * Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
+ * isp bus may be dead when switch isp.
+ */
+ cif_iowrite32(
+ CIF_MIPI_FRAME_END |
+ CIF_MIPI_ERR_CSI |
+ CIF_MIPI_ERR_DPHY |
+ CIF_MIPI_SYNC_FIFO_OVFLW(3) |
+ CIF_MIPI_ADD_DATA_OVFLW,
+ dev->config.base_addr + CIF_MIPI_IMSC);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MIPI_CTRL 0x%08x\n"
+ " MIPI_IMG_DATA_SEL 0x%08x\n"
+ " MIPI_STATUS 0x%08x\n"
+ " MIPI_IMSC 0x%08x\n",
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_IMG_DATA_SEL),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_STATUS),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_IMSC));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_mi_mp(
+ struct cif_isp10_device *dev)
+{
+ enum cif_isp10_pix_fmt out_pix_fmt =
+ dev->config.mi_config.mp.output.pix_fmt;
+ u32 llength =
+ dev->config.mi_config.mp.llength;
+ u32 width =
+ dev->config.mi_config.mp.output.width;
+ u32 height =
+ dev->config.mi_config.mp.output.height;
+ u32 writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ u32 swap_cb_cr = 0;
+ u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+ u32 size = llength * height * bpp / 8;
+ u32 mi_ctrl;
+
+ dev->config.mi_config.mp.input =
+ &dev->config.mp_config.rsz_config.output;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d, llength = %d\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt),
+ width,
+ height,
+ llength);
+
+ dev->config.mi_config.mp.y_size = size;
+ dev->config.mi_config.mp.cb_size = 0;
+ dev->config.mi_config.mp.cr_size = 0;
+ if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+ u32 num_cplanes =
+ CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+ if (num_cplanes == 0) {
+ writeformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+ } else {
+ dev->config.mi_config.mp.y_size =
+ (dev->config.mi_config.mp.y_size * 4) /
+ (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ out_pix_fmt) *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ out_pix_fmt) / 2));
+ dev->config.mi_config.mp.cb_size =
+ size -
+ dev->config.mi_config.mp.y_size;
+ if (num_cplanes == 1) {
+ writeformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+ } else if (num_cplanes == 2) {
+ writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ dev->config.mi_config.mp.cb_size /= 2;
+ }
+ /* for U<->V swapping: */
+ dev->config.mi_config.mp.cr_size =
+ dev->config.mi_config.mp.cb_size;
+ }
+ if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(out_pix_fmt))
+ swap_cb_cr = CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP;
+
+ if (writeformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+ dev->config.mi_config.mp.cb_offs =
+ dev->config.mi_config.mp.y_size;
+ dev->config.mi_config.mp.cr_offs =
+ dev->config.mi_config.mp.cb_offs;
+ } else if (writeformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+ if (swap_cb_cr) {
+ swap_cb_cr = 0;
+ dev->config.mi_config.mp.cr_offs =
+ dev->config.mi_config.mp.y_size;
+ dev->config.mi_config.mp.cb_offs =
+ dev->config.mi_config.mp.cr_offs +
+ dev->config.mi_config.mp.cr_size;
+ } else {
+ dev->config.mi_config.mp.cb_offs =
+ dev->config.mi_config.mp.y_size;
+ dev->config.mi_config.mp.cr_offs =
+ dev->config.mi_config.mp.cb_offs +
+ dev->config.mi_config.mp.cb_size;
+ }
+ }
+ } else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(out_pix_fmt)) {
+ if (CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt) > 8) {
+ writeformat = CIF_ISP10_BUFF_FMT_RAW12;
+ dev->config.mi_config.mp.y_size = width * height * 2;
+ } else {
+ writeformat = CIF_ISP10_BUFF_FMT_RAW8;
+ dev->config.mi_config.mp.y_size = width * height;
+ }
+ dev->config.mi_config.mp.cb_offs = 0x00;
+ dev->config.mi_config.mp.cr_offs = 0x00;
+ dev->config.mi_config.mp.cb_size = 0x00;
+ dev->config.mi_config.mp.cr_size = 0x00;
+ }
+
+ cif_iowrite32_verify(dev->config.mi_config.mp.y_size,
+ dev->config.base_addr + CIF_MI_MP_Y_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.mp.cb_size,
+ dev->config.base_addr + CIF_MI_MP_CB_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.mp.cr_size,
+ dev->config.base_addr + CIF_MI_MP_CR_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32OR_verify(CIF_MI_MP_FRAME,
+ dev->config.base_addr +
+ CIF_MI_IMSC, ~0);
+
+ if (swap_cb_cr) {
+ cif_iowrite32OR(swap_cb_cr,
+ dev->config.base_addr + CIF_MI_XTD_FORMAT_CTRL);
+ }
+
+ mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_CTRL) |
+ CIF_MI_CTRL_MP_WRITE_FMT(writeformat) |
+ CIF_MI_CTRL_BURST_LEN_LUM_64 |
+ CIF_MI_CTRL_BURST_LEN_CHROM_64 |
+ CIF_MI_CTRL_INIT_BASE_EN |
+ CIF_MI_CTRL_INIT_OFFSET_EN |
+ CIF_MI_MP_AUTOUPDATE_ENABLE;
+
+ cif_iowrite32_verify(mi_ctrl,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_CTRL 0x%08x\n"
+ " MI_STATUS 0x%08x\n"
+ " MI_MP_Y_SIZE %d\n"
+ " MI_MP_CB_SIZE %d\n"
+ " MI_MP_CR_SIZE %d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_STATUS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_SIZE_INIT));
+
+ return 0;
+}
+
+static int cif_isp10_config_mi_sp(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ enum cif_isp10_pix_fmt out_pix_fmt =
+ dev->config.mi_config.sp.output.pix_fmt;
+ enum cif_isp10_pix_fmt in_pix_fmt =
+ dev->config.sp_config.rsz_config.output.pix_fmt;
+ u32 llength =
+ dev->config.mi_config.sp.llength;
+ u32 width =
+ dev->config.mi_config.sp.output.width;
+ u32 height =
+ dev->config.mi_config.sp.output.height;
+ u32 writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ u32 swap_cb_cr = 0;
+ u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+ u32 size = llength * height * bpp / 8;
+ u32 input_format = 0;
+ u32 output_format;
+ u32 mi_ctrl;
+
+ dev->config.mi_config.sp.input =
+ &dev->config.sp_config.rsz_config.output;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d, llength = %d\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt),
+ width,
+ height,
+ llength);
+
+ if (!CIF_ISP10_PIX_FMT_IS_YUV(in_pix_fmt)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported format %s (must be YUV)\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev->config.mi_config.sp.y_size = size;
+ dev->config.mi_config.sp.cb_size = 0;
+ dev->config.mi_config.sp.cr_size = 0;
+ if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+ u32 num_cplanes =
+ CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+ if (num_cplanes == 0) {
+ writeformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+ } else {
+ dev->config.mi_config.sp.y_size =
+ (dev->config.mi_config.sp.y_size * 4) /
+ (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ out_pix_fmt) *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ out_pix_fmt) / 2));
+ dev->config.mi_config.sp.cb_size =
+ size -
+ dev->config.mi_config.sp.y_size;
+ if (num_cplanes == 1) {
+ writeformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+ } else if (num_cplanes == 2) {
+ writeformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ dev->config.mi_config.sp.cb_size /= 2;
+ }
+ /* for U<->V swapping: */
+ dev->config.mi_config.sp.cr_size =
+ dev->config.mi_config.sp.cb_size;
+ }
+ if (CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(out_pix_fmt))
+ swap_cb_cr = CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP;
+
+ if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 0) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 0))
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV400;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2))
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV420;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV422;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_YUV444;
+ else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported YUV output format %s\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if (CIF_ISP10_PIX_FMT_IS_RGB(out_pix_fmt)) {
+ if (out_pix_fmt == CIF_RGB565) {
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB565;
+ } else if (out_pix_fmt == CIF_RGB666) {
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB666;
+ } else if (out_pix_fmt == CIF_RGB888) {
+ output_format = CIF_MI_CTRL_SP_OUTPUT_FMT_RGB888;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported RGB output format %s\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported output format %s\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 0) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 0))
+ input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV400;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 2))
+ input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV420;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4))
+ input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV422;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(in_pix_fmt) == 4) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(in_pix_fmt) == 4))
+ input_format = CIF_MI_CTRL_SP_INPUT_FMT_YUV444;
+ else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported YUV input format %s\n",
+ cif_isp10_pix_fmt_string(in_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (writeformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+ dev->config.mi_config.sp.cb_offs =
+ dev->config.mi_config.sp.y_size;
+ dev->config.mi_config.sp.cr_offs =
+ dev->config.mi_config.sp.cb_offs;
+ } else if (writeformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+ if (swap_cb_cr) {
+ swap_cb_cr = 0;
+ dev->config.mi_config.sp.cr_offs =
+ dev->config.mi_config.sp.y_size;
+ dev->config.mi_config.sp.cb_offs =
+ dev->config.mi_config.sp.cr_offs +
+ dev->config.mi_config.sp.cr_size;
+ } else {
+ dev->config.mi_config.sp.cb_offs =
+ dev->config.mi_config.sp.y_size;
+ dev->config.mi_config.sp.cr_offs =
+ dev->config.mi_config.sp.cb_offs +
+ dev->config.mi_config.sp.cb_size;
+ }
+ }
+
+ cif_iowrite32_verify(dev->config.mi_config.sp.y_size,
+ dev->config.base_addr + CIF_MI_SP_Y_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.sp.y_size,
+ dev->config.base_addr + CIF_MI_SP_Y_PIC_SIZE,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.sp.cb_size,
+ dev->config.base_addr + CIF_MI_SP_CB_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.sp.cr_size,
+ dev->config.base_addr + CIF_MI_SP_CR_SIZE_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(width,
+ dev->config.base_addr + CIF_MI_SP_Y_PIC_WIDTH, ~0x3);
+ cif_iowrite32_verify(height,
+ dev->config.base_addr + CIF_MI_SP_Y_PIC_HEIGHT, ~0x3);
+ cif_iowrite32_verify(llength,
+ dev->config.base_addr + CIF_MI_SP_Y_LLENGTH, ~0x3);
+ cif_iowrite32OR_verify(CIF_MI_SP_FRAME,
+ dev->config.base_addr +
+ CIF_MI_IMSC, ~0);
+
+ if (swap_cb_cr) {
+ cif_iowrite32OR(swap_cb_cr,
+ dev->config.base_addr + CIF_MI_XTD_FORMAT_CTRL);
+ }
+
+ mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_CTRL) |
+ CIF_MI_CTRL_SP_WRITE_FMT(writeformat) |
+ input_format |
+ output_format |
+ CIF_MI_CTRL_BURST_LEN_LUM_64 |
+ CIF_MI_CTRL_BURST_LEN_CHROM_64 |
+ CIF_MI_CTRL_INIT_BASE_EN |
+ CIF_MI_CTRL_INIT_OFFSET_EN |
+ CIF_MI_SP_AUTOUPDATE_ENABLE;
+ cif_iowrite32_verify(mi_ctrl,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_CTRL 0x%08x\n"
+ " MI_STATUS 0x%08x\n"
+ " MI_SP_Y_SIZE %d\n"
+ " MI_SP_CB_SIZE %d\n"
+ " MI_SP_CR_SIZE %d\n"
+ " MI_SP_PIC_WIDTH %d\n"
+ " MI_SP_PIC_HEIGHT %d\n"
+ " MI_SP_PIC_LLENGTH %d\n"
+ " MI_SP_PIC_SIZE %d\n",
+ cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_MI_STATUS),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_CB_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_CR_SIZE_INIT),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_WIDTH),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_HEIGHT),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_LLENGTH),
+ cif_ioread32(dev->config.base_addr + CIF_MI_SP_Y_PIC_SIZE));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_mi_dma(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ enum cif_isp10_pix_fmt out_pix_fmt =
+ dev->config.mi_config.dma.output.pix_fmt;
+ u32 llength =
+ dev->config.mi_config.dma.llength;
+ u32 width =
+ dev->config.mi_config.dma.output.width;
+ u32 height =
+ dev->config.mi_config.dma.output.height;
+ u32 readformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ u32 bpp = CIF_ISP10_PIX_FMT_GET_BPP(out_pix_fmt);
+ u32 size = llength * height * bpp / 8;
+ u32 output_format;
+ u32 mi_ctrl;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d, llength = %d\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt),
+ width,
+ height,
+ llength);
+
+ dev->config.mi_config.dma.y_size = size;
+ dev->config.mi_config.dma.cb_size = 0;
+ dev->config.mi_config.dma.cr_size = 0;
+ if (CIF_ISP10_PIX_FMT_IS_YUV(out_pix_fmt)) {
+ u32 num_cplanes =
+ CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(out_pix_fmt);
+ if (num_cplanes == 0) {
+ readformat = CIF_ISP10_BUFF_FMT_INTERLEAVED;
+ } else {
+ dev->config.mi_config.dma.y_size =
+ (dev->config.mi_config.dma.y_size * 4) /
+ (4 + (CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ out_pix_fmt) *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ out_pix_fmt) / 2));
+ dev->config.mi_config.dma.cb_size =
+ size -
+ dev->config.mi_config.dma.y_size;
+ if (num_cplanes == 1) {
+ readformat = CIF_ISP10_BUFF_FMT_SEMIPLANAR;
+ } else if (num_cplanes == 2) {
+ readformat = CIF_ISP10_BUFF_FMT_PLANAR;
+ dev->config.mi_config.dma.cb_size /= 2;
+ }
+ /* for U<->V swapping: */
+ dev->config.mi_config.dma.cr_size =
+ dev->config.mi_config.dma.cb_size;
+ }
+
+ if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 0) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 0))
+ output_format = CIF_MI_DMA_CTRL_FMT_YUV400;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 2))
+ output_format = CIF_MI_DMA_CTRL_FMT_YUV420;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 2) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+ output_format = CIF_MI_DMA_CTRL_FMT_YUV422;
+ else if ((CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(out_pix_fmt) == 4) &&
+ (CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(out_pix_fmt) == 4))
+ output_format = CIF_MI_DMA_CTRL_FMT_YUV444;
+ else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported YUV output format %s\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unsupported output format %s\n",
+ cif_isp10_pix_fmt_string(out_pix_fmt));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (readformat == CIF_ISP10_BUFF_FMT_SEMIPLANAR) {
+ dev->config.mi_config.dma.cb_offs =
+ dev->config.mi_config.dma.y_size;
+ dev->config.mi_config.dma.cr_offs =
+ dev->config.mi_config.dma.cb_offs;
+ } else if (readformat == CIF_ISP10_BUFF_FMT_PLANAR) {
+ dev->config.mi_config.dma.cb_offs =
+ dev->config.mi_config.dma.y_size;
+ dev->config.mi_config.dma.cr_offs =
+ dev->config.mi_config.dma.cb_offs +
+ dev->config.mi_config.dma.cb_size;
+ }
+
+ cif_iowrite32_verify(dev->config.mi_config.dma.y_size,
+ dev->config.base_addr + CIF_MI_DMA_Y_PIC_SIZE, ~0x3);
+ cif_iowrite32_verify(width,
+ dev->config.base_addr + CIF_MI_DMA_Y_PIC_WIDTH, ~0x3);
+ cif_iowrite32_verify(llength,
+ dev->config.base_addr + CIF_MI_DMA_Y_LLENGTH, ~0x3);
+
+ mi_ctrl = cif_ioread32(dev->config.base_addr + CIF_MI_DMA_CTRL) |
+ CIF_MI_DMA_CTRL_READ_FMT(readformat) |
+ output_format |
+ CIF_MI_DMA_CTRL_BURST_LEN_LUM_64 |
+ CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64;
+ cif_iowrite32_verify(mi_ctrl,
+ dev->config.base_addr + CIF_MI_DMA_CTRL, ~0);
+
+ cif_iowrite32OR_verify(CIF_MI_DMA_READY,
+ dev->config.base_addr + CIF_MI_IMSC, ~0);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_DMA_CTRL 0x%08x\n"
+ " MI_DMA_STATUS 0x%08x\n"
+ " MI_DMA_Y_PIC_WIDTH %d\n"
+ " MI_DMA_Y_LLENGTH %d\n"
+ " MI_DMA_Y_PIC_SIZE %d\n"
+ " MI_DMA_Y_PIC_START_AD %d\n"
+ " MI_DMA_CB_PIC_START_AD %d\n"
+ " MI_DMA_CR_PIC_START_AD %d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_STATUS),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_Y_PIC_WIDTH),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_Y_LLENGTH),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_Y_PIC_SIZE),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_Y_PIC_START_AD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CB_PIC_START_AD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CR_PIC_START_AD));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_jpeg_enc(
+ struct cif_isp10_device *dev)
+{
+ struct cif_isp10_frm_fmt *inp_fmt =
+ &dev->config.mp_config.rsz_config.output;
+ dev->config.jpeg_config.input = inp_fmt;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s %dx%d\n",
+ cif_isp10_pix_fmt_string(inp_fmt->pix_fmt),
+ inp_fmt->width, inp_fmt->height);
+
+ /*
+ * Reset JPEG-Encoder. In contrast to other software
+ * resets this triggers the modules asynchronous reset
+ * resulting in loss of all data
+ */
+ cif_iowrite32OR(CIF_IRCL_JPEG_SW_RST,
+ dev->config.base_addr + CIF_IRCL);
+ cif_iowrite32AND(~CIF_IRCL_JPEG_SW_RST,
+ dev->config.base_addr + CIF_IRCL);
+
+ cif_iowrite32(CIF_JPE_ERROR_MASK,
+ dev->config.base_addr + CIF_JPE_ERROR_IMSC);
+
+ /* Set configuration for the Jpeg capturing */
+ cif_iowrite32(inp_fmt->width,
+ dev->config.base_addr + CIF_JPE_ENC_HSIZE);
+ cif_iowrite32(inp_fmt->height,
+ dev->config.base_addr + CIF_JPE_ENC_VSIZE);
+
+ if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel) ||
+ !CIF_ISP10_PIX_FMT_IS_RAW_BAYER(
+ dev->config.isp_config.input->pix_fmt)) {
+ /*
+ * upscaling of BT601 color space to full range 0..255
+ * TODO: DMA or YUV sensor input in full range.
+ */
+ cif_iowrite32(CIF_JPE_LUM_SCALE_ENABLE,
+ dev->config.base_addr + CIF_JPE_Y_SCALE_EN);
+ cif_iowrite32(CIF_JPE_CHROM_SCALE_ENABLE,
+ dev->config.base_addr + CIF_JPE_CBCR_SCALE_EN);
+ }
+
+ switch (inp_fmt->pix_fmt) {
+ case CIF_YUV422I:
+ case CIF_YVU422I:
+ case CIF_YUV422SP:
+ case CIF_YVU422SP:
+ case CIF_YUV422P:
+ case CIF_YVU422P:
+ cif_iowrite32(CIF_JPE_PIC_FORMAT_YUV422,
+ dev->config.base_addr + CIF_JPE_PIC_FORMAT);
+ break;
+ case CIF_YUV400:
+ case CIF_YVU400:
+ cif_iowrite32(CIF_JPE_PIC_FORMAT_YUV400,
+ dev->config.base_addr + CIF_JPE_PIC_FORMAT);
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "format %s not supported as input for JPEG encoder\n",
+ cif_isp10_pix_fmt_string(inp_fmt->pix_fmt));
+ WARN_ON(1);
+ break;
+ }
+
+ /*
+ * Set to normal operation (wait for encoded image data
+ * to fill output buffer)
+ */
+ cif_iowrite32(0, dev->config.base_addr + CIF_JPE_TABLE_FLUSH);
+
+ /*
+ * CIF Spec 4.7
+ * 3.14 JPEG Encoder Programming
+ * Do not forget to re-program all AC and DC tables
+ * after system reset as well as after
+ * module software reset because after any reset
+ * the internal RAM is filled with FFH which
+ * is an illegal symbol. This filling takes
+ * approximately 400 clock cycles. So do not start
+ * any table programming during the first 400 clock
+ * cycles after reset is de-asserted.
+ * Note: depends on CIF clock setting
+ * 400 clock cycles at 312 Mhz CIF clock-> 1.3 us
+ * 400 clock cycles at 208 Mhz CIF clock-> 1.93 us
+ * -> 2us ok for both
+ */
+ udelay(2);
+
+ /* Program JPEG tables */
+ cif_isp10_program_jpeg_tables(dev);
+ /* Select JPEG tables */
+ cif_isp10_select_jpeg_tables(dev);
+
+ switch (dev->config.jpeg_config.header) {
+ case CIF_ISP10_JPEG_HEADER_JFIF:
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "generate JFIF header\n");
+ cif_iowrite32(CIF_JPE_HEADER_MODE_JFIF,
+ dev->config.base_addr +
+ CIF_JPE_HEADER_MODE);
+ break;
+ case CIF_ISP10_JPEG_HEADER_NONE:
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "generate no JPEG header\n");
+ cif_iowrite32(CIF_JPE_HEADER_MODE_NOAPPN,
+ dev->config.base_addr +
+ CIF_JPE_HEADER_MODE);
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupport JPEG header type %d\n",
+ dev->config.jpeg_config.header);
+ WARN_ON(1);
+ break;
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n JPE_PIC_FORMAT 0x%08x\n"
+ " JPE_ENC_HSIZE %d\n"
+ " JPE_ENC_VSIZE %d\n"
+ " JPE_Y_SCALE_EN 0x%08x\n"
+ " JPE_CBCR_SCALE_EN 0x%08x\n"
+ " JPE_ERROR_RIS 0x%08x\n"
+ " JPE_ERROR_IMSC 0x%08x\n"
+ " JPE_STATUS_RIS 0x%08x\n"
+ " JPE_STATUS_IMSC 0x%08x\n"
+ " JPE_DEBUG 0x%08x\n",
+ cif_ioread32(dev->config.base_addr + CIF_JPE_PIC_FORMAT),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_ENC_HSIZE),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_ENC_VSIZE),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_Y_SCALE_EN),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_CBCR_SCALE_EN),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_ERROR_RIS),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_ERROR_IMSC),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_STATUS_RIS),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_STATUS_IMSC),
+ cif_ioread32(dev->config.base_addr + CIF_JPE_DEBUG));
+
+ return 0;
+}
+
+static int cif_isp10_config_path(
+ struct cif_isp10_device *dev,
+ u32 stream_ids)
+{
+ u32 dpcl = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+ /* if_sel */
+ if (dev->config.input_sel == CIF_ISP10_INP_DMA) {
+ dpcl |= CIF_VI_DPCL_DMA_SW_ISP;
+ } else if (dev->config.input_sel == CIF_ISP10_INP_DMA_IE) {
+ dpcl |= CIF_VI_DPCL_DMA_IE_MUX_DMA |
+ CIF_VI_DPCL_DMA_SW_IE;
+ } else if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP) {
+ dpcl |= CIF_VI_DPCL_DMA_SP_MUX_DMA;
+ } else {
+ if (PLTFRM_CAM_ITF_IS_DVP(dev->config.cam_itf.type)) {
+ dpcl |= CIF_VI_DPCL_IF_SEL_PARALLEL;
+ } else if (PLTFRM_CAM_ITF_IS_MIPI(dev->config.cam_itf.type)) {
+ dpcl |= CIF_VI_DPCL_IF_SEL_MIPI;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "Sensor Interface: 0x%x isn't support\n",
+ dev->config.cam_itf.type);
+ return -EINVAL;
+ }
+ }
+
+ /* chan_mode */
+ if (stream_ids & CIF_ISP10_STREAM_SP)
+ dpcl |= CIF_VI_DPCL_CHAN_MODE_SP;
+
+ if ((stream_ids & CIF_ISP10_STREAM_MP) &&
+ !(dev->config.input_sel == CIF_ISP10_INP_DMA_SP)) {
+ dpcl |= CIF_VI_DPCL_CHAN_MODE_MP;
+ /* mp_dmux */
+ if (dev->config.jpeg_config.enable)
+ dpcl |= CIF_VI_DPCL_MP_MUX_MRSZ_JPEG;
+ else
+ dpcl |= CIF_VI_DPCL_MP_MUX_MRSZ_MI;
+ }
+
+ cif_iowrite32(dpcl,
+ dev->config.base_addr + CIF_VI_DPCL);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "CIF_DPCL 0x%08x\n", dpcl);
+
+ return 0;
+}
+
+int cif_isp10_config_dcrop(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ bool async)
+{
+ unsigned int dc_ctrl = cif_ioread32(
+ dev->config.base_addr +
+ CIF_DUAL_CROP_CTRL);
+
+ if (stream_id == CIF_ISP10_STREAM_MP) {
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_M_H_OFFS);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_M_V_OFFS);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_M_H_SIZE);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_M_V_SIZE);
+
+ dc_ctrl |= CIF_DUAL_CROP_MP_MODE_BYPASS;
+ if (async)
+ dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
+ else
+ dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
+
+ cif_iowrite32(dc_ctrl,
+ dev->config.base_addr + CIF_DUAL_CROP_CTRL);
+ } else if (stream_id == CIF_ISP10_STREAM_SP) {
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_S_H_OFFS);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_S_V_OFFS);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_S_H_SIZE);
+ cif_iowrite32(0, dev->config.base_addr +
+ CIF_DUAL_CROP_S_V_SIZE);
+
+ dc_ctrl |= CIF_DUAL_CROP_MP_MODE_BYPASS;
+ if (async)
+ dc_ctrl |= CIF_DUAL_CROP_GEN_CFG_UPD;
+ else
+ dc_ctrl |= CIF_DUAL_CROP_CFG_UPD;
+
+ cif_iowrite32(dc_ctrl,
+ dev->config.base_addr + CIF_DUAL_CROP_CTRL);
+ }
+
+ return 0;
+}
+
+int cif_isp10_config_rsz(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ bool async)
+{
+ int ret;
+ u32 i;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_y_addr =
+ dev->config.base_addr;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_cr_addr =
+ dev->config.base_addr;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_h_cb_addr =
+ dev->config.base_addr;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_v_y_addr =
+ dev->config.base_addr;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR scale_v_c_addr =
+ dev->config.base_addr;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR rsz_ctrl_addr =
+ dev->config.base_addr;
+ struct cif_isp10_frm_fmt *rsz_input;
+ struct cif_isp10_frm_fmt *rsz_output;
+ struct cif_isp10_frm_fmt *mi_output;
+ u32 rsz_ctrl;
+ u32 input_width_y;
+ u32 output_width_y;
+ u32 input_height_y;
+ u32 output_height_y;
+ u32 input_width_c;
+ u32 output_width_c;
+ u32 input_height_c;
+ u32 output_height_c;
+ u32 scale_h_c;
+
+ if (stream_id == CIF_ISP10_STREAM_MP) {
+ rsz_ctrl_addr += CIF_MRSZ_CTRL;
+ scale_h_y_addr += CIF_MRSZ_SCALE_HY;
+ scale_v_y_addr += CIF_MRSZ_SCALE_VY;
+ scale_h_cb_addr += CIF_MRSZ_SCALE_HCB;
+ scale_h_cr_addr += CIF_MRSZ_SCALE_HCR;
+ scale_v_c_addr += CIF_MRSZ_SCALE_VC;
+ dev->config.mp_config.rsz_config.input =
+ &dev->config.isp_config.output;
+ rsz_input = dev->config.mp_config.rsz_config.input;
+ rsz_output = &dev->config.mp_config.rsz_config.output;
+ mi_output = &dev->config.mi_config.mp.output;
+ /* No phase offset */
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_HY);
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_HC);
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_VY);
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_PHASE_VC);
+ /* Linear interpolation */
+ for (i = 0; i < 64; i++) {
+ cif_iowrite32(i,
+ dev->config.base_addr +
+ CIF_MRSZ_SCALE_LUT_ADDR);
+ cif_iowrite32(i,
+ dev->config.base_addr +
+ CIF_MRSZ_SCALE_LUT);
+ }
+ } else {
+ rsz_ctrl_addr += CIF_SRSZ_CTRL;
+ scale_h_y_addr += CIF_SRSZ_SCALE_HY;
+ scale_v_y_addr += CIF_SRSZ_SCALE_VY;
+ scale_h_cb_addr += CIF_SRSZ_SCALE_HCB;
+ scale_h_cr_addr += CIF_SRSZ_SCALE_HCR;
+ scale_v_c_addr += CIF_SRSZ_SCALE_VC;
+ if (dev->config.input_sel == CIF_ISP10_INP_DMA_SP)
+ dev->config.sp_config.rsz_config.input =
+ &dev->config.mi_config.dma.output;
+ else
+ dev->config.sp_config.rsz_config.input =
+ &dev->config.isp_config.output;
+
+ rsz_input = dev->config.sp_config.rsz_config.input;
+ rsz_output = &dev->config.sp_config.rsz_config.output;
+ mi_output = &dev->config.mi_config.sp.output;
+ /* No phase offset */
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_HY);
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_HC);
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_VY);
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_PHASE_VC);
+ /* Linear interpolation */
+ for (i = 0; i < 64; i++) {
+ cif_iowrite32(i,
+ dev->config.base_addr +
+ CIF_SRSZ_SCALE_LUT_ADDR);
+ cif_iowrite32(i,
+ dev->config.base_addr +
+ CIF_SRSZ_SCALE_LUT);
+ }
+ }
+
+ /* set RSZ input and output */
+ rsz_output->width = mi_output->width;
+ rsz_output->height = mi_output->height;
+ rsz_output->pix_fmt = rsz_input->pix_fmt;
+ if (CIF_ISP10_PIX_FMT_IS_YUV(mi_output->pix_fmt)) {
+ cif_isp10_pix_fmt_set_y_subs(
+ rsz_output->pix_fmt,
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(mi_output->pix_fmt));
+ cif_isp10_pix_fmt_set_x_subs(
+ rsz_output->pix_fmt,
+ CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(mi_output->pix_fmt));
+ cif_isp10_pix_fmt_set_bpp(
+ rsz_output->pix_fmt,
+ CIF_ISP10_PIX_FMT_GET_BPP(mi_output->pix_fmt));
+ } else if (CIF_ISP10_PIX_FMT_IS_JPEG(mi_output->pix_fmt)) {
+ cif_isp10_pix_fmt_set_y_subs(
+ rsz_output->pix_fmt, 4);
+ cif_isp10_pix_fmt_set_x_subs(
+ rsz_output->pix_fmt, 2);
+ cif_isp10_pix_fmt_set_bpp(
+ rsz_output->pix_fmt, 16);
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %s %dx%d -> %s %dx%d\n",
+ cif_isp10_stream_id_string(stream_id),
+ cif_isp10_pix_fmt_string(rsz_input->pix_fmt),
+ rsz_input->width,
+ rsz_input->height,
+ cif_isp10_pix_fmt_string(rsz_output->pix_fmt),
+ rsz_output->width,
+ rsz_output->height);
+
+ /* set input and output sizes for scale calculation */
+ input_width_y = rsz_input->width;
+ output_width_y = rsz_output->width;
+ input_height_y = rsz_input->height;
+ output_height_y = rsz_output->height;
+ input_width_c = input_width_y;
+ output_width_c = output_width_y;
+ input_height_c = input_height_y;
+ output_height_c = output_height_y;
+
+ if (CIF_ISP10_PIX_FMT_IS_YUV(rsz_output->pix_fmt)) {
+ input_width_c = (input_width_c *
+ CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ rsz_input->pix_fmt)) / 4;
+ input_height_c = (input_height_c *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ rsz_input->pix_fmt)) / 4;
+ output_width_c = (output_width_c *
+ CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(
+ rsz_output->pix_fmt)) / 4;
+ output_height_c = (output_height_c *
+ CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(
+ rsz_output->pix_fmt)) / 4;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "chroma scaling %dx%d -> %dx%d\n",
+ input_width_c, input_height_c,
+ output_width_c, output_height_c);
+
+ if (((input_width_c == 0) && (output_width_c > 0)) ||
+ ((input_height_c == 0) && (output_height_c > 0))) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "input is black and white, cannot output colour\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ if ((input_width_y != output_width_y) ||
+ (input_height_y != output_height_y)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "%dx%d -> %dx%d isn't support, can only scale YUV input\n",
+ input_width_y, input_height_y,
+ output_width_y, output_height_y);
+ ret = -EINVAL;
+ goto err;
+ }
+ }
+
+ /* calculate and set scale */
+ rsz_ctrl = 0;
+ if (input_width_y < output_width_y) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE |
+ CIF_RSZ_CTRL_SCALE_HY_UP;
+ cif_iowrite32(
+ DIV_TRUNCATE((input_width_y - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ output_width_y - 1),
+ scale_h_y_addr);
+ } else if (input_width_y > output_width_y) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HY_ENABLE;
+ cif_iowrite32(
+ DIV_TRUNCATE((output_width_y - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ input_width_y - 1) + 1,
+ scale_h_y_addr);
+ }
+ if (input_width_c < output_width_c) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE |
+ CIF_RSZ_CTRL_SCALE_HC_UP;
+ scale_h_c = DIV_TRUNCATE((input_width_c - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ output_width_c - 1);
+ cif_iowrite32(scale_h_c, scale_h_cb_addr);
+ cif_iowrite32(scale_h_c, scale_h_cr_addr);
+ } else if (input_width_c > output_width_c) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_HC_ENABLE;
+ scale_h_c = DIV_TRUNCATE((output_width_c - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ input_width_c - 1) + 1;
+ cif_iowrite32(scale_h_c, scale_h_cb_addr);
+ cif_iowrite32(scale_h_c, scale_h_cr_addr);
+ }
+
+ if (input_height_y < output_height_y) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE |
+ CIF_RSZ_CTRL_SCALE_VY_UP;
+ cif_iowrite32(
+ DIV_TRUNCATE((input_height_y - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ output_height_y - 1),
+ scale_v_y_addr);
+ } else if (input_height_y > output_height_y) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VY_ENABLE;
+ cif_iowrite32(
+ DIV_TRUNCATE((output_height_y - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ input_height_y - 1) + 1,
+ scale_v_y_addr);
+ }
+
+ if (input_height_c < output_height_c) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE |
+ CIF_RSZ_CTRL_SCALE_VC_UP;
+ cif_iowrite32(
+ DIV_TRUNCATE((input_height_c - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ output_height_c - 1),
+ scale_v_c_addr);
+ } else if (input_height_c > output_height_c) {
+ rsz_ctrl |= CIF_RSZ_CTRL_SCALE_VC_ENABLE;
+ cif_iowrite32(
+ DIV_TRUNCATE((output_height_c - 1)
+ * CIF_RSZ_SCALER_BYPASS,
+ input_height_c - 1) + 1,
+ scale_v_c_addr);
+ }
+
+ cif_iowrite32(rsz_ctrl, rsz_ctrl_addr);
+
+ if (stream_id == CIF_ISP10_STREAM_MP) {
+ if (async)
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_MRSZ_CTRL);
+ dev->config.mp_config.rsz_config.ycflt_adjust = false;
+ dev->config.mp_config.rsz_config.ism_adjust = false;
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MRSZ_CTRL 0x%08x/0x%08x\n"
+ " MRSZ_SCALE_HY %d/%d\n"
+ " MRSZ_SCALE_HCB %d/%d\n"
+ " MRSZ_SCALE_HCR %d/%d\n"
+ " MRSZ_SCALE_VY %d/%d\n"
+ " MRSZ_SCALE_VC %d/%d\n"
+ " MRSZ_PHASE_HY %d/%d\n"
+ " MRSZ_PHASE_HC %d/%d\n"
+ " MRSZ_PHASE_VY %d/%d\n"
+ " MRSZ_PHASE_VC %d/%d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCB),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCB_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCR),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_HCR_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_SCALE_VC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_HC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MRSZ_PHASE_VC_SHD));
+ } else {
+ if (async)
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_SRSZ_CTRL);
+ dev->config.sp_config.rsz_config.ycflt_adjust = false;
+ dev->config.sp_config.rsz_config.ism_adjust = false;
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n SRSZ_CTRL 0x%08x/0x%08x\n"
+ " SRSZ_SCALE_HY %d/%d\n"
+ " SRSZ_SCALE_HCB %d/%d\n"
+ " SRSZ_SCALE_HCR %d/%d\n"
+ " SRSZ_SCALE_VY %d/%d\n"
+ " SRSZ_SCALE_VC %d/%d\n"
+ " SRSZ_PHASE_HY %d/%d\n"
+ " SRSZ_PHASE_HC %d/%d\n"
+ " SRSZ_PHASE_VY %d/%d\n"
+ " SRSZ_PHASE_VC %d/%d\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_CTRL_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCB),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCB_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCR),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_HCR_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_SCALE_VC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_HC_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VY),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VY_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VC),
+ cif_ioread32(dev->config.base_addr +
+ CIF_SRSZ_PHASE_VC_SHD));
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_sp(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_SP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = cif_isp10_config_dcrop(dev, CIF_ISP10_STREAM_SP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = cif_isp10_config_mi_sp(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ dev->sp_stream.updt_cfg = false;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_config_mp(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_MP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = cif_isp10_config_dcrop(dev, CIF_ISP10_STREAM_MP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = cif_isp10_config_mi_mp(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ if (dev->config.jpeg_config.enable) {
+ ret = cif_isp10_config_jpeg_enc(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ dev->config.jpeg_config.busy = false;
+ }
+
+ dev->mp_stream.updt_cfg = false;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static void cif_isp10_config_clk(
+ struct cif_isp10_device *dev)
+{
+ cif_iowrite32(CIF_CCL_CIF_CLK_ENA,
+ dev->config.base_addr + CIF_CCL);
+ cif_iowrite32(0x0000187B, dev->config.base_addr + CIF_ICCL);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n CIF_CCL 0x%08x\n"
+ " CIF_ICCL 0x%08x\n",
+ cif_ioread32(dev->config.base_addr + CIF_CCL),
+ cif_ioread32(dev->config.base_addr + CIF_ICCL));
+}
+
+static int cif_isp10_config_cif(
+ struct cif_isp10_device *dev,
+ u32 stream_ids)
+{
+ int ret = 0;
+ u32 cif_id;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "config MP = %d, config SP = %d, img_src state = %s, PM state = %s, SP state = %s, MP state = %s\n",
+ (stream_ids & CIF_ISP10_STREAM_MP) == CIF_ISP10_STREAM_MP,
+ (stream_ids & CIF_ISP10_STREAM_SP) == CIF_ISP10_STREAM_SP,
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ cif_isp10_pm_state_string(dev->pm_state),
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state));
+
+ cif_isp10_pltfrm_rtrace_printf(NULL,
+ "start configuring CIF...\n");
+
+ if ((stream_ids & CIF_ISP10_STREAM_MP) ||
+ (stream_ids & CIF_ISP10_STREAM_SP)) {
+ ret = cif_isp10_set_pm_state(dev,
+ CIF_ISP10_PM_STATE_SW_STNDBY);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ /* configure sensor */
+ ret = cif_isp10_config_img_src(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+
+ cif_id = cif_ioread32(dev->config.base_addr + CIF_VI_ID);
+ dev->config.out_of_buffer_stall =
+ CIF_ISP10_ALWAYS_STALL_ON_NO_BUFS;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "CIF_ID 0x%08x\n", cif_id);
+
+ /*
+ * Cancel isp reset internal here temporary for
+ * isp bus may be dead when switch isp.
+ */
+ /*
+ * cif_iowrite32(CIF_IRCL_CIF_SW_RST,
+ * dev->config.base_addr + CIF_IRCL);
+ */
+
+ cif_isp10_config_clk(dev);
+
+ /* Decide when to switch to asynchronous mode */
+ /*
+ * TODO: remove dev->isp_dev.ycflt_en check for
+ * HW with the scaler fix.
+ */
+ dev->config.mi_config.async_updt = CIF_ISP10_ALWAYS_ASYNC;
+ if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ dev->config.mi_config.async_updt |= CIF_ISP10_ASYNC_DMA;
+ ret = cif_isp10_config_mi_dma(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+ if ((stream_ids & CIF_ISP10_STREAM_MP) &&
+ (dev->config.jpeg_config.enable))
+ dev->config.mi_config.async_updt |=
+ CIF_ISP10_ASYNC_JPEG;
+ if (dev->config.isp_config.ism_config.ism_en)
+ dev->config.mi_config.async_updt |=
+ CIF_ISP10_ASYNC_ISM;
+
+ if (PLTFRM_CAM_ITF_IS_MIPI(dev->config.cam_itf.type)) {
+ ret = cif_isp10_config_mipi(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+
+ ret = cif_isp10_config_isp(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ cif_isp10_config_ism(dev, true);
+ dev->config.isp_config.ism_config.ism_update_needed = false;
+
+ if (stream_ids & CIF_ISP10_STREAM_SP)
+ dev->config.sp_config.rsz_config.ism_adjust = true;
+ if (stream_ids & CIF_ISP10_STREAM_MP)
+ dev->config.mp_config.rsz_config.ism_adjust = true;
+
+ if (stream_ids & CIF_ISP10_STREAM_SP) {
+ ret = cif_isp10_config_sp(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+
+ if (stream_ids & CIF_ISP10_STREAM_MP) {
+ ret = cif_isp10_config_mp(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+ ret = cif_isp10_config_path(dev, stream_ids);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+
+ /* Turn off XNR vertical subsampling when ism cropping is enabled */
+ if (dev->config.isp_config.ism_config.ism_en) {
+ if (!dev->isp_dev.cif_ism_cropping)
+ dev->isp_dev.cif_ism_cropping = true;
+ } else {
+ if (dev->isp_dev.cif_ism_cropping)
+ dev->isp_dev.cif_ism_cropping = false;
+ }
+
+ if (dev->config.sp_config.rsz_config.ycflt_adjust ||
+ dev->config.sp_config.rsz_config.ism_adjust) {
+ if (dev->sp_stream.state == CIF_ISP10_STATE_READY) {
+ ret = cif_isp10_config_rsz(dev,
+ CIF_ISP10_STREAM_SP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ } else {
+ /* Disable SRSZ if SP is not used */
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_CTRL);
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_SRSZ_CTRL);
+ dev->config.sp_config.rsz_config.ycflt_adjust = false;
+ dev->config.sp_config.rsz_config.ism_adjust = false;
+ }
+ }
+
+ if (dev->config.mp_config.rsz_config.ycflt_adjust ||
+ dev->config.mp_config.rsz_config.ism_adjust) {
+ if (dev->mp_stream.state == CIF_ISP10_STATE_READY) {
+ ret = cif_isp10_config_rsz(dev,
+ CIF_ISP10_STREAM_MP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ } else {
+ /* Disable MRSZ if MP is not used */
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_CTRL);
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_MRSZ_CTRL);
+ dev->config.mp_config.rsz_config.ycflt_adjust = false;
+ dev->config.mp_config.rsz_config.ism_adjust = false;
+ }
+ }
+
+ if (dev->config.mi_config.async_updt)
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "CIF in asynchronous mode (0x%08x)\n",
+ dev->config.mi_config.async_updt);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static void cif_isp10_init_stream(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id)
+{
+ struct cif_isp10_stream *stream = NULL;
+
+ switch (stream_id) {
+ case CIF_ISP10_STREAM_SP:
+ stream = &dev->sp_stream;
+ dev->config.sp_config.rsz_config.ycflt_adjust = false;
+ dev->config.sp_config.rsz_config.ism_adjust = false;
+ dev->config.mi_config.sp.busy = false;
+ break;
+ case CIF_ISP10_STREAM_MP:
+ stream = &dev->mp_stream;
+ dev->config.jpeg_config.ratio = 50;
+ dev->config.jpeg_config.header =
+ CIF_ISP10_JPEG_HEADER_JFIF;
+ dev->config.jpeg_config.enable = false;
+ dev->config.mi_config.raw_enable = false;
+ dev->config.mp_config.rsz_config.ycflt_adjust = false;
+ dev->config.mp_config.rsz_config.ism_adjust = false;
+ dev->config.mi_config.mp.busy = false;
+ break;
+ case CIF_ISP10_STREAM_DMA:
+ stream = &dev->dma_stream;
+ dev->config.mi_config.dma.busy = false;
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported stream ID %d\n", stream_id);
+ WARN_ON(1);
+ break;
+ }
+
+ INIT_LIST_HEAD(&stream->buf_queue);
+ stream->next_buf = NULL;
+ stream->curr_buf = NULL;
+ stream->updt_cfg = false;
+ stream->stop = false;
+ stream->stall = false;
+
+ cif_isp10_pltfrm_event_clear(dev->dev, &stream->done);
+ stream->state = CIF_ISP10_STATE_INACTIVE;
+}
+
+static int cif_isp10_jpeg_gen_header(
+ struct cif_isp10_device *dev)
+{
+ unsigned int timeout = 10000;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ cif_iowrite32(CIF_JPE_GEN_HEADER_ENABLE,
+ dev->config.base_addr + CIF_JPE_GEN_HEADER);
+
+ while (timeout--) {
+ if (cif_ioread32(dev->config.base_addr +
+ CIF_JPE_STATUS_RIS) &
+ CIF_JPE_STATUS_GENHEADER_DONE) {
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "JPEG header generated\n");
+ cif_iowrite32(CIF_JPE_STATUS_GENHEADER_DONE,
+ dev->config.base_addr + CIF_JPE_STATUS_ICR);
+ break;
+ }
+ }
+
+ if (!timeout) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "JPEG header generation timeout\n");
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", -ETIMEDOUT);
+ return -ETIMEDOUT;
+ }
+
+#ifdef CIF_ISP10_VERIFY_JPEG_HEADER
+ {
+ u32 *buff = (u32 *)phys_to_virt(
+ dev->config.mi_config.mp.curr_buff_addr);
+ if (buff[0] != 0xe0ffd8ff)
+ cif_isp10_pltfrm_pr_err(NULL,
+ "JPEG HEADER WRONG: 0x%08x\n"
+ "curr_buff_addr 0x%08x\n"
+ "MI_MP_Y_SIZE_SHD 0x%08x\n"
+ "MI_MP_Y_BASE_AD_SHD 0x%08x\n",
+ buff[0],
+ dev->config.mi_config.mp.curr_buff_addr,
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_SIZE_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_SHD));
+ }
+#endif
+
+ return 0;
+}
+
+static void cif_isp10_mi_update_buff_addr(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id strm_id)
+{
+ if (strm_id == CIF_ISP10_STREAM_SP) {
+ cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr,
+ dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
+ dev->config.mi_config.sp.cb_offs,
+ dev->config.base_addr +
+ CIF_MI_SP_CB_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.sp.next_buff_addr +
+ dev->config.mi_config.sp.cr_offs,
+ dev->config.base_addr +
+ CIF_MI_SP_CR_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ /*
+ * There have bee repeatedly issues with
+ * the offset registers, it is safer to write
+ * them each time, even though it is always
+ * 0 and even though that is the
+ * register's default value
+ */
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_SP_Y_OFFS_CNT_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_SP_CB_OFFS_CNT_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_SP_CR_OFFS_CNT_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_SP_Y_BASE_AD 0x%08x/0x%08x\n"
+ " MI_SP_CB_BASE_AD 0x%08x/0x%08x\n"
+ " MI_SP_CR_BASE_AD 0x%08x/0x%08x\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CB_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_CR_BASE_AD_SHD));
+ } else if (strm_id == CIF_ISP10_STREAM_MP) {
+ cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr,
+ dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr +
+ dev->config.mi_config.mp.cb_offs,
+ dev->config.base_addr +
+ CIF_MI_MP_CB_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.mp.next_buff_addr +
+ dev->config.mi_config.mp.cr_offs,
+ dev->config.base_addr +
+ CIF_MI_MP_CR_BASE_AD_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ /*
+ * There have bee repeatedly issues with
+ * the offset registers, it is safer to write
+ * them each time, even though it is always
+ * 0 and even though that is the
+ * register's default value
+ */
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_MP_Y_OFFS_CNT_INIT, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_MP_CB_OFFS_CNT_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(0,
+ dev->config.base_addr +
+ CIF_MI_MP_CR_OFFS_CNT_INIT,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_MP_Y_BASE_AD 0x%08x/0x%08x\n"
+ " MI_MP_CB_BASE_AD 0x%08x/0x%08x\n"
+ " MI_MP_CR_BASE_AD 0x%08x/0x%08x\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CB_BASE_AD_SHD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_BASE_AD_INIT),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_CR_BASE_AD_SHD));
+ } else { /* DMA */
+ cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr,
+ dev->config.base_addr +
+ CIF_MI_DMA_Y_PIC_START_AD, CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr +
+ dev->config.mi_config.dma.cb_offs,
+ dev->config.base_addr +
+ CIF_MI_DMA_CB_PIC_START_AD,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_iowrite32_verify(dev->config.mi_config.dma.next_buff_addr +
+ dev->config.mi_config.dma.cr_offs,
+ dev->config.base_addr +
+ CIF_MI_DMA_CR_PIC_START_AD,
+ CIF_MI_ADDR_SIZE_ALIGN_MASK);
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_DMA_Y_PIC_START_AD 0x%08x\n"
+ " MI_DMA_CB_PIC_START_AD 0x%08x\n"
+ " MI_DMA_CR_PIC_START_AD 0x%08x\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_Y_PIC_START_AD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CB_PIC_START_AD),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CR_PIC_START_AD));
+ }
+}
+
+static int cif_isp10_update_mi_mp(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+ enum cif_isp10_pix_fmt out_pix_fmt =
+ dev->config.mi_config.mp.output.pix_fmt;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "curr 0x%08x next 0x%08x\n",
+ dev->config.mi_config.mp.curr_buff_addr,
+ dev->config.mi_config.mp.next_buff_addr);
+
+ if (dev->config.jpeg_config.enable) {
+ /*
+ * in case of jpeg encoding, we don't have to disable the
+ * MI, because the encoding
+ * anyway has to be started explicitly
+ */
+ if (!dev->config.jpeg_config.busy) {
+ if ((dev->config.mi_config.mp.curr_buff_addr !=
+ dev->config.mi_config.mp.next_buff_addr) &&
+ (dev->config.mi_config.mp.curr_buff_addr !=
+ CIF_ISP10_INVALID_BUFF_ADDR)) {
+ ret = cif_isp10_jpeg_gen_header(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "Starting JPEG encoding\n");
+ cif_isp10_pltfrm_rtrace_printf(dev->dev,
+ "Starting JPEG encoding\n");
+ cif_iowrite32(CIF_JPE_ENCODE_ENABLE,
+ dev->config.base_addr + CIF_JPE_ENCODE);
+ cif_iowrite32(CIF_JPE_INIT_ENABLE,
+ dev->config.base_addr +
+ CIF_JPE_INIT);
+ dev->config.jpeg_config.busy = true;
+ }
+ if (dev->config.mi_config.mp.next_buff_addr !=
+ CIF_ISP10_INVALID_BUFF_ADDR)
+ cif_isp10_mi_update_buff_addr(dev,
+ CIF_ISP10_STREAM_MP);
+ dev->config.mi_config.mp.curr_buff_addr =
+ dev->config.mi_config.mp.next_buff_addr;
+ }
+ } else {
+ if (dev->config.mi_config.mp.next_buff_addr !=
+ dev->config.mi_config.mp.curr_buff_addr) {
+ if (dev->config.mi_config.mp.next_buff_addr ==
+ CIF_ISP10_INVALID_BUFF_ADDR) {
+ /* disable MI MP */
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "disabling MP MI\n");
+ cif_iowrite32AND_verify(
+ ~(CIF_MI_CTRL_MP_ENABLE_IN |
+ CIF_MI_CTRL_JPEG_ENABLE |
+ CIF_MI_CTRL_RAW_ENABLE),
+ dev->config.base_addr + CIF_MI_CTRL,
+ ~0);
+ } else if (dev->config.mi_config.mp.curr_buff_addr ==
+ CIF_ISP10_INVALID_BUFF_ADDR) {
+ /* re-enable MI MP */
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "enabling MP MI\n");
+ cif_iowrite32(CIF_MI_MP_FRAME,
+ dev->config.base_addr + CIF_MI_ICR);
+ cif_iowrite32AND_verify(
+ ~(CIF_MI_CTRL_MP_ENABLE_IN |
+ CIF_MI_CTRL_JPEG_ENABLE |
+ CIF_MI_CTRL_RAW_ENABLE),
+ dev->config.base_addr +
+ CIF_MI_CTRL, ~0);
+ if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER
+ (out_pix_fmt)) {
+ cif_iowrite32OR_verify(
+ CIF_MI_CTRL_RAW_ENABLE,
+ dev->config.base_addr +
+ CIF_MI_CTRL,
+ ~0);
+ } else if (CIF_ISP10_PIX_FMT_IS_YUV
+ (out_pix_fmt)) {
+ cif_iowrite32OR_verify(
+ CIF_MI_CTRL_MP_ENABLE_IN,
+ dev->config.base_addr +
+ CIF_MI_CTRL, ~0);
+ }
+ }
+ cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_MP);
+ dev->config.mi_config.mp.curr_buff_addr =
+ dev->config.mi_config.mp.next_buff_addr;
+ }
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_update_mi_sp(
+ struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "curr 0x%08x next 0x%08x\n",
+ dev->config.mi_config.sp.curr_buff_addr,
+ dev->config.mi_config.sp.next_buff_addr);
+
+ if (dev->config.mi_config.sp.next_buff_addr !=
+ dev->config.mi_config.sp.curr_buff_addr) {
+ if (dev->config.mi_config.sp.next_buff_addr ==
+ CIF_ISP10_INVALID_BUFF_ADDR) {
+ /* disable MI SP */
+ cif_isp10_pltfrm_pr_dbg(NULL, "disabling SP MI\n");
+ /* 'switch off' MI interface */
+ cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ } else if (dev->config.mi_config.sp.curr_buff_addr ==
+ CIF_ISP10_INVALID_BUFF_ADDR) {
+ /* re-enable MI SP */
+ cif_isp10_pltfrm_pr_dbg(NULL, "enabling SP MI\n");
+ cif_iowrite32(CIF_MI_SP_FRAME,
+ dev->config.base_addr + CIF_MI_ICR);
+ cif_iowrite32OR_verify(CIF_MI_CTRL_SP_ENABLE,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ }
+ cif_isp10_mi_update_buff_addr(dev, CIF_ISP10_STREAM_SP);
+ dev->config.mi_config.sp.curr_buff_addr =
+ dev->config.mi_config.sp.next_buff_addr;
+ }
+
+ return 0;
+}
+
+static int cif_isp10_s_fmt_mp(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_strm_fmt *strm_fmt,
+ u32 stride)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d@%d/%dfps, stride = %d, quantization: %d\n",
+ cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+ strm_fmt->frm_fmt.width,
+ strm_fmt->frm_fmt.height,
+ strm_fmt->frm_intrvl.numerator,
+ strm_fmt->frm_intrvl.denominator,
+ stride,
+ strm_fmt->frm_fmt.quantization);
+
+ /* TBD: check whether format is a valid format for MP */
+
+ if (CIF_ISP10_PIX_FMT_IS_JPEG(strm_fmt->frm_fmt.pix_fmt)) {
+ dev->config.jpeg_config.enable = true;
+ } else if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER
+ (strm_fmt->frm_fmt.pix_fmt)) {
+ if ((dev->sp_stream.state == CIF_ISP10_STATE_READY) ||
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "cannot output RAW data when SP is active, you will not be able to (re-)start streaming\n");
+ dev->config.mi_config.raw_enable = true;
+ }
+
+ dev->config.mi_config.mp.output = strm_fmt->frm_fmt;
+ dev->config.mi_config.mp.output.stride = stride;
+
+ dev->config.mi_config.mp.llength =
+ cif_isp10_calc_llength(
+ strm_fmt->frm_fmt.width,
+ stride,
+ strm_fmt->frm_fmt.pix_fmt);
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "mp llength=0x%x\n", dev->config.mi_config.mp.llength);
+
+ dev->mp_stream.updt_cfg = true;
+ dev->mp_stream.state = CIF_ISP10_STATE_READY;
+
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ ret = cif_isp10_img_src_select_strm_fmt(dev);
+ if (IS_ERR_VALUE(ret)) {
+ dev->mp_stream.updt_cfg = false;
+ dev->mp_stream.state = CIF_ISP10_STATE_INACTIVE;
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_s_fmt_sp(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_strm_fmt *strm_fmt,
+ u32 stride)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d@%d/%dfps, stride = %d, quantization: %d\n",
+ cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+ strm_fmt->frm_fmt.width,
+ strm_fmt->frm_fmt.height,
+ strm_fmt->frm_intrvl.numerator,
+ strm_fmt->frm_intrvl.denominator,
+ stride,
+ strm_fmt->frm_fmt.quantization);
+
+ if (dev->config.mi_config.raw_enable)
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "cannot activate SP when MP is set to RAW data output, you will not be able to (re-)start streaming\n");
+
+ /* TBD: more detailed check whether format is a valid format for SP */
+ /* TBD: remove the mode stuff */
+ if (!CIF_ISP10_PIX_FMT_IS_YUV(strm_fmt->frm_fmt.pix_fmt) &&
+ !CIF_ISP10_PIX_FMT_IS_RGB(strm_fmt->frm_fmt.pix_fmt)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "format %s %dx%d@%d/%dfps, stride = %d not supported on SP\n",
+ cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+ strm_fmt->frm_fmt.width,
+ strm_fmt->frm_fmt.height,
+ strm_fmt->frm_intrvl.numerator,
+ strm_fmt->frm_intrvl.denominator,
+ stride);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev->config.mi_config.sp.output = strm_fmt->frm_fmt;
+ dev->config.mi_config.sp.llength =
+ cif_isp10_calc_llength(
+ strm_fmt->frm_fmt.width,
+ stride,
+ strm_fmt->frm_fmt.pix_fmt);
+
+ dev->sp_stream.updt_cfg = true;
+ dev->sp_stream.state = CIF_ISP10_STATE_READY;
+
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ ret = cif_isp10_img_src_select_strm_fmt(dev);
+ if (IS_ERR_VALUE(ret)) {
+ dev->sp_stream.updt_cfg = false;
+ dev->sp_stream.state = CIF_ISP10_STATE_INACTIVE;
+ goto err;
+ }
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_s_fmt_dma(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_strm_fmt *strm_fmt,
+ u32 stride)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s %dx%d@%d/%dfps, stride = %d\n",
+ cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+ strm_fmt->frm_fmt.width,
+ strm_fmt->frm_fmt.height,
+ strm_fmt->frm_intrvl.numerator,
+ strm_fmt->frm_intrvl.denominator,
+ stride);
+
+ if (!CIF_ISP10_PIX_FMT_IS_YUV(strm_fmt->frm_fmt.pix_fmt) &&
+ !CIF_ISP10_PIX_FMT_IS_RAW_BAYER(strm_fmt->frm_fmt.pix_fmt)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "format %s %dx%d@%d/%dfps, stride = %d not supported for DMA\n",
+ cif_isp10_pix_fmt_string(strm_fmt->frm_fmt.pix_fmt),
+ strm_fmt->frm_fmt.width,
+ strm_fmt->frm_fmt.height,
+ strm_fmt->frm_intrvl.numerator,
+ strm_fmt->frm_intrvl.denominator,
+ stride);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev->config.mi_config.dma.output = strm_fmt->frm_fmt;
+ dev->config.mi_config.dma.llength =
+ cif_isp10_calc_llength(
+ strm_fmt->frm_fmt.width,
+ stride,
+ strm_fmt->frm_fmt.pix_fmt);
+
+ dev->dma_stream.updt_cfg = true;
+ dev->dma_stream.state = CIF_ISP10_STATE_READY;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static void cif_isp10_dma_next_buff(
+ struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ if (!list_empty(&dev->dma_stream.buf_queue) &&
+ !dev->dma_stream.stop) {
+ if (dev->dma_stream.curr_buf)
+ WARN_ON(1);
+ dev->dma_stream.curr_buf =
+ list_first_entry(&dev->dma_stream.buf_queue,
+ struct videobuf_buffer, queue);
+ list_del(&dev->dma_stream.curr_buf->queue);
+ dev->dma_stream.curr_buf->state = VIDEOBUF_ACTIVE;
+ dev->config.mi_config.dma.next_buff_addr =
+ videobuf_to_dma_contig(
+ dev->dma_stream.curr_buf);
+ cif_isp10_mi_update_buff_addr(dev,
+ CIF_ISP10_STREAM_DMA);
+ dev->config.mi_config.dma.busy = true;
+ if ((dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) &&
+ dev->sp_stream.curr_buf)
+ dev->config.mi_config.sp.busy = true;
+ if ((dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) &&
+ dev->mp_stream.curr_buf)
+ dev->config.mi_config.mp.busy = true;
+ /* workaround for write register failure bug */
+ do {
+ cif_iowrite32(CIF_MI_DMA_START_ENABLE,
+ dev->config.base_addr + CIF_MI_DMA_START);
+ udelay(1);
+ } while (!cif_ioread32(
+ dev->config.base_addr + CIF_MI_DMA_STATUS));
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_DMA_CTRL 0x%08x\n"
+ " MI_DMA_STATUS 0x%08x\n",
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_CTRL),
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_DMA_STATUS));
+}
+
+static void cif_isp10_dma_ready(
+ struct cif_isp10_device *dev)
+{
+ unsigned int mi_mis_tmp;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ cif_iowrite32(CIF_MI_DMA_READY,
+ dev->config.base_addr + CIF_MI_ICR);
+ mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+ if (mi_mis_tmp & CIF_MI_DMA_READY)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "dma icr err: 0x%x\n",
+ mi_mis_tmp);
+ dev->dma_stream.curr_buf->state = VIDEOBUF_DONE;
+ wake_up(&dev->dma_stream.curr_buf->done);
+ dev->dma_stream.curr_buf = NULL;
+ dev->config.mi_config.dma.busy = false;
+ cif_isp10_pltfrm_event_signal(dev->dev, &dev->dma_stream.done);
+}
+
+static int cif_isp10_mi_frame_end(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id)
+{
+ struct cif_isp10_stream *stream = NULL;
+ u32 *next_buff_addr = NULL;
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR y_base_addr;
+ int (*update_mi)(
+ struct cif_isp10_device *dev);
+ struct cif_isp10_isp_readout_work *work;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+ cif_isp10_stream_id_string(stream_id));
+
+ if (stream_id == CIF_ISP10_STREAM_MP) {
+ stream = &dev->mp_stream;
+ y_base_addr =
+ dev->config.base_addr + CIF_MI_MP_Y_BASE_AD_SHD;
+ next_buff_addr = &dev->config.mi_config.mp.next_buff_addr;
+ update_mi = cif_isp10_update_mi_mp;
+ if (dev->config.jpeg_config.enable) {
+ unsigned int jpe_status =
+ cif_ioread32(dev->config.base_addr +
+ CIF_JPE_STATUS_RIS);
+ if (jpe_status & CIF_JPE_STATUS_ENCODE_DONE) {
+ cif_iowrite32(CIF_JPE_STATUS_ENCODE_DONE,
+ dev->config.base_addr +
+ CIF_JPE_STATUS_ICR);
+ if (stream->curr_buf) {
+ stream->curr_buf->size =
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_BYTE_CNT);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "JPEG encoding done, size %lu\n",
+ stream->curr_buf->size);
+ if (cif_ioread32(dev->config.base_addr +
+ CIF_MI_RIS) & CIF_MI_WRAP_MP_Y)
+ cif_isp10_pltfrm_pr_err(NULL,
+ "buffer wrap around detected, JPEG presumably corrupted (%d/%d/%lu)\n",
+ dev->config.mi_config.
+ mp.y_size,
+ cif_ioread32(
+ dev->config.base_addr +
+ CIF_MI_MP_Y_SIZE_SHD),
+ stream->curr_buf->size);
+ }
+ }
+ }
+ } else if (stream_id == CIF_ISP10_STREAM_SP) {
+ stream = &dev->sp_stream;
+ y_base_addr =
+ dev->config.base_addr + CIF_MI_SP_Y_BASE_AD_SHD;
+ next_buff_addr = &dev->config.mi_config.sp.next_buff_addr;
+ update_mi = cif_isp10_update_mi_sp;
+ } else {
+ WARN_ON(1);
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s Y_BASE_AD_INIT/Y_BASE_AD_SHD (0x%08x/0x%08x)\n",
+ cif_isp10_stream_id_string(stream_id),
+ (stream_id & CIF_ISP10_STREAM_MP) ?
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_INIT) :
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_INIT),
+ cif_ioread32(y_base_addr));
+
+ if ((!stream->next_buf) &&
+ !(dev->config.jpeg_config.enable &&
+ (stream_id == CIF_ISP10_STREAM_MP))) {
+ stream->stall = dev->config.out_of_buffer_stall;
+ } else if ((stream->next_buf) &&
+ (videobuf_to_dma_contig(stream->next_buf) !=
+ cif_ioread32(y_base_addr))) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "%s buffer queue is not advancing (0x%08x/0x%08x)\n",
+ cif_isp10_stream_id_string(stream_id),
+ (stream_id & CIF_ISP10_STREAM_MP) ?
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_BASE_AD_INIT) :
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_BASE_AD_INIT),
+ cif_ioread32(y_base_addr));
+ stream->stall = true;
+ }
+
+ if (!stream->stall) {
+ /*
+ * If mi restart after switch off for buffer is empty,
+ * mi may be restart failed. So mi write data to last
+ * buffer, the last buffer isn't been release to user
+ * until new buffer queue;
+ */
+ if ((stream->curr_buf) &&
+ (stream->next_buf)) {
+ bool wake_now;
+
+ stream->curr_buf->field_count = dev->isp_dev.frame_id;
+ stream->curr_buf->state = VIDEOBUF_DONE;
+ wake_now = false;
+
+ if (stream->metadata.d && dev->isp_dev.streamon) {
+ struct v4l2_buffer_metadata_s *metadata;
+
+ metadata = (struct v4l2_buffer_metadata_s *)
+ (stream->metadata.d +
+ stream->curr_buf->i *
+ CAMERA_METADATA_LEN);
+ metadata->frame_id = dev->isp_dev.frame_id;
+ metadata->frame_t.vs_t = dev->isp_dev.vs_t;
+ metadata->frame_t.fi_t = dev->isp_dev.fi_t;
+
+ work = (struct cif_isp10_isp_readout_work *)
+ kmalloc(
+ sizeof(
+ struct cif_isp10_isp_readout_work),
+ GFP_ATOMIC);
+ if (work) {
+ INIT_WORK((struct work_struct *)work,
+ cifisp_isp_readout_work);
+ work->readout =
+ CIF_ISP10_ISP_READOUT_META;
+ work->isp_dev =
+ &dev->isp_dev;
+ work->frame_id =
+ dev->isp_dev.frame_id;
+ work->vb = stream->curr_buf;
+ work->stream_id = stream->id;
+ if (!queue_work(dev->isp_dev.readout_wq,
+ (struct work_struct *)work)) {
+ cif_isp10_pltfrm_pr_err(
+ dev->dev,
+ "Could not schedule work\n");
+ wake_now = true;
+ kfree((void *)work);
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "Could not allocate work\n");
+ wake_now = true;
+ }
+ } else {
+ wake_now = true;
+ }
+
+ if (wake_now) {
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "frame done\n");
+ wake_up(&stream->curr_buf->done);
+ }
+ stream->curr_buf = NULL;
+ }
+
+ if (!stream->curr_buf) {
+ stream->curr_buf = stream->next_buf;
+ stream->next_buf = NULL;
+ }
+ }
+
+ if (!stream->next_buf) {
+ /*
+ * in case of jpeg encoding, we are only programming
+ * a new buffer, if the jpeg header was generated, because
+ * we need the curent buffer for the jpeg encoding
+ * in the current frame period
+ */
+ if (!list_empty(&stream->buf_queue)) {
+ stream->next_buf =
+ list_first_entry(&stream->buf_queue,
+ struct videobuf_buffer, queue);
+ list_del(&stream->next_buf->queue);
+ stream->next_buf->state = VIDEOBUF_ACTIVE;
+ *next_buff_addr = videobuf_to_dma_contig(
+ stream->next_buf);
+ } else if (
+ !dev->config.out_of_buffer_stall ||
+ (dev->config.jpeg_config.enable &&
+ (stream_id == CIF_ISP10_STREAM_MP))) {
+/*
+ * If mi restart after switch off for buffer is empty,
+ * mi may be restart failed. So mi write data to last
+ * buffer, the last buffer isn't been release to user
+ * until new buffer queue;
+ *
+ * if
+ * *next_buff_addr = CIF_ISP10_INVALID_BUFF_ADDR;
+ * mi will stop;
+ */
+ *next_buff_addr =
+ videobuf_to_dma_contig(
+ stream->curr_buf);
+ }
+ }
+ (void)update_mi(dev);
+
+ stream->stall = false;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s curr_buff: %d, 0x%08x next_buf: %d, 0x%x\n",
+ cif_isp10_stream_id_string(stream_id),
+ (stream->curr_buf) ? stream->curr_buf->i : -1,
+ (stream->curr_buf) ? (int)videobuf_to_dma_contig
+ (stream->curr_buf) : -1,
+ (stream->next_buf) ? stream->next_buf->i : -1,
+ *next_buff_addr);
+
+ return 0;
+}
+
+static void cif_isp10_stream_metadata_reset(
+ struct cif_isp10_stream *stream_dev
+)
+{
+ unsigned int i;
+ struct v4l2_buffer_metadata_s *metadata;
+ struct cifisp_isp_metadata *isp_metadata;
+
+ if (stream_dev->metadata.d) {
+ for (i = 0; i < stream_dev->metadata.cnt; i++) {
+ metadata = (struct v4l2_buffer_metadata_s *)
+ (stream_dev->metadata.d +
+ i * CAMERA_METADATA_LEN);
+ isp_metadata = (struct cifisp_isp_metadata *)
+ metadata->isp;
+ isp_metadata->other_cfg.s_frame_id = 0xffffffff;
+ isp_metadata->meas_cfg.s_frame_id = 0xffffffff;
+ }
+ }
+}
+
+static void cif_isp10_start_mi(
+ struct cif_isp10_device *dev,
+ bool start_mi_sp,
+ bool start_mi_mp)
+{
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+ if (start_mi_sp &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+ start_mi_sp = false;
+ if (start_mi_mp &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+ start_mi_mp = false;
+ if (!start_mi_sp && !start_mi_mp)
+ return;
+
+ if ((start_mi_sp &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) ||
+ (start_mi_mp &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))
+ WARN_ON(1);
+
+ if (start_mi_sp) {
+ cif_isp10_stream_metadata_reset(&dev->sp_stream);
+ dev->config.mi_config.sp.next_buff_addr =
+ CIF_ISP10_INVALID_BUFF_ADDR;
+ dev->config.mi_config.sp.curr_buff_addr =
+ CIF_ISP10_INVALID_BUFF_ADDR;
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_SP);
+ spin_unlock(&dev->vbq_lock);
+ dev->sp_stream.stall = false;
+ }
+
+ if (start_mi_mp) {
+ cif_isp10_stream_metadata_reset(&dev->mp_stream);
+ dev->config.mi_config.mp.next_buff_addr =
+ CIF_ISP10_INVALID_BUFF_ADDR;
+ dev->config.mi_config.mp.curr_buff_addr =
+ CIF_ISP10_INVALID_BUFF_ADDR;
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_MP);
+ spin_unlock(&dev->vbq_lock);
+ dev->mp_stream.stall = false;
+ }
+
+ cif_iowrite32OR(CIF_MI_INIT_SOFT_UPD,
+ dev->config.base_addr + CIF_MI_INIT);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "CIF_MI_INIT_SOFT_UPD\n");
+
+ if (start_mi_sp) {
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_SP);
+ spin_unlock(&dev->vbq_lock);
+ if (dev->sp_stream.curr_buf &&
+ (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)))
+ dev->config.mi_config.sp.busy = true;
+ }
+
+ if (start_mi_mp) {
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_mi_frame_end(dev, CIF_ISP10_STREAM_MP);
+ spin_unlock(&dev->vbq_lock);
+ if (dev->mp_stream.curr_buf &&
+ (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)))
+ dev->config.mi_config.mp.busy = true;
+ }
+
+ if (!dev->config.mi_config.async_updt)
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_GEN_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+}
+
+static void cif_isp10_stop_mi(
+ struct cif_isp10_device *dev,
+ bool stop_mi_sp,
+ bool stop_mi_mp)
+{
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "\n");
+
+ if (stop_mi_sp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING))
+ stop_mi_sp = false;
+ if (stop_mi_mp &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING))
+ stop_mi_mp = false;
+
+ if (!stop_mi_sp && !stop_mi_mp)
+ return;
+
+ if (stop_mi_sp && stop_mi_mp) {
+ cif_iowrite32AND_verify(~(CIF_MI_SP_FRAME |
+ CIF_MI_MP_FRAME |
+ CIF_JPE_STATUS_ENCODE_DONE),
+ dev->config.base_addr + CIF_MI_IMSC, ~0);
+ cif_iowrite32(CIF_MI_SP_FRAME |
+ CIF_MI_MP_FRAME |
+ CIF_JPE_STATUS_ENCODE_DONE,
+ dev->config.base_addr + CIF_MI_ICR);
+ cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ cif_iowrite32AND_verify(~(CIF_MI_CTRL_MP_ENABLE_IN |
+ CIF_MI_CTRL_SP_ENABLE |
+ CIF_MI_CTRL_JPEG_ENABLE |
+ CIF_MI_CTRL_RAW_ENABLE),
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ cif_iowrite32(CIF_MI_INIT_SOFT_UPD,
+ dev->config.base_addr + CIF_MI_INIT);
+ } else if (stop_mi_sp) {
+ cif_iowrite32(CIF_MI_SP_FRAME,
+ dev->config.base_addr + CIF_MI_ICR);
+ cif_iowrite32AND_verify(~CIF_MI_CTRL_SP_ENABLE,
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ } else if (stop_mi_mp) {
+ cif_iowrite32(CIF_MI_MP_FRAME |
+ CIF_JPE_STATUS_ENCODE_DONE,
+ dev->config.base_addr + CIF_MI_ICR);
+ cif_iowrite32AND_verify(~(CIF_MI_CTRL_MP_ENABLE_IN |
+ CIF_MI_CTRL_JPEG_ENABLE |
+ CIF_MI_CTRL_RAW_ENABLE),
+ dev->config.base_addr + CIF_MI_CTRL, ~0);
+ }
+}
+
+static void cif_isp10_requeue_bufs(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_stream *stream)
+{
+ INIT_LIST_HEAD(&stream->buf_queue);
+ stream->next_buf = NULL;
+ stream->curr_buf = NULL;
+ dev->requeue_bufs(dev, stream->id);
+}
+
+static void cif_isp10_stop_sp(
+ struct cif_isp10_device *dev)
+{
+ int ret;
+
+ if (dev->sp_stream.state ==
+ CIF_ISP10_STATE_STREAMING) {
+ dev->sp_stream.stop = true;
+ ret = cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+ &dev->sp_stream.done,
+ dev->sp_stream.state !=
+ CIF_ISP10_STATE_STREAMING,
+ 1000000);
+ dev->sp_stream.stop = false;
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_warn(NULL,
+ "waiting on event returned with error %d\n",
+ ret);
+ }
+ if (dev->config.mi_config.sp.busy)
+ cif_isp10_pltfrm_pr_warn(NULL,
+ "SP path still active while stopping it\n");
+ }
+}
+
+static void cif_isp10_stop_mp(
+ struct cif_isp10_device *dev)
+{
+ int ret;
+
+ if (dev->mp_stream.state ==
+ CIF_ISP10_STATE_STREAMING) {
+ dev->mp_stream.stop = true;
+ ret = cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+ &dev->mp_stream.done,
+ dev->mp_stream.state !=
+ CIF_ISP10_STATE_STREAMING,
+ 1000000);
+ dev->mp_stream.stop = false;
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_warn(NULL,
+ "waiting on event returned with error %d\n",
+ ret);
+ }
+ if (dev->config.mi_config.mp.busy ||
+ dev->config.jpeg_config.busy)
+ cif_isp10_pltfrm_pr_warn(NULL,
+ "MP path still active while stopping it\n");
+ }
+}
+
+static void cif_isp10_stop_dma(
+ struct cif_isp10_device *dev)
+{
+ unsigned long flags = 0;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ if (dev->dma_stream.state ==
+ CIF_ISP10_STATE_STREAMING) {
+ /* we should not stop during an active DMA transfer */
+ dev->dma_stream.stop = true;
+ (void)cif_isp10_pltfrm_event_wait_timeout(dev->dev,
+ &dev->dma_stream.done,
+ dev->dma_stream.state !=
+ CIF_ISP10_STATE_STREAMING,
+ 50000);
+ /* intentionally NOT checking dma.busy again */
+ if (dev->config.mi_config.dma.busy)
+ cif_isp10_pltfrm_pr_warn(NULL,
+ "DMA transfer still active while stopping it\n");
+ dev->dma_stream.state = CIF_ISP10_STATE_READY;
+ spin_lock_irqsave(&dev->vbq_lock, flags);
+ cif_isp10_requeue_bufs(dev, &dev->dma_stream);
+ spin_unlock_irqrestore(&dev->vbq_lock, flags);
+ }
+}
+
+static int cif_isp10_stop(
+ struct cif_isp10_device *dev,
+ bool stop_sp,
+ bool stop_mp)
+{
+ unsigned long flags = 0;
+ bool stop_all;
+ int timeout;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, img_src state = %s, stop_sp = %d, stop_mp = %d\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ stop_sp,
+ stop_mp);
+
+ if (!((stop_mp &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) ||
+ (stop_sp &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))) {
+ return 0;
+ }
+
+ stop_all = ((stop_mp && stop_sp) ||
+ (stop_sp &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+ (stop_mp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)));
+
+ if (stop_all) {
+ /*
+ * Modify ISP stop sequence for isp bus dead:
+ * ISP(mi) stop in mi frame end -> Stop ISP(mipi) ->
+ * Stop ISP(isp) ->wait for ISP isp off
+ */
+
+ cif_isp10_stop_mp(dev);
+ cif_isp10_stop_sp(dev);
+ cif_isp10_stop_dma(dev);
+
+ local_irq_save(flags);
+ /* stop and clear MI, MIPI, and ISP interrupts */
+ cif_iowrite32(0, dev->config.base_addr + CIF_MIPI_IMSC);
+ cif_iowrite32(~0, dev->config.base_addr + CIF_MIPI_ICR);
+
+ cif_iowrite32(0, dev->config.base_addr + CIF_ISP_IMSC);
+ cif_iowrite32(~0, dev->config.base_addr + CIF_ISP_ICR);
+
+ cif_iowrite32_verify(0,
+ dev->config.base_addr + CIF_MI_IMSC, ~0);
+ cif_iowrite32(~0, dev->config.base_addr + CIF_MI_ICR);
+
+ cif_iowrite32AND(~CIF_MIPI_CTRL_OUTPUT_ENA,
+ dev->config.base_addr + CIF_MIPI_CTRL);
+ /* stop ISP */
+ cif_iowrite32AND(~(CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+ CIF_ISP_CTRL_ISP_ENABLE),
+ dev->config.base_addr + CIF_ISP_CTRL);
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+
+ timeout = 100;
+ while ((timeout-- > 0) &&
+ ((cif_ioread32(dev->config.base_addr + CIF_ISP_RIS)
+ & CIF_ISP_OFF) != CIF_ISP_OFF)) {
+ msleep(20);
+ };
+ local_irq_restore(flags);
+
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ if (IS_ERR_VALUE(cif_isp10_img_src_set_state(dev,
+ CIF_ISP10_IMG_SRC_STATE_SW_STNDBY)))
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "unable to put image source into standby\n");
+ }
+ if (IS_ERR_VALUE(cif_isp10_set_pm_state(dev,
+ CIF_ISP10_PM_STATE_SW_STNDBY)))
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "unable to put CIF into standby\n");
+ } else if (stop_sp) {
+ if (!dev->config.mi_config.async_updt) {
+ local_irq_save(flags);
+ cif_isp10_stop_mi(dev, true, false);
+ local_irq_restore(flags);
+ }
+ cif_isp10_stop_sp(dev);
+ cif_iowrite32AND_verify(~CIF_MI_SP_FRAME,
+ dev->config.base_addr + CIF_MI_IMSC, ~0);
+
+ } else /* stop_mp */ {
+ if (!dev->config.mi_config.async_updt) {
+ local_irq_save(flags);
+ cif_isp10_stop_mi(dev, false, true);
+ local_irq_restore(flags);
+ }
+ cif_isp10_stop_mp(dev);
+ cif_iowrite32AND_verify(~(CIF_MI_MP_FRAME |
+ CIF_JPE_STATUS_ENCODE_DONE),
+ dev->config.base_addr + CIF_MI_IMSC, ~0);
+ }
+
+ if (stop_mp && (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+ dev->mp_stream.state = CIF_ISP10_STATE_READY;
+
+ if (stop_sp && (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+ dev->sp_stream.state = CIF_ISP10_STATE_READY;
+
+ spin_lock(&dev->vbq_lock);
+ if (stop_sp) {
+ dev->config.mi_config.sp.busy = false;
+ cif_isp10_requeue_bufs(dev, &dev->sp_stream);
+ }
+ if (stop_mp) {
+ dev->config.mi_config.mp.busy = false;
+ cif_isp10_requeue_bufs(dev, &dev->mp_stream);
+ }
+ spin_unlock(&dev->vbq_lock);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+ " MI_CTRL 0x%08x\n"
+ " ISP_CTRL 0x%08x\n"
+ " MIPI_CTRL 0x%08x\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+
+ return 0;
+}
+
+static int cif_isp10_start(
+ struct cif_isp10_device *dev,
+ bool start_sp,
+ bool start_mp)
+{
+ unsigned int ret;
+ struct videobuf_buffer *vb, *n;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s, start_sp = %d, start_mp = %d\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ start_sp,
+ start_mp);
+
+ if (!((start_mp &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+ (start_sp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING))))
+ return 0;
+
+ if (CIF_ISP10_INP_IS_DMA(dev->config.input_sel) &&
+ (dev->dma_stream.state < CIF_ISP10_STATE_READY)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "cannot start streaming, input source (DMA) not ready\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ /* Activate MI */
+ cif_isp10_start_mi(dev, start_sp, start_mp);
+
+ if ((dev->sp_stream.state != CIF_ISP10_STATE_STREAMING) &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+ /* Activate MIPI */
+ if (CIF_ISP10_INP_IS_MIPI(dev->config.input_sel))
+ cif_iowrite32OR(CIF_MIPI_CTRL_OUTPUT_ENA,
+ dev->config.base_addr + CIF_MIPI_CTRL);
+
+ /* Activate ISP ! */
+ if (CIF_ISP10_INP_NEED_ISP(dev->config.input_sel))
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD |
+ CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+ CIF_ISP_CTRL_ISP_ENABLE,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ }
+
+ if (start_sp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+ dev->sp_stream.state = CIF_ISP10_STATE_STREAMING;
+ }
+ if (start_mp &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING)) {
+ dev->mp_stream.state = CIF_ISP10_STATE_STREAMING;
+ }
+ ret = cif_isp10_set_pm_state(dev,
+ CIF_ISP10_PM_STATE_STREAMING);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ /*
+ * CIF spec says to wait for sufficient time after enabling
+ * the MIPI interface and before starting the sensor output.
+ */
+ mdelay(1);
+ /* start sensor output! */
+ dev->isp_dev.frame_id = 0;
+ dev->isp_dev.frame_id_setexp = 0;
+ videobuf_queue_lock(&dev->isp_dev.vbq_stat);
+ list_for_each_entry_safe(
+ vb, n, &dev->isp_dev.vbq_stat.stream, queue) {
+ if (vb->state == VIDEOBUF_DONE) {
+ vb->field_count = -1;
+ cif_isp10_pltfrm_pr_info(
+ dev->dev,
+ "discard vb: %d\n", vb->i);
+ }
+ }
+ videobuf_queue_unlock(&dev->isp_dev.vbq_stat);
+
+ mutex_lock(&dev->img_src_exps.mutex);
+ cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_SENSOR_MODE_DATA,
+ &dev->img_src_exps.data[0].data);
+ cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_SENSOR_MODE_DATA,
+ &dev->img_src_exps.data[1].data);
+ dev->img_src_exps.data[0].v_frame_id = 0;
+ dev->img_src_exps.data[1].v_frame_id = 0;
+ mutex_unlock(&dev->img_src_exps.mutex);
+
+ cif_isp10_pltfrm_rtrace_printf(dev->dev,
+ "starting image source...\n");
+ ret = cif_isp10_img_src_set_state(dev,
+ CIF_ISP10_IMG_SRC_STATE_STREAMING);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ } else {
+ cif_isp10_pltfrm_rtrace_printf(dev->dev,
+ "starting DMA...\n");
+ dev->dma_stream.state = CIF_ISP10_STATE_STREAMING;
+ dev->dma_stream.stop = false;
+ cif_isp10_dma_next_buff(dev);
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+ " MI_CTRL 0x%08x\n"
+ " ISP_CTRL 0x%08x\n"
+ " MIPI_CTRL 0x%08x\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, img_src state = %s\n"
+ " MI_CTRL 0x%08x\n"
+ " ISP_CTRL 0x%08x\n"
+ " MIPI_CTRL 0x%08x\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ cif_isp10_img_src_state_string(dev->img_src_state),
+ cif_ioread32(dev->config.base_addr + CIF_MI_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_CTRL),
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_CTRL));
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+/* Function to be called inside ISR to update CIF ISM/DCROP/RSZ */
+static int cif_isp10_update_ism_dcr_rsz(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ if (dev->config.isp_config.ism_config.ism_update_needed) {
+ if (dev->config.isp_config.ism_config.ism_en) {
+ if (!dev->isp_dev.cif_ism_cropping)
+ dev->isp_dev.cif_ism_cropping = true;
+ } else {
+ if (dev->isp_dev.cif_ism_cropping)
+ dev->isp_dev.cif_ism_cropping = false;
+ }
+ }
+
+ /*
+ * Update ISM, cif_isp10_config_ism() changes the output size of isp,
+ * so it must be called before cif_isp10_config_rsz()
+ */
+ if (dev->config.isp_config.ism_config.ism_update_needed) {
+ cif_isp10_config_ism(dev, false);
+ if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)
+ dev->config.mp_config.rsz_config.ism_adjust = true;
+ if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)
+ dev->config.sp_config.rsz_config.ism_adjust = true;
+
+ dev->config.isp_config.ism_config.ism_update_needed = false;
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+
+ if (dev->config.isp_config.ism_config.ism_en)
+ dev->config.mi_config.async_updt |= CIF_ISP10_ASYNC_ISM;
+ }
+
+ /* Update RSZ */
+ if ((dev->config.mp_config.rsz_config.ycflt_adjust ||
+ dev->config.mp_config.rsz_config.ism_adjust)) {
+ ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_MP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+ if ((dev->config.sp_config.rsz_config.ycflt_adjust ||
+ dev->config.sp_config.rsz_config.ism_adjust)) {
+ ret = cif_isp10_config_rsz(dev, CIF_ISP10_STREAM_SP, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_mi_isr(unsigned int mi_mis, void *cntxt)
+{
+ struct cif_isp10_device *dev = cntxt;
+ unsigned int mi_mis_tmp;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "\n MI_RIS 0x%08x\n"
+ " MI_IMSC 0x%08x\n"
+ " MI_MIS 0x%08x\n",
+ cif_ioread32(dev->config.base_addr + CIF_MI_RIS),
+ cif_ioread32(dev->config.base_addr + CIF_MI_IMSC),
+ mi_mis);
+
+ cif_isp10_pltfrm_rtrace_printf(dev->dev,
+ "MI_MIS %08x, MI_RIS %08x, MI_IMSC %08x\n",
+ mi_mis,
+ cif_ioread32(dev->config.base_addr + CIF_MI_RIS),
+ cif_ioread32(dev->config.base_addr + CIF_MI_IMSC));
+
+ if (mi_mis & CIF_MI_SP_FRAME) {
+ dev->config.mi_config.sp.busy = false;
+ cif_iowrite32(CIF_MI_SP_FRAME,
+ dev->config.base_addr + CIF_MI_ICR);
+ mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+ if (mi_mis_tmp & CIF_MI_SP_FRAME)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "sp icr err: 0x%x\n",
+ mi_mis_tmp);
+ }
+
+ if (mi_mis & CIF_MI_MP_FRAME) {
+ dev->config.mi_config.mp.busy = false;
+ cif_iowrite32(CIF_MI_MP_FRAME,
+ dev->config.base_addr + CIF_MI_ICR);
+ mi_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_MI_MIS);
+ if (mi_mis_tmp & CIF_MI_MP_FRAME)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "mp icr err: 0x%x\n",
+ mi_mis_tmp);
+ }
+ if (mi_mis & CIF_MI_DMA_READY)
+ (void)cif_isp10_dma_ready(dev);
+ if (dev->config.jpeg_config.enable &&
+ (cif_ioread32(dev->config.base_addr +
+ CIF_JPE_STATUS_RIS) & CIF_JPE_STATUS_ENCODE_DONE))
+ dev->config.jpeg_config.busy = false;
+
+ if (!CIF_ISP10_MI_IS_BUSY(dev) &&
+ !dev->config.jpeg_config.busy) {
+ if (dev->config.mi_config.async_updt) {
+ u32 mp_y_off_cnt_shd =
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_MP_Y_OFFS_CNT_SHD);
+ u32 sp_y_off_cnt_shd =
+ cif_ioread32(dev->config.base_addr +
+ CIF_MI_SP_Y_OFFS_CNT_SHD);
+
+ cif_iowrite32(CIF_MI_INIT_SOFT_UPD,
+ dev->config.base_addr + CIF_MI_INIT);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "CIF_MI_INIT_SOFT_UPD\n");
+ if (!dev->config.isp_config.ism_config.ism_en &&
+ (dev->config.mi_config.async_updt &
+ CIF_ISP10_ASYNC_ISM))
+ dev->config.mi_config.async_updt &=
+ ~CIF_ISP10_ASYNC_ISM;
+ if (sp_y_off_cnt_shd != 0) {
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_requeue_bufs(dev, &dev->sp_stream);
+ spin_unlock(&dev->vbq_lock);
+ }
+ if ((mp_y_off_cnt_shd != 0) &&
+ (!dev->config.jpeg_config.enable)) {
+ spin_lock(&dev->vbq_lock);
+ cif_isp10_requeue_bufs(dev, &dev->mp_stream);
+ spin_unlock(&dev->vbq_lock);
+ }
+ if (((mp_y_off_cnt_shd != 0) &&
+ !dev->config.jpeg_config.enable) ||
+ (sp_y_off_cnt_shd != 0)) {
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "soft update too late (SP offset %d, MP offset %d)\n",
+ sp_y_off_cnt_shd, mp_y_off_cnt_shd);
+ }
+ }
+
+ if (dev->mp_stream.stop &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+ cif_isp10_stop_mi(dev, false, true);
+ dev->mp_stream.state = CIF_ISP10_STATE_READY;
+ dev->mp_stream.stop = false;
+
+ /* Turn off MRSZ since it is not needed */
+ cif_iowrite32(0, dev->config.base_addr + CIF_MRSZ_CTRL);
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_MRSZ_CTRL);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "MP has stopped\n");
+ cif_isp10_pltfrm_event_signal(dev->dev,
+ &dev->mp_stream.done);
+ }
+ if (dev->sp_stream.stop &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+ cif_isp10_stop_mi(dev, true, false);
+ dev->sp_stream.state = CIF_ISP10_STATE_READY;
+ dev->sp_stream.stop = false;
+
+ /* Turn off SRSZ since it is not needed */
+ cif_iowrite32(0, dev->config.base_addr + CIF_SRSZ_CTRL);
+ cif_iowrite32OR(CIF_RSZ_CTRL_CFG_UPD,
+ dev->config.base_addr + CIF_SRSZ_CTRL);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "SP has stopped\n");
+ cif_isp10_pltfrm_event_signal(dev->dev,
+ &dev->sp_stream.done);
+ }
+
+ if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ spin_lock(&dev->vbq_lock);
+ (void)cif_isp10_mi_frame_end(dev,
+ CIF_ISP10_STREAM_SP);
+ spin_unlock(&dev->vbq_lock);
+ }
+ if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ spin_lock(&dev->vbq_lock);
+ (void)cif_isp10_mi_frame_end(dev,
+ CIF_ISP10_STREAM_MP);
+ spin_unlock(&dev->vbq_lock);
+ }
+
+ dev->b_mi_frame_end = true;
+
+ if (dev->dma_stream.state == CIF_ISP10_STATE_STREAMING) {
+ cif_isp10_dma_next_buff(dev);
+ } else {
+ if ((dev->sp_stream.state ==
+ CIF_ISP10_STATE_STREAMING) &&
+ dev->sp_stream.curr_buf)
+ dev->config.mi_config.sp.busy = true;
+ if ((dev->mp_stream.state ==
+ CIF_ISP10_STATE_STREAMING) &&
+ dev->mp_stream.curr_buf)
+ dev->config.mi_config.mp.busy = true;
+ }
+
+ if (dev->b_isp_frame_in &&
+ ((dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) ||
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)))
+ cif_isp10_update_ism_dcr_rsz(dev);
+ }
+
+ cif_iowrite32(~(CIF_MI_MP_FRAME |
+ CIF_MI_SP_FRAME | CIF_MI_DMA_READY),
+ dev->config.base_addr + CIF_MI_ICR);
+
+ return 0;
+}
+
+static int cif_isp10_register_isrs(struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_irq_register_isr(
+ dev->dev,
+ CIF_ISP_MIS,
+ cif_isp10_isp_isr,
+ dev);
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "unable to register ISP ISR, some processing errors may go unnoticed\n");
+
+ cif_isp10_pltfrm_irq_register_isr(
+ dev->dev,
+ CIF_MIPI_MIS,
+ cif_isp10_mipi_isr,
+ dev);
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "unable to register MIPI ISR, MIPI errors may go unnoticed\n");
+
+ ret = cif_isp10_pltfrm_irq_register_isr(
+ dev->dev,
+ CIF_MI_MIS,
+ cif_isp10_mi_isr,
+ dev);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unable to register MI ISR, aborting\n");
+ goto err;
+ }
+
+ return 0;
+
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d", ret);
+ return ret;
+}
+
+static void cif_isp10_vs_work(struct work_struct *work)
+{
+ struct cif_isp10_isp_vs_work *vs_wk =
+ container_of(work, struct cif_isp10_isp_vs_work, work);
+ struct cif_isp10_device *dev = vs_wk->dev;
+
+ switch (vs_wk->cmd) {
+ case CIF_ISP10_VS_EXP: {
+ struct cif_isp10_img_src_exp *exp =
+ (struct cif_isp10_img_src_exp *)vs_wk->param;
+ struct cif_isp10_img_src_ext_ctrl *exp_ctrl = exp->exp;
+ struct cif_isp10_img_src_data *new_data;
+
+ if (dev->img_src)
+ cif_isp10_img_src_s_ext_ctrls(dev->img_src, exp_ctrl);
+ else
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "dev->img_src is NULL\n");
+
+ if (dev->img_src_exps.data[0].v_frame_id <
+ dev->img_src_exps.data[1].v_frame_id)
+ new_data = &dev->img_src_exps.data[0];
+ else
+ new_data = &dev->img_src_exps.data[1];
+
+ mutex_lock(&dev->img_src_exps.mutex);
+ new_data->v_frame_id = dev->isp_dev.frame_id +
+ dev->img_src_exps.exp_valid_frms;
+ cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_SENSOR_MODE_DATA,
+ &new_data->data);
+ mutex_unlock(&dev->img_src_exps.mutex);
+
+ /*
+ * pr_info("%s: exp_time: %d gain: %d, frame_id: s %d, v %d\n",
+ * __func__,
+ * new_data->data.exp_time,
+ * new_data->data.gain,
+ * dev->isp_dev.frame_id,
+ * new_data->v_frame_id);
+ */
+
+ kfree(exp->exp->ctrls);
+ exp->exp->ctrls = NULL;
+ kfree(exp->exp);
+ exp->exp = NULL;
+ kfree(exp);
+ exp = NULL;
+ break;
+ }
+ default:
+ break;
+ }
+
+ kfree(vs_wk);
+ vs_wk = NULL;
+}
+
+/* Public Functions */
+void cif_isp10_sensor_mode_data_sync(
+ struct cif_isp10_device *dev,
+ unsigned int frame_id,
+ struct isp_supplemental_sensor_mode_data *data)
+{
+ struct cif_isp10_img_src_data *last_data;
+ struct cif_isp10_img_src_data *new_data;
+
+ mutex_lock(&dev->img_src_exps.mutex);
+ if (dev->img_src_exps.data[0].v_frame_id <
+ dev->img_src_exps.data[1].v_frame_id) {
+ last_data = &dev->img_src_exps.data[0];
+ new_data = &dev->img_src_exps.data[1];
+ } else {
+ last_data = &dev->img_src_exps.data[1];
+ new_data = &dev->img_src_exps.data[0];
+ }
+
+ if (frame_id >= new_data->v_frame_id) {
+ memcpy(data,
+ &new_data->data,
+ sizeof(struct isp_supplemental_sensor_mode_data));
+ } else {
+ memcpy(data,
+ &last_data->data,
+ sizeof(struct isp_supplemental_sensor_mode_data));
+ }
+ mutex_unlock(&dev->img_src_exps.mutex);
+}
+
+int cif_isp10_streamon(
+ struct cif_isp10_device *dev,
+ u32 stream_ids)
+{
+ int ret = 0;
+ bool streamon_sp = stream_ids & CIF_ISP10_STREAM_SP;
+ bool streamon_mp = stream_ids & CIF_ISP10_STREAM_MP;
+ bool streamon_dma = stream_ids & CIF_ISP10_STREAM_DMA;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, streamon SP = %d, streamon MP = %d, streamon DMA = %d\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ streamon_sp, streamon_mp, streamon_dma);
+
+ if (!((streamon_sp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_STREAMING)) ||
+ (streamon_mp &&
+ (dev->mp_stream.state != CIF_ISP10_STATE_STREAMING))))
+ return 0;
+
+ if (streamon_sp &&
+ (dev->sp_stream.state != CIF_ISP10_STATE_READY)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cannot start streaming on SP path, path not yet enabled\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ if (streamon_mp && (dev->mp_stream.state != CIF_ISP10_STATE_READY)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cannot start streaming on MP path, path not yet enabled\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ if (streamon_sp && dev->config.mi_config.raw_enable &&
+ (streamon_mp ||
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cannot start streaming on SP path when MP is active and set to RAW output\n");
+ ret = -EBUSY;
+ goto err;
+ }
+
+ if (streamon_mp &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING))
+ dev->mp_stream.updt_cfg = true;
+ if (streamon_sp &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING))
+ dev->sp_stream.updt_cfg = true;
+
+ if (streamon_sp && dev->sp_stream.updt_cfg &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+ ret = cif_isp10_stop(dev, false, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ streamon_mp = true;
+ dev->mp_stream.updt_cfg = true;
+ }
+ if (streamon_mp && dev->mp_stream.updt_cfg &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)) {
+ ret = cif_isp10_stop(dev, true, false);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ streamon_sp = true;
+ dev->sp_stream.updt_cfg = true;
+ }
+
+ stream_ids = 0;
+ if (streamon_mp && dev->mp_stream.updt_cfg)
+ stream_ids |= CIF_ISP10_STREAM_MP;
+ if (streamon_sp && dev->sp_stream.updt_cfg)
+ stream_ids |= CIF_ISP10_STREAM_SP;
+
+ ret = cif_isp10_config_cif(dev, stream_ids);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ ret = cif_isp10_start(dev, streamon_sp, streamon_mp);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state));
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state));
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_streamoff(
+ struct cif_isp10_device *dev,
+ u32 stream_ids)
+{
+ int ret = 0;
+ bool streamoff_sp = stream_ids & CIF_ISP10_STREAM_SP;
+ bool streamoff_mp = stream_ids & CIF_ISP10_STREAM_MP;
+ bool streamoff_dma = stream_ids & CIF_ISP10_STREAM_DMA;
+ unsigned int streamoff_all = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, streamoff SP = %d, streamoff MP = %d, streamoff DMA = %d\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ streamoff_sp,
+ streamoff_mp,
+ streamoff_dma);
+
+ if (dev->config.flash_mode != CIF_ISP10_FLASH_MODE_OFF &&
+ ((streamoff_sp &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_INACTIVE)) ||
+ (streamoff_mp &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_INACTIVE))))
+ cif_isp10_img_src_s_ctrl(dev->img_src,
+ CIF_ISP10_CID_FLASH_MODE,
+ CIF_ISP10_FLASH_MODE_OFF);
+
+ streamoff_all = 0;
+ if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ if (streamoff_sp)
+ streamoff_all |= CIF_ISP10_STREAM_SP;
+ } else {
+ streamoff_all |= CIF_ISP10_STREAM_SP;
+ }
+ if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ if (streamoff_mp)
+ streamoff_all |= CIF_ISP10_STREAM_MP;
+ } else {
+ streamoff_all |= CIF_ISP10_STREAM_MP;
+ }
+ if (streamoff_all == (CIF_ISP10_STREAM_MP | CIF_ISP10_STREAM_SP))
+ drain_workqueue(dev->vs_wq);
+
+ ret = cif_isp10_stop(dev, streamoff_sp, streamoff_mp);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ if ((streamoff_sp) &&
+ (dev->sp_stream.state == CIF_ISP10_STATE_READY))
+ dev->sp_stream.state = CIF_ISP10_STATE_INACTIVE;
+ if (streamoff_mp) {
+ dev->config.jpeg_config.enable = false;
+ dev->config.mi_config.raw_enable = false;
+ dev->config.mi_config.mp.output.width = 0;
+ dev->config.mi_config.mp.output.height = 0;
+ dev->config.mi_config.mp.output.pix_fmt =
+ CIF_UNKNOWN_FORMAT;
+ if (dev->mp_stream.state == CIF_ISP10_STATE_READY)
+ dev->mp_stream.state = CIF_ISP10_STATE_INACTIVE;
+ }
+ if (streamoff_dma) {
+ cif_isp10_stop_dma(dev);
+ if (dev->dma_stream.state == CIF_ISP10_STATE_READY)
+ dev->dma_stream.state = CIF_ISP10_STATE_INACTIVE;
+ }
+ if ((dev->dma_stream.state <= CIF_ISP10_STATE_INACTIVE) &&
+ (dev->mp_stream.state <= CIF_ISP10_STATE_INACTIVE) &&
+ (dev->sp_stream.state <= CIF_ISP10_STATE_INACTIVE)) {
+ dev->isp_dev.input_width = 0;
+ dev->isp_dev.input_height = 0;
+ dev->config.isp_config.ism_config.ism_en = 0;
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s, # frames received = %d\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state),
+ dev->isp_dev.frame_id >> 1);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s, DMA state = %s\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state),
+ cif_isp10_state_string(dev->dma_stream.state));
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_suspend(
+ struct cif_isp10_device *dev)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state));
+
+ if ((dev->pm_state == CIF_ISP10_PM_STATE_SUSPENDED) ||
+ (dev->pm_state == CIF_ISP10_PM_STATE_OFF))
+ return 0;
+
+ dev->sp_stream.saved_state = dev->sp_stream.state;
+ dev->mp_stream.saved_state = dev->mp_stream.state;
+ ret = cif_isp10_stop(dev, true, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ ret = cif_isp10_set_pm_state(dev, CIF_ISP10_PM_STATE_SUSPENDED);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ ret = cif_isp10_img_src_set_state(dev, CIF_ISP10_IMG_SRC_STATE_OFF);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_resume(
+ struct cif_isp10_device *dev)
+{
+ u32 stream_ids = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "SP state = %s, MP state = %s\n",
+ cif_isp10_state_string(dev->sp_stream.state),
+ cif_isp10_state_string(dev->mp_stream.state));
+
+ if ((dev->sp_stream.saved_state == CIF_ISP10_STATE_READY) ||
+ (dev->sp_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+ dev->sp_stream.updt_cfg = true;
+ dev->sp_stream.state = CIF_ISP10_STATE_READY;
+ if (dev->sp_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+ stream_ids |= CIF_ISP10_STREAM_SP;
+ }
+ if ((dev->mp_stream.saved_state == CIF_ISP10_STATE_READY) ||
+ (dev->mp_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+ dev->mp_stream.updt_cfg = true;
+ dev->mp_stream.state = CIF_ISP10_STATE_READY;
+ if (dev->mp_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+ stream_ids |= CIF_ISP10_STREAM_MP;
+ }
+
+ if ((dev->dma_stream.saved_state == CIF_ISP10_STATE_READY) ||
+ (dev->dma_stream.saved_state == CIF_ISP10_STATE_STREAMING)) {
+ dev->dma_stream.state = CIF_ISP10_STATE_READY;
+ if (dev->dma_stream.saved_state == CIF_ISP10_STATE_STREAMING)
+ stream_ids |= CIF_ISP10_STREAM_DMA;
+ }
+
+ return cif_isp10_streamon(dev, stream_ids);
+}
+
+int cif_isp10_s_fmt(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ struct cif_isp10_strm_fmt *strm_fmt,
+ u32 stride)
+{
+ int ret;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+ cif_isp10_stream_id_string(stream_id));
+
+ switch (stream_id) {
+ case CIF_ISP10_STREAM_SP:
+ return cif_isp10_s_fmt_sp(dev, strm_fmt, stride);
+ case CIF_ISP10_STREAM_MP:
+ return cif_isp10_s_fmt_mp(dev, strm_fmt, stride);
+ case CIF_ISP10_STREAM_DMA:
+ return cif_isp10_s_fmt_dma(dev, strm_fmt, stride);
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported stream ID %d\n", stream_id);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_init(
+ struct cif_isp10_device *dev,
+ u32 stream_ids)
+{
+ int ret;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "0x%08x\n", stream_ids);
+
+ if (stream_ids & ~(CIF_ISP10_ALL_STREAMS)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported stream IDs 0x%08x\n",
+ stream_ids);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* set default input, failure is not fatal here */
+ if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED)) {
+ (void)cif_isp10_s_input(dev, 0);
+ dev->config.isp_config.si_enable = false;
+ dev->config.isp_config.ie_config.effect =
+ CIF_ISP10_IE_NONE;
+ }
+
+ if (stream_ids & CIF_ISP10_STREAM_SP)
+ cif_isp10_init_stream(dev, CIF_ISP10_STREAM_SP);
+ if (stream_ids & CIF_ISP10_STREAM_MP)
+ cif_isp10_init_stream(dev, CIF_ISP10_STREAM_MP);
+ if (stream_ids & CIF_ISP10_STREAM_DMA)
+ cif_isp10_init_stream(dev, CIF_ISP10_STREAM_DMA);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_release(
+ struct cif_isp10_device *dev,
+ int stream_ids)
+{
+ int ret;
+ struct cif_isp10_stream *strm_dev;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "0x%08x\n", stream_ids);
+
+ if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+ (dev->dma_stream.state == CIF_ISP10_STATE_DISABLED))
+ return 0;
+
+ if (stream_ids & ~(CIF_ISP10_ALL_STREAMS)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported stream IDs 0x%08x\n",
+ stream_ids);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (stream_ids == CIF_ISP10_STREAM_MP)
+ strm_dev = &dev->mp_stream;
+ else if (stream_ids == CIF_ISP10_STREAM_SP)
+ strm_dev = &dev->sp_stream;
+ else
+ strm_dev = NULL;
+
+ if (strm_dev) {
+ if (strm_dev->metadata.d) {
+ vfree(strm_dev->metadata.d);
+ strm_dev->metadata.d = NULL;
+ strm_dev->metadata.cnt = 0;
+ }
+ }
+
+ if (stream_ids & CIF_ISP10_STREAM_SP) {
+ if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF SP in streaming state, should be stopped before release, trying to stop it\n");
+ ret = cif_isp10_stop(dev, true, false);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+ dev->sp_stream.state = CIF_ISP10_STATE_DISABLED;
+ }
+ if (stream_ids & CIF_ISP10_STREAM_MP) {
+ if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF MP in streaming state, should be stopped before release, trying to stop it\n");
+ ret = cif_isp10_stop(dev, false, true);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ }
+ dev->mp_stream.state = CIF_ISP10_STATE_DISABLED;
+ }
+
+ if ((dev->sp_stream.state == CIF_ISP10_STATE_DISABLED) &&
+ (dev->mp_stream.state == CIF_ISP10_STATE_DISABLED)) {
+ if (IS_ERR_VALUE(cif_isp10_set_pm_state(dev,
+ CIF_ISP10_PM_STATE_OFF)))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF power off failed\n");
+ if (dev->img_src) {
+ if (IS_ERR_VALUE(cif_isp10_img_src_set_state(dev,
+ CIF_ISP10_IMG_SRC_STATE_OFF)))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "image source power off failed\n");
+ dev->img_src = NULL;
+ }
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+struct cif_isp10_device *cif_isp10_create(
+ CIF_ISP10_PLTFRM_DEVICE pdev,
+ void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence),
+ void (*requeue_bufs)(struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id),
+ struct pltfrm_soc_cfg *soc_cfg)
+{
+ int ret;
+ struct cif_isp10_device *dev;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ /* Allocate needed structures */
+ dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+ if (!dev) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "memory allocation failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ dev->sof_event = sof_event;
+ dev->requeue_bufs = requeue_bufs;
+
+ ret = cif_isp10_pltfrm_dev_init(dev,
+ &pdev, &dev->config.base_addr);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ cif_isp10_pltfrm_debug_register_print_cb(
+ dev->dev,
+ (void (*)(void *, const char *))cif_isp10_debug_print_block,
+ dev);
+
+ cif_isp10_pltfrm_soc_init(dev, soc_cfg);
+
+ ret = cif_isp10_img_srcs_init(dev);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cif_isp10_img_srcs_init failed\n");
+ goto err;
+ }
+
+ ret = cif_isp10_register_isrs(dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ (void)cif_isp10_init(dev, CIF_ISP10_ALL_STREAMS);
+ dev->pm_state = CIF_ISP10_PM_STATE_OFF;
+ dev->sp_stream.state = CIF_ISP10_STATE_DISABLED;
+ dev->sp_stream.id = CIF_ISP10_STREAM_SP;
+ dev->mp_stream.state = CIF_ISP10_STATE_DISABLED;
+ dev->mp_stream.id = CIF_ISP10_STREAM_MP;
+ dev->dma_stream.state = CIF_ISP10_STATE_DISABLED;
+ dev->dma_stream.id = CIF_ISP10_STREAM_DMA;
+ dev->config.mi_config.async_updt = 0;
+ cif_isp10_pltfrm_event_init(dev->dev, &dev->dma_stream.done);
+ cif_isp10_pltfrm_event_init(dev->dev, &dev->sp_stream.done);
+ cif_isp10_pltfrm_event_init(dev->dev, &dev->mp_stream.done);
+
+ dev->img_src_exps.exp_valid_frms = 2;
+ mutex_init(&dev->img_src_exps.mutex);
+ memset(&dev->img_src_exps.data, 0x00, sizeof(dev->img_src_exps.data));
+ spin_lock_init(&dev->img_src_exps.lock);
+ INIT_LIST_HEAD(&dev->img_src_exps.list);
+ dev->vs_wq = alloc_workqueue("cif isp10 vs workqueue",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+
+ /* TBD: clean this up */
+ init_output_formats();
+
+ return dev;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ if (!IS_ERR_OR_NULL(dev))
+ kfree(dev);
+ return ERR_PTR(ret);
+}
+
+void cif_isp10_destroy(
+ struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+ if (!IS_ERR_OR_NULL(dev))
+ kfree(dev);
+}
+
+int cif_isp10_s_input(
+ struct cif_isp10_device *dev,
+ unsigned int input)
+{
+ int ret;
+ enum cif_isp10_inp inp;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "setting input to %s\n",
+ cif_isp10_inp_string(
+ cif_isp10_input_index2inp(dev, input)));
+
+ if (input >= dev->img_src_cnt + CIF_ISP10_INP_DMA_CNT()) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "invalid input %d\n", input);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev->img_src = NULL;
+
+ inp = cif_isp10_input_index2inp(dev, input);
+
+ /* DMA -> ISP or DMA -> IE */
+ if ((inp == CIF_ISP10_INP_DMA) || (inp == CIF_ISP10_INP_DMA_IE))
+ dev->config.isp_config.input =
+ &dev->config.mi_config.dma.output;
+ else {
+ dev->img_src = dev->img_src_array[input];
+ dev->config.isp_config.input =
+ &dev->config.img_src_output.frm_fmt;
+ }
+ dev->config.input_sel = inp;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+const char *cif_isp10_g_input_name(
+ struct cif_isp10_device *dev,
+ unsigned int input_index)
+{
+ if (input_index >=
+ dev->img_src_cnt + CIF_ISP10_INP_DMA_CNT()) {
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "index %d out of bounds\n",
+ input_index);
+ return NULL;
+ }
+
+ if (input_index < dev->img_src_cnt)
+ return cif_isp10_img_src_g_name(
+ dev->img_src_array[input_index]);
+ else
+ return cif_isp10_inp_string(CIF_ISP10_INP_DMA +
+ ((input_index - dev->img_src_cnt) << 24));
+}
+
+int cif_isp10_qbuf(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream,
+ struct cif_isp10_buffer *buf)
+{
+ int ret = 0;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "%s\n",
+ cif_isp10_stream_id_string(stream));
+
+ switch (stream) {
+ case CIF_ISP10_STREAM_SP:
+ list_add_tail(&buf->queue, &dev->sp_stream.buf_queue);
+ break;
+ case CIF_ISP10_STREAM_MP:
+ list_add_tail(&buf->queue, &dev->mp_stream.buf_queue);
+ break;
+ case CIF_ISP10_STREAM_DMA:
+ list_add_tail(&buf->queue, &dev->dma_stream.buf_queue);
+ if ((dev->dma_stream.state == CIF_ISP10_STATE_STREAMING) &&
+ !CIF_ISP10_MI_IS_BUSY(dev))
+ cif_isp10_dma_next_buff(dev);
+ break;
+ case CIF_ISP10_STREAM_ISP:
+ WARN_ON(1);
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown stream %d\n", stream);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_reqbufs(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id strm,
+ struct v4l2_requestbuffers *req)
+{
+ struct cif_isp10_stream *strm_dev = NULL;
+
+ switch (strm) {
+ case CIF_ISP10_STREAM_MP:
+ strm_dev = &dev->mp_stream;
+ break;
+ case CIF_ISP10_STREAM_SP:
+ strm_dev = &dev->sp_stream;
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown stream id%d\n", strm);
+ break;
+ }
+
+ strm_dev->metadata.cnt = req->count;
+
+ return 0;
+}
+
+int cif_isp10_s_exp(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_img_src_ext_ctrl *exp_ctrl)
+{
+ struct cif_isp10_img_src_exp *exp = NULL;
+ unsigned long lock_flags;
+ int retval;
+
+ if (!dev->vs_wq)
+ return -ENODEV;
+
+ exp = kmalloc(sizeof(*exp), GFP_KERNEL);
+ if (!exp) {
+ retval = -ENOMEM;
+ goto failed;
+ }
+
+ exp->exp = exp_ctrl;
+
+ spin_lock_irqsave(&dev->img_src_exps.lock, lock_flags);
+ list_add_tail(&exp->list, &dev->img_src_exps.list);
+ spin_unlock_irqrestore(&dev->img_src_exps.lock, lock_flags);
+
+ return 0;
+
+failed:
+ return retval;
+}
+
+int cif_isp10_s_isp_metadata(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_isp_readout_work *readout_work,
+ struct cifisp_isp_other_cfg *new_other,
+ struct cifisp_isp_meas_cfg *new_meas,
+ struct cifisp_stat_buffer *new_stats)
+{
+ unsigned int stream_id =
+ readout_work->stream_id;
+ struct videobuf_buffer *vb =
+ readout_work->vb;
+ struct cif_isp10_stream *strm_dev = NULL;
+ struct v4l2_buffer_metadata_s *metadata;
+ struct cifisp_isp_metadata *isp_last;
+
+ switch (stream_id) {
+ case CIF_ISP10_STREAM_MP:
+ strm_dev = &dev->mp_stream;
+ break;
+ case CIF_ISP10_STREAM_SP:
+ strm_dev = &dev->sp_stream;
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown stream id%d\n", stream_id);
+ break;
+ }
+
+ if (vb && strm_dev->metadata.d) {
+ metadata = (struct v4l2_buffer_metadata_s *)
+ (strm_dev->metadata.d +
+ vb->i * CAMERA_METADATA_LEN);
+
+ metadata->frame_id = readout_work->frame_id;
+ isp_last =
+ (struct cifisp_isp_metadata *)metadata->isp;
+
+ if (new_meas) {
+ if ((isp_last->meas_cfg.s_frame_id == 0xffffffff) ||
+ (isp_last->meas_cfg.s_frame_id <
+ new_meas->s_frame_id)) {
+ memcpy(&isp_last->meas_cfg,
+ new_meas,
+ sizeof(struct cifisp_isp_meas_cfg));
+ }
+ }
+
+ if (new_other) {
+ if ((isp_last->other_cfg.s_frame_id == 0xffffffff) ||
+ (isp_last->other_cfg.s_frame_id <
+ new_other->s_frame_id)) {
+ memcpy(&isp_last->other_cfg,
+ new_other,
+ sizeof(struct cifisp_isp_other_cfg));
+ }
+ }
+
+ if (new_stats) {
+ memcpy(&isp_last->meas_stat,
+ new_stats,
+ sizeof(struct cifisp_stat_buffer));
+ metadata->sensor.exp_time =
+ new_stats->sensor_mode.exp_time;
+ metadata->sensor.gain =
+ new_stats->sensor_mode.gain;
+ } else {
+ isp_last->meas_stat.meas_type = 0x00;
+ }
+ }
+
+ if (vb) {
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "frame done\n");
+ wake_up(&vb->done);
+ }
+
+ return 0;
+}
+
+int cif_isp10_mmap(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ struct vm_area_struct *vma)
+{
+ struct cif_isp10_stream *strm_dev;
+ void *mem_vaddr;
+ int retval = 0, pages;
+ unsigned long mem_size;
+
+ switch (stream_id) {
+ case CIF_ISP10_STREAM_MP:
+ strm_dev = &dev->mp_stream;
+ break;
+ case CIF_ISP10_STREAM_SP:
+ strm_dev = &dev->sp_stream;
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown stream id%d\n", stream_id);
+ return -ENODEV;
+ }
+
+ mem_size = vma->vm_end - vma->vm_start;
+ if (mem_size > strm_dev->metadata.cnt * CAMERA_METADATA_LEN) {
+ retval = -ENOMEM;
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "mmap size(0x%lx) > metadata memory size(0x%lx), so failed!",
+ mem_size,
+ (unsigned long)(strm_dev->metadata.cnt
+ * CAMERA_METADATA_LEN));
+ goto done;
+ }
+
+ pages = PAGE_ALIGN(vma->vm_end - vma->vm_start);
+ mem_vaddr = (struct v4l2_buffer_metadata_s *)vmalloc_user(pages);
+ if (!mem_vaddr) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "vmalloc (%d bytes) failed for %s metadata\n",
+ pages,
+ (stream_id == CIF_ISP10_STREAM_MP) ? "mp" : "sp");
+ retval = -ENOMEM;
+ goto done;
+ }
+
+ /* Try to remap memory */
+ retval = remap_vmalloc_range(vma, mem_vaddr, 0);
+ if (retval < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "mmap: remap failed with error %d. ", retval);
+ vfree(mem_vaddr);
+ goto done;
+ }
+
+ strm_dev->metadata.d = (unsigned char *)mem_vaddr;
+
+ vma->vm_private_data = (void *)&strm_dev->metadata;
+
+done:
+ return retval;
+}
+
+int cif_isp10_get_target_frm_size(
+ struct cif_isp10_device *dev,
+ u32 *target_width,
+ u32 *target_height)
+{
+ if (dev->sp_stream.state >= CIF_ISP10_STATE_READY) {
+ if ((dev->mp_stream.state >= CIF_ISP10_STATE_READY) &&
+ (dev->config.mi_config.mp.output.width >
+ dev->config.mi_config.sp.output.width))
+ *target_width =
+ dev->config.mi_config.mp.output.width;
+ else
+ *target_width =
+ dev->config.mi_config.sp.output.width;
+ if ((dev->mp_stream.state >= CIF_ISP10_STATE_READY) &&
+ (dev->config.mi_config.mp.output.height >
+ dev->config.mi_config.sp.output.height))
+ *target_height =
+ dev->config.mi_config.mp.output.height;
+ else
+ *target_height =
+ dev->config.mi_config.sp.output.height;
+ } else if (dev->mp_stream.state >= CIF_ISP10_STATE_READY) {
+ *target_width = dev->config.mi_config.mp.output.width;
+ *target_height = dev->config.mi_config.mp.output.height;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cannot get target frame size, no path ready\n");
+ return -EFAULT;
+ }
+ return 0;
+}
+
+int cif_isp10_calc_isp_cropping(
+ struct cif_isp10_device *dev,
+ u32 *width,
+ u32 *height,
+ u32 *h_offs,
+ u32 *v_offs)
+{
+ int ret = 0;
+ u32 input_width;
+ u32 input_height;
+ u32 target_width;
+ u32 target_height;
+
+ if (IS_ERR_OR_NULL(dev->config.isp_config.input)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "no input selected for ISP\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ input_width = dev->config.isp_config.input->defrect.width;
+ input_height = dev->config.isp_config.input->defrect.height;
+
+ ret = cif_isp10_get_target_frm_size(dev,
+ &target_width, &target_height);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ *width = input_width;
+ *height = input_width * target_height / target_width;
+ *v_offs = 0;
+ *h_offs = 0;
+ *height &= ~1;
+ if (*height < input_height)
+ /* vertical cropping */
+ *v_offs = (input_height - *height) >> 1;
+ else if (*height > input_height) {
+ /* horizontal cropping */
+ *height = input_height;
+ *width = input_height * target_width / target_height;
+ *width &= ~1;
+ *h_offs = (input_width - *width) >> 1;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_calc_min_out_buff_size(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ u32 *size)
+{
+ int ret = 0;
+ enum cif_isp10_pix_fmt pix_fmt;
+ u32 llength;
+ u32 height;
+ u32 bpp;
+ struct cif_isp10_mi_path_config *mi_path;
+ struct cif_isp10_stream *stream;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s\n",
+ cif_isp10_stream_id_string(stream_id));
+
+ if (stream_id == CIF_ISP10_STREAM_SP) {
+ mi_path = &dev->config.mi_config.sp;
+ stream = &dev->sp_stream;
+ } else if (stream_id == CIF_ISP10_STREAM_MP) {
+ mi_path = &dev->config.mi_config.mp;
+ stream = &dev->mp_stream;
+ } else if (stream_id == CIF_ISP10_STREAM_DMA) {
+ mi_path = &dev->config.mi_config.dma;
+ stream = &dev->dma_stream;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "cannot calculate buffer size for this stream (%s)\n",
+ cif_isp10_stream_id_string(stream_id));
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (stream->state < CIF_ISP10_STATE_READY) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "cannot calculate buffer size, %s stream not ready\n",
+ cif_isp10_stream_id_string(stream_id));
+ ret = -EINVAL;
+ goto err;
+ }
+ pix_fmt = mi_path->output.pix_fmt;
+ llength = mi_path->llength;
+ height = mi_path->output.height;
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "mi_path->llength: 0x%x\n",
+ mi_path->llength);
+
+ if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) &&
+ CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) > 8)
+ /* RAW input > 8BPP is stored with 16BPP by MI */
+ bpp = 16;
+ else
+ bpp = CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt);
+ *size = llength * height * bpp / 8;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "calculated buffer size: %d\n",
+ *size);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_s_ctrl(
+ struct cif_isp10_device *dev,
+ const enum cif_isp10_cid id,
+ int val)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "id %d, val %d\n",
+ id, val);
+
+ switch (id) {
+ case CIF_ISP10_CID_SUPER_IMPOSE:
+ dev->config.isp_config.si_enable = val;
+ break;
+ case CIF_ISP10_CID_IMAGE_EFFECT:
+ if ((u32)val > CIF_ISP10_IE_NONE) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported image effect %d\n", val);
+ return -EINVAL;
+ }
+ dev->config.isp_config.ie_config.effect = val;
+ break;
+ case CIF_ISP10_CID_JPEG_QUALITY:
+ if ((u32)val > 100) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "JPEG quality (%d) must be in [1..100]\n", val);
+ return -EINVAL;
+ }
+ dev->config.jpeg_config.ratio = val;
+ break;
+ case CIF_ISP10_CID_FLASH_MODE:
+ if ((u32)val > CIF_ISP10_FLASH_MODE_TORCH) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported flash mode (%d)\n", val);
+ return -EINVAL;
+ }
+ dev->config.flash_mode = val;
+ cif_isp10_img_src_s_ctrl(
+ dev->img_src,
+ CIF_ISP10_CID_FLASH_MODE,
+ dev->config.flash_mode);
+ if (dev->config.flash_mode == CIF_ISP10_FLASH_MODE_FLASH) {
+ do_gettimeofday(&dev->flash_t.mainflash_start_t);
+ dev->flash_t.mainflash_start_t.tv_usec +=
+ dev->flash_t.flash_turn_on_time;
+ dev->flash_t.mainflash_end_t =
+ dev->flash_t.mainflash_start_t;
+ dev->flash_t.mainflash_end_t.tv_sec +=
+ dev->flash_t.flash_on_timeout;
+ } else if (dev->config.flash_mode ==
+ CIF_ISP10_FLASH_MODE_TORCH) {
+ do_gettimeofday(&dev->flash_t.preflash_start_t);
+ dev->flash_t.preflash_end_t =
+ dev->flash_t.preflash_start_t;
+ dev->flash_t.preflash_end_t.tv_sec = 0x00;
+ dev->flash_t.preflash_end_t.tv_usec = 0x00;
+ } else if (dev->config.flash_mode == CIF_ISP10_FLASH_MODE_OFF) {
+ do_gettimeofday(&dev->flash_t.preflash_end_t);
+ if (dev->flash_t.preflash_end_t.tv_sec * 1000000 +
+ dev->flash_t.preflash_end_t.tv_usec <
+ dev->flash_t.mainflash_end_t.tv_sec * 1000000 +
+ dev->flash_t.mainflash_end_t.tv_usec) {
+ dev->flash_t.mainflash_end_t =
+ dev->flash_t.preflash_end_t;
+ }
+ }
+ break;
+ case CIF_ISP10_CID_WB_TEMPERATURE:
+ case CIF_ISP10_CID_ANALOG_GAIN:
+ case CIF_ISP10_CID_EXPOSURE_TIME:
+ case CIF_ISP10_CID_BLACK_LEVEL:
+ case CIF_ISP10_CID_FOCUS_ABSOLUTE:
+ case CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE:
+ case CIF_ISP10_CID_SCENE_MODE:
+ case CIF_ISP10_CID_AUTO_FPS:
+ case CIF_ISP10_CID_HFLIP:
+ case CIF_ISP10_CID_VFLIP:
+ return cif_isp10_img_src_s_ctrl(dev->img_src,
+ id, val);
+ default:
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "unknown/unsupported control %d\n", id);
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+/* end */
+
+enum {
+ isp_data_loss = 0,
+ isp_pic_size_err,
+ mipi_fifo_err,
+ dphy_err_sot,
+ dphy_err_sot_sync,
+ dphy_err_eot_sync,
+ dphy_err_ctrl,
+ csi_err_protocol,
+ csi_ecc1_err,
+ csi_ecc2_err,
+ csi_cs_err,
+};
+
+static void cif_isp10_hw_restart(struct cif_isp10_device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ cif_isp10_hw_errors[isp_pic_size_err].count = 0;
+ cif_isp10_hw_errors[isp_data_loss].count = 0;
+ cif_isp10_hw_errors[csi_err_protocol].count = 0;
+ cif_isp10_hw_errors[csi_ecc1_err].count = 0;
+ cif_isp10_hw_errors[csi_ecc2_err].count = 0;
+ cif_isp10_hw_errors[csi_cs_err].count = 0;
+ cif_iowrite32(0x00000841, dev->config.base_addr + CIF_IRCL);
+ cif_iowrite32(0x0, dev->config.base_addr + CIF_IRCL);
+
+ /* enable mipi frame end interrupt */
+ cif_iowrite32(CIF_MIPI_FRAME_END,
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ /* enable csi protocol errors interrupts */
+ cif_iowrite32OR(CIF_MIPI_ERR_CSI,
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ /* enable dphy errors interrupts */
+ cif_iowrite32OR(CIF_MIPI_ERR_DPHY,
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ /* add fifo error */
+ cif_iowrite32OR(CIF_MIPI_SYNC_FIFO_OVFLW(3),
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ /* add data overflow_error */
+ cif_iowrite32OR(CIF_MIPI_ADD_DATA_OVFLW,
+ dev->config.base_addr + CIF_MIPI_IMSC);
+
+ cif_iowrite32(0x0,
+ dev->config.base_addr + CIF_MI_MP_Y_OFFS_CNT_INIT);
+ cif_iowrite32(0x0,
+ dev->config.base_addr +
+ CIF_MI_MP_CR_OFFS_CNT_INIT);
+ cif_iowrite32(0x0,
+ dev->config.base_addr +
+ CIF_MI_MP_CB_OFFS_CNT_INIT);
+ cif_iowrite32(0x0,
+ dev->config.base_addr + CIF_MI_SP_Y_OFFS_CNT_INIT);
+ cif_iowrite32(0x0,
+ dev->config.base_addr +
+ CIF_MI_SP_CR_OFFS_CNT_INIT);
+ cif_iowrite32(0x0,
+ dev->config.base_addr +
+ CIF_MI_SP_CB_OFFS_CNT_INIT);
+ cif_iowrite32OR(CIF_MI_CTRL_INIT_OFFSET_EN,
+ dev->config.base_addr + CIF_MI_CTRL);
+
+ /* Enable ISP ! */
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD |
+ CIF_ISP_CTRL_ISP_INFORM_ENABLE |
+ CIF_ISP_CTRL_ISP_ENABLE,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ /* enable MIPI */
+ cif_iowrite32OR(CIF_MIPI_CTRL_OUTPUT_ENA,
+ dev->config.base_addr + CIF_MIPI_CTRL);
+}
+
+int cif_isp10_mipi_isr(unsigned int mipi_mis, void *cntxt)
+{
+ struct cif_isp10_device *dev =
+ (struct cif_isp10_device *)cntxt;
+ unsigned int mipi_ris = 0;
+
+ mipi_ris = cif_ioread32(dev->config.base_addr + CIF_MIPI_RIS);
+ mipi_mis = cif_ioread32(dev->config.base_addr + CIF_MIPI_MIS);
+
+ cif_isp10_pltfrm_rtrace_printf(dev->dev,
+ "MIPI_MIS %08x, MIPI_RIS %08x, MIPI_IMSC %08x\n",
+ mipi_mis,
+ mipi_ris,
+ cif_ioread32(dev->config.base_addr + CIF_MIPI_IMSC));
+
+ cif_iowrite32(~0,
+ dev->config.base_addr + CIF_MIPI_ICR);
+
+ if (mipi_mis & CIF_MIPI_ERR_DPHY) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF_MIPI_ERR_DPHY: 0x%x\n", mipi_mis);
+
+ /*
+ * Disable DPHY errctrl interrupt, because this dphy
+ * erctrl signal is assert and until the next changes
+ * in line state. This time is may be too long and cpu
+ * is hold in this interrupt.
+ */
+ if (mipi_mis & CIF_MIPI_ERR_CTRL(3))
+ cif_iowrite32AND(~(CIF_MIPI_ERR_CTRL(3)),
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ }
+
+ if (mipi_mis & CIF_MIPI_ERR_CSI) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF_MIPI_ERR_CSI: 0x%x\n", mipi_mis);
+ }
+
+ if (mipi_mis & CIF_MIPI_SYNC_FIFO_OVFLW(3)) {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "CIF_MIPI_SYNC_FIFO_OVFLW: 0x%x\n", mipi_mis);
+ }
+
+ if (mipi_mis == CIF_MIPI_FRAME_END) {
+ /*
+ * Enable DPHY errctrl interrupt again, if mipi have receive
+ * the whole frame without any error.
+ */
+ cif_iowrite32OR(CIF_MIPI_ERR_CTRL(3),
+ dev->config.base_addr + CIF_MIPI_IMSC);
+ }
+
+ mipi_mis = cif_ioread32(dev->config.base_addr + CIF_MIPI_MIS);
+
+ if (mipi_mis) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "mipi_mis icr err: 0x%x\n", mipi_mis);
+ }
+
+ return 0;
+}
+
+/* ======================================================================== */
+int cif_isp10_isp_isr(unsigned int isp_mis, void *cntxt)
+{
+ struct cif_isp10_device *dev =
+ (struct cif_isp10_device *)cntxt;
+ unsigned int isp_mis_tmp = 0;
+ unsigned int isp_err = 0;
+ struct timeval tv;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "ISP_MIS %08x, ISP_RIS %08x, ISP_IMSC %08x\n",
+ isp_mis,
+ cif_ioread32(dev->config.base_addr + CIF_ISP_RIS),
+ cif_ioread32(dev->config.base_addr + CIF_ISP_IMSC));
+
+ if (isp_mis & CIF_ISP_V_START) {
+ struct cif_isp10_isp_vs_work *vs_wk;
+ struct cif_isp10_img_src_exp *exp;
+
+ do_gettimeofday(&tv);
+ dev->b_isp_frame_in = false;
+ dev->b_mi_frame_end = false;
+ cifisp_v_start(&dev->isp_dev, &tv);
+
+ cif_iowrite32(CIF_ISP_V_START,
+ dev->config.base_addr + CIF_ISP_ICR);
+ isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+ if (isp_mis_tmp & CIF_ISP_V_START)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "isp icr v_statr err: 0x%x\n",
+ isp_mis_tmp);
+
+ if (!dev->config.mi_config.async_updt) {
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_GEN_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "CIF_ISP_CTRL_ISP_GEN_CFG_UPD\n");
+ }
+ if (dev->sof_event)
+ dev->sof_event(dev, dev->isp_dev.frame_id >> 1);
+ spin_lock(&dev->img_src_exps.lock);
+ if (!list_empty(&dev->img_src_exps.list)) {
+ exp = list_first_entry(&dev->img_src_exps.list,
+ struct cif_isp10_img_src_exp,
+ list);
+ list_del(&exp->list);
+ } else {
+ exp = NULL;
+ }
+ spin_unlock(&dev->img_src_exps.lock);
+
+ if (exp) {
+ vs_wk = kmalloc(sizeof(*vs_wk),
+ GFP_KERNEL);
+ if (vs_wk) {
+ vs_wk->cmd = CIF_ISP10_VS_EXP;
+ vs_wk->dev = dev;
+ vs_wk->param = (void *)exp;
+ INIT_WORK((struct work_struct *)&vs_wk->work,
+ cif_isp10_vs_work);
+ if (!queue_work(dev->vs_wq,
+ (struct work_struct *)&vs_wk->work)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "%s: queue work failed\n", __func__);
+ kfree(vs_wk);
+ }
+ }
+ }
+ }
+
+ if (isp_mis & CIF_ISP_FRAME_IN) {
+ do_gettimeofday(&tv);
+ cif_iowrite32(CIF_ISP_FRAME_IN,
+ dev->config.base_addr + CIF_ISP_ICR);
+ cifisp_frame_in(&dev->isp_dev, &tv);
+ }
+
+ if ((isp_mis & (CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR))) {
+ dev->sp_stream.stall = true;
+ dev->mp_stream.stall = true;
+
+ if ((isp_mis & CIF_ISP_PIC_SIZE_ERROR)) {
+ /* Clear pic_size_error */
+ cif_iowrite32(CIF_ISP_PIC_SIZE_ERROR,
+ dev->config.base_addr +
+ CIF_ISP_ICR);
+ cif_isp10_hw_errors[isp_pic_size_err].count++;
+ isp_err =
+ cif_ioread32(dev->config.base_addr +
+ CIF_ISP_ERR);
+ dev_err(dev->dev,
+ "CIF_ISP_PIC_SIZE_ERROR (0x%08x)",
+ isp_err);
+ cif_iowrite32(isp_err,
+ dev->config.base_addr +
+ CIF_ISP_ERR_CLR);
+ } else if ((isp_mis & CIF_ISP_DATA_LOSS)) {
+ /* Clear data_loss */
+ cif_iowrite32(CIF_ISP_DATA_LOSS,
+ dev->config.base_addr +
+ CIF_ISP_ICR);
+ cif_isp10_hw_errors[isp_data_loss].count++;
+ dev_err(dev->dev,
+ "CIF_ISP_DATA_LOSS\n");
+ cif_iowrite32(CIF_ISP_DATA_LOSS,
+ dev->config.base_addr +
+ CIF_ISP_ICR);
+ }
+
+ /* Stop ISP */
+ cif_iowrite32AND(~CIF_ISP_CTRL_ISP_INFORM_ENABLE &
+ ~CIF_ISP_CTRL_ISP_ENABLE,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ /* isp_update */
+ cif_iowrite32OR(CIF_ISP_CTRL_ISP_CFG_UPD,
+ dev->config.base_addr + CIF_ISP_CTRL);
+ cif_isp10_hw_restart(dev);
+ }
+
+ if (isp_mis & CIF_ISP_FRAME_IN) {
+ cif_iowrite32(CIF_ISP_FRAME_IN,
+ dev->config.base_addr + CIF_ISP_ICR);
+ isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+ if (isp_mis_tmp & CIF_ISP_FRAME_IN)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "isp icr frame_in err: 0x%x\n",
+ isp_mis_tmp);
+
+ /* restart MI if CIF has run out of buffers */
+ if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel) &&
+ !CIF_ISP10_MI_IS_BUSY(dev) &&
+ !dev->config.jpeg_config.busy &&
+ (dev->config.mi_config.async_updt ||
+ (!dev->sp_stream.next_buf &&
+ !dev->mp_stream.next_buf))){
+ u32 mi_isr = 0;
+
+ if (dev->sp_stream.state == CIF_ISP10_STATE_STREAMING)
+ mi_isr |= CIF_MI_SP_FRAME;
+ if (dev->mp_stream.state == CIF_ISP10_STATE_STREAMING)
+ mi_isr |= CIF_MI_MP_FRAME;
+ cif_iowrite32(mi_isr,
+ dev->config.base_addr + CIF_MI_ISR);
+ }
+ }
+
+ if (isp_mis & CIF_ISP_FRAME) {
+ /* Clear Frame In (ISP) */
+ cif_iowrite32(CIF_ISP_FRAME,
+ dev->config.base_addr + CIF_ISP_ICR);
+ isp_mis_tmp = cif_ioread32(dev->config.base_addr + CIF_ISP_MIS);
+ if (isp_mis_tmp & CIF_ISP_FRAME)
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "isp icr frame end err: 0x%x\n",
+ isp_mis_tmp);
+
+ if (dev->b_mi_frame_end)
+ cif_isp10_update_ism_dcr_rsz(dev);
+ dev->b_isp_frame_in = true;
+ }
+
+ cifisp_isp_isr(&dev->isp_dev, isp_mis);
+
+ return 0;
+}
+
+/* ======================================================================== */
+
+void init_output_formats(void)
+{
+ unsigned int i = 0;
+ int ret = 0; /* RF*/
+ int xgold_num_format = 0; /*RF*/
+
+ xgold_num_format =
+ (sizeof(cif_isp10_output_format) / sizeof(struct cif_isp10_fmt));
+
+ for (i = 0; i < xgold_num_format; i++) {
+ struct v4l2_fmtdesc fmtdesc;
+
+ memset(&fmtdesc, 0, sizeof(fmtdesc));
+ fmtdesc.index = i;
+ fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
+ strlcpy((&fmtdesc)->description,
+ cif_isp10_output_format[(&fmtdesc)->index].name,
+ sizeof((&fmtdesc)->description));
+ (&fmtdesc)->pixelformat =
+ cif_isp10_output_format[(&fmtdesc)->index].fourcc;
+ (&fmtdesc)->flags =
+ cif_isp10_output_format[(&fmtdesc)->index].flags;
+
+ if (ret < 0)
+ break;
+
+ output_formats[i] = fmtdesc;
+ }
+}
+
+int get_cif_isp10_output_format_size(void)
+{
+ return sizeof(cif_isp10_output_format) / sizeof(struct cif_isp10_fmt);
+}
+
+struct cif_isp10_fmt *get_cif_isp10_output_format(int index)
+{
+ struct cif_isp10_fmt *fmt = NULL;
+
+ if ((index >= 0) && (index < get_cif_isp10_output_format_size()))
+ fmt = &cif_isp10_output_format[index];
+
+ return fmt;
+}
+
+struct v4l2_fmtdesc *get_cif_isp10_output_format_desc(int index)
+{
+ struct v4l2_fmtdesc *desc = NULL;
+
+ if ((index >= 0) && (index < get_cif_isp10_output_format_desc_size()))
+ desc = &output_formats[index];
+
+ return desc;
+}
+
+int get_cif_isp10_output_format_desc_size(void)
+{
+ return ARRAY_SIZE(cif_isp10_output_format);
+}
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_H
+#define _CIF_ISP10_H
+
+#include <linux/platform_device.h>
+#include "cif_isp10_pltfrm.h"
+#include "cif_isp10_img_src.h"
+#include "cif_isp10_isp.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-controls_rockchip.h>
+/*****************************************************************************/
+/* Definitions */
+
+#define CONFIG_CIF_ISP_AUTO_UPD_CFG_BUG
+
+#define CIF_ISP10_NUM_INPUTS 10
+
+/* FORMAT */
+#define MAX_NB_FORMATS 30
+
+#define CONTRAST_DEF 0x80
+#define BRIGHTNESS_DEF 0x0
+#define HUE_DEF 0x0
+
+/*
+ * MIPI CSI2.0
+ */
+#define CSI2_DT_YUV420_8b (0x18)
+#define CSI2_DT_YUV420_10b (0x19)
+#define CSI2_DT_YUV422_8b (0x1E)
+#define CSI2_DT_YUV422_10b (0x1F)
+#define CSI2_DT_RGB565 (0x22)
+#define CSI2_DT_RGB666 (0x23)
+#define CSI2_DT_RGB888 (0x24)
+#define CSI2_DT_RAW8 (0x2A)
+#define CSI2_DT_RAW10 (0x2B)
+#define CSI2_DT_RAW12 (0x2C)
+
+enum cif_isp10_img_src_state {
+ CIF_ISP10_IMG_SRC_STATE_OFF = 0,
+ CIF_ISP10_IMG_SRC_STATE_SW_STNDBY = 1,
+ CIF_ISP10_IMG_SRC_STATE_STREAMING = 2
+};
+
+enum cif_isp10_state {
+ /* path not yet opened: */
+ CIF_ISP10_STATE_DISABLED = 0,
+ /* path opened but not yet configured: */
+ CIF_ISP10_STATE_INACTIVE = 1,
+ /* path opened and configured, ready for streaming: */
+ CIF_ISP10_STATE_READY = 2,
+ /* path is streaming: */
+ CIF_ISP10_STATE_STREAMING = 3
+};
+
+enum cif_isp10_pm_state {
+ CIF_ISP10_PM_STATE_OFF,
+ CIF_ISP10_PM_STATE_SUSPENDED,
+ CIF_ISP10_PM_STATE_SW_STNDBY,
+ CIF_ISP10_PM_STATE_STREAMING
+};
+
+enum cif_isp10_inp {
+ CIF_ISP10_INP_CSI = 0x10000000,
+ CIF_ISP10_INP_CPI = 0x20000000,
+
+ CIF_ISP10_INP_DMA = 0x30000000, /* DMA -> ISP */
+ CIF_ISP10_INP_DMA_IE = 0x31000000, /* DMA -> IE */
+ CIF_ISP10_INP_DMA_SP = 0x32000000, /* DMA -> SP */
+ CIF_ISP10_INP_DMA_MAX = 0x33000000,
+
+ CIF_ISP10_INP_MAX = 0x7fffffff
+};
+
+#define CIF_ISP10_INP_IS_DMA(inp) \
+ (((inp) & 0xf0000000) == CIF_ISP10_INP_DMA)
+#define CIF_ISP10_INP_IS_MIPI(inp) \
+ (((inp) & 0xf0000000) == CIF_ISP10_INP_CSI)
+#define CIF_ISP10_INP_IS_DVP(inp) \
+ (((inp) & 0xf0000000) == CIF_ISP10_INP_CPI)
+#define CIF_ISP10_INP_NEED_ISP(inp) \
+ ((inp) < CIF_ISP10_INP_DMA_IE)
+#define CIF_ISP10_INP_DMA_CNT() \
+ ((CIF_ISP10_INP_DMA_MAX -\
+ CIF_ISP10_INP_DMA) >> 24)
+
+enum cif_isp10_pinctrl_state {
+ CIF_ISP10_PINCTRL_STATE_SLEEP,
+ CIF_ISP10_PINCTRL_STATE_INACTIVE,
+ CIF_ISP10_PINCTRL_STATE_DEFAULT,
+ CIF_ISP10_PINCTRL_STATE_ACTIVE
+};
+
+enum cif_isp10_flash_mode {
+ CIF_ISP10_FLASH_MODE_OFF,
+ CIF_ISP10_FLASH_MODE_FLASH,
+ CIF_ISP10_FLASH_MODE_TORCH,
+};
+
+enum cif_isp10_cid {
+ CIF_ISP10_CID_FLASH_MODE = 0,
+ CIF_ISP10_CID_EXPOSURE_TIME = 1,
+ CIF_ISP10_CID_ANALOG_GAIN = 2,
+ CIF_ISP10_CID_WB_TEMPERATURE = 3,
+ CIF_ISP10_CID_BLACK_LEVEL = 4,
+ CIF_ISP10_CID_AUTO_GAIN = 5,
+ CIF_ISP10_CID_AUTO_EXPOSURE = 6,
+ CIF_ISP10_CID_AUTO_WHITE_BALANCE = 7,
+ CIF_ISP10_CID_FOCUS_ABSOLUTE = 8,
+ CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE = 9,
+ CIF_ISP10_CID_SCENE_MODE = 10,
+ CIF_ISP10_CID_SUPER_IMPOSE = 11,
+ CIF_ISP10_CID_JPEG_QUALITY = 12,
+ CIF_ISP10_CID_IMAGE_EFFECT = 13,
+ CIF_ISP10_CID_HFLIP = 14,
+ CIF_ISP10_CID_VFLIP = 15,
+ CIF_ISP10_CID_AUTO_FPS = 16,
+ CIF_ISP10_CID_VBLANKING = 17,
+ CIF_ISP10_CID_ISO_SENSITIVITY = 18,
+
+};
+
+/* correspond to bit field values */
+enum cif_isp10_image_effect {
+ CIF_ISP10_IE_BW = 0,
+ CIF_ISP10_IE_NEGATIVE = 1,
+ CIF_ISP10_IE_SEPIA = 2,
+ CIF_ISP10_IE_C_SEL = 3,
+ CIF_ISP10_IE_EMBOSS = 4,
+ CIF_ISP10_IE_SKETCH = 5,
+ CIF_ISP10_IE_NONE /* not a bit field value */
+};
+
+#define CIF_ISP10_PIX_FMT_MASK 0xf0000000
+#define CIF_ISP10_PIX_FMT_MASK_BPP 0x0003f000
+#define CIF_ISP10_PIX_FMT_YUV_MASK_CPLANES 0x00000003
+#define CIF_ISP10_PIX_FMT_YUV_MASK_UVSWAP 0x00000004
+#define CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP 0x00000008
+#define CIF_ISP10_PIX_FMT_YUV_MASK_X 0x00000f00
+#define CIF_ISP10_PIX_FMT_YUV_MASK_Y 0x000000f0
+#define CIF_ISP10_PIX_FMT_RGB_MASK_PAT 0x000000f0
+#define CIF_ISP10_PIX_FMT_BAYER_MASK_PAT 0x000000f0
+#define CIF_ISP10_PIX_FMT_GET_BPP(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK_BPP) >> 12)
+#define cif_isp10_pix_fmt_set_bpp(pix_fmt, bpp) \
+ { \
+ pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_MASK_BPP) | \
+ (((bpp) << 12) & CIF_ISP10_PIX_FMT_MASK_BPP)); \
+ }
+
+#define CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt) \
+ ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_CPLANES)
+#define CIF_ISP10_PIX_FMT_YUV_IS_YC_SWAPPED(pix_fmt) \
+ ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP)
+#define CIF_ISP10_PIX_FMT_YUV_IS_UV_SWAPPED(pix_fmt) \
+ ((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_UVSWAP)
+#define CIF_ISP10_PIX_FMT_YUV_GET_X_SUBS(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_X) >> 8)
+#define CIF_ISP10_PIX_FMT_YUV_GET_Y_SUBS(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_YUV_MASK_Y) >> 4)
+#define cif_isp10_pix_fmt_set_y_subs(pix_fmt, y_subs) \
+ { \
+ pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_Y) | \
+ ((y_subs << 4) & CIF_ISP10_PIX_FMT_YUV_MASK_Y)); \
+ }
+#define cif_isp10_pix_fmt_set_x_subs(pix_fmt, x_subs) \
+ { \
+ pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_X) | \
+ (((x_subs) << 8) & CIF_ISP10_PIX_FMT_YUV_MASK_X)); \
+ }
+#define cif_isp10_pix_fmt_set_yc_swapped(pix_fmt, yc_swapped) \
+ { \
+ pix_fmt = (((pix_fmt) & ~CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP) | \
+ (((yc_swapped) << 3) & \
+ CIF_ISP10_PIX_FMT_YUV_MASK_YCSWAP)); \
+ }
+
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x0)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x10)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x20)
+#define CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_BAYER_MASK_PAT) == 0x30)
+
+#define CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x10000000)
+#define CIF_ISP10_PIX_FMT_IS_RGB(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x20000000)
+#define CIF_ISP10_PIX_FMT_IS_RAW_BAYER(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x30000000)
+#define CIF_ISP10_PIX_FMT_IS_JPEG(pix_fmt) \
+ (((pix_fmt) & CIF_ISP10_PIX_FMT_MASK) == 0x40000000)
+
+#define CIF_ISP10_PIX_FMT_IS_INTERLEAVED(pix_fmt) \
+ (!CIF_ISP10_PIX_FMT_IS_YUV(pix_fmt) ||\
+ !CIF_ISP10_PIX_FMT_YUV_GET_NUM_CPLANES(pix_fmt))
+
+enum cif_isp10_pix_fmt {
+ /* YUV */
+ CIF_YUV400 = 0x10008000,
+ CIF_YVU400 = 0x10008004,
+
+ CIF_YUV420I = 0x1000c220,
+ CIF_YUV420SP = 0x1000c221, /* NV12 */
+ CIF_YUV420P = 0x1000c222,
+ CIF_YVU420I = 0x1000c224,
+ CIF_YVU420SP = 0x1000c225, /* NV21 */
+ CIF_YVU420P = 0x1000c226, /* YV12 */
+
+ CIF_YUV422I = 0x10010240,
+ CIF_YUV422SP = 0x10010241,
+ CIF_YUV422P = 0x10010242,
+ CIF_YVU422I = 0x10010244,
+ CIF_YVU422SP = 0x10010245,
+ CIF_YVU422P = 0x10010246,
+
+ CIF_YUV444I = 0x10018440,
+ CIF_YUV444SP = 0x10018441,
+ CIF_YUV444P = 0x10018442,
+ CIF_YVU444I = 0x10018444,
+ CIF_YVU444SP = 0x10018445,
+ CIF_YVU444P = 0x10018446,
+
+ CIF_UYV400 = 0x10008008,
+
+ CIF_UYV420I = 0x1000c228,
+ CIF_UYV420SP = 0x1000c229,
+ CIF_UYV420P = 0x1000c22a,
+ CIF_VYU420I = 0x1000c22c,
+ CIF_VYU420SP = 0x1000c22d,
+ CIF_VYU420P = 0x1000c22e,
+
+ CIF_UYV422I = 0x10010248,
+ CIF_UYV422SP = 0x10010249,
+ CIF_UYV422P = 0x1001024a,
+ CIF_VYU422I = 0x1001024c,
+ CIF_VYU422SP = 0x1001024d,
+ CIF_VYU422P = 0x1001024e,
+
+ CIF_UYV444I = 0x10018448,
+ CIF_UYV444SP = 0x10018449,
+ CIF_UYV444P = 0x1001844a,
+ CIF_VYU444I = 0x1001844c,
+ CIF_VYU444SP = 0x1001844d,
+ CIF_VYU444P = 0x1001844e,
+
+ /* RGB */
+ CIF_RGB565 = 0x20010000,
+ CIF_RGB666 = 0x20012000,
+ CIF_RGB888 = 0x20018000,
+
+ /* RAW Bayer */
+ CIF_BAYER_SBGGR8 = 0x30008000,
+ CIF_BAYER_SGBRG8 = 0x30008010,
+ CIF_BAYER_SGRBG8 = 0x30008020,
+ CIF_BAYER_SRGGB8 = 0x30008030,
+
+ CIF_BAYER_SBGGR10 = 0x3000a000,
+ CIF_BAYER_SGBRG10 = 0x3000a010,
+ CIF_BAYER_SGRBG10 = 0x3000a020,
+ CIF_BAYER_SRGGB10 = 0x3000a030,
+
+ CIF_BAYER_SBGGR12 = 0x3000c000,
+ CIF_BAYER_SGBRG12 = 0x3000c010,
+ CIF_BAYER_SGRBG12 = 0x3000c020,
+ CIF_BAYER_SRGGB12 = 0x3000c030,
+
+ /* JPEG */
+ CIF_JPEG = 0x40008000,
+
+ /* Data */
+ CIF_DATA = 0x70000000,
+
+ CIF_UNKNOWN_FORMAT = 0x80000000
+};
+
+enum cif_isp10_stream_id {
+ CIF_ISP10_STREAM_SP = 0x1,
+ CIF_ISP10_STREAM_MP = 0x2,
+ CIF_ISP10_STREAM_DMA = 0x4,
+ CIF_ISP10_STREAM_ISP = 0x8
+};
+
+#define CIF_ISP10_ALL_STREAMS \
+ (CIF_ISP10_STREAM_SP | \
+ CIF_ISP10_STREAM_MP | \
+ CIF_ISP10_STREAM_DMA)
+
+enum cif_isp10_buff_fmt {
+ /* values correspond to bitfield values */
+ CIF_ISP10_BUFF_FMT_PLANAR = 0,
+ CIF_ISP10_BUFF_FMT_SEMIPLANAR = 1,
+ CIF_ISP10_BUFF_FMT_INTERLEAVED = 2,
+
+ CIF_ISP10_BUFF_FMT_RAW8 = 0,
+ CIF_ISP10_BUFF_FMT_RAW12 = 2
+};
+
+enum cif_isp10_jpeg_header {
+ CIF_ISP10_JPEG_HEADER_JFIF,
+ CIF_ISP10_JPEG_HEADER_NONE
+};
+
+struct cif_isp10_csi_config {
+ u32 vc;
+ u32 nb_lanes;
+ u32 bit_rate;
+ /* really used csi */
+ u32 used_csi; /* xuhf@rock-chips.com: v1.0.4 */
+};
+
+struct cif_isp10_paraport_config {
+ u32 cif_vsync;
+ u32 cif_hsync;
+ u32 cif_pclk;
+ /* really used csi */
+ u32 used_csi; /* xuhf@rock-chips.com: v1.0.4 */
+};
+
+struct cif_isp10_frm_intrvl {
+ u32 numerator;
+ u32 denominator;
+};
+
+struct cif_isp10_frm_fmt {
+ u32 width;
+ u32 height;
+ u32 stride;
+ u32 std_id;
+ enum cif_isp10_pix_fmt pix_fmt;
+ enum cif_isp10_pix_fmt_quantization quantization;
+ struct v4l2_rect defrect;
+};
+
+struct cif_isp10_strm_fmt {
+ struct cif_isp10_frm_fmt frm_fmt;
+ struct cif_isp10_frm_intrvl frm_intrvl;
+};
+
+struct cif_isp10_strm_fmt_desc {
+ bool discrete_frmsize;
+ struct {
+ u32 width;
+ u32 height;
+ } min_frmsize;
+ struct {
+ u32 width;
+ u32 height;
+ } max_frmsize;
+ enum cif_isp10_pix_fmt pix_fmt;
+ bool discrete_intrvl;
+ struct cif_isp10_frm_intrvl min_intrvl;
+ struct cif_isp10_frm_intrvl max_intrvl;
+ struct v4l2_rect defrect;
+ u32 std_id;
+};
+
+struct cif_isp10_rsz_config {
+ struct cif_isp10_frm_fmt *input;
+ struct cif_isp10_frm_fmt output;
+ bool ycflt_adjust;
+ bool ism_adjust;
+};
+
+struct cif_isp10_dcrop_config {
+ unsigned int h_offs;
+ unsigned int v_offs;
+ unsigned int h_size;
+ unsigned int v_size;
+};
+
+struct cif_isp10_sp_config {
+ struct cif_isp10_rsz_config rsz_config;
+ struct cif_isp10_dcrop_config dcrop;
+};
+
+struct cif_isp10_mp_config {
+ struct cif_isp10_rsz_config rsz_config;
+ struct cif_isp10_dcrop_config dcrop;
+};
+
+struct cif_isp10_mi_path_config {
+ struct cif_isp10_frm_fmt *input;
+ struct cif_isp10_frm_fmt output;
+ u32 llength;
+ u32 curr_buff_addr;
+ u32 next_buff_addr;
+ u32 cb_offs;
+ u32 cr_offs;
+ u32 y_size;
+ u32 cb_size;
+ u32 cr_size;
+ bool busy;
+};
+
+struct cif_isp10_zoom_buffer_info {
+ u32 width;
+ u32 height;
+ unsigned long buff_addr;
+ u32 flags;
+};
+
+struct cif_isp10_mi_config {
+ bool raw_enable;
+ u32 async_updt;
+ struct cif_isp10_mi_path_config mp;
+ struct cif_isp10_mi_path_config sp;
+ struct cif_isp10_mi_path_config dma;
+};
+
+#ifdef NO_YET
+struct cif_isp10_buffer {
+ struct list_head list;
+ u32 dma_addr;
+ u32 size;
+};
+#else
+#define cif_isp10_buffer videobuf_buffer
+#endif
+
+struct cif_isp10_metadata_s {
+ unsigned int cnt;
+ unsigned int vmas;
+ unsigned char *d;
+};
+
+struct cif_isp10_stream {
+ enum cif_isp10_stream_id id;
+ enum cif_isp10_state state;
+ enum cif_isp10_state saved_state;
+ struct list_head buf_queue;
+ struct videobuf_buffer *curr_buf;
+ struct videobuf_buffer *next_buf;
+ bool updt_cfg;
+ bool stall;
+ bool stop;
+ CIF_ISP10_PLTFRM_EVENT done;
+ struct cif_isp10_metadata_s metadata;
+};
+
+struct cif_isp10_jpeg_config {
+ bool enable;
+ bool busy;
+ u32 ratio;
+ struct cif_isp10_frm_fmt *input;
+ enum cif_isp10_jpeg_header header;
+};
+
+struct cif_isp10_ie_config {
+ enum cif_isp10_image_effect effect;
+};
+
+/* IS */
+struct cif_isp10_ism_params {
+ unsigned int ctrl;
+ unsigned int recenter;
+ unsigned int h_offs;
+ unsigned int v_offs;
+ unsigned int h_size;
+ unsigned int v_size;
+ unsigned int max_dx;
+ unsigned int max_dy;
+ unsigned int displace;
+};
+
+struct cif_isp10_ism_config {
+ bool ism_en;
+ struct cif_isp10_ism_params ism_params;
+ bool ism_update_needed;
+};
+
+struct cif_isp10_isp_config {
+ bool si_enable;
+ struct cif_isp10_ie_config ie_config;
+ struct cif_isp10_ism_config ism_config;
+ struct cif_isp10_frm_fmt *input;
+ struct cif_isp10_frm_fmt output;
+};
+
+struct cif_isp10_config {
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR base_addr;
+ enum cif_isp10_flash_mode flash_mode;
+ enum cif_isp10_inp input_sel;
+ struct cif_isp10_jpeg_config jpeg_config;
+ struct cif_isp10_mi_config mi_config;
+ struct cif_isp10_sp_config sp_config;
+ struct cif_isp10_mp_config mp_config;
+ struct cif_isp10_strm_fmt img_src_output;
+ struct cif_isp10_isp_config isp_config;
+ struct pltfrm_cam_itf cam_itf;
+ bool out_of_buffer_stall;
+};
+
+struct cif_isp10_mi_state {
+ unsigned long flags;
+ unsigned int isp_ctrl;
+ unsigned int y_base_ad;
+ unsigned int y_size;
+ unsigned int cb_base_ad;
+ unsigned int cb_size;
+ unsigned int cr_base_ad;
+ unsigned int cr_size;
+};
+
+struct cif_isp10_img_src_exp {
+ struct list_head list;
+ struct cif_isp10_img_src_ext_ctrl *exp;
+};
+
+struct cif_isp10_img_src_data {
+ unsigned int v_frame_id;
+ struct isp_supplemental_sensor_mode_data data;
+};
+
+struct cif_isp10_img_src_exps {
+ spinlock_t lock; /* protect list */
+ struct list_head list;
+
+ struct mutex mutex; /* protect frm_exp */
+ struct cif_isp10_img_src_data data[2];
+ unsigned char exp_valid_frms;
+};
+
+enum cif_isp10_isp_vs_cmd {
+ CIF_ISP10_VS_EXP = 0,
+};
+
+struct cif_isp10_isp_vs_work {
+ struct work_struct work;
+ struct cif_isp10_device *dev;
+ enum cif_isp10_isp_vs_cmd cmd;
+ void *param;
+};
+
+struct cif_isp10_fmt {
+ char *name;
+ u32 fourcc;
+ int flags;
+ int depth;
+ unsigned char rotation;
+ unsigned char overlay;
+};
+
+struct cif_isp10_device {
+ unsigned int dev_id;
+ CIF_ISP10_PLTFRM_DEVICE dev;
+ struct v4l2_device v4l2_dev;
+ enum cif_isp10_pm_state pm_state;
+ enum cif_isp10_img_src_state img_src_state;
+
+ spinlock_t vbq_lock; /* spinlock for videobuf queues */
+ spinlock_t vbreq_lock; /* spinlock for videobuf requeues */
+
+ struct cif_isp10_img_src *img_src;
+ struct cif_isp10_img_src *img_src_array[CIF_ISP10_NUM_INPUTS];
+ unsigned int img_src_cnt;
+ struct cif_isp10_img_src_exps img_src_exps;
+
+ struct cif_isp10_config config;
+ struct cif_isp10_isp_dev isp_dev;
+ struct cif_isp10_stream sp_stream;
+ struct cif_isp10_stream mp_stream;
+ struct cif_isp10_stream dma_stream;
+
+ struct workqueue_struct *vs_wq;
+ void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence);
+ /*
+ * requeue_bufs() is used to clean and rebuild the local buffer
+ * lists xx_stream.buf_queue. This is used e.g. in the CAPTURE use
+ * case where we start MP and SP separately and needs to shortly
+ * stop and start SP when start MP
+ */
+ void (*requeue_bufs)(struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id);
+ bool b_isp_frame_in;
+ bool b_mi_frame_end;
+ int otf_zsl_mode;
+ struct flash_timeinfo_s flash_t;
+
+ struct pltfrm_soc_cfg *soc_cfg;
+ void *nodes;
+
+};
+
+struct cif_isp10_fmt *get_cif_isp10_output_format(int index);
+int get_cif_isp10_output_format_size(void);
+
+struct v4l2_fmtdesc *get_cif_isp10_output_format_desc(int index);
+int get_cif_isp10_output_format_desc_size(void);
+
+/* Clean code starts from here */
+
+struct cif_isp10_device *cif_isp10_create(
+ CIF_ISP10_PLTFRM_DEVICE pdev,
+ void (*sof_event)(struct cif_isp10_device *dev, __u32 frame_sequence),
+ void (*requeue_bufs)(struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id),
+ struct pltfrm_soc_cfg *soc_cfg);
+
+void cif_isp10_destroy(
+ struct cif_isp10_device *dev);
+
+int cif_isp10_init(
+ struct cif_isp10_device *dev,
+ u32 stream_ids);
+
+int cif_isp10_release(
+ struct cif_isp10_device *dev,
+ int stream_ids);
+
+int cif_isp10_streamon(
+ struct cif_isp10_device *dev,
+ u32 stream_ids);
+
+int cif_isp10_streamoff(
+ struct cif_isp10_device *dev,
+ u32 stream_ids);
+
+int cif_isp10_s_input(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_inp inp);
+
+int cif_isp10_s_fmt(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ struct cif_isp10_strm_fmt *strm_fmt,
+ u32 stride);
+
+int cif_isp10_resume(
+ struct cif_isp10_device *dev);
+
+int cif_isp10_suspend(
+ struct cif_isp10_device *dev);
+
+int cif_isp10_qbuf(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream,
+ struct cif_isp10_buffer *buf);
+
+int cif_isp10_reqbufs(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id strm,
+ struct v4l2_requestbuffers *req);
+int cif_isp10_mmap(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ struct vm_area_struct *vma);
+
+int cif_isp10_get_target_frm_size(
+ struct cif_isp10_device *dev,
+ u32 *target_width,
+ u32 *target_height);
+
+int cif_isp10_calc_isp_cropping(
+ struct cif_isp10_device *dev,
+ u32 *width,
+ u32 *height,
+ u32 *h_offs,
+ u32 *v_offs);
+
+const char *cif_isp10_g_input_name(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_inp inp);
+
+int cif_isp10_calc_min_out_buff_size(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id,
+ u32 *size);
+
+int cif_isp10_s_ctrl(
+ struct cif_isp10_device *dev,
+ const enum cif_isp10_cid id,
+ int val);
+
+void cif_isp10_dbgfs_fill_sensor_aec_para(
+ struct cif_isp10_device *cif_isp10_dev,
+ s32 exp_time,
+ u16 gain);
+
+int cif_isp10_s_isp_metadata(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_isp_readout_work *readout_work,
+ struct cifisp_isp_other_cfg *new_other,
+ struct cifisp_isp_meas_cfg *new_meas,
+ struct cifisp_stat_buffer *new_stats);
+
+int cif_isp10_s_exp(
+ struct cif_isp10_device *dev,
+ struct cif_isp10_img_src_ext_ctrl *exp_ctrl);
+
+void cif_isp10_sensor_mode_data_sync(
+ struct cif_isp10_device *dev,
+ unsigned int frame_id,
+ struct isp_supplemental_sensor_mode_data *data);
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10.h"
+#include "cif_isp10_img_src_ops.h"
+
+struct cif_isp10_img_src {
+ void *img_src;
+ const struct cif_isp10_img_src_ops *ops;
+};
+
+struct cif_isp10_img_src *cif_isp10_img_src_to_img_src(
+ CIF_ISP10_PLTFRM_DEVICE dev,
+ struct pltfrm_soc_cfg *soc_cfg)
+{
+ int ret = 0;
+ int i;
+ const char *device_type;
+ struct cif_isp10_img_src *img_src;
+
+ img_src = devm_kzalloc(dev, sizeof(*img_src), GFP_KERNEL);
+ if (!img_src) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ device_type = cif_isp10_pltfrm_get_device_type(dev);
+
+ img_src->ops = NULL;
+ for (i = 0; i < ARRAY_SIZE(cif_isp10_img_src_ops); i++) {
+ if (!strcmp(device_type, cif_isp10_img_src_ops->device_type)) {
+ img_src->ops = &cif_isp10_img_src_ops[i].ops;
+ break;
+ }
+ }
+ if (!img_src->ops) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unsupported device type %s\n",
+ device_type);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ WARN_ON(!img_src->ops->to_img_src);
+ WARN_ON(!img_src->ops->s_streaming);
+ WARN_ON(!img_src->ops->s_power);
+ WARN_ON(!img_src->ops->enum_strm_fmts);
+ WARN_ON(!img_src->ops->s_strm_fmt);
+ WARN_ON(!img_src->ops->g_ctrl);
+ WARN_ON(!img_src->ops->s_ctrl);
+
+ img_src->img_src = img_src->ops->to_img_src(dev, soc_cfg);
+ if (IS_ERR_OR_NULL(img_src->img_src)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "to_img_src failed!\n");
+ ret = -EFAULT;
+ goto err;
+ }
+
+ return img_src;
+err:
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n",
+ ret);
+ if (!IS_ERR_OR_NULL(img_src))
+ devm_kfree(dev, img_src);
+
+ return ERR_PTR(ret);
+}
+
+int cif_isp10_img_src_s_streaming(
+ struct cif_isp10_img_src *img_src,
+ bool enable)
+{
+ return img_src->ops->s_streaming(img_src->img_src, enable);
+}
+
+int cif_isp10_img_src_s_power(
+ struct cif_isp10_img_src *img_src,
+ bool on)
+{
+ return img_src->ops->s_power(img_src->img_src, on);
+}
+
+int cif_isp10_img_src_enum_strm_fmts(
+ struct cif_isp10_img_src *img_src,
+ u32 index,
+ struct cif_isp10_strm_fmt_desc *strm_fmt_desc)
+{
+ return img_src->ops->enum_strm_fmts(img_src->img_src,
+ index, strm_fmt_desc);
+}
+
+int cif_isp10_img_src_s_strm_fmt(
+ struct cif_isp10_img_src *img_src,
+ struct cif_isp10_strm_fmt *strm_fmt)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return -EINVAL;
+ }
+ return img_src->ops->s_strm_fmt(img_src->img_src, strm_fmt);
+}
+
+int cif_isp10_img_src_g_ctrl(
+ struct cif_isp10_img_src *img_src,
+ int id,
+ int *val)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return -EINVAL;
+ }
+ return img_src->ops->g_ctrl(img_src->img_src, id, val);
+}
+
+int cif_isp10_img_src_s_ctrl(
+ struct cif_isp10_img_src *img_src,
+ int id,
+ int val)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return -EINVAL;
+ }
+ return img_src->ops->s_ctrl(img_src->img_src, id, val);
+}
+
+int cif_isp10_img_src_s_ext_ctrls(
+ struct cif_isp10_img_src *img_src,
+ struct cif_isp10_img_src_ext_ctrl *ctrl)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return -EINVAL;
+ }
+ return img_src->ops->s_ext_ctrls(img_src->img_src, ctrl);
+}
+
+long cif_isp10_img_src_ioctl(
+ struct cif_isp10_img_src *img_src,
+ unsigned int cmd,
+ void *arg)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return -EINVAL;
+ }
+ return img_src->ops->ioctl(img_src->img_src, cmd, arg);
+}
+
+const char *cif_isp10_img_src_g_name(
+ struct cif_isp10_img_src *img_src)
+{
+ if (!img_src) {
+ cif_isp10_pltfrm_pr_err(NULL, "img_src is NULL\n");
+ return ERR_PTR(-EINVAL);
+ }
+ return img_src->ops->g_name(img_src->img_src);
+}
+
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_H
+#define _CIF_ISP10_IMG_SRC_H
+
+struct cif_isp10_img_src;
+struct cif_isp10_strm_fmt_desc;
+struct cif_isp10_strm_fmt;
+struct cif_isp10_csi_config;
+enum cif_isp10_pix_fmt;
+
+struct cif_isp10_img_src;
+struct pltfrm_soc_cfg;
+
+struct cif_isp10_img_src_ctrl {
+ unsigned int id;
+ int val;
+};
+
+struct cif_isp10_img_src_ext_ctrl {
+ int cnt;
+ unsigned int class;
+ struct cif_isp10_img_src_ctrl *ctrls;
+};
+
+struct cif_isp10_img_src *cif_isp10_img_src_to_img_src(
+ CIF_ISP10_PLTFRM_DEVICE dev,
+ struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_img_src_s_streaming(
+ struct cif_isp10_img_src *img_src,
+ bool enable);
+
+int cif_isp10_img_src_s_power(
+ struct cif_isp10_img_src *img_src,
+ bool on);
+
+int cif_isp10_img_src_enum_strm_fmts(
+ struct cif_isp10_img_src *img_src,
+ u32 index,
+ struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+
+int cif_isp10_img_src_s_strm_fmt(
+ struct cif_isp10_img_src *img_src,
+ struct cif_isp10_strm_fmt *strm_fmt);
+
+int cif_isp10_img_src_g_ctrl(
+ struct cif_isp10_img_src *img_src,
+ int id,
+ int *val);
+
+int cif_isp10_img_src_s_ctrl(
+ struct cif_isp10_img_src *img_src,
+ int id,
+ int val);
+
+const char *cif_isp10_img_src_g_name(
+ struct cif_isp10_img_src *img_src);
+
+int cif_isp10_img_src_s_ext_ctrls(
+ struct cif_isp10_img_src *img_src,
+ struct cif_isp10_img_src_ext_ctrl *ctrls);
+
+long cif_isp10_img_src_ioctl(
+ struct cif_isp10_img_src *img_src,
+ unsigned int cmd,
+ void *arg);
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_OPS_H
+#define _CIF_ISP10_IMG_SRC_OPS_H
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10_img_src_v4l2-subdev.h"
+
+struct cif_isp10_img_src_ops {
+ void * (*to_img_src)(
+ CIF_ISP10_PLTFRM_DEVICE dev,
+ struct pltfrm_soc_cfg *soc_cfg);
+ int (*s_streaming)(
+ void *img_src,
+ bool enable);
+ int (*s_power)(
+ void *img_src,
+ bool on);
+ int (*enum_strm_fmts)(
+ void *img_src,
+ u32 index,
+ struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+ int (*s_strm_fmt)(
+ void *img_src,
+ struct cif_isp10_strm_fmt *strm_fmt);
+ int (*g_ctrl)(
+ void *img_src,
+ int id,
+ int *val);
+ const char * (*g_name)(
+ void *img_src);
+ int (*s_ctrl)(
+ void *img_src,
+ int id,
+ int val);
+ int (*s_ext_ctrls)(
+ void *img_src,
+ struct cif_isp10_img_src_ext_ctrl *ctrl);
+ long (*ioctl)(
+ void *img_src,
+ unsigned int cmd,
+ void *arg);
+};
+
+const struct {
+ const char *device_type;
+ struct cif_isp10_img_src_ops ops;
+} cif_isp10_img_src_ops[] = {
+ {
+ .device_type = CIF_ISP10_IMG_SRC_V4L2_I2C_SUBDEV,
+ .ops = {
+ .to_img_src =
+ cif_isp10_img_src_v4l2_i2c_subdev_to_img_src,
+ .s_streaming =
+ cif_isp10_img_src_v4l2_subdev_s_streaming,
+ .s_power =
+ cif_isp10_img_src_v4l2_subdev_s_power,
+ .enum_strm_fmts =
+ cif_isp10_img_src_v4l2_subdev_enum_strm_fmts,
+ .s_strm_fmt =
+ cif_isp10_img_src_v4l2_subdev_s_strm_fmt,
+ .g_ctrl =
+ cif_isp10_img_src_v4l2_subdev_g_ctrl,
+ .g_name =
+ cif_isp10_img_src_v4l2_subdev_g_name,
+ .s_ctrl =
+ cif_isp10_img_src_v4l2_subdev_s_ctrl,
+ .s_ext_ctrls =
+ cif_isp10_img_src_v4l2_subdev_s_ext_ctrls,
+ .ioctl =
+ cif_isp10_img_src_v4l2_subdev_ioctl
+ }
+ },
+};
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <media/v4l2-subdev.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include "cif_isp10.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include <media/v4l2-controls_rockchip.h>
+#include <linux/slab.h>
+/* ===================== */
+/* Image Source */
+/* ===================== */
+void *cif_isp10_img_src_v4l2_i2c_subdev_to_img_src(
+ struct device *dev,
+ struct pltfrm_soc_cfg *soc_cfg)
+{
+ int ret = 0;
+ struct i2c_client *client;
+ struct v4l2_subdev *subdev;
+
+ client = i2c_verify_client(dev);
+ if (IS_ERR_OR_NULL(client)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "not an I2C device\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ subdev = i2c_get_clientdata(client);
+ if (IS_ERR_OR_NULL(subdev))
+ return subdev;
+
+ ret = v4l2_subdev_call(subdev,
+ core,
+ ioctl,
+ PLTFRM_CIFCAM_ATTACH,
+ (void *)soc_cfg);
+ if (ret != 0)
+ goto err;
+
+ return (void *)subdev;
+err:
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+ return ERR_PTR(ret);
+}
+
+static enum cif_isp10_pix_fmt img_src_v4l2_subdev_pix_fmt2cif_isp10_pix_fmt(
+ int img_src_pix_fmt)
+{
+ switch (img_src_pix_fmt) {
+ case MEDIA_BUS_FMT_YUYV8_1_5X8:
+ case MEDIA_BUS_FMT_YUYV8_2X8:
+ case MEDIA_BUS_FMT_YUYV10_2X10:
+ case MEDIA_BUS_FMT_YUYV8_1X16:
+ case MEDIA_BUS_FMT_YUYV10_1X20:
+ return CIF_YUV422I;
+ case MEDIA_BUS_FMT_UYVY8_1_5X8:
+ case MEDIA_BUS_FMT_UYVY8_2X8:
+ case MEDIA_BUS_FMT_UYVY8_1X16:
+ return CIF_UYV422I;
+ case MEDIA_BUS_FMT_RGB565_2X8_BE:
+ case MEDIA_BUS_FMT_RGB565_2X8_LE:
+ return CIF_RGB565;
+ case MEDIA_BUS_FMT_RGB666_1X18:
+ return CIF_RGB666;
+ case MEDIA_BUS_FMT_RGB888_1X24:
+ case MEDIA_BUS_FMT_RGB888_2X12_BE:
+ case MEDIA_BUS_FMT_RGB888_2X12_LE:
+ return CIF_RGB888;
+ case MEDIA_BUS_FMT_SBGGR8_1X8:
+ return CIF_BAYER_SBGGR8;
+ case MEDIA_BUS_FMT_SGBRG8_1X8:
+ return CIF_BAYER_SGBRG8;
+ case MEDIA_BUS_FMT_SGRBG8_1X8:
+ return CIF_BAYER_SGRBG8;
+ case MEDIA_BUS_FMT_SRGGB8_1X8:
+ return CIF_BAYER_SRGGB8;
+ case MEDIA_BUS_FMT_SBGGR10_ALAW8_1X8:
+ case MEDIA_BUS_FMT_SBGGR10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_BE:
+ case MEDIA_BUS_FMT_SBGGR10_2X8_PADHI_LE:
+ case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_BE:
+ case MEDIA_BUS_FMT_SBGGR10_2X8_PADLO_LE:
+ case MEDIA_BUS_FMT_SBGGR10_1X10:
+ return CIF_BAYER_SBGGR10;
+ case MEDIA_BUS_FMT_SGBRG10_ALAW8_1X8:
+ case MEDIA_BUS_FMT_SGBRG10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SGBRG10_1X10:
+ return CIF_BAYER_SGBRG10;
+ case MEDIA_BUS_FMT_SGRBG10_ALAW8_1X8:
+ case MEDIA_BUS_FMT_SGRBG10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SGRBG10_1X10:
+ return CIF_BAYER_SGRBG10;
+ case MEDIA_BUS_FMT_SRGGB10_ALAW8_1X8:
+ case MEDIA_BUS_FMT_SRGGB10_DPCM8_1X8:
+ case MEDIA_BUS_FMT_SRGGB10_1X10:
+ return CIF_BAYER_SRGGB10;
+ case MEDIA_BUS_FMT_SBGGR12_1X12:
+ return CIF_BAYER_SBGGR12;
+ case MEDIA_BUS_FMT_SGBRG12_1X12:
+ return CIF_BAYER_SGBRG12;
+ case MEDIA_BUS_FMT_SGRBG12_1X12:
+ return CIF_BAYER_SGRBG12;
+ case MEDIA_BUS_FMT_SRGGB12_1X12:
+ return CIF_BAYER_SRGGB12;
+ case MEDIA_BUS_FMT_JPEG_1X8:
+ return CIF_JPEG;
+ default:
+ return CIF_UNKNOWN_FORMAT;
+ }
+}
+
+static int cif_isp10_pix_fmt2img_src_v4l2_subdev_pix_fmt(
+ enum cif_isp10_pix_fmt cif_isp10_pix_fmt)
+{
+ switch (cif_isp10_pix_fmt) {
+ case CIF_YUV422I:
+ return MEDIA_BUS_FMT_YUYV8_2X8;
+ case CIF_UYV422I:
+ return MEDIA_BUS_FMT_UYVY8_2X8;
+ case CIF_RGB565:
+ return MEDIA_BUS_FMT_RGB565_2X8_LE;
+ case CIF_RGB666:
+ return MEDIA_BUS_FMT_RGB666_1X18;
+ case CIF_RGB888:
+ return MEDIA_BUS_FMT_RGB888_1X24;
+ case CIF_BAYER_SBGGR8:
+ return MEDIA_BUS_FMT_SBGGR8_1X8;
+ case CIF_BAYER_SGBRG8:
+ return MEDIA_BUS_FMT_SGBRG8_1X8;
+ case CIF_BAYER_SGRBG8:
+ return MEDIA_BUS_FMT_SGRBG8_1X8;
+ case CIF_BAYER_SRGGB8:
+ return MEDIA_BUS_FMT_SRGGB8_1X8;
+ case CIF_BAYER_SBGGR10:
+ return MEDIA_BUS_FMT_SBGGR10_1X10;
+ case CIF_BAYER_SGBRG10:
+ return MEDIA_BUS_FMT_SGBRG10_1X10;
+ case CIF_BAYER_SGRBG10:
+ return MEDIA_BUS_FMT_SGRBG10_1X10;
+ case CIF_BAYER_SRGGB10:
+ return MEDIA_BUS_FMT_SRGGB10_1X10;
+ case CIF_BAYER_SBGGR12:
+ return MEDIA_BUS_FMT_SBGGR12_1X12;
+ case CIF_BAYER_SGBRG12:
+ return MEDIA_BUS_FMT_SGBRG12_1X12;
+ case CIF_BAYER_SGRBG12:
+ return MEDIA_BUS_FMT_SGRBG12_1X12;
+ case CIF_BAYER_SRGGB12:
+ return MEDIA_BUS_FMT_SRGGB12_1X12;
+ case CIF_JPEG:
+ return MEDIA_BUS_FMT_JPEG_1X8;
+ default:
+ return -EINVAL;
+ }
+}
+
+static int cif_isp10_v4l2_cid2v4l2_cid(u32 cif_isp10_cid)
+{
+ switch (cif_isp10_cid) {
+ case CIF_ISP10_CID_FLASH_MODE:
+ return V4L2_CID_FLASH_LED_MODE;
+ case CIF_ISP10_CID_AUTO_GAIN:
+ return V4L2_CID_AUTOGAIN;
+ case CIF_ISP10_CID_AUTO_EXPOSURE:
+ return V4L2_EXPOSURE_AUTO;
+ case CIF_ISP10_CID_AUTO_WHITE_BALANCE:
+ return V4L2_CID_AUTO_WHITE_BALANCE;
+ case CIF_ISP10_CID_BLACK_LEVEL:
+ return V4L2_CID_BLACK_LEVEL;
+ case CIF_ISP10_CID_WB_TEMPERATURE:
+ return V4L2_CID_WHITE_BALANCE_TEMPERATURE;
+ case CIF_ISP10_CID_EXPOSURE_TIME:
+ return V4L2_CID_EXPOSURE;
+ case CIF_ISP10_CID_ANALOG_GAIN:
+ return V4L2_CID_GAIN;
+ case CIF_ISP10_CID_FOCUS_ABSOLUTE:
+ return V4L2_CID_FOCUS_ABSOLUTE;
+ case CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE:
+ return V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE;
+ case CIF_ISP10_CID_SCENE_MODE:
+ return V4L2_CID_SCENE_MODE;
+ case CIF_ISP10_CID_ISO_SENSITIVITY:
+ return V4L2_CID_ISO_SENSITIVITY;
+ case CIF_ISP10_CID_AUTO_FPS:
+ return RK_V4L2_CID_AUTO_FPS;
+ case CIF_ISP10_CID_VBLANKING:
+ return RK_V4L2_CID_VBLANKING;
+ case CIF_ISP10_CID_HFLIP:
+ return V4L2_CID_HFLIP;
+ case CIF_ISP10_CID_VFLIP:
+ return V4L2_CID_VFLIP;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported CIF ISP20 ID %d\n",
+ cif_isp10_cid);
+ break;
+ }
+ return -EINVAL;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_streaming(
+ void *img_src,
+ bool enable)
+{
+ struct v4l2_subdev *subdev = img_src;
+
+ if (enable)
+ return v4l2_subdev_call(subdev, video, s_stream, 1);
+ else
+ return v4l2_subdev_call(subdev, video, s_stream, 0);
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_power(
+ void *img_src,
+ bool on)
+{
+ struct v4l2_subdev *subdev = img_src;
+
+ if (on)
+ return v4l2_subdev_call(subdev, core, s_power, 1);
+ else
+ return v4l2_subdev_call(subdev, core, s_power, 0);
+}
+
+int cif_isp10_img_src_v4l2_subdev_enum_strm_fmts(
+ void *img_src,
+ u32 index,
+ struct cif_isp10_strm_fmt_desc *strm_fmt_desc)
+{
+ int ret;
+ struct v4l2_subdev *subdev = img_src;
+ struct v4l2_subdev_frame_interval_enum fie = {.index = index};
+ struct pltfrm_cam_defrect defrect;
+ v4l2_std_id std;
+
+ ret = v4l2_subdev_call(subdev, video, querystd, &std);
+ if (!IS_ERR_VALUE(ret))
+ strm_fmt_desc->std_id = std;
+ else
+ strm_fmt_desc->std_id = 0;
+
+ ret = v4l2_subdev_call(subdev, pad,
+ enum_frame_interval, NULL, &fie);
+ if (!IS_ERR_VALUE(ret)) {
+ strm_fmt_desc->discrete_intrvl = true;
+ strm_fmt_desc->min_intrvl.numerator =
+ fie.interval.numerator;
+ strm_fmt_desc->min_intrvl.denominator =
+ fie.interval.denominator;
+ strm_fmt_desc->discrete_frmsize = true;
+ strm_fmt_desc->min_frmsize.width = fie.width;
+ strm_fmt_desc->min_frmsize.height = fie.height;
+ strm_fmt_desc->pix_fmt =
+ img_src_v4l2_subdev_pix_fmt2cif_isp10_pix_fmt(
+ fie.code);
+
+ defrect.width = fie.width;
+ defrect.height = fie.height;
+ memset(&defrect, 0x00, sizeof(struct v4l2_rect));
+ v4l2_subdev_call(subdev,
+ core,
+ ioctl,
+ PLTFRM_CIFCAM_G_DEFRECT,
+ (void *)&defrect);
+ if ((defrect.defrect.width == 0) ||
+ (defrect.defrect.height == 0)) {
+ strm_fmt_desc->defrect.left = 0;
+ strm_fmt_desc->defrect.top = 0;
+ strm_fmt_desc->defrect.width = fie.width;
+ strm_fmt_desc->defrect.height = fie.height;
+ } else {
+ strm_fmt_desc->defrect = defrect.defrect;
+ }
+ }
+
+ return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_strm_fmt(
+ void *img_src,
+ struct cif_isp10_strm_fmt *strm_fmt)
+{
+ int ret = 0;
+ struct v4l2_subdev *subdev = img_src;
+ struct v4l2_subdev_format format;
+ struct v4l2_subdev_frame_interval intrvl;
+
+ format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
+ format.format.code = cif_isp10_pix_fmt2img_src_v4l2_subdev_pix_fmt(
+ strm_fmt->frm_fmt.pix_fmt);
+ format.format.width = strm_fmt->frm_fmt.width;
+ format.format.height = strm_fmt->frm_fmt.height;
+ ret = v4l2_subdev_call(subdev, pad, set_fmt, NULL, &format);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ intrvl.interval.numerator = strm_fmt->frm_intrvl.numerator;
+ intrvl.interval.denominator = strm_fmt->frm_intrvl.denominator;
+ ret = v4l2_subdev_call(subdev, video, s_frame_interval, &intrvl);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ return 0;
+err:
+ pr_err("img_src.%s ERR: failed with error %d\n", __func__, ret);
+ return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_g_ctrl(
+ void *img_src,
+ int id,
+ int *val)
+{
+ struct v4l2_control ctrl;
+ int ret;
+ struct v4l2_subdev *subdev = img_src;
+
+ ctrl.id = cif_isp10_v4l2_cid2v4l2_cid(id);
+
+ if (IS_ERR_VALUE(ctrl.id))
+ return (int)ctrl.id;
+
+ ret = v4l2_subdev_call(subdev, core, g_ctrl, &ctrl);
+ if (!IS_ERR_VALUE(ret)) {
+ if (id == CIF_ISP10_CID_FLASH_MODE) {
+ if (ctrl.value == V4L2_FLASH_LED_MODE_NONE) {
+ ctrl.value = CIF_ISP10_FLASH_MODE_OFF;
+ } else if (ctrl.value == V4L2_FLASH_LED_MODE_FLASH) {
+ ctrl.value = CIF_ISP10_FLASH_MODE_FLASH;
+ } else if (ctrl.value == V4L2_FLASH_LED_MODE_TORCH) {
+ ctrl.value = CIF_ISP10_FLASH_MODE_TORCH;
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported value %d for control ID 0x%x\n",
+ ctrl.value, id);
+ return -EINVAL;
+ }
+ }
+ *val = ctrl.value;
+ }
+ return ret;
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_ctrl(
+ void *img_src,
+ int id,
+ int val)
+{
+ struct v4l2_control ctrl;
+ struct v4l2_subdev *subdev = img_src;
+
+ ctrl.value = val;
+ ctrl.id = cif_isp10_v4l2_cid2v4l2_cid(id);
+
+ if (IS_ERR_VALUE(ctrl.id)) {
+ return (int)ctrl.id;
+ } else if (id == CIF_ISP10_CID_FLASH_MODE) {
+ if (val == CIF_ISP10_FLASH_MODE_OFF) {
+ ctrl.value = V4L2_FLASH_LED_MODE_NONE;
+ } else if (val == CIF_ISP10_FLASH_MODE_FLASH) {
+ ctrl.value = V4L2_FLASH_LED_MODE_FLASH;
+ } else if (val == CIF_ISP10_FLASH_MODE_TORCH) {
+ ctrl.value = V4L2_FLASH_LED_MODE_TORCH;
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported value %d for control ID %d\n",
+ val, id);
+ return -EINVAL;
+ }
+ }
+ return v4l2_subdev_call(subdev, core, s_ctrl, &ctrl);
+}
+
+const char *cif_isp10_img_src_v4l2_subdev_g_name(
+ void *img_src)
+{
+ struct v4l2_subdev *subdev = img_src;
+
+ return dev_driver_string(subdev->dev);
+}
+
+int cif_isp10_img_src_v4l2_subdev_s_ext_ctrls(
+ void *img_src,
+ struct cif_isp10_img_src_ext_ctrl *ctrl)
+{
+ struct v4l2_ext_controls ctrls;
+ struct v4l2_ext_control *controls;
+ int i;
+ int ret;
+ struct v4l2_subdev *subdev = img_src;
+
+ if (ctrl->cnt == 0)
+ return -EINVAL;
+
+ controls = kmalloc_array(ctrl->cnt, sizeof(struct v4l2_ext_control),
+ GFP_KERNEL);
+
+ if (!controls)
+ return -ENOMEM;
+
+ for (i = 0; i < ctrl->cnt; i++) {
+ controls[i].id = ctrl->ctrls[i].id;
+ controls[i].value = ctrl->ctrls[i].val;
+ }
+
+ ctrls.count = ctrl->cnt;
+ ctrls.controls = controls;
+ /*
+ * current kernel version don't define
+ * this member for struct v4l2_ext_control.
+ */
+ /* ctrls.ctrl_class = ctrl->class; */
+ ctrls.reserved[0] = 0;
+ ctrls.reserved[1] = 0;
+
+ ret = v4l2_subdev_call(subdev,
+ core, s_ext_ctrls, &ctrls);
+
+ kfree(controls);
+
+ return ret;
+}
+
+long cif_isp10_img_src_v4l2_subdev_ioctl(
+ void *img_src,
+ unsigned int cmd,
+ void *arg)
+{
+ struct v4l2_subdev *subdev = img_src;
+ long ret = -EINVAL;
+
+ switch (cmd) {
+ case RK_VIDIOC_SENSOR_MODE_DATA:
+ case RK_VIDIOC_CAMERA_MODULEINFO:
+
+ case PLTFRM_CIFCAM_G_ITF_CFG:
+ case PLTFRM_CIFCAM_G_DEFRECT:
+ case PLTFRM_CIFCAM_ATTACH:
+ ret = v4l2_subdev_call(subdev,
+ core,
+ ioctl,
+ cmd,
+ arg);
+
+ break;
+ default:
+ break;
+ }
+
+ if (IS_ERR_VALUE(ret))
+ pr_err("img_src.%s subdev call(cmd: 0x%x) failed with error %ld\n",
+ __func__, cmd, ret);
+
+ return ret;
+}
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_IMG_SRC_V4L2_SUBDEV_H
+#define _CIF_ISP10_IMG_SRC_V4L2_SUBDEV_H
+
+#define CIF_ISP10_IMG_SRC_V4L2_I2C_SUBDEV "v4l2-i2c-subdev"
+
+void *cif_isp10_img_src_v4l2_i2c_subdev_to_img_src(
+ struct device *dev,
+ struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_img_src_v4l2_subdev_s_streaming(
+ void *img_src,
+ bool enable);
+
+int cif_isp10_img_src_v4l2_subdev_s_power(
+ void *img_src,
+ bool on);
+
+int cif_isp10_img_src_v4l2_subdev_enum_strm_fmts(
+ void *img_src,
+ u32 index,
+ struct cif_isp10_strm_fmt_desc *strm_fmt_desc);
+
+int cif_isp10_img_src_v4l2_subdev_s_strm_fmt(
+ void *img_src,
+ struct cif_isp10_strm_fmt *strm_fmt);
+
+int cif_isp10_img_src_v4l2_subdev_g_ctrl(
+ void *img_src,
+ int id,
+ int *val);
+
+int cif_isp10_img_src_v4l2_subdev_s_ctrl(
+ void *img_src,
+ int id,
+ int val);
+
+const char *cif_isp10_img_src_v4l2_subdev_g_name(
+ void *img_src);
+
+int cif_isp10_img_src_v4l2_subdev_s_ext_ctrls(
+ void *img_src,
+ struct cif_isp10_img_src_ext_ctrl *ctrl);
+
+long cif_isp10_img_src_v4l2_subdev_ioctl(
+ void *img_src,
+ unsigned int cmd,
+ void *arg);
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/types.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <linux/videodev2.h>
+#include <media/videobuf-core.h>
+#include <media/videobuf-vmalloc.h> /* for ISP statistics */
+#include <linux/io.h>
+#include <linux/wait.h>
+#include <linux/sched.h>
+#include <linux/workqueue.h>
+#include "cif_isp10_regs.h"
+#include "cif_isp10_isp.h"
+#include "cif_isp10_pltfrm.h"
+#include "cif_isp10.h"
+
+#define _GET_ 0
+#define _SET_ 1
+#define CIFISP_MODULE_EN(v, m) ((v) |= (m))
+#define CIFISP_MODULE_DIS(v, m) ((v) &= ~(m))
+#define CIFISP_MODULE_IS_EN(v, m) (((v) & (m)) == (m))
+#define CIFISP_MODULE_UPDATE(v, m) ((v) |= (m))
+#define CIFISP_MODULE_CLR_UPDATE(v, m) ((v) &= ~(m))
+#define CIFISP_MODULE_IS_UPDATE(v, m) (((v) & (m)) == (m))
+
+/* Demosaic */
+#define CIFISP_BDM_BYPASS_EN(val) ((val) << 10)
+/* HIST */
+#define CIFISP_HIST_PREDIV_SET(val) ((val) << 3)
+#define CIFISP_HIST_WEIGHT_SET(v0, v1, v2, v3) ((v0) | ((v1) << 8) |\
+ ((v2) << 16) | ((v3) << 24))
+#define CIFISP_HIST_WINDOW_OFFSET_RESERVED (0xFFFFF000)
+#define CIFISP_HIST_WINDOW_SIZE_RESERVED (0xFFFFF800)
+#define CIFISP_HIST_WEIGHT_RESERVED (0xE0E0E0E0)
+#define CIFISP_MAX_HIST_PREDIVIDER (0x0000007F)
+#define CIFISP_HIST_ROW_NUM (5)
+#define CIFISP_HIST_COLUMN_NUM (5)
+/* ISP Ctrl */
+#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA BIT(6)
+#define CIF_ISP_CTRL_ISP_AWB_ENA BIT(7)
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA BIT(11)
+/* AWB */
+#define CIFISP_AWB_GAIN_R_SET(val) ((val) << 16)
+#define CIFISP_AWB_GAIN_R_READ(val) ((val) >> 16)
+#define CIFISP_AWB_GAIN_B_READ(val) ((val) & 0xFFFF)
+
+#define CIFISP_AWB_YMAX_CMP_EN BIT(2)
+#define CIFISP_AWB_REF_CR_SET(val) ((val) << 8)
+#define CIFISP_AWB_REF_CR_READ(val) ((val) >> 8)
+#define CIFISP_AWB_REF_CB_READ(val) ((val) & 0xFF)
+#define CIFISP_AWB_MAX_CS_SET(val) ((val) << 8)
+#define CIFISP_AWB_MAX_CS_READ(val) (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_MIN_C_READ(val) ((val) & 0xFF)
+#define CIFISP_AWB_MIN_Y_SET(val) ((val) << 16)
+#define CIFISP_AWB_MIN_Y_READ(val) (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_MAX_Y_SET(val) ((val) << 24)
+#define CIFISP_AWB_MAX_Y_READ(val) ((val) >> 24)
+#define CIFISP_AWB_MODE_RGB_EN ((1 << 31) | (0x02 << 0))
+#define CIFISP_AWB_MODE_YCBCR_EN ((0 << 31) | (0x02 << 0))
+#define CIFISP_AWB_MODE_READ(val) ((val) & 3)
+#define CIFISP_AWB_YMAX_READ(val) (((val) >> 2) & 1)
+
+#define CIFISP_AWB_GET_MEAN_CR(val) ((val) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_CB(val) (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_Y(val) (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_R(val) ((val) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_B(val) (((val) >> 8) & 0xFF)
+#define CIFISP_AWB_GET_MEAN_G(val) (((val) >> 16) & 0xFF)
+#define CIFISP_AWB_GET_PIXEL_CNT(val) ((val) & 0x3FFFFFF)
+
+#define CIFISP_AWB_GAINS_MAX_VAL (0x000003FF)
+#define CIFISP_AWB_WINDOW_OFFSET_MAX (0x00000FFF)
+#define CIFISP_AWB_WINDOW_MAX_SIZE (0x00001FFF)
+#define CIFISP_AWB_CBCR_MAX_REF (0x000000FF)
+#define CIFISP_AWB_THRES_MAX_YC (0x000000FF)
+/* AE */
+#define CIFISP_EXP_ENA (1)
+#define CIFISP_EXP_DIS (0)
+#define CIFISP_EXP_ROW_NUM (5)
+#define CIFISP_EXP_COLUMN_NUM (5)
+#define CIFISP_EXP_NUM_LUMA_REGS (CIFISP_EXP_ROW_NUM *\
+ CIFISP_EXP_COLUMN_NUM)
+#define CIFISP_EXP_MAX_HOFFS (2424)
+#define CIFISP_EXP_MAX_VOFFS (1806)
+#define CIFISP_EXP_BLOCK_MAX_HSIZE (516)
+#define CIFISP_EXP_BLOCK_MIN_HSIZE (35)
+#define CIFISP_EXP_BLOCK_MAX_VSIZE (390)
+#define CIFISP_EXP_BLOCK_MIN_VSIZE (28)
+#define CIFISP_EXP_MAX_HSIZE \
+ (CIFISP_EXP_BLOCK_MAX_HSIZE * CIFISP_EXP_COLUMN_NUM + 1)
+#define CIFISP_EXP_MIN_HSIZE \
+ (CIFISP_EXP_BLOCK_MIN_HSIZE * CIFISP_EXP_COLUMN_NUM + 1)
+#define CIFISP_EXP_MAX_VSIZE \
+ (CIFISP_EXP_BLOCK_MAX_VSIZE * CIFISP_EXP_ROW_NUM + 1)
+#define CIFISP_EXP_MIN_VSIZE \
+ (CIFISP_EXP_BLOCK_MIN_VSIZE * CIFISP_EXP_ROW_NUM + 1)
+#define CIFISP_EXP_HEIGHT_MASK (0x000007FF)
+#define CIFISP_EXP_MAX_HOFFSET (0x00000FFF)
+#define CIFISP_EXP_MAX_VOFFSET (0x00000FFF)
+
+#define CIFISP_EXP_CTRL_AUTOSTOP(val) ((val) << 1)
+#define CIFISP_EXP_CTRL_MEASMODE(val) ((val) << 31)
+#define CIFISP_EXP_HSIZE(val) ((val) & 0x7FF)
+#define CIFISP_EXP_VSIZE(val) ((val) & 0x7FE)
+/* LSC */
+#define CIFISP_LSC_GRADH_SET(val) ((val) << 11)
+#define CIFISP_LSC_SECTH_SET(val) ((val) << 10)
+
+/* FLT */
+#define CIFISP_FLT_MODE_MAX (1)
+#define CIFISP_FLT_CHROMA_MODE_MAX (3)
+#define CIFISP_FLT_GREEN_STAGE1_MAX (8)
+#define CIFISP_FLT_MODE(v) ((v) << 1)
+#define CIFISP_FLT_CHROMA_V_MODE(v) ((v) << 4)
+#define CIFISP_FLT_CHROMA_H_MODE(v) ((v) << 6)
+#define CIFISP_FLT_GREEN_STAGE1(v) ((v) << 8)
+#define CIFISP_FLT_THREAD_RESERVED (0xfffffc00)
+#define CIFISP_FLT_FAC_RESERVED (0xffffffc0)
+#define CIFISP_FLT_LUM_WEIGHT_RESERVED (0xfff80000)
+#define CIFISP_FLT_ENA (1)
+#define CIFISP_FLT_DIS (0)
+
+#define CIFISP_CTK_COEFF_RESERVED 0xFFFFF800
+#define CIFISP_XTALK_OFFSET_RESERVED 0xFFFFF000
+
+/* GOC */
+#define CIFISP_GOC_MODE_MAX (1)
+#define CIFISP_GOC_RESERVED 0xFFFFF800
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA_READ(value) (((value) >> 11) & 1)
+/* DPCC */
+#define CIFISP_DPCC_ENA BIT(0)
+#define CIFISP_DPCC_DIS (0 << 0)
+#define CIFISP_DPCC_MODE_MAX (0x07)
+#define CIFISP_DPCC_OUTPUTMODE_MAX (0x0f)
+#define CIFISP_DPCC_SETUSE_MAX (0x0f)
+#define CIFISP_DPCC_METHODS_SET_RESERVED (0xFFFFE000)
+#define CIFISP_DPCC_LINE_THRESH_RESERVED (0xFFFF0000)
+#define CIFISP_DPCC_LINE_MAD_FAC_RESERVED (0xFFFFC0C0)
+#define CIFISP_DPCC_PG_FAC_RESERVED (0xFFFFC0C0)
+#define CIFISP_DPCC_RND_THRESH_RESERVED (0xFFFF0000)
+#define CIFISP_DPCC_RG_FAC_RESERVED (0xFFFFC0C0)
+#define CIFISP_DPCC_RO_LIMIT_RESERVED (0xFFFFF000)
+#define CIFISP_DPCC_RND_OFFS_RESERVED (0xFFFFF000)
+/* BLS */
+#define CIFISP_BLS_ENA BIT(0)
+#define CIFISP_BLS_DIS (0 << 0)
+#define CIFISP_BLS_MODE_MEASURED BIT(1)
+#define CIFISP_BLS_MODE_FIXED (0 << 1)
+#define CIFISP_BLS_WINDOW_1 BIT(2)
+#define CIFISP_BLS_WINDOW_2 BIT(3)
+/* GAMMA-IN */
+#define CIFISP_DEGAMMA_X_RESERVED \
+ ((1 << 31) | (1 << 27) | (1 << 23) | (1 << 19) |\
+ (1 << 15) | (1 << 11) | (1 << 7) | (1 << 3))
+#define CIFISP_DEGAMMA_Y_RESERVED 0xFFFFF000
+/*CPROC*/
+#define CIFISP_CPROC_CTRL_RESERVED 0xFFFFFFFE
+#define CIFISP_CPROC_CONTRAST_RESERVED 0xFFFFFF00
+#define CIFISP_CPROC_BRIGHTNESS_RESERVED 0xFFFFFF00
+#define CIFISP_CPROC_HUE_RESERVED 0xFFFFFF00
+#define CIFISP_CPROC_SATURATION_RESERVED 0xFFFFFF00
+#define CIFISP_CPROC_MACC_RESERVED 0xE000E000
+#define CIFISP_CPROC_TONE_RESERVED 0xF000
+#define CIFISP_CPROC_TONE_Y(value) ((value) << 16)
+#define CIFISP_CPROC_TONE_C(value) ((value))
+#define CIFISP_CPROC_TONE_Y_READ(value) ((value) >> 16)
+#define CIFISP_CPROC_TONE_C_READ(value) ((value) & 0xFFFF)
+#define CIFISP_CPROC_EN 1
+#define CIFISP_CPROC_MACC_EN BIT(4)
+#define CIFISP_CPROC_TMAP_EN BIT(5)
+/* LSC */
+#define CIFISP_LSC_SECT_SIZE_RESERVED 0xFC00FC00
+#define CIFISP_LSC_GRAD_RESERVED 0xF000F000
+#define CIFISP_LSC_SAMPLE_RESERVED 0xF000F000
+#define CIFISP_LSC_SECTORS_MAX 16
+#define CIFISP_LSC_TABLE_DATA(v0, v1) (v0 | ((v1) << 12))
+#define CIFISP_LSC_SECT_SIZE(v0, v1) (v0 | ((v1) << 16))
+#define CIFISP_LSC_GRAD_SIZE(v0, v1) (v0 | ((v1) << 16))
+/* AFC */
+#define CIFISP_AFC_THRES_RESERVED 0xFFFF0000
+#define CIFISP_AFC_VAR_SHIFT_RESERVED 0xFFF8FFF8
+#define CIFISP_AFC_WINDOW_X_RESERVED 0xE000
+#define CIFISP_AFC_WINDOW_Y_RESERVED 0xF000
+#define CIFISP_AFC_WINDOW_X_MIN 0x5
+#define CIFISP_AFC_WINDOW_Y_MIN 0x2
+#define CIFISP_AFC_WINDOW_X(value) ((value) << 16)
+#define CIFISP_AFC_WINDOW_Y(value) (value)
+#define CIFISP_AFC_ENA (1)
+#define CIFISP_AFC_DIS (0)
+
+/* DPF */
+#define CIFISP_DPF_NF_GAIN_RESERVED 0xFFFFF000
+#define CIFISP_DPF_SPATIAL_COEFF_MAX 0x1f
+#define CIFISP_DPF_NLL_COEFF_N_MAX 0x3ff
+
+#define CIFISP_DPF_MODE_USE_NF_GAIN BIT(9)
+#define CIFISP_DPF_MODE_LSC_GAIN_COMP BIT(8)
+#define CIFISP_DPF_MODE_AWB_GAIN_COMP BIT(7)
+#define CIFISP_DPF_MODE_NLL_SEGMENTATION(a) ((a) << 6)
+#define CIFISP_DPF_MODE_RB_FLTSIZE(a) ((a) << 5)
+#define CIFISP_DPF_MODE_R_FLT_DIS BIT(4)
+#define CIFISP_DPF_MODE_R_FLT_EN (0 << 4)
+#define CIFISP_DPF_MODE_GR_FLT_DIS BIT(3)
+#define CIFISP_DPF_MODE_GR_FLT_EN (0 << 3)
+#define CIFISP_DPF_MODE_GB_FLT_DIS BIT(2)
+#define CIFISP_DPF_MODE_GB_FLT_EN (0 << 2)
+#define CIFISP_DPF_MODE_B_FLT_DIS BIT(1)
+#define CIFISP_DPF_MODE_B_FLT_EN (0 << 1)
+#define CIFISP_DPF_MODE_EN BIT(0)
+
+#define CIFISP_DEBUG BIT(0)
+#define CIFISP_ERROR BIT(1)
+
+/*
+ * Empirical rough (relative) times it takes to perform
+ * given function.
+ */
+#define CIFISP_MODULE_DPCC_PROC_TIME 3
+#define CIFISP_MODULE_BLS_PROC_TIME 10
+#define CIFISP_MODULE_LSC_PROC_TIME 1747
+#define CIFISP_MODULE_FLT_PROC_TIME 15
+#define CIFISP_MODULE_BDM_PROC_TIME 1
+#define CIFISP_MODULE_SDG_PROC_TIME 53
+#define CIFISP_MODULE_GOC_PROC_TIME 1000
+#define CIFISP_MODULE_CTK_PROC_TIME 772
+#define CIFISP_MODULE_AWB_PROC_TIME 8
+#define CIFISP_MODULE_HST_PROC_TIME 5
+#define CIFISP_MODULE_AEC_PROC_TIME 5
+#define CIFISP_MODULE_AWB_GAIN_PROC_TIME 2
+#define CIFISP_MODULE_CPROC_PROC_TIME 5
+#define CIFISP_MODULE_AFC_PROC_TIME 8
+#define CIFISP_MODULE_IE_PROC_TIME 5
+#define CIFISP_MODULE_DPF_TIME 5
+#define CIFISP_MODULE_DPF_STRENGTH_TIME 2
+#define CIFISP_MODULE_CSM_PROC_TIME 8
+
+/* For Debugging only!!! */
+
+#define CIFISP_MODULE_DEFAULT_VBLANKING_TIME 2000
+
+#define V4L2_DEV_DEBUG_LEVEL 0
+
+#define CIFISP_DPRINT(level, fmt, arg...) \
+ do { \
+ if (level == CIFISP_ERROR) \
+ pr_err(fmt, ##arg); \
+ else \
+ pr_debug(fmt, ##arg); \
+ } while (0)
+
+#define cifisp_iowrite32(d, a) \
+ cif_isp10_pltfrm_write_reg(NULL, (u32)(d), isp_dev->base_addr + (a))
+#define cifisp_ioread32(a) \
+ cif_isp10_pltfrm_read_reg(NULL, isp_dev->base_addr + (a))
+#define cifisp_iowrite32OR(d, a) \
+ cif_isp10_pltfrm_write_reg_OR(NULL, (u32)(d), isp_dev->base_addr + (a))
+#define cifisp_iowrite32AND(d, a) \
+ cif_isp10_pltfrm_write_reg_AND(NULL, (u32)(d), isp_dev->base_addr + (a))
+
+/*
+ * Set this flag to enable CIF ISP Register debug
+ * #define CIFISP_DEBUG_REG
+ */
+/*
+ * Set this flag to dump the parameters
+ * #define CIFISP_DEBUG_PARAM
+ */
+/*
+ * Set this flag to trace the capture params
+ * #define LOG_CAPTURE_PARAMS
+ */
+/*
+ * Set this flag to trace the isr execution time
+ * #define LOG_ISR_EXE_TIME
+ */
+/*
+ * Set this flag to exclude everything except
+ * measurements
+ * #define CIFISP_DEBUG_DISABLE_BLOCKS
+ */
+
+#ifdef LOG_CAPTURE_PARAMS
+static struct cifisp_last_capture_config g_last_capture_config;
+#endif
+
+#ifdef LOG_ISR_EXE_TIME
+static unsigned int g_longest_isr_time;
+#endif
+
+/* Functions for Debugging */
+static void cifisp_param_dump(const void *config, unsigned int module);
+#ifdef CIFISP_DEBUG_REG
+static void cifisp_reg_dump(const struct cif_isp10_isp_dev *isp_dev,
+ unsigned int module, int level);
+#endif
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_reg_dump_capture(const struct cif_isp10_isp_dev *isp_dev);
+#endif
+
+static int cifisp_module_enable(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, __s32 *value, unsigned int module)
+{
+ unsigned int *curr_ens, *updates, *new_ens;
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (module & (CIFISP_MODULE_AWB |
+ CIFISP_MODULE_AEC |
+ CIFISP_MODULE_AFC |
+ CIFISP_MODULE_HST)) {
+ curr_ens = &isp_dev->meas_cfgs.curr->module_ens;
+ new_ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+ updates = &isp_dev->meas_cfgs.module_updates;
+ } else {
+ curr_ens = &isp_dev->other_cfgs.curr->module_ens;
+ new_ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+ updates = &isp_dev->other_cfgs.module_updates;
+ }
+
+ if (flag == _GET_) {
+ *value = CIFISP_MODULE_IS_EN(*curr_ens, module);
+ goto end;
+ }
+
+ if (CIFISP_MODULE_IS_EN(*curr_ens, module) != *value) {
+ if (*value)
+ CIFISP_MODULE_EN(*new_ens, module);
+ else
+ CIFISP_MODULE_DIS(*new_ens, module);
+
+ CIFISP_MODULE_UPDATE(*updates, module);
+ }
+
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP BP interface function */
+static int cifisp_dpcc_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_dpcc_config *arg)
+{
+ unsigned long lock_flags = 0;
+ unsigned int i;
+ struct cifisp_dpcc_methods_config *method;
+ int retval = 0;
+
+ if (!arg) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "arg is NULL: %s\n", __func__);
+
+ return -EINVAL;
+ }
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->dpcc_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_DPCC);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->dpcc_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->mode > CIFISP_DPCC_MODE_MAX ||
+ arg->output_mode > CIFISP_DPCC_OUTPUTMODE_MAX ||
+ arg->set_use > CIFISP_DPCC_SETUSE_MAX ||
+ arg->ro_limits & CIFISP_DPCC_RO_LIMIT_RESERVED ||
+ arg->rnd_offs & CIFISP_DPCC_RND_OFFS_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ method = &arg->methods[i];
+ for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
+ if ((method->method &
+ CIFISP_DPCC_METHODS_SET_RESERVED) ||
+ (method->line_thresh &
+ CIFISP_DPCC_LINE_THRESH_RESERVED) ||
+ (method->line_mad_fac &
+ CIFISP_DPCC_LINE_MAD_FAC_RESERVED) ||
+ (method->pg_fac &
+ CIFISP_DPCC_PG_FAC_RESERVED) ||
+ (method->rnd_thresh &
+ CIFISP_DPCC_RND_THRESH_RESERVED) ||
+ (method->rg_fac & CIFISP_DPCC_RG_FAC_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ method++;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->dpcc_config,
+ arg,
+ sizeof(struct cifisp_dpcc_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPCC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP black level subtraction interface function */
+static int cifisp_bls_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_bls_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->bls_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_BLS);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->bls_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->bls_window1.h_offs > CIFISP_BLS_START_H_MAX ||
+ arg->bls_window1.h_size > CIFISP_BLS_STOP_H_MAX ||
+ arg->bls_window1.v_offs > CIFISP_BLS_START_V_MAX ||
+ arg->bls_window1.v_size > CIFISP_BLS_STOP_V_MAX ||
+ arg->bls_window2.h_offs > CIFISP_BLS_START_H_MAX ||
+ arg->bls_window2.h_size > CIFISP_BLS_STOP_H_MAX ||
+ arg->bls_window2.v_offs > CIFISP_BLS_START_V_MAX ||
+ arg->bls_window2.v_size > CIFISP_BLS_STOP_V_MAX ||
+ arg->bls_samples > CIFISP_BLS_SAMPLES_MAX ||
+ arg->fixed_val.r > CIFISP_BLS_FIX_SUB_MAX ||
+ arg->fixed_val.gr > CIFISP_BLS_FIX_SUB_MAX ||
+ arg->fixed_val.gb > CIFISP_BLS_FIX_SUB_MAX ||
+ arg->fixed_val.b > CIFISP_BLS_FIX_SUB_MAX ||
+ arg->fixed_val.r < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+ arg->fixed_val.gr < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+ arg->fixed_val.gb < (s16)CIFISP_BLS_FIX_SUB_MIN ||
+ arg->fixed_val.b < (s16)CIFISP_BLS_FIX_SUB_MIN) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->bls_config,
+ arg,
+ sizeof(struct cifisp_bls_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BLS);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP LS correction interface function */
+static int cifisp_lsc_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_lsc_config *arg)
+{
+ int i;
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->lsc_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_LSC);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->lsc_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ for (i = 0; i < CIFISP_LSC_SIZE_TBL_SIZE; i++) {
+ if ((*(arg->x_size_tbl + i) & CIFISP_LSC_SECT_SIZE_RESERVED) ||
+ (*(arg->y_size_tbl + i) & CIFISP_LSC_SECT_SIZE_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible sect size x 0x%x y 0x%x in function: %s\n",
+ *(arg->x_size_tbl + i),
+ *(arg->y_size_tbl + i), __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ for (i = 0; i < CIFISP_LSC_GRAD_TBL_SIZE; i++) {
+ if ((*(arg->x_grad_tbl + i) & CIFISP_LSC_GRAD_RESERVED) ||
+ (*(arg->y_grad_tbl + i) & CIFISP_LSC_GRAD_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible grad x 0x%x y 0x%xin function: %s\n",
+ *(arg->x_grad_tbl + i),
+ *(arg->y_grad_tbl + i), __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ for (i = 0; i < CIFISP_LSC_DATA_TBL_SIZE; i++) {
+ if ((*(arg->r_data_tbl + i) &
+ CIFISP_LSC_SAMPLE_RESERVED) ||
+ (*(arg->gr_data_tbl + i) &
+ CIFISP_LSC_SAMPLE_RESERVED) ||
+ (*(arg->gb_data_tbl + i) &
+ CIFISP_LSC_SAMPLE_RESERVED) ||
+ (*(arg->b_data_tbl + i) &
+ CIFISP_LSC_SAMPLE_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible sample r 0x%x gr 0x%x gb 0x%x b 0x%x in function: %s\n",
+ *(arg->r_data_tbl + i),
+ *(arg->gr_data_tbl + i),
+ *(arg->gb_data_tbl + i),
+ *(arg->b_data_tbl + i), __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->lsc_config,
+ arg,
+ sizeof(struct cifisp_lsc_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_LSC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP Filtering function */
+static int cifisp_flt_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_flt_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->flt_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_FLT);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->flt_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ /* Parameter check */
+ if (arg->mode > CIFISP_FLT_MODE_MAX ||
+ arg->grn_stage1 > CIFISP_FLT_GREEN_STAGE1_MAX ||
+ arg->chr_v_mode > CIFISP_FLT_CHROMA_MODE_MAX ||
+ arg->chr_h_mode > CIFISP_FLT_CHROMA_MODE_MAX ||
+ arg->thresh_sh0 & CIFISP_FLT_THREAD_RESERVED ||
+ arg->thresh_sh1 & CIFISP_FLT_THREAD_RESERVED ||
+ arg->thresh_bl0 & CIFISP_FLT_THREAD_RESERVED ||
+ arg->thresh_bl1 & CIFISP_FLT_THREAD_RESERVED ||
+ arg->fac_bl0 & CIFISP_FLT_FAC_RESERVED ||
+ arg->fac_bl1 & CIFISP_FLT_FAC_RESERVED ||
+ arg->fac_sh0 & CIFISP_FLT_FAC_RESERVED ||
+ arg->fac_sh1 & CIFISP_FLT_FAC_RESERVED ||
+ arg->fac_mid & CIFISP_FLT_FAC_RESERVED ||
+ arg->lum_weight & CIFISP_FLT_LUM_WEIGHT_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->flt_config,
+ arg,
+ sizeof(struct cifisp_flt_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_FLT);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP demosaic interface function */
+static int cifisp_bdm_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_bdm_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->bdm_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_BDM);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->bdm_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->bdm_config,
+ arg,
+ sizeof(struct cifisp_bdm_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BDM);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP GAMMA correction interface function */
+static int cifisp_sdg_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_sdg_config *arg)
+{
+ unsigned long lock_flags = 0;
+ unsigned int i;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->sdg_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_SDG);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->sdg_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->xa_pnts.gamma_dx0 & CIFISP_DEGAMMA_X_RESERVED ||
+ arg->xa_pnts.gamma_dx1 & CIFISP_DEGAMMA_X_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+ if ((arg->curve_b.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED) ||
+ (arg->curve_r.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED) ||
+ (arg->curve_g.gamma_y[i] & CIFISP_DEGAMMA_Y_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->sdg_config,
+ arg,
+ sizeof(struct cifisp_sdg_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_SDG);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP GAMMA correction interface function */
+static int cifisp_goc_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_goc_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->goc_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_GOC);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->goc_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->mode > CIFISP_GOC_MODE_MAX) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param 0x%x in function: %s\n",
+ arg->mode, __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->goc_config,
+ arg,
+ sizeof(struct cifisp_goc_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_GOC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP Cross Talk */
+static int cifisp_ctk_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_ctk_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->ctk_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_CTK);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->ctk_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ /* Perform parameter check */
+ if (arg->coeff0 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff1 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff2 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff3 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff4 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff5 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff6 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff7 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->coeff8 & CIFISP_CTK_COEFF_RESERVED ||
+ arg->ct_offset_r & CIFISP_XTALK_OFFSET_RESERVED ||
+ arg->ct_offset_g & CIFISP_XTALK_OFFSET_RESERVED ||
+ arg->ct_offset_b & CIFISP_XTALK_OFFSET_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->ctk_config,
+ arg,
+ sizeof(struct cifisp_ctk_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CTK);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP White Balance Mode */
+static int cifisp_awb_meas_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_awb_meas_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->meas_cfgs.curr->awb_meas_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_AWB);
+
+ if (memcmp(arg,
+ &isp_dev->meas_cfgs.curr->awb_meas_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->awb_mode > CIFISP_AWB_MODE_YCBCR ||
+ arg->awb_wnd.h_offs > CIFISP_AWB_WINDOW_OFFSET_MAX ||
+ arg->awb_wnd.v_offs > CIFISP_AWB_WINDOW_OFFSET_MAX ||
+ arg->awb_wnd.h_size > CIFISP_AWB_WINDOW_MAX_SIZE ||
+ arg->awb_wnd.v_size > CIFISP_AWB_WINDOW_MAX_SIZE ||
+ arg->frames > CIFISP_AWB_MAX_FRAMES) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->meas_cfgs.last_or_new->awb_meas_config,
+ arg,
+ sizeof(struct cifisp_awb_meas_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AWB);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_awb_gain_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_awb_gain_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->awb_gain_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_AWB_GAIN);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->awb_gain_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->gain_red > CIFISP_AWB_GAINS_MAX_VAL ||
+ arg->gain_green_r > CIFISP_AWB_GAINS_MAX_VAL ||
+ arg->gain_green_b > CIFISP_AWB_GAINS_MAX_VAL ||
+ arg->gain_blue > CIFISP_AWB_GAINS_MAX_VAL) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->awb_gain_config,
+ arg,
+ sizeof(struct cifisp_awb_gain_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_AWB_GAIN);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_aec_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_aec_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->meas_cfgs.curr->aec_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_AEC);
+
+ if (memcmp(arg,
+ &isp_dev->meas_cfgs.curr->aec_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->meas_window.h_offs > CIFISP_EXP_MAX_HOFFS ||
+ arg->meas_window.h_size > CIFISP_EXP_MAX_HSIZE ||
+ arg->meas_window.h_size < CIFISP_EXP_MIN_HSIZE ||
+ arg->meas_window.v_offs > CIFISP_EXP_MAX_VOFFS ||
+ arg->meas_window.v_size > CIFISP_EXP_MAX_VSIZE ||
+ arg->meas_window.v_size < CIFISP_EXP_MIN_VSIZE ||
+ arg->mode > CIFISP_EXP_MEASURING_MODE_1) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->meas_cfgs.last_or_new->aec_config,
+ arg,
+ sizeof(struct cifisp_aec_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AEC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_cproc_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_cproc_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->cproc_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_CPROC);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->cproc_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->c_out_range & CIFISP_CPROC_CTRL_RESERVED ||
+ arg->y_out_range & CIFISP_CPROC_CTRL_RESERVED ||
+ arg->y_in_range & CIFISP_CPROC_CTRL_RESERVED ||
+ arg->contrast & CIFISP_CPROC_CONTRAST_RESERVED ||
+ arg->brightness & CIFISP_CPROC_BRIGHTNESS_RESERVED ||
+ arg->sat & CIFISP_CPROC_SATURATION_RESERVED ||
+ arg->hue & CIFISP_CPROC_HUE_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->cproc_config,
+ arg,
+ sizeof(struct cifisp_cproc_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CPROC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_hst_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_hst_config *arg)
+{
+ unsigned long lock_flags = 0;
+ unsigned int i;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->meas_cfgs.curr->hst_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ if (memcmp(arg,
+ &isp_dev->meas_cfgs.curr->hst_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->mode > CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM ||
+ arg->histogram_predivider > CIFISP_MAX_HIST_PREDIVIDER ||
+ arg->meas_window.v_offs & CIFISP_HIST_WINDOW_OFFSET_RESERVED ||
+ arg->meas_window.h_offs & CIFISP_HIST_WINDOW_OFFSET_RESERVED ||
+ (arg->meas_window.v_size / (CIFISP_HIST_ROW_NUM - 1)) &
+ CIFISP_HIST_WINDOW_SIZE_RESERVED ||
+ (arg->meas_window.h_size / (CIFISP_HIST_COLUMN_NUM - 1)) &
+ CIFISP_HIST_WINDOW_SIZE_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s line: %d\n",
+ __func__, __LINE__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ for (i = 0; i < CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE; i++) {
+ if (arg->hist_weight[i] & CIFISP_HIST_WEIGHT_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s line: %d\n",
+ __func__, __LINE__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ memcpy(&isp_dev->meas_cfgs.last_or_new->hst_config,
+ arg,
+ sizeof(struct cifisp_hst_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_HST);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_afc_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_afc_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int i;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->meas_cfgs.curr->afc_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_AFC);
+
+ if (memcmp(arg,
+ &isp_dev->meas_cfgs.curr->afc_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->num_afm_win > CIFISP_AFM_MAX_WINDOWS ||
+ arg->thres & CIFISP_AFC_THRES_RESERVED ||
+ arg->var_shift & CIFISP_AFC_VAR_SHIFT_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ for (i = 0; i < arg->num_afm_win; i++) {
+ if (arg->afm_win[i].h_offs & CIFISP_AFC_WINDOW_X_RESERVED ||
+ arg->afm_win[i].h_offs < CIFISP_AFC_WINDOW_X_MIN ||
+ arg->afm_win[i].v_offs & CIFISP_AFC_WINDOW_Y_RESERVED ||
+ arg->afm_win[i].v_offs < CIFISP_AFC_WINDOW_Y_MIN ||
+ arg->afm_win[i].h_size & CIFISP_AFC_WINDOW_X_RESERVED ||
+ arg->afm_win[i].v_size & CIFISP_AFC_WINDOW_Y_RESERVED) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ memcpy(&isp_dev->meas_cfgs.last_or_new->afc_config,
+ arg,
+ sizeof(struct cifisp_afc_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AFC);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_ie_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_ie_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->ie_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_IE);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->ie_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ if (arg->effect != V4L2_COLORFX_NONE &&
+ arg->effect != V4L2_COLORFX_BW &&
+ arg->effect != V4L2_COLORFX_SEPIA &&
+ arg->effect != V4L2_COLORFX_NEGATIVE &&
+ arg->effect != V4L2_COLORFX_EMBOSS &&
+ arg->effect != V4L2_COLORFX_SKETCH &&
+ arg->effect != V4L2_COLORFX_AQUA &&
+ arg->effect != V4L2_COLORFX_SET_CBCR) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible param in function: %s\n", __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->ie_config,
+ arg,
+ sizeof(struct cifisp_ie_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_IE);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+/* ISP De-noise Pre-Filter(DPF) function */
+static int cifisp_dpf_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_dpf_config *arg)
+{
+ unsigned long lock_flags = 0;
+ unsigned int i;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->dpf_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_DPF);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->dpf_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ /* Parameter check */
+ if ((arg->gain.mode >= CIFISP_DPF_GAIN_USAGE_MAX) ||
+ (arg->gain.mode < CIFISP_DPF_GAIN_USAGE_DISABLED) ||
+ (arg->gain.nf_b_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+ (arg->gain.nf_r_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+ (arg->gain.nf_gr_gain & CIFISP_DPF_NF_GAIN_RESERVED) ||
+ (arg->gain.nf_gb_gain & CIFISP_DPF_NF_GAIN_RESERVED)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF GAIN param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ for (i = 0; i < CIFISP_DPF_MAX_SPATIAL_COEFFS; i++) {
+ if ((arg->g_flt.spatial_coeff[i] >
+ CIFISP_DPF_SPATIAL_COEFF_MAX)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF G Spatial param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ if (arg->rb_flt.spatial_coeff[i] >
+ CIFISP_DPF_SPATIAL_COEFF_MAX) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF RB Spatial param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ if ((arg->rb_flt.fltsize != CIFISP_DPF_RB_FILTERSIZE_9x9) &&
+ (arg->rb_flt.fltsize != CIFISP_DPF_RB_FILTERSIZE_13x9)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF RB filter size param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
+ if (arg->nll.coeff[i] > CIFISP_DPF_NLL_COEFF_N_MAX) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF NLL coeff param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+ }
+
+ if ((arg->nll.scale_mode != CIFISP_NLL_SCALE_LINEAR) &&
+ (arg->nll.scale_mode != CIFISP_NLL_SCALE_LOGARITHMIC)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "incompatible DPF NLL scale mode param in function: %s\n",
+ __func__);
+ retval = -EINVAL;
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->dpf_config,
+ arg,
+ sizeof(struct cifisp_dpf_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_dpf_strength_param(struct cif_isp10_isp_dev *isp_dev,
+ bool flag, struct cifisp_dpf_strength_config *arg)
+{
+ unsigned long lock_flags = 0;
+ int retval = 0;
+
+ if (!arg)
+ return -EINVAL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (flag == _GET_) {
+ memcpy(arg,
+ &isp_dev->other_cfgs.curr->dpf_strength_config,
+ sizeof(*arg));
+ goto end;
+ }
+
+ cifisp_param_dump(arg, CIFISP_MODULE_DPF_STRENGTH);
+
+ if (memcmp(arg,
+ &isp_dev->other_cfgs.curr->dpf_strength_config,
+ sizeof(*arg)) == 0) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "same param in function: %s\n", __func__);
+ goto end;
+ }
+
+ memcpy(&isp_dev->other_cfgs.last_or_new->dpf_strength_config,
+ arg,
+ sizeof(struct cifisp_dpf_strength_config));
+ CIFISP_MODULE_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF_STRENGTH);
+end:
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ return retval;
+}
+
+static int cifisp_last_capture_config(struct cifisp_last_capture_config *arg)
+{
+#ifdef LOG_CAPTURE_PARAMS
+ if (!arg)
+ return -EINVAL;
+
+ memcpy(arg, &g_last_capture_config, sizeof(*arg));
+
+ return 0;
+#else
+ return -EPERM;
+#endif
+}
+
+/* DPCC */
+static void cifisp_dpcc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_dpcc_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->dpcc_config;
+ unsigned int i;
+
+ cifisp_iowrite32(pconfig->mode, CIF_ISP_DPCC_MODE);
+ cifisp_iowrite32(pconfig->output_mode, CIF_ISP_DPCC_OUTPUT_MODE);
+ cifisp_iowrite32(pconfig->set_use, CIF_ISP_DPCC_SET_USE);
+
+ cifisp_iowrite32(pconfig->methods[0].method,
+ CIF_ISP_DPCC_METHODS_SET_1);
+ cifisp_iowrite32(pconfig->methods[1].method,
+ CIF_ISP_DPCC_METHODS_SET_2);
+ cifisp_iowrite32(pconfig->methods[2].method,
+ CIF_ISP_DPCC_METHODS_SET_3);
+ for (i = 0; i < CIFISP_DPCC_METHODS_MAX; i++) {
+ cifisp_iowrite32(pconfig->methods[i].line_thresh,
+ CIF_ISP_DPCC_LINE_THRESH_1 + 0x14 * i);
+ cifisp_iowrite32(pconfig->methods[i].line_mad_fac,
+ CIF_ISP_DPCC_LINE_MAD_FAC_1 + 0x14 * i);
+ cifisp_iowrite32(pconfig->methods[i].pg_fac,
+ CIF_ISP_DPCC_PG_FAC_1 + 0x14 * i);
+ cifisp_iowrite32(pconfig->methods[i].rnd_thresh,
+ CIF_ISP_DPCC_RND_THRESH_1 + 0x14 * i);
+ cifisp_iowrite32(pconfig->methods[i].rg_fac,
+ CIF_ISP_DPCC_RG_FAC_1 + 0x14 * i);
+ }
+
+ cifisp_iowrite32(pconfig->rnd_offs, CIF_ISP_DPCC_RND_OFFS);
+ cifisp_iowrite32(pconfig->ro_limits, CIF_ISP_DPCC_RO_LIMITS);
+}
+
+static void cifisp_dpcc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIFISP_DPCC_ENA, CIF_ISP_DPCC_MODE);
+}
+
+static void cifisp_dpcc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(CIFISP_DPCC_DIS, CIF_ISP_DPCC_MODE);
+}
+
+/* Lens Shade Correction */
+
+/*****************************************************************************/
+static void cifisp_lsc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(0, CIF_ISP_LSC_CTRL);
+}
+
+static bool cifisp_lsc_correct_matrix_config(struct cif_isp10_isp_dev *isp_dev)
+{
+ int i, n;
+ unsigned int isp_lsc_status, sram_addr, isp_lsc_table_sel;
+ unsigned int data;
+ struct cifisp_lsc_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->lsc_config;
+
+ isp_lsc_status = cifisp_ioread32(CIF_ISP_LSC_STATUS);
+ sram_addr = (isp_lsc_status & 0x2U) ? 0U : 153U; /* ( 17 * 18 ) >> 1 */
+
+ cifisp_iowrite32(sram_addr, CIF_ISP_LSC_R_TABLE_ADDR);
+ cifisp_iowrite32(sram_addr, CIF_ISP_LSC_GR_TABLE_ADDR);
+ cifisp_iowrite32(sram_addr, CIF_ISP_LSC_GB_TABLE_ADDR);
+ cifisp_iowrite32(sram_addr, CIF_ISP_LSC_B_TABLE_ADDR);
+
+ /* program data tables (table size is 9 * 17 = 153) */
+ for (n = 0; n < ((CIFISP_LSC_SECTORS_MAX + 1) *
+ (CIFISP_LSC_SECTORS_MAX + 1));
+ n += CIFISP_LSC_SECTORS_MAX + 1) {
+ /*
+ * 17 sectors with 2 values in one DWORD = 9
+ * DWORDs (8 steps + 1 outside loop)
+ */
+ for (i = 0; i < (CIFISP_LSC_SECTORS_MAX); i += 2) {
+ data = CIFISP_LSC_TABLE_DATA(pconfig->r_data_tbl[n + i],
+ pconfig->r_data_tbl[n + i + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_R_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->gr_data_tbl[n + i],
+ pconfig->gr_data_tbl[n + i + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_GR_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->gb_data_tbl[n + i],
+ pconfig->gb_data_tbl[n + i + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_GB_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(pconfig->b_data_tbl[n + i],
+ pconfig->b_data_tbl[n + i + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_B_TABLE_DATA);
+ }
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->r_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+ /* isp_dev->lsc_config.r_data_tbl[n + i] */0);
+ cifisp_iowrite32(data, CIF_ISP_LSC_R_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->gr_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+ /* isp_dev->lsc_config.gr_data_tbl[n + i] */0);
+ cifisp_iowrite32(data, CIF_ISP_LSC_GR_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->gb_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+ /* isp_dev->lsc_config.gr_data_tbl[n + i] */0);
+ cifisp_iowrite32(data, CIF_ISP_LSC_GB_TABLE_DATA);
+
+ data = CIFISP_LSC_TABLE_DATA(
+ pconfig->b_data_tbl[n + CIFISP_LSC_SECTORS_MAX],
+ /* isp_dev->lsc_config.b_data_tbl[n + i] */0);
+ cifisp_iowrite32(data, CIF_ISP_LSC_B_TABLE_DATA);
+ }
+
+ isp_lsc_table_sel = (isp_lsc_status & 0x2U) ? 0U : 1U;
+ cifisp_iowrite32(isp_lsc_table_sel, CIF_ISP_LSC_TABLE_SEL);
+ return true;
+}
+
+/*****************************************************************************/
+static bool cifisp_lsc_config(struct cif_isp10_isp_dev *isp_dev)
+{
+ int i;
+ unsigned int data;
+ struct cifisp_lsc_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->lsc_config;
+
+ if (pconfig->config_width != isp_dev->input_width ||
+ pconfig->config_height != isp_dev->input_height) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "LSC config: lsc_w %d lsc_h %d act_w %d act_h %d\n",
+ pconfig->config_width,
+ pconfig->config_height,
+ isp_dev->input_width,
+ isp_dev->input_height);
+ return false;
+ }
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "LSC config: lsc_w %d lsc_h %d\n",
+ pconfig->config_width,
+ pconfig->config_height);
+
+ /* To config must be off */
+ cifisp_iowrite32(0, CIF_ISP_LSC_CTRL);
+
+ cifisp_lsc_correct_matrix_config(isp_dev);
+
+ if (isp_dev->active_lsc_width !=
+ pconfig->config_width ||
+ isp_dev->active_lsc_height !=
+ pconfig->config_height) {
+ for (i = 0; i < 4; i++) {
+ /* program x size tables */
+ data = CIFISP_LSC_SECT_SIZE(
+ pconfig->x_size_tbl[i * 2],
+ pconfig->x_size_tbl[i * 2 + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_XSIZE_01 + i * 4);
+
+ /* program x grad tables */
+ data = CIFISP_LSC_SECT_SIZE(
+ pconfig->x_grad_tbl[i * 2],
+ pconfig->x_grad_tbl[i * 2 + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_XGRAD_01 + i * 4);
+
+ /* program y size tables */
+ data = CIFISP_LSC_SECT_SIZE(
+ pconfig->y_size_tbl[i * 2],
+ pconfig->y_size_tbl[i * 2 + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_YSIZE_01 + i * 4);
+
+ /* program y grad tables */
+ data = CIFISP_LSC_SECT_SIZE(
+ pconfig->y_grad_tbl[i * 2],
+ pconfig->y_grad_tbl[i * 2 + 1]);
+ cifisp_iowrite32(data, CIF_ISP_LSC_YGRAD_01 + i * 4);
+ }
+
+ isp_dev->active_lsc_width = pconfig->config_width;
+ isp_dev->active_lsc_height = pconfig->config_height;
+ }
+
+ cifisp_iowrite32(1, CIF_ISP_LSC_CTRL);
+
+ return true;
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_lsc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_lsc_config *pconfig)
+{
+);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_bls_get_meas(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_stat_buffer *pbuf)
+{
+ const struct cif_isp10_device *cif_dev =
+ container_of(isp_dev, struct cif_isp10_device, isp_dev);
+ enum cif_isp10_pix_fmt in_pix_fmt;
+
+ in_pix_fmt = cif_dev->config.isp_config.input->pix_fmt;
+ if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+ pbuf->params.ae.bls_val.meas_b =
+ cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+ pbuf->params.ae.bls_val.meas_gb =
+ cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+ pbuf->params.ae.bls_val.meas_gr =
+ cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+ pbuf->params.ae.bls_val.meas_r =
+ cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+ pbuf->params.ae.bls_val.meas_gb =
+ cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+ pbuf->params.ae.bls_val.meas_b =
+ cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+ pbuf->params.ae.bls_val.meas_r =
+ cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+ pbuf->params.ae.bls_val.meas_gr =
+ cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+ pbuf->params.ae.bls_val.meas_gr =
+ cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+ pbuf->params.ae.bls_val.meas_r =
+ cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+ pbuf->params.ae.bls_val.meas_b =
+ cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+ pbuf->params.ae.bls_val.meas_gb =
+ cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+ pbuf->params.ae.bls_val.meas_r =
+ cifisp_ioread32(CIF_ISP_BLS_A_MEASURED);
+ pbuf->params.ae.bls_val.meas_gr =
+ cifisp_ioread32(CIF_ISP_BLS_B_MEASURED);
+ pbuf->params.ae.bls_val.meas_gb =
+ cifisp_ioread32(CIF_ISP_BLS_C_MEASURED);
+ pbuf->params.ae.bls_val.meas_b =
+ cifisp_ioread32(CIF_ISP_BLS_D_MEASURED);
+ }
+}
+
+/*****************************************************************************/
+static void cifisp_bls_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_bls_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->bls_config;
+ u32 new_control = 0;
+ const struct cif_isp10_device *cif_dev =
+ container_of(isp_dev, struct cif_isp10_device, isp_dev);
+ enum cif_isp10_pix_fmt in_pix_fmt;
+
+ in_pix_fmt = cif_dev->config.isp_config.input->pix_fmt;
+
+ /* fixed subtraction values */
+ if (!pconfig->enable_auto) {
+ const struct cifisp_bls_fixed_val *pval =
+ &isp_dev->other_cfgs.last_or_new->bls_config.fixed_val;
+
+ if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_BGGR(in_pix_fmt)) {
+ cifisp_iowrite32(pval->r, CIF_ISP_BLS_D_FIXED);
+ cifisp_iowrite32(pval->gr, CIF_ISP_BLS_C_FIXED);
+ cifisp_iowrite32(pval->gb, CIF_ISP_BLS_B_FIXED);
+ cifisp_iowrite32(pval->b, CIF_ISP_BLS_A_FIXED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GBRG(in_pix_fmt)) {
+ cifisp_iowrite32(pval->r, CIF_ISP_BLS_C_FIXED);
+ cifisp_iowrite32(pval->gr, CIF_ISP_BLS_D_FIXED);
+ cifisp_iowrite32(pval->gb, CIF_ISP_BLS_A_FIXED);
+ cifisp_iowrite32(pval->b, CIF_ISP_BLS_B_FIXED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_GRBG(in_pix_fmt)) {
+ cifisp_iowrite32(pval->r, CIF_ISP_BLS_B_FIXED);
+ cifisp_iowrite32(pval->gr, CIF_ISP_BLS_A_FIXED);
+ cifisp_iowrite32(pval->gb, CIF_ISP_BLS_D_FIXED);
+ cifisp_iowrite32(pval->b, CIF_ISP_BLS_C_FIXED);
+ } else if (CIF_ISP10_PIX_FMT_BAYER_PAT_IS_RGGB(in_pix_fmt)) {
+ cifisp_iowrite32(pval->r, CIF_ISP_BLS_A_FIXED);
+ cifisp_iowrite32(pval->gr, CIF_ISP_BLS_B_FIXED);
+ cifisp_iowrite32(pval->gb, CIF_ISP_BLS_C_FIXED);
+ cifisp_iowrite32(pval->b, CIF_ISP_BLS_D_FIXED);
+ }
+
+ new_control = CIFISP_BLS_MODE_FIXED;
+ cifisp_iowrite32(new_control, CIF_ISP_BLS_CTRL);
+ } else {
+ if (pconfig->en_windows & 2) {
+ cifisp_iowrite32(pconfig->bls_window2.h_offs,
+ CIF_ISP_BLS_H2_START);
+ cifisp_iowrite32(pconfig->bls_window2.h_size,
+ CIF_ISP_BLS_H2_STOP);
+ cifisp_iowrite32(pconfig->bls_window2.v_offs,
+ CIF_ISP_BLS_V2_START);
+ cifisp_iowrite32(pconfig->bls_window2.v_size,
+ CIF_ISP_BLS_V2_STOP);
+ new_control |= CIFISP_BLS_WINDOW_2;
+ }
+
+ if (pconfig->en_windows & 1) {
+ cifisp_iowrite32(pconfig->bls_window1.h_offs,
+ CIF_ISP_BLS_H1_START);
+ cifisp_iowrite32(pconfig->bls_window1.h_size,
+ CIF_ISP_BLS_H1_STOP);
+ cifisp_iowrite32(pconfig->bls_window1.v_offs,
+ CIF_ISP_BLS_V1_START);
+ cifisp_iowrite32(pconfig->bls_window1.v_size,
+ CIF_ISP_BLS_V1_STOP);
+ new_control |= CIFISP_BLS_WINDOW_1;
+ }
+
+ cifisp_iowrite32(pconfig->bls_samples, CIF_ISP_BLS_SAMPLES);
+
+ new_control |= CIFISP_BLS_MODE_MEASURED;
+
+ cifisp_iowrite32(new_control, CIF_ISP_BLS_CTRL);
+ }
+}
+
+/*****************************************************************************/
+static void cifisp_bls_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIFISP_BLS_ENA, CIF_ISP_BLS_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_bls_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(CIFISP_BLS_DIS, CIF_ISP_BLS_CTRL);
+}
+
+/* Gamma correction */
+/*****************************************************************************/
+static void cifisp_sdg_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_sdg_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->sdg_config;
+ unsigned int i;
+
+ cifisp_iowrite32(pconfig->xa_pnts.gamma_dx0, CIF_ISP_GAMMA_DX_LO);
+ cifisp_iowrite32(pconfig->xa_pnts.gamma_dx1, CIF_ISP_GAMMA_DX_HI);
+
+ for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+ cifisp_iowrite32(pconfig->curve_r.gamma_y[i],
+ CIF_ISP_GAMMA_R_Y0 + i * 4);
+ cifisp_iowrite32(pconfig->curve_g.gamma_y[i],
+ CIF_ISP_GAMMA_G_Y0 + i * 4);
+ cifisp_iowrite32(pconfig->curve_b.gamma_y[i],
+ CIF_ISP_GAMMA_B_Y0 + i * 4);
+ }
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_sdg_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_sdg_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_sdg_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_sdg_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_IN_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_goc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ int i;
+ const struct cifisp_goc_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->goc_config;
+
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+
+ cifisp_iowrite32(pconfig->mode, CIF_ISP_GAMMA_OUT_MODE);
+ for (i = 0; i < CIFISP_GAMMA_OUT_MAX_SAMPLES; i++)
+ cifisp_iowrite32(pconfig->gamma_y[i],
+ CIF_ISP_GAMMA_OUT_Y_0 + i * 4);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_goc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_goc_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_goc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_goc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_bdm_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->bdm_config;
+
+ /*set demosaic threshold */
+ cifisp_iowrite32(pconfig->demosaic_th, CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32AND(~(CIFISP_BDM_BYPASS_EN(1)), CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_bdm_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(0, CIF_ISP_DEMOSAIC);
+}
+
+/*****************************************************************************/
+static void cifisp_flt_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_flt_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->flt_config;
+
+ cifisp_iowrite32(pconfig->thresh_bl0,
+ CIF_ISP_FILT_THRESH_BL0);
+ cifisp_iowrite32(pconfig->thresh_bl1,
+ CIF_ISP_FILT_THRESH_BL1);
+ cifisp_iowrite32(pconfig->thresh_sh0,
+ CIF_ISP_FILT_THRESH_SH0);
+ cifisp_iowrite32(pconfig->thresh_sh1,
+ CIF_ISP_FILT_THRESH_SH1);
+ cifisp_iowrite32(pconfig->fac_bl0,
+ CIF_ISP_FILT_FAC_BL0);
+ cifisp_iowrite32(pconfig->fac_bl1,
+ CIF_ISP_FILT_FAC_BL1);
+ cifisp_iowrite32(pconfig->fac_mid,
+ CIF_ISP_FILT_FAC_MID);
+ cifisp_iowrite32(pconfig->fac_sh0,
+ CIF_ISP_FILT_FAC_SH0);
+ cifisp_iowrite32(pconfig->fac_sh1,
+ CIF_ISP_FILT_FAC_SH1);
+ cifisp_iowrite32(pconfig->lum_weight,
+ CIF_ISP_FILT_LUM_WEIGHT);
+
+ cifisp_iowrite32(CIFISP_FLT_MODE(pconfig->mode) |
+ CIFISP_FLT_CHROMA_V_MODE(pconfig->chr_v_mode) |
+ CIFISP_FLT_CHROMA_H_MODE(pconfig->chr_h_mode) |
+ CIFISP_FLT_GREEN_STAGE1(pconfig->grn_stage1),
+ CIF_ISP_FILT_MODE);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_flt_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_flt_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_flt_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIFISP_FLT_ENA, CIF_ISP_FILT_MODE);
+}
+
+/*****************************************************************************/
+static void cifisp_flt_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(CIFISP_FLT_DIS, CIF_ISP_FILT_MODE);
+}
+
+/* Auto White Balance */
+/*****************************************************************************/
+static void cifisp_awb_gain_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_awb_gain_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->awb_gain_config;
+
+ cifisp_iowrite32(CIFISP_AWB_GAIN_R_SET(pconfig->gain_green_r) |
+ pconfig->gain_green_b, CIF_ISP_AWB_GAIN_G);
+
+ cifisp_iowrite32(CIFISP_AWB_GAIN_R_SET(pconfig->gain_red) |
+ pconfig->gain_blue, CIF_ISP_AWB_GAIN_RB);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_awb_gain_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_awb_gain_config *pconfig)
+{
+ unsigned int reg = cifisp_ioread32(CIF_ISP_AWB_GAIN_G);
+
+ pconfig->gain_green_r = CIFISP_AWB_GAIN_R_READ(reg);
+ pconfig->gain_green_b = CIFISP_AWB_GAIN_B_READ(reg);
+ reg = cifisp_ioread32(CIF_ISP_AWB_GAIN_RB);
+ pconfig->gain_red = CIFISP_AWB_GAIN_R_READ(reg);
+ pconfig->gain_blue = CIFISP_AWB_GAIN_B_READ(reg);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_awb_meas_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_awb_meas_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->awb_meas_config;
+ unsigned int awb_prob = 0;
+
+ /* based on the mode,configure the awb module */
+ if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB) {
+ awb_prob = CIFISP_AWB_MODE_RGB_EN;
+ } else {
+ if (pconfig->enable_ymax_cmp)
+ awb_prob = CIFISP_AWB_YMAX_CMP_EN;
+
+ /* Reference Cb and Cr */
+ cifisp_iowrite32(CIFISP_AWB_REF_CR_SET(pconfig->awb_ref_cr) |
+ pconfig->awb_ref_cb, CIF_ISP_AWB_REF);
+ /* Yc Threshold */
+ cifisp_iowrite32(CIFISP_AWB_MAX_Y_SET(pconfig->max_y) |
+ CIFISP_AWB_MIN_Y_SET(pconfig->min_y) |
+ CIFISP_AWB_MAX_CS_SET(pconfig->max_csum) |
+ pconfig->min_c, CIF_ISP_AWB_THRESH);
+ }
+
+ /* Common Configuration */
+ cifisp_iowrite32(awb_prob, CIF_ISP_AWB_PROP);
+ /* window offset */
+ cifisp_iowrite32(pconfig->awb_wnd.v_offs,
+ CIF_ISP_AWB_WND_V_OFFS);
+ cifisp_iowrite32(pconfig->awb_wnd.h_offs,
+ CIF_ISP_AWB_WND_H_OFFS);
+ /* AWB window size */
+ cifisp_iowrite32(pconfig->awb_wnd.v_size, CIF_ISP_AWB_WND_V_SIZE);
+ cifisp_iowrite32(pconfig->awb_wnd.h_size, CIF_ISP_AWB_WND_H_SIZE);
+ /* Number of frames */
+ cifisp_iowrite32(pconfig->frames, CIF_ISP_AWB_FRAMES);
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_awb_meas_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_awb_meas_config *pconfig)
+{
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_awb_meas_en(struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_awb_meas_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->awb_meas_config;
+ u32 reg_val = cifisp_ioread32(CIF_ISP_AWB_PROP);
+
+ /* switch off */
+ reg_val &= 0xFFFFFFFC;
+
+ if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB)
+ reg_val |= CIFISP_AWB_MODE_RGB_EN;
+ else
+ reg_val |= CIFISP_AWB_MODE_YCBCR_EN;
+
+ cifisp_iowrite32(reg_val, CIF_ISP_AWB_PROP);
+
+ isp_dev->active_meas |= CIF_ISP_AWB_DONE;
+
+ /* Measurements require AWB block be active. */
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_AWB_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_meas_end(struct cif_isp10_isp_dev *isp_dev)
+{
+ u32 reg_val = cifisp_ioread32(CIF_ISP_AWB_PROP);
+
+ /* switch off */
+ reg_val &= 0xFFFFFFFC;
+
+ cifisp_iowrite32(reg_val, CIF_ISP_AWB_PROP);
+
+ isp_dev->active_meas &= ~CIF_ISP_AWB_DONE;
+
+ if (!CIFISP_MODULE_IS_EN(
+ isp_dev->meas_cfgs.last_or_new->module_ens,
+ CIFISP_MODULE_AWB))
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_AWB_ENA,
+ CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_gain_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_AWB_ENA, CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_awb_gain_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ if (!CIFISP_MODULE_IS_EN(
+ isp_dev->meas_cfgs.last_or_new->module_ens,
+ CIFISP_MODULE_AWB))
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_AWB_ENA,
+ CIF_ISP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_get_awb_meas(struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_stat_buffer *pbuf)
+{
+ /* Protect against concurrent access from ISR? */
+ u32 reg_val;
+ const struct cifisp_awb_meas_config *pconfig =
+ &isp_dev->meas_cfgs.curr->awb_meas_config;
+
+ pbuf->meas_type |= CIFISP_STAT_AWB;
+ reg_val = cifisp_ioread32(CIF_ISP_AWB_WHITE_CNT);
+ pbuf->params.awb.awb_mean[0].cnt =
+ CIFISP_AWB_GET_PIXEL_CNT(reg_val);
+ reg_val = cifisp_ioread32(CIF_ISP_AWB_MEAN);
+
+ if (pconfig->awb_mode == CIFISP_AWB_MODE_RGB) {
+ pbuf->params.awb.awb_mean[0].mean_r =
+ CIFISP_AWB_GET_MEAN_R(reg_val);
+ pbuf->params.awb.awb_mean[0].mean_b =
+ CIFISP_AWB_GET_MEAN_B(reg_val);
+ pbuf->params.awb.awb_mean[0].mean_g =
+ CIFISP_AWB_GET_MEAN_G(reg_val);
+ } else {
+ pbuf->params.awb.awb_mean[0].mean_cr =
+ (u8)CIFISP_AWB_GET_MEAN_CR(reg_val);
+ pbuf->params.awb.awb_mean[0].mean_cb =
+ (u8)CIFISP_AWB_GET_MEAN_CB(reg_val);
+ pbuf->params.awb.awb_mean[0].mean_y =
+ (u8)CIFISP_AWB_GET_MEAN_Y(reg_val);
+ }
+}
+
+/* Auto Exposure */
+/*****************************************************************************/
+static void cifisp_aec_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_aec_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->aec_config;
+ unsigned int block_hsize, block_vsize;
+
+ cifisp_iowrite32(CIFISP_EXP_CTRL_AUTOSTOP(pconfig->autostop) |
+ CIFISP_EXP_CTRL_MEASMODE(pconfig->mode),
+ CIF_ISP_EXP_CTRL);
+
+ cifisp_iowrite32(pconfig->meas_window.h_offs, CIF_ISP_EXP_H_OFFSET);
+ cifisp_iowrite32(pconfig->meas_window.v_offs, CIF_ISP_EXP_V_OFFSET);
+
+ block_hsize = pconfig->meas_window.h_size /
+ CIFISP_EXP_COLUMN_NUM - 1;
+ block_vsize = pconfig->meas_window.v_size /
+ CIFISP_EXP_ROW_NUM - 1;
+
+ cifisp_iowrite32(CIFISP_EXP_HSIZE(block_hsize), CIF_ISP_EXP_H_SIZE);
+ cifisp_iowrite32(CIFISP_EXP_VSIZE(block_vsize), CIF_ISP_EXP_V_SIZE);
+}
+
+/*****************************************************************************/
+static void cifisp_aec_en(struct cif_isp10_isp_dev *isp_dev)
+{
+ isp_dev->active_meas |= CIF_ISP_EXP_END;
+
+ cifisp_iowrite32OR(CIFISP_EXP_ENA, CIF_ISP_EXP_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_aec_end(struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(CIFISP_EXP_DIS, CIF_ISP_EXP_CTRL);
+
+ isp_dev->active_meas &= ~CIF_ISP_EXP_END;
+}
+
+/*****************************************************************************/
+static void cifisp_get_aec_meas(struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_stat_buffer *pbuf)
+{
+ unsigned int i;
+
+ pbuf->meas_type |= CIFISP_STAT_AUTOEXP; /*Set the measurement type */
+ for (i = 0; i < CIFISP_AE_MEAN_MAX; i++) {
+ pbuf->params.ae.exp_mean[i] =
+ (u8)cifisp_ioread32(CIF_ISP_EXP_MEAN_00 + i * 4);
+ }
+}
+
+/* X-Talk Matrix */
+/*****************************************************************************/
+static void cifisp_ctk_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ /* Nothing to do */
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_ctk_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_ctk_config *pconfig)
+{
+ pconfig->coeff0 = cifisp_ioread32(CIF_ISP_CT_COEFF_0);
+ pconfig->coeff1 = cifisp_ioread32(CIF_ISP_CT_COEFF_1);
+ pconfig->coeff2 = cifisp_ioread32(CIF_ISP_CT_COEFF_2);
+ pconfig->coeff3 = cifisp_ioread32(CIF_ISP_CT_COEFF_3);
+ pconfig->coeff4 = cifisp_ioread32(CIF_ISP_CT_COEFF_4);
+ pconfig->coeff5 = cifisp_ioread32(CIF_ISP_CT_COEFF_5);
+ pconfig->coeff6 = cifisp_ioread32(CIF_ISP_CT_COEFF_6);
+ pconfig->coeff7 = cifisp_ioread32(CIF_ISP_CT_COEFF_7);
+ pconfig->coeff8 = cifisp_ioread32(CIF_ISP_CT_COEFF_8);
+ pconfig->ct_offset_r = cifisp_ioread32(CIF_ISP_CT_OFFSET_R);
+ pconfig->ct_offset_g = cifisp_ioread32(CIF_ISP_CT_OFFSET_G);
+ pconfig->ct_offset_b = cifisp_ioread32(CIF_ISP_CT_OFFSET_B);
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_ctk_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_ctk_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->ctk_config;
+
+ cifisp_iowrite32(pconfig->coeff0, CIF_ISP_CT_COEFF_0);
+ cifisp_iowrite32(pconfig->coeff1, CIF_ISP_CT_COEFF_1);
+ cifisp_iowrite32(pconfig->coeff2, CIF_ISP_CT_COEFF_2);
+ cifisp_iowrite32(pconfig->coeff3, CIF_ISP_CT_COEFF_3);
+ cifisp_iowrite32(pconfig->coeff4, CIF_ISP_CT_COEFF_4);
+ cifisp_iowrite32(pconfig->coeff5, CIF_ISP_CT_COEFF_5);
+ cifisp_iowrite32(pconfig->coeff6, CIF_ISP_CT_COEFF_6);
+ cifisp_iowrite32(pconfig->coeff7, CIF_ISP_CT_COEFF_7);
+ cifisp_iowrite32(pconfig->coeff8, CIF_ISP_CT_COEFF_8);
+ cifisp_iowrite32(pconfig->ct_offset_r, CIF_ISP_CT_OFFSET_R);
+ cifisp_iowrite32(pconfig->ct_offset_g, CIF_ISP_CT_OFFSET_G);
+ cifisp_iowrite32(pconfig->ct_offset_b, CIF_ISP_CT_OFFSET_B);
+}
+
+/*****************************************************************************/
+static void cifisp_ctk_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ /* Write back the default values. */
+ cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_0);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_1);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_2);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_3);
+ cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_4);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_5);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_6);
+ cifisp_iowrite32(0, CIF_ISP_CT_COEFF_7);
+ cifisp_iowrite32(0x80, CIF_ISP_CT_COEFF_8);
+
+ cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_R);
+ cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_G);
+ cifisp_iowrite32(0, CIF_ISP_CT_OFFSET_B);
+}
+
+/* CPROC */
+/*****************************************************************************/
+static void cifisp_cproc_config(const struct cif_isp10_isp_dev *isp_dev,
+ enum cif_isp10_pix_fmt_quantization quantization)
+{
+ const struct cifisp_cproc_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->cproc_config;
+ const struct cifisp_ie_config *ie_pconfig =
+ &isp_dev->other_cfgs.last_or_new->ie_config;
+
+ cifisp_iowrite32(pconfig->contrast, CIF_C_PROC_CONTRAST);
+ cifisp_iowrite32(pconfig->hue, CIF_C_PROC_HUE);
+ cifisp_iowrite32(pconfig->sat, CIF_C_PROC_SATURATION);
+ cifisp_iowrite32(pconfig->brightness, CIF_C_PROC_BRIGHTNESS);
+
+ if ((quantization != CIF_ISP10_QUANTIZATION_FULL_RANGE) ||
+ (ie_pconfig->effect != V4L2_COLORFX_NONE)) {
+ cifisp_iowrite32(
+ ~(CIF_C_PROC_YOUT_FULL |
+ CIF_C_PROC_YIN_FULL |
+ CIF_C_PROC_COUT_FULL),
+ CIF_C_PROC_CTRL);
+ } else {
+ cifisp_iowrite32OR(
+ (CIF_C_PROC_YOUT_FULL |
+ CIF_C_PROC_YIN_FULL |
+ CIF_C_PROC_COUT_FULL),
+ CIF_C_PROC_CTRL);
+ }
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_cproc_config_read(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_cproc_config *pconfig)
+{
+ unsigned int reg;
+
+ pconfig->contrast = cifisp_ioread32(CIF_C_PROC_CONTRAST);
+ pconfig->hue = cifisp_ioread32(CIF_C_PROC_HUE);
+ pconfig->sat = cifisp_ioread32(CIF_C_PROC_SATURATION);
+ pconfig->brightness = cifisp_ioread32(CIF_C_PROC_BRIGHTNESS);
+ reg = cifisp_ioread32(CIF_C_PROC_CTRL);
+ pconfig->y_out_range = (reg >> 1) & 1;
+ pconfig->y_in_range = (reg >> 2) & 1;
+ pconfig->c_out_range = (reg >> 3) & 1;
+}
+#endif
+
+/*****************************************************************************/
+static void cifisp_cproc_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIFISP_CPROC_EN, CIF_C_PROC_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_cproc_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32AND(~CIFISP_CPROC_EN, CIF_C_PROC_CTRL);
+}
+
+static void cifisp_afc_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_afc_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->afc_config;
+ int num_of_win = pconfig->num_afm_win, i;
+
+ /* Switch off to configure. Enabled during normal flow in frame isr. */
+ cifisp_iowrite32(0, CIF_ISP_AFM_CTRL);
+
+ for (i = 0; i < num_of_win; i++) {
+ cifisp_iowrite32(
+ CIFISP_AFC_WINDOW_X(pconfig->afm_win[0].h_offs) |
+ CIFISP_AFC_WINDOW_Y(pconfig->afm_win[0].v_offs),
+ CIF_ISP_AFM_LT_A + i * 8);
+ cifisp_iowrite32(
+ CIFISP_AFC_WINDOW_X(pconfig->afm_win[0].h_size +
+ pconfig->afm_win[0].h_offs) |
+ CIFISP_AFC_WINDOW_Y(pconfig->afm_win[0].v_size +
+ pconfig->afm_win[0].v_offs),
+ CIF_ISP_AFM_RB_A + i * 8);
+ }
+
+ cifisp_iowrite32(pconfig->thres, CIF_ISP_AFM_THRES);
+ cifisp_iowrite32(pconfig->var_shift, CIF_ISP_AFM_VAR_SHIFT);
+}
+
+/*****************************************************************************/
+static void cifisp_afc_en(struct cif_isp10_isp_dev *isp_dev)
+{
+ isp_dev->active_meas |= CIF_ISP_AFM_FIN;
+
+ cifisp_iowrite32(CIFISP_AFC_ENA, CIF_ISP_AFM_CTRL);
+}
+
+/*****************************************************************************/
+static void cifisp_afc_end(struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32(CIFISP_AFC_DIS, CIF_ISP_AFM_CTRL);
+ isp_dev->active_meas &= ~CIF_ISP_AFM_FIN;
+}
+
+/*****************************************************************************/
+static void cifisp_get_afc_meas(struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_stat_buffer *pbuf)
+{
+ pbuf->meas_type = CIFISP_STAT_AFM_FIN;
+
+ pbuf->params.af.window[0].sum =
+ cifisp_ioread32(CIF_ISP_AFM_SUM_A);
+ pbuf->params.af.window[0].lum =
+ cifisp_ioread32(CIF_ISP_AFM_LUM_A);
+ pbuf->params.af.window[1].sum =
+ cifisp_ioread32(CIF_ISP_AFM_SUM_B);
+ pbuf->params.af.window[1].lum =
+ cifisp_ioread32(CIF_ISP_AFM_LUM_B);
+ pbuf->params.af.window[2].sum =
+ cifisp_ioread32(CIF_ISP_AFM_SUM_C);
+ pbuf->params.af.window[2].lum =
+ cifisp_ioread32(CIF_ISP_AFM_LUM_C);
+}
+
+/* HISTOGRAM CALCULATION */
+/*****************************************************************************/
+static void cifisp_hst_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_hst_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->hst_config;
+ unsigned int block_hsize, block_vsize;
+
+ cifisp_iowrite32(CIFISP_HIST_PREDIV_SET(pconfig->histogram_predivider),
+ CIF_ISP_HIST_PROP);
+ cifisp_iowrite32(pconfig->meas_window.h_offs, CIF_ISP_HIST_H_OFFS);
+ cifisp_iowrite32(pconfig->meas_window.v_offs, CIF_ISP_HIST_V_OFFS);
+
+ block_hsize = pconfig->meas_window.h_size /
+ CIFISP_HIST_COLUMN_NUM - 1;
+ block_vsize = pconfig->meas_window.v_size /
+ CIFISP_HIST_ROW_NUM - 1;
+
+ cifisp_iowrite32(block_hsize, CIF_ISP_HIST_H_SIZE);
+ cifisp_iowrite32(block_vsize, CIF_ISP_HIST_V_SIZE);
+
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[0],
+ pconfig->hist_weight[1], pconfig->hist_weight[2],
+ pconfig->hist_weight[3]), CIF_ISP_HIST_WEIGHT_00TO30);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[4],
+ pconfig->hist_weight[5], pconfig->hist_weight[6],
+ pconfig->hist_weight[7]), CIF_ISP_HIST_WEIGHT_40TO21);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[8],
+ pconfig->hist_weight[9], pconfig->hist_weight[10],
+ pconfig->hist_weight[11]), CIF_ISP_HIST_WEIGHT_31TO12);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[12],
+ pconfig->hist_weight[13], pconfig->hist_weight[14],
+ pconfig->hist_weight[15]), CIF_ISP_HIST_WEIGHT_22TO03);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[16],
+ pconfig->hist_weight[17], pconfig->hist_weight[18],
+ pconfig->hist_weight[19]), CIF_ISP_HIST_WEIGHT_13TO43);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[20],
+ pconfig->hist_weight[21], pconfig->hist_weight[22],
+ pconfig->hist_weight[23]), CIF_ISP_HIST_WEIGHT_04TO34);
+ cifisp_iowrite32(CIFISP_HIST_WEIGHT_SET(pconfig->hist_weight[24],
+ 0, 0, 0), CIF_ISP_HIST_WEIGHT_44);
+}
+
+static void cifisp_hst_en(struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_hst_config *pconfig =
+ &isp_dev->meas_cfgs.last_or_new->hst_config;
+
+ isp_dev->active_meas |= CIF_ISP_HIST_MEASURE_RDY;
+
+ cifisp_iowrite32OR(pconfig->mode,
+ CIF_ISP_HIST_PROP);
+}
+
+/*****************************************************************************/
+static void cifisp_hst_end(struct cif_isp10_isp_dev *isp_dev)
+{
+ /* Disable measurement */
+ cifisp_iowrite32(CIFISP_HISTOGRAM_MODE_DISABLE,
+ CIF_ISP_HIST_PROP);
+
+ isp_dev->active_meas &= ~CIF_ISP_HIST_MEASURE_RDY;
+}
+
+/*****************************************************************************/
+static void cifisp_get_hst_meas(const struct cif_isp10_isp_dev *isp_dev,
+ struct cifisp_stat_buffer *pbuf)
+{
+ int i;
+
+ pbuf->meas_type |= CIFISP_STAT_HIST;
+ for (i = 0; i < CIFISP_HIST_BIN_N_MAX; i++) {
+ pbuf->params.hist.hist_bins[i] =
+ cifisp_ioread32(CIF_ISP_HIST_BIN_0 + (i * 4));
+ }
+}
+
+/* IMAGE EFFECT */
+/*****************************************************************************/
+static void cifisp_ie_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_ie_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->ie_config;
+
+ switch (pconfig->effect) {
+ case V4L2_COLORFX_SET_CBCR:
+ cifisp_iowrite32(pconfig->eff_tint, CIF_IMG_EFF_TINT);
+ break;
+ /*
+ * Color selection is similar to water color(AQUA):
+ * grayscale + selected color w threshold
+ */
+ case V4L2_COLORFX_AQUA:
+ cifisp_iowrite32(pconfig->color_sel, CIF_IMG_EFF_COLOR_SEL);
+ break;
+ case V4L2_COLORFX_EMBOSS:
+ cifisp_iowrite32(pconfig->eff_mat_1, CIF_IMG_EFF_MAT_1);
+ cifisp_iowrite32(pconfig->eff_mat_2, CIF_IMG_EFF_MAT_2);
+ cifisp_iowrite32(pconfig->eff_mat_3, CIF_IMG_EFF_MAT_3);
+ break;
+ case V4L2_COLORFX_SKETCH:
+ cifisp_iowrite32(pconfig->eff_mat_3, CIF_IMG_EFF_MAT_3);
+ cifisp_iowrite32(pconfig->eff_mat_4, CIF_IMG_EFF_MAT_4);
+ cifisp_iowrite32(pconfig->eff_mat_5, CIF_IMG_EFF_MAT_5);
+ break;
+ default:
+ break;
+ }
+}
+
+static void cifisp_ie_en(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_ie_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->ie_config;
+ enum cif_isp10_image_effect effect;
+
+ switch (pconfig->effect) {
+ case V4L2_COLORFX_SEPIA:
+ case V4L2_COLORFX_SET_CBCR:
+ effect = CIF_ISP10_IE_SEPIA;
+ break;
+ case V4L2_COLORFX_BW:
+ effect = CIF_ISP10_IE_BW;
+ break;
+ case V4L2_COLORFX_NEGATIVE:
+ effect = CIF_ISP10_IE_NEGATIVE;
+ break;
+ case V4L2_COLORFX_EMBOSS:
+ effect = CIF_ISP10_IE_EMBOSS;
+ break;
+ case V4L2_COLORFX_SKETCH:
+ effect = CIF_ISP10_IE_SKETCH;
+ break;
+ case V4L2_COLORFX_AQUA:
+ effect = CIF_ISP10_IE_C_SEL;
+ break;
+ case V4L2_COLORFX_NONE:
+ default:
+ effect = CIF_ISP10_IE_NONE;
+ break;
+ }
+
+ if (effect < CIF_ISP10_IE_NONE) {
+ cifisp_iowrite32OR(CIF_ICCL_IE_CLK, CIF_ICCL);
+ cifisp_iowrite32(CIF_IMG_EFF_CTRL_ENABLE |
+ effect << 1, CIF_IMG_EFF_CTRL);
+ cifisp_iowrite32OR(CIF_IMG_EFF_CTRL_CFG_UPD, CIF_IMG_EFF_CTRL);
+ } else if (effect == CIF_ISP10_IE_NONE) {
+ cifisp_iowrite32AND(~CIF_IMG_EFF_CTRL_ENABLE, CIF_IMG_EFF_CTRL);
+ cifisp_iowrite32AND(~CIF_ICCL_IE_CLK, CIF_ICCL);
+ }
+}
+
+static void cifisp_ie_end(const struct cif_isp10_isp_dev *isp_dev)
+{
+ /* Disable measurement */
+ cifisp_iowrite32AND(~CIF_IMG_EFF_CTRL_ENABLE, CIF_IMG_EFF_CTRL);
+ cifisp_iowrite32AND(~CIF_ICCL_IE_CLK, CIF_ICCL);
+}
+
+static void cifisp_csm_config(const struct cif_isp10_isp_dev *isp_dev,
+ enum cif_isp10_pix_fmt_quantization quantization)
+{
+ const struct cifisp_ie_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->ie_config;
+
+ if ((quantization != CIF_ISP10_QUANTIZATION_FULL_RANGE) ||
+ ((pconfig->effect != V4L2_COLORFX_NONE) &&
+ CIFISP_MODULE_IS_EN(
+ isp_dev->other_cfgs.last_or_new->module_ens,
+ CIFISP_MODULE_CPROC))) {
+ /* Limit range conversion */
+ cifisp_iowrite32(0x21, CIF_ISP_CC_COEFF_0);
+ cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_1);
+ cifisp_iowrite32(0xd, CIF_ISP_CC_COEFF_2);
+ cifisp_iowrite32(0x1ed, CIF_ISP_CC_COEFF_3);
+ cifisp_iowrite32(0x1db, CIF_ISP_CC_COEFF_4);
+ cifisp_iowrite32(0x38, CIF_ISP_CC_COEFF_5);
+ cifisp_iowrite32(0x38, CIF_ISP_CC_COEFF_6);
+ cifisp_iowrite32(0x1d1, CIF_ISP_CC_COEFF_7);
+ cifisp_iowrite32(0x1f7, CIF_ISP_CC_COEFF_8);
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA,
+ CIF_ISP_CTRL);
+ cifisp_iowrite32AND(~CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA,
+ CIF_ISP_CTRL);
+ } else {
+ cifisp_iowrite32(0x26, CIF_ISP_CC_COEFF_0);
+ cifisp_iowrite32(0x4b, CIF_ISP_CC_COEFF_1);
+ cifisp_iowrite32(0xf, CIF_ISP_CC_COEFF_2);
+ cifisp_iowrite32(0x1ea, CIF_ISP_CC_COEFF_3);
+ cifisp_iowrite32(0x1d6, CIF_ISP_CC_COEFF_4);
+ cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_5);
+ cifisp_iowrite32(0x40, CIF_ISP_CC_COEFF_6);
+ cifisp_iowrite32(0x1ca, CIF_ISP_CC_COEFF_7);
+ cifisp_iowrite32(0x1f6, CIF_ISP_CC_COEFF_8);
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA,
+ CIF_ISP_CTRL);
+ cifisp_iowrite32OR(CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA,
+ CIF_ISP_CTRL);
+ }
+}
+
+/* DPF */
+/*****************************************************************************/
+static void cifisp_dpf_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_dpf_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->dpf_config;
+ unsigned int isp_dpf_mode;
+ unsigned int i;
+ unsigned int spatial_coeff;
+
+ isp_dpf_mode = 0x00;
+
+ switch (pconfig->gain.mode) {
+ case CIFISP_DPF_GAIN_USAGE_DISABLED:
+ break;
+ case CIFISP_DPF_GAIN_USAGE_NF_GAINS:
+ isp_dpf_mode |= CIFISP_DPF_MODE_USE_NF_GAIN |
+ CIFISP_DPF_MODE_AWB_GAIN_COMP;
+ break;
+ case CIFISP_DPF_GAIN_USAGE_LSC_GAINS:
+ isp_dpf_mode |= CIFISP_DPF_MODE_LSC_GAIN_COMP;
+ break;
+ case CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS:
+ isp_dpf_mode |= CIFISP_DPF_MODE_USE_NF_GAIN |
+ CIFISP_DPF_MODE_AWB_GAIN_COMP |
+ CIFISP_DPF_MODE_LSC_GAIN_COMP;
+ break;
+ case CIFISP_DPF_GAIN_USAGE_AWB_GAINS:
+ isp_dpf_mode |= CIFISP_DPF_MODE_AWB_GAIN_COMP;
+ break;
+ case CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS:
+ isp_dpf_mode |= CIFISP_DPF_MODE_LSC_GAIN_COMP |
+ CIFISP_DPF_MODE_AWB_GAIN_COMP;
+ break;
+ default:
+ break;
+ }
+
+ isp_dpf_mode |=
+ CIFISP_DPF_MODE_NLL_SEGMENTATION(pconfig->nll.scale_mode);
+ isp_dpf_mode |=
+ CIFISP_DPF_MODE_RB_FLTSIZE(pconfig->rb_flt.fltsize);
+
+ isp_dpf_mode |= (pconfig->rb_flt.r_enable) ?
+ CIFISP_DPF_MODE_R_FLT_EN : CIFISP_DPF_MODE_R_FLT_DIS;
+ isp_dpf_mode |= (pconfig->rb_flt.b_enable) ?
+ CIFISP_DPF_MODE_B_FLT_EN : CIFISP_DPF_MODE_B_FLT_DIS;
+ isp_dpf_mode |= (pconfig->g_flt.gb_enable) ?
+ CIFISP_DPF_MODE_GB_FLT_EN : CIFISP_DPF_MODE_GB_FLT_DIS;
+ isp_dpf_mode |= (pconfig->g_flt.gr_enable) ?
+ CIFISP_DPF_MODE_GR_FLT_EN : CIFISP_DPF_MODE_GR_FLT_DIS;
+
+ cifisp_iowrite32(isp_dpf_mode, CIF_ISP_DPF_MODE);
+ cifisp_iowrite32(pconfig->gain.nf_b_gain, CIF_ISP_DPF_NF_GAIN_B);
+ cifisp_iowrite32(pconfig->gain.nf_r_gain, CIF_ISP_DPF_NF_GAIN_R);
+ cifisp_iowrite32(pconfig->gain.nf_gb_gain, CIF_ISP_DPF_NF_GAIN_GB);
+ cifisp_iowrite32(pconfig->gain.nf_gr_gain, CIF_ISP_DPF_NF_GAIN_GR);
+
+ for (i = 0; i < CIFISP_DPF_MAX_NLF_COEFFS; i++) {
+ cifisp_iowrite32(pconfig->nll.coeff[i],
+ CIF_ISP_DPF_NULL_COEFF_0 + i * 4);
+ }
+
+ spatial_coeff = pconfig->g_flt.spatial_coeff[0] |
+ ((unsigned int)pconfig->g_flt.spatial_coeff[1] << 8) |
+ ((unsigned int)pconfig->g_flt.spatial_coeff[2] << 16) |
+ ((unsigned int)pconfig->g_flt.spatial_coeff[3] << 24);
+ cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_G_1_4);
+ spatial_coeff = pconfig->g_flt.spatial_coeff[4] |
+ ((unsigned int)pconfig->g_flt.spatial_coeff[5] << 8);
+ cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_G_5_6);
+ spatial_coeff = pconfig->rb_flt.spatial_coeff[0] |
+ ((unsigned int)pconfig->rb_flt.spatial_coeff[1] << 8) |
+ ((unsigned int)pconfig->rb_flt.spatial_coeff[2] << 16) |
+ ((unsigned int)pconfig->rb_flt.spatial_coeff[3] << 24);
+ cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_RB_1_4);
+ spatial_coeff = pconfig->rb_flt.spatial_coeff[4] |
+ ((unsigned int)pconfig->rb_flt.spatial_coeff[5] << 8);
+ cifisp_iowrite32(spatial_coeff, CIF_ISP_DPF_S_WEIGHT_RB_5_6);
+}
+
+static void cifisp_dpf_strength_config(const struct cif_isp10_isp_dev *isp_dev)
+{
+ const struct cifisp_dpf_strength_config *pconfig =
+ &isp_dev->other_cfgs.last_or_new->dpf_strength_config;
+
+ cifisp_iowrite32(pconfig->b, CIF_ISP_DPF_STRENGTH_B);
+ cifisp_iowrite32(pconfig->g, CIF_ISP_DPF_STRENGTH_G);
+ cifisp_iowrite32(pconfig->r, CIF_ISP_DPF_STRENGTH_R);
+}
+
+static void cifisp_dpf_en(struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32OR(CIFISP_DPF_MODE_EN,
+ CIF_ISP_DPF_MODE);
+}
+
+static void cifisp_dpf_end(struct cif_isp10_isp_dev *isp_dev)
+{
+ cifisp_iowrite32AND(~CIFISP_DPF_MODE_EN,
+ CIF_ISP_DPF_MODE);
+}
+
+/* ================================QUEUE OPS ================== */
+static int cifisp_stat_vbq_setup(struct videobuf_queue *vq,
+ unsigned int *cnt, unsigned int *size)
+{
+ *size = sizeof(struct cifisp_stat_buffer);
+
+ return 0;
+}
+
+static void cifisp_stat_vbq_release(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer entry!\n");
+
+ videobuf_waiton(vq, vb, 0, 0);
+
+ videobuf_vmalloc_free(vb);
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "Releasing buffer exit!\n");
+}
+
+static int cifisp_stat_vbq_prepare(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb,
+ enum v4l2_field field)
+{
+ int err = 0;
+
+ vb->size = sizeof(struct cifisp_stat_buffer);
+ vb->width = 0;
+ vb->height = 0;
+ vb->field = field;
+
+ if (vb->state == VIDEOBUF_NEEDS_INIT)
+ err = videobuf_iolock(vq, vb, NULL);
+
+ if (!err)
+ vb->state = VIDEOBUF_PREPARED;
+ else
+ cifisp_stat_vbq_release(vq, vb);
+
+ return err;
+}
+
+static void cifisp_stat_vbq_queue(struct videobuf_queue *vq,
+ struct videobuf_buffer *vb)
+{
+ struct cif_isp10_isp_dev *isp_dev = vq->priv_data;
+
+ vb->state = VIDEOBUF_QUEUED;
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "Queueing stat buffer!\n");
+
+ list_add_tail(&vb->queue, &isp_dev->stat);
+}
+
+/* Queue Ops */
+static struct videobuf_queue_ops cifisp_stat_qops = {
+ .buf_setup = cifisp_stat_vbq_setup,
+ .buf_prepare = cifisp_stat_vbq_prepare,
+ .buf_queue = cifisp_stat_vbq_queue,
+ .buf_release = cifisp_stat_vbq_release,
+};
+
+/* ================== IOCTL implementation ========================= */
+static int cifisp_reqbufs(struct file *file, void *priv,
+ struct v4l2_requestbuffers *p)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: p->type %d p->count %d\n",
+ ISP_VDEV_NAME, __func__, p->type, p->count);
+
+ return videobuf_reqbufs(&isp_dev->vbq_stat, p);
+}
+
+static int cifisp_querybuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: p->type %d p->index %d\n",
+ ISP_VDEV_NAME, __func__, p->type, p->index);
+
+ return videobuf_querybuf(&isp_dev->vbq_stat, p);
+}
+
+static int cifisp_qbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: p->type %d p->index %d\n",
+ ISP_VDEV_NAME, __func__, p->type, p->index);
+
+ return videobuf_qbuf(&isp_dev->vbq_stat, p);
+}
+
+/* ========================================================== */
+
+static int cifisp_dqbuf(struct file *file, void *priv, struct v4l2_buffer *p)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: p->type %d p->index %d\n",
+ ISP_VDEV_NAME, __func__, p->type, p->index);
+
+ return videobuf_dqbuf(&isp_dev->vbq_stat, p,
+ file->f_flags & O_NONBLOCK);
+}
+
+static int cifisp_streamon(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ int ret = videobuf_streamon(&isp_dev->vbq_stat);
+
+ if (ret == 0)
+ isp_dev->streamon = true;
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: ret %d\n", ISP_VDEV_NAME, __func__, ret);
+
+ return ret;
+}
+
+/* ========================================================== */
+static int cifisp_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+ int ret;
+
+ drain_workqueue(isp_dev->readout_wq);
+
+ ret = videobuf_streamoff(&isp_dev->vbq_stat);
+
+ if (ret == 0)
+ isp_dev->streamon = false;
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " %s: %s: ret %d\n", ISP_VDEV_NAME, __func__, ret);
+
+ return ret;
+}
+
+static int cifisp_g_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+ int ret;
+
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ switch (vc->id) {
+ case V4L2_CID_CIFISP_DPCC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_DPCC);
+ break;
+ case V4L2_CID_CIFISP_BLS:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_BLS);
+ break;
+ case V4L2_CID_CIFISP_SDG:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_SDG);
+ break;
+ case V4L2_CID_CIFISP_LSC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_LSC);
+ break;
+ case V4L2_CID_CIFISP_AWB_MEAS:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_AWB);
+ break;
+ case V4L2_CID_CIFISP_AWB_GAIN:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_AWB_GAIN);
+ break;
+ case V4L2_CID_CIFISP_FLT:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_FLT);
+ break;
+ case V4L2_CID_CIFISP_BDM:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_BDM);
+ break;
+ case V4L2_CID_CIFISP_CTK:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_CTK);
+ break;
+ case V4L2_CID_CIFISP_GOC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_GOC);
+ break;
+ case V4L2_CID_CIFISP_HST:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_HST);
+ break;
+ case V4L2_CID_CIFISP_AEC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_AEC);
+ break;
+ case V4L2_CID_CIFISP_CPROC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_CPROC);
+ break;
+ case V4L2_CID_CIFISP_AFC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_AFC);
+ break;
+ case V4L2_CID_CIFISP_IE:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_IE);
+ break;
+ case V4L2_CID_CIFISP_DPF:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _GET_,
+ &vc->value,
+ CIFISP_MODULE_DPF);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int cifisp_s_ctrl(struct file *file, void *priv, struct v4l2_control *vc)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+ int ret;
+
+ switch (vc->id) {
+ case V4L2_CID_CIFISP_DPCC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_DPCC);
+ break;
+ case V4L2_CID_CIFISP_BLS:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_BLS);
+ break;
+ case V4L2_CID_CIFISP_SDG:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_SDG);
+ break;
+ case V4L2_CID_CIFISP_LSC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_LSC);
+ break;
+ case V4L2_CID_CIFISP_AWB_MEAS:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_AWB);
+ break;
+ case V4L2_CID_CIFISP_AWB_GAIN:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_AWB_GAIN);
+ break;
+ case V4L2_CID_CIFISP_FLT:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_FLT);
+ break;
+ case V4L2_CID_CIFISP_BDM:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_BDM);
+ break;
+ case V4L2_CID_CIFISP_CTK:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_CTK);
+ break;
+ case V4L2_CID_CIFISP_GOC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_GOC);
+ break;
+ case V4L2_CID_CIFISP_HST:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_HST);
+ break;
+ case V4L2_CID_CIFISP_AEC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_AEC);
+ break;
+ case V4L2_CID_CIFISP_CPROC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_CPROC);
+ break;
+ case V4L2_CID_CIFISP_AFC:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_AFC);
+ break;
+ case V4L2_CID_CIFISP_IE:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_IE);
+ break;
+ case V4L2_CID_CIFISP_DPF:
+ ret = cifisp_module_enable(
+ isp_dev,
+ _SET_,
+ &vc->value,
+ CIFISP_MODULE_DPF);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static long cifisp_ioctl_default(struct file *file,
+ void *fh, bool valid_prio, unsigned int cmd, void *arg)
+{
+ struct cif_isp10_isp_dev *isp = video_get_drvdata(video_devdata(file));
+ long ret;
+
+ switch (cmd) {
+ case CIFISP_IOC_G_DPCC:
+ ret = cifisp_dpcc_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_DPCC:
+ ret = cifisp_dpcc_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_BLS:
+ ret = cifisp_bls_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_BLS:
+ ret = cifisp_bls_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_SDG:
+ ret = cifisp_sdg_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_SDG:
+ ret = cifisp_sdg_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_LSC:
+ ret = cifisp_lsc_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_LSC:
+ ret = cifisp_lsc_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_AWB_MEAS:
+ ret = cifisp_awb_meas_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_AWB_MEAS:
+ ret = cifisp_awb_meas_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_AWB_GAIN:
+ ret = cifisp_awb_gain_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_AWB_GAIN:
+ ret = cifisp_awb_gain_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_FLT:
+ ret = cifisp_flt_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_FLT:
+ ret = cifisp_flt_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_BDM:
+ ret = cifisp_bdm_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_BDM:
+ ret = cifisp_bdm_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_CTK:
+ ret = cifisp_ctk_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_CTK:
+ ret = cifisp_ctk_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_GOC:
+ ret = cifisp_goc_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_GOC:
+ ret = cifisp_goc_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_HST:
+ ret = cifisp_hst_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_HST:
+ ret = cifisp_hst_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_AEC:
+ ret = cifisp_aec_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_AEC:
+ ret = cifisp_aec_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_CPROC:
+ ret = cifisp_cproc_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_CPROC:
+ ret = cifisp_cproc_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_AFC:
+ ret = cifisp_afc_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_AFC:
+ ret = cifisp_afc_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_IE:
+ ret = cifisp_ie_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_IE:
+ ret = cifisp_ie_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_DPF:
+ ret = cifisp_dpf_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_DPF:
+ ret = cifisp_dpf_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_DPF_STRENGTH:
+ ret = cifisp_dpf_strength_param(isp, _GET_, arg);
+ break;
+ case CIFISP_IOC_S_DPF_STRENGTH:
+ ret = cifisp_dpf_strength_param(isp, _SET_, arg);
+ break;
+ case CIFISP_IOC_G_LAST_CONFIG:
+ ret = cifisp_last_capture_config(arg);
+ break;
+ default:
+ ret = -EINVAL;
+ break;
+ }
+ return ret;
+}
+
+static int cifisp_g_fmt_vid_cap(struct file *file, void *fh,
+ struct v4l2_format *f)
+{
+ /*
+ * Dummy function needed to allow allocation of
+ * buffers on this device
+ */
+ return 0;
+}
+
+static int cifisp_querycap(struct file *file,
+ void *priv, struct v4l2_capability *cap)
+{
+ struct video_device *vdev = video_devdata(file);
+ struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(vdev);
+
+ strcpy(cap->driver, DRIVER_NAME);
+ strlcpy(cap->card, vdev->name, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "platform:" DRIVER_NAME "-%03i",
+ *isp_dev->dev_id);
+
+ cap->capabilities = V4L2_CAP_DEVICE_CAPS;
+ cap->device_caps = V4L2_CAP_DEVICE_CAPS;
+ return 0;
+}
+
+/* ISP video device IOCTLs */
+static const struct v4l2_ioctl_ops cifisp_ioctl = {
+ .vidioc_reqbufs = cifisp_reqbufs,
+ .vidioc_querybuf = cifisp_querybuf,
+ .vidioc_qbuf = cifisp_qbuf,
+ .vidioc_dqbuf = cifisp_dqbuf,
+ .vidioc_streamon = cifisp_streamon,
+ .vidioc_streamoff = cifisp_streamoff,
+ .vidioc_g_ctrl = cifisp_g_ctrl,
+ .vidioc_s_ctrl = cifisp_s_ctrl,
+ .vidioc_default = cifisp_ioctl_default,
+ .vidioc_g_fmt_vid_cap = cifisp_g_fmt_vid_cap,
+ .vidioc_querycap = cifisp_querycap
+};
+
+/* ======================================================== */
+
+static unsigned int cifisp_poll(struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+ unsigned int ret;
+
+ ret = videobuf_poll_stream(file, &isp_dev->vbq_stat, wait);
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "Polling on vbq_stat buffer %d\n", ret);
+
+ return ret;
+}
+
+/* ======================================================== */
+static int cifisp_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ return videobuf_mmap_mapper(&isp_dev->vbq_stat, vma);
+}
+
+/* ddl@rock-chips.com: v1.0.8 */
+static int cifisp_reset(struct file *file)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ memset(isp_dev->other_cfgs.cfgs, 0, sizeof(isp_dev->other_cfgs.cfgs));
+ memset(isp_dev->meas_cfgs.cfgs, 0, sizeof(isp_dev->meas_cfgs.cfgs));
+
+ isp_dev->other_cfgs.last_or_new = &isp_dev->other_cfgs.cfgs[0];
+ isp_dev->other_cfgs.curr = &isp_dev->other_cfgs.cfgs[1];
+ isp_dev->other_cfgs.module_updates = 0;
+
+ isp_dev->meas_cfgs.last_or_new = &isp_dev->meas_cfgs.cfgs[0];
+ isp_dev->meas_cfgs.curr = &isp_dev->meas_cfgs.cfgs[1];
+ isp_dev->meas_cfgs.module_updates = 0;
+ isp_dev->active_lsc_width = 0;
+ isp_dev->active_lsc_height = 0;
+
+ isp_dev->streamon = false;
+ isp_dev->active_meas = 0;
+ isp_dev->frame_id = 0;
+ isp_dev->cif_ism_cropping = false;
+ return 0;
+}
+
+static int cifisp_open(struct file *file)
+{
+ CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_open\n");
+
+ cifisp_reset(file);
+
+ return 0;
+}
+
+static int cifisp_close(struct file *file)
+{
+ struct cif_isp10_isp_dev *isp_dev =
+ video_get_drvdata(video_devdata(file));
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_close\n");
+
+ videobuf_stop(&isp_dev->vbq_stat);
+ videobuf_mmap_free(&isp_dev->vbq_stat);
+
+ /* cifisp_reset(file); */
+ return 0;
+}
+
+struct v4l2_file_operations cifisp_fops = {
+ .mmap = cifisp_mmap,
+ .unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2,
+#endif
+ .poll = cifisp_poll,
+ .open = cifisp_open,
+ .release = cifisp_close
+};
+
+static void cifisp_release(struct video_device *vdev)
+{
+ struct cif_isp10_isp_dev *isp_dev = video_get_drvdata(vdev);
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "cifisp_release\n");
+ video_device_release(vdev);
+ destroy_workqueue(isp_dev->readout_wq);
+}
+
+/************************************************************/
+int register_cifisp_device(struct cif_isp10_isp_dev *isp_dev,
+ struct video_device *vdev_cifisp,
+ struct v4l2_device *v4l2_dev,
+ void __iomem *cif_reg_baseaddress)
+{
+ isp_dev->base_addr = cif_reg_baseaddress;
+ WARN_ON(!(isp_dev->base_addr));
+
+ INIT_LIST_HEAD(&isp_dev->stat);
+ spin_lock_init(&isp_dev->irq_lock);
+ spin_lock_init(&isp_dev->config_lock);
+ strlcpy(vdev_cifisp->name, ISP_VDEV_NAME, sizeof(vdev_cifisp->name));
+ vdev_cifisp->vfl_type = V4L2_CAP_VIDEO_CAPTURE;
+ video_set_drvdata(vdev_cifisp, isp_dev);
+ vdev_cifisp->ioctl_ops = &cifisp_ioctl;
+ vdev_cifisp->fops = &cifisp_fops;
+
+ /*
+ * This might not release all resources,
+ * but unregistering is anyway not going to happen.
+ */
+ vdev_cifisp->release = cifisp_release;
+ mutex_init(&isp_dev->mutex);
+ /*
+ * Provide a mutex to v4l2 core. It will be used
+ * to protect all fops and v4l2 ioctls.
+ */
+ vdev_cifisp->lock = &isp_dev->mutex;
+ vdev_cifisp->v4l2_dev = v4l2_dev;
+
+ videobuf_queue_vmalloc_init(
+ &isp_dev->vbq_stat,
+ &cifisp_stat_qops,
+ NULL,
+ &isp_dev->irq_lock,
+ V4L2_BUF_TYPE_VIDEO_CAPTURE,
+ V4L2_FIELD_NONE,
+ sizeof(struct videobuf_buffer),
+ isp_dev,
+ NULL); /* ext_lock: NULL */
+
+ if (video_register_device(vdev_cifisp, VFL_TYPE_GRABBER, -1) < 0) {
+ dev_err(&vdev_cifisp->dev,
+ "could not register Video for Linux device\n");
+ return -ENODEV;
+ }
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "%s: CIFISP vdev minor = %d\n",
+ __func__, vdev_cifisp->minor);
+
+ isp_dev->readout_wq =
+ alloc_workqueue("measurement_queue",
+ WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
+
+ if (!isp_dev->readout_wq)
+ return -ENOMEM;
+
+ isp_dev->v_blanking_us = CIFISP_MODULE_DEFAULT_VBLANKING_TIME;
+
+ return 0;
+}
+
+void unregister_cifisp_device(struct video_device *vdev_cifisp)
+{
+ if (!IS_ERR_OR_NULL(vdev_cifisp))
+ video_unregister_device(vdev_cifisp);
+}
+
+static void cifisp_dump_reg(struct cif_isp10_isp_dev *isp_dev, int level)
+{
+#ifdef CIFISP_DEBUG_REG
+ if (isp_dev->dpcc_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_DPCC, level);
+
+ if (isp_dev->lsc_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_LSC, level);
+
+ if (isp_dev->bls_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_BLS, level);
+
+ if (isp_dev->sdg_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_SDG, level);
+
+ if (isp_dev->goc_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_GOC, level);
+
+ if (isp_dev->bdm_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_BDM, level);
+
+ if (isp_dev->flt_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_FLT, level);
+
+ if (isp_dev->awb_meas_en || isp_dev->awb_gain_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_AWB, level);
+
+ if (isp_dev->aec_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_AEC, level);
+
+ if (isp_dev->ctk_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_CTK, level);
+
+ if (isp_dev->cproc_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_CPROC, level);
+
+ if (isp_dev->afc_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_AFC, level);
+
+ if (isp_dev->hst_en)
+ cifisp_reg_dump(isp_dev, CIFISP_MODULE_HST, level);
+#endif
+}
+
+static inline void cifisp_meas_config_swap(
+ struct cif_isp10_isp_dev *isp_dev)
+{
+ struct cifisp_isp_meas_cfg *new_cfg;
+
+ new_cfg = isp_dev->meas_cfgs.last_or_new;
+ new_cfg->s_frame_id = isp_dev->frame_id;
+ isp_dev->meas_cfgs.last_or_new =
+ isp_dev->meas_cfgs.curr;
+ isp_dev->meas_cfgs.curr = new_cfg;
+}
+
+static inline void cifisp_other_config_swap(
+ struct cif_isp10_isp_dev *isp_dev)
+{
+ struct cifisp_isp_other_cfg *new_cfg;
+
+ new_cfg = isp_dev->other_cfgs.last_or_new;
+ new_cfg->s_frame_id = isp_dev->frame_id;
+ isp_dev->other_cfgs.last_or_new =
+ isp_dev->other_cfgs.curr;
+ isp_dev->other_cfgs.curr = new_cfg;
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void cifisp_configure_isp(
+ struct cif_isp10_isp_dev *isp_dev,
+ enum cif_isp10_pix_fmt in_pix_fmt,
+ enum cif_isp10_pix_fmt_quantization quantization)
+{
+ unsigned int *other_ens, *other_updates;
+ unsigned int *meas_ens, *meas_updates;
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "%s\n", __func__);
+
+ mutex_lock(&isp_dev->mutex);
+ spin_lock(&isp_dev->config_lock);
+
+ other_ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+ other_updates = &isp_dev->other_cfgs.module_updates;
+ meas_ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+ meas_updates = &isp_dev->meas_cfgs.module_updates;
+ isp_dev->quantization = quantization;
+ if (CIF_ISP10_PIX_FMT_IS_RAW_BAYER(in_pix_fmt)) {
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_DPCC)) {
+ cifisp_dpcc_config(isp_dev);
+ cifisp_dpcc_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_DPCC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_LSC)) {
+ if (cifisp_lsc_config(isp_dev))
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_LSC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_BLS)) {
+ cifisp_bls_config(isp_dev);
+ cifisp_bls_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_BLS);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_SDG)) {
+ cifisp_sdg_config(isp_dev);
+ cifisp_sdg_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_SDG);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_GOC)) {
+ cifisp_goc_config(isp_dev);
+ cifisp_goc_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_GOC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_BDM)) {
+ cifisp_bdm_config(isp_dev);
+ cifisp_bdm_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_BDM);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_FLT)) {
+ cifisp_flt_config(isp_dev);
+ cifisp_flt_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_FLT);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_AWB_GAIN)) {
+ cifisp_awb_gain_config(isp_dev);
+ cifisp_awb_gain_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_AWB_GAIN);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CTK)) {
+ cifisp_ctk_config(isp_dev);
+ cifisp_ctk_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_CTK);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CPROC)) {
+ cifisp_cproc_config(isp_dev, quantization);
+ cifisp_cproc_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_CPROC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_IE)) {
+ cifisp_ie_config(isp_dev);
+ cifisp_ie_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_IE);
+ }
+
+ cifisp_csm_config(isp_dev, quantization);
+
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_DPF)) {
+ cifisp_dpf_config(isp_dev);
+ cifisp_dpf_strength_config(isp_dev);
+ cifisp_dpf_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_DPF | CIFISP_MODULE_DPF_STRENGTH);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AFC)) {
+ cifisp_afc_config(isp_dev);
+ cifisp_afc_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AFC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AWB)) {
+ cifisp_awb_meas_config(isp_dev);
+ cifisp_awb_meas_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AWB);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_AEC)) {
+ cifisp_aec_config(isp_dev);
+ cifisp_aec_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AEC);
+ }
+
+ if (CIFISP_MODULE_IS_EN(*meas_ens, CIFISP_MODULE_HST)) {
+ cifisp_hst_config(isp_dev);
+ cifisp_hst_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_HST);
+ }
+ } else {
+ /* Disable modules for yuv */
+ cifisp_dpcc_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_DPCC);
+
+ cifisp_lsc_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_LSC);
+
+ cifisp_bls_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_BLS);
+
+ cifisp_sdg_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_SDG);
+
+ cifisp_goc_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_GOC);
+
+ cifisp_bdm_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_BDM);
+
+ cifisp_flt_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_FLT);
+
+ cifisp_awb_meas_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AWB);
+
+ cifisp_awb_gain_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_AWB_GAIN);
+
+ cifisp_aec_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AEC);
+
+ cifisp_ctk_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_CTK);
+
+ cifisp_dpf_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_DPF);
+
+ /* cproc can be used for yuv in reduced range */
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_CPROC)) {
+ cifisp_cproc_config(isp_dev, false);
+ cifisp_cproc_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_CPROC);
+ }
+
+ cifisp_hst_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_HST);
+
+ cifisp_afc_end(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*meas_updates,
+ CIFISP_MODULE_AFC);
+ /* ie can be used for yuv */
+ if (CIFISP_MODULE_IS_EN(*other_ens, CIFISP_MODULE_IE)) {
+ cifisp_ie_config(isp_dev);
+ cifisp_ie_en(isp_dev);
+ CIFISP_MODULE_CLR_UPDATE(*other_updates,
+ CIFISP_MODULE_IE);
+ } else {
+ cifisp_ie_end(isp_dev);
+ }
+ }
+
+ cifisp_dump_reg(isp_dev, CIFISP_DEBUG);
+
+ cifisp_meas_config_swap(isp_dev);
+ cifisp_other_config_swap(isp_dev);
+
+ memcpy(isp_dev->other_cfgs.last_or_new,
+ isp_dev->other_cfgs.curr,
+ sizeof(struct cifisp_isp_other_cfg));
+ memcpy(isp_dev->meas_cfgs.last_or_new,
+ isp_dev->meas_cfgs.curr,
+ sizeof(struct cifisp_isp_meas_cfg));
+
+ spin_unlock(&isp_dev->config_lock);
+ mutex_unlock(&isp_dev->mutex);
+}
+
+void cifisp_frame_in(
+ struct cif_isp10_isp_dev *isp_dev,
+ const struct timeval *fi_t)
+{
+ /* Called in an interrupt context. */
+ isp_dev->fi_t = *fi_t;
+}
+
+void cifisp_v_start(
+ struct cif_isp10_isp_dev *isp_dev,
+ const struct timeval *vs_t)
+{
+ /* Called in an interrupt context. */
+ isp_dev->frame_id += 2;
+ isp_dev->vs_t = *vs_t;
+}
+
+/* Not called when the camera active, thus not isr protection. */
+void cifisp_disable_isp(struct cif_isp10_isp_dev *isp_dev)
+{
+ CIFISP_DPRINT(CIFISP_DEBUG, "%s\n", __func__);
+
+ mutex_lock(&isp_dev->mutex);
+
+ cifisp_dpcc_end(isp_dev);
+ cifisp_lsc_end(isp_dev);
+ cifisp_bls_end(isp_dev);
+ cifisp_sdg_end(isp_dev);
+ cifisp_goc_end(isp_dev);
+ cifisp_bdm_end(isp_dev);
+ cifisp_flt_end(isp_dev);
+ cifisp_awb_meas_end(isp_dev);
+ cifisp_awb_gain_end(isp_dev);
+ cifisp_aec_end(isp_dev);
+ cifisp_ctk_end(isp_dev);
+ cifisp_cproc_end(isp_dev);
+ cifisp_hst_end(isp_dev);
+ cifisp_afc_end(isp_dev);
+ cifisp_ie_end(isp_dev);
+ cifisp_dpf_end(isp_dev);
+
+ /*
+ * Isp isn't active, isp interrupt isn't enabled, spin_lock is enough;
+ */
+ spin_lock(&isp_dev->config_lock);
+
+ isp_dev->other_cfgs.last_or_new->module_ens = 0;
+ isp_dev->meas_cfgs.last_or_new->module_ens = 0;
+
+ /*
+ * 1. Swap last_or_new and curr pointer;
+ * 2. Sync last_or_new and curr configuration;
+ */
+ cifisp_meas_config_swap(isp_dev);
+ cifisp_other_config_swap(isp_dev);
+
+ memcpy(isp_dev->other_cfgs.last_or_new,
+ isp_dev->other_cfgs.curr,
+ sizeof(struct cifisp_isp_other_cfg));
+ memcpy(isp_dev->meas_cfgs.last_or_new,
+ isp_dev->meas_cfgs.curr,
+ sizeof(struct cifisp_isp_meas_cfg));
+
+ spin_unlock(&isp_dev->config_lock);
+
+ mutex_unlock(&isp_dev->mutex);
+}
+
+static void cifisp_send_measurement(
+ struct cif_isp10_isp_dev *isp_dev,
+ struct cif_isp10_isp_readout_work *meas_work)
+{
+ unsigned long lock_flags = 0;
+ struct videobuf_buffer *vb = NULL;
+ unsigned int active_meas = isp_dev->active_meas;
+ struct cifisp_stat_buffer *stat_buf;
+ struct cif_isp10_device *cif_dev =
+ container_of(isp_dev, struct cif_isp10_device, isp_dev);
+
+ spin_lock_irqsave(&isp_dev->irq_lock, lock_flags);
+ if (isp_dev->frame_id != meas_work->frame_id) {
+ spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "Measurement late(%d, %d)\n",
+ isp_dev->frame_id,
+ meas_work->frame_id);
+ goto end;
+ }
+
+ if (!list_empty(&isp_dev->stat)) {
+ vb = list_first_entry(&isp_dev->stat,
+ struct videobuf_buffer, queue);
+ } else {
+ spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "Not enought measurement bufs\n");
+ goto end;
+ }
+
+ spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+ vb->state = VIDEOBUF_ACTIVE;
+
+ stat_buf = (struct cifisp_stat_buffer *)videobuf_to_vmalloc(vb);
+ memset(stat_buf, 0x00, sizeof(struct cifisp_stat_buffer));
+
+ if (active_meas & CIF_ISP_AWB_DONE)
+ cifisp_get_awb_meas(isp_dev, stat_buf);
+
+ if (active_meas & CIF_ISP_AFM_FIN)
+ cifisp_get_afc_meas(isp_dev, stat_buf);
+
+ if (active_meas & CIF_ISP_EXP_END) {
+ cifisp_get_aec_meas(isp_dev, stat_buf);
+ cifisp_bls_get_meas(isp_dev, stat_buf);
+ }
+
+ if (active_meas & CIF_ISP_HIST_MEASURE_RDY)
+ cifisp_get_hst_meas(isp_dev, stat_buf);
+
+ spin_lock_irqsave(&isp_dev->irq_lock, lock_flags);
+
+ if (isp_dev->frame_id != meas_work->frame_id) {
+ spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "Measurement late(%d, %d)\n",
+ isp_dev->frame_id,
+ meas_work->frame_id);
+ goto end;
+ }
+
+ vb->ts = isp_dev->vs_t;
+ list_del(&vb->queue);
+ spin_unlock_irqrestore(&isp_dev->irq_lock, lock_flags);
+
+ if (active_meas & CIF_ISP_AWB_DONE) {
+ memcpy(&isp_dev->meas_stats.stat.params.awb,
+ &stat_buf->params.awb,
+ sizeof(struct cifisp_awb_stat));
+ isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AWB;
+ }
+ if (active_meas & CIF_ISP_AFM_FIN) {
+ memcpy(&isp_dev->meas_stats.stat.params.af,
+ &stat_buf->params.af,
+ sizeof(struct cifisp_af_stat));
+ isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AFM_FIN;
+ }
+ if (active_meas & CIF_ISP_EXP_END) {
+ cif_isp10_sensor_mode_data_sync(cif_dev,
+ meas_work->frame_id,
+ &stat_buf->sensor_mode);
+ memcpy(&isp_dev->meas_stats.stat.params.ae,
+ &stat_buf->params.ae,
+ sizeof(struct cifisp_ae_stat));
+ memcpy(&isp_dev->meas_stats.stat.sensor_mode,
+ &stat_buf->sensor_mode,
+ sizeof(struct isp_supplemental_sensor_mode_data));
+
+ isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_AUTOEXP;
+ }
+ if (active_meas & CIF_ISP_HIST_MEASURE_RDY) {
+ memcpy(&isp_dev->meas_stats.stat.params.hist,
+ &stat_buf->params.hist,
+ sizeof(struct cifisp_hist_stat));
+ isp_dev->meas_stats.stat.meas_type |= CIFISP_STAT_HIST;
+ }
+ isp_dev->meas_stats.g_frame_id = meas_work->frame_id;
+
+ vb->field_count = meas_work->frame_id;
+ vb->state = VIDEOBUF_DONE;
+ wake_up(&vb->done);
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "Measurement done(%d, %d)\n",
+ vb->field_count,
+ vb->i);
+ vb = NULL;
+end:
+
+ if (vb && (vb->state == VIDEOBUF_ACTIVE))
+ vb->state = VIDEOBUF_QUEUED;
+}
+
+void cifisp_isp_readout_work(struct work_struct *work)
+{
+ struct cif_isp10_isp_readout_work *readout_work =
+ (struct cif_isp10_isp_readout_work *)work;
+ struct cif_isp10_isp_dev *isp_dev =
+ readout_work->isp_dev;
+ struct cif_isp10_device *cif_dev =
+ container_of(isp_dev, struct cif_isp10_device, isp_dev);
+ unsigned long int lock_flags;
+
+ if (!isp_dev->streamon)
+ return;
+
+ switch (readout_work->readout) {
+ case CIF_ISP10_ISP_READOUT_MEAS:
+ cifisp_send_measurement(isp_dev, readout_work);
+ break;
+
+ case CIF_ISP10_ISP_READOUT_META: {
+ struct cifisp_isp_other_cfg *other_new = NULL;
+ struct cifisp_isp_meas_cfg *meas_new = NULL;
+ struct cifisp_stat_buffer *stat_new = NULL;
+
+ spin_lock_irqsave(&isp_dev->config_lock, lock_flags);
+
+ if (isp_dev->other_cfgs.module_updates == 0) {
+ if (readout_work->frame_id ==
+ isp_dev->other_cfgs.curr->s_frame_id)
+ other_new = isp_dev->other_cfgs.last_or_new;
+ else if (readout_work->frame_id >
+ isp_dev->other_cfgs.curr->s_frame_id)
+ other_new = isp_dev->other_cfgs.curr;
+ else
+ other_new = NULL;
+ }
+
+ if (isp_dev->meas_cfgs.module_updates == 0) {
+ if (readout_work->frame_id ==
+ isp_dev->meas_cfgs.curr->s_frame_id)
+ meas_new = isp_dev->meas_cfgs.last_or_new;
+ else if (readout_work->frame_id >
+ isp_dev->meas_cfgs.curr->s_frame_id)
+ meas_new = isp_dev->meas_cfgs.curr;
+ else
+ meas_new = NULL;
+ }
+
+ if ((isp_dev->meas_stats.g_frame_id ==
+ readout_work->frame_id) &&
+ isp_dev->meas_stats.stat.meas_type)
+ stat_new = &isp_dev->meas_stats.stat;
+ else
+ stat_new = NULL;
+
+ cif_isp10_s_isp_metadata(
+ cif_dev,
+ readout_work,
+ other_new,
+ meas_new,
+ stat_new);
+ spin_unlock_irqrestore(&isp_dev->config_lock, lock_flags);
+
+ break;
+ }
+ default:
+ break;
+ }
+
+ kfree((void *)work);
+}
+
+static inline bool cifisp_isp_isr_other_config(
+ struct cif_isp10_isp_dev *isp_dev,
+ unsigned int *time_left)
+{
+ unsigned int time_in = *time_left;
+ bool config_chk;
+ unsigned int *ens;
+
+ ens = &isp_dev->other_cfgs.last_or_new->module_ens;
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPCC)) {
+ /*update dpc config */
+ cifisp_dpcc_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPCC))
+ cifisp_dpcc_en(isp_dev);
+ else
+ cifisp_dpcc_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPCC);
+
+ *time_left -= CIFISP_MODULE_DPCC_PROC_TIME;
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "dpcc time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BLS) &&
+ *time_left >= CIFISP_MODULE_BLS_PROC_TIME) {
+ /* update bls config */
+ cifisp_bls_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_BLS))
+ cifisp_bls_en(isp_dev);
+ else
+ cifisp_bls_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BLS);
+
+ *time_left -= CIFISP_MODULE_BLS_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "bls time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_SDG) &&
+ *time_left >= CIFISP_MODULE_SDG_PROC_TIME) {
+ /* update sdg config */
+ cifisp_sdg_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_SDG))
+ cifisp_sdg_en(isp_dev);
+ else
+ cifisp_sdg_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_SDG);
+
+ *time_left -= CIFISP_MODULE_SDG_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "sdg time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_LSC) &&
+ *time_left >= CIFISP_MODULE_LSC_PROC_TIME) {
+ /* update lsc config */
+ bool res = true;
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_LSC)) {
+ if (!cifisp_lsc_config(isp_dev))
+ res = false;
+ } else {
+ cifisp_lsc_end(isp_dev);
+ }
+
+ if (res)
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_LSC);
+
+ *time_left -= CIFISP_MODULE_LSC_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "lsc time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_AWB_GAIN) &&
+ *time_left >= CIFISP_MODULE_AWB_GAIN_PROC_TIME) {
+ /* update awb gains */
+ cifisp_awb_gain_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AWB_GAIN))
+ cifisp_awb_gain_en(isp_dev);
+ else
+ cifisp_awb_gain_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_AWB_GAIN);
+
+ *time_left -= CIFISP_MODULE_AWB_GAIN_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "awb-g time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BDM) &&
+ *time_left >= CIFISP_MODULE_BDM_PROC_TIME) {
+ /* update bdm config */
+ cifisp_bdm_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_BDM))
+ cifisp_bdm_en(isp_dev);
+ else
+ cifisp_bdm_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_BDM);
+
+ *time_left -= CIFISP_MODULE_BDM_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "bdm time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_FLT) &&
+ *time_left >= CIFISP_MODULE_FLT_PROC_TIME) {
+ /* update filter config */
+ cifisp_flt_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_FLT))
+ cifisp_flt_en(isp_dev);
+ else
+ cifisp_flt_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_FLT);
+
+ *time_left -= CIFISP_MODULE_FLT_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "flt time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CTK) &&
+ *time_left >= CIFISP_MODULE_CTK_PROC_TIME) {
+ /* update ctk config */
+ cifisp_ctk_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_CTK))
+ cifisp_ctk_en(isp_dev);
+ else
+ cifisp_ctk_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CTK);
+
+ *time_left -= CIFISP_MODULE_CTK_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "ctk time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_GOC) &&
+ *time_left >= CIFISP_MODULE_GOC_PROC_TIME) {
+ /* update goc config */
+ cifisp_goc_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_GOC))
+ cifisp_goc_en(isp_dev);
+ else
+ cifisp_goc_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_IE);
+
+ *time_left -= CIFISP_MODULE_GOC_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "goc time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CPROC) &&
+ *time_left >= CIFISP_MODULE_CPROC_PROC_TIME) {
+ /* update cprc config */
+ cifisp_cproc_config(
+ isp_dev,
+ isp_dev->quantization);
+
+ cifisp_csm_config(isp_dev,
+ isp_dev->quantization);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_CPROC))
+ cifisp_cproc_en(isp_dev);
+ else
+ cifisp_cproc_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_CPROC);
+
+ *time_left -= CIFISP_MODULE_CPROC_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "cproc time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_IE) &&
+ *time_left >= CIFISP_MODULE_IE_PROC_TIME) {
+ /* update ie config */
+ cifisp_ie_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_IE))
+ cifisp_ie_en(isp_dev);
+ else
+ cifisp_ie_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_IE);
+
+ *time_left -= CIFISP_MODULE_IE_PROC_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "ie time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF) &&
+ *time_left >= CIFISP_MODULE_DPF_TIME) {
+ /* update dpf config */
+ cifisp_dpf_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPF))
+ cifisp_dpf_en(isp_dev);
+ else
+ cifisp_dpf_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF);
+
+ *time_left -= CIFISP_MODULE_DPF_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "dpf time-left :%d\n",
+ *time_left);
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF_STRENGTH) &&
+ *time_left >= CIFISP_MODULE_DPF_STRENGTH_TIME) {
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_DPF)) {
+ /* update dpf strength config */
+ cifisp_dpf_strength_config(isp_dev);
+ cifisp_dpf_en(isp_dev);
+ } else {
+ cifisp_dpf_end(isp_dev);
+ }
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->other_cfgs.module_updates,
+ CIFISP_MODULE_DPF_STRENGTH);
+
+ *time_left -= CIFISP_MODULE_DPF_STRENGTH_TIME;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "dpf strength time-left :%d\n",
+ *time_left);
+ }
+
+ config_chk = time_in > *time_left;
+ if (config_chk)
+ cifisp_other_config_swap(isp_dev);
+
+ return config_chk;
+}
+
+static inline bool cifisp_isp_isr_meas_config(
+ struct cif_isp10_isp_dev *isp_dev,
+ unsigned int *time_left)
+{
+ unsigned int time_in = *time_left;
+ bool config_chk;
+ unsigned int *ens;
+
+ ens = &isp_dev->meas_cfgs.last_or_new->module_ens;
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AWB)) {
+ /* update awb config */
+ cifisp_awb_meas_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AWB))
+ cifisp_awb_meas_en(isp_dev);
+ else
+ cifisp_awb_meas_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AWB);
+ *time_left -= CIFISP_MODULE_AWB_PROC_TIME;
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AFC)) {
+ /* update afc config */
+ cifisp_afc_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AFC))
+ cifisp_afc_en(isp_dev);
+ else
+ cifisp_afc_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AFC);
+ *time_left -= CIFISP_MODULE_AFC_PROC_TIME;
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_HST)) {
+ /* update hst config */
+ cifisp_hst_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_HST))
+ cifisp_hst_en(isp_dev);
+ else
+ cifisp_hst_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_HST);
+ *time_left -= CIFISP_MODULE_HST_PROC_TIME;
+ }
+
+ if (CIFISP_MODULE_IS_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AEC)) {
+ /* update aec config */
+ cifisp_aec_config(isp_dev);
+
+ if (CIFISP_MODULE_IS_EN(*ens, CIFISP_MODULE_AEC))
+ cifisp_aec_en(isp_dev);
+ else
+ cifisp_aec_end(isp_dev);
+
+ CIFISP_MODULE_CLR_UPDATE(
+ isp_dev->meas_cfgs.module_updates,
+ CIFISP_MODULE_AEC);
+ *time_left -= CIFISP_MODULE_AEC_PROC_TIME;
+ }
+
+ config_chk = time_in > *time_left;
+ if (config_chk)
+ cifisp_meas_config_swap(isp_dev);
+
+ return config_chk;
+}
+
+int cifisp_isp_isr(struct cif_isp10_isp_dev *isp_dev, u32 isp_mis)
+{
+ unsigned int isp_mis_tmp = 0;
+ struct cif_isp10_isp_readout_work *work;
+ unsigned int time_left = isp_dev->v_blanking_us;
+#ifdef LOG_ISR_EXE_TIME
+ ktime_t in_t = ktime_get();
+#endif
+ if (isp_mis & (CIF_ISP_DATA_LOSS | CIF_ISP_PIC_SIZE_ERROR))
+ return 0;
+
+ if (isp_mis & CIF_ISP_FRAME) {
+ u32 isp_ris = cifisp_ioread32(CIF_ISP_RIS);
+
+ cifisp_iowrite32(
+ (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+ CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY),
+ CIF_ISP_ICR);
+ isp_mis_tmp = cifisp_ioread32(CIF_ISP_MIS);
+ if (isp_mis_tmp &
+ (CIF_ISP_AWB_DONE | CIF_ISP_AFM_FIN |
+ CIF_ISP_EXP_END | CIF_ISP_HIST_MEASURE_RDY))
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "isp icr 3A info err: 0x%x\n",
+ isp_mis_tmp);
+
+ CIFISP_DPRINT(CIFISP_DEBUG, "isp_ris 0x%x\n", isp_ris);
+
+ if (((isp_dev->meas_cfgs.module_updates &
+ (CIFISP_MODULE_AWB |
+ CIFISP_MODULE_AEC |
+ CIFISP_MODULE_AFC)) == 0) &&
+ isp_dev->active_meas &&
+ ((isp_dev->active_meas & isp_ris) ==
+ isp_dev->active_meas)) {
+ work = (struct cif_isp10_isp_readout_work *)
+ kmalloc(sizeof(
+ struct cif_isp10_isp_readout_work),
+ GFP_ATOMIC);
+ if (work) {
+ INIT_WORK((struct work_struct *)work,
+ cifisp_isp_readout_work);
+ work->readout = CIF_ISP10_ISP_READOUT_MEAS;
+ work->isp_dev = isp_dev;
+ work->frame_id = isp_dev->frame_id;
+ if (!queue_work(isp_dev->readout_wq,
+ (struct work_struct *)work)) {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "Could not schedule work\n");
+ kfree((void *)work);
+ }
+ } else {
+ CIFISP_DPRINT(CIFISP_ERROR,
+ "Could not allocate work\n");
+ }
+ }
+
+ /*
+ * Then update changed configs. Some of them involve
+ * lot of register writes. Do those only one per frame.
+ * Do the updates in the order of the processing flow.
+ */
+ spin_lock(&isp_dev->config_lock);
+ if (cifisp_isp_isr_other_config(isp_dev, &time_left) == false)
+ cifisp_isp_isr_meas_config(isp_dev, &time_left);
+ spin_unlock(&isp_dev->config_lock);
+
+ cifisp_dump_reg(isp_dev, CIFISP_DEBUG);
+ }
+#ifdef LOG_ISR_EXE_TIME
+ if (isp_mis & (CIF_ISP_EXP_END | CIF_ISP_AWB_DONE |
+ CIF_ISP_FRAME | CIF_ISP_HIST_MEASURE_RDY)) {
+ unsigned int diff_us =
+ ktime_to_us(ktime_sub(ktime_get(), in_t));
+
+ if (diff_us > g_longest_isr_time)
+ g_longest_isr_time = diff_us;
+
+ pr_info("isp_isr time %d %d\n", diff_us, g_longest_isr_time);
+ }
+#endif
+
+ return 0;
+}
+
+static void cifisp_param_dump(const void *config, unsigned int module)
+{
+#ifdef CIFISP_DEBUG_PARAM
+ switch (module) {
+ case CIFISP_MODULE_AWB_GAIN:{
+ struct cifisp_awb_gain_config *pconfig =
+ (struct cifisp_awb_gain_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AWB Gain Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, "g_g: %d\n",
+ pconfig->gain_green_r);
+ CIFISP_DPRINT(CIFISP_DEBUG, "g_b: %d\n",
+ pconfig->gain_green_b);
+ CIFISP_DPRINT(CIFISP_DEBUG, "r: %d\n",
+ pconfig->gain_red);
+ CIFISP_DPRINT(CIFISP_DEBUG, "b: %d\n",
+ pconfig->gain_blue);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AWB Gain Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+ case CIFISP_MODULE_DPCC:{
+ }
+ break;
+
+ case CIFISP_MODULE_BLS:{
+ struct cifisp_bls_config *pconfig =
+ (struct cifisp_bls_config *)config;
+ struct cifisp_bls_fixed_val *pval = &pconfig->fixed_val;
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: BLS Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " enable_auto: %d\n",
+ pconfig->enable_auto);
+ CIFISP_DPRINT(CIFISP_DEBUG, " en_windows: %d\n",
+ pconfig->en_windows);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window1.h_offs: %d\n",
+ pconfig->bls_window1.h_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window1.v_offs: %d\n",
+ pconfig->bls_window1.v_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window1.h_size: %d\n",
+ pconfig->bls_window1.h_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window1.v_size: %d\n",
+ pconfig->bls_window1.v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window2.h_offs: %d\n",
+ pconfig->bls_window2.h_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window2.v_offs: %d\n",
+ pconfig->bls_window2.v_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window2.h_size: %d\n",
+ pconfig->bls_window2.h_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " bls_window2.v_size: %d\n",
+ pconfig->bls_window2.v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG, " bls_samples: %d\n",
+ pconfig->bls_samples);
+ CIFISP_DPRINT(CIFISP_DEBUG, " fixed_A: %d\n",
+ pval->fixed_a);
+ CIFISP_DPRINT(CIFISP_DEBUG, " fixed_B: %d\n",
+ pval->fixed_b);
+ CIFISP_DPRINT(CIFISP_DEBUG, " fixed_C: %d\n",
+ pval->fixed_c);
+ CIFISP_DPRINT(CIFISP_DEBUG, " fixed_D: %d\n",
+ pval->fixed_d);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: BLS Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+ case CIFISP_MODULE_LSC:{
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### LSC Parameters - BEGIN ####\n");
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### LSC Parameters - END ####\n");
+ }
+ break;
+ case CIFISP_MODULE_FLT:{
+ struct cifisp_flt_config *pconfig =
+ (struct cifisp_flt_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: FLT Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_mask_sharp0: %d\n",
+ pconfig->flt_mask_sharp0);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_mask_sharp1: %d\n",
+ pconfig->flt_mask_sharp1);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_diag: %d\n",
+ pconfig->flt_mask_diag);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_mask_blur_max: %d\n",
+ pconfig->flt_mask_blur_max);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_blur: %d\n",
+ pconfig->flt_mask_blur);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_lin: %d\n",
+ pconfig->flt_mask_lin);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_mask_orth: %d\n",
+ pconfig->flt_mask_orth);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_mask_v_diag: %d\n",
+ pconfig->flt_mask_v_diag);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_mask_h_diag: %d\n",
+ pconfig->flt_mask_h_diag);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_lum_weight: %d\n",
+ pconfig->flt_lum_weight);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_blur_th0: %d\n",
+ pconfig->flt_blur_th0);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_blur_th1: %d\n",
+ pconfig->flt_blur_th1);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_sharp0_th: %d\n",
+ pconfig->flt_sharp0_th);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_sharp1_th: %d\n",
+ pconfig->flt_sharp1_th);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_chrom_h_mode: %d\n",
+ pconfig->flt_chrom_h_mode);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_chrom_v_mode: %d\n",
+ pconfig->flt_chrom_v_mode);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " flt_diag_sharp_mode: %d\n",
+ pconfig->flt_diag_sharp_mode);
+ CIFISP_DPRINT(CIFISP_DEBUG, " flt_mode: %d\n",
+ pconfig->flt_mode);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: FLT Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_BDM:{
+ struct cifisp_bdm_config *pconfig =
+ (struct cifisp_bdm_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: BDM Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " demosaic_th: %d\n",
+ pconfig->demosaic_th);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: BDM Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_SDG:{
+ struct cifisp_sdg_config *pconfig =
+ (struct cifisp_sdg_config *)config;
+ unsigned int i;
+
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: SDG Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " RED -Curve parameters\n");
+ for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " gamma_y[%d]: %d\n",
+ pconfig->curve_r.gamma_y[i]);
+ }
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " GREEN -Curve parameters\n");
+ for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " gamma_y[%d]: %d\n",
+ pconfig->curve_g.gamma_y[i]);
+ }
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " BLUE -Curve parameters\n");
+ for (i = 0; i < CIFISP_DEGAMMA_CURVE_SIZE; i++) {
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " gamma_y[%d]: %d\n",
+ pconfig->curve_b.gamma_y[i]);
+ }
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: SDG Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_GOC:{
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: GOC Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: GOC Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_CTK:{
+ struct cifisp_ctk_config *pconfig =
+ (struct cifisp_ctk_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: CTK Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff0: %d\n",
+ pconfig->coeff0);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff1: %d\n",
+ pconfig->coeff1);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff2: %d\n",
+ pconfig->coeff2);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff3: %d\n",
+ pconfig->coeff3);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff4: %d\n",
+ pconfig->coeff4);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff5: %d\n",
+ pconfig->coeff5);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff6: %d\n",
+ pconfig->coeff6);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff7: %d\n",
+ pconfig->coeff7);
+ CIFISP_DPRINT(CIFISP_DEBUG, " coeff8: %d\n",
+ pconfig->coeff8);
+ CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_r: %d\n",
+ pconfig->ct_offset_r);
+ CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_g: %d\n",
+ pconfig->ct_offset_g);
+ CIFISP_DPRINT(CIFISP_DEBUG, " ct_offset_b: %d\n",
+ pconfig->ct_offset_b);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: CTK Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_AWB:{
+ struct cifisp_awb_meas_config *pconfig =
+ (struct cifisp_awb_meas_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AWB Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " awb_mode: %d\n",
+ pconfig->awb_mode);
+ CIFISP_DPRINT(CIFISP_DEBUG, " max_y: %d\n",
+ pconfig->max_y);
+ CIFISP_DPRINT(CIFISP_DEBUG, " min_y: %d\n",
+ pconfig->min_y);
+ CIFISP_DPRINT(CIFISP_DEBUG, " max_csum: %d\n",
+ pconfig->max_csum);
+ CIFISP_DPRINT(CIFISP_DEBUG, " min_c: %d\n",
+ pconfig->min_c);
+ CIFISP_DPRINT(CIFISP_DEBUG, " frames: %d\n",
+ pconfig->frames);
+ CIFISP_DPRINT(CIFISP_DEBUG, " awb_ref_cr: %d\n",
+ pconfig->awb_ref_cr);
+ CIFISP_DPRINT(CIFISP_DEBUG, " awb_ref_cb: %d\n",
+ pconfig->awb_ref_cb);
+ CIFISP_DPRINT(CIFISP_DEBUG, " gb_sat: %d\n",
+ pconfig->gb_sat);
+ CIFISP_DPRINT(CIFISP_DEBUG, " gr_sat: %d\n",
+ pconfig->gr_sat);
+ CIFISP_DPRINT(CIFISP_DEBUG, " r_sat: %d\n",
+ pconfig->b_sat);
+ CIFISP_DPRINT(CIFISP_DEBUG, " grid_h_dim: %d\n",
+ pconfig->grid_h_dim);
+ CIFISP_DPRINT(CIFISP_DEBUG, " grid_v_dim: %d\n",
+ pconfig->grid_v_dim);
+ CIFISP_DPRINT(CIFISP_DEBUG, " grid_h_dist: %d\n",
+ pconfig->grid_h_dist);
+ CIFISP_DPRINT(CIFISP_DEBUG, " grid_v_dist: %d\n",
+ pconfig->grid_v_dist);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " enable_ymax_cmp: %d\n",
+ pconfig->enable_ymax_cmp);
+ CIFISP_DPRINT(CIFISP_DEBUG, " rgb_meas_pnt: %d\n",
+ pconfig->rgb_meas_pnt);
+ CIFISP_DPRINT(CIFISP_DEBUG, " AWB Window size\n");
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+ pconfig->awb_wnd.h_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+ pconfig->awb_wnd.v_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+ pconfig->awb_wnd.h_size);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+ pconfig->awb_wnd.v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AWB Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_HST:{
+ struct cifisp_hst_config *pconfig =
+ (struct cifisp_hst_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: HST Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " mode: %d\n",
+ pconfig->mode);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " histogram_predivider: %d\n",
+ pconfig->histogram_predivider);
+ CIFISP_DPRINT(CIFISP_DEBUG, " HST Window size\n");
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+ pconfig->meas_window.h_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+ pconfig->meas_window.v_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+ pconfig->meas_window.h_size);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+ pconfig->meas_window.v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: HST Parameters - END ####\n",
+ ISP_VDEV_NAME);
+
+ } break;
+
+ case CIFISP_MODULE_AEC:{
+ struct cifisp_aec_config *pconfig =
+ (struct cifisp_aec_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AEC Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " autostop: %d\n",
+ pconfig->autostop);
+ CIFISP_DPRINT(CIFISP_DEBUG, " AEC Window size\n");
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_offs: %d\n",
+ pconfig->meas_window.h_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_offs: %d\n",
+ pconfig->meas_window.v_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " h_size: %d\n",
+ pconfig->meas_window.h_size);
+ CIFISP_DPRINT(CIFISP_DEBUG, " v_size: %d\n",
+ pconfig->meas_window.v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AEC Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+
+ case CIFISP_MODULE_CPROC:{
+ struct cifisp_cproc_config *pconfig =
+ (struct cifisp_cproc_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: CPROC Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " contrast: %d\n",
+ pconfig->contrast);
+ CIFISP_DPRINT(CIFISP_DEBUG, " hue: %d\n",
+ pconfig->hue);
+ CIFISP_DPRINT(CIFISP_DEBUG, " sat: %d\n",
+ pconfig->sat);
+ CIFISP_DPRINT(CIFISP_DEBUG, " brightness: %d\n",
+ pconfig->brightness);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: CPROC Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ } break;
+ case CIFISP_MODULE_YCFLT:{
+ struct cifisp_ycflt_config *pconfig =
+ (struct cifisp_ycflt_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: YCFLT Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_ctrl: %d\n",
+ CIFISP_DPRINT(CIFISP_DEBUG, " ctrl: %d\n",
+ pconfig->ctrl);
+ CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_ctrl: %d\n",
+ pconfig->chr_ss_ctrl);
+ CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_fac: %d\n",
+ pconfig->chr_ss_fac);
+ CIFISP_DPRINT(CIFISP_DEBUG, " chr_ss_offs: %d\n",
+ pconfig->chr_ss_offs);
+ CIFISP_DPRINT(CIFISP_DEBUG, " chr_nr_ctrl: %d\n",
+ pconfig->chr_nr_ctrl);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_edge_gain: %d\n",
+ pconfig->lum_eenr_edge_gain);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_corner_gain: %d\n",
+ pconfig->lum_eenr_corner_gain);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_fc_crop_neg: %d\n",
+ pconfig->lum_eenr_fc_crop_neg);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_fc_crop_pos: %d\n",
+ pconfig->lum_eenr_fc_crop_pos);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_fc_gain_neg: %d\n",
+ pconfig->lum_eenr_fc_gain_neg);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " lum_eenr_fc_gain_pos: %d\n",
+ pconfig->lum_eenr_fc_gain_pos);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: YCFLT Parameters - END ####\n",
+ ISP_VDEV_NAME);
+ break;
+ }
+ case CIFISP_MODULE_AFC:{
+ struct cifisp_afc_config *pconfig =
+ (struct cifisp_afc_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "#### %s: AFC Parameters - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " window A %d %d %d %d\n",
+ pconfig->afm_win[0].h_offs,
+ pconfig->afm_win[0].v_offs,
+ pconfig->afm_win[0].h_size,
+ pconfig->afm_win[0].v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " window B %d %d %d %d\n",
+ pconfig->afm_win[1].h_offs,
+ pconfig->afm_win[1].v_offs,
+ pconfig->afm_win[1].h_size,
+ pconfig->afm_win[1].v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ " window C %d %d %d %d\n",
+ pconfig->afm_win[2].h_offs,
+ pconfig->afm_win[2].v_offs,
+ pconfig->afm_win[2].h_size,
+ pconfig->afm_win[2].v_size);
+ CIFISP_DPRINT(CIFISP_DEBUG, " thres: %d\n",
+ pconfig->thres);
+ CIFISP_DPRINT(CIFISP_DEBUG, " var_shift: %d\n",
+ pconfig->var_shift);
+ break;
+ }
+ case CIFISP_MODULE_IE: {
+ struct cifisp_ie_config *pconfig =
+ (struct cifisp_ie_config *)config;
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "effect %d, %x, %x, %x, %x, %x, %x %d\n",
+ pconfig->effect, pconfig->color_sel,
+ pconfig->eff_mat_1, pconfig->eff_mat_2,
+ pconfig->eff_mat_3, pconfig->eff_mat_4,
+ pconfig->eff_mat_5, pconfig->eff_tint);
+ break;
+ }
+ default:
+ CIFISP_DPRINT(CIFISP_DEBUG,
+ "####%s: Invalid Module ID ####\n", ISP_VDEV_NAME);
+ break;
+ }
+#endif
+}
+
+#ifdef LOG_CAPTURE_PARAMS
+static void cifisp_reg_dump_capture(const struct cif_isp10_isp_dev *isp_dev)
+{
+ memset(&g_last_capture_config, 0, sizeof(g_last_capture_config));
+
+ if (isp_dev->bls_en) {
+ g_last_capture_config.bls.fixed_val.fixed_a =
+ cifisp_ioread32(CIF_ISP_BLS_A_FIXED);
+ g_last_capture_config.bls.fixed_val.fixed_b =
+ cifisp_ioread32(CIF_ISP_BLS_B_FIXED);
+ g_last_capture_config.bls.fixed_val.fixed_c =
+ cifisp_ioread32(CIF_ISP_BLS_C_FIXED);
+ g_last_capture_config.bls.fixed_val.fixed_d =
+ cifisp_ioread32(CIF_ISP_BLS_D_FIXED);
+ }
+
+ if (isp_dev->lsc_en)
+ cifisp_lsc_config_read(isp_dev, &g_last_capture_config.lsc);
+
+ if (isp_dev->flt_en)
+ cifisp_flt_config_read(isp_dev, &g_last_capture_config.flt);
+
+ if (isp_dev->bdm_en)
+ g_last_capture_config.bdm.demosaic_th =
+ cifisp_ioread32(CIF_ISP_DEMOSAIC);
+
+ if (isp_dev->sdg_en)
+ cifisp_sdg_config_read(isp_dev, &g_last_capture_config.sdg);
+
+ if (isp_dev->goc_en)
+ cifisp_goc_config_read(isp_dev, &g_last_capture_config.goc);
+
+ if (isp_dev->ctk_en)
+ cifisp_ctk_config_read(isp_dev, &g_last_capture_config.ctk);
+
+ if (isp_dev->awb_meas_en)
+ cifisp_awb_meas_config_read(isp_dev,
+ &g_last_capture_config.awb_meas);
+
+ if (isp_dev->awb_gain_en)
+ cifisp_awb_gain_config_read(isp_dev,
+ &g_last_capture_config.awb_gain);
+
+ if (isp_dev->cproc_en)
+ cifisp_cproc_config_read(isp_dev, &g_last_capture_config.cproc);
+}
+#endif
+
+#ifdef CIFISP_DEBUG_REG
+static void cifisp_reg_dump(const struct cif_isp10_isp_dev *isp_dev,
+ unsigned int module, int level)
+{
+ switch (module) {
+ case CIFISP_MODULE_DPCC:
+ CIFISP_DPRINT(level, "#### BPC Registers - BEGIN ####\n");
+ CIFISP_DPRINT(level, "#### BPC Registers - END ####\n");
+ break;
+ case CIFISP_MODULE_BLS:
+ CIFISP_DPRINT(level, "#### BLS Registers - BEGIN ####\n");
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_CTRL: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_CTRL));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_SAMPLES: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_SAMPLES));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_START: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_H1_START));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_STOP: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_H1_STOP));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_H1_START: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_H1_START));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_V1_START: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_V1_START));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_V1_STOP: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_V1_STOP));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_H2_START: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_H2_START));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_H2_STOP: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_H2_STOP));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_V2_START: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_V2_START));
+ CIFISP_DPRINT(level, " CIF_ISP_BLS_V2_STOP: %d\n",
+ cifisp_ioread32(CIF_ISP_BLS_V2_STOP));
+ CIFISP_DPRINT(level, "#### BLS Registers - END ####\n");
+ break;
+ case CIFISP_MODULE_LSC:
+ CIFISP_DPRINT(level, "#### LSC Registers - BEGIN ####\n");
+ CIFISP_DPRINT(level, "#### LSC Registers - END ####\n");
+ break;
+ case CIFISP_MODULE_FLT:{
+ CIFISP_DPRINT(level,
+ "#### %s: FLT Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level,
+ " CIF_ISP_FILT_MODE: %d\n",
+ cifisp_ioread32(CIF_ISP_FILT_MODE));
+ CIFISP_DPRINT(level,
+ " CIF_ISP_FILT_LUM_WEIGHT: %d\n",
+ cifisp_ioread32(CIF_ISP_FILT_LUM_WEIGHT));
+ CIFISP_DPRINT(level,
+ "#### %s: FLT Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_BDM:{
+ CIFISP_DPRINT(level,
+ "#### %s: BDM Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_DEMOSAIC: %d\n",
+ cifisp_ioread32(CIF_ISP_DEMOSAIC));
+ CIFISP_DPRINT(level,
+ "#### %s: BDM Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_SDG:{
+ CIFISP_DPRINT(level,
+ "#### %s: SDG Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_DX_LO: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_DX_LO));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_DX_HI: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_DX_HI));
+
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y0: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y0));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y1: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y1));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y2: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y2));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y3: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y3));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y4: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y4));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y5: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y5));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y6: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y6));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y7: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y7));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y8: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y8));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y9: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y9));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y10: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y10));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y11: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y11));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y12: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y12));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y13: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y13));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y14: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y14));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y15: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y15));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_R_Y16: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_R_Y16));
+
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y0: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y0));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y1: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y1));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y2: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y2));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y3: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y3));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y4: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y4));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y5: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y5));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y6: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y6));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y7: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y7));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y8: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y8));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y9: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y9));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y10: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y10));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y11: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y11));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y12: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y12));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y13: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y13));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y14: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y14));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y15: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y15));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_G_Y16: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_G_Y16));
+
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y0: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y0));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y1: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y1));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y2: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y2));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y3: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y3));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y4: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y4));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y5: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y5));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y6: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y6));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y7: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y7));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y8: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y8));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y9: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y9));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y10: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y10));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y11: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y11));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y12: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y12));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y13: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y13));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y14: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y14));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y15: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y15));
+ CIFISP_DPRINT(level, " CIF_ISP_GAMMA_B_Y16: %d\n",
+ cifisp_ioread32(CIF_ISP_GAMMA_B_Y16));
+ CIFISP_DPRINT(level,
+ "#### %s: SDG Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_GOC:{
+ CIFISP_DPRINT(level,
+ "#### %s: GOC Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level,
+ "#### %s: GOC registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_CTK:{
+ CIFISP_DPRINT(level,
+ "#### %s: CTK Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_0: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_0));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_1: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_1));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_2: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_2));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_3: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_3));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_4: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_4));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_5: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_5));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_6: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_6));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_7: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_7));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_COEFF_8: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_COEFF_8));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_R: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_OFFSET_R));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_G: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_OFFSET_G));
+ CIFISP_DPRINT(level, " CIF_ISP_CT_OFFSET_B: %d\n",
+ cifisp_ioread32(CIF_ISP_CT_OFFSET_B));
+ CIFISP_DPRINT(level,
+ "#### %s: CTK Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_AWB:{
+ CIFISP_DPRINT(level,
+ "#### %s: AWB Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_PROP: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_PROP));
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_G: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_GAIN_G));
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_RB: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_GAIN_RB));
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_REF: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_REF));
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_GAIN_RB: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_PROP));
+ CIFISP_DPRINT(level, " CIF_ISP_AWB_FRAMES: %x\n",
+ cifisp_ioread32(CIF_ISP_AWB_FRAMES));
+ CIFISP_DPRINT(level,
+ "#### %s: AWB Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_HST:{
+ CIFISP_DPRINT(level,
+ "#### %s: HST Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_HIST_PROP: %d\n",
+ cifisp_ioread32(CIF_ISP_HIST_PROP));
+ CIFISP_DPRINT(level, " CIF_ISP_HIST_H_OFFS: %d\n",
+ cifisp_ioread32(CIF_ISP_HIST_H_OFFS));
+ CIFISP_DPRINT(level, " CIF_ISP_HIST_H_SIZE: %d\n",
+ cifisp_ioread32(CIF_ISP_HIST_H_SIZE));
+ CIFISP_DPRINT(level, " CIF_ISP_HIST_V_OFFS: %d\n",
+ cifisp_ioread32(CIF_ISP_HIST_V_OFFS));
+ CIFISP_DPRINT(level, " CIF_ISP_HIST_V_SIZE: %d\n",
+ cifisp_ioread32(CIF_ISP_HIST_V_SIZE));
+ CIFISP_DPRINT(level,
+ "#### %s: HST Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_AEC:{
+ CIFISP_DPRINT(level,
+ "#### %s: AEC Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " CIF_ISP_EXP_CTRL: %d\n",
+ cifisp_ioread32(CIF_ISP_EXP_CTRL));
+ CIFISP_DPRINT(level, " CIF_ISP_EXP_H_OFFSET: %d\n",
+ cifisp_ioread32(CIF_ISP_EXP_H_OFFSET));
+ CIFISP_DPRINT(level, " CIF_ISP_EXP_V_OFFSET: %d\n",
+ cifisp_ioread32(CIF_ISP_EXP_V_OFFSET));
+ CIFISP_DPRINT(level, " CIF_ISP_EXP_H_SIZE: %d\n",
+ cifisp_ioread32(CIF_ISP_EXP_H_SIZE));
+ CIFISP_DPRINT(level, " CIF_ISP_EXP_V_SIZE: %d\n",
+ cifisp_ioread32(CIF_ISP_EXP_V_SIZE));
+ CIFISP_DPRINT(level,
+ "#### %s: AEC Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+
+ case CIFISP_MODULE_CPROC:{
+ CIFISP_DPRINT(level,
+ "#### %s: CPROC Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " ctrl: %d\n",
+ cifisp_ioread32(CIF_C_PROC_CTRL));
+ CIFISP_DPRINT(level, " contrast: %d\n",
+ cifisp_ioread32(CIF_C_PROC_CONTRAST));
+ CIFISP_DPRINT(level, " hue: %d\n",
+ cifisp_ioread32(CIF_C_PROC_HUE));
+ CIFISP_DPRINT(level, " sat: %d\n",
+ cifisp_ioread32(CIF_C_PROC_SATURATION));
+ CIFISP_DPRINT(level, " brightness: %d\n",
+ cifisp_ioread32(CIF_C_PROC_BRIGHTNESS));
+ CIFISP_DPRINT(level,
+ "#### %s: CPROC Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+ case CIFISP_MODULE_AFC:{
+ CIFISP_DPRINT(level,
+ "#### %s: AFC Registers - BEGIN ####\n",
+ ISP_VDEV_NAME);
+ CIFISP_DPRINT(level, " afm_ctr: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_CTRL));
+ CIFISP_DPRINT(level, " afm_lt_a: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_LT_A));
+ CIFISP_DPRINT(level, " afm_rb_a: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_RB_A));
+ CIFISP_DPRINT(level, " afm_lt_b: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_LT_B));
+ CIFISP_DPRINT(level, " afm_rb_b: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_RB_B));
+ CIFISP_DPRINT(level, " afm_lt_c: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_LT_C));
+ CIFISP_DPRINT(level, " afm_rb_c: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_RB_C));
+ CIFISP_DPRINT(level, " afm_thres: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_THRES));
+ CIFISP_DPRINT(level, " afm_var_shift: %d\n",
+ cifisp_ioread32(CIF_ISP_AFM_VAR_SHIFT));
+ CIFISP_DPRINT(level,
+ "#### %s: YCFLT Registers - END ####\n",
+ ISP_VDEV_NAME);
+ }
+ break;
+ default:
+ CIFISP_DPRINT(level, "####%s: Invalid Module ID ####\n",
+ ISP_VDEV_NAME);
+ break;
+ }
+}
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_ISP_H
+#define _CIF_ISP10_ISP_H
+
+#include <media/v4l2-common.h>
+#include <media/videobuf-core.h>
+#include <media/rk-isp10-ioctl.h>
+#include <media/v4l2-controls_rockchip.h>
+
+/*
+ * ISP device struct
+ */
+enum cif_isp10_pix_fmt;
+
+enum cif_isp10_pix_fmt_quantization {
+ CIF_ISP10_QUANTIZATION_DEFAULT = 0,
+ CIF_ISP10_QUANTIZATION_FULL_RANGE = 1,
+ CIF_ISP10_QUANTIZATION_LIM_RANGE = 2
+};
+
+struct cif_isp10_isp_other_cfgs {
+ struct cifisp_isp_other_cfg *last_or_new;
+ struct cifisp_isp_other_cfg *curr;
+ struct cifisp_isp_other_cfg cfgs[2];
+ unsigned int module_updates;
+};
+
+struct cif_isp10_isp_meas_cfgs {
+ struct cifisp_isp_meas_cfg *last_or_new;
+ struct cifisp_isp_meas_cfg *curr;
+ struct cifisp_isp_meas_cfg cfgs[2];
+ unsigned int module_updates;
+};
+
+struct cif_isp10_isp_meas_stats {
+ unsigned int g_frame_id;
+ struct cifisp_stat_buffer stat;
+};
+
+struct cif_isp10_isp_dev {
+ /*
+ * Purpose of mutex is to protect and serialize use
+ * of isp data structure and CIF API calls.
+ */
+ struct mutex mutex;
+ /* Current ISP parameters */
+ spinlock_t config_lock;
+ struct cif_isp10_isp_other_cfgs other_cfgs;
+ struct cif_isp10_isp_meas_cfgs meas_cfgs;
+ struct cif_isp10_isp_meas_stats meas_stats;
+
+ bool cif_ism_cropping;
+
+ enum cif_isp10_pix_fmt_quantization quantization;
+
+ /* input resolution needed for LSC param check */
+ unsigned int input_width;
+ unsigned int input_height;
+ unsigned int active_lsc_width;
+ unsigned int active_lsc_height;
+
+ /* ISP statistics related */
+ spinlock_t irq_lock;
+ /* ISP statistics related */
+ spinlock_t req_lock;
+ struct videobuf_queue vbq_stat;
+ struct list_head stat;
+ void __iomem *base_addr; /* registers base address */
+
+ bool streamon;
+ unsigned int v_blanking_us;
+
+ unsigned int frame_id;
+ unsigned int frame_id_setexp;
+ unsigned int active_meas;
+
+ struct timeval vs_t; /* updated each frame */
+ struct timeval fi_t; /* updated each frame */
+ struct workqueue_struct *readout_wq;
+
+ unsigned int *dev_id;
+};
+
+enum cif_isp10_isp_readout_cmd {
+ CIF_ISP10_ISP_READOUT_MEAS = 0,
+ CIF_ISP10_ISP_READOUT_META = 1,
+};
+
+struct cif_isp10_isp_readout_work {
+ struct work_struct work;
+ struct cif_isp10_isp_dev *isp_dev;
+
+ unsigned int frame_id;
+ enum cif_isp10_isp_readout_cmd readout;
+ struct videobuf_buffer *vb;
+ unsigned int stream_id;
+};
+
+int register_cifisp_device(
+ struct cif_isp10_isp_dev *isp_dev,
+ struct video_device *vdev_cifisp,
+ struct v4l2_device *v4l2_dev,
+ void __iomem *cif_reg_baseaddress);
+void unregister_cifisp_device(struct video_device *vdev_cifisp);
+void cifisp_configure_isp(
+ struct cif_isp10_isp_dev *isp_dev,
+ enum cif_isp10_pix_fmt in_pix_fmt,
+ enum cif_isp10_pix_fmt_quantization quantization);
+void cifisp_disable_isp(struct cif_isp10_isp_dev *isp_dev);
+int cifisp_isp_isr(struct cif_isp10_isp_dev *isp_dev, u32 isp_mis);
+void cifisp_v_start(struct cif_isp10_isp_dev *isp_dev,
+ const struct timeval *timestamp);
+void cifisp_frame_in(
+ struct cif_isp10_isp_dev *isp_dev,
+ const struct timeval *fi_t);
+void cifisp_isp_readout_work(struct work_struct *work);
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef CONFIG_OF
+#error "this driver requires a kernel with device tree support"
+#endif
+
+#include <linux/of.h>
+#include <linux/platform_device.h>
+#include <linux/interrupt.h>
+#include <linux/kernel.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/jiffies.h>
+#include <linux/list.h>
+#include "cif_isp10.h"
+#include <linux/platform_data/rk_isp10_platform.h>
+#include "cif_isp10_regs.h"
+#ifndef CONFIG_DEBUG_FS
+#include <linux/debugfs.h>
+#include <linux/fs.h>
+#include <media/v4l2-controls_rockchip.h>
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+#include <stdarg.h>
+
+static struct {
+ char *reg_trace;
+ loff_t reg_trace_read_pos;
+ loff_t reg_trace_write_pos;
+ size_t reg_trace_max_size;
+ void __iomem *base_addr;
+ bool rtrace;
+ bool ftrace;
+ bool internal;
+ spinlock_t lock;/* spin lock */
+} cif_isp10_reg_trace;
+#endif
+#endif
+
+struct cif_isp10_pltfrm_csi_config {
+ struct list_head list;
+ u32 pps;
+ struct cif_isp10_csi_config csi_config;
+};
+
+struct cif_isp10_pltfrm_data {
+ struct pinctrl *pinctrl;
+ struct pinctrl_state *pins_default;
+ struct pinctrl_state *pins_sleep;
+ struct pinctrl_state *pins_inactive;
+ void __iomem *base_addr;
+ int irq;
+ struct {
+ int mis;
+ int (*isr)(unsigned int mis, void *cntxt);
+ } irq_handlers[4];
+ struct list_head csi0_configs;
+ struct list_head csi1_configs;
+ s32 exp_time;
+ u16 gain;
+
+#ifndef CONFIG_DEBUG_FS
+ struct {
+ struct dentry *dir;
+ struct dentry *cif_isp10_file;
+ struct dentry *csi0_file;
+ struct dentry *csi1_file;
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+ struct dentry *reg_trace_file;
+#endif
+ void (*print_func)(void *cntxt, const char *block_name);
+ void *print_cntxt;
+ } dbgfs;
+#endif
+};
+
+void cif_isp10_pltfrm_debug_register_print_cb(
+ struct device *dev,
+ void (*print)(void *cntxt, const char *block),
+ void *cntxt) {
+#ifndef CONFIG_DEBUG_FS
+ struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+ pdata->dbgfs.print_cntxt = cntxt;
+ pdata->dbgfs.print_func = print;
+#endif
+}
+
+#ifndef CONFIG_DEBUG_FS
+#define CIF_ISP10_DBGFS_BUF_SIZE 1024
+static char cif_isp10_dbgfs_buf[CIF_ISP10_DBGFS_BUF_SIZE];
+
+static int cif_isp10_dbgfs_fill_csi_config_from_string(
+ struct device *dev,
+ struct cif_isp10_csi_config *csi_config,
+ char *strp)
+{
+ char *token;
+
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token))
+ goto missing_token;
+ if (IS_ERR_VALUE(kstrtou32(token, 10,
+ &csi_config->vc)))
+ goto wrong_token_format;
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token))
+ goto missing_token;
+ if (IS_ERR_VALUE(kstrtou32(token, 10,
+ &csi_config->nb_lanes)))
+ goto wrong_token_format;
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token))
+ goto missing_token;
+ if (IS_ERR_VALUE(kstrtou32(token, 16,
+ &csi_config->dphy1)))
+ goto wrong_token_format;
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token))
+ goto missing_token;
+ if (IS_ERR_VALUE(kstrtou32(token, 16,
+ &csi_config->dphy2)))
+ goto wrong_token_format;
+ token = strsep(&strp, " ");
+ if (!IS_ERR_OR_NULL(token)) {
+ if (IS_ERR_VALUE(kstrtou32(token, 10,
+ &csi_config->ana_bandgab_bias)))
+ goto wrong_token_format;
+ } else {
+ csi_config->ana_bandgab_bias = (u32)-1;
+ }
+
+ return 0;
+missing_token:
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+ return -EINVAL;
+wrong_token_format:
+ cif_isp10_pltfrm_pr_err(dev,
+ "wrong token format, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+ return -EINVAL;
+}
+
+static int cif_isp10_dbgfs_csi_configs_init(
+ struct device *dev,
+ enum cif_isp10_inp inp,
+ struct list_head *csi_configs)
+{
+ int ret = 0;
+ struct device *img_src_dev = NULL;
+ struct device_node *parent_node = NULL;
+ struct device_node *child_node = NULL, *prev_node = NULL;
+ struct cif_isp10_pltfrm_csi_config *cfg = NULL;
+ u32 pps;
+
+ img_src_dev = cif_isp10_pltfrm_get_img_src_device(dev, inp);
+ if (IS_ERR_OR_NULL(img_src_dev)) {
+ ret = -EFAULT;
+ goto err;
+ }
+ parent_node = of_node_get(img_src_dev->of_node);
+ put_device(img_src_dev);
+ img_src_dev = NULL;
+
+ while (!IS_ERR_OR_NULL(child_node =
+ of_get_next_child(parent_node, prev_node))) {
+ if (!strncasecmp(child_node->name,
+ "intel,camera-module-csi-config",
+ strlen("intel,camera-module-csi-config"))) {
+ ret = of_property_read_u32(child_node,
+ "intel,csi-pixels-per-second", &pps);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "reading property 'intel,csi-pixels-per-second'\n");
+ goto err;
+ }
+ cfg = kmalloc(
+ sizeof(struct cif_isp10_pltfrm_csi_config),
+ GFP_KERNEL);
+ if (!cfg) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "memory allocation failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ cfg->pps = pps;
+ ret = cif_isp10_pltfrm_fill_csi_config_from_node(
+ dev, &cfg->csi_config, child_node);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ list_add_tail(&cfg->list, csi_configs);
+ cfg = NULL;
+ }
+ of_node_put(prev_node);
+ prev_node = child_node;
+ }
+ of_node_put(prev_node);
+ of_node_put(parent_node);
+
+ return 0;
+err:
+ of_node_put(prev_node);
+ of_node_put(child_node);
+ of_node_put(parent_node);
+ kfree(cfg);
+ if (!IS_ERR_OR_NULL(img_src_dev))
+ put_device(img_src_dev);
+ return ret;
+}
+
+static ssize_t cif_isp10_dbgfs_csi_read(
+ struct file *f,
+ char __user *out,
+ size_t count,
+ loff_t *pos)
+{
+ u32 out_size = 0;
+ u32 str_len;
+ struct cif_isp10_pltfrm_csi_config *cfg;
+ u32 index = 0;
+ struct list_head *list_pos;
+ struct device *dev = f->f_inode->i_private;
+ struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+ struct list_head *csi_configs;
+ enum cif_isp10_inp inp;
+
+ if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
+ csi_configs = &pdata->csi0_configs;
+ inp = CIF_ISP10_INP_CSI_0;
+ } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
+ csi_configs = &pdata->csi1_configs;
+ inp = CIF_ISP10_INP_CSI_1;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
+ return -EINVAL;
+ }
+
+ if (list_empty(csi_configs))
+ if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
+ dev, inp, csi_configs)))
+ return -EFAULT;
+
+ if (*pos)
+ return 0;
+
+ list_for_each(list_pos, csi_configs) {
+ cfg = list_entry(list_pos,
+ struct cif_isp10_pltfrm_csi_config, list);
+ sprintf(cif_isp10_dbgfs_buf,
+ "csi-config-%d:\n"
+ " pps = %d\n"
+ " vc = %d\n"
+ " nb_lanes = %d\n"
+ " dphy1 = 0x%08x\n"
+ " dphy2 = 0x%08x\n"
+ " ana_bandgap_bias = %d\n",
+ index,
+ cfg->pps, cfg->csi_config.vc, cfg->csi_config.nb_lanes,
+ cfg->csi_config.dphy1, cfg->csi_config.dphy2,
+ cfg->csi_config.ana_bandgab_bias);
+ index++;
+ str_len = strnlen(cif_isp10_dbgfs_buf,
+ CIF_ISP10_DBGFS_BUF_SIZE);
+ if (str_len > count) {
+ *pos += out_size;
+ return 0;
+ }
+ *pos = 0;
+ if (IS_ERR_VALUE(simple_read_from_buffer(
+ out + out_size, str_len, pos,
+ cif_isp10_dbgfs_buf, str_len)))
+ break;
+ out_size += strnlen(cif_isp10_dbgfs_buf,
+ CIF_ISP10_DBGFS_BUF_SIZE);
+ count -= str_len;
+ }
+
+ *pos += out_size;
+ return out_size;
+}
+
+static ssize_t cif_isp10_dbgfs_csi_write(
+ struct file *f,
+ const char __user *in,
+ size_t count,
+ loff_t *pos)
+{
+ ssize_t ret;
+ char *strp = cif_isp10_dbgfs_buf;
+ char *token;
+ struct device *dev = f->f_inode->i_private;
+ struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+ struct list_head *csi_configs;
+ enum cif_isp10_inp inp;
+
+ if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+ cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
+ return -EINVAL;
+ }
+
+ if (f->f_inode == pdata->dbgfs.csi0_file->d_inode) {
+ csi_configs = &pdata->csi0_configs;
+ inp = CIF_ISP10_INP_CSI_0;
+ } else if (f->f_inode == pdata->dbgfs.csi1_file->d_inode) {
+ csi_configs = &pdata->csi1_configs;
+ inp = CIF_ISP10_INP_CSI_1;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev, "wrong file handle\n");
+ return -EINVAL;
+ }
+
+ if (list_empty(csi_configs))
+ if (IS_ERR_VALUE(cif_isp10_dbgfs_csi_configs_init(
+ dev, inp, csi_configs)))
+ return -EFAULT;
+
+ memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+ ret = simple_write_to_buffer(strp,
+ CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ token = strsep(&strp, " ");
+ if (!strcmp(token, "push")) {
+ struct cif_isp10_pltfrm_csi_config cfg;
+
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+ return -EINVAL;
+ }
+ if (IS_ERR_VALUE(kstrtou32(token, 10,
+ &cfg.pps))) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'push <pps> <vc> <#lanes> <HEX dphy1> <HEX dphy2> <analog bandgap bias>'\n");
+ return -EINVAL;
+ }
+ ret = cif_isp10_dbgfs_fill_csi_config_from_string(
+ dev, &cfg.csi_config, strp);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ ret = cif_isp10_pltfrm_l_s_csi_config(
+ dev, inp, cfg.pps, &cfg.csi_config);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+ } else if (!strncmp(token, "reset", 5)) {
+ } else {
+ cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
+ return -EINVAL;
+ }
+
+ return count;
+}
+
+void cif_isp10_dbgfs_fill_sensor_aec_para(
+ struct cif_isp10_device *cif_isp10_dev,
+ s32 exp_time,
+ u16 gain)
+{
+ struct cif_isp10_pltfrm_data *pdata;
+
+ pdata = (struct cif_isp10_pltfrm_data *)
+ cif_isp10_dev->dev->platform_data;
+ pdata->exp_time = exp_time;
+ pdata->gain = gain;
+}
+
+static ssize_t cif_isp10_dbgfs_sensor_read(
+ struct file *f,
+ char __user *out,
+ size_t count,
+ loff_t *pos)
+{
+ u32 out_size = 0;
+ u32 str_len;
+ struct device *dev = f->f_inode->i_private;
+ struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+ if (*pos)
+ return 0;
+
+ sprintf(cif_isp10_dbgfs_buf,
+ "sensor current exp_time: %d\n"
+ " gain = %d\n",
+ pdata->exp_time,
+ pdata->gain);
+ str_len = strnlen(cif_isp10_dbgfs_buf,
+ CIF_ISP10_DBGFS_BUF_SIZE);
+ if (str_len > count) {
+ *pos += out_size;
+ return 0;
+ }
+ *pos = 0;
+ if (IS_ERR_VALUE(simple_read_from_buffer(
+ out + out_size, str_len, pos,
+ cif_isp10_dbgfs_buf, str_len)))
+ goto ERR;
+ out_size += strnlen(cif_isp10_dbgfs_buf,
+ CIF_ISP10_DBGFS_BUF_SIZE);
+ count -= str_len;
+
+ *pos += out_size;
+ERR:
+ return out_size;
+}
+
+static ssize_t cif_isp10_dbgfs_sensor_write(
+ struct file *f,
+ const char __user *in,
+ size_t count,
+ loff_t *pos)
+{
+ return 0;
+}
+
+static ssize_t cif_isp10_dbgfs_write(
+ struct file *f,
+ const char __user *in,
+ size_t count,
+ loff_t *pos)
+{
+ ssize_t ret;
+ char *strp = cif_isp10_dbgfs_buf;
+ char *token;
+ struct device *dev = f->f_inode->i_private;
+ struct cif_isp10_pltfrm_data *pdata = dev->platform_data;
+
+ if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+ cif_isp10_pltfrm_pr_err(dev, "command line too large\n");
+ return -EINVAL;
+ }
+
+ memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+ ret = simple_write_to_buffer(strp,
+ CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+ if (IS_ERR_VALUE(ret))
+ return ret;
+
+ token = strsep(&strp, " ");
+ if (!strncmp(token, "print", 5)) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'print all|<list of block name>'\n");
+ return -EINVAL;
+ }
+ if (!strncmp(token, "register", 8)) {
+ u32 addr;
+ struct cif_isp10_pltfrm_data *pdata =
+ dev->platform_data;
+ token = strsep(&strp, " ");
+ while (token) {
+ if (IS_ERR_VALUE(kstrtou32(token,
+ 16, &addr))) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "malformed token, must be a hexadecimal register address\n");
+ return -EINVAL;
+ }
+ pr_info("0x%04x: 0x%08x\n",
+ addr,
+ ioread32(pdata->base_addr +
+ addr));
+ token = strsep(&strp, " ");
+ }
+ } else if (pdata->dbgfs.print_func) {
+ unsigned long flags;
+
+ local_irq_save(flags);
+ while (token) {
+ pdata->dbgfs.print_func(
+ pdata->dbgfs.print_cntxt,
+ token);
+ token = strsep(&strp, " ");
+ }
+ local_irq_restore(flags);
+ }
+ } else if (!strncmp(token, "power", 5)) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'power [off|on]'\n");
+ return -EINVAL;
+ }
+ if (!strncmp(token, "on", 2)) {
+ if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
+ CIF_ISP10_PM_STATE_SW_STNDBY, NULL)))
+ cif_isp10_pltfrm_pr_err(dev,
+ "power on failed\n");
+ else
+ cif_isp10_pltfrm_pr_info(dev,
+ "switched on\n");
+ } else if (!strncmp(token, "off", 3)) {
+ if (IS_ERR_VALUE(cif_isp10_pltfrm_pm_set_state(dev,
+ CIF_ISP10_PM_STATE_OFF, NULL)))
+ cif_isp10_pltfrm_pr_err(dev,
+ "power off failed\n");
+ else
+ cif_isp10_pltfrm_pr_info(dev,
+ "switched off\n");
+ } else {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'power [off|on]'\n");
+ return -EINVAL;
+ }
+ } else if (!strncmp(token, "set", 3)) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'set register <hex addr>=<hex val>'\n");
+ return -EINVAL;
+ }
+ if (!strncmp(token, "register", 8)) {
+ u32 addr;
+ u32 val;
+ struct cif_isp10_pltfrm_data *pdata =
+ dev->platform_data;
+ token = strsep(&strp, "=");
+ if (IS_ERR_VALUE(kstrtou32(token,
+ 16, &addr))) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "malformed token, address must be a hexadecimal register address\n");
+ return -EINVAL;
+ }
+ token = strp;
+ if (IS_ERR_VALUE(kstrtou32(token,
+ 16, &val))) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "malformed token, value must be a hexadecimal value\n");
+ return -EINVAL;
+ }
+ iowrite32(val, pdata->base_addr + addr);
+ } else {
+ cif_isp10_pltfrm_pr_err(dev,
+ "unknown command %s\n", token);
+ return -EINVAL;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev,
+ "unknown command %s\n", token);
+ return -EINVAL;
+ }
+ return count;
+}
+
+static const struct file_operations cif_isp10_dbgfs_csi_fops = {
+ .read = cif_isp10_dbgfs_csi_read,
+ .write = cif_isp10_dbgfs_csi_write
+};
+
+static const struct file_operations cif_isp10_dbgfs_fops = {
+ .write = cif_isp10_dbgfs_write
+};
+
+static const struct file_operations cif_isp10_dbgfs_sensor_fops = {
+ .read = cif_isp10_dbgfs_sensor_read,
+ .write = cif_isp10_dbgfs_sensor_write
+};
+
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+
+static inline int cif_isp10_pltfrm_trace_printf(
+ struct device *dev,
+ const char *fmt,
+ va_list args)
+{
+ int i;
+ u32 rem_size;
+ unsigned long flags = 0;
+
+ if (!in_irq())
+ spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+ cif_isp10_reg_trace.internal = true;
+
+ rem_size = cif_isp10_reg_trace.reg_trace_max_size -
+ cif_isp10_reg_trace.reg_trace_write_pos;
+
+ if (rem_size <= 0) {
+ if (!in_irq())
+ spin_unlock_irqrestore(
+ &cif_isp10_reg_trace.lock, flags);
+ cif_isp10_reg_trace.internal = false;
+ return 0;
+ }
+
+ i = vsnprintf(cif_isp10_reg_trace.reg_trace +
+ cif_isp10_reg_trace.reg_trace_write_pos,
+ rem_size,
+ fmt, args);
+ if (i == rem_size) /* buffer full */
+ i = 0;
+ else if (i < 0)
+ cif_isp10_pltfrm_pr_err(dev,
+ "error writing trace buffer, error %d\n", i);
+ else
+ cif_isp10_reg_trace.reg_trace_write_pos += i;
+ cif_isp10_reg_trace.internal = false;
+ if (!in_irq())
+ spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+
+ return i;
+}
+
+inline int cif_isp10_pltfrm_rtrace_printf(
+ struct device *dev,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ int i;
+
+ va_start(args, fmt);
+ i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
+ va_end(args);
+
+ return i;
+}
+
+inline int cif_isp10_pltfrm_ftrace_printf(
+ struct device *dev,
+ const char *fmt,
+ ...)
+{
+ va_list args;
+ int i;
+
+ if (!cif_isp10_reg_trace.ftrace ||
+ cif_isp10_reg_trace.internal)
+ return 0;
+
+ va_start(args, fmt);
+ i = cif_isp10_pltfrm_trace_printf(dev, fmt, args);
+ va_end(args);
+
+ return i;
+}
+
+static void cif_isp10_dbgfs_reg_trace_clear(
+ struct device *dev)
+{
+ cif_isp10_reg_trace.reg_trace_write_pos = 0;
+ cif_isp10_reg_trace.reg_trace_read_pos = 0;
+}
+
+static ssize_t cif_isp10_dbgfs_reg_trace_read(
+ struct file *f,
+ char __user *out,
+ size_t count,
+ loff_t *pos)
+{
+ ssize_t bytes;
+ size_t available = cif_isp10_reg_trace.reg_trace_write_pos -
+ cif_isp10_reg_trace.reg_trace_read_pos;
+ size_t rem = count;
+
+ cif_isp10_reg_trace.internal = true;
+
+ if (!available)
+ cif_isp10_reg_trace.reg_trace_read_pos = 0;
+
+ while (rem && available) {
+ bytes = simple_read_from_buffer(
+ out + (count - rem), count,
+ &cif_isp10_reg_trace.reg_trace_read_pos,
+ cif_isp10_reg_trace.reg_trace,
+ cif_isp10_reg_trace.reg_trace_write_pos);
+ if (bytes < 0) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "buffer read failed with error %d\n",
+ bytes);
+ cif_isp10_reg_trace.internal = false;
+ return bytes;
+ }
+ rem -= bytes;
+ available = cif_isp10_reg_trace.reg_trace_write_pos -
+ cif_isp10_reg_trace.reg_trace_read_pos;
+ }
+
+ cif_isp10_reg_trace.internal = false;
+ return count - rem;
+}
+
+static ssize_t cif_isp10_dbgfs_reg_trace_write(
+ struct file *f,
+ const char __user *in,
+ size_t count,
+ loff_t *pos)
+{
+ ssize_t ret;
+ char *strp = cif_isp10_dbgfs_buf;
+ char *token;
+ struct device *dev = f->f_inode->i_private;
+ u32 max_size;
+ unsigned long flags = 0;
+
+ if (!in_irq())
+ spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+
+ cif_isp10_reg_trace.internal = true;
+
+ if (count > CIF_ISP10_DBGFS_BUF_SIZE) {
+ cif_isp10_pltfrm_pr_err(dev, "command line too long\n");
+ return -EINVAL;
+ }
+
+ memset(cif_isp10_dbgfs_buf, 0, CIF_ISP10_DBGFS_BUF_SIZE);
+ ret = simple_write_to_buffer(strp,
+ CIF_ISP10_DBGFS_BUF_SIZE, pos, in, count);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ token = strsep(&strp, " ");
+ if (!strncmp(token, "clear", 5)) {
+ cif_isp10_dbgfs_reg_trace_clear(dev);
+ cif_isp10_pltfrm_pr_info(dev,
+ "register trace buffer cleared\n");
+ } else if (!strcmp(token, "size")) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'size <num entries>'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (IS_ERR_VALUE(kstrtou32(token, 10,
+ &max_size))) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "wrong token format, <num entries> must be positive integer>'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (cif_isp10_reg_trace.reg_trace) {
+ devm_kfree(dev, cif_isp10_reg_trace.reg_trace);
+ cif_isp10_reg_trace.reg_trace = NULL;
+ }
+ cif_isp10_dbgfs_reg_trace_clear(dev);
+ if (max_size > 0) {
+ cif_isp10_reg_trace.reg_trace = devm_kzalloc(dev,
+ max_size, GFP_KERNEL);
+ if (!cif_isp10_reg_trace.reg_trace) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "memory allocation failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ cif_isp10_reg_trace.reg_trace_max_size = max_size;
+ cif_isp10_pltfrm_pr_info(dev,
+ "register trace buffer size set to %d Byte\n",
+ max_size);
+ }
+ } else if (!strncmp(token, "rtrace", 6)) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'rtrace [off|on]'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (!strncmp(token, "on", 2)) {
+ cif_isp10_reg_trace.rtrace = true;
+ cif_isp10_pltfrm_pr_info(dev,
+ "register trace enabled\n");
+ } else if (!strncmp(token, "off", 3)) {
+ cif_isp10_reg_trace.rtrace = false;
+ cif_isp10_pltfrm_pr_info(dev,
+ "register trace disabled\n");
+ } else {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'rtrace [off|on]'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else if (!strncmp(token, "ftrace", 6)) {
+ token = strsep(&strp, " ");
+ if (IS_ERR_OR_NULL(token)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'ftrace [off|on]'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (!strncmp(token, "on", 2)) {
+ cif_isp10_reg_trace.ftrace = true;
+ cif_isp10_pltfrm_pr_info(dev,
+ "function trace enabled\n");
+ } else if (!strncmp(token, "off", 3)) {
+ cif_isp10_reg_trace.ftrace = false;
+ cif_isp10_pltfrm_pr_info(dev,
+ "function trace disabled\n");
+ } else {
+ cif_isp10_pltfrm_pr_err(dev,
+ "missing token, command format is 'ftrace [off|on]'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_err(dev, "unknown command %s\n", token);
+ ret = -EINVAL;
+ goto err;
+ }
+ cif_isp10_reg_trace.internal = false;
+ if (!in_irq())
+ spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+ return count;
+err:
+ cif_isp10_reg_trace.internal = false;
+ if (!in_irq())
+ spin_unlock_irqrestore(&cif_isp10_reg_trace.lock, flags);
+ return ret;
+}
+
+static const struct file_operations
+cif_isp10_dbgfs_reg_trace_fops = {
+ .read = cif_isp10_dbgfs_reg_trace_read,
+ .write = cif_isp10_dbgfs_reg_trace_write
+};
+
+#endif
+#endif
+
+static irqreturn_t cif_isp10_pltfrm_irq_handler(int irq, void *cntxt)
+{
+ unsigned int i, mis_val;
+ int ret;
+ struct device *dev = cntxt;
+ struct cif_isp10_pltfrm_data *pdata =
+ dev_get_platdata(dev);
+ void *cif_isp10_dev = dev_get_drvdata(dev);
+
+ if (irq != pdata->irq)
+ return IRQ_NONE;
+
+ for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
+ if (IS_ERR_VALUE(pdata->irq_handlers[i].mis))
+ break;
+
+ if (IS_ERR_OR_NULL(pdata->irq_handlers[i].isr)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "ISR for IRQ #%d not set\n", irq);
+ break;
+ }
+
+ mis_val = cif_ioread32(pdata->base_addr +
+ pdata->irq_handlers[i].mis);
+ if (mis_val == 0)
+ continue;
+
+ ret = pdata->irq_handlers[i].isr(mis_val, cif_isp10_dev);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "ISR for IRQ #%d failed with error %d\n",
+ irq, ret);
+ }
+ return IRQ_HANDLED;
+ }
+
+ return IRQ_NONE;
+}
+
+const char *cif_isp10_pltfrm_pm_state_string(
+ enum cif_isp10_pm_state pm_state)
+{
+ switch (pm_state) {
+ case CIF_ISP10_PM_STATE_OFF:
+ return "CIF_ISP10_PM_STATE_OFF";
+ case CIF_ISP10_PM_STATE_SUSPENDED:
+ return "CIF_ISP10_PM_STATE_SUSPENDED";
+ case CIF_ISP10_PM_STATE_SW_STNDBY:
+ return "CIF_ISP10_PM_STATE_SW_STNDBY";
+ case CIF_ISP10_PM_STATE_STREAMING:
+ return "CIF_ISP10_PM_STATE_STREAMING";
+ default:
+ return "PM_STATE_UNKNOWN";
+ }
+}
+
+inline void cif_isp10_pltfrm_write_reg(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+ iowrite32(data, addr);
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+ {
+ unsigned long flags = 0;
+
+ if (!in_irq())
+ spin_lock_irqsave(&cif_isp10_reg_trace.lock, flags);
+ cif_isp10_reg_trace.internal = true;
+ if (((cif_isp10_reg_trace.reg_trace_write_pos +
+ (20 * sizeof(char))) <
+ cif_isp10_reg_trace.reg_trace_max_size) &&
+ cif_isp10_reg_trace.rtrace) {
+ int bytes =
+ sprintf(cif_isp10_reg_trace.reg_trace +
+ cif_isp10_reg_trace.reg_trace_write_pos,
+ "%04x %08x\n",
+ addr - cif_isp10_reg_trace.base_addr,
+ data);
+ if (bytes > 0)
+ cif_isp10_reg_trace.reg_trace_write_pos +=
+ bytes;
+ else
+ cif_isp10_pltfrm_pr_err(dev,
+ "error writing trace buffer, error %d\n",
+ bytes);
+ }
+ cif_isp10_reg_trace.internal = false;
+ if (!in_irq())
+ spin_unlock_irqrestore(
+ &cif_isp10_reg_trace.lock, flags);
+ }
+#endif
+}
+
+inline void cif_isp10_pltfrm_write_reg_OR(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+ cif_isp10_pltfrm_write_reg(dev,
+ (ioread32(addr) | data), addr);
+}
+
+inline void cif_isp10_pltfrm_write_reg_AND(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+ cif_isp10_pltfrm_write_reg(dev,
+ (ioread32(addr) & data), addr);
+}
+
+inline u32 cif_isp10_pltfrm_read_reg(
+ struct device *dev,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr)
+{
+ return ioread32(addr);
+}
+
+int cif_isp10_pltfrm_dev_init(
+ struct cif_isp10_device *cif_isp10_dev,
+ struct device **_dev,
+ void __iomem **reg_base_addr)
+{
+ int ret;
+ struct cif_isp10_pltfrm_data *pdata;
+ struct device *dev = *_dev;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct resource *res;
+ void __iomem *base_addr;
+ unsigned int i, irq;
+
+ dev_set_drvdata(dev, cif_isp10_dev);
+ cif_isp10_dev->dev = dev;
+
+ pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL);
+ if (!pdata) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "could not allocate memory for platform data\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "register");
+ if (!res) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "platform_get_resource_byname failed\n");
+ ret = -ENODEV;
+ goto err;
+ }
+ base_addr = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR_OR_NULL(base_addr)) {
+ cif_isp10_pltfrm_pr_err(NULL, "devm_ioremap_resource failed\n");
+ if (IS_ERR(base_addr))
+ ret = PTR_ERR(base_addr);
+ else
+ ret = -ENODEV;
+ }
+ *reg_base_addr = base_addr;
+ pdata->base_addr = base_addr;
+
+ irq = platform_get_irq_byname(pdev, "cif_isp10_irq");
+ if (IS_ERR_VALUE(irq)) {
+ ret = irq;
+ cif_isp10_pltfrm_pr_err(NULL,
+ "platform_get_irq_byname failed\n");
+ goto err;
+ }
+
+ ret = devm_request_threaded_irq(dev,
+ irq,
+ cif_isp10_pltfrm_irq_handler,
+ NULL,
+ 0,
+ dev_driver_string(dev),
+ dev);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "devm_request_threaded_irq failed\n");
+ goto err;
+ }
+ pdata->irq = irq;
+
+ pdata->pinctrl = devm_pinctrl_get(dev);
+ if (!IS_ERR_OR_NULL(pdata->pinctrl)) {
+ pdata->pins_default = pinctrl_lookup_state(pdata->pinctrl,
+ PINCTRL_STATE_DEFAULT);
+ if (IS_ERR(pdata->pins_default))
+ cif_isp10_pltfrm_pr_err(dev,
+ "could not get default pinstate\n");
+
+ pdata->pins_sleep = pinctrl_lookup_state(pdata->pinctrl,
+ PINCTRL_STATE_SLEEP);
+ if (IS_ERR(pdata->pins_sleep))
+ cif_isp10_pltfrm_pr_warn(dev,
+ "could not get pins_sleep pinstate\n");
+
+ pdata->pins_inactive = pinctrl_lookup_state(pdata->pinctrl,
+ "inactive");
+ if (IS_ERR(pdata->pins_inactive))
+ cif_isp10_pltfrm_pr_warn(dev,
+ "could not get pins_inactive pinstate\n");
+
+ if (!IS_ERR_OR_NULL(pdata->pins_default))
+ pinctrl_select_state(pdata->pinctrl,
+ pdata->pins_default);
+ }
+
+ for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++)
+ pdata->irq_handlers[i].mis = -EINVAL;
+
+ dev->platform_data = pdata;
+
+ INIT_LIST_HEAD(&pdata->csi0_configs);
+ INIT_LIST_HEAD(&pdata->csi1_configs);
+
+#ifndef CONFIG_DEBUG_FS
+ pdata->dbgfs.dir = debugfs_create_dir("cif_isp10", NULL);
+ pdata->dbgfs.csi0_file = debugfs_create_file(
+ "csi-0",
+ 0644,
+ pdata->dbgfs.dir,
+ dev,
+ &cif_isp10_dbgfs_csi_fops);
+ pdata->dbgfs.csi1_file = debugfs_create_file(
+ "csi-1",
+ 0644,
+ pdata->dbgfs.dir,
+ dev,
+ &cif_isp10_dbgfs_csi_fops);
+ pdata->dbgfs.cif_isp10_file = debugfs_create_file(
+ "cif_isp20",
+ 0200,
+ pdata->dbgfs.dir,
+ dev,
+ &cif_isp10_dbgfs_fops);
+ pdata->dbgfs.cif_isp10_file = debugfs_create_file(
+ "sensor",
+ 0644,
+ pdata->dbgfs.dir,
+ dev,
+ &cif_isp10_dbgfs_sensor_fops);
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+ pdata->dbgfs.reg_trace_file = debugfs_create_file(
+ "reg_trace",
+ 0644,
+ pdata->dbgfs.dir,
+ dev,
+ &cif_isp10_dbgfs_reg_trace_fops);
+ spin_lock_init(&cif_isp10_reg_trace.lock);
+ cif_isp10_reg_trace.reg_trace = NULL;
+ cif_isp10_dbgfs_reg_trace_clear(dev);
+ cif_isp10_reg_trace.reg_trace_max_size = 0;
+ cif_isp10_reg_trace.base_addr = base_addr;
+ cif_isp10_reg_trace.rtrace = true;
+ cif_isp10_reg_trace.ftrace = false;
+ cif_isp10_reg_trace.internal = false;
+#endif
+#endif
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+ if (!IS_ERR_OR_NULL(pdata))
+ devm_kfree(dev, pdata);
+ return ret;
+}
+
+int cif_isp10_pltfrm_soc_init(
+ struct cif_isp10_device *cif_isp10_dev,
+ struct pltfrm_soc_cfg *soc_cfg)
+{
+ struct pltfrm_soc_cfg_para cfg_para;
+ struct device *dev = cif_isp10_dev->dev;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct pltfrm_soc_init_para init_para;
+ int ret = 0;
+
+ if (!IS_ERR_OR_NULL(soc_cfg) && !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
+ cfg_para.cmd = PLTFRM_SOC_INIT;
+ cfg_para.cfg_para = &init_para;
+ init_para.pdev = pdev;
+ init_para.isp_base = cif_isp10_dev->config.base_addr;
+ ret = soc_cfg->soc_cfg(&cfg_para);
+ if (ret == 0)
+ cif_isp10_dev->soc_cfg = soc_cfg;
+ }
+
+ return ret;
+}
+
+int cif_isp10_pltfrm_mipi_dphy_config(
+ struct cif_isp10_device *cif_isp10_dev)
+{
+ struct pltfrm_soc_cfg_para cfg_para;
+ struct pltfrm_soc_cfg *soc_cfg;
+ int ret = 0;
+
+ soc_cfg = cif_isp10_dev->soc_cfg;
+ if (!IS_ERR_OR_NULL(soc_cfg) &&
+ !IS_ERR_OR_NULL(soc_cfg->soc_cfg)) {
+ cfg_para.cmd =
+ PLTFRM_MIPI_DPHY_CFG;
+ cfg_para.cfg_para =
+ (void *)(&cif_isp10_dev->config.cam_itf.cfg.mipi);
+ ret = soc_cfg->soc_cfg(&cfg_para);
+ }
+
+ return ret;
+}
+
+int cif_isp10_pltfrm_pm_set_state(
+ struct device *dev,
+ enum cif_isp10_pm_state pm_state)
+{
+ int ret;
+ struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
+ struct pltfrm_soc_cfg *soc_cfg = cif_isp10_dev->soc_cfg;
+ struct pltfrm_soc_cfg_para cfg_para;
+
+ switch (pm_state) {
+ case CIF_ISP10_PM_STATE_OFF:
+ case CIF_ISP10_PM_STATE_SUSPENDED:
+ cfg_para.cmd = PLTFRM_CLKDIS;
+ cfg_para.cfg_para = NULL;
+ ret = soc_cfg->soc_cfg(&cfg_para);
+ break;
+ case CIF_ISP10_PM_STATE_SW_STNDBY:
+ case CIF_ISP10_PM_STATE_STREAMING:
+ cfg_para.cmd = PLTFRM_CLKEN;
+ cfg_para.cfg_para = NULL;
+ ret = soc_cfg->soc_cfg(&cfg_para);
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev,
+ "unknown or unsupported PM state %d\n", pm_state);
+ return -EINVAL;
+ }
+
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(dev,
+ "setting pm state to %s failed with error %d\n",
+ cif_isp10_pltfrm_pm_state_string(pm_state), ret);
+ else
+ cif_isp10_pltfrm_pr_dbg(dev,
+ "successfully changed pm state to %s\n",
+ cif_isp10_pltfrm_pm_state_string(pm_state));
+ return ret;
+}
+
+int cif_isp10_pltfrm_g_interface_config(
+ struct cif_isp10_img_src *img_src,
+ struct pltfrm_cam_itf *cam_itf)
+{
+ int ret = 0;
+
+ ret = cif_isp10_img_src_ioctl(img_src,
+ PLTFRM_CIFCAM_G_ITF_CFG, (void *)cam_itf);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(
+ dev,
+ "cif_isp10_img_src_ioctl PLTFRM_CIFCAM_G_ITF_CFG failed!\n");
+ return ret;
+ }
+ return 0;
+}
+
+int cif_isp10_pltfrm_pinctrl_set_state(
+ struct device *dev,
+ enum cif_isp10_pinctrl_state pinctrl_state)
+{
+ int ret = 0;
+ struct cif_isp10_pltfrm_data *pdata = dev_get_platdata(dev);
+
+ cif_isp10_pltfrm_pr_dbg(dev,
+ "set pinctrl state to %d\n", pinctrl_state);
+
+ if (!pdata) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "unable to retrieve CIF platform data\n");
+ ret = -EINVAL;
+ goto err;
+ }
+ if (IS_ERR_OR_NULL(pdata->pinctrl))
+ return 0;
+
+ switch (pinctrl_state) {
+ case CIF_ISP10_PINCTRL_STATE_SLEEP:
+ if (!IS_ERR_OR_NULL(pdata->pins_sleep))
+ ret = pinctrl_select_state(pdata->pinctrl,
+ pdata->pins_sleep);
+ break;
+ case CIF_ISP10_PINCTRL_STATE_ACTIVE:
+ case CIF_ISP10_PINCTRL_STATE_DEFAULT:
+ if (!IS_ERR_OR_NULL(pdata->pins_default))
+ ret = pinctrl_select_state(pdata->pinctrl,
+ pdata->pins_default);
+ break;
+ case CIF_ISP10_PINCTRL_STATE_INACTIVE:
+ if (!IS_ERR_OR_NULL(pdata->pins_inactive))
+ ret = pinctrl_select_state(pdata->pinctrl,
+ pdata->pins_inactive);
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev,
+ "unknown or unsupported pinctrl state %d\n",
+ pinctrl_state);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
+ return ret;
+}
+
+int cif_isp10_pltfrm_irq_register_isr(
+ struct device *dev,
+ unsigned int mis,
+ int (*isr)(unsigned int mis, void *cntxt),
+ void *cntxt)
+{
+ int ret = 0;
+ unsigned int i;
+ int slot = -EINVAL;
+ struct platform_device *pdev =
+ container_of(dev, struct platform_device, dev);
+ struct cif_isp10_pltfrm_data *pdata =
+ dev_get_platdata(&pdev->dev);
+ bool skip_request_irq = false;
+ const char *irq_name;
+
+ switch (mis) {
+ case CIF_MIPI_MIS:
+ irq_name = "CIF_ISP10_MIPI_IRQ";
+ break;
+ case CIF_ISP_MIS:
+ irq_name = "CIF_ISP10_ISP_IRQ";
+ break;
+ case CIF_MI_MIS:
+ irq_name = "CIF_ISP10_MI_IRQ";
+ break;
+ default:
+ cif_isp10_pltfrm_pr_err(dev,
+ "unknown or unsupported IRQ %d\n", mis);
+ ret = -EINVAL;
+ goto err;
+ }
+ cif_isp10_pltfrm_pr_dbg(dev,
+ "registering ISR for IRQ %s\n", irq_name);
+
+ for (i = 0; i < ARRAY_SIZE(pdata->irq_handlers); i++) {
+ if (IS_ERR_VALUE(slot) &&
+ IS_ERR_VALUE(pdata->irq_handlers[i].mis))
+ slot = (int)i;
+ if (pdata->irq_handlers[i].mis == mis) {
+ cif_isp10_pltfrm_pr_dbg(dev,
+ "overwriting ISR for IRQ %s\n", irq_name);
+ slot = (int)i;
+ skip_request_irq = true;
+ break;
+ }
+ }
+ if (IS_ERR_VALUE(slot)) {
+ if (!isr)
+ return 0;
+ cif_isp10_pltfrm_pr_err(dev,
+ "cannot register ISR for IRQ %s, too many ISRs already registered\n",
+ irq_name);
+ ret = -EFAULT;
+ goto err;
+ }
+ pdata->irq_handlers[slot].isr = isr;
+ if (!isr) {
+ pdata->irq_handlers[slot].mis = -EINVAL;
+ skip_request_irq = true;
+ } else {
+ pdata->irq_handlers[slot].mis = mis;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(dev, "failed with error %d\n", ret);
+ return ret;
+}
+
+const char *cif_isp10_pltfrm_get_device_type(
+ struct device *dev)
+{
+ return dev->of_node->type;
+}
+
+const char *cif_isp10_pltfrm_dev_string(
+ struct device *dev)
+{
+ return dev_driver_string(dev);
+}
+
+int cif_isp10_pltfrm_get_img_src_device(
+ struct device *dev,
+ struct cif_isp10_img_src **img_src_array,
+ unsigned int array_len)
+{
+ struct device_node *node = NULL;
+ struct device_node *camera_list_node = NULL;
+ struct i2c_client *client = NULL;
+ int ret = 0;
+ int index, size = 0;
+ const __be32 *phandle;
+ int num_cameras = 0;
+ struct cif_isp10_device *cif_isp10_dev = dev_get_drvdata(dev);
+
+ node = of_node_get(dev->of_node);
+ if (IS_ERR_OR_NULL(node)) {
+ dev_err(dev, "Unable to obtain CIF device node\n");
+ ret = -EEXIST;
+ goto err;
+ }
+
+ phandle = of_get_property(node,
+ "rockchip,camera-modules-attached", &size);
+ if (IS_ERR_OR_NULL(phandle)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "no camera-modules-attached'\n");
+ ret = -EINVAL;
+ goto err;
+ }
+
+ for (index = 0; index < size / sizeof(*phandle); index++) {
+ camera_list_node = of_parse_phandle(node,
+ "rockchip,camera-modules-attached", index);
+ of_node_put(node);
+ if (IS_ERR_OR_NULL(camera_list_node)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "invalid index %d for property 'rockchip,camera-modules-attached'\n",
+ index);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ if (!strcmp(camera_list_node->type,
+ "v4l2-i2c-subdev")) {
+ client = of_find_i2c_device_by_node(
+ camera_list_node);
+ of_node_put(camera_list_node);
+ if (IS_ERR_OR_NULL(client)) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "could not get camera i2c client, maybe not yet created, deferring device probing...\n");
+ continue;
+ }
+ } else {
+ cif_isp10_pltfrm_pr_dbg(dev,
+ "device of type %s not supported\n",
+ camera_list_node->type);
+ of_node_put(camera_list_node);
+ continue;
+ }
+
+ img_src_array[num_cameras] =
+ cif_isp10_img_src_to_img_src(
+ &client->dev,
+ cif_isp10_dev->soc_cfg);
+ if (!IS_ERR_OR_NULL(img_src_array[num_cameras])) {
+ cif_isp10_pltfrm_pr_info(dev,
+ "%s attach to cif isp10 img_src_array[%d]\n",
+ cif_isp10_img_src_g_name(
+ img_src_array[num_cameras]),
+ num_cameras);
+ num_cameras++;
+ if (num_cameras >= array_len) {
+ cif_isp10_pltfrm_pr_err(dev,
+ "cif isp10 isn't support > %d 'camera modules attached'\n",
+ array_len);
+ break;
+ }
+ } else {
+ continue;
+ }
+ }
+
+ return num_cameras;
+err:
+ dev_err(dev, "failed with error %d\n", ret);
+ if (!IS_ERR_OR_NULL(client))
+ put_device(&client->dev);
+ if (!IS_ERR_OR_NULL(camera_list_node))
+ of_node_put(camera_list_node);
+ return ret;
+}
+
+void cif_isp10_pltfrm_dev_release(
+ struct device *dev)
+{
+#ifndef CONFIG_DEBUG_FS
+ {
+ struct cif_isp10_pltfrm_data *pdata =
+ dev->platform_data;
+ debugfs_remove(pdata->dbgfs.csi0_file);
+ debugfs_remove(pdata->dbgfs.csi1_file);
+ debugfs_remove_recursive(pdata->dbgfs.dir);
+ }
+#endif
+}
+
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _CIF_ISP10_PLTFRM_H
+#define _CIF_ISP10_PLTFRM_H
+
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/delay.h>
+#include <linux/wait.h>
+#include <linux/string.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+struct cif_isp10_strm_fmt;
+struct cif_isp10_csi_config;
+struct cif_isp10_device;
+struct cif_isp10_img_src;
+struct pltfrm_cam_itf;
+enum cif_isp10_pinctrl_state;
+enum cif_isp10_inp;
+enum cif_isp10_pm_state;
+
+#define CIF_ISP10_PLTFRM_DEVICE struct device *
+#define CIF_ISP10_PLTFRM_MEM_IO_ADDR void __iomem *
+#define CIF_ISP10_PLTFRM_EVENT wait_queue_head_t
+
+extern spinlock_t iowrite32_verify_lock;
+#ifdef CONFIG_CIF_ISP10_REG_TRACE
+int
+cif_isp10_pltfrm_rtrace_printf(
+ struct device *dev,
+ const char *fmt,
+ ...);
+
+int
+cif_isp10_pltfrm_ftrace_printf(
+ struct device *dev,
+ const char *fmt,
+ ...);
+
+#else
+#define cif_isp10_pltfrm_rtrace_printf(dev, str, ...)
+#define cif_isp10_pltfrm_ftrace_printf(dev, str, ...)
+#endif
+
+#define cif_isp10_pltfrm_pr_dbg(dev, fmt, arg...) \
+ do { \
+ pr_debug("%s: " fmt, \
+ __func__, ## arg); \
+ cif_isp10_pltfrm_ftrace_printf(dev, "%s: " fmt, \
+ __func__, ## arg); \
+ } while (0)
+#define cif_isp10_pltfrm_pr_info(dev, fmt, arg...) \
+ do { \
+ pr_info("%s: " fmt, \
+ __func__, ## arg); \
+ cif_isp10_pltfrm_ftrace_printf(dev, "%s: " fmt, \
+ __func__, ## arg); \
+ } while (0)
+#define cif_isp10_pltfrm_pr_warn(dev, fmt, arg...) \
+ do { \
+ pr_warn("%s WARN: " fmt, \
+ __func__, ## arg); \
+ cif_isp10_pltfrm_ftrace_printf(dev, "%s WARN: " fmt, \
+ __func__, ## arg); \
+ } while (0)
+#define cif_isp10_pltfrm_pr_err(dev, fmt, arg...) \
+ do { \
+ pr_err("%s(%d) ERR: " fmt, \
+ __func__, __LINE__, ## arg); \
+ cif_isp10_pltfrm_ftrace_printf(dev, "%s(%d) ERR: " fmt, \
+ __func__, __LINE__, ## arg); \
+ } while (0)
+
+void cif_isp10_pltfrm_write_reg(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+void cif_isp10_pltfrm_write_reg_OR(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+void cif_isp10_pltfrm_write_reg_AND(
+ struct device *dev,
+ u32 data,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+u32 cif_isp10_pltfrm_read_reg(
+ struct device *dev,
+ CIF_ISP10_PLTFRM_MEM_IO_ADDR addr);
+
+#define cif_iowrite32(d, a) \
+ cif_isp10_pltfrm_write_reg(NULL, (u32)(d), a)
+#define cif_ioread32(a) \
+ cif_isp10_pltfrm_read_reg(NULL, a)
+#define cif_iowrite32OR(d, a) \
+ cif_isp10_pltfrm_write_reg_OR(NULL, (u32)(d), a)
+#define cif_iowrite32AND(d, a) \
+ cif_isp10_pltfrm_write_reg_AND(NULL, (u32)(d), a)
+/* BUG: Register write seems to fail sometimes w/o read before write. */
+#define cif_iowrite32_verify(d, a, mask) \
+ { \
+ unsigned int i = 0; \
+ unsigned long flags = 0; \
+ spin_lock_irqsave(&iowrite32_verify_lock, flags); \
+ do { \
+ cif_iowrite32(d, a); \
+ udelay(1); \
+ if (i++ == 50) { \
+ pr_err("Error in writing %x@0x%p, read %x\n", \
+ (d) & (mask), a, ioread32(a)); \
+ WARN_ON(1); \
+ } \
+ } while ((ioread32(a) & mask) != ((d) & mask)); \
+ spin_unlock_irqrestore(&iowrite32_verify_lock, flags);\
+ }
+#define cif_iowrite32OR_verify(d, a, mask) \
+ cif_iowrite32_verify((u32)(d) | cif_ioread32(a), a, mask)
+#define cif_iowrite32AND_verify(d, a, mask) \
+ cif_iowrite32_verify((u32)(d) & cif_ioread32(a), a, mask)
+
+#define cif_isp10_pltfrm_event_init(_dev, _event) \
+ init_waitqueue_head(_event)
+
+#define cif_isp10_pltfrm_event_clear(_dev, _event)
+
+#define cif_isp10_pltfrm_event_signal(_dev, _event) \
+ wake_up_interruptible(_event)
+
+#define cif_isp10_pltfrm_event_wait_timeout( \
+ _dev, _event, _condition, _timeout_us) \
+ wait_event_interruptible_timeout( \
+ *(_event), _condition, ((_timeout_us) * HZ) / 1000000)
+
+void
+cif_isp10_pltfrm_debug_register_print_cb(
+ struct device *dev,
+ void (*print)(void *cntxt, const char *block_name),
+ void *cntxt);
+
+int cif_isp10_pltfrm_dev_init(
+ struct cif_isp10_device *cif_isp_dev,
+ struct device **dev,
+ void __iomem **reg_base_addr);
+
+void cif_isp10_pltfrm_dev_release(
+ struct device *dev);
+
+int cif_isp10_pltfrm_pm_set_state(
+ struct device *dev,
+ enum cif_isp10_pm_state state);
+
+int cif_isp10_pltfrm_write_cif_ana_bandgap_bias(
+ struct device *dev,
+ u32 val);
+
+int cif_isp10_pltfrm_pinctrl_set_state(
+ struct device *dev,
+ enum cif_isp10_pinctrl_state pinctrl_state);
+
+int cif_isp10_pltfrm_get_img_src_device(
+ struct device *dev,
+ struct cif_isp10_img_src **img_src_array,
+ unsigned int array_len);
+
+int cif_isp10_pltfrm_g_interface_config(
+ struct cif_isp10_img_src *img_src,
+ struct pltfrm_cam_itf *cam_itf);
+
+int cif_isp10_pltfrm_irq_register_isr(
+ struct device *dev,
+ unsigned int mis,
+ int (*isr)(unsigned int mis, void *cntxt),
+ void *cntxt);
+
+const char *cif_isp10_pltfrm_get_device_type(
+ struct device *dev);
+
+const char *cif_isp10_pltfrm_dev_string(
+ struct device *dev);
+
+int cif_isp10_pltfrm_soc_init(
+ struct cif_isp10_device *cif_isp10_dev,
+ struct pltfrm_soc_cfg *soc_cfg);
+
+int cif_isp10_pltfrm_mipi_dphy_config(
+ struct cif_isp10_device *cif_isp10_dev);
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _RK_CIF_ISP10_REGS_H
+#define _RK_CIF_ISP10_REGS_H
+
+/* ISP_CTRL */
+#define CIF_ISP_CTRL_ISP_ENABLE BIT(0)
+#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT (0 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_ITU656 BIT(1)
+#define CIF_ISP_CTRL_ISP_MODE_ITU601 (2 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU601 (3 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_DATA_MODE (4 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_BAYER_ITU656 (5 << 1)
+#define CIF_ISP_CTRL_ISP_MODE_RAW_PICT_ITU656 (6 << 1)
+#define CIF_ISP_CTRL_ISP_INFORM_ENABLE BIT(4)
+#define CIF_ISP_CTRL_ISP_GAMMA_IN_ENA BIT(6)
+#define CIF_ISP_CTRL_ISP_GAMMA_IN_DIS (0 << 6)
+#define CIF_ISP_CTRL_ISP_AWB_ENA BIT(7)
+#define CIF_ISP_CTRL_ISP_AWB_DIS (0 << 7)
+#define CIF_ISP_CTRL_ISP_CFG_UPD_PERMANENT BIT(8)
+#define CIF_ISP_CTRL_ISP_CFG_UPD BIT(9)
+#define CIF_ISP_CTRL_ISP_GEN_CFG_UPD BIT(10)
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_ENA BIT(11)
+#define CIF_ISP_CTRL_ISP_GAMMA_OUT_DIS (0 << 11)
+#define CIF_ISP_CTRL_ISP_FLASH_MODE_ENA BIT(12)
+#define CIF_ISP_CTRL_ISP_FLASH_MODE_DIS (0 << 12)
+#define CIF_ISP_CTRL_ISP_CSM_Y_FULL_ENA BIT(13)
+#define CIF_ISP_CTRL_ISP_CSM_C_FULL_ENA BIT(14)
+
+/* ISP_ACQ_PROP */
+#define CIF_ISP_ACQ_PROP_NEG_EDGE (0 << 0)
+#define CIF_ISP_ACQ_PROP_POS_EDGE BIT(0)
+#define CIF_ISP_ACQ_PROP_HSYNC_HIGH (0 << 1)
+#define CIF_ISP_ACQ_PROP_HSYNC_LOW BIT(1)
+#define CIF_ISP_ACQ_PROP_VSYNC_HIGH (0 << 2)
+#define CIF_ISP_ACQ_PROP_VSYNC_LOW BIT(2)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_RGGB (0 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_GRBG BIT(3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_GBRG (2 << 3)
+#define CIF_ISP_ACQ_PROP_BAYER_PAT_BGGR (3 << 3)
+#define CIF_ISP_ACQ_PROP_YCBYCR (0 << 7)
+#define CIF_ISP_ACQ_PROP_YCRYCB BIT(7)
+#define CIF_ISP_ACQ_PROP_CBYCRY (2 << 7)
+#define CIF_ISP_ACQ_PROP_CRYCBY (3 << 7)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_ALL (0 << 9)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_EVEN BIT(9)
+#define CIF_ISP_ACQ_PROP_FIELD_SEL_ODD (2 << 9)
+#define CIF_ISP_ACQ_PROP_IN_SEL_12B (0 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_10B_ZERO BIT(12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_10B_MSB (2 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_8B_ZERO (3 << 12)
+#define CIF_ISP_ACQ_PROP_IN_SEL_8B_MSB (4 << 12)
+
+/* VI_DPCL */
+#define CIF_VI_DPCL_DMA_JPEG (0 << 0)
+#define CIF_VI_DPCL_MP_MUX_MRSZ_MI BIT(0)
+#define CIF_VI_DPCL_MP_MUX_MRSZ_JPEG (2 << 0)
+#define CIF_VI_DPCL_CHAN_MODE_MP BIT(2)
+#define CIF_VI_DPCL_CHAN_MODE_SP (2 << 2)
+#define CIF_VI_DPCL_CHAN_MODE_MPSP (3 << 2)
+#define CIF_VI_DPCL_DMA_SW_SPMUX (0 << 4)
+#define CIF_VI_DPCL_DMA_SW_SI BIT(4)
+#define CIF_VI_DPCL_DMA_SW_IE (2 << 4)
+#define CIF_VI_DPCL_DMA_SW_JPEG (3 << 4)
+#define CIF_VI_DPCL_DMA_SW_ISP (4 << 4)
+#define CIF_VI_DPCL_IF_SEL_PARALLEL (0 << 8)
+#define CIF_VI_DPCL_IF_SEL_SMIA BIT(8)
+#define CIF_VI_DPCL_IF_SEL_MIPI (2 << 8)
+#define CIF_VI_DPCL_DMA_IE_MUX_CIF (0 << 10)
+#define CIF_VI_DPCL_DMA_IE_MUX_DMA BIT(10)
+#define CIF_VI_DPCL_DMA_SP_MUX_CIF (0 << 11)
+#define CIF_VI_DPCL_DMA_SP_MUX_DMA BIT(11)
+
+/* ISP_IMSC - ISP_MIS - ISP_RIS - ISP_ICR - ISP_ISR */
+#define CIF_ISP_OFF BIT(0)
+#define CIF_ISP_FRAME BIT(1)
+#define CIF_ISP_DATA_LOSS BIT(2)
+#define CIF_ISP_PIC_SIZE_ERROR BIT(3)
+#define CIF_ISP_AWB_DONE BIT(4)
+#define CIF_ISP_FRAME_IN BIT(5)
+#define CIF_ISP_V_START BIT(6)
+#define CIF_ISP_H_START BIT(7)
+#define CIF_ISP_FLASH_ON BIT(8)
+#define CIF_ISP_FLASH_OFF BIT(9)
+#define CIF_ISP_SHUTTER_ON BIT(10)
+#define CIF_ISP_SHUTTER_OFF BIT(11)
+#define CIF_ISP_AFM_SUM_OF BIT(12)
+#define CIF_ISP_AFM_LUM_OF BIT(13)
+#define CIF_ISP_AFM_FIN BIT(14)
+#define CIF_ISP_HIST_MEASURE_RDY BIT(15)
+#define CIF_ISP_FLASH_CAP BIT(17)
+#define CIF_ISP_EXP_END BIT(18)
+#define CIF_ISP_VSM_END BIT(19)
+
+/* ISP_ERR */
+#define CIF_ISP_ERR_INFORM_SIZE BIT(0)
+#define CIF_ISP_ERR_IS_SIZE BIT(1)
+#define CIF_ISP_ERR_OUTFORM_SIZE BIT(2)
+
+/* MI_CTRL */
+#define CIF_MI_CTRL_MP_ENABLE_IN BIT(0)
+#define CIF_MI_CTRL_MP_ENABLE_OUT BIT(16)
+#define CIF_MI_CTRL_MP_DISABLE (0 << 0)
+#define CIF_MI_CTRL_SP_ENABLE BIT(1)
+#define CIF_MI_CTRL_SP_DISABLE (0 << 1)
+#define CIF_MI_CTRL_JPEG_ENABLE BIT(2)
+#define CIF_MI_CTRL_JPEG_DISABLE (0 << 2)
+#define CIF_MI_CTRL_RAW_ENABLE BIT(3)
+#define CIF_MI_CTRL_RAW_DISABLE (0 << 3)
+#define CIF_MI_CTRL_HFLIP BIT(4)
+#define CIF_MI_CTRL_VFLIP BIT(5)
+#define CIF_MI_CTRL_ROT BIT(6)
+#define CIF_MI_BYTE_SWAP BIT(7)
+#define CIF_MI_NO_BYTE_SWAP (0 << 7)
+#define CIF_MI_SP_Y_FULL_YUV2RGB BIT(8)
+#define CIF_MI_SP_Y_REDUCED_YUV2RGB (0 << 8)
+#define CIF_MI_SP_CBCR_FULL_YUV2RGB BIT(9)
+#define CIF_MI_SP_CBCR_REDUCED_YUV2RGB (0 << 9)
+#define CIF_MI_SP_422NONCOSITEED BIT(10)
+#define CIF_MI_MP_PINGPONG_ENABEL BIT(11)
+#define CIF_MI_MP_PINGPONG_DISABEL (0 << 11)
+#define CIF_MI_SP_PINGPONG_ENABEL BIT(12)
+#define CIF_MI_SP_PINGPONG_DISABEL (0 << 12)
+#define CIF_MI_MP_AUTOUPDATE_ENABLE BIT(13)
+#define CIF_MI_MP_AUTOUPDATE_DISABLE (0 << 13)
+#define CIF_MI_SP_AUTOUPDATE_ENABLE BIT(14)
+#define CIF_MI_SP_AUTOUPDATE_DISABLE (0 << 14)
+#define CIF_MI_LAST_PIXEL_SIG_ENABLE BIT(15)
+#define CIF_MI_LAST_PIXEL_SIG_DISABLE (0 << 15)
+#define CIF_MI_CTRL_BURST_LEN_LUM_16 (0 << 16)
+#define CIF_MI_CTRL_BURST_LEN_LUM_32 BIT(16)
+#define CIF_MI_CTRL_BURST_LEN_LUM_64 (2 << 16)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_16 (0 << 18)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_32 BIT(18)
+#define CIF_MI_CTRL_BURST_LEN_CHROM_64 (2 << 18)
+#define CIF_MI_CTRL_INIT_BASE_EN BIT(20)
+#define CIF_MI_CTRL_INIT_BASE_DIS (0 << 20)
+#define CIF_MI_CTRL_INIT_OFFSET_EN BIT(21)
+#define CIF_MI_CTRL_INIT_OFFSET_DIS (0 << 21)
+#define CIF_MI_CTRL_MP_WRITE_FMT(a) ((a) << 22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_PLA (0 << 22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_SPLA BIT(22)
+#define CIF_MI_CTRL_MP_WRITE_FMT_INT (2 << 22)
+#define CIF_MI_CTRL_SP_WRITE_FMT(a) ((a) << 24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_PLA (0 << 24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_SPLA BIT(24)
+#define CIF_MI_CTRL_SP_WRITE_FMT_INT (2 << 24)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV400 (0 << 26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV420 BIT(26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV422 (2 << 26)
+#define CIF_MI_CTRL_SP_INPUT_FMT_YUV444 (3 << 26)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV400 (0 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV420 BIT(28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV422 (2 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_YUV444 (3 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB565 (4 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB666 (5 << 28)
+#define CIF_MI_CTRL_SP_OUTPUT_FMT_RGB888 (6 << 28)
+
+#define CIF_MI_CTRL_HFLIP_SHIFT 4
+#define CIF_MI_CTRL_VFLIP_SHIFT 5
+
+/* MI_INIT */
+#define CIF_MI_INIT_SKIP BIT(2)
+#define CIF_MI_INIT_SOFT_UPD BIT(4)
+
+/* RSZ_CTRL */
+#define CIF_RSZ_CTRL_SCALE_HY_ENABLE BIT(0)
+#define CIF_RSZ_CTRL_SCALE_HC_ENABLE BIT(1)
+#define CIF_RSZ_CTRL_SCALE_VY_ENABLE BIT(2)
+#define CIF_RSZ_CTRL_SCALE_VC_ENABLE BIT(3)
+#define CIF_RSZ_CTRL_SCALE_HY_UP BIT(4)
+#define CIF_RSZ_CTRL_SCALE_HC_UP BIT(5)
+#define CIF_RSZ_CTRL_SCALE_VY_UP BIT(6)
+#define CIF_RSZ_CTRL_SCALE_VC_UP BIT(7)
+#define CIF_RSZ_CTRL_CFG_UPD BIT(8)
+#define CIF_RSZ_CTRL_CFG_UPD_AUTO BIT(9)
+#define CIF_RSZ_SCALER_BYPASS BIT(16)
+
+/* MI_IMSC - MI_MIS - MI_RIS - MI_ICR - MI_ISR */
+#define CIF_MI_NOTHING (0 << 0)
+#define CIF_MI_MP_FRAME BIT(0)
+#define CIF_MI_SP_FRAME BIT(1)
+#define CIF_MI_MBLK_LINE BIT(2)
+#define CIF_MI_FILL_MP_Y BIT(3)
+#define CIF_MI_WRAP_MP_Y BIT(4)
+#define CIF_MI_WRAP_MP_CB BIT(5)
+#define CIF_MI_WRAP_MP_CR BIT(6)
+#define CIF_MI_WRAP_SP_Y BIT(7)
+#define CIF_MI_WRAP_SP_CB BIT(8)
+#define CIF_MI_WRAP_SP_CR BIT(9)
+#define CIF_MI_DMA_READY BIT(11)
+
+/* MI_STATUS */
+#define CIF_MI_STATUS_MP_Y_FIFO_FULL BIT(0)
+#define CIF_MI_STATUS_SP_Y_FIFO_FULL BIT(4)
+
+/* MI_DMA_CTRL */
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_16 (0 << 0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_32 BIT(0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_LUM_64 (2 << 0)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_16 (0 << 2)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_32 BIT(2)
+#define CIF_MI_DMA_CTRL_BURST_LEN_CHROM_64 (2 << 2)
+#define CIF_MI_DMA_CTRL_READ_FMT(a) ((a) << 4)
+#define CIF_MI_DMA_CTRL_READ_FMT_PLANAR (0 << 4)
+#define CIF_MI_DMA_CTRL_READ_FMT_SPLANAR BIT(4)
+#define CIF_MI_DMA_CTRL_READ_FMT_PACKED (2 << 4)
+#define CIF_MI_DMA_CTRL_FMT_YUV444 (3 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV422 (2 << 6)
+#define CIF_MI_DMA_CTRL_FMT_YUV420 BIT(6)
+#define CIF_MI_DMA_CTRL_FMT_YUV400 (0 << 6)
+#define CIF_MI_DMA_CTRL_BYTE_SWAP BIT(8)
+#define CIF_MI_DMA_CTRL_NO_BYTE_SWAP (0 << 8)
+#define CIF_MI_DMA_CTRL_CONTINUOUS_ENA BIT(9)
+#define CIF_MI_DMA_CTRL_CONTINUOUS_DIS (0 << 9)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_NO (0 << 12)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_8BIT BIT(12)
+#define CIF_MI_DMA_CTRL_RGB_BAYER_16BIT (2 << 12)
+/* MI_DMA_START */
+#define CIF_MI_DMA_START_ENABLE BIT(0)
+/* MI_XTD_FORMAT_CTRL */
+#define CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP BIT(0)
+#define CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP BIT(1)
+#define CIF_MI_XTD_FMT_CTRL_DMA_CB_CR_SWAP BIT(2)
+
+#define CIF_MI_ADDR_SIZE_ALIGN_MASK 0xfffffff8
+
+/* CCL */
+#define CIF_CCL_CIF_CLK_ENA (0 << 2)
+#define CIF_CCL_CIF_CLK_DIS BIT(2)
+/* ICCL */
+#define CIF_ICCL_ISP_CLK BIT(0)
+#define CIF_ICCL_CP_CLK BIT(1)
+#define CIF_ICCL_RES_2 BIT(2)
+#define CIF_ICCL_MRSZ_CLK BIT(3)
+#define CIF_ICCL_SRSZ_CLK BIT(4)
+#define CIF_ICCL_JPEG_CLK BIT(5)
+#define CIF_ICCL_MI_CLK BIT(6)
+#define CIF_ICCL_RES_7 BIT(7)
+#define CIF_ICCL_IE_CLK BIT(8)
+#define CIF_ICCL_SIMP_CLK BIT(9)
+#define CIF_ICCL_SMIA_CLK BIT(10)
+#define CIF_ICCL_MIPI_CLK BIT(11)
+#define CIF_ICCL_ALL_CLK (-1)
+#define CIF_ICCL_NO_CLK (0)
+/* IRCL */
+#define CIF_IRCL_ISP_SW_RST BIT(0)
+#define CIF_IRCL_CP_SW_RST BIT(1)
+#define CIF_IRCL_YCS_SW_RST BIT(2)
+#define CIF_IRCL_MRSZ_SW_RST BIT(3)
+#define CIF_IRCL_SRSZ_SW_RST BIT(4)
+#define CIF_IRCL_JPEG_SW_RST BIT(5)
+#define CIF_IRCL_MI_SW_RST BIT(6)
+#define CIF_IRCL_CIF_SW_RST BIT(7)
+#define CIF_IRCL_IE_SW_RST BIT(8)
+#define CIF_IRCL_SI_SW_RST BIT(9)
+#define CIF_IRCL_MIPI_SW_RST BIT(11)
+
+/* C_PROC_CTR */
+#define CIF_C_PROC_CTR_ENABLE BIT(0)
+#define CIF_C_PROC_CTR_DIS (0 << 0)
+#define CIF_C_PROC_YOUT_FULL BIT(1)
+#define CIF_C_PROC_YOUT_LIM (0 << 1)
+#define CIF_C_PROC_YIN_FULL BIT(2)
+#define CIF_C_PROC_YIN_LIM (0 << 2)
+#define CIF_C_PROC_COUT_FULL BIT(3)
+#define CIF_C_PROC_COUT_LIM (0 << 3)
+
+/* DUAL_CROP_CTRL */
+#define CIF_DUAL_CROP_MP_MODE_BYPASS (0 << 0)
+#define CIF_DUAL_CROP_MP_MODE_YUV BIT(0)
+#define CIF_DUAL_CROP_MP_MODE_RAW (2 << 0)
+#define CIF_DUAL_CROP_SP_MODE_BYPASS (0 << 2)
+#define CIF_DUAL_CROP_SP_MODE_YUV BIT(2)
+#define CIF_DUAL_CROP_SP_MODE_RAW (2 << 2)
+#define CIF_DUAL_CROP_CFG_UPD_PERMANENT BIT(4)
+#define CIF_DUAL_CROP_CFG_UPD BIT(5)
+#define CIF_DUAL_CROP_GEN_CFG_UPD BIT(6)
+
+/* IMG_EFF_CTRL */
+#define CIF_IMG_EFF_CTRL_ENABLE BIT(0)
+#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE (0 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE BIT(1)
+#define CIF_IMG_EFF_CTRL_MODE_SEPIA (2 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL (3 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_EMBOSS (4 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_SKETCH (5 << 1)
+#define CIF_IMG_EFF_CTRL_MODE_SHARPEN (6 << 1)
+#define CIF_IMG_EFF_CTRL_CFG_UPD BIT(4)
+#define CIF_IMG_EFF_CTRL_YCBCR_FULL BIT(5)
+
+#define CIF_IMG_EFF_CTRL_MODE_BLACKWHITE_SHIFT (0)
+#define CIF_IMG_EFF_CTRL_MODE_NEGATIVE_SHIFT (1)
+#define CIF_IMG_EFF_CTRL_MODE_SEPIA_SHIFT (2)
+#define CIF_IMG_EFF_CTRL_MODE_COLOR_SEL_SHIFT (3)
+#define CIF_IMG_EFF_CTRL_MODE_EMBOSS_SHIFT (4)
+#define CIF_IMG_EFF_CTRL_MODE_SKETCH_SHIFT (5)
+#define CIF_IMG_EFF_CTRL_MODE_SHARPEN_SHIFT (6)
+
+/* IMG_EFF_COLOR_SEL */
+#define CIF_IMG_EFF_COLOR_RGB (0 << 0)
+#define CIF_IMG_EFF_COLOR_B BIT(0)
+#define CIF_IMG_EFF_COLOR_G (2 << 0)
+#define CIF_IMG_EFF_COLOR_GB (3 << 0)
+#define CIF_IMG_EFF_COLOR_R (4 << 0)
+#define CIF_IMG_EFF_COLOR_RB (5 << 0)
+#define CIF_IMG_EFF_COLOR_RG (6 << 0)
+#define CIF_IMG_EFF_COLOR_RGB2 (7 << 0)
+
+/* JPE */
+#define CIF_JPE_GEN_HEADER_ENABLE BIT(0)
+#define CIF_JPE_ENCODE_ENABLE BIT(0)
+#define CIF_JPE_INIT_ENABLE BIT(0)
+#define CIF_JPE_LUM_SCALE_ENABLE BIT(0)
+#define CIF_JPE_CHROM_SCALE_ENABLE BIT(0)
+#define CIF_JPE_PIC_FORMAT_YUV422 BIT(0)
+#define CIF_JPE_PIC_FORMAT_YUV400 (4 << 0)
+
+#define CIF_JPE_TQ_TAB3 (3 << 0)
+#define CIF_JPE_TQ_TAB2 (2 << 0)
+#define CIF_JPE_TQ_TAB1 BIT(0)
+#define CIF_JPE_TQ_TAB0 (0 << 0)
+
+#define CIF_TQ_Y_SELECT (3 << 0)
+#define CIF_TQ_U_SELECT (3 << 0)
+#define CIF_TQ_V_SELECT (3 << 0)
+#define CIF_DC_V_TABLE (4 << 0)
+#define CIF_DC_U_TABLE (2 << 0)
+#define CIF_DC_Y_TABLE BIT(0)
+#define CIF_AC_V_TABLE (4 << 0)
+#define CIF_AC_U_TABLE (2 << 0)
+#define CIF_AC_Y_TABLE BIT(0)
+
+/* JPE_TAB_ID */
+#define CIF_JPE_TAB_ID_HUFFAC1 (7 << 0)
+#define CIF_JPE_TAB_ID_HUFFDC1 (6 << 0)
+#define CIF_JPE_TAB_ID_HUFFAC0 (5 << 0)
+#define CIF_JPE_TAB_ID_HUFFDC0 (4 << 0)
+#define CIF_JPE_TAB_ID_QUANT3 (3 << 0)
+#define CIF_JPE_TAB_ID_QUANT2 (2 << 0)
+#define CIF_JPE_TAB_ID_QUANT1 BIT(0)
+#define CIF_JPE_TAB_ID_QUANT0 (0 << 0)
+/* JPE_ENCODER_BUSY */
+#define CIF_ENCODER_BUSY BIT(0)
+/* JPE_HEADER_MODE */
+#define CIF_JPE_HEADER_MODE_NOAPPN (0 << 0)
+#define CIF_JPE_HEADER_MODE_NOAPPN1 BIT(0)
+#define CIF_JPE_HEADER_MODE_JFIF (2 << 0)
+#define CIF_JPE_HEADER_MODE_JFIF1 (3 << 0)
+/* JPE_ERROR_RIS */
+#define CIF_JPE_VLC_SYMB_ERROR BIT(4)
+#define CIF_JPE_DCT_ERROR BIT(7)
+#define CIF_JPE_R2B_IMG_SIZE_ERROR BIT(9)
+#define CIF_JPE_VLC_TAB_ERROR BIT(10)
+#define CIF_JPE_ERROR_MASK (CIF_JPE_VLC_SYMB_ERROR |\
+ CIF_JPE_DCT_ERROR |\
+ CIF_JPE_R2B_IMG_SIZE_ERROR |\
+ CIF_JPE_VLC_TAB_ERROR)
+/* JPE_STATUS_RIS */
+#define CIF_JPE_STATUS_ENCODE_DONE BIT(4)
+#define CIF_JPE_STATUS_GENHEADER_DONE BIT(5)
+
+/* MIPI */
+
+/* MIPI_DPHY1 */
+
+/* MIPI_DPHY2 */
+
+/* MIPI_CTRL */
+#define CIF_MIPI_CTRL_OUTPUT_ENA BIT(0)
+#define CIF_MIPI_CTRL_SHUTDOWNLANES(a) ((a) << 8)
+#define CIF_CSI_LANE_2 BIT(1)
+#define CIF_CSI_LANE_3 BIT(2)
+#define CIF_CSI_LANE_4 BIT(3)
+#define CIF_MIPI_CTRL_NUM_LANES(a) ((a) << 12)
+#define CIF_MIPI_CTRL_ERR_SOT_HS_ENA (0 << 16)
+#define CIF_MIPI_CTRL_ERR_SOT_HS_SKIP BIT(16)
+#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_ENA (0 << 17)
+#define CIF_MIPI_CTRL_ERR_SOT_SYNC_HS_SKIP BIT(17)
+#define CIF_MIPI_CTRL_CLOCKLANE_ENA BIT(18)
+
+/* MIPI_DATA_SEL */
+#define CIF_MIPI_DATA_SEL_VC(a) ((a) << 6)
+#define CIF_MIPI_DATA_SEL_DT(a) ((a) << 0)
+
+#define CIF_MIPI_INTERRUPT_ALL (-1)
+
+/* MIPI_IMSC, MIPI_RIS, MIPI_MIS, MIPI_ICR, MIPI_ISR */
+#define CIF_MIPI_SYNC_FIFO_OVFLW(a) ((a) << 0)
+#define CIF_MIPI_ERR_SOT(a) ((a) << 4)
+#define CIF_MIPI_ERR_SOT_SYNC(a) ((a) << 8)
+#define CIF_MIPI_ERR_EOT_SYNC(a) ((a) << 12)
+#define CIF_MIPI_ERR_CTRL(a) ((a) << 16)
+#define CIF_MIPI_ERR_PROTOCOL BIT(20)
+#define CIF_MIPI_ERR_ECC1 BIT(21)
+#define CIF_MIPI_ERR_ECC2 BIT(22)
+#define CIF_MIPI_ERR_CS BIT(23)
+#define CIF_MIPI_FRAME_END BIT(24)
+#define CIF_MIPI_ADD_DATA_OVFLW BIT(25)
+#define CIF_MIPI_ADD_DATA_WATER_MARK BIT(26)
+
+#define CIF_MIPI_ERR_CSI (CIF_MIPI_ERR_PROTOCOL | \
+ CIF_MIPI_ERR_ECC1 | \
+ CIF_MIPI_ERR_ECC2 | \
+ CIF_MIPI_ERR_CS)
+
+#define CIF_MIPI_ERR_DPHY (CIF_MIPI_ERR_SOT(3) | \
+ CIF_MIPI_ERR_SOT_SYNC(3) | \
+ CIF_MIPI_ERR_EOT_SYNC(3) | \
+ CIF_MIPI_ERR_CTRL(3))
+
+/* SUPER_IMPOSE */
+#define CIF_SUPER_IMP_CTRL_NORMAL_MODE BIT(0)
+#define CIF_SUPER_IMP_CTRL_BYPASS_MODE (0 << 0)
+#define CIF_SUPER_IMP_CTRL_REF_IMG_MEM BIT(1)
+#define CIF_SUPER_IMP_CTRL_REF_IMG_IE (0 << 1)
+#define CIF_SUPER_IMP_CTRL_TRANSP_DIS BIT(2)
+#define CIF_SUPER_IMP_CTRL_TRANSP_ENA (0 << 2)
+
+/* ISP HISTOGRAM CALCULATION : ISP_HIST_PROP */
+#define CIF_ISP_HIST_PROP_PDIV(a) ((a) << 3)
+#define CIF_ISP_HIST_PROP_MODE_DIS (0 << 0)
+#define CIF_ISP_HIST_PROP_MODE_RGB BIT(0)
+#define CIF_ISP_HIST_PROP_MODE_RED (2 << 0)
+#define CIF_ISP_HIST_PROP_MODE_GREEN (3 << 0)
+#define CIF_ISP_HIST_PROP_MODE_BLUE (4 << 0)
+#define CIF_ISP_HIST_PROP_MODE_LUM (5 << 0)
+
+/* AUTO FOCUS MEASUREMENT: ISP_AFM_CTRL */
+#define ISP_AFM_CTRL_ENABLE BIT(0)
+#define ISP_AFM_CTRL_DISABLE (0 << 0)
+
+/* SHUTTER CONTROL */
+#define CIF_ISP_SH_CTRL_SH_ENA BIT(0)
+#define CIF_ISP_SH_CTRL_SH_DIS (0 << 0)
+#define CIF_ISP_SH_CTRL_REP_EN BIT(1)
+#define CIF_ISP_SH_CTRL_REP_DIS (0 << 1)
+#define CIF_ISP_SH_CTRL_SRC_SH_TRIG BIT(2)
+#define CIF_ISP_SH_CTRL_SRC_VSYNC (0 << 2)
+#define CIF_ISP_SH_CTRL_EDGE_POS BIT(3)
+#define CIF_ISP_SH_CTRL_EDGE_NEG (0 << 3)
+#define CIF_ISP_SH_CTRL_POL_LOW BIT(4)
+#define CIF_ISP_SH_CTRL_POL_HIGH (0 << 4)
+
+/* FLASH MODULE */
+/* ISP_FLASH_CMD */
+#define CIF_FLASH_CMD_PRELIGHT_ON BIT(0)
+#define CIF_FLASH_CMD_PRELIGHT_OFF (0 << 0)
+#define CIF_FLASH_CMD_FLASH_ON BIT(1)
+#define CIF_FLASH_CMD_FLASH_OFF (0 << 1)
+#define CIF_FLASH_CMD_PRE_FLASH_ON BIT(2)
+#define CIF_FLASH_CMD_PRE_FLASH_OFF (0 << 2)
+/* ISP_FLASH_CONFIG */
+#define CIF_FLASH_CONFIG_PRELIGHT_BEG (0 << 1)
+#define CIF_FLASH_CONFIG_PRELIGHT_END BIT(0)
+#define CIF_FLASH_CONFIG_VSYNC_NEG (0 << 1)
+#define CIF_FLASH_CONFIG_VSYNC_POS BIT(1)
+#define CIF_FLASH_CONFIG_PRELIGHT_HIGH (0 << 2)
+#define CIF_FLASH_CONFIG_PRELIGHT_LOW BIT(2)
+#define CIF_FLASH_CONFIG_SRC_VSYNC (0 << 3)
+#define CIF_FLASH_CONFIG_SRC_FL_TRIG BIT(3)
+#define CIF_FLASH_CONFIG_DELAY(a) ((a) << 4)
+
+/* BAD PIXEL DETECTION */
+
+/* =================================================================== */
+/* CIF Registers */
+/* =================================================================== */
+#define CIF_CTRL_BASE (0x00000000)
+#define CIF_CCL ((CIF_CTRL_BASE + 0x00000000))
+#define CIF_VI_ID ((CIF_CTRL_BASE + 0x00000008))
+#define CIF_ICCL ((CIF_CTRL_BASE + 0x00000010))
+#define CIF_IRCL ((CIF_CTRL_BASE + 0x00000014))
+#define CIF_VI_DPCL ((CIF_CTRL_BASE + 0x00000018))
+
+#define CIF_IMG_EFF_BASE (0x00000200)
+#define CIF_IMG_EFF_CTRL ((CIF_IMG_EFF_BASE + 0x00000000))
+#define CIF_IMG_EFF_COLOR_SEL ((CIF_IMG_EFF_BASE + 0x00000004))
+#define CIF_IMG_EFF_MAT_1 ((CIF_IMG_EFF_BASE + 0x00000008))
+#define CIF_IMG_EFF_MAT_2 ((CIF_IMG_EFF_BASE + 0x0000000C))
+#define CIF_IMG_EFF_MAT_3 ((CIF_IMG_EFF_BASE + 0x00000010))
+#define CIF_IMG_EFF_MAT_4 ((CIF_IMG_EFF_BASE + 0x00000014))
+#define CIF_IMG_EFF_MAT_5 ((CIF_IMG_EFF_BASE + 0x00000018))
+#define CIF_IMG_EFF_TINT ((CIF_IMG_EFF_BASE + 0x0000001C))
+#define CIF_IMG_EFF_CTRL_SHD ((CIF_IMG_EFF_BASE + 0x00000020))
+#define CIF_IMG_EFF_SHARPEN ((CIF_IMG_EFF_BASE + 0x00000024))
+
+#define CIF_SUPER_IMP_BASE (0x00000300)
+#define CIF_SUPER_IMP_CTRL ((CIF_SUPER_IMP_BASE + 0x00000000))
+#define CIF_SUPER_IMP_OFFSET_X ((CIF_SUPER_IMP_BASE + 0x00000004))
+#define CIF_SUPER_IMP_OFFSET_Y ((CIF_SUPER_IMP_BASE + 0x00000008))
+#define CIF_SUPER_IMP_COLOR_Y ((CIF_SUPER_IMP_BASE + 0x0000000C))
+#define CIF_SUPER_IMP_COLOR_CB ((CIF_SUPER_IMP_BASE + 0x00000010))
+#define CIF_SUPER_IMP_COLOR_CR ((CIF_SUPER_IMP_BASE + 0x00000014))
+
+#define CIF_ISP_BASE (0x00000400)
+#define CIF_ISP_CTRL ((CIF_ISP_BASE + 0x00000000))
+#define CIF_ISP_ACQ_PROP ((CIF_ISP_BASE + 0x00000004))
+#define CIF_ISP_ACQ_H_OFFS ((CIF_ISP_BASE + 0x00000008))
+#define CIF_ISP_ACQ_V_OFFS ((CIF_ISP_BASE + 0x0000000C))
+#define CIF_ISP_ACQ_H_SIZE ((CIF_ISP_BASE + 0x00000010))
+#define CIF_ISP_ACQ_V_SIZE ((CIF_ISP_BASE + 0x00000014))
+#define CIF_ISP_ACQ_NR_FRAMES ((CIF_ISP_BASE + 0x00000018))
+#define CIF_ISP_GAMMA_DX_LO ((CIF_ISP_BASE + 0x0000001C))
+#define CIF_ISP_GAMMA_DX_HI ((CIF_ISP_BASE + 0x00000020))
+#define CIF_ISP_GAMMA_R_Y0 ((CIF_ISP_BASE + 0x00000024))
+#define CIF_ISP_GAMMA_R_Y1 ((CIF_ISP_BASE + 0x00000028))
+#define CIF_ISP_GAMMA_R_Y2 ((CIF_ISP_BASE + 0x0000002C))
+#define CIF_ISP_GAMMA_R_Y3 ((CIF_ISP_BASE + 0x00000030))
+#define CIF_ISP_GAMMA_R_Y4 ((CIF_ISP_BASE + 0x00000034))
+#define CIF_ISP_GAMMA_R_Y5 ((CIF_ISP_BASE + 0x00000038))
+#define CIF_ISP_GAMMA_R_Y6 ((CIF_ISP_BASE + 0x0000003C))
+#define CIF_ISP_GAMMA_R_Y7 ((CIF_ISP_BASE + 0x00000040))
+#define CIF_ISP_GAMMA_R_Y8 ((CIF_ISP_BASE + 0x00000044))
+#define CIF_ISP_GAMMA_R_Y9 ((CIF_ISP_BASE + 0x00000048))
+#define CIF_ISP_GAMMA_R_Y10 ((CIF_ISP_BASE + 0x0000004C))
+#define CIF_ISP_GAMMA_R_Y11 ((CIF_ISP_BASE + 0x00000050))
+#define CIF_ISP_GAMMA_R_Y12 ((CIF_ISP_BASE + 0x00000054))
+#define CIF_ISP_GAMMA_R_Y13 ((CIF_ISP_BASE + 0x00000058))
+#define CIF_ISP_GAMMA_R_Y14 ((CIF_ISP_BASE + 0x0000005C))
+#define CIF_ISP_GAMMA_R_Y15 ((CIF_ISP_BASE + 0x00000060))
+#define CIF_ISP_GAMMA_R_Y16 ((CIF_ISP_BASE + 0x00000064))
+#define CIF_ISP_GAMMA_G_Y0 ((CIF_ISP_BASE + 0x00000068))
+#define CIF_ISP_GAMMA_G_Y1 ((CIF_ISP_BASE + 0x0000006C))
+#define CIF_ISP_GAMMA_G_Y2 ((CIF_ISP_BASE + 0x00000070))
+#define CIF_ISP_GAMMA_G_Y3 ((CIF_ISP_BASE + 0x00000074))
+#define CIF_ISP_GAMMA_G_Y4 ((CIF_ISP_BASE + 0x00000078))
+#define CIF_ISP_GAMMA_G_Y5 ((CIF_ISP_BASE + 0x0000007C))
+#define CIF_ISP_GAMMA_G_Y6 ((CIF_ISP_BASE + 0x00000080))
+#define CIF_ISP_GAMMA_G_Y7 ((CIF_ISP_BASE + 0x00000084))
+#define CIF_ISP_GAMMA_G_Y8 ((CIF_ISP_BASE + 0x00000088))
+#define CIF_ISP_GAMMA_G_Y9 ((CIF_ISP_BASE + 0x0000008C))
+#define CIF_ISP_GAMMA_G_Y10 ((CIF_ISP_BASE + 0x00000090))
+#define CIF_ISP_GAMMA_G_Y11 ((CIF_ISP_BASE + 0x00000094))
+#define CIF_ISP_GAMMA_G_Y12 ((CIF_ISP_BASE + 0x00000098))
+#define CIF_ISP_GAMMA_G_Y13 ((CIF_ISP_BASE + 0x0000009C))
+#define CIF_ISP_GAMMA_G_Y14 ((CIF_ISP_BASE + 0x000000A0))
+#define CIF_ISP_GAMMA_G_Y15 ((CIF_ISP_BASE + 0x000000A4))
+#define CIF_ISP_GAMMA_G_Y16 ((CIF_ISP_BASE + 0x000000A8))
+#define CIF_ISP_GAMMA_B_Y0 ((CIF_ISP_BASE + 0x000000AC))
+#define CIF_ISP_GAMMA_B_Y1 ((CIF_ISP_BASE + 0x000000B0))
+#define CIF_ISP_GAMMA_B_Y2 ((CIF_ISP_BASE + 0x000000B4))
+#define CIF_ISP_GAMMA_B_Y3 ((CIF_ISP_BASE + 0x000000B8))
+#define CIF_ISP_GAMMA_B_Y4 ((CIF_ISP_BASE + 0x000000BC))
+#define CIF_ISP_GAMMA_B_Y5 ((CIF_ISP_BASE + 0x000000C0))
+#define CIF_ISP_GAMMA_B_Y6 ((CIF_ISP_BASE + 0x000000C4))
+#define CIF_ISP_GAMMA_B_Y7 ((CIF_ISP_BASE + 0x000000C8))
+#define CIF_ISP_GAMMA_B_Y8 ((CIF_ISP_BASE + 0x000000CC))
+#define CIF_ISP_GAMMA_B_Y9 ((CIF_ISP_BASE + 0x000000D0))
+#define CIF_ISP_GAMMA_B_Y10 ((CIF_ISP_BASE + 0x000000D4))
+#define CIF_ISP_GAMMA_B_Y11 ((CIF_ISP_BASE + 0x000000D8))
+#define CIF_ISP_GAMMA_B_Y12 ((CIF_ISP_BASE + 0x000000DC))
+#define CIF_ISP_GAMMA_B_Y13 ((CIF_ISP_BASE + 0x000000E0))
+#define CIF_ISP_GAMMA_B_Y14 ((CIF_ISP_BASE + 0x000000E4))
+#define CIF_ISP_GAMMA_B_Y15 ((CIF_ISP_BASE + 0x000000E8))
+#define CIF_ISP_GAMMA_B_Y16 ((CIF_ISP_BASE + 0x000000EC))
+#define CIF_ISP_AWB_PROP ((CIF_ISP_BASE + 0x00000110))
+#define CIF_ISP_AWB_WND_H_OFFS ((CIF_ISP_BASE + 0x00000114))
+#define CIF_ISP_AWB_WND_V_OFFS ((CIF_ISP_BASE + 0x00000118))
+#define CIF_ISP_AWB_WND_H_SIZE ((CIF_ISP_BASE + 0x0000011C))
+#define CIF_ISP_AWB_WND_V_SIZE ((CIF_ISP_BASE + 0x00000120))
+#define CIF_ISP_AWB_FRAMES ((CIF_ISP_BASE + 0x00000124))
+#define CIF_ISP_AWB_REF ((CIF_ISP_BASE + 0x00000128))
+#define CIF_ISP_AWB_THRESH ((CIF_ISP_BASE + 0x0000012C))
+#define CIF_ISP_AWB_GAIN_G ((CIF_ISP_BASE + 0x00000138))
+#define CIF_ISP_AWB_GAIN_RB ((CIF_ISP_BASE + 0x0000013C))
+#define CIF_ISP_AWB_WHITE_CNT ((CIF_ISP_BASE + 0x00000140))
+#define CIF_ISP_AWB_MEAN ((CIF_ISP_BASE + 0x00000144))
+#define CIF_ISP_CC_COEFF_0 ((CIF_ISP_BASE + 0x00000170))
+#define CIF_ISP_CC_COEFF_1 ((CIF_ISP_BASE + 0x00000174))
+#define CIF_ISP_CC_COEFF_2 ((CIF_ISP_BASE + 0x00000178))
+#define CIF_ISP_CC_COEFF_3 ((CIF_ISP_BASE + 0x0000017C))
+#define CIF_ISP_CC_COEFF_4 ((CIF_ISP_BASE + 0x00000180))
+#define CIF_ISP_CC_COEFF_5 ((CIF_ISP_BASE + 0x00000184))
+#define CIF_ISP_CC_COEFF_6 ((CIF_ISP_BASE + 0x00000188))
+#define CIF_ISP_CC_COEFF_7 ((CIF_ISP_BASE + 0x0000018C))
+#define CIF_ISP_CC_COEFF_8 ((CIF_ISP_BASE + 0x00000190))
+#define CIF_ISP_OUT_H_OFFS ((CIF_ISP_BASE + 0x00000194))
+#define CIF_ISP_OUT_V_OFFS ((CIF_ISP_BASE + 0x00000198))
+#define CIF_ISP_OUT_H_SIZE ((CIF_ISP_BASE + 0x0000019C))
+#define CIF_ISP_OUT_V_SIZE ((CIF_ISP_BASE + 0x000001A0))
+#define CIF_ISP_DEMOSAIC ((CIF_ISP_BASE + 0x000001A4))
+#define CIF_ISP_FLAGS_SHD ((CIF_ISP_BASE + 0x000001A8))
+#define CIF_ISP_OUT_H_OFFS_SHD ((CIF_ISP_BASE + 0x000001AC))
+#define CIF_ISP_OUT_V_OFFS_SHD ((CIF_ISP_BASE + 0x000001B0))
+#define CIF_ISP_OUT_H_SIZE_SHD ((CIF_ISP_BASE + 0x000001B4))
+#define CIF_ISP_OUT_V_SIZE_SHD ((CIF_ISP_BASE + 0x000001B8))
+#define CIF_ISP_IMSC ((CIF_ISP_BASE + 0x000001BC))
+#define CIF_ISP_RIS ((CIF_ISP_BASE + 0x000001C0))
+#define CIF_ISP_MIS ((CIF_ISP_BASE + 0x000001C4))
+#define CIF_ISP_ICR ((CIF_ISP_BASE + 0x000001C8))
+#define CIF_ISP_ISR ((CIF_ISP_BASE + 0x000001CC))
+#define CIF_ISP_CT_COEFF_0 ((CIF_ISP_BASE + 0x000001D0))
+#define CIF_ISP_CT_COEFF_1 ((CIF_ISP_BASE + 0x000001D4))
+#define CIF_ISP_CT_COEFF_2 ((CIF_ISP_BASE + 0x000001D8))
+#define CIF_ISP_CT_COEFF_3 ((CIF_ISP_BASE + 0x000001DC))
+#define CIF_ISP_CT_COEFF_4 ((CIF_ISP_BASE + 0x000001E0))
+#define CIF_ISP_CT_COEFF_5 ((CIF_ISP_BASE + 0x000001E4))
+#define CIF_ISP_CT_COEFF_6 ((CIF_ISP_BASE + 0x000001E8))
+#define CIF_ISP_CT_COEFF_7 ((CIF_ISP_BASE + 0x000001EC))
+#define CIF_ISP_CT_COEFF_8 ((CIF_ISP_BASE + 0x000001F0))
+#define CIF_ISP_GAMMA_OUT_MODE ((CIF_ISP_BASE + 0x000001F4))
+#define CIF_ISP_GAMMA_OUT_Y_0 ((CIF_ISP_BASE + 0x000001F8))
+#define CIF_ISP_GAMMA_OUT_Y_1 ((CIF_ISP_BASE + 0x000001FC))
+#define CIF_ISP_GAMMA_OUT_Y_2 ((CIF_ISP_BASE + 0x00000200))
+#define CIF_ISP_GAMMA_OUT_Y_3 ((CIF_ISP_BASE + 0x00000204))
+#define CIF_ISP_GAMMA_OUT_Y_4 ((CIF_ISP_BASE + 0x00000208))
+#define CIF_ISP_GAMMA_OUT_Y_5 ((CIF_ISP_BASE + 0x0000020C))
+#define CIF_ISP_GAMMA_OUT_Y_6 ((CIF_ISP_BASE + 0x00000210))
+#define CIF_ISP_GAMMA_OUT_Y_7 ((CIF_ISP_BASE + 0x00000214))
+#define CIF_ISP_GAMMA_OUT_Y_8 ((CIF_ISP_BASE + 0x00000218))
+#define CIF_ISP_GAMMA_OUT_Y_9 ((CIF_ISP_BASE + 0x0000021C))
+#define CIF_ISP_GAMMA_OUT_Y_10 ((CIF_ISP_BASE + 0x00000220))
+#define CIF_ISP_GAMMA_OUT_Y_11 ((CIF_ISP_BASE + 0x00000224))
+#define CIF_ISP_GAMMA_OUT_Y_12 ((CIF_ISP_BASE + 0x00000228))
+#define CIF_ISP_GAMMA_OUT_Y_13 ((CIF_ISP_BASE + 0x0000022C))
+#define CIF_ISP_GAMMA_OUT_Y_14 ((CIF_ISP_BASE + 0x00000230))
+#define CIF_ISP_GAMMA_OUT_Y_15 ((CIF_ISP_BASE + 0x00000234))
+#define CIF_ISP_GAMMA_OUT_Y_16 ((CIF_ISP_BASE + 0x00000238))
+#define CIF_ISP_ERR ((CIF_ISP_BASE + 0x0000023C))
+#define CIF_ISP_ERR_CLR ((CIF_ISP_BASE + 0x00000240))
+#define CIF_ISP_FRAME_COUNT ((CIF_ISP_BASE + 0x00000244))
+#define CIF_ISP_CT_OFFSET_R ((CIF_ISP_BASE + 0x00000248))
+#define CIF_ISP_CT_OFFSET_G ((CIF_ISP_BASE + 0x0000024C))
+#define CIF_ISP_CT_OFFSET_B ((CIF_ISP_BASE + 0x00000250))
+
+#define CIF_ISP_FLASH_BASE (0x00000660)
+#define CIF_ISP_FLASH_CMD ((CIF_ISP_FLASH_BASE + 0x00000000))
+#define CIF_ISP_FLASH_CONFIG ((CIF_ISP_FLASH_BASE + 0x00000004))
+#define CIF_ISP_FLASH_PREDIV ((CIF_ISP_FLASH_BASE + 0x00000008))
+#define CIF_ISP_FLASH_DELAY ((CIF_ISP_FLASH_BASE + 0x0000000C))
+#define CIF_ISP_FLASH_TIME ((CIF_ISP_FLASH_BASE + 0x00000010))
+#define CIF_ISP_FLASH_MAXP ((CIF_ISP_FLASH_BASE + 0x00000014))
+
+#define CIF_ISP_SH_BASE (0x00000680)
+#define CIF_ISP_SH_CTRL ((CIF_ISP_SH_BASE + 0x00000000))
+#define CIF_ISP_SH_PREDIV ((CIF_ISP_SH_BASE + 0x00000004))
+#define CIF_ISP_SH_DELAY ((CIF_ISP_SH_BASE + 0x00000008))
+#define CIF_ISP_SH_TIME ((CIF_ISP_SH_BASE + 0x0000000C))
+
+#define CIF_C_PROC_BASE (0x00000800)
+#define CIF_C_PROC_CTRL ((CIF_C_PROC_BASE + 0x00000000))
+#define CIF_C_PROC_CONTRAST ((CIF_C_PROC_BASE + 0x00000004))
+#define CIF_C_PROC_BRIGHTNESS ((CIF_C_PROC_BASE + 0x00000008))
+#define CIF_C_PROC_SATURATION ((CIF_C_PROC_BASE + 0x0000000C))
+#define CIF_C_PROC_HUE ((CIF_C_PROC_BASE + 0x00000010))
+
+#define CIF_DUAL_CROP_BASE (0x00000880)
+#define CIF_DUAL_CROP_CTRL (CIF_DUAL_CROP_BASE + 0x00000000)
+#define CIF_DUAL_CROP_M_H_OFFS (CIF_DUAL_CROP_BASE + 0x00000004)
+#define CIF_DUAL_CROP_M_V_OFFS (CIF_DUAL_CROP_BASE + 0x00000008)
+#define CIF_DUAL_CROP_M_H_SIZE (CIF_DUAL_CROP_BASE + 0x0000000C)
+#define CIF_DUAL_CROP_M_V_SIZE (CIF_DUAL_CROP_BASE + 0x00000010)
+#define CIF_DUAL_CROP_S_H_OFFS (CIF_DUAL_CROP_BASE + 0x00000014)
+#define CIF_DUAL_CROP_S_V_OFFS (CIF_DUAL_CROP_BASE + 0x00000018)
+#define CIF_DUAL_CROP_S_H_SIZE (CIF_DUAL_CROP_BASE + 0x0000001C)
+#define CIF_DUAL_CROP_S_V_SIZE (CIF_DUAL_CROP_BASE + 0x00000020)
+#define CIF_DUAL_CROP_M_H_OFFS_SHD (CIF_DUAL_CROP_BASE + 0x00000024)
+#define CIF_DUAL_CROP_M_V_OFFS_SHD (CIF_DUAL_CROP_BASE + 0x00000028)
+#define CIF_DUAL_CROP_M_H_SIZE_SHD (CIF_DUAL_CROP_BASE + 0x0000002C)
+#define CIF_DUAL_CROP_M_V_SIZE_SHD (CIF_DUAL_CROP_BASE + 0x00000030)
+#define CIF_DUAL_CROP_S_H_OFFS_SHD (CIF_DUAL_CROP_BASE + 0x00000034)
+#define CIF_DUAL_CROP_S_V_OFFS_SHD (CIF_DUAL_CROP_BASE + 0x00000038)
+#define CIF_DUAL_CROP_S_H_SIZE_SHD (CIF_DUAL_CROP_BASE + 0x0000003C)
+#define CIF_DUAL_CROP_S_V_SIZE_SHD \
+ (CIF_DUAL_CROP_BASE + 0x00000040)
+
+#define CIF_MRSZ_BASE (0x00000C00)
+#define CIF_MRSZ_CTRL ((CIF_MRSZ_BASE + 0x00000000))
+#define CIF_MRSZ_SCALE_HY ((CIF_MRSZ_BASE + 0x00000004))
+#define CIF_MRSZ_SCALE_HCB ((CIF_MRSZ_BASE + 0x00000008))
+#define CIF_MRSZ_SCALE_HCR ((CIF_MRSZ_BASE + 0x0000000C))
+#define CIF_MRSZ_SCALE_VY ((CIF_MRSZ_BASE + 0x00000010))
+#define CIF_MRSZ_SCALE_VC ((CIF_MRSZ_BASE + 0x00000014))
+#define CIF_MRSZ_PHASE_HY ((CIF_MRSZ_BASE + 0x00000018))
+#define CIF_MRSZ_PHASE_HC ((CIF_MRSZ_BASE + 0x0000001C))
+#define CIF_MRSZ_PHASE_VY ((CIF_MRSZ_BASE + 0x00000020))
+#define CIF_MRSZ_PHASE_VC ((CIF_MRSZ_BASE + 0x00000024))
+#define CIF_MRSZ_SCALE_LUT_ADDR ((CIF_MRSZ_BASE + 0x00000028))
+#define CIF_MRSZ_SCALE_LUT ((CIF_MRSZ_BASE + 0x0000002C))
+#define CIF_MRSZ_CTRL_SHD ((CIF_MRSZ_BASE + 0x00000030))
+#define CIF_MRSZ_SCALE_HY_SHD ((CIF_MRSZ_BASE + 0x00000034))
+#define CIF_MRSZ_SCALE_HCB_SHD ((CIF_MRSZ_BASE + 0x00000038))
+#define CIF_MRSZ_SCALE_HCR_SHD ((CIF_MRSZ_BASE + 0x0000003C))
+#define CIF_MRSZ_SCALE_VY_SHD ((CIF_MRSZ_BASE + 0x00000040))
+#define CIF_MRSZ_SCALE_VC_SHD ((CIF_MRSZ_BASE + 0x00000044))
+#define CIF_MRSZ_PHASE_HY_SHD ((CIF_MRSZ_BASE + 0x00000048))
+#define CIF_MRSZ_PHASE_HC_SHD ((CIF_MRSZ_BASE + 0x0000004C))
+#define CIF_MRSZ_PHASE_VY_SHD ((CIF_MRSZ_BASE + 0x00000050))
+#define CIF_MRSZ_PHASE_VC_SHD ((CIF_MRSZ_BASE + 0x00000054))
+
+#define CIF_SRSZ_BASE (0x00001000)
+#define CIF_SRSZ_CTRL ((CIF_SRSZ_BASE + 0x00000000))
+#define CIF_SRSZ_SCALE_HY ((CIF_SRSZ_BASE + 0x00000004))
+#define CIF_SRSZ_SCALE_HCB ((CIF_SRSZ_BASE + 0x00000008))
+#define CIF_SRSZ_SCALE_HCR ((CIF_SRSZ_BASE + 0x0000000C))
+#define CIF_SRSZ_SCALE_VY ((CIF_SRSZ_BASE + 0x00000010))
+#define CIF_SRSZ_SCALE_VC ((CIF_SRSZ_BASE + 0x00000014))
+#define CIF_SRSZ_PHASE_HY ((CIF_SRSZ_BASE + 0x00000018))
+#define CIF_SRSZ_PHASE_HC ((CIF_SRSZ_BASE + 0x0000001C))
+#define CIF_SRSZ_PHASE_VY ((CIF_SRSZ_BASE + 0x00000020))
+#define CIF_SRSZ_PHASE_VC ((CIF_SRSZ_BASE + 0x00000024))
+#define CIF_SRSZ_SCALE_LUT_ADDR ((CIF_SRSZ_BASE + 0x00000028))
+#define CIF_SRSZ_SCALE_LUT ((CIF_SRSZ_BASE + 0x0000002C))
+#define CIF_SRSZ_CTRL_SHD ((CIF_SRSZ_BASE + 0x00000030))
+#define CIF_SRSZ_SCALE_HY_SHD ((CIF_SRSZ_BASE + 0x00000034))
+#define CIF_SRSZ_SCALE_HCB_SHD ((CIF_SRSZ_BASE + 0x00000038))
+#define CIF_SRSZ_SCALE_HCR_SHD ((CIF_SRSZ_BASE + 0x0000003C))
+#define CIF_SRSZ_SCALE_VY_SHD ((CIF_SRSZ_BASE + 0x00000040))
+#define CIF_SRSZ_SCALE_VC_SHD ((CIF_SRSZ_BASE + 0x00000044))
+#define CIF_SRSZ_PHASE_HY_SHD ((CIF_SRSZ_BASE + 0x00000048))
+#define CIF_SRSZ_PHASE_HC_SHD ((CIF_SRSZ_BASE + 0x0000004C))
+#define CIF_SRSZ_PHASE_VY_SHD ((CIF_SRSZ_BASE + 0x00000050))
+#define CIF_SRSZ_PHASE_VC_SHD ((CIF_SRSZ_BASE + 0x00000054))
+
+#define CIF_MI_BASE (0x00001400)
+#define CIF_MI_CTRL ((CIF_MI_BASE + 0x00000000))
+#define CIF_MI_INIT ((CIF_MI_BASE + 0x00000004))
+#define CIF_MI_MP_Y_BASE_AD_INIT ((CIF_MI_BASE + 0x00000008))
+#define CIF_MI_MP_Y_SIZE_INIT ((CIF_MI_BASE + 0x0000000C))
+#define CIF_MI_MP_Y_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000010))
+#define CIF_MI_MP_Y_OFFS_CNT_START ((CIF_MI_BASE + 0x00000014))
+#define CIF_MI_MP_Y_IRQ_OFFS_INIT ((CIF_MI_BASE + 0x00000018))
+#define CIF_MI_MP_CB_BASE_AD_INIT ((CIF_MI_BASE + 0x0000001C))
+#define CIF_MI_MP_CB_SIZE_INIT ((CIF_MI_BASE + 0x00000020))
+#define CIF_MI_MP_CB_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000024))
+#define CIF_MI_MP_CB_OFFS_CNT_START ((CIF_MI_BASE + 0x00000028))
+#define CIF_MI_MP_CR_BASE_AD_INIT ((CIF_MI_BASE + 0x0000002C))
+#define CIF_MI_MP_CR_SIZE_INIT ((CIF_MI_BASE + 0x00000030))
+#define CIF_MI_MP_CR_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000034))
+#define CIF_MI_MP_CR_OFFS_CNT_START ((CIF_MI_BASE + 0x00000038))
+#define CIF_MI_SP_Y_BASE_AD_INIT ((CIF_MI_BASE + 0x0000003C))
+#define CIF_MI_SP_Y_SIZE_INIT ((CIF_MI_BASE + 0x00000040))
+#define CIF_MI_SP_Y_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000044))
+#define CIF_MI_SP_Y_OFFS_CNT_START ((CIF_MI_BASE + 0x00000048))
+#define CIF_MI_SP_Y_LLENGTH ((CIF_MI_BASE + 0x0000004C))
+#define CIF_MI_SP_CB_BASE_AD_INIT ((CIF_MI_BASE + 0x00000050))
+#define CIF_MI_SP_CB_SIZE_INIT ((CIF_MI_BASE + 0x00000054))
+#define CIF_MI_SP_CB_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000058))
+#define CIF_MI_SP_CB_OFFS_CNT_START ((CIF_MI_BASE + 0x0000005C))
+#define CIF_MI_SP_CR_BASE_AD_INIT ((CIF_MI_BASE + 0x00000060))
+#define CIF_MI_SP_CR_SIZE_INIT ((CIF_MI_BASE + 0x00000064))
+#define CIF_MI_SP_CR_OFFS_CNT_INIT ((CIF_MI_BASE + 0x00000068))
+#define CIF_MI_SP_CR_OFFS_CNT_START ((CIF_MI_BASE + 0x0000006C))
+#define CIF_MI_BYTE_CNT ((CIF_MI_BASE + 0x00000070))
+#define CIF_MI_CTRL_SHD ((CIF_MI_BASE + 0x00000074))
+#define CIF_MI_MP_Y_BASE_AD_SHD ((CIF_MI_BASE + 0x00000078))
+#define CIF_MI_MP_Y_SIZE_SHD ((CIF_MI_BASE + 0x0000007C))
+#define CIF_MI_MP_Y_OFFS_CNT_SHD ((CIF_MI_BASE + 0x00000080))
+#define CIF_MI_MP_Y_IRQ_OFFS_SHD ((CIF_MI_BASE + 0x00000084))
+#define CIF_MI_MP_CB_BASE_AD_SHD ((CIF_MI_BASE + 0x00000088))
+#define CIF_MI_MP_CB_SIZE_SHD ((CIF_MI_BASE + 0x0000008C))
+#define CIF_MI_MP_CB_OFFS_CNT_SHD ((CIF_MI_BASE + 0x00000090))
+#define CIF_MI_MP_CR_BASE_AD_SHD ((CIF_MI_BASE + 0x00000094))
+#define CIF_MI_MP_CR_SIZE_SHD ((CIF_MI_BASE + 0x00000098))
+#define CIF_MI_MP_CR_OFFS_CNT_SHD ((CIF_MI_BASE + 0x0000009C))
+#define CIF_MI_SP_Y_BASE_AD_SHD ((CIF_MI_BASE + 0x000000A0))
+#define CIF_MI_SP_Y_SIZE_SHD ((CIF_MI_BASE + 0x000000A4))
+#define CIF_MI_SP_Y_OFFS_CNT_SHD ((CIF_MI_BASE + 0x000000A8))
+#define CIF_MI_SP_CB_BASE_AD_SHD ((CIF_MI_BASE + 0x000000B0))
+#define CIF_MI_SP_CB_SIZE_SHD ((CIF_MI_BASE + 0x000000B4))
+#define CIF_MI_SP_CB_OFFS_CNT_SHD ((CIF_MI_BASE + 0x000000B8))
+#define CIF_MI_SP_CR_BASE_AD_SHD ((CIF_MI_BASE + 0x000000BC))
+#define CIF_MI_SP_CR_SIZE_SHD ((CIF_MI_BASE + 0x000000C0))
+#define CIF_MI_SP_CR_OFFS_CNT_SHD ((CIF_MI_BASE + 0x000000C4))
+#define CIF_MI_DMA_Y_PIC_START_AD ((CIF_MI_BASE + 0x000000C8))
+#define CIF_MI_DMA_Y_PIC_WIDTH ((CIF_MI_BASE + 0x000000CC))
+#define CIF_MI_DMA_Y_LLENGTH ((CIF_MI_BASE + 0x000000D0))
+#define CIF_MI_DMA_Y_PIC_SIZE ((CIF_MI_BASE + 0x000000D4))
+#define CIF_MI_DMA_CB_PIC_START_AD ((CIF_MI_BASE + 0x000000D8))
+#define CIF_MI_DMA_CR_PIC_START_AD ((CIF_MI_BASE + 0x000000E8))
+#define CIF_MI_IMSC ((CIF_MI_BASE + 0x000000F8))
+#define CIF_MI_RIS ((CIF_MI_BASE + 0x000000FC))
+#define CIF_MI_MIS ((CIF_MI_BASE + 0x00000100))
+#define CIF_MI_ICR ((CIF_MI_BASE + 0x00000104))
+#define CIF_MI_ISR ((CIF_MI_BASE + 0x00000108))
+#define CIF_MI_STATUS ((CIF_MI_BASE + 0x0000010C))
+#define CIF_MI_STATUS_CLR ((CIF_MI_BASE + 0x00000110))
+#define CIF_MI_SP_Y_PIC_WIDTH ((CIF_MI_BASE + 0x00000114))
+#define CIF_MI_SP_Y_PIC_HEIGHT ((CIF_MI_BASE + 0x00000118))
+#define CIF_MI_SP_Y_PIC_SIZE ((CIF_MI_BASE + 0x0000011C))
+#define CIF_MI_DMA_CTRL ((CIF_MI_BASE + 0x00000120))
+#define CIF_MI_DMA_START ((CIF_MI_BASE + 0x00000124))
+#define CIF_MI_DMA_STATUS ((CIF_MI_BASE + 0x00000128))
+#define CIF_MI_PIXEL_COUNT ((CIF_MI_BASE + 0x0000012C))
+#define CIF_MI_MP_Y_BASE_AD_INIT2 ((CIF_MI_BASE + 0x00000130))
+#define CIF_MI_MP_CB_BASE_AD_INIT2 ((CIF_MI_BASE + 0x00000134))
+#define CIF_MI_MP_CR_BASE_AD_INIT2 ((CIF_MI_BASE + 0x00000138))
+#define CIF_MI_SP_Y_BASE_AD_INIT2 ((CIF_MI_BASE + 0x0000013C))
+#define CIF_MI_SP_CB_BASE_AD_INIT2 ((CIF_MI_BASE + 0x00000140))
+#define CIF_MI_SP_CR_BASE_AD_INIT2 ((CIF_MI_BASE + 0x00000144))
+#define CIF_MI_XTD_FORMAT_CTRL ((CIF_MI_BASE + 0x00000148))
+
+#define CIF_JPE_BASE (0x00001800)
+#define CIF_JPE_GEN_HEADER ((CIF_JPE_BASE + 0x00000000))
+#define CIF_JPE_ENCODE ((CIF_JPE_BASE + 0x00000004))
+#define CIF_JPE_INIT ((CIF_JPE_BASE + 0x00000008))
+#define CIF_JPE_Y_SCALE_EN ((CIF_JPE_BASE + 0x0000000C))
+#define CIF_JPE_CBCR_SCALE_EN ((CIF_JPE_BASE + 0x00000010))
+#define CIF_JPE_TABLE_FLUSH ((CIF_JPE_BASE + 0x00000014))
+#define CIF_JPE_ENC_HSIZE ((CIF_JPE_BASE + 0x00000018))
+#define CIF_JPE_ENC_VSIZE ((CIF_JPE_BASE + 0x0000001C))
+#define CIF_JPE_PIC_FORMAT ((CIF_JPE_BASE + 0x00000020))
+#define CIF_JPE_RESTART_INTERVAL ((CIF_JPE_BASE + 0x00000024))
+#define CIF_JPE_TQ_Y_SELECT ((CIF_JPE_BASE + 0x00000028))
+#define CIF_JPE_TQ_U_SELECT ((CIF_JPE_BASE + 0x0000002C))
+#define CIF_JPE_TQ_V_SELECT ((CIF_JPE_BASE + 0x00000030))
+#define CIF_JPE_DC_TABLE_SELECT ((CIF_JPE_BASE + 0x00000034))
+#define CIF_JPE_AC_TABLE_SELECT ((CIF_JPE_BASE + 0x00000038))
+#define CIF_JPE_TABLE_DATA ((CIF_JPE_BASE + 0x0000003C))
+#define CIF_JPE_TABLE_ID ((CIF_JPE_BASE + 0x00000040))
+#define CIF_JPE_TAC0_LEN ((CIF_JPE_BASE + 0x00000044))
+#define CIF_JPE_TDC0_LEN ((CIF_JPE_BASE + 0x00000048))
+#define CIF_JPE_TAC1_LEN ((CIF_JPE_BASE + 0x0000004C))
+#define CIF_JPE_TDC1_LEN ((CIF_JPE_BASE + 0x00000050))
+#define CIF_JPE_ENCODER_BUSY ((CIF_JPE_BASE + 0x00000058))
+#define CIF_JPE_HEADER_MODE ((CIF_JPE_BASE + 0x0000005C))
+#define CIF_JPE_ENCODE_MODE ((CIF_JPE_BASE + 0x00000060))
+#define CIF_JPE_DEBUG ((CIF_JPE_BASE + 0x00000064))
+#define CIF_JPE_ERROR_IMSC ((CIF_JPE_BASE + 0x00000068))
+#define CIF_JPE_ERROR_RIS ((CIF_JPE_BASE + 0x0000006C))
+#define CIF_JPE_ERROR_MIS ((CIF_JPE_BASE + 0x00000070))
+#define CIF_JPE_ERROR_ICR ((CIF_JPE_BASE + 0x00000074))
+#define CIF_JPE_ERROR_ISR ((CIF_JPE_BASE + 0x00000078))
+#define CIF_JPE_STATUS_IMSC ((CIF_JPE_BASE + 0x0000007C))
+#define CIF_JPE_STATUS_RIS ((CIF_JPE_BASE + 0x00000080))
+#define CIF_JPE_STATUS_MIS ((CIF_JPE_BASE + 0x00000084))
+#define CIF_JPE_STATUS_ICR ((CIF_JPE_BASE + 0x00000088))
+#define CIF_JPE_STATUS_ISR ((CIF_JPE_BASE + 0x0000008C))
+#define CIF_JPE_CONFIG ((CIF_JPE_BASE + 0x00000090))
+
+#define CIF_SMIA_BASE (0x00001A00)
+#define CIF_SMIA_CTRL ((CIF_SMIA_BASE + 0x00000000))
+#define CIF_SMIA_STATUS ((CIF_SMIA_BASE + 0x00000004))
+#define CIF_SMIA_IMSC ((CIF_SMIA_BASE + 0x00000008))
+#define CIF_SMIA_RIS ((CIF_SMIA_BASE + 0x0000000C))
+#define CIF_SMIA_MIS ((CIF_SMIA_BASE + 0x00000010))
+#define CIF_SMIA_ICR ((CIF_SMIA_BASE + 0x00000014))
+#define CIF_SMIA_ISR ((CIF_SMIA_BASE + 0x00000018))
+#define CIF_SMIA_DATA_FORMAT_SEL ((CIF_SMIA_BASE + 0x0000001C))
+#define CIF_SMIA_SOF_EMB_DATA_LINES ((CIF_SMIA_BASE + 0x00000020))
+#define CIF_SMIA_EMB_HSTART ((CIF_SMIA_BASE + 0x00000024))
+#define CIF_SMIA_EMB_HSIZE ((CIF_SMIA_BASE + 0x00000028))
+#define CIF_SMIA_EMB_VSTART ((CIF_SMIA_BASE + 0x0000002c))
+#define CIF_SMIA_NUM_LINES ((CIF_SMIA_BASE + 0x00000030))
+#define CIF_SMIA_EMB_DATA_FIFO ((CIF_SMIA_BASE + 0x00000034))
+#define CIF_SMIA_EMB_DATA_WATERMARK ((CIF_SMIA_BASE + 0x00000038))
+
+#define CIF_MIPI_BASE (0x00001C00)
+#define CIF_MIPI_CTRL ((CIF_MIPI_BASE + 0x00000000))
+#define CIF_MIPI_STATUS ((CIF_MIPI_BASE + 0x00000004))
+#define CIF_MIPI_IMSC ((CIF_MIPI_BASE + 0x00000008))
+#define CIF_MIPI_RIS ((CIF_MIPI_BASE + 0x0000000C))
+#define CIF_MIPI_MIS ((CIF_MIPI_BASE + 0x00000010))
+#define CIF_MIPI_ICR ((CIF_MIPI_BASE + 0x00000014))
+#define CIF_MIPI_ISR ((CIF_MIPI_BASE + 0x00000018))
+#define CIF_MIPI_CUR_DATA_ID ((CIF_MIPI_BASE + 0x0000001C))
+#define CIF_MIPI_IMG_DATA_SEL ((CIF_MIPI_BASE + 0x00000020))
+#define CIF_MIPI_ADD_DATA_SEL_1 ((CIF_MIPI_BASE + 0x00000024))
+#define CIF_MIPI_ADD_DATA_SEL_2 ((CIF_MIPI_BASE + 0x00000028))
+#define CIF_MIPI_ADD_DATA_SEL_3 ((CIF_MIPI_BASE + 0x0000002C))
+#define CIF_MIPI_ADD_DATA_SEL_4 ((CIF_MIPI_BASE + 0x00000030))
+#define CIF_MIPI_ADD_DATA_FIFO ((CIF_MIPI_BASE + 0x00000034))
+#define CIF_MIPI_FIFO_FILL_LEVEL ((CIF_MIPI_BASE + 0x00000038))
+#define CIF_MIPI_COMPRESSED_MODE ((CIF_MIPI_BASE + 0x0000003C))
+#define CIF_MIPI_FRAME ((CIF_MIPI_BASE + 0x00000040))
+#define CIF_MIPI_GEN_SHORT_DT ((CIF_MIPI_BASE + 0x00000044))
+#define CIF_MIPI_GEN_SHORT_8_9 ((CIF_MIPI_BASE + 0x00000048))
+#define CIF_MIPI_GEN_SHORT_A_B ((CIF_MIPI_BASE + 0x0000004C))
+#define CIF_MIPI_GEN_SHORT_C_D ((CIF_MIPI_BASE + 0x00000050))
+#define CIF_MIPI_GEN_SHORT_E_F ((CIF_MIPI_BASE + 0x00000054))
+
+#define CIF_ISP_AFM_BASE (0x00002000)
+#define CIF_ISP_AFM_CTRL ((CIF_ISP_AFM_BASE + 0x00000000))
+#define CIF_ISP_AFM_LT_A ((CIF_ISP_AFM_BASE + 0x00000004))
+#define CIF_ISP_AFM_RB_A ((CIF_ISP_AFM_BASE + 0x00000008))
+#define CIF_ISP_AFM_LT_B ((CIF_ISP_AFM_BASE + 0x0000000C))
+#define CIF_ISP_AFM_RB_B ((CIF_ISP_AFM_BASE + 0x00000010))
+#define CIF_ISP_AFM_LT_C ((CIF_ISP_AFM_BASE + 0x00000014))
+#define CIF_ISP_AFM_RB_C ((CIF_ISP_AFM_BASE + 0x00000018))
+#define CIF_ISP_AFM_THRES ((CIF_ISP_AFM_BASE + 0x0000001C))
+#define CIF_ISP_AFM_VAR_SHIFT ((CIF_ISP_AFM_BASE + 0x00000020))
+#define CIF_ISP_AFM_SUM_A ((CIF_ISP_AFM_BASE + 0x00000024))
+#define CIF_ISP_AFM_SUM_B ((CIF_ISP_AFM_BASE + 0x00000028))
+#define CIF_ISP_AFM_SUM_C ((CIF_ISP_AFM_BASE + 0x0000002C))
+#define CIF_ISP_AFM_LUM_A ((CIF_ISP_AFM_BASE + 0x00000030))
+#define CIF_ISP_AFM_LUM_B ((CIF_ISP_AFM_BASE + 0x00000034))
+#define CIF_ISP_AFM_LUM_C ((CIF_ISP_AFM_BASE + 0x00000038))
+
+#define CIF_ISP_LSC_BASE (0x00002200)
+#define CIF_ISP_LSC_CTRL ((CIF_ISP_LSC_BASE + 0x00000000))
+#define CIF_ISP_LSC_R_TABLE_ADDR ((CIF_ISP_LSC_BASE + 0x00000004))
+#define CIF_ISP_LSC_GR_TABLE_ADDR ((CIF_ISP_LSC_BASE + 0x00000008))
+#define CIF_ISP_LSC_B_TABLE_ADDR ((CIF_ISP_LSC_BASE + 0x0000000C))
+#define CIF_ISP_LSC_GB_TABLE_ADDR ((CIF_ISP_LSC_BASE + 0x00000010))
+#define CIF_ISP_LSC_R_TABLE_DATA ((CIF_ISP_LSC_BASE + 0x00000014))
+#define CIF_ISP_LSC_GR_TABLE_DATA ((CIF_ISP_LSC_BASE + 0x00000018))
+#define CIF_ISP_LSC_B_TABLE_DATA ((CIF_ISP_LSC_BASE + 0x0000001C))
+#define CIF_ISP_LSC_GB_TABLE_DATA ((CIF_ISP_LSC_BASE + 0x00000020))
+#define CIF_ISP_LSC_XGRAD_01 ((CIF_ISP_LSC_BASE + 0x00000024))
+#define CIF_ISP_LSC_XGRAD_23 ((CIF_ISP_LSC_BASE + 0x00000028))
+#define CIF_ISP_LSC_XGRAD_45 ((CIF_ISP_LSC_BASE + 0x0000002C))
+#define CIF_ISP_LSC_XGRAD_67 ((CIF_ISP_LSC_BASE + 0x00000030))
+#define CIF_ISP_LSC_YGRAD_01 ((CIF_ISP_LSC_BASE + 0x00000034))
+#define CIF_ISP_LSC_YGRAD_23 ((CIF_ISP_LSC_BASE + 0x00000038))
+#define CIF_ISP_LSC_YGRAD_45 ((CIF_ISP_LSC_BASE + 0x0000003C))
+#define CIF_ISP_LSC_YGRAD_67 ((CIF_ISP_LSC_BASE + 0x00000040))
+#define CIF_ISP_LSC_XSIZE_01 ((CIF_ISP_LSC_BASE + 0x00000044))
+#define CIF_ISP_LSC_XSIZE_23 ((CIF_ISP_LSC_BASE + 0x00000048))
+#define CIF_ISP_LSC_XSIZE_45 ((CIF_ISP_LSC_BASE + 0x0000004C))
+#define CIF_ISP_LSC_XSIZE_67 ((CIF_ISP_LSC_BASE + 0x00000050))
+#define CIF_ISP_LSC_YSIZE_01 ((CIF_ISP_LSC_BASE + 0x00000054))
+#define CIF_ISP_LSC_YSIZE_23 ((CIF_ISP_LSC_BASE + 0x00000058))
+#define CIF_ISP_LSC_YSIZE_45 ((CIF_ISP_LSC_BASE + 0x0000005C))
+#define CIF_ISP_LSC_YSIZE_67 ((CIF_ISP_LSC_BASE + 0x00000060))
+#define CIF_ISP_LSC_TABLE_SEL ((CIF_ISP_LSC_BASE + 0x00000064))
+#define CIF_ISP_LSC_STATUS ((CIF_ISP_LSC_BASE + 0x00000068))
+
+#define CIF_ISP_IS_BASE (0x00002300)
+#define CIF_ISP_IS_CTRL ((CIF_ISP_IS_BASE + 0x00000000))
+#define CIF_ISP_IS_RECENTER ((CIF_ISP_IS_BASE + 0x00000004))
+#define CIF_ISP_IS_H_OFFS ((CIF_ISP_IS_BASE + 0x00000008))
+#define CIF_ISP_IS_V_OFFS ((CIF_ISP_IS_BASE + 0x0000000C))
+#define CIF_ISP_IS_H_SIZE ((CIF_ISP_IS_BASE + 0x00000010))
+#define CIF_ISP_IS_V_SIZE ((CIF_ISP_IS_BASE + 0x00000014))
+#define CIF_ISP_IS_MAX_DX ((CIF_ISP_IS_BASE + 0x00000018))
+#define CIF_ISP_IS_MAX_DY ((CIF_ISP_IS_BASE + 0x0000001C))
+#define CIF_ISP_IS_DISPLACE ((CIF_ISP_IS_BASE + 0x00000020))
+#define CIF_ISP_IS_H_OFFS_SHD ((CIF_ISP_IS_BASE + 0x00000024))
+#define CIF_ISP_IS_V_OFFS_SHD ((CIF_ISP_IS_BASE + 0x00000028))
+#define CIF_ISP_IS_H_SIZE_SHD ((CIF_ISP_IS_BASE + 0x0000002C))
+#define CIF_ISP_IS_V_SIZE_SHD ((CIF_ISP_IS_BASE + 0x00000030))
+
+#define CIF_ISP_HIST_BASE (0x00002400)
+
+#define CIF_ISP_HIST_PROP ((CIF_ISP_HIST_BASE + 0x00000000))
+#define CIF_ISP_HIST_H_OFFS ((CIF_ISP_HIST_BASE + 0x00000004))
+#define CIF_ISP_HIST_V_OFFS ((CIF_ISP_HIST_BASE + 0x00000008))
+#define CIF_ISP_HIST_H_SIZE ((CIF_ISP_HIST_BASE + 0x0000000C))
+#define CIF_ISP_HIST_V_SIZE ((CIF_ISP_HIST_BASE + 0x00000010))
+#define CIF_ISP_HIST_BIN_0 ((CIF_ISP_HIST_BASE + 0x00000014))
+#define CIF_ISP_HIST_BIN_1 ((CIF_ISP_HIST_BASE + 0x00000018))
+#define CIF_ISP_HIST_BIN_2 ((CIF_ISP_HIST_BASE + 0x0000001C))
+#define CIF_ISP_HIST_BIN_3 ((CIF_ISP_HIST_BASE + 0x00000020))
+#define CIF_ISP_HIST_BIN_4 ((CIF_ISP_HIST_BASE + 0x00000024))
+#define CIF_ISP_HIST_BIN_5 ((CIF_ISP_HIST_BASE + 0x00000028))
+#define CIF_ISP_HIST_BIN_6 ((CIF_ISP_HIST_BASE + 0x0000002C))
+#define CIF_ISP_HIST_BIN_7 ((CIF_ISP_HIST_BASE + 0x00000030))
+#define CIF_ISP_HIST_BIN_8 ((CIF_ISP_HIST_BASE + 0x00000034))
+#define CIF_ISP_HIST_BIN_9 ((CIF_ISP_HIST_BASE + 0x00000038))
+#define CIF_ISP_HIST_BIN_10 ((CIF_ISP_HIST_BASE + 0x0000003C))
+#define CIF_ISP_HIST_BIN_11 ((CIF_ISP_HIST_BASE + 0x00000040))
+#define CIF_ISP_HIST_BIN_12 ((CIF_ISP_HIST_BASE + 0x00000044))
+#define CIF_ISP_HIST_BIN_13 ((CIF_ISP_HIST_BASE + 0x00000048))
+#define CIF_ISP_HIST_BIN_14 ((CIF_ISP_HIST_BASE + 0x0000004C))
+#define CIF_ISP_HIST_BIN_15 ((CIF_ISP_HIST_BASE + 0x00000050))
+#define CIF_ISP_HIST_WEIGHT_00TO30 ((CIF_ISP_HIST_BASE + 0x00000054))
+#define CIF_ISP_HIST_WEIGHT_40TO21 ((CIF_ISP_HIST_BASE + 0x00000058))
+#define CIF_ISP_HIST_WEIGHT_31TO12 ((CIF_ISP_HIST_BASE + 0x0000005C))
+#define CIF_ISP_HIST_WEIGHT_22TO03 ((CIF_ISP_HIST_BASE + 0x00000060))
+#define CIF_ISP_HIST_WEIGHT_13TO43 ((CIF_ISP_HIST_BASE + 0x00000064))
+#define CIF_ISP_HIST_WEIGHT_04TO34 ((CIF_ISP_HIST_BASE + 0x00000068))
+#define CIF_ISP_HIST_WEIGHT_44 ((CIF_ISP_HIST_BASE + 0x0000006C))
+
+#define CIF_ISP_FILT_BASE (0x00002500)
+#define CIF_ISP_FILT_MODE ((CIF_ISP_FILT_BASE + 0x00000000))
+#define CIF_ISP_FILT_THRESH_BL0 ((CIF_ISP_FILT_BASE + 0x00000028))
+#define CIF_ISP_FILT_THRESH_BL1 ((CIF_ISP_FILT_BASE + 0x0000002c))
+#define CIF_ISP_FILT_THRESH_SH0 ((CIF_ISP_FILT_BASE + 0x00000030))
+#define CIF_ISP_FILT_THRESH_SH1 ((CIF_ISP_FILT_BASE + 0x00000034))
+#define CIF_ISP_FILT_LUM_WEIGHT ((CIF_ISP_FILT_BASE + 0x00000038))
+#define CIF_ISP_FILT_FAC_SH1 ((CIF_ISP_FILT_BASE + 0x0000003c))
+#define CIF_ISP_FILT_FAC_SH0 ((CIF_ISP_FILT_BASE + 0x00000040))
+#define CIF_ISP_FILT_FAC_MID ((CIF_ISP_FILT_BASE + 0x00000044))
+#define CIF_ISP_FILT_FAC_BL0 ((CIF_ISP_FILT_BASE + 0x00000048))
+#define CIF_ISP_FILT_FAC_BL1 ((CIF_ISP_FILT_BASE + 0x0000004C))
+
+#define CIF_ISP_CAC_BASE (0x00002580)
+#define CIF_ISP_CAC_CTRL (CIF_ISP_CAC_BASE + 0x00000000)
+#define CIF_ISP_CAC_COUNT_START (CIF_ISP_CAC_BASE + 0x00000004)
+#define CIF_ISP_CAC_A (CIF_ISP_CAC_BASE + 0x00000008)
+#define CIF_ISP_CAC_B (CIF_ISP_CAC_BASE + 0x0000000C)
+#define CIF_ISP_CAC_C (CIF_ISP_CAC_BASE + 0x00000010)
+#define CIF_ISP_X_NORM (CIF_ISP_CAC_BASE + 0x00000014)
+#define CIF_ISP_Y_NORM (CIF_ISP_CAC_BASE + 0x00000018)
+
+#define CIF_ISP_EXP_BASE (0x00002600)
+#define CIF_ISP_EXP_CTRL ((CIF_ISP_EXP_BASE + 0x00000000))
+#define CIF_ISP_EXP_H_OFFSET ((CIF_ISP_EXP_BASE + 0x00000004))
+#define CIF_ISP_EXP_V_OFFSET ((CIF_ISP_EXP_BASE + 0x00000008))
+#define CIF_ISP_EXP_H_SIZE ((CIF_ISP_EXP_BASE + 0x0000000C))
+#define CIF_ISP_EXP_V_SIZE ((CIF_ISP_EXP_BASE + 0x00000010))
+#define CIF_ISP_EXP_MEAN_00 ((CIF_ISP_EXP_BASE + 0x00000014))
+#define CIF_ISP_EXP_MEAN_10 ((CIF_ISP_EXP_BASE + 0x00000018))
+#define CIF_ISP_EXP_MEAN_20 ((CIF_ISP_EXP_BASE + 0x0000001c))
+#define CIF_ISP_EXP_MEAN_30 ((CIF_ISP_EXP_BASE + 0x00000020))
+#define CIF_ISP_EXP_MEAN_40 ((CIF_ISP_EXP_BASE + 0x00000024))
+#define CIF_ISP_EXP_MEAN_01 ((CIF_ISP_EXP_BASE + 0x00000028))
+#define CIF_ISP_EXP_MEAN_11 ((CIF_ISP_EXP_BASE + 0x0000002c))
+#define CIF_ISP_EXP_MEAN_21 ((CIF_ISP_EXP_BASE + 0x00000030))
+#define CIF_ISP_EXP_MEAN_31 ((CIF_ISP_EXP_BASE + 0x00000034))
+#define CIF_ISP_EXP_MEAN_41 ((CIF_ISP_EXP_BASE + 0x00000038))
+#define CIF_ISP_EXP_MEAN_02 ((CIF_ISP_EXP_BASE + 0x0000003c))
+#define CIF_ISP_EXP_MEAN_12 ((CIF_ISP_EXP_BASE + 0x00000040))
+#define CIF_ISP_EXP_MEAN_22 ((CIF_ISP_EXP_BASE + 0x00000044))
+#define CIF_ISP_EXP_MEAN_32 ((CIF_ISP_EXP_BASE + 0x00000048))
+#define CIF_ISP_EXP_MEAN_42 ((CIF_ISP_EXP_BASE + 0x0000004c))
+#define CIF_ISP_EXP_MEAN_03 ((CIF_ISP_EXP_BASE + 0x00000050))
+#define CIF_ISP_EXP_MEAN_13 ((CIF_ISP_EXP_BASE + 0x00000054))
+#define CIF_ISP_EXP_MEAN_23 ((CIF_ISP_EXP_BASE + 0x00000058))
+#define CIF_ISP_EXP_MEAN_33 ((CIF_ISP_EXP_BASE + 0x0000005c))
+#define CIF_ISP_EXP_MEAN_43 ((CIF_ISP_EXP_BASE + 0x00000060))
+#define CIF_ISP_EXP_MEAN_04 ((CIF_ISP_EXP_BASE + 0x00000064))
+#define CIF_ISP_EXP_MEAN_14 ((CIF_ISP_EXP_BASE + 0x00000068))
+#define CIF_ISP_EXP_MEAN_24 ((CIF_ISP_EXP_BASE + 0x0000006c))
+#define CIF_ISP_EXP_MEAN_34 ((CIF_ISP_EXP_BASE + 0x00000070))
+#define CIF_ISP_EXP_MEAN_44 ((CIF_ISP_EXP_BASE + 0x00000074))
+
+#define CIF_ISP_BLS_BASE (0x00002700)
+#define CIF_ISP_BLS_CTRL ((CIF_ISP_BLS_BASE + 0x00000000))
+#define CIF_ISP_BLS_SAMPLES ((CIF_ISP_BLS_BASE + 0x00000004))
+#define CIF_ISP_BLS_H1_START ((CIF_ISP_BLS_BASE + 0x00000008))
+#define CIF_ISP_BLS_H1_STOP ((CIF_ISP_BLS_BASE + 0x0000000c))
+#define CIF_ISP_BLS_V1_START ((CIF_ISP_BLS_BASE + 0x00000010))
+#define CIF_ISP_BLS_V1_STOP ((CIF_ISP_BLS_BASE + 0x00000014))
+#define CIF_ISP_BLS_H2_START ((CIF_ISP_BLS_BASE + 0x00000018))
+#define CIF_ISP_BLS_H2_STOP ((CIF_ISP_BLS_BASE + 0x0000001c))
+#define CIF_ISP_BLS_V2_START ((CIF_ISP_BLS_BASE + 0x00000020))
+#define CIF_ISP_BLS_V2_STOP ((CIF_ISP_BLS_BASE + 0x00000024))
+#define CIF_ISP_BLS_A_FIXED ((CIF_ISP_BLS_BASE + 0x00000028))
+#define CIF_ISP_BLS_B_FIXED ((CIF_ISP_BLS_BASE + 0x0000002c))
+#define CIF_ISP_BLS_C_FIXED ((CIF_ISP_BLS_BASE + 0x00000030))
+#define CIF_ISP_BLS_D_FIXED ((CIF_ISP_BLS_BASE + 0x00000034))
+#define CIF_ISP_BLS_A_MEASURED ((CIF_ISP_BLS_BASE + 0x00000038))
+#define CIF_ISP_BLS_B_MEASURED ((CIF_ISP_BLS_BASE + 0x0000003c))
+#define CIF_ISP_BLS_C_MEASURED ((CIF_ISP_BLS_BASE + 0x00000040))
+#define CIF_ISP_BLS_D_MEASURED ((CIF_ISP_BLS_BASE + 0x00000044))
+
+#define CIF_ISP_DPF_BASE (0x00002800)
+#define CIF_ISP_DPF_MODE (CIF_ISP_DPF_BASE + 0x00000000)
+#define CIF_ISP_DPF_STRENGTH_R (CIF_ISP_DPF_BASE + 0x00000004)
+#define CIF_ISP_DPF_STRENGTH_G (CIF_ISP_DPF_BASE + 0x00000008)
+#define CIF_ISP_DPF_STRENGTH_B (CIF_ISP_DPF_BASE + 0x0000000C)
+#define CIF_ISP_DPF_S_WEIGHT_G_1_4 (CIF_ISP_DPF_BASE + 0x00000010)
+#define CIF_ISP_DPF_S_WEIGHT_G_5_6 (CIF_ISP_DPF_BASE + 0x00000014)
+#define CIF_ISP_DPF_S_WEIGHT_RB_1_4 (CIF_ISP_DPF_BASE + 0x00000018)
+#define CIF_ISP_DPF_S_WEIGHT_RB_5_6 (CIF_ISP_DPF_BASE + 0x0000001C)
+#define CIF_ISP_DPF_NULL_COEFF_0 (CIF_ISP_DPF_BASE + 0x00000020)
+#define CIF_ISP_DPF_NULL_COEFF_1 (CIF_ISP_DPF_BASE + 0x00000024)
+#define CIF_ISP_DPF_NULL_COEFF_2 (CIF_ISP_DPF_BASE + 0x00000028)
+#define CIF_ISP_DPF_NULL_COEFF_3 (CIF_ISP_DPF_BASE + 0x0000002C)
+#define CIF_ISP_DPF_NULL_COEFF_4 (CIF_ISP_DPF_BASE + 0x00000030)
+#define CIF_ISP_DPF_NULL_COEFF_5 (CIF_ISP_DPF_BASE + 0x00000034)
+#define CIF_ISP_DPF_NULL_COEFF_6 (CIF_ISP_DPF_BASE + 0x00000038)
+#define CIF_ISP_DPF_NULL_COEFF_7 (CIF_ISP_DPF_BASE + 0x0000003C)
+#define CIF_ISP_DPF_NULL_COEFF_8 (CIF_ISP_DPF_BASE + 0x00000040)
+#define CIF_ISP_DPF_NULL_COEFF_9 (CIF_ISP_DPF_BASE + 0x00000044)
+#define CIF_ISP_DPF_NULL_COEFF_10 (CIF_ISP_DPF_BASE + 0x00000048)
+#define CIF_ISP_DPF_NULL_COEFF_11 (CIF_ISP_DPF_BASE + 0x0000004C)
+#define CIF_ISP_DPF_NULL_COEFF_12 (CIF_ISP_DPF_BASE + 0x00000050)
+#define CIF_ISP_DPF_NULL_COEFF_13 (CIF_ISP_DPF_BASE + 0x00000054)
+#define CIF_ISP_DPF_NULL_COEFF_14 (CIF_ISP_DPF_BASE + 0x00000058)
+#define CIF_ISP_DPF_NULL_COEFF_15 (CIF_ISP_DPF_BASE + 0x0000005C)
+#define CIF_ISP_DPF_NULL_COEFF_16 (CIF_ISP_DPF_BASE + 0x00000060)
+#define CIF_ISP_DPF_NF_GAIN_R (CIF_ISP_DPF_BASE + 0x00000064)
+#define CIF_ISP_DPF_NF_GAIN_GR (CIF_ISP_DPF_BASE + 0x00000068)
+#define CIF_ISP_DPF_NF_GAIN_GB (CIF_ISP_DPF_BASE + 0x0000006C)
+#define CIF_ISP_DPF_NF_GAIN_B (CIF_ISP_DPF_BASE + 0x00000070)
+
+#define CIF_ISP_DPCC_BASE (0x00002900)
+#define CIF_ISP_DPCC_MODE (CIF_ISP_DPCC_BASE + 0x00000000)
+#define CIF_ISP_DPCC_OUTPUT_MODE (CIF_ISP_DPCC_BASE + 0x00000004)
+#define CIF_ISP_DPCC_SET_USE (CIF_ISP_DPCC_BASE + 0x00000008)
+#define CIF_ISP_DPCC_METHODS_SET_1 (CIF_ISP_DPCC_BASE + 0x0000000C)
+#define CIF_ISP_DPCC_METHODS_SET_2 (CIF_ISP_DPCC_BASE + 0x00000010)
+#define CIF_ISP_DPCC_METHODS_SET_3 (CIF_ISP_DPCC_BASE + 0x00000014)
+#define CIF_ISP_DPCC_LINE_THRESH_1 (CIF_ISP_DPCC_BASE + 0x00000018)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_1 (CIF_ISP_DPCC_BASE + 0x0000001C)
+#define CIF_ISP_DPCC_PG_FAC_1 (CIF_ISP_DPCC_BASE + 0x00000020)
+#define CIF_ISP_DPCC_RND_THRESH_1 (CIF_ISP_DPCC_BASE + 0x00000024)
+#define CIF_ISP_DPCC_RG_FAC_1 (CIF_ISP_DPCC_BASE + 0x00000028)
+#define CIF_ISP_DPCC_LINE_THRESH_2 (CIF_ISP_DPCC_BASE + 0x0000002C)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_2 (CIF_ISP_DPCC_BASE + 0x00000030)
+#define CIF_ISP_DPCC_PG_FAC_2 (CIF_ISP_DPCC_BASE + 0x00000034)
+#define CIF_ISP_DPCC_RND_THRESH_2 (CIF_ISP_DPCC_BASE + 0x00000038)
+#define CIF_ISP_DPCC_RG_FAC_2 (CIF_ISP_DPCC_BASE + 0x0000003C)
+#define CIF_ISP_DPCC_LINE_THRESH_3 (CIF_ISP_DPCC_BASE + 0x00000040)
+#define CIF_ISP_DPCC_LINE_MAD_FAC_3 (CIF_ISP_DPCC_BASE + 0x00000044)
+#define CIF_ISP_DPCC_PG_FAC_3 (CIF_ISP_DPCC_BASE + 0x00000048)
+#define CIF_ISP_DPCC_RND_THRESH_3 (CIF_ISP_DPCC_BASE + 0x0000004C)
+#define CIF_ISP_DPCC_RG_FAC_3 (CIF_ISP_DPCC_BASE + 0x00000050)
+#define CIF_ISP_DPCC_RO_LIMITS (CIF_ISP_DPCC_BASE + 0x00000054)
+#define CIF_ISP_DPCC_RND_OFFS (CIF_ISP_DPCC_BASE + 0x00000058)
+#define CIF_ISP_DPCC_BPT_CTRL (CIF_ISP_DPCC_BASE + 0x0000005C)
+#define CIF_ISP_DPCC_BPT_NUMBER (CIF_ISP_DPCC_BASE + 0x00000060)
+#define CIF_ISP_DPCC_BPT_ADDR (CIF_ISP_DPCC_BASE + 0x00000064)
+#define CIF_ISP_DPCC_BPT_DATA (CIF_ISP_DPCC_BASE + 0x00000068)
+
+#define CIF_ISP_WDR_BASE (0x00002A00)
+#define CIF_ISP_WDR_CTRL (CIF_ISP_WDR_BASE + 0x00000000)
+#define CIF_ISP_WDR_TONECURVE_1 (CIF_ISP_WDR_BASE + 0x00000004)
+#define CIF_ISP_WDR_TONECURVE_2 (CIF_ISP_WDR_BASE + 0x00000008)
+#define CIF_ISP_WDR_TONECURVE_3 (CIF_ISP_WDR_BASE + 0x0000000C)
+#define CIF_ISP_WDR_TONECURVE_4 (CIF_ISP_WDR_BASE + 0x00000010)
+#define CIF_ISP_WDR_TONECURVE_YM_0 (CIF_ISP_WDR_BASE + 0x00000014)
+#define CIF_ISP_WDR_TONECURVE_YM_1 (CIF_ISP_WDR_BASE + 0x00000018)
+#define CIF_ISP_WDR_TONECURVE_YM_2 (CIF_ISP_WDR_BASE + 0x0000001C)
+#define CIF_ISP_WDR_TONECURVE_YM_3 (CIF_ISP_WDR_BASE + 0x00000020)
+#define CIF_ISP_WDR_TONECURVE_YM_4 (CIF_ISP_WDR_BASE + 0x00000024)
+#define CIF_ISP_WDR_TONECURVE_YM_5 (CIF_ISP_WDR_BASE + 0x00000028)
+#define CIF_ISP_WDR_TONECURVE_YM_6 (CIF_ISP_WDR_BASE + 0x0000002C)
+#define CIF_ISP_WDR_TONECURVE_YM_7 (CIF_ISP_WDR_BASE + 0x00000030)
+#define CIF_ISP_WDR_TONECURVE_YM_8 (CIF_ISP_WDR_BASE + 0x00000034)
+#define CIF_ISP_WDR_TONECURVE_YM_9 (CIF_ISP_WDR_BASE + 0x00000038)
+#define CIF_ISP_WDR_TONECURVE_YM_10 (CIF_ISP_WDR_BASE + 0x0000003C)
+#define CIF_ISP_WDR_TONECURVE_YM_11 (CIF_ISP_WDR_BASE + 0x00000040)
+#define CIF_ISP_WDR_TONECURVE_YM_12 (CIF_ISP_WDR_BASE + 0x00000044)
+#define CIF_ISP_WDR_TONECURVE_YM_13 (CIF_ISP_WDR_BASE + 0x00000048)
+#define CIF_ISP_WDR_TONECURVE_YM_14 (CIF_ISP_WDR_BASE + 0x0000004C)
+#define CIF_ISP_WDR_TONECURVE_YM_15 (CIF_ISP_WDR_BASE + 0x00000050)
+#define CIF_ISP_WDR_TONECURVE_YM_16 (CIF_ISP_WDR_BASE + 0x00000054)
+#define CIF_ISP_WDR_TONECURVE_YM_17 (CIF_ISP_WDR_BASE + 0x00000058)
+#define CIF_ISP_WDR_TONECURVE_YM_18 (CIF_ISP_WDR_BASE + 0x0000005C)
+#define CIF_ISP_WDR_TONECURVE_YM_19 (CIF_ISP_WDR_BASE + 0x00000060)
+#define CIF_ISP_WDR_TONECURVE_YM_20 (CIF_ISP_WDR_BASE + 0x00000064)
+#define CIF_ISP_WDR_TONECURVE_YM_21 (CIF_ISP_WDR_BASE + 0x00000068)
+#define CIF_ISP_WDR_TONECURVE_YM_22 (CIF_ISP_WDR_BASE + 0x0000006C)
+#define CIF_ISP_WDR_TONECURVE_YM_23 (CIF_ISP_WDR_BASE + 0x00000070)
+#define CIF_ISP_WDR_TONECURVE_YM_24 (CIF_ISP_WDR_BASE + 0x00000074)
+#define CIF_ISP_WDR_TONECURVE_YM_25 (CIF_ISP_WDR_BASE + 0x00000078)
+#define CIF_ISP_WDR_TONECURVE_YM_26 (CIF_ISP_WDR_BASE + 0x0000007C)
+#define CIF_ISP_WDR_TONECURVE_YM_27 (CIF_ISP_WDR_BASE + 0x00000080)
+#define CIF_ISP_WDR_TONECURVE_YM_28 (CIF_ISP_WDR_BASE + 0x00000084)
+#define CIF_ISP_WDR_TONECURVE_YM_29 (CIF_ISP_WDR_BASE + 0x00000088)
+#define CIF_ISP_WDR_TONECURVE_YM_30 (CIF_ISP_WDR_BASE + 0x0000008C)
+#define CIF_ISP_WDR_TONECURVE_YM_31 (CIF_ISP_WDR_BASE + 0x00000090)
+#define CIF_ISP_WDR_TONECURVE_YM_32 (CIF_ISP_WDR_BASE + 0x00000094)
+#define CIF_ISP_WDR_OFFSET (CIF_ISP_WDR_BASE + 0x00000098)
+#define CIF_ISP_WDR_DELTAMIN (CIF_ISP_WDR_BASE + 0x0000009C)
+#define CIF_ISP_WDR_TONECURVE_1_SHD (CIF_ISP_WDR_BASE + 0x000000A0)
+#define CIF_ISP_WDR_TONECURVE_2_SHD (CIF_ISP_WDR_BASE + 0x000000A4)
+#define CIF_ISP_WDR_TONECURVE_3_SHD (CIF_ISP_WDR_BASE + 0x000000A8)
+#define CIF_ISP_WDR_TONECURVE_4_SHD (CIF_ISP_WDR_BASE + 0x000000AC)
+#define CIF_ISP_WDR_TONECURVE_YM_0_SHD (CIF_ISP_WDR_BASE + 0x000000B0)
+#define CIF_ISP_WDR_TONECURVE_YM_1_SHD (CIF_ISP_WDR_BASE + 0x000000B4)
+#define CIF_ISP_WDR_TONECURVE_YM_2_SHD (CIF_ISP_WDR_BASE + 0x000000B8)
+#define CIF_ISP_WDR_TONECURVE_YM_3_SHD (CIF_ISP_WDR_BASE + 0x000000BC)
+#define CIF_ISP_WDR_TONECURVE_YM_4_SHD (CIF_ISP_WDR_BASE + 0x000000C0)
+#define CIF_ISP_WDR_TONECURVE_YM_5_SHD (CIF_ISP_WDR_BASE + 0x000000C4)
+#define CIF_ISP_WDR_TONECURVE_YM_6_SHD (CIF_ISP_WDR_BASE + 0x000000C8)
+#define CIF_ISP_WDR_TONECURVE_YM_7_SHD (CIF_ISP_WDR_BASE + 0x000000CC)
+#define CIF_ISP_WDR_TONECURVE_YM_8_SHD (CIF_ISP_WDR_BASE + 0x000000D0)
+#define CIF_ISP_WDR_TONECURVE_YM_9_SHD (CIF_ISP_WDR_BASE + 0x000000D4)
+#define CIF_ISP_WDR_TONECURVE_YM_10_SHD (CIF_ISP_WDR_BASE + 0x000000D8)
+#define CIF_ISP_WDR_TONECURVE_YM_11_SHD (CIF_ISP_WDR_BASE + 0x000000DC)
+#define CIF_ISP_WDR_TONECURVE_YM_12_SHD (CIF_ISP_WDR_BASE + 0x000000E0)
+#define CIF_ISP_WDR_TONECURVE_YM_13_SHD (CIF_ISP_WDR_BASE + 0x000000E4)
+#define CIF_ISP_WDR_TONECURVE_YM_14_SHD (CIF_ISP_WDR_BASE + 0x000000E8)
+#define CIF_ISP_WDR_TONECURVE_YM_15_SHD (CIF_ISP_WDR_BASE + 0x000000EC)
+#define CIF_ISP_WDR_TONECURVE_YM_16_SHD (CIF_ISP_WDR_BASE + 0x000000F0)
+#define CIF_ISP_WDR_TONECURVE_YM_17_SHD (CIF_ISP_WDR_BASE + 0x000000F4)
+#define CIF_ISP_WDR_TONECURVE_YM_18_SHD (CIF_ISP_WDR_BASE + 0x000000F8)
+#define CIF_ISP_WDR_TONECURVE_YM_19_SHD (CIF_ISP_WDR_BASE + 0x000000FC)
+#define CIF_ISP_WDR_TONECURVE_YM_20_SHD (CIF_ISP_WDR_BASE + 0x00000100)
+#define CIF_ISP_WDR_TONECURVE_YM_21_SHD (CIF_ISP_WDR_BASE + 0x00000104)
+#define CIF_ISP_WDR_TONECURVE_YM_22_SHD (CIF_ISP_WDR_BASE + 0x00000108)
+#define CIF_ISP_WDR_TONECURVE_YM_23_SHD (CIF_ISP_WDR_BASE + 0x0000010C)
+#define CIF_ISP_WDR_TONECURVE_YM_24_SHD (CIF_ISP_WDR_BASE + 0x00000110)
+#define CIF_ISP_WDR_TONECURVE_YM_25_SHD (CIF_ISP_WDR_BASE + 0x00000114)
+#define CIF_ISP_WDR_TONECURVE_YM_26_SHD (CIF_ISP_WDR_BASE + 0x00000118)
+#define CIF_ISP_WDR_TONECURVE_YM_27_SHD (CIF_ISP_WDR_BASE + 0x0000011C)
+#define CIF_ISP_WDR_TONECURVE_YM_28_SHD (CIF_ISP_WDR_BASE + 0x00000120)
+#define CIF_ISP_WDR_TONECURVE_YM_29_SHD (CIF_ISP_WDR_BASE + 0x00000124)
+#define CIF_ISP_WDR_TONECURVE_YM_30_SHD (CIF_ISP_WDR_BASE + 0x00000128)
+#define CIF_ISP_WDR_TONECURVE_YM_31_SHD (CIF_ISP_WDR_BASE + 0x0000012C)
+#define CIF_ISP_WDR_TONECURVE_YM_32_SHD (CIF_ISP_WDR_BASE + 0x00000130)
+
+#define CIF_ISP_VSM_BASE (0x00002F00)
+#define CIF_ISP_VSM_MODE (CIF_ISP_VSM_BASE + 0x00000000)
+#define CIF_ISP_VSM_H_OFFS (CIF_ISP_VSM_BASE + 0x00000004)
+#define CIF_ISP_VSM_V_OFFS (CIF_ISP_VSM_BASE + 0x00000008)
+#define CIF_ISP_VSM_H_SIZE (CIF_ISP_VSM_BASE + 0x0000000C)
+#define CIF_ISP_VSM_V_SIZE (CIF_ISP_VSM_BASE + 0x00000010)
+#define CIF_ISP_VSM_H_SEGMENTS (CIF_ISP_VSM_BASE + 0x00000014)
+#define CIF_ISP_VSM_V_SEGMENTS (CIF_ISP_VSM_BASE + 0x00000018)
+#define CIF_ISP_VSM_DELTA_H (CIF_ISP_VSM_BASE + 0x0000001C)
+#define CIF_ISP_VSM_DELTA_V (CIF_ISP_VSM_BASE + 0x00000020)
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+#define ONE_LANE_ENABLE_BIT 0x1
+#define TWO_LANE_ENABLE_BIT 0x2
+#define FOUR_LANE_ENABLE_BIT 0x4
+
+#define MRV_MIPI_BASE 0x1C00
+#define MRV_MIPI_CTRL 0x00
+
+/*
+ * GRF_SOC_CON14
+ * bit 0 dphy_rx0_testclr
+ * bit 1 dphy_rx0_testclk
+ * bit 2 dphy_rx0_testen
+ * bit 3:10 dphy_rx0_testdin
+ */
+#define GRF_SOC_CON14_OFFSET (0x027c)
+#define DPHY_RX0_TESTCLR_MASK (0x1 << 16)
+#define DPHY_RX0_TESTCLK_MASK (0x1 << 17)
+#define DPHY_RX0_TESTEN_MASK (0x1 << 18)
+#define DPHY_RX0_TESTDIN_MASK (0xff << 19)
+
+#define DPHY_RX0_TESTCLR BIT(0)
+#define DPHY_RX0_TESTCLK BIT(1)
+#define DPHY_RX0_TESTEN BIT(2)
+#define DPHY_RX0_TESTDIN_OFFSET (3)
+
+#define DPHY_TX1RX1_ENABLECLK_MASK (0x1 << 28)
+#define DPHY_RX1_SRC_SEL_MASK (0x1 << 29)
+#define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 30)
+#define DPHY_TX1RX1_BASEDIR_OFFSET (0x1 << 31)
+
+#define DPHY_TX1RX1_ENABLECLK (0x1 << 12)
+#define DPHY_TX1RX1_DISABLECLK (0x0 << 12)
+#define DPHY_RX1_SRC_SEL_ISP (0x1 << 13)
+#define DPHY_TX1RX1_SLAVEZ (0x0 << 14)
+#define DPHY_TX1RX1_BASEDIR_REC (0x1 << 15)
+
+/*
+ * GRF_SOC_CON6
+ * bit 0 grf_con_disable_isp
+ * bit 1 grf_con_isp_dphy_sel 1'b0 mipi phy rx0
+ */
+#define GRF_SOC_CON6_OFFSET (0x025c)
+#define MIPI_PHY_DISABLE_ISP_MASK (0x1 << 16)
+#define MIPI_PHY_DISABLE_ISP (0x0 << 0)
+
+#define DSI_CSI_TESTBUS_SEL_MASK (0x1 << 30)
+#define DSI_CSI_TESTBUS_SEL_OFFSET_BIT (14)
+
+#define MIPI_PHY_DPHYSEL_OFFSET_MASK (0x1 << 17)
+#define MIPI_PHY_DPHYSEL_OFFSET_BIT (0x1)
+
+/*
+ * GRF_SOC_CON10
+ * bit12:15 grf_dphy_rx0_enable
+ * bit 0:3 turn disable
+ */
+#define GRF_SOC_CON10_OFFSET (0x026c)
+#define DPHY_RX0_TURN_DISABLE_MASK (0xf << 16)
+#define DPHY_RX0_TURN_DISABLE_OFFSET_BITS (0x0)
+#define DPHY_RX0_ENABLE_MASK (0xf << 28)
+#define DPHY_RX0_ENABLE_OFFSET_BITS (12)
+
+/*
+ * GRF_SOC_CON9
+ * bit12:15 grf_dphy_rx0_enable
+ * bit 0:3 turn disable
+ */
+#define GRF_SOC_CON9_OFFSET (0x0268)
+#define DPHY_TX1RX1_TURN_DISABLE_MASK (0xf << 16)
+#define DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS (0x0)
+#define DPHY_TX1RX1_ENABLE_MASK (0xf << 28)
+#define DPHY_TX1RX1_ENABLE_OFFSET_BITS (12)
+
+/*
+ * GRF_SOC_CON15
+ * bit 0:3 turn request
+ */
+#define GRF_SOC_CON15_OFFSET (0x03a4)
+#define DPHY_RX0_TURN_REQUEST_MASK (0xf << 16)
+#define DPHY_RX0_TURN_REQUEST_OFFSET_BITS (0x0)
+
+#define DPHY_TX1RX1_TURN_REQUEST_MASK (0xf << 20)
+#define DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS (0x0)
+
+/*
+ * GRF_SOC_STATUS21
+ * bit0:7 dphy_rx0_testdout
+ */
+#define GRF_SOC_STATUS21_OFFSET (0x2D4)
+#define DPHY_RX0_TESTDOUT(a) ((a) & 0xff)
+
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_IO_VSEL_OFFSET (0x0380)
+#define DVP_V18SEL ((1 << 1) | (1 << 17))
+#define DVP_V33SEL ((0 << 1) | (1 << 17))
+
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_GPIO2B_E_OFFSET (0x0380)
+#define CIF_CLKOUT_STRENGTH(a) ((((a) & 0x03) << 3) | (0x03 << 19))
+
+/*
+ * CSI HOST
+ */
+
+#define CSIHOST_PHY_TEST_CTRL0 (0x30)
+#define CSIHOST_PHY_TEST_CTRL1 (0x34)
+#define CSIHOST_PHY_SHUTDOWNZ (0x08)
+#define CSIHOST_DPHY_RSTZ (0x0c)
+#define CSIHOST_N_LANES (0x04)
+#define CSIHOST_CSI2_RESETN (0x10)
+#define CSIHOST_PHY_STATE (0x14)
+#define CSIHOST_DATA_IDS1 (0x18)
+#define CSIHOST_DATA_IDS2 (0x1C)
+#define CSIHOST_ERR1 (0x20)
+#define CSIHOST_ERR2 (0x24)
+
+#define write_cifisp_reg(addr, val) \
+ __raw_writel(val, (addr) + rk3288->isp_base)
+#define read_cifisp_reg(addr) \
+ __raw_readl((addr) + rk3288->isp_base)
+
+#define write_grf_reg(addr, val) \
+ regmap_write(rk3288->regmap_grf, addr, val)
+#define read_grf_reg(addr, val) regmap_read(rk3288->regmap_grf, addr, val)
+
+#define write_csihost_reg(addr, val) \
+ __raw_writel(val, (addr) + rk3288->csihost_base)
+#define read_csihost_reg(addr) __raw_readl((addr) + rk3288->csihost_base)
+
+struct cif_isp10_clk_rst_rk3288 {
+ struct clk *aclk_isp;
+ struct clk *hclk_isp;
+ struct clk *sclk_isp;
+ struct clk *sclk_isp_jpe;
+ struct clk *sclk_mipidsi_24m;
+ struct clk *pclk_mipi_csi;
+ struct clk *pclk_isp_in;
+ struct reset_control *isp_rst;
+};
+
+struct cif_isp10_rk3288 {
+ struct regmap *regmap_grf;
+ void __iomem *csihost_base;
+ void __iomem *isp_base;
+ struct cif_isp10_clk_rst_rk3288 clk_rst;
+ struct cif_isp10_device *cif_isp10;
+};
+
+struct mipi_dphy_hsfreqrange {
+ unsigned int range_l;
+ unsigned int range_h;
+ unsigned char cfg_bit;
+};
+
+static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = {
+ {80, 90, 0x00},
+ {90, 100, 0x10},
+ {100, 110, 0x20},
+ {110, 130, 0x01},
+ {130, 140, 0x11},
+ {140, 150, 0x21},
+ {150, 170, 0x02},
+ {170, 180, 0x12},
+ {180, 200, 0x22},
+ {200, 220, 0x03},
+ {220, 240, 0x13},
+ {240, 250, 0x23},
+ {250, 270, 0x4},
+ {270, 300, 0x14},
+ {300, 330, 0x5},
+ {330, 360, 0x15},
+ {360, 400, 0x25},
+ {400, 450, 0x06},
+ {450, 500, 0x16},
+ {500, 550, 0x07},
+ {550, 600, 0x17},
+ {600, 650, 0x08},
+ {650, 700, 0x18},
+ {700, 750, 0x09},
+ {750, 800, 0x19},
+ {800, 850, 0x29},
+ {850, 900, 0x39},
+ {900, 950, 0x0a},
+ {950, 1000, 0x1a}
+};
+
+static struct cif_isp10_rk3288 *rk3288;
+static int mipi_dphy0_wr_reg(unsigned char addr, unsigned char data)
+{
+ /*
+ * TESTCLK=1
+ * TESTEN =1,TESTDIN=addr
+ * TESTCLK=0
+ */
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ ((addr << DPHY_RX0_TESTDIN_OFFSET) | DPHY_RX0_TESTDIN_MASK
+ | DPHY_RX0_TESTEN | DPHY_RX0_TESTEN_MASK));
+ write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLK_MASK);
+
+ /*
+ * write data:
+ * TESTEN =0,TESTDIN=data
+ * TESTCLK=1
+ */
+ if (data != 0xff) {
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ ((data << DPHY_RX0_TESTDIN_OFFSET) |
+ DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+ }
+ return 0;
+}
+
+static int mipi_dphy1_wr_reg(unsigned char addr, unsigned char data)
+{
+ /*
+ * TESTEN =1,TESTDIN=addr
+ * TESTCLK=0
+ * TESTEN =0,TESTDIN=data
+ * TESTCLK=1
+ */
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000000);
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+
+ return 0;
+}
+
+static int mipi_dphy1_rd_reg(unsigned char addr)
+{
+ return (read_csihost_reg(((CSIHOST_PHY_TEST_CTRL1) & 0xff00)) >> 8);
+}
+
+static int mipi_dphy_cfg(struct pltfrm_cam_mipi_config *para)
+{
+ unsigned char hsfreqrange = 0xff, i;
+ struct mipi_dphy_hsfreqrange *hsfreqrange_p;
+ unsigned char datalane_en, input_sel;
+
+ hsfreqrange_p = mipi_dphy_hsfreq_range;
+ for (i = 0;
+ i < (sizeof(mipi_dphy_hsfreq_range) /
+ sizeof(struct mipi_dphy_hsfreqrange));
+ i++) {
+ if ((para->bit_rate > hsfreqrange_p->range_l) &&
+ (para->bit_rate <= hsfreqrange_p->range_h)) {
+ hsfreqrange = hsfreqrange_p->cfg_bit;
+ break;
+ }
+ hsfreqrange_p++;
+ }
+
+ if (hsfreqrange == 0xff)
+ hsfreqrange = 0x00;
+
+ hsfreqrange <<= 1;
+
+ input_sel = para->dphy_index;
+ datalane_en = 0;
+ for (i = 0; i < para->nb_lanes; i++)
+ datalane_en |= (1 << i);
+
+ if (input_sel == 0) {
+ write_grf_reg(GRF_SOC_CON6_OFFSET,
+ MIPI_PHY_DPHYSEL_OFFSET_MASK |
+ (input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
+ /* set lane num */
+ write_grf_reg(GRF_SOC_CON10_OFFSET,
+ DPHY_RX0_ENABLE_MASK |
+ (datalane_en << DPHY_RX0_ENABLE_OFFSET_BITS));
+ /* set lan turndisab as 1 */
+ write_grf_reg(GRF_SOC_CON10_OFFSET,
+ DPHY_RX0_TURN_DISABLE_MASK |
+ (0xf << DPHY_RX0_TURN_DISABLE_OFFSET_BITS));
+ write_grf_reg(GRF_SOC_CON10_OFFSET,
+ (0x0 << 4) | (0xf << 20));
+ /* set lan turnrequest as 0 */
+ write_grf_reg(GRF_SOC_CON15_OFFSET,
+ DPHY_RX0_TURN_REQUEST_MASK |
+ (0x0 << DPHY_RX0_TURN_REQUEST_OFFSET_BITS));
+
+ /* phy start */
+ /*
+ * TESTCLK=1
+ * TESTCLR=1
+ * delay 100us
+ * TESTCLR=0
+ */
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX0_TESTCLR_MASK | DPHY_RX0_TESTCLR);
+ usleep_range(100, 150);
+ write_grf_reg(GRF_SOC_CON14_OFFSET, DPHY_RX0_TESTCLR_MASK);
+ usleep_range(100, 150);
+
+ /* set clock lane */
+ mipi_dphy0_wr_reg(0x34, 0x15);
+ if (datalane_en == ONE_LANE_ENABLE_BIT) {
+ mipi_dphy0_wr_reg(0x44, hsfreqrange);
+ } else if (datalane_en == TWO_LANE_ENABLE_BIT) {
+ mipi_dphy0_wr_reg(0x44, hsfreqrange);
+ mipi_dphy0_wr_reg(0x54, hsfreqrange);
+ } else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
+ mipi_dphy0_wr_reg(0x44, hsfreqrange);
+ mipi_dphy0_wr_reg(0x54, hsfreqrange);
+ mipi_dphy0_wr_reg(0x84, hsfreqrange);
+ mipi_dphy0_wr_reg(0x94, hsfreqrange);
+ }
+
+ /* Normal operation */
+ /*
+ * TESTCLK=1
+ * TESTEN =0
+ */
+ mipi_dphy0_wr_reg(0x0, -1);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | DPHY_RX0_TESTCLK);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ (DPHY_RX0_TESTEN_MASK));
+
+ write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
+ read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL) |
+ (0x0f << 8));
+
+ } else if (input_sel == 1) {
+ write_grf_reg(GRF_SOC_CON6_OFFSET,
+ MIPI_PHY_DPHYSEL_OFFSET_MASK |
+ (input_sel << MIPI_PHY_DPHYSEL_OFFSET_BIT));
+ write_grf_reg(GRF_SOC_CON6_OFFSET,
+ DSI_CSI_TESTBUS_SEL_MASK |
+ (1 << DSI_CSI_TESTBUS_SEL_OFFSET_BIT));
+
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_RX1_SRC_SEL_ISP | DPHY_RX1_SRC_SEL_MASK);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_TX1RX1_SLAVEZ | DPHY_TX1RX1_MASTERSLAVEZ_MASK);
+ write_grf_reg(GRF_SOC_CON14_OFFSET,
+ DPHY_TX1RX1_BASEDIR_REC | DPHY_TX1RX1_BASEDIR_OFFSET);
+
+ /* set lane num */
+ write_grf_reg(GRF_SOC_CON9_OFFSET,
+ DPHY_TX1RX1_ENABLE_MASK |
+ (datalane_en << DPHY_TX1RX1_ENABLE_OFFSET_BITS));
+ /* set lan turndisab as 1 */
+ write_grf_reg(GRF_SOC_CON9_OFFSET,
+ DPHY_TX1RX1_TURN_DISABLE_MASK |
+ (0xf << DPHY_TX1RX1_TURN_DISABLE_OFFSET_BITS));
+ /* set lan turnrequest as 0 */
+ write_grf_reg(GRF_SOC_CON15_OFFSET,
+ DPHY_TX1RX1_TURN_REQUEST_MASK |
+ (0x0 << DPHY_TX1RX1_TURN_REQUEST_OFFSET_BITS));
+
+ /* phy1 start */
+ /*
+ * SHUTDOWNZ=0
+ * RSTZ=0
+ * TESTCLK=1
+ * TESTCLR=1 TESTCLK=1
+ * TESTCLR=0 TESTCLK=1
+ */
+ write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000000);
+ write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000000);
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000003);
+ usleep_range(100, 150);
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ usleep_range(100, 150);
+
+ /* set clock lane */
+ mipi_dphy1_wr_reg(0x34, 0x15);
+
+ if (datalane_en == ONE_LANE_ENABLE_BIT) {
+ mipi_dphy1_wr_reg(0x44, hsfreqrange);
+ } else if (datalane_en == TWO_LANE_ENABLE_BIT) {
+ mipi_dphy1_wr_reg(0x44, hsfreqrange);
+ mipi_dphy1_wr_reg(0x54, hsfreqrange);
+ } else if (datalane_en == FOUR_LANE_ENABLE_BIT) {
+ mipi_dphy1_wr_reg(0x44, hsfreqrange);
+ mipi_dphy1_wr_reg(0x54, hsfreqrange);
+ mipi_dphy1_wr_reg(0x84, hsfreqrange);
+ mipi_dphy1_wr_reg(0x94, hsfreqrange);
+ }
+
+ mipi_dphy1_rd_reg(0x0);
+ /*
+ * TESTCLK=1
+ * TESTEN =0
+ * SHUTDOWNZ=1
+ * RSTZ=1
+ */
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ write_csihost_reg(CSIHOST_PHY_TEST_CTRL1, 0x00000000);
+ write_csihost_reg(CSIHOST_PHY_SHUTDOWNZ, 0x00000001);
+ write_csihost_reg(CSIHOST_DPHY_RSTZ, 0x00000001);
+ } else {
+ goto fail;
+ }
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int soc_clk_enable(void)
+{
+ struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
+
+ clk_prepare_enable(clk_rst->hclk_isp);
+ clk_prepare_enable(clk_rst->aclk_isp);
+ clk_prepare_enable(clk_rst->sclk_isp);
+ clk_prepare_enable(clk_rst->sclk_isp_jpe);
+ clk_prepare_enable(clk_rst->sclk_mipidsi_24m);
+ clk_prepare_enable(clk_rst->pclk_isp_in);
+ clk_prepare_enable(clk_rst->pclk_mipi_csi);
+ return 0;
+}
+
+static int soc_clk_disable(void)
+{
+ struct cif_isp10_clk_rst_rk3288 *clk_rst = &rk3288->clk_rst;
+
+ clk_disable_unprepare(clk_rst->hclk_isp);
+ clk_disable_unprepare(clk_rst->aclk_isp);
+ clk_disable_unprepare(clk_rst->sclk_isp);
+ clk_disable_unprepare(clk_rst->sclk_isp_jpe);
+ clk_disable_unprepare(clk_rst->sclk_mipidsi_24m);
+ clk_disable_unprepare(clk_rst->pclk_isp_in);
+ clk_disable_unprepare(clk_rst->pclk_mipi_csi);
+ return 0;
+}
+
+static int soc_init(struct pltfrm_soc_init_para *init)
+{
+ struct cif_isp10_clk_rst_rk3288 *clk_rst;
+ struct platform_device *pdev = init->pdev;
+ struct device_node *np = pdev->dev.of_node, *node;
+ struct resource *res;
+ int err;
+
+ rk3288 = (struct cif_isp10_rk3288 *)devm_kzalloc(
+ &pdev->dev,
+ sizeof(struct cif_isp10_rk3288),
+ GFP_KERNEL);
+ if (!rk3288) {
+ dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
+ err = -ENOMEM;
+ goto alloc_failed;
+ }
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ rk3288->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(rk3288->regmap_grf)) {
+ dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3288\n");
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+ }
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "csihost-register");
+ if (!res) {
+ dev_err(&pdev->dev,
+ "platform_get_resource_byname csihost-register failed\n");
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+ rk3288->csihost_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR_OR_NULL(rk3288->csihost_base)) {
+ dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+ if (IS_ERR(rk3288->csihost_base))
+ err = PTR_ERR(rk3288->csihost_base);
+ else
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+
+ clk_rst = &rk3288->clk_rst;
+ clk_rst->aclk_isp = devm_clk_get(&pdev->dev, "aclk_isp");
+ clk_rst->hclk_isp = devm_clk_get(&pdev->dev, "hclk_isp");
+ clk_rst->sclk_isp = devm_clk_get(&pdev->dev, "sclk_isp");
+ clk_rst->sclk_isp_jpe = devm_clk_get(&pdev->dev, "sclk_isp_jpe");
+ clk_rst->sclk_mipidsi_24m =
+ devm_clk_get(&pdev->dev, "sclk_mipidsi_24m");
+ clk_rst->pclk_mipi_csi = devm_clk_get(&pdev->dev, "pclk_mipi_csi");
+ clk_rst->isp_rst = devm_reset_control_get(&pdev->dev, "rst_isp");
+ clk_rst->pclk_isp_in = devm_clk_get(&pdev->dev, "pclk_isp_in");
+
+ if (IS_ERR_OR_NULL(clk_rst->aclk_isp) ||
+ IS_ERR_OR_NULL(clk_rst->hclk_isp) ||
+ IS_ERR_OR_NULL(clk_rst->sclk_isp) ||
+ IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe) ||
+ IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi) ||
+ IS_ERR_OR_NULL(clk_rst->isp_rst) ||
+ IS_ERR_OR_NULL(clk_rst->pclk_isp_in) ||
+ IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m)) {
+ dev_err(&pdev->dev, "Get rk3288 cif isp10 clock resouce failed !\n");
+ err = -EINVAL;
+ goto clk_failed;
+ }
+
+ clk_set_rate(clk_rst->sclk_isp, 400000000);
+ clk_set_rate(clk_rst->sclk_isp_jpe, 400000000);
+ reset_control_deassert(clk_rst->isp_rst);
+
+ rk3288->isp_base = init->isp_base;
+ return 0;
+
+clk_failed:
+ if (!IS_ERR_OR_NULL(clk_rst->aclk_isp))
+ devm_clk_put(&pdev->dev, clk_rst->aclk_isp);
+ if (!IS_ERR_OR_NULL(clk_rst->hclk_isp))
+ devm_clk_put(&pdev->dev, clk_rst->hclk_isp);
+ if (!IS_ERR_OR_NULL(clk_rst->sclk_isp))
+ devm_clk_put(&pdev->dev, clk_rst->sclk_isp);
+ if (!IS_ERR_OR_NULL(clk_rst->sclk_isp_jpe))
+ devm_clk_put(&pdev->dev, clk_rst->sclk_isp_jpe);
+ if (!IS_ERR_OR_NULL(clk_rst->pclk_mipi_csi))
+ devm_clk_put(&pdev->dev, clk_rst->pclk_mipi_csi);
+ if (!IS_ERR_OR_NULL(clk_rst->pclk_isp_in))
+ devm_clk_put(&pdev->dev, clk_rst->pclk_isp_in);
+ if (!IS_ERR_OR_NULL(clk_rst->sclk_mipidsi_24m))
+ devm_clk_put(&pdev->dev, clk_rst->sclk_mipidsi_24m);
+
+ if (!IS_ERR_OR_NULL(clk_rst->isp_rst))
+ reset_control_put(clk_rst->isp_rst);
+
+regmap_failed:
+
+alloc_failed:
+
+ return err;
+}
+
+int pltfrm_rk3288_cfg(
+ struct pltfrm_soc_cfg_para *cfg)
+{
+ switch (cfg->cmd) {
+ case PLTFRM_MCLK_CFG: {
+ struct pltfrm_soc_mclk_para *mclk_para;
+
+ mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para;
+ if (mclk_para->io_voltage == PLTFRM_IO_1V8)
+ write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL);
+ else
+ write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL);
+
+ write_grf_reg(GRF_GPIO2B_E_OFFSET,
+ CIF_CLKOUT_STRENGTH(mclk_para->drv_strength));
+ break;
+ }
+ case PLTFRM_MIPI_DPHY_CFG:
+ mipi_dphy_cfg((struct pltfrm_cam_mipi_config *)cfg->cfg_para);
+ break;
+
+ case PLTFRM_CLKEN:
+ soc_clk_enable();
+ break;
+
+ case PLTFRM_CLKDIS:
+ soc_clk_disable();
+ break;
+
+ case PLTFRM_CLKRST:
+ reset_control_assert(rk3288->clk_rst.isp_rst);
+ usleep_range(10, 15);
+ reset_control_deassert(rk3288->clk_rst.isp_rst);
+ break;
+
+ case PLTFRM_SOC_INIT:
+ soc_init((struct pltfrm_soc_init_para *)cfg->cfg_para);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
+
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/regmap.h>
+#include <linux/mfd/syscon.h>
+#include <linux/clk.h>
+#include <linux/reset.h>
+#include <linux/io.h>
+#include <linux/of.h>
+#include <linux/kernel.h>
+#include <linux/platform_device.h>
+#include <linux/platform_data/rk_isp10_platform.h>
+
+#define VI_IRCL 0x0014
+#define MRV_MIPI_BASE 0x1C00
+#define MRV_MIPI_CTRL 0x00
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_IO_VSEL_OFFSET (0x0900)
+#define DVP_V18SEL ((1 << 1) | (1 << 17))
+#define DVP_V33SEL ((0 << 1) | (1 << 17))
+/*
+ * GRF_IO_VSEL
+ */
+#define GRF_GPIO2B_E_OFFSET (0x0204)
+#define CIF_CLKOUT_STRENGTH(a) \
+ ((((a) & 0x03) << 3) | (0x03 << 19))
+#define GRF_SOC_STATUS1 (0x0e2a4)
+
+#define GRF_SOC_CON9_OFFSET (0x6224)
+#define DPHY_RX0_TURNREQUEST_MASK (0xF << 16)
+#define DPHY_RX0_TURNREQUEST_BIT (0)
+
+#define GRF_SOC_CON21_OFFSET (0x6254)
+#define DPHY_RX0_FORCERXMODE_MASK (0xF << 20)
+#define DPHY_RX0_FORCERXMODE_BIT (4)
+#define DPHY_RX0_FORCETXSTOPMODE_MASK (0xF << 24)
+#define DPHY_RX0_FORCETXSTOPMODE_BIT (8)
+#define DPHY_RX0_TURNDISABLE_MASK (0xF << 28)
+#define DPHY_RX0_TURNDISABLE_BIT (12)
+#define DPHY_RX0_ENABLE_MASK (0xF << 16)
+#define DPHY_RX0_ENABLE_BIT (0)
+
+#define GRF_SOC_CON23_OFFSET (0x625c)
+#define DPHY_TX1RX1_TURNDISABLE_MASK (0xF << 28)
+#define DPHY_TX1RX1_TURNDISABLE_BIT (12)
+#define DPHY_TX1RX1_FORCERXMODE_MASK (0xF << 20)
+#define DPHY_TX1RX1_FORCERXMODE_BIT (4)
+#define DPHY_TX1RX1_FORCETXSTOPMODE_MASK (0xF << 24)
+#define DPHY_TX1RX1_FORCETXSTOPMODE_BIT (8)
+#define DPHY_TX1RX1_ENABLE_MASK (0xF << 16)
+#define DPHY_TX1RX1_ENABLE_BIT (0)
+
+#define GRF_SOC_CON24_OFFSET (0x6260)
+#define DPHY_TX1RX1_MASTERSLAVEZ_MASK (0x1 << 23)
+#define DPHY_TX1RX1_MASTERSLAVEZ_BIT (7)
+#define DPHY_TX1RX1_BASEDIR_MASK (0x1 << 21)
+#define DPHY_TX1RX1_BASEDIR_BIT (5)
+#define DPHY_RX1_MASK (0x1 << 20)
+#define DPHY_RX1_SEL_BIT (4)
+
+#define GRF_SOC_CON25_OFFSET (0x6264)
+#define DPHY_RX0_TESTCLK_MASK (0x1 << 25)
+#define DPHY_RX0_TESTCLK_BIT (9)
+#define DPHY_RX0_TESTCLR_MASK (0x1 << 26)
+#define DPHY_RX0_TESTCLR_BIT (10)
+#define DPHY_RX0_TESTDIN_MASK (0xFF << 16)
+#define DPHY_RX0_TESTDIN_BIT (0)
+#define DPHY_RX0_TESTEN_MASK (0x1 << 24)
+#define DPHY_RX0_TESTEN_BIT (8)
+
+#define DPHY_TX1RX1_TURNREQUEST_MASK (0xF << 16)
+#define DPHY_TX1RX1_TURNREQUEST_BIT (0)
+
+#define DSIHOST_PHY_SHUTDOWNZ (0x00a0)
+#define DSIHOST_DPHY_RSTZ (0x00a0)
+#define DSIHOST_PHY_TEST_CTRL0 (0x00b4)
+#define DSIHOST_PHY_TEST_CTRL1 (0x00b8)
+
+#define write_cifisp_reg(addr, val) \
+ __raw_writel(val, (addr) + rk3399->isp_base)
+#define read_cifisp_reg(addr) \
+ __raw_readl((addr) + rk3399->isp_base)
+
+#define write_grf_reg(addr, val) \
+ regmap_write(rk3399->regmap_grf, addr, val)
+#define read_grf_reg(addr, val) \
+ regmap_read(rk3399->regmap_grf, addr, val)
+
+#define write_dsihost_reg(addr, val) \
+ __raw_writel(val, (addr) + rk3399->dsihost_base)
+#define read_dsihost_reg(addr) \
+ __raw_readl((addr) + rk3399->dsihost_base)
+
+struct cif_isp10_clk_rst_rk3399 {
+ struct clk *hclk_isp0_noc;
+ struct clk *hclk_isp0_wrapper;
+ struct clk *hclk_isp1_noc;
+ struct clk *hclk_isp1_wrapper;
+ struct clk *aclk_isp0_noc;
+ struct clk *aclk_isp0_wrapper;
+ struct clk *aclk_isp1_noc;
+ struct clk *aclk_isp1_wrapper;
+ struct clk *clk_isp0;
+ struct clk *clk_isp1;
+ struct clk *pclkin_isp1;
+ struct clk *pclk_dphy_ref;
+ struct clk *pclk_dphytxrx;
+ struct clk *pclk_dphyrx;
+ struct clk *cif_clk_out;
+ struct clk *cif_clk_pll;
+ struct clk *cif_clk_mipi_dsi;
+ struct clk *cif_clk_mipi_dphy_cfg;
+};
+
+struct cif_isp10_rk3399 {
+ struct regmap *regmap_grf;
+ void __iomem *dsihost_base;
+ void __iomem *isp_base;
+ struct cif_isp10_clk_rst_rk3399 clk_rst;
+ struct cif_isp10_device *cif_isp10;
+};
+
+struct mipi_dphy_hsfreqrange {
+ unsigned int range_l;
+ unsigned int range_h;
+ unsigned char cfg_bit;
+};
+
+static struct mipi_dphy_hsfreqrange mipi_dphy_hsfreq_range[] = {
+ {80, 90, 0x00},
+ {90, 100, 0x10},
+ {100, 110, 0x20},
+ {110, 130, 0x01},
+ {130, 140, 0x11},
+ {140, 150, 0x21},
+ {150, 170, 0x02},
+ {170, 180, 0x12},
+ {180, 200, 0x22},
+ {200, 220, 0x03},
+ {220, 240, 0x13},
+ {240, 250, 0x23},
+ {250, 270, 0x4},
+ {270, 300, 0x14},
+ {300, 330, 0x5},
+ {330, 360, 0x15},
+ {360, 400, 0x25},
+ {400, 450, 0x06},
+ {450, 500, 0x16},
+ {500, 550, 0x07},
+ {550, 600, 0x17},
+ {600, 650, 0x08},
+ {650, 700, 0x18},
+ {700, 750, 0x09},
+ {750, 800, 0x19},
+ {800, 850, 0x29},
+ {850, 900, 0x39},
+ {900, 950, 0x0a},
+ {950, 1000, 0x1a},
+ {1000, 1050, 0x2a},
+ {1100, 1150, 0x3a},
+ {1150, 1200, 0x0b},
+ {1200, 1250, 0x1b},
+ {1250, 1300, 0x2b},
+ {1300, 1350, 0x0c},
+ {1350, 1400, 0x1c},
+ {1400, 1450, 0x2c},
+ {1450, 1500, 0x3c}
+};
+
+static struct cif_isp10_rk3399 *rk3399;
+static int mipi_dphy0_wr_reg(unsigned char addr, unsigned char data)
+{
+ /*
+ * TESTCLK=1
+ * TESTEN =1,TESTDIN=addr
+ * TESTCLK=0
+ */
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ ((addr << DPHY_RX0_TESTDIN_BIT) | DPHY_RX0_TESTDIN_MASK
+ | (1 << DPHY_RX0_TESTEN_BIT) | DPHY_RX0_TESTEN_MASK));
+ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
+
+ /*
+ * write data:
+ * TESTEN =0,TESTDIN=data
+ * TESTCLK=1
+ */
+ if (data != 0xff) {
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ ((data << DPHY_RX0_TESTDIN_BIT) |
+ DPHY_RX0_TESTDIN_MASK | DPHY_RX0_TESTEN_MASK));
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+ }
+ return 0;
+}
+
+static int mipi_dphy0_rd_reg(unsigned char addr)
+{
+ int val = 0;
+ /*TESTCLK=1*/
+ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK |
+ (1 << DPHY_RX0_TESTCLK_BIT));
+ /*TESTEN =1,TESTDIN=addr*/
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ ((addr << DPHY_RX0_TESTDIN_BIT) |
+ DPHY_RX0_TESTDIN_MASK |
+ (1 << DPHY_RX0_TESTEN_BIT) |
+ DPHY_RX0_TESTEN_MASK));
+ /*TESTCLK=0*/
+ write_grf_reg(GRF_SOC_CON25_OFFSET, DPHY_RX0_TESTCLK_MASK);
+ read_grf_reg(GRF_SOC_STATUS1, &val);
+ return val & 0xff;
+}
+
+static int mipi_dphy1_wr_reg(unsigned char addr, unsigned char data)
+{
+ /*
+ * TESTEN =1,TESTDIN=addr
+ * TESTCLK=0
+ * TESTEN =0,TESTDIN=data
+ * TESTCLK=1
+ */
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00000000 | data));
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+
+ return 0;
+}
+
+static int mipi_dphy1_rd_reg(unsigned char addr)
+{
+ /* TESTEN =1,TESTDIN=addr */
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, (0x00010000 | addr));
+ /* TESTCLK=0 */
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000000);
+ return (read_dsihost_reg(DSIHOST_PHY_TEST_CTRL1) >> 8);
+}
+
+static int mipi_dphy_cfg(struct pltfrm_cam_mipi_config *para)
+{
+ unsigned char hsfreqrange = 0xff, i;
+ struct mipi_dphy_hsfreqrange *hsfreqrange_p;
+ unsigned char datalane_en, input_sel;
+
+ hsfreqrange_p = mipi_dphy_hsfreq_range;
+ for (i = 0;
+ i < (sizeof(mipi_dphy_hsfreq_range) /
+ sizeof(struct mipi_dphy_hsfreqrange));
+ i++) {
+ if ((para->bit_rate > hsfreqrange_p->range_l) &&
+ (para->bit_rate <= hsfreqrange_p->range_h)) {
+ hsfreqrange = hsfreqrange_p->cfg_bit;
+ break;
+ }
+ hsfreqrange_p++;
+ }
+
+ if (hsfreqrange == 0xff)
+ hsfreqrange = 0x00;
+
+ hsfreqrange <<= 1;
+
+ input_sel = para->dphy_index;
+ datalane_en = 0;
+ for (i = 0; i < para->nb_lanes; i++)
+ datalane_en |= (1 << i);
+
+ if (input_sel == 0) {
+ write_grf_reg(GRF_SOC_CON21_OFFSET,
+ DPHY_RX0_FORCERXMODE_MASK |
+ (0x0 << DPHY_RX0_FORCERXMODE_BIT) |
+ DPHY_RX0_FORCETXSTOPMODE_MASK |
+ (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
+
+ /* set lane num */
+ write_grf_reg(GRF_SOC_CON21_OFFSET,
+ DPHY_RX0_ENABLE_MASK |
+ (datalane_en << DPHY_RX0_ENABLE_BIT));
+
+ /* set lan turndisab as 1 */
+ write_grf_reg(GRF_SOC_CON21_OFFSET,
+ DPHY_RX0_TURNDISABLE_MASK |
+ (0xf << DPHY_RX0_TURNDISABLE_BIT));
+ write_grf_reg(GRF_SOC_CON21_OFFSET, (0x0 << 4) | (0xf << 20));
+
+ /* set lan turnrequest as 0 */
+ write_grf_reg(GRF_SOC_CON9_OFFSET,
+ DPHY_RX0_TURNREQUEST_MASK |
+ (0x0 << DPHY_RX0_TURNREQUEST_BIT));
+
+ /* phy start */
+ /*
+ * TESTCLK=1
+ * TESTCLR=1
+ * delay 100us
+ * TESTCLR=0
+ */
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLK_MASK |
+ (0x1 << DPHY_RX0_TESTCLK_BIT)); /* TESTCLK=1 */
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLR_MASK |
+ (0x1 << DPHY_RX0_TESTCLR_BIT)); /* TESTCLR=1 */
+ usleep_range(100, 150);
+ /* TESTCLR=0 zyc */
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLR_MASK);
+ usleep_range(100, 150);
+
+ /* set clock lane */
+ mipi_dphy0_wr_reg
+ (0x34, 0);
+ /* HS hsfreqrange & lane 0 settle bypass */
+ mipi_dphy0_wr_reg(0x44, hsfreqrange);
+ mipi_dphy0_wr_reg(0x54, 0);
+ mipi_dphy0_wr_reg(0x84, 0);
+ mipi_dphy0_wr_reg(0x94, 0);
+ mipi_dphy0_wr_reg(0x75, 0x04);
+ mipi_dphy0_rd_reg(0x75);
+
+ /* Normal operation */
+ /*
+ * TESTCLK=1
+ * TESTEN =0
+ */
+ mipi_dphy0_wr_reg(0x0, -1);
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ DPHY_RX0_TESTCLK_MASK | (1 << DPHY_RX0_TESTCLK_BIT));
+ write_grf_reg(GRF_SOC_CON25_OFFSET,
+ (DPHY_RX0_TESTEN_MASK));
+
+ write_cifisp_reg((MRV_MIPI_BASE + MRV_MIPI_CTRL),
+ read_cifisp_reg(MRV_MIPI_BASE + MRV_MIPI_CTRL)
+ | (0x0f << 8));
+
+ } else if (input_sel == 1) {
+ write_grf_reg(GRF_SOC_CON23_OFFSET,
+ DPHY_RX0_FORCERXMODE_MASK |
+ (0x0 << DPHY_RX0_FORCERXMODE_BIT) |
+ DPHY_RX0_FORCETXSTOPMODE_MASK |
+ (0x0 << DPHY_RX0_FORCETXSTOPMODE_BIT));
+ write_grf_reg(GRF_SOC_CON24_OFFSET,
+ DPHY_TX1RX1_MASTERSLAVEZ_MASK |
+ (0x0 << DPHY_TX1RX1_MASTERSLAVEZ_BIT) |
+ DPHY_TX1RX1_BASEDIR_MASK |
+ (0x1 << DPHY_TX1RX1_BASEDIR_BIT) |
+ DPHY_RX1_MASK | 0x0 << DPHY_RX1_SEL_BIT);
+
+ /* set lane num */
+ write_grf_reg(GRF_SOC_CON23_OFFSET,
+ DPHY_TX1RX1_ENABLE_MASK |
+ (datalane_en << DPHY_TX1RX1_ENABLE_BIT));
+
+ /* set lan turndisab as 1 */
+ write_grf_reg(GRF_SOC_CON23_OFFSET,
+ DPHY_TX1RX1_TURNDISABLE_MASK |
+ (0xf << DPHY_TX1RX1_TURNDISABLE_BIT));
+ write_grf_reg(GRF_SOC_CON23_OFFSET, (0x0 << 4) | (0xf << 20));
+
+ /* set lan turnrequest as 0 */
+ write_grf_reg(GRF_SOC_CON24_OFFSET,
+ DPHY_TX1RX1_TURNREQUEST_MASK |
+ (0x0 << DPHY_TX1RX1_TURNREQUEST_BIT));
+
+ /* phy1 start */
+ /*
+ * SHUTDOWNZ=0
+ * RSTZ=0
+ * TESTCLK=1
+ * TESTCLR=1 TESTCLK=1
+ * TESTCLR=0 TESTCLK=1
+ */
+ write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000000);
+ write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000000);
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000003);
+ usleep_range(100, 150);
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ usleep_range(100, 150);
+
+ /* set clock lane */
+ mipi_dphy1_wr_reg(0x34, 0x00);
+ mipi_dphy1_wr_reg(0x44, hsfreqrange);
+ mipi_dphy1_wr_reg(0x54, 0);
+ mipi_dphy1_wr_reg(0x84, 0);
+ mipi_dphy1_wr_reg(0x94, 0);
+ mipi_dphy1_wr_reg(0x75, 0x04);
+
+ mipi_dphy1_rd_reg(0x0);
+ /*
+ * TESTCLK=1
+ * TESTEN =0
+ * SHUTDOWNZ=1
+ * RSTZ=1
+ */
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL0, 0x00000002);
+ write_dsihost_reg(DSIHOST_PHY_TEST_CTRL1, 0x00000000);
+ write_dsihost_reg(DSIHOST_PHY_SHUTDOWNZ, 0x00000001);
+ write_dsihost_reg(DSIHOST_DPHY_RSTZ, 0x00000001);
+ } else {
+ goto fail;
+ }
+
+ return 0;
+fail:
+ return -1;
+}
+
+static int soc_clk_enable(void)
+{
+ struct cif_isp10_clk_rst_rk3399 *clk_rst = &rk3399->clk_rst;
+
+ clk_prepare_enable(clk_rst->hclk_isp0_noc);
+ clk_prepare_enable(clk_rst->hclk_isp0_wrapper);
+ clk_prepare_enable(clk_rst->aclk_isp0_noc);
+ clk_prepare_enable(clk_rst->aclk_isp0_wrapper);
+ clk_prepare_enable(clk_rst->clk_isp0);
+ clk_prepare_enable(clk_rst->cif_clk_out);
+ clk_prepare_enable(clk_rst->pclk_dphyrx);
+ clk_prepare_enable(clk_rst->pclk_dphy_ref);
+
+ return 0;
+}
+
+static int soc_clk_disable(void)
+{
+ struct cif_isp10_clk_rst_rk3399 *clk_rst = &rk3399->clk_rst;
+
+ clk_disable_unprepare(clk_rst->hclk_isp0_noc);
+ clk_disable_unprepare(clk_rst->hclk_isp0_wrapper);
+ clk_disable_unprepare(clk_rst->aclk_isp0_noc);
+ clk_disable_unprepare(clk_rst->aclk_isp0_wrapper);
+ clk_disable_unprepare(clk_rst->clk_isp0);
+ clk_disable_unprepare(clk_rst->pclk_dphyrx);
+ clk_disable_unprepare(clk_rst->pclk_dphy_ref);
+ if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll)) {
+ clk_set_parent(clk_rst->cif_clk_out,
+ clk_rst->cif_clk_pll);
+ }
+ clk_disable_unprepare(clk_rst->cif_clk_out);
+
+ return 0;
+}
+
+static int soc_init(struct pltfrm_soc_init_para *init)
+{
+ struct cif_isp10_clk_rst_rk3399 *clk_rst;
+ struct platform_device *pdev = init->pdev;
+ struct device_node *np = pdev->dev.of_node, *node;
+ struct resource *res;
+ int err;
+
+ rk3399 = (struct cif_isp10_rk3399 *)devm_kzalloc(
+ &pdev->dev,
+ sizeof(struct cif_isp10_rk3399),
+ GFP_KERNEL);
+ if (!rk3399) {
+ dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
+ err = -ENOMEM;
+ goto alloc_failed;
+ }
+
+ node = of_parse_phandle(np, "rockchip,grf", 0);
+ if (node) {
+ rk3399->regmap_grf = syscon_node_to_regmap(node);
+ if (IS_ERR(rk3399->regmap_grf)) {
+ dev_err(&pdev->dev, "Can't allocate cif_isp10_rk3399\n");
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+ }
+
+ res = platform_get_resource_byname(pdev,
+ IORESOURCE_MEM, "dsihost-register");
+ if (!res) {
+ dev_err(&pdev->dev,
+ "platform_get_resource_byname dsihost-register failed\n");
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+ rk3399->dsihost_base = devm_ioremap_resource(&pdev->dev, res);
+ if (IS_ERR_OR_NULL(rk3399->dsihost_base)) {
+ dev_err(&pdev->dev, "devm_ioremap_resource failed\n");
+ if (IS_ERR(rk3399->dsihost_base))
+ err = PTR_ERR(rk3399->dsihost_base);
+ else
+ err = -ENODEV;
+ goto regmap_failed;
+ }
+
+ clk_rst = &rk3399->clk_rst;
+
+ clk_rst->hclk_isp0_noc =
+ devm_clk_get(&pdev->dev, "hclk_isp0_noc");
+ clk_rst->hclk_isp0_wrapper =
+ devm_clk_get(&pdev->dev, "hclk_isp0_wrapper");
+ clk_rst->aclk_isp0_noc =
+ devm_clk_get(&pdev->dev, "aclk_isp0_noc");
+ clk_rst->aclk_isp0_wrapper =
+ devm_clk_get(&pdev->dev, "aclk_isp0_wrapper");
+ clk_rst->clk_isp0 =
+ devm_clk_get(&pdev->dev, "clk_isp0");
+ clk_rst->cif_clk_out =
+ devm_clk_get(&pdev->dev, "clk_cif_out");
+ clk_rst->cif_clk_pll =
+ devm_clk_get(&pdev->dev, "cif_clk_pll");
+ clk_rst->pclk_dphyrx =
+ devm_clk_get(&pdev->dev, "pclk_dphyrx");
+ clk_rst->pclk_dphy_ref =
+ devm_clk_get(&pdev->dev, "pclk_dphy_ref");
+
+ if (IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc) ||
+ IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper) ||
+ IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc) ||
+ IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper) ||
+ IS_ERR_OR_NULL(clk_rst->clk_isp0) ||
+ IS_ERR_OR_NULL(clk_rst->cif_clk_out) ||
+ IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref) ||
+ IS_ERR_OR_NULL(clk_rst->pclk_dphyrx)) {
+ dev_err(&pdev->dev, "Get rk3399 cif isp10 clock resouce failed !\n");
+ err = -EINVAL;
+ goto clk_failed;
+ }
+
+ clk_set_rate(clk_rst->clk_isp0, 420000000);
+
+ rk3399->isp_base = init->isp_base;
+ return 0;
+
+clk_failed:
+ if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_noc))
+ devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_noc);
+
+ if (!IS_ERR_OR_NULL(clk_rst->hclk_isp0_wrapper))
+ devm_clk_put(&pdev->dev, clk_rst->hclk_isp0_wrapper);
+
+ if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_noc))
+ devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_noc);
+
+ if (!IS_ERR_OR_NULL(clk_rst->aclk_isp0_wrapper))
+ devm_clk_put(&pdev->dev, clk_rst->aclk_isp0_wrapper);
+
+ if (!IS_ERR_OR_NULL(clk_rst->clk_isp0))
+ devm_clk_put(&pdev->dev, clk_rst->clk_isp0);
+
+ if (!IS_ERR_OR_NULL(clk_rst->cif_clk_out))
+ devm_clk_put(&pdev->dev, clk_rst->cif_clk_out);
+
+ if (!IS_ERR_OR_NULL(clk_rst->cif_clk_pll))
+ devm_clk_put(&pdev->dev, clk_rst->cif_clk_pll);
+
+ if (!IS_ERR_OR_NULL(clk_rst->pclk_dphyrx))
+ devm_clk_put(&pdev->dev, clk_rst->pclk_dphyrx);
+
+ if (!IS_ERR_OR_NULL(clk_rst->pclk_dphy_ref))
+ devm_clk_put(&pdev->dev, clk_rst->pclk_dphy_ref);
+
+regmap_failed:
+
+alloc_failed:
+
+ return err;
+}
+
+int pltfrm_rk3399_cfg(
+ struct pltfrm_soc_cfg_para *cfg)
+{
+ switch (cfg->cmd) {
+ case PLTFRM_MCLK_CFG: {
+ struct pltfrm_soc_mclk_para *mclk_para;
+
+ mclk_para = (struct pltfrm_soc_mclk_para *)cfg->cfg_para;
+ if (mclk_para->io_voltage == PLTFRM_IO_1V8)
+ write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V18SEL);
+ else
+ write_grf_reg(GRF_IO_VSEL_OFFSET, DVP_V33SEL);
+
+ write_grf_reg(GRF_GPIO2B_E_OFFSET,
+ CIF_CLKOUT_STRENGTH(mclk_para->drv_strength));
+ break;
+ }
+ case PLTFRM_MIPI_DPHY_CFG:
+ mipi_dphy_cfg((struct pltfrm_cam_mipi_config *)cfg->cfg_para);
+ break;
+
+ case PLTFRM_CLKEN:
+ soc_clk_enable();
+ break;
+
+ case PLTFRM_CLKDIS:
+ soc_clk_disable();
+ break;
+
+ case PLTFRM_CLKRST:
+ write_cifisp_reg(VI_IRCL, 0x80);
+ usleep_range(10, 15);
+ write_cifisp_reg(VI_IRCL, 0x00);
+ break;
+
+ case PLTFRM_SOC_INIT:
+ soc_init((struct pltfrm_soc_init_para *)cfg->cfg_para);
+ break;
+
+ default:
+ break;
+ }
+
+ return 0;
+}
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf-dma-contig.h>
+#include "cif_isp10.h"
+#include "cif_isp10_regs.h"
+#include "cif_isp10_version.h"
+#include <linux/module.h>
+#include <linux/of.h>
+#include <media/v4l2-controls_rockchip.h>
+#include <linux/pm_runtime.h>
+#include <linux/pagemap.h>
+#include <linux/slab.h>
+
+#define CIF_ISP10_V4L2_SP_DEV_MAJOR 0
+#define CIF_ISP10_V4L2_ISP_DEV_MAJOR 1
+#define CIF_ISP10_V4L2_MP_DEV_MAJOR 2
+#define CIF_ISP10_V4L2_DMA_DEV_MAJOR 3
+
+#define SP_DEV 0
+#define MP_DEV 1
+#define DMA_DEV 2
+#define ISP_DEV 3
+
+/* One structure per open file handle */
+struct cif_isp10_v4l2_fh {
+ enum cif_isp10_stream_id stream_id;
+ struct v4l2_fh fh;
+};
+
+/* One structure per video node */
+struct cif_isp10_v4l2_node {
+ struct videobuf_queue buf_queue;
+ struct video_device vdev;
+ int users;
+ struct cif_isp10_v4l2_fh *owner;
+};
+
+/* One structure per device */
+struct cif_isp10_v4l2_device {
+ struct cif_isp10_v4l2_node node[4];
+};
+
+/* spinlock define */
+spinlock_t iowrite32_verify_lock;
+
+static struct cif_isp10_v4l2_fh *to_fh(struct file *file)
+{
+ if (!file || !file->private_data)
+ return NULL;
+
+ return container_of(file->private_data, struct cif_isp10_v4l2_fh, fh);
+}
+
+static struct cif_isp10_v4l2_node *to_node(struct cif_isp10_v4l2_fh *fh)
+{
+ struct video_device *vdev = fh ? fh->fh.vdev : NULL;
+
+ if (!fh || !vdev)
+ return NULL;
+
+ return container_of(vdev, struct cif_isp10_v4l2_node, vdev);
+}
+
+static struct videobuf_queue *to_videobuf_queue(
+ struct file *file)
+{
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct video_device *vdev = fh ? fh->fh.vdev : NULL;
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ struct videobuf_queue *q;
+
+ if (unlikely(!vdev)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "vdev is NULL\n");
+ WARN_ON(1);
+ }
+ q = &node->buf_queue;
+ if (unlikely(!q)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "buffer queue is NULL\n");
+ WARN_ON(1);
+ }
+
+ return q;
+}
+
+static enum cif_isp10_stream_id to_stream_id(
+ struct file *file)
+{
+ struct cif_isp10_v4l2_fh *fh;
+
+ if (unlikely(!file)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "NULL file handle\n");
+ WARN_ON(1);
+ }
+ fh = to_fh(file);
+ if (unlikely(!fh)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "fh is NULL\n");
+ WARN_ON(1);
+ }
+
+ return fh->stream_id;
+}
+
+static struct cif_isp10_device *to_cif_isp10_device(
+ struct videobuf_queue *queue)
+{
+ return queue->priv_data;
+}
+
+static enum cif_isp10_stream_id to_cif_isp10_stream_id(
+ struct videobuf_queue *queue)
+{
+ struct cif_isp10_v4l2_node *node =
+ container_of(queue, struct cif_isp10_v4l2_node, buf_queue);
+ struct video_device *vdev =
+ &node->vdev;
+
+ if (!strcmp(vdev->name, SP_VDEV_NAME))
+ return CIF_ISP10_STREAM_SP;
+ if (!strcmp(vdev->name, MP_VDEV_NAME))
+ return CIF_ISP10_STREAM_MP;
+ if (!strcmp(vdev->name, DMA_VDEV_NAME))
+ return CIF_ISP10_STREAM_DMA;
+
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unsupported/unknown device name %s\n", vdev->name);
+ return -EINVAL;
+}
+
+static const char *cif_isp10_v4l2_buf_type_string(
+ enum v4l2_buf_type buf_type)
+{
+ switch (buf_type) {
+ case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+ return "VIDEO_CAPTURE";
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ return "VIDEO_OVERLAY";
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+ return "VIDEO_OUTPUT";
+ default:
+ break;
+ }
+ return "UNKNOWN/UNSUPPORTED";
+}
+
+const char *cif_isp10_v4l2_pix_fmt_string(
+ int pix_fmt)
+{
+ switch (pix_fmt) {
+ case V4L2_PIX_FMT_RGB332:
+ return "V4L2-RGB332";
+ case V4L2_PIX_FMT_RGB555:
+ return "V4L2-RGB555";
+ case V4L2_PIX_FMT_RGB565:
+ return "V4L2-RGB565";
+ case V4L2_PIX_FMT_RGB555X:
+ return "V4L2-RGB555X";
+ case V4L2_PIX_FMT_RGB565X:
+ return "V4L2-RGB565X";
+ case V4L2_PIX_FMT_BGR24:
+ return "V4L2-BGR24";
+ case V4L2_PIX_FMT_RGB24:
+ return "V4L2-RGB24";
+ case V4L2_PIX_FMT_BGR32:
+ return "V4L2-BGR32";
+ case V4L2_PIX_FMT_RGB32:
+ return "V4L2-RGB32";
+ case V4L2_PIX_FMT_GREY:
+ return "V4L2-GREY";
+ case V4L2_PIX_FMT_YVU410:
+ return "V4L2-YVU410";
+ case V4L2_PIX_FMT_YVU420:
+ return "V4L2-YVU420";
+ case V4L2_PIX_FMT_YUYV:
+ return "V4L2-YUYV";
+ case V4L2_PIX_FMT_UYVY:
+ return "V4L2-UYVY";
+ case V4L2_PIX_FMT_YUV422P:
+ return "V4L2-YUV422P";
+ case V4L2_PIX_FMT_YUV411P:
+ return "V4L2-YUV411P";
+ case V4L2_PIX_FMT_Y41P:
+ return "V4L2-Y41P";
+ case V4L2_PIX_FMT_NV12:
+ return "V4L2-NV12";
+ case V4L2_PIX_FMT_NV21:
+ return "V4L2-NV21";
+ case V4L2_PIX_FMT_YUV410:
+ return "V4L2-YUV410";
+ case V4L2_PIX_FMT_YUV420:
+ return "V4L2--YUV420";
+ case V4L2_PIX_FMT_YYUV:
+ return "V4L2-YYUV";
+ case V4L2_PIX_FMT_HI240:
+ return "V4L2-HI240";
+ case V4L2_PIX_FMT_WNVA:
+ return "V4L2-WNVA";
+ case V4L2_PIX_FMT_NV16:
+ return "V4L2-NV16";
+ case V4L2_PIX_FMT_YUV444:
+ return "V4L2-YUV444P";
+ case V4L2_PIX_FMT_NV24:
+ return "M5-YUV444SP";
+ case V4L2_PIX_FMT_JPEG:
+ return "V4L2-JPEG";
+ case V4L2_PIX_FMT_SGRBG10:
+ return "RAW-BAYER-10Bits";
+ case V4L2_PIX_FMT_SGRBG8:
+ return "RAW-BAYER-8Bits";
+ }
+ return "UNKNOWN/UNSUPPORTED";
+}
+
+static int cif_isp10_v4l2_cid2cif_isp10_cid(u32 v4l2_cid)
+{
+ switch (v4l2_cid) {
+ case V4L2_CID_FLASH_LED_MODE:
+ return CIF_ISP10_CID_FLASH_MODE;
+ case V4L2_CID_AUTOGAIN:
+ return CIF_ISP10_CID_AUTO_GAIN;
+ case V4L2_EXPOSURE_AUTO:
+ return CIF_ISP10_CID_AUTO_EXPOSURE;
+ case V4L2_CID_AUTO_WHITE_BALANCE:
+ return CIF_ISP10_CID_AUTO_WHITE_BALANCE;
+ case V4L2_CID_BLACK_LEVEL:
+ return CIF_ISP10_CID_BLACK_LEVEL;
+ case V4L2_CID_WHITE_BALANCE_TEMPERATURE:
+ return CIF_ISP10_CID_WB_TEMPERATURE;
+ case V4L2_CID_EXPOSURE:
+ return CIF_ISP10_CID_EXPOSURE_TIME;
+ case V4L2_CID_GAIN:
+ return CIF_ISP10_CID_ANALOG_GAIN;
+ case V4L2_CID_FOCUS_ABSOLUTE:
+ return CIF_ISP10_CID_FOCUS_ABSOLUTE;
+ case V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE:
+ return CIF_ISP10_CID_AUTO_N_PRESET_WHITE_BALANCE;
+ case V4L2_CID_SCENE_MODE:
+ return CIF_ISP10_CID_SCENE_MODE;
+ case V4L2_CID_COLORFX:
+ return CIF_ISP10_CID_IMAGE_EFFECT;
+ case V4L2_CID_JPEG_COMPRESSION_QUALITY:
+ return CIF_ISP10_CID_JPEG_QUALITY;
+ case V4L2_CID_HFLIP:
+ return CIF_ISP10_CID_HFLIP;
+ case V4L2_CID_VFLIP:
+ return CIF_ISP10_CID_VFLIP;
+ case V4L2_CID_ISO_SENSITIVITY:
+ return CIF_ISP10_CID_ISO_SENSITIVITY;
+ case RK_V4L2_CID_AUTO_FPS:
+ return CIF_ISP10_CID_AUTO_FPS;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported V4L2 CID 0x%x\n",
+ v4l2_cid);
+ break;
+ }
+ return -EINVAL;
+}
+
+static enum cif_isp10_image_effect cif_isp10_v4l2_colorfx2cif_isp10_ie(
+ u32 v4l2_colorfx)
+{
+ switch (v4l2_colorfx) {
+ case V4L2_COLORFX_SEPIA:
+ return CIF_ISP10_IE_SEPIA;
+ case V4L2_COLORFX_BW:
+ return CIF_ISP10_IE_BW;
+ case V4L2_COLORFX_NEGATIVE:
+ return CIF_ISP10_IE_NEGATIVE;
+ case V4L2_COLORFX_EMBOSS:
+ return CIF_ISP10_IE_EMBOSS;
+ case V4L2_COLORFX_SKETCH:
+ return CIF_ISP10_IE_SKETCH;
+ case V4L2_COLORFX_NONE:
+ return CIF_ISP10_IE_NONE;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown/unsupported V4L2 COLORFX %d\n",
+ v4l2_colorfx);
+ break;
+ }
+ return -EINVAL;
+}
+
+static enum cif_isp10_pix_fmt cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
+ u32 v4l2_pix_fmt, struct videobuf_queue *queue)
+{
+/*struct cif_isp10_v4l2_node *node =
+ * container_of(queue, struct cif_isp10_v4l2_node, buf_queue);
+ * struct video_device *vdev =
+ * &node->vdev;
+ */
+
+ switch (v4l2_pix_fmt) {
+ case V4L2_PIX_FMT_GREY:
+ return CIF_YUV400;
+ case V4L2_PIX_FMT_YUV420:
+ return CIF_YUV420P;
+ case V4L2_PIX_FMT_YVU420:
+ return CIF_YVU420P;
+ case V4L2_PIX_FMT_NV12:
+ return CIF_YUV420SP;
+ case V4L2_PIX_FMT_NV21:
+ return CIF_YVU420SP;
+ case V4L2_PIX_FMT_YUYV:
+ return CIF_YUV422I;
+ case V4L2_PIX_FMT_UYVY:
+ return CIF_UYV422I;
+ case V4L2_PIX_FMT_YUV422P:
+ return CIF_YUV422P;
+ case V4L2_PIX_FMT_NV16:
+ return CIF_YUV422SP;
+ case V4L2_PIX_FMT_YUV444:
+ return CIF_YUV444P;
+ case V4L2_PIX_FMT_NV24:
+ return CIF_YUV444SP;
+ case V4L2_PIX_FMT_RGB565:
+ return CIF_RGB565;
+ case V4L2_PIX_FMT_RGB24:
+ return CIF_RGB888;
+ case V4L2_PIX_FMT_SBGGR8:
+ return CIF_BAYER_SBGGR8;
+ case V4L2_PIX_FMT_SGBRG8:
+ return CIF_BAYER_SGBRG8;
+ case V4L2_PIX_FMT_SGRBG8:
+ return CIF_BAYER_SGRBG8;
+ case V4L2_PIX_FMT_SRGGB8:
+ return CIF_BAYER_SRGGB8;
+ case V4L2_PIX_FMT_SBGGR10:
+ return CIF_BAYER_SBGGR10;
+ case V4L2_PIX_FMT_SGBRG10:
+ return CIF_BAYER_SGBRG10;
+ case V4L2_PIX_FMT_SGRBG10:
+ return CIF_BAYER_SGRBG10;
+ case V4L2_PIX_FMT_SRGGB10:
+ return CIF_BAYER_SRGGB10;
+ case V4L2_PIX_FMT_SBGGR12:
+ return CIF_BAYER_SBGGR12;
+ case V4L2_PIX_FMT_SGBRG12:
+ return CIF_BAYER_SGBRG12;
+ case V4L2_PIX_FMT_SGRBG12:
+ return CIF_BAYER_SGRBG12;
+ case V4L2_PIX_FMT_SRGGB12:
+ return CIF_BAYER_SRGGB12;
+ case V4L2_PIX_FMT_JPEG:
+ return CIF_JPEG;
+ default:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "unknown or unsupported V4L2 pixel format %c%c%c%c\n",
+ (u8)(v4l2_pix_fmt & 0xff),
+ (u8)((v4l2_pix_fmt >> 8) & 0xff),
+ (u8)((v4l2_pix_fmt >> 16) & 0xff),
+ (u8)((v4l2_pix_fmt >> 24) & 0xff));
+ return CIF_UNKNOWN_FORMAT;
+ }
+}
+
+static int cif_isp10_v4l2_register_video_device(
+ struct cif_isp10_device *dev,
+ struct video_device *vdev,
+ const char *name,
+ int qtype,
+ int major,
+ const struct v4l2_file_operations *fops,
+ const struct v4l2_ioctl_ops *ioctl_ops)
+{
+ int ret;
+
+ vdev->release = video_device_release;
+ strlcpy(vdev->name, name, sizeof(vdev->name));
+ vdev->vfl_type = qtype;
+ vdev->fops = fops;
+ video_set_drvdata(vdev, dev);
+ vdev->minor = -1;
+ vdev->ioctl_ops = ioctl_ops;
+ vdev->v4l2_dev = &dev->v4l2_dev;
+ if (qtype == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ vdev->vfl_dir = VFL_DIR_TX;
+ else
+ vdev->vfl_dir = VFL_DIR_RX;
+
+ ret = video_register_device(vdev, VFL_TYPE_GRABBER, major);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "video_register_device failed with error %d\n", ret);
+ goto err;
+ }
+
+ cif_isp10_pltfrm_pr_info(NULL,
+ "video device video%d.%d (%s) successfully registered\n",
+ major, vdev->minor, name);
+
+ return 0;
+err:
+ video_device_release(vdev);
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with err %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_streamon(
+ struct file *file,
+ void *priv,
+ enum v4l2_buf_type buf_type)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ static u32 streamon_cnt_sp;
+ static u32 streamon_cnt_mp;
+ static u32 streamon_cnt_dma;
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ u32 stream_ids = to_stream_id(file);
+
+ if (node->owner != fh)
+ return -EBUSY;
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%s(%d)\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ (stream_ids & CIF_ISP10_STREAM_MP) ? ++streamon_cnt_mp :
+ ((stream_ids & CIF_ISP10_STREAM_SP) ? ++streamon_cnt_sp :
+ ++streamon_cnt_dma));
+
+ ret = videobuf_streamon(queue);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "videobuf_streamon failed\n");
+ goto err;
+ }
+
+ ret = cif_isp10_streamon(dev, stream_ids);
+ if (IS_ERR_VALUE(ret)) {
+ videobuf_queue_cancel(queue);
+ goto err;
+ }
+
+ return 0;
+err:
+ (void)videobuf_mmap_free(queue);
+ cif_isp10_pltfrm_pr_err(dev->dev, "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_do_streamoff(
+ struct file *file)
+{
+ int ret = 0;
+ int err;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ u32 stream_ids = to_stream_id(file);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (node->owner != fh)
+ return -EBUSY;
+
+ err = cif_isp10_streamoff(dev, stream_ids);
+ if (IS_ERR_VALUE(err))
+ ret = -EFAULT;
+ err = videobuf_streamoff(queue);
+ if (IS_ERR_VALUE(err)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "videobuf_streamoff failed with error %d\n", err);
+ ret = -EFAULT;
+ }
+ err = videobuf_mmap_free(queue);
+ if (IS_ERR_VALUE(err)) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "videobuf_mmap_free failed with error %d\n", err);
+ ret = -EFAULT;
+ }
+
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+
+ return ret;
+}
+
+static int cif_isp10_v4l2_streamoff(
+ struct file *file,
+ void *priv,
+ enum v4l2_buf_type buf_type)
+{
+ int ret = cif_isp10_v4l2_do_streamoff(file);
+
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+
+ return ret;
+}
+
+static int cif_isp10_v4l2_qbuf(
+ struct file *file,
+ void *priv,
+ struct v4l2_buffer *buf)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s buffer type %s, index %d, length %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ cif_isp10_v4l2_buf_type_string(buf->type),
+ buf->index, buf->length);
+
+ if (node->owner != fh)
+ return -EBUSY;
+
+ ret = videobuf_qbuf(queue, buf);
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_qbuf failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_dqbuf(
+ struct file *file,
+ void *priv,
+ struct v4l2_buffer *buf)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (node->owner != fh)
+ return -EBUSY;
+
+ ret = videobuf_dqbuf(queue, buf, file->f_flags & O_NONBLOCK);
+ if (IS_ERR_VALUE(ret) && (ret != -EAGAIN))
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_dqbuf failed with error %d\n", ret);
+ else
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "dequeued buffer %d, size %d\n",
+ buf->index, buf->length);
+ return ret;
+}
+
+static void cif_isp10_v4l2_buf_release(
+ struct videobuf_queue *queue,
+ struct videobuf_buffer *buf)
+{
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (in_interrupt())
+ WARN_ON(1);
+
+ videobuf_dma_contig_free(queue, buf);
+
+ buf->state = VIDEOBUF_NEEDS_INIT;
+}
+
+static void cif_isp10_v4l2_buf_queue(
+ struct videobuf_queue *queue,
+ struct videobuf_buffer *buf)
+{
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s %dx%d, size %lu, bytesperline %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ buf->width, buf->height, buf->size, buf->bytesperline);
+
+ if (!IS_ERR_VALUE(cif_isp10_qbuf(dev, strm, buf)))
+ buf->state = VIDEOBUF_QUEUED;
+ else
+ cif_isp10_pltfrm_pr_err(NULL, "failed\n");
+}
+
+static int cif_isp10_v4l2_buf_setup(
+ struct videobuf_queue *queue,
+ unsigned int *cnt,
+ unsigned int *size)
+{
+ int ret;
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ *cnt, *size);
+
+ ret = cif_isp10_calc_min_out_buff_size(
+ dev, strm, size);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+ return ret;
+ }
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s count %d, size %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ *cnt, *size);
+
+ return 0;
+}
+
+static int cif_isp10_v4l2_buf_prepare(
+ struct videobuf_queue *queue,
+ struct videobuf_buffer *buf,
+ enum v4l2_field field)
+{
+ int ret;
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+ u32 size;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ ret = cif_isp10_calc_min_out_buff_size(
+ dev, strm, &size);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+ buf->size = size;
+ if (strm == CIF_ISP10_STREAM_SP) {
+ buf->width =
+ dev->config.mi_config.sp.output.width;
+ buf->height =
+ dev->config.mi_config.sp.output.height;
+ } else if (strm == CIF_ISP10_STREAM_MP) {
+ buf->width =
+ dev->config.mi_config.mp.output.width;
+ buf->height =
+ dev->config.mi_config.mp.output.height;
+ } else if (strm == CIF_ISP10_STREAM_DMA) {
+ buf->width =
+ dev->config.mi_config.dma.output.width;
+ buf->height =
+ dev->config.mi_config.dma.output.height;
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "wrong buffer queue %d\n", queue->type);
+ ret = -EINVAL;
+ goto err;
+ }
+ buf->field = field;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s buffer prepared %dx%d, size %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ buf->width, buf->height, size);
+
+ if (buf->state == VIDEOBUF_NEEDS_INIT) {
+ ret = videobuf_iolock(queue, buf, NULL);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_iolock failed with error %d\n", ret);
+ goto err;
+ }
+ }
+ buf->state = VIDEOBUF_PREPARED;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+ cif_isp10_v4l2_buf_release(queue, buf);
+ return ret;
+}
+
+static int cif_isp10_v4l2_reqbufs(
+ struct file *file,
+ void *priv,
+ struct v4l2_requestbuffers *req)
+{
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_stream_id strm = to_cif_isp10_stream_id(queue);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s requested type %s, count %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type),
+ cif_isp10_v4l2_buf_type_string(req->type),
+ req->count);
+
+ if (node->owner && node->owner != fh)
+ return -EBUSY;
+ node->owner = fh;
+
+ ret = videobuf_reqbufs(queue, req);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_reqbufs failed with error %d\n", ret);
+ }
+ cif_isp10_reqbufs(dev, strm, req);
+ return ret;
+}
+
+static int cif_isp10_v4l2_querybuf(
+ struct file *file,
+ void *priv,
+ struct v4l2_buffer *buf)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s, index %d\n",
+ cif_isp10_v4l2_buf_type_string(queue->type), buf->index);
+
+ ret = videobuf_querybuf(queue, buf);
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_querybuf failed with error %d\n", ret);
+
+ return ret;
+}
+
+static int cif_isp10_v4l2_s_ctrl(
+ struct file *file,
+ void *priv,
+ struct v4l2_control *vc)
+{
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_cid id =
+ cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
+ int val = vc->value;
+
+ if (IS_ERR_VALUE(id))
+ return id;
+
+ switch (vc->id) {
+ case V4L2_CID_COLORFX:
+ val = cif_isp10_v4l2_colorfx2cif_isp10_ie(val);
+ break;
+ case V4L2_CID_FLASH_LED_MODE:
+ if (vc->value == V4L2_FLASH_LED_MODE_NONE)
+ val = CIF_ISP10_FLASH_MODE_OFF;
+ else if (vc->value == V4L2_FLASH_LED_MODE_FLASH)
+ val = CIF_ISP10_FLASH_MODE_FLASH;
+ else if (vc->value == V4L2_FLASH_LED_MODE_TORCH)
+ val = CIF_ISP10_FLASH_MODE_TORCH;
+ else
+ val = -EINVAL;
+ break;
+ default:
+ break;
+ }
+
+ return cif_isp10_s_ctrl(dev, id, val);
+}
+
+static int cif_isp10_v4l2_s_fmt(
+ struct file *file,
+ void *priv,
+ struct v4l2_format *f)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ struct cif_isp10_strm_fmt strm_fmt;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (node->owner && node->owner != fh)
+ return -EBUSY;
+
+ strm_fmt.frm_fmt.pix_fmt =
+ cif_isp10_v4l2_pix_fmt2cif_isp10_pix_fmt(
+ f->fmt.pix.pixelformat, queue);
+ strm_fmt.frm_fmt.width = f->fmt.pix.width;
+ strm_fmt.frm_fmt.height = f->fmt.pix.height;
+/* strm_fmt.frm_fmt.quantization = f->fmt.pix.quantization; */
+ strm_fmt.frm_fmt.quantization = 0;
+ ret = cif_isp10_s_fmt(dev,
+ to_stream_id(file),
+ &strm_fmt,
+ f->fmt.pix.bytesperline);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+/* existence of this function is checked by V4L2 */
+static int cif_isp10_v4l2_g_fmt(
+ struct file *file,
+ void *priv,
+ struct v4l2_format *f)
+{
+ return -EFAULT;
+}
+
+static int cif_isp10_v4l2_s_input(
+ struct file *file,
+ void *priv,
+ unsigned int i)
+{
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "setting input to %d\n", i);
+
+ ret = cif_isp10_s_input(dev, i);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_enum_framesizes(
+ struct file *file,
+ void *priv,
+ struct v4l2_frmsizeenum *fsize)
+{
+ /* THIS FUNCTION IS UNDER CONSTRUCTION */
+ int ret;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+ if (IS_ERR_OR_NULL(dev->img_src)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "input has not yet been selected, cannot enumerate formats\n");
+ ret = -ENODEV;
+ goto err;
+ }
+
+ return -EINVAL;
+err:
+ cif_isp10_pltfrm_pr_err(NULL, "failed with error %d\n", ret);
+ return ret;
+}
+
+/* fops **********************************************************************/
+
+const struct videobuf_queue_ops cif_isp10_qops = {
+ .buf_setup = cif_isp10_v4l2_buf_setup,
+ .buf_prepare = cif_isp10_v4l2_buf_prepare,
+ .buf_queue = cif_isp10_v4l2_buf_queue,
+ .buf_release = cif_isp10_v4l2_buf_release,
+};
+
+static int cif_isp10_v4l2_open(
+ struct file *file)
+{
+ int ret;
+ struct video_device *vdev = video_devdata(file);
+ struct cif_isp10_device *dev = video_get_drvdata(vdev);
+ struct cif_isp10_v4l2_fh *fh;
+ struct cif_isp10_v4l2_node *node;
+ enum v4l2_buf_type buf_type;
+ enum cif_isp10_stream_id stream_id;
+ struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+ (struct cif_isp10_v4l2_device *)dev->nodes;
+
+ cif_isp10_pltfrm_pr_dbg(NULL,
+ "video device video%d.%d (%s)\n",
+ vdev->num, vdev->minor, vdev->name);
+
+ if (vdev->minor == cif_isp10_v4l2_dev->node[SP_DEV].vdev.minor) {
+ buf_type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ stream_id = CIF_ISP10_STREAM_SP;
+ } else if (vdev->minor == cif_isp10_v4l2_dev->node[MP_DEV].vdev.minor) {
+ buf_type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+ stream_id = CIF_ISP10_STREAM_MP;
+ } else if (vdev->minor ==
+ cif_isp10_v4l2_dev->node[DMA_DEV].vdev.minor) {
+ buf_type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+ stream_id = CIF_ISP10_STREAM_DMA;
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "invalid video device video%d.%d (%s)\n",
+ vdev->num, vdev->minor, vdev->name);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ fh = kzalloc(sizeof(*fh), GFP_KERNEL);
+ if (!fh) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "memory allocation failed\n");
+ ret = -ENOMEM;
+ goto err;
+ }
+ fh->stream_id = stream_id;
+
+ file->private_data = &fh->fh;
+ v4l2_fh_init(&fh->fh, vdev);
+ v4l2_fh_add(&fh->fh);
+
+ node = to_node(fh);
+ if (++node->users > 1)
+ return 0;
+
+ /* First open of the device, so initialize everything */
+ node->owner = NULL;
+
+ videobuf_queue_dma_contig_init(
+ to_videobuf_queue(file),
+ &cif_isp10_qops,
+ dev->dev,
+ &dev->vbq_lock,
+ buf_type,
+ V4L2_FIELD_NONE,
+ sizeof(struct videobuf_buffer),
+ dev, NULL);
+
+ ret = cif_isp10_init(dev, to_stream_id(file));
+ if (IS_ERR_VALUE(ret)) {
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ kfree(fh);
+ node->users--;
+ goto err;
+ }
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_release(struct file *file)
+{
+ int ret = 0;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ struct cif_isp10_v4l2_node *node = to_node(fh);
+ enum cif_isp10_stream_id stream_id = to_stream_id(file);
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (node->users) {
+ --node->users;
+ } else {
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "number of users for this device is already 0\n");
+ return 0;
+ }
+
+ if (!node->users) {
+ if (queue->streaming)
+ if (IS_ERR_VALUE(cif_isp10_v4l2_do_streamoff(file)))
+ cif_isp10_pltfrm_pr_warn(dev->dev,
+ "streamoff failed\n");
+
+ /* Last close, so uninitialize hardware */
+ ret = cif_isp10_release(dev, stream_id);
+ }
+
+ if (node->owner == fh)
+ node->owner = NULL;
+
+ v4l2_fh_del(&fh->fh);
+ v4l2_fh_exit(&fh->fh);
+ kfree(fh);
+
+ if (IS_ERR_VALUE(ret))
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static unsigned int cif_isp10_v4l2_poll(
+ struct file *file,
+ struct poll_table_struct *wait)
+{
+ struct cif_isp10_v4l2_fh *fh = to_fh(file);
+ int ret = 0;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ unsigned long req_events = poll_requested_events(wait);
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "%s\n",
+ cif_isp10_v4l2_buf_type_string(queue->type));
+
+ if (v4l2_event_pending(&fh->fh))
+ ret = POLLPRI;
+ else if (req_events & POLLPRI)
+ poll_wait(file, &fh->fh.wait, wait);
+
+ if (!(req_events & (POLLIN | POLLOUT | POLLRDNORM)))
+ return ret;
+
+ ret |= videobuf_poll_stream(file, queue, wait);
+ if (ret & POLLERR) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "videobuf_poll_stream failed with error 0x%x\n", ret);
+ }
+ return ret;
+}
+
+/*
+ * VMA operations.
+ */
+static void cif_isp10_v4l2_vm_open(struct vm_area_struct *vma)
+{
+ struct cif_isp10_metadata_s *metadata =
+ (struct cif_isp10_metadata_s *)vma->vm_private_data;
+
+ metadata->vmas++;
+}
+
+static void cif_isp10_v4l2_vm_close(struct vm_area_struct *vma)
+{
+ struct cif_isp10_metadata_s *metadata =
+ (struct cif_isp10_metadata_s *)vma->vm_private_data;
+
+ metadata->vmas--;
+}
+
+static const struct vm_operations_struct cif_isp10_vm_ops = {
+ .open = cif_isp10_v4l2_vm_open,
+ .close = cif_isp10_v4l2_vm_close,
+};
+
+int cif_isp10_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_stream_id strm = to_stream_id(file);
+ int retval;
+
+ retval = cif_isp10_mmap(dev, strm, vma);
+ if (retval < 0)
+ goto done;
+
+ vma->vm_ops = &cif_isp10_vm_ops;
+ vma->vm_flags |= VM_DONTEXPAND | VM_DONTDUMP;
+ cif_isp10_v4l2_vm_open(vma);
+
+done:
+ return retval;
+}
+
+const struct v4l2_file_operations cif_isp10_v4l2_fops = {
+ .open = cif_isp10_v4l2_open,
+ .unlocked_ioctl = video_ioctl2,
+#ifdef CONFIG_COMPAT
+ .compat_ioctl32 = video_ioctl2,
+#endif
+ .release = cif_isp10_v4l2_release,
+ .poll = cif_isp10_v4l2_poll,
+ .mmap = cif_isp10_v4l2_mmap,
+};
+
+/*TBD: clean up code below this line******************************************/
+
+static int v4l2_querycap(struct file *file,
+ void *priv, struct v4l2_capability *cap)
+{
+ int ret = 0;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct video_device *vdev = video_devdata(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ u32 stream_ids = to_stream_id(file);
+
+ strcpy(cap->driver, DRIVER_NAME);
+ strlcpy(cap->card, vdev->name, sizeof(cap->card));
+ snprintf(cap->bus_info, sizeof(cap->bus_info),
+ "platform:" DRIVER_NAME "-%03i",
+ dev->dev_id);
+
+ if (stream_ids == CIF_ISP10_STREAM_SP)
+ cap->capabilities = V4L2_CAP_VIDEO_OVERLAY |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+ V4L2_CAP_STREAMING;
+ else if (stream_ids == CIF_ISP10_STREAM_MP)
+ cap->capabilities = V4L2_CAP_VIDEO_CAPTURE |
+ V4L2_CAP_VIDEO_CAPTURE_MPLANE |
+ V4L2_CAP_STREAMING;
+ else if (stream_ids == CIF_ISP10_STREAM_DMA)
+ cap->capabilities = V4L2_CAP_VIDEO_M2M_MPLANE |
+ V4L2_CAP_VIDEO_M2M;
+ cap->capabilities |= V4L2_CAP_DEVICE_CAPS;
+ cap->device_caps = V4L2_CAP_DEVICE_CAPS;
+ return ret;
+}
+
+static int cif_isp10_v4l2_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+ if (sub->type != V4L2_EVENT_FRAME_SYNC)
+ return -EINVAL;
+ return v4l2_event_subscribe(fh, sub, 16, NULL);
+}
+
+static int cif_isp10_v4l2_unsubscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+ return v4l2_event_unsubscribe(fh, sub);
+}
+
+static void cif_isp10_v4l2_event(
+ struct cif_isp10_device *dev,
+ __u32 frame_sequence)
+{
+ struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+ (struct cif_isp10_v4l2_device *)dev->nodes;
+ struct v4l2_event ev;
+
+ memset(&ev, 0, sizeof(ev));
+ ev.type = V4L2_EVENT_FRAME_SYNC;
+ ev.u.frame_sync.frame_sequence = frame_sequence;
+ v4l2_event_queue(&cif_isp10_v4l2_dev->node[SP_DEV].vdev, &ev);
+}
+
+static void cif_isp10_v4l2_requeue_bufs(
+ struct cif_isp10_device *dev,
+ enum cif_isp10_stream_id stream_id)
+{
+ struct videobuf_buffer *buf;
+ struct videobuf_queue *q = NULL;
+ struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+ (struct cif_isp10_v4l2_device *)dev->nodes;
+
+ if (stream_id == CIF_ISP10_STREAM_SP)
+ q = &cif_isp10_v4l2_dev->node[SP_DEV].buf_queue;
+ else if (stream_id == CIF_ISP10_STREAM_MP)
+ q = &cif_isp10_v4l2_dev->node[MP_DEV].buf_queue;
+ else if (stream_id == CIF_ISP10_STREAM_DMA)
+ q = &cif_isp10_v4l2_dev->node[DMA_DEV].buf_queue;
+ else
+ WARN_ON(1);
+
+ dev = to_cif_isp10_device(q);
+
+ list_for_each_entry(buf, &q->stream, stream) {
+ if (!IS_ERR_VALUE(cif_isp10_qbuf(
+ to_cif_isp10_device(q), stream_id, buf))) {
+ spin_lock(&dev->vbreq_lock);
+ if ((buf->state == VIDEOBUF_QUEUED) ||
+ (buf->state == VIDEOBUF_ACTIVE) ||
+ (buf->state == VIDEOBUF_DONE))
+ buf->state = VIDEOBUF_QUEUED;
+ else
+ cif_isp10_pltfrm_pr_err(NULL,
+ "ERR: buf->state is: %d\n",
+ buf->state);
+ spin_unlock(&dev->vbreq_lock);
+ } else {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "failed for buffer %d\n", buf->i);
+ }
+ }
+}
+
+static long v4l2_default_ioctl(struct file *file, void *fh,
+ bool valid_prio, unsigned int cmd, void *arg)
+{
+ int ret = -EINVAL;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+
+ if (!arg) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "NULL Pointer Violation from IOCTL arg:0x%lx\n",
+ (unsigned long)arg);
+ return ret;
+ }
+
+ if (cmd == RK_VIDIOC_SENSOR_MODE_DATA) {
+ struct isp_supplemental_sensor_mode_data *p_mode_data =
+ (struct isp_supplemental_sensor_mode_data *)arg;
+
+ ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_SENSOR_MODE_DATA, p_mode_data);
+
+ if (ret < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed to get sensor mode data\n");
+ return ret;
+ }
+
+ p_mode_data->isp_input_width =
+ dev->config.isp_config.input->defrect.width;
+ p_mode_data->isp_input_height =
+ dev->config.isp_config.input->defrect.height;
+ p_mode_data->isp_input_horizontal_start =
+ dev->config.isp_config.input->defrect.left;
+ p_mode_data->isp_input_vertical_start =
+ dev->config.isp_config.input->defrect.top;
+
+ p_mode_data->isp_output_width =
+ dev->config.isp_config.output.width;
+ p_mode_data->isp_output_height =
+ dev->config.isp_config.output.height;
+
+ if (ret < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed to get isp input info\n");
+ return ret;
+ }
+ } else if (cmd == RK_VIDIOC_CAMERA_MODULEINFO) {
+ struct camera_module_info_s *p_camera_module =
+ (struct camera_module_info_s *)arg;
+
+ ret = (int)cif_isp10_img_src_ioctl(dev->img_src,
+ RK_VIDIOC_CAMERA_MODULEINFO, p_camera_module);
+
+ if (ret < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed to get camera module information\n");
+ return ret;
+ }
+ }
+
+ return ret;
+}
+
+static int v4l2_s_parm(
+ struct file *file,
+ void *priv,
+ struct v4l2_streamparm *a)
+{
+ return 0;
+}
+
+static int v4l2_enum_input(struct file *file, void *priv,
+ struct v4l2_input *input)
+{
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ const char *inp_name;
+
+ if ((queue->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) &&
+ (queue->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "wrong buffer queue %d\n", queue->type);
+ return -EINVAL;
+ }
+
+ inp_name = cif_isp10_g_input_name(dev, input->index);
+ if (IS_ERR_OR_NULL(inp_name))
+ return -EINVAL;
+
+ input->type = V4L2_INPUT_TYPE_CAMERA;
+ input->std = V4L2_STD_UNKNOWN;
+ strncpy(input->name, inp_name, sizeof(input->name)-1);
+
+ return 0;
+}
+
+/* ================================================================= */
+
+static int mainpath_g_ctrl(
+ struct file *file,
+ void *priv,
+ struct v4l2_control *vc)
+{
+ int ret = -EINVAL;
+
+ switch (vc->id) {
+ default:
+ return -EINVAL;
+ }
+ return ret;
+}
+
+#ifdef NOT_YET
+static int mainpath_try_fmt_cap(struct v4l2_format *f)
+{
+ int ifmt = 0;
+ struct v4l2_pix_format *pix = &f->fmt.pix;
+
+ cif_isp10_pltfrm_pr_dbg(NULL, "\n");
+
+ for (ifmt = 0; ifmt < get_cif_isp10_output_format_size(); ifmt++) {
+ if (pix->pixelformat ==
+ get_cif_isp10_output_format(ifmt)->fourcc)
+ break;
+ }
+
+ if (ifmt == get_cif_isp10_output_format_size())
+ ifmt = 0;
+
+ pix->bytesperline = pix->width *
+ get_cif_isp10_output_format(ifmt)->depth / 8;
+
+ switch (pix->pixelformat) {
+ case V4L2_PIX_FMT_YUYV:
+ case V4L2_PIX_FMT_UYVY:
+ case V4L2_PIX_FMT_YUV422P:
+ case V4L2_PIX_FMT_NV16:
+ case V4L2_PIX_FMT_YUV420:
+ case V4L2_PIX_FMT_YVU420:
+ case V4L2_PIX_FMT_NV12:
+ case V4L2_PIX_FMT_NV21:
+ case V4L2_PIX_FMT_GREY:
+ case V4L2_PIX_FMT_YUV444:
+ case V4L2_PIX_FMT_NV24:
+ case V4L2_PIX_FMT_JPEG:
+ pix->colorspace = V4L2_COLORSPACE_JPEG;
+ break;
+ case V4L2_PIX_FMT_RGB32:
+ case V4L2_PIX_FMT_BGR32:
+ case V4L2_PIX_FMT_RGB565:
+ case V4L2_PIX_FMT_RGB565X:
+ case V4L2_PIX_FMT_SGRBG10:
+ pix->colorspace = V4L2_COLORSPACE_SRGB;
+ break;
+ default:
+ WARN_ON(1);
+ break;
+ }
+
+ return 0;
+}
+#endif
+
+static int v4l2_enum_fmt_cap(struct file *file, void *fh,
+ struct v4l2_fmtdesc *f)
+{
+ int ret = 0;
+ int xgold_num_format = 0;
+
+ xgold_num_format = get_cif_isp10_output_format_desc_size();
+ if ((f->index >= xgold_num_format) ||
+ (get_cif_isp10_output_format_desc(f->index)->pixelformat == 0)) {
+ cif_isp10_pltfrm_pr_err(NULL, "index %d\n", f->index);
+ return -EINVAL;
+ }
+ strlcpy(f->description,
+ get_cif_isp10_output_format_desc(f->index)->description,
+ sizeof(f->description));
+ f->pixelformat =
+ get_cif_isp10_output_format_desc(f->index)->pixelformat;
+ f->flags = get_cif_isp10_output_format_desc(f->index)->flags;
+
+ return ret;
+}
+
+static int v4l2_g_ctrl(struct file *file, void *priv,
+ struct v4l2_control *vc)
+{
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ enum cif_isp10_cid id =
+ cif_isp10_v4l2_cid2cif_isp10_cid(vc->id);
+
+ return cif_isp10_img_src_g_ctrl(dev->img_src,
+ id, &vc->value);
+}
+
+static int v4l2_s_ext_ctrls(struct file *file, void *priv,
+ struct v4l2_ext_controls *vc_ext)
+{
+ struct cif_isp10_img_src_ctrl *ctrls;
+ struct cif_isp10_img_src_ext_ctrl *ctrl;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ int ret = -EINVAL;
+ unsigned int i;
+
+ /* The only use-case is gain and exposure to sensor. Thus no check if
+ * this shall go to img_src or not as of now.
+ */
+ cif_isp10_pltfrm_pr_dbg(dev->dev, "count %d\n",
+ vc_ext->count);
+
+ if (vc_ext->count == 0)
+ return ret;
+
+ ctrl = kmalloc(sizeof(*ctrl), GFP_KERNEL);
+ if (!ctrl)
+ return -ENOMEM;
+
+ ctrls = kmalloc(vc_ext->count *
+ sizeof(struct cif_isp10_img_src_ctrl), GFP_KERNEL);
+ if (!ctrls) {
+ kfree(ctrl);
+ return -ENOMEM;
+ }
+
+ ctrl->cnt = vc_ext->count;
+ /*current kernel version don't define
+ *this member for struct v4l2_ext_control.
+ */
+ /*ctrl->class = vc_ext->ctrl_class;*/
+ ctrl->ctrls = ctrls;
+
+ for (i = 0; i < vc_ext->count; i++) {
+ ctrls[i].id = vc_ext->controls[i].id;
+ ctrls[i].val = vc_ext->controls[i].value;
+ }
+
+ ret = cif_isp10_s_exp(dev, ctrl);
+ return ret;
+}
+
+int cif_isp10_v4l2_cropcap(
+ struct file *file,
+ void *fh,
+ struct v4l2_cropcap *a)
+{
+ int ret = 0;
+ struct videobuf_queue *queue = to_videobuf_queue(file);
+ struct cif_isp10_device *dev = to_cif_isp10_device(queue);
+ u32 target_width, target_height;
+ u32 h_offs, v_offs;
+
+ if ((dev->config.input_sel == CIF_ISP10_INP_DMA) ||
+ (dev->config.input_sel == CIF_ISP10_INP_DMA_IE)) {
+ /* calculate cropping for aspect ratio */
+ ret = cif_isp10_calc_isp_cropping(dev,
+ &dev->isp_dev.input_width, &dev->isp_dev.input_height,
+ &h_offs, &v_offs);
+
+ /* Get output size */
+ ret = cif_isp10_get_target_frm_size(dev,
+ &target_width, &target_height);
+ if (ret < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed to get target frame size\n");
+ return ret;
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "CIF_IN_W=%d, CIF_IN_H=%d, ISP_IN_W=%d, ISP_IN_H=%d, target_width=%d, target_height=%d\n",
+ dev->config.isp_config.input->width,
+ dev->config.isp_config.input->height,
+ dev->isp_dev.input_width,
+ dev->isp_dev.input_height,
+ target_width,
+ target_height);
+
+ /* This is the input to Bayer after input formatter cropping */
+ a->defrect.top = 0;
+ a->defrect.left = 0;
+ a->defrect.width = dev->isp_dev.input_width;
+ a->defrect.height = dev->isp_dev.input_height;
+ /* This is the minimum cropping window for the IS module */
+ a->bounds.width = 2;
+ a->bounds.height = 2;
+ a->bounds.top = (a->defrect.height - a->bounds.height) / 2;
+ a->bounds.left = (a->defrect.width - a->bounds.width) / 2;
+
+ a->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ } else if (!CIF_ISP10_INP_IS_DMA(dev->config.input_sel)) {
+ /* calculate cropping for aspect ratio */
+ ret = cif_isp10_calc_isp_cropping(dev,
+ &dev->isp_dev.input_width, &dev->isp_dev.input_height,
+ &h_offs, &v_offs);
+
+ /* Get output size */
+ ret = cif_isp10_get_target_frm_size(dev,
+ &target_width, &target_height);
+ if (ret < 0) {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "failed to get target frame size\n");
+ return ret;
+ }
+
+ /* This is the input to Bayer after input formatter cropping */
+ a->defrect.top =
+ v_offs + dev->config.isp_config.input->defrect.top;
+ a->defrect.left =
+ h_offs + dev->config.isp_config.input->defrect.left;
+ a->defrect.width = dev->isp_dev.input_width;
+ a->defrect.height = dev->isp_dev.input_height;
+
+ a->bounds.top = 0;
+ a->bounds.left = 0;
+ a->bounds.width = dev->config.isp_config.input->width;
+ a->bounds.height = dev->config.isp_config.input->height;
+ a->type = V4L2_BUF_TYPE_VIDEO_OVERLAY;
+ } else {
+ cif_isp10_pltfrm_pr_err(dev->dev,
+ "invalid input\n");
+ }
+
+ cif_isp10_pltfrm_pr_dbg(dev->dev,
+ "v4l2_cropcap: defrect(%d,%d,%d,%d) bounds(%d,%d,%d,%d)\n",
+ a->defrect.width,
+ a->defrect.height,
+ a->defrect.left,
+ a->defrect.top,
+ a->bounds.width,
+ a->bounds.height,
+ a->bounds.left,
+ a->bounds.top);
+
+ return ret;
+}
+
+int cif_isp10_v4l2_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
+{
+ return 0;
+}
+
+/*
+ * This is a write only function, so the upper layer
+ * will ignore the changes to 'a'. So don't use 'a' to pass
+ * the actual cropping parameters, the upper layer
+ * should call g_crop to get the actual window.
+ */
+int cif_isp10_v4l2_s_crop(
+ struct file *file,
+ void *fh,
+ const struct v4l2_crop *a)
+{
+ return 0;
+}
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_sp_ioctlops = {
+ .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+ .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+ .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+ .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+ .vidioc_streamon = cif_isp10_v4l2_streamon,
+ .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+ .vidioc_s_input = cif_isp10_v4l2_s_input,
+ .vidioc_enum_input = v4l2_enum_input,
+ .vidioc_g_ctrl = v4l2_g_ctrl,
+ .vidioc_s_ctrl = cif_isp10_v4l2_s_ctrl,
+ .vidioc_s_fmt_vid_overlay = cif_isp10_v4l2_s_fmt,
+ .vidioc_g_fmt_vid_overlay = cif_isp10_v4l2_g_fmt,
+ .vidioc_s_ext_ctrls = v4l2_s_ext_ctrls,
+ .vidioc_querycap = v4l2_querycap,
+ .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+ .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+ .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+ .vidioc_subscribe_event = cif_isp10_v4l2_subscribe_event,
+ .vidioc_unsubscribe_event = cif_isp10_v4l2_unsubscribe_event,
+ .vidioc_default = v4l2_default_ioctl,
+};
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_mp_ioctlops = {
+ .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+ .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+ .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+ .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+ .vidioc_streamon = cif_isp10_v4l2_streamon,
+ .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+ .vidioc_s_input = cif_isp10_v4l2_s_input,
+ .vidioc_enum_input = v4l2_enum_input,
+ .vidioc_g_ctrl = mainpath_g_ctrl,
+ .vidioc_s_ctrl = cif_isp10_v4l2_s_ctrl,
+ .vidioc_s_fmt_vid_cap = cif_isp10_v4l2_s_fmt,
+ .vidioc_g_fmt_vid_cap = cif_isp10_v4l2_g_fmt,
+ .vidioc_enum_fmt_vid_cap = v4l2_enum_fmt_cap,
+ .vidioc_enum_framesizes = cif_isp10_v4l2_enum_framesizes,
+ .vidioc_s_parm = v4l2_s_parm,
+ .vidioc_querycap = v4l2_querycap,
+ .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+ .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+ .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+ .vidioc_default = v4l2_default_ioctl,
+};
+
+const struct v4l2_ioctl_ops cif_isp10_v4l2_dma_ioctlops = {
+ .vidioc_reqbufs = cif_isp10_v4l2_reqbufs,
+ .vidioc_querybuf = cif_isp10_v4l2_querybuf,
+ .vidioc_qbuf = cif_isp10_v4l2_qbuf,
+ .vidioc_dqbuf = cif_isp10_v4l2_dqbuf,
+ .vidioc_streamon = cif_isp10_v4l2_streamon,
+ .vidioc_streamoff = cif_isp10_v4l2_streamoff,
+ .vidioc_s_fmt_vid_out = cif_isp10_v4l2_s_fmt,
+ .vidioc_g_fmt_vid_out = cif_isp10_v4l2_g_fmt,
+ .vidioc_cropcap = cif_isp10_v4l2_cropcap,
+ .vidioc_s_crop = cif_isp10_v4l2_s_crop,
+ .vidioc_g_crop = cif_isp10_v4l2_g_crop,
+};
+
+static struct pltfrm_soc_cfg rk3288_cfg = {
+ .name = CIF_ISP10_SOC_RK3288,
+ .soc_cfg = pltfrm_rk3288_cfg,
+};
+
+static struct pltfrm_soc_cfg rk3399_cfg = {
+ .name = CIF_ISP10_SOC_RK3399,
+ .soc_cfg = pltfrm_rk3399_cfg,
+};
+
+static const struct of_device_id cif_isp10_v4l2_of_match[] = {
+ {.compatible = "rockchip,rk3288-cif-isp",
+ .data = (void *)&rk3288_cfg},
+ {.compatible = "rockchip,rk3399-cif-isp",
+ .data = (void *)&rk3399_cfg},
+ {},
+};
+
+static unsigned int cif_isp10_v4l2_dev_cnt;
+static int cif_isp10_v4l2_drv_probe(struct platform_device *pdev)
+{
+ const struct of_device_id *match;
+ struct device_node *node = pdev->dev.of_node;
+ struct cif_isp10_device *dev = NULL;
+ struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev;
+ int ret;
+
+ cif_isp10_pltfrm_pr_info(NULL, "probing...\n");
+
+ cif_isp10_v4l2_dev = devm_kzalloc(
+ &pdev->dev,
+ sizeof(struct cif_isp10_v4l2_device),
+ GFP_KERNEL);
+ if (IS_ERR_OR_NULL(cif_isp10_v4l2_dev)) {
+ ret = -ENOMEM;
+ goto err;
+ }
+
+ match = of_match_node(cif_isp10_v4l2_of_match, node);
+ dev = cif_isp10_create(&pdev->dev,
+ cif_isp10_v4l2_event,
+ cif_isp10_v4l2_requeue_bufs,
+ (struct pltfrm_soc_cfg *)match->data);
+ if (IS_ERR_OR_NULL(dev)) {
+ ret = -ENODEV;
+ goto err;
+ }
+
+ dev->dev_id = cif_isp10_v4l2_dev_cnt;
+ dev->isp_dev.dev_id = &dev->dev_id;
+ dev->nodes = (void *)cif_isp10_v4l2_dev;
+ spin_lock_init(&dev->vbq_lock);
+ spin_lock_init(&dev->vbreq_lock);
+ spin_lock_init(&iowrite32_verify_lock);
+
+ ret = v4l2_device_register(dev->dev, &dev->v4l2_dev);
+ if (IS_ERR_VALUE(ret)) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "V4L2 device registration failed\n");
+ goto err;
+ }
+
+ ret = cif_isp10_v4l2_register_video_device(
+ dev,
+ &cif_isp10_v4l2_dev->node[SP_DEV].vdev,
+ SP_VDEV_NAME,
+ V4L2_CAP_VIDEO_OVERLAY,
+ CIF_ISP10_V4L2_SP_DEV_MAJOR,
+ &cif_isp10_v4l2_fops,
+ &cif_isp10_v4l2_sp_ioctlops);
+ if (ret)
+ goto err;
+
+ ret = register_cifisp_device(&dev->isp_dev,
+ &cif_isp10_v4l2_dev->node[ISP_DEV].vdev,
+ &dev->v4l2_dev,
+ dev->config.base_addr);
+ if (ret)
+ goto err;
+
+ ret = cif_isp10_v4l2_register_video_device(
+ dev,
+ &cif_isp10_v4l2_dev->node[MP_DEV].vdev,
+ MP_VDEV_NAME,
+ V4L2_CAP_VIDEO_CAPTURE,
+ CIF_ISP10_V4L2_MP_DEV_MAJOR,
+ &cif_isp10_v4l2_fops,
+ &cif_isp10_v4l2_mp_ioctlops);
+ if (ret)
+ goto err;
+
+ ret = cif_isp10_v4l2_register_video_device(
+ dev,
+ &cif_isp10_v4l2_dev->node[DMA_DEV].vdev,
+ DMA_VDEV_NAME,
+ V4L2_CAP_VIDEO_OUTPUT,
+ CIF_ISP10_V4L2_DMA_DEV_MAJOR,
+ &cif_isp10_v4l2_fops,
+ &cif_isp10_v4l2_dma_ioctlops);
+ if (ret)
+ goto err;
+
+ pm_runtime_enable(&pdev->dev);
+
+ cif_isp10_v4l2_dev_cnt++;
+ return 0;
+err:
+ cif_isp10_destroy(dev);
+ return ret;
+}
+
+/* ======================================================================== */
+
+static int cif_isp10_v4l2_drv_remove(struct platform_device *pdev)
+{
+ struct cif_isp10_device *cif_isp10_dev =
+ (struct cif_isp10_device *)platform_get_drvdata(pdev);
+ struct cif_isp10_v4l2_device *cif_isp10_v4l2_dev =
+ (struct cif_isp10_v4l2_device *)cif_isp10_dev->nodes;
+
+ if (IS_ERR_VALUE(cif_isp10_release(cif_isp10_dev,
+ CIF_ISP10_ALL_STREAMS)))
+ cif_isp10_pltfrm_pr_warn(cif_isp10_dev->dev,
+ "CIF power off failed\n");
+
+ video_unregister_device(&cif_isp10_v4l2_dev->node[SP_DEV].vdev);
+ video_unregister_device(&cif_isp10_v4l2_dev->node[MP_DEV].vdev);
+ video_unregister_device(&cif_isp10_v4l2_dev->node[DMA_DEV].vdev);
+ unregister_cifisp_device(&cif_isp10_v4l2_dev->node[ISP_DEV].vdev);
+ v4l2_device_unregister(&cif_isp10_dev->v4l2_dev);
+ cif_isp10_pltfrm_dev_release(&pdev->dev);
+ cif_isp10_destroy(cif_isp10_dev);
+
+ cif_isp10_v4l2_dev_cnt--;
+ return 0;
+}
+
+static int cif_isp10_v4l2_drv_suspend(struct platform_device *pdev,
+ pm_message_t state)
+{
+ int ret = 0;
+ struct cif_isp10_device *cif_isp10_dev =
+ (struct cif_isp10_device *)platform_get_drvdata(pdev);
+
+ cif_isp10_pltfrm_pr_dbg(cif_isp10_dev->dev, "\n");
+
+ ret = cif_isp10_suspend(cif_isp10_dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ cif_isp10_pltfrm_pinctrl_set_state(&pdev->dev,
+ CIF_ISP10_PINCTRL_STATE_SLEEP);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(cif_isp10_dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_v4l2_drv_resume(struct platform_device *pdev)
+{
+ int ret = 0;
+ struct cif_isp10_device *cif_isp10_dev =
+ (struct cif_isp10_device *)platform_get_drvdata(pdev);
+
+ cif_isp10_pltfrm_pr_dbg(cif_isp10_dev->dev, "\n");
+
+ if (!cif_isp10_dev->img_src) {
+ cif_isp10_pltfrm_pr_err(
+ cif_isp10_dev->dev,
+ "cif_isp10_dev img_src is null!\n");
+ goto err;
+ }
+
+ ret = cif_isp10_resume(cif_isp10_dev);
+ if (IS_ERR_VALUE(ret))
+ goto err;
+
+ cif_isp10_pltfrm_pinctrl_set_state(&pdev->dev,
+ CIF_ISP10_PINCTRL_STATE_DEFAULT);
+
+ return 0;
+err:
+ cif_isp10_pltfrm_pr_err(cif_isp10_dev->dev,
+ "failed with error %d\n", ret);
+ return ret;
+}
+
+static int cif_isp10_runtime_suspend(struct device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(dev, "\n");
+ return cif_isp10_pltfrm_pm_set_state(dev, CIF_ISP10_PM_STATE_SUSPENDED);
+}
+
+static int cif_isp10_runtime_resume(struct device *dev)
+{
+ cif_isp10_pltfrm_pr_dbg(dev, "\n");
+ return cif_isp10_pltfrm_pm_set_state(dev, CIF_ISP10_PM_STATE_SW_STNDBY);
+}
+
+static const struct dev_pm_ops cif_isp10_dev_pm_ops = {
+ SET_RUNTIME_PM_OPS(cif_isp10_runtime_suspend,
+ cif_isp10_runtime_resume, NULL)
+};
+
+static struct platform_driver cif_isp10_v4l2_plat_drv = {
+ .driver = {
+ .name = DRIVER_NAME,
+ .of_match_table = of_match_ptr(cif_isp10_v4l2_of_match),
+ .pm = &cif_isp10_dev_pm_ops,
+ },
+ .probe = cif_isp10_v4l2_drv_probe,
+ .remove = cif_isp10_v4l2_drv_remove,
+ .suspend = cif_isp10_v4l2_drv_suspend,
+ .resume = cif_isp10_v4l2_drv_resume,
+};
+
+/* ======================================================================== */
+static int cif_isp10_v4l2_init(void)
+{
+ int ret;
+
+ ret = platform_driver_register(&cif_isp10_v4l2_plat_drv);
+ if (ret) {
+ cif_isp10_pltfrm_pr_err(NULL,
+ "cannot register platform driver, failed with %d\n",
+ ret);
+ return -ENODEV;
+ }
+
+ return ret;
+}
+
+/* ======================================================================== */
+static void __exit cif_isp10_v4l2_exit(void)
+{
+ platform_driver_unregister(&cif_isp10_v4l2_plat_drv);
+}
+
+device_initcall_sync(cif_isp10_v4l2_init);
+module_exit(cif_isp10_v4l2_exit);
+
+MODULE_DESCRIPTION("V4L2 interface for CIF ISP10 driver");
+MODULE_AUTHOR("George");
+MODULE_LICENSE("GPL");
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+ #ifndef _CIF_ISP10_RK_VERSION_H_
+#define _CIF_ISP10_RK_VERSION_H_
+#include <linux/version.h>
+
+/*
+ * CIF DRIVER VERSION NOTE
+ *
+ *v0.1.0:
+ *1. New mi register update mode is invalidate in raw/jpeg for rk1108,
+ * All path used old mode for rk1108;
+ *v0.1.1:
+ *1. Modify CIF stop sequence for fix isp bus may dead when switch isp:
+ *Original stop sequence: Stop ISP(mipi) -> Stop ISP(isp) ->wait for ISP
+ *isp off -> Stop ISP(mi)
+ *Current stop sequence: ISP(mi) stop in mi frame end -> Stop ISP(mipi)
+ *-> Stop ISP(isp) ->wait for ISP isp off;
+ * Current stop sequence is only match sensor stream v-blanking >= 1.5ms;
+ *
+ *v0.1.2:
+ *1. Disable CIF_MIPI_ERR_DPHY interrupt here temporary for
+ *isp bus may be dead when switch isp;
+ *2. Cancel hw restart isp operation in mipi isr, only notice error log;
+ *
+ *v0.1.3:
+ *1. fix camerahal query exp info failed from cifisp_stat_buffer, because
+ *wake_up buffer before cif_isp11_sensor_mode_data_sync;
+ *
+ *v0.1.4:
+ *1. Disable DPHY errctrl interrupt, because this dphy erctrl signal
+ *is assert and until the next changes in line state. This time is may
+ *be too long and cpu is hold in this interrupt. Enable DPHY errctrl
+ *interrupt again, if mipi have receive the whole frame without any error.
+ *2. Modify mipi_dphy_cfg follow vendor recommended process in
+ *document.
+ *3. Select the limit dphy setting if sensor mipi datarate is overflow,
+ *and print warning information to user.
+ *
+ *v0.1.5:
+ *Exposure list must be queue operation, not stack. list_add switch to
+ *list_add_tail in cif_isp11_s_exp;
+ *
+ *v0.1.6:
+ *Add isp output size in struct isp_supplemental_sensor_mode_data.
+ *
+ */
+
+#define CONFIG_CIFISP10_DRIVER_VERSION KERNEL_VERSION(0, 1, 6)
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#ifndef _CIF_ISP10_PLATFORM_H
+#define _CIF_ISP10_PLATFORM_H
+#include <linux/videodev2.h>
+
+#define CIF_ISP10_SOC_RK3288 "rk3288"
+#define CIF_ISP10_SOC_RK3368 "rk3368"
+#define CIF_ISP10_SOC_RK3399 "rk3399"
+
+#define DRIVER_NAME "rkisp10"
+#define ISP_VDEV_NAME DRIVER_NAME "_ispdev"
+#define SP_VDEV_NAME DRIVER_NAME "_selfpath"
+#define MP_VDEV_NAME DRIVER_NAME "_mainpath"
+#define DMA_VDEV_NAME DRIVER_NAME "_dmapath"
+
+enum pltfrm_cam_signal_polarity {
+ PLTFRM_CAM_SIGNAL_HIGH_LEVEL = 0,
+ PLTFRM_CAM_SIGNAL_LOW_LEVEL = 1,
+};
+
+enum pltfrm_cam_sample_type {
+ PLTFRM_CAM_SDR_NEG_EDG = 0x10000001,
+ PLTFRM_CAM_SDR_POS_EDG = 0x10000002,
+ PLTFRM_CAM_DDR = 0x20000000
+};
+
+enum pltfrm_cam_itf_type {
+ PLTFRM_CAM_ITF_MIPI = 0x10000000,
+ PLTFRM_CAM_ITF_BT601_8 = 0x20000071,
+ PLTFRM_CAM_ITF_BT656_8 = 0x20000072,
+ PLTFRM_CAM_ITF_BT601_10 = 0x20000091,
+ PLTFRM_CAM_ITF_BT656_10 = 0x20000092,
+ PLTFRM_CAM_ITF_BT601_12 = 0x200000B1,
+ PLTFRM_CAM_ITF_BT656_12 = 0x200000B2,
+ PLTFRM_CAM_ITF_BT601_16 = 0x200000F1,
+ PLTFRM_CAM_ITF_BT656_16 = 0x200000F2
+};
+
+#define PLTFRM_CAM_ITF_MAIN_MASK 0xf0000000
+#define PLTFRM_CAM_ITF_SUB_MASK 0x0000000f
+#define PLTFRM_CAM_ITF_DVP_BW_MASK 0x000000f0
+
+#define PLTFRM_CAM_ITF_IS_MIPI(a) \
+ (((a) & PLTFRM_CAM_ITF_MAIN_MASK) == 0x10000000)
+#define PLTFRM_CAM_ITF_IS_DVP(a) \
+ (((a) & PLTFRM_CAM_ITF_MAIN_MASK) == 0x20000000)
+#define PLTFRM_CAM_ITF_IS_BT656(a) (PLTFRM_CAM_ITF_IS_DVP(a) &&\
+ (((a) & PLTFRM_CAM_ITF_SUB_MASK) == 0x02))
+#define PLTFRM_CAM_ITF_IS_BT601(a) (PLTFRM_CAM_ITF_IS_DVP(a) &&\
+ (((a) & PLTFRM_CAM_ITF_SUB_MASK) == 0x01))
+#define PLTFRM_CAM_ITF_DVP_BW(a) \
+ ((((a) & PLTFRM_CAM_ITF_DVP_BW_MASK) >> 4) + 1)
+
+struct pltfrm_cam_mipi_config {
+ u32 dphy_index;
+ u32 vc;
+ u32 nb_lanes;
+ u32 bit_rate;
+};
+
+struct pltfrm_cam_dvp_config {
+ enum pltfrm_cam_signal_polarity vsync;
+ enum pltfrm_cam_signal_polarity hsync;
+ enum pltfrm_cam_sample_type pclk;
+};
+
+struct pltfrm_cam_itf {
+ enum pltfrm_cam_itf_type type;
+
+ union {
+ struct pltfrm_cam_mipi_config mipi;
+ struct pltfrm_cam_dvp_config dvp;
+ } cfg;
+ unsigned int mclk_hz;
+};
+
+#define PLTFRM_CAM_ITF_MIPI_CFG(v, nb, br, mk)\
+ .itf_cfg = {\
+ .type = PLTFRM_CAM_ITF_MIPI,\
+ .cfg = {\
+ .mipi = {\
+ .dphy_index = 0,\
+ .vc = v,\
+ .nb_lanes = nb,\
+ .bit_rate = br,\
+ } \
+ },\
+ .mclk_hz = mk\
+ }
+#define PLTFRM_CAM_ITF_DVP_CFG(ty, vs, hs, ck, mk)\
+ .itf_cfg = {\
+ .type = ty,\
+ .cfg = {\
+ .dvp = {\
+ .vsync = vs,\
+ .hsync = hs,\
+ .pclk = ck,\
+ } \
+ },\
+ .mclk_hz = mk\
+ }
+
+#define PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE 0x00
+#define PLTFRM_CIFCAM_G_ITF_CFG \
+ (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 1)
+#define PLTFRM_CIFCAM_G_DEFRECT \
+ (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 2)
+#define PLTFRM_CIFCAM_ATTACH \
+ (PLTFRM_CIFCAM_IOCTL_INTERNAL_BASE + 3)
+
+struct pltfrm_cam_defrect {
+ unsigned int width;
+ unsigned int height;
+ struct v4l2_rect defrect;
+};
+
+enum pltfrm_soc_cfg_cmd {
+ PLTFRM_MCLK_CFG = 0,
+ PLTFRM_MIPI_DPHY_CFG,
+
+ PLTFRM_CLKEN,
+ PLTFRM_CLKDIS,
+ PLTFRM_CLKRST,
+
+ PLTFRM_SOC_INIT
+};
+
+enum pltfrm_soc_io_voltage {
+ PLTFRM_IO_1V8 = 0,
+ PLTFRM_IO_3V3 = 1
+};
+
+enum pltfrm_soc_drv_strength {
+ PLTFRM_DRV_STRENGTH_0 = 0,
+ PLTFRM_DRV_STRENGTH_1 = 1,
+ PLTFRM_DRV_STRENGTH_2 = 2,
+ PLTFRM_DRV_STRENGTH_3 = 3
+
+};
+
+struct pltfrm_soc_init_para {
+ struct platform_device *pdev;
+ void __iomem *isp_base;
+};
+
+struct pltfrm_soc_mclk_para {
+ enum pltfrm_soc_io_voltage io_voltage;
+ enum pltfrm_soc_drv_strength drv_strength;
+};
+
+struct pltfrm_soc_cfg_para {
+ enum pltfrm_soc_cfg_cmd cmd;
+ void *cfg_para;
+};
+
+struct pltfrm_soc_cfg {
+ char name[32];
+ int (*soc_cfg)(struct pltfrm_soc_cfg_para *cfg);
+};
+
+int pltfrm_rk3288_cfg(
+ struct pltfrm_soc_cfg_para *cfg);
+int pltfrm_rk3399_cfg(
+ struct pltfrm_soc_cfg_para *cfg);
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef PLATFORM_CAMERA_MODULE_H
+#define PLATFORM_CAMERA_MODULE_H
+#include <linux/videodev2.h>
+
+#define PLTFRM_CAMERA_MODULE_REG_TYPE_DATA 0
+#define PLTFRM_CAMERA_MODULE_REG_TYPE_TIMEOUT 1
+
+extern const char *PLTFRM_CAMERA_MODULE_PIN_PD;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_PWR;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_FLASH;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_TORCH;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_RESET;
+extern const char *PLTFRM_CAMERA_MODULE_PIN_VSYNC;
+
+enum pltfrm_camera_module_pin_state {
+ PLTFRM_CAMERA_MODULE_PIN_STATE_INACTIVE = 0,
+ PLTFRM_CAMERA_MODULE_PIN_STATE_ACTIVE = 1
+};
+
+struct pltfrm_camera_module_reg {
+ u32 flag;
+ u16 reg;
+ u16 val;
+};
+
+struct pltfrm_camera_module_reg_table {
+ u32 reg_table_num_entries;
+ struct pltfrm_camera_module_reg *reg_table;
+};
+
+int pltfrm_camera_module_set_pm_state(
+ struct v4l2_subdev *sd,
+ int on);
+
+int pltfrm_camera_module_set_pin_state(
+ struct v4l2_subdev *sd,
+ const char *pin,
+ enum pltfrm_camera_module_pin_state state);
+
+int pltfrm_camera_module_get_pin_state(
+ struct v4l2_subdev *sd,
+ const char *pin);
+
+int pltfrm_camera_module_s_power(
+ struct v4l2_subdev *sd,
+ int on);
+
+int pltfrm_camera_module_patch_config(
+ struct v4l2_subdev *sd,
+ struct v4l2_mbus_framefmt *frm_fmt,
+ struct v4l2_subdev_frame_interval *frm_intrvl);
+
+struct v4l2_subdev *pltfrm_camera_module_get_af_ctrl(
+ struct v4l2_subdev *sd);
+
+struct v4l2_subdev *pltfrm_camera_module_get_fl_ctrl(
+ struct v4l2_subdev *sd);
+
+char *pltfrm_camera_module_get_flash_driver_name(
+ struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_init(
+ struct v4l2_subdev *sd,
+ void **pldata);
+
+void pltfrm_camera_module_release(
+ struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_read_reg(struct v4l2_subdev *sd,
+ u16 data_length,
+ u16 reg,
+ u32 *val);
+
+int pltfrm_superpix_camera_module_read_reg(struct v4l2_subdev *sd,
+ u16 data_length,
+ u8 reg,
+ u8 *val);
+
+int pltfrm_camera_module_write_reg(struct v4l2_subdev *sd,
+ u16 reg, u8 val);
+
+int pltfrm_camera_module_write_reglist(
+ struct v4l2_subdev *sd,
+ const struct pltfrm_camera_module_reg reglist[],
+ int len);
+
+long pltfrm_camera_module_ioctl(struct v4l2_subdev *sd,
+ unsigned int cmd,
+ void *arg);
+
+const char *pltfrm_dev_string(struct v4l2_subdev *sd);
+
+int pltfrm_camera_module_get_flip_mirror(
+ struct v4l2_subdev *sd);
+
+#define pltfrm_camera_module_pr_debug(dev, fmt, arg...) \
+ pr_debug("%s.%s: " fmt, \
+ pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_info(dev, fmt, arg...) \
+ pr_info("%s.%s: " fmt, \
+ pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_warn(dev, fmt, arg...) \
+ pr_warn("%s.%s WARN: " fmt, \
+ pltfrm_dev_string(dev), __func__, ## arg)
+#define pltfrm_camera_module_pr_err(dev, fmt, arg...) \
+ pr_err("%s.%s(%d) ERR: " fmt, \
+ pltfrm_dev_string(dev), __func__, __LINE__, \
+ ## arg)
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#ifndef _RK_ISP11_CONFIG_H
+#define _RK_ISP11_CONFIG_H
+
+#include <media/v4l2-config_rockchip.h>
+
+#define CIFISP_MODULE_DPCC BIT(0)
+#define CIFISP_MODULE_BLS BIT(1)
+#define CIFISP_MODULE_SDG BIT(2)
+#define CIFISP_MODULE_HST BIT(3)
+#define CIFISP_MODULE_LSC BIT(4)
+#define CIFISP_MODULE_AWB_GAIN BIT(5)
+#define CIFISP_MODULE_FLT BIT(6)
+#define CIFISP_MODULE_BDM BIT(7)
+#define CIFISP_MODULE_CTK BIT(8)
+#define CIFISP_MODULE_GOC BIT(9)
+#define CIFISP_MODULE_CPROC BIT(10)
+#define CIFISP_MODULE_AFC BIT(11)
+#define CIFISP_MODULE_AWB BIT(12)
+#define CIFISP_MODULE_IE BIT(13)
+#define CIFISP_MODULE_AEC BIT(14)
+#define CIFISP_MODULE_WDR BIT(15)
+#define CIFISP_MODULE_DPF BIT(16)
+#define CIFISP_MODULE_DPF_STRENGTH BIT(17)
+
+#define CIFISP_CTK_COEFF_MAX 0x100
+#define CIFISP_CTK_OFFSET_MAX 0x800
+
+#define CIFISP_AE_MEAN_MAX 25
+#define CIFISP_HIST_BIN_N_MAX 16
+#define CIFISP_AFM_MAX_WINDOWS 3
+#define CIFISP_DEGAMMA_CURVE_SIZE 17
+
+#define CIFISP_BDM_MAX_TH 0xFF
+
+/* maximum value for horizontal start address */
+#define CIFISP_BLS_START_H_MAX (0x00000FFF)
+/* maximum value for horizontal stop address */
+#define CIFISP_BLS_STOP_H_MAX (0x00000FFF)
+/* maximum value for vertical start address */
+#define CIFISP_BLS_START_V_MAX (0x00000FFF)
+/* maximum value for vertical stop address */
+#define CIFISP_BLS_STOP_V_MAX (0x00000FFF)
+/* maximum is 2^18 = 262144*/
+#define CIFISP_BLS_SAMPLES_MAX (0x00000012)
+/* maximum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MAX (0x00000FFF)
+/* minimum value for fixed black level */
+#define CIFISP_BLS_FIX_SUB_MIN (0xFFFFF000)
+/* 13 bit range (signed)*/
+#define CIFISP_BLS_FIX_MASK (0x00001FFF)
+/* AWB */
+#define CIFISP_AWB_MAX_GRID 1
+#define CIFISP_AWB_MAX_FRAMES 7
+
+/* Gamma out*/
+/* Maximum number of color samples supported */
+#define CIFISP_GAMMA_OUT_MAX_SAMPLES 17
+
+/* LSC */
+#define CIFISP_LSC_GRAD_TBL_SIZE 8
+#define CIFISP_LSC_SIZE_TBL_SIZE 8
+/*
+ * The following matches the tuning process,
+ * not the max capabilities of the chip.
+ */
+#define CIFISP_LSC_DATA_TBL_SIZE 289
+/* HIST */
+#define CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE 25
+
+/* DPCC */
+#define CIFISP_DPCC_METHODS_MAX (3)
+
+/* DPF */
+#define CIFISP_DPF_MAX_NLF_COEFFS 17
+#define CIFISP_DPF_MAX_SPATIAL_COEFFS 6
+
+#define CIFISP_STAT_AWB BIT(0)
+#define CIFISP_STAT_AUTOEXP BIT(1)
+#define CIFISP_STAT_AFM_FIN BIT(2)
+#define CIFISP_STAT_HIST BIT(3)
+
+enum cifisp_histogram_mode {
+ CIFISP_HISTOGRAM_MODE_DISABLE = 0,
+ CIFISP_HISTOGRAM_MODE_RGB_COMBINED = 1,
+ CIFISP_HISTOGRAM_MODE_R_HISTOGRAM = 2,
+ CIFISP_HISTOGRAM_MODE_G_HISTOGRAM = 3,
+ CIFISP_HISTOGRAM_MODE_B_HISTOGRAM = 4,
+ CIFISP_HISTOGRAM_MODE_Y_HISTOGRAM = 5
+};
+
+enum cifisp_exp_ctrl_autostop {
+ CIFISP_EXP_CTRL_AUTOSTOP_0 = 0,
+ CIFISP_EXP_CTRL_AUTOSTOP_1 = 1
+};
+
+enum cifisp_exp_meas_mode {
+/* < Y = 16 + 0.25R + 0.5G + 0.1094B */
+ CIFISP_EXP_MEASURING_MODE_0 = 0,
+/* < Y = (R + G + B) x (85/256) */
+ CIFISP_EXP_MEASURING_MODE_1 = 1,
+};
+
+struct cifisp_window {
+ unsigned short h_offs;
+ unsigned short v_offs;
+ unsigned short h_size;
+ unsigned short v_size;
+};
+
+enum cifisp_awb_mode_type {
+ CIFISP_AWB_MODE_MANUAL = 0,
+ CIFISP_AWB_MODE_RGB = 1,
+ CIFISP_AWB_MODE_YCBCR = 2
+};
+
+enum cifisp_bls_win_enable {
+ ISP_BLS_CTRL_WINDOW_ENABLE_0 = 0,
+ ISP_BLS_CTRL_WINDOW_ENABLE_1 = 1,
+ ISP_BLS_CTRL_WINDOW_ENABLE_2 = 2,
+ ISP_BLS_CTRL_WINDOW_ENABLE_3 = 3
+};
+
+enum cifisp_flt_mode {
+ CIFISP_FLT_STATIC_MODE,
+ CIFISP_FLT_DYNAMIC_MODE
+};
+
+struct cifisp_awb_meas {
+ unsigned int cnt;
+ unsigned char mean_y;
+ unsigned char mean_cb;
+ unsigned char mean_cr;
+ unsigned short mean_r;
+ unsigned short mean_b;
+ unsigned short mean_g;
+};
+
+struct cifisp_awb_stat {
+ struct cifisp_awb_meas awb_mean[CIFISP_AWB_MAX_GRID];
+};
+
+struct cifisp_hist_stat {
+ unsigned short hist_bins[CIFISP_HIST_BIN_N_MAX];
+};
+
+/*! BLS mean measured values */
+struct cifisp_bls_meas_val {
+ /*! Mean measured value for Bayer pattern R.*/
+ unsigned short meas_r;
+ /*! Mean measured value for Bayer pattern Gr.*/
+ unsigned short meas_gr;
+ /*! Mean measured value for Bayer pattern Gb.*/
+ unsigned short meas_gb;
+ /*! Mean measured value for Bayer pattern B.*/
+ unsigned short meas_b;
+};
+
+/*
+ * BLS fixed subtraction values. The values will be subtracted from the sensor
+ * values. Therefore a negative value means addition instead of subtraction!
+ */
+struct cifisp_bls_fixed_val {
+ /*! Fixed (signed!) subtraction value for Bayer pattern R. */
+ signed short r;
+ /*! Fixed (signed!) subtraction value for Bayer pattern Gr. */
+ signed short gr;
+ /*! Fixed (signed!) subtraction value for Bayer pattern Gb. */
+ signed short gb;
+ /*! Fixed (signed!) subtraction value for Bayer pattern B. */
+ signed short b;
+};
+
+/* Configuration used by black level subtraction */
+struct cifisp_bls_config {
+ /*
+ * Automatic mode activated means that the measured values
+ * are subtracted.Otherwise the fixed subtraction
+ * values will be subtracted.
+ */
+ bool enable_auto;
+ unsigned char en_windows;
+ struct cifisp_window bls_window1; /* < Measurement window 1. */
+ struct cifisp_window bls_window2; /* !< Measurement window 2 */
+ /*
+ * Set amount of measured pixels for each Bayer position
+ * (A, B,C and D) to 2^bls_samples.
+ */
+ unsigned char bls_samples;
+ /* !< Fixed subtraction values. */
+ struct cifisp_bls_fixed_val fixed_val;
+};
+
+struct cifisp_ae_stat {
+ unsigned char exp_mean[CIFISP_AE_MEAN_MAX];
+ struct cifisp_bls_meas_val bls_val; /* available wit exposure results */
+};
+
+struct cifisp_af_meas_val {
+ unsigned int sum;
+ unsigned int lum;
+};
+
+struct cifisp_af_stat {
+ struct cifisp_af_meas_val window[CIFISP_AFM_MAX_WINDOWS];
+};
+
+struct cifisp_stat {
+ struct cifisp_awb_stat awb;
+ struct cifisp_ae_stat ae;
+ struct cifisp_af_stat af;
+ struct cifisp_hist_stat hist;
+};
+
+struct cifisp_stat_buffer {
+ unsigned int meas_type;
+ struct cifisp_stat params;
+ struct isp_supplemental_sensor_mode_data sensor_mode;
+};
+
+struct cifisp_dpcc_methods_config {
+ unsigned int method;
+ unsigned int line_thresh;
+ unsigned int line_mad_fac;
+ unsigned int pg_fac;
+ unsigned int rnd_thresh;
+ unsigned int rg_fac;
+};
+
+struct cifisp_dpcc_config {
+ unsigned int mode;
+ unsigned int output_mode;
+ unsigned int set_use;
+ struct cifisp_dpcc_methods_config methods[CIFISP_DPCC_METHODS_MAX];
+ unsigned int ro_limits;
+ unsigned int rnd_offs;
+};
+
+struct cifisp_gamma_corr_curve {
+ unsigned short gamma_y[CIFISP_DEGAMMA_CURVE_SIZE];
+};
+
+struct cifisp_gamma_curve_x_axis_pnts {
+ unsigned int gamma_dx0;
+ unsigned int gamma_dx1;
+};
+
+/* Configuration used by sensor degamma */
+struct cifisp_sdg_config {
+ struct cifisp_gamma_corr_curve curve_r;
+ struct cifisp_gamma_corr_curve curve_g;
+ struct cifisp_gamma_corr_curve curve_b;
+ struct cifisp_gamma_curve_x_axis_pnts xa_pnts;
+};
+
+/* Configuration used by Lens shading correction */
+struct cifisp_lsc_config {
+ unsigned int r_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+ unsigned int gr_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+ unsigned int gb_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+ unsigned int b_data_tbl[CIFISP_LSC_DATA_TBL_SIZE];
+
+ unsigned int x_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
+ unsigned int y_grad_tbl[CIFISP_LSC_GRAD_TBL_SIZE];
+
+ unsigned int x_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
+ unsigned int y_size_tbl[CIFISP_LSC_SIZE_TBL_SIZE];
+ unsigned short config_width;
+ unsigned short config_height;
+};
+
+struct cifisp_ie_config {
+ enum v4l2_colorfx effect;
+ unsigned short color_sel;
+ /* 3x3 Matrix Coefficients for Emboss Effect 1 */
+ unsigned short eff_mat_1;
+ /* 3x3 Matrix Coefficients for Emboss Effect 2 */
+ unsigned short eff_mat_2;
+ /* 3x3 Matrix Coefficients for Emboss 3/Sketch 1 */
+ unsigned short eff_mat_3;
+ /* 3x3 Matrix Coefficients for Sketch Effect 2 */
+ unsigned short eff_mat_4;
+ /* 3x3 Matrix Coefficients for Sketch Effect 3 */
+ unsigned short eff_mat_5;
+ /* Chrominance increment values of tint (used for sepia effect) */
+ unsigned short eff_tint;
+};
+
+/* Configuration used by auto white balance */
+struct cifisp_awb_meas_config {
+ /*
+ * white balance measurement window (in pixels)
+ * Note: currently the h and v offsets are mapped to grid offsets
+ */
+ struct cifisp_window awb_wnd;
+ enum cifisp_awb_mode_type awb_mode;
+ /*
+ * only pixels values < max_y contribute to awb measurement
+ * (set to 0 to disable this feature)
+ */
+ unsigned char max_y;
+ /* only pixels values > min_y contribute to awb measurement */
+ unsigned char min_y;
+ /*
+ * Chrominance sum maximum value, only consider pixels with Cb+Cr
+ * smaller than threshold for awb measurements
+ */
+ unsigned char max_csum;
+ /*
+ * Chrominance minimum value, only consider pixels with Cb/Cr
+ * each greater than threshold value for awb measurements
+ */
+ unsigned char min_c;
+ /*
+ * number of frames - 1 used for mean value calculation
+ * (ucFrames=0 means 1 Frame)
+ */
+ unsigned char frames;
+ /* reference Cr value for AWB regulation, target for AWB */
+ unsigned char awb_ref_cr;
+ /* reference Cb value for AWB regulation, target for AWB */
+ unsigned char awb_ref_cb;
+ bool enable_ymax_cmp;
+};
+
+struct cifisp_awb_gain_config {
+ unsigned short gain_red;
+ unsigned short gain_green_r;
+ unsigned short gain_blue;
+ unsigned short gain_green_b;
+};
+
+/* Configuration used by ISP filtering */
+struct cifisp_flt_config {
+ enum cifisp_flt_mode mode; /* ISP_FILT_MODE register fields */
+ unsigned char grn_stage1; /* ISP_FILT_MODE register fields */
+ unsigned char chr_h_mode; /* ISP_FILT_MODE register fields */
+ unsigned char chr_v_mode; /* ISP_FILT_MODE register fields */
+ unsigned int thresh_bl0;
+ unsigned int thresh_bl1;
+ unsigned int thresh_sh0;
+ unsigned int thresh_sh1;
+ unsigned int lum_weight;
+ unsigned int fac_sh1;
+ unsigned int fac_sh0;
+ unsigned int fac_mid;
+ unsigned int fac_bl0;
+ unsigned int fac_bl1;
+};
+
+/* Configuration used by Bayer DeMosaic */
+struct cifisp_bdm_config {
+ unsigned char demosaic_th;
+};
+
+/* Configuration used by Cross Talk correction */
+struct cifisp_ctk_config {
+ unsigned short coeff0;
+ unsigned short coeff1;
+ unsigned short coeff2;
+ unsigned short coeff3;
+ unsigned short coeff4;
+ unsigned short coeff5;
+ unsigned short coeff6;
+ unsigned short coeff7;
+ unsigned short coeff8;
+ /* offset for the crosstalk correction matrix */
+ unsigned short ct_offset_r;
+ unsigned short ct_offset_g;
+ unsigned short ct_offset_b;
+};
+
+enum cifisp_goc_mode {
+ CIFISP_GOC_MODE_LOGARITHMIC,
+ CIFISP_GOC_MODE_EQUIDISTANT
+};
+
+/* Configuration used by Gamma Out correction */
+struct cifisp_goc_config {
+ enum cifisp_goc_mode mode;
+ unsigned short gamma_y[CIFISP_GAMMA_OUT_MAX_SAMPLES];
+};
+
+/* CCM (Color Correction) */
+struct cifisp_cproc_config {
+ unsigned char c_out_range;
+ unsigned char y_in_range;
+ unsigned char y_out_range;
+ unsigned char contrast;
+ unsigned char brightness;
+ unsigned char sat;
+ unsigned char hue;
+};
+
+/* Configuration used by Histogram */
+struct cifisp_hst_config {
+ enum cifisp_histogram_mode mode;
+ unsigned char histogram_predivider;
+ struct cifisp_window meas_window;
+ unsigned char hist_weight[CIFISP_HISTOGRAM_WEIGHT_GRIDS_SIZE];
+};
+
+/* Configuration used by Auto Exposure Control */
+struct cifisp_aec_config {
+ enum cifisp_exp_meas_mode mode;
+ enum cifisp_exp_ctrl_autostop autostop;
+ struct cifisp_window meas_window;
+};
+
+struct cifisp_afc_config {
+ unsigned char num_afm_win; /* max CIFISP_AFM_MAX_WINDOWS */
+ struct cifisp_window afm_win[CIFISP_AFM_MAX_WINDOWS];
+ unsigned int thres;
+ unsigned int var_shift;
+};
+
+enum cifisp_dpf_gain_usage {
+/* don't use any gains in preprocessing stage */
+ CIFISP_DPF_GAIN_USAGE_DISABLED = 1,
+/* use only the noise function gains from registers DPF_NF_GAIN_R, ... */
+ CIFISP_DPF_GAIN_USAGE_NF_GAINS = 2,
+/* use only the gains from LSC module */
+ CIFISP_DPF_GAIN_USAGE_LSC_GAINS = 3,
+/* use the moise function gains and the gains from LSC module */
+ CIFISP_DPF_GAIN_USAGE_NF_LSC_GAINS = 4,
+/* use only the gains from AWB module */
+ CIFISP_DPF_GAIN_USAGE_AWB_GAINS = 5,
+/* use the gains from AWB and LSC module */
+ CIFISP_DPF_GAIN_USAGE_AWB_LSC_GAINS = 6,
+/* upper border (only for an internal evaluation) */
+ CIFISP_DPF_GAIN_USAGE_MAX
+};
+
+enum cifisp_dpf_rb_filtersize {
+/* red and blue filter kernel size 13x9 (means 7x5 active pixel) */
+ CIFISP_DPF_RB_FILTERSIZE_13x9 = 0,
+/* red and blue filter kernel size 9x9 (means 5x5 active pixel) */
+ CIFISP_DPF_RB_FILTERSIZE_9x9 = 1,
+};
+
+enum cifisp_dpf_nll_scale_mode {
+/* use a linear scaling */
+ CIFISP_NLL_SCALE_LINEAR = 0,
+/* use a logarithmic scaling */
+ CIFISP_NLL_SCALE_LOGARITHMIC = 1,
+};
+
+struct cifisp_dpf_nll {
+ unsigned short coeff[CIFISP_DPF_MAX_NLF_COEFFS];
+ enum cifisp_dpf_nll_scale_mode scale_mode;
+};
+
+struct cifisp_dpf_rb_flt {
+ enum cifisp_dpf_rb_filtersize fltsize;
+ unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
+ bool r_enable;
+ bool b_enable;
+};
+
+struct cifisp_dpf_g_flt {
+ unsigned char spatial_coeff[CIFISP_DPF_MAX_SPATIAL_COEFFS];
+ bool gr_enable;
+ bool gb_enable;
+};
+
+struct cifisp_dpf_gain {
+ enum cifisp_dpf_gain_usage mode;
+ unsigned short nf_r_gain;
+ unsigned short nf_b_gain;
+ unsigned short nf_gr_gain;
+ unsigned short nf_gb_gain;
+};
+
+struct cifisp_dpf_config {
+ struct cifisp_dpf_gain gain;
+ struct cifisp_dpf_g_flt g_flt;
+ struct cifisp_dpf_rb_flt rb_flt;
+ struct cifisp_dpf_nll nll;
+};
+
+struct cifisp_dpf_strength_config {
+ unsigned char r;
+ unsigned char g;
+ unsigned char b;
+};
+
+struct cifisp_last_capture_config {
+ struct cifisp_cproc_config cproc;
+ struct cifisp_goc_config goc;
+ struct cifisp_ctk_config ctk;
+ struct cifisp_bdm_config bdm;
+ struct cifisp_flt_config flt;
+ struct cifisp_awb_gain_config awb_gain;
+ struct cifisp_awb_meas_config awb_meas;
+ struct cifisp_lsc_config lsc;
+ struct cifisp_sdg_config sdg;
+ struct cifisp_bls_config bls;
+};
+
+struct cifisp_isp_other_cfg {
+ unsigned int s_frame_id;/* Set isp hardware frame id */
+
+ unsigned int module_ens;
+
+ struct cifisp_dpcc_config dpcc_config;
+ struct cifisp_bls_config bls_config;
+ struct cifisp_sdg_config sdg_config;
+ struct cifisp_lsc_config lsc_config;
+ struct cifisp_awb_gain_config awb_gain_config;
+ struct cifisp_flt_config flt_config;
+ struct cifisp_bdm_config bdm_config;
+ struct cifisp_ctk_config ctk_config;
+ struct cifisp_goc_config goc_config;
+ struct cifisp_cproc_config cproc_config;
+ struct cifisp_ie_config ie_config;
+ struct cifisp_dpf_config dpf_config;
+ struct cifisp_dpf_strength_config dpf_strength_config;
+};
+
+struct cifisp_isp_meas_cfg {
+ unsigned int s_frame_id; /* Set isp hardware frame id */
+
+ unsigned int module_ens;
+
+ struct cifisp_awb_meas_config awb_meas_config;
+ struct cifisp_hst_config hst_config;
+ struct cifisp_aec_config aec_config;
+ struct cifisp_afc_config afc_config;
+};
+
+struct cifisp_isp_metadata {
+ struct cifisp_isp_other_cfg other_cfg;
+ struct cifisp_isp_meas_cfg meas_cfg;
+ struct cifisp_stat_buffer meas_stat;
+};
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+#include <linux/v4l2-controls.h>
+#include <media/rk-isp10-config.h>
+#include <media/v4l2-controls_rockchip.h>
+
+#ifndef _RK_ISP10_IOCTL_H
+#define _RK_ISP10_IOCTL_H
+
+/* Private IOCTLs */
+/* DPCC */
+#define CIFISP_IOC_G_DPCC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 0, struct cifisp_dpcc_config)
+#define CIFISP_IOC_S_DPCC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 1, struct cifisp_dpcc_config)
+/* Black Level Subtraction */
+#define CIFISP_IOC_G_BLS \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 2, struct cifisp_bls_config)
+#define CIFISP_IOC_S_BLS \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 3, struct cifisp_bls_config)
+/* Sensor DeGamma */
+#define CIFISP_IOC_G_SDG \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 4, struct cifisp_sdg_config)
+#define CIFISP_IOC_S_SDG \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 5, struct cifisp_sdg_config)
+/* Lens Shading Correction */
+#define CIFISP_IOC_G_LSC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 6, struct cifisp_lsc_config)
+#define CIFISP_IOC_S_LSC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 7, struct cifisp_lsc_config)
+/* Auto White Balance */
+#define CIFISP_IOC_G_AWB_MEAS \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 8, struct cifisp_awb_meas_config)
+#define CIFISP_IOC_S_AWB_MEAS \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 9, struct cifisp_awb_meas_config)
+/* ISP Filtering( Sharpening & Noise reduction */
+#define CIFISP_IOC_G_FLT \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 10, struct cifisp_flt_config)
+#define CIFISP_IOC_S_FLT \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 11, struct cifisp_flt_config)
+/* Bayer Demosaic */
+#define CIFISP_IOC_G_BDM \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 12, struct cifisp_bdm_config)
+#define CIFISP_IOC_S_BDM \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 13, struct cifisp_bdm_config)
+/* Cross Talk correction */
+#define CIFISP_IOC_G_CTK \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 14, struct cifisp_ctk_config)
+#define CIFISP_IOC_S_CTK \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 15, struct cifisp_ctk_config)
+/* Gamma Out Correction */
+#define CIFISP_IOC_G_GOC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 16, struct cifisp_goc_config)
+#define CIFISP_IOC_S_GOC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 17, struct cifisp_goc_config)
+/* Histogram Measurement */
+#define CIFISP_IOC_G_HST \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 18, struct cifisp_hst_config)
+#define CIFISP_IOC_S_HST \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 19, struct cifisp_hst_config)
+/* Auto Exposure Measurements */
+#define CIFISP_IOC_G_AEC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 20, struct cifisp_aec_config)
+#define CIFISP_IOC_S_AEC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 21, struct cifisp_aec_config)
+#define CIFISP_IOC_G_BPL \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 22, struct cifisp_aec_config)
+#define CIFISP_IOC_G_AWB_GAIN \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 23, struct cifisp_awb_gain_config)
+#define CIFISP_IOC_S_AWB_GAIN \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 24, struct cifisp_awb_gain_config)
+#define CIFISP_IOC_G_CPROC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 25, struct cifisp_cproc_config)
+#define CIFISP_IOC_S_CPROC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 26, struct cifisp_cproc_config)
+#define CIFISP_IOC_G_AFC \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 27, struct cifisp_afc_config)
+#define CIFISP_IOC_S_AFC \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 28, struct cifisp_afc_config)
+#define CIFISP_IOC_G_IE \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 29, struct cifisp_ie_config)
+#define CIFISP_IOC_S_IE \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 30, struct cifisp_ie_config)
+#define CIFISP_IOC_G_DPF \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 31, struct cifisp_dpf_config)
+#define CIFISP_IOC_S_DPF \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 32, struct cifisp_dpf_config)
+#define CIFISP_IOC_G_DPF_STRENGTH \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 33, struct cifisp_dpf_strength_config)
+#define CIFISP_IOC_S_DPF_STRENGTH \
+ _IOW('v', BASE_VIDIOC_PRIVATE + 34, struct cifisp_dpf_strength_config)
+#define CIFISP_IOC_G_LAST_CONFIG \
+ _IOR('v', BASE_VIDIOC_PRIVATE + 35, struct cifisp_last_capture_config)
+
+/* CIF-ISP Private control IDs */
+#define V4L2_CID_CIFISP_DPCC (V4L2_CID_PRIVATE_BASE + 0)
+#define V4L2_CID_CIFISP_BLS (V4L2_CID_PRIVATE_BASE + 1)
+#define V4L2_CID_CIFISP_SDG (V4L2_CID_PRIVATE_BASE + 2)
+#define V4L2_CID_CIFISP_LSC (V4L2_CID_PRIVATE_BASE + 3)
+#define V4L2_CID_CIFISP_AWB_MEAS (V4L2_CID_PRIVATE_BASE + 4)
+#define V4L2_CID_CIFISP_FLT (V4L2_CID_PRIVATE_BASE + 5)
+#define V4L2_CID_CIFISP_BDM (V4L2_CID_PRIVATE_BASE + 6)
+#define V4L2_CID_CIFISP_CTK (V4L2_CID_PRIVATE_BASE + 7)
+#define V4L2_CID_CIFISP_GOC (V4L2_CID_PRIVATE_BASE + 8)
+#define V4L2_CID_CIFISP_HST (V4L2_CID_PRIVATE_BASE + 9)
+#define V4L2_CID_CIFISP_AEC (V4L2_CID_PRIVATE_BASE + 10)
+#define V4L2_CID_CIFISP_AWB_GAIN (V4L2_CID_PRIVATE_BASE + 11)
+#define V4L2_CID_CIFISP_CPROC (V4L2_CID_PRIVATE_BASE + 12)
+#define V4L2_CID_CIFISP_AFC (V4L2_CID_PRIVATE_BASE + 13)
+#define V4L2_CID_CIFISP_IE (V4L2_CID_PRIVATE_BASE + 14)
+#define V4L2_CID_CIFISP_DPF (V4L2_CID_PRIVATE_BASE + 15)
+
+/* Camera Sensors' running modes */
+#define CI_MODE_PREVIEW 0x8000
+#define CI_MODE_VIDEO 0x4000
+#define CI_MODE_STILL_CAPTURE 0x2000
+#define CI_MODE_CONTINUOUS 0x1000
+#define CI_MODE_NONE 0x0000
+
+#endif
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _V4L2_CONFIG_ROCKCHIP_H
+#define _V4L2_CONFIG_ROCKCHIP_H
+
+#define CAMERA_STRLEN 32
+#define CAMERA_METADATA_LEN (2 * PAGE_SIZE)
+
+/* Sensor resolution specific data for AE calculation.*/
+struct isp_supplemental_sensor_mode_data {
+ unsigned int coarse_integration_time_min;
+ unsigned int coarse_integration_time_max_margin;
+ unsigned int fine_integration_time_min;
+ unsigned int fine_integration_time_max_margin;
+ unsigned int frame_length_lines;
+ unsigned int line_length_pck;
+ unsigned int vt_pix_clk_freq_hz;
+ unsigned int crop_horizontal_start; /* Sensor crop start cord. (x0,y0)*/
+ unsigned int crop_vertical_start;
+ unsigned int crop_horizontal_end; /* Sensor crop end cord. (x1,y1)*/
+ unsigned int crop_vertical_end;
+ unsigned int sensor_output_width; /* input size to ISP */
+ unsigned int sensor_output_height;
+ unsigned int isp_input_horizontal_start; /* cif isp input */
+ unsigned int isp_input_vertical_start;
+ unsigned int isp_input_width;
+ unsigned int isp_input_height;
+ unsigned int isp_output_width; /* cif isp output */
+ unsigned int isp_output_height;
+ unsigned char binning_factor_x; /* horizontal binning factor used */
+ unsigned char binning_factor_y; /* vertical binning factor used */
+ unsigned char exposure_valid_frame;
+ int exp_time;
+ unsigned short gain;
+};
+
+struct camera_module_info_s {
+ char sensor_name[CAMERA_STRLEN];
+ char module_name[CAMERA_STRLEN];
+ char len_name[CAMERA_STRLEN];
+ char fov_h[CAMERA_STRLEN];
+ char fov_v[CAMERA_STRLEN];
+ char focal_length[CAMERA_STRLEN];
+ char focus_distance[CAMERA_STRLEN];
+ int facing;
+ int orientation;
+ bool iq_mirror;
+ bool iq_flip;
+ int flash_support;
+ int flash_exp_percent;
+};
+
+struct flash_timeinfo_s {
+ struct timeval preflash_start_t;
+ struct timeval preflash_end_t;
+ struct timeval mainflash_start_t;
+ struct timeval mainflash_end_t;
+ int flash_turn_on_time;
+ int flash_on_timeout;
+};
+
+struct frame_timeinfo_s {
+ struct timeval vs_t;
+ struct timeval fi_t;
+};
+
+struct sensor_metadata_s {
+ unsigned int exp_time;
+ unsigned int gain;
+};
+
+struct v4l2_buffer_metadata_s {
+ unsigned int frame_id;
+ struct frame_timeinfo_s frame_t;
+ struct flash_timeinfo_s flash_t;
+ struct sensor_metadata_s sensor;
+ unsigned char isp[CAMERA_METADATA_LEN - 512];
+};
+
+#endif
+
--- /dev/null
+/*
+ *************************************************************************
+ * Rockchip driver for CIF ISP 1.0
+ * (Based on Intel driver for sofiaxxx)
+ *
+ * Copyright (C) 2015 Intel Mobile Communications GmbH
+ * Copyright (C) 2016 Fuzhou Rockchip Electronics Co., Ltd.
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *************************************************************************
+ */
+
+#ifndef _V4L2_CONTROLS_ROCKCHIP_H
+#define _V4L2_CONTROLS_ROCKCHIP_H
+
+#include <linux/videodev2.h>
+#include <media/v4l2-config_rockchip.h>
+
+#define RK_VIDIOC_CAMERA_MODULEINFO \
+ _IOWR('v', BASE_VIDIOC_PRIVATE + 10, struct camera_module_info_s)
+#define RK_VIDIOC_SENSOR_MODE_DATA \
+ _IOR('v', BASE_VIDIOC_PRIVATE, struct isp_supplemental_sensor_mode_data)
+
+#define V4L2_CID_USER_RK_BASE (V4L2_CID_USER_BASE + 0x1080)
+#define RK_V4L2_CID_VBLANKING (V4L2_CID_USER_RK_BASE + 1)
+#define RK_V4L2_CID_GAIN_PERCENT (V4L2_CID_USER_RK_BASE + 2)
+#define RK_V4L2_CID_AUTO_FPS (V4L2_CID_USER_RK_BASE + 3)
+#endif