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