1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * Copyright (c) 2011-2018 Magewell Electronics Co., Ltd. (Nanjing)
4  * All rights reserved.
5  * Author: Yong Deng <yong.deng@magewell.com>
6  */
7 
8 #include <linux/of.h>
9 
10 #include <media/v4l2-device.h>
11 #include <media/v4l2-event.h>
12 #include <media/v4l2-ioctl.h>
13 #include <media/v4l2-mc.h>
14 #include <media/videobuf2-dma-contig.h>
15 #include <media/videobuf2-v4l2.h>
16 
17 #include "sun6i_csi.h"
18 #include "sun6i_video.h"
19 
20 /* This is got from BSP sources. */
21 #define MIN_WIDTH	(32)
22 #define MIN_HEIGHT	(32)
23 #define MAX_WIDTH	(4800)
24 #define MAX_HEIGHT	(4800)
25 
26 /* Helpers */
27 
28 static struct v4l2_subdev *
sun6i_video_remote_subdev(struct sun6i_video * video,u32 * pad)29 sun6i_video_remote_subdev(struct sun6i_video *video, u32 *pad)
30 {
31 	struct media_pad *remote;
32 
33 	remote = media_pad_remote_pad_first(&video->pad);
34 
35 	if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
36 		return NULL;
37 
38 	if (pad)
39 		*pad = remote->index;
40 
41 	return media_entity_to_v4l2_subdev(remote->entity);
42 }
43 
44 /* Format */
45 
46 static const u32 sun6i_video_formats[] = {
47 	V4L2_PIX_FMT_SBGGR8,
48 	V4L2_PIX_FMT_SGBRG8,
49 	V4L2_PIX_FMT_SGRBG8,
50 	V4L2_PIX_FMT_SRGGB8,
51 	V4L2_PIX_FMT_SBGGR10,
52 	V4L2_PIX_FMT_SGBRG10,
53 	V4L2_PIX_FMT_SGRBG10,
54 	V4L2_PIX_FMT_SRGGB10,
55 	V4L2_PIX_FMT_SBGGR12,
56 	V4L2_PIX_FMT_SGBRG12,
57 	V4L2_PIX_FMT_SGRBG12,
58 	V4L2_PIX_FMT_SRGGB12,
59 	V4L2_PIX_FMT_YUYV,
60 	V4L2_PIX_FMT_YVYU,
61 	V4L2_PIX_FMT_UYVY,
62 	V4L2_PIX_FMT_VYUY,
63 	V4L2_PIX_FMT_NV12_16L16,
64 	V4L2_PIX_FMT_NV12,
65 	V4L2_PIX_FMT_NV21,
66 	V4L2_PIX_FMT_YUV420,
67 	V4L2_PIX_FMT_YVU420,
68 	V4L2_PIX_FMT_NV16,
69 	V4L2_PIX_FMT_NV61,
70 	V4L2_PIX_FMT_YUV422P,
71 	V4L2_PIX_FMT_RGB565,
72 	V4L2_PIX_FMT_RGB565X,
73 	V4L2_PIX_FMT_JPEG,
74 };
75 
sun6i_video_format_check(u32 format)76 static bool sun6i_video_format_check(u32 format)
77 {
78 	unsigned int i;
79 
80 	for (i = 0; i < ARRAY_SIZE(sun6i_video_formats); i++)
81 		if (sun6i_video_formats[i] == format)
82 			return true;
83 
84 	return false;
85 }
86 
87 /* Video */
88 
sun6i_video_buffer_configure(struct sun6i_csi_device * csi_dev,struct sun6i_csi_buffer * csi_buffer)89 static void sun6i_video_buffer_configure(struct sun6i_csi_device *csi_dev,
90 					 struct sun6i_csi_buffer *csi_buffer)
91 {
92 	csi_buffer->queued_to_csi = true;
93 	sun6i_csi_update_buf_addr(csi_dev, csi_buffer->dma_addr);
94 }
95 
sun6i_video_configure(struct sun6i_csi_device * csi_dev)96 static void sun6i_video_configure(struct sun6i_csi_device *csi_dev)
97 {
98 	struct sun6i_video *video = &csi_dev->video;
99 	struct sun6i_csi_config config = { 0 };
100 
101 	config.pixelformat = video->format.fmt.pix.pixelformat;
102 	config.code = video->mbus_code;
103 	config.field = video->format.fmt.pix.field;
104 	config.width = video->format.fmt.pix.width;
105 	config.height = video->format.fmt.pix.height;
106 
107 	sun6i_csi_update_config(csi_dev, &config);
108 }
109 
110 /* Queue */
111 
sun6i_video_queue_setup(struct vb2_queue * queue,unsigned int * buffers_count,unsigned int * planes_count,unsigned int sizes[],struct device * alloc_devs[])112 static int sun6i_video_queue_setup(struct vb2_queue *queue,
113 				   unsigned int *buffers_count,
114 				   unsigned int *planes_count,
115 				   unsigned int sizes[],
116 				   struct device *alloc_devs[])
117 {
118 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
119 	struct sun6i_video *video = &csi_dev->video;
120 	unsigned int size = video->format.fmt.pix.sizeimage;
121 
122 	if (*planes_count)
123 		return sizes[0] < size ? -EINVAL : 0;
124 
125 	*planes_count = 1;
126 	sizes[0] = size;
127 
128 	return 0;
129 }
130 
sun6i_video_buffer_prepare(struct vb2_buffer * buffer)131 static int sun6i_video_buffer_prepare(struct vb2_buffer *buffer)
132 {
133 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue);
134 	struct sun6i_video *video = &csi_dev->video;
135 	struct v4l2_device *v4l2_dev = &csi_dev->v4l2.v4l2_dev;
136 	struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer);
137 	struct sun6i_csi_buffer *csi_buffer =
138 		container_of(v4l2_buffer, struct sun6i_csi_buffer, v4l2_buffer);
139 	unsigned long size = video->format.fmt.pix.sizeimage;
140 
141 	if (vb2_plane_size(buffer, 0) < size) {
142 		v4l2_err(v4l2_dev, "buffer too small (%lu < %lu)\n",
143 			 vb2_plane_size(buffer, 0), size);
144 		return -EINVAL;
145 	}
146 
147 	vb2_set_plane_payload(buffer, 0, size);
148 
149 	csi_buffer->dma_addr = vb2_dma_contig_plane_dma_addr(buffer, 0);
150 	v4l2_buffer->field = video->format.fmt.pix.field;
151 
152 	return 0;
153 }
154 
sun6i_video_buffer_queue(struct vb2_buffer * buffer)155 static void sun6i_video_buffer_queue(struct vb2_buffer *buffer)
156 {
157 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(buffer->vb2_queue);
158 	struct sun6i_video *video = &csi_dev->video;
159 	struct vb2_v4l2_buffer *v4l2_buffer = to_vb2_v4l2_buffer(buffer);
160 	struct sun6i_csi_buffer *csi_buffer =
161 		container_of(v4l2_buffer, struct sun6i_csi_buffer, v4l2_buffer);
162 	unsigned long flags;
163 
164 	spin_lock_irqsave(&video->dma_queue_lock, flags);
165 	csi_buffer->queued_to_csi = false;
166 	list_add_tail(&csi_buffer->list, &video->dma_queue);
167 	spin_unlock_irqrestore(&video->dma_queue_lock, flags);
168 }
169 
sun6i_video_start_streaming(struct vb2_queue * queue,unsigned int count)170 static int sun6i_video_start_streaming(struct vb2_queue *queue,
171 				       unsigned int count)
172 {
173 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
174 	struct sun6i_video *video = &csi_dev->video;
175 	struct video_device *video_dev = &video->video_dev;
176 	struct sun6i_csi_buffer *buf;
177 	struct sun6i_csi_buffer *next_buf;
178 	struct v4l2_subdev *subdev;
179 	unsigned long flags;
180 	int ret;
181 
182 	video->sequence = 0;
183 
184 	ret = video_device_pipeline_alloc_start(video_dev);
185 	if (ret < 0)
186 		goto error_dma_queue_flush;
187 
188 	if (video->mbus_code == 0) {
189 		ret = -EINVAL;
190 		goto error_media_pipeline;
191 	}
192 
193 	subdev = sun6i_video_remote_subdev(video, NULL);
194 	if (!subdev) {
195 		ret = -EINVAL;
196 		goto error_media_pipeline;
197 	}
198 
199 	sun6i_video_configure(csi_dev);
200 
201 	spin_lock_irqsave(&video->dma_queue_lock, flags);
202 
203 	buf = list_first_entry(&video->dma_queue,
204 			       struct sun6i_csi_buffer, list);
205 	sun6i_video_buffer_configure(csi_dev, buf);
206 
207 	sun6i_csi_set_stream(csi_dev, true);
208 
209 	/*
210 	 * CSI will lookup the next dma buffer for next frame before the
211 	 * current frame done IRQ triggered. This is not documented
212 	 * but reported by Ondřej Jirman.
213 	 * The BSP code has workaround for this too. It skip to mark the
214 	 * first buffer as frame done for VB2 and pass the second buffer
215 	 * to CSI in the first frame done ISR call. Then in second frame
216 	 * done ISR call, it mark the first buffer as frame done for VB2
217 	 * and pass the third buffer to CSI. And so on. The bad thing is
218 	 * that the first buffer will be written twice and the first frame
219 	 * is dropped even the queued buffer is sufficient.
220 	 * So, I make some improvement here. Pass the next buffer to CSI
221 	 * just follow starting the CSI. In this case, the first frame
222 	 * will be stored in first buffer, second frame in second buffer.
223 	 * This method is used to avoid dropping the first frame, it
224 	 * would also drop frame when lacking of queued buffer.
225 	 */
226 	next_buf = list_next_entry(buf, list);
227 	sun6i_video_buffer_configure(csi_dev, next_buf);
228 
229 	spin_unlock_irqrestore(&video->dma_queue_lock, flags);
230 
231 	ret = v4l2_subdev_call(subdev, video, s_stream, 1);
232 	if (ret && ret != -ENOIOCTLCMD)
233 		goto error_stream;
234 
235 	return 0;
236 
237 error_stream:
238 	sun6i_csi_set_stream(csi_dev, false);
239 
240 error_media_pipeline:
241 	video_device_pipeline_stop(video_dev);
242 
243 error_dma_queue_flush:
244 	spin_lock_irqsave(&video->dma_queue_lock, flags);
245 	list_for_each_entry(buf, &video->dma_queue, list)
246 		vb2_buffer_done(&buf->v4l2_buffer.vb2_buf,
247 				VB2_BUF_STATE_QUEUED);
248 	INIT_LIST_HEAD(&video->dma_queue);
249 	spin_unlock_irqrestore(&video->dma_queue_lock, flags);
250 
251 	return ret;
252 }
253 
sun6i_video_stop_streaming(struct vb2_queue * queue)254 static void sun6i_video_stop_streaming(struct vb2_queue *queue)
255 {
256 	struct sun6i_csi_device *csi_dev = vb2_get_drv_priv(queue);
257 	struct sun6i_video *video = &csi_dev->video;
258 	struct v4l2_subdev *subdev;
259 	unsigned long flags;
260 	struct sun6i_csi_buffer *buf;
261 
262 	subdev = sun6i_video_remote_subdev(video, NULL);
263 	if (subdev)
264 		v4l2_subdev_call(subdev, video, s_stream, 0);
265 
266 	sun6i_csi_set_stream(csi_dev, false);
267 
268 	video_device_pipeline_stop(&video->video_dev);
269 
270 	/* Release all active buffers */
271 	spin_lock_irqsave(&video->dma_queue_lock, flags);
272 	list_for_each_entry(buf, &video->dma_queue, list)
273 		vb2_buffer_done(&buf->v4l2_buffer.vb2_buf, VB2_BUF_STATE_ERROR);
274 	INIT_LIST_HEAD(&video->dma_queue);
275 	spin_unlock_irqrestore(&video->dma_queue_lock, flags);
276 }
277 
sun6i_video_frame_done(struct sun6i_csi_device * csi_dev)278 void sun6i_video_frame_done(struct sun6i_csi_device *csi_dev)
279 {
280 	struct sun6i_video *video = &csi_dev->video;
281 	struct sun6i_csi_buffer *buf;
282 	struct sun6i_csi_buffer *next_buf;
283 	struct vb2_v4l2_buffer *v4l2_buffer;
284 
285 	spin_lock(&video->dma_queue_lock);
286 
287 	buf = list_first_entry(&video->dma_queue,
288 			       struct sun6i_csi_buffer, list);
289 	if (list_is_last(&buf->list, &video->dma_queue)) {
290 		dev_dbg(csi_dev->dev, "Frame dropped!\n");
291 		goto complete;
292 	}
293 
294 	next_buf = list_next_entry(buf, list);
295 	/* If a new buffer (#next_buf) had not been queued to CSI, the old
296 	 * buffer (#buf) is still holding by CSI for storing the next
297 	 * frame. So, we queue a new buffer (#next_buf) to CSI then wait
298 	 * for next ISR call.
299 	 */
300 	if (!next_buf->queued_to_csi) {
301 		sun6i_video_buffer_configure(csi_dev, next_buf);
302 		dev_dbg(csi_dev->dev, "Frame dropped!\n");
303 		goto complete;
304 	}
305 
306 	list_del(&buf->list);
307 	v4l2_buffer = &buf->v4l2_buffer;
308 	v4l2_buffer->vb2_buf.timestamp = ktime_get_ns();
309 	v4l2_buffer->sequence = video->sequence;
310 	vb2_buffer_done(&v4l2_buffer->vb2_buf, VB2_BUF_STATE_DONE);
311 
312 	/* Prepare buffer for next frame but one.  */
313 	if (!list_is_last(&next_buf->list, &video->dma_queue)) {
314 		next_buf = list_next_entry(next_buf, list);
315 		sun6i_video_buffer_configure(csi_dev, next_buf);
316 	} else {
317 		dev_dbg(csi_dev->dev, "Next frame will be dropped!\n");
318 	}
319 
320 complete:
321 	video->sequence++;
322 	spin_unlock(&video->dma_queue_lock);
323 }
324 
325 static const struct vb2_ops sun6i_video_queue_ops = {
326 	.queue_setup		= sun6i_video_queue_setup,
327 	.buf_prepare		= sun6i_video_buffer_prepare,
328 	.buf_queue		= sun6i_video_buffer_queue,
329 	.start_streaming	= sun6i_video_start_streaming,
330 	.stop_streaming		= sun6i_video_stop_streaming,
331 	.wait_prepare		= vb2_ops_wait_prepare,
332 	.wait_finish		= vb2_ops_wait_finish,
333 };
334 
335 /* V4L2 Device */
336 
sun6i_video_querycap(struct file * file,void * private,struct v4l2_capability * capability)337 static int sun6i_video_querycap(struct file *file, void *private,
338 				struct v4l2_capability *capability)
339 {
340 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
341 	struct video_device *video_dev = &csi_dev->video.video_dev;
342 
343 	strscpy(capability->driver, SUN6I_CSI_NAME, sizeof(capability->driver));
344 	strscpy(capability->card, video_dev->name, sizeof(capability->card));
345 	snprintf(capability->bus_info, sizeof(capability->bus_info),
346 		 "platform:%s", dev_name(csi_dev->dev));
347 
348 	return 0;
349 }
350 
sun6i_video_enum_fmt(struct file * file,void * private,struct v4l2_fmtdesc * fmtdesc)351 static int sun6i_video_enum_fmt(struct file *file, void *private,
352 				struct v4l2_fmtdesc *fmtdesc)
353 {
354 	u32 index = fmtdesc->index;
355 
356 	if (index >= ARRAY_SIZE(sun6i_video_formats))
357 		return -EINVAL;
358 
359 	fmtdesc->pixelformat = sun6i_video_formats[index];
360 
361 	return 0;
362 }
363 
sun6i_video_g_fmt(struct file * file,void * private,struct v4l2_format * format)364 static int sun6i_video_g_fmt(struct file *file, void *private,
365 			     struct v4l2_format *format)
366 {
367 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
368 	struct sun6i_video *video = &csi_dev->video;
369 
370 	*format = video->format;
371 
372 	return 0;
373 }
374 
sun6i_video_format_try(struct sun6i_video * video,struct v4l2_format * format)375 static int sun6i_video_format_try(struct sun6i_video *video,
376 				  struct v4l2_format *format)
377 {
378 	struct v4l2_pix_format *pix_format = &format->fmt.pix;
379 	int bpp;
380 
381 	if (!sun6i_video_format_check(pix_format->pixelformat))
382 		pix_format->pixelformat = sun6i_video_formats[0];
383 
384 	v4l_bound_align_image(&pix_format->width, MIN_WIDTH, MAX_WIDTH, 1,
385 			      &pix_format->height, MIN_HEIGHT, MAX_WIDTH, 1, 1);
386 
387 	bpp = sun6i_csi_get_bpp(pix_format->pixelformat);
388 	pix_format->bytesperline = (pix_format->width * bpp) >> 3;
389 	pix_format->sizeimage = pix_format->bytesperline * pix_format->height;
390 
391 	if (pix_format->field == V4L2_FIELD_ANY)
392 		pix_format->field = V4L2_FIELD_NONE;
393 
394 	if (pix_format->pixelformat == V4L2_PIX_FMT_JPEG)
395 		pix_format->colorspace = V4L2_COLORSPACE_JPEG;
396 	else
397 		pix_format->colorspace = V4L2_COLORSPACE_SRGB;
398 
399 	pix_format->ycbcr_enc = V4L2_YCBCR_ENC_DEFAULT;
400 	pix_format->quantization = V4L2_QUANTIZATION_DEFAULT;
401 	pix_format->xfer_func = V4L2_XFER_FUNC_DEFAULT;
402 
403 	return 0;
404 }
405 
sun6i_video_format_set(struct sun6i_video * video,struct v4l2_format * format)406 static int sun6i_video_format_set(struct sun6i_video *video,
407 				  struct v4l2_format *format)
408 {
409 	int ret;
410 
411 	ret = sun6i_video_format_try(video, format);
412 	if (ret)
413 		return ret;
414 
415 	video->format = *format;
416 
417 	return 0;
418 }
419 
sun6i_video_s_fmt(struct file * file,void * private,struct v4l2_format * format)420 static int sun6i_video_s_fmt(struct file *file, void *private,
421 			     struct v4l2_format *format)
422 {
423 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
424 	struct sun6i_video *video = &csi_dev->video;
425 
426 	if (vb2_is_busy(&video->queue))
427 		return -EBUSY;
428 
429 	return sun6i_video_format_set(video, format);
430 }
431 
sun6i_video_try_fmt(struct file * file,void * private,struct v4l2_format * format)432 static int sun6i_video_try_fmt(struct file *file, void *private,
433 			       struct v4l2_format *format)
434 {
435 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
436 	struct sun6i_video *video = &csi_dev->video;
437 
438 	return sun6i_video_format_try(video, format);
439 }
440 
sun6i_video_enum_input(struct file * file,void * private,struct v4l2_input * input)441 static int sun6i_video_enum_input(struct file *file, void *private,
442 				  struct v4l2_input *input)
443 {
444 	if (input->index != 0)
445 		return -EINVAL;
446 
447 	input->type = V4L2_INPUT_TYPE_CAMERA;
448 	strscpy(input->name, "Camera", sizeof(input->name));
449 
450 	return 0;
451 }
452 
sun6i_video_g_input(struct file * file,void * private,unsigned int * index)453 static int sun6i_video_g_input(struct file *file, void *private,
454 			       unsigned int *index)
455 {
456 	*index = 0;
457 
458 	return 0;
459 }
460 
sun6i_video_s_input(struct file * file,void * private,unsigned int index)461 static int sun6i_video_s_input(struct file *file, void *private,
462 			       unsigned int index)
463 {
464 	if (index != 0)
465 		return -EINVAL;
466 
467 	return 0;
468 }
469 
470 static const struct v4l2_ioctl_ops sun6i_video_ioctl_ops = {
471 	.vidioc_querycap		= sun6i_video_querycap,
472 
473 	.vidioc_enum_fmt_vid_cap	= sun6i_video_enum_fmt,
474 	.vidioc_g_fmt_vid_cap		= sun6i_video_g_fmt,
475 	.vidioc_s_fmt_vid_cap		= sun6i_video_s_fmt,
476 	.vidioc_try_fmt_vid_cap		= sun6i_video_try_fmt,
477 
478 	.vidioc_enum_input		= sun6i_video_enum_input,
479 	.vidioc_g_input			= sun6i_video_g_input,
480 	.vidioc_s_input			= sun6i_video_s_input,
481 
482 	.vidioc_create_bufs		= vb2_ioctl_create_bufs,
483 	.vidioc_prepare_buf		= vb2_ioctl_prepare_buf,
484 	.vidioc_reqbufs			= vb2_ioctl_reqbufs,
485 	.vidioc_querybuf		= vb2_ioctl_querybuf,
486 	.vidioc_expbuf			= vb2_ioctl_expbuf,
487 	.vidioc_qbuf			= vb2_ioctl_qbuf,
488 	.vidioc_dqbuf			= vb2_ioctl_dqbuf,
489 	.vidioc_streamon		= vb2_ioctl_streamon,
490 	.vidioc_streamoff		= vb2_ioctl_streamoff,
491 };
492 
493 /* V4L2 File */
494 
sun6i_video_open(struct file * file)495 static int sun6i_video_open(struct file *file)
496 {
497 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
498 	struct sun6i_video *video = &csi_dev->video;
499 	int ret = 0;
500 
501 	if (mutex_lock_interruptible(&video->lock))
502 		return -ERESTARTSYS;
503 
504 	ret = v4l2_fh_open(file);
505 	if (ret < 0)
506 		goto error_lock;
507 
508 	ret = v4l2_pipeline_pm_get(&video->video_dev.entity);
509 	if (ret < 0)
510 		goto error_v4l2_fh;
511 
512 	/* Power on at first open. */
513 	if (v4l2_fh_is_singular_file(file)) {
514 		ret = sun6i_csi_set_power(csi_dev, true);
515 		if (ret < 0)
516 			goto error_v4l2_fh;
517 	}
518 
519 	mutex_unlock(&video->lock);
520 
521 	return 0;
522 
523 error_v4l2_fh:
524 	v4l2_fh_release(file);
525 
526 error_lock:
527 	mutex_unlock(&video->lock);
528 
529 	return ret;
530 }
531 
sun6i_video_close(struct file * file)532 static int sun6i_video_close(struct file *file)
533 {
534 	struct sun6i_csi_device *csi_dev = video_drvdata(file);
535 	struct sun6i_video *video = &csi_dev->video;
536 	bool last_close;
537 
538 	mutex_lock(&video->lock);
539 
540 	last_close = v4l2_fh_is_singular_file(file);
541 
542 	_vb2_fop_release(file, NULL);
543 	v4l2_pipeline_pm_put(&video->video_dev.entity);
544 
545 	/* Power off at last close. */
546 	if (last_close)
547 		sun6i_csi_set_power(csi_dev, false);
548 
549 	mutex_unlock(&video->lock);
550 
551 	return 0;
552 }
553 
554 static const struct v4l2_file_operations sun6i_video_fops = {
555 	.owner		= THIS_MODULE,
556 	.open		= sun6i_video_open,
557 	.release	= sun6i_video_close,
558 	.unlocked_ioctl	= video_ioctl2,
559 	.mmap		= vb2_fop_mmap,
560 	.poll		= vb2_fop_poll
561 };
562 
563 /* Media Entity */
564 
sun6i_video_link_validate_get_format(struct media_pad * pad,struct v4l2_subdev_format * fmt)565 static int sun6i_video_link_validate_get_format(struct media_pad *pad,
566 						struct v4l2_subdev_format *fmt)
567 {
568 	if (is_media_entity_v4l2_subdev(pad->entity)) {
569 		struct v4l2_subdev *sd =
570 				media_entity_to_v4l2_subdev(pad->entity);
571 
572 		fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
573 		fmt->pad = pad->index;
574 		return v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
575 	}
576 
577 	return -EINVAL;
578 }
579 
sun6i_video_link_validate(struct media_link * link)580 static int sun6i_video_link_validate(struct media_link *link)
581 {
582 	struct video_device *vdev = container_of(link->sink->entity,
583 						 struct video_device, entity);
584 	struct sun6i_csi_device *csi_dev = video_get_drvdata(vdev);
585 	struct sun6i_video *video = &csi_dev->video;
586 	struct v4l2_subdev_format source_fmt;
587 	int ret;
588 
589 	video->mbus_code = 0;
590 
591 	if (!media_pad_remote_pad_first(link->sink->entity->pads)) {
592 		dev_info(csi_dev->dev, "video node %s pad not connected\n",
593 			 vdev->name);
594 		return -ENOLINK;
595 	}
596 
597 	ret = sun6i_video_link_validate_get_format(link->source, &source_fmt);
598 	if (ret < 0)
599 		return ret;
600 
601 	if (!sun6i_csi_is_format_supported(csi_dev,
602 					   video->format.fmt.pix.pixelformat,
603 					   source_fmt.format.code)) {
604 		dev_err(csi_dev->dev,
605 			"Unsupported pixformat: 0x%x with mbus code: 0x%x!\n",
606 			video->format.fmt.pix.pixelformat,
607 			source_fmt.format.code);
608 		return -EPIPE;
609 	}
610 
611 	if (source_fmt.format.width != video->format.fmt.pix.width ||
612 	    source_fmt.format.height != video->format.fmt.pix.height) {
613 		dev_err(csi_dev->dev,
614 			"Wrong width or height %ux%u (%ux%u expected)\n",
615 			video->format.fmt.pix.width, video->format.fmt.pix.height,
616 			source_fmt.format.width, source_fmt.format.height);
617 		return -EPIPE;
618 	}
619 
620 	video->mbus_code = source_fmt.format.code;
621 
622 	return 0;
623 }
624 
625 static const struct media_entity_operations sun6i_video_media_ops = {
626 	.link_validate = sun6i_video_link_validate
627 };
628 
629 /* Video */
630 
sun6i_video_setup(struct sun6i_csi_device * csi_dev)631 int sun6i_video_setup(struct sun6i_csi_device *csi_dev)
632 {
633 	struct sun6i_video *video = &csi_dev->video;
634 	struct v4l2_device *v4l2_dev = &csi_dev->v4l2.v4l2_dev;
635 	struct video_device *video_dev = &video->video_dev;
636 	struct vb2_queue *queue = &video->queue;
637 	struct media_pad *pad = &video->pad;
638 	struct v4l2_format format = { 0 };
639 	struct v4l2_pix_format *pix_format = &format.fmt.pix;
640 	int ret;
641 
642 	/* Media Entity */
643 
644 	video_dev->entity.ops = &sun6i_video_media_ops;
645 
646 	/* Media Pad */
647 
648 	pad->flags = MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
649 
650 	ret = media_entity_pads_init(&video_dev->entity, 1, pad);
651 	if (ret < 0)
652 		return ret;
653 
654 	/* DMA queue */
655 
656 	INIT_LIST_HEAD(&video->dma_queue);
657 	spin_lock_init(&video->dma_queue_lock);
658 
659 	video->sequence = 0;
660 
661 	/* Queue */
662 
663 	mutex_init(&video->lock);
664 
665 	queue->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
666 	queue->io_modes = VB2_MMAP | VB2_DMABUF;
667 	queue->buf_struct_size = sizeof(struct sun6i_csi_buffer);
668 	queue->ops = &sun6i_video_queue_ops;
669 	queue->mem_ops = &vb2_dma_contig_memops;
670 	queue->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
671 	queue->lock = &video->lock;
672 	queue->dev = csi_dev->dev;
673 	queue->drv_priv = csi_dev;
674 
675 	/* Make sure non-dropped frame. */
676 	queue->min_buffers_needed = 3;
677 
678 	ret = vb2_queue_init(queue);
679 	if (ret) {
680 		v4l2_err(v4l2_dev, "failed to initialize vb2 queue: %d\n", ret);
681 		goto error_media_entity;
682 	}
683 
684 	/* V4L2 Format */
685 
686 	format.type = queue->type;
687 	pix_format->pixelformat = sun6i_video_formats[0];
688 	pix_format->width = 1280;
689 	pix_format->height = 720;
690 	pix_format->field = V4L2_FIELD_NONE;
691 
692 	sun6i_video_format_set(video, &format);
693 
694 	/* Video Device */
695 
696 	strscpy(video_dev->name, SUN6I_CSI_NAME, sizeof(video_dev->name));
697 	video_dev->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
698 	video_dev->vfl_dir = VFL_DIR_RX;
699 	video_dev->release = video_device_release_empty;
700 	video_dev->fops = &sun6i_video_fops;
701 	video_dev->ioctl_ops = &sun6i_video_ioctl_ops;
702 	video_dev->v4l2_dev = v4l2_dev;
703 	video_dev->queue = queue;
704 	video_dev->lock = &video->lock;
705 
706 	video_set_drvdata(video_dev, csi_dev);
707 
708 	ret = video_register_device(video_dev, VFL_TYPE_VIDEO, -1);
709 	if (ret < 0) {
710 		v4l2_err(v4l2_dev, "failed to register video device: %d\n",
711 			 ret);
712 		goto error_media_entity;
713 	}
714 
715 	return 0;
716 
717 error_media_entity:
718 	media_entity_cleanup(&video_dev->entity);
719 
720 	mutex_destroy(&video->lock);
721 
722 	return ret;
723 }
724 
sun6i_video_cleanup(struct sun6i_csi_device * csi_dev)725 void sun6i_video_cleanup(struct sun6i_csi_device *csi_dev)
726 {
727 	struct sun6i_video *video = &csi_dev->video;
728 	struct video_device *video_dev = &video->video_dev;
729 
730 	vb2_video_unregister_device(video_dev);
731 	media_entity_cleanup(&video_dev->entity);
732 	mutex_destroy(&video->lock);
733 }
734