xref: /OK3568_Linux_fs/kernel/drivers/media/platform/rockchip/cif/cif-tools.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /* Copyright (c) 2020 Rockchip Electronics Co., Ltd. */
3*4882a593Smuzhiyun 
4*4882a593Smuzhiyun #include <linux/kfifo.h>
5*4882a593Smuzhiyun #include <media/v4l2-common.h>
6*4882a593Smuzhiyun #include <media/v4l2-ioctl.h>
7*4882a593Smuzhiyun #include <media/videobuf2-core.h>
8*4882a593Smuzhiyun #include <media/videobuf2-vmalloc.h>
9*4882a593Smuzhiyun #include <media/videobuf2-dma-contig.h>
10*4882a593Smuzhiyun #include <media/videobuf2-dma-sg.h>
11*4882a593Smuzhiyun #include <linux/of.h>
12*4882a593Smuzhiyun #include <linux/of_gpio.h>
13*4882a593Smuzhiyun #include <linux/of_graph.h>
14*4882a593Smuzhiyun #include <linux/of_platform.h>
15*4882a593Smuzhiyun #include <linux/of_reserved_mem.h>
16*4882a593Smuzhiyun #include <media/v4l2-event.h>
17*4882a593Smuzhiyun #include "dev.h"
18*4882a593Smuzhiyun #include "regs.h"
19*4882a593Smuzhiyun #include "mipi-csi2.h"
20*4882a593Smuzhiyun #include <media/v4l2-fwnode.h>
21*4882a593Smuzhiyun #include <linux/pm_runtime.h>
22*4882a593Smuzhiyun #include <linux/delay.h>
23*4882a593Smuzhiyun 
24*4882a593Smuzhiyun #define MEMORY_ALIGN_ROUND_UP_HEIGHT		16
25*4882a593Smuzhiyun 
26*4882a593Smuzhiyun #define TOOLS_MIN_WIDTH		4
27*4882a593Smuzhiyun #define TOOLS_MIN_HEIGHT	4
28*4882a593Smuzhiyun #define TOOLS_OUTPUT_STEP_WISE	1
29*4882a593Smuzhiyun #define CIF_TOOLS_REQ_BUFS_MIN	1
30*4882a593Smuzhiyun 
31*4882a593Smuzhiyun static const struct cif_output_fmt tools_out_fmts[] = {
32*4882a593Smuzhiyun 	{
33*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SRGGB8,
34*4882a593Smuzhiyun 		.cplanes = 1,
35*4882a593Smuzhiyun 		.mplanes = 1,
36*4882a593Smuzhiyun 		.bpp = { 8 },
37*4882a593Smuzhiyun 		.raw_bpp = 8,
38*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
39*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
40*4882a593Smuzhiyun 	}, {
41*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGRBG8,
42*4882a593Smuzhiyun 		.cplanes = 1,
43*4882a593Smuzhiyun 		.mplanes = 1,
44*4882a593Smuzhiyun 		.bpp = { 8 },
45*4882a593Smuzhiyun 		.raw_bpp = 8,
46*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
47*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
48*4882a593Smuzhiyun 	}, {
49*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGBRG8,
50*4882a593Smuzhiyun 		.cplanes = 1,
51*4882a593Smuzhiyun 		.mplanes = 1,
52*4882a593Smuzhiyun 		.bpp = { 8 },
53*4882a593Smuzhiyun 		.raw_bpp = 8,
54*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
55*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
56*4882a593Smuzhiyun 	}, {
57*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SBGGR8,
58*4882a593Smuzhiyun 		.cplanes = 1,
59*4882a593Smuzhiyun 		.mplanes = 1,
60*4882a593Smuzhiyun 		.bpp = { 8 },
61*4882a593Smuzhiyun 		.raw_bpp = 8,
62*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW8,
63*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
64*4882a593Smuzhiyun 	}, {
65*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SRGGB10,
66*4882a593Smuzhiyun 		.cplanes = 1,
67*4882a593Smuzhiyun 		.mplanes = 1,
68*4882a593Smuzhiyun 		.bpp = { 16 },
69*4882a593Smuzhiyun 		.raw_bpp = 10,
70*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
71*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
72*4882a593Smuzhiyun 	}, {
73*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGRBG10,
74*4882a593Smuzhiyun 		.cplanes = 1,
75*4882a593Smuzhiyun 		.mplanes = 1,
76*4882a593Smuzhiyun 		.bpp = { 16 },
77*4882a593Smuzhiyun 		.raw_bpp = 10,
78*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
79*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
80*4882a593Smuzhiyun 	}, {
81*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGBRG10,
82*4882a593Smuzhiyun 		.cplanes = 1,
83*4882a593Smuzhiyun 		.mplanes = 1,
84*4882a593Smuzhiyun 		.bpp = { 16 },
85*4882a593Smuzhiyun 		.raw_bpp = 10,
86*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
87*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
88*4882a593Smuzhiyun 	}, {
89*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SBGGR10,
90*4882a593Smuzhiyun 		.cplanes = 1,
91*4882a593Smuzhiyun 		.mplanes = 1,
92*4882a593Smuzhiyun 		.bpp = { 16 },
93*4882a593Smuzhiyun 		.raw_bpp = 10,
94*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW10,
95*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
96*4882a593Smuzhiyun 	}, {
97*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SRGGB12,
98*4882a593Smuzhiyun 		.cplanes = 1,
99*4882a593Smuzhiyun 		.mplanes = 1,
100*4882a593Smuzhiyun 		.bpp = { 16 },
101*4882a593Smuzhiyun 		.raw_bpp = 12,
102*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
103*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
104*4882a593Smuzhiyun 	}, {
105*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGRBG12,
106*4882a593Smuzhiyun 		.cplanes = 1,
107*4882a593Smuzhiyun 		.mplanes = 1,
108*4882a593Smuzhiyun 		.bpp = { 16 },
109*4882a593Smuzhiyun 		.raw_bpp = 12,
110*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
111*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
112*4882a593Smuzhiyun 	}, {
113*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SGBRG12,
114*4882a593Smuzhiyun 		.cplanes = 1,
115*4882a593Smuzhiyun 		.mplanes = 1,
116*4882a593Smuzhiyun 		.bpp = { 16 },
117*4882a593Smuzhiyun 		.raw_bpp = 12,
118*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
119*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
120*4882a593Smuzhiyun 	}, {
121*4882a593Smuzhiyun 		.fourcc = V4L2_PIX_FMT_SBGGR12,
122*4882a593Smuzhiyun 		.cplanes = 1,
123*4882a593Smuzhiyun 		.mplanes = 1,
124*4882a593Smuzhiyun 		.bpp = { 16 },
125*4882a593Smuzhiyun 		.raw_bpp = 12,
126*4882a593Smuzhiyun 		.csi_fmt_val = CSI_WRDDR_TYPE_RAW12,
127*4882a593Smuzhiyun 		.fmt_type = CIF_FMT_TYPE_RAW,
128*4882a593Smuzhiyun 	}
129*4882a593Smuzhiyun };
130*4882a593Smuzhiyun 
rkcif_tools_enum_fmt_vid_cap(struct file * file,void * priv,struct v4l2_fmtdesc * f)131*4882a593Smuzhiyun static int rkcif_tools_enum_fmt_vid_cap(struct file *file, void *priv,
132*4882a593Smuzhiyun 					struct v4l2_fmtdesc *f)
133*4882a593Smuzhiyun {
134*4882a593Smuzhiyun 	const struct cif_output_fmt *fmt = NULL;
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun 	if (f->index >= ARRAY_SIZE(tools_out_fmts))
137*4882a593Smuzhiyun 		return -EINVAL;
138*4882a593Smuzhiyun 	fmt = &tools_out_fmts[f->index];
139*4882a593Smuzhiyun 	f->pixelformat = fmt->fourcc;
140*4882a593Smuzhiyun 	return 0;
141*4882a593Smuzhiyun }
142*4882a593Smuzhiyun 
rkcif_tools_g_fmt_vid_cap_mplane(struct file * file,void * priv,struct v4l2_format * f)143*4882a593Smuzhiyun static int rkcif_tools_g_fmt_vid_cap_mplane(struct file *file, void *priv,
144*4882a593Smuzhiyun 					    struct v4l2_format *f)
145*4882a593Smuzhiyun {
146*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
147*4882a593Smuzhiyun 
148*4882a593Smuzhiyun 	f->fmt.pix_mp = tools_vdev->pixm;
149*4882a593Smuzhiyun 	return 0;
150*4882a593Smuzhiyun }
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun static const struct
rkcif_tools_find_output_fmt(u32 pixelfmt)153*4882a593Smuzhiyun cif_output_fmt *rkcif_tools_find_output_fmt(u32 pixelfmt)
154*4882a593Smuzhiyun {
155*4882a593Smuzhiyun 	const struct cif_output_fmt *fmt;
156*4882a593Smuzhiyun 	u32 i;
157*4882a593Smuzhiyun 
158*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(tools_out_fmts); i++) {
159*4882a593Smuzhiyun 		fmt = &tools_out_fmts[i];
160*4882a593Smuzhiyun 		if (fmt->fourcc == pixelfmt)
161*4882a593Smuzhiyun 			return fmt;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun 	return NULL;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
rkcif_tools_set_fmt(struct rkcif_tools_vdev * tools_vdev,struct v4l2_pix_format_mplane * pixm,bool try)167*4882a593Smuzhiyun static int rkcif_tools_set_fmt(struct rkcif_tools_vdev *tools_vdev,
168*4882a593Smuzhiyun 			       struct v4l2_pix_format_mplane *pixm,
169*4882a593Smuzhiyun 			       bool try)
170*4882a593Smuzhiyun {
171*4882a593Smuzhiyun 	struct rkcif_stream *stream = tools_vdev->stream;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	*pixm = stream->pixm;
174*4882a593Smuzhiyun 
175*4882a593Smuzhiyun 	if (!try) {
176*4882a593Smuzhiyun 		tools_vdev->tools_out_fmt = stream->cif_fmt_out;
177*4882a593Smuzhiyun 		tools_vdev->pixm = *pixm;
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 		v4l2_dbg(1, rkcif_debug, &stream->cifdev->v4l2_dev,
180*4882a593Smuzhiyun 			 "%s: req(%d, %d)\n", __func__,
181*4882a593Smuzhiyun 			 pixm->width, pixm->height);
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun 	return 0;
184*4882a593Smuzhiyun }
185*4882a593Smuzhiyun 
rkcif_tools_s_fmt_vid_cap_mplane(struct file * file,void * priv,struct v4l2_format * f)186*4882a593Smuzhiyun static int rkcif_tools_s_fmt_vid_cap_mplane(struct file *file,
187*4882a593Smuzhiyun 					    void *priv, struct v4l2_format *f)
188*4882a593Smuzhiyun {
189*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
190*4882a593Smuzhiyun 	int ret = 0;
191*4882a593Smuzhiyun 
192*4882a593Smuzhiyun 	if (vb2_is_busy(&tools_vdev->vnode.buf_queue)) {
193*4882a593Smuzhiyun 		v4l2_err(&tools_vdev->cifdev->v4l2_dev, "%s queue busy\n", __func__);
194*4882a593Smuzhiyun 		return -EBUSY;
195*4882a593Smuzhiyun 	}
196*4882a593Smuzhiyun 
197*4882a593Smuzhiyun 	ret = rkcif_tools_set_fmt(tools_vdev, &f->fmt.pix_mp, false);
198*4882a593Smuzhiyun 
199*4882a593Smuzhiyun 	return ret;
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
rkcif_tools_querycap(struct file * file,void * priv,struct v4l2_capability * cap)202*4882a593Smuzhiyun static int rkcif_tools_querycap(struct file *file,
203*4882a593Smuzhiyun 				void *priv, struct v4l2_capability *cap)
204*4882a593Smuzhiyun {
205*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
206*4882a593Smuzhiyun 	struct device *dev = tools_vdev->cifdev->dev;
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	strscpy(cap->driver, dev->driver->name, sizeof(cap->driver));
209*4882a593Smuzhiyun 	strscpy(cap->card, dev->driver->name, sizeof(cap->card));
210*4882a593Smuzhiyun 	snprintf(cap->bus_info, sizeof(cap->bus_info),
211*4882a593Smuzhiyun 		 "platform:%s", dev_name(dev));
212*4882a593Smuzhiyun 	return 0;
213*4882a593Smuzhiyun }
214*4882a593Smuzhiyun 
rkcif_tools_ioctl_default(struct file * file,void * fh,bool valid_prio,unsigned int cmd,void * arg)215*4882a593Smuzhiyun static long rkcif_tools_ioctl_default(struct file *file, void *fh,
216*4882a593Smuzhiyun 				    bool valid_prio, unsigned int cmd, void *arg)
217*4882a593Smuzhiyun {
218*4882a593Smuzhiyun 	return 0;
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
rkcif_tools_enum_input(struct file * file,void * priv,struct v4l2_input * input)221*4882a593Smuzhiyun static int rkcif_tools_enum_input(struct file *file, void *priv,
222*4882a593Smuzhiyun 				  struct v4l2_input *input)
223*4882a593Smuzhiyun {
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	if (input->index > 0)
226*4882a593Smuzhiyun 		return -EINVAL;
227*4882a593Smuzhiyun 
228*4882a593Smuzhiyun 	input->type = V4L2_INPUT_TYPE_CAMERA;
229*4882a593Smuzhiyun 	strscpy(input->name, "Camera", sizeof(input->name));
230*4882a593Smuzhiyun 
231*4882a593Smuzhiyun 	return 0;
232*4882a593Smuzhiyun }
233*4882a593Smuzhiyun 
rkcif_tools_try_fmt_vid_cap_mplane(struct file * file,void * fh,struct v4l2_format * f)234*4882a593Smuzhiyun static int rkcif_tools_try_fmt_vid_cap_mplane(struct file *file, void *fh,
235*4882a593Smuzhiyun 					      struct v4l2_format *f)
236*4882a593Smuzhiyun {
237*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
238*4882a593Smuzhiyun 	int ret = 0;
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	ret = rkcif_tools_set_fmt(tools_vdev, &f->fmt.pix_mp, true);
241*4882a593Smuzhiyun 
242*4882a593Smuzhiyun 	return ret;
243*4882a593Smuzhiyun }
244*4882a593Smuzhiyun 
rkcif_tools_enum_frameintervals(struct file * file,void * fh,struct v4l2_frmivalenum * fival)245*4882a593Smuzhiyun static int rkcif_tools_enum_frameintervals(struct file *file, void *fh,
246*4882a593Smuzhiyun 					   struct v4l2_frmivalenum *fival)
247*4882a593Smuzhiyun {
248*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
249*4882a593Smuzhiyun 	struct rkcif_device *dev = tools_vdev->cifdev;
250*4882a593Smuzhiyun 	struct rkcif_sensor_info *sensor = &dev->terminal_sensor;
251*4882a593Smuzhiyun 	struct v4l2_subdev_frame_interval fi;
252*4882a593Smuzhiyun 	int ret;
253*4882a593Smuzhiyun 
254*4882a593Smuzhiyun 	if (fival->index != 0)
255*4882a593Smuzhiyun 		return -EINVAL;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	if (!sensor || !sensor->sd) {
258*4882a593Smuzhiyun 		/* TODO: active_sensor is NULL if using DMARX path */
259*4882a593Smuzhiyun 		v4l2_err(&dev->v4l2_dev, "%s Not active sensor\n", __func__);
260*4882a593Smuzhiyun 		return -ENODEV;
261*4882a593Smuzhiyun 	}
262*4882a593Smuzhiyun 
263*4882a593Smuzhiyun 	ret = v4l2_subdev_call(sensor->sd, video, g_frame_interval, &fi);
264*4882a593Smuzhiyun 	if (ret && ret != -ENOIOCTLCMD) {
265*4882a593Smuzhiyun 		return ret;
266*4882a593Smuzhiyun 	} else if (ret == -ENOIOCTLCMD) {
267*4882a593Smuzhiyun 		/* Set a default value for sensors not implements ioctl */
268*4882a593Smuzhiyun 		fi.interval.numerator = 1;
269*4882a593Smuzhiyun 		fi.interval.denominator = 30;
270*4882a593Smuzhiyun 	}
271*4882a593Smuzhiyun 
272*4882a593Smuzhiyun 	fival->type = V4L2_FRMIVAL_TYPE_CONTINUOUS;
273*4882a593Smuzhiyun 	fival->stepwise.step.numerator = 1;
274*4882a593Smuzhiyun 	fival->stepwise.step.denominator = 1;
275*4882a593Smuzhiyun 	fival->stepwise.max.numerator = 1;
276*4882a593Smuzhiyun 	fival->stepwise.max.denominator = 1;
277*4882a593Smuzhiyun 	fival->stepwise.min.numerator = fi.interval.numerator;
278*4882a593Smuzhiyun 	fival->stepwise.min.denominator = fi.interval.denominator;
279*4882a593Smuzhiyun 
280*4882a593Smuzhiyun 	return 0;
281*4882a593Smuzhiyun }
282*4882a593Smuzhiyun 
rkcif_tools_enum_framesizes(struct file * file,void * prov,struct v4l2_frmsizeenum * fsize)283*4882a593Smuzhiyun static int rkcif_tools_enum_framesizes(struct file *file, void *prov,
284*4882a593Smuzhiyun 				       struct v4l2_frmsizeenum *fsize)
285*4882a593Smuzhiyun {
286*4882a593Smuzhiyun 	struct v4l2_frmsize_discrete *s = &fsize->discrete;
287*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = video_drvdata(file);
288*4882a593Smuzhiyun 	struct rkcif_device *dev = tools_vdev->cifdev;
289*4882a593Smuzhiyun 	struct v4l2_rect input_rect;
290*4882a593Smuzhiyun 	struct rkcif_sensor_info *terminal_sensor = &dev->terminal_sensor;
291*4882a593Smuzhiyun 	struct csi_channel_info csi_info;
292*4882a593Smuzhiyun 
293*4882a593Smuzhiyun 	if (fsize->index >= ARRAY_SIZE(tools_out_fmts))
294*4882a593Smuzhiyun 		return -EINVAL;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun 	if (!rkcif_tools_find_output_fmt(fsize->pixel_format))
297*4882a593Smuzhiyun 		return -EINVAL;
298*4882a593Smuzhiyun 
299*4882a593Smuzhiyun 	input_rect.width = RKCIF_DEFAULT_WIDTH;
300*4882a593Smuzhiyun 	input_rect.height = RKCIF_DEFAULT_HEIGHT;
301*4882a593Smuzhiyun 
302*4882a593Smuzhiyun 	if (terminal_sensor && terminal_sensor->sd)
303*4882a593Smuzhiyun 		rkcif_get_input_fmt(dev,
304*4882a593Smuzhiyun 				    &input_rect, 0, &csi_info);
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	fsize->type = V4L2_FRMSIZE_TYPE_DISCRETE;
307*4882a593Smuzhiyun 	s->width = input_rect.width;
308*4882a593Smuzhiyun 	s->height = input_rect.height;
309*4882a593Smuzhiyun 
310*4882a593Smuzhiyun 	return 0;
311*4882a593Smuzhiyun }
312*4882a593Smuzhiyun 
313*4882a593Smuzhiyun /* ISP video device IOCTLs */
314*4882a593Smuzhiyun static const struct v4l2_ioctl_ops rkcif_tools_ioctl = {
315*4882a593Smuzhiyun 	.vidioc_reqbufs = vb2_ioctl_reqbufs,
316*4882a593Smuzhiyun 	.vidioc_querybuf = vb2_ioctl_querybuf,
317*4882a593Smuzhiyun 	.vidioc_create_bufs = vb2_ioctl_create_bufs,
318*4882a593Smuzhiyun 	.vidioc_qbuf = vb2_ioctl_qbuf,
319*4882a593Smuzhiyun 	.vidioc_dqbuf = vb2_ioctl_dqbuf,
320*4882a593Smuzhiyun 	.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
321*4882a593Smuzhiyun 	.vidioc_expbuf = vb2_ioctl_expbuf,
322*4882a593Smuzhiyun 	.vidioc_streamon = vb2_ioctl_streamon,
323*4882a593Smuzhiyun 	.vidioc_streamoff = vb2_ioctl_streamoff,
324*4882a593Smuzhiyun 	.vidioc_enum_input = rkcif_tools_enum_input,
325*4882a593Smuzhiyun 	.vidioc_enum_fmt_vid_cap = rkcif_tools_enum_fmt_vid_cap,
326*4882a593Smuzhiyun 	.vidioc_g_fmt_vid_cap_mplane = rkcif_tools_g_fmt_vid_cap_mplane,
327*4882a593Smuzhiyun 	.vidioc_s_fmt_vid_cap_mplane = rkcif_tools_s_fmt_vid_cap_mplane,
328*4882a593Smuzhiyun 	.vidioc_try_fmt_vid_cap_mplane = rkcif_tools_try_fmt_vid_cap_mplane,
329*4882a593Smuzhiyun 	.vidioc_querycap = rkcif_tools_querycap,
330*4882a593Smuzhiyun 	.vidioc_enum_frameintervals = rkcif_tools_enum_frameintervals,
331*4882a593Smuzhiyun 	.vidioc_enum_framesizes = rkcif_tools_enum_framesizes,
332*4882a593Smuzhiyun 	.vidioc_default = rkcif_tools_ioctl_default,
333*4882a593Smuzhiyun };
334*4882a593Smuzhiyun 
rkcif_tools_fh_open(struct file * file)335*4882a593Smuzhiyun static int rkcif_tools_fh_open(struct file *file)
336*4882a593Smuzhiyun {
337*4882a593Smuzhiyun 	struct video_device *vdev = video_devdata(file);
338*4882a593Smuzhiyun 	struct rkcif_vdev_node *vnode = vdev_to_node(vdev);
339*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = to_rkcif_tools_vdev(vnode);
340*4882a593Smuzhiyun 	struct rkcif_device *cifdev = tools_vdev->cifdev;
341*4882a593Smuzhiyun 	int ret;
342*4882a593Smuzhiyun 
343*4882a593Smuzhiyun 	ret = rkcif_update_sensor_info(tools_vdev->stream);
344*4882a593Smuzhiyun 	if (ret < 0) {
345*4882a593Smuzhiyun 		v4l2_err(vdev,
346*4882a593Smuzhiyun 			 "update sensor info failed %d\n",
347*4882a593Smuzhiyun 			 ret);
348*4882a593Smuzhiyun 
349*4882a593Smuzhiyun 		return ret;
350*4882a593Smuzhiyun 	}
351*4882a593Smuzhiyun 
352*4882a593Smuzhiyun 	ret = pm_runtime_resume_and_get(cifdev->dev);
353*4882a593Smuzhiyun 	if (ret < 0)
354*4882a593Smuzhiyun 		v4l2_err(&cifdev->v4l2_dev, "Failed to get runtime pm, %d\n",
355*4882a593Smuzhiyun 			 ret);
356*4882a593Smuzhiyun 	ret = v4l2_fh_open(file);
357*4882a593Smuzhiyun 	if (!ret) {
358*4882a593Smuzhiyun 		ret = v4l2_pipeline_pm_get(&vnode->vdev.entity);
359*4882a593Smuzhiyun 		if (ret < 0)
360*4882a593Smuzhiyun 			vb2_fop_release(file);
361*4882a593Smuzhiyun 	}
362*4882a593Smuzhiyun 	return ret;
363*4882a593Smuzhiyun }
364*4882a593Smuzhiyun 
rkcif_tools_fop_release(struct file * file)365*4882a593Smuzhiyun static int rkcif_tools_fop_release(struct file *file)
366*4882a593Smuzhiyun {
367*4882a593Smuzhiyun 	struct video_device *vdev = video_devdata(file);
368*4882a593Smuzhiyun 	struct rkcif_vdev_node *vnode = vdev_to_node(vdev);
369*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = to_rkcif_tools_vdev(vnode);
370*4882a593Smuzhiyun 	struct rkcif_device *cifdev = tools_vdev->cifdev;
371*4882a593Smuzhiyun 	int ret = 0;
372*4882a593Smuzhiyun 
373*4882a593Smuzhiyun 	ret = vb2_fop_release(file);
374*4882a593Smuzhiyun 	if (!ret)
375*4882a593Smuzhiyun 		v4l2_pipeline_pm_put(&vnode->vdev.entity);
376*4882a593Smuzhiyun 	pm_runtime_put_sync(cifdev->dev);
377*4882a593Smuzhiyun 	return 0;
378*4882a593Smuzhiyun }
379*4882a593Smuzhiyun 
380*4882a593Smuzhiyun struct v4l2_file_operations rkcif_tools_fops = {
381*4882a593Smuzhiyun 	.mmap = vb2_fop_mmap,
382*4882a593Smuzhiyun 	.unlocked_ioctl = video_ioctl2,
383*4882a593Smuzhiyun 	.poll = vb2_fop_poll,
384*4882a593Smuzhiyun 	.open = rkcif_tools_fh_open,
385*4882a593Smuzhiyun 	.release = rkcif_tools_fop_release
386*4882a593Smuzhiyun };
387*4882a593Smuzhiyun 
rkcif_tools_vb2_queue_setup(struct vb2_queue * queue,unsigned int * num_buffers,unsigned int * num_planes,unsigned int sizes[],struct device * alloc_ctxs[])388*4882a593Smuzhiyun static int rkcif_tools_vb2_queue_setup(struct vb2_queue *queue,
389*4882a593Smuzhiyun 				       unsigned int *num_buffers,
390*4882a593Smuzhiyun 				       unsigned int *num_planes,
391*4882a593Smuzhiyun 				       unsigned int sizes[],
392*4882a593Smuzhiyun 				       struct device *alloc_ctxs[])
393*4882a593Smuzhiyun {
394*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = queue->drv_priv;
395*4882a593Smuzhiyun 	struct rkcif_device *cif_dev = tools_vdev->cifdev;
396*4882a593Smuzhiyun 	const struct v4l2_pix_format_mplane *pixm = NULL;
397*4882a593Smuzhiyun 	const struct cif_output_fmt *cif_fmt;
398*4882a593Smuzhiyun 	u32 i;
399*4882a593Smuzhiyun 	const struct v4l2_plane_pix_format *plane_fmt;
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun 	pixm = &tools_vdev->pixm;
402*4882a593Smuzhiyun 	cif_fmt = tools_vdev->tools_out_fmt;
403*4882a593Smuzhiyun 	*num_planes = cif_fmt->mplanes;
404*4882a593Smuzhiyun 
405*4882a593Smuzhiyun 	for (i = 0; i < cif_fmt->mplanes; i++) {
406*4882a593Smuzhiyun 		plane_fmt = &pixm->plane_fmt[i];
407*4882a593Smuzhiyun 		sizes[i] = plane_fmt->sizeimage;
408*4882a593Smuzhiyun 	}
409*4882a593Smuzhiyun 
410*4882a593Smuzhiyun 	v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev, "%s count %d, size %d\n",
411*4882a593Smuzhiyun 		 v4l2_type_names[queue->type], *num_buffers, sizes[0]);
412*4882a593Smuzhiyun 	return 0;
413*4882a593Smuzhiyun 
414*4882a593Smuzhiyun }
415*4882a593Smuzhiyun 
rkcif_tools_vb2_buf_queue(struct vb2_buffer * vb)416*4882a593Smuzhiyun static void rkcif_tools_vb2_buf_queue(struct vb2_buffer *vb)
417*4882a593Smuzhiyun {
418*4882a593Smuzhiyun 	struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
419*4882a593Smuzhiyun 	struct rkcif_buffer *cifbuf = to_rkcif_buffer(vbuf);
420*4882a593Smuzhiyun 	struct vb2_queue *queue = vb->vb2_queue;
421*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = queue->drv_priv;
422*4882a593Smuzhiyun 	struct v4l2_pix_format_mplane *pixm = &tools_vdev->pixm;
423*4882a593Smuzhiyun 	const struct cif_output_fmt *fmt = tools_vdev->tools_out_fmt;
424*4882a593Smuzhiyun 	struct rkcif_hw *hw_dev = tools_vdev->cifdev->hw_dev;
425*4882a593Smuzhiyun 	unsigned long lock_flags = 0;
426*4882a593Smuzhiyun 	int i;
427*4882a593Smuzhiyun 
428*4882a593Smuzhiyun 	memset(cifbuf->buff_addr, 0, sizeof(cifbuf->buff_addr));
429*4882a593Smuzhiyun 	/* If mplanes > 1, every c-plane has its own m-plane,
430*4882a593Smuzhiyun 	 * otherwise, multiple c-planes are in the same m-plane
431*4882a593Smuzhiyun 	 */
432*4882a593Smuzhiyun 	for (i = 0; i < fmt->mplanes; i++) {
433*4882a593Smuzhiyun 		void *addr = vb2_plane_vaddr(vb, i);
434*4882a593Smuzhiyun 
435*4882a593Smuzhiyun 		if (hw_dev->is_dma_sg_ops) {
436*4882a593Smuzhiyun 			struct sg_table *sgt = vb2_dma_sg_plane_desc(vb, i);
437*4882a593Smuzhiyun 
438*4882a593Smuzhiyun 			cifbuf->buff_addr[i] = sg_dma_address(sgt->sgl);
439*4882a593Smuzhiyun 		} else {
440*4882a593Smuzhiyun 			cifbuf->buff_addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
441*4882a593Smuzhiyun 		}
442*4882a593Smuzhiyun 		if (rkcif_debug && addr && !hw_dev->iommu_en) {
443*4882a593Smuzhiyun 			memset(addr, 0, pixm->plane_fmt[i].sizeimage);
444*4882a593Smuzhiyun 			v4l2_dbg(3, rkcif_debug, &tools_vdev->cifdev->v4l2_dev,
445*4882a593Smuzhiyun 				 "Clear buffer, size: 0x%08x\n",
446*4882a593Smuzhiyun 				 pixm->plane_fmt[i].sizeimage);
447*4882a593Smuzhiyun 		}
448*4882a593Smuzhiyun 	}
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	if (fmt->mplanes == 1) {
451*4882a593Smuzhiyun 		for (i = 0; i < fmt->cplanes - 1; i++)
452*4882a593Smuzhiyun 			cifbuf->buff_addr[i + 1] = cifbuf->buff_addr[i] +
453*4882a593Smuzhiyun 				pixm->plane_fmt[i].bytesperline * pixm->height;
454*4882a593Smuzhiyun 	}
455*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, lock_flags);
456*4882a593Smuzhiyun 	list_add_tail(&cifbuf->queue, &tools_vdev->buf_head);
457*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, lock_flags);
458*4882a593Smuzhiyun }
459*4882a593Smuzhiyun 
rkcif_tools_stop(struct rkcif_tools_vdev * tools_vdev)460*4882a593Smuzhiyun static int rkcif_tools_stop(struct rkcif_tools_vdev *tools_vdev)
461*4882a593Smuzhiyun {
462*4882a593Smuzhiyun 	unsigned long flags;
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
465*4882a593Smuzhiyun 	tools_vdev->state = RKCIF_STATE_READY;
466*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
467*4882a593Smuzhiyun 	tools_vdev->frame_idx = 0;
468*4882a593Smuzhiyun 	return 0;
469*4882a593Smuzhiyun }
470*4882a593Smuzhiyun 
rkcif_tools_vb2_stop_streaming(struct vb2_queue * vq)471*4882a593Smuzhiyun static void rkcif_tools_vb2_stop_streaming(struct vb2_queue *vq)
472*4882a593Smuzhiyun {
473*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = vq->drv_priv;
474*4882a593Smuzhiyun 	struct rkcif_device *dev = tools_vdev->cifdev;
475*4882a593Smuzhiyun 	struct rkcif_buffer *buf = NULL;
476*4882a593Smuzhiyun 	struct rkcif_tools_buffer *tools_buf;
477*4882a593Smuzhiyun 	int ret = 0;
478*4882a593Smuzhiyun 
479*4882a593Smuzhiyun 	mutex_lock(&dev->tools_lock);
480*4882a593Smuzhiyun 
481*4882a593Smuzhiyun 	tools_vdev->stopping = true;
482*4882a593Smuzhiyun 	ret = wait_event_timeout(tools_vdev->wq_stopped,
483*4882a593Smuzhiyun 				 tools_vdev->state != RKCIF_STATE_STREAMING,
484*4882a593Smuzhiyun 				 msecs_to_jiffies(1000));
485*4882a593Smuzhiyun 	if (!ret) {
486*4882a593Smuzhiyun 		rkcif_tools_stop(tools_vdev);
487*4882a593Smuzhiyun 		tools_vdev->stopping = false;
488*4882a593Smuzhiyun 	}
489*4882a593Smuzhiyun 	/* release buffers */
490*4882a593Smuzhiyun 	if (tools_vdev->curr_buf)
491*4882a593Smuzhiyun 		list_add_tail(&tools_vdev->curr_buf->queue, &tools_vdev->buf_head);
492*4882a593Smuzhiyun 
493*4882a593Smuzhiyun 	tools_vdev->curr_buf = NULL;
494*4882a593Smuzhiyun 	while (!list_empty(&tools_vdev->buf_head)) {
495*4882a593Smuzhiyun 		buf = list_first_entry(&tools_vdev->buf_head,
496*4882a593Smuzhiyun 				       struct rkcif_buffer, queue);
497*4882a593Smuzhiyun 		list_del(&buf->queue);
498*4882a593Smuzhiyun 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
499*4882a593Smuzhiyun 	}
500*4882a593Smuzhiyun 	while (!list_empty(&tools_vdev->src_buf_head)) {
501*4882a593Smuzhiyun 		tools_buf = list_first_entry(&tools_vdev->src_buf_head,
502*4882a593Smuzhiyun 				       struct rkcif_tools_buffer, list);
503*4882a593Smuzhiyun 		list_del(&tools_buf->list);
504*4882a593Smuzhiyun 		kfree(tools_buf);
505*4882a593Smuzhiyun 		tools_buf = NULL;
506*4882a593Smuzhiyun 	}
507*4882a593Smuzhiyun 	mutex_unlock(&dev->tools_lock);
508*4882a593Smuzhiyun }
509*4882a593Smuzhiyun 
rkcif_tools_start(struct rkcif_tools_vdev * tools_vdev)510*4882a593Smuzhiyun static int rkcif_tools_start(struct rkcif_tools_vdev *tools_vdev)
511*4882a593Smuzhiyun {
512*4882a593Smuzhiyun 	int ret = 0;
513*4882a593Smuzhiyun 	struct rkcif_device *dev = tools_vdev->cifdev;
514*4882a593Smuzhiyun 	struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
515*4882a593Smuzhiyun 
516*4882a593Smuzhiyun 	mutex_lock(&dev->tools_lock);
517*4882a593Smuzhiyun 	if (tools_vdev->state == RKCIF_STATE_STREAMING) {
518*4882a593Smuzhiyun 		ret = -EBUSY;
519*4882a593Smuzhiyun 		v4l2_err(v4l2_dev, "stream in busy state\n");
520*4882a593Smuzhiyun 		goto destroy_buf;
521*4882a593Smuzhiyun 	}
522*4882a593Smuzhiyun 
523*4882a593Smuzhiyun 	tools_vdev->frame_idx = 0;
524*4882a593Smuzhiyun 	tools_vdev->state = RKCIF_STATE_STREAMING;
525*4882a593Smuzhiyun 	mutex_unlock(&dev->tools_lock);
526*4882a593Smuzhiyun 	return 0;
527*4882a593Smuzhiyun 
528*4882a593Smuzhiyun destroy_buf:
529*4882a593Smuzhiyun 	if (tools_vdev->curr_buf) {
530*4882a593Smuzhiyun 		vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf,
531*4882a593Smuzhiyun 				VB2_BUF_STATE_QUEUED);
532*4882a593Smuzhiyun 		tools_vdev->curr_buf = NULL;
533*4882a593Smuzhiyun 	}
534*4882a593Smuzhiyun 	while (!list_empty(&tools_vdev->buf_head)) {
535*4882a593Smuzhiyun 		struct rkcif_buffer *buf;
536*4882a593Smuzhiyun 
537*4882a593Smuzhiyun 		buf = list_first_entry(&tools_vdev->buf_head,
538*4882a593Smuzhiyun 				       struct rkcif_buffer, queue);
539*4882a593Smuzhiyun 		vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_QUEUED);
540*4882a593Smuzhiyun 		list_del(&buf->queue);
541*4882a593Smuzhiyun 	}
542*4882a593Smuzhiyun 	mutex_unlock(&dev->tools_lock);
543*4882a593Smuzhiyun 	return ret;
544*4882a593Smuzhiyun }
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun static int
rkcif_tools_vb2_start_streaming(struct vb2_queue * queue,unsigned int count)547*4882a593Smuzhiyun rkcif_tools_vb2_start_streaming(struct vb2_queue *queue,
548*4882a593Smuzhiyun 				unsigned int count)
549*4882a593Smuzhiyun {
550*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = queue->drv_priv;
551*4882a593Smuzhiyun 	int ret = 0;
552*4882a593Smuzhiyun 
553*4882a593Smuzhiyun 	ret = rkcif_tools_start(tools_vdev);
554*4882a593Smuzhiyun 	if (ret)
555*4882a593Smuzhiyun 		return -EINVAL;
556*4882a593Smuzhiyun 	return 0;
557*4882a593Smuzhiyun }
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun static const struct vb2_ops rkcif_tools_vb2_ops = {
560*4882a593Smuzhiyun 	.queue_setup = rkcif_tools_vb2_queue_setup,
561*4882a593Smuzhiyun 	.buf_queue = rkcif_tools_vb2_buf_queue,
562*4882a593Smuzhiyun 	.wait_prepare = vb2_ops_wait_prepare,
563*4882a593Smuzhiyun 	.wait_finish = vb2_ops_wait_finish,
564*4882a593Smuzhiyun 	.stop_streaming = rkcif_tools_vb2_stop_streaming,
565*4882a593Smuzhiyun 	.start_streaming = rkcif_tools_vb2_start_streaming,
566*4882a593Smuzhiyun };
567*4882a593Smuzhiyun 
rkcif_tools_init_vb2_queue(struct vb2_queue * q,struct rkcif_tools_vdev * tools_vdev,enum v4l2_buf_type buf_type)568*4882a593Smuzhiyun static int rkcif_tools_init_vb2_queue(struct vb2_queue *q,
569*4882a593Smuzhiyun 				      struct rkcif_tools_vdev *tools_vdev,
570*4882a593Smuzhiyun 				      enum v4l2_buf_type buf_type)
571*4882a593Smuzhiyun {
572*4882a593Smuzhiyun 	struct rkcif_hw *hw_dev = tools_vdev->cifdev->hw_dev;
573*4882a593Smuzhiyun 
574*4882a593Smuzhiyun 	q->type = buf_type;
575*4882a593Smuzhiyun 	q->io_modes = VB2_MMAP | VB2_DMABUF;
576*4882a593Smuzhiyun 	q->drv_priv = tools_vdev;
577*4882a593Smuzhiyun 	q->ops = &rkcif_tools_vb2_ops;
578*4882a593Smuzhiyun 	q->mem_ops = hw_dev->mem_ops;
579*4882a593Smuzhiyun 	q->buf_struct_size = sizeof(struct rkcif_buffer);
580*4882a593Smuzhiyun 	q->min_buffers_needed = CIF_TOOLS_REQ_BUFS_MIN;
581*4882a593Smuzhiyun 	q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
582*4882a593Smuzhiyun 	q->lock = &tools_vdev->vnode.vlock;
583*4882a593Smuzhiyun 	q->dev = hw_dev->dev;
584*4882a593Smuzhiyun 	q->allow_cache_hints = 1;
585*4882a593Smuzhiyun 	q->bidirectional = 1;
586*4882a593Smuzhiyun 	q->gfp_flags = GFP_DMA32;
587*4882a593Smuzhiyun 	if (hw_dev->is_dma_contig)
588*4882a593Smuzhiyun 		q->dma_attrs = DMA_ATTR_FORCE_CONTIGUOUS;
589*4882a593Smuzhiyun 	return vb2_queue_init(q);
590*4882a593Smuzhiyun }
591*4882a593Smuzhiyun 
rkcif_tools_buf_done(struct rkcif_tools_vdev * tools_vdev)592*4882a593Smuzhiyun static void rkcif_tools_buf_done(struct rkcif_tools_vdev *tools_vdev)
593*4882a593Smuzhiyun {
594*4882a593Smuzhiyun 	struct rkcif_stream *stream = tools_vdev->stream;
595*4882a593Smuzhiyun 	struct rkcif_tools_buffer *tools_buf;
596*4882a593Smuzhiyun 	const struct cif_output_fmt *fmt = tools_vdev->tools_out_fmt;
597*4882a593Smuzhiyun 	struct rkcif_buffer *buf = NULL;
598*4882a593Smuzhiyun 	int i = 0;
599*4882a593Smuzhiyun 	bool is_find_tools_buf = false;
600*4882a593Smuzhiyun 	unsigned long flags;
601*4882a593Smuzhiyun 
602*4882a593Smuzhiyun retry_done_buf:
603*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
604*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_done_head)) {
605*4882a593Smuzhiyun 		buf = list_first_entry(&tools_vdev->buf_done_head,
606*4882a593Smuzhiyun 				       struct rkcif_buffer, queue);
607*4882a593Smuzhiyun 		if (buf)
608*4882a593Smuzhiyun 			list_del(&buf->queue);
609*4882a593Smuzhiyun 	}
610*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
611*4882a593Smuzhiyun 	if (!buf) {
612*4882a593Smuzhiyun 		v4l2_err(&stream->cifdev->v4l2_dev, "stream[%d] tools fail to get buf form list\n",
613*4882a593Smuzhiyun 			 stream->id);
614*4882a593Smuzhiyun 		return;
615*4882a593Smuzhiyun 	}
616*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->src_buf_head)) {
617*4882a593Smuzhiyun 		list_for_each_entry(tools_buf, &tools_vdev->src_buf_head, list) {
618*4882a593Smuzhiyun 			if (tools_buf->vb == &buf->vb) {
619*4882a593Smuzhiyun 				is_find_tools_buf = true;
620*4882a593Smuzhiyun 				break;
621*4882a593Smuzhiyun 			}
622*4882a593Smuzhiyun 		}
623*4882a593Smuzhiyun 	}
624*4882a593Smuzhiyun 	if (!is_find_tools_buf) {
625*4882a593Smuzhiyun 		tools_buf = kzalloc(sizeof(struct rkcif_tools_buffer), GFP_KERNEL);
626*4882a593Smuzhiyun 		tools_buf->vb = &buf->vb;
627*4882a593Smuzhiyun 		list_add_tail(&tools_buf->list, &tools_vdev->src_buf_head);
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 	tools_buf->use_cnt = 2;
630*4882a593Smuzhiyun 	tools_buf->frame_idx = buf->vb.sequence;
631*4882a593Smuzhiyun 	tools_buf->timestamp = buf->vb.vb2_buf.timestamp;
632*4882a593Smuzhiyun 
633*4882a593Smuzhiyun 	if (tools_vdev->stopping) {
634*4882a593Smuzhiyun 		rkcif_tools_stop(tools_vdev);
635*4882a593Smuzhiyun 		tools_vdev->stopping = false;
636*4882a593Smuzhiyun 		rkcif_vb_done_oneframe(stream, &buf->vb);
637*4882a593Smuzhiyun 		spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
638*4882a593Smuzhiyun 		while (!list_empty(&tools_vdev->buf_done_head)) {
639*4882a593Smuzhiyun 			buf = list_first_entry(&tools_vdev->buf_done_head,
640*4882a593Smuzhiyun 					       struct rkcif_buffer, queue);
641*4882a593Smuzhiyun 			if (buf) {
642*4882a593Smuzhiyun 				list_del(&buf->queue);
643*4882a593Smuzhiyun 				rkcif_vb_done_oneframe(stream, &buf->vb);
644*4882a593Smuzhiyun 			}
645*4882a593Smuzhiyun 		}
646*4882a593Smuzhiyun 		spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
647*4882a593Smuzhiyun 		wake_up(&tools_vdev->wq_stopped);
648*4882a593Smuzhiyun 		return;
649*4882a593Smuzhiyun 	}
650*4882a593Smuzhiyun 	rkcif_vb_done_oneframe(stream, &buf->vb);
651*4882a593Smuzhiyun 
652*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_head)) {
653*4882a593Smuzhiyun 		tools_vdev->curr_buf = list_first_entry(&tools_vdev->buf_head,
654*4882a593Smuzhiyun 						    struct rkcif_buffer, queue);
655*4882a593Smuzhiyun 		if (!tools_vdev->curr_buf || tools_vdev->state != RKCIF_STATE_STREAMING) {
656*4882a593Smuzhiyun 			rkcif_buf_queue(&tools_buf->vb->vb2_buf);
657*4882a593Smuzhiyun 			spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
658*4882a593Smuzhiyun 			if (!list_empty(&tools_vdev->buf_done_head)) {
659*4882a593Smuzhiyun 				spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
660*4882a593Smuzhiyun 				goto retry_done_buf;
661*4882a593Smuzhiyun 			}
662*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
663*4882a593Smuzhiyun 			return;
664*4882a593Smuzhiyun 		}
665*4882a593Smuzhiyun 		list_del(&tools_vdev->curr_buf->queue);
666*4882a593Smuzhiyun 
667*4882a593Smuzhiyun 		/* Dequeue a filled buffer */
668*4882a593Smuzhiyun 		for (i = 0; i < fmt->mplanes; i++) {
669*4882a593Smuzhiyun 			u32 payload_size = tools_vdev->pixm.plane_fmt[i].sizeimage;
670*4882a593Smuzhiyun 			void *src = vb2_plane_vaddr(&buf->vb.vb2_buf, i);
671*4882a593Smuzhiyun 			void *dst = vb2_plane_vaddr(&tools_vdev->curr_buf->vb.vb2_buf, i);
672*4882a593Smuzhiyun 
673*4882a593Smuzhiyun 			if (!src || !dst)
674*4882a593Smuzhiyun 				break;
675*4882a593Smuzhiyun 
676*4882a593Smuzhiyun 			if (buf->vb.vb2_buf.vb2_queue->mem_ops->finish)
677*4882a593Smuzhiyun 				buf->vb.vb2_buf.vb2_queue->mem_ops->finish(buf->vb.vb2_buf.planes[i].mem_priv);
678*4882a593Smuzhiyun 
679*4882a593Smuzhiyun 			vb2_set_plane_payload(&tools_vdev->curr_buf->vb.vb2_buf, i,
680*4882a593Smuzhiyun 					      payload_size);
681*4882a593Smuzhiyun 			memcpy(dst, src, payload_size);
682*4882a593Smuzhiyun 		}
683*4882a593Smuzhiyun 		rkcif_buf_queue(&tools_buf->vb->vb2_buf);
684*4882a593Smuzhiyun 		tools_vdev->curr_buf->vb.sequence = tools_buf->frame_idx;
685*4882a593Smuzhiyun 		tools_vdev->curr_buf->vb.vb2_buf.timestamp = tools_buf->frame_idx;
686*4882a593Smuzhiyun 		vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
687*4882a593Smuzhiyun 		tools_vdev->curr_buf = NULL;
688*4882a593Smuzhiyun 	} else {
689*4882a593Smuzhiyun 		rkcif_buf_queue(&tools_buf->vb->vb2_buf);
690*4882a593Smuzhiyun 	}
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
693*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_done_head)) {
694*4882a593Smuzhiyun 		spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
695*4882a593Smuzhiyun 		goto retry_done_buf;
696*4882a593Smuzhiyun 	}
697*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
698*4882a593Smuzhiyun }
699*4882a593Smuzhiyun 
rkcif_tools_buf_done_rdbk(struct rkcif_tools_vdev * tools_vdev)700*4882a593Smuzhiyun static void rkcif_tools_buf_done_rdbk(struct rkcif_tools_vdev *tools_vdev)
701*4882a593Smuzhiyun {
702*4882a593Smuzhiyun 	struct rkcif_stream *stream = tools_vdev->stream;
703*4882a593Smuzhiyun 	struct rkcif_device *dev = stream->cifdev;
704*4882a593Smuzhiyun 	const struct cif_output_fmt *fmt = tools_vdev->tools_out_fmt;
705*4882a593Smuzhiyun 	struct rkcif_rx_buffer *buf = NULL;
706*4882a593Smuzhiyun 	int i = 0;
707*4882a593Smuzhiyun 	unsigned long flags;
708*4882a593Smuzhiyun 
709*4882a593Smuzhiyun retry_done_rdbk_buf:
710*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
711*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_done_head)) {
712*4882a593Smuzhiyun 		buf = list_first_entry(&tools_vdev->buf_done_head,
713*4882a593Smuzhiyun 				       struct rkcif_rx_buffer, list);
714*4882a593Smuzhiyun 		if (buf)
715*4882a593Smuzhiyun 			list_del(&buf->list);
716*4882a593Smuzhiyun 	}
717*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
718*4882a593Smuzhiyun 	if (!buf) {
719*4882a593Smuzhiyun 		v4l2_err(&dev->v4l2_dev, "stream[%d] tools fail to get buf form list\n",
720*4882a593Smuzhiyun 			 stream->id);
721*4882a593Smuzhiyun 		return;
722*4882a593Smuzhiyun 	}
723*4882a593Smuzhiyun 
724*4882a593Smuzhiyun 	if (tools_vdev->stopping) {
725*4882a593Smuzhiyun 		rkcif_tools_stop(tools_vdev);
726*4882a593Smuzhiyun 		tools_vdev->stopping = false;
727*4882a593Smuzhiyun 		spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
728*4882a593Smuzhiyun 		while (!list_empty(&tools_vdev->buf_done_head)) {
729*4882a593Smuzhiyun 			buf = list_first_entry(&tools_vdev->buf_done_head,
730*4882a593Smuzhiyun 					       struct rkcif_rx_buffer, list);
731*4882a593Smuzhiyun 			if (buf)
732*4882a593Smuzhiyun 				list_del(&buf->list);
733*4882a593Smuzhiyun 		}
734*4882a593Smuzhiyun 		spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
735*4882a593Smuzhiyun 		wake_up(&tools_vdev->wq_stopped);
736*4882a593Smuzhiyun 		return;
737*4882a593Smuzhiyun 	}
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_head)) {
740*4882a593Smuzhiyun 		tools_vdev->curr_buf = list_first_entry(&tools_vdev->buf_head,
741*4882a593Smuzhiyun 						    struct rkcif_buffer, queue);
742*4882a593Smuzhiyun 		if (!tools_vdev->curr_buf || tools_vdev->state != RKCIF_STATE_STREAMING) {
743*4882a593Smuzhiyun 			spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
744*4882a593Smuzhiyun 			if (!list_empty(&tools_vdev->buf_done_head)) {
745*4882a593Smuzhiyun 				spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
746*4882a593Smuzhiyun 				goto retry_done_rdbk_buf;
747*4882a593Smuzhiyun 			}
748*4882a593Smuzhiyun 			spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
749*4882a593Smuzhiyun 			return;
750*4882a593Smuzhiyun 		}
751*4882a593Smuzhiyun 		list_del(&tools_vdev->curr_buf->queue);
752*4882a593Smuzhiyun 		/* Dequeue a filled buffer */
753*4882a593Smuzhiyun 		for (i = 0; i < fmt->mplanes; i++) {
754*4882a593Smuzhiyun 			u32 payload_size = tools_vdev->pixm.plane_fmt[i].sizeimage;
755*4882a593Smuzhiyun 			void *src = buf->dummy.vaddr;
756*4882a593Smuzhiyun 			void *dst = vb2_plane_vaddr(&tools_vdev->curr_buf->vb.vb2_buf, i);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 			if (!src || !dst)
759*4882a593Smuzhiyun 				break;
760*4882a593Smuzhiyun 			dma_sync_single_for_device(dev->dev,
761*4882a593Smuzhiyun 						   buf->dummy.dma_addr,
762*4882a593Smuzhiyun 						   buf->dummy.size,
763*4882a593Smuzhiyun 						   DMA_FROM_DEVICE);
764*4882a593Smuzhiyun 			vb2_set_plane_payload(&tools_vdev->curr_buf->vb.vb2_buf, i,
765*4882a593Smuzhiyun 					      payload_size);
766*4882a593Smuzhiyun 			memcpy(dst, src, payload_size);
767*4882a593Smuzhiyun 		}
768*4882a593Smuzhiyun 		tools_vdev->curr_buf->vb.sequence = buf->dbufs.sequence;
769*4882a593Smuzhiyun 		tools_vdev->curr_buf->vb.vb2_buf.timestamp = buf->dbufs.timestamp;
770*4882a593Smuzhiyun 		vb2_buffer_done(&tools_vdev->curr_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
771*4882a593Smuzhiyun 		tools_vdev->curr_buf = NULL;
772*4882a593Smuzhiyun 	}
773*4882a593Smuzhiyun 
774*4882a593Smuzhiyun 	spin_lock_irqsave(&tools_vdev->vbq_lock, flags);
775*4882a593Smuzhiyun 	if (!list_empty(&tools_vdev->buf_done_head)) {
776*4882a593Smuzhiyun 		spin_unlock_irqrestore(&stream->tools_vdev->vbq_lock, flags);
777*4882a593Smuzhiyun 		goto retry_done_rdbk_buf;
778*4882a593Smuzhiyun 	}
779*4882a593Smuzhiyun 	spin_unlock_irqrestore(&tools_vdev->vbq_lock, flags);
780*4882a593Smuzhiyun }
781*4882a593Smuzhiyun 
rkcif_tools_work(struct work_struct * work)782*4882a593Smuzhiyun static void rkcif_tools_work(struct work_struct *work)
783*4882a593Smuzhiyun {
784*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = container_of(work,
785*4882a593Smuzhiyun 						struct rkcif_tools_vdev,
786*4882a593Smuzhiyun 						work);
787*4882a593Smuzhiyun 	if (tools_vdev->stream->dma_en & RKCIF_DMAEN_BY_VICAP)
788*4882a593Smuzhiyun 		rkcif_tools_buf_done(tools_vdev);
789*4882a593Smuzhiyun 	else if (tools_vdev->stream->dma_en & RKCIF_DMAEN_BY_ISP)
790*4882a593Smuzhiyun 		rkcif_tools_buf_done_rdbk(tools_vdev);
791*4882a593Smuzhiyun }
792*4882a593Smuzhiyun 
rkcif_init_tools_vdev(struct rkcif_device * cif_dev,u32 ch)793*4882a593Smuzhiyun void rkcif_init_tools_vdev(struct rkcif_device *cif_dev, u32 ch)
794*4882a593Smuzhiyun {
795*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev = &cif_dev->tools_vdev[ch];
796*4882a593Smuzhiyun 	struct rkcif_stream *stream = &cif_dev->stream[ch];
797*4882a593Smuzhiyun 	struct v4l2_pix_format_mplane pixm;
798*4882a593Smuzhiyun 
799*4882a593Smuzhiyun 	memset(tools_vdev, 0, sizeof(*tools_vdev));
800*4882a593Smuzhiyun 	memset(&pixm, 0, sizeof(pixm));
801*4882a593Smuzhiyun 	tools_vdev->cifdev = cif_dev;
802*4882a593Smuzhiyun 	tools_vdev->stream = stream;
803*4882a593Smuzhiyun 	stream->tools_vdev = tools_vdev;
804*4882a593Smuzhiyun 	tools_vdev->ch = ch;
805*4882a593Smuzhiyun 	tools_vdev->frame_idx = 0;
806*4882a593Smuzhiyun 	pixm.pixelformat = V4L2_PIX_FMT_SBGGR10;
807*4882a593Smuzhiyun 	pixm.width = RKCIF_DEFAULT_WIDTH;
808*4882a593Smuzhiyun 	pixm.height = RKCIF_DEFAULT_HEIGHT;
809*4882a593Smuzhiyun 	tools_vdev->state = RKCIF_STATE_READY;
810*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tools_vdev->buf_head);
811*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tools_vdev->buf_done_head);
812*4882a593Smuzhiyun 	INIT_LIST_HEAD(&tools_vdev->src_buf_head);
813*4882a593Smuzhiyun 	spin_lock_init(&tools_vdev->vbq_lock);
814*4882a593Smuzhiyun 	rkcif_tools_set_fmt(tools_vdev, &pixm, false);
815*4882a593Smuzhiyun 	init_waitqueue_head(&tools_vdev->wq_stopped);
816*4882a593Smuzhiyun 	INIT_WORK(&tools_vdev->work, rkcif_tools_work);
817*4882a593Smuzhiyun }
818*4882a593Smuzhiyun 
rkcif_register_tools_vdev(struct rkcif_tools_vdev * tools_vdev,bool is_multi_input)819*4882a593Smuzhiyun static int rkcif_register_tools_vdev(struct rkcif_tools_vdev *tools_vdev, bool is_multi_input)
820*4882a593Smuzhiyun {
821*4882a593Smuzhiyun 	int ret = 0;
822*4882a593Smuzhiyun 	struct video_device *vdev = &tools_vdev->vnode.vdev;
823*4882a593Smuzhiyun 	struct rkcif_vdev_node *node;
824*4882a593Smuzhiyun 	char *vdev_name;
825*4882a593Smuzhiyun 
826*4882a593Smuzhiyun 	switch (tools_vdev->ch) {
827*4882a593Smuzhiyun 	case RKCIF_TOOLS_CH0:
828*4882a593Smuzhiyun 		vdev_name = CIF_TOOLS_CH0_VDEV_NAME;
829*4882a593Smuzhiyun 		break;
830*4882a593Smuzhiyun 	case RKCIF_TOOLS_CH1:
831*4882a593Smuzhiyun 		vdev_name = CIF_TOOLS_CH1_VDEV_NAME;
832*4882a593Smuzhiyun 		break;
833*4882a593Smuzhiyun 	case RKCIF_TOOLS_CH2:
834*4882a593Smuzhiyun 		vdev_name = CIF_TOOLS_CH2_VDEV_NAME;
835*4882a593Smuzhiyun 		break;
836*4882a593Smuzhiyun 	default:
837*4882a593Smuzhiyun 		ret = -EINVAL;
838*4882a593Smuzhiyun 		v4l2_err(&tools_vdev->cifdev->v4l2_dev, "Invalid stream\n");
839*4882a593Smuzhiyun 		goto err_cleanup_media_entity;
840*4882a593Smuzhiyun 	}
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	strscpy(vdev->name, vdev_name, sizeof(vdev->name));
843*4882a593Smuzhiyun 	node = container_of(vdev, struct rkcif_vdev_node, vdev);
844*4882a593Smuzhiyun 	mutex_init(&node->vlock);
845*4882a593Smuzhiyun 
846*4882a593Smuzhiyun 	vdev->ioctl_ops = &rkcif_tools_ioctl;
847*4882a593Smuzhiyun 	vdev->fops = &rkcif_tools_fops;
848*4882a593Smuzhiyun 	vdev->release = video_device_release_empty;
849*4882a593Smuzhiyun 	vdev->lock = &node->vlock;
850*4882a593Smuzhiyun 	vdev->v4l2_dev = &tools_vdev->cifdev->v4l2_dev;
851*4882a593Smuzhiyun 	vdev->queue = &node->buf_queue;
852*4882a593Smuzhiyun 	vdev->device_caps = V4L2_CAP_VIDEO_CAPTURE_MPLANE |
853*4882a593Smuzhiyun 			    V4L2_CAP_STREAMING;
854*4882a593Smuzhiyun 	vdev->vfl_dir =  VFL_DIR_RX;
855*4882a593Smuzhiyun 	node->pad.flags = MEDIA_PAD_FL_SINK;
856*4882a593Smuzhiyun 	video_set_drvdata(vdev, tools_vdev);
857*4882a593Smuzhiyun 
858*4882a593Smuzhiyun 	rkcif_tools_init_vb2_queue(&node->buf_queue,
859*4882a593Smuzhiyun 				   tools_vdev,
860*4882a593Smuzhiyun 				   V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE);
861*4882a593Smuzhiyun 	vdev->queue = &node->buf_queue;
862*4882a593Smuzhiyun 
863*4882a593Smuzhiyun 	ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
864*4882a593Smuzhiyun 	if (ret < 0)
865*4882a593Smuzhiyun 		goto err_release_queue;
866*4882a593Smuzhiyun 
867*4882a593Smuzhiyun 	ret = video_register_device(vdev, VFL_TYPE_VIDEO, -1);
868*4882a593Smuzhiyun 	if (ret < 0) {
869*4882a593Smuzhiyun 		dev_err(&vdev->dev,
870*4882a593Smuzhiyun 			"could not register Video for Linux device\n");
871*4882a593Smuzhiyun 		goto err_cleanup_media_entity;
872*4882a593Smuzhiyun 	}
873*4882a593Smuzhiyun 	return 0;
874*4882a593Smuzhiyun 
875*4882a593Smuzhiyun err_cleanup_media_entity:
876*4882a593Smuzhiyun 	media_entity_cleanup(&vdev->entity);
877*4882a593Smuzhiyun err_release_queue:
878*4882a593Smuzhiyun 	vb2_queue_release(vdev->queue);
879*4882a593Smuzhiyun 	return ret;
880*4882a593Smuzhiyun }
881*4882a593Smuzhiyun 
rkcif_unregister_tools_vdev(struct rkcif_tools_vdev * tools_vdev)882*4882a593Smuzhiyun static void rkcif_unregister_tools_vdev(struct rkcif_tools_vdev *tools_vdev)
883*4882a593Smuzhiyun {
884*4882a593Smuzhiyun 	struct rkcif_vdev_node *node = &tools_vdev->vnode;
885*4882a593Smuzhiyun 	struct video_device *vdev = &node->vdev;
886*4882a593Smuzhiyun 
887*4882a593Smuzhiyun 	video_unregister_device(vdev);
888*4882a593Smuzhiyun 	media_entity_cleanup(&vdev->entity);
889*4882a593Smuzhiyun 	vb2_queue_release(vdev->queue);
890*4882a593Smuzhiyun }
891*4882a593Smuzhiyun 
rkcif_register_tools_vdevs(struct rkcif_device * cif_dev,int stream_num,bool is_multi_input)892*4882a593Smuzhiyun int rkcif_register_tools_vdevs(struct rkcif_device *cif_dev,
893*4882a593Smuzhiyun 			       int stream_num,
894*4882a593Smuzhiyun 			       bool is_multi_input)
895*4882a593Smuzhiyun {
896*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev;
897*4882a593Smuzhiyun 	int i, j, ret;
898*4882a593Smuzhiyun 
899*4882a593Smuzhiyun 	for (i = 0; i < stream_num; i++) {
900*4882a593Smuzhiyun 		tools_vdev = &cif_dev->tools_vdev[i];
901*4882a593Smuzhiyun 		ret = rkcif_register_tools_vdev(tools_vdev, is_multi_input);
902*4882a593Smuzhiyun 		if (ret < 0)
903*4882a593Smuzhiyun 			goto err;
904*4882a593Smuzhiyun 	}
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 	return 0;
907*4882a593Smuzhiyun err:
908*4882a593Smuzhiyun 	for (j = 0; j < i; j++) {
909*4882a593Smuzhiyun 		tools_vdev = &cif_dev->tools_vdev[j];
910*4882a593Smuzhiyun 		rkcif_unregister_tools_vdev(tools_vdev);
911*4882a593Smuzhiyun 	}
912*4882a593Smuzhiyun 
913*4882a593Smuzhiyun 	return ret;
914*4882a593Smuzhiyun }
915*4882a593Smuzhiyun 
rkcif_unregister_tools_vdevs(struct rkcif_device * cif_dev,int stream_num)916*4882a593Smuzhiyun void rkcif_unregister_tools_vdevs(struct rkcif_device *cif_dev,
917*4882a593Smuzhiyun 				  int stream_num)
918*4882a593Smuzhiyun {
919*4882a593Smuzhiyun 	struct rkcif_tools_vdev *tools_vdev;
920*4882a593Smuzhiyun 	int i;
921*4882a593Smuzhiyun 
922*4882a593Smuzhiyun 	for (i = 0; i < stream_num; i++) {
923*4882a593Smuzhiyun 		tools_vdev = &cif_dev->tools_vdev[i];
924*4882a593Smuzhiyun 		rkcif_unregister_tools_vdev(tools_vdev);
925*4882a593Smuzhiyun 	}
926*4882a593Smuzhiyun }
927