blob: 89dd6b989254fabaa2f9a23df18d20d885b23e40 [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);
426 return -ENODEV;
427 }
428 /* Increment device users counter */
429 video->usrs++;
430 /* Set io_allowed member to false */
431 handle->io_allowed = 0;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300432 handle->video = video;
433 file->private_data = &handle->vfh;
434 mutex_unlock(&video->lock);
435
436 return 0;
437}
438
439/* get the next buffer available from dma queue */
440static unsigned long
441vpfe_video_get_next_buffer(struct vpfe_video_device *video)
442{
443 video->cur_frm = video->next_frm =
444 list_entry(video->dma_queue.next,
445 struct vpfe_cap_buffer, list);
446
447 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -0300448 video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
449 return vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300450}
451
452/* schedule the next buffer which is available on dma queue */
453void vpfe_video_schedule_next_buffer(struct vpfe_video_device *video)
454{
455 struct vpfe_device *vpfe_dev = video->vpfe_dev;
456 unsigned long addr;
457
458 if (list_empty(&video->dma_queue))
459 return;
460
461 video->next_frm = list_entry(video->dma_queue.next,
462 struct vpfe_cap_buffer, list);
463
Thaissa Falbob369a872016-02-15 02:52:49 -0200464 if (video->pipe.state == VPFE_PIPELINE_STREAM_SINGLESHOT)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300465 video->cur_frm = video->next_frm;
466
467 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -0300468 video->next_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
469 addr = vb2_dma_contig_plane_dma_addr(&video->next_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300470 video->ops->queue(vpfe_dev, addr);
471 video->state = VPFE_VIDEO_BUFFER_QUEUED;
472}
473
474/* schedule the buffer for capturing bottom field */
475void vpfe_video_schedule_bottom_field(struct vpfe_video_device *video)
476{
477 struct vpfe_device *vpfe_dev = video->vpfe_dev;
478 unsigned long addr;
479
Junghak Sung2d700712015-09-22 10:30:30 -0300480 addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300481 addr += video->field_off;
482 video->ops->queue(vpfe_dev, addr);
483}
484
485/* make buffer available for dequeue */
486void vpfe_video_process_buffer_complete(struct vpfe_video_device *video)
487{
488 struct vpfe_pipeline *pipe = &video->pipe;
489
Junghak Sungd6dd6452015-11-03 08:16:37 -0200490 video->cur_frm->vb.vb2_buf.timestamp = ktime_get_ns();
Junghak Sung2d700712015-09-22 10:30:30 -0300491 vb2_buffer_done(&video->cur_frm->vb.vb2_buf, VB2_BUF_STATE_DONE);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300492 if (pipe->state == VPFE_PIPELINE_STREAM_CONTINUOUS)
493 video->cur_frm = video->next_frm;
494}
495
496/* vpfe_stop_capture() - stop streaming */
497static void vpfe_stop_capture(struct vpfe_video_device *video)
498{
499 struct vpfe_pipeline *pipe = &video->pipe;
500
501 video->started = 0;
502
503 if (video->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
504 return;
505 if (all_videos_stopped(video))
506 vpfe_pipeline_set_stream(pipe,
507 VPFE_PIPELINE_STREAM_STOPPED);
508}
509
510/*
511 * vpfe_release() - release video device
512 * @file: file pointer
513 *
514 * deletes buffer queue, frees the buffers and the vpfe file handle
515 *
516 * Return 0
517 */
518static int vpfe_release(struct file *file)
519{
520 struct vpfe_video_device *video = video_drvdata(file);
521 struct v4l2_fh *vfh = file->private_data;
522 struct vpfe_device *vpfe_dev = video->vpfe_dev;
523 struct vpfe_fh *fh = container_of(vfh, struct vpfe_fh, vfh);
524
525 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_release\n");
526
527 /* Get the device lock */
528 mutex_lock(&video->lock);
529 /* if this instance is doing IO */
530 if (fh->io_allowed) {
531 if (video->started) {
532 vpfe_stop_capture(video);
Thaissa Falbo9c5d8932016-02-15 02:07:41 -0200533 /*
534 * mark pipe state as stopped in vpfe_release(),
535 * as app might call streamon() after streamoff()
536 * in which case driver has to start streaming.
537 */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300538 video->pipe.state = VPFE_PIPELINE_STREAM_STOPPED;
539 vb2_streamoff(&video->buffer_queue,
540 video->buffer_queue.type);
541 }
542 video->io_usrs = 0;
543 /* Free buffers allocated */
544 vb2_queue_release(&video->buffer_queue);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300545 }
546 /* Decrement device users counter */
547 video->usrs--;
Lad, Prabhakar933fd6e2014-03-23 03:37:24 -0300548 v4l2_fh_del(&fh->vfh);
549 v4l2_fh_exit(&fh->vfh);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300550 /* If this is the last file handle */
551 if (!video->usrs)
552 video->initialized = 0;
553 mutex_unlock(&video->lock);
554 file->private_data = NULL;
555 /* Free memory allocated to file handle object */
556 v4l2_fh_del(vfh);
557 kzfree(fh);
558 return 0;
559}
560
561/*
562 * vpfe_mmap() - It is used to map kernel space buffers
563 * into user spaces
564 */
565static int vpfe_mmap(struct file *file, struct vm_area_struct *vma)
566{
567 struct vpfe_video_device *video = video_drvdata(file);
568 struct vpfe_device *vpfe_dev = video->vpfe_dev;
569
570 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_mmap\n");
571 return vb2_mmap(&video->buffer_queue, vma);
572}
573
574/*
575 * vpfe_poll() - It is used for select/poll system call
576 */
577static unsigned int vpfe_poll(struct file *file, poll_table *wait)
578{
579 struct vpfe_video_device *video = video_drvdata(file);
580 struct vpfe_device *vpfe_dev = video->vpfe_dev;
581
582 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_poll\n");
583 if (video->started)
584 return vb2_poll(&video->buffer_queue, file, wait);
585 return 0;
586}
587
588/* vpfe capture driver file operations */
589static const struct v4l2_file_operations vpfe_fops = {
590 .owner = THIS_MODULE,
591 .open = vpfe_open,
592 .release = vpfe_release,
593 .unlocked_ioctl = video_ioctl2,
594 .mmap = vpfe_mmap,
595 .poll = vpfe_poll
596};
597
598/*
599 * vpfe_querycap() - query capabilities of video device
600 * @file: file pointer
601 * @priv: void pointer
602 * @cap: pointer to v4l2_capability structure
603 *
604 * fills v4l2 capabilities structure
605 *
606 * Return 0
607 */
608static int vpfe_querycap(struct file *file, void *priv,
609 struct v4l2_capability *cap)
610{
611 struct vpfe_video_device *video = video_drvdata(file);
612 struct vpfe_device *vpfe_dev = video->vpfe_dev;
613
614 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querycap\n");
615
616 if (video->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
Hans Verkuil57e774c2014-11-24 06:37:22 -0300617 cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300618 else
Hans Verkuil57e774c2014-11-24 06:37:22 -0300619 cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
620 cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
621 V4L2_CAP_STREAMING | V4L2_CAP_DEVICE_CAPS;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300622 strlcpy(cap->driver, CAPTURE_DRV_NAME, sizeof(cap->driver));
623 strlcpy(cap->bus_info, "VPFE", sizeof(cap->bus_info));
624 strlcpy(cap->card, vpfe_dev->cfg->card_name, sizeof(cap->card));
625
626 return 0;
627}
628
629/*
630 * vpfe_g_fmt() - get the format which is active on video device
631 * @file: file pointer
632 * @priv: void pointer
633 * @fmt: pointer to v4l2_format structure
634 *
635 * fills v4l2 format structure with active format
636 *
637 * Return 0
638 */
639static int vpfe_g_fmt(struct file *file, void *priv,
640 struct v4l2_format *fmt)
641{
642 struct vpfe_video_device *video = video_drvdata(file);
643 struct vpfe_device *vpfe_dev = video->vpfe_dev;
644
645 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_fmt\n");
646 /* Fill in the information about format */
647 *fmt = video->fmt;
648 return 0;
649}
650
651/*
652 * vpfe_enum_fmt() - enum formats supported on media chain
653 * @file: file pointer
654 * @priv: void pointer
655 * @fmt: pointer to v4l2_fmtdesc structure
656 *
657 * fills v4l2_fmtdesc structure with output format set on adjacent subdev,
658 * only one format is enumearted as subdevs are already configured
659 *
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300660 * Return 0 if successful, error code otherwise
Manjunath Hadli622897d2012-11-28 02:03:38 -0300661 */
662static int vpfe_enum_fmt(struct file *file, void *priv,
663 struct v4l2_fmtdesc *fmt)
664{
665 struct vpfe_video_device *video = video_drvdata(file);
666 struct vpfe_device *vpfe_dev = video->vpfe_dev;
667 struct v4l2_subdev_format sd_fmt;
668 struct v4l2_mbus_framefmt mbus;
669 struct v4l2_subdev *subdev;
670 struct v4l2_format format;
671 struct media_pad *remote;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300672 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300673
674 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_fmt\n");
675
Thaissa Falbo9c5d8932016-02-15 02:07:41 -0200676 /*
677 * since already subdev pad format is set,
678 * only one pixel format is available
679 */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300680 if (fmt->index > 0) {
681 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid index\n");
682 return -EINVAL;
683 }
684 /* get the remote pad */
Andrzej Hajda1bddf1b2013-06-03 05:16:13 -0300685 remote = media_entity_remote_pad(&video->pad);
sayli karnika0db9c02016-09-16 23:29:30 +0530686 if (!remote) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300687 v4l2_err(&vpfe_dev->v4l2_dev,
688 "invalid remote pad for video node\n");
689 return -EINVAL;
690 }
691 /* get the remote subdev */
692 subdev = vpfe_video_remote_subdev(video, NULL);
sayli karnika0db9c02016-09-16 23:29:30 +0530693 if (!subdev) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300694 v4l2_err(&vpfe_dev->v4l2_dev,
695 "invalid remote subdev for video node\n");
696 return -EINVAL;
697 }
698 sd_fmt.pad = remote->index;
699 sd_fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
700 /* get output format of remote subdev */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300701 ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &sd_fmt);
702 if (ret) {
Manjunath Hadli622897d2012-11-28 02:03:38 -0300703 v4l2_err(&vpfe_dev->v4l2_dev,
704 "invalid remote subdev for video node\n");
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300705 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300706 }
707 /* convert to pix format */
708 mbus.code = sd_fmt.format.code;
709 mbus_to_pix(&mbus, &format.fmt.pix);
710 /* copy the result */
711 fmt->pixelformat = format.fmt.pix.pixelformat;
712
713 return 0;
714}
715
716/*
717 * vpfe_s_fmt() - set the format on video device
718 * @file: file pointer
719 * @priv: void pointer
720 * @fmt: pointer to v4l2_format structure
721 *
722 * validate and set the format on video device
723 *
724 * Return 0 on success, error code otherwise
725 */
726static int vpfe_s_fmt(struct file *file, void *priv,
727 struct v4l2_format *fmt)
728{
729 struct vpfe_video_device *video = video_drvdata(file);
730 struct vpfe_device *vpfe_dev = video->vpfe_dev;
731 struct v4l2_format format;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300732 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300733
734 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_fmt\n");
735 /* If streaming is started, return error */
736 if (video->started) {
737 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is started\n");
738 return -EBUSY;
739 }
740 /* get adjacent subdev's output pad format */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300741 ret = __vpfe_video_get_format(video, &format);
742 if (ret)
743 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300744 *fmt = format;
745 video->fmt = *fmt;
746 return 0;
747}
748
749/*
750 * vpfe_try_fmt() - try the format on video device
751 * @file: file pointer
752 * @priv: void pointer
753 * @fmt: pointer to v4l2_format structure
754 *
755 * validate the format, update with correct format
756 * based on output format set on adjacent subdev
757 *
758 * Return 0 on success, error code otherwise
759 */
760static int vpfe_try_fmt(struct file *file, void *priv,
761 struct v4l2_format *fmt)
762{
763 struct vpfe_video_device *video = video_drvdata(file);
764 struct vpfe_device *vpfe_dev = video->vpfe_dev;
765 struct v4l2_format format;
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300766 int ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300767
768 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_try_fmt\n");
769 /* get adjacent subdev's output pad format */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300770 ret = __vpfe_video_get_format(video, &format);
771 if (ret)
772 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300773
774 *fmt = format;
775 return 0;
776}
777
778/*
779 * vpfe_enum_input() - enum inputs supported on media chain
780 * @file: file pointer
781 * @priv: void pointer
782 * @fmt: pointer to v4l2_fmtdesc structure
783 *
784 * fills v4l2_input structure with input available on media chain,
785 * only one input is enumearted as media chain is setup by this time
786 *
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300787 * Return 0 if successful, -EINVAL is media chain is invalid
Manjunath Hadli622897d2012-11-28 02:03:38 -0300788 */
789static int vpfe_enum_input(struct file *file, void *priv,
790 struct v4l2_input *inp)
791{
792 struct vpfe_video_device *video = video_drvdata(file);
793 struct vpfe_ext_subdev_info *sdinfo = video->current_ext_subdev;
794 struct vpfe_device *vpfe_dev = video->vpfe_dev;
795
796 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_input\n");
Masanari Iida2f9e96c2013-03-26 11:23:28 -0300797 /* enumerate from the subdev user has chosen through mc */
Manjunath Hadli622897d2012-11-28 02:03:38 -0300798 if (inp->index < sdinfo->num_inputs) {
799 memcpy(inp, &sdinfo->inputs[inp->index],
800 sizeof(struct v4l2_input));
801 return 0;
802 }
803 return -EINVAL;
804}
805
806/*
807 * vpfe_g_input() - get index of the input which is active
808 * @file: file pointer
809 * @priv: void pointer
810 * @index: pointer to unsigned int
811 *
812 * set index with input index which is active
813 */
814static int vpfe_g_input(struct file *file, void *priv, unsigned int *index)
815{
816 struct vpfe_video_device *video = video_drvdata(file);
817 struct vpfe_device *vpfe_dev = video->vpfe_dev;
818
819 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_input\n");
820
821 *index = video->current_input;
822 return 0;
823}
824
825/*
826 * vpfe_s_input() - set input which is pointed by input index
827 * @file: file pointer
828 * @priv: void pointer
829 * @index: pointer to unsigned int
830 *
831 * set input on external subdev
832 *
833 * Return 0 on success, error code otherwise
834 */
835static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
836{
837 struct vpfe_video_device *video = video_drvdata(file);
838 struct vpfe_device *vpfe_dev = video->vpfe_dev;
839 struct vpfe_ext_subdev_info *sdinfo;
840 struct vpfe_route *route;
841 struct v4l2_input *inps;
842 u32 output;
843 u32 input;
844 int ret;
845 int i;
846
847 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_input\n");
848
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300849 ret = mutex_lock_interruptible(&video->lock);
850 if (ret)
851 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300852 /*
853 * If streaming is started return device busy
854 * error
855 */
856 if (video->started) {
857 v4l2_err(&vpfe_dev->v4l2_dev, "Streaming is on\n");
858 ret = -EBUSY;
859 goto unlock_out;
860 }
861
862 sdinfo = video->current_ext_subdev;
863 if (!sdinfo->registered) {
864 ret = -EINVAL;
865 goto unlock_out;
866 }
867 if (vpfe_dev->cfg->setup_input &&
868 vpfe_dev->cfg->setup_input(sdinfo->grp_id) < 0) {
869 ret = -EFAULT;
870 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
871 "couldn't setup input for %s\n",
872 sdinfo->module_name);
873 goto unlock_out;
874 }
875 route = &sdinfo->routes[index];
876 if (route && sdinfo->can_route) {
877 input = route->input;
878 output = route->output;
879 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
880 sdinfo->grp_id, video,
881 s_routing, input, output, 0);
882 if (ret) {
883 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
884 "s_input:error in setting input in decoder\n");
885 ret = -EINVAL;
886 goto unlock_out;
887 }
888 }
889 /* set standards set by subdev in video device */
890 for (i = 0; i < sdinfo->num_inputs; i++) {
891 inps = &sdinfo->inputs[i];
892 video->video_dev.tvnorms |= inps->std;
893 }
894 video->current_input = index;
895unlock_out:
896 mutex_unlock(&video->lock);
897 return ret;
898}
899
900/*
901 * vpfe_querystd() - query std which is being input on external subdev
902 * @file: file pointer
903 * @priv: void pointer
904 * @std_id: pointer to v4l2_std_id structure
905 *
906 * call external subdev through v4l2_device_call_until_err to
907 * get the std that is being active.
908 *
909 * Return 0 on success, error code otherwise
910 */
911static int vpfe_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
912{
913 struct vpfe_video_device *video = video_drvdata(file);
914 struct vpfe_device *vpfe_dev = video->vpfe_dev;
915 struct vpfe_ext_subdev_info *sdinfo;
916 int ret;
917
918 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querystd\n");
919
920 ret = mutex_lock_interruptible(&video->lock);
921 sdinfo = video->current_ext_subdev;
922 if (ret)
923 return ret;
924 /* Call querystd function of decoder device */
925 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
926 video, querystd, std_id);
927 mutex_unlock(&video->lock);
928 return ret;
929}
930
931/*
932 * vpfe_s_std() - set std on external subdev
933 * @file: file pointer
934 * @priv: void pointer
935 * @std_id: pointer to v4l2_std_id structure
936 *
937 * set std pointed by std_id on external subdev by calling it using
938 * v4l2_device_call_until_err
939 *
940 * Return 0 on success, error code otherwise
941 */
Hans Verkuil314527a2013-03-15 06:10:40 -0300942static int vpfe_s_std(struct file *file, void *priv, v4l2_std_id std_id)
Manjunath Hadli622897d2012-11-28 02:03:38 -0300943{
944 struct vpfe_video_device *video = video_drvdata(file);
945 struct vpfe_device *vpfe_dev = video->vpfe_dev;
946 struct vpfe_ext_subdev_info *sdinfo;
947 int ret;
948
949 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_std\n");
950
951 /* Call decoder driver function to set the standard */
Hans Verkuil8bbb6562016-04-15 08:58:10 -0300952 ret = mutex_lock_interruptible(&video->lock);
953 if (ret)
954 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300955 sdinfo = video->current_ext_subdev;
956 /* If streaming is started, return device busy error */
957 if (video->started) {
958 v4l2_err(&vpfe_dev->v4l2_dev, "streaming is started\n");
959 ret = -EBUSY;
960 goto unlock_out;
961 }
962 ret = v4l2_device_call_until_err(&vpfe_dev->v4l2_dev, sdinfo->grp_id,
Laurent Pinchart8774bed2014-04-28 16:53:01 -0300963 video, s_std, std_id);
Manjunath Hadli622897d2012-11-28 02:03:38 -0300964 if (ret < 0) {
965 v4l2_err(&vpfe_dev->v4l2_dev, "Failed to set standard\n");
966 video->stdid = V4L2_STD_UNKNOWN;
967 goto unlock_out;
968 }
Hans Verkuil314527a2013-03-15 06:10:40 -0300969 video->stdid = std_id;
Manjunath Hadli622897d2012-11-28 02:03:38 -0300970unlock_out:
971 mutex_unlock(&video->lock);
972 return ret;
973}
974
975static int vpfe_g_std(struct file *file, void *priv, v4l2_std_id *tvnorm)
976{
977 struct vpfe_video_device *video = video_drvdata(file);
978 struct vpfe_device *vpfe_dev = video->vpfe_dev;
979
980 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_std\n");
981 *tvnorm = video->stdid;
982 return 0;
983}
984
985/*
986 * vpfe_enum_dv_timings() - enumerate dv_timings which are supported by
987 * to external subdev
988 * @file: file pointer
989 * @priv: void pointer
990 * @timings: pointer to v4l2_enum_dv_timings structure
991 *
992 * enum dv_timings's which are supported by external subdev through
993 * v4l2_subdev_call
994 *
995 * Return 0 on success, error code otherwise
996 */
997static int
998vpfe_enum_dv_timings(struct file *file, void *fh,
999 struct v4l2_enum_dv_timings *timings)
1000{
1001 struct vpfe_video_device *video = video_drvdata(file);
1002 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1003 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1004
Laurent Pinchart0eda1852014-01-31 09:04:19 -03001005 timings->pad = 0;
1006
Manjunath Hadli622897d2012-11-28 02:03:38 -03001007 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_enum_dv_timings\n");
Laurent Pinchart0eda1852014-01-31 09:04:19 -03001008 return v4l2_subdev_call(subdev, pad, enum_dv_timings, timings);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001009}
1010
1011/*
1012 * vpfe_query_dv_timings() - query the dv_timings which is being input
1013 * to external subdev
1014 * @file: file pointer
1015 * @priv: void pointer
1016 * @timings: pointer to v4l2_dv_timings structure
1017 *
1018 * get dv_timings which is being input on external subdev through
1019 * v4l2_subdev_call
1020 *
1021 * Return 0 on success, error code otherwise
1022 */
1023static int
1024vpfe_query_dv_timings(struct file *file, void *fh,
1025 struct v4l2_dv_timings *timings)
1026{
1027 struct vpfe_video_device *video = video_drvdata(file);
1028 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1029 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1030
1031 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_query_dv_timings\n");
1032 return v4l2_subdev_call(subdev, video, query_dv_timings, timings);
1033}
1034
1035/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001036 * vpfe_s_dv_timings() - set dv_timings on external subdev
Manjunath Hadli622897d2012-11-28 02:03:38 -03001037 * @file: file pointer
1038 * @priv: void pointer
1039 * @timings: pointer to v4l2_dv_timings structure
1040 *
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001041 * set dv_timings pointed by timings on external subdev through
Manjunath Hadli622897d2012-11-28 02:03:38 -03001042 * v4l2_device_call_until_err, this configures amplifier also
1043 *
1044 * Return 0 on success, error code otherwise
1045 */
1046static int
1047vpfe_s_dv_timings(struct file *file, void *fh,
1048 struct v4l2_dv_timings *timings)
1049{
1050 struct vpfe_video_device *video = video_drvdata(file);
1051 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1052
1053 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_dv_timings\n");
1054
1055 video->stdid = V4L2_STD_UNKNOWN;
1056 return v4l2_device_call_until_err(&vpfe_dev->v4l2_dev,
1057 video->current_ext_subdev->grp_id,
1058 video, s_dv_timings, timings);
1059}
1060
1061/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001062 * vpfe_g_dv_timings() - get dv_timings which is set on external subdev
Manjunath Hadli622897d2012-11-28 02:03:38 -03001063 * @file: file pointer
1064 * @priv: void pointer
1065 * @timings: pointer to v4l2_dv_timings structure
1066 *
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001067 * get dv_timings which is set on external subdev through
Manjunath Hadli622897d2012-11-28 02:03:38 -03001068 * v4l2_subdev_call
1069 *
1070 * Return 0 on success, error code otherwise
1071 */
1072static int
1073vpfe_g_dv_timings(struct file *file, void *fh,
1074 struct v4l2_dv_timings *timings)
1075{
1076 struct vpfe_video_device *video = video_drvdata(file);
1077 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1078 struct v4l2_subdev *subdev = video->current_ext_subdev->subdev;
1079
1080 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_g_dv_timings\n");
1081 return v4l2_subdev_call(subdev, video, g_dv_timings, timings);
1082}
1083
1084/*
1085 * Videobuf operations
1086 */
1087/*
1088 * vpfe_buffer_queue_setup : Callback function for buffer setup.
1089 * @vq: vb2_queue ptr
1090 * @fmt: v4l2 format
1091 * @nbuffers: ptr to number of buffers requested by application
1092 * @nplanes:: contains number of distinct video planes needed to hold a frame
1093 * @sizes[]: contains the size (in bytes) of each plane.
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03001094 * @alloc_devs: ptr to allocation context
Manjunath Hadli622897d2012-11-28 02:03:38 -03001095 *
1096 * This callback function is called when reqbuf() is called to adjust
1097 * the buffer nbuffers and buffer size
1098 */
1099static int
Hans Verkuildf9ecb02015-10-28 00:50:37 -02001100vpfe_buffer_queue_setup(struct vb2_queue *vq,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001101 unsigned int *nbuffers, unsigned int *nplanes,
Hans Verkuil36c0f8b2016-04-15 09:15:05 -03001102 unsigned int sizes[], struct device *alloc_devs[])
Manjunath Hadli622897d2012-11-28 02:03:38 -03001103{
1104 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1105 struct vpfe_video_device *video = fh->video;
1106 struct vpfe_device *vpfe_dev = video->vpfe_dev;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001107 unsigned long size;
1108
1109 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_queue_setup\n");
1110 size = video->fmt.fmt.pix.sizeimage;
1111
Lad, Prabhakar171fe6d2015-05-25 12:34:28 -03001112 if (vq->num_buffers + *nbuffers < 3)
1113 *nbuffers = 3 - vq->num_buffers;
1114
Manjunath Hadli622897d2012-11-28 02:03:38 -03001115 *nplanes = 1;
1116 sizes[0] = size;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001117 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
1118 "nbuffers=%d, size=%lu\n", *nbuffers, size);
1119 return 0;
1120}
1121
1122/*
1123 * vpfe_buffer_prepare : callback function for buffer prepare
1124 * @vb: ptr to vb2_buffer
1125 *
1126 * This is the callback function for buffer prepare when vb2_qbuf()
1127 * function is called. The buffer is prepared and user space virtual address
1128 * or user address is converted into physical address
1129 */
1130static int vpfe_buffer_prepare(struct vb2_buffer *vb)
1131{
1132 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1133 struct vpfe_video_device *video = fh->video;
1134 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1135 unsigned long addr;
1136
1137 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buffer_prepare\n");
1138
1139 if (vb->state != VB2_BUF_STATE_ACTIVE &&
1140 vb->state != VB2_BUF_STATE_PREPARED)
1141 return 0;
1142
1143 /* Initialize buffer */
1144 vb2_set_plane_payload(vb, 0, video->fmt.fmt.pix.sizeimage);
1145 if (vb2_plane_vaddr(vb, 0) &&
1146 vb2_get_plane_payload(vb, 0) > vb2_plane_size(vb, 0))
1147 return -EINVAL;
1148
1149 addr = vb2_dma_contig_plane_dma_addr(vb, 0);
1150 /* Make sure user addresses are aligned to 32 bytes */
1151 if (!ALIGN(addr, 32))
1152 return -EINVAL;
1153
1154 return 0;
1155}
1156
1157static void vpfe_buffer_queue(struct vb2_buffer *vb)
1158{
Junghak Sung2d700712015-09-22 10:30:30 -03001159 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001160 /* Get the file handle object and device object */
1161 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1162 struct vpfe_video_device *video = fh->video;
1163 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1164 struct vpfe_pipeline *pipe = &video->pipe;
Junghak Sung2d700712015-09-22 10:30:30 -03001165 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001166 struct vpfe_cap_buffer, vb);
1167 unsigned long flags;
1168 unsigned long empty;
1169 unsigned long addr;
1170
1171 spin_lock_irqsave(&video->dma_queue_lock, flags);
1172 empty = list_empty(&video->dma_queue);
1173 /* add the buffer to the DMA queue */
1174 list_add_tail(&buf->list, &video->dma_queue);
1175 spin_unlock_irqrestore(&video->dma_queue_lock, flags);
1176 /* this case happens in case of single shot */
1177 if (empty && video->started && pipe->state ==
1178 VPFE_PIPELINE_STREAM_SINGLESHOT &&
1179 video->state == VPFE_VIDEO_BUFFER_NOT_QUEUED) {
1180 spin_lock(&video->dma_queue_lock);
1181 addr = vpfe_video_get_next_buffer(video);
1182 video->ops->queue(vpfe_dev, addr);
1183
1184 video->state = VPFE_VIDEO_BUFFER_QUEUED;
1185 spin_unlock(&video->dma_queue_lock);
1186
1187 /* enable h/w each time in single shot */
1188 if (vpfe_video_is_pipe_ready(pipe))
1189 vpfe_pipeline_set_stream(pipe,
1190 VPFE_PIPELINE_STREAM_SINGLESHOT);
1191 }
1192}
1193
1194/* vpfe_start_capture() - start streaming on all the subdevs */
1195static int vpfe_start_capture(struct vpfe_video_device *video)
1196{
1197 struct vpfe_pipeline *pipe = &video->pipe;
1198 int ret = 0;
1199
1200 video->started = 1;
1201 if (vpfe_video_is_pipe_ready(pipe))
1202 ret = vpfe_pipeline_set_stream(pipe, pipe->state);
1203
1204 return ret;
1205}
1206
1207static int vpfe_start_streaming(struct vb2_queue *vq, unsigned int count)
1208{
1209 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1210 struct vpfe_video_device *video = fh->video;
1211 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1212 unsigned long addr;
1213 int ret;
1214
1215 ret = mutex_lock_interruptible(&video->lock);
1216 if (ret)
1217 goto streamoff;
1218
1219 /* Get the next frame from the buffer queue */
1220 video->cur_frm = video->next_frm =
1221 list_entry(video->dma_queue.next, struct vpfe_cap_buffer, list);
1222 /* Remove buffer from the buffer queue */
1223 list_del(&video->cur_frm->list);
1224 /* Mark state of the current frame to active */
Junghak Sung2d700712015-09-22 10:30:30 -03001225 video->cur_frm->vb.vb2_buf.state = VB2_BUF_STATE_ACTIVE;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001226 /* Initialize field_id and started member */
1227 video->field_id = 0;
Junghak Sung2d700712015-09-22 10:30:30 -03001228 addr = vb2_dma_contig_plane_dma_addr(&video->cur_frm->vb.vb2_buf, 0);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001229 video->ops->queue(vpfe_dev, addr);
1230 video->state = VPFE_VIDEO_BUFFER_QUEUED;
1231
1232 ret = vpfe_start_capture(video);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001233 if (ret) {
1234 struct vpfe_cap_buffer *buf, *tmp;
1235
Junghak Sung2d700712015-09-22 10:30:30 -03001236 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
1237 VB2_BUF_STATE_QUEUED);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001238 list_for_each_entry_safe(buf, tmp, &video->dma_queue, list) {
1239 list_del(&buf->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001240 vb2_buffer_done(&buf->vb.vb2_buf,
1241 VB2_BUF_STATE_QUEUED);
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001242 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001243 goto unlock_out;
Lad, Prabhakar8f7402a2014-03-23 03:37:25 -03001244 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001245
1246 mutex_unlock(&video->lock);
1247
1248 return ret;
1249unlock_out:
1250 mutex_unlock(&video->lock);
1251streamoff:
1252 ret = vb2_streamoff(&video->buffer_queue, video->buffer_queue.type);
1253 return 0;
1254}
1255
1256static int vpfe_buffer_init(struct vb2_buffer *vb)
1257{
Junghak Sung2d700712015-09-22 10:30:30 -03001258 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
1259 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001260 struct vpfe_cap_buffer, vb);
1261
1262 INIT_LIST_HEAD(&buf->list);
1263 return 0;
1264}
1265
1266/* abort streaming and wait for last buffer */
Hans Verkuile37559b2014-04-17 02:47:21 -03001267static void vpfe_stop_streaming(struct vb2_queue *vq)
Manjunath Hadli622897d2012-11-28 02:03:38 -03001268{
1269 struct vpfe_fh *fh = vb2_get_drv_priv(vq);
1270 struct vpfe_video_device *video = fh->video;
1271
Manjunath Hadli622897d2012-11-28 02:03:38 -03001272 /* release all active buffers */
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001273 if (video->cur_frm == video->next_frm) {
Junghak Sung2d700712015-09-22 10:30:30 -03001274 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
1275 VB2_BUF_STATE_ERROR);
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001276 } else {
1277 if (video->cur_frm != NULL)
Junghak Sung2d700712015-09-22 10:30:30 -03001278 vb2_buffer_done(&video->cur_frm->vb.vb2_buf,
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001279 VB2_BUF_STATE_ERROR);
1280 if (video->next_frm != NULL)
Junghak Sung2d700712015-09-22 10:30:30 -03001281 vb2_buffer_done(&video->next_frm->vb.vb2_buf,
Lad, Prabhakard891ae52014-03-23 02:16:46 -03001282 VB2_BUF_STATE_ERROR);
1283 }
1284
Manjunath Hadli622897d2012-11-28 02:03:38 -03001285 while (!list_empty(&video->dma_queue)) {
1286 video->next_frm = list_entry(video->dma_queue.next,
1287 struct vpfe_cap_buffer, list);
1288 list_del(&video->next_frm->list);
Junghak Sung2d700712015-09-22 10:30:30 -03001289 vb2_buffer_done(&video->next_frm->vb.vb2_buf,
1290 VB2_BUF_STATE_ERROR);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001291 }
Manjunath Hadli622897d2012-11-28 02:03:38 -03001292}
1293
1294static void vpfe_buf_cleanup(struct vb2_buffer *vb)
1295{
Junghak Sung2d700712015-09-22 10:30:30 -03001296 struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001297 struct vpfe_fh *fh = vb2_get_drv_priv(vb->vb2_queue);
1298 struct vpfe_video_device *video = fh->video;
1299 struct vpfe_device *vpfe_dev = video->vpfe_dev;
Junghak Sung2d700712015-09-22 10:30:30 -03001300 struct vpfe_cap_buffer *buf = container_of(vbuf,
Manjunath Hadli622897d2012-11-28 02:03:38 -03001301 struct vpfe_cap_buffer, vb);
1302
1303 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_buf_cleanup\n");
1304 if (vb->state == VB2_BUF_STATE_ACTIVE)
1305 list_del_init(&buf->list);
1306}
1307
1308static struct vb2_ops video_qops = {
1309 .queue_setup = vpfe_buffer_queue_setup,
1310 .buf_init = vpfe_buffer_init,
1311 .buf_prepare = vpfe_buffer_prepare,
1312 .start_streaming = vpfe_start_streaming,
1313 .stop_streaming = vpfe_stop_streaming,
1314 .buf_cleanup = vpfe_buf_cleanup,
1315 .buf_queue = vpfe_buffer_queue,
1316};
1317
1318/*
1319 * vpfe_reqbufs() - supported REQBUF only once opening
1320 * the device.
1321 */
1322static int vpfe_reqbufs(struct file *file, void *priv,
1323 struct v4l2_requestbuffers *req_buf)
1324{
1325 struct vpfe_video_device *video = video_drvdata(file);
1326 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1327 struct vpfe_fh *fh = file->private_data;
1328 struct vb2_queue *q;
1329 int ret;
1330
1331 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_reqbufs\n");
1332
Thaissa Falbob369a872016-02-15 02:52:49 -02001333 if (req_buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1334 req_buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT){
Manjunath Hadli622897d2012-11-28 02:03:38 -03001335 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buffer type\n");
1336 return -EINVAL;
1337 }
1338
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001339 ret = mutex_lock_interruptible(&video->lock);
1340 if (ret)
1341 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001342
1343 if (video->io_usrs != 0) {
1344 v4l2_err(&vpfe_dev->v4l2_dev, "Only one IO user allowed\n");
1345 ret = -EBUSY;
1346 goto unlock_out;
1347 }
1348 video->memory = req_buf->memory;
1349
1350 /* Initialize videobuf2 queue as per the buffer type */
Manjunath Hadli622897d2012-11-28 02:03:38 -03001351 q = &video->buffer_queue;
1352 q->type = req_buf->type;
1353 q->io_modes = VB2_MMAP | VB2_USERPTR;
1354 q->drv_priv = fh;
Hans Verkuilb3379c62014-02-24 13:51:03 -03001355 q->min_buffers_needed = 1;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001356 q->ops = &video_qops;
1357 q->mem_ops = &vb2_dma_contig_memops;
1358 q->buf_struct_size = sizeof(struct vpfe_cap_buffer);
Lad, Prabhakar4f26aa12015-05-25 12:34:29 -03001359 q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
Hans Verkuil57813da2016-02-15 12:58:44 -02001360 q->dev = vpfe_dev->pdev;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001361
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001362 ret = vb2_queue_init(q);
1363 if (ret) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001364 v4l2_err(&vpfe_dev->v4l2_dev, "vb2_queue_init() failed\n");
Dan Carpenter257349b2016-11-18 09:30:24 -02001365 goto unlock_out;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001366 }
1367
1368 fh->io_allowed = 1;
1369 video->io_usrs = 1;
1370 INIT_LIST_HEAD(&video->dma_queue);
1371 ret = vb2_reqbufs(&video->buffer_queue, req_buf);
1372
1373unlock_out:
1374 mutex_unlock(&video->lock);
1375 return ret;
1376}
1377
1378/*
1379 * vpfe_querybuf() - query buffers for exchange
1380 */
1381static int vpfe_querybuf(struct file *file, void *priv,
1382 struct v4l2_buffer *buf)
1383{
1384 struct vpfe_video_device *video = video_drvdata(file);
1385 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1386
1387 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_querybuf\n");
1388
Thaissa Falbob369a872016-02-15 02:52:49 -02001389 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1390 buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001391 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1392 return -EINVAL;
1393 }
1394
1395 if (video->memory != V4L2_MEMORY_MMAP) {
1396 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid memory\n");
1397 return -EINVAL;
1398 }
1399
1400 /* Call vb2_querybuf to get information */
1401 return vb2_querybuf(&video->buffer_queue, buf);
1402}
1403
1404/*
1405 * vpfe_qbuf() - queue buffers for capture or processing
1406 */
1407static int vpfe_qbuf(struct file *file, void *priv,
1408 struct v4l2_buffer *p)
1409{
1410 struct vpfe_video_device *video = video_drvdata(file);
1411 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1412 struct vpfe_fh *fh = file->private_data;
1413
1414 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_qbuf\n");
1415
Thaissa Falbob369a872016-02-15 02:52:49 -02001416 if (p->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1417 p->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001418 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1419 return -EINVAL;
1420 }
1421 /*
1422 * If this file handle is not allowed to do IO,
1423 * return error
1424 */
1425 if (!fh->io_allowed) {
1426 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1427 return -EACCES;
1428 }
1429
1430 return vb2_qbuf(&video->buffer_queue, p);
1431}
1432
1433/*
1434 * vpfe_dqbuf() - deque buffer which is done with processing
1435 */
1436static int vpfe_dqbuf(struct file *file, void *priv,
1437 struct v4l2_buffer *buf)
1438{
1439 struct vpfe_video_device *video = video_drvdata(file);
1440 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1441
1442 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_dqbuf\n");
1443
Thaissa Falbob369a872016-02-15 02:52:49 -02001444 if (buf->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1445 buf->type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001446 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1447 return -EINVAL;
1448 }
1449
1450 return vb2_dqbuf(&video->buffer_queue,
1451 buf, (file->f_flags & O_NONBLOCK));
1452}
1453
1454/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001455 * vpfe_streamon() - start streaming
Manjunath Hadli622897d2012-11-28 02:03:38 -03001456 * @file: file pointer
1457 * @priv: void pointer
1458 * @buf_type: enum v4l2_buf_type
1459 *
1460 * queue buffer onto hardware for capture/processing and
1461 * start all the subdevs which are in media chain
1462 *
1463 * Return 0 on success, error code otherwise
1464 */
1465static int vpfe_streamon(struct file *file, void *priv,
1466 enum v4l2_buf_type buf_type)
1467{
1468 struct vpfe_video_device *video = video_drvdata(file);
1469 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1470 struct vpfe_pipeline *pipe = &video->pipe;
1471 struct vpfe_fh *fh = file->private_data;
1472 struct vpfe_ext_subdev_info *sdinfo;
1473 int ret = -EINVAL;
1474
1475 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamon\n");
1476
Thaissa Falbob369a872016-02-15 02:52:49 -02001477 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1478 buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001479 v4l2_err(&vpfe_dev->v4l2_dev, "Invalid buf type\n");
1480 return ret;
1481 }
1482 /* If file handle is not allowed IO, return error */
1483 if (!fh->io_allowed) {
1484 v4l2_err(&vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1485 return -EACCES;
1486 }
1487 sdinfo = video->current_ext_subdev;
1488 /* If buffer queue is empty, return error */
1489 if (list_empty(&video->buffer_queue.queued_list)) {
1490 v4l2_err(&vpfe_dev->v4l2_dev, "buffer queue is empty\n");
1491 return -EIO;
1492 }
1493 /* Validate the pipeline */
Thaissa Falbob369a872016-02-15 02:52:49 -02001494 if (buf_type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001495 ret = vpfe_video_validate_pipeline(pipe);
1496 if (ret < 0)
1497 return ret;
1498 }
1499 /* Call vb2_streamon to start streaming */
1500 return vb2_streamon(&video->buffer_queue, buf_type);
1501}
1502
1503/*
Hans Verkuil4bd3bb72013-02-15 14:51:23 -03001504 * vpfe_streamoff() - stop streaming
Manjunath Hadli622897d2012-11-28 02:03:38 -03001505 * @file: file pointer
1506 * @priv: void pointer
1507 * @buf_type: enum v4l2_buf_type
1508 *
1509 * stop all the subdevs which are in media chain
1510 *
1511 * Return 0 on success, error code otherwise
1512 */
1513static int vpfe_streamoff(struct file *file, void *priv,
1514 enum v4l2_buf_type buf_type)
1515{
1516 struct vpfe_video_device *video = video_drvdata(file);
1517 struct vpfe_device *vpfe_dev = video->vpfe_dev;
1518 struct vpfe_fh *fh = file->private_data;
1519 int ret = 0;
1520
1521 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_streamoff\n");
1522
1523 if (buf_type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
1524 buf_type != V4L2_BUF_TYPE_VIDEO_OUTPUT) {
1525 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "Invalid buf type\n");
1526 return -EINVAL;
1527 }
1528
1529 /* If io is allowed for this file handle, return error */
1530 if (!fh->io_allowed) {
1531 v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "fh->io_allowed\n");
1532 return -EACCES;
1533 }
1534
1535 /* If streaming is not started, return error */
1536 if (!video->started) {
1537 v4l2_err(&vpfe_dev->v4l2_dev, "device is not started\n");
1538 return -EINVAL;
1539 }
1540
Hans Verkuil8bbb6562016-04-15 08:58:10 -03001541 ret = mutex_lock_interruptible(&video->lock);
1542 if (ret)
1543 return ret;
Manjunath Hadli622897d2012-11-28 02:03:38 -03001544
1545 vpfe_stop_capture(video);
1546 ret = vb2_streamoff(&video->buffer_queue, buf_type);
1547 mutex_unlock(&video->lock);
1548
1549 return ret;
1550}
1551
1552/* vpfe capture ioctl operations */
1553static const struct v4l2_ioctl_ops vpfe_ioctl_ops = {
1554 .vidioc_querycap = vpfe_querycap,
1555 .vidioc_g_fmt_vid_cap = vpfe_g_fmt,
1556 .vidioc_s_fmt_vid_cap = vpfe_s_fmt,
1557 .vidioc_try_fmt_vid_cap = vpfe_try_fmt,
1558 .vidioc_enum_fmt_vid_cap = vpfe_enum_fmt,
1559 .vidioc_g_fmt_vid_out = vpfe_g_fmt,
1560 .vidioc_s_fmt_vid_out = vpfe_s_fmt,
1561 .vidioc_try_fmt_vid_out = vpfe_try_fmt,
1562 .vidioc_enum_fmt_vid_out = vpfe_enum_fmt,
1563 .vidioc_enum_input = vpfe_enum_input,
1564 .vidioc_g_input = vpfe_g_input,
1565 .vidioc_s_input = vpfe_s_input,
1566 .vidioc_querystd = vpfe_querystd,
1567 .vidioc_s_std = vpfe_s_std,
1568 .vidioc_g_std = vpfe_g_std,
1569 .vidioc_enum_dv_timings = vpfe_enum_dv_timings,
1570 .vidioc_query_dv_timings = vpfe_query_dv_timings,
1571 .vidioc_s_dv_timings = vpfe_s_dv_timings,
1572 .vidioc_g_dv_timings = vpfe_g_dv_timings,
1573 .vidioc_reqbufs = vpfe_reqbufs,
1574 .vidioc_querybuf = vpfe_querybuf,
1575 .vidioc_qbuf = vpfe_qbuf,
1576 .vidioc_dqbuf = vpfe_dqbuf,
1577 .vidioc_streamon = vpfe_streamon,
1578 .vidioc_streamoff = vpfe_streamoff,
1579};
1580
1581/* VPFE video init function */
1582int vpfe_video_init(struct vpfe_video_device *video, const char *name)
1583{
1584 const char *direction;
1585 int ret;
1586
1587 switch (video->type) {
1588 case V4L2_BUF_TYPE_VIDEO_CAPTURE:
1589 direction = "output";
1590 video->pad.flags = MEDIA_PAD_FL_SINK;
1591 video->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
1592 break;
1593
1594 case V4L2_BUF_TYPE_VIDEO_OUTPUT:
1595 direction = "input";
1596 video->pad.flags = MEDIA_PAD_FL_SOURCE;
1597 video->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
1598 break;
1599
1600 default:
1601 return -EINVAL;
1602 }
1603 /* Initialize field of video device */
1604 video->video_dev.release = video_device_release;
1605 video->video_dev.fops = &vpfe_fops;
1606 video->video_dev.ioctl_ops = &vpfe_ioctl_ops;
1607 video->video_dev.minor = -1;
1608 video->video_dev.tvnorms = 0;
1609 snprintf(video->video_dev.name, sizeof(video->video_dev.name),
1610 "DAVINCI VIDEO %s %s", name, direction);
1611
Manjunath Hadli622897d2012-11-28 02:03:38 -03001612 spin_lock_init(&video->irqlock);
1613 spin_lock_init(&video->dma_queue_lock);
1614 mutex_init(&video->lock);
Mauro Carvalho Chehabab22e772015-12-11 07:44:40 -02001615 ret = media_entity_pads_init(&video->video_dev.entity,
Mauro Carvalho Chehab18095102015-08-06 09:25:57 -03001616 1, &video->pad);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001617 if (ret < 0)
1618 return ret;
1619
1620 video_set_drvdata(&video->video_dev, video);
1621
1622 return 0;
1623}
1624
1625/* vpfe video device register function */
1626int vpfe_video_register(struct vpfe_video_device *video,
1627 struct v4l2_device *vdev)
1628{
1629 int ret;
1630
1631 video->video_dev.v4l2_dev = vdev;
1632
1633 ret = video_register_device(&video->video_dev, VFL_TYPE_GRABBER, -1);
1634 if (ret < 0)
1635 pr_err("%s: could not register video device (%d)\n",
1636 __func__, ret);
1637 return ret;
1638}
1639
1640/* vpfe video device unregister function */
1641void vpfe_video_unregister(struct vpfe_video_device *video)
1642{
1643 if (video_is_registered(&video->video_dev)) {
Manjunath Hadli622897d2012-11-28 02:03:38 -03001644 video_unregister_device(&video->video_dev);
Sakari Ailus7bb151b2013-06-11 06:50:49 -03001645 media_entity_cleanup(&video->video_dev.entity);
Manjunath Hadli622897d2012-11-28 02:03:38 -03001646 }
1647}