root/drivers/media/platform/sunxi/sun4i-csi/sun4i_csi.h
/* SPDX-License-Identifier: GPL-2.0+ */
/*
 * Copyright (C) 2016 NextThing Co
 * Copyright (C) 2016-2019 Bootlin
 *
 * Author: Maxime Ripard <maxime.ripard@bootlin.com>
 */

#ifndef _SUN4I_CSI_H_
#define _SUN4I_CSI_H_

#include <media/media-device.h>
#include <media/v4l2-async.h>
#include <media/v4l2-dev.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/videobuf2-core.h>

#define CSI_EN_REG                      0x00

#define CSI_CFG_REG                     0x04
#define CSI_CFG_INPUT_FMT(fmt)                  ((fmt) << 20)
#define CSI_CFG_OUTPUT_FMT(fmt)                 ((fmt) << 16)
#define CSI_CFG_YUV_DATA_SEQ(seq)               ((seq) << 8)
#define CSI_CFG_VREF_POL(pol)                   ((pol) << 2)
#define CSI_CFG_HREF_POL(pol)                   ((pol) << 1)
#define CSI_CFG_PCLK_POL(pol)                   ((pol) << 0)

#define CSI_CPT_CTRL_REG                0x08
#define CSI_CPT_CTRL_VIDEO_START                BIT(1)
#define CSI_CPT_CTRL_IMAGE_START                BIT(0)

#define CSI_BUF_ADDR_REG(fifo, buf)     (0x10 + (0x8 * (fifo)) + (0x4 * (buf)))

#define CSI_BUF_CTRL_REG                0x28
#define CSI_BUF_CTRL_DBN                        BIT(2)
#define CSI_BUF_CTRL_DBS                        BIT(1)
#define CSI_BUF_CTRL_DBE                        BIT(0)

#define CSI_INT_EN_REG                  0x30
#define CSI_INT_FRM_DONE                        BIT(1)
#define CSI_INT_CPT_DONE                        BIT(0)

#define CSI_INT_STA_REG                 0x34

#define CSI_WIN_CTRL_W_REG              0x40
#define CSI_WIN_CTRL_W_ACTIVE(w)                ((w) << 16)

#define CSI_WIN_CTRL_H_REG              0x44
#define CSI_WIN_CTRL_H_ACTIVE(h)                ((h) << 16)

#define CSI_BUF_LEN_REG                 0x48

#define CSI_MAX_BUFFER          2
#define CSI_MAX_HEIGHT          8192U
#define CSI_MAX_WIDTH           8192U

enum csi_input {
        CSI_INPUT_RAW   = 0,
        CSI_INPUT_BT656 = 2,
        CSI_INPUT_YUV   = 3,
};

enum csi_output_raw {
        CSI_OUTPUT_RAW_PASSTHROUGH = 0,
};

enum csi_output_yuv {
        CSI_OUTPUT_YUV_422_PLANAR       = 0,
        CSI_OUTPUT_YUV_420_PLANAR       = 1,
        CSI_OUTPUT_YUV_422_UV           = 4,
        CSI_OUTPUT_YUV_420_UV           = 5,
        CSI_OUTPUT_YUV_422_MACRO        = 8,
        CSI_OUTPUT_YUV_420_MACRO        = 9,
};

enum csi_yuv_data_seq {
        CSI_YUV_DATA_SEQ_YUYV   = 0,
        CSI_YUV_DATA_SEQ_YVYU   = 1,
        CSI_YUV_DATA_SEQ_UYVY   = 2,
        CSI_YUV_DATA_SEQ_VYUY   = 3,
};

enum csi_subdev_pads {
        CSI_SUBDEV_SINK,
        CSI_SUBDEV_SOURCE,

        CSI_SUBDEV_PADS,
};

extern const struct v4l2_subdev_ops sun4i_csi_subdev_ops;
extern const struct v4l2_subdev_internal_ops sun4i_csi_subdev_internal_ops;

struct sun4i_csi_format {
        u32                     mbus;
        u32                     fourcc;
        enum csi_input          input;
        u32                     output;
        unsigned int            num_planes;
        u8                      bpp[3];
        unsigned int            hsub;
        unsigned int            vsub;
};

const struct sun4i_csi_format *sun4i_csi_find_format(const u32 *fourcc,
                                                     const u32 *mbus);

struct sun4i_csi {
        /* Device resources */
        struct device                   *dev;

        const struct sun4i_csi_traits   *traits;

        void __iomem                    *regs;
        struct clk                      *bus_clk;
        struct clk                      *isp_clk;
        struct clk                      *ram_clk;
        struct reset_control            *rst;

        struct vb2_v4l2_buffer          *current_buf[CSI_MAX_BUFFER];

        struct {
                size_t                  size;
                void                    *vaddr;
                dma_addr_t              paddr;
        } scratch;

        struct v4l2_mbus_config_parallel        bus;

        /* Main Device */
        struct v4l2_device              v4l;
        struct media_device             mdev;
        struct video_device             vdev;
        struct media_pad                vdev_pad;
        struct v4l2_pix_format_mplane   fmt;

        /* Local subdev */
        struct v4l2_subdev              subdev;
        struct media_pad                subdev_pads[CSI_SUBDEV_PADS];
        struct v4l2_mbus_framefmt       subdev_fmt;

        /* V4L2 Async variables */
        struct v4l2_async_notifier      notifier;
        struct v4l2_subdev              *src_subdev;
        int                             src_pad;

        /* V4L2 variables */
        struct mutex                    lock;

        /* Videobuf2 */
        struct vb2_queue                queue;
        struct list_head                buf_list;
        spinlock_t                      qlock;
        unsigned int                    sequence;
};

int sun4i_csi_dma_register(struct sun4i_csi *csi, int irq);
void sun4i_csi_dma_unregister(struct sun4i_csi *csi);

int sun4i_csi_v4l2_register(struct sun4i_csi *csi);

#endif /* _SUN4I_CSI_H_ */