blob: e0440807b4ed2cb3740c1a50ea8678a981e716b0 [file] [log] [blame]
Manjunath Hadli622897d2012-11-28 02:03:38 -03001/*
2 * Copyright (C) 2012 Texas Instruments Inc
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation version 2.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16 *
17 * Contributors:
18 * Manjunath Hadli <manjunath.hadli@ti.com>
19 * Prabhakar Lad <prabhakar.lad@ti.com>
20 */
21
22#include <linux/module.h>
23#include <linux/slab.h>
24
25#include <media/v4l2-ioctl.h>
26
27#include "vpfe.h"
28#include "vpfe_mc_capture.h"
29
Manjunath Hadli622897d2012-11-28 02:03:38 -030030static int debug;
31
32/* get v4l2 subdev pointer to external subdev which is active */
33static struct media_entity *vpfe_get_input_entity
34 (struct vpfe_video_device *video)
35{
36 struct vpfe_device *vpfe_dev = video->vpfe_dev;
37 struct media_pad *remote;
38
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -030039 remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]);
sayli karnika0db9c02016-09-16 23:29:30 +053040 if (!remote) {
Manjunath Hadli622897d2012-11-28 02:03:38 -030041 pr_err("Invalid media connection to isif/ccdc\n");
42 return NULL;
43 }
44 return remote->entity;
45}
46
47/* updates external subdev(sensor/decoder) which is active */
48static int vpfe_update_current_ext_subdev(struct vpfe_video_device *video)
49{
50 struct vpfe_device *vpfe_dev = video->vpfe_dev;
51 struct vpfe_config *vpfe_cfg;
52 struct v4l2_subdev *subdev;
53 struct media_pad *remote;
54 int i;
55
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -030056 remote = media_entity_remote_pad(&vpfe_dev->vpfe_isif.pads[0]);
sayli karnika0db9c02016-09-16 23:29:30 +053057 if (!remote) {
Manjunath Hadli622897d2012-11-28 02:03:38 -030058 pr_err("Invalid media connection to isif/ccdc\n");
59 return -EINVAL;
60 }
61
62 subdev = media_entity_to_v4l2_subdev(remote->entity);
63 vpfe_cfg = vpfe_dev->pdev->platform_data;
64 for (i = 0; i < vpfe_cfg->num_subdevs; i++) {
65 if (!strcmp(vpfe_cfg->sub_devs[i].module_name, subdev->name)) {
66 video->current_ext_subdev = &vpfe_cfg->sub_devs[i];
67 break;
68 }
69 }
70
71 /* if user not linked decoder/sensor to isif/ccdc */
72 if (i == vpfe_cfg->num_subdevs) {
73 pr_err("Invalid media chain connection to isif/ccdc\n");
74 return -EINVAL;
75 }
76 /* find the v4l2 subdev pointer */
77 for (i = 0; i < vpfe_dev->num_ext_subdevs; i++) {
78 if (!strcmp(video->current_ext_subdev->module_name,
79 vpfe_dev->sd[i]->name))
80 video->current_ext_subdev->subdev = vpfe_dev->sd[i];
81 }
82 return 0;
83}
84
85/* get the subdev which is connected to the output video node */
86static struct v4l2_subdev *
87vpfe_video_remote_subdev(struct vpfe_video_device *video, u32 *pad)
88{
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -030089 struct media_pad *remote = media_entity_remote_pad(&video->pad);
Manjunath Hadli622897d2012-11-28 02:03:38 -030090
Mauro Carvalho Chehab14fae6f2015-05-07 22:12:36 -030091 if (!remote || !is_media_entity_v4l2_subdev(remote->entity))
Manjunath Hadli622897d2012-11-28 02:03:38 -030092 return NULL;
93 if (pad)
94 *pad = remote->index;
95 return media_entity_to_v4l2_subdev(remote->entity);
96}
97
98/* get the format set at output pad of the adjacent subdev */
99static int
100__vpfe_video_get_format(struct vpfe_video_device *video,
101 struct v4l2_format *format)
102{
103 struct v4l2_subdev_format fmt;
104 struct v4l2_subdev *subdev;
105 struct media_pad *remote;
106 u32 pad;
107 int ret;
108
109 subdev = vpfe_video_remote_subdev(video, &pad);
sayli karnika0db9c02016-09-16 23:29:30 +0530110 if (!subdev)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300111 return -EINVAL;
112
113 fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300114 remote = media_entity_remote_pad(&video->pad);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300115 fmt.pad = remote->index;
116
117 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
118 if (ret == -ENOIOCTLCMD)
119 return -EINVAL;
120
121 format->type = video->type;
122 /* convert mbus_format to v4l2_format */
123 v4l2_fill_pix_format(&format->fmt.pix, &fmt.format);
124 mbus_to_pix(&fmt.format, &format->fmt.pix);
125
126 return 0;
127}
128
129/* make a note of pipeline details */
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200130static int vpfe_prepare_pipeline(struct vpfe_video_device *video)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300131{
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200132 struct media_entity_graph graph;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300133 struct media_entity *entity = &video->video_dev.entity;
Javier Martinez Canillasd10c9892015-08-19 12:35:21 -0300134 struct media_device *mdev = entity->graph_obj.mdev;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300135 struct vpfe_pipeline *pipe = &video->pipe;
136 struct vpfe_video_device *far_end = NULL;
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200137 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300138
139 pipe->input_num = 0;
140 pipe->output_num = 0;
141
142 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
143 pipe->inputs[pipe->input_num++] = video;
144 else
145 pipe->outputs[pipe->output_num++] = video;
146
147 mutex_lock(&mdev->graph_mutex);
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200148 ret = media_entity_graph_walk_init(&graph, entity->graph_obj.mdev);
149 if (ret) {
Wei Yongjun4f388a92016-02-05 11:52:00 -0200150 mutex_unlock(&mdev->graph_mutex);
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200151 return -ENOMEM;
152 }
Manjunath Hadli622897d2012-11-28 02:03:38 -0300153 media_entity_graph_walk_start(&graph, entity);
154 while ((entity = media_entity_graph_walk_next(&graph))) {
155 if (entity == &video->video_dev.entity)
156 continue;
Laurent Pinchart45b46872016-02-29 08:45:45 -0300157 if (!is_media_entity_v4l2_video_device(entity))
Manjunath Hadli622897d2012-11-28 02:03:38 -0300158 continue;
159 far_end = to_vpfe_video(media_entity_to_video_device(entity));
160 if (far_end->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
161 pipe->inputs[pipe->input_num++] = far_end;
162 else
163 pipe->outputs[pipe->output_num++] = far_end;
164 }
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200165 media_entity_graph_walk_cleanup(&graph);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300166 mutex_unlock(&mdev->graph_mutex);
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200167
168 return 0;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300169}
170
171/* update pipe state selected by user */
172static int vpfe_update_pipe_state(struct vpfe_video_device *video)
173{
174 struct vpfe_pipeline *pipe = &video->pipe;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300175 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300176
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300177 ret = vpfe_prepare_pipeline(video);
178 if (ret)
179 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300180
Thaissa Falbo9c5d8932016-02-15 02:07:41 -0200181 /*
182 * Find out if there is any input video
183 * if yes, it is single shot.
184 */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300185 if (pipe->input_num == 0) {
186 pipe->state = VPFE_PIPELINE_STREAM_CONTINUOUS;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300187 ret = vpfe_update_current_ext_subdev(video);
188 if (ret) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300189 pr_err("Invalid external subdev\n");
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300190 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300191 }
192 } else {
193 pipe->state = VPFE_PIPELINE_STREAM_SINGLESHOT;
194 }
195 video->initialized = 1;
196 video->skip_frame_count = 1;
197 video->skip_frame_count_init = 1;
198 return 0;
199}
200
201/* checks wether pipeline is ready for enabling */
202int vpfe_video_is_pipe_ready(struct vpfe_pipeline *pipe)
203{
204 int i;
205
206 for (i = 0; i < pipe->input_num; i++)
207 if (!pipe->inputs[i]->started ||
208 pipe->inputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED)
209 return 0;
210 for (i = 0; i < pipe->output_num; i++)
211 if (!pipe->outputs[i]->started ||
212 pipe->outputs[i]->state != VPFE_VIDEO_BUFFER_QUEUED)
213 return 0;
214 return 1;
215}
216
217/**
218 * Validate a pipeline by checking both ends of all links for format
219 * discrepancies.
220 *
221 * Return 0 if all formats match, or -EPIPE if at least one link is found with
222 * different formats on its two ends.
223 */
224static int vpfe_video_validate_pipeline(struct vpfe_pipeline *pipe)
225{
226 struct v4l2_subdev_format fmt_source;
227 struct v4l2_subdev_format fmt_sink;
228 struct v4l2_subdev *subdev;
229 struct media_pad *pad;
230 int ret;
231
232 /*
233 * Should not matter if it is output[0] or 1 as
234 * the general ideas is to traverse backwards and
235 * the fact that the out video node always has the
236 * format of the connected pad.
237 */
238 subdev = vpfe_video_remote_subdev(pipe->outputs[0], NULL);
sayli karnika0db9c02016-09-16 23:29:30 +0530239 if (!subdev)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300240 return -EPIPE;
241
242 while (1) {
243 /* Retrieve the sink format */
244 pad = &subdev->entity.pads[0];
245 if (!(pad->flags & MEDIA_PAD_FL_SINK))
246 break;
247
248 fmt_sink.which = V4L2_SUBDEV_FORMAT_ACTIVE;
249 fmt_sink.pad = pad->index;
250 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL,
251 &fmt_sink);
252
253 if (ret < 0 && ret != -ENOIOCTLCMD)
254 return -EPIPE;
255
256 /* Retrieve the source format */
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300257 pad = media_entity_remote_pad(pad);
Mauro Carvalho Chehab14fae6f2015-05-07 22:12:36 -0300258 if (!pad || !is_media_entity_v4l2_subdev(pad->entity))
Manjunath Hadli622897d2012-11-28 02:03:38 -0300259 break;
260
261 subdev = media_entity_to_v4l2_subdev(pad->entity);
262
263 fmt_source.which = V4L2_SUBDEV_FORMAT_ACTIVE;
264 fmt_source.pad = pad->index;
265 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt_source);
266 if (ret < 0 && ret != -ENOIOCTLCMD)
267 return -EPIPE;
268
269 /* Check if the two ends match */
270 if (fmt_source.format.code != fmt_sink.format.code ||
271 fmt_source.format.width != fmt_sink.format.width ||
272 fmt_source.format.height != fmt_sink.format.height)
273 return -EPIPE;
274 }
275 return 0;
276}
277
278/*
279 * vpfe_pipeline_enable() - Enable streaming on a pipeline
280 * @vpfe_dev: vpfe device
281 * @pipe: vpfe pipeline
282 *
283 * Walk the entities chain starting at the pipeline output video node and start
284 * all modules in the chain in the given mode.
285 *
286 * Return 0 if successful, or the return value of the failed video::s_stream
287 * operation otherwise.
288 */
289static int vpfe_pipeline_enable(struct vpfe_pipeline *pipe)
290{
Manjunath Hadli622897d2012-11-28 02:03:38 -0300291 struct media_entity *entity;
292 struct v4l2_subdev *subdev;
293 struct media_device *mdev;
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200294 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300295
296 if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
297 entity = vpfe_get_input_entity(pipe->outputs[0]);
298 else
299 entity = &pipe->inputs[0]->video_dev.entity;
300
Javier Martinez Canillasd10c9892015-08-19 12:35:21 -0300301 mdev = entity->graph_obj.mdev;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300302 mutex_lock(&mdev->graph_mutex);
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200303 ret = media_entity_graph_walk_init(&pipe->graph,
304 entity->graph_obj.mdev);
305 if (ret)
306 goto out;
307 media_entity_graph_walk_start(&pipe->graph, entity);
308 while ((entity = media_entity_graph_walk_next(&pipe->graph))) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300309
Mauro Carvalho Chehab59ecd592015-05-07 22:12:33 -0300310 if (!is_media_entity_v4l2_subdev(entity))
Manjunath Hadli622897d2012-11-28 02:03:38 -0300311 continue;
312 subdev = media_entity_to_v4l2_subdev(entity);
313 ret = v4l2_subdev_call(subdev, video, s_stream, 1);
314 if (ret < 0 && ret != -ENOIOCTLCMD)
315 break;
316 }
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200317out:
318 if (ret)
319 media_entity_graph_walk_cleanup(&pipe->graph);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300320 mutex_unlock(&mdev->graph_mutex);
321 return ret;
322}
323
324/*
325 * vpfe_pipeline_disable() - Disable streaming on a pipeline
326 * @vpfe_dev: vpfe device
327 * @pipe: VPFE pipeline
328 *
329 * Walk the entities chain starting at the pipeline output video node and stop
330 * all modules in the chain.
331 *
332 * Return 0 if all modules have been properly stopped, or -ETIMEDOUT if a module
333 * can't be stopped.
334 */
335static int vpfe_pipeline_disable(struct vpfe_pipeline *pipe)
336{
Manjunath Hadli622897d2012-11-28 02:03:38 -0300337 struct media_entity *entity;
338 struct v4l2_subdev *subdev;
339 struct media_device *mdev;
340 int ret = 0;
341
342 if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
343 entity = vpfe_get_input_entity(pipe->outputs[0]);
344 else
345 entity = &pipe->inputs[0]->video_dev.entity;
346
Javier Martinez Canillasd10c9892015-08-19 12:35:21 -0300347 mdev = entity->graph_obj.mdev;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300348 mutex_lock(&mdev->graph_mutex);
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200349 media_entity_graph_walk_start(&pipe->graph, entity);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300350
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200351 while ((entity = media_entity_graph_walk_next(&pipe->graph))) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300352
Mauro Carvalho Chehab3efdf622015-05-07 22:12:32 -0300353 if (!is_media_entity_v4l2_subdev(entity))
Manjunath Hadli622897d2012-11-28 02:03:38 -0300354 continue;
355 subdev = media_entity_to_v4l2_subdev(entity);
356 ret = v4l2_subdev_call(subdev, video, s_stream, 0);
357 if (ret < 0 && ret != -ENOIOCTLCMD)
358 break;
359 }
360 mutex_unlock(&mdev->graph_mutex);
361
Sakari Ailusbb0faeb2015-12-16 11:32:35 -0200362 media_entity_graph_walk_cleanup(&pipe->graph);
Lisa Nguyen3e6e3b32013-12-11 03:09:22 -0300363 return ret ? -ETIMEDOUT : 0;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300364}
365
366/*
367 * vpfe_pipeline_set_stream() - Enable/disable streaming on a pipeline
368 * @vpfe_dev: VPFE device
369 * @pipe: VPFE pipeline
370 * @state: Stream state (stopped or active)
371 *
372 * Set the pipeline to the given stream state.
373 *
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300374 * Return 0 if successful, or the return value of the failed video::s_stream
Manjunath Hadli622897d2012-11-28 02:03:38 -0300375 * operation otherwise.
376 */
377static int vpfe_pipeline_set_stream(struct vpfe_pipeline *pipe,
378 enum vpfe_pipeline_stream_state state)
379{
380 if (state == VPFE_PIPELINE_STREAM_STOPPED)
381 return vpfe_pipeline_disable(pipe);
382
383 return vpfe_pipeline_enable(pipe);
384}
385
386static int all_videos_stopped(struct vpfe_video_device *video)
387{
388 struct vpfe_pipeline *pipe = &video->pipe;
389 int i;
390
391 for (i = 0; i < pipe->input_num; i++)
392 if (pipe->inputs[i]->started)
393 return 0;
394 for (i = 0; i < pipe->output_num; i++)
395 if (pipe->outputs[i]->started)
396 return 0;
397 return 1;
398}
399
400/*
401 * vpfe_open() - open video device
402 * @file: file pointer
403 *
404 * initialize media pipeline state, allocate memory for file handle
405 *
406 * Return 0 if successful, or the return -ENODEV otherwise.
407 */
408static int vpfe_open(struct file *file)
409{
410 struct vpfe_video_device *video = video_drvdata(file);
411 struct vpfe_fh *handle;
412
413 /* Allocate memory for the file handle object */
414 handle = kzalloc(sizeof(struct vpfe_fh), GFP_KERNEL);
415
sayli karnika0db9c02016-09-16 23:29:30 +0530416 if (!handle)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300417 return -ENOMEM;
418
419 v4l2_fh_init(&handle->vfh, &video->video_dev);
420 v4l2_fh_add(&handle->vfh);
421
422 mutex_lock(&video->lock);
423 /* If decoder is not initialized. initialize it */
424 if (!video->initialized && vpfe_update_pipe_state(video)) {
425 mutex_unlock(&video->lock);
Shailendra Verma209085e2016-11-24 23:57:34 -0500426 v4l2_fh_del(&handle->vfh);
427 v4l2_fh_exit(&handle->vfh);
428 kfree(handle);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300429 return -ENODEV;
430 }
431 /* Increment device users counter */
432 video->usrs++;
433 /* Set io_allowed member to false */
434 handle->io_allowed = 0;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300435 handle->video = video;
436 file->private_data = &handle->vfh;
437 mutex_unlock(&video->lock);
438
439 return 0;
440}
441
442/* get the next buffer available from dma queue */
443static unsigned long
444vpfe_video_get_next_buffer(struct vpfe_video_device *video)
445{
446 video->cur_frm = video->next_frm =
447 list_entry(video->dma_queue.next,
448 struct vpfe_cap_buffer, list);
449
450 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -0300451 video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
452 return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300453}
454
455/* schedule the next buffer which is available on dma queue */
456void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video)
457{
458 struct vpfe_device *vpfe_dev = video->vpfe_dev;
459 unsigned long addr;
460
461 if (list_empty(&video->dma_queue))
462 return;
463
464 video->next_frm = list_entry(video->dma_queue.next,
465 struct vpfe_cap_buffer, list);
466
Thaissa Falbob369a872016-02-15 02:52:49 -0200467 if (video->pipe.state == VPFE_PIPELINE_STREAM_SINGLESHOT)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300468 video->cur_frm = video->next_frm;
469
470 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -0300471 video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
472 addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300473 video->ops->queue(vpfe_dev, addr);
474 video->state = VPFE_VIDEO_BUFFER_QUEUED;
475}
476
477/* schedule the buffer for capturing bottom field */
478void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video)
479{
480 struct vpfe_device *vpfe_dev = video->vpfe_dev;
481 unsigned long addr;
482
Junghak Sung2d700712015-09-22 10:30:30 -0300483 addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300484 addr += video->field_off;
485 video->ops->queue(vpfe_dev, addr);
486}
487
488/* make buffer available for dequeue */
489void vpfe_video_process_buffer_complete(struct vpfe_video_device *video)
490{
491 struct vpfe_pipeline *pipe = &video->pipe;
492
Junghak Sungd6dd6452015-11-03 08:16:37 -0200493 video->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
Junghak Sung2d700712015-09-22 10:30:30 -0300494 vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300495 if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
496 video->cur_frm = video->next_frm;
497}
498
499/* vpfe_stop_capture() - stop streaming */
500static void vpfe_stop_capture(struct vpfe_video_device *video)
501{
502 struct vpfe_pipeline *pipe = &video->pipe;
503
504 video->started = 0;
505
506 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
507 return;
508 if (all_videos_stopped(video))
509 vpfe_pipeline_set_stream(pipe,
510 VPFE_PIPELINE_STREAM_STOPPED);
511}
512
513/*
514 * vpfe_release() - release video device
515 * @file: file pointer
516 *
517 * deletes buffer queue, frees the buffers and the vpfe file handle
518 *
519 * Return 0
520 */
521static int vpfe_release(struct file *file)
522{
523 struct vpfe_video_device *video = video_drvdata(file);
524 struct v4l2_fh *vfh = file->private_data;
525 struct vpfe_device *vpfe_dev = video->vpfe_dev;
526 struct vpfe_fh *fh = container_of(vfh, struct vpfe_fh, vfh);
527
528 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
529
530 /* Get the device lock */
531 mutex_lock(&video->lock);
532 /* if this instance is doing IO */
533 if (fh->io_allowed) {
534 if (video->started) {
535 vpfe_stop_capture(video);
Thaissa Falbo9c5d8932016-02-15 02:07:41 -0200536 /*
537 * mark pipe state as stopped in vpfe_release(),
538 * as app might call streamon() after streamoff()
539 * in which case driver has to start streaming.
540 */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300541 video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED;
542 vb2_streamoff(&video->buffer_queue,
543 video->buffer_queue.type);
544 }
545 video->io_usrs = 0;
546 /* Free buffers allocated */
547 vb2_queue_release(&video->buffer_queue);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300548 }
549 /* Decrement device users counter */
550 video->usrs--;
Lad, Prabhakar933fd6e2014-03-23 03:37:24 -0300551 v4l2_fh_del(&fh->vfh);
552 v4l2_fh_exit(&fh->vfh);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300553 /* If this is the last file handle */
554 if (!video->usrs)
555 video->initialized = 0;
556 mutex_unlock(&video->lock);
557 file->private_data = NULL;
558 /* Free memory allocated to file handle object */
559 v4l2_fh_del(vfh);
560 kzfree(fh);
561 return 0;
562}
563
564/*
565 * vpfe_mmap() - It is used to map kernel space buffers
566 * into user spaces
567 */
568static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
569{
570 struct vpfe_video_device *video = video_drvdata(file);
571 struct vpfe_device *vpfe_dev = video->vpfe_dev;
572
573 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
574 return vb2_mmap(&video->buffer_queue, vma);
575}
576
577/*
578 * vpfe_poll() - It is used for select/poll system call
579 */
580static unsigned int vpfe_poll(struct file *file, poll_table *wait)
581{
582 struct vpfe_video_device *video = video_drvdata(file);
583 struct vpfe_device *vpfe_dev = video->vpfe_dev;
584
585 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
586 if (video->started)
587 return vb2_poll(&video->buffer_queue, file, wait);
588 return 0;
589}
590
591/* vpfe capture driver file operations */
592static const struct v4l2_file_operations vpfe_fops = {
593 .owner = THIS_MODULE,
594 .open = vpfe_open,
595 .release = vpfe_release,
596 .unlocked_ioctl = video_ioctl2,
597 .mmap = vpfe_mmap,
598 .poll = vpfe_poll
599};
600
601/*
602 * vpfe_querycap() - query capabilities of video device
603 * @file: file pointer
604 * @priv: void pointer
605 * @cap: pointer to v4l2_capability structure
606 *
607 * fills v4l2 capabilities structure
608 *
609 * Return 0
610 */
611static int vpfe_querycap(struct file *file, void *priv,
612 struct v4l2_capability *cap)
613{
614 struct vpfe_video_device *video = video_drvdata(file);
615 struct vpfe_device *vpfe_dev = video->vpfe_dev;
616
617 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
618
619 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuil57e774c2014-11-24 06:37:22 -0300620 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300621 else
Hans Verkuil57e774c2014-11-24 06:37:22 -0300622 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
623 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
624 V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300625 strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
626 strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
627 strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
628
629 return 0;
630}
631
632/*
633 * vpfe_g_fmt() - get the format which is active on video device
634 * @file: file pointer
635 * @priv: void pointer
636 * @fmt: pointer to v4l2_format structure
637 *
638 * fills v4l2 format structure with active format
639 *
640 * Return 0
641 */
642static int vpfe_g_fmt(struct file *file, void *priv,
643 struct v4l2_format *fmt)
644{
645 struct vpfe_video_device *video = video_drvdata(file);
646 struct vpfe_device *vpfe_dev = video->vpfe_dev;
647
648 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n");
649 /* Fill in the information about format */
650 *fmt = video->fmt;
651 return 0;
652}
653
654/*
655 * vpfe_enum_fmt() - enum formats supported on media chain
656 * @file: file pointer
657 * @priv: void pointer
658 * @fmt: pointer to v4l2_fmtdesc structure
659 *
660 * fills v4l2_fmtdesc structure with output format set on adjacent subdev,
661 * only one format is enumearted as subdevs are already configured
662 *
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300663 * Return 0 if successful, error code otherwise
Manjunath Hadli622897d2012-11-28 02:03:38 -0300664 */
665static int vpfe_enum_fmt(struct file *file, void *priv,
666 struct v4l2_fmtdesc *fmt)
667{
668 struct vpfe_video_device *video = video_drvdata(file);
669 struct vpfe_device *vpfe_dev = video->vpfe_dev;
670 struct v4l2_subdev_format sd_fmt;
671 struct v4l2_mbus_framefmt mbus;
672 struct v4l2_subdev *subdev;
673 struct v4l2_format format;
674 struct media_pad *remote;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300675 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300676
677 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n");
678
Thaissa Falbo9c5d8932016-02-15 02:07:41 -0200679 /*
680 * since already subdev pad format is set,
681 * only one pixel format is available
682 */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300683 if (fmt->index > 0) {
684 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n");
685 return -EINVAL;
686 }
687 /* get the remote pad */
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300688 remote = media_entity_remote_pad(&video->pad);
sayli karnika0db9c02016-09-16 23:29:30 +0530689 if (!remote) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300690 v4l2_err(&vpfe_dev->v4l2_dev,
691 "invalid remote pad for video node\n");
692 return -EINVAL;
693 }
694 /* get the remote subdev */
695 subdev = vpfe_video_remote_subdev(video, NULL);
sayli karnika0db9c02016-09-16 23:29:30 +0530696 if (!subdev) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300697 v4l2_err(&vpfe_dev->v4l2_dev,
698 "invalid remote subdev for video node\n");
699 return -EINVAL;
700 }
701 sd_fmt.pad = remote->index;
702 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
703 /* get output format of remote subdev */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300704 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt);
705 if (ret) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300706 v4l2_err(&vpfe_dev->v4l2_dev,
707 "invalid remote subdev for video node\n");
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300708 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300709 }
710 /* convert to pix format */
711 mbus.code = sd_fmt.format.code;
712 mbus_to_pix(&mbus, &format.fmt.pix);
713 /* copy the result */
714 fmt->pixelformat = format.fmt.pix.pixelformat;
715
716 return 0;
717}
718
719/*
720 * vpfe_s_fmt() - set the format on video device
721 * @file: file pointer
722 * @priv: void pointer
723 * @fmt: pointer to v4l2_format structure
724 *
725 * validate and set the format on video device
726 *
727 * Return 0 on success, error code otherwise
728 */
729static int vpfe_s_fmt(struct file *file, void *priv,
730 struct v4l2_format *fmt)
731{
732 struct vpfe_video_device *video = video_drvdata(file);
733 struct vpfe_device *vpfe_dev = video->vpfe_dev;
734 struct v4l2_format format;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300735 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300736
737 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n");
738 /* If streaming is started, return error */
739 if (video->started) {
740 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
741 return -EBUSY;
742 }
743 /* get adjacent subdev's output pad format */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300744 ret = __vpfe_video_get_format(video, &format);
745 if (ret)
746 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300747 *fmt = format;
748 video->fmt = *fmt;
749 return 0;
750}
751
752/*
753 * vpfe_try_fmt() - try the format on video device
754 * @file: file pointer
755 * @priv: void pointer
756 * @fmt: pointer to v4l2_format structure
757 *
758 * validate the format, update with correct format
759 * based on output format set on adjacent subdev
760 *
761 * Return 0 on success, error code otherwise
762 */
763static int vpfe_try_fmt(struct file *file, void *priv,
764 struct v4l2_format *fmt)
765{
766 struct vpfe_video_device *video = video_drvdata(file);
767 struct vpfe_device *vpfe_dev = video->vpfe_dev;
768 struct v4l2_format format;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300769 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300770
771 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n");
772 /* get adjacent subdev's output pad format */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300773 ret = __vpfe_video_get_format(video, &format);
774 if (ret)
775 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300776
777 *fmt = format;
778 return 0;
779}
780
781/*
782 * vpfe_enum_input() - enum inputs supported on media chain
783 * @file: file pointer
784 * @priv: void pointer
785 * @fmt: pointer to v4l2_fmtdesc structure
786 *
787 * fills v4l2_input structure with input available on media chain,
788 * only one input is enumearted as media chain is setup by this time
789 *
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300790 * Return 0 if successful, -EINVAL is media chain is invalid
Manjunath Hadli622897d2012-11-28 02:03:38 -0300791 */
792static int vpfe_enum_input(struct file *file, void *priv,
793 struct v4l2_input *inp)
794{
795 struct vpfe_video_device *video = video_drvdata(file);
796 struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev;
797 struct vpfe_device *vpfe_dev = video->vpfe_dev;
798
799 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300800 /* enumerate from the subdev user has chosen through mc */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300801 if (inp->index < sdinfo->num_inputs) {
802 memcpy(inp, &sdinfo->inputs[inp->index],
803 sizeof(struct v4l2_input));
804 return 0;
805 }
806 return -EINVAL;
807}
808
809/*
810 * vpfe_g_input() - get index of the input which is active
811 * @file: file pointer
812 * @priv: void pointer
813 * @index: pointer to unsigned int
814 *
815 * set index with input index which is active
816 */
817static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
818{
819 struct vpfe_video_device *video = video_drvdata(file);
820 struct vpfe_device *vpfe_dev = video->vpfe_dev;
821
822 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
823
824 *index = video->current_input;
825 return 0;
826}
827
828/*
829 * vpfe_s_input() - set input which is pointed by input index
830 * @file: file pointer
831 * @priv: void pointer
832 * @index: pointer to unsigned int
833 *
834 * set input on external subdev
835 *
836 * Return 0 on success, error code otherwise
837 */
838static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
839{
840 struct vpfe_video_device *video = video_drvdata(file);
841 struct vpfe_device *vpfe_dev = video->vpfe_dev;
842 struct vpfe_ext_subdev_info *sdinfo;
843 struct vpfe_route *route;
844 struct v4l2_input *inps;
845 u32 output;
846 u32 input;
847 int ret;
848 int i;
849
850 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
851
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300852 ret = mutex_lock_interruptible(&video->lock);
853 if (ret)
854 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300855 /*
856 * If streaming is started return device busy
857 * error
858 */
859 if (video->started) {
860 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
861 ret = -EBUSY;
862 goto unlock_out;
863 }
864
865 sdinfo = video->current_ext_subdev;
866 if (!sdinfo->registered) {
867 ret = -EINVAL;
868 goto unlock_out;
869 }
870 if (vpfe_dev->cfg->setup_input &&
871 vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) {
872 ret = -EFAULT;
873 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
874 "couldn't setup input for %s\n",
875 sdinfo->module_name);
876 goto unlock_out;
877 }
878 route = &sdinfo->routes[index];
879 if (route && sdinfo->can_route) {
880 input = route->input;
881 output = route->output;
882 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
883 sdinfo->grp_id, video,
884 s_routing, input, output, 0);
885 if (ret) {
886 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
887 "s_input:error in setting input in decoder\n");
888 ret = -EINVAL;
889 goto unlock_out;
890 }
891 }
892 /* set standards set by subdev in video device */
893 for (i = 0; i < sdinfo->num_inputs; i++) {
894 inps = &sdinfo->inputs[i];
895 video->video_dev.tvnorms |= inps->std;
896 }
897 video->current_input = index;
898unlock_out:
899 mutex_unlock(&video->lock);
900 return ret;
901}
902
903/*
904 * vpfe_querystd() - query std which is being input on external subdev
905 * @file: file pointer
906 * @priv: void pointer
907 * @std_id: pointer to v4l2_std_id structure
908 *
909 * call external subdev through v4l2_device_call_until_err to
910 * get the std that is being active.
911 *
912 * Return 0 on success, error code otherwise
913 */
914static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
915{
916 struct vpfe_video_device *video = video_drvdata(file);
917 struct vpfe_device *vpfe_dev = video->vpfe_dev;
918 struct vpfe_ext_subdev_info *sdinfo;
919 int ret;
920
921 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
922
923 ret = mutex_lock_interruptible(&video->lock);
924 sdinfo = video->current_ext_subdev;
925 if (ret)
926 return ret;
927 /* Call querystd function of decoder device */
928 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
929 video, querystd, std_id);
930 mutex_unlock(&video->lock);
931 return ret;
932}
933
934/*
935 * vpfe_s_std() - set std on external subdev
936 * @file: file pointer
937 * @priv: void pointer
938 * @std_id: pointer to v4l2_std_id structure
939 *
940 * set std pointed by std_id on external subdev by calling it using
941 * v4l2_device_call_until_err
942 *
943 * Return 0 on success, error code otherwise
944 */
Hans Verkuil314527a2013-03-15 06:10:40 -0300945static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300946{
947 struct vpfe_video_device *video = video_drvdata(file);
948 struct vpfe_device *vpfe_dev = video->vpfe_dev;
949 struct vpfe_ext_subdev_info *sdinfo;
950 int ret;
951
952 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
953
954 /* Call decoder driver function to set the standard */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300955 ret = mutex_lock_interruptible(&video->lock);
956 if (ret)
957 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300958 sdinfo = video->current_ext_subdev;
959 /* If streaming is started, return device busy error */
960 if (video->started) {
961 v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
962 ret = -EBUSY;
963 goto unlock_out;
964 }
965 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300966 video, s_std, std_id);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300967 if (ret < 0) {
968 v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
969 video->stdid = V4L2_STD_UNKNOWN;
970 goto unlock_out;
971 }
Hans Verkuil314527a2013-03-15 06:10:40 -0300972 video->stdid = std_id;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300973unlock_out:
974 mutex_unlock(&video->lock);
975 return ret;
976}
977
978static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
979{
980 struct vpfe_video_device *video = video_drvdata(file);
981 struct vpfe_device *vpfe_dev = video->vpfe_dev;
982
983 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
984 *tvnorm = video->stdid;
985 return 0;
986}
987
988/*
989 * vpfe_enum_dv_timings() - enumerate dv_timings which are supported by
990 * to external subdev
991 * @file: file pointer
992 * @priv: void pointer
993 * @timings: pointer to v4l2_enum_dv_timings structure
994 *
995 * enum dv_timings's which are supported by external subdev through
996 * v4l2_subdev_call
997 *
998 * Return 0 on success, error code otherwise
999 */
1000static int
1001vpfe_enum_dv_timings(struct file *file, void *fh,
1002 struct v4l2_enum_dv_timings *timings)
1003{
1004 struct vpfe_video_device *video = video_drvdata(file);
1005 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1006 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1007
Laurent Pinchart0eda1852014-01-31 09:04:19 -03001008 timings->pad = 0;
1009
Manjunath Hadli622897d2012-11-28 02:03:38 -03001010 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n");
Laurent Pinchart0eda1852014-01-31 09:04:19 -03001011 return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001012}
1013
1014/*
1015 * vpfe_query_dv_timings() - query the dv_timings which is being input
1016 * to external subdev
1017 * @file: file pointer
1018 * @priv: void pointer
1019 * @timings: pointer to v4l2_dv_timings structure
1020 *
1021 * get dv_timings which is being input on external subdev through
1022 * v4l2_subdev_call
1023 *
1024 * Return 0 on success, error code otherwise
1025 */
1026static int
1027vpfe_query_dv_timings(struct file *file, void *fh,
1028 struct v4l2_dv_timings *timings)
1029{
1030 struct vpfe_video_device *video = video_drvdata(file);
1031 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1032 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1033
1034 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_dv_timings\n");
1035 return v4l2_subdev_call(subdev, video, query_dv_timings, timings);
1036}
1037
1038/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001039 * vpfe_s_dv_timings() - set dv_timings on external subdev
Manjunath Hadli622897d2012-11-28 02:03:38 -03001040 * @file: file pointer
1041 * @priv: void pointer
1042 * @timings: pointer to v4l2_dv_timings structure
1043 *
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001044 * set dv_timings pointed by timings on external subdev through
Manjunath Hadli622897d2012-11-28 02:03:38 -03001045 * v4l2_device_call_until_err, this configures amplifier also
1046 *
1047 * Return 0 on success, error code otherwise
1048 */
1049static int
1050vpfe_s_dv_timings(struct file *file, void *fh,
1051 struct v4l2_dv_timings *timings)
1052{
1053 struct vpfe_video_device *video = video_drvdata(file);
1054 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1055
1056 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_dv_timings\n");
1057
1058 video->stdid = V4L2_STD_UNKNOWN;
1059 return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
1060 video->current_ext_subdev->grp_id,
1061 video, s_dv_timings, timings);
1062}
1063
1064/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001065 * vpfe_g_dv_timings() - get dv_timings which is set on external subdev
Manjunath Hadli622897d2012-11-28 02:03:38 -03001066 * @file: file pointer
1067 * @priv: void pointer
1068 * @timings: pointer to v4l2_dv_timings structure
1069 *
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001070 * get dv_timings which is set on external subdev through
Manjunath Hadli622897d2012-11-28 02:03:38 -03001071 * v4l2_subdev_call
1072 *
1073 * Return 0 on success, error code otherwise
1074 */
1075static int
1076vpfe_g_dv_timings(struct file *file, void *fh,
1077 struct v4l2_dv_timings *timings)
1078{
1079 struct vpfe_video_device *video = video_drvdata(file);
1080 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1081 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1082
1083 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_dv_timings\n");
1084 return v4l2_subdev_call(subdev, video, g_dv_timings, timings);
1085}
1086
1087/*
1088 * Videobuf operations
1089 */
1090/*
1091 * vpfe_buffer_queue_setup : Callback function for buffer setup.
1092 * @vq: vb2_queue ptr
1093 * @fmt: v4l2 format
1094 * @nbuffers: ptr to number of buffers requested by application
1095 * @nplanes:: contains number of distinct video planes needed to hold a frame
1096 * @sizes[]: contains the size (in bytes) of each plane.
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03001097 * @alloc_devs: ptr to allocation context
Manjunath Hadli622897d2012-11-28 02:03:38 -03001098 *
1099 * This callback function is called when reqbuf() is called to adjust
1100 * the buffer nbuffers and buffer size
1101 */
1102static int
Hans Verkuildf9ecb02015-10-28 00:50:37 -02001103vpfe_buffer_queue_setup(struct vb2_queue *vq,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001104 unsigned int *nbuffers, unsigned int *nplanes,
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03001105 unsigned int sizes[], struct device *alloc_devs[])
Manjunath Hadli622897d2012-11-28 02:03:38 -03001106{
1107 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1108 struct vpfe_video_device *video = fh->video;
1109 struct vpfe_device *vpfe_dev = video->vpfe_dev;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001110 unsigned long size;
1111
1112 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue_setup\n");
1113 size = video->fmt.fmt.pix.sizeimage;
1114
Lad, Prabhakar171fe6d2015-05-25 12:34:28 -03001115 if (vq->num_buffers + *nbuffers < 3)
1116 *nbuffers = 3 - vq->num_buffers;
1117
Manjunath Hadli622897d2012-11-28 02:03:38 -03001118 *nplanes = 1;
1119 sizes[0] = size;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001120 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1121 "nbuffers=%d, size=%lu\n", *nbuffers, size);
1122 return 0;
1123}
1124
1125/*
1126 * vpfe_buffer_prepare : callback function for buffer prepare
1127 * @vb: ptr to vb2_buffer
1128 *
1129 * This is the callback function for buffer prepare when vb2_qbuf()
1130 * function is called. The buffer is prepared and user space virtual address
1131 * or user address is converted into physical address
1132 */
1133static int vpfe_buffer_prepare(struct vb2_buffer *vb)
1134{
1135 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1136 struct vpfe_video_device *video = fh->video;
1137 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1138 unsigned long addr;
1139
1140 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
1141
1142 if (vb->state != VB2_BUF_STATE_ACTIVE &&
1143 vb->state != VB2_BUF_STATE_PREPARED)
1144 return 0;
1145
1146 /* Initialize buffer */
1147 vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
1148 if (vb2_plane_vaddr(vb, 0) &&
1149 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
1150 return -EINVAL;
1151
1152 addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1153 /* Make sure user addresses are aligned to 32 bytes */
1154 if (!ALIGN(addr, 32))
1155 return -EINVAL;
1156
1157 return 0;
1158}
1159
1160static void vpfe_buffer_queue(struct vb2_buffer *vb)
1161{
Junghak Sung2d700712015-09-22 10:30:30 -03001162 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001163 /* Get the file handle object and device object */
1164 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1165 struct vpfe_video_device *video = fh->video;
1166 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1167 struct vpfe_pipeline *pipe = &video->pipe;
Junghak Sung2d700712015-09-22 10:30:30 -03001168 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001169 struct vpfe_cap_buffer, vb);
1170 unsigned long flags;
1171 unsigned long empty;
1172 unsigned long addr;
1173
1174 spin_lock_irqsave(&video->dma_queue_lock, flags);
1175 empty = list_empty(&video->dma_queue);
1176 /* add the buffer to the DMA queue */
1177 list_add_tail(&buf->list, &video->dma_queue);
1178 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
1179 /* this case happens in case of single shot */
1180 if (empty && video->started && pipe->state ==
1181 VPFE_PIPELINE_STREAM_SINGLESHOT &&
1182 video->state == VPFE_VIDEO_BUFFER_NOT_QUEUED) {
1183 spin_lock(&video->dma_queue_lock);
1184 addr = vpfe_video_get_next_buffer(video);
1185 video->ops->queue(vpfe_dev, addr);
1186
1187 video->state = VPFE_VIDEO_BUFFER_QUEUED;
1188 spin_unlock(&video->dma_queue_lock);
1189
1190 /* enable h/w each time in single shot */
1191 if (vpfe_video_is_pipe_ready(pipe))
1192 vpfe_pipeline_set_stream(pipe,
1193 VPFE_PIPELINE_STREAM_SINGLESHOT);
1194 }
1195}
1196
1197/* vpfe_start_capture() - start streaming on all the subdevs */
1198static int vpfe_start_capture(struct vpfe_video_device *video)
1199{
1200 struct vpfe_pipeline *pipe = &video->pipe;
1201 int ret = 0;
1202
1203 video->started = 1;
1204 if (vpfe_video_is_pipe_ready(pipe))
1205 ret = vpfe_pipeline_set_stream(pipe, pipe->state);
1206
1207 return ret;
1208}
1209
1210static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
1211{
1212 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1213 struct vpfe_video_device *video = fh->video;
1214 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1215 unsigned long addr;
1216 int ret;
1217
1218 ret = mutex_lock_interruptible(&video->lock);
1219 if (ret)
1220 goto streamoff;
1221
1222 /* Get the next frame from the buffer queue */
1223 video->cur_frm = video->next_frm =
1224 list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list);
1225 /* Remove buffer from the buffer queue */
1226 list_del(&video->cur_frm->list);
1227 /* Mark state of the current frame to active */
Junghak Sung2d700712015-09-22 10:30:30 -03001228 video->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001229 /* Initialize field_id and started member */
1230 video->field_id = 0;
Junghak Sung2d700712015-09-22 10:30:30 -03001231 addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001232 video->ops->queue(vpfe_dev, addr);
1233 video->state = VPFE_VIDEO_BUFFER_QUEUED;
1234
1235 ret = vpfe_start_capture(video);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001236 if (ret) {
1237 struct vpfe_cap_buffer *buf, *tmp;
1238
Junghak Sung2d700712015-09-22 10:30:30 -03001239 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
1240 VB2_BUF_STATE_QUEUED);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001241 list_for_each_entry_safe(buf, tmp, &video->dma_queue, list) {
1242 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001243 vb2_buffer_done(&buf->vb.vb2_buf,
1244 VB2_BUF_STATE_QUEUED);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001245 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001246 goto unlock_out;
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001247 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001248
1249 mutex_unlock(&video->lock);
1250
1251 return ret;
1252unlock_out:
1253 mutex_unlock(&video->lock);
1254streamoff:
1255 ret = vb2_streamoff(&video->buffer_queue, video->buffer_queue.type);
1256 return 0;
1257}
1258
1259static int vpfe_buffer_init(struct vb2_buffer *vb)
1260{
Junghak Sung2d700712015-09-22 10:30:30 -03001261 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1262 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001263 struct vpfe_cap_buffer, vb);
1264
1265 INIT_LIST_HEAD(&buf->list);
1266 return 0;
1267}
1268
1269/* abort streaming and wait for last buffer */
Hans Verkuile37559b2014-04-17 02:47:21 -03001270static void vpfe_stop_streaming(struct vb2_queue *vq)
Manjunath Hadli622897d2012-11-28 02:03:38 -03001271{
1272 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1273 struct vpfe_video_device *video = fh->video;
1274
Manjunath Hadli622897d2012-11-28 02:03:38 -03001275 /* release all active buffers */
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001276 if (video->cur_frm == video->next_frm) {
Junghak Sung2d700712015-09-22 10:30:30 -03001277 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
1278 VB2_BUF_STATE_ERROR);
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001279 } else {
1280 if (video->cur_frm != NULL)
Junghak Sung2d700712015-09-22 10:30:30 -03001281 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001282 VB2_BUF_STATE_ERROR);
1283 if (video->next_frm != NULL)
Junghak Sung2d700712015-09-22 10:30:30 -03001284 vb2_buffer_done(&video->next_frm->vb.vb2_buf,
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001285 VB2_BUF_STATE_ERROR);
1286 }
1287
Manjunath Hadli622897d2012-11-28 02:03:38 -03001288 while (!list_empty(&video->dma_queue)) {
1289 video->next_frm = list_entry(video->dma_queue.next,
1290 struct vpfe_cap_buffer, list);
1291 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001292 vb2_buffer_done(&video->next_frm->vb.vb2_buf,
1293 VB2_BUF_STATE_ERROR);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001294 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001295}
1296
1297static void vpfe_buf_cleanup(struct vb2_buffer *vb)
1298{
Junghak Sung2d700712015-09-22 10:30:30 -03001299 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001300 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1301 struct vpfe_video_device *video = fh->video;
1302 struct vpfe_device *vpfe_dev = video->vpfe_dev;
Junghak Sung2d700712015-09-22 10:30:30 -03001303 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001304 struct vpfe_cap_buffer, vb);
1305
1306 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n");
1307 if (vb->state == VB2_BUF_STATE_ACTIVE)
1308 list_del_init(&buf->list);
1309}
1310
1311static struct vb2_ops video_qops = {
1312 .queue_setup = vpfe_buffer_queue_setup,
1313 .buf_init = vpfe_buffer_init,
1314 .buf_prepare = vpfe_buffer_prepare,
1315 .start_streaming = vpfe_start_streaming,
1316 .stop_streaming = vpfe_stop_streaming,
1317 .buf_cleanup = vpfe_buf_cleanup,
1318 .buf_queue = vpfe_buffer_queue,
1319};
1320
1321/*
1322 * vpfe_reqbufs() - supported REQBUF only once opening
1323 * the device.
1324 */
1325static int vpfe_reqbufs(struct file *file, void *priv,
1326 struct v4l2_requestbuffers *req_buf)
1327{
1328 struct vpfe_video_device *video = video_drvdata(file);
1329 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1330 struct vpfe_fh *fh = file->private_data;
1331 struct vb2_queue *q;
1332 int ret;
1333
1334 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
1335
Thaissa Falbob369a872016-02-15 02:52:49 -02001336 if (req_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1337 req_buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT){
Manjunath Hadli622897d2012-11-28 02:03:38 -03001338 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
1339 return -EINVAL;
1340 }
1341
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001342 ret = mutex_lock_interruptible(&video->lock);
1343 if (ret)
1344 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001345
1346 if (video->io_usrs != 0) {
1347 v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
1348 ret = -EBUSY;
1349 goto unlock_out;
1350 }
1351 video->memory = req_buf->memory;
1352
1353 /* Initialize videobuf2 queue as per the buffer type */
Manjunath Hadli622897d2012-11-28 02:03:38 -03001354 q = &video->buffer_queue;
1355 q->type = req_buf->type;
1356 q->io_modes = VB2_MMAP | VB2_USERPTR;
1357 q->drv_priv = fh;
Hans Verkuilb3379c62014-02-24 13:51:03 -03001358 q->min_buffers_needed = 1;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001359 q->ops = &video_qops;
1360 q->mem_ops = &vb2_dma_contig_memops;
1361 q->buf_struct_size = sizeof(struct vpfe_cap_buffer);
Lad, Prabhakar4f26aa12015-05-25 12:34:29 -03001362 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Hans Verkuil57813da2016-02-15 12:58:44 -02001363 q->dev = vpfe_dev->pdev;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001364
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001365 ret = vb2_queue_init(q);
1366 if (ret) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001367 v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n");
Dan Carpenter257349b2016-11-18 09:30:24 -02001368 goto unlock_out;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001369 }
1370
1371 fh->io_allowed = 1;
1372 video->io_usrs = 1;
1373 INIT_LIST_HEAD(&video->dma_queue);
1374 ret = vb2_reqbufs(&video->buffer_queue, req_buf);
1375
1376unlock_out:
1377 mutex_unlock(&video->lock);
1378 return ret;
1379}
1380
1381/*
1382 * vpfe_querybuf() - query buffers for exchange
1383 */
1384static int vpfe_querybuf(struct file *file, void *priv,
1385 struct v4l2_buffer *buf)
1386{
1387 struct vpfe_video_device *video = video_drvdata(file);
1388 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1389
1390 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
1391
Thaissa Falbob369a872016-02-15 02:52:49 -02001392 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1393 buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001394 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1395 return -EINVAL;
1396 }
1397
1398 if (video->memory != V4L2_MEMORY_MMAP) {
1399 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
1400 return -EINVAL;
1401 }
1402
1403 /* Call vb2_querybuf to get information */
1404 return vb2_querybuf(&video->buffer_queue, buf);
1405}
1406
1407/*
1408 * vpfe_qbuf() - queue buffers for capture or processing
1409 */
1410static int vpfe_qbuf(struct file *file, void *priv,
1411 struct v4l2_buffer *p)
1412{
1413 struct vpfe_video_device *video = video_drvdata(file);
1414 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1415 struct vpfe_fh *fh = file->private_data;
1416
1417 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
1418
Thaissa Falbob369a872016-02-15 02:52:49 -02001419 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1420 p->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001421 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1422 return -EINVAL;
1423 }
1424 /*
1425 * If this file handle is not allowed to do IO,
1426 * return error
1427 */
1428 if (!fh->io_allowed) {
1429 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1430 return -EACCES;
1431 }
1432
1433 return vb2_qbuf(&video->buffer_queue, p);
1434}
1435
1436/*
1437 * vpfe_dqbuf() - deque buffer which is done with processing
1438 */
1439static int vpfe_dqbuf(struct file *file, void *priv,
1440 struct v4l2_buffer *buf)
1441{
1442 struct vpfe_video_device *video = video_drvdata(file);
1443 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1444
1445 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
1446
Thaissa Falbob369a872016-02-15 02:52:49 -02001447 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1448 buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001449 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1450 return -EINVAL;
1451 }
1452
1453 return vb2_dqbuf(&video->buffer_queue,
1454 buf, (file->f_flags & O_NONBLOCK));
1455}
1456
1457/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001458 * vpfe_streamon() - start streaming
Manjunath Hadli622897d2012-11-28 02:03:38 -03001459 * @file: file pointer
1460 * @priv: void pointer
1461 * @buf_type: enum v4l2_buf_type
1462 *
1463 * queue buffer onto hardware for capture/processing and
1464 * start all the subdevs which are in media chain
1465 *
1466 * Return 0 on success, error code otherwise
1467 */
1468static int vpfe_streamon(struct file *file, void *priv,
1469 enum v4l2_buf_type buf_type)
1470{
1471 struct vpfe_video_device *video = video_drvdata(file);
1472 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1473 struct vpfe_pipeline *pipe = &video->pipe;
1474 struct vpfe_fh *fh = file->private_data;
1475 struct vpfe_ext_subdev_info *sdinfo;
1476 int ret = -EINVAL;
1477
1478 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
1479
Thaissa Falbob369a872016-02-15 02:52:49 -02001480 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1481 buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001482 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1483 return ret;
1484 }
1485 /* If file handle is not allowed IO, return error */
1486 if (!fh->io_allowed) {
1487 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1488 return -EACCES;
1489 }
1490 sdinfo = video->current_ext_subdev;
1491 /* If buffer queue is empty, return error */
1492 if (list_empty(&video->buffer_queue.queued_list)) {
1493 v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
1494 return -EIO;
1495 }
1496 /* Validate the pipeline */
Thaissa Falbob369a872016-02-15 02:52:49 -02001497 if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001498 ret = vpfe_video_validate_pipeline(pipe);
1499 if (ret < 0)
1500 return ret;
1501 }
1502 /* Call vb2_streamon to start streaming */
1503 return vb2_streamon(&video->buffer_queue, buf_type);
1504}
1505
1506/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001507 * vpfe_streamoff() - stop streaming
Manjunath Hadli622897d2012-11-28 02:03:38 -03001508 * @file: file pointer
1509 * @priv: void pointer
1510 * @buf_type: enum v4l2_buf_type
1511 *
1512 * stop all the subdevs which are in media chain
1513 *
1514 * Return 0 on success, error code otherwise
1515 */
1516static int vpfe_streamoff(struct file *file, void *priv,
1517 enum v4l2_buf_type buf_type)
1518{
1519 struct vpfe_video_device *video = video_drvdata(file);
1520 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1521 struct vpfe_fh *fh = file->private_data;
1522 int ret = 0;
1523
1524 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
1525
1526 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1527 buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1528 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n");
1529 return -EINVAL;
1530 }
1531
1532 /* If io is allowed for this file handle, return error */
1533 if (!fh->io_allowed) {
1534 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1535 return -EACCES;
1536 }
1537
1538 /* If streaming is not started, return error */
1539 if (!video->started) {
1540 v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n");
1541 return -EINVAL;
1542 }
1543
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001544 ret = mutex_lock_interruptible(&video->lock);
1545 if (ret)
1546 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001547
1548 vpfe_stop_capture(video);
1549 ret = vb2_streamoff(&video->buffer_queue, buf_type);
1550 mutex_unlock(&video->lock);
1551
1552 return ret;
1553}
1554
1555/* vpfe capture ioctl operations */
1556static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
1557 .vidioc_querycap = vpfe_querycap,
1558 .vidioc_g_fmt_vid_cap = vpfe_g_fmt,
1559 .vidioc_s_fmt_vid_cap = vpfe_s_fmt,
1560 .vidioc_try_fmt_vid_cap = vpfe_try_fmt,
1561 .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt,
1562 .vidioc_g_fmt_vid_out = vpfe_g_fmt,
1563 .vidioc_s_fmt_vid_out = vpfe_s_fmt,
1564 .vidioc_try_fmt_vid_out = vpfe_try_fmt,
1565 .vidioc_enum_fmt_vid_out = vpfe_enum_fmt,
1566 .vidioc_enum_input = vpfe_enum_input,
1567 .vidioc_g_input = vpfe_g_input,
1568 .vidioc_s_input = vpfe_s_input,
1569 .vidioc_querystd = vpfe_querystd,
1570 .vidioc_s_std = vpfe_s_std,
1571 .vidioc_g_std = vpfe_g_std,
1572 .vidioc_enum_dv_timings = vpfe_enum_dv_timings,
1573 .vidioc_query_dv_timings = vpfe_query_dv_timings,
1574 .vidioc_s_dv_timings = vpfe_s_dv_timings,
1575 .vidioc_g_dv_timings = vpfe_g_dv_timings,
1576 .vidioc_reqbufs = vpfe_reqbufs,
1577 .vidioc_querybuf = vpfe_querybuf,
1578 .vidioc_qbuf = vpfe_qbuf,
1579 .vidioc_dqbuf = vpfe_dqbuf,
1580 .vidioc_streamon = vpfe_streamon,
1581 .vidioc_streamoff = vpfe_streamoff,
1582};
1583
1584/* VPFE video init function */
1585int vpfe_video_init(struct vpfe_video_device *video, const char *name)
1586{
1587 const char *direction;
1588 int ret;
1589
1590 switch (video->type) {
1591 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1592 direction = "output";
1593 video->pad.flags = MEDIA_PAD_FL_SINK;
1594 video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1595 break;
1596
1597 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1598 direction = "input";
1599 video->pad.flags = MEDIA_PAD_FL_SOURCE;
1600 video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1601 break;
1602
1603 default:
1604 return -EINVAL;
1605 }
1606 /* Initialize field of video device */
1607 video->video_dev.release = video_device_release;
1608 video->video_dev.fops = &vpfe_fops;
1609 video->video_dev.ioctl_ops = &vpfe_ioctl_ops;
1610 video->video_dev.minor = -1;
1611 video->video_dev.tvnorms = 0;
1612 snprintf(video->video_dev.name, sizeof(video->video_dev.name),
1613 "DAVINCI VIDEO %s %s", name, direction);
1614
Manjunath Hadli622897d2012-11-28 02:03:38 -03001615 spin_lock_init(&video->irqlock);
1616 spin_lock_init(&video->dma_queue_lock);
1617 mutex_init(&video->lock);
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02001618 ret = media_entity_pads_init(&video->video_dev.entity,
Mauro Carvalho Chehab18095102015-08-06 09:25:57 -03001619 1, &video->pad);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001620 if (ret < 0)
1621 return ret;
1622
1623 video_set_drvdata(&video->video_dev, video);
1624
1625 return 0;
1626}
1627
1628/* vpfe video device register function */
1629int vpfe_video_register(struct vpfe_video_device *video,
1630 struct v4l2_device *vdev)
1631{
1632 int ret;
1633
1634 video->video_dev.v4l2_dev = vdev;
1635
1636 ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1);
1637 if (ret < 0)
1638 pr_err("%s: could not register video device (%d)\n",
1639 __func__, ret);
1640 return ret;
1641}
1642
1643/* vpfe video device unregister function */
1644void vpfe_video_unregister(struct vpfe_video_device *video)
1645{
1646 if (video_is_registered(&video->video_dev)) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001647 video_unregister_device(&video->video_dev);
Sakari Ailus7bb151b2013-06-11 06:50:49 -03001648 media_entity_cleanup(&video->video_dev.entity);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001649 }
1650}