diff options
Diffstat (limited to 'drivers/staging/media/rkisp1/rkisp1-capture.c')
-rw-r--r-- | drivers/staging/media/rkisp1/rkisp1-capture.c | 1431 |
1 files changed, 0 insertions, 1431 deletions
diff --git a/drivers/staging/media/rkisp1/rkisp1-capture.c b/drivers/staging/media/rkisp1/rkisp1-capture.c deleted file mode 100644 index b81235afd053..000000000000 --- a/drivers/staging/media/rkisp1/rkisp1-capture.c +++ /dev/null @@ -1,1431 +0,0 @@ -// SPDX-License-Identifier: (GPL-2.0+ OR MIT) -/* - * Rockchip ISP1 Driver - V4l capture device - * - * Copyright (C) 2019 Collabora, Ltd. - * - * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. - * Copyright (C) 2017 Rockchip Electronics Co., Ltd. - */ - -#include <linux/delay.h> -#include <linux/pm_runtime.h> -#include <media/v4l2-common.h> -#include <media/v4l2-event.h> -#include <media/v4l2-fh.h> -#include <media/v4l2-ioctl.h> -#include <media/v4l2-mc.h> -#include <media/v4l2-subdev.h> -#include <media/videobuf2-dma-contig.h> - -#include "rkisp1-common.h" - -/* - * NOTE: There are two capture video devices in rkisp1, selfpath and mainpath. - * - * differences between selfpath and mainpath - * available mp sink input: isp - * available sp sink input : isp, dma(TODO) - * available mp sink pad fmts: yuv422, raw - * available sp sink pad fmts: yuv422, yuv420...... - * available mp source fmts: yuv, raw, jpeg(TODO) - * available sp source fmts: yuv, rgb - */ - -#define RKISP1_SP_DEV_NAME RKISP1_DRIVER_NAME "_selfpath" -#define RKISP1_MP_DEV_NAME RKISP1_DRIVER_NAME "_mainpath" - -#define RKISP1_MIN_BUFFERS_NEEDED 3 - -enum rkisp1_plane { - RKISP1_PLANE_Y = 0, - RKISP1_PLANE_CB = 1, - RKISP1_PLANE_CR = 2 -}; - -/* - * @fourcc: pixel format - * @fmt_type: helper filed for pixel format - * @uv_swap: if cb cr swaped, for yuv - * @write_format: defines how YCbCr self picture data is written to memory - * @output_format: defines sp output format - * @mbus: the mbus code on the src resizer pad that matches the pixel format - */ -struct rkisp1_capture_fmt_cfg { - u32 fourcc; - u8 uv_swap; - u32 write_format; - u32 output_format; - u32 mbus; -}; - -struct rkisp1_capture_ops { - void (*config)(struct rkisp1_capture *cap); - void (*stop)(struct rkisp1_capture *cap); - void (*enable)(struct rkisp1_capture *cap); - void (*disable)(struct rkisp1_capture *cap); - void (*set_data_path)(struct rkisp1_capture *cap); - bool (*is_stopped)(struct rkisp1_capture *cap); -}; - -struct rkisp1_capture_config { - const struct rkisp1_capture_fmt_cfg *fmts; - int fmt_size; - struct { - u32 y_size_init; - u32 cb_size_init; - u32 cr_size_init; - u32 y_base_ad_init; - u32 cb_base_ad_init; - u32 cr_base_ad_init; - u32 y_offs_cnt_init; - u32 cb_offs_cnt_init; - u32 cr_offs_cnt_init; - } mi; -}; - -/* - * The supported pixel formats for mainpath. NOTE, pixel formats with identical 'mbus' - * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes - */ -static const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = { - /* yuv422 */ - { - .fourcc = V4L2_PIX_FMT_YUYV, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV422P, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV16, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV61, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU422M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv400 */ - { - .fourcc = V4L2_PIX_FMT_GREY, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv420 */ - { - .fourcc = V4L2_PIX_FMT_NV21, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV21M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12M, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV420, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU420, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, - /* raw */ - { - .fourcc = V4L2_PIX_FMT_SRGGB8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SRGGB8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SGRBG8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SGBRG8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR8, - .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, - .mbus = MEDIA_BUS_FMT_SBGGR8_1X8, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SRGGB10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGRBG10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGBRG10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR10, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SBGGR10_1X10, - }, { - .fourcc = V4L2_PIX_FMT_SRGGB12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SRGGB12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SGRBG12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGRBG12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SGBRG12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SGBRG12_1X12, - }, { - .fourcc = V4L2_PIX_FMT_SBGGR12, - .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, - .mbus = MEDIA_BUS_FMT_SBGGR12_1X12, - }, -}; - -/* - * The supported pixel formats for selfpath. NOTE, pixel formats with identical 'mbus' - * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes - */ -static const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = { - /* yuv422 */ - { - .fourcc = V4L2_PIX_FMT_YUYV, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_INT, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV422P, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV16, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_NV61, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU422M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv400 */ - { - .fourcc = V4L2_PIX_FMT_GREY, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV400, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* rgb */ - { - .fourcc = V4L2_PIX_FMT_XBGR32, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, { - .fourcc = V4L2_PIX_FMT_RGB565, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565, - .mbus = MEDIA_BUS_FMT_YUYV8_2X8, - }, - /* yuv420 */ - { - .fourcc = V4L2_PIX_FMT_NV21, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV21M, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_NV12M, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YUV420, - .uv_swap = 0, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, { - .fourcc = V4L2_PIX_FMT_YVU420, - .uv_swap = 1, - .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, - .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, - .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, - }, -}; - -static const struct rkisp1_capture_config rkisp1_capture_config_mp = { - .fmts = rkisp1_mp_fmts, - .fmt_size = ARRAY_SIZE(rkisp1_mp_fmts), - .mi = { - .y_size_init = RKISP1_CIF_MI_MP_Y_SIZE_INIT, - .cb_size_init = RKISP1_CIF_MI_MP_CB_SIZE_INIT, - .cr_size_init = RKISP1_CIF_MI_MP_CR_SIZE_INIT, - .y_base_ad_init = RKISP1_CIF_MI_MP_Y_BASE_AD_INIT, - .cb_base_ad_init = RKISP1_CIF_MI_MP_CB_BASE_AD_INIT, - .cr_base_ad_init = RKISP1_CIF_MI_MP_CR_BASE_AD_INIT, - .y_offs_cnt_init = RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT, - .cb_offs_cnt_init = RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT, - .cr_offs_cnt_init = RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT, - }, -}; - -static const struct rkisp1_capture_config rkisp1_capture_config_sp = { - .fmts = rkisp1_sp_fmts, - .fmt_size = ARRAY_SIZE(rkisp1_sp_fmts), - .mi = { - .y_size_init = RKISP1_CIF_MI_SP_Y_SIZE_INIT, - .cb_size_init = RKISP1_CIF_MI_SP_CB_SIZE_INIT, - .cr_size_init = RKISP1_CIF_MI_SP_CR_SIZE_INIT, - .y_base_ad_init = RKISP1_CIF_MI_SP_Y_BASE_AD_INIT, - .cb_base_ad_init = RKISP1_CIF_MI_SP_CB_BASE_AD_INIT, - .cr_base_ad_init = RKISP1_CIF_MI_SP_CR_BASE_AD_INIT, - .y_offs_cnt_init = RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT, - .cb_offs_cnt_init = RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT, - .cr_offs_cnt_init = RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT, - }, -}; - -static inline struct rkisp1_vdev_node * -rkisp1_vdev_to_node(struct video_device *vdev) -{ - return container_of(vdev, struct rkisp1_vdev_node, vdev); -} - -int rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, - struct v4l2_subdev_mbus_code_enum *code) -{ - const struct rkisp1_capture_fmt_cfg *fmts = cap->config->fmts; - /* - * initialize curr_mbus to non existing mbus code 0 to ensure it is - * different from fmts[0].mbus - */ - u32 curr_mbus = 0; - int i, n = 0; - - for (i = 0; i < cap->config->fmt_size; i++) { - if (fmts[i].mbus == curr_mbus) - continue; - - curr_mbus = fmts[i].mbus; - if (n++ == code->index) { - code->code = curr_mbus; - return 0; - } - } - return -EINVAL; -} - -/* ---------------------------------------------------------------------------- - * Stream operations for self-picture path (sp) and main-picture path (mp) - */ - -static void rkisp1_mi_config_ctrl(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~GENMASK(17, 16); - mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64; - - mi_ctrl &= ~GENMASK(19, 18); - mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64; - - mi_ctrl |= RKISP1_CIF_MI_CTRL_INIT_BASE_EN | - RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN; - - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static u32 rkisp1_pixfmt_comp_size(const struct v4l2_pix_format_mplane *pixm, - unsigned int component) -{ - /* - * If packed format, then plane_fmt[0].sizeimage is the sum of all - * components, so we need to calculate just the size of Y component. - * See rkisp1_fill_pixfmt(). - */ - if (!component && pixm->num_planes == 1) - return pixm->plane_fmt[0].bytesperline * pixm->height; - return pixm->plane_fmt[component].sizeimage; -} - -static void rkisp1_irq_frame_end_enable(struct rkisp1_capture *cap) -{ - u32 mi_imsc = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_IMSC); - - mi_imsc |= RKISP1_CIF_MI_FRAME(cap); - rkisp1_write(cap->rkisp1, mi_imsc, RKISP1_CIF_MI_IMSC); -} - -static void rkisp1_mp_config(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_device *rkisp1 = cap->rkisp1; - u32 reg; - - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - cap->config->mi.y_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - cap->config->mi.cb_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), - cap->config->mi.cr_size_init); - - rkisp1_irq_frame_end_enable(cap); - - /* set uv swapping for semiplanar formats */ - if (cap->pix.info->comp_planes == 2) { - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - if (cap->pix.cfg->uv_swap) - reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; - else - reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - } - - rkisp1_mi_config_ctrl(cap); - - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - reg &= ~RKISP1_MI_CTRL_MP_FMT_MASK; - reg |= cap->pix.cfg->write_format; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); - - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - reg |= RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_config(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_device *rkisp1 = cap->rkisp1; - u32 mi_ctrl, reg; - - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - cap->config->mi.y_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - cap->config->mi.cb_size_init); - rkisp1_write(rkisp1, rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR), - cap->config->mi.cr_size_init); - - rkisp1_write(rkisp1, pixm->width, RKISP1_CIF_MI_SP_Y_PIC_WIDTH); - rkisp1_write(rkisp1, pixm->height, RKISP1_CIF_MI_SP_Y_PIC_HEIGHT); - rkisp1_write(rkisp1, cap->sp_y_stride, RKISP1_CIF_MI_SP_Y_LLENGTH); - - rkisp1_irq_frame_end_enable(cap); - - /* set uv swapping for semiplanar formats */ - if (cap->pix.info->comp_planes == 2) { - reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - if (cap->pix.cfg->uv_swap) - reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; - else - reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; - rkisp1_write(rkisp1, reg, RKISP1_CIF_MI_XTD_FORMAT_CTRL); - } - - rkisp1_mi_config_ctrl(cap); - - mi_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); - mi_ctrl &= ~RKISP1_MI_CTRL_SP_FMT_MASK; - mi_ctrl |= cap->pix.cfg->write_format | - RKISP1_MI_CTRL_SP_INPUT_YUV422 | - cap->pix.cfg->output_format | - RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE; - rkisp1_write(rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_disable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~(RKISP1_CIF_MI_CTRL_MP_ENABLE | - RKISP1_CIF_MI_CTRL_RAW_ENABLE); - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_disable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl &= ~RKISP1_CIF_MI_CTRL_SP_ENABLE; - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_enable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl; - - rkisp1_mp_disable(cap); - - mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - if (v4l2_is_format_bayer(cap->pix.info)) - mi_ctrl |= RKISP1_CIF_MI_CTRL_RAW_ENABLE; - /* YUV */ - else - mi_ctrl |= RKISP1_CIF_MI_CTRL_MP_ENABLE; - - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_sp_enable(struct rkisp1_capture *cap) -{ - u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); - - mi_ctrl |= RKISP1_CIF_MI_CTRL_SP_ENABLE; - rkisp1_write(cap->rkisp1, mi_ctrl, RKISP1_CIF_MI_CTRL); -} - -static void rkisp1_mp_sp_stop(struct rkisp1_capture *cap) -{ - if (!cap->is_streaming) - return; - rkisp1_write(cap->rkisp1, - RKISP1_CIF_MI_FRAME(cap), RKISP1_CIF_MI_ICR); - cap->ops->disable(cap); -} - -static bool rkisp1_mp_is_stopped(struct rkisp1_capture *cap) -{ - u32 en = RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED | - RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED; - - return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & en); -} - -static bool rkisp1_sp_is_stopped(struct rkisp1_capture *cap) -{ - return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & - RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED); -} - -static void rkisp1_mp_set_data_path(struct rkisp1_capture *cap) -{ - u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); - - dpcl = dpcl | RKISP1_CIF_VI_DPCL_CHAN_MODE_MP | - RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI; - rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); -} - -static void rkisp1_sp_set_data_path(struct rkisp1_capture *cap) -{ - u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); - - dpcl |= RKISP1_CIF_VI_DPCL_CHAN_MODE_SP; - rkisp1_write(cap->rkisp1, dpcl, RKISP1_CIF_VI_DPCL); -} - -static struct rkisp1_capture_ops rkisp1_capture_ops_mp = { - .config = rkisp1_mp_config, - .enable = rkisp1_mp_enable, - .disable = rkisp1_mp_disable, - .stop = rkisp1_mp_sp_stop, - .set_data_path = rkisp1_mp_set_data_path, - .is_stopped = rkisp1_mp_is_stopped, -}; - -static struct rkisp1_capture_ops rkisp1_capture_ops_sp = { - .config = rkisp1_sp_config, - .enable = rkisp1_sp_enable, - .disable = rkisp1_sp_disable, - .stop = rkisp1_mp_sp_stop, - .set_data_path = rkisp1_sp_set_data_path, - .is_stopped = rkisp1_sp_is_stopped, -}; - -/* ---------------------------------------------------------------------------- - * Frame buffer operations - */ - -static int rkisp1_dummy_buf_create(struct rkisp1_capture *cap) -{ - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - struct rkisp1_dummy_buffer *dummy_buf = &cap->buf.dummy; - - dummy_buf->size = max3(rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); - - /* The driver never access vaddr, no mapping is required */ - dummy_buf->vaddr = dma_alloc_attrs(cap->rkisp1->dev, - dummy_buf->size, - &dummy_buf->dma_addr, - GFP_KERNEL, - DMA_ATTR_NO_KERNEL_MAPPING); - if (!dummy_buf->vaddr) - return -ENOMEM; - - return 0; -} - -static void rkisp1_dummy_buf_destroy(struct rkisp1_capture *cap) -{ - dma_free_attrs(cap->rkisp1->dev, - cap->buf.dummy.size, cap->buf.dummy.vaddr, - cap->buf.dummy.dma_addr, DMA_ATTR_NO_KERNEL_MAPPING); -} - -static void rkisp1_set_next_buf(struct rkisp1_capture *cap) -{ - cap->buf.curr = cap->buf.next; - cap->buf.next = NULL; - - if (!list_empty(&cap->buf.queue)) { - u32 *buff_addr; - - cap->buf.next = list_first_entry(&cap->buf.queue, struct rkisp1_buffer, queue); - list_del(&cap->buf.next->queue); - - buff_addr = cap->buf.next->buff_addr; - - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_Y], - cap->config->mi.y_base_ad_init); - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_CB], - cap->config->mi.cb_base_ad_init); - rkisp1_write(cap->rkisp1, - buff_addr[RKISP1_PLANE_CR], - cap->config->mi.cr_base_ad_init); - } else { - /* - * Use the dummy space allocated by dma_alloc_coherent to - * throw data if there is no available buffer. - */ - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.y_base_ad_init); - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.cb_base_ad_init); - rkisp1_write(cap->rkisp1, - cap->buf.dummy.dma_addr, - cap->config->mi.cr_base_ad_init); - } - - /* Set plane offsets */ - rkisp1_write(cap->rkisp1, 0, cap->config->mi.y_offs_cnt_init); - rkisp1_write(cap->rkisp1, 0, cap->config->mi.cb_offs_cnt_init); - rkisp1_write(cap->rkisp1, 0, cap->config->mi.cr_offs_cnt_init); -} - -/* - * This function is called when a frame end comes. The next frame - * is processing and we should set up buffer for next-next frame, - * otherwise it will overflow. - */ -static void rkisp1_handle_buffer(struct rkisp1_capture *cap) -{ - struct rkisp1_isp *isp = &cap->rkisp1->isp; - struct rkisp1_buffer *curr_buf; - - spin_lock(&cap->buf.lock); - curr_buf = cap->buf.curr; - - if (curr_buf) { - curr_buf->vb.sequence = isp->frame_sequence; - curr_buf->vb.vb2_buf.timestamp = ktime_get_boottime_ns(); - curr_buf->vb.field = V4L2_FIELD_NONE; - vb2_buffer_done(&curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); - } else { - cap->rkisp1->debug.frame_drop[cap->id]++; - } - - rkisp1_set_next_buf(cap); - spin_unlock(&cap->buf.lock); -} - -void rkisp1_capture_isr(struct rkisp1_device *rkisp1) -{ - unsigned int i; - u32 status; - - status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS); - rkisp1_write(rkisp1, status, RKISP1_CIF_MI_ICR); - - for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) { - struct rkisp1_capture *cap = &rkisp1->capture_devs[i]; - - if (!(status & RKISP1_CIF_MI_FRAME(cap))) - continue; - if (!cap->is_stopping) { - rkisp1_handle_buffer(cap); - continue; - } - /* - * Make sure stream is actually stopped, whose state - * can be read from the shadow register, before - * wake_up() thread which would immediately free all - * frame buffers. stop() takes effect at the next - * frame end that sync the configurations to shadow - * regs. - */ - if (!cap->ops->is_stopped(cap)) { - cap->ops->stop(cap); - continue; - } - cap->is_stopping = false; - cap->is_streaming = false; - wake_up(&cap->done); - } -} - -/* ---------------------------------------------------------------------------- - * Vb2 operations - */ - -static int rkisp1_vb2_queue_setup(struct vb2_queue *queue, - unsigned int *num_buffers, - unsigned int *num_planes, - unsigned int sizes[], - struct device *alloc_devs[]) -{ - struct rkisp1_capture *cap = queue->drv_priv; - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - unsigned int i; - - if (*num_planes) { - if (*num_planes != pixm->num_planes) - return -EINVAL; - - for (i = 0; i < pixm->num_planes; i++) - if (sizes[i] < pixm->plane_fmt[i].sizeimage) - return -EINVAL; - } else { - *num_planes = pixm->num_planes; - for (i = 0; i < pixm->num_planes; i++) - sizes[i] = pixm->plane_fmt[i].sizeimage; - } - - return 0; -} - -static void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) -{ - struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); - struct rkisp1_buffer *ispbuf = - container_of(vbuf, struct rkisp1_buffer, vb); - struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; - const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; - unsigned int i; - - memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr)); - for (i = 0; i < pixm->num_planes; i++) - ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); - - /* Convert to non-MPLANE */ - if (pixm->num_planes == 1) { - ispbuf->buff_addr[RKISP1_PLANE_CB] = - ispbuf->buff_addr[RKISP1_PLANE_Y] + - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y); - ispbuf->buff_addr[RKISP1_PLANE_CR] = - ispbuf->buff_addr[RKISP1_PLANE_CB] + - rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB); - } - - /* - * uv swap can be supported for planar formats by switching - * the address of cb and cr - */ - if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap) - swap(ispbuf->buff_addr[RKISP1_PLANE_CR], - ispbuf->buff_addr[RKISP1_PLANE_CB]); - - spin_lock_irq(&cap->buf.lock); - list_add_tail(&ispbuf->queue, &cap->buf.queue); - spin_unlock_irq(&cap->buf.lock); -} - -static int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb) -{ - struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; - unsigned int i; - - for (i = 0; i < cap->pix.fmt.num_planes; i++) { - unsigned long size = cap->pix.fmt.plane_fmt[i].sizeimage; - - if (vb2_plane_size(vb, i) < size) { - dev_err(cap->rkisp1->dev, - "User buffer too small (%ld < %ld)\n", - vb2_plane_size(vb, i), size); - return -EINVAL; - } - vb2_set_plane_payload(vb, i, size); - } - - return 0; -} - -static void rkisp1_return_all_buffers(struct rkisp1_capture *cap, - enum vb2_buffer_state state) -{ - struct rkisp1_buffer *buf; - - spin_lock_irq(&cap->buf.lock); - if (cap->buf.curr) { - vb2_buffer_done(&cap->buf.curr->vb.vb2_buf, state); - cap->buf.curr = NULL; - } - if (cap->buf.next) { - vb2_buffer_done(&cap->buf.next->vb.vb2_buf, state); - cap->buf.next = NULL; - } - while (!list_empty(&cap->buf.queue)) { - buf = list_first_entry(&cap->buf.queue, - struct rkisp1_buffer, queue); - list_del(&buf->queue); - vb2_buffer_done(&buf->vb.vb2_buf, state); - } - spin_unlock_irq(&cap->buf.lock); -} - -/* - * Most of registers inside rockchip ISP1 have shadow register since - * they must be not be changed during processing a frame. - * Usually, each sub-module updates its shadow register after - * processing the last pixel of a frame. - */ -static void rkisp1_cap_stream_enable(struct rkisp1_capture *cap) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - struct rkisp1_capture *other = &rkisp1->capture_devs[cap->id ^ 1]; - - cap->ops->set_data_path(cap); - cap->ops->config(cap); - - /* Setup a buffer for the next frame */ - spin_lock_irq(&cap->buf.lock); - rkisp1_set_next_buf(cap); - cap->ops->enable(cap); - /* It's safe to config ACTIVE and SHADOW regs for the - * first stream. While when the second is starting, do NOT - * force update because it also update the first one. - * - * The latter case would drop one more buf(that is 2) since - * there's not buf in shadow when the second FE received. This's - * also required because the second FE maybe corrupt especially - * when run at 120fps. - */ - if (!other->is_streaming) { - /* force cfg update */ - rkisp1_write(rkisp1, - RKISP1_CIF_MI_INIT_SOFT_UPD, RKISP1_CIF_MI_INIT); - rkisp1_set_next_buf(cap); - } - spin_unlock_irq(&cap->buf.lock); - cap->is_streaming = true; -} - -static void rkisp1_cap_stream_disable(struct rkisp1_capture *cap) -{ - int ret; - - /* Stream should stop in interrupt. If it dosn't, stop it by force. */ - cap->is_stopping = true; - ret = wait_event_timeout(cap->done, - !cap->is_streaming, - msecs_to_jiffies(1000)); - if (!ret) { - cap->rkisp1->debug.stop_timeout[cap->id]++; - cap->ops->stop(cap); - cap->is_stopping = false; - cap->is_streaming = false; - } -} - -/* - * rkisp1_pipeline_stream_disable - disable nodes in the pipeline - * - * Call s_stream(false) in the reverse order from - * rkisp1_pipeline_stream_enable() and disable the DMA engine. - * Should be called before media_pipeline_stop() - */ -static void rkisp1_pipeline_stream_disable(struct rkisp1_capture *cap) - __must_hold(&cap->rkisp1->stream_lock) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - - rkisp1_cap_stream_disable(cap); - - /* - * If the other capture is streaming, isp and sensor nodes shouldn't - * be disabled, skip them. - */ - if (rkisp1->pipe.streaming_count < 2) { - v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, - false); - v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); - } - - v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, - false); -} - -/* - * rkisp1_pipeline_stream_enable - enable nodes in the pipeline - * - * Enable the DMA Engine and call s_stream(true) through the pipeline. - * Should be called after media_pipeline_start() - */ -static int rkisp1_pipeline_stream_enable(struct rkisp1_capture *cap) - __must_hold(&cap->rkisp1->stream_lock) -{ - struct rkisp1_device *rkisp1 = cap->rkisp1; - int ret; - - rkisp1_cap_stream_enable(cap); - - ret = v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, - s_stream, true); - if (ret) - goto err_disable_cap; - - /* - * If the other capture is streaming, isp and sensor nodes are already - * enabled, skip them. - */ - if (rkisp1->pipe.streaming_count > 1) - return 0; - - ret = v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, true); - if (ret) - goto err_disable_rsz; - - ret = v4l2_subdev_call(rkisp1->active_sensor->sd, video, s_stream, - true); - if (ret) - goto err_disable_isp; - - return 0; - -err_disable_isp: - v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); -err_disable_rsz: - v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, - false); -err_disable_cap: - rkisp1_cap_stream_disable(cap); - - return ret; -} - -static void rkisp1_vb2_stop_streaming(struct vb2_queue *queue) -{ - struct rkisp1_capture *cap = queue->drv_priv; - struct rkisp1_vdev_node *node = &cap->vnode; - struct rkisp1_device *rkisp1 = cap->rkisp1; - int ret; - - mutex_lock(&cap->rkisp1->stream_lock); - - rkisp1_pipeline_stream_disable(cap); - - rkisp1_return_all_buffers(cap, VB2_BUF_STATE_ERROR); - - v4l2_pipeline_pm_put(&node->vdev.entity); - ret = pm_runtime_put(rkisp1->dev); - if (ret < 0) - dev_err(rkisp1->dev, "power down failed error:%d\n", ret); - - rkisp1_dummy_buf_destroy(cap); - - media_pipeline_stop(&node->vdev.entity); - - mutex_unlock(&cap->rkisp1->stream_lock); -} - -static int -rkisp1_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) -{ - struct rkisp1_capture *cap = queue->drv_priv; - struct media_entity *entity = &cap->vnode.vdev.entity; - int ret; - - mutex_lock(&cap->rkisp1->stream_lock); - - ret = media_pipeline_start(entity, &cap->rkisp1->pipe); - if (ret) { - dev_err(cap->rkisp1->dev, "start pipeline failed %d\n", ret); - goto err_ret_buffers; - } - - ret = rkisp1_dummy_buf_create(cap); - if (ret) - goto err_pipeline_stop; - - ret = pm_runtime_get_sync(cap->rkisp1->dev); - if (ret < 0) { - pm_runtime_put_noidle(cap->rkisp1->dev); - dev_err(cap->rkisp1->dev, "power up failed %d\n", ret); - goto err_destroy_dummy; - } - ret = v4l2_pipeline_pm_get(entity); - if (ret) { - dev_err(cap->rkisp1->dev, "open cif pipeline failed %d\n", ret); - goto err_pipe_pm_put; - } - - ret = rkisp1_pipeline_stream_enable(cap); - if (ret) - goto err_v4l2_pm_put; - - mutex_unlock(&cap->rkisp1->stream_lock); - - return 0; - -err_v4l2_pm_put: - v4l2_pipeline_pm_put(entity); -err_pipe_pm_put: - pm_runtime_put(cap->rkisp1->dev); -err_destroy_dummy: - rkisp1_dummy_buf_destroy(cap); -err_pipeline_stop: - media_pipeline_stop(entity); -err_ret_buffers: - rkisp1_return_all_buffers(cap, VB2_BUF_STATE_QUEUED); - mutex_unlock(&cap->rkisp1->stream_lock); - - return ret; -} - -static struct vb2_ops rkisp1_vb2_ops = { - .queue_setup = rkisp1_vb2_queue_setup, - .buf_queue = rkisp1_vb2_buf_queue, - .buf_prepare = rkisp1_vb2_buf_prepare, - .wait_prepare = vb2_ops_wait_prepare, - .wait_finish = vb2_ops_wait_finish, - .stop_streaming = rkisp1_vb2_stop_streaming, - .start_streaming = rkisp1_vb2_start_streaming, -}; - -/* ---------------------------------------------------------------------------- - * IOCTLs operations - */ - -static const struct v4l2_format_info * -rkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm, - enum rkisp1_stream_id id) -{ - struct v4l2_plane_pix_format *plane_y = &pixm->plane_fmt[0]; - const struct v4l2_format_info *info; - unsigned int i; - u32 stride; - - memset(pixm->plane_fmt, 0, sizeof(pixm->plane_fmt)); - info = v4l2_format_info(pixm->pixelformat); - pixm->num_planes = info->mem_planes; - stride = info->bpp[0] * pixm->width; - /* Self path supports custom stride but Main path doesn't */ - if (id == RKISP1_MAINPATH || plane_y->bytesperline < stride) - plane_y->bytesperline = stride; - plane_y->sizeimage = plane_y->bytesperline * pixm->height; - - /* normalize stride to pixels per line */ - stride = DIV_ROUND_UP(plane_y->bytesperline, info->bpp[0]); - - for (i = 1; i < info->comp_planes; i++) { - struct v4l2_plane_pix_format *plane = &pixm->plane_fmt[i]; - - /* bytesperline for other components derive from Y component */ - plane->bytesperline = DIV_ROUND_UP(stride, info->hdiv) * - info->bpp[i]; - plane->sizeimage = plane->bytesperline * - DIV_ROUND_UP(pixm->height, info->vdiv); - } - - /* - * If pixfmt is packed, then plane_fmt[0] should contain the total size - * considering all components. plane_fmt[i] for i > 0 should be ignored - * by userspace as mem_planes == 1, but we are keeping information there - * for convenience. - */ - if (info->mem_planes == 1) - for (i = 1; i < info->comp_planes; i++) - plane_y->sizeimage += pixm->plane_fmt[i].sizeimage; - - return info; -} - -static const struct rkisp1_capture_fmt_cfg * -rkisp1_find_fmt_cfg(const struct rkisp1_capture *cap, const u32 pixelfmt) -{ - unsigned int i; - - for (i = 0; i < cap->config->fmt_size; i++) { - if (cap->config->fmts[i].fourcc == pixelfmt) - return &cap->config->fmts[i]; - } - return NULL; -} - -static void rkisp1_try_fmt(const struct rkisp1_capture *cap, - struct v4l2_pix_format_mplane *pixm, - const struct rkisp1_capture_fmt_cfg **fmt_cfg, - const struct v4l2_format_info **fmt_info) -{ - const struct rkisp1_capture_config *config = cap->config; - const struct rkisp1_capture_fmt_cfg *fmt; - const struct v4l2_format_info *info; - const unsigned int max_widths[] = { RKISP1_RSZ_MP_SRC_MAX_WIDTH, |