162306a36Sopenharmony_ci// SPDX-License-Identifier: (GPL-2.0+ OR MIT) 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Rockchip ISP1 Driver - V4l capture device 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Copyright (C) 2019 Collabora, Ltd. 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Based on Rockchip ISP1 driver by Rockchip Electronics Co., Ltd. 862306a36Sopenharmony_ci * Copyright (C) 2017 Rockchip Electronics Co., Ltd. 962306a36Sopenharmony_ci */ 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_ci#include <linux/delay.h> 1262306a36Sopenharmony_ci#include <linux/pm_runtime.h> 1362306a36Sopenharmony_ci#include <media/v4l2-common.h> 1462306a36Sopenharmony_ci#include <media/v4l2-event.h> 1562306a36Sopenharmony_ci#include <media/v4l2-fh.h> 1662306a36Sopenharmony_ci#include <media/v4l2-ioctl.h> 1762306a36Sopenharmony_ci#include <media/v4l2-mc.h> 1862306a36Sopenharmony_ci#include <media/v4l2-subdev.h> 1962306a36Sopenharmony_ci#include <media/videobuf2-dma-contig.h> 2062306a36Sopenharmony_ci 2162306a36Sopenharmony_ci#include "rkisp1-common.h" 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* 2462306a36Sopenharmony_ci * NOTE: There are two capture video devices in rkisp1, selfpath and mainpath. 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * differences between selfpath and mainpath 2762306a36Sopenharmony_ci * available mp sink input: isp 2862306a36Sopenharmony_ci * available sp sink input : isp, dma(TODO) 2962306a36Sopenharmony_ci * available mp sink pad fmts: yuv422, raw 3062306a36Sopenharmony_ci * available sp sink pad fmts: yuv422, yuv420...... 3162306a36Sopenharmony_ci * available mp source fmts: yuv, raw, jpeg(TODO) 3262306a36Sopenharmony_ci * available sp source fmts: yuv, rgb 3362306a36Sopenharmony_ci */ 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci#define RKISP1_SP_DEV_NAME RKISP1_DRIVER_NAME "_selfpath" 3662306a36Sopenharmony_ci#define RKISP1_MP_DEV_NAME RKISP1_DRIVER_NAME "_mainpath" 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_ci#define RKISP1_MIN_BUFFERS_NEEDED 3 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_cienum rkisp1_plane { 4162306a36Sopenharmony_ci RKISP1_PLANE_Y = 0, 4262306a36Sopenharmony_ci RKISP1_PLANE_CB = 1, 4362306a36Sopenharmony_ci RKISP1_PLANE_CR = 2 4462306a36Sopenharmony_ci}; 4562306a36Sopenharmony_ci 4662306a36Sopenharmony_ci/* 4762306a36Sopenharmony_ci * @fourcc: pixel format 4862306a36Sopenharmony_ci * @fmt_type: helper filed for pixel format 4962306a36Sopenharmony_ci * @uv_swap: if cb cr swapped, for yuv 5062306a36Sopenharmony_ci * @write_format: defines how YCbCr self picture data is written to memory 5162306a36Sopenharmony_ci * @output_format: defines sp output format 5262306a36Sopenharmony_ci * @mbus: the mbus code on the src resizer pad that matches the pixel format 5362306a36Sopenharmony_ci */ 5462306a36Sopenharmony_cistruct rkisp1_capture_fmt_cfg { 5562306a36Sopenharmony_ci u32 fourcc; 5662306a36Sopenharmony_ci u8 uv_swap; 5762306a36Sopenharmony_ci u32 write_format; 5862306a36Sopenharmony_ci u32 output_format; 5962306a36Sopenharmony_ci u32 mbus; 6062306a36Sopenharmony_ci}; 6162306a36Sopenharmony_ci 6262306a36Sopenharmony_cistruct rkisp1_capture_ops { 6362306a36Sopenharmony_ci void (*config)(struct rkisp1_capture *cap); 6462306a36Sopenharmony_ci void (*stop)(struct rkisp1_capture *cap); 6562306a36Sopenharmony_ci void (*enable)(struct rkisp1_capture *cap); 6662306a36Sopenharmony_ci void (*disable)(struct rkisp1_capture *cap); 6762306a36Sopenharmony_ci void (*set_data_path)(struct rkisp1_capture *cap); 6862306a36Sopenharmony_ci bool (*is_stopped)(struct rkisp1_capture *cap); 6962306a36Sopenharmony_ci}; 7062306a36Sopenharmony_ci 7162306a36Sopenharmony_cistruct rkisp1_capture_config { 7262306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg *fmts; 7362306a36Sopenharmony_ci int fmt_size; 7462306a36Sopenharmony_ci struct { 7562306a36Sopenharmony_ci u32 y_size_init; 7662306a36Sopenharmony_ci u32 cb_size_init; 7762306a36Sopenharmony_ci u32 cr_size_init; 7862306a36Sopenharmony_ci u32 y_base_ad_init; 7962306a36Sopenharmony_ci u32 cb_base_ad_init; 8062306a36Sopenharmony_ci u32 cr_base_ad_init; 8162306a36Sopenharmony_ci u32 y_offs_cnt_init; 8262306a36Sopenharmony_ci u32 cb_offs_cnt_init; 8362306a36Sopenharmony_ci u32 cr_offs_cnt_init; 8462306a36Sopenharmony_ci } mi; 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* 8862306a36Sopenharmony_ci * The supported pixel formats for mainpath. NOTE, pixel formats with identical 'mbus' 8962306a36Sopenharmony_ci * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes 9062306a36Sopenharmony_ci */ 9162306a36Sopenharmony_cistatic const struct rkisp1_capture_fmt_cfg rkisp1_mp_fmts[] = { 9262306a36Sopenharmony_ci /* yuv422 */ 9362306a36Sopenharmony_ci { 9462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUYV, 9562306a36Sopenharmony_ci .uv_swap = 0, 9662306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUVINT, 9762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 9862306a36Sopenharmony_ci }, { 9962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUV422P, 10062306a36Sopenharmony_ci .uv_swap = 0, 10162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 10262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 10362306a36Sopenharmony_ci }, { 10462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV16, 10562306a36Sopenharmony_ci .uv_swap = 0, 10662306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 10762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 10862306a36Sopenharmony_ci }, { 10962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV61, 11062306a36Sopenharmony_ci .uv_swap = 1, 11162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 11262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 11362306a36Sopenharmony_ci }, { 11462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV16M, 11562306a36Sopenharmony_ci .uv_swap = 0, 11662306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 11762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 11862306a36Sopenharmony_ci }, { 11962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV61M, 12062306a36Sopenharmony_ci .uv_swap = 1, 12162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 12262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 12362306a36Sopenharmony_ci }, { 12462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YVU422M, 12562306a36Sopenharmony_ci .uv_swap = 1, 12662306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 12762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 12862306a36Sopenharmony_ci }, 12962306a36Sopenharmony_ci /* yuv400 */ 13062306a36Sopenharmony_ci { 13162306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_GREY, 13262306a36Sopenharmony_ci .uv_swap = 0, 13362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 13462306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 13562306a36Sopenharmony_ci }, 13662306a36Sopenharmony_ci /* yuv420 */ 13762306a36Sopenharmony_ci { 13862306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV21, 13962306a36Sopenharmony_ci .uv_swap = 1, 14062306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 14162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 14262306a36Sopenharmony_ci }, { 14362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV12, 14462306a36Sopenharmony_ci .uv_swap = 0, 14562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 14662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 14762306a36Sopenharmony_ci }, { 14862306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV21M, 14962306a36Sopenharmony_ci .uv_swap = 1, 15062306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 15162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 15262306a36Sopenharmony_ci }, { 15362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV12M, 15462306a36Sopenharmony_ci .uv_swap = 0, 15562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_SPLA, 15662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 15762306a36Sopenharmony_ci }, { 15862306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUV420, 15962306a36Sopenharmony_ci .uv_swap = 0, 16062306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 16162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 16262306a36Sopenharmony_ci }, { 16362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YVU420, 16462306a36Sopenharmony_ci .uv_swap = 1, 16562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 16662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 16762306a36Sopenharmony_ci }, 16862306a36Sopenharmony_ci /* raw */ 16962306a36Sopenharmony_ci { 17062306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SRGGB8, 17162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 17262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SRGGB8_1X8, 17362306a36Sopenharmony_ci }, { 17462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGRBG8, 17562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 17662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGRBG8_1X8, 17762306a36Sopenharmony_ci }, { 17862306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGBRG8, 17962306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 18062306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGBRG8_1X8, 18162306a36Sopenharmony_ci }, { 18262306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SBGGR8, 18362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_YUV_PLA_OR_RAW8, 18462306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SBGGR8_1X8, 18562306a36Sopenharmony_ci }, { 18662306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SRGGB10, 18762306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 18862306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SRGGB10_1X10, 18962306a36Sopenharmony_ci }, { 19062306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGRBG10, 19162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 19262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGRBG10_1X10, 19362306a36Sopenharmony_ci }, { 19462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGBRG10, 19562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 19662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGBRG10_1X10, 19762306a36Sopenharmony_ci }, { 19862306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SBGGR10, 19962306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 20062306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SBGGR10_1X10, 20162306a36Sopenharmony_ci }, { 20262306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SRGGB12, 20362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 20462306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SRGGB12_1X12, 20562306a36Sopenharmony_ci }, { 20662306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGRBG12, 20762306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 20862306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGRBG12_1X12, 20962306a36Sopenharmony_ci }, { 21062306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SGBRG12, 21162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 21262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SGBRG12_1X12, 21362306a36Sopenharmony_ci }, { 21462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_SBGGR12, 21562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_MP_WRITE_RAW12, 21662306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_SBGGR12_1X12, 21762306a36Sopenharmony_ci }, 21862306a36Sopenharmony_ci}; 21962306a36Sopenharmony_ci 22062306a36Sopenharmony_ci/* 22162306a36Sopenharmony_ci * The supported pixel formats for selfpath. NOTE, pixel formats with identical 'mbus' 22262306a36Sopenharmony_ci * are grouped together. This is assumed and used by the function rkisp1_cap_enum_mbus_codes 22362306a36Sopenharmony_ci */ 22462306a36Sopenharmony_cistatic const struct rkisp1_capture_fmt_cfg rkisp1_sp_fmts[] = { 22562306a36Sopenharmony_ci /* yuv422 */ 22662306a36Sopenharmony_ci { 22762306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUYV, 22862306a36Sopenharmony_ci .uv_swap = 0, 22962306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_INT, 23062306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 23162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 23262306a36Sopenharmony_ci }, { 23362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUV422P, 23462306a36Sopenharmony_ci .uv_swap = 0, 23562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 23662306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 23762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 23862306a36Sopenharmony_ci }, { 23962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV16, 24062306a36Sopenharmony_ci .uv_swap = 0, 24162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 24262306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 24362306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 24462306a36Sopenharmony_ci }, { 24562306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV61, 24662306a36Sopenharmony_ci .uv_swap = 1, 24762306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 24862306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 24962306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 25062306a36Sopenharmony_ci }, { 25162306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV16M, 25262306a36Sopenharmony_ci .uv_swap = 0, 25362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 25462306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 25562306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 25662306a36Sopenharmony_ci }, { 25762306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV61M, 25862306a36Sopenharmony_ci .uv_swap = 1, 25962306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 26062306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 26162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 26262306a36Sopenharmony_ci }, { 26362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YVU422M, 26462306a36Sopenharmony_ci .uv_swap = 1, 26562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 26662306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 26762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 26862306a36Sopenharmony_ci }, 26962306a36Sopenharmony_ci /* yuv400 */ 27062306a36Sopenharmony_ci { 27162306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_GREY, 27262306a36Sopenharmony_ci .uv_swap = 0, 27362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 27462306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV422, 27562306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 27662306a36Sopenharmony_ci }, 27762306a36Sopenharmony_ci /* rgb */ 27862306a36Sopenharmony_ci { 27962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_XBGR32, 28062306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 28162306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB888, 28262306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 28362306a36Sopenharmony_ci }, { 28462306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_RGB565, 28562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 28662306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_RGB565, 28762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_2X8, 28862306a36Sopenharmony_ci }, 28962306a36Sopenharmony_ci /* yuv420 */ 29062306a36Sopenharmony_ci { 29162306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV21, 29262306a36Sopenharmony_ci .uv_swap = 1, 29362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 29462306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 29562306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 29662306a36Sopenharmony_ci }, { 29762306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV12, 29862306a36Sopenharmony_ci .uv_swap = 0, 29962306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 30062306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 30162306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 30262306a36Sopenharmony_ci }, { 30362306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV21M, 30462306a36Sopenharmony_ci .uv_swap = 1, 30562306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 30662306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 30762306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 30862306a36Sopenharmony_ci }, { 30962306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_NV12M, 31062306a36Sopenharmony_ci .uv_swap = 0, 31162306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_SPLA, 31262306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 31362306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 31462306a36Sopenharmony_ci }, { 31562306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YUV420, 31662306a36Sopenharmony_ci .uv_swap = 0, 31762306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 31862306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 31962306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 32062306a36Sopenharmony_ci }, { 32162306a36Sopenharmony_ci .fourcc = V4L2_PIX_FMT_YVU420, 32262306a36Sopenharmony_ci .uv_swap = 1, 32362306a36Sopenharmony_ci .write_format = RKISP1_MI_CTRL_SP_WRITE_PLA, 32462306a36Sopenharmony_ci .output_format = RKISP1_MI_CTRL_SP_OUTPUT_YUV420, 32562306a36Sopenharmony_ci .mbus = MEDIA_BUS_FMT_YUYV8_1_5X8, 32662306a36Sopenharmony_ci }, 32762306a36Sopenharmony_ci}; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_cistatic const struct rkisp1_capture_config rkisp1_capture_config_mp = { 33062306a36Sopenharmony_ci .fmts = rkisp1_mp_fmts, 33162306a36Sopenharmony_ci .fmt_size = ARRAY_SIZE(rkisp1_mp_fmts), 33262306a36Sopenharmony_ci .mi = { 33362306a36Sopenharmony_ci .y_size_init = RKISP1_CIF_MI_MP_Y_SIZE_INIT, 33462306a36Sopenharmony_ci .cb_size_init = RKISP1_CIF_MI_MP_CB_SIZE_INIT, 33562306a36Sopenharmony_ci .cr_size_init = RKISP1_CIF_MI_MP_CR_SIZE_INIT, 33662306a36Sopenharmony_ci .y_base_ad_init = RKISP1_CIF_MI_MP_Y_BASE_AD_INIT, 33762306a36Sopenharmony_ci .cb_base_ad_init = RKISP1_CIF_MI_MP_CB_BASE_AD_INIT, 33862306a36Sopenharmony_ci .cr_base_ad_init = RKISP1_CIF_MI_MP_CR_BASE_AD_INIT, 33962306a36Sopenharmony_ci .y_offs_cnt_init = RKISP1_CIF_MI_MP_Y_OFFS_CNT_INIT, 34062306a36Sopenharmony_ci .cb_offs_cnt_init = RKISP1_CIF_MI_MP_CB_OFFS_CNT_INIT, 34162306a36Sopenharmony_ci .cr_offs_cnt_init = RKISP1_CIF_MI_MP_CR_OFFS_CNT_INIT, 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci}; 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_cistatic const struct rkisp1_capture_config rkisp1_capture_config_sp = { 34662306a36Sopenharmony_ci .fmts = rkisp1_sp_fmts, 34762306a36Sopenharmony_ci .fmt_size = ARRAY_SIZE(rkisp1_sp_fmts), 34862306a36Sopenharmony_ci .mi = { 34962306a36Sopenharmony_ci .y_size_init = RKISP1_CIF_MI_SP_Y_SIZE_INIT, 35062306a36Sopenharmony_ci .cb_size_init = RKISP1_CIF_MI_SP_CB_SIZE_INIT, 35162306a36Sopenharmony_ci .cr_size_init = RKISP1_CIF_MI_SP_CR_SIZE_INIT, 35262306a36Sopenharmony_ci .y_base_ad_init = RKISP1_CIF_MI_SP_Y_BASE_AD_INIT, 35362306a36Sopenharmony_ci .cb_base_ad_init = RKISP1_CIF_MI_SP_CB_BASE_AD_INIT, 35462306a36Sopenharmony_ci .cr_base_ad_init = RKISP1_CIF_MI_SP_CR_BASE_AD_INIT, 35562306a36Sopenharmony_ci .y_offs_cnt_init = RKISP1_CIF_MI_SP_Y_OFFS_CNT_INIT, 35662306a36Sopenharmony_ci .cb_offs_cnt_init = RKISP1_CIF_MI_SP_CB_OFFS_CNT_INIT, 35762306a36Sopenharmony_ci .cr_offs_cnt_init = RKISP1_CIF_MI_SP_CR_OFFS_CNT_INIT, 35862306a36Sopenharmony_ci }, 35962306a36Sopenharmony_ci}; 36062306a36Sopenharmony_ci 36162306a36Sopenharmony_cistatic inline struct rkisp1_vdev_node * 36262306a36Sopenharmony_cirkisp1_vdev_to_node(struct video_device *vdev) 36362306a36Sopenharmony_ci{ 36462306a36Sopenharmony_ci return container_of(vdev, struct rkisp1_vdev_node, vdev); 36562306a36Sopenharmony_ci} 36662306a36Sopenharmony_ci 36762306a36Sopenharmony_ciint rkisp1_cap_enum_mbus_codes(struct rkisp1_capture *cap, 36862306a36Sopenharmony_ci struct v4l2_subdev_mbus_code_enum *code) 36962306a36Sopenharmony_ci{ 37062306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg *fmts = cap->config->fmts; 37162306a36Sopenharmony_ci /* 37262306a36Sopenharmony_ci * initialize curr_mbus to non existing mbus code 0 to ensure it is 37362306a36Sopenharmony_ci * different from fmts[0].mbus 37462306a36Sopenharmony_ci */ 37562306a36Sopenharmony_ci u32 curr_mbus = 0; 37662306a36Sopenharmony_ci int i, n = 0; 37762306a36Sopenharmony_ci 37862306a36Sopenharmony_ci for (i = 0; i < cap->config->fmt_size; i++) { 37962306a36Sopenharmony_ci if (fmts[i].mbus == curr_mbus) 38062306a36Sopenharmony_ci continue; 38162306a36Sopenharmony_ci 38262306a36Sopenharmony_ci curr_mbus = fmts[i].mbus; 38362306a36Sopenharmony_ci if (n++ == code->index) { 38462306a36Sopenharmony_ci code->code = curr_mbus; 38562306a36Sopenharmony_ci return 0; 38662306a36Sopenharmony_ci } 38762306a36Sopenharmony_ci } 38862306a36Sopenharmony_ci return -EINVAL; 38962306a36Sopenharmony_ci} 39062306a36Sopenharmony_ci 39162306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 39262306a36Sopenharmony_ci * Stream operations for self-picture path (sp) and main-picture path (mp) 39362306a36Sopenharmony_ci */ 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_cistatic void rkisp1_mi_config_ctrl(struct rkisp1_capture *cap) 39662306a36Sopenharmony_ci{ 39762306a36Sopenharmony_ci u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); 39862306a36Sopenharmony_ci 39962306a36Sopenharmony_ci mi_ctrl &= ~GENMASK(17, 16); 40062306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_LUM_64; 40162306a36Sopenharmony_ci 40262306a36Sopenharmony_ci mi_ctrl &= ~GENMASK(19, 18); 40362306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_BURST_LEN_CHROM_64; 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_INIT_BASE_EN | 40662306a36Sopenharmony_ci RKISP1_CIF_MI_CTRL_INIT_OFFSET_EN; 40762306a36Sopenharmony_ci 40862306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic u32 rkisp1_pixfmt_comp_size(const struct v4l2_pix_format_mplane *pixm, 41262306a36Sopenharmony_ci unsigned int component) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci /* 41562306a36Sopenharmony_ci * If packed format, then plane_fmt[0].sizeimage is the sum of all 41662306a36Sopenharmony_ci * components, so we need to calculate just the size of Y component. 41762306a36Sopenharmony_ci * See rkisp1_fill_pixfmt(). 41862306a36Sopenharmony_ci */ 41962306a36Sopenharmony_ci if (!component && pixm->num_planes == 1) 42062306a36Sopenharmony_ci return pixm->plane_fmt[0].bytesperline * pixm->height; 42162306a36Sopenharmony_ci return pixm->plane_fmt[component].sizeimage; 42262306a36Sopenharmony_ci} 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_cistatic void rkisp1_irq_frame_end_enable(struct rkisp1_capture *cap) 42562306a36Sopenharmony_ci{ 42662306a36Sopenharmony_ci u32 mi_imsc = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_IMSC); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci mi_imsc |= RKISP1_CIF_MI_FRAME(cap); 42962306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_IMSC, mi_imsc); 43062306a36Sopenharmony_ci} 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_cistatic void rkisp1_mp_config(struct rkisp1_capture *cap) 43362306a36Sopenharmony_ci{ 43462306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; 43562306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 43662306a36Sopenharmony_ci u32 reg; 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.y_size_init, 43962306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y)); 44062306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.cb_size_init, 44162306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB)); 44262306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.cr_size_init, 44362306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); 44462306a36Sopenharmony_ci 44562306a36Sopenharmony_ci rkisp1_irq_frame_end_enable(cap); 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci /* set uv swapping for semiplanar formats */ 44862306a36Sopenharmony_ci if (cap->pix.info->comp_planes == 2) { 44962306a36Sopenharmony_ci reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); 45062306a36Sopenharmony_ci if (cap->pix.cfg->uv_swap) 45162306a36Sopenharmony_ci reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; 45262306a36Sopenharmony_ci else 45362306a36Sopenharmony_ci reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_MP_CB_CR_SWAP; 45462306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL, reg); 45562306a36Sopenharmony_ci } 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci rkisp1_mi_config_ctrl(cap); 45862306a36Sopenharmony_ci 45962306a36Sopenharmony_ci reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); 46062306a36Sopenharmony_ci reg &= ~RKISP1_MI_CTRL_MP_FMT_MASK; 46162306a36Sopenharmony_ci reg |= cap->pix.cfg->write_format; 46262306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_CTRL, reg); 46362306a36Sopenharmony_ci 46462306a36Sopenharmony_ci reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); 46562306a36Sopenharmony_ci reg |= RKISP1_CIF_MI_MP_AUTOUPDATE_ENABLE; 46662306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_CTRL, reg); 46762306a36Sopenharmony_ci} 46862306a36Sopenharmony_ci 46962306a36Sopenharmony_cistatic void rkisp1_sp_config(struct rkisp1_capture *cap) 47062306a36Sopenharmony_ci{ 47162306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; 47262306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 47362306a36Sopenharmony_ci u32 mi_ctrl, reg; 47462306a36Sopenharmony_ci 47562306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.y_size_init, 47662306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y)); 47762306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.cb_size_init, 47862306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB)); 47962306a36Sopenharmony_ci rkisp1_write(rkisp1, cap->config->mi.cr_size_init, 48062306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); 48162306a36Sopenharmony_ci 48262306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_PIC_WIDTH, pixm->width); 48362306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_PIC_HEIGHT, pixm->height); 48462306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_SP_Y_LLENGTH, cap->sp_y_stride); 48562306a36Sopenharmony_ci 48662306a36Sopenharmony_ci rkisp1_irq_frame_end_enable(cap); 48762306a36Sopenharmony_ci 48862306a36Sopenharmony_ci /* set uv swapping for semiplanar formats */ 48962306a36Sopenharmony_ci if (cap->pix.info->comp_planes == 2) { 49062306a36Sopenharmony_ci reg = rkisp1_read(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL); 49162306a36Sopenharmony_ci if (cap->pix.cfg->uv_swap) 49262306a36Sopenharmony_ci reg |= RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; 49362306a36Sopenharmony_ci else 49462306a36Sopenharmony_ci reg &= ~RKISP1_CIF_MI_XTD_FMT_CTRL_SP_CB_CR_SWAP; 49562306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_XTD_FORMAT_CTRL, reg); 49662306a36Sopenharmony_ci } 49762306a36Sopenharmony_ci 49862306a36Sopenharmony_ci rkisp1_mi_config_ctrl(cap); 49962306a36Sopenharmony_ci 50062306a36Sopenharmony_ci mi_ctrl = rkisp1_read(rkisp1, RKISP1_CIF_MI_CTRL); 50162306a36Sopenharmony_ci mi_ctrl &= ~RKISP1_MI_CTRL_SP_FMT_MASK; 50262306a36Sopenharmony_ci mi_ctrl |= cap->pix.cfg->write_format | 50362306a36Sopenharmony_ci RKISP1_MI_CTRL_SP_INPUT_YUV422 | 50462306a36Sopenharmony_ci cap->pix.cfg->output_format | 50562306a36Sopenharmony_ci RKISP1_CIF_MI_SP_AUTOUPDATE_ENABLE; 50662306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 50762306a36Sopenharmony_ci} 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_cistatic void rkisp1_mp_disable(struct rkisp1_capture *cap) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci mi_ctrl &= ~(RKISP1_CIF_MI_CTRL_MP_ENABLE | 51462306a36Sopenharmony_ci RKISP1_CIF_MI_CTRL_RAW_ENABLE); 51562306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 51662306a36Sopenharmony_ci} 51762306a36Sopenharmony_ci 51862306a36Sopenharmony_cistatic void rkisp1_sp_disable(struct rkisp1_capture *cap) 51962306a36Sopenharmony_ci{ 52062306a36Sopenharmony_ci u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); 52162306a36Sopenharmony_ci 52262306a36Sopenharmony_ci mi_ctrl &= ~RKISP1_CIF_MI_CTRL_SP_ENABLE; 52362306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 52462306a36Sopenharmony_ci} 52562306a36Sopenharmony_ci 52662306a36Sopenharmony_cistatic void rkisp1_mp_enable(struct rkisp1_capture *cap) 52762306a36Sopenharmony_ci{ 52862306a36Sopenharmony_ci u32 mi_ctrl; 52962306a36Sopenharmony_ci 53062306a36Sopenharmony_ci rkisp1_mp_disable(cap); 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); 53362306a36Sopenharmony_ci if (v4l2_is_format_bayer(cap->pix.info)) 53462306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_RAW_ENABLE; 53562306a36Sopenharmony_ci /* YUV */ 53662306a36Sopenharmony_ci else 53762306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_MP_ENABLE; 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 54062306a36Sopenharmony_ci} 54162306a36Sopenharmony_ci 54262306a36Sopenharmony_cistatic void rkisp1_sp_enable(struct rkisp1_capture *cap) 54362306a36Sopenharmony_ci{ 54462306a36Sopenharmony_ci u32 mi_ctrl = rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL); 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci mi_ctrl |= RKISP1_CIF_MI_CTRL_SP_ENABLE; 54762306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_CTRL, mi_ctrl); 54862306a36Sopenharmony_ci} 54962306a36Sopenharmony_ci 55062306a36Sopenharmony_cistatic void rkisp1_mp_sp_stop(struct rkisp1_capture *cap) 55162306a36Sopenharmony_ci{ 55262306a36Sopenharmony_ci if (!cap->is_streaming) 55362306a36Sopenharmony_ci return; 55462306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_MI_ICR, RKISP1_CIF_MI_FRAME(cap)); 55562306a36Sopenharmony_ci cap->ops->disable(cap); 55662306a36Sopenharmony_ci} 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_cistatic bool rkisp1_mp_is_stopped(struct rkisp1_capture *cap) 55962306a36Sopenharmony_ci{ 56062306a36Sopenharmony_ci u32 en = RKISP1_CIF_MI_CTRL_SHD_MP_IN_ENABLED | 56162306a36Sopenharmony_ci RKISP1_CIF_MI_CTRL_SHD_RAW_OUT_ENABLED; 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & en); 56462306a36Sopenharmony_ci} 56562306a36Sopenharmony_ci 56662306a36Sopenharmony_cistatic bool rkisp1_sp_is_stopped(struct rkisp1_capture *cap) 56762306a36Sopenharmony_ci{ 56862306a36Sopenharmony_ci return !(rkisp1_read(cap->rkisp1, RKISP1_CIF_MI_CTRL_SHD) & 56962306a36Sopenharmony_ci RKISP1_CIF_MI_CTRL_SHD_SP_IN_ENABLED); 57062306a36Sopenharmony_ci} 57162306a36Sopenharmony_ci 57262306a36Sopenharmony_cistatic void rkisp1_mp_set_data_path(struct rkisp1_capture *cap) 57362306a36Sopenharmony_ci{ 57462306a36Sopenharmony_ci u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); 57562306a36Sopenharmony_ci 57662306a36Sopenharmony_ci dpcl = dpcl | RKISP1_CIF_VI_DPCL_CHAN_MODE_MP | 57762306a36Sopenharmony_ci RKISP1_CIF_VI_DPCL_MP_MUX_MRSZ_MI; 57862306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_VI_DPCL, dpcl); 57962306a36Sopenharmony_ci} 58062306a36Sopenharmony_ci 58162306a36Sopenharmony_cistatic void rkisp1_sp_set_data_path(struct rkisp1_capture *cap) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci u32 dpcl = rkisp1_read(cap->rkisp1, RKISP1_CIF_VI_DPCL); 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci dpcl |= RKISP1_CIF_VI_DPCL_CHAN_MODE_SP; 58662306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, RKISP1_CIF_VI_DPCL, dpcl); 58762306a36Sopenharmony_ci} 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_cistatic const struct rkisp1_capture_ops rkisp1_capture_ops_mp = { 59062306a36Sopenharmony_ci .config = rkisp1_mp_config, 59162306a36Sopenharmony_ci .enable = rkisp1_mp_enable, 59262306a36Sopenharmony_ci .disable = rkisp1_mp_disable, 59362306a36Sopenharmony_ci .stop = rkisp1_mp_sp_stop, 59462306a36Sopenharmony_ci .set_data_path = rkisp1_mp_set_data_path, 59562306a36Sopenharmony_ci .is_stopped = rkisp1_mp_is_stopped, 59662306a36Sopenharmony_ci}; 59762306a36Sopenharmony_ci 59862306a36Sopenharmony_cistatic const struct rkisp1_capture_ops rkisp1_capture_ops_sp = { 59962306a36Sopenharmony_ci .config = rkisp1_sp_config, 60062306a36Sopenharmony_ci .enable = rkisp1_sp_enable, 60162306a36Sopenharmony_ci .disable = rkisp1_sp_disable, 60262306a36Sopenharmony_ci .stop = rkisp1_mp_sp_stop, 60362306a36Sopenharmony_ci .set_data_path = rkisp1_sp_set_data_path, 60462306a36Sopenharmony_ci .is_stopped = rkisp1_sp_is_stopped, 60562306a36Sopenharmony_ci}; 60662306a36Sopenharmony_ci 60762306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 60862306a36Sopenharmony_ci * Frame buffer operations 60962306a36Sopenharmony_ci */ 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic int rkisp1_dummy_buf_create(struct rkisp1_capture *cap) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; 61462306a36Sopenharmony_ci struct rkisp1_dummy_buffer *dummy_buf = &cap->buf.dummy; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci dummy_buf->size = max3(rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y), 61762306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB), 61862306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CR)); 61962306a36Sopenharmony_ci 62062306a36Sopenharmony_ci /* The driver never access vaddr, no mapping is required */ 62162306a36Sopenharmony_ci dummy_buf->vaddr = dma_alloc_attrs(cap->rkisp1->dev, 62262306a36Sopenharmony_ci dummy_buf->size, 62362306a36Sopenharmony_ci &dummy_buf->dma_addr, 62462306a36Sopenharmony_ci GFP_KERNEL, 62562306a36Sopenharmony_ci DMA_ATTR_NO_KERNEL_MAPPING); 62662306a36Sopenharmony_ci if (!dummy_buf->vaddr) 62762306a36Sopenharmony_ci return -ENOMEM; 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_ci return 0; 63062306a36Sopenharmony_ci} 63162306a36Sopenharmony_ci 63262306a36Sopenharmony_cistatic void rkisp1_dummy_buf_destroy(struct rkisp1_capture *cap) 63362306a36Sopenharmony_ci{ 63462306a36Sopenharmony_ci dma_free_attrs(cap->rkisp1->dev, 63562306a36Sopenharmony_ci cap->buf.dummy.size, cap->buf.dummy.vaddr, 63662306a36Sopenharmony_ci cap->buf.dummy.dma_addr, DMA_ATTR_NO_KERNEL_MAPPING); 63762306a36Sopenharmony_ci} 63862306a36Sopenharmony_ci 63962306a36Sopenharmony_cistatic void rkisp1_set_next_buf(struct rkisp1_capture *cap) 64062306a36Sopenharmony_ci{ 64162306a36Sopenharmony_ci cap->buf.curr = cap->buf.next; 64262306a36Sopenharmony_ci cap->buf.next = NULL; 64362306a36Sopenharmony_ci 64462306a36Sopenharmony_ci if (!list_empty(&cap->buf.queue)) { 64562306a36Sopenharmony_ci u32 *buff_addr; 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci cap->buf.next = list_first_entry(&cap->buf.queue, struct rkisp1_buffer, queue); 64862306a36Sopenharmony_ci list_del(&cap->buf.next->queue); 64962306a36Sopenharmony_ci 65062306a36Sopenharmony_ci buff_addr = cap->buf.next->buff_addr; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.y_base_ad_init, 65362306a36Sopenharmony_ci buff_addr[RKISP1_PLANE_Y]); 65462306a36Sopenharmony_ci /* 65562306a36Sopenharmony_ci * In order to support grey format we capture 65662306a36Sopenharmony_ci * YUV422 planar format from the camera and 65762306a36Sopenharmony_ci * set the U and V planes to the dummy buffer 65862306a36Sopenharmony_ci */ 65962306a36Sopenharmony_ci if (cap->pix.cfg->fourcc == V4L2_PIX_FMT_GREY) { 66062306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, 66162306a36Sopenharmony_ci cap->config->mi.cb_base_ad_init, 66262306a36Sopenharmony_ci cap->buf.dummy.dma_addr); 66362306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, 66462306a36Sopenharmony_ci cap->config->mi.cr_base_ad_init, 66562306a36Sopenharmony_ci cap->buf.dummy.dma_addr); 66662306a36Sopenharmony_ci } else { 66762306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, 66862306a36Sopenharmony_ci cap->config->mi.cb_base_ad_init, 66962306a36Sopenharmony_ci buff_addr[RKISP1_PLANE_CB]); 67062306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, 67162306a36Sopenharmony_ci cap->config->mi.cr_base_ad_init, 67262306a36Sopenharmony_ci buff_addr[RKISP1_PLANE_CR]); 67362306a36Sopenharmony_ci } 67462306a36Sopenharmony_ci } else { 67562306a36Sopenharmony_ci /* 67662306a36Sopenharmony_ci * Use the dummy space allocated by dma_alloc_coherent to 67762306a36Sopenharmony_ci * throw data if there is no available buffer. 67862306a36Sopenharmony_ci */ 67962306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.y_base_ad_init, 68062306a36Sopenharmony_ci cap->buf.dummy.dma_addr); 68162306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.cb_base_ad_init, 68262306a36Sopenharmony_ci cap->buf.dummy.dma_addr); 68362306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.cr_base_ad_init, 68462306a36Sopenharmony_ci cap->buf.dummy.dma_addr); 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci 68762306a36Sopenharmony_ci /* Set plane offsets */ 68862306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.y_offs_cnt_init, 0); 68962306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.cb_offs_cnt_init, 0); 69062306a36Sopenharmony_ci rkisp1_write(cap->rkisp1, cap->config->mi.cr_offs_cnt_init, 0); 69162306a36Sopenharmony_ci} 69262306a36Sopenharmony_ci 69362306a36Sopenharmony_ci/* 69462306a36Sopenharmony_ci * This function is called when a frame end comes. The next frame 69562306a36Sopenharmony_ci * is processing and we should set up buffer for next-next frame, 69662306a36Sopenharmony_ci * otherwise it will overflow. 69762306a36Sopenharmony_ci */ 69862306a36Sopenharmony_cistatic void rkisp1_handle_buffer(struct rkisp1_capture *cap) 69962306a36Sopenharmony_ci{ 70062306a36Sopenharmony_ci struct rkisp1_isp *isp = &cap->rkisp1->isp; 70162306a36Sopenharmony_ci struct rkisp1_buffer *curr_buf; 70262306a36Sopenharmony_ci 70362306a36Sopenharmony_ci spin_lock(&cap->buf.lock); 70462306a36Sopenharmony_ci curr_buf = cap->buf.curr; 70562306a36Sopenharmony_ci 70662306a36Sopenharmony_ci if (curr_buf) { 70762306a36Sopenharmony_ci curr_buf->vb.sequence = isp->frame_sequence; 70862306a36Sopenharmony_ci curr_buf->vb.vb2_buf.timestamp = ktime_get_boottime_ns(); 70962306a36Sopenharmony_ci curr_buf->vb.field = V4L2_FIELD_NONE; 71062306a36Sopenharmony_ci vb2_buffer_done(&curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE); 71162306a36Sopenharmony_ci } else { 71262306a36Sopenharmony_ci cap->rkisp1->debug.frame_drop[cap->id]++; 71362306a36Sopenharmony_ci } 71462306a36Sopenharmony_ci 71562306a36Sopenharmony_ci rkisp1_set_next_buf(cap); 71662306a36Sopenharmony_ci spin_unlock(&cap->buf.lock); 71762306a36Sopenharmony_ci} 71862306a36Sopenharmony_ci 71962306a36Sopenharmony_ciirqreturn_t rkisp1_capture_isr(int irq, void *ctx) 72062306a36Sopenharmony_ci{ 72162306a36Sopenharmony_ci struct device *dev = ctx; 72262306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = dev_get_drvdata(dev); 72362306a36Sopenharmony_ci unsigned int i; 72462306a36Sopenharmony_ci u32 status; 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci if (!rkisp1->irqs_enabled) 72762306a36Sopenharmony_ci return IRQ_NONE; 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci status = rkisp1_read(rkisp1, RKISP1_CIF_MI_MIS); 73062306a36Sopenharmony_ci if (!status) 73162306a36Sopenharmony_ci return IRQ_NONE; 73262306a36Sopenharmony_ci 73362306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_ICR, status); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); ++i) { 73662306a36Sopenharmony_ci struct rkisp1_capture *cap = &rkisp1->capture_devs[i]; 73762306a36Sopenharmony_ci 73862306a36Sopenharmony_ci if (!(status & RKISP1_CIF_MI_FRAME(cap))) 73962306a36Sopenharmony_ci continue; 74062306a36Sopenharmony_ci if (!cap->is_stopping) { 74162306a36Sopenharmony_ci rkisp1_handle_buffer(cap); 74262306a36Sopenharmony_ci continue; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci /* 74562306a36Sopenharmony_ci * Make sure stream is actually stopped, whose state 74662306a36Sopenharmony_ci * can be read from the shadow register, before 74762306a36Sopenharmony_ci * wake_up() thread which would immediately free all 74862306a36Sopenharmony_ci * frame buffers. stop() takes effect at the next 74962306a36Sopenharmony_ci * frame end that sync the configurations to shadow 75062306a36Sopenharmony_ci * regs. 75162306a36Sopenharmony_ci */ 75262306a36Sopenharmony_ci if (!cap->ops->is_stopped(cap)) { 75362306a36Sopenharmony_ci cap->ops->stop(cap); 75462306a36Sopenharmony_ci continue; 75562306a36Sopenharmony_ci } 75662306a36Sopenharmony_ci cap->is_stopping = false; 75762306a36Sopenharmony_ci cap->is_streaming = false; 75862306a36Sopenharmony_ci wake_up(&cap->done); 75962306a36Sopenharmony_ci } 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return IRQ_HANDLED; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 76562306a36Sopenharmony_ci * Vb2 operations 76662306a36Sopenharmony_ci */ 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_cistatic int rkisp1_vb2_queue_setup(struct vb2_queue *queue, 76962306a36Sopenharmony_ci unsigned int *num_buffers, 77062306a36Sopenharmony_ci unsigned int *num_planes, 77162306a36Sopenharmony_ci unsigned int sizes[], 77262306a36Sopenharmony_ci struct device *alloc_devs[]) 77362306a36Sopenharmony_ci{ 77462306a36Sopenharmony_ci struct rkisp1_capture *cap = queue->drv_priv; 77562306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; 77662306a36Sopenharmony_ci unsigned int i; 77762306a36Sopenharmony_ci 77862306a36Sopenharmony_ci if (*num_planes) { 77962306a36Sopenharmony_ci if (*num_planes != pixm->num_planes) 78062306a36Sopenharmony_ci return -EINVAL; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci for (i = 0; i < pixm->num_planes; i++) 78362306a36Sopenharmony_ci if (sizes[i] < pixm->plane_fmt[i].sizeimage) 78462306a36Sopenharmony_ci return -EINVAL; 78562306a36Sopenharmony_ci } else { 78662306a36Sopenharmony_ci *num_planes = pixm->num_planes; 78762306a36Sopenharmony_ci for (i = 0; i < pixm->num_planes; i++) 78862306a36Sopenharmony_ci sizes[i] = pixm->plane_fmt[i].sizeimage; 78962306a36Sopenharmony_ci } 79062306a36Sopenharmony_ci 79162306a36Sopenharmony_ci return 0; 79262306a36Sopenharmony_ci} 79362306a36Sopenharmony_ci 79462306a36Sopenharmony_cistatic int rkisp1_vb2_buf_init(struct vb2_buffer *vb) 79562306a36Sopenharmony_ci{ 79662306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 79762306a36Sopenharmony_ci struct rkisp1_buffer *ispbuf = 79862306a36Sopenharmony_ci container_of(vbuf, struct rkisp1_buffer, vb); 79962306a36Sopenharmony_ci struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; 80062306a36Sopenharmony_ci const struct v4l2_pix_format_mplane *pixm = &cap->pix.fmt; 80162306a36Sopenharmony_ci unsigned int i; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci memset(ispbuf->buff_addr, 0, sizeof(ispbuf->buff_addr)); 80462306a36Sopenharmony_ci for (i = 0; i < pixm->num_planes; i++) 80562306a36Sopenharmony_ci ispbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i); 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci /* Convert to non-MPLANE */ 80862306a36Sopenharmony_ci if (pixm->num_planes == 1) { 80962306a36Sopenharmony_ci ispbuf->buff_addr[RKISP1_PLANE_CB] = 81062306a36Sopenharmony_ci ispbuf->buff_addr[RKISP1_PLANE_Y] + 81162306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_Y); 81262306a36Sopenharmony_ci ispbuf->buff_addr[RKISP1_PLANE_CR] = 81362306a36Sopenharmony_ci ispbuf->buff_addr[RKISP1_PLANE_CB] + 81462306a36Sopenharmony_ci rkisp1_pixfmt_comp_size(pixm, RKISP1_PLANE_CB); 81562306a36Sopenharmony_ci } 81662306a36Sopenharmony_ci 81762306a36Sopenharmony_ci /* 81862306a36Sopenharmony_ci * uv swap can be supported for planar formats by switching 81962306a36Sopenharmony_ci * the address of cb and cr 82062306a36Sopenharmony_ci */ 82162306a36Sopenharmony_ci if (cap->pix.info->comp_planes == 3 && cap->pix.cfg->uv_swap) 82262306a36Sopenharmony_ci swap(ispbuf->buff_addr[RKISP1_PLANE_CR], 82362306a36Sopenharmony_ci ispbuf->buff_addr[RKISP1_PLANE_CB]); 82462306a36Sopenharmony_ci return 0; 82562306a36Sopenharmony_ci} 82662306a36Sopenharmony_ci 82762306a36Sopenharmony_cistatic void rkisp1_vb2_buf_queue(struct vb2_buffer *vb) 82862306a36Sopenharmony_ci{ 82962306a36Sopenharmony_ci struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb); 83062306a36Sopenharmony_ci struct rkisp1_buffer *ispbuf = 83162306a36Sopenharmony_ci container_of(vbuf, struct rkisp1_buffer, vb); 83262306a36Sopenharmony_ci struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci spin_lock_irq(&cap->buf.lock); 83562306a36Sopenharmony_ci list_add_tail(&ispbuf->queue, &cap->buf.queue); 83662306a36Sopenharmony_ci spin_unlock_irq(&cap->buf.lock); 83762306a36Sopenharmony_ci} 83862306a36Sopenharmony_ci 83962306a36Sopenharmony_cistatic int rkisp1_vb2_buf_prepare(struct vb2_buffer *vb) 84062306a36Sopenharmony_ci{ 84162306a36Sopenharmony_ci struct rkisp1_capture *cap = vb->vb2_queue->drv_priv; 84262306a36Sopenharmony_ci unsigned int i; 84362306a36Sopenharmony_ci 84462306a36Sopenharmony_ci for (i = 0; i < cap->pix.fmt.num_planes; i++) { 84562306a36Sopenharmony_ci unsigned long size = cap->pix.fmt.plane_fmt[i].sizeimage; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if (vb2_plane_size(vb, i) < size) { 84862306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, 84962306a36Sopenharmony_ci "User buffer too small (%ld < %ld)\n", 85062306a36Sopenharmony_ci vb2_plane_size(vb, i), size); 85162306a36Sopenharmony_ci return -EINVAL; 85262306a36Sopenharmony_ci } 85362306a36Sopenharmony_ci vb2_set_plane_payload(vb, i, size); 85462306a36Sopenharmony_ci } 85562306a36Sopenharmony_ci 85662306a36Sopenharmony_ci return 0; 85762306a36Sopenharmony_ci} 85862306a36Sopenharmony_ci 85962306a36Sopenharmony_cistatic void rkisp1_return_all_buffers(struct rkisp1_capture *cap, 86062306a36Sopenharmony_ci enum vb2_buffer_state state) 86162306a36Sopenharmony_ci{ 86262306a36Sopenharmony_ci struct rkisp1_buffer *buf; 86362306a36Sopenharmony_ci 86462306a36Sopenharmony_ci spin_lock_irq(&cap->buf.lock); 86562306a36Sopenharmony_ci if (cap->buf.curr) { 86662306a36Sopenharmony_ci vb2_buffer_done(&cap->buf.curr->vb.vb2_buf, state); 86762306a36Sopenharmony_ci cap->buf.curr = NULL; 86862306a36Sopenharmony_ci } 86962306a36Sopenharmony_ci if (cap->buf.next) { 87062306a36Sopenharmony_ci vb2_buffer_done(&cap->buf.next->vb.vb2_buf, state); 87162306a36Sopenharmony_ci cap->buf.next = NULL; 87262306a36Sopenharmony_ci } 87362306a36Sopenharmony_ci while (!list_empty(&cap->buf.queue)) { 87462306a36Sopenharmony_ci buf = list_first_entry(&cap->buf.queue, 87562306a36Sopenharmony_ci struct rkisp1_buffer, queue); 87662306a36Sopenharmony_ci list_del(&buf->queue); 87762306a36Sopenharmony_ci vb2_buffer_done(&buf->vb.vb2_buf, state); 87862306a36Sopenharmony_ci } 87962306a36Sopenharmony_ci spin_unlock_irq(&cap->buf.lock); 88062306a36Sopenharmony_ci} 88162306a36Sopenharmony_ci 88262306a36Sopenharmony_ci/* 88362306a36Sopenharmony_ci * Most registers inside the rockchip ISP1 have shadow register since 88462306a36Sopenharmony_ci * they must not be changed while processing a frame. 88562306a36Sopenharmony_ci * Usually, each sub-module updates its shadow register after 88662306a36Sopenharmony_ci * processing the last pixel of a frame. 88762306a36Sopenharmony_ci */ 88862306a36Sopenharmony_cistatic void rkisp1_cap_stream_enable(struct rkisp1_capture *cap) 88962306a36Sopenharmony_ci{ 89062306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 89162306a36Sopenharmony_ci struct rkisp1_capture *other = &rkisp1->capture_devs[cap->id ^ 1]; 89262306a36Sopenharmony_ci 89362306a36Sopenharmony_ci cap->ops->set_data_path(cap); 89462306a36Sopenharmony_ci cap->ops->config(cap); 89562306a36Sopenharmony_ci 89662306a36Sopenharmony_ci /* Setup a buffer for the next frame */ 89762306a36Sopenharmony_ci spin_lock_irq(&cap->buf.lock); 89862306a36Sopenharmony_ci rkisp1_set_next_buf(cap); 89962306a36Sopenharmony_ci cap->ops->enable(cap); 90062306a36Sopenharmony_ci /* It's safe to configure ACTIVE and SHADOW registers for the 90162306a36Sopenharmony_ci * first stream. While when the second is starting, do NOT 90262306a36Sopenharmony_ci * force update because it also updates the first one. 90362306a36Sopenharmony_ci * 90462306a36Sopenharmony_ci * The latter case would drop one more buffer(that is 2) since 90562306a36Sopenharmony_ci * there's no buffer in a shadow register when the second FE received. 90662306a36Sopenharmony_ci * This's also required because the second FE maybe corrupt 90762306a36Sopenharmony_ci * especially when run at 120fps. 90862306a36Sopenharmony_ci */ 90962306a36Sopenharmony_ci if (!other->is_streaming) { 91062306a36Sopenharmony_ci /* force cfg update */ 91162306a36Sopenharmony_ci rkisp1_write(rkisp1, RKISP1_CIF_MI_INIT, 91262306a36Sopenharmony_ci RKISP1_CIF_MI_INIT_SOFT_UPD); 91362306a36Sopenharmony_ci rkisp1_set_next_buf(cap); 91462306a36Sopenharmony_ci } 91562306a36Sopenharmony_ci spin_unlock_irq(&cap->buf.lock); 91662306a36Sopenharmony_ci cap->is_streaming = true; 91762306a36Sopenharmony_ci} 91862306a36Sopenharmony_ci 91962306a36Sopenharmony_cistatic void rkisp1_cap_stream_disable(struct rkisp1_capture *cap) 92062306a36Sopenharmony_ci{ 92162306a36Sopenharmony_ci int ret; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci /* Stream should stop in interrupt. If it doesn't, stop it by force. */ 92462306a36Sopenharmony_ci cap->is_stopping = true; 92562306a36Sopenharmony_ci ret = wait_event_timeout(cap->done, 92662306a36Sopenharmony_ci !cap->is_streaming, 92762306a36Sopenharmony_ci msecs_to_jiffies(1000)); 92862306a36Sopenharmony_ci if (!ret) { 92962306a36Sopenharmony_ci cap->rkisp1->debug.stop_timeout[cap->id]++; 93062306a36Sopenharmony_ci cap->ops->stop(cap); 93162306a36Sopenharmony_ci cap->is_stopping = false; 93262306a36Sopenharmony_ci cap->is_streaming = false; 93362306a36Sopenharmony_ci } 93462306a36Sopenharmony_ci} 93562306a36Sopenharmony_ci 93662306a36Sopenharmony_ci/* 93762306a36Sopenharmony_ci * rkisp1_pipeline_stream_disable - disable nodes in the pipeline 93862306a36Sopenharmony_ci * 93962306a36Sopenharmony_ci * Call s_stream(false) in the reverse order from 94062306a36Sopenharmony_ci * rkisp1_pipeline_stream_enable() and disable the DMA engine. 94162306a36Sopenharmony_ci * Should be called before video_device_pipeline_stop() 94262306a36Sopenharmony_ci */ 94362306a36Sopenharmony_cistatic void rkisp1_pipeline_stream_disable(struct rkisp1_capture *cap) 94462306a36Sopenharmony_ci __must_hold(&cap->rkisp1->stream_lock) 94562306a36Sopenharmony_ci{ 94662306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 94762306a36Sopenharmony_ci 94862306a36Sopenharmony_ci rkisp1_cap_stream_disable(cap); 94962306a36Sopenharmony_ci 95062306a36Sopenharmony_ci /* 95162306a36Sopenharmony_ci * If the other capture is streaming, isp and sensor nodes shouldn't 95262306a36Sopenharmony_ci * be disabled, skip them. 95362306a36Sopenharmony_ci */ 95462306a36Sopenharmony_ci if (rkisp1->pipe.start_count < 2) 95562306a36Sopenharmony_ci v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, false); 95662306a36Sopenharmony_ci 95762306a36Sopenharmony_ci v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, 95862306a36Sopenharmony_ci false); 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_ci/* 96262306a36Sopenharmony_ci * rkisp1_pipeline_stream_enable - enable nodes in the pipeline 96362306a36Sopenharmony_ci * 96462306a36Sopenharmony_ci * Enable the DMA Engine and call s_stream(true) through the pipeline. 96562306a36Sopenharmony_ci * Should be called after video_device_pipeline_start() 96662306a36Sopenharmony_ci */ 96762306a36Sopenharmony_cistatic int rkisp1_pipeline_stream_enable(struct rkisp1_capture *cap) 96862306a36Sopenharmony_ci __must_hold(&cap->rkisp1->stream_lock) 96962306a36Sopenharmony_ci{ 97062306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 97162306a36Sopenharmony_ci int ret; 97262306a36Sopenharmony_ci 97362306a36Sopenharmony_ci rkisp1_cap_stream_enable(cap); 97462306a36Sopenharmony_ci 97562306a36Sopenharmony_ci ret = v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, 97662306a36Sopenharmony_ci s_stream, true); 97762306a36Sopenharmony_ci if (ret) 97862306a36Sopenharmony_ci goto err_disable_cap; 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci /* 98162306a36Sopenharmony_ci * If the other capture is streaming, isp and sensor nodes are already 98262306a36Sopenharmony_ci * enabled, skip them. 98362306a36Sopenharmony_ci */ 98462306a36Sopenharmony_ci if (rkisp1->pipe.start_count > 1) 98562306a36Sopenharmony_ci return 0; 98662306a36Sopenharmony_ci 98762306a36Sopenharmony_ci ret = v4l2_subdev_call(&rkisp1->isp.sd, video, s_stream, true); 98862306a36Sopenharmony_ci if (ret) 98962306a36Sopenharmony_ci goto err_disable_rsz; 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci return 0; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_cierr_disable_rsz: 99462306a36Sopenharmony_ci v4l2_subdev_call(&rkisp1->resizer_devs[cap->id].sd, video, s_stream, 99562306a36Sopenharmony_ci false); 99662306a36Sopenharmony_cierr_disable_cap: 99762306a36Sopenharmony_ci rkisp1_cap_stream_disable(cap); 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_ci return ret; 100062306a36Sopenharmony_ci} 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_cistatic void rkisp1_vb2_stop_streaming(struct vb2_queue *queue) 100362306a36Sopenharmony_ci{ 100462306a36Sopenharmony_ci struct rkisp1_capture *cap = queue->drv_priv; 100562306a36Sopenharmony_ci struct rkisp1_vdev_node *node = &cap->vnode; 100662306a36Sopenharmony_ci struct rkisp1_device *rkisp1 = cap->rkisp1; 100762306a36Sopenharmony_ci int ret; 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci mutex_lock(&cap->rkisp1->stream_lock); 101062306a36Sopenharmony_ci 101162306a36Sopenharmony_ci rkisp1_pipeline_stream_disable(cap); 101262306a36Sopenharmony_ci 101362306a36Sopenharmony_ci rkisp1_return_all_buffers(cap, VB2_BUF_STATE_ERROR); 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci v4l2_pipeline_pm_put(&node->vdev.entity); 101662306a36Sopenharmony_ci ret = pm_runtime_put(rkisp1->dev); 101762306a36Sopenharmony_ci if (ret < 0) 101862306a36Sopenharmony_ci dev_err(rkisp1->dev, "power down failed error:%d\n", ret); 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci rkisp1_dummy_buf_destroy(cap); 102162306a36Sopenharmony_ci 102262306a36Sopenharmony_ci video_device_pipeline_stop(&node->vdev); 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci mutex_unlock(&cap->rkisp1->stream_lock); 102562306a36Sopenharmony_ci} 102662306a36Sopenharmony_ci 102762306a36Sopenharmony_cistatic int 102862306a36Sopenharmony_cirkisp1_vb2_start_streaming(struct vb2_queue *queue, unsigned int count) 102962306a36Sopenharmony_ci{ 103062306a36Sopenharmony_ci struct rkisp1_capture *cap = queue->drv_priv; 103162306a36Sopenharmony_ci struct media_entity *entity = &cap->vnode.vdev.entity; 103262306a36Sopenharmony_ci int ret; 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_ci mutex_lock(&cap->rkisp1->stream_lock); 103562306a36Sopenharmony_ci 103662306a36Sopenharmony_ci ret = video_device_pipeline_start(&cap->vnode.vdev, &cap->rkisp1->pipe); 103762306a36Sopenharmony_ci if (ret) { 103862306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, "start pipeline failed %d\n", ret); 103962306a36Sopenharmony_ci goto err_ret_buffers; 104062306a36Sopenharmony_ci } 104162306a36Sopenharmony_ci 104262306a36Sopenharmony_ci ret = rkisp1_dummy_buf_create(cap); 104362306a36Sopenharmony_ci if (ret) 104462306a36Sopenharmony_ci goto err_pipeline_stop; 104562306a36Sopenharmony_ci 104662306a36Sopenharmony_ci ret = pm_runtime_resume_and_get(cap->rkisp1->dev); 104762306a36Sopenharmony_ci if (ret < 0) { 104862306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, "power up failed %d\n", ret); 104962306a36Sopenharmony_ci goto err_destroy_dummy; 105062306a36Sopenharmony_ci } 105162306a36Sopenharmony_ci ret = v4l2_pipeline_pm_get(entity); 105262306a36Sopenharmony_ci if (ret) { 105362306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, "open cif pipeline failed %d\n", ret); 105462306a36Sopenharmony_ci goto err_pipe_pm_put; 105562306a36Sopenharmony_ci } 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci ret = rkisp1_pipeline_stream_enable(cap); 105862306a36Sopenharmony_ci if (ret) 105962306a36Sopenharmony_ci goto err_v4l2_pm_put; 106062306a36Sopenharmony_ci 106162306a36Sopenharmony_ci mutex_unlock(&cap->rkisp1->stream_lock); 106262306a36Sopenharmony_ci 106362306a36Sopenharmony_ci return 0; 106462306a36Sopenharmony_ci 106562306a36Sopenharmony_cierr_v4l2_pm_put: 106662306a36Sopenharmony_ci v4l2_pipeline_pm_put(entity); 106762306a36Sopenharmony_cierr_pipe_pm_put: 106862306a36Sopenharmony_ci pm_runtime_put(cap->rkisp1->dev); 106962306a36Sopenharmony_cierr_destroy_dummy: 107062306a36Sopenharmony_ci rkisp1_dummy_buf_destroy(cap); 107162306a36Sopenharmony_cierr_pipeline_stop: 107262306a36Sopenharmony_ci video_device_pipeline_stop(&cap->vnode.vdev); 107362306a36Sopenharmony_cierr_ret_buffers: 107462306a36Sopenharmony_ci rkisp1_return_all_buffers(cap, VB2_BUF_STATE_QUEUED); 107562306a36Sopenharmony_ci mutex_unlock(&cap->rkisp1->stream_lock); 107662306a36Sopenharmony_ci 107762306a36Sopenharmony_ci return ret; 107862306a36Sopenharmony_ci} 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_cistatic const struct vb2_ops rkisp1_vb2_ops = { 108162306a36Sopenharmony_ci .queue_setup = rkisp1_vb2_queue_setup, 108262306a36Sopenharmony_ci .buf_init = rkisp1_vb2_buf_init, 108362306a36Sopenharmony_ci .buf_queue = rkisp1_vb2_buf_queue, 108462306a36Sopenharmony_ci .buf_prepare = rkisp1_vb2_buf_prepare, 108562306a36Sopenharmony_ci .wait_prepare = vb2_ops_wait_prepare, 108662306a36Sopenharmony_ci .wait_finish = vb2_ops_wait_finish, 108762306a36Sopenharmony_ci .stop_streaming = rkisp1_vb2_stop_streaming, 108862306a36Sopenharmony_ci .start_streaming = rkisp1_vb2_start_streaming, 108962306a36Sopenharmony_ci}; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 109262306a36Sopenharmony_ci * IOCTLs operations 109362306a36Sopenharmony_ci */ 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_cistatic const struct v4l2_format_info * 109662306a36Sopenharmony_cirkisp1_fill_pixfmt(struct v4l2_pix_format_mplane *pixm, 109762306a36Sopenharmony_ci enum rkisp1_stream_id id) 109862306a36Sopenharmony_ci{ 109962306a36Sopenharmony_ci struct v4l2_plane_pix_format *plane_y = &pixm->plane_fmt[0]; 110062306a36Sopenharmony_ci const struct v4l2_format_info *info; 110162306a36Sopenharmony_ci unsigned int i; 110262306a36Sopenharmony_ci u32 stride; 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci memset(pixm->plane_fmt, 0, sizeof(pixm->plane_fmt)); 110562306a36Sopenharmony_ci info = v4l2_format_info(pixm->pixelformat); 110662306a36Sopenharmony_ci pixm->num_planes = info->mem_planes; 110762306a36Sopenharmony_ci stride = info->bpp[0] * pixm->width; 110862306a36Sopenharmony_ci /* Self path supports custom stride but Main path doesn't */ 110962306a36Sopenharmony_ci if (id == RKISP1_MAINPATH || plane_y->bytesperline < stride) 111062306a36Sopenharmony_ci plane_y->bytesperline = stride; 111162306a36Sopenharmony_ci plane_y->sizeimage = plane_y->bytesperline * pixm->height; 111262306a36Sopenharmony_ci 111362306a36Sopenharmony_ci /* normalize stride to pixels per line */ 111462306a36Sopenharmony_ci stride = DIV_ROUND_UP(plane_y->bytesperline, info->bpp[0]); 111562306a36Sopenharmony_ci 111662306a36Sopenharmony_ci for (i = 1; i < info->comp_planes; i++) { 111762306a36Sopenharmony_ci struct v4l2_plane_pix_format *plane = &pixm->plane_fmt[i]; 111862306a36Sopenharmony_ci 111962306a36Sopenharmony_ci /* bytesperline for other components derive from Y component */ 112062306a36Sopenharmony_ci plane->bytesperline = DIV_ROUND_UP(stride, info->hdiv) * 112162306a36Sopenharmony_ci info->bpp[i]; 112262306a36Sopenharmony_ci plane->sizeimage = plane->bytesperline * 112362306a36Sopenharmony_ci DIV_ROUND_UP(pixm->height, info->vdiv); 112462306a36Sopenharmony_ci } 112562306a36Sopenharmony_ci 112662306a36Sopenharmony_ci /* 112762306a36Sopenharmony_ci * If pixfmt is packed, then plane_fmt[0] should contain the total size 112862306a36Sopenharmony_ci * considering all components. plane_fmt[i] for i > 0 should be ignored 112962306a36Sopenharmony_ci * by userspace as mem_planes == 1, but we are keeping information there 113062306a36Sopenharmony_ci * for convenience. 113162306a36Sopenharmony_ci */ 113262306a36Sopenharmony_ci if (info->mem_planes == 1) 113362306a36Sopenharmony_ci for (i = 1; i < info->comp_planes; i++) 113462306a36Sopenharmony_ci plane_y->sizeimage += pixm->plane_fmt[i].sizeimage; 113562306a36Sopenharmony_ci 113662306a36Sopenharmony_ci return info; 113762306a36Sopenharmony_ci} 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_cistatic const struct rkisp1_capture_fmt_cfg * 114062306a36Sopenharmony_cirkisp1_find_fmt_cfg(const struct rkisp1_capture *cap, const u32 pixelfmt) 114162306a36Sopenharmony_ci{ 114262306a36Sopenharmony_ci unsigned int i; 114362306a36Sopenharmony_ci 114462306a36Sopenharmony_ci for (i = 0; i < cap->config->fmt_size; i++) { 114562306a36Sopenharmony_ci if (cap->config->fmts[i].fourcc == pixelfmt) 114662306a36Sopenharmony_ci return &cap->config->fmts[i]; 114762306a36Sopenharmony_ci } 114862306a36Sopenharmony_ci return NULL; 114962306a36Sopenharmony_ci} 115062306a36Sopenharmony_ci 115162306a36Sopenharmony_cistatic void rkisp1_try_fmt(const struct rkisp1_capture *cap, 115262306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pixm, 115362306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg **fmt_cfg, 115462306a36Sopenharmony_ci const struct v4l2_format_info **fmt_info) 115562306a36Sopenharmony_ci{ 115662306a36Sopenharmony_ci const struct rkisp1_capture_config *config = cap->config; 115762306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg *fmt; 115862306a36Sopenharmony_ci const struct v4l2_format_info *info; 115962306a36Sopenharmony_ci static const unsigned int max_widths[] = { 116062306a36Sopenharmony_ci RKISP1_RSZ_MP_SRC_MAX_WIDTH, RKISP1_RSZ_SP_SRC_MAX_WIDTH 116162306a36Sopenharmony_ci }; 116262306a36Sopenharmony_ci static const unsigned int max_heights[] = { 116362306a36Sopenharmony_ci RKISP1_RSZ_MP_SRC_MAX_HEIGHT, RKISP1_RSZ_SP_SRC_MAX_HEIGHT 116462306a36Sopenharmony_ci }; 116562306a36Sopenharmony_ci 116662306a36Sopenharmony_ci fmt = rkisp1_find_fmt_cfg(cap, pixm->pixelformat); 116762306a36Sopenharmony_ci if (!fmt) { 116862306a36Sopenharmony_ci fmt = config->fmts; 116962306a36Sopenharmony_ci pixm->pixelformat = fmt->fourcc; 117062306a36Sopenharmony_ci } 117162306a36Sopenharmony_ci 117262306a36Sopenharmony_ci pixm->width = clamp_t(u32, pixm->width, 117362306a36Sopenharmony_ci RKISP1_RSZ_SRC_MIN_WIDTH, max_widths[cap->id]); 117462306a36Sopenharmony_ci pixm->height = clamp_t(u32, pixm->height, 117562306a36Sopenharmony_ci RKISP1_RSZ_SRC_MIN_HEIGHT, max_heights[cap->id]); 117662306a36Sopenharmony_ci 117762306a36Sopenharmony_ci pixm->field = V4L2_FIELD_NONE; 117862306a36Sopenharmony_ci pixm->colorspace = V4L2_COLORSPACE_DEFAULT; 117962306a36Sopenharmony_ci pixm->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT; 118062306a36Sopenharmony_ci pixm->quantization = V4L2_QUANTIZATION_DEFAULT; 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci info = rkisp1_fill_pixfmt(pixm, cap->id); 118362306a36Sopenharmony_ci 118462306a36Sopenharmony_ci if (fmt_cfg) 118562306a36Sopenharmony_ci *fmt_cfg = fmt; 118662306a36Sopenharmony_ci if (fmt_info) 118762306a36Sopenharmony_ci *fmt_info = info; 118862306a36Sopenharmony_ci} 118962306a36Sopenharmony_ci 119062306a36Sopenharmony_cistatic void rkisp1_set_fmt(struct rkisp1_capture *cap, 119162306a36Sopenharmony_ci struct v4l2_pix_format_mplane *pixm) 119262306a36Sopenharmony_ci{ 119362306a36Sopenharmony_ci rkisp1_try_fmt(cap, pixm, &cap->pix.cfg, &cap->pix.info); 119462306a36Sopenharmony_ci cap->pix.fmt = *pixm; 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci /* SP supports custom stride in number of pixels of the Y plane */ 119762306a36Sopenharmony_ci if (cap->id == RKISP1_SELFPATH) 119862306a36Sopenharmony_ci cap->sp_y_stride = pixm->plane_fmt[0].bytesperline / 119962306a36Sopenharmony_ci cap->pix.info->bpp[0]; 120062306a36Sopenharmony_ci} 120162306a36Sopenharmony_ci 120262306a36Sopenharmony_cistatic int rkisp1_try_fmt_vid_cap_mplane(struct file *file, void *fh, 120362306a36Sopenharmony_ci struct v4l2_format *f) 120462306a36Sopenharmony_ci{ 120562306a36Sopenharmony_ci struct rkisp1_capture *cap = video_drvdata(file); 120662306a36Sopenharmony_ci 120762306a36Sopenharmony_ci rkisp1_try_fmt(cap, &f->fmt.pix_mp, NULL, NULL); 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci return 0; 121062306a36Sopenharmony_ci} 121162306a36Sopenharmony_ci 121262306a36Sopenharmony_cistatic int rkisp1_enum_fmt_vid_cap_mplane(struct file *file, void *priv, 121362306a36Sopenharmony_ci struct v4l2_fmtdesc *f) 121462306a36Sopenharmony_ci{ 121562306a36Sopenharmony_ci struct rkisp1_capture *cap = video_drvdata(file); 121662306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg *fmt = NULL; 121762306a36Sopenharmony_ci unsigned int i, n = 0; 121862306a36Sopenharmony_ci 121962306a36Sopenharmony_ci if (!f->mbus_code) { 122062306a36Sopenharmony_ci if (f->index >= cap->config->fmt_size) 122162306a36Sopenharmony_ci return -EINVAL; 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci fmt = &cap->config->fmts[f->index]; 122462306a36Sopenharmony_ci f->pixelformat = fmt->fourcc; 122562306a36Sopenharmony_ci return 0; 122662306a36Sopenharmony_ci } 122762306a36Sopenharmony_ci 122862306a36Sopenharmony_ci for (i = 0; i < cap->config->fmt_size; i++) { 122962306a36Sopenharmony_ci if (cap->config->fmts[i].mbus != f->mbus_code) 123062306a36Sopenharmony_ci continue; 123162306a36Sopenharmony_ci 123262306a36Sopenharmony_ci if (n++ == f->index) { 123362306a36Sopenharmony_ci f->pixelformat = cap->config->fmts[i].fourcc; 123462306a36Sopenharmony_ci return 0; 123562306a36Sopenharmony_ci } 123662306a36Sopenharmony_ci } 123762306a36Sopenharmony_ci return -EINVAL; 123862306a36Sopenharmony_ci} 123962306a36Sopenharmony_ci 124062306a36Sopenharmony_cistatic int rkisp1_enum_framesizes(struct file *file, void *fh, 124162306a36Sopenharmony_ci struct v4l2_frmsizeenum *fsize) 124262306a36Sopenharmony_ci{ 124362306a36Sopenharmony_ci static const unsigned int max_widths[] = { 124462306a36Sopenharmony_ci RKISP1_RSZ_MP_SRC_MAX_WIDTH, 124562306a36Sopenharmony_ci RKISP1_RSZ_SP_SRC_MAX_WIDTH, 124662306a36Sopenharmony_ci }; 124762306a36Sopenharmony_ci static const unsigned int max_heights[] = { 124862306a36Sopenharmony_ci RKISP1_RSZ_MP_SRC_MAX_HEIGHT, 124962306a36Sopenharmony_ci RKISP1_RSZ_SP_SRC_MAX_HEIGHT, 125062306a36Sopenharmony_ci }; 125162306a36Sopenharmony_ci struct rkisp1_capture *cap = video_drvdata(file); 125262306a36Sopenharmony_ci 125362306a36Sopenharmony_ci if (fsize->index != 0) 125462306a36Sopenharmony_ci return -EINVAL; 125562306a36Sopenharmony_ci 125662306a36Sopenharmony_ci fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE; 125762306a36Sopenharmony_ci 125862306a36Sopenharmony_ci fsize->stepwise.min_width = RKISP1_RSZ_SRC_MIN_WIDTH; 125962306a36Sopenharmony_ci fsize->stepwise.max_width = max_widths[cap->id]; 126062306a36Sopenharmony_ci fsize->stepwise.step_width = 2; 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci fsize->stepwise.min_height = RKISP1_RSZ_SRC_MIN_HEIGHT; 126362306a36Sopenharmony_ci fsize->stepwise.max_height = max_heights[cap->id]; 126462306a36Sopenharmony_ci fsize->stepwise.step_height = 2; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci return 0; 126762306a36Sopenharmony_ci} 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistatic int rkisp1_s_fmt_vid_cap_mplane(struct file *file, 127062306a36Sopenharmony_ci void *priv, struct v4l2_format *f) 127162306a36Sopenharmony_ci{ 127262306a36Sopenharmony_ci struct rkisp1_capture *cap = video_drvdata(file); 127362306a36Sopenharmony_ci struct rkisp1_vdev_node *node = 127462306a36Sopenharmony_ci rkisp1_vdev_to_node(&cap->vnode.vdev); 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci if (vb2_is_busy(&node->buf_queue)) 127762306a36Sopenharmony_ci return -EBUSY; 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_ci rkisp1_set_fmt(cap, &f->fmt.pix_mp); 128062306a36Sopenharmony_ci 128162306a36Sopenharmony_ci return 0; 128262306a36Sopenharmony_ci} 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_cistatic int rkisp1_g_fmt_vid_cap_mplane(struct file *file, void *fh, 128562306a36Sopenharmony_ci struct v4l2_format *f) 128662306a36Sopenharmony_ci{ 128762306a36Sopenharmony_ci struct rkisp1_capture *cap = video_drvdata(file); 128862306a36Sopenharmony_ci 128962306a36Sopenharmony_ci f->fmt.pix_mp = cap->pix.fmt; 129062306a36Sopenharmony_ci 129162306a36Sopenharmony_ci return 0; 129262306a36Sopenharmony_ci} 129362306a36Sopenharmony_ci 129462306a36Sopenharmony_cistatic int 129562306a36Sopenharmony_cirkisp1_querycap(struct file *file, void *priv, struct v4l2_capability *cap) 129662306a36Sopenharmony_ci{ 129762306a36Sopenharmony_ci strscpy(cap->driver, RKISP1_DRIVER_NAME, sizeof(cap->driver)); 129862306a36Sopenharmony_ci strscpy(cap->card, RKISP1_DRIVER_NAME, sizeof(cap->card)); 129962306a36Sopenharmony_ci strscpy(cap->bus_info, RKISP1_BUS_INFO, sizeof(cap->bus_info)); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci return 0; 130262306a36Sopenharmony_ci} 130362306a36Sopenharmony_ci 130462306a36Sopenharmony_cistatic const struct v4l2_ioctl_ops rkisp1_v4l2_ioctl_ops = { 130562306a36Sopenharmony_ci .vidioc_reqbufs = vb2_ioctl_reqbufs, 130662306a36Sopenharmony_ci .vidioc_querybuf = vb2_ioctl_querybuf, 130762306a36Sopenharmony_ci .vidioc_create_bufs = vb2_ioctl_create_bufs, 130862306a36Sopenharmony_ci .vidioc_qbuf = vb2_ioctl_qbuf, 130962306a36Sopenharmony_ci .vidioc_expbuf = vb2_ioctl_expbuf, 131062306a36Sopenharmony_ci .vidioc_dqbuf = vb2_ioctl_dqbuf, 131162306a36Sopenharmony_ci .vidioc_prepare_buf = vb2_ioctl_prepare_buf, 131262306a36Sopenharmony_ci .vidioc_streamon = vb2_ioctl_streamon, 131362306a36Sopenharmony_ci .vidioc_streamoff = vb2_ioctl_streamoff, 131462306a36Sopenharmony_ci .vidioc_try_fmt_vid_cap_mplane = rkisp1_try_fmt_vid_cap_mplane, 131562306a36Sopenharmony_ci .vidioc_s_fmt_vid_cap_mplane = rkisp1_s_fmt_vid_cap_mplane, 131662306a36Sopenharmony_ci .vidioc_g_fmt_vid_cap_mplane = rkisp1_g_fmt_vid_cap_mplane, 131762306a36Sopenharmony_ci .vidioc_enum_fmt_vid_cap = rkisp1_enum_fmt_vid_cap_mplane, 131862306a36Sopenharmony_ci .vidioc_enum_framesizes = rkisp1_enum_framesizes, 131962306a36Sopenharmony_ci .vidioc_querycap = rkisp1_querycap, 132062306a36Sopenharmony_ci .vidioc_subscribe_event = v4l2_ctrl_subscribe_event, 132162306a36Sopenharmony_ci .vidioc_unsubscribe_event = v4l2_event_unsubscribe, 132262306a36Sopenharmony_ci}; 132362306a36Sopenharmony_ci 132462306a36Sopenharmony_cistatic int rkisp1_capture_link_validate(struct media_link *link) 132562306a36Sopenharmony_ci{ 132662306a36Sopenharmony_ci struct video_device *vdev = 132762306a36Sopenharmony_ci media_entity_to_video_device(link->sink->entity); 132862306a36Sopenharmony_ci struct v4l2_subdev *sd = 132962306a36Sopenharmony_ci media_entity_to_v4l2_subdev(link->source->entity); 133062306a36Sopenharmony_ci struct rkisp1_capture *cap = video_get_drvdata(vdev); 133162306a36Sopenharmony_ci const struct rkisp1_capture_fmt_cfg *fmt = 133262306a36Sopenharmony_ci rkisp1_find_fmt_cfg(cap, cap->pix.fmt.pixelformat); 133362306a36Sopenharmony_ci struct v4l2_subdev_format sd_fmt = { 133462306a36Sopenharmony_ci .which = V4L2_SUBDEV_FORMAT_ACTIVE, 133562306a36Sopenharmony_ci .pad = link->source->index, 133662306a36Sopenharmony_ci }; 133762306a36Sopenharmony_ci int ret; 133862306a36Sopenharmony_ci 133962306a36Sopenharmony_ci ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, &sd_fmt); 134062306a36Sopenharmony_ci if (ret) 134162306a36Sopenharmony_ci return ret; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci if (sd_fmt.format.height != cap->pix.fmt.height || 134462306a36Sopenharmony_ci sd_fmt.format.width != cap->pix.fmt.width || 134562306a36Sopenharmony_ci sd_fmt.format.code != fmt->mbus) { 134662306a36Sopenharmony_ci dev_dbg(cap->rkisp1->dev, 134762306a36Sopenharmony_ci "link '%s':%u -> '%s':%u not valid: 0x%04x/%ux%u != 0x%04x/%ux%u\n", 134862306a36Sopenharmony_ci link->source->entity->name, link->source->index, 134962306a36Sopenharmony_ci link->sink->entity->name, link->sink->index, 135062306a36Sopenharmony_ci sd_fmt.format.code, sd_fmt.format.width, 135162306a36Sopenharmony_ci sd_fmt.format.height, fmt->mbus, cap->pix.fmt.width, 135262306a36Sopenharmony_ci cap->pix.fmt.height); 135362306a36Sopenharmony_ci return -EPIPE; 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci return 0; 135762306a36Sopenharmony_ci} 135862306a36Sopenharmony_ci 135962306a36Sopenharmony_ci/* ---------------------------------------------------------------------------- 136062306a36Sopenharmony_ci * core functions 136162306a36Sopenharmony_ci */ 136262306a36Sopenharmony_ci 136362306a36Sopenharmony_cistatic const struct media_entity_operations rkisp1_media_ops = { 136462306a36Sopenharmony_ci .link_validate = rkisp1_capture_link_validate, 136562306a36Sopenharmony_ci}; 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_cistatic const struct v4l2_file_operations rkisp1_fops = { 136862306a36Sopenharmony_ci .open = v4l2_fh_open, 136962306a36Sopenharmony_ci .release = vb2_fop_release, 137062306a36Sopenharmony_ci .unlocked_ioctl = video_ioctl2, 137162306a36Sopenharmony_ci .poll = vb2_fop_poll, 137262306a36Sopenharmony_ci .mmap = vb2_fop_mmap, 137362306a36Sopenharmony_ci}; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_cistatic void rkisp1_unregister_capture(struct rkisp1_capture *cap) 137662306a36Sopenharmony_ci{ 137762306a36Sopenharmony_ci if (!video_is_registered(&cap->vnode.vdev)) 137862306a36Sopenharmony_ci return; 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_ci media_entity_cleanup(&cap->vnode.vdev.entity); 138162306a36Sopenharmony_ci vb2_video_unregister_device(&cap->vnode.vdev); 138262306a36Sopenharmony_ci mutex_destroy(&cap->vnode.vlock); 138362306a36Sopenharmony_ci} 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_civoid rkisp1_capture_devs_unregister(struct rkisp1_device *rkisp1) 138662306a36Sopenharmony_ci{ 138762306a36Sopenharmony_ci struct rkisp1_capture *mp = &rkisp1->capture_devs[RKISP1_MAINPATH]; 138862306a36Sopenharmony_ci struct rkisp1_capture *sp = &rkisp1->capture_devs[RKISP1_SELFPATH]; 138962306a36Sopenharmony_ci 139062306a36Sopenharmony_ci rkisp1_unregister_capture(mp); 139162306a36Sopenharmony_ci rkisp1_unregister_capture(sp); 139262306a36Sopenharmony_ci} 139362306a36Sopenharmony_ci 139462306a36Sopenharmony_cistatic int rkisp1_register_capture(struct rkisp1_capture *cap) 139562306a36Sopenharmony_ci{ 139662306a36Sopenharmony_ci static const char * const dev_names[] = { 139762306a36Sopenharmony_ci RKISP1_MP_DEV_NAME, RKISP1_SP_DEV_NAME 139862306a36Sopenharmony_ci }; 139962306a36Sopenharmony_ci struct v4l2_device *v4l2_dev = &cap->rkisp1->v4l2_dev; 140062306a36Sopenharmony_ci struct video_device *vdev = &cap->vnode.vdev; 140162306a36Sopenharmony_ci struct rkisp1_vdev_node *node; 140262306a36Sopenharmony_ci struct vb2_queue *q; 140362306a36Sopenharmony_ci int ret; 140462306a36Sopenharmony_ci 140562306a36Sopenharmony_ci strscpy(vdev->name, dev_names[cap->id], sizeof(vdev->name)); 140662306a36Sopenharmony_ci node = rkisp1_vdev_to_node(vdev); 140762306a36Sopenharmony_ci mutex_init(&node->vlock); 140862306a36Sopenharmony_ci 140962306a36Sopenharmony_ci vdev->ioctl_ops = &rkisp1_v4l2_ioctl_ops; 141062306a36Sopenharmony_ci vdev->release = video_device_release_empty; 141162306a36Sopenharmony_ci vdev->fops = &rkisp1_fops; 141262306a36Sopenharmony_ci vdev->minor = -1; 141362306a36Sopenharmony_ci vdev->v4l2_dev = v4l2_dev; 141462306a36Sopenharmony_ci vdev->lock = &node->vlock; 141562306a36Sopenharmony_ci vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE | 141662306a36Sopenharmony_ci V4L2_CAP_STREAMING | V4L2_CAP_IO_MC; 141762306a36Sopenharmony_ci vdev->entity.ops = &rkisp1_media_ops; 141862306a36Sopenharmony_ci video_set_drvdata(vdev, cap); 141962306a36Sopenharmony_ci vdev->vfl_dir = VFL_DIR_RX; 142062306a36Sopenharmony_ci node->pad.flags = MEDIA_PAD_FL_SINK; 142162306a36Sopenharmony_ci 142262306a36Sopenharmony_ci q = &node->buf_queue; 142362306a36Sopenharmony_ci q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE; 142462306a36Sopenharmony_ci q->io_modes = VB2_MMAP | VB2_DMABUF; 142562306a36Sopenharmony_ci q->drv_priv = cap; 142662306a36Sopenharmony_ci q->ops = &rkisp1_vb2_ops; 142762306a36Sopenharmony_ci q->mem_ops = &vb2_dma_contig_memops; 142862306a36Sopenharmony_ci q->buf_struct_size = sizeof(struct rkisp1_buffer); 142962306a36Sopenharmony_ci q->min_buffers_needed = RKISP1_MIN_BUFFERS_NEEDED; 143062306a36Sopenharmony_ci q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC; 143162306a36Sopenharmony_ci q->lock = &node->vlock; 143262306a36Sopenharmony_ci q->dev = cap->rkisp1->dev; 143362306a36Sopenharmony_ci ret = vb2_queue_init(q); 143462306a36Sopenharmony_ci if (ret) { 143562306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, 143662306a36Sopenharmony_ci "vb2 queue init failed (err=%d)\n", ret); 143762306a36Sopenharmony_ci goto error; 143862306a36Sopenharmony_ci } 143962306a36Sopenharmony_ci 144062306a36Sopenharmony_ci vdev->queue = q; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci ret = media_entity_pads_init(&vdev->entity, 1, &node->pad); 144362306a36Sopenharmony_ci if (ret) 144462306a36Sopenharmony_ci goto error; 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1); 144762306a36Sopenharmony_ci if (ret) { 144862306a36Sopenharmony_ci dev_err(cap->rkisp1->dev, 144962306a36Sopenharmony_ci "failed to register %s, ret=%d\n", vdev->name, ret); 145062306a36Sopenharmony_ci goto error; 145162306a36Sopenharmony_ci } 145262306a36Sopenharmony_ci 145362306a36Sopenharmony_ci v4l2_info(v4l2_dev, "registered %s as /dev/video%d\n", vdev->name, 145462306a36Sopenharmony_ci vdev->num); 145562306a36Sopenharmony_ci 145662306a36Sopenharmony_ci return 0; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_cierror: 145962306a36Sopenharmony_ci media_entity_cleanup(&vdev->entity); 146062306a36Sopenharmony_ci mutex_destroy(&node->vlock); 146162306a36Sopenharmony_ci return ret; 146262306a36Sopenharmony_ci} 146362306a36Sopenharmony_ci 146462306a36Sopenharmony_cistatic void 146562306a36Sopenharmony_cirkisp1_capture_init(struct rkisp1_device *rkisp1, enum rkisp1_stream_id id) 146662306a36Sopenharmony_ci{ 146762306a36Sopenharmony_ci struct rkisp1_capture *cap = &rkisp1->capture_devs[id]; 146862306a36Sopenharmony_ci struct v4l2_pix_format_mplane pixm; 146962306a36Sopenharmony_ci 147062306a36Sopenharmony_ci memset(cap, 0, sizeof(*cap)); 147162306a36Sopenharmony_ci cap->id = id; 147262306a36Sopenharmony_ci cap->rkisp1 = rkisp1; 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci INIT_LIST_HEAD(&cap->buf.queue); 147562306a36Sopenharmony_ci init_waitqueue_head(&cap->done); 147662306a36Sopenharmony_ci spin_lock_init(&cap->buf.lock); 147762306a36Sopenharmony_ci if (cap->id == RKISP1_SELFPATH) { 147862306a36Sopenharmony_ci cap->ops = &rkisp1_capture_ops_sp; 147962306a36Sopenharmony_ci cap->config = &rkisp1_capture_config_sp; 148062306a36Sopenharmony_ci } else { 148162306a36Sopenharmony_ci cap->ops = &rkisp1_capture_ops_mp; 148262306a36Sopenharmony_ci cap->config = &rkisp1_capture_config_mp; 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci cap->is_streaming = false; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci memset(&pixm, 0, sizeof(pixm)); 148862306a36Sopenharmony_ci pixm.pixelformat = V4L2_PIX_FMT_YUYV; 148962306a36Sopenharmony_ci pixm.width = RKISP1_DEFAULT_WIDTH; 149062306a36Sopenharmony_ci pixm.height = RKISP1_DEFAULT_HEIGHT; 149162306a36Sopenharmony_ci rkisp1_set_fmt(cap, &pixm); 149262306a36Sopenharmony_ci} 149362306a36Sopenharmony_ci 149462306a36Sopenharmony_ciint rkisp1_capture_devs_register(struct rkisp1_device *rkisp1) 149562306a36Sopenharmony_ci{ 149662306a36Sopenharmony_ci unsigned int i; 149762306a36Sopenharmony_ci int ret; 149862306a36Sopenharmony_ci 149962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(rkisp1->capture_devs); i++) { 150062306a36Sopenharmony_ci struct rkisp1_capture *cap = &rkisp1->capture_devs[i]; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci rkisp1_capture_init(rkisp1, i); 150362306a36Sopenharmony_ci 150462306a36Sopenharmony_ci ret = rkisp1_register_capture(cap); 150562306a36Sopenharmony_ci if (ret) { 150662306a36Sopenharmony_ci rkisp1_capture_devs_unregister(rkisp1); 150762306a36Sopenharmony_ci return ret; 150862306a36Sopenharmony_ci } 150962306a36Sopenharmony_ci } 151062306a36Sopenharmony_ci 151162306a36Sopenharmony_ci return 0; 151262306a36Sopenharmony_ci 151362306a36Sopenharmony_ci} 1514